Message ID | 20200824063623.7581-2-kai.heng.feng@canonical.com |
---|---|
State | New |
Headers | show |
Series | Fix non-working USB devices plugged during system sleep | expand |
On 24.08.20 08:36, Kai-Heng Feng wrote: > BugLink: https://bugs.launchpad.net/bugs/1892678 > > Sometimes re-plugging a USB device during system sleep renders the device > useless: > [ 173.418345] xhci_hcd 0000:00:14.0: Get port status 2-4 read: 0x14203e2, return 0x10262 > ... > [ 176.496485] usb 2-4: Waited 2000ms for CONNECT > [ 176.496781] usb usb2-port4: status 0000.0262 after resume, -19 > [ 176.497103] usb 2-4: can't resume, status -19 > [ 176.497438] usb usb2-port4: logical disconnect > > Because PLS equals to XDEV_RESUME, xHCI driver reports U3 to usbcore, > despite of CAS bit is flagged. > > So proritize CAS over XDEV_RESUME to let usbcore handle warm-reset for > the port. > > Cc: stable <stable@vger.kernel.org> > Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com> > Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> > Link: https://lore.kernel.org/r/20200821091549.20556-3-mathias.nyman@linux.intel.com > Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> > (cherry picked from commit 904df64a5f4d5ebd670801d869ca0a6d6a6e8df6 linux-next) > Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com> Acked-by: Stefan Bader <stefan.bader@canonical.com> > --- > drivers/usb/host/xhci-hub.c | 19 ++++++++++--------- > 1 file changed, 10 insertions(+), 9 deletions(-) > > diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c > index f37316d2c8fa..fa8f7935c2ab 100644 > --- a/drivers/usb/host/xhci-hub.c > +++ b/drivers/usb/host/xhci-hub.c > @@ -740,15 +740,6 @@ static void xhci_hub_report_usb3_link_state(struct xhci_hcd *xhci, > { > u32 pls = status_reg & PORT_PLS_MASK; > > - /* resume state is a xHCI internal state. > - * Do not report it to usb core, instead, pretend to be U3, > - * thus usb core knows it's not ready for transfer > - */ > - if (pls == XDEV_RESUME) { > - *status |= USB_SS_PORT_LS_U3; > - return; > - } > - > /* When the CAS bit is set then warm reset > * should be performed on port > */ > @@ -770,6 +761,16 @@ static void xhci_hub_report_usb3_link_state(struct xhci_hcd *xhci, > */ > pls |= USB_PORT_STAT_CONNECTION; > } else { > + /* > + * Resume state is an xHCI internal state. Do not report it to > + * usb core, instead, pretend to be U3, thus usb core knows > + * it's not ready for transfer. > + */ > + if (pls == XDEV_RESUME) { > + *status |= USB_SS_PORT_LS_U3; > + return; > + } > + > /* > * If CAS bit isn't set but the Port is already at > * Compliance Mode, fake a connection so the USB core >
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index f37316d2c8fa..fa8f7935c2ab 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -740,15 +740,6 @@ static void xhci_hub_report_usb3_link_state(struct xhci_hcd *xhci, { u32 pls = status_reg & PORT_PLS_MASK; - /* resume state is a xHCI internal state. - * Do not report it to usb core, instead, pretend to be U3, - * thus usb core knows it's not ready for transfer - */ - if (pls == XDEV_RESUME) { - *status |= USB_SS_PORT_LS_U3; - return; - } - /* When the CAS bit is set then warm reset * should be performed on port */ @@ -770,6 +761,16 @@ static void xhci_hub_report_usb3_link_state(struct xhci_hcd *xhci, */ pls |= USB_PORT_STAT_CONNECTION; } else { + /* + * Resume state is an xHCI internal state. Do not report it to + * usb core, instead, pretend to be U3, thus usb core knows + * it's not ready for transfer. + */ + if (pls == XDEV_RESUME) { + *status |= USB_SS_PORT_LS_U3; + return; + } + /* * If CAS bit isn't set but the Port is already at * Compliance Mode, fake a connection so the USB core