History

Merge tag 'pm-5.2-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

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

Linus Torvalds committed 7 years ago

Commit 702c31e2 parents 72cea7a d491f2b7 files · +48 −22Browse files

Unified · Split

7 files
  1. drivers/acpi/device_pm.c +2 −2
  2. drivers/acpi/sleep.c +24 −15
  3. drivers/pci/pci-acpi.c +2 −1
  4. drivers/pci/pci-driver.c +16 −1
  5. include/linux/pci.h +1 −0
  6. include/linux/suspend.h +1 −1
  7. kernel/power/hibernate.c +2 −2
drivers/acpi/device_pm.c+2−2
@@ -944,8 +944,8 @@ static bool acpi_dev_needs_resume(struct device *dev, struct acpi_device *adev) · 943 unmodified lines
944944 u32 sys_target = acpi_target_system_state();
945945 int ret, state;
946946
947− if (!pm_runtime_suspended(dev) || !adev ||
948− device_may_wakeup(dev) != !!adev->wakeup.prepare_count)
947+ if (!pm_runtime_suspended(dev) || !adev || (adev->wakeup.flags.valid &&
948+ device_may_wakeup(dev) != !!adev->wakeup.prepare_count))
949949 return true;
950950
951951 if (sys_target == ACPI_STATE_S0)
drivers/acpi/sleep.c+24−15
@@ -1132,15 +1132,19 @@ void __init acpi_no_s4_hw_signature(void) · 1131 unmodified lines
11321132 nosigcheck = true;
11331133 }
11341134
1135−static int acpi_hibernation_begin(void)
1135+static int acpi_hibernation_begin(pm_message_t stage)
11361136 {
1137− int error;
1137+ if (!nvs_nosave) {
1138+ int error = suspend_nvs_alloc();
1139+ if (error)
1140+ return error;
1141+ }
11381142
1139− error = nvs_nosave ? 0 : suspend_nvs_alloc();
1140− if (!error)
1141− acpi_pm_start(ACPI_STATE_S4);
1143+ if (stage.event == PM_EVENT_HIBERNATE)
1144+ pm_set_suspend_via_firmware();
11421145
1143− return error;
1146+ acpi_pm_start(ACPI_STATE_S4);
1147+ return 0;
11441148 }
11451149
11461150 static int acpi_hibernation_enter(void)
@@ -1200,7 +1204,7 @@ static const struct platform_hibernation_ops acpi_hibernation_ops = { · 53 unmodified lines
12001204 * function is used if the pre-ACPI 2.0 suspend ordering has been
12011205 * requested.
12021206 */
1203−static int acpi_hibernation_begin_old(void)
1207+static int acpi_hibernation_begin_old(pm_message_t stage)
12041208 {
12051209 int error;
12061210 /*
@@ -1211,16 +1215,21 @@ static int acpi_hibernation_begin_old(void) · 4 unmodified lines
12111215 acpi_sleep_tts_switch(ACPI_STATE_S4);
12121216
12131217 error = acpi_sleep_prepare(ACPI_STATE_S4);
1218+ if (error)
1219+ return error;
12141220
1215− if (!error) {
1216− if (!nvs_nosave)
1217− error = suspend_nvs_alloc();
1218− if (!error) {
1219− acpi_target_sleep_state = ACPI_STATE_S4;
1220− acpi_scan_lock_acquire();
1221− }
1221+ if (!nvs_nosave) {
1222+ error = suspend_nvs_alloc();
1223+ if (error)
1224+ return error;
12221225 }
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;
12241233 }
12251234
12261235 /*
drivers/pci/pci-acpi.c+2−1
@@ -733,7 +733,8 @@ static bool acpi_pci_need_resume(struct pci_dev *dev) · 732 unmodified lines
733733 if (!adev || !acpi_device_power_manageable(adev))
734734 return false;
735735
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)
737738 return true;
738739
739740 if (acpi_target_system_state() == ACPI_STATE_S0)
drivers/pci/pci-driver.c+16−1
@@ -734,6 +734,8 @@ static int pci_pm_suspend(struct device *dev) · 733 unmodified lines
734734 struct pci_dev *pci_dev = to_pci_dev(dev);
735735 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
736736
737+ pci_dev->skip_bus_pm = false;
738+
737739 if (pci_has_legacy_pm_support(pci_dev))
738740 return pci_legacy_suspend(dev, PMSG_SUSPEND);
739741
@@ -827,7 +829,20 @@ static int pci_pm_suspend_noirq(struct device *dev) · 87 unmodified lines
827829 }
828830 }
829831
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 {
831846 pci_save_state(pci_dev);
832847 if (pci_power_manageable(pci_dev))
833848 pci_prepare_to_sleep(pci_dev);
include/linux/pci.h+1−0
@@ -344,6 +344,7 @@ struct pci_dev { · 343 unmodified lines
344344 D3cold, not set for devices
345345 powered on/off by the
346346 corresponding bridge */
347+ unsigned int skip_bus_pm:1; /* Internal: Skip bus-level PM */
347348 unsigned int ignore_hotplug:1; /* Ignore hotplug events */
348349 unsigned int hotplug_user_indicators:1; /* SlotCtl indicators
349350 controlled exclusively by
include/linux/suspend.h+1−1
@@ -359,7 +359,7 @@ extern void mark_free_pages(struct zone *zone); · 358 unmodified lines
359359 * platforms which require special recovery actions in that situation.
360360 */
361361 struct platform_hibernation_ops {
362− int (*begin)(void);
362+ int (*begin)(pm_message_t stage);
363363 void (*end)(void);
364364 int (*pre_snapshot)(void);
365365 void (*finish)(void);
kernel/power/hibernate.c+2−2
@@ -129,7 +129,7 @@ static int hibernation_test(int level) { return 0; } · 128 unmodified lines
129129 static int platform_begin(int platform_mode)
130130 {
131131 return (platform_mode && hibernation_ops) ?
132− hibernation_ops->begin() : 0;
132+ hibernation_ops->begin(PMSG_FREEZE) : 0;
133133 }
134134
135135 /**
@@ -542,7 +542,7 @@ int hibernation_platform_enter(void) · 406 unmodified lines
542542 * hibernation_ops->finish() before saving the image, so we should let
543543 * the firmware know that we're going to enter the sleep state after all
544544 */
545− error = hibernation_ops->begin();
545+ error = hibernation_ops->begin(PMSG_HIBERNATE);
546546 if (error)
547547 goto Close;
548548