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 <jwerner@chromium.org>
(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 <taysom@chromium.org>
Commit-Queue: Julius Werner <jwerner@chromium.org>
Tested-by: Julius Werner <jwerner@chromium.org>
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <linux/dmi.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/module.h>
{
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) {
}
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);