aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/hub.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/core/hub.c')
-rw-r--r--drivers/usb/core/hub.c73
1 files changed, 65 insertions, 8 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index b574f9131b4..feb6e596c7c 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -82,6 +82,10 @@ struct usb_hub {
82 void **port_owners; 82 void **port_owners;
83}; 83};
84 84
85static inline int hub_is_superspeed(struct usb_device *hdev)
86{
87 return (hdev->descriptor.bDeviceProtocol == 3);
88}
85 89
86/* Protect struct usb_device->state and ->children members 90/* Protect struct usb_device->state and ->children members
87 * Note: Both are also protected by ->dev.sem, except that ->state can 91 * Note: Both are also protected by ->dev.sem, except that ->state can
@@ -172,14 +176,23 @@ static struct usb_hub *hdev_to_hub(struct usb_device *hdev)
172} 176}
173 177
174/* USB 2.0 spec Section 11.24.4.5 */ 178/* USB 2.0 spec Section 11.24.4.5 */
175static int get_hub_descriptor(struct usb_device *hdev, void *data, int size) 179static int get_hub_descriptor(struct usb_device *hdev, void *data)
176{ 180{
177 int i, ret; 181 int i, ret, size;
182 unsigned dtype;
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 }
178 191
179 for (i = 0; i < 3; i++) { 192 for (i = 0; i < 3; i++) {
180 ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), 193 ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
181 USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB, 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 USB_CTRL_GET_TIMEOUT); 196 USB_CTRL_GET_TIMEOUT);
184 if (ret >= (USB_DT_HUB_NONVAR_SIZE + 2)) 197 if (ret >= (USB_DT_HUB_NONVAR_SIZE + 2))
185 return ret; 198 return ret;
@@ -365,6 +378,19 @@ static int hub_port_status(struct usb_hub *hub, int port1,
365 } else { 378 } else {
366 *status = le16_to_cpu(hub->status->port.wPortStatus); 379 *status = le16_to_cpu(hub->status->port.wPortStatus);
367 *change = le16_to_cpu(hub->status->port.wPortChange); 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 ret = 0; 394 ret = 0;
369 } 395 }
370 mutex_unlock(&hub->status_mutex); 396 mutex_unlock(&hub->status_mutex);
@@ -607,7 +633,7 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
607 if (hdev->children[port1-1] && set_state) 633 if (hdev->children[port1-1] && set_state)
608 usb_set_device_state(hdev->children[port1-1], 634 usb_set_device_state(hdev->children[port1-1],
609 USB_STATE_NOTATTACHED); 635 USB_STATE_NOTATTACHED);
610 if (!hub->error) 636 if (!hub->error && !hub_is_superspeed(hub->hdev))
611 ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE); 637 ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
612 if (ret) 638 if (ret)
613 dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", 639 dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
@@ -795,6 +821,11 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
795 clear_port_feature(hub->hdev, port1, 821 clear_port_feature(hub->hdev, port1,
796 USB_PORT_FEAT_C_ENABLE); 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 /* We can forget about a "removed" device when there's a 830 /* We can forget about a "removed" device when there's a
800 * physical disconnect or the connect status changes. 831 * physical disconnect or the connect status changes.
@@ -964,12 +995,23 @@ static int hub_configure(struct usb_hub *hub,
964 goto fail; 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 /* Request the entire hub descriptor. 1010 /* Request the entire hub descriptor.
968 * hub->descriptor can handle USB_MAXCHILDREN ports, 1011 * hub->descriptor can handle USB_MAXCHILDREN ports,
969 * but the hub can/will return fewer bytes here. 1012 * but the hub can/will return fewer bytes here.
970 */ 1013 */
971 ret = get_hub_descriptor(hdev, hub->descriptor, 1014 ret = get_hub_descriptor(hdev, hub->descriptor);
972 sizeof(*hub->descriptor));
973 if (ret < 0) { 1015 if (ret < 0) {
974 message = "can't read hub descriptor"; 1016 message = "can't read hub descriptor";
975 goto fail; 1017 goto fail;
@@ -991,12 +1033,14 @@ static int hub_configure(struct usb_hub *hub,
991 1033
992 wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics); 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 int i; 1039 int i;
996 char portstr [USB_MAXCHILDREN + 1]; 1040 char portstr [USB_MAXCHILDREN + 1];
997 1041
998 for (i = 0; i < hdev->maxchild; i++) 1042 for (i = 0; i < hdev->maxchild; i++)
999 portstr[i] = hub->descriptor->DeviceRemovable 1043 portstr[i] = hub->descriptor->u.hs.DeviceRemovable
1000 [((i + 1) / 8)] & (1 << ((i + 1) % 8)) 1044 [((i + 1) / 8)] & (1 << ((i + 1) % 8))
1001 ? 'F' : 'R'; 1045 ? 'F' : 'R';
1002 portstr[hdev->maxchild] = 0; 1046 portstr[hdev->maxchild] = 0;
@@ -2029,6 +2073,8 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
2029 udev->speed = USB_SPEED_HIGH; 2073 udev->speed = USB_SPEED_HIGH;
2030 else if (portstatus & USB_PORT_STAT_LOW_SPEED) 2074 else if (portstatus & USB_PORT_STAT_LOW_SPEED)
2031 udev->speed = USB_SPEED_LOW; 2075 udev->speed = USB_SPEED_LOW;
2076 else if (portstatus & USB_PORT_STAT_SUPER_SPEED)
2077 udev->speed = USB_SPEED_SUPER;
2032 else 2078 else
2033 udev->speed = USB_SPEED_FULL; 2079 udev->speed = USB_SPEED_FULL;
2034 return 0; 2080 return 0;
@@ -3430,6 +3476,17 @@ static void hub_events(void)
3430 clear_port_feature(hdev, i, 3476 clear_port_feature(hdev, i,
3431 USB_PORT_FEAT_C_RESET); 3477 USB_PORT_FEAT_C_RESET);
3432 } 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);
3489 }
3433 3490
3434 if (connect_change) 3491 if (connect_change)
3435 hub_port_connect_change(hub, i, 3492 hub_port_connect_change(hub, i,