aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2009-04-27 22:54:10 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-06-16 00:44:48 -0400
commit6b403b020c1f42180b14d28d832da61167cff822 (patch)
tree4b7271244f3b150a31c856970651d2171343d2c7 /drivers/usb/core
parent7f84eef0dafb1d318263d8b71c38700aaf2d530d (diff)
USB: Add SuperSpeed to the list of USB device speeds.
Modify the USB core to handle the new USB 3.0 speed, "SuperSpeed". This is 5.0 Gbps (wire speed). There are probably more places that check for speed that I've missed. SuperSpeed devices have a 512 byte endpoint 0 max packet size. This shows up as a bMaxPacketSize0 set to 0x09 (see table 9-8 of the USB 3.0 bus spec). xHCI spec says that the xHC can handle intervals up to 2^15 microframes. That might change when real silicon becomes available. Add FIXME note for SuperSpeed isochronous endpoints. They can transmit up to 16 packets in one "burst" before they wait for an acknowledgment of the packets. They can do up to 3 bursts per microframe (determined by the mult value in the endpoint companion descriptor). The xHCI driver doesn't have support for isoc yet, so fix this later. Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/core')
-rw-r--r--drivers/usb/core/config.c1
-rw-r--r--drivers/usb/core/hcd.c16
-rw-r--r--drivers/usb/core/hcd.h1
-rw-r--r--drivers/usb/core/hub.c11
-rw-r--r--drivers/usb/core/urb.c6
5 files changed, 31 insertions, 4 deletions
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 568244c99bdc..e9426acf5682 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -92,6 +92,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
92 if (usb_endpoint_xfer_int(d)) { 92 if (usb_endpoint_xfer_int(d)) {
93 i = 1; 93 i = 1;
94 switch (to_usb_device(ddev)->speed) { 94 switch (to_usb_device(ddev)->speed) {
95 case USB_SPEED_SUPER:
95 case USB_SPEED_HIGH: 96 case USB_SPEED_HIGH:
96 /* Many device manufacturers are using full-speed 97 /* Many device manufacturers are using full-speed
97 * bInterval values in high-speed interrupt endpoint 98 * bInterval values in high-speed interrupt endpoint
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index c65d95604028..120bb56c4b84 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1870,8 +1870,20 @@ int usb_add_hcd(struct usb_hcd *hcd,
1870 retval = -ENOMEM; 1870 retval = -ENOMEM;
1871 goto err_allocate_root_hub; 1871 goto err_allocate_root_hub;
1872 } 1872 }
1873 rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH : 1873
1874 USB_SPEED_FULL; 1874 switch (hcd->driver->flags & HCD_MASK) {
1875 case HCD_USB11:
1876 rhdev->speed = USB_SPEED_FULL;
1877 break;
1878 case HCD_USB2:
1879 rhdev->speed = USB_SPEED_HIGH;
1880 break;
1881 case HCD_USB3:
1882 rhdev->speed = USB_SPEED_SUPER;
1883 break;
1884 default:
1885 goto err_allocate_root_hub;
1886 }
1875 hcd->self.root_hub = rhdev; 1887 hcd->self.root_hub = rhdev;
1876 1888
1877 /* wakeup flag init defaults to "everything works" for root hubs, 1889 /* wakeup flag init defaults to "everything works" for root hubs,
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index 7a47498b0aac..4f6ee60d97c6 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -174,6 +174,7 @@ struct hc_driver {
174#define HCD_USB11 0x0010 /* USB 1.1 */ 174#define HCD_USB11 0x0010 /* USB 1.1 */
175#define HCD_USB2 0x0020 /* USB 2.0 */ 175#define HCD_USB2 0x0020 /* USB 2.0 */
176#define HCD_USB3 0x0040 /* USB 3.0 */ 176#define HCD_USB3 0x0040 /* USB 3.0 */
177#define HCD_MASK 0x0070
177 178
178 /* called to init HCD and root hub */ 179 /* called to init HCD and root hub */
179 int (*reset) (struct usb_hcd *hcd); 180 int (*reset) (struct usb_hcd *hcd);
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index c7a1a1d4bcb1..fa0208e0da6a 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -2471,6 +2471,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
2471 * reported as 0xff in the device descriptor). WUSB1.0[4.8.1]. 2471 * reported as 0xff in the device descriptor). WUSB1.0[4.8.1].
2472 */ 2472 */
2473 switch (udev->speed) { 2473 switch (udev->speed) {
2474 case USB_SPEED_SUPER:
2474 case USB_SPEED_VARIABLE: /* fixed at 512 */ 2475 case USB_SPEED_VARIABLE: /* fixed at 512 */
2475 udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512); 2476 udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512);
2476 break; 2477 break;
@@ -2496,6 +2497,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
2496 case USB_SPEED_LOW: speed = "low"; break; 2497 case USB_SPEED_LOW: speed = "low"; break;
2497 case USB_SPEED_FULL: speed = "full"; break; 2498 case USB_SPEED_FULL: speed = "full"; break;
2498 case USB_SPEED_HIGH: speed = "high"; break; 2499 case USB_SPEED_HIGH: speed = "high"; break;
2500 case USB_SPEED_SUPER:
2501 speed = "super";
2502 break;
2499 case USB_SPEED_VARIABLE: 2503 case USB_SPEED_VARIABLE:
2500 speed = "variable"; 2504 speed = "variable";
2501 type = "Wireless "; 2505 type = "Wireless ";
@@ -2634,8 +2638,11 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
2634 if (retval) 2638 if (retval)
2635 goto fail; 2639 goto fail;
2636 2640
2637 i = udev->descriptor.bMaxPacketSize0 == 0xff? /* wusb device? */ 2641 if (udev->descriptor.bMaxPacketSize0 == 0xff ||
2638 512 : udev->descriptor.bMaxPacketSize0; 2642 udev->speed == USB_SPEED_SUPER)
2643 i = 512;
2644 else
2645 i = udev->descriptor.bMaxPacketSize0;
2639 if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) { 2646 if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) {
2640 if (udev->speed != USB_SPEED_FULL || 2647 if (udev->speed != USB_SPEED_FULL ||
2641 !(i == 8 || i == 16 || i == 32 || i == 64)) { 2648 !(i == 8 || i == 16 || i == 32 || i == 64)) {
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 3376055f36e7..02eb0ef7a4c3 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -351,6 +351,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
351 if (xfertype == USB_ENDPOINT_XFER_ISOC) { 351 if (xfertype == USB_ENDPOINT_XFER_ISOC) {
352 int n, len; 352 int n, len;
353 353
354 /* FIXME SuperSpeed isoc endpoints have up to 16 bursts */
354 /* "high bandwidth" mode, 1-3 packets/uframe? */ 355 /* "high bandwidth" mode, 1-3 packets/uframe? */
355 if (dev->speed == USB_SPEED_HIGH) { 356 if (dev->speed == USB_SPEED_HIGH) {
356 int mult = 1 + ((max >> 11) & 0x03); 357 int mult = 1 + ((max >> 11) & 0x03);
@@ -426,6 +427,11 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
426 return -EINVAL; 427 return -EINVAL;
427 /* too big? */ 428 /* too big? */
428 switch (dev->speed) { 429 switch (dev->speed) {
430 case USB_SPEED_SUPER: /* units are 125us */
431 /* Handle up to 2^(16-1) microframes */
432 if (urb->interval > (1 << 15))
433 return -EINVAL;
434 max = 1 << 15;
429 case USB_SPEED_HIGH: /* units are microframes */ 435 case USB_SPEED_HIGH: /* units are microframes */
430 /* NOTE usb handles 2^15 */ 436 /* NOTE usb handles 2^15 */
431 if (urb->interval > (1024 * 8)) 437 if (urb->interval > (1024 * 8))