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 | |
| 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')
| -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 | } |
