From: Alexander Sverdlin <alexander.sverdlin@xxxxxxxxx> While get_dma_channel() is protected against concurrent calls, there is a race against kref_put() in mport_cdev_release(): CPU0 CPU1 get_dma_channel() kref_init(&priv->md->dma_ref); ... mport_cdev_release_dma() kref_put(&md->dma_ref, mport_release_def_dma); get_dma_channel() if (priv->md->dma_chan) { ... kref_get(&priv->md->dma_ref); mport_release_def_dma() md->dma_chan = NULL; which may appear like this: ------------[ cut here ]------------ WARNING: CPU: 1 PID: 12057 at .../linux/include/linux/kref.h:46 rio_dma_transfer.isra.12+0x8e0/0xbe8 [rio_mport_cdev] ... CPU: 1 PID: 12057 Comm: ... Tainted: G O 4.9.109-... #1 Stack : ... Call Trace: [<ffffffff80140040>] show_stack+0x90/0xb0 [<ffffffff803eeeb8>] dump_stack+0x88/0xc0 [<ffffffff80159670>] __warn+0x108/0x120 [<ffffffffc0541df0>] rio_dma_transfer.isra.12+0x8e0/0xbe8 [rio_mport_cdev] [<ffffffffc05426fc>] mport_cdev_ioctl+0x604/0x2988 [rio_mport_cdev] [<ffffffff802881e8>] do_vfs_ioctl+0xb8/0x780 [<ffffffff80288938>] SyS_ioctl+0x88/0xc0 [<ffffffff80146ae8>] syscall_common+0x34/0x58 ---[ end trace 78842d4915cfc502 ]--- Fixes: e8de370188d0 ("rapidio: add mport char device driver") Cc: stable@xxxxxxxxxxxxxxx Signed-off-by: Alexander Sverdlin <alexander.sverdlin@xxxxxxxxx> --- drivers/rapidio/devices/rio_mport_cdev.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/rapidio/devices/rio_mport_cdev.c b/drivers/rapidio/devices/rio_mport_cdev.c index 8155f59..a6276dc 100644 --- a/drivers/rapidio/devices/rio_mport_cdev.c +++ b/drivers/rapidio/devices/rio_mport_cdev.c @@ -1980,6 +1980,7 @@ static void mport_cdev_release_dma(struct file *filp) current->comm, task_pid_nr(current), wret); } + mutex_lock(&priv->dma_lock); if (priv->dmach != priv->md->dma_chan) { rmcd_debug(EXIT, "Release DMA channel for filp=%p %s(%d)", filp, current->comm, task_pid_nr(current)); @@ -1990,6 +1991,7 @@ static void mport_cdev_release_dma(struct file *filp) } priv->dmach = NULL; + mutex_unlock(&priv->dma_lock); } #else #define mport_cdev_release_dma(priv) do {} while (0) -- 2.4.6