提交 151b6128 编写于 作者: A Alan Stern 提交者: Greg Kroah-Hartman

USB: EHCI: fix crash during suspend on ASUS computers

This patch (as1545) fixes a problem affecting several ASUS computers:
The machine crashes or corrupts memory when going into suspend if the
ehci-hcd driver is bound to any controllers.  Users have been forced
to unbind or unload ehci-hcd before putting their systems to sleep.

After extensive testing, it was determined that the machines don't
like going into suspend when any EHCI controllers are in the PCI D3
power state.  Presumably this is a firmware bug, but there's nothing
we can do about it except to avoid putting the controllers in D3
during system sleep.

The patch adds a new flag to indicate whether the problem is present,
and avoids changing the controller's power state if the flag is set.
Runtime suspend is unaffected; this matters only for system suspend.
However as a side effect, the controller will not respond to remote
wakeup requests while the system is asleep.  Hence USB wakeup is not
functional -- but of course, this is already true in the current state
of affairs.

This fixes Bugzilla #42728.
Signed-off-by: NAlan Stern <stern@rowland.harvard.edu>
Tested-by: NSteven Rostedt <rostedt@goodmis.org>
Tested-by: NAndrey Rahmatullin <wrar@wrar.name>
Tested-by: NOleksij Rempel (fishor) <bug-track@fisher-privat.net>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
上级 6f6543f5
...@@ -493,6 +493,15 @@ static int hcd_pci_suspend_noirq(struct device *dev) ...@@ -493,6 +493,15 @@ static int hcd_pci_suspend_noirq(struct device *dev)
pci_save_state(pci_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 /* If the root hub is dead rather than suspended, disallow remote
* wakeup. usb_hc_died() should ensure that both hosts are marked as * wakeup. usb_hc_died() should ensure that both hosts are marked as
* dying, so we only need to check the primary roothub. * dying, so we only need to check the primary roothub.
......
...@@ -144,6 +144,14 @@ static int ehci_pci_setup(struct usb_hcd *hcd) ...@@ -144,6 +144,14 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
hcd->has_tt = 1; hcd->has_tt = 1;
tdi_reset(ehci); 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; break;
case PCI_VENDOR_ID_TDI: case PCI_VENDOR_ID_TDI:
if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
......
...@@ -126,6 +126,8 @@ struct usb_hcd { ...@@ -126,6 +126,8 @@ struct usb_hcd {
unsigned wireless:1; /* Wireless USB HCD */ unsigned wireless:1; /* Wireless USB HCD */
unsigned authorized_default:1; unsigned authorized_default:1;
unsigned has_tt:1; /* Integrated TT in root hub */ 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 */ unsigned int irq; /* irq allocated */
void __iomem *regs; /* device memory/io */ void __iomem *regs; /* device memory/io */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册