diff options
author | Ian Abbott <abbotti@mev.co.uk> | 2015-11-18 12:55:04 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-12-21 18:58:54 -0500 |
commit | 06181de14ff09b274b699ee2dd39fe5e37efb419 (patch) | |
tree | 66eba4cfa2f1d2b7874a5a3dc084b0657a5aade3 | |
parent | b4717ff608c180115ace1d307e7f452e114ca29c (diff) |
staging: comedi: rearrange comedi_write() code
Rearrange the code in `comedi_write()` to reduce the amount of
indentation. The code never reiterates the `while` loop once `count`
has become non-zero, so we can check that in the `while` condition to
save an indentation level. (Note that `nbytes` has been checked to be
non-zero before entering the loop, so we can remove that check.) Move
the code that makes the subdevice "become non-busy" outside the `while`
loop, using a new flag variable `become_nonbusy` to decide whether it
needs to be done. This simplifies the wait queue handling so there is a
single place where the task is removed from the wait queue, and we can
remove the `on_wait_queue` flag variable.
Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Reviewed-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/staging/comedi/comedi_fops.c | 71 |
1 files changed, 30 insertions, 41 deletions
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 7b4af519e17e..c9da6f39b1c6 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c | |||
@@ -2307,7 +2307,7 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, | |||
2307 | DECLARE_WAITQUEUE(wait, current); | 2307 | DECLARE_WAITQUEUE(wait, current); |
2308 | struct comedi_file *cfp = file->private_data; | 2308 | struct comedi_file *cfp = file->private_data; |
2309 | struct comedi_device *dev = cfp->dev; | 2309 | struct comedi_device *dev = cfp->dev; |
2310 | bool on_wait_queue = false; | 2310 | bool become_nonbusy = false; |
2311 | bool attach_locked; | 2311 | bool attach_locked; |
2312 | unsigned int old_detach_count; | 2312 | unsigned int old_detach_count; |
2313 | 2313 | ||
@@ -2342,48 +2342,16 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, | |||
2342 | } | 2342 | } |
2343 | 2343 | ||
2344 | add_wait_queue(&async->wait_head, &wait); | 2344 | add_wait_queue(&async->wait_head, &wait); |
2345 | on_wait_queue = true; | 2345 | while (count == 0 && !retval) { |
2346 | while (nbytes > 0 && !retval) { | ||
2347 | unsigned runflags; | 2346 | unsigned runflags; |
2348 | 2347 | ||
2349 | set_current_state(TASK_INTERRUPTIBLE); | 2348 | set_current_state(TASK_INTERRUPTIBLE); |
2350 | 2349 | ||
2351 | runflags = comedi_get_subdevice_runflags(s); | 2350 | runflags = comedi_get_subdevice_runflags(s); |
2352 | if (!comedi_is_runflags_running(runflags)) { | 2351 | if (!comedi_is_runflags_running(runflags)) { |
2353 | if (count == 0) { | 2352 | if (comedi_is_runflags_in_error(runflags)) |
2354 | struct comedi_subdevice *new_s; | 2353 | retval = -EPIPE; |
2355 | 2354 | become_nonbusy = true; | |
2356 | if (comedi_is_runflags_in_error(runflags)) | ||
2357 | retval = -EPIPE; | ||
2358 | else | ||
2359 | retval = 0; | ||
2360 | /* | ||
2361 | * To avoid deadlock, cannot acquire dev->mutex | ||
2362 | * while dev->attach_lock is held. Need to | ||
2363 | * remove task from the async wait queue before | ||
2364 | * releasing dev->attach_lock, as it might not | ||
2365 | * be valid afterwards. | ||
2366 | */ | ||
2367 | remove_wait_queue(&async->wait_head, &wait); | ||
2368 | on_wait_queue = false; | ||
2369 | up_read(&dev->attach_lock); | ||
2370 | attach_locked = false; | ||
2371 | mutex_lock(&dev->mutex); | ||
2372 | /* | ||
2373 | * Become non-busy unless things have changed | ||
2374 | * behind our back. Checking dev->detach_count | ||
2375 | * is unchanged ought to be sufficient (unless | ||
2376 | * there have been 2**32 detaches in the | ||
2377 | * meantime!), but check the subdevice pointer | ||
2378 | * as well just in case. | ||
2379 | */ | ||
2380 | new_s = comedi_file_write_subdevice(file); | ||
2381 | if (dev->attached && | ||
2382 | old_detach_count == dev->detach_count && | ||
2383 | s == new_s && new_s->async == async) | ||
2384 | do_become_nonbusy(dev, s); | ||
2385 | mutex_unlock(&dev->mutex); | ||
2386 | } | ||
2387 | break; | 2355 | break; |
2388 | } | 2356 | } |
2389 | 2357 | ||
@@ -2433,12 +2401,33 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, | |||
2433 | nbytes -= n; | 2401 | nbytes -= n; |
2434 | 2402 | ||
2435 | buf += n; | 2403 | buf += n; |
2436 | break; /* makes device work like a pipe */ | ||
2437 | } | 2404 | } |
2438 | out: | 2405 | remove_wait_queue(&async->wait_head, &wait); |
2439 | if (on_wait_queue) | ||
2440 | remove_wait_queue(&async->wait_head, &wait); | ||
2441 | set_current_state(TASK_RUNNING); | 2406 | set_current_state(TASK_RUNNING); |
2407 | if (become_nonbusy && count == 0) { | ||
2408 | struct comedi_subdevice *new_s; | ||
2409 | |||
2410 | /* | ||
2411 | * To avoid deadlock, cannot acquire dev->mutex | ||
2412 | * while dev->attach_lock is held. | ||
2413 | */ | ||
2414 | up_read(&dev->attach_lock); | ||
2415 | attach_locked = false; | ||
2416 | mutex_lock(&dev->mutex); | ||
2417 | /* | ||
2418 | * Check device hasn't become detached behind our back. | ||
2419 | * Checking dev->detach_count is unchanged ought to be | ||
2420 | * sufficient (unless there have been 2**32 detaches in the | ||
2421 | * meantime!), but check the subdevice pointer as well just in | ||
2422 | * case. | ||
2423 | */ | ||
2424 | new_s = comedi_file_write_subdevice(file); | ||
2425 | if (dev->attached && old_detach_count == dev->detach_count && | ||
2426 | s == new_s && new_s->async == async) | ||
2427 | do_become_nonbusy(dev, s); | ||
2428 | mutex_unlock(&dev->mutex); | ||
2429 | } | ||
2430 | out: | ||
2442 | if (attach_locked) | 2431 | if (attach_locked) |
2443 | up_read(&dev->attach_lock); | 2432 | up_read(&dev->attach_lock); |
2444 | 2433 | ||