diff options
author | David Vrabel <david.vrabel@csr.com> | 2009-08-18 11:11:24 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-12-11 14:55:14 -0500 |
commit | 8e08b9766b50826e12139a821b6b3bdfcadcceda (patch) | |
tree | 0430b4ea03a4e92b6e1d503c763a2a38359a4873 /drivers | |
parent | 294a39e7829dfd663e6c5c94cede0c6a0c13e37f (diff) |
USB: allow interrupt transfers to WUSB devices
Check urb->interval on interrupt transfers and allow those with valid
values (6 <= interval <= 16).
Signed-off-by: David Vrabel <david.vrabel@csr.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/core/urb.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 0885d4abdc62..e7cae1334693 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c | |||
@@ -429,8 +429,16 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) | |||
429 | case USB_ENDPOINT_XFER_ISOC: | 429 | case USB_ENDPOINT_XFER_ISOC: |
430 | case USB_ENDPOINT_XFER_INT: | 430 | case USB_ENDPOINT_XFER_INT: |
431 | /* too small? */ | 431 | /* too small? */ |
432 | if (urb->interval <= 0) | 432 | switch (dev->speed) { |
433 | return -EINVAL; | 433 | case USB_SPEED_VARIABLE: |
434 | if (urb->interval < 6) | ||
435 | return -EINVAL; | ||
436 | break; | ||
437 | default: | ||
438 | if (urb->interval <= 0) | ||
439 | return -EINVAL; | ||
440 | break; | ||
441 | } | ||
434 | /* too big? */ | 442 | /* too big? */ |
435 | switch (dev->speed) { | 443 | switch (dev->speed) { |
436 | case USB_SPEED_SUPER: /* units are 125us */ | 444 | case USB_SPEED_SUPER: /* units are 125us */ |
@@ -438,6 +446,10 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) | |||
438 | if (urb->interval > (1 << 15)) | 446 | if (urb->interval > (1 << 15)) |
439 | return -EINVAL; | 447 | return -EINVAL; |
440 | max = 1 << 15; | 448 | max = 1 << 15; |
449 | case USB_SPEED_VARIABLE: | ||
450 | if (urb->interval > 16) | ||
451 | return -EINVAL; | ||
452 | break; | ||
441 | case USB_SPEED_HIGH: /* units are microframes */ | 453 | case USB_SPEED_HIGH: /* units are microframes */ |
442 | /* NOTE usb handles 2^15 */ | 454 | /* NOTE usb handles 2^15 */ |
443 | if (urb->interval > (1024 * 8)) | 455 | if (urb->interval > (1024 * 8)) |
@@ -461,8 +473,10 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) | |||
461 | default: | 473 | default: |
462 | return -EINVAL; | 474 | return -EINVAL; |
463 | } | 475 | } |
464 | /* Round down to a power of 2, no more than max */ | 476 | if (dev->speed != USB_SPEED_VARIABLE) { |
465 | urb->interval = min(max, 1 << ilog2(urb->interval)); | 477 | /* Round down to a power of 2, no more than max */ |
478 | urb->interval = min(max, 1 << ilog2(urb->interval)); | ||
479 | } | ||
466 | } | 480 | } |
467 | 481 | ||
468 | return usb_hcd_submit_urb(urb, mem_flags); | 482 | return usb_hcd_submit_urb(urb, mem_flags); |