From 0e93b14ce4804b38ec2fdbec25ac96fd2415906a Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Wed, 30 Jan 2013 18:02:45 -0800 Subject: [PATCH] CHROMIUM: xhci: crude USB resume fix for Stout (temporary) Stout's USB 3.0 ports show a variety of nasty issues after resume, some of which are more reproducible than others. They all have in common that the host controller bails with "Device not responding to set address." during enumeration. A trace pulled from a USB cable showed that the host controller just fills the bus with garbage and does not even generate correct SOF sequences. This seems like a large and time-consuming problem that could hide anywhere in the USB software or hardware stack. With Stout being close to release, we need an interim solution to make it usable while we find the underlying problem. This patch sets the XHCI_RESET_ON_RESUME quirk flag on Stout, which makes device reenumeration after resume work, but it creates a new issue that makes the host controller hang on the next suspend while trying to save its state. This looks like an unrelated hardware bug... but since we don't actually need to save state when we will reset anyway, we can just add some code to skip that step in xhci_suspend(). This patch is intended to be temporary, and should be reverted as soon as the root cause for this is found and fixed. BUG=chrome-os-partner:16781 TEST=Plug a USB device into the yellow port on the right. Run lsusb. Run powerd_suspend and wake the machine. Run lsusb again and ensure that the output stayed the same. Original-Change-Id: Id21ab972c698d02c14937509f699c9bc659b70c0 Signed-off-by: Julius Werner (cherry picked from commit 8b145d803ef366508c212072db0cd01718247241) Applied without conflicts to R25. Tested on 3428.124.0 stout canary image. Change-Id: I10bbe5414f1f52762ddd6a97e4231ab544b8e3b4 Reviewed-on: https://gerrit.chromium.org/gerrit/42541 Reviewed-by: Paul Taysom Commit-Queue: Julius Werner Tested-by: Julius Werner --- drivers/usb/host/xhci-pci.c | 13 +++++++++++++ drivers/usb/host/xhci.c | 7 +++++++ 2 files changed, 20 insertions(+) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 7a856a767e77c..97ca68f922fbb 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -20,6 +20,7 @@ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include #include #include @@ -56,6 +57,18 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) { struct pci_dev *pdev = to_pci_dev(dev); + /* TODO(jwerner): fix real problem and remove this */ + static struct dmi_system_id dmi_stout[] = { + { + .ident = "ChromeOS Stout", + .matches = {DMI_MATCH(DMI_PRODUCT_NAME, "Stout")} + }, { } + }; + if (dmi_check_system(dmi_stout)) { + xhci_warn(xhci, "Stout detected, using reset-on-resume hack\n"); + xhci->quirks |= XHCI_RESET_ON_RESUME; + } + /* Look for vendor-specific quirks */ if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC && pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK) { diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index a35fe76996d07..284cee3112ce4 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -780,6 +780,13 @@ int xhci_suspend(struct xhci_hcd *xhci) } xhci_clear_command_ring(xhci); + if (xhci->quirks & XHCI_RESET_ON_RESUME) { + xhci_info(xhci, "Will reset on resume, not saving xHC regs.\n"); + spin_unlock_irq(&xhci->lock); + xhci_msix_sync_irqs(xhci); + return rc; + } + /* step 3: save registers */ xhci_save_registers(xhci); -- 2.39.5