diff options
Diffstat (limited to 'drivers/usb/core/hub.c')
-rw-r--r-- | drivers/usb/core/hub.c | 616 |
1 files changed, 344 insertions, 272 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index cbf7168e3ce7..1775ad471edd 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -26,11 +26,12 @@ | |||
26 | #include <linux/mutex.h> | 26 | #include <linux/mutex.h> |
27 | #include <linux/freezer.h> | 27 | #include <linux/freezer.h> |
28 | #include <linux/random.h> | 28 | #include <linux/random.h> |
29 | #include <linux/pm_qos.h> | ||
29 | 30 | ||
30 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
31 | #include <asm/byteorder.h> | 32 | #include <asm/byteorder.h> |
32 | 33 | ||
33 | #include "usb.h" | 34 | #include "hub.h" |
34 | 35 | ||
35 | /* if we are in debug mode, always announce new devices */ | 36 | /* if we are in debug mode, always announce new devices */ |
36 | #ifdef DEBUG | 37 | #ifdef DEBUG |
@@ -42,62 +43,6 @@ | |||
42 | #define USB_VENDOR_GENESYS_LOGIC 0x05e3 | 43 | #define USB_VENDOR_GENESYS_LOGIC 0x05e3 |
43 | #define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND 0x01 | 44 | #define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND 0x01 |
44 | 45 | ||
45 | struct usb_port { | ||
46 | struct usb_device *child; | ||
47 | struct device dev; | ||
48 | struct dev_state *port_owner; | ||
49 | enum usb_port_connect_type connect_type; | ||
50 | }; | ||
51 | |||
52 | struct usb_hub { | ||
53 | struct device *intfdev; /* the "interface" device */ | ||
54 | struct usb_device *hdev; | ||
55 | struct kref kref; | ||
56 | struct urb *urb; /* for interrupt polling pipe */ | ||
57 | |||
58 | /* buffer for urb ... with extra space in case of babble */ | ||
59 | char (*buffer)[8]; | ||
60 | union { | ||
61 | struct usb_hub_status hub; | ||
62 | struct usb_port_status port; | ||
63 | } *status; /* buffer for status reports */ | ||
64 | struct mutex status_mutex; /* for the status buffer */ | ||
65 | |||
66 | int error; /* last reported error */ | ||
67 | int nerrors; /* track consecutive errors */ | ||
68 | |||
69 | struct list_head event_list; /* hubs w/data or errs ready */ | ||
70 | unsigned long event_bits[1]; /* status change bitmask */ | ||
71 | unsigned long change_bits[1]; /* ports with logical connect | ||
72 | status change */ | ||
73 | unsigned long busy_bits[1]; /* ports being reset or | ||
74 | resumed */ | ||
75 | unsigned long removed_bits[1]; /* ports with a "removed" | ||
76 | device present */ | ||
77 | unsigned long wakeup_bits[1]; /* ports that have signaled | ||
78 | remote wakeup */ | ||
79 | #if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */ | ||
80 | #error event_bits[] is too short! | ||
81 | #endif | ||
82 | |||
83 | struct usb_hub_descriptor *descriptor; /* class descriptor */ | ||
84 | struct usb_tt tt; /* Transaction Translator */ | ||
85 | |||
86 | unsigned mA_per_port; /* current for each child */ | ||
87 | |||
88 | unsigned limited_power:1; | ||
89 | unsigned quiescing:1; | ||
90 | unsigned disconnected:1; | ||
91 | |||
92 | unsigned quirk_check_port_auto_suspend:1; | ||
93 | |||
94 | unsigned has_indicators:1; | ||
95 | u8 indicator[USB_MAXCHILDREN]; | ||
96 | struct delayed_work leds; | ||
97 | struct delayed_work init_work; | ||
98 | struct usb_port **ports; | ||
99 | }; | ||
100 | |||
101 | static inline int hub_is_superspeed(struct usb_device *hdev) | 46 | static inline int hub_is_superspeed(struct usb_device *hdev) |
102 | { | 47 | { |
103 | return (hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS); | 48 | return (hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS); |
@@ -164,13 +109,10 @@ MODULE_PARM_DESC(use_both_schemes, | |||
164 | DECLARE_RWSEM(ehci_cf_port_reset_rwsem); | 109 | DECLARE_RWSEM(ehci_cf_port_reset_rwsem); |
165 | EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem); | 110 | EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem); |
166 | 111 | ||
167 | #define HUB_DEBOUNCE_TIMEOUT 1500 | 112 | #define HUB_DEBOUNCE_TIMEOUT 2000 |
168 | #define HUB_DEBOUNCE_STEP 25 | 113 | #define HUB_DEBOUNCE_STEP 25 |
169 | #define HUB_DEBOUNCE_STABLE 100 | 114 | #define HUB_DEBOUNCE_STABLE 100 |
170 | 115 | ||
171 | #define to_usb_port(_dev) \ | ||
172 | container_of(_dev, struct usb_port, dev) | ||
173 | |||
174 | static int usb_reset_and_verify_device(struct usb_device *udev); | 116 | static int usb_reset_and_verify_device(struct usb_device *udev); |
175 | 117 | ||
176 | static inline char *portspeed(struct usb_hub *hub, int portstatus) | 118 | static inline char *portspeed(struct usb_hub *hub, int portstatus) |
@@ -186,7 +128,7 @@ static inline char *portspeed(struct usb_hub *hub, int portstatus) | |||
186 | } | 128 | } |
187 | 129 | ||
188 | /* Note that hdev or one of its children must be locked! */ | 130 | /* Note that hdev or one of its children must be locked! */ |
189 | static struct usb_hub *hdev_to_hub(struct usb_device *hdev) | 131 | struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev) |
190 | { | 132 | { |
191 | if (!hdev || !hdev->actconfig || !hdev->maxchild) | 133 | if (!hdev || !hdev->actconfig || !hdev->maxchild) |
192 | return NULL; | 134 | return NULL; |
@@ -360,7 +302,7 @@ static void usb_set_lpm_parameters(struct usb_device *udev) | |||
360 | if (!udev->lpm_capable || udev->speed != USB_SPEED_SUPER) | 302 | if (!udev->lpm_capable || udev->speed != USB_SPEED_SUPER) |
361 | return; | 303 | return; |
362 | 304 | ||
363 | hub = hdev_to_hub(udev->parent); | 305 | hub = usb_hub_to_struct_hub(udev->parent); |
364 | /* It doesn't take time to transition the roothub into U0, since it | 306 | /* It doesn't take time to transition the roothub into U0, since it |
365 | * doesn't have an upstream link. | 307 | * doesn't have an upstream link. |
366 | */ | 308 | */ |
@@ -452,7 +394,7 @@ static int clear_hub_feature(struct usb_device *hdev, int feature) | |||
452 | /* | 394 | /* |
453 | * USB 2.0 spec Section 11.24.2.2 | 395 | * USB 2.0 spec Section 11.24.2.2 |
454 | */ | 396 | */ |
455 | static int clear_port_feature(struct usb_device *hdev, int port1, int feature) | 397 | int usb_clear_port_feature(struct usb_device *hdev, int port1, int feature) |
456 | { | 398 | { |
457 | return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), | 399 | return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), |
458 | USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port1, | 400 | USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port1, |
@@ -645,7 +587,7 @@ static void kick_khubd(struct usb_hub *hub) | |||
645 | 587 | ||
646 | void usb_kick_khubd(struct usb_device *hdev) | 588 | void usb_kick_khubd(struct usb_device *hdev) |
647 | { | 589 | { |
648 | struct usb_hub *hub = hdev_to_hub(hdev); | 590 | struct usb_hub *hub = usb_hub_to_struct_hub(hdev); |
649 | 591 | ||
650 | if (hub) | 592 | if (hub) |
651 | kick_khubd(hub); | 593 | kick_khubd(hub); |
@@ -667,7 +609,7 @@ void usb_wakeup_notification(struct usb_device *hdev, | |||
667 | if (!hdev) | 609 | if (!hdev) |
668 | return; | 610 | return; |
669 | 611 | ||
670 | hub = hdev_to_hub(hdev); | 612 | hub = usb_hub_to_struct_hub(hdev); |
671 | if (hub) { | 613 | if (hub) { |
672 | set_bit(portnum, hub->wakeup_bits); | 614 | set_bit(portnum, hub->wakeup_bits); |
673 | kick_khubd(hub); | 615 | kick_khubd(hub); |
@@ -774,6 +716,32 @@ static void hub_tt_work(struct work_struct *work) | |||
774 | } | 716 | } |
775 | 717 | ||
776 | /** | 718 | /** |
719 | * usb_hub_set_port_power - control hub port's power state | ||
720 | * @hdev: target hub | ||
721 | * @port1: port index | ||
722 | * @set: expected status | ||
723 | * | ||
724 | * call this function to control port's power via setting or | ||
725 | * clearing the port's PORT_POWER feature. | ||
726 | */ | ||
727 | int usb_hub_set_port_power(struct usb_device *hdev, int port1, | ||
728 | bool set) | ||
729 | { | ||
730 | int ret; | ||
731 | struct usb_hub *hub = usb_hub_to_struct_hub(hdev); | ||
732 | struct usb_port *port_dev = hub->ports[port1 - 1]; | ||
733 | |||
734 | if (set) | ||
735 | ret = set_port_feature(hdev, port1, USB_PORT_FEAT_POWER); | ||
736 | else | ||
737 | ret = usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_POWER); | ||
738 | |||
739 | if (!ret) | ||
740 | port_dev->power_is_on = set; | ||
741 | return ret; | ||
742 | } | ||
743 | |||
744 | /** | ||
777 | * usb_hub_clear_tt_buffer - clear control/bulk TT state in high speed hub | 745 | * usb_hub_clear_tt_buffer - clear control/bulk TT state in high speed hub |
778 | * @urb: an URB associated with the failed or incomplete split transaction | 746 | * @urb: an URB associated with the failed or incomplete split transaction |
779 | * | 747 | * |
@@ -849,7 +817,11 @@ static unsigned hub_power_on(struct usb_hub *hub, bool do_delay) | |||
849 | dev_dbg(hub->intfdev, "trying to enable port power on " | 817 | dev_dbg(hub->intfdev, "trying to enable port power on " |
850 | "non-switchable hub\n"); | 818 | "non-switchable hub\n"); |
851 | for (port1 = 1; port1 <= hub->descriptor->bNbrPorts; port1++) | 819 | for (port1 = 1; port1 <= hub->descriptor->bNbrPorts; port1++) |
852 | set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER); | 820 | if (hub->ports[port1 - 1]->power_is_on) |
821 | set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER); | ||
822 | else | ||
823 | usb_clear_port_feature(hub->hdev, port1, | ||
824 | USB_PORT_FEAT_POWER); | ||
853 | 825 | ||
854 | /* Wait at least 100 msec for power to become stable */ | 826 | /* Wait at least 100 msec for power to become stable */ |
855 | delay = max(pgood_delay, (unsigned) 100); | 827 | delay = max(pgood_delay, (unsigned) 100); |
@@ -943,7 +915,7 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) | |||
943 | if (hub_is_superspeed(hub->hdev)) | 915 | if (hub_is_superspeed(hub->hdev)) |
944 | ret = hub_usb3_port_disable(hub, port1); | 916 | ret = hub_usb3_port_disable(hub, port1); |
945 | else | 917 | else |
946 | ret = clear_port_feature(hdev, port1, | 918 | ret = usb_clear_port_feature(hdev, port1, |
947 | USB_PORT_FEAT_ENABLE); | 919 | USB_PORT_FEAT_ENABLE); |
948 | } | 920 | } |
949 | if (ret) | 921 | if (ret) |
@@ -992,7 +964,7 @@ int usb_remove_device(struct usb_device *udev) | |||
992 | 964 | ||
993 | if (!udev->parent) /* Can't remove a root hub */ | 965 | if (!udev->parent) /* Can't remove a root hub */ |
994 | return -EINVAL; | 966 | return -EINVAL; |
995 | hub = hdev_to_hub(udev->parent); | 967 | hub = usb_hub_to_struct_hub(udev->parent); |
996 | intf = to_usb_interface(hub->intfdev); | 968 | intf = to_usb_interface(hub->intfdev); |
997 | 969 | ||
998 | usb_autopm_get_interface(intf); | 970 | usb_autopm_get_interface(intf); |
@@ -1124,7 +1096,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) | |||
1124 | * Do not disable USB3 protocol ports. | 1096 | * Do not disable USB3 protocol ports. |
1125 | */ | 1097 | */ |
1126 | if (!hub_is_superspeed(hdev)) { | 1098 | if (!hub_is_superspeed(hdev)) { |
1127 | clear_port_feature(hdev, port1, | 1099 | usb_clear_port_feature(hdev, port1, |
1128 | USB_PORT_FEAT_ENABLE); | 1100 | USB_PORT_FEAT_ENABLE); |
1129 | portstatus &= ~USB_PORT_STAT_ENABLE; | 1101 | portstatus &= ~USB_PORT_STAT_ENABLE; |
1130 | } else { | 1102 | } else { |
@@ -1136,18 +1108,18 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) | |||
1136 | /* Clear status-change flags; we'll debounce later */ | 1108 | /* Clear status-change flags; we'll debounce later */ |
1137 | if (portchange & USB_PORT_STAT_C_CONNECTION) { | 1109 | if (portchange & USB_PORT_STAT_C_CONNECTION) { |
1138 | need_debounce_delay = true; | 1110 | need_debounce_delay = true; |
1139 | clear_port_feature(hub->hdev, port1, | 1111 | usb_clear_port_feature(hub->hdev, port1, |
1140 | USB_PORT_FEAT_C_CONNECTION); | 1112 | USB_PORT_FEAT_C_CONNECTION); |
1141 | } | 1113 | } |
1142 | if (portchange & USB_PORT_STAT_C_ENABLE) { | 1114 | if (portchange & USB_PORT_STAT_C_ENABLE) { |
1143 | need_debounce_delay = true; | 1115 | need_debounce_delay = true; |
1144 | clear_port_feature(hub->hdev, port1, | 1116 | usb_clear_port_feature(hub->hdev, port1, |
1145 | USB_PORT_FEAT_C_ENABLE); | 1117 | USB_PORT_FEAT_C_ENABLE); |
1146 | } | 1118 | } |
1147 | if ((portchange & USB_PORT_STAT_C_BH_RESET) && | 1119 | if ((portchange & USB_PORT_STAT_C_BH_RESET) && |
1148 | hub_is_superspeed(hub->hdev)) { | 1120 | hub_is_superspeed(hub->hdev)) { |
1149 | need_debounce_delay = true; | 1121 | need_debounce_delay = true; |
1150 | clear_port_feature(hub->hdev, port1, | 1122 | usb_clear_port_feature(hub->hdev, port1, |
1151 | USB_PORT_FEAT_C_BH_PORT_RESET); | 1123 | USB_PORT_FEAT_C_BH_PORT_RESET); |
1152 | } | 1124 | } |
1153 | /* We can forget about a "removed" device when there's a | 1125 | /* We can forget about a "removed" device when there's a |
@@ -1181,10 +1153,16 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) | |||
1181 | set_bit(port1, hub->change_bits); | 1153 | set_bit(port1, hub->change_bits); |
1182 | 1154 | ||
1183 | } else if (udev->persist_enabled) { | 1155 | } else if (udev->persist_enabled) { |
1156 | struct usb_port *port_dev = hub->ports[port1 - 1]; | ||
1157 | |||
1184 | #ifdef CONFIG_PM | 1158 | #ifdef CONFIG_PM |
1185 | udev->reset_resume = 1; | 1159 | udev->reset_resume = 1; |
1186 | #endif | 1160 | #endif |
1187 | set_bit(port1, hub->change_bits); | 1161 | /* Don't set the change_bits when the device |
1162 | * was powered off. | ||
1163 | */ | ||
1164 | if (port_dev->power_is_on) | ||
1165 | set_bit(port1, hub->change_bits); | ||
1188 | 1166 | ||
1189 | } else { | 1167 | } else { |
1190 | /* The power session is gone; tell khubd */ | 1168 | /* The power session is gone; tell khubd */ |
@@ -1294,52 +1272,6 @@ static int hub_post_reset(struct usb_interface *intf) | |||
1294 | return 0; | 1272 | return 0; |
1295 | } | 1273 | } |
1296 | 1274 | ||
1297 | static void usb_port_device_release(struct device *dev) | ||
1298 | { | ||
1299 | struct usb_port *port_dev = to_usb_port(dev); | ||
1300 | |||
1301 | kfree(port_dev); | ||
1302 | } | ||
1303 | |||
1304 | static void usb_hub_remove_port_device(struct usb_hub *hub, | ||
1305 | int port1) | ||
1306 | { | ||
1307 | device_unregister(&hub->ports[port1 - 1]->dev); | ||
1308 | } | ||
1309 | |||
1310 | struct device_type usb_port_device_type = { | ||
1311 | .name = "usb_port", | ||
1312 | .release = usb_port_device_release, | ||
1313 | }; | ||
1314 | |||
1315 | static int usb_hub_create_port_device(struct usb_hub *hub, | ||
1316 | int port1) | ||
1317 | { | ||
1318 | struct usb_port *port_dev = NULL; | ||
1319 | int retval; | ||
1320 | |||
1321 | port_dev = kzalloc(sizeof(*port_dev), GFP_KERNEL); | ||
1322 | if (!port_dev) { | ||
1323 | retval = -ENOMEM; | ||
1324 | goto exit; | ||
1325 | } | ||
1326 | |||
1327 | hub->ports[port1 - 1] = port_dev; | ||
1328 | port_dev->dev.parent = hub->intfdev; | ||
1329 | port_dev->dev.type = &usb_port_device_type; | ||
1330 | dev_set_name(&port_dev->dev, "port%d", port1); | ||
1331 | |||
1332 | retval = device_register(&port_dev->dev); | ||
1333 | if (retval) | ||
1334 | goto error_register; | ||
1335 | return 0; | ||
1336 | |||
1337 | error_register: | ||
1338 | put_device(&port_dev->dev); | ||
1339 | exit: | ||
1340 | return retval; | ||
1341 | } | ||
1342 | |||
1343 | static int hub_configure(struct usb_hub *hub, | 1275 | static int hub_configure(struct usb_hub *hub, |
1344 | struct usb_endpoint_descriptor *endpoint) | 1276 | struct usb_endpoint_descriptor *endpoint) |
1345 | { | 1277 | { |
@@ -1351,6 +1283,8 @@ static int hub_configure(struct usb_hub *hub, | |||
1351 | unsigned int pipe; | 1283 | unsigned int pipe; |
1352 | int maxp, ret, i; | 1284 | int maxp, ret, i; |
1353 | char *message = "out of memory"; | 1285 | char *message = "out of memory"; |
1286 | unsigned unit_load; | ||
1287 | unsigned full_load; | ||
1354 | 1288 | ||
1355 | hub->buffer = kmalloc(sizeof(*hub->buffer), GFP_KERNEL); | 1289 | hub->buffer = kmalloc(sizeof(*hub->buffer), GFP_KERNEL); |
1356 | if (!hub->buffer) { | 1290 | if (!hub->buffer) { |
@@ -1397,6 +1331,13 @@ static int hub_configure(struct usb_hub *hub, | |||
1397 | } | 1331 | } |
1398 | 1332 | ||
1399 | wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics); | 1333 | wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics); |
1334 | if (hub_is_superspeed(hdev)) { | ||
1335 | unit_load = 150; | ||
1336 | full_load = 900; | ||
1337 | } else { | ||
1338 | unit_load = 100; | ||
1339 | full_load = 500; | ||
1340 | } | ||
1400 | 1341 | ||
1401 | /* FIXME for USB 3.0, skip for now */ | 1342 | /* FIXME for USB 3.0, skip for now */ |
1402 | if ((wHubCharacteristics & HUB_CHAR_COMPOUND) && | 1343 | if ((wHubCharacteristics & HUB_CHAR_COMPOUND) && |
@@ -1516,40 +1457,44 @@ static int hub_configure(struct usb_hub *hub, | |||
1516 | goto fail; | 1457 | goto fail; |
1517 | } | 1458 | } |
1518 | le16_to_cpus(&hubstatus); | 1459 | le16_to_cpus(&hubstatus); |
1460 | hcd = bus_to_hcd(hdev->bus); | ||
1519 | if (hdev == hdev->bus->root_hub) { | 1461 | if (hdev == hdev->bus->root_hub) { |
1520 | if (hdev->bus_mA == 0 || hdev->bus_mA >= 500) | 1462 | if (hcd->power_budget > 0) |
1521 | hub->mA_per_port = 500; | 1463 | hdev->bus_mA = hcd->power_budget; |
1464 | else | ||
1465 | hdev->bus_mA = full_load * hdev->maxchild; | ||
1466 | if (hdev->bus_mA >= full_load) | ||
1467 | hub->mA_per_port = full_load; | ||
1522 | else { | 1468 | else { |
1523 | hub->mA_per_port = hdev->bus_mA; | 1469 | hub->mA_per_port = hdev->bus_mA; |
1524 | hub->limited_power = 1; | 1470 | hub->limited_power = 1; |
1525 | } | 1471 | } |
1526 | } else if ((hubstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0) { | 1472 | } else if ((hubstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0) { |
1473 | int remaining = hdev->bus_mA - | ||
1474 | hub->descriptor->bHubContrCurrent; | ||
1475 | |||
1527 | dev_dbg(hub_dev, "hub controller current requirement: %dmA\n", | 1476 | dev_dbg(hub_dev, "hub controller current requirement: %dmA\n", |
1528 | hub->descriptor->bHubContrCurrent); | 1477 | hub->descriptor->bHubContrCurrent); |
1529 | hub->limited_power = 1; | 1478 | hub->limited_power = 1; |
1530 | if (hdev->maxchild > 0) { | ||
1531 | int remaining = hdev->bus_mA - | ||
1532 | hub->descriptor->bHubContrCurrent; | ||
1533 | 1479 | ||
1534 | if (remaining < hdev->maxchild * 100) | 1480 | if (remaining < hdev->maxchild * unit_load) |
1535 | dev_warn(hub_dev, | 1481 | dev_warn(hub_dev, |
1536 | "insufficient power available " | 1482 | "insufficient power available " |
1537 | "to use all downstream ports\n"); | 1483 | "to use all downstream ports\n"); |
1538 | hub->mA_per_port = 100; /* 7.2.1.1 */ | 1484 | hub->mA_per_port = unit_load; /* 7.2.1 */ |
1539 | } | 1485 | |
1540 | } else { /* Self-powered external hub */ | 1486 | } else { /* Self-powered external hub */ |
1541 | /* FIXME: What about battery-powered external hubs that | 1487 | /* FIXME: What about battery-powered external hubs that |
1542 | * provide less current per port? */ | 1488 | * provide less current per port? */ |
1543 | hub->mA_per_port = 500; | 1489 | hub->mA_per_port = full_load; |
1544 | } | 1490 | } |
1545 | if (hub->mA_per_port < 500) | 1491 | if (hub->mA_per_port < full_load) |
1546 | dev_dbg(hub_dev, "%umA bus power budget for each child\n", | 1492 | dev_dbg(hub_dev, "%umA bus power budget for each child\n", |
1547 | hub->mA_per_port); | 1493 | hub->mA_per_port); |
1548 | 1494 | ||
1549 | /* Update the HCD's internal representation of this hub before khubd | 1495 | /* Update the HCD's internal representation of this hub before khubd |
1550 | * starts getting port status changes for devices under the hub. | 1496 | * starts getting port status changes for devices under the hub. |
1551 | */ | 1497 | */ |
1552 | hcd = bus_to_hcd(hdev->bus); | ||
1553 | if (hcd->driver->update_hub_device) { | 1498 | if (hcd->driver->update_hub_device) { |
1554 | ret = hcd->driver->update_hub_device(hcd, hdev, | 1499 | ret = hcd->driver->update_hub_device(hcd, hdev, |
1555 | &hub->tt, GFP_KERNEL); | 1500 | &hub->tt, GFP_KERNEL); |
@@ -1605,6 +1550,8 @@ static int hub_configure(struct usb_hub *hub, | |||
1605 | dev_err(hub->intfdev, | 1550 | dev_err(hub->intfdev, |
1606 | "couldn't create port%d device.\n", i + 1); | 1551 | "couldn't create port%d device.\n", i + 1); |
1607 | 1552 | ||
1553 | usb_hub_adjust_deviceremovable(hdev, hub->descriptor); | ||
1554 | |||
1608 | hub_activate(hub, HUB_INIT); | 1555 | hub_activate(hub, HUB_INIT); |
1609 | return 0; | 1556 | return 0; |
1610 | 1557 | ||
@@ -1659,6 +1606,7 @@ static void hub_disconnect(struct usb_interface *intf) | |||
1659 | kfree(hub->status); | 1606 | kfree(hub->status); |
1660 | kfree(hub->buffer); | 1607 | kfree(hub->buffer); |
1661 | 1608 | ||
1609 | pm_suspend_ignore_children(&intf->dev, false); | ||
1662 | kref_put(&hub->kref, hub_release); | 1610 | kref_put(&hub->kref, hub_release); |
1663 | } | 1611 | } |
1664 | 1612 | ||
@@ -1761,6 +1709,7 @@ descriptor_error: | |||
1761 | 1709 | ||
1762 | usb_set_intfdata (intf, hub); | 1710 | usb_set_intfdata (intf, hub); |
1763 | intf->needs_remote_wakeup = 1; | 1711 | intf->needs_remote_wakeup = 1; |
1712 | pm_suspend_ignore_children(&intf->dev, true); | ||
1764 | 1713 | ||
1765 | if (hdev->speed == USB_SPEED_HIGH) | 1714 | if (hdev->speed == USB_SPEED_HIGH) |
1766 | highspeed_hubs++; | 1715 | highspeed_hubs++; |
@@ -1779,7 +1728,7 @@ static int | |||
1779 | hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data) | 1728 | hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data) |
1780 | { | 1729 | { |
1781 | struct usb_device *hdev = interface_to_usbdev (intf); | 1730 | struct usb_device *hdev = interface_to_usbdev (intf); |
1782 | struct usb_hub *hub = hdev_to_hub(hdev); | 1731 | struct usb_hub *hub = usb_hub_to_struct_hub(hdev); |
1783 | 1732 | ||
1784 | /* assert ifno == 0 (part of hub spec) */ | 1733 | /* assert ifno == 0 (part of hub spec) */ |
1785 | switch (code) { | 1734 | switch (code) { |
@@ -1825,7 +1774,7 @@ static int find_port_owner(struct usb_device *hdev, unsigned port1, | |||
1825 | /* This assumes that devices not managed by the hub driver | 1774 | /* This assumes that devices not managed by the hub driver |
1826 | * will always have maxchild equal to 0. | 1775 | * will always have maxchild equal to 0. |
1827 | */ | 1776 | */ |
1828 | *ppowner = &(hdev_to_hub(hdev)->ports[port1 - 1]->port_owner); | 1777 | *ppowner = &(usb_hub_to_struct_hub(hdev)->ports[port1 - 1]->port_owner); |
1829 | return 0; | 1778 | return 0; |
1830 | } | 1779 | } |
1831 | 1780 | ||
@@ -1862,7 +1811,7 @@ int usb_hub_release_port(struct usb_device *hdev, unsigned port1, | |||
1862 | 1811 | ||
1863 | void usb_hub_release_all_ports(struct usb_device *hdev, struct dev_state *owner) | 1812 | void usb_hub_release_all_ports(struct usb_device *hdev, struct dev_state *owner) |
1864 | { | 1813 | { |
1865 | struct usb_hub *hub = hdev_to_hub(hdev); | 1814 | struct usb_hub *hub = usb_hub_to_struct_hub(hdev); |
1866 | int n; | 1815 | int n; |
1867 | 1816 | ||
1868 | for (n = 0; n < hdev->maxchild; n++) { | 1817 | for (n = 0; n < hdev->maxchild; n++) { |
@@ -1879,13 +1828,13 @@ bool usb_device_is_owned(struct usb_device *udev) | |||
1879 | 1828 | ||
1880 | if (udev->state == USB_STATE_NOTATTACHED || !udev->parent) | 1829 | if (udev->state == USB_STATE_NOTATTACHED || !udev->parent) |
1881 | return false; | 1830 | return false; |
1882 | hub = hdev_to_hub(udev->parent); | 1831 | hub = usb_hub_to_struct_hub(udev->parent); |
1883 | return !!hub->ports[udev->portnum - 1]->port_owner; | 1832 | return !!hub->ports[udev->portnum - 1]->port_owner; |
1884 | } | 1833 | } |
1885 | 1834 | ||
1886 | static void recursively_mark_NOTATTACHED(struct usb_device *udev) | 1835 | static void recursively_mark_NOTATTACHED(struct usb_device *udev) |
1887 | { | 1836 | { |
1888 | struct usb_hub *hub = hdev_to_hub(udev); | 1837 | struct usb_hub *hub = usb_hub_to_struct_hub(udev); |
1889 | int i; | 1838 | int i; |
1890 | 1839 | ||
1891 | for (i = 0; i < udev->maxchild; ++i) { | 1840 | for (i = 0; i < udev->maxchild; ++i) { |
@@ -2054,7 +2003,7 @@ static void hub_free_dev(struct usb_device *udev) | |||
2054 | void usb_disconnect(struct usb_device **pdev) | 2003 | void usb_disconnect(struct usb_device **pdev) |
2055 | { | 2004 | { |
2056 | struct usb_device *udev = *pdev; | 2005 | struct usb_device *udev = *pdev; |
2057 | struct usb_hub *hub = hdev_to_hub(udev); | 2006 | struct usb_hub *hub = usb_hub_to_struct_hub(udev); |
2058 | int i; | 2007 | int i; |
2059 | 2008 | ||
2060 | /* mark the device as inactive, so any further urb submissions for | 2009 | /* mark the device as inactive, so any further urb submissions for |
@@ -2081,6 +2030,19 @@ void usb_disconnect(struct usb_device **pdev) | |||
2081 | usb_disable_device(udev, 0); | 2030 | usb_disable_device(udev, 0); |
2082 | usb_hcd_synchronize_unlinks(udev); | 2031 | usb_hcd_synchronize_unlinks(udev); |
2083 | 2032 | ||
2033 | if (udev->parent) { | ||
2034 | struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent); | ||
2035 | struct usb_port *port_dev = hub->ports[udev->portnum - 1]; | ||
2036 | |||
2037 | sysfs_remove_link(&udev->dev.kobj, "port"); | ||
2038 | sysfs_remove_link(&port_dev->dev.kobj, "device"); | ||
2039 | |||
2040 | if (!port_dev->did_runtime_put) | ||
2041 | pm_runtime_put(&port_dev->dev); | ||
2042 | else | ||
2043 | port_dev->did_runtime_put = false; | ||
2044 | } | ||
2045 | |||
2084 | usb_remove_ep_devs(&udev->ep0); | 2046 | usb_remove_ep_devs(&udev->ep0); |
2085 | usb_unlock_device(udev); | 2047 | usb_unlock_device(udev); |
2086 | 2048 | ||
@@ -2267,7 +2229,7 @@ static void set_usb_port_removable(struct usb_device *udev) | |||
2267 | if (!hdev) | 2229 | if (!hdev) |
2268 | return; | 2230 | return; |
2269 | 2231 | ||
2270 | hub = hdev_to_hub(udev->parent); | 2232 | hub = usb_hub_to_struct_hub(udev->parent); |
2271 | 2233 | ||
2272 | wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics); | 2234 | wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics); |
2273 | 2235 | ||
@@ -2373,6 +2335,26 @@ int usb_new_device(struct usb_device *udev) | |||
2373 | goto fail; | 2335 | goto fail; |
2374 | } | 2336 | } |
2375 | 2337 | ||
2338 | /* Create link files between child device and usb port device. */ | ||
2339 | if (udev->parent) { | ||
2340 | struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent); | ||
2341 | struct usb_port *port_dev = hub->ports[udev->portnum - 1]; | ||
2342 | |||
2343 | err = sysfs_create_link(&udev->dev.kobj, | ||
2344 | &port_dev->dev.kobj, "port"); | ||
2345 | if (err) | ||
2346 | goto fail; | ||
2347 | |||
2348 | err = sysfs_create_link(&port_dev->dev.kobj, | ||
2349 | &udev->dev.kobj, "device"); | ||
2350 | if (err) { | ||
2351 | sysfs_remove_link(&udev->dev.kobj, "port"); | ||
2352 | goto fail; | ||
2353 | } | ||
2354 | |||
2355 | pm_runtime_get_sync(&port_dev->dev); | ||
2356 | } | ||
2357 | |||
2376 | (void) usb_create_ep_devs(&udev->dev, &udev->ep0, udev); | 2358 | (void) usb_create_ep_devs(&udev->dev, &udev->ep0, udev); |
2377 | usb_mark_last_busy(udev); | 2359 | usb_mark_last_busy(udev); |
2378 | pm_runtime_put_sync_autosuspend(&udev->dev); | 2360 | pm_runtime_put_sync_autosuspend(&udev->dev); |
@@ -2535,77 +2517,9 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, | |||
2535 | return ret; | 2517 | return ret; |
2536 | 2518 | ||
2537 | /* The port state is unknown until the reset completes. */ | 2519 | /* The port state is unknown until the reset completes. */ |
2538 | if ((portstatus & USB_PORT_STAT_RESET)) | 2520 | if (!(portstatus & USB_PORT_STAT_RESET)) |
2539 | goto delay; | 2521 | break; |
2540 | |||
2541 | /* | ||
2542 | * Some buggy devices require a warm reset to be issued even | ||
2543 | * when the port appears not to be connected. | ||
2544 | */ | ||
2545 | if (!warm) { | ||
2546 | /* | ||
2547 | * Some buggy devices can cause an NEC host controller | ||
2548 | * to transition to the "Error" state after a hot port | ||
2549 | * reset. This will show up as the port state in | ||
2550 | * "Inactive", and the port may also report a | ||
2551 | * disconnect. Forcing a warm port reset seems to make | ||
2552 | * the device work. | ||
2553 | * | ||
2554 | * See https://bugzilla.kernel.org/show_bug.cgi?id=41752 | ||
2555 | */ | ||
2556 | if (hub_port_warm_reset_required(hub, portstatus)) { | ||
2557 | int ret; | ||
2558 | |||
2559 | if ((portchange & USB_PORT_STAT_C_CONNECTION)) | ||
2560 | clear_port_feature(hub->hdev, port1, | ||
2561 | USB_PORT_FEAT_C_CONNECTION); | ||
2562 | if (portchange & USB_PORT_STAT_C_LINK_STATE) | ||
2563 | clear_port_feature(hub->hdev, port1, | ||
2564 | USB_PORT_FEAT_C_PORT_LINK_STATE); | ||
2565 | if (portchange & USB_PORT_STAT_C_RESET) | ||
2566 | clear_port_feature(hub->hdev, port1, | ||
2567 | USB_PORT_FEAT_C_RESET); | ||
2568 | dev_dbg(hub->intfdev, "hot reset failed, warm reset port %d\n", | ||
2569 | port1); | ||
2570 | ret = hub_port_reset(hub, port1, | ||
2571 | udev, HUB_BH_RESET_TIME, | ||
2572 | true); | ||
2573 | if ((portchange & USB_PORT_STAT_C_CONNECTION)) | ||
2574 | clear_port_feature(hub->hdev, port1, | ||
2575 | USB_PORT_FEAT_C_CONNECTION); | ||
2576 | return ret; | ||
2577 | } | ||
2578 | /* Device went away? */ | ||
2579 | if (!(portstatus & USB_PORT_STAT_CONNECTION)) | ||
2580 | return -ENOTCONN; | ||
2581 | |||
2582 | /* bomb out completely if the connection bounced */ | ||
2583 | if ((portchange & USB_PORT_STAT_C_CONNECTION)) | ||
2584 | return -ENOTCONN; | ||
2585 | |||
2586 | if ((portstatus & USB_PORT_STAT_ENABLE)) { | ||
2587 | if (hub_is_wusb(hub)) | ||
2588 | udev->speed = USB_SPEED_WIRELESS; | ||
2589 | else if (hub_is_superspeed(hub->hdev)) | ||
2590 | udev->speed = USB_SPEED_SUPER; | ||
2591 | else if (portstatus & USB_PORT_STAT_HIGH_SPEED) | ||
2592 | udev->speed = USB_SPEED_HIGH; | ||
2593 | else if (portstatus & USB_PORT_STAT_LOW_SPEED) | ||
2594 | udev->speed = USB_SPEED_LOW; | ||
2595 | else | ||
2596 | udev->speed = USB_SPEED_FULL; | ||
2597 | return 0; | ||
2598 | } | ||
2599 | } else { | ||
2600 | if (!(portstatus & USB_PORT_STAT_CONNECTION) || | ||
2601 | hub_port_warm_reset_required(hub, | ||
2602 | portstatus)) | ||
2603 | return -ENOTCONN; | ||
2604 | |||
2605 | return 0; | ||
2606 | } | ||
2607 | 2522 | ||
2608 | delay: | ||
2609 | /* switch to the long delay after two short delay failures */ | 2523 | /* switch to the long delay after two short delay failures */ |
2610 | if (delay_time >= 2 * HUB_SHORT_RESET_TIME) | 2524 | if (delay_time >= 2 * HUB_SHORT_RESET_TIME) |
2611 | delay = HUB_LONG_RESET_TIME; | 2525 | delay = HUB_LONG_RESET_TIME; |
@@ -2615,20 +2529,54 @@ delay: | |||
2615 | port1, warm ? "warm " : "", delay); | 2529 | port1, warm ? "warm " : "", delay); |
2616 | } | 2530 | } |
2617 | 2531 | ||
2618 | return -EBUSY; | 2532 | if ((portstatus & USB_PORT_STAT_RESET)) |
2533 | return -EBUSY; | ||
2534 | |||
2535 | if (hub_port_warm_reset_required(hub, portstatus)) | ||
2536 | return -ENOTCONN; | ||
2537 | |||
2538 | /* Device went away? */ | ||
2539 | if (!(portstatus & USB_PORT_STAT_CONNECTION)) | ||
2540 | return -ENOTCONN; | ||
2541 | |||
2542 | /* bomb out completely if the connection bounced. A USB 3.0 | ||
2543 | * connection may bounce if multiple warm resets were issued, | ||
2544 | * but the device may have successfully re-connected. Ignore it. | ||
2545 | */ | ||
2546 | if (!hub_is_superspeed(hub->hdev) && | ||
2547 | (portchange & USB_PORT_STAT_C_CONNECTION)) | ||
2548 | return -ENOTCONN; | ||
2549 | |||
2550 | if (!(portstatus & USB_PORT_STAT_ENABLE)) | ||
2551 | return -EBUSY; | ||
2552 | |||
2553 | if (!udev) | ||
2554 | return 0; | ||
2555 | |||
2556 | if (hub_is_wusb(hub)) | ||
2557 | udev->speed = USB_SPEED_WIRELESS; | ||
2558 | else if (hub_is_superspeed(hub->hdev)) | ||
2559 | udev->speed = USB_SPEED_SUPER; | ||
2560 | else if (portstatus & USB_PORT_STAT_HIGH_SPEED) | ||
2561 | udev->speed = USB_SPEED_HIGH; | ||
2562 | else if (portstatus & USB_PORT_STAT_LOW_SPEED) | ||
2563 | udev->speed = USB_SPEED_LOW; | ||
2564 | else | ||
2565 | udev->speed = USB_SPEED_FULL; | ||
2566 | return 0; | ||
2619 | } | 2567 | } |
2620 | 2568 | ||
2621 | static void hub_port_finish_reset(struct usb_hub *hub, int port1, | 2569 | static void hub_port_finish_reset(struct usb_hub *hub, int port1, |
2622 | struct usb_device *udev, int *status, bool warm) | 2570 | struct usb_device *udev, int *status) |
2623 | { | 2571 | { |
2624 | switch (*status) { | 2572 | switch (*status) { |
2625 | case 0: | 2573 | case 0: |
2626 | if (!warm) { | 2574 | /* TRSTRCY = 10 ms; plus some extra */ |
2627 | struct usb_hcd *hcd; | 2575 | msleep(10 + 40); |
2628 | /* TRSTRCY = 10 ms; plus some extra */ | 2576 | if (udev) { |
2629 | msleep(10 + 40); | 2577 | struct usb_hcd *hcd = bus_to_hcd(udev->bus); |
2578 | |||
2630 | update_devnum(udev, 0); | 2579 | update_devnum(udev, 0); |
2631 | hcd = bus_to_hcd(udev->bus); | ||
2632 | /* The xHC may think the device is already reset, | 2580 | /* The xHC may think the device is already reset, |
2633 | * so ignore the status. | 2581 | * so ignore the status. |
2634 | */ | 2582 | */ |
@@ -2638,16 +2586,17 @@ static void hub_port_finish_reset(struct usb_hub *hub, int port1, | |||
2638 | /* FALL THROUGH */ | 2586 | /* FALL THROUGH */ |
2639 | case -ENOTCONN: | 2587 | case -ENOTCONN: |
2640 | case -ENODEV: | 2588 | case -ENODEV: |
2641 | clear_port_feature(hub->hdev, | 2589 | usb_clear_port_feature(hub->hdev, |
2642 | port1, USB_PORT_FEAT_C_RESET); | 2590 | port1, USB_PORT_FEAT_C_RESET); |
2643 | /* FIXME need disconnect() for NOTATTACHED device */ | ||
2644 | if (hub_is_superspeed(hub->hdev)) { | 2591 | if (hub_is_superspeed(hub->hdev)) { |
2645 | clear_port_feature(hub->hdev, port1, | 2592 | usb_clear_port_feature(hub->hdev, port1, |
2646 | USB_PORT_FEAT_C_BH_PORT_RESET); | 2593 | USB_PORT_FEAT_C_BH_PORT_RESET); |
2647 | clear_port_feature(hub->hdev, port1, | 2594 | usb_clear_port_feature(hub->hdev, port1, |
2648 | USB_PORT_FEAT_C_PORT_LINK_STATE); | 2595 | USB_PORT_FEAT_C_PORT_LINK_STATE); |
2596 | usb_clear_port_feature(hub->hdev, port1, | ||
2597 | USB_PORT_FEAT_C_CONNECTION); | ||
2649 | } | 2598 | } |
2650 | if (!warm) | 2599 | if (udev) |
2651 | usb_set_device_state(udev, *status | 2600 | usb_set_device_state(udev, *status |
2652 | ? USB_STATE_NOTATTACHED | 2601 | ? USB_STATE_NOTATTACHED |
2653 | : USB_STATE_DEFAULT); | 2602 | : USB_STATE_DEFAULT); |
@@ -2660,18 +2609,30 @@ static int hub_port_reset(struct usb_hub *hub, int port1, | |||
2660 | struct usb_device *udev, unsigned int delay, bool warm) | 2609 | struct usb_device *udev, unsigned int delay, bool warm) |
2661 | { | 2610 | { |
2662 | int i, status; | 2611 | int i, status; |
2612 | u16 portchange, portstatus; | ||
2663 | 2613 | ||
2664 | if (!warm) { | 2614 | if (!hub_is_superspeed(hub->hdev)) { |
2665 | /* Block EHCI CF initialization during the port reset. | 2615 | if (warm) { |
2666 | * Some companion controllers don't like it when they mix. | ||
2667 | */ | ||
2668 | down_read(&ehci_cf_port_reset_rwsem); | ||
2669 | } else { | ||
2670 | if (!hub_is_superspeed(hub->hdev)) { | ||
2671 | dev_err(hub->intfdev, "only USB3 hub support " | 2616 | dev_err(hub->intfdev, "only USB3 hub support " |
2672 | "warm reset\n"); | 2617 | "warm reset\n"); |
2673 | return -EINVAL; | 2618 | return -EINVAL; |
2674 | } | 2619 | } |
2620 | /* Block EHCI CF initialization during the port reset. | ||
2621 | * Some companion controllers don't like it when they mix. | ||
2622 | */ | ||
2623 | down_read(&ehci_cf_port_reset_rwsem); | ||
2624 | } else if (!warm) { | ||
2625 | /* | ||
2626 | * If the caller hasn't explicitly requested a warm reset, | ||
2627 | * double check and see if one is needed. | ||
2628 | */ | ||
2629 | status = hub_port_status(hub, port1, | ||
2630 | &portstatus, &portchange); | ||
2631 | if (status < 0) | ||
2632 | goto done; | ||
2633 | |||
2634 | if (hub_port_warm_reset_required(hub, portstatus)) | ||
2635 | warm = true; | ||
2675 | } | 2636 | } |
2676 | 2637 | ||
2677 | /* Reset the port */ | 2638 | /* Reset the port */ |
@@ -2692,10 +2653,33 @@ static int hub_port_reset(struct usb_hub *hub, int port1, | |||
2692 | status); | 2653 | status); |
2693 | } | 2654 | } |
2694 | 2655 | ||
2695 | /* return on disconnect or reset */ | 2656 | /* Check for disconnect or reset */ |
2696 | if (status == 0 || status == -ENOTCONN || status == -ENODEV) { | 2657 | if (status == 0 || status == -ENOTCONN || status == -ENODEV) { |
2697 | hub_port_finish_reset(hub, port1, udev, &status, warm); | 2658 | hub_port_finish_reset(hub, port1, udev, &status); |
2698 | goto done; | 2659 | |
2660 | if (!hub_is_superspeed(hub->hdev)) | ||
2661 | goto done; | ||
2662 | |||
2663 | /* | ||
2664 | * If a USB 3.0 device migrates from reset to an error | ||
2665 | * state, re-issue the warm reset. | ||
2666 | */ | ||
2667 | if (hub_port_status(hub, port1, | ||
2668 | &portstatus, &portchange) < 0) | ||
2669 | goto done; | ||
2670 | |||
2671 | if (!hub_port_warm_reset_required(hub, portstatus)) | ||
2672 | goto done; | ||
2673 | |||
2674 | /* | ||
2675 | * If the port is in SS.Inactive or Compliance Mode, the | ||
2676 | * hot or warm reset failed. Try another warm reset. | ||
2677 | */ | ||
2678 | if (!warm) { | ||
2679 | dev_dbg(hub->intfdev, "hot reset failed, warm reset port %d\n", | ||
2680 | port1); | ||
2681 | warm = true; | ||
2682 | } | ||
2699 | } | 2683 | } |
2700 | 2684 | ||
2701 | dev_dbg (hub->intfdev, | 2685 | dev_dbg (hub->intfdev, |
@@ -2709,7 +2693,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1, | |||
2709 | port1); | 2693 | port1); |
2710 | 2694 | ||
2711 | done: | 2695 | done: |
2712 | if (!warm) | 2696 | if (!hub_is_superspeed(hub->hdev)) |
2713 | up_read(&ehci_cf_port_reset_rwsem); | 2697 | up_read(&ehci_cf_port_reset_rwsem); |
2714 | 2698 | ||
2715 | return status; | 2699 | return status; |
@@ -2783,10 +2767,10 @@ static int check_port_resume_type(struct usb_device *udev, | |||
2783 | 2767 | ||
2784 | /* Late port handoff can set status-change bits */ | 2768 | /* Late port handoff can set status-change bits */ |
2785 | if (portchange & USB_PORT_STAT_C_CONNECTION) | 2769 | if (portchange & USB_PORT_STAT_C_CONNECTION) |
2786 | clear_port_feature(hub->hdev, port1, | 2770 | usb_clear_port_feature(hub->hdev, port1, |
2787 | USB_PORT_FEAT_C_CONNECTION); | 2771 | USB_PORT_FEAT_C_CONNECTION); |
2788 | if (portchange & USB_PORT_STAT_C_ENABLE) | 2772 | if (portchange & USB_PORT_STAT_C_ENABLE) |
2789 | clear_port_feature(hub->hdev, port1, | 2773 | usb_clear_port_feature(hub->hdev, port1, |
2790 | USB_PORT_FEAT_C_ENABLE); | 2774 | USB_PORT_FEAT_C_ENABLE); |
2791 | } | 2775 | } |
2792 | 2776 | ||
@@ -2904,7 +2888,9 @@ static int usb_disable_function_remotewakeup(struct usb_device *udev) | |||
2904 | */ | 2888 | */ |
2905 | int usb_port_suspend(struct usb_device *udev, pm_message_t msg) | 2889 | int usb_port_suspend(struct usb_device *udev, pm_message_t msg) |
2906 | { | 2890 | { |
2907 | struct usb_hub *hub = hdev_to_hub(udev->parent); | 2891 | struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent); |
2892 | struct usb_port *port_dev = hub->ports[udev->portnum - 1]; | ||
2893 | enum pm_qos_flags_status pm_qos_stat; | ||
2908 | int port1 = udev->portnum; | 2894 | int port1 = udev->portnum; |
2909 | int status; | 2895 | int status; |
2910 | 2896 | ||
@@ -2962,9 +2948,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) | |||
2962 | 2948 | ||
2963 | /* see 7.1.7.6 */ | 2949 | /* see 7.1.7.6 */ |
2964 | if (hub_is_superspeed(hub->hdev)) | 2950 | if (hub_is_superspeed(hub->hdev)) |
2965 | status = set_port_feature(hub->hdev, | 2951 | status = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_U3); |
2966 | port1 | (USB_SS_PORT_LS_U3 << 3), | ||
2967 | USB_PORT_FEAT_LINK_STATE); | ||
2968 | else | 2952 | else |
2969 | status = set_port_feature(hub->hdev, port1, | 2953 | status = set_port_feature(hub->hdev, port1, |
2970 | USB_PORT_FEAT_SUSPEND); | 2954 | USB_PORT_FEAT_SUSPEND); |
@@ -3006,6 +2990,21 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) | |||
3006 | udev->port_is_suspended = 1; | 2990 | udev->port_is_suspended = 1; |
3007 | msleep(10); | 2991 | msleep(10); |
3008 | } | 2992 | } |
2993 | |||
2994 | /* | ||
2995 | * Check whether current status meets the requirement of | ||
2996 | * usb port power off mechanism | ||
2997 | */ | ||
2998 | pm_qos_stat = dev_pm_qos_flags(&port_dev->dev, | ||
2999 | PM_QOS_FLAG_NO_POWER_OFF); | ||
3000 | if (!udev->do_remote_wakeup | ||
3001 | && pm_qos_stat != PM_QOS_FLAGS_ALL | ||
3002 | && udev->persist_enabled | ||
3003 | && !status) { | ||
3004 | pm_runtime_put_sync(&port_dev->dev); | ||
3005 | port_dev->did_runtime_put = true; | ||
3006 | } | ||
3007 | |||
3009 | usb_mark_last_busy(hub->hdev); | 3008 | usb_mark_last_busy(hub->hdev); |
3010 | return status; | 3009 | return status; |
3011 | } | 3010 | } |
@@ -3141,11 +3140,22 @@ static int finish_port_resume(struct usb_device *udev) | |||
3141 | */ | 3140 | */ |
3142 | int usb_port_resume(struct usb_device *udev, pm_message_t msg) | 3141 | int usb_port_resume(struct usb_device *udev, pm_message_t msg) |
3143 | { | 3142 | { |
3144 | struct usb_hub *hub = hdev_to_hub(udev->parent); | 3143 | struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent); |
3144 | struct usb_port *port_dev = hub->ports[udev->portnum - 1]; | ||
3145 | int port1 = udev->portnum; | 3145 | int port1 = udev->portnum; |
3146 | int status; | 3146 | int status; |
3147 | u16 portchange, portstatus; | 3147 | u16 portchange, portstatus; |
3148 | 3148 | ||
3149 | if (port_dev->did_runtime_put) { | ||
3150 | status = pm_runtime_get_sync(&port_dev->dev); | ||
3151 | port_dev->did_runtime_put = false; | ||
3152 | if (status < 0) { | ||
3153 | dev_dbg(&udev->dev, "can't resume usb port, status %d\n", | ||
3154 | status); | ||
3155 | return status; | ||
3156 | } | ||
3157 | } | ||
3158 | |||
3149 | /* Skip the initial Clear-Suspend step for a remote wakeup */ | 3159 | /* Skip the initial Clear-Suspend step for a remote wakeup */ |
3150 | status = hub_port_status(hub, port1, &portstatus, &portchange); | 3160 | status = hub_port_status(hub, port1, &portstatus, &portchange); |
3151 | if (status == 0 && !port_is_suspended(hub, portstatus)) | 3161 | if (status == 0 && !port_is_suspended(hub, portstatus)) |
@@ -3157,11 +3167,9 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) | |||
3157 | 3167 | ||
3158 | /* see 7.1.7.7; affects power usage, but not budgeting */ | 3168 | /* see 7.1.7.7; affects power usage, but not budgeting */ |
3159 | if (hub_is_superspeed(hub->hdev)) | 3169 | if (hub_is_superspeed(hub->hdev)) |
3160 | status = set_port_feature(hub->hdev, | 3170 | status = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_U0); |
3161 | port1 | (USB_SS_PORT_LS_U0 << 3), | ||
3162 | USB_PORT_FEAT_LINK_STATE); | ||
3163 | else | 3171 | else |
3164 | status = clear_port_feature(hub->hdev, | 3172 | status = usb_clear_port_feature(hub->hdev, |
3165 | port1, USB_PORT_FEAT_SUSPEND); | 3173 | port1, USB_PORT_FEAT_SUSPEND); |
3166 | if (status) { | 3174 | if (status) { |
3167 | dev_dbg(hub->intfdev, "can't resume port %d, status %d\n", | 3175 | dev_dbg(hub->intfdev, "can't resume port %d, status %d\n", |
@@ -3187,11 +3195,11 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) | |||
3187 | udev->port_is_suspended = 0; | 3195 | udev->port_is_suspended = 0; |
3188 | if (hub_is_superspeed(hub->hdev)) { | 3196 | if (hub_is_superspeed(hub->hdev)) { |
3189 | if (portchange & USB_PORT_STAT_C_LINK_STATE) | 3197 | if (portchange & USB_PORT_STAT_C_LINK_STATE) |
3190 | clear_port_feature(hub->hdev, port1, | 3198 | usb_clear_port_feature(hub->hdev, port1, |
3191 | USB_PORT_FEAT_C_PORT_LINK_STATE); | 3199 | USB_PORT_FEAT_C_PORT_LINK_STATE); |
3192 | } else { | 3200 | } else { |
3193 | if (portchange & USB_PORT_STAT_C_SUSPEND) | 3201 | if (portchange & USB_PORT_STAT_C_SUSPEND) |
3194 | clear_port_feature(hub->hdev, port1, | 3202 | usb_clear_port_feature(hub->hdev, port1, |
3195 | USB_PORT_FEAT_C_SUSPEND); | 3203 | USB_PORT_FEAT_C_SUSPEND); |
3196 | } | 3204 | } |
3197 | } | 3205 | } |
@@ -3247,7 +3255,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) | |||
3247 | 3255 | ||
3248 | int usb_port_resume(struct usb_device *udev, pm_message_t msg) | 3256 | int usb_port_resume(struct usb_device *udev, pm_message_t msg) |
3249 | { | 3257 | { |
3250 | struct usb_hub *hub = hdev_to_hub(udev->parent); | 3258 | struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent); |
3251 | int port1 = udev->portnum; | 3259 | int port1 = udev->portnum; |
3252 | int status; | 3260 | int status; |
3253 | u16 portchange, portstatus; | 3261 | u16 portchange, portstatus; |
@@ -3826,7 +3834,7 @@ EXPORT_SYMBOL_GPL(usb_enable_ltm); | |||
3826 | * every 25ms for transient disconnects. When the port status has been | 3834 | * every 25ms for transient disconnects. When the port status has been |
3827 | * unchanged for 100ms it returns the port status. | 3835 | * unchanged for 100ms it returns the port status. |
3828 | */ | 3836 | */ |
3829 | static int hub_port_debounce(struct usb_hub *hub, int port1) | 3837 | int hub_port_debounce(struct usb_hub *hub, int port1, bool must_be_connected) |
3830 | { | 3838 | { |
3831 | int ret; | 3839 | int ret; |
3832 | int total_time, stable_time = 0; | 3840 | int total_time, stable_time = 0; |
@@ -3840,7 +3848,9 @@ static int hub_port_debounce(struct usb_hub *hub, int port1) | |||
3840 | 3848 | ||
3841 | if (!(portchange & USB_PORT_STAT_C_CONNECTION) && | 3849 | if (!(portchange & USB_PORT_STAT_C_CONNECTION) && |
3842 | (portstatus & USB_PORT_STAT_CONNECTION) == connection) { | 3850 | (portstatus & USB_PORT_STAT_CONNECTION) == connection) { |
3843 | stable_time += HUB_DEBOUNCE_STEP; | 3851 | if (!must_be_connected || |
3852 | (connection == USB_PORT_STAT_CONNECTION)) | ||
3853 | stable_time += HUB_DEBOUNCE_STEP; | ||
3844 | if (stable_time >= HUB_DEBOUNCE_STABLE) | 3854 | if (stable_time >= HUB_DEBOUNCE_STABLE) |
3845 | break; | 3855 | break; |
3846 | } else { | 3856 | } else { |
@@ -3849,7 +3859,7 @@ static int hub_port_debounce(struct usb_hub *hub, int port1) | |||
3849 | } | 3859 | } |
3850 | 3860 | ||
3851 | if (portchange & USB_PORT_STAT_C_CONNECTION) { | 3861 | if (portchange & USB_PORT_STAT_C_CONNECTION) { |
3852 | clear_port_feature(hub->hdev, port1, | 3862 | usb_clear_port_feature(hub->hdev, port1, |
3853 | USB_PORT_FEAT_C_CONNECTION); | 3863 | USB_PORT_FEAT_C_CONNECTION); |
3854 | } | 3864 | } |
3855 | 3865 | ||
@@ -4246,16 +4256,23 @@ hub_power_remaining (struct usb_hub *hub) | |||
4246 | for (port1 = 1; port1 <= hdev->maxchild; ++port1) { | 4256 | for (port1 = 1; port1 <= hdev->maxchild; ++port1) { |
4247 | struct usb_device *udev = hub->ports[port1 - 1]->child; | 4257 | struct usb_device *udev = hub->ports[port1 - 1]->child; |
4248 | int delta; | 4258 | int delta; |
4259 | unsigned unit_load; | ||
4249 | 4260 | ||
4250 | if (!udev) | 4261 | if (!udev) |
4251 | continue; | 4262 | continue; |
4263 | if (hub_is_superspeed(udev)) | ||
4264 | unit_load = 150; | ||
4265 | else | ||
4266 | unit_load = 100; | ||
4252 | 4267 | ||
4253 | /* Unconfigured devices may not use more than 100mA, | 4268 | /* |
4254 | * or 8mA for OTG ports */ | 4269 | * Unconfigured devices may not use more than one unit load, |
4270 | * or 8mA for OTG ports | ||
4271 | */ | ||
4255 | if (udev->actconfig) | 4272 | if (udev->actconfig) |
4256 | delta = udev->actconfig->desc.bMaxPower * 2; | 4273 | delta = usb_get_max_power(udev, udev->actconfig); |
4257 | else if (port1 != udev->bus->otg_port || hdev->parent) | 4274 | else if (port1 != udev->bus->otg_port || hdev->parent) |
4258 | delta = 100; | 4275 | delta = unit_load; |
4259 | else | 4276 | else |
4260 | delta = 8; | 4277 | delta = 8; |
4261 | if (delta > hub->mA_per_port) | 4278 | if (delta > hub->mA_per_port) |
@@ -4290,6 +4307,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, | |||
4290 | le16_to_cpu(hub->descriptor->wHubCharacteristics); | 4307 | le16_to_cpu(hub->descriptor->wHubCharacteristics); |
4291 | struct usb_device *udev; | 4308 | struct usb_device *udev; |
4292 | int status, i; | 4309 | int status, i; |
4310 | unsigned unit_load; | ||
4293 | 4311 | ||
4294 | dev_dbg (hub_dev, | 4312 | dev_dbg (hub_dev, |
4295 | "port %d, status %04x, change %04x, %s\n", | 4313 | "port %d, status %04x, change %04x, %s\n", |
@@ -4353,7 +4371,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, | |||
4353 | 4371 | ||
4354 | if (portchange & (USB_PORT_STAT_C_CONNECTION | | 4372 | if (portchange & (USB_PORT_STAT_C_CONNECTION | |
4355 | USB_PORT_STAT_C_ENABLE)) { | 4373 | USB_PORT_STAT_C_ENABLE)) { |
4356 | status = hub_port_debounce(hub, port1); | 4374 | status = hub_port_debounce_be_stable(hub, port1); |
4357 | if (status < 0) { | 4375 | if (status < 0) { |
4358 | if (printk_ratelimit()) | 4376 | if (printk_ratelimit()) |
4359 | dev_err(hub_dev, "connect-debounce failed, " | 4377 | dev_err(hub_dev, "connect-debounce failed, " |
@@ -4379,6 +4397,10 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, | |||
4379 | goto done; | 4397 | goto done; |
4380 | return; | 4398 | return; |
4381 | } | 4399 | } |
4400 | if (hub_is_superspeed(hub->hdev)) | ||
4401 | unit_load = 150; | ||
4402 | else | ||
4403 | unit_load = 100; | ||
4382 | 4404 | ||
4383 | for (i = 0; i < SET_CONFIG_TRIES; i++) { | 4405 | for (i = 0; i < SET_CONFIG_TRIES; i++) { |
4384 | 4406 | ||
@@ -4426,7 +4448,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, | |||
4426 | * on the parent. | 4448 | * on the parent. |
4427 | */ | 4449 | */ |
4428 | if (udev->descriptor.bDeviceClass == USB_CLASS_HUB | 4450 | if (udev->descriptor.bDeviceClass == USB_CLASS_HUB |
4429 | && udev->bus_mA <= 100) { | 4451 | && udev->bus_mA <= unit_load) { |
4430 | u16 devstat; | 4452 | u16 devstat; |
4431 | 4453 | ||
4432 | status = usb_get_status(udev, USB_RECIP_DEVICE, 0, | 4454 | status = usb_get_status(udev, USB_RECIP_DEVICE, 0, |
@@ -4528,7 +4550,7 @@ static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port, | |||
4528 | if (!hub_is_superspeed(hdev)) { | 4550 | if (!hub_is_superspeed(hdev)) { |
4529 | if (!(portchange & USB_PORT_STAT_C_SUSPEND)) | 4551 | if (!(portchange & USB_PORT_STAT_C_SUSPEND)) |
4530 | return 0; | 4552 | return 0; |
4531 | clear_port_feature(hdev, port, USB_PORT_FEAT_C_SUSPEND); | 4553 | usb_clear_port_feature(hdev, port, USB_PORT_FEAT_C_SUSPEND); |
4532 | } else { | 4554 | } else { |
4533 | if (!udev || udev->state != USB_STATE_SUSPENDED || | 4555 | if (!udev || udev->state != USB_STATE_SUSPENDED || |
4534 | (portstatus & USB_PORT_STAT_LINK_STATE) != | 4556 | (portstatus & USB_PORT_STAT_LINK_STATE) != |
@@ -4656,7 +4678,7 @@ static void hub_events(void) | |||
4656 | continue; | 4678 | continue; |
4657 | 4679 | ||
4658 | if (portchange & USB_PORT_STAT_C_CONNECTION) { | 4680 | if (portchange & USB_PORT_STAT_C_CONNECTION) { |
4659 | clear_port_feature(hdev, i, | 4681 | usb_clear_port_feature(hdev, i, |
4660 | USB_PORT_FEAT_C_CONNECTION); | 4682 | USB_PORT_FEAT_C_CONNECTION); |
4661 | connect_change = 1; | 4683 | connect_change = 1; |
4662 | } | 4684 | } |
@@ -4667,7 +4689,7 @@ static void hub_events(void) | |||
4667 | "port %d enable change, " | 4689 | "port %d enable change, " |
4668 | "status %08x\n", | 4690 | "status %08x\n", |
4669 | i, portstatus); | 4691 | i, portstatus); |
4670 | clear_port_feature(hdev, i, | 4692 | usb_clear_port_feature(hdev, i, |
4671 | USB_PORT_FEAT_C_ENABLE); | 4693 | USB_PORT_FEAT_C_ENABLE); |
4672 | 4694 | ||
4673 | /* | 4695 | /* |
@@ -4698,7 +4720,7 @@ static void hub_events(void) | |||
4698 | 4720 | ||
4699 | dev_dbg(hub_dev, "over-current change on port " | 4721 | dev_dbg(hub_dev, "over-current change on port " |
4700 | "%d\n", i); | 4722 | "%d\n", i); |
4701 | clear_port_feature(hdev, i, | 4723 | usb_clear_port_feature(hdev, i, |
4702 | USB_PORT_FEAT_C_OVER_CURRENT); | 4724 | USB_PORT_FEAT_C_OVER_CURRENT); |
4703 | msleep(100); /* Cool down */ | 4725 | msleep(100); /* Cool down */ |
4704 | hub_power_on(hub, true); | 4726 | hub_power_on(hub, true); |
@@ -4712,7 +4734,7 @@ static void hub_events(void) | |||
4712 | dev_dbg (hub_dev, | 4734 | dev_dbg (hub_dev, |
4713 | "reset change on port %d\n", | 4735 | "reset change on port %d\n", |
4714 | i); | 4736 | i); |
4715 | clear_port_feature(hdev, i, | 4737 | usb_clear_port_feature(hdev, i, |
4716 | USB_PORT_FEAT_C_RESET); | 4738 | USB_PORT_FEAT_C_RESET); |
4717 | } | 4739 | } |
4718 | if ((portchange & USB_PORT_STAT_C_BH_RESET) && | 4740 | if ((portchange & USB_PORT_STAT_C_BH_RESET) && |
@@ -4720,18 +4742,18 @@ static void hub_events(void) | |||
4720 | dev_dbg(hub_dev, | 4742 | dev_dbg(hub_dev, |
4721 | "warm reset change on port %d\n", | 4743 | "warm reset change on port %d\n", |
4722 | i); | 4744 | i); |
4723 | clear_port_feature(hdev, i, | 4745 | usb_clear_port_feature(hdev, i, |
4724 | USB_PORT_FEAT_C_BH_PORT_RESET); | 4746 | USB_PORT_FEAT_C_BH_PORT_RESET); |
4725 | } | 4747 | } |
4726 | if (portchange & USB_PORT_STAT_C_LINK_STATE) { | 4748 | if (portchange & USB_PORT_STAT_C_LINK_STATE) { |
4727 | clear_port_feature(hub->hdev, i, | 4749 | usb_clear_port_feature(hub->hdev, i, |
4728 | USB_PORT_FEAT_C_PORT_LINK_STATE); | 4750 | USB_PORT_FEAT_C_PORT_LINK_STATE); |
4729 | } | 4751 | } |
4730 | if (portchange & USB_PORT_STAT_C_CONFIG_ERROR) { | 4752 | if (portchange & USB_PORT_STAT_C_CONFIG_ERROR) { |
4731 | dev_warn(hub_dev, | 4753 | dev_warn(hub_dev, |
4732 | "config error on port %d\n", | 4754 | "config error on port %d\n", |
4733 | i); | 4755 | i); |
4734 | clear_port_feature(hub->hdev, i, | 4756 | usb_clear_port_feature(hub->hdev, i, |
4735 | USB_PORT_FEAT_C_PORT_CONFIG_ERROR); | 4757 | USB_PORT_FEAT_C_PORT_CONFIG_ERROR); |
4736 | } | 4758 | } |
4737 | 4759 | ||
@@ -4740,12 +4762,21 @@ static void hub_events(void) | |||
4740 | */ | 4762 | */ |
4741 | if (hub_port_warm_reset_required(hub, portstatus)) { | 4763 | if (hub_port_warm_reset_required(hub, portstatus)) { |
4742 | int status; | 4764 | int status; |
4765 | struct usb_device *udev = | ||
4766 | hub->ports[i - 1]->child; | ||
4743 | 4767 | ||
4744 | dev_dbg(hub_dev, "warm reset port %d\n", i); | 4768 | dev_dbg(hub_dev, "warm reset port %d\n", i); |
4745 | status = hub_port_reset(hub, i, NULL, | 4769 | if (!udev) { |
4746 | HUB_BH_RESET_TIME, true); | 4770 | status = hub_port_reset(hub, i, |
4747 | if (status < 0) | 4771 | NULL, HUB_BH_RESET_TIME, |
4748 | hub_port_disable(hub, i, 1); | 4772 | true); |
4773 | if (status < 0) | ||
4774 | hub_port_disable(hub, i, 1); | ||
4775 | } else { | ||
4776 | usb_lock_device(udev); | ||
4777 | status = usb_reset_device(udev); | ||
4778 | usb_unlock_device(udev); | ||
4779 | } | ||
4749 | connect_change = 0; | 4780 | connect_change = 0; |
4750 | } | 4781 | } |
4751 | 4782 | ||
@@ -5006,7 +5037,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev) | |||
5006 | dev_dbg(&udev->dev, "%s for root hub!\n", __func__); | 5037 | dev_dbg(&udev->dev, "%s for root hub!\n", __func__); |
5007 | return -EISDIR; | 5038 | return -EISDIR; |
5008 | } | 5039 | } |
5009 | parent_hub = hdev_to_hub(parent_hdev); | 5040 | parent_hub = usb_hub_to_struct_hub(parent_hdev); |
5010 | 5041 | ||
5011 | /* Disable LPM and LTM while we reset the device and reinstall the alt | 5042 | /* Disable LPM and LTM while we reset the device and reinstall the alt |
5012 | * settings. Device-initiated LPM settings, and system exit latency | 5043 | * settings. Device-initiated LPM settings, and system exit latency |
@@ -5262,7 +5293,7 @@ EXPORT_SYMBOL_GPL(usb_queue_reset_device); | |||
5262 | struct usb_device *usb_hub_find_child(struct usb_device *hdev, | 5293 | struct usb_device *usb_hub_find_child(struct usb_device *hdev, |
5263 | int port1) | 5294 | int port1) |
5264 | { | 5295 | { |
5265 | struct usb_hub *hub = hdev_to_hub(hdev); | 5296 | struct usb_hub *hub = usb_hub_to_struct_hub(hdev); |
5266 | 5297 | ||
5267 | if (port1 < 1 || port1 > hdev->maxchild) | 5298 | if (port1 < 1 || port1 > hdev->maxchild) |
5268 | return NULL; | 5299 | return NULL; |
@@ -5279,7 +5310,7 @@ EXPORT_SYMBOL_GPL(usb_hub_find_child); | |||
5279 | void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1, | 5310 | void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1, |
5280 | enum usb_port_connect_type type) | 5311 | enum usb_port_connect_type type) |
5281 | { | 5312 | { |
5282 | struct usb_hub *hub = hdev_to_hub(hdev); | 5313 | struct usb_hub *hub = usb_hub_to_struct_hub(hdev); |
5283 | 5314 | ||
5284 | hub->ports[port1 - 1]->connect_type = type; | 5315 | hub->ports[port1 - 1]->connect_type = type; |
5285 | } | 5316 | } |
@@ -5295,11 +5326,52 @@ void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1, | |||
5295 | enum usb_port_connect_type | 5326 | enum usb_port_connect_type |
5296 | usb_get_hub_port_connect_type(struct usb_device *hdev, int port1) | 5327 | usb_get_hub_port_connect_type(struct usb_device *hdev, int port1) |
5297 | { | 5328 | { |
5298 | struct usb_hub *hub = hdev_to_hub(hdev); | 5329 | struct usb_hub *hub = usb_hub_to_struct_hub(hdev); |
5299 | 5330 | ||
5300 | return hub->ports[port1 - 1]->connect_type; | 5331 | return hub->ports[port1 - 1]->connect_type; |
5301 | } | 5332 | } |
5302 | 5333 | ||
5334 | void usb_hub_adjust_deviceremovable(struct usb_device *hdev, | ||
5335 | struct usb_hub_descriptor *desc) | ||
5336 | { | ||
5337 | enum usb_port_connect_type connect_type; | ||
5338 | int i; | ||
5339 | |||
5340 | if (!hub_is_superspeed(hdev)) { | ||
5341 | for (i = 1; i <= hdev->maxchild; i++) { | ||
5342 | connect_type = usb_get_hub_port_connect_type(hdev, i); | ||
5343 | |||
5344 | if (connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) { | ||
5345 | u8 mask = 1 << (i%8); | ||
5346 | |||
5347 | if (!(desc->u.hs.DeviceRemovable[i/8] & mask)) { | ||
5348 | dev_dbg(&hdev->dev, "usb port%d's DeviceRemovable is changed to 1 according to platform information.\n", | ||
5349 | i); | ||
5350 | desc->u.hs.DeviceRemovable[i/8] |= mask; | ||
5351 | } | ||
5352 | } | ||
5353 | } | ||
5354 | } else { | ||
5355 | u16 port_removable = le16_to_cpu(desc->u.ss.DeviceRemovable); | ||
5356 | |||
5357 | for (i = 1; i <= hdev->maxchild; i++) { | ||
5358 | connect_type = usb_get_hub_port_connect_type(hdev, i); | ||
5359 | |||
5360 | if (connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) { | ||
5361 | u16 mask = 1 << i; | ||
5362 | |||
5363 | if (!(port_removable & mask)) { | ||
5364 | dev_dbg(&hdev->dev, "usb port%d's DeviceRemovable is changed to 1 according to platform information.\n", | ||
5365 | i); | ||
5366 | port_removable |= mask; | ||
5367 | } | ||
5368 | } | ||
5369 | } | ||
5370 | |||
5371 | desc->u.ss.DeviceRemovable = cpu_to_le16(port_removable); | ||
5372 | } | ||
5373 | } | ||
5374 | |||
5303 | #ifdef CONFIG_ACPI | 5375 | #ifdef CONFIG_ACPI |
5304 | /** | 5376 | /** |
5305 | * usb_get_hub_port_acpi_handle - Get the usb port's acpi handle | 5377 | * usb_get_hub_port_acpi_handle - Get the usb port's acpi handle |
@@ -5312,7 +5384,7 @@ usb_get_hub_port_connect_type(struct usb_device *hdev, int port1) | |||
5312 | acpi_handle usb_get_hub_port_acpi_handle(struct usb_device *hdev, | 5384 | acpi_handle usb_get_hub_port_acpi_handle(struct usb_device *hdev, |
5313 | int port1) | 5385 | int port1) |
5314 | { | 5386 | { |
5315 | struct usb_hub *hub = hdev_to_hub(hdev); | 5387 | struct usb_hub *hub = usb_hub_to_struct_hub(hdev); |
5316 | 5388 | ||
5317 | return DEVICE_ACPI_HANDLE(&hub->ports[port1 - 1]->dev); | 5389 | return DEVICE_ACPI_HANDLE(&hub->ports[port1 - 1]->dev); |
5318 | } | 5390 | } |