aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Wilcox <willy@linux.intel.com>2010-03-16 15:55:44 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-03-19 10:24:23 -0400
commitf09a15e6e69884cedec4d1c022089a973aa01f1e (patch)
treeed2902d5f29c3ede3fdadcf165d4c09e4831b498
parente549a17f698e266373f6757bd068d1e98397b4c0 (diff)
USB: Fix usb_fill_int_urb for SuperSpeed devices
USB 3 and Wireless USB specify a logarithmic encoding of the endpoint interval that matches the USB 2 specification. usb_fill_int_urb() didn't know that and was filling in the interval as if it was USB 1.1. Fix usb_fill_int_urb() for SuperSpeed devices, but leave the wireless case alone, because David Vrabel wants to keep the old encoding. Update the struct urb kernel doc to note that SuperSpeed URBs must have urb->interval specified in microframes. Add a missing break statement in the usb_submit_urb() interrupt URB checking, since wireless USB and SuperSpeed USB encode urb->interval differently. This allows xHCI roothubs to actually register with khubd. Signed-off-by: Matthew Wilcox <willy@linux.intel.com> Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/core/urb.c1
-rw-r--r--include/linux/usb.h18
2 files changed, 14 insertions, 5 deletions
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 27080561a1c2..45a32dadb406 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -453,6 +453,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
453 if (urb->interval > (1 << 15)) 453 if (urb->interval > (1 << 15))
454 return -EINVAL; 454 return -EINVAL;
455 max = 1 << 15; 455 max = 1 << 15;
456 break;
456 case USB_SPEED_WIRELESS: 457 case USB_SPEED_WIRELESS:
457 if (urb->interval > 16) 458 if (urb->interval > 16)
458 return -EINVAL; 459 return -EINVAL;
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 8c9f053111bb..ce1323c4e47c 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -1055,7 +1055,8 @@ typedef void (*usb_complete_t)(struct urb *);
1055 * @number_of_packets: Lists the number of ISO transfer buffers. 1055 * @number_of_packets: Lists the number of ISO transfer buffers.
1056 * @interval: Specifies the polling interval for interrupt or isochronous 1056 * @interval: Specifies the polling interval for interrupt or isochronous
1057 * transfers. The units are frames (milliseconds) for full and low 1057 * transfers. The units are frames (milliseconds) for full and low
1058 * speed devices, and microframes (1/8 millisecond) for highspeed ones. 1058 * speed devices, and microframes (1/8 millisecond) for highspeed
1059 * and SuperSpeed devices.
1059 * @error_count: Returns the number of ISO transfers that reported errors. 1060 * @error_count: Returns the number of ISO transfers that reported errors.
1060 * @context: For use in completion functions. This normally points to 1061 * @context: For use in completion functions. This normally points to
1061 * request-specific driver context. 1062 * request-specific driver context.
@@ -1286,9 +1287,16 @@ static inline void usb_fill_bulk_urb(struct urb *urb,
1286 * 1287 *
1287 * Initializes a interrupt urb with the proper information needed to submit 1288 * Initializes a interrupt urb with the proper information needed to submit
1288 * it to a device. 1289 * it to a device.
1289 * Note that high speed interrupt endpoints use a logarithmic encoding of 1290 *
1290 * the endpoint interval, and express polling intervals in microframes 1291 * Note that High Speed and SuperSpeed interrupt endpoints use a logarithmic
1291 * (eight per millisecond) rather than in frames (one per millisecond). 1292 * encoding of the endpoint interval, and express polling intervals in
1293 * microframes (eight per millisecond) rather than in frames (one per
1294 * millisecond).
1295 *
1296 * Wireless USB also uses the logarithmic encoding, but specifies it in units of
1297 * 128us instead of 125us. For Wireless USB devices, the interval is passed
1298 * through to the host controller, rather than being translated into microframe
1299 * units.
1292 */ 1300 */
1293static inline void usb_fill_int_urb(struct urb *urb, 1301static inline void usb_fill_int_urb(struct urb *urb,
1294 struct usb_device *dev, 1302 struct usb_device *dev,
@@ -1305,7 +1313,7 @@ static inline void usb_fill_int_urb(struct urb *urb,
1305 urb->transfer_buffer_length = buffer_length; 1313 urb->transfer_buffer_length = buffer_length;
1306 urb->complete = complete_fn; 1314 urb->complete = complete_fn;
1307 urb->context = context; 1315 urb->context = context;
1308 if (dev->speed == USB_SPEED_HIGH) 1316 if (dev->speed == USB_SPEED_HIGH || dev->speed == USB_SPEED_SUPER)
1309 urb->interval = 1 << (interval - 1); 1317 urb->interval = 1 << (interval - 1);
1310 else 1318 else
1311 urb->interval = interval; 1319 urb->interval = interval;