diff options
author | Vidya Sagar <sagar.tv@gmail.com> | 2014-07-16 06:03:42 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2014-07-16 16:27:31 -0400 |
commit | 1f6ae47ecff7f23da73417e068018b311f3b5583 (patch) | |
tree | 2356701528c4c2ea96768f504f63d20e91035988 /drivers/pci | |
parent | cbace46a9710a480cae51e4611697df5de41713e (diff) |
PCI: Configure ASPM when enabling device
We can't do ASPM configuration at enumeration-time because enabling it
makes some defective hardware unresponsive, even if ASPM is disabled later
(see 41cd766b0659 ("PCI: Don't enable aspm before drivers have had a chance
to veto it"). Therefore, we have to do it after a driver claims the
device.
We previously configured ASPM in pci_set_power_state(), but that's not a
very good place because it's not really related to setting the PCI device
power state, and doing it there means:
- We incorrectly skipped ASPM config when setting a device that's
already in D0 to D0.
- We unnecessarily configured ASPM when setting a device to a low-power
state (the ASPM feature only applies when the device is in D0).
- We unnecessarily configured ASPM when called from a .resume() method
(ASPM configuration needs to be restored during resume, but
pci_restore_pcie_state() should already do this).
Move ASPM configuration from pci_set_power_state() to
do_pci_enable_device() so we do it when a driver enables a device.
[bhelgaas: changelog]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=79621
Fixes: db288c9c5f9d ("PCI / PM: restore the original behavior of pci_set_power_state()")
Suggested-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Vidya Sagar <sagar.tv@gmail.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
CC: stable@vger.kernel.org # v3.6+
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/pci.c | 12 |
1 files changed, 6 insertions, 6 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 63a54a340863..75fabd1f72bc 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -839,12 +839,6 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
839 | 839 | ||
840 | if (!__pci_complete_power_transition(dev, state)) | 840 | if (!__pci_complete_power_transition(dev, state)) |
841 | error = 0; | 841 | error = 0; |
842 | /* | ||
843 | * When aspm_policy is "powersave" this call ensures | ||
844 | * that ASPM is configured. | ||
845 | */ | ||
846 | if (!error && dev->bus->self) | ||
847 | pcie_aspm_powersave_config_link(dev->bus->self); | ||
848 | 842 | ||
849 | return error; | 843 | return error; |
850 | } | 844 | } |
@@ -1195,12 +1189,18 @@ int __weak pcibios_enable_device(struct pci_dev *dev, int bars) | |||
1195 | static int do_pci_enable_device(struct pci_dev *dev, int bars) | 1189 | static int do_pci_enable_device(struct pci_dev *dev, int bars) |
1196 | { | 1190 | { |
1197 | int err; | 1191 | int err; |
1192 | struct pci_dev *bridge; | ||
1198 | u16 cmd; | 1193 | u16 cmd; |
1199 | u8 pin; | 1194 | u8 pin; |
1200 | 1195 | ||
1201 | err = pci_set_power_state(dev, PCI_D0); | 1196 | err = pci_set_power_state(dev, PCI_D0); |
1202 | if (err < 0 && err != -EIO) | 1197 | if (err < 0 && err != -EIO) |
1203 | return err; | 1198 | return err; |
1199 | |||
1200 | bridge = pci_upstream_bridge(dev); | ||
1201 | if (bridge) | ||
1202 | pcie_aspm_powersave_config_link(bridge); | ||
1203 | |||
1204 | err = pcibios_enable_device(dev, bars); | 1204 | err = pcibios_enable_device(dev, bars); |
1205 | if (err < 0) | 1205 | if (err < 0) |
1206 | return err; | 1206 | return err; |