提交 49db1399 编写于 作者: Z Zhao Yakui 提交者: Jesse Barnes

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: NZhao Yakui <yakui.zhao@intel.com>
Signed-off-by: NLi Shaohua <shaohua.li@intel.com>
Signed-off-by: NJesse Barnes <jbarnes@virtuousgeek.org>
上级 e1a2a51e
......@@ -857,6 +857,49 @@ int pci_cfg_space_size_ext(struct pci_dev *dev)
return PCI_CFG_SPACE_SIZE;
}
/**
* pci_disable_pme - Disable the PME function of PCI device
* @dev: PCI device affected
* -EINVAL is returned if PCI device doesn't support PME.
* Zero is returned if the PME is supported and can be disabled.
*/
static int pci_disable_pme(struct pci_dev *dev)
{
int pm;
u16 value;
/* find PCI PM capability in list */
pm = pci_find_capability(dev, PCI_CAP_ID_PM);
/* If device doesn't support PM Capabilities, it means that PME is
* not supported.
*/
if (!pm)
return -EINVAL;
/* Check device's ability to generate PME# */
pci_read_config_word(dev, pm + PCI_PM_PMC, &value);
value &= PCI_PM_CAP_PME_MASK;
/* Check if it can generate PME# */
if (!value) {
/*
* If it is zero, it means that PME is still unsupported
* although there exists the PM capability.
*/
return -EINVAL;
}
pci_read_config_word(dev, pm + PCI_PM_CTRL, &value);
/* Clear PME_Status by writing 1 to it */
value |= PCI_PM_CTRL_PME_STATUS ;
/* Disable PME enable bit */
value &= ~PCI_PM_CTRL_PME_ENABLE;
pci_write_config_word(dev, pm + PCI_PM_CTRL, value);
return 0;
}
int pci_cfg_space_size(struct pci_dev *dev)
{
int pos;
......@@ -964,6 +1007,7 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
}
pci_vpd_pci22_init(dev);
pci_disable_pme(dev);
return dev;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册