xhci: Avoid USB autosuspend when resuming USB2 ports.
authorAnshuman Gupta <anshuman.gupta@intel.com>
Thu, 20 Sep 2018 16:13:40 +0000 (19:13 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 28 Sep 2018 13:04:45 +0000 (15:04 +0200)
When USB bus host controller root hub resumes from autosuspend,
it immediately tries to enter auto-suspend, but there can be a
scenario when root hub is resuming its usb2 ports, in that particular
case USB host controller auto suspend fails since it is busy
to resuming its usb2 ports.

This makes multiple failed cycles of auto-suspend until all usb2
ports of host controller root hub do not resume.

This patch uses USB core framework usb_hcd_start_port_resume,
usb_hcd_end_port_resume API's in order to  autoresume/autosuspend
root hub properly.

Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-ring.c

index 7e2a531ba321d4d3d50b24fe1278332e128821c1..12eea73d9f20b00701e22da8debdcaa1d9283c92 100644 (file)
@@ -900,6 +900,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
                                set_bit(wIndex, &bus_state->resuming_ports);
                                bus_state->resume_done[wIndex] = timeout;
                                mod_timer(&hcd->rh_timer, timeout);
+                               usb_hcd_start_port_resume(&hcd->self, wIndex);
                        }
                /* Has resume been signalled for USB_RESUME_TIME yet? */
                } else if (time_after_eq(jiffies,
@@ -940,6 +941,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
                                clear_bit(wIndex, &bus_state->rexit_ports);
                        }
 
+                       usb_hcd_end_port_resume(&hcd->self, wIndex);
                        bus_state->port_c_suspend |= 1 << wIndex;
                        bus_state->suspended_ports &= ~(1 << wIndex);
                } else {
@@ -962,6 +964,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
            (raw_port_status & PORT_PLS_MASK) != XDEV_RESUME) {
                bus_state->resume_done[wIndex] = 0;
                clear_bit(wIndex, &bus_state->resuming_ports);
+               usb_hcd_end_port_resume(&hcd->self, wIndex);
        }
 
 
@@ -1337,6 +1340,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                                        goto error;
 
                                set_bit(wIndex, &bus_state->resuming_ports);
+                               usb_hcd_start_port_resume(&hcd->self, wIndex);
                                xhci_set_link_state(xhci, ports[wIndex],
                                                    XDEV_RESUME);
                                spin_unlock_irqrestore(&xhci->lock, flags);
@@ -1345,6 +1349,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                                xhci_set_link_state(xhci, ports[wIndex],
                                                        XDEV_U0);
                                clear_bit(wIndex, &bus_state->resuming_ports);
+                               usb_hcd_end_port_resume(&hcd->self, wIndex);
                        }
                        bus_state->port_c_suspend |= 1 << wIndex;
 
index c41341ea84496a518170200836412c4f5a86b1e3..a8d92c90fb58755ad4359d94d4e52f50b949b2a0 100644 (file)
@@ -1606,6 +1606,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
                        set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
                        mod_timer(&hcd->rh_timer,
                                  bus_state->resume_done[hcd_portnum]);
+                       usb_hcd_start_port_resume(&hcd->self, hcd_portnum);
                        bogus_port_status = true;
                }
        }