|
@@ -2324,12 +2324,16 @@ static unsigned hub_is_wusb(struct usb_hub *hub)
|
|
|
static int hub_port_reset(struct usb_hub *hub, int port1,
|
|
static int hub_port_reset(struct usb_hub *hub, int port1,
|
|
|
struct usb_device *udev, unsigned int delay, bool warm);
|
|
struct usb_device *udev, unsigned int delay, bool warm);
|
|
|
|
|
|
|
|
-/* Is a USB 3.0 port in the Inactive state? */
|
|
|
|
|
-static bool hub_port_inactive(struct usb_hub *hub, u16 portstatus)
|
|
|
|
|
|
|
+/* Is a USB 3.0 port in the Inactive or Complinance Mode state?
|
|
|
|
|
+ * Port worm reset is required to recover
|
|
|
|
|
+ */
|
|
|
|
|
+static bool hub_port_warm_reset_required(struct usb_hub *hub, u16 portstatus)
|
|
|
{
|
|
{
|
|
|
return hub_is_superspeed(hub->hdev) &&
|
|
return hub_is_superspeed(hub->hdev) &&
|
|
|
- (portstatus & USB_PORT_STAT_LINK_STATE) ==
|
|
|
|
|
- USB_SS_PORT_LS_SS_INACTIVE;
|
|
|
|
|
|
|
+ (((portstatus & USB_PORT_STAT_LINK_STATE) ==
|
|
|
|
|
+ USB_SS_PORT_LS_SS_INACTIVE) ||
|
|
|
|
|
+ ((portstatus & USB_PORT_STAT_LINK_STATE) ==
|
|
|
|
|
+ USB_SS_PORT_LS_COMP_MOD)) ;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static int hub_port_wait_reset(struct usb_hub *hub, int port1,
|
|
static int hub_port_wait_reset(struct usb_hub *hub, int port1,
|
|
@@ -2365,7 +2369,7 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
|
|
|
*
|
|
*
|
|
|
* See https://bugzilla.kernel.org/show_bug.cgi?id=41752
|
|
* See https://bugzilla.kernel.org/show_bug.cgi?id=41752
|
|
|
*/
|
|
*/
|
|
|
- if (hub_port_inactive(hub, portstatus)) {
|
|
|
|
|
|
|
+ if (hub_port_warm_reset_required(hub, portstatus)) {
|
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
|
|
if ((portchange & USB_PORT_STAT_C_CONNECTION))
|
|
if ((portchange & USB_PORT_STAT_C_CONNECTION))
|
|
@@ -4408,9 +4412,7 @@ static void hub_events(void)
|
|
|
/* Warm reset a USB3 protocol port if it's in
|
|
/* Warm reset a USB3 protocol port if it's in
|
|
|
* SS.Inactive state.
|
|
* SS.Inactive state.
|
|
|
*/
|
|
*/
|
|
|
- if (hub_is_superspeed(hub->hdev) &&
|
|
|
|
|
- (portstatus & USB_PORT_STAT_LINK_STATE)
|
|
|
|
|
- == USB_SS_PORT_LS_SS_INACTIVE) {
|
|
|
|
|
|
|
+ if (hub_port_warm_reset_required(hub, portstatus)) {
|
|
|
dev_dbg(hub_dev, "warm reset port %d\n", i);
|
|
dev_dbg(hub_dev, "warm reset port %d\n", i);
|
|
|
hub_port_reset(hub, i, NULL,
|
|
hub_port_reset(hub, i, NULL,
|
|
|
HUB_BH_RESET_TIME, true);
|
|
HUB_BH_RESET_TIME, true);
|