patch "xhci: workaround for hosts missing CAS bit" added to usb-linus
Subsystems (3)
This is a note to let you know that I've just added the patch titled
xhci: workaround for hosts missing CAS bit
to my usb git tree which can be found at
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git
in the usb-linus branch.
The patch will show up in the next release of the linux-next tree (usually sometime within the next 24 hours during the week.)
The patch will hopefully also be merged in Linus's tree for the next -rc kernel release.
If you have any questions about this process, please let me know.
Quoted 1 line
From
346e99736c3ce328fd42d678343b70243aca5f36Mon Sep 17 00:00:00 2001
From: Mathias Nyman <[email protected]>
Date: Thu, 20 Oct 2016 18:09:19 +0300
Subject: xhci: workaround for hosts missing CAS bit
If a device is unplugged and replugged during Sx system suspend some Intel xHC hosts will overwrite the CAS (Cold attach status) flag and no device connection is noticed in resume.
A device in this state can be identified in resume if its link state is in polling or compliance mode, and the current connect status is 0. A device in this state needs to be warm reset.
Intel 100/c230 series PCH specification update Doc #332692-006 Errata #8
Observed on Cherryview and Apollolake as they go into compliance mode if LFPS times out during polling, and re-plugged devices are not discovered at resume.
--- drivers/usb/host/xhci-hub.c | 37 +++++++++++++++++++++++++++++++++++++ drivers/usb/host/xhci-pci.c | 6 ++++++ drivers/usb/host/xhci.h | 3 +++ 3 files changed, 46 insertions(+)
drivers/usb/host/xhci-hub.c +37 -0
@@ -1355,6 +1355,35 @@ int xhci_bus_suspend(struct usb_hcd *hcd)return 0 ; } +/* +* Workaround for missing Cold Attach Status (CAS) if device re-plugged in S3. +* warm reset a USB3 device stuck in polling or compliance mode after resume. +* See Intel 100/c230 series PCH specification update Doc #332692-006 Errata #8 +*/ +static bool xhci_port_missing_cas_quirk (int port_index, +__le32 __iomem **port_array) +{ +u32 portsc; + + portsc =readl (port_array[port_index]); + +/* if any of these are set we are not stuck */ +if (portsc & (PORT_CONNECT |PORT_CAS )) +return false; + +if (((portsc &PORT_PLS_MASK ) !=XDEV_POLLING ) && + ((portsc &PORT_PLS_MASK ) !=XDEV_COMP_MODE )) +return false; + +/* clear wakeup/change bits, and do a warm port reset */ + portsc &= ~(PORT_RWC_BITS |PORT_CEC |PORT_WAKE_BITS ); + portsc |=PORT_WR ; +writel (portsc, port_array[port_index]); +/* flush write */ +readl (port_array[port_index]); +return true; +} +int xhci_bus_resume (struct usb_hcd *hcd) {struct xhci_hcd *xhci =hcd_to_xhci (hcd);
@@ -1392,6 +1421,14 @@ int xhci_bus_resume(struct usb_hcd *hcd)u32 temp; temp =readl (port_array[port_index]); + +/* warm reset CAS limited ports stuck in polling/compliance */ +if ((xhci->quirks &XHCI_MISSING_CAS ) && + (hcd->speed >=HCD_USB3 ) && +xhci_port_missing_cas_quirk (port_index, port_array)) { +xhci_dbg (xhci,"reset stuck port %d\n" , port_index); +continue ; + }if (DEV_SUPERSPEED_ANY (temp)) temp &= ~(PORT_RWC_BITS |PORT_CEC |PORT_WAKE_BITS );else
drivers/usb/host/xhci-pci.c +6 -0
@@ -51,6 +51,7 @@#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI 0x9d2f#define PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI 0x0aa8#define PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI 0x1aa8 +#define PCI_DEVICE_ID_INTEL_APL_XHCI 0x5aa8static const char hcd_name[] ="xhci_hcd" ;
@@ -171,6 +172,11 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) { xhci->quirks |=XHCI_SSIC_PORT_UNUSED ; } +if (pdev->vendor ==PCI_VENDOR_ID_INTEL && + (pdev->device ==PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI || + pdev->device ==PCI_DEVICE_ID_INTEL_APL_XHCI )) + xhci->quirks |=XHCI_MISSING_CAS ; +if (pdev->vendor ==PCI_VENDOR_ID_ETRON && pdev->device ==PCI_DEVICE_ID_EJ168 ) { xhci->quirks |=XHCI_RESET_ON_RESUME ;
drivers/usb/host/xhci.h +3 -0
@@ -314,6 +314,8 @@ struct xhci_op_regs {#define XDEV_U2 (0x2 << 5)#define XDEV_U3 (0x3 << 5)#define XDEV_INACTIVE (0x6 << 5) +#define XDEV_POLLING (0x7 << 5) +#define XDEV_COMP_MODE (0xa << 5)#define XDEV_RESUME (0xf << 5)/* true: port has power (see HCC_PPC) */ #define PORT_POWER (1 << 9)
@@ -1653,6 +1655,7 @@ struct xhci_hcd {#define XHCI_MTK_HOST (1 << 21)#define XHCI_SSIC_PORT_UNUSED (1 << 22)#define XHCI_NO_64BIT_SUPPORT (1 << 23) +#define XHCI_MISSING_CAS (1 << 24)unsigned int num_active_eps;unsigned int limit_active_eps;/* There are two roothubs to keep track of bus suspend info for */
Signature · 1 line
2.10.0