diff options
| -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); |
