diff mbox series

[1/1] xhci: Do warm-reset when both CAS and XDEV_RESUME are set

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

Commit Message

Kai-Heng Feng Aug. 24, 2020, 6:36 a.m. UTC
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>
---
 drivers/usb/host/xhci-hub.c | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

Comments

Stefan Bader Aug. 24, 2020, 7:20 a.m. UTC | #1
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 mbox series

Patch

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