diff options
Diffstat (limited to 'recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.24/0037-PCI-EHCI-fix-crash-during-suspend-on-ASUS-computers.patch')
-rw-r--r-- | recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.24/0037-PCI-EHCI-fix-crash-during-suspend-on-ASUS-computers.patch | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.24/0037-PCI-EHCI-fix-crash-during-suspend-on-ASUS-computers.patch b/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.24/0037-PCI-EHCI-fix-crash-during-suspend-on-ASUS-computers.patch new file mode 100644 index 00000000..a5540c3f --- /dev/null +++ b/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.24/0037-PCI-EHCI-fix-crash-during-suspend-on-ASUS-computers.patch | |||
@@ -0,0 +1,166 @@ | |||
1 | From 45cd1f6207fb66990e5f25e11fb4cd9486c31794 Mon Sep 17 00:00:00 2001 | ||
2 | From: Alan Stern <stern@rowland.harvard.edu> | ||
3 | Date: Mon, 9 Jul 2012 11:09:21 -0400 | ||
4 | Subject: [PATCH 037/109] PCI: EHCI: fix crash during suspend on ASUS | ||
5 | computers | ||
6 | MIME-Version: 1.0 | ||
7 | Content-Type: text/plain; charset=UTF-8 | ||
8 | Content-Transfer-Encoding: 8bit | ||
9 | |||
10 | commit dbf0e4c7257f8d684ec1a3c919853464293de66e upstream. | ||
11 | |||
12 | Quite a few ASUS computers experience a nasty problem, related to the | ||
13 | EHCI controllers, when going into system suspend. It was observed | ||
14 | that the problem didn't occur if the controllers were not put into the | ||
15 | D3 power state before starting the suspend, and commit | ||
16 | 151b61284776be2d6f02d48c23c3625678960b97 (USB: EHCI: fix crash during | ||
17 | suspend on ASUS computers) was created to do this. | ||
18 | |||
19 | It turned out this approach messed up other computers that didn't have | ||
20 | the problem -- it prevented USB wakeup from working. Consequently | ||
21 | commit c2fb8a3fa25513de8fedb38509b1f15a5bbee47b (USB: add | ||
22 | NO_D3_DURING_SLEEP flag and revert 151b61284776be2) was merged; it | ||
23 | reverted the earlier commit and added a whitelist of known good board | ||
24 | names. | ||
25 | |||
26 | Now we know the actual cause of the problem. Thanks to AceLan Kao for | ||
27 | tracking it down. | ||
28 | |||
29 | According to him, an engineer at ASUS explained that some of their | ||
30 | BIOSes contain a bug that was added in an attempt to work around a | ||
31 | problem in early versions of Windows. When the computer goes into S3 | ||
32 | suspend, the BIOS tries to verify that the EHCI controllers were first | ||
33 | quiesced by the OS. Nothing's wrong with this, but the BIOS does it | ||
34 | by checking that the PCI COMMAND registers contain 0 without checking | ||
35 | the controllers' power state. If the register isn't 0, the BIOS | ||
36 | assumes the controller needs to be quiesced and tries to do so. This | ||
37 | involves making various MMIO accesses to the controller, which don't | ||
38 | work very well if the controller is already in D3. The end result is | ||
39 | a system hang or memory corruption. | ||
40 | |||
41 | Since the value in the PCI COMMAND register doesn't matter once the | ||
42 | controller has been suspended, and since the value will be restored | ||
43 | anyway when the controller is resumed, we can work around the BIOS bug | ||
44 | simply by setting the register to 0 during system suspend. This patch | ||
45 | (as1590) does so and also reverts the second commit mentioned above, | ||
46 | which is now unnecessary. | ||
47 | |||
48 | In theory we could do this for every PCI device. However to avoid | ||
49 | introducing new problems, the patch restricts itself to EHCI host | ||
50 | controllers. | ||
51 | |||
52 | Finally the affected systems can suspend with USB wakeup working | ||
53 | properly. | ||
54 | |||
55 | Reference: https://bugzilla.kernel.org/show_bug.cgi?id=37632 | ||
56 | Reference: https://bugzilla.kernel.org/show_bug.cgi?id=42728 | ||
57 | Based-on-patch-by: AceLan Kao <acelan.kao@canonical.com> | ||
58 | Signed-off-by: Alan Stern <stern@rowland.harvard.edu> | ||
59 | Tested-by: Dâniel Fraga <fragabr@gmail.com> | ||
60 | Tested-by: Javier Marcet <jmarcet@gmail.com> | ||
61 | Tested-by: Andrey Rahmatullin <wrar@wrar.name> | ||
62 | Tested-by: Oleksij Rempel <bug-track@fisher-privat.net> | ||
63 | Tested-by: Pavel Pisa <pisa@cmp.felk.cvut.cz> | ||
64 | Acked-by: Bjorn Helgaas <bhelgaas@google.com> | ||
65 | Acked-by: Rafael J. Wysocki <rjw@sisk.pl> | ||
66 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | ||
67 | Signed-off-by: Ben Hutchings <ben@decadent.org.uk> | ||
68 | --- | ||
69 | drivers/pci/pci-driver.c | 12 ++++++++++++ | ||
70 | drivers/pci/pci.c | 5 ----- | ||
71 | drivers/pci/quirks.c | 26 -------------------------- | ||
72 | include/linux/pci.h | 2 -- | ||
73 | 4 files changed, 12 insertions(+), 33 deletions(-) | ||
74 | |||
75 | diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c | ||
76 | index 12d1e81..d024f83 100644 | ||
77 | --- a/drivers/pci/pci-driver.c | ||
78 | +++ b/drivers/pci/pci-driver.c | ||
79 | @@ -742,6 +742,18 @@ static int pci_pm_suspend_noirq(struct device *dev) | ||
80 | |||
81 | pci_pm_set_unknown_state(pci_dev); | ||
82 | |||
83 | + /* | ||
84 | + * Some BIOSes from ASUS have a bug: If a USB EHCI host controller's | ||
85 | + * PCI COMMAND register isn't 0, the BIOS assumes that the controller | ||
86 | + * hasn't been quiesced and tries to turn it off. If the controller | ||
87 | + * is already in D3, this can hang or cause memory corruption. | ||
88 | + * | ||
89 | + * Since the value of the COMMAND register doesn't matter once the | ||
90 | + * device has been suspended, we can safely set it to 0 here. | ||
91 | + */ | ||
92 | + if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI) | ||
93 | + pci_write_config_word(pci_dev, PCI_COMMAND, 0); | ||
94 | + | ||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c | ||
99 | index e5b75eb..6d4a531 100644 | ||
100 | --- a/drivers/pci/pci.c | ||
101 | +++ b/drivers/pci/pci.c | ||
102 | @@ -1689,11 +1689,6 @@ int pci_prepare_to_sleep(struct pci_dev *dev) | ||
103 | if (target_state == PCI_POWER_ERROR) | ||
104 | return -EIO; | ||
105 | |||
106 | - /* Some devices mustn't be in D3 during system sleep */ | ||
107 | - if (target_state == PCI_D3hot && | ||
108 | - (dev->dev_flags & PCI_DEV_FLAGS_NO_D3_DURING_SLEEP)) | ||
109 | - return 0; | ||
110 | - | ||
111 | pci_enable_wake(dev, target_state, device_may_wakeup(&dev->dev)); | ||
112 | |||
113 | error = pci_set_power_state(dev, target_state); | ||
114 | diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c | ||
115 | index 3c56fec..78fda9c 100644 | ||
116 | --- a/drivers/pci/quirks.c | ||
117 | +++ b/drivers/pci/quirks.c | ||
118 | @@ -2940,32 +2940,6 @@ static void __devinit disable_igfx_irq(struct pci_dev *dev) | ||
119 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0102, disable_igfx_irq); | ||
120 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq); | ||
121 | |||
122 | -/* | ||
123 | - * The Intel 6 Series/C200 Series chipset's EHCI controllers on many | ||
124 | - * ASUS motherboards will cause memory corruption or a system crash | ||
125 | - * if they are in D3 while the system is put into S3 sleep. | ||
126 | - */ | ||
127 | -static void __devinit asus_ehci_no_d3(struct pci_dev *dev) | ||
128 | -{ | ||
129 | - const char *sys_info; | ||
130 | - static const char good_Asus_board[] = "P8Z68-V"; | ||
131 | - | ||
132 | - if (dev->dev_flags & PCI_DEV_FLAGS_NO_D3_DURING_SLEEP) | ||
133 | - return; | ||
134 | - if (dev->subsystem_vendor != PCI_VENDOR_ID_ASUSTEK) | ||
135 | - return; | ||
136 | - sys_info = dmi_get_system_info(DMI_BOARD_NAME); | ||
137 | - if (sys_info && memcmp(sys_info, good_Asus_board, | ||
138 | - sizeof(good_Asus_board) - 1) == 0) | ||
139 | - return; | ||
140 | - | ||
141 | - dev_info(&dev->dev, "broken D3 during system sleep on ASUS\n"); | ||
142 | - dev->dev_flags |= PCI_DEV_FLAGS_NO_D3_DURING_SLEEP; | ||
143 | - device_set_wakeup_capable(&dev->dev, false); | ||
144 | -} | ||
145 | -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1c26, asus_ehci_no_d3); | ||
146 | -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1c2d, asus_ehci_no_d3); | ||
147 | - | ||
148 | static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, | ||
149 | struct pci_fixup *end) | ||
150 | { | ||
151 | diff --git a/include/linux/pci.h b/include/linux/pci.h | ||
152 | index c0cfa0d..7cda65b 100644 | ||
153 | --- a/include/linux/pci.h | ||
154 | +++ b/include/linux/pci.h | ||
155 | @@ -176,8 +176,6 @@ enum pci_dev_flags { | ||
156 | PCI_DEV_FLAGS_NO_D3 = (__force pci_dev_flags_t) 2, | ||
157 | /* Provide indication device is assigned by a Virtual Machine Manager */ | ||
158 | PCI_DEV_FLAGS_ASSIGNED = (__force pci_dev_flags_t) 4, | ||
159 | - /* Device causes system crash if in D3 during S3 sleep */ | ||
160 | - PCI_DEV_FLAGS_NO_D3_DURING_SLEEP = (__force pci_dev_flags_t) 8, | ||
161 | }; | ||
162 | |||
163 | enum pci_irq_reroute_variant { | ||
164 | -- | ||
165 | 1.7.7.6 | ||
166 | |||