diff options
-rw-r--r-- | drivers/pci/pci.c | 5 | ||||
-rw-r--r-- | drivers/pci/quirks.c | 26 | ||||
-rw-r--r-- | drivers/usb/core/hcd-pci.c | 9 | ||||
-rw-r--r-- | drivers/usb/host/ehci-pci.c | 8 | ||||
-rw-r--r-- | include/linux/pci.h | 2 | ||||
-rw-r--r-- | include/linux/usb/hcd.h | 2 |
6 files changed, 33 insertions, 19 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index d549bbc93cd..bf401aead87 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -1682,6 +1682,11 @@ int pci_prepare_to_sleep(struct pci_dev *dev) | |||
1682 | if (target_state == PCI_POWER_ERROR) | 1682 | if (target_state == PCI_POWER_ERROR) |
1683 | return -EIO; | 1683 | return -EIO; |
1684 | 1684 | ||
1685 | /* Some devices mustn't be in D3 during system sleep */ | ||
1686 | if (target_state == PCI_D3hot && | ||
1687 | (dev->dev_flags & PCI_DEV_FLAGS_NO_D3_DURING_SLEEP)) | ||
1688 | return 0; | ||
1689 | |||
1685 | pci_enable_wake(dev, target_state, device_may_wakeup(&dev->dev)); | 1690 | pci_enable_wake(dev, target_state, device_may_wakeup(&dev->dev)); |
1686 | 1691 | ||
1687 | error = pci_set_power_state(dev, target_state); | 1692 | error = pci_set_power_state(dev, target_state); |
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index a6b07ddad71..975af4353e7 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -2856,6 +2856,32 @@ static void __devinit disable_igfx_irq(struct pci_dev *dev) | |||
2856 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0102, disable_igfx_irq); | 2856 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0102, disable_igfx_irq); |
2857 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq); | 2857 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq); |
2858 | 2858 | ||
2859 | /* | ||
2860 | * The Intel 6 Series/C200 Series chipset's EHCI controllers on many | ||
2861 | * ASUS motherboards will cause memory corruption or a system crash | ||
2862 | * if they are in D3 while the system is put into S3 sleep. | ||
2863 | */ | ||
2864 | static void __devinit asus_ehci_no_d3(struct pci_dev *dev) | ||
2865 | { | ||
2866 | const char *sys_info; | ||
2867 | static const char good_Asus_board[] = "P8Z68-V"; | ||
2868 | |||
2869 | if (dev->dev_flags & PCI_DEV_FLAGS_NO_D3_DURING_SLEEP) | ||
2870 | return; | ||
2871 | if (dev->subsystem_vendor != PCI_VENDOR_ID_ASUSTEK) | ||
2872 | return; | ||
2873 | sys_info = dmi_get_system_info(DMI_BOARD_NAME); | ||
2874 | if (sys_info && memcmp(sys_info, good_Asus_board, | ||
2875 | sizeof(good_Asus_board) - 1) == 0) | ||
2876 | return; | ||
2877 | |||
2878 | dev_info(&dev->dev, "broken D3 during system sleep on ASUS\n"); | ||
2879 | dev->dev_flags |= PCI_DEV_FLAGS_NO_D3_DURING_SLEEP; | ||
2880 | device_set_wakeup_capable(&dev->dev, false); | ||
2881 | } | ||
2882 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1c26, asus_ehci_no_d3); | ||
2883 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1c2d, asus_ehci_no_d3); | ||
2884 | |||
2859 | static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, | 2885 | static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, |
2860 | struct pci_fixup *end) | 2886 | struct pci_fixup *end) |
2861 | { | 2887 | { |
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index aa7bbbcf9d8..6c1642b382f 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c | |||
@@ -495,15 +495,6 @@ static int hcd_pci_suspend_noirq(struct device *dev) | |||
495 | 495 | ||
496 | pci_save_state(pci_dev); | 496 | pci_save_state(pci_dev); |
497 | 497 | ||
498 | /* | ||
499 | * Some systems crash if an EHCI controller is in D3 during | ||
500 | * a sleep transition. We have to leave such controllers in D0. | ||
501 | */ | ||
502 | if (hcd->broken_pci_sleep) { | ||
503 | dev_dbg(dev, "Staying in PCI D0\n"); | ||
504 | return retval; | ||
505 | } | ||
506 | |||
507 | /* If the root hub is dead rather than suspended, disallow remote | 498 | /* If the root hub is dead rather than suspended, disallow remote |
508 | * wakeup. usb_hc_died() should ensure that both hosts are marked as | 499 | * wakeup. usb_hc_died() should ensure that both hosts are marked as |
509 | * dying, so we only need to check the primary roothub. | 500 | * dying, so we only need to check the primary roothub. |
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index efb9efcffe4..f76831480c6 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c | |||
@@ -144,14 +144,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) | |||
144 | hcd->has_tt = 1; | 144 | hcd->has_tt = 1; |
145 | tdi_reset(ehci); | 145 | tdi_reset(ehci); |
146 | } | 146 | } |
147 | if (pdev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK) { | ||
148 | /* EHCI #1 or #2 on 6 Series/C200 Series chipset */ | ||
149 | if (pdev->device == 0x1c26 || pdev->device == 0x1c2d) { | ||
150 | ehci_info(ehci, "broken D3 during system sleep on ASUS\n"); | ||
151 | hcd->broken_pci_sleep = 1; | ||
152 | device_set_wakeup_capable(&pdev->dev, false); | ||
153 | } | ||
154 | } | ||
155 | break; | 147 | break; |
156 | case PCI_VENDOR_ID_TDI: | 148 | case PCI_VENDOR_ID_TDI: |
157 | if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { | 149 | if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { |
diff --git a/include/linux/pci.h b/include/linux/pci.h index c446b5ca2d3..ff5970b7a17 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -174,6 +174,8 @@ enum pci_dev_flags { | |||
174 | PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG = (__force pci_dev_flags_t) 1, | 174 | PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG = (__force pci_dev_flags_t) 1, |
175 | /* Device configuration is irrevocably lost if disabled into D3 */ | 175 | /* Device configuration is irrevocably lost if disabled into D3 */ |
176 | PCI_DEV_FLAGS_NO_D3 = (__force pci_dev_flags_t) 2, | 176 | PCI_DEV_FLAGS_NO_D3 = (__force pci_dev_flags_t) 2, |
177 | /* Device causes system crash if in D3 during S3 sleep */ | ||
178 | PCI_DEV_FLAGS_NO_D3_DURING_SLEEP = (__force pci_dev_flags_t) 8, | ||
177 | }; | 179 | }; |
178 | 180 | ||
179 | enum pci_irq_reroute_variant { | 181 | enum pci_irq_reroute_variant { |
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index 32ba8c55b3a..c0ecc5a2ef9 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h | |||
@@ -128,8 +128,6 @@ struct usb_hcd { | |||
128 | unsigned wireless:1; /* Wireless USB HCD */ | 128 | unsigned wireless:1; /* Wireless USB HCD */ |
129 | unsigned authorized_default:1; | 129 | unsigned authorized_default:1; |
130 | unsigned has_tt:1; /* Integrated TT in root hub */ | 130 | unsigned has_tt:1; /* Integrated TT in root hub */ |
131 | unsigned broken_pci_sleep:1; /* Don't put the | ||
132 | controller in PCI-D3 for system sleep */ | ||
133 | 131 | ||
134 | int irq; /* irq allocated */ | 132 | int irq; /* irq allocated */ |
135 | void __iomem *regs; /* device memory/io */ | 133 | void __iomem *regs; /* device memory/io */ |