summaryrefslogtreecommitdiff
path: root/drivers/staging/comedi/comedi_fops.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-04-22 17:08:40 (GMT)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-04-22 17:08:40 (GMT)
commit3eb9992caff10b62cf0ed0bcb1667a58b13188fa (patch)
treeabe4b4b586978773e2df21898eda611bc6eb822c /drivers/staging/comedi/comedi_fops.c
parente347fa5f4271769bc31fb462631c213aa3824588 (diff)
parenta798c10faf62a505d24e5f6213fbaf904a39623f (diff)
downloadlinux-3eb9992caff10b62cf0ed0bcb1667a58b13188fa.tar.xz
Merge 3.15-rc2 into staging-next
This resolves a bunch of merge errors with other fixes that are already in Linus's tree. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/comedi/comedi_fops.c')
-rw-r--r--drivers/staging/comedi/comedi_fops.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index e283e6c..70545e6 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -1925,14 +1925,21 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
struct comedi_device *dev = file->private_data;
struct comedi_subdevice *s;
struct comedi_async *async;
- struct comedi_buf_map *bm;
+ struct comedi_buf_map *bm = NULL;
unsigned long start = vma->vm_start;
unsigned long size;
int n_pages;
int i;
int retval;
- mutex_lock(&dev->mutex);
+ /*
+ * 'trylock' avoids circular dependency with current->mm->mmap_sem
+ * and down-reading &dev->attach_lock should normally succeed without
+ * contention unless the device is in the process of being attached
+ * or detached.
+ */
+ if (!down_read_trylock(&dev->attach_lock))
+ return -EAGAIN;
if (!dev->attached) {
dev_dbg(dev->class_dev, "no driver attached\n");
@@ -1972,7 +1979,9 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
}
n_pages = size >> PAGE_SHIFT;
- bm = async->buf_map;
+
+ /* get reference to current buf map (if any) */
+ bm = comedi_buf_map_from_subdev_get(s);
if (!bm || n_pages > bm->n_pages) {
retval = -EINVAL;
goto done;
@@ -1996,7 +2005,8 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
retval = 0;
done:
- mutex_unlock(&dev->mutex);
+ up_read(&dev->attach_lock);
+ comedi_buf_map_put(bm); /* put reference to buf map - okay if NULL */
return retval;
}