aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pcie
diff options
context:
space:
mode:
authorHuang Ying <ying.huang@intel.com>2012-08-14 21:43:03 -0400
committerBjorn Helgaas <bhelgaas@google.com>2012-08-21 19:34:24 -0400
commit3d8387efe1ad9eb5bfe8a2e58cdbd1b88b247eef (patch)
treea589e0ab38c2ecda5aff3792b677bd2b0c06b718 /drivers/pci/pcie
parentea8c88f13d9fb1d6b39a05bfa07ae076ca1c6803 (diff)
PCI/PM: Fix config reg access for D3cold and bridge suspending
This patch fixes the following bug: http://marc.info/?l=linux-pci&m=134338059022620&w=2 Where lspci does not work properly if a device and the corresponding parent bridge (such as PCIe port) is suspended. This is because the device configuration space registers will be not accessible if the corresponding parent bridge is suspended or the device is put into D3cold state. To solve the issue, the bridge/PCIe port connected to the device is put into active state before read/write configuration space registers. If the device is in D3cold state, it will be put into active state too. To avoid resume/suspend PCIe port for each configuration register read/write, a small delay is added before the PCIe port to go suspended. Reported-by: Bjorn Mork <bjorn@mork.no> Signed-off-by: Huang Ying <ying.huang@intel.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'drivers/pci/pcie')
-rw-r--r--drivers/pci/pcie/portdrv_pci.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index 62f5a76c8f8..e76b44777db 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -140,9 +140,17 @@ static int pcie_port_runtime_resume(struct device *dev)
140{ 140{
141 return 0; 141 return 0;
142} 142}
143
144static int pcie_port_runtime_idle(struct device *dev)
145{
146 /* Delay for a short while to prevent too frequent suspend/resume */
147 pm_schedule_suspend(dev, 10);
148 return -EBUSY;
149}
143#else 150#else
144#define pcie_port_runtime_suspend NULL 151#define pcie_port_runtime_suspend NULL
145#define pcie_port_runtime_resume NULL 152#define pcie_port_runtime_resume NULL
153#define pcie_port_runtime_idle NULL
146#endif 154#endif
147 155
148static const struct dev_pm_ops pcie_portdrv_pm_ops = { 156static const struct dev_pm_ops pcie_portdrv_pm_ops = {
@@ -155,6 +163,7 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = {
155 .resume_noirq = pcie_port_resume_noirq, 163 .resume_noirq = pcie_port_resume_noirq,
156 .runtime_suspend = pcie_port_runtime_suspend, 164 .runtime_suspend = pcie_port_runtime_suspend,
157 .runtime_resume = pcie_port_runtime_resume, 165 .runtime_resume = pcie_port_runtime_resume,
166 .runtime_idle = pcie_port_runtime_idle,
158}; 167};
159 168
160#define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops) 169#define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops)