Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit de24ca61 authored by Kai-Heng Feng's avatar Kai-Heng Feng Committed by Greg Kroah-Hartman
Browse files

xhci: Do warm-reset when both CAS and XDEV_RESUME are set



commit 904df64a5f4d5ebd670801d869ca0a6d6a6e8df6 upstream.

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: default avatarKai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: default avatarMathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20200821091549.20556-3-mathias.nyman@linux.intel.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 567e1a91
Loading
Loading
Loading
Loading
+10 −9
Original line number Original line Diff line number Diff line
@@ -736,15 +736,6 @@ static void xhci_hub_report_usb3_link_state(struct xhci_hcd *xhci,
{
{
	u32 pls = status_reg & PORT_PLS_MASK;
	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
	/* When the CAS bit is set then warm reset
	 * should be performed on port
	 * should be performed on port
	 */
	 */
@@ -766,6 +757,16 @@ static void xhci_hub_report_usb3_link_state(struct xhci_hcd *xhci,
		 */
		 */
		pls |= USB_PORT_STAT_CONNECTION;
		pls |= USB_PORT_STAT_CONNECTION;
	} else {
	} 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
		 * If CAS bit isn't set but the Port is already at
		 * Compliance Mode, fake a connection so the USB core
		 * Compliance Mode, fake a connection so the USB core