aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorZhao Yakui <yakui.zhao@intel.com>2008-05-12 23:15:05 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2008-06-10 13:59:47 -0400
commit49db139955d3392c6c4facf987905d0a9afed581 (patch)
treea6add566bb0fefbddd09d53e26b680be3ccd3a9b /drivers
parente1a2a51e684bfe9d6165992d4a065439617a3107 (diff)
PCI: Disable PME during PCI scan
If a device supports #PME and can generate PME events from D0, we may see superfluous events before a driver is loaded (drivers should only enable PME as needed), preventing suspend from working if the corresponding GPE was enabled. Likewise, if the ACPI device has the _PRW object, the _PSW/_DSW object will be called in order to disable the wakeup functionality. But when it is allowed to wake up the sleeping state, OSPM will enable it again. So we should disable PME in the course of scanning PCI devices and enable it again only when PME events are actually required to be generated from the requested PCI state (for example, D3_hot or D3_cold). It is also safe to disable PME again when the PME is disabled for the PCI devices. Signed-off-by: Zhao Yakui <yakui.zhao@intel.com> Signed-off-by: Li Shaohua <shaohua.li@intel.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pci/probe.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 3706ce7972dd..aebab71abebf 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -857,6 +857,49 @@ int pci_cfg_space_size_ext(struct pci_dev *dev)
857 return PCI_CFG_SPACE_SIZE; 857 return PCI_CFG_SPACE_SIZE;
858} 858}
859 859
860/**
861 * pci_disable_pme - Disable the PME function of PCI device
862 * @dev: PCI device affected
863 * -EINVAL is returned if PCI device doesn't support PME.
864 * Zero is returned if the PME is supported and can be disabled.
865 */
866static int pci_disable_pme(struct pci_dev *dev)
867{
868 int pm;
869 u16 value;
870
871 /* find PCI PM capability in list */
872 pm = pci_find_capability(dev, PCI_CAP_ID_PM);
873
874 /* If device doesn't support PM Capabilities, it means that PME is
875 * not supported.
876 */
877 if (!pm)
878 return -EINVAL;
879 /* Check device's ability to generate PME# */
880 pci_read_config_word(dev, pm + PCI_PM_PMC, &value);
881
882 value &= PCI_PM_CAP_PME_MASK;
883 /* Check if it can generate PME# */
884 if (!value) {
885 /*
886 * If it is zero, it means that PME is still unsupported
887 * although there exists the PM capability.
888 */
889 return -EINVAL;
890 }
891
892 pci_read_config_word(dev, pm + PCI_PM_CTRL, &value);
893
894 /* Clear PME_Status by writing 1 to it */
895 value |= PCI_PM_CTRL_PME_STATUS ;
896 /* Disable PME enable bit */
897 value &= ~PCI_PM_CTRL_PME_ENABLE;
898 pci_write_config_word(dev, pm + PCI_PM_CTRL, value);
899
900 return 0;
901}
902
860int pci_cfg_space_size(struct pci_dev *dev) 903int pci_cfg_space_size(struct pci_dev *dev)
861{ 904{
862 int pos; 905 int pos;
@@ -964,6 +1007,7 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
964 } 1007 }
965 1008
966 pci_vpd_pci22_init(dev); 1009 pci_vpd_pci22_init(dev);
1010 pci_disable_pme(dev);
967 1011
968 return dev; 1012 return dev;
969} 1013}