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>
This commit is contained in:
parent
f06fc0b6f8
commit
a79d682f78
|
@ -41,7 +41,6 @@ static int pcie_portdrv_restore_config(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
pci_restore_state(dev);
|
|
||||||
retval = pci_enable_device(dev);
|
retval = pci_enable_device(dev);
|
||||||
if (retval)
|
if (retval)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -50,23 +49,32 @@ static int pcie_portdrv_restore_config(struct pci_dev *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
|
static int pcie_portdrv_suspend(struct pci_dev *dev, pm_message_t state)
|
||||||
|
{
|
||||||
|
return pcie_port_device_suspend(dev, state);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static int pcie_portdrv_suspend_late(struct pci_dev *dev, pm_message_t state)
|
static int pcie_portdrv_suspend_late(struct pci_dev *dev, pm_message_t state)
|
||||||
{
|
{
|
||||||
int ret = pcie_port_device_suspend(dev, state);
|
return pci_save_state(dev);
|
||||||
|
|
||||||
if (!ret)
|
|
||||||
ret = pcie_portdrv_save_config(dev);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pcie_portdrv_resume_early(struct pci_dev *dev)
|
static int pcie_portdrv_resume_early(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
return pci_restore_state(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pcie_portdrv_resume(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
pcie_portdrv_restore_config(dev);
|
pcie_portdrv_restore_config(dev);
|
||||||
return pcie_port_device_resume(dev);
|
return pcie_port_device_resume(dev);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
#define pcie_portdrv_suspend NULL
|
||||||
#define pcie_portdrv_suspend_late NULL
|
#define pcie_portdrv_suspend_late NULL
|
||||||
#define pcie_portdrv_resume_early NULL
|
#define pcie_portdrv_resume_early NULL
|
||||||
|
#define pcie_portdrv_resume NULL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -221,6 +229,7 @@ static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev)
|
||||||
|
|
||||||
/* If fatal, restore cfg space for possible link reset at upstream */
|
/* If fatal, restore cfg space for possible link reset at upstream */
|
||||||
if (dev->error_state == pci_channel_io_frozen) {
|
if (dev->error_state == pci_channel_io_frozen) {
|
||||||
|
pci_restore_state(dev);
|
||||||
pcie_portdrv_restore_config(dev);
|
pcie_portdrv_restore_config(dev);
|
||||||
pci_enable_pcie_error_reporting(dev);
|
pci_enable_pcie_error_reporting(dev);
|
||||||
}
|
}
|
||||||
|
@ -282,8 +291,10 @@ static struct pci_driver pcie_portdriver = {
|
||||||
.probe = pcie_portdrv_probe,
|
.probe = pcie_portdrv_probe,
|
||||||
.remove = pcie_portdrv_remove,
|
.remove = pcie_portdrv_remove,
|
||||||
|
|
||||||
|
.suspend = pcie_portdrv_suspend,
|
||||||
.suspend_late = pcie_portdrv_suspend_late,
|
.suspend_late = pcie_portdrv_suspend_late,
|
||||||
.resume_early = pcie_portdrv_resume_early,
|
.resume_early = pcie_portdrv_resume_early,
|
||||||
|
.resume = pcie_portdrv_resume,
|
||||||
|
|
||||||
.err_handler = &pcie_portdrv_err_handler,
|
.err_handler = &pcie_portdrv_err_handler,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue