diff options
author | Oliver Neukum <oliver@neukum.org> | 2009-09-09 04:12:48 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-09-23 09:46:16 -0400 |
commit | 7f1dc313d01f5f0f84c06051343a3b8623932d3c (patch) | |
tree | 762ae2c12f103f039a8215161172b0b52101c1c9 /drivers/usb/class/cdc-wdm.c | |
parent | ce60c48871d2b3a15ab3fa2450e783bebb4ae407 (diff) |
USB: CDC WDM driver doesn't support non-blocking reads
support for O_NONBLOCK in read and write path
by simply not waiting for data in read or availability
of the write urb in write but returning -EAGAIN
Signed-off-by: Oliver Neukum <oliver@neukum.org>
Tested-by: Marcel Holtmann <marcel@holtmann.org>
Cc: stable <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/class/cdc-wdm.c')
-rw-r--r-- | drivers/usb/class/cdc-wdm.c | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 8c64c018b676..3e564bfe17d1 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c | |||
@@ -313,8 +313,13 @@ static ssize_t wdm_write | |||
313 | r = usb_autopm_get_interface(desc->intf); | 313 | r = usb_autopm_get_interface(desc->intf); |
314 | if (r < 0) | 314 | if (r < 0) |
315 | goto outnp; | 315 | goto outnp; |
316 | r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE, | 316 | |
317 | &desc->flags)); | 317 | if (!file->f_flags && O_NONBLOCK) |
318 | r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE, | ||
319 | &desc->flags)); | ||
320 | else | ||
321 | if (test_bit(WDM_IN_USE, &desc->flags)) | ||
322 | r = -EAGAIN; | ||
318 | if (r < 0) | 323 | if (r < 0) |
319 | goto out; | 324 | goto out; |
320 | 325 | ||
@@ -377,7 +382,7 @@ outnl: | |||
377 | static ssize_t wdm_read | 382 | static ssize_t wdm_read |
378 | (struct file *file, char __user *buffer, size_t count, loff_t *ppos) | 383 | (struct file *file, char __user *buffer, size_t count, loff_t *ppos) |
379 | { | 384 | { |
380 | int rv, cntr; | 385 | int rv, cntr = 0; |
381 | int i = 0; | 386 | int i = 0; |
382 | struct wdm_device *desc = file->private_data; | 387 | struct wdm_device *desc = file->private_data; |
383 | 388 | ||
@@ -389,10 +394,23 @@ static ssize_t wdm_read | |||
389 | if (desc->length == 0) { | 394 | if (desc->length == 0) { |
390 | desc->read = 0; | 395 | desc->read = 0; |
391 | retry: | 396 | retry: |
397 | if (test_bit(WDM_DISCONNECTING, &desc->flags)) { | ||
398 | rv = -ENODEV; | ||
399 | goto err; | ||
400 | } | ||
392 | i++; | 401 | i++; |
393 | rv = wait_event_interruptible(desc->wait, | 402 | if (file->f_flags & O_NONBLOCK) { |
394 | test_bit(WDM_READ, &desc->flags)); | 403 | if (!test_bit(WDM_READ, &desc->flags)) { |
404 | rv = cntr ? cntr : -EAGAIN; | ||
405 | goto err; | ||
406 | } | ||
407 | rv = 0; | ||
408 | } else { | ||
409 | rv = wait_event_interruptible(desc->wait, | ||
410 | test_bit(WDM_READ, &desc->flags)); | ||
411 | } | ||
395 | 412 | ||
413 | /* may have happened while we slept */ | ||
396 | if (test_bit(WDM_DISCONNECTING, &desc->flags)) { | 414 | if (test_bit(WDM_DISCONNECTING, &desc->flags)) { |
397 | rv = -ENODEV; | 415 | rv = -ENODEV; |
398 | goto err; | 416 | goto err; |
@@ -448,7 +466,7 @@ retry: | |||
448 | 466 | ||
449 | err: | 467 | err: |
450 | mutex_unlock(&desc->rlock); | 468 | mutex_unlock(&desc->rlock); |
451 | if (rv < 0) | 469 | if (rv < 0 && rv != -EAGAIN) |
452 | dev_err(&desc->intf->dev, "wdm_read: exit error\n"); | 470 | dev_err(&desc->intf->dev, "wdm_read: exit error\n"); |
453 | return rv; | 471 | return rv; |
454 | } | 472 | } |