@@ -763,6 +763,20 @@ static int pci_pm_resume(struct device *
#ifdef CONFIG_HIBERNATE_CALLBACKS
+
+/*
+ * provide arch specific hooks when a pci device is doing
+ * a hibernate transition
+ */
+int __weak pcibios_pm_freeze(struct pci_dev *pdev) { return 0; }
+int __weak pcibios_pm_freeze_noirq(struct pci_dev *pdev) { return 0; }
+int __weak pcibios_pm_thaw(struct pci_dev *pdev) { return 0; }
+int __weak pcibios_pm_thaw_noirq(struct pci_dev *pdev) { return 0; }
+int __weak pcibios_pm_poweroff(struct pci_dev *pdev) { return 0; }
+int __weak pcibios_pm_poweroff_noirq(struct pci_dev *pdev) { return 0; }
+int __weak pcibios_pm_restore(struct pci_dev *pdev) { return 0; }
+int __weak pcibios_pm_restore_noirq(struct pci_dev *pdev) { return 0; }
+
static int pci_pm_freeze(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
@@ -786,7 +800,7 @@ static int pci_pm_freeze(struct device *
return error;
}
- return 0;
+ return pcibios_pm_freeze(pci_dev);
}
static int pci_pm_freeze_noirq(struct device *dev)
@@ -811,14 +825,18 @@ static int pci_pm_freeze_noirq(struct de
pci_pm_set_unknown_state(pci_dev);
- return 0;
+ return pcibios_pm_freeze_noirq(pci_dev);
}
static int pci_pm_thaw_noirq(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
struct device_driver *drv = dev->driver;
- int error = 0;
+ int error;
+
+ error = pcibios_pm_thaw_noirq(pci_dev);
+ if (error)
+ return error;
if (pci_has_legacy_pm_support(pci_dev))
return pci_legacy_resume_early(dev);
@@ -835,7 +853,11 @@ static int pci_pm_thaw(struct device *de
{
struct pci_dev *pci_dev = to_pci_dev(dev);
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
- int error = 0;
+ int error;
+
+ error = pcibios_pm_thaw(pci_dev);
+ if (error)
+ return error;
if (pci_has_legacy_pm_support(pci_dev))
return pci_legacy_resume(dev);
@@ -878,7 +900,7 @@ static int pci_pm_poweroff(struct device
Fixup:
pci_fixup_device(pci_fixup_suspend, pci_dev);
- return 0;
+ return pcibios_pm_poweroff(pci_dev);
}
static int pci_pm_poweroff_noirq(struct device *dev)
@@ -911,14 +933,18 @@ static int pci_pm_poweroff_noirq(struct
if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI)
pci_write_config_word(pci_dev, PCI_COMMAND, 0);
- return 0;
+ return pcibios_pm_poweroff_noirq(pci_dev);
}
static int pci_pm_restore_noirq(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
struct device_driver *drv = dev->driver;
- int error = 0;
+ int error;
+
+ error = pcibios_pm_restore_noirq(pci_dev);
+ if (error)
+ return error;
pci_pm_default_resume_early(pci_dev);
@@ -935,7 +961,11 @@ static int pci_pm_restore(struct device
{
struct pci_dev *pci_dev = to_pci_dev(dev);
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
- int error = 0;
+ int error;
+
+ error = pcibios_pm_restore(pci_dev);
+ if (error)
+ return error;
/*
* This is necessary for the hibernation error path in which restore is
@@ -1648,6 +1648,17 @@ int pcibios_set_pcie_reset_state(struct
int pcibios_add_device(struct pci_dev *dev);
void pcibios_release_device(struct pci_dev *dev);
+#ifdef CONFIG_HIBERNATE_CALLBACKS
+int pcibios_pm_freeze(struct pci_dev *pdev);
+int pcibios_pm_freeze_noirq(struct pci_dev *pdev);
+int pcibios_pm_thaw(struct pci_dev *pdev);
+int pcibios_pm_thaw_noirq(struct pci_dev *pdev);
+int pcibios_pm_poweroff(struct pci_dev *pdev);
+int pcibios_pm_poweroff_noirq(struct pci_dev *pdev);
+int pcibios_pm_restore(struct pci_dev *pdev);
+int pcibios_pm_restore_noirq(struct pci_dev *pdev);
+#endif
+
#ifdef CONFIG_PCI_MMCONFIG
void __init pci_mmcfg_early_init(void);
void __init pci_mmcfg_late_init(void);