aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pcie
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2008-12-27 10:28:58 -0500
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-01-07 14:13:08 -0500
commita79d682f789730dfabaebbb507c87a90c0671a62 (patch)
treed58b75d734e88086770ceaa726ea614507b53b59 /drivers/pci/pcie
parentf06fc0b6f8a6846e0ad48aee7b0f282b4fb5dcdc (diff)
PCI PM: Split PCI Express port suspend-resume
Suspend-resume of PCI Express ports has recently been moved into _suspend_late() and _resume_early() callbacks, but some functions executed from there should not be called with interrupts disabled, eg. pci_enable_device(). For this reason, split the suspend-resume of PCI Express ports into parts to be executed with interrupts disabled and with interrupts enabled. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/pcie')
-rw-r--r--drivers/pci/pcie/portdrv_pci.c23
1 files changed, 17 insertions, 6 deletions
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index 0549fe2bdac9..99a914a027f8 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -41,7 +41,6 @@ static int pcie_portdrv_restore_config(struct pci_dev *dev)
41{ 41{
42 int retval; 42 int retval;
43 43
44 pci_restore_state(dev);
45 retval = pci_enable_device(dev); 44 retval = pci_enable_device(dev);
46 if (retval) 45 if (retval)
47 return retval; 46 return retval;
@@ -50,23 +49,32 @@ static int pcie_portdrv_restore_config(struct pci_dev *dev)
50} 49}
51 50
52#ifdef CONFIG_PM 51#ifdef CONFIG_PM
53static int pcie_portdrv_suspend_late(struct pci_dev *dev, pm_message_t state) 52static int pcie_portdrv_suspend(struct pci_dev *dev, pm_message_t state)
54{ 53{
55 int ret = pcie_port_device_suspend(dev, state); 54 return pcie_port_device_suspend(dev, state);
56 55
57 if (!ret) 56}
58 ret = pcie_portdrv_save_config(dev); 57
59 return ret; 58static int pcie_portdrv_suspend_late(struct pci_dev *dev, pm_message_t state)
59{
60 return pci_save_state(dev);
60} 61}
61 62
62static int pcie_portdrv_resume_early(struct pci_dev *dev) 63static int pcie_portdrv_resume_early(struct pci_dev *dev)
63{ 64{
65 return pci_restore_state(dev);
66}
67
68static int pcie_portdrv_resume(struct pci_dev *dev)
69{
64 pcie_portdrv_restore_config(dev); 70 pcie_portdrv_restore_config(dev);
65 return pcie_port_device_resume(dev); 71 return pcie_port_device_resume(dev);
66} 72}
67#else 73#else
74#define pcie_portdrv_suspend NULL
68#define pcie_portdrv_suspend_late NULL 75#define pcie_portdrv_suspend_late NULL
69#define pcie_portdrv_resume_early NULL 76#define pcie_portdrv_resume_early NULL
77#define pcie_portdrv_resume NULL
70#endif 78#endif
71 79
72/* 80/*
@@ -221,6 +229,7 @@ static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev)
221 229
222 /* If fatal, restore cfg space for possible link reset at upstream */ 230 /* If fatal, restore cfg space for possible link reset at upstream */
223 if (dev->error_state == pci_channel_io_frozen) { 231 if (dev->error_state == pci_channel_io_frozen) {
232 pci_restore_state(dev);
224 pcie_portdrv_restore_config(dev); 233 pcie_portdrv_restore_config(dev);
225 pci_enable_pcie_error_reporting(dev); 234 pci_enable_pcie_error_reporting(dev);
226 } 235 }
@@ -282,8 +291,10 @@ static struct pci_driver pcie_portdriver = {
282 .probe = pcie_portdrv_probe, 291 .probe = pcie_portdrv_probe,
283 .remove = pcie_portdrv_remove, 292 .remove = pcie_portdrv_remove,
284 293
294 .suspend = pcie_portdrv_suspend,
285 .suspend_late = pcie_portdrv_suspend_late, 295 .suspend_late = pcie_portdrv_suspend_late,
286 .resume_early = pcie_portdrv_resume_early, 296 .resume_early = pcie_portdrv_resume_early,
297 .resume = pcie_portdrv_resume,
287 298
288 .err_handler = &pcie_portdrv_err_handler, 299 .err_handler = &pcie_portdrv_err_handler,
289}; 300};