diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2012-01-09 02:38:23 -0500 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2012-01-09 02:38:23 -0500 |
commit | da733563be5a9da26fe81d9f007262d00b846e22 (patch) | |
tree | db28291df94a2043af2123911984c5c173da4e6f /drivers/usb/core/hub.c | |
parent | 6ccbcf2cb41131f8d56ef0723bf3f7c1f8486076 (diff) | |
parent | dab78d7924598ea4031663dd10db814e2e324928 (diff) |
Merge branch 'next' into for-linus
Diffstat (limited to 'drivers/usb/core/hub.c')
-rw-r--r-- | drivers/usb/core/hub.c | 332 |
1 files changed, 196 insertions, 136 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index a428aa080a36..79781461eec9 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -813,6 +813,12 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) | |||
813 | USB_PORT_FEAT_C_PORT_LINK_STATE); | 813 | USB_PORT_FEAT_C_PORT_LINK_STATE); |
814 | } | 814 | } |
815 | 815 | ||
816 | if ((portchange & USB_PORT_STAT_C_BH_RESET) && | ||
817 | hub_is_superspeed(hub->hdev)) { | ||
818 | need_debounce_delay = true; | ||
819 | clear_port_feature(hub->hdev, port1, | ||
820 | USB_PORT_FEAT_C_BH_PORT_RESET); | ||
821 | } | ||
816 | /* We can forget about a "removed" device when there's a | 822 | /* We can forget about a "removed" device when there's a |
817 | * physical disconnect or the connect status changes. | 823 | * physical disconnect or the connect status changes. |
818 | */ | 824 | */ |
@@ -1636,11 +1642,6 @@ void usb_disconnect(struct usb_device **pdev) | |||
1636 | int i; | 1642 | int i; |
1637 | struct usb_hcd *hcd = bus_to_hcd(udev->bus); | 1643 | struct usb_hcd *hcd = bus_to_hcd(udev->bus); |
1638 | 1644 | ||
1639 | if (!udev) { | ||
1640 | pr_debug ("%s nodev\n", __func__); | ||
1641 | return; | ||
1642 | } | ||
1643 | |||
1644 | /* mark the device as inactive, so any further urb submissions for | 1645 | /* mark the device as inactive, so any further urb submissions for |
1645 | * this device (and any of its children) will fail immediately. | 1646 | * this device (and any of its children) will fail immediately. |
1646 | * this quiesces everything except pending urbs. | 1647 | * this quiesces everything except pending urbs. |
@@ -2030,11 +2031,23 @@ static unsigned hub_is_wusb(struct usb_hub *hub) | |||
2030 | 2031 | ||
2031 | #define HUB_ROOT_RESET_TIME 50 /* times are in msec */ | 2032 | #define HUB_ROOT_RESET_TIME 50 /* times are in msec */ |
2032 | #define HUB_SHORT_RESET_TIME 10 | 2033 | #define HUB_SHORT_RESET_TIME 10 |
2034 | #define HUB_BH_RESET_TIME 50 | ||
2033 | #define HUB_LONG_RESET_TIME 200 | 2035 | #define HUB_LONG_RESET_TIME 200 |
2034 | #define HUB_RESET_TIMEOUT 500 | 2036 | #define HUB_RESET_TIMEOUT 500 |
2035 | 2037 | ||
2038 | static int hub_port_reset(struct usb_hub *hub, int port1, | ||
2039 | struct usb_device *udev, unsigned int delay, bool warm); | ||
2040 | |||
2041 | /* Is a USB 3.0 port in the Inactive state? */ | ||
2042 | static bool hub_port_inactive(struct usb_hub *hub, u16 portstatus) | ||
2043 | { | ||
2044 | return hub_is_superspeed(hub->hdev) && | ||
2045 | (portstatus & USB_PORT_STAT_LINK_STATE) == | ||
2046 | USB_SS_PORT_LS_SS_INACTIVE; | ||
2047 | } | ||
2048 | |||
2036 | static int hub_port_wait_reset(struct usb_hub *hub, int port1, | 2049 | static int hub_port_wait_reset(struct usb_hub *hub, int port1, |
2037 | struct usb_device *udev, unsigned int delay) | 2050 | struct usb_device *udev, unsigned int delay, bool warm) |
2038 | { | 2051 | { |
2039 | int delay_time, ret; | 2052 | int delay_time, ret; |
2040 | u16 portstatus; | 2053 | u16 portstatus; |
@@ -2051,28 +2064,71 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, | |||
2051 | if (ret < 0) | 2064 | if (ret < 0) |
2052 | return ret; | 2065 | return ret; |
2053 | 2066 | ||
2054 | /* Device went away? */ | 2067 | /* |
2055 | if (!(portstatus & USB_PORT_STAT_CONNECTION)) | 2068 | * Some buggy devices require a warm reset to be issued even |
2056 | return -ENOTCONN; | 2069 | * when the port appears not to be connected. |
2057 | 2070 | */ | |
2058 | /* bomb out completely if the connection bounced */ | 2071 | if (!warm) { |
2059 | if ((portchange & USB_PORT_STAT_C_CONNECTION)) | 2072 | /* |
2060 | return -ENOTCONN; | 2073 | * Some buggy devices can cause an NEC host controller |
2061 | 2074 | * to transition to the "Error" state after a hot port | |
2062 | /* if we`ve finished resetting, then break out of the loop */ | 2075 | * reset. This will show up as the port state in |
2063 | if (!(portstatus & USB_PORT_STAT_RESET) && | 2076 | * "Inactive", and the port may also report a |
2064 | (portstatus & USB_PORT_STAT_ENABLE)) { | 2077 | * disconnect. Forcing a warm port reset seems to make |
2065 | if (hub_is_wusb(hub)) | 2078 | * the device work. |
2066 | udev->speed = USB_SPEED_WIRELESS; | 2079 | * |
2067 | else if (hub_is_superspeed(hub->hdev)) | 2080 | * See https://bugzilla.kernel.org/show_bug.cgi?id=41752 |
2068 | udev->speed = USB_SPEED_SUPER; | 2081 | */ |
2069 | else if (portstatus & USB_PORT_STAT_HIGH_SPEED) | 2082 | if (hub_port_inactive(hub, portstatus)) { |
2070 | udev->speed = USB_SPEED_HIGH; | 2083 | int ret; |
2071 | else if (portstatus & USB_PORT_STAT_LOW_SPEED) | 2084 | |
2072 | udev->speed = USB_SPEED_LOW; | 2085 | if ((portchange & USB_PORT_STAT_C_CONNECTION)) |
2073 | else | 2086 | clear_port_feature(hub->hdev, port1, |
2074 | udev->speed = USB_SPEED_FULL; | 2087 | USB_PORT_FEAT_C_CONNECTION); |
2075 | return 0; | 2088 | if (portchange & USB_PORT_STAT_C_LINK_STATE) |
2089 | clear_port_feature(hub->hdev, port1, | ||
2090 | USB_PORT_FEAT_C_PORT_LINK_STATE); | ||
2091 | if (portchange & USB_PORT_STAT_C_RESET) | ||
2092 | clear_port_feature(hub->hdev, port1, | ||
2093 | USB_PORT_FEAT_C_RESET); | ||
2094 | dev_dbg(hub->intfdev, "hot reset failed, warm reset port %d\n", | ||
2095 | port1); | ||
2096 | ret = hub_port_reset(hub, port1, | ||
2097 | udev, HUB_BH_RESET_TIME, | ||
2098 | true); | ||
2099 | if ((portchange & USB_PORT_STAT_C_CONNECTION)) | ||
2100 | clear_port_feature(hub->hdev, port1, | ||
2101 | USB_PORT_FEAT_C_CONNECTION); | ||
2102 | return ret; | ||
2103 | } | ||
2104 | /* Device went away? */ | ||
2105 | if (!(portstatus & USB_PORT_STAT_CONNECTION)) | ||
2106 | return -ENOTCONN; | ||
2107 | |||
2108 | /* bomb out completely if the connection bounced */ | ||
2109 | if ((portchange & USB_PORT_STAT_C_CONNECTION)) | ||
2110 | return -ENOTCONN; | ||
2111 | |||
2112 | /* if we`ve finished resetting, then break out of | ||
2113 | * the loop | ||
2114 | */ | ||
2115 | if (!(portstatus & USB_PORT_STAT_RESET) && | ||
2116 | (portstatus & USB_PORT_STAT_ENABLE)) { | ||
2117 | if (hub_is_wusb(hub)) | ||
2118 | udev->speed = USB_SPEED_WIRELESS; | ||
2119 | else if (hub_is_superspeed(hub->hdev)) | ||
2120 | udev->speed = USB_SPEED_SUPER; | ||
2121 | else if (portstatus & USB_PORT_STAT_HIGH_SPEED) | ||
2122 | udev->speed = USB_SPEED_HIGH; | ||
2123 | else if (portstatus & USB_PORT_STAT_LOW_SPEED) | ||
2124 | udev->speed = USB_SPEED_LOW; | ||
2125 | else | ||
2126 | udev->speed = USB_SPEED_FULL; | ||
2127 | return 0; | ||
2128 | } | ||
2129 | } else { | ||
2130 | if (portchange & USB_PORT_STAT_C_BH_RESET) | ||
2131 | return 0; | ||
2076 | } | 2132 | } |
2077 | 2133 | ||
2078 | /* switch to the long delay after two short delay failures */ | 2134 | /* switch to the long delay after two short delay failures */ |
@@ -2080,35 +2136,84 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, | |||
2080 | delay = HUB_LONG_RESET_TIME; | 2136 | delay = HUB_LONG_RESET_TIME; |
2081 | 2137 | ||
2082 | dev_dbg (hub->intfdev, | 2138 | dev_dbg (hub->intfdev, |
2083 | "port %d not reset yet, waiting %dms\n", | 2139 | "port %d not %sreset yet, waiting %dms\n", |
2084 | port1, delay); | 2140 | port1, warm ? "warm " : "", delay); |
2085 | } | 2141 | } |
2086 | 2142 | ||
2087 | return -EBUSY; | 2143 | return -EBUSY; |
2088 | } | 2144 | } |
2089 | 2145 | ||
2146 | static void hub_port_finish_reset(struct usb_hub *hub, int port1, | ||
2147 | struct usb_device *udev, int *status, bool warm) | ||
2148 | { | ||
2149 | switch (*status) { | ||
2150 | case 0: | ||
2151 | if (!warm) { | ||
2152 | struct usb_hcd *hcd; | ||
2153 | /* TRSTRCY = 10 ms; plus some extra */ | ||
2154 | msleep(10 + 40); | ||
2155 | update_devnum(udev, 0); | ||
2156 | hcd = bus_to_hcd(udev->bus); | ||
2157 | if (hcd->driver->reset_device) { | ||
2158 | *status = hcd->driver->reset_device(hcd, udev); | ||
2159 | if (*status < 0) { | ||
2160 | dev_err(&udev->dev, "Cannot reset " | ||
2161 | "HCD device state\n"); | ||
2162 | break; | ||
2163 | } | ||
2164 | } | ||
2165 | } | ||
2166 | /* FALL THROUGH */ | ||
2167 | case -ENOTCONN: | ||
2168 | case -ENODEV: | ||
2169 | clear_port_feature(hub->hdev, | ||
2170 | port1, USB_PORT_FEAT_C_RESET); | ||
2171 | /* FIXME need disconnect() for NOTATTACHED device */ | ||
2172 | if (warm) { | ||
2173 | clear_port_feature(hub->hdev, port1, | ||
2174 | USB_PORT_FEAT_C_BH_PORT_RESET); | ||
2175 | clear_port_feature(hub->hdev, port1, | ||
2176 | USB_PORT_FEAT_C_PORT_LINK_STATE); | ||
2177 | } else { | ||
2178 | usb_set_device_state(udev, *status | ||
2179 | ? USB_STATE_NOTATTACHED | ||
2180 | : USB_STATE_DEFAULT); | ||
2181 | } | ||
2182 | break; | ||
2183 | } | ||
2184 | } | ||
2185 | |||
2186 | /* Handle port reset and port warm(BH) reset (for USB3 protocol ports) */ | ||
2090 | static int hub_port_reset(struct usb_hub *hub, int port1, | 2187 | static int hub_port_reset(struct usb_hub *hub, int port1, |
2091 | struct usb_device *udev, unsigned int delay) | 2188 | struct usb_device *udev, unsigned int delay, bool warm) |
2092 | { | 2189 | { |
2093 | int i, status; | 2190 | int i, status; |
2094 | struct usb_hcd *hcd; | ||
2095 | 2191 | ||
2096 | hcd = bus_to_hcd(udev->bus); | 2192 | if (!warm) { |
2097 | /* Block EHCI CF initialization during the port reset. | 2193 | /* Block EHCI CF initialization during the port reset. |
2098 | * Some companion controllers don't like it when they mix. | 2194 | * Some companion controllers don't like it when they mix. |
2099 | */ | 2195 | */ |
2100 | down_read(&ehci_cf_port_reset_rwsem); | 2196 | down_read(&ehci_cf_port_reset_rwsem); |
2197 | } else { | ||
2198 | if (!hub_is_superspeed(hub->hdev)) { | ||
2199 | dev_err(hub->intfdev, "only USB3 hub support " | ||
2200 | "warm reset\n"); | ||
2201 | return -EINVAL; | ||
2202 | } | ||
2203 | } | ||
2101 | 2204 | ||
2102 | /* Reset the port */ | 2205 | /* Reset the port */ |
2103 | for (i = 0; i < PORT_RESET_TRIES; i++) { | 2206 | for (i = 0; i < PORT_RESET_TRIES; i++) { |
2104 | status = set_port_feature(hub->hdev, | 2207 | status = set_port_feature(hub->hdev, port1, (warm ? |
2105 | port1, USB_PORT_FEAT_RESET); | 2208 | USB_PORT_FEAT_BH_PORT_RESET : |
2106 | if (status) | 2209 | USB_PORT_FEAT_RESET)); |
2210 | if (status) { | ||
2107 | dev_err(hub->intfdev, | 2211 | dev_err(hub->intfdev, |
2108 | "cannot reset port %d (err = %d)\n", | 2212 | "cannot %sreset port %d (err = %d)\n", |
2109 | port1, status); | 2213 | warm ? "warm " : "", port1, status); |
2110 | else { | 2214 | } else { |
2111 | status = hub_port_wait_reset(hub, port1, udev, delay); | 2215 | status = hub_port_wait_reset(hub, port1, udev, delay, |
2216 | warm); | ||
2112 | if (status && status != -ENOTCONN) | 2217 | if (status && status != -ENOTCONN) |
2113 | dev_dbg(hub->intfdev, | 2218 | dev_dbg(hub->intfdev, |
2114 | "port_wait_reset: err = %d\n", | 2219 | "port_wait_reset: err = %d\n", |
@@ -2116,34 +2221,14 @@ static int hub_port_reset(struct usb_hub *hub, int port1, | |||
2116 | } | 2221 | } |
2117 | 2222 | ||
2118 | /* return on disconnect or reset */ | 2223 | /* return on disconnect or reset */ |
2119 | switch (status) { | 2224 | if (status == 0 || status == -ENOTCONN || status == -ENODEV) { |
2120 | case 0: | 2225 | hub_port_finish_reset(hub, port1, udev, &status, warm); |
2121 | /* TRSTRCY = 10 ms; plus some extra */ | ||
2122 | msleep(10 + 40); | ||
2123 | update_devnum(udev, 0); | ||
2124 | if (hcd->driver->reset_device) { | ||
2125 | status = hcd->driver->reset_device(hcd, udev); | ||
2126 | if (status < 0) { | ||
2127 | dev_err(&udev->dev, "Cannot reset " | ||
2128 | "HCD device state\n"); | ||
2129 | break; | ||
2130 | } | ||
2131 | } | ||
2132 | /* FALL THROUGH */ | ||
2133 | case -ENOTCONN: | ||
2134 | case -ENODEV: | ||
2135 | clear_port_feature(hub->hdev, | ||
2136 | port1, USB_PORT_FEAT_C_RESET); | ||
2137 | /* FIXME need disconnect() for NOTATTACHED device */ | ||
2138 | usb_set_device_state(udev, status | ||
2139 | ? USB_STATE_NOTATTACHED | ||
2140 | : USB_STATE_DEFAULT); | ||
2141 | goto done; | 2226 | goto done; |
2142 | } | 2227 | } |
2143 | 2228 | ||
2144 | dev_dbg (hub->intfdev, | 2229 | dev_dbg (hub->intfdev, |
2145 | "port %d not enabled, trying reset again...\n", | 2230 | "port %d not enabled, trying %sreset again...\n", |
2146 | port1); | 2231 | port1, warm ? "warm " : ""); |
2147 | delay = HUB_LONG_RESET_TIME; | 2232 | delay = HUB_LONG_RESET_TIME; |
2148 | } | 2233 | } |
2149 | 2234 | ||
@@ -2151,45 +2236,11 @@ static int hub_port_reset(struct usb_hub *hub, int port1, | |||
2151 | "Cannot enable port %i. Maybe the USB cable is bad?\n", | 2236 | "Cannot enable port %i. Maybe the USB cable is bad?\n", |
2152 | port1); | 2237 | port1); |
2153 | 2238 | ||
2154 | done: | 2239 | done: |
2155 | up_read(&ehci_cf_port_reset_rwsem); | 2240 | if (!warm) |
2156 | return status; | 2241 | up_read(&ehci_cf_port_reset_rwsem); |
2157 | } | ||
2158 | |||
2159 | /* Warm reset a USB3 protocol port */ | ||
2160 | static int hub_port_warm_reset(struct usb_hub *hub, int port) | ||
2161 | { | ||
2162 | int ret; | ||
2163 | u16 portstatus, portchange; | ||
2164 | |||
2165 | if (!hub_is_superspeed(hub->hdev)) { | ||
2166 | dev_err(hub->intfdev, "only USB3 hub support warm reset\n"); | ||
2167 | return -EINVAL; | ||
2168 | } | ||
2169 | |||
2170 | /* Warm reset the port */ | ||
2171 | ret = set_port_feature(hub->hdev, | ||
2172 | port, USB_PORT_FEAT_BH_PORT_RESET); | ||
2173 | if (ret) { | ||
2174 | dev_err(hub->intfdev, "cannot warm reset port %d\n", port); | ||
2175 | return ret; | ||
2176 | } | ||
2177 | |||
2178 | msleep(20); | ||
2179 | ret = hub_port_status(hub, port, &portstatus, &portchange); | ||
2180 | |||
2181 | if (portchange & USB_PORT_STAT_C_RESET) | ||
2182 | clear_port_feature(hub->hdev, port, USB_PORT_FEAT_C_RESET); | ||
2183 | |||
2184 | if (portchange & USB_PORT_STAT_C_BH_RESET) | ||
2185 | clear_port_feature(hub->hdev, port, | ||
2186 | USB_PORT_FEAT_C_BH_PORT_RESET); | ||
2187 | |||
2188 | if (portchange & USB_PORT_STAT_C_LINK_STATE) | ||
2189 | clear_port_feature(hub->hdev, port, | ||
2190 | USB_PORT_FEAT_C_PORT_LINK_STATE); | ||
2191 | 2242 | ||
2192 | return ret; | 2243 | return status; |
2193 | } | 2244 | } |
2194 | 2245 | ||
2195 | /* Check if a port is power on */ | 2246 | /* Check if a port is power on */ |
@@ -2324,8 +2375,6 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) | |||
2324 | int port1 = udev->portnum; | 2375 | int port1 = udev->portnum; |
2325 | int status; | 2376 | int status; |
2326 | 2377 | ||
2327 | // dev_dbg(hub->intfdev, "suspend port %d\n", port1); | ||
2328 | |||
2329 | /* enable remote wakeup when appropriate; this lets the device | 2378 | /* enable remote wakeup when appropriate; this lets the device |
2330 | * wake up the upstream hub (including maybe the root hub). | 2379 | * wake up the upstream hub (including maybe the root hub). |
2331 | * | 2380 | * |
@@ -2342,11 +2391,15 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) | |||
2342 | dev_dbg(&udev->dev, "won't remote wakeup, status %d\n", | 2391 | dev_dbg(&udev->dev, "won't remote wakeup, status %d\n", |
2343 | status); | 2392 | status); |
2344 | /* bail if autosuspend is requested */ | 2393 | /* bail if autosuspend is requested */ |
2345 | if (msg.event & PM_EVENT_AUTO) | 2394 | if (PMSG_IS_AUTO(msg)) |
2346 | return status; | 2395 | return status; |
2347 | } | 2396 | } |
2348 | } | 2397 | } |
2349 | 2398 | ||
2399 | /* disable USB2 hardware LPM */ | ||
2400 | if (udev->usb2_hw_lpm_enabled == 1) | ||
2401 | usb_set_usb2_hardware_lpm(udev, 0); | ||
2402 | |||
2350 | /* see 7.1.7.6 */ | 2403 | /* see 7.1.7.6 */ |
2351 | if (hub_is_superspeed(hub->hdev)) | 2404 | if (hub_is_superspeed(hub->hdev)) |
2352 | status = set_port_feature(hub->hdev, | 2405 | status = set_port_feature(hub->hdev, |
@@ -2367,12 +2420,13 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) | |||
2367 | USB_CTRL_SET_TIMEOUT); | 2420 | USB_CTRL_SET_TIMEOUT); |
2368 | 2421 | ||
2369 | /* System sleep transitions should never fail */ | 2422 | /* System sleep transitions should never fail */ |
2370 | if (!(msg.event & PM_EVENT_AUTO)) | 2423 | if (!PMSG_IS_AUTO(msg)) |
2371 | status = 0; | 2424 | status = 0; |
2372 | } else { | 2425 | } else { |
2373 | /* device has up to 10 msec to fully suspend */ | 2426 | /* device has up to 10 msec to fully suspend */ |
2374 | dev_dbg(&udev->dev, "usb %ssuspend\n", | 2427 | dev_dbg(&udev->dev, "usb %ssuspend, wakeup %d\n", |
2375 | (msg.event & PM_EVENT_AUTO ? "auto-" : "")); | 2428 | (PMSG_IS_AUTO(msg) ? "auto-" : ""), |
2429 | udev->do_remote_wakeup); | ||
2376 | usb_set_device_state(udev, USB_STATE_SUSPENDED); | 2430 | usb_set_device_state(udev, USB_STATE_SUSPENDED); |
2377 | msleep(10); | 2431 | msleep(10); |
2378 | } | 2432 | } |
@@ -2523,7 +2577,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) | |||
2523 | } else { | 2577 | } else { |
2524 | /* drive resume for at least 20 msec */ | 2578 | /* drive resume for at least 20 msec */ |
2525 | dev_dbg(&udev->dev, "usb %sresume\n", | 2579 | dev_dbg(&udev->dev, "usb %sresume\n", |
2526 | (msg.event & PM_EVENT_AUTO ? "auto-" : "")); | 2580 | (PMSG_IS_AUTO(msg) ? "auto-" : "")); |
2527 | msleep(25); | 2581 | msleep(25); |
2528 | 2582 | ||
2529 | /* Virtual root hubs can trigger on GET_PORT_STATUS to | 2583 | /* Virtual root hubs can trigger on GET_PORT_STATUS to |
@@ -2558,7 +2612,12 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) | |||
2558 | if (status < 0) { | 2612 | if (status < 0) { |
2559 | dev_dbg(&udev->dev, "can't resume, status %d\n", status); | 2613 | dev_dbg(&udev->dev, "can't resume, status %d\n", status); |
2560 | hub_port_logical_disconnect(hub, port1); | 2614 | hub_port_logical_disconnect(hub, port1); |
2615 | } else { | ||
2616 | /* Try to enable USB2 hardware LPM */ | ||
2617 | if (udev->usb2_hw_lpm_capable == 1) | ||
2618 | usb_set_usb2_hardware_lpm(udev, 1); | ||
2561 | } | 2619 | } |
2620 | |||
2562 | return status; | 2621 | return status; |
2563 | } | 2622 | } |
2564 | 2623 | ||
@@ -2625,7 +2684,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) | |||
2625 | udev = hdev->children [port1-1]; | 2684 | udev = hdev->children [port1-1]; |
2626 | if (udev && udev->can_submit) { | 2685 | if (udev && udev->can_submit) { |
2627 | dev_warn(&intf->dev, "port %d nyet suspended\n", port1); | 2686 | dev_warn(&intf->dev, "port %d nyet suspended\n", port1); |
2628 | if (msg.event & PM_EVENT_AUTO) | 2687 | if (PMSG_IS_AUTO(msg)) |
2629 | return -EBUSY; | 2688 | return -EBUSY; |
2630 | } | 2689 | } |
2631 | } | 2690 | } |
@@ -2798,7 +2857,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, | |||
2798 | int i, j, retval; | 2857 | int i, j, retval; |
2799 | unsigned delay = HUB_SHORT_RESET_TIME; | 2858 | unsigned delay = HUB_SHORT_RESET_TIME; |
2800 | enum usb_device_speed oldspeed = udev->speed; | 2859 | enum usb_device_speed oldspeed = udev->speed; |
2801 | char *speed, *type; | 2860 | const char *speed; |
2802 | int devnum = udev->devnum; | 2861 | int devnum = udev->devnum; |
2803 | 2862 | ||
2804 | /* root hub ports have a slightly longer reset period | 2863 | /* root hub ports have a slightly longer reset period |
@@ -2819,7 +2878,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, | |||
2819 | 2878 | ||
2820 | /* Reset the device; full speed may morph to high speed */ | 2879 | /* Reset the device; full speed may morph to high speed */ |
2821 | /* FIXME a USB 2.0 device may morph into SuperSpeed on reset. */ | 2880 | /* FIXME a USB 2.0 device may morph into SuperSpeed on reset. */ |
2822 | retval = hub_port_reset(hub, port1, udev, delay); | 2881 | retval = hub_port_reset(hub, port1, udev, delay, false); |
2823 | if (retval < 0) /* error or disconnect */ | 2882 | if (retval < 0) /* error or disconnect */ |
2824 | goto fail; | 2883 | goto fail; |
2825 | /* success, speed is known */ | 2884 | /* success, speed is known */ |
@@ -2858,25 +2917,16 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, | |||
2858 | default: | 2917 | default: |
2859 | goto fail; | 2918 | goto fail; |
2860 | } | 2919 | } |
2861 | 2920 | ||
2862 | type = ""; | 2921 | if (udev->speed == USB_SPEED_WIRELESS) |
2863 | switch (udev->speed) { | 2922 | speed = "variable speed Wireless"; |
2864 | case USB_SPEED_LOW: speed = "low"; break; | 2923 | else |
2865 | case USB_SPEED_FULL: speed = "full"; break; | 2924 | speed = usb_speed_string(udev->speed); |
2866 | case USB_SPEED_HIGH: speed = "high"; break; | 2925 | |
2867 | case USB_SPEED_SUPER: | ||
2868 | speed = "super"; | ||
2869 | break; | ||
2870 | case USB_SPEED_WIRELESS: | ||
2871 | speed = "variable"; | ||
2872 | type = "Wireless "; | ||
2873 | break; | ||
2874 | default: speed = "?"; break; | ||
2875 | } | ||
2876 | if (udev->speed != USB_SPEED_SUPER) | 2926 | if (udev->speed != USB_SPEED_SUPER) |
2877 | dev_info(&udev->dev, | 2927 | dev_info(&udev->dev, |
2878 | "%s %s speed %sUSB device number %d using %s\n", | 2928 | "%s %s USB device number %d using %s\n", |
2879 | (udev->config) ? "reset" : "new", speed, type, | 2929 | (udev->config) ? "reset" : "new", speed, |
2880 | devnum, udev->bus->controller->driver->name); | 2930 | devnum, udev->bus->controller->driver->name); |
2881 | 2931 | ||
2882 | /* Set up TT records, if needed */ | 2932 | /* Set up TT records, if needed */ |
@@ -2949,7 +2999,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, | |||
2949 | buf->bMaxPacketSize0; | 2999 | buf->bMaxPacketSize0; |
2950 | kfree(buf); | 3000 | kfree(buf); |
2951 | 3001 | ||
2952 | retval = hub_port_reset(hub, port1, udev, delay); | 3002 | retval = hub_port_reset(hub, port1, udev, delay, false); |
2953 | if (retval < 0) /* error or disconnect */ | 3003 | if (retval < 0) /* error or disconnect */ |
2954 | goto fail; | 3004 | goto fail; |
2955 | if (oldspeed != udev->speed) { | 3005 | if (oldspeed != udev->speed) { |
@@ -3023,7 +3073,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, | |||
3023 | i = 512; | 3073 | i = 512; |
3024 | else | 3074 | else |
3025 | i = udev->descriptor.bMaxPacketSize0; | 3075 | i = udev->descriptor.bMaxPacketSize0; |
3026 | if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) { | 3076 | if (usb_endpoint_maxp(&udev->ep0.desc) != i) { |
3027 | if (udev->speed == USB_SPEED_LOW || | 3077 | if (udev->speed == USB_SPEED_LOW || |
3028 | !(i == 8 || i == 16 || i == 32 || i == 64)) { | 3078 | !(i == 8 || i == 16 || i == 32 || i == 64)) { |
3029 | dev_err(&udev->dev, "Invalid ep0 maxpacket: %d\n", i); | 3079 | dev_err(&udev->dev, "Invalid ep0 maxpacket: %d\n", i); |
@@ -3047,6 +3097,15 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, | |||
3047 | goto fail; | 3097 | goto fail; |
3048 | } | 3098 | } |
3049 | 3099 | ||
3100 | if (udev->wusb == 0 && le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0201) { | ||
3101 | retval = usb_get_bos_descriptor(udev); | ||
3102 | if (!retval) { | ||
3103 | if (udev->bos->ext_cap && (USB_LPM_SUPPORT & | ||
3104 | le32_to_cpu(udev->bos->ext_cap->bmAttributes))) | ||
3105 | udev->lpm_capable = 1; | ||
3106 | } | ||
3107 | } | ||
3108 | |||
3050 | retval = 0; | 3109 | retval = 0; |
3051 | /* notify HCD that we have a device connected and addressed */ | 3110 | /* notify HCD that we have a device connected and addressed */ |
3052 | if (hcd->driver->update_device) | 3111 | if (hcd->driver->update_device) |
@@ -3570,7 +3629,8 @@ static void hub_events(void) | |||
3570 | (portstatus & USB_PORT_STAT_LINK_STATE) | 3629 | (portstatus & USB_PORT_STAT_LINK_STATE) |
3571 | == USB_SS_PORT_LS_SS_INACTIVE) { | 3630 | == USB_SS_PORT_LS_SS_INACTIVE) { |
3572 | dev_dbg(hub_dev, "warm reset port %d\n", i); | 3631 | dev_dbg(hub_dev, "warm reset port %d\n", i); |
3573 | hub_port_warm_reset(hub, i); | 3632 | hub_port_reset(hub, i, NULL, |
3633 | HUB_BH_RESET_TIME, true); | ||
3574 | } | 3634 | } |
3575 | 3635 | ||
3576 | if (connect_change) | 3636 | if (connect_change) |