aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/staging/comedi/comedi_fops.c25
1 files changed, 15 insertions, 10 deletions
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index 6cdef9d5f8d0..f4a197b2d1fd 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -1413,22 +1413,19 @@ static int do_cmd_ioctl(struct comedi_device *dev,
1413 DPRINTK("subdevice busy\n"); 1413 DPRINTK("subdevice busy\n");
1414 return -EBUSY; 1414 return -EBUSY;
1415 } 1415 }
1416 s->busy = file;
1417 1416
1418 /* make sure channel/gain list isn't too long */ 1417 /* make sure channel/gain list isn't too long */
1419 if (cmd.chanlist_len > s->len_chanlist) { 1418 if (cmd.chanlist_len > s->len_chanlist) {
1420 DPRINTK("channel/gain list too long %u > %d\n", 1419 DPRINTK("channel/gain list too long %u > %d\n",
1421 cmd.chanlist_len, s->len_chanlist); 1420 cmd.chanlist_len, s->len_chanlist);
1422 ret = -EINVAL; 1421 return -EINVAL;
1423 goto cleanup;
1424 } 1422 }
1425 1423
1426 /* make sure channel/gain list isn't too short */ 1424 /* make sure channel/gain list isn't too short */
1427 if (cmd.chanlist_len < 1) { 1425 if (cmd.chanlist_len < 1) {
1428 DPRINTK("channel/gain list too short %u < 1\n", 1426 DPRINTK("channel/gain list too short %u < 1\n",
1429 cmd.chanlist_len); 1427 cmd.chanlist_len);
1430 ret = -EINVAL; 1428 return -EINVAL;
1431 goto cleanup;
1432 } 1429 }
1433 1430
1434 async->cmd = cmd; 1431 async->cmd = cmd;
@@ -1438,8 +1435,7 @@ static int do_cmd_ioctl(struct comedi_device *dev,
1438 kmalloc(async->cmd.chanlist_len * sizeof(int), GFP_KERNEL); 1435 kmalloc(async->cmd.chanlist_len * sizeof(int), GFP_KERNEL);
1439 if (!async->cmd.chanlist) { 1436 if (!async->cmd.chanlist) {
1440 DPRINTK("allocation failed\n"); 1437 DPRINTK("allocation failed\n");
1441 ret = -ENOMEM; 1438 return -ENOMEM;
1442 goto cleanup;
1443 } 1439 }
1444 1440
1445 if (copy_from_user(async->cmd.chanlist, user_chanlist, 1441 if (copy_from_user(async->cmd.chanlist, user_chanlist,
@@ -1491,6 +1487,9 @@ static int do_cmd_ioctl(struct comedi_device *dev,
1491 1487
1492 comedi_set_subdevice_runflags(s, ~0, SRF_USER | SRF_RUNNING); 1488 comedi_set_subdevice_runflags(s, ~0, SRF_USER | SRF_RUNNING);
1493 1489
1490 /* set s->busy _after_ setting SRF_RUNNING flag to avoid race with
1491 * comedi_read() or comedi_write() */
1492 s->busy = file;
1494 ret = s->do_cmd(dev, s); 1493 ret = s->do_cmd(dev, s);
1495 if (ret == 0) 1494 if (ret == 0)
1496 return 0; 1495 return 0;
@@ -2058,11 +2057,13 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
2058 2057
2059 if (!comedi_is_subdevice_running(s)) { 2058 if (!comedi_is_subdevice_running(s)) {
2060 if (count == 0) { 2059 if (count == 0) {
2060 mutex_lock(&dev->mutex);
2061 if (comedi_is_subdevice_in_error(s)) 2061 if (comedi_is_subdevice_in_error(s))
2062 retval = -EPIPE; 2062 retval = -EPIPE;
2063 else 2063 else
2064 retval = 0; 2064 retval = 0;
2065 do_become_nonbusy(dev, s); 2065 do_become_nonbusy(dev, s);
2066 mutex_unlock(&dev->mutex);
2066 } 2067 }
2067 break; 2068 break;
2068 } 2069 }
@@ -2161,11 +2162,13 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
2161 2162
2162 if (n == 0) { 2163 if (n == 0) {
2163 if (!comedi_is_subdevice_running(s)) { 2164 if (!comedi_is_subdevice_running(s)) {
2165 mutex_lock(&dev->mutex);
2164 do_become_nonbusy(dev, s); 2166 do_become_nonbusy(dev, s);
2165 if (comedi_is_subdevice_in_error(s)) 2167 if (comedi_is_subdevice_in_error(s))
2166 retval = -EPIPE; 2168 retval = -EPIPE;
2167 else 2169 else
2168 retval = 0; 2170 retval = 0;
2171 mutex_unlock(&dev->mutex);
2169 break; 2172 break;
2170 } 2173 }
2171 if (file->f_flags & O_NONBLOCK) { 2174 if (file->f_flags & O_NONBLOCK) {
@@ -2203,9 +2206,11 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
2203 buf += n; 2206 buf += n;
2204 break; /* makes device work like a pipe */ 2207 break; /* makes device work like a pipe */
2205 } 2208 }
2206 if (comedi_is_subdevice_idle(s) && 2209 if (comedi_is_subdevice_idle(s)) {
2207 async->buf_read_count - async->buf_write_count == 0) { 2210 mutex_lock(&dev->mutex);
2208 do_become_nonbusy(dev, s); 2211 if (async->buf_read_count - async->buf_write_count == 0)
2212 do_become_nonbusy(dev, s);
2213 mutex_unlock(&dev->mutex);
2209 } 2214 }
2210 set_current_state(TASK_RUNNING); 2215 set_current_state(TASK_RUNNING);
2211 remove_wait_queue(&async->wait_head, &wait); 2216 remove_wait_queue(&async->wait_head, &wait);