diff options
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r-- | drivers/pci/pci.c | 45 |
1 files changed, 35 insertions, 10 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index d00f0e0d8453..c9884bba22de 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -572,6 +572,10 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
572 | if (!ret) | 572 | if (!ret) |
573 | pci_update_current_state(dev); | 573 | pci_update_current_state(dev); |
574 | } | 574 | } |
575 | /* This device is quirked not to be put into D3, so | ||
576 | don't put it in D3 */ | ||
577 | if (state == PCI_D3hot && (dev->dev_flags & PCI_DEV_FLAGS_NO_D3)) | ||
578 | return 0; | ||
575 | 579 | ||
576 | error = pci_raw_set_power_state(dev, state); | 580 | error = pci_raw_set_power_state(dev, state); |
577 | 581 | ||
@@ -1040,7 +1044,7 @@ int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state) | |||
1040 | * @dev: PCI device to handle. | 1044 | * @dev: PCI device to handle. |
1041 | * @state: PCI state from which device will issue PME#. | 1045 | * @state: PCI state from which device will issue PME#. |
1042 | */ | 1046 | */ |
1043 | static bool pci_pme_capable(struct pci_dev *dev, pci_power_t state) | 1047 | bool pci_pme_capable(struct pci_dev *dev, pci_power_t state) |
1044 | { | 1048 | { |
1045 | if (!dev->pm_cap) | 1049 | if (!dev->pm_cap) |
1046 | return false; | 1050 | return false; |
@@ -1056,7 +1060,7 @@ static bool pci_pme_capable(struct pci_dev *dev, pci_power_t state) | |||
1056 | * The caller must verify that the device is capable of generating PME# before | 1060 | * The caller must verify that the device is capable of generating PME# before |
1057 | * calling this function with @enable equal to 'true'. | 1061 | * calling this function with @enable equal to 'true'. |
1058 | */ | 1062 | */ |
1059 | static void pci_pme_active(struct pci_dev *dev, bool enable) | 1063 | void pci_pme_active(struct pci_dev *dev, bool enable) |
1060 | { | 1064 | { |
1061 | u16 pmcsr; | 1065 | u16 pmcsr; |
1062 | 1066 | ||
@@ -1123,17 +1127,16 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable) | |||
1123 | } | 1127 | } |
1124 | 1128 | ||
1125 | /** | 1129 | /** |
1126 | * pci_prepare_to_sleep - prepare PCI device for system-wide transition into a sleep state | 1130 | * pci_target_state - find an appropriate low power state for a given PCI dev |
1127 | * @dev: Device to handle. | 1131 | * @dev: PCI device |
1128 | * | 1132 | * |
1129 | * Choose the power state appropriate for the device depending on whether | 1133 | * Use underlying platform code to find a supported low power state for @dev. |
1130 | * it can wake up the system and/or is power manageable by the platform | 1134 | * If the platform can't manage @dev, return the deepest state from which it |
1131 | * (PCI_D3hot is the default) and put the device into that state. | 1135 | * can generate wake events, based on any available PME info. |
1132 | */ | 1136 | */ |
1133 | int pci_prepare_to_sleep(struct pci_dev *dev) | 1137 | pci_power_t pci_target_state(struct pci_dev *dev) |
1134 | { | 1138 | { |
1135 | pci_power_t target_state = PCI_D3hot; | 1139 | pci_power_t target_state = PCI_D3hot; |
1136 | int error; | ||
1137 | 1140 | ||
1138 | if (platform_pci_power_manageable(dev)) { | 1141 | if (platform_pci_power_manageable(dev)) { |
1139 | /* | 1142 | /* |
@@ -1160,7 +1163,7 @@ int pci_prepare_to_sleep(struct pci_dev *dev) | |||
1160 | * to generate PME#. | 1163 | * to generate PME#. |
1161 | */ | 1164 | */ |
1162 | if (!dev->pm_cap) | 1165 | if (!dev->pm_cap) |
1163 | return -EIO; | 1166 | return PCI_POWER_ERROR; |
1164 | 1167 | ||
1165 | if (dev->pme_support) { | 1168 | if (dev->pme_support) { |
1166 | while (target_state | 1169 | while (target_state |
@@ -1169,6 +1172,25 @@ int pci_prepare_to_sleep(struct pci_dev *dev) | |||
1169 | } | 1172 | } |
1170 | } | 1173 | } |
1171 | 1174 | ||
1175 | return target_state; | ||
1176 | } | ||
1177 | |||
1178 | /** | ||
1179 | * pci_prepare_to_sleep - prepare PCI device for system-wide transition into a sleep state | ||
1180 | * @dev: Device to handle. | ||
1181 | * | ||
1182 | * Choose the power state appropriate for the device depending on whether | ||
1183 | * it can wake up the system and/or is power manageable by the platform | ||
1184 | * (PCI_D3hot is the default) and put the device into that state. | ||
1185 | */ | ||
1186 | int pci_prepare_to_sleep(struct pci_dev *dev) | ||
1187 | { | ||
1188 | pci_power_t target_state = pci_target_state(dev); | ||
1189 | int error; | ||
1190 | |||
1191 | if (target_state == PCI_POWER_ERROR) | ||
1192 | return -EIO; | ||
1193 | |||
1172 | pci_enable_wake(dev, target_state, true); | 1194 | pci_enable_wake(dev, target_state, true); |
1173 | 1195 | ||
1174 | error = pci_set_power_state(dev, target_state); | 1196 | error = pci_set_power_state(dev, target_state); |
@@ -1918,7 +1940,10 @@ EXPORT_SYMBOL(pci_select_bars); | |||
1918 | EXPORT_SYMBOL(pci_set_power_state); | 1940 | EXPORT_SYMBOL(pci_set_power_state); |
1919 | EXPORT_SYMBOL(pci_save_state); | 1941 | EXPORT_SYMBOL(pci_save_state); |
1920 | EXPORT_SYMBOL(pci_restore_state); | 1942 | EXPORT_SYMBOL(pci_restore_state); |
1943 | EXPORT_SYMBOL(pci_pme_capable); | ||
1944 | EXPORT_SYMBOL(pci_pme_active); | ||
1921 | EXPORT_SYMBOL(pci_enable_wake); | 1945 | EXPORT_SYMBOL(pci_enable_wake); |
1946 | EXPORT_SYMBOL(pci_target_state); | ||
1922 | EXPORT_SYMBOL(pci_prepare_to_sleep); | 1947 | EXPORT_SYMBOL(pci_prepare_to_sleep); |
1923 | EXPORT_SYMBOL(pci_back_from_sleep); | 1948 | EXPORT_SYMBOL(pci_back_from_sleep); |
1924 | EXPORT_SYMBOL_GPL(pci_set_pcie_reset_state); | 1949 | EXPORT_SYMBOL_GPL(pci_set_pcie_reset_state); |