]> git.hungrycats.org Git - linux/commitdiff
xhci: clear usb2 resume related variables in one place.
authorMathias Nyman <mathias.nyman@linux.intel.com>
Thu, 2 Feb 2023 15:05:04 +0000 (17:05 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 1 Mar 2024 12:21:57 +0000 (13:21 +0100)
[ Upstream commit 0e6275452ce26d7ff274a5c1b15ed581a26f7986 ]

Initially resume related USB2 variables were cleared once port
successfully resumed to U0. Later code was added to clean up
stale resume variables in case of port failed to resume to U0.

Clear the variables in one place after port is no longer resuming
or in suspended U3 state.

Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20230202150505.618915-11-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Stable-dep-of: d7cdfc319b2b ("xhci: track port suspend state correctly in unsuccessful resume cases")
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/usb/host/xhci-hub.c

index d3d3dadaca10bb7ad95c67baf4df4dc17485b1ad..660a7d0f79a42d1636022774e32d7ba7836b3131 100644 (file)
@@ -1071,7 +1071,6 @@ static void xhci_get_usb2_port_status(struct xhci_port *port, u32 *status,
        struct xhci_bus_state *bus_state;
        u32 link_state;
        u32 portnum;
-       int ret;
 
        bus_state = &port->rhub->bus_state;
        link_state = portsc & PORT_PLS_MASK;
@@ -1087,23 +1086,30 @@ static void xhci_get_usb2_port_status(struct xhci_port *port, u32 *status,
                if (link_state == XDEV_U2)
                        *status |= USB_PORT_STAT_L1;
                if (link_state == XDEV_U0) {
-                       if (port->resume_timestamp)
-                               usb_hcd_end_port_resume(&port->rhub->hcd->self,
-                                                       portnum);
-                       port->resume_timestamp = 0;
-                       clear_bit(portnum, &bus_state->resuming_ports);
                        if (bus_state->suspended_ports & (1 << portnum)) {
                                bus_state->suspended_ports &= ~(1 << portnum);
                                bus_state->port_c_suspend |= 1 << portnum;
                        }
                }
                if (link_state == XDEV_RESUME) {
-                       ret = xhci_handle_usb2_port_link_resume(port, status,
-                                                               portsc, flags);
-                       if (ret)
-                               return;
+                       xhci_handle_usb2_port_link_resume(port, status, portsc,
+                                                         flags);
                }
        }
+
+       /*
+        * Clear usb2 resume signalling variables if port is no longer suspended
+        * or resuming. Port either resumed to U0/U1/U2, disconnected, or in a
+        * error state. Resume related variables should be cleared in all those cases.
+        */
+       if ((link_state != XDEV_U3 &&
+            link_state != XDEV_RESUME) &&
+           (port->resume_timestamp ||
+            test_bit(portnum, &bus_state->resuming_ports))) {
+               port->resume_timestamp = 0;
+               clear_bit(portnum, &bus_state->resuming_ports);
+               usb_hcd_end_port_resume(&port->rhub->hcd->self, portnum);
+       }
 }
 
 /*
@@ -1158,18 +1164,6 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
        else
                xhci_get_usb2_port_status(port, &status, raw_port_status,
                                          flags);
-       /*
-        * Clear stale usb2 resume signalling variables in case port changed
-        * state during resume signalling. For example on error
-        */
-       if ((port->resume_timestamp ||
-            test_bit(wIndex, &bus_state->resuming_ports)) &&
-           (raw_port_status & PORT_PLS_MASK) != XDEV_U3 &&
-           (raw_port_status & PORT_PLS_MASK) != XDEV_RESUME) {
-               port->resume_timestamp = 0;
-               clear_bit(wIndex, &bus_state->resuming_ports);
-               usb_hcd_end_port_resume(&hcd->self, wIndex);
-       }
 
        if (bus_state->port_c_suspend & (1 << wIndex))
                status |= USB_PORT_STAT_C_SUSPEND << 16;