summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikhil Rao <nikhil.rao@intel.com>2020-06-22 13:38:34 -0700
committerVinod Koul <vkoul@kernel.org>2020-06-24 11:17:46 +0530
commit66983bc18fad17d10766650b3685045f6f092d73 (patch)
treed37c1f3ae350218ad08902cef5f72e5b06b92c6e
parent2f57b8d57673af2c2caf8c2c7bef01be940a5c2c (diff)
dmaengine: idxd: fix cdev locking for open and release
add the wq lock in cdev open and release call. This fixes race conditions observed in the open and close routines. Fixes: 42d279f9137a ("dmaengine: idxd: add char driver to expose submission portal to userland") Signed-off-by: Nikhil Rao <nikhil.rao@intel.com> Signed-off-by: Dave Jiang <dave.jiang@intel.com> Link: https://lore.kernel.org/r/159285824892.64944.2905413694915141834.stgit@djiang5-desk3.ch.intel.com Signed-off-by: Vinod Koul <vkoul@kernel.org>
-rw-r--r--drivers/dma/idxd/cdev.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/drivers/dma/idxd/cdev.c b/drivers/dma/idxd/cdev.c
index ff49847e37a8..cb376cf6a2d2 100644
--- a/drivers/dma/idxd/cdev.c
+++ b/drivers/dma/idxd/cdev.c
@@ -74,6 +74,7 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp)
struct idxd_device *idxd;
struct idxd_wq *wq;
struct device *dev;
+ int rc = 0;
wq = inode_wq(inode);
idxd = wq->idxd;
@@ -81,17 +82,27 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp)
dev_dbg(dev, "%s called: %d\n", __func__, idxd_wq_refcount(wq));
- if (idxd_wq_refcount(wq) > 0 && wq_dedicated(wq))
- return -EBUSY;
-
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
+ mutex_lock(&wq->wq_lock);
+
+ if (idxd_wq_refcount(wq) > 0 && wq_dedicated(wq)) {
+ rc = -EBUSY;
+ goto failed;
+ }
+
ctx->wq = wq;
filp->private_data = ctx;
idxd_wq_get(wq);
+ mutex_unlock(&wq->wq_lock);
return 0;
+
+ failed:
+ mutex_unlock(&wq->wq_lock);
+ kfree(ctx);
+ return rc;
}
static int idxd_cdev_release(struct inode *node, struct file *filep)
@@ -105,7 +116,9 @@ static int idxd_cdev_release(struct inode *node, struct file *filep)
filep->private_data = NULL;
kfree(ctx);
+ mutex_lock(&wq->wq_lock);
idxd_wq_put(wq);
+ mutex_unlock(&wq->wq_lock);
return 0;
}