diff options
Diffstat (limited to 'drivers/pci/pci-driver.c')
-rw-r--r-- | drivers/pci/pci-driver.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index e6515e21afa3..98f7b9b89507 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -763,6 +763,13 @@ static int pci_pm_resume(struct device *dev) | |||
763 | 763 | ||
764 | #ifdef CONFIG_HIBERNATE_CALLBACKS | 764 | #ifdef CONFIG_HIBERNATE_CALLBACKS |
765 | 765 | ||
766 | |||
767 | /* | ||
768 | * pcibios_pm_ops - provide arch-specific hooks when a PCI device is doing | ||
769 | * a hibernate transition | ||
770 | */ | ||
771 | struct dev_pm_ops __weak pcibios_pm_ops; | ||
772 | |||
766 | static int pci_pm_freeze(struct device *dev) | 773 | static int pci_pm_freeze(struct device *dev) |
767 | { | 774 | { |
768 | struct pci_dev *pci_dev = to_pci_dev(dev); | 775 | struct pci_dev *pci_dev = to_pci_dev(dev); |
@@ -786,6 +793,9 @@ static int pci_pm_freeze(struct device *dev) | |||
786 | return error; | 793 | return error; |
787 | } | 794 | } |
788 | 795 | ||
796 | if (pcibios_pm_ops.freeze) | ||
797 | return pcibios_pm_ops.freeze(dev); | ||
798 | |||
789 | return 0; | 799 | return 0; |
790 | } | 800 | } |
791 | 801 | ||
@@ -811,6 +821,9 @@ static int pci_pm_freeze_noirq(struct device *dev) | |||
811 | 821 | ||
812 | pci_pm_set_unknown_state(pci_dev); | 822 | pci_pm_set_unknown_state(pci_dev); |
813 | 823 | ||
824 | if (pcibios_pm_ops.freeze_noirq) | ||
825 | return pcibios_pm_ops.freeze_noirq(dev); | ||
826 | |||
814 | return 0; | 827 | return 0; |
815 | } | 828 | } |
816 | 829 | ||
@@ -820,6 +833,12 @@ static int pci_pm_thaw_noirq(struct device *dev) | |||
820 | struct device_driver *drv = dev->driver; | 833 | struct device_driver *drv = dev->driver; |
821 | int error = 0; | 834 | int error = 0; |
822 | 835 | ||
836 | if (pcibios_pm_ops.thaw_noirq) { | ||
837 | error = pcibios_pm_ops.thaw_noirq(dev); | ||
838 | if (error) | ||
839 | return error; | ||
840 | } | ||
841 | |||
823 | if (pci_has_legacy_pm_support(pci_dev)) | 842 | if (pci_has_legacy_pm_support(pci_dev)) |
824 | return pci_legacy_resume_early(dev); | 843 | return pci_legacy_resume_early(dev); |
825 | 844 | ||
@@ -837,6 +856,12 @@ static int pci_pm_thaw(struct device *dev) | |||
837 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 856 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
838 | int error = 0; | 857 | int error = 0; |
839 | 858 | ||
859 | if (pcibios_pm_ops.thaw) { | ||
860 | error = pcibios_pm_ops.thaw(dev); | ||
861 | if (error) | ||
862 | return error; | ||
863 | } | ||
864 | |||
840 | if (pci_has_legacy_pm_support(pci_dev)) | 865 | if (pci_has_legacy_pm_support(pci_dev)) |
841 | return pci_legacy_resume(dev); | 866 | return pci_legacy_resume(dev); |
842 | 867 | ||
@@ -878,6 +903,9 @@ static int pci_pm_poweroff(struct device *dev) | |||
878 | Fixup: | 903 | Fixup: |
879 | pci_fixup_device(pci_fixup_suspend, pci_dev); | 904 | pci_fixup_device(pci_fixup_suspend, pci_dev); |
880 | 905 | ||
906 | if (pcibios_pm_ops.poweroff) | ||
907 | return pcibios_pm_ops.poweroff(dev); | ||
908 | |||
881 | return 0; | 909 | return 0; |
882 | } | 910 | } |
883 | 911 | ||
@@ -911,6 +939,9 @@ static int pci_pm_poweroff_noirq(struct device *dev) | |||
911 | if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI) | 939 | if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI) |
912 | pci_write_config_word(pci_dev, PCI_COMMAND, 0); | 940 | pci_write_config_word(pci_dev, PCI_COMMAND, 0); |
913 | 941 | ||
942 | if (pcibios_pm_ops.poweroff_noirq) | ||
943 | return pcibios_pm_ops.poweroff_noirq(dev); | ||
944 | |||
914 | return 0; | 945 | return 0; |
915 | } | 946 | } |
916 | 947 | ||
@@ -920,6 +951,12 @@ static int pci_pm_restore_noirq(struct device *dev) | |||
920 | struct device_driver *drv = dev->driver; | 951 | struct device_driver *drv = dev->driver; |
921 | int error = 0; | 952 | int error = 0; |
922 | 953 | ||
954 | if (pcibios_pm_ops.restore_noirq) { | ||
955 | error = pcibios_pm_ops.restore_noirq(dev); | ||
956 | if (error) | ||
957 | return error; | ||
958 | } | ||
959 | |||
923 | pci_pm_default_resume_early(pci_dev); | 960 | pci_pm_default_resume_early(pci_dev); |
924 | 961 | ||
925 | if (pci_has_legacy_pm_support(pci_dev)) | 962 | if (pci_has_legacy_pm_support(pci_dev)) |
@@ -937,6 +974,12 @@ static int pci_pm_restore(struct device *dev) | |||
937 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 974 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
938 | int error = 0; | 975 | int error = 0; |
939 | 976 | ||
977 | if (pcibios_pm_ops.restore) { | ||
978 | error = pcibios_pm_ops.restore(dev); | ||
979 | if (error) | ||
980 | return error; | ||
981 | } | ||
982 | |||
940 | /* | 983 | /* |
941 | * This is necessary for the hibernation error path in which restore is | 984 | * This is necessary for the hibernation error path in which restore is |
942 | * called without restoring the standard config registers of the device. | 985 | * called without restoring the standard config registers of the device. |