From 0b4c290665ab192a941df068659706c41e1a9ad0 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 24 Apr 2012 14:07:22 -0400 Subject: [PATCH] --- yaml --- r: 299825 b: refs/heads/master c: 151b61284776be2d6f02d48c23c3625678960b97 h: refs/heads/master i: 299823: 01ea9639032197a4af8a8e3622878974a37626b4 v: v3 --- [refs] | 2 +- trunk/drivers/usb/core/hcd-pci.c | 9 +++++++++ trunk/drivers/usb/host/ehci-pci.c | 8 ++++++++ trunk/include/linux/usb/hcd.h | 2 ++ 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index 2fff4a504e65..5599e727c590 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 6f6543f53f9ce136e01d7114bf6f0818ca54fb41 +refs/heads/master: 151b61284776be2d6f02d48c23c3625678960b97 diff --git a/trunk/drivers/usb/core/hcd-pci.c b/trunk/drivers/usb/core/hcd-pci.c index 622b4a48e732..57ed9e400c06 100644 --- a/trunk/drivers/usb/core/hcd-pci.c +++ b/trunk/drivers/usb/core/hcd-pci.c @@ -493,6 +493,15 @@ static int hcd_pci_suspend_noirq(struct device *dev) pci_save_state(pci_dev); + /* + * Some systems crash if an EHCI controller is in D3 during + * a sleep transition. We have to leave such controllers in D0. + */ + if (hcd->broken_pci_sleep) { + dev_dbg(dev, "Staying in PCI D0\n"); + return retval; + } + /* If the root hub is dead rather than suspended, disallow remote * wakeup. usb_hc_died() should ensure that both hosts are marked as * dying, so we only need to check the primary roothub. diff --git a/trunk/drivers/usb/host/ehci-pci.c b/trunk/drivers/usb/host/ehci-pci.c index 01bb7241d6ef..fe8dc069164e 100644 --- a/trunk/drivers/usb/host/ehci-pci.c +++ b/trunk/drivers/usb/host/ehci-pci.c @@ -144,6 +144,14 @@ static int ehci_pci_setup(struct usb_hcd *hcd) hcd->has_tt = 1; tdi_reset(ehci); } + if (pdev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK) { + /* EHCI #1 or #2 on 6 Series/C200 Series chipset */ + if (pdev->device == 0x1c26 || pdev->device == 0x1c2d) { + ehci_info(ehci, "broken D3 during system sleep on ASUS\n"); + hcd->broken_pci_sleep = 1; + device_set_wakeup_capable(&pdev->dev, false); + } + } break; case PCI_VENDOR_ID_TDI: if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { diff --git a/trunk/include/linux/usb/hcd.h b/trunk/include/linux/usb/hcd.h index 5de415707c23..d28cc78a38e4 100644 --- a/trunk/include/linux/usb/hcd.h +++ b/trunk/include/linux/usb/hcd.h @@ -126,6 +126,8 @@ struct usb_hcd { unsigned wireless:1; /* Wireless USB HCD */ unsigned authorized_default:1; unsigned has_tt:1; /* Integrated TT in root hub */ + unsigned broken_pci_sleep:1; /* Don't put the + controller in PCI-D3 for system sleep */ unsigned int irq; /* irq allocated */ void __iomem *regs; /* device memory/io */