Commit dbe79bbe9dcb22cb3651c46f18943477141ca452
Committed by
Sarah Sharp
1 parent
ad73dff32e
Exists in
master
and in
7 other branches
USB 3.0 Hub Changes
Update the USB core to deal with USB 3.0 hubs. These hubs have a slightly different hub descriptor than USB 2.0 hubs, with a fixed (rather than variable length) size. Change the USB core's hub descriptor to have a union for the last fields that differ. Change the host controller drivers that access those last fields (DeviceRemovable and PortPowerCtrlMask) to use the union. Translate the new version of the hub port status field into the old version that khubd understands. (Note: we need to fix it to translate the roothub's port status once we stop converting it to USB 2.0 hub status internally.) Add new code to handle link state change status. Send out new control messages that are needed for USB 3.0 hubs, like Set Hub Depth. This patch is a modified version of the original patch submitted by John Youn. It's updated to reflect the removal of the "bitmap" #define, and change the hub descriptor accesses of a couple new host controller drivers. Signed-off-by: John Youn <johnyoun@synopsys.com> Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Cc: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com> Cc: Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> Cc: Tony Olech <tony.olech@elandigitalsystems.com> Cc: "Robert P. J. Day" <rpjday@crashcourse.ca> Cc: Max Vozeler <mvz@vozeler.com> Cc: Tejun Heo <tj@kernel.org> Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> Cc: Rodolfo Giometti <giometti@linux.it> Cc: Mike Frysinger <vapier@gentoo.org> Cc: Anton Vorontsov <avorontsov@mvista.com> Cc: Sebastian Siewior <bigeasy@linutronix.de> Cc: Lothar Wassmann <LW@KARO-electronics.de> Cc: Olav Kongas <ok@artecdesign.ee> Cc: Martin Fuzzey <mfuzzey@gmail.com> Cc: Alan Stern <stern@rowland.harvard.edu> Cc: David Brownell <dbrownell@users.sourceforge.net>
Showing 17 changed files with 141 additions and 48 deletions Side-by-side Diff
- drivers/staging/usbip/vhci_hcd.c
- drivers/usb/core/hub.c
- drivers/usb/gadget/dummy_hcd.c
- drivers/usb/host/ehci-hub.c
- drivers/usb/host/imx21-hcd.c
- drivers/usb/host/isp116x-hcd.c
- drivers/usb/host/isp1362-hcd.c
- drivers/usb/host/isp1760-hcd.c
- drivers/usb/host/ohci-hub.c
- drivers/usb/host/oxu210hp-hcd.c
- drivers/usb/host/r8a66597-hcd.c
- drivers/usb/host/sl811-hcd.c
- drivers/usb/host/u132-hcd.c
- drivers/usb/host/xhci-hub.c
- drivers/usb/musb/musb_virthub.c
- drivers/usb/wusbcore/rh.c
- include/linux/usb/ch11.h
drivers/staging/usbip/vhci_hcd.c
... | ... | @@ -255,8 +255,8 @@ |
255 | 255 | desc->wHubCharacteristics = (__force __u16) |
256 | 256 | (__constant_cpu_to_le16(0x0001)); |
257 | 257 | desc->bNbrPorts = VHCI_NPORTS; |
258 | - desc->DeviceRemovable[0] = 0xff; | |
259 | - desc->DeviceRemovable[1] = 0xff; | |
258 | + desc->u.hs.DeviceRemovable[0] = 0xff; | |
259 | + desc->u.hs.DeviceRemovable[1] = 0xff; | |
260 | 260 | } |
261 | 261 | |
262 | 262 | static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, |
drivers/usb/core/hub.c
... | ... | @@ -82,6 +82,10 @@ |
82 | 82 | void **port_owners; |
83 | 83 | }; |
84 | 84 | |
85 | +static inline int hub_is_superspeed(struct usb_device *hdev) | |
86 | +{ | |
87 | + return (hdev->descriptor.bDeviceProtocol == 3); | |
88 | +} | |
85 | 89 | |
86 | 90 | /* Protect struct usb_device->state and ->children members |
87 | 91 | * Note: Both are also protected by ->dev.sem, except that ->state can |
88 | 92 | |
89 | 93 | |
90 | 94 | |
... | ... | @@ -172,14 +176,23 @@ |
172 | 176 | } |
173 | 177 | |
174 | 178 | /* USB 2.0 spec Section 11.24.4.5 */ |
175 | -static int get_hub_descriptor(struct usb_device *hdev, void *data, int size) | |
179 | +static int get_hub_descriptor(struct usb_device *hdev, void *data) | |
176 | 180 | { |
177 | - int i, ret; | |
181 | + int i, ret, size; | |
182 | + unsigned dtype; | |
178 | 183 | |
184 | + if (hub_is_superspeed(hdev)) { | |
185 | + dtype = USB_DT_SS_HUB; | |
186 | + size = USB_DT_SS_HUB_SIZE; | |
187 | + } else { | |
188 | + dtype = USB_DT_HUB; | |
189 | + size = sizeof(struct usb_hub_descriptor); | |
190 | + } | |
191 | + | |
179 | 192 | for (i = 0; i < 3; i++) { |
180 | 193 | ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), |
181 | 194 | USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB, |
182 | - USB_DT_HUB << 8, 0, data, size, | |
195 | + dtype << 8, 0, data, size, | |
183 | 196 | USB_CTRL_GET_TIMEOUT); |
184 | 197 | if (ret >= (USB_DT_HUB_NONVAR_SIZE + 2)) |
185 | 198 | return ret; |
... | ... | @@ -365,6 +378,19 @@ |
365 | 378 | } else { |
366 | 379 | *status = le16_to_cpu(hub->status->port.wPortStatus); |
367 | 380 | *change = le16_to_cpu(hub->status->port.wPortChange); |
381 | + | |
382 | + if ((hub->hdev->parent != NULL) && | |
383 | + hub_is_superspeed(hub->hdev)) { | |
384 | + /* Translate the USB 3 port status */ | |
385 | + u16 tmp = *status & USB_SS_PORT_STAT_MASK; | |
386 | + if (*status & USB_SS_PORT_STAT_POWER) | |
387 | + tmp |= USB_PORT_STAT_POWER; | |
388 | + if ((*status & USB_SS_PORT_STAT_SPEED) == | |
389 | + USB_PORT_STAT_SPEED_5GBPS) | |
390 | + tmp |= USB_PORT_STAT_SUPER_SPEED; | |
391 | + *status = tmp; | |
392 | + } | |
393 | + | |
368 | 394 | ret = 0; |
369 | 395 | } |
370 | 396 | mutex_unlock(&hub->status_mutex); |
... | ... | @@ -607,7 +633,7 @@ |
607 | 633 | if (hdev->children[port1-1] && set_state) |
608 | 634 | usb_set_device_state(hdev->children[port1-1], |
609 | 635 | USB_STATE_NOTATTACHED); |
610 | - if (!hub->error) | |
636 | + if (!hub->error && !hub_is_superspeed(hub->hdev)) | |
611 | 637 | ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE); |
612 | 638 | if (ret) |
613 | 639 | dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", |
... | ... | @@ -795,6 +821,11 @@ |
795 | 821 | clear_port_feature(hub->hdev, port1, |
796 | 822 | USB_PORT_FEAT_C_ENABLE); |
797 | 823 | } |
824 | + if (portchange & USB_PORT_STAT_C_LINK_STATE) { | |
825 | + need_debounce_delay = true; | |
826 | + clear_port_feature(hub->hdev, port1, | |
827 | + USB_PORT_FEAT_C_PORT_LINK_STATE); | |
828 | + } | |
798 | 829 | |
799 | 830 | /* We can forget about a "removed" device when there's a |
800 | 831 | * physical disconnect or the connect status changes. |
801 | 832 | |
... | ... | @@ -964,12 +995,23 @@ |
964 | 995 | goto fail; |
965 | 996 | } |
966 | 997 | |
998 | + if (hub_is_superspeed(hdev) && (hdev->parent != NULL)) { | |
999 | + ret = usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), | |
1000 | + HUB_SET_DEPTH, USB_RT_HUB, | |
1001 | + hdev->level - 1, 0, NULL, 0, | |
1002 | + USB_CTRL_SET_TIMEOUT); | |
1003 | + | |
1004 | + if (ret < 0) { | |
1005 | + message = "can't set hub depth"; | |
1006 | + goto fail; | |
1007 | + } | |
1008 | + } | |
1009 | + | |
967 | 1010 | /* Request the entire hub descriptor. |
968 | 1011 | * hub->descriptor can handle USB_MAXCHILDREN ports, |
969 | 1012 | * but the hub can/will return fewer bytes here. |
970 | 1013 | */ |
971 | - ret = get_hub_descriptor(hdev, hub->descriptor, | |
972 | - sizeof(*hub->descriptor)); | |
1014 | + ret = get_hub_descriptor(hdev, hub->descriptor); | |
973 | 1015 | if (ret < 0) { |
974 | 1016 | message = "can't read hub descriptor"; |
975 | 1017 | goto fail; |
976 | 1018 | |
... | ... | @@ -991,12 +1033,14 @@ |
991 | 1033 | |
992 | 1034 | wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics); |
993 | 1035 | |
994 | - if (wHubCharacteristics & HUB_CHAR_COMPOUND) { | |
1036 | + /* FIXME for USB 3.0, skip for now */ | |
1037 | + if ((wHubCharacteristics & HUB_CHAR_COMPOUND) && | |
1038 | + !(hub_is_superspeed(hdev))) { | |
995 | 1039 | int i; |
996 | 1040 | char portstr [USB_MAXCHILDREN + 1]; |
997 | 1041 | |
998 | 1042 | for (i = 0; i < hdev->maxchild; i++) |
999 | - portstr[i] = hub->descriptor->DeviceRemovable | |
1043 | + portstr[i] = hub->descriptor->u.hs.DeviceRemovable | |
1000 | 1044 | [((i + 1) / 8)] & (1 << ((i + 1) % 8)) |
1001 | 1045 | ? 'F' : 'R'; |
1002 | 1046 | portstr[hdev->maxchild] = 0; |
... | ... | @@ -2029,6 +2073,8 @@ |
2029 | 2073 | udev->speed = USB_SPEED_HIGH; |
2030 | 2074 | else if (portstatus & USB_PORT_STAT_LOW_SPEED) |
2031 | 2075 | udev->speed = USB_SPEED_LOW; |
2076 | + else if (portstatus & USB_PORT_STAT_SUPER_SPEED) | |
2077 | + udev->speed = USB_SPEED_SUPER; | |
2032 | 2078 | else |
2033 | 2079 | udev->speed = USB_SPEED_FULL; |
2034 | 2080 | return 0; |
... | ... | @@ -3429,6 +3475,17 @@ |
3429 | 3475 | i); |
3430 | 3476 | clear_port_feature(hdev, i, |
3431 | 3477 | USB_PORT_FEAT_C_RESET); |
3478 | + } | |
3479 | + if (portchange & USB_PORT_STAT_C_LINK_STATE) { | |
3480 | + clear_port_feature(hub->hdev, i, | |
3481 | + USB_PORT_FEAT_C_PORT_LINK_STATE); | |
3482 | + } | |
3483 | + if (portchange & USB_PORT_STAT_C_CONFIG_ERROR) { | |
3484 | + dev_warn(hub_dev, | |
3485 | + "config error on port %d\n", | |
3486 | + i); | |
3487 | + clear_port_feature(hub->hdev, i, | |
3488 | + USB_PORT_FEAT_C_PORT_CONFIG_ERROR); | |
3432 | 3489 | } |
3433 | 3490 | |
3434 | 3491 | if (connect_change) |
drivers/usb/gadget/dummy_hcd.c
... | ... | @@ -1593,8 +1593,8 @@ |
1593 | 1593 | desc->bDescLength = 9; |
1594 | 1594 | desc->wHubCharacteristics = cpu_to_le16(0x0001); |
1595 | 1595 | desc->bNbrPorts = 1; |
1596 | - desc->DeviceRemovable[0] = 0xff; | |
1597 | - desc->DeviceRemovable[1] = 0xff; | |
1596 | + desc->u.hs.DeviceRemovable[0] = 0xff; | |
1597 | + desc->u.hs.DeviceRemovable[1] = 0xff; | |
1598 | 1598 | } |
1599 | 1599 | |
1600 | 1600 | static int dummy_hub_control ( |
drivers/usb/host/ehci-hub.c
... | ... | @@ -717,8 +717,8 @@ |
717 | 717 | desc->bDescLength = 7 + 2 * temp; |
718 | 718 | |
719 | 719 | /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ |
720 | - memset(&desc->DeviceRemovable[0], 0, temp); | |
721 | - memset(&desc->DeviceRemovable[temp], 0xff, temp); | |
720 | + memset(&desc->u.hs.DeviceRemovable[0], 0, temp); | |
721 | + memset(&desc->u.hs.DeviceRemovable[temp], 0xff, temp); | |
722 | 722 | |
723 | 723 | temp = 0x0008; /* per-port overcurrent reporting */ |
724 | 724 | if (HCS_PPC (ehci->hcs_params)) |
drivers/usb/host/imx21-hcd.c
... | ... | @@ -1472,8 +1472,8 @@ |
1472 | 1472 | 0x0010 | /* No over current protection */ |
1473 | 1473 | 0); |
1474 | 1474 | |
1475 | - desc->DeviceRemovable[0] = 1 << 1; | |
1476 | - desc->DeviceRemovable[1] = ~0; | |
1475 | + desc->u.hs.DeviceRemovable[0] = 1 << 1; | |
1476 | + desc->u.hs.DeviceRemovable[1] = ~0; | |
1477 | 1477 | return 0; |
1478 | 1478 | } |
1479 | 1479 |
drivers/usb/host/isp116x-hcd.c
... | ... | @@ -952,8 +952,8 @@ |
952 | 952 | desc->wHubCharacteristics = cpu_to_le16((u16) ((reg >> 8) & 0x1f)); |
953 | 953 | desc->bPwrOn2PwrGood = (u8) ((reg >> 24) & 0xff); |
954 | 954 | /* ports removable, and legacy PortPwrCtrlMask */ |
955 | - desc->DeviceRemovable[0] = 0; | |
956 | - desc->DeviceRemovable[1] = ~0; | |
955 | + desc->u.hs.DeviceRemovable[0] = 0; | |
956 | + desc->u.hs.DeviceRemovable[1] = ~0; | |
957 | 957 | } |
958 | 958 | |
959 | 959 | /* Perform reset of a given port. |
drivers/usb/host/isp1362-hcd.c
... | ... | @@ -1553,8 +1553,8 @@ |
1553 | 1553 | DBG(0, "%s: hubcharacteristics = %02x\n", __func__, cpu_to_le16((reg >> 8) & 0x1f)); |
1554 | 1554 | desc->bPwrOn2PwrGood = (reg >> 24) & 0xff; |
1555 | 1555 | /* ports removable, and legacy PortPwrCtrlMask */ |
1556 | - desc->DeviceRemovable[0] = desc->bNbrPorts == 1 ? 1 << 1 : 3 << 1; | |
1557 | - desc->DeviceRemovable[1] = ~0; | |
1556 | + desc->u.hs.DeviceRemovable[0] = desc->bNbrPorts == 1 ? 1 << 1 : 3 << 1; | |
1557 | + desc->u.hs.DeviceRemovable[1] = ~0; | |
1558 | 1558 | |
1559 | 1559 | DBG(3, "%s: exit\n", __func__); |
1560 | 1560 | } |
drivers/usb/host/isp1760-hcd.c
... | ... | @@ -1752,8 +1752,8 @@ |
1752 | 1752 | desc->bDescLength = 7 + 2 * temp; |
1753 | 1753 | |
1754 | 1754 | /* ports removable, and usb 1.0 legacy PortPwrCtrlMask */ |
1755 | - memset(&desc->DeviceRemovable[0], 0, temp); | |
1756 | - memset(&desc->DeviceRemovable[temp], 0xff, temp); | |
1755 | + memset(&desc->u.hs.DeviceRemovable[0], 0, temp); | |
1756 | + memset(&desc->u.hs.DeviceRemovable[temp], 0xff, temp); | |
1757 | 1757 | |
1758 | 1758 | /* per-port overcurrent reporting */ |
1759 | 1759 | temp = 0x0008; |
drivers/usb/host/ohci-hub.c
... | ... | @@ -582,13 +582,14 @@ |
582 | 582 | |
583 | 583 | /* ports removable, and usb 1.0 legacy PortPwrCtrlMask */ |
584 | 584 | rh = roothub_b (ohci); |
585 | - memset(desc->DeviceRemovable, 0xff, sizeof(desc->DeviceRemovable)); | |
586 | - desc->DeviceRemovable[0] = rh & RH_B_DR; | |
585 | + memset(desc->u.hs.DeviceRemovable, 0xff, | |
586 | + sizeof(desc->u.hs.DeviceRemovable)); | |
587 | + desc->u.hs.DeviceRemovable[0] = rh & RH_B_DR; | |
587 | 588 | if (ohci->num_ports > 7) { |
588 | - desc->DeviceRemovable[1] = (rh & RH_B_DR) >> 8; | |
589 | - desc->DeviceRemovable[2] = 0xff; | |
589 | + desc->u.hs.DeviceRemovable[1] = (rh & RH_B_DR) >> 8; | |
590 | + desc->u.hs.DeviceRemovable[2] = 0xff; | |
590 | 591 | } else |
591 | - desc->DeviceRemovable[1] = 0xff; | |
592 | + desc->u.hs.DeviceRemovable[1] = 0xff; | |
592 | 593 | } |
593 | 594 | |
594 | 595 | /*-------------------------------------------------------------------------*/ |
drivers/usb/host/oxu210hp-hcd.c
... | ... | @@ -452,8 +452,8 @@ |
452 | 452 | desc->bDescLength = 7 + 2 * temp; |
453 | 453 | |
454 | 454 | /* ports removable, and usb 1.0 legacy PortPwrCtrlMask */ |
455 | - memset(&desc->DeviceRemovable[0], 0, temp); | |
456 | - memset(&desc->DeviceRemovable[temp], 0xff, temp); | |
455 | + memset(&desc->u.hs.DeviceRemovable[0], 0, temp); | |
456 | + memset(&desc->u.hs.DeviceRemovable[temp], 0xff, temp); | |
457 | 457 | |
458 | 458 | temp = 0x0008; /* per-port overcurrent reporting */ |
459 | 459 | if (HCS_PPC(oxu->hcs_params)) |
drivers/usb/host/r8a66597-hcd.c
... | ... | @@ -2150,8 +2150,9 @@ |
2150 | 2150 | desc->bDescLength = 9; |
2151 | 2151 | desc->bPwrOn2PwrGood = 0; |
2152 | 2152 | desc->wHubCharacteristics = cpu_to_le16(0x0011); |
2153 | - desc->DeviceRemovable[0] = ((1 << r8a66597->max_root_hub) - 1) << 1; | |
2154 | - desc->DeviceRemovable[1] = ~0; | |
2153 | + desc->u.hs.DeviceRemovable[0] = | |
2154 | + ((1 << r8a66597->max_root_hub) - 1) << 1; | |
2155 | + desc->u.hs.DeviceRemovable[1] = ~0; | |
2155 | 2156 | } |
2156 | 2157 | |
2157 | 2158 | static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, |
drivers/usb/host/sl811-hcd.c
... | ... | @@ -1112,8 +1112,8 @@ |
1112 | 1112 | desc->wHubCharacteristics = cpu_to_le16(temp); |
1113 | 1113 | |
1114 | 1114 | /* ports removable, and legacy PortPwrCtrlMask */ |
1115 | - desc->DeviceRemovable[0] = 0 << 1; | |
1116 | - desc->DeviceRemovable[1] = ~0; | |
1115 | + desc->u.hs.DeviceRemovable[0] = 0 << 1; | |
1116 | + desc->u.hs.DeviceRemovable[1] = ~0; | |
1117 | 1117 | } |
1118 | 1118 | |
1119 | 1119 | static void |
drivers/usb/host/u132-hcd.c
... | ... | @@ -2604,13 +2604,14 @@ |
2604 | 2604 | retval = u132_read_pcimem(u132, roothub.b, &rh_b); |
2605 | 2605 | if (retval) |
2606 | 2606 | return retval; |
2607 | - memset(desc->DeviceRemovable, 0xff, sizeof(desc->DeviceRemovable)); | |
2608 | - desc->DeviceRemovable[0] = rh_b & RH_B_DR; | |
2607 | + memset(desc->u.hs.DeviceRemovable, 0xff, | |
2608 | + sizeof(desc->u.hs.DeviceRemovable)); | |
2609 | + desc->u.hs.DeviceRemovable[0] = rh_b & RH_B_DR; | |
2609 | 2610 | if (u132->num_ports > 7) { |
2610 | - desc->DeviceRemovable[1] = (rh_b & RH_B_DR) >> 8; | |
2611 | - desc->DeviceRemovable[2] = 0xff; | |
2611 | + desc->u.hs.DeviceRemovable[1] = (rh_b & RH_B_DR) >> 8; | |
2612 | + desc->u.hs.DeviceRemovable[2] = 0xff; | |
2612 | 2613 | } else |
2613 | - desc->DeviceRemovable[1] = 0xff; | |
2614 | + desc->u.hs.DeviceRemovable[1] = 0xff; | |
2614 | 2615 | return 0; |
2615 | 2616 | } |
2616 | 2617 |
drivers/usb/host/xhci-hub.c
... | ... | @@ -45,8 +45,8 @@ |
45 | 45 | temp = 1 + (ports / 8); |
46 | 46 | desc->bDescLength = 7 + 2 * temp; |
47 | 47 | |
48 | - memset(&desc->DeviceRemovable[0], 0, temp); | |
49 | - memset(&desc->DeviceRemovable[temp], 0xff, temp); | |
48 | + memset(&desc->u.hs.DeviceRemovable[0], 0, temp); | |
49 | + memset(&desc->u.hs.DeviceRemovable[temp], 0xff, temp); | |
50 | 50 | |
51 | 51 | /* Ugh, these should be #defines, FIXME */ |
52 | 52 | /* Using table 11-13 in USB 2.0 spec. */ |
drivers/usb/musb/musb_virthub.c
... | ... | @@ -305,8 +305,8 @@ |
305 | 305 | desc->bHubContrCurrent = 0; |
306 | 306 | |
307 | 307 | /* workaround bogus struct definition */ |
308 | - desc->DeviceRemovable[0] = 0x02; /* port 1 */ | |
309 | - desc->DeviceRemovable[1] = 0xff; | |
308 | + desc->u.hs.DeviceRemovable[0] = 0x02; /* port 1 */ | |
309 | + desc->u.hs.DeviceRemovable[1] = 0xff; | |
310 | 310 | } |
311 | 311 | break; |
312 | 312 | case GetHubStatus: |
drivers/usb/wusbcore/rh.c
... | ... | @@ -184,8 +184,8 @@ |
184 | 184 | descr->bPwrOn2PwrGood = 0; |
185 | 185 | descr->bHubContrCurrent = 0; |
186 | 186 | /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ |
187 | - memset(&descr->DeviceRemovable[0], 0, temp); | |
188 | - memset(&descr->DeviceRemovable[temp], 0xff, temp); | |
187 | + memset(&descr->u.hs.DeviceRemovable[0], 0, temp); | |
188 | + memset(&descr->u.hs.DeviceRemovable[temp], 0xff, temp); | |
189 | 189 | return 0; |
190 | 190 | } |
191 | 191 |
include/linux/usb/ch11.h
... | ... | @@ -26,6 +26,7 @@ |
26 | 26 | #define HUB_RESET_TT 9 |
27 | 27 | #define HUB_GET_TT_STATE 10 |
28 | 28 | #define HUB_STOP_TT 11 |
29 | +#define HUB_SET_DEPTH 12 | |
29 | 30 | |
30 | 31 | /* |
31 | 32 | * Hub class additional requests defined by USB 3.0 spec |
... | ... | @@ -61,6 +62,12 @@ |
61 | 62 | #define USB_PORT_FEAT_TEST 21 |
62 | 63 | #define USB_PORT_FEAT_INDICATOR 22 |
63 | 64 | #define USB_PORT_FEAT_C_PORT_L1 23 |
65 | +#define USB_PORT_FEAT_C_PORT_LINK_STATE 25 | |
66 | +#define USB_PORT_FEAT_C_PORT_CONFIG_ERROR 26 | |
67 | +#define USB_PORT_FEAT_PORT_REMOTE_WAKE_MASK 27 | |
68 | +#define USB_PORT_FEAT_BH_PORT_RESET 28 | |
69 | +#define USB_PORT_FEAT_C_BH_PORT_RESET 29 | |
70 | +#define USB_PORT_FEAT_FORCE_LINKPM_ACCEPT 30 | |
64 | 71 | |
65 | 72 | /* |
66 | 73 | * Port feature selectors added by USB 3.0 spec. |
67 | 74 | |
... | ... | @@ -110,8 +117,14 @@ |
110 | 117 | */ |
111 | 118 | #define USB_PORT_STAT_LINK_STATE 0x01e0 |
112 | 119 | #define USB_SS_PORT_STAT_POWER 0x0200 |
120 | +#define USB_SS_PORT_STAT_SPEED 0x1c00 | |
113 | 121 | #define USB_PORT_STAT_SPEED_5GBPS 0x0000 |
114 | 122 | /* Valid only if port is enabled */ |
123 | +/* Bits that are the same from USB 2.0 */ | |
124 | +#define USB_SS_PORT_STAT_MASK (USB_PORT_STAT_CONNECTION | \ | |
125 | + USB_PORT_STAT_ENABLE | \ | |
126 | + USB_PORT_STAT_OVERCURRENT | \ | |
127 | + USB_PORT_STAT_RESET) | |
115 | 128 | |
116 | 129 | /* |
117 | 130 | * Definitions for PORT_LINK_STATE values |
... | ... | @@ -141,6 +154,13 @@ |
141 | 154 | #define USB_PORT_STAT_C_OVERCURRENT 0x0008 |
142 | 155 | #define USB_PORT_STAT_C_RESET 0x0010 |
143 | 156 | #define USB_PORT_STAT_C_L1 0x0020 |
157 | +/* | |
158 | + * USB 3.0 wPortChange bit fields | |
159 | + * See USB 3.0 spec Table 10-11 | |
160 | + */ | |
161 | +#define USB_PORT_STAT_C_BH_RESET 0x0020 | |
162 | +#define USB_PORT_STAT_C_LINK_STATE 0x0040 | |
163 | +#define USB_PORT_STAT_C_CONFIG_ERROR 0x0080 | |
144 | 164 | |
145 | 165 | /* |
146 | 166 | * wHubCharacteristics (masks) |
147 | 167 | |
... | ... | @@ -175,7 +195,9 @@ |
175 | 195 | */ |
176 | 196 | |
177 | 197 | #define USB_DT_HUB (USB_TYPE_CLASS | 0x09) |
198 | +#define USB_DT_SS_HUB (USB_TYPE_CLASS | 0x0a) | |
178 | 199 | #define USB_DT_HUB_NONVAR_SIZE 7 |
200 | +#define USB_DT_SS_HUB_SIZE 12 | |
179 | 201 | |
180 | 202 | struct usb_hub_descriptor { |
181 | 203 | __u8 bDescLength; |
182 | 204 | |
... | ... | @@ -184,11 +206,22 @@ |
184 | 206 | __le16 wHubCharacteristics; |
185 | 207 | __u8 bPwrOn2PwrGood; |
186 | 208 | __u8 bHubContrCurrent; |
187 | - /* add 1 bit for hub status change; round to bytes */ | |
188 | - __u8 DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8]; | |
189 | - __u8 PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8]; | |
190 | -} __attribute__ ((packed)); | |
191 | 209 | |
210 | + /* 2.0 and 3.0 hubs differ here */ | |
211 | + union { | |
212 | + struct { | |
213 | + /* add 1 bit for hub status change; round to bytes */ | |
214 | + __u8 DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8]; | |
215 | + __u8 PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8]; | |
216 | + } __attribute__ ((packed)) hs; | |
217 | + | |
218 | + struct { | |
219 | + __u8 bHubHdrDecLat; | |
220 | + __u16 wHubDelay; | |
221 | + __u16 DeviceRemovable; | |
222 | + } __attribute__ ((packed)) ss; | |
223 | + } u; | |
224 | +} __attribute__ ((packed)); | |
192 | 225 | |
193 | 226 | /* port indicator status selectors, tables 11-7 and 11-25 */ |
194 | 227 | #define HUB_LED_AUTO 0 |