Pull power management fixes from Rafael Wysocki: "These fix three issues in the system-wide suspend and hibernation area related to PCI device PM handling by suspend-to-idle, device wakeup optimizations and arbitrary differences between suspend and hiberantion. Specifics: - Modify the PCI bus type's PM code to avoid putting devices left by their drivers in D0 on purpose during suspend to idle into low-power states as doing that may confuse the system resume callbacks of the drivers in question (Rafael Wysocki). - Avoid checking ACPI wakeup configuration during system-wide suspend for suspended devices that do not use ACPI-based wakeup to allow them to stay in suspend more often (Rafael Wysocki). - The last phase of hibernation is analogous to system-wide suspend also because on platforms with ACPI it passes control to the platform firmware to complete the transision, so make it indicate that by calling pm_set_suspend_via_firmware() to allow the drivers that care about this to do the right thing (Rafael Wysocki)" * tag 'pm-5.2-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: PCI: PM: Avoid possible suspend-to-idle issue ACPI: PM: Call pm_set_suspend_via_firmware() during hibernation ACPI/PCI: PM: Add missing wakeup.flags.valid checks
Unified · Split
| @@ -944,8 +944,8 @@ static bool acpi_dev_needs_resume(struct device *dev, struct acpi_device *adev) · 943 unmodified lines | |||
| 944 | u32 sys_target = acpi_target_system_state(); | 944 | u32 sys_target = acpi_target_system_state(); |
| 945 | int ret, state; | 945 | int ret, state; |
| 946 | 946 | ||
| 947 | if (!pm_runtime_suspended(dev) || !adev || | 947 | if (!pm_runtime_suspended(dev) || !adev || (adev->wakeup.flags.valid && |
| 948 | device_may_wakeup(dev) != !!adev->wakeup.prepare_count) | 948 | device_may_wakeup(dev) != !!adev->wakeup.prepare_count)) |
| 949 | return true; | 949 | return true; |
| 950 | 950 | ||
| 951 | if (sys_target == ACPI_STATE_S0) | 951 | if (sys_target == ACPI_STATE_S0) |
| @@ -1132,15 +1132,19 @@ void __init acpi_no_s4_hw_signature(void) · 1131 unmodified lines | |||
| 1132 | nosigcheck = true; | 1132 | nosigcheck = true; |
| 1133 | } | 1133 | } |
| 1134 | 1134 | ||
| 1135 | static int acpi_hibernation_begin(void) | 1135 | static int acpi_hibernation_begin(pm_message_t stage) |
| 1136 | { | 1136 | { |
| 1137 | int error; | 1137 | if (!nvs_nosave) { |
| 1138 | int error = suspend_nvs_alloc(); | ||
| 1139 | if (error) | ||
| 1140 | return error; | ||
| 1141 | } | ||
| 1138 | 1142 | ||
| 1139 | error = nvs_nosave ? 0 : suspend_nvs_alloc(); | 1143 | if (stage.event == PM_EVENT_HIBERNATE) |
| 1140 | if (!error) | 1144 | pm_set_suspend_via_firmware(); |
| 1141 | acpi_pm_start(ACPI_STATE_S4); | ||
| 1142 | 1145 | ||
| 1143 | return error; | 1146 | acpi_pm_start(ACPI_STATE_S4); |
| 1147 | return 0; | ||
| 1144 | } | 1148 | } |
| 1145 | 1149 | ||
| 1146 | static int acpi_hibernation_enter(void) | 1150 | static int acpi_hibernation_enter(void) |
| @@ -1200,7 +1204,7 @@ static const struct platform_hibernation_ops acpi_hibernation_ops = { · 53 unmodified lines | |||
| 1200 | * function is used if the pre-ACPI 2.0 suspend ordering has been | 1204 | * function is used if the pre-ACPI 2.0 suspend ordering has been |
| 1201 | * requested. | 1205 | * requested. |
| 1202 | */ | 1206 | */ |
| 1203 | static int acpi_hibernation_begin_old(void) | 1207 | static int acpi_hibernation_begin_old(pm_message_t stage) |
| 1204 | { | 1208 | { |
| 1205 | int error; | 1209 | int error; |
| 1206 | /* | 1210 | /* |
| @@ -1211,16 +1215,21 @@ static int acpi_hibernation_begin_old(void) · 4 unmodified lines | |||
| 1211 | acpi_sleep_tts_switch(ACPI_STATE_S4); | 1215 | acpi_sleep_tts_switch(ACPI_STATE_S4); |
| 1212 | 1216 | ||
| 1213 | error = acpi_sleep_prepare(ACPI_STATE_S4); | 1217 | error = acpi_sleep_prepare(ACPI_STATE_S4); |
| 1218 | if (error) | ||
| 1219 | return error; | ||
| 1214 | 1220 | ||
| 1215 | if (!error) { | 1221 | if (!nvs_nosave) { |
| 1216 | if (!nvs_nosave) | 1222 | error = suspend_nvs_alloc(); |
| 1217 | error = suspend_nvs_alloc(); | 1223 | if (error) |
| 1218 | if (!error) { | 1224 | return error; |
| 1219 | acpi_target_sleep_state = ACPI_STATE_S4; | ||
| 1220 | acpi_scan_lock_acquire(); | ||
| 1221 | } | ||
| 1222 | } | 1225 | } |
| 1223 | return error; | 1226 | |
| 1227 | if (stage.event == PM_EVENT_HIBERNATE) | ||
| 1228 | pm_set_suspend_via_firmware(); | ||
| 1229 | |||
| 1230 | acpi_target_sleep_state = ACPI_STATE_S4; | ||
| 1231 | acpi_scan_lock_acquire(); | ||
| 1232 | return 0; | ||
| 1224 | } | 1233 | } |
| 1225 | 1234 | ||
| 1226 | /* | 1235 | /* |
| @@ -733,7 +733,8 @@ static bool acpi_pci_need_resume(struct pci_dev *dev) · 732 unmodified lines | |||
| 733 | if (!adev || !acpi_device_power_manageable(adev)) | 733 | if (!adev || !acpi_device_power_manageable(adev)) |
| 734 | return false; | 734 | return false; |
| 735 | 735 | ||
| 736 | if (device_may_wakeup(&dev->dev) != !!adev->wakeup.prepare_count) | 736 | if (adev->wakeup.flags.valid && |
| 737 | device_may_wakeup(&dev->dev) != !!adev->wakeup.prepare_count) | ||
| 737 | return true; | 738 | return true; |
| 738 | 739 | ||
| 739 | if (acpi_target_system_state() == ACPI_STATE_S0) | 740 | if (acpi_target_system_state() == ACPI_STATE_S0) |
| @@ -734,6 +734,8 @@ static int pci_pm_suspend(struct device *dev) · 733 unmodified lines | |||
| 734 | struct pci_dev *pci_dev = to_pci_dev(dev); | 734 | struct pci_dev *pci_dev = to_pci_dev(dev); |
| 735 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 735 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
| 736 | 736 | ||
| 737 | pci_dev->skip_bus_pm = false; | ||
| 738 | |||
| 737 | if (pci_has_legacy_pm_support(pci_dev)) | 739 | if (pci_has_legacy_pm_support(pci_dev)) |
| 738 | return pci_legacy_suspend(dev, PMSG_SUSPEND); | 740 | return pci_legacy_suspend(dev, PMSG_SUSPEND); |
| 739 | 741 | ||
| @@ -827,7 +829,20 @@ static int pci_pm_suspend_noirq(struct device *dev) · 87 unmodified lines | |||
| 827 | } | 829 | } |
| 828 | } | 830 | } |
| 829 | 831 | ||
| 830 | if (!pci_dev->state_saved) { | 832 | if (pci_dev->skip_bus_pm) { |
| 833 | /* | ||
| 834 | * The function is running for the second time in a row without | ||
| 835 | * going through full resume, which is possible only during | ||
| 836 | * suspend-to-idle in a spurious wakeup case. Moreover, the | ||
| 837 | * device was originally left in D0, so its power state should | ||
| 838 | * not be changed here and the device register values saved | ||
| 839 | * originally should be restored on resume again. | ||
| 840 | */ | ||
| 841 | pci_dev->state_saved = true; | ||
| 842 | } else if (pci_dev->state_saved) { | ||
| 843 | if (pci_dev->current_state == PCI_D0) | ||
| 844 | pci_dev->skip_bus_pm = true; | ||
| 845 | } else { | ||
| 831 | pci_save_state(pci_dev); | 846 | pci_save_state(pci_dev); |
| 832 | if (pci_power_manageable(pci_dev)) | 847 | if (pci_power_manageable(pci_dev)) |
| 833 | pci_prepare_to_sleep(pci_dev); | 848 | pci_prepare_to_sleep(pci_dev); |
| @@ -344,6 +344,7 @@ struct pci_dev { · 343 unmodified lines | |||
| 344 | D3cold, not set for devices | 344 | D3cold, not set for devices |
| 345 | powered on/off by the | 345 | powered on/off by the |
| 346 | corresponding bridge */ | 346 | corresponding bridge */ |
| 347 | unsigned int skip_bus_pm:1; /* Internal: Skip bus-level PM */ | ||
| 347 | unsigned int ignore_hotplug:1; /* Ignore hotplug events */ | 348 | unsigned int ignore_hotplug:1; /* Ignore hotplug events */ |
| 348 | unsigned int hotplug_user_indicators:1; /* SlotCtl indicators | 349 | unsigned int hotplug_user_indicators:1; /* SlotCtl indicators |
| 349 | controlled exclusively by | 350 | controlled exclusively by |
| @@ -359,7 +359,7 @@ extern void mark_free_pages(struct zone *zone); · 358 unmodified lines | |||
| 359 | * platforms which require special recovery actions in that situation. | 359 | * platforms which require special recovery actions in that situation. |
| 360 | */ | 360 | */ |
| 361 | struct platform_hibernation_ops { | 361 | struct platform_hibernation_ops { |
| 362 | int (*begin)(void); | 362 | int (*begin)(pm_message_t stage); |
| 363 | void (*end)(void); | 363 | void (*end)(void); |
| 364 | int (*pre_snapshot)(void); | 364 | int (*pre_snapshot)(void); |
| 365 | void (*finish)(void); | 365 | void (*finish)(void); |
| @@ -129,7 +129,7 @@ static int hibernation_test(int level) { return 0; } · 128 unmodified lines | |||
| 129 | static int platform_begin(int platform_mode) | 129 | static int platform_begin(int platform_mode) |
| 130 | { | 130 | { |
| 131 | return (platform_mode && hibernation_ops) ? | 131 | return (platform_mode && hibernation_ops) ? |
| 132 | hibernation_ops->begin() : 0; | 132 | hibernation_ops->begin(PMSG_FREEZE) : 0; |
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | /** | 135 | /** |
| @@ -542,7 +542,7 @@ int hibernation_platform_enter(void) · 406 unmodified lines | |||
| 542 | * hibernation_ops->finish() before saving the image, so we should let | 542 | * hibernation_ops->finish() before saving the image, so we should let |
| 543 | * the firmware know that we're going to enter the sleep state after all | 543 | * the firmware know that we're going to enter the sleep state after all |
| 544 | */ | 544 | */ |
| 545 | error = hibernation_ops->begin(); | 545 | error = hibernation_ops->begin(PMSG_HIBERNATE); |
| 546 | if (error) | 546 | if (error) |
| 547 | goto Close; | 547 | goto Close; |
| 548 | 548 | ||