History

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

Pull power management fix from Rafael Wysocki: "Avoid skipping bus-level PCI power management during system resume for PCIe ports left in D0 during the preceding suspend transition on platforms where the power states of those ports can change out of the PCI layer's control" * tag 'pm-5.2-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: PCI: PM: Avoid skipping bus-level PM on platforms without ACPI

Linus Torvalds committed 7 years ago

Commit 2407e482 parents 01305db 471a7393 files · +31 −6Browse files

Unified · Split

3 files
  1. drivers/pci/pci-driver.c +4 −4
  2. include/linux/suspend.h +24 −2
  3. kernel/power/suspend.c +3 −0
drivers/pci/pci-driver.c+4−4
@@ -859,7 +859,7 @@ static int pci_pm_suspend_noirq(struct device *dev) · 858 unmodified lines
859859 pci_dev->bus->self->skip_bus_pm = true;
860860 }
861861
862− if (pci_dev->skip_bus_pm && !pm_suspend_via_firmware()) {
862+ if (pci_dev->skip_bus_pm && pm_suspend_no_platform()) {
863863 dev_dbg(dev, "PCI PM: Skipped\n");
864864 goto Fixup;
865865 }
@@ -914,10 +914,10 @@ static int pci_pm_resume_noirq(struct device *dev) · 48 unmodified lines
914914 /*
915915 * In the suspend-to-idle case, devices left in D0 during suspend will
916916 * stay in D0, so it is not necessary to restore or update their
917− * configuration here and attempting to put them into D0 again may
918− * confuse some firmware, so avoid doing that.
917+ * configuration here and attempting to put them into D0 again is
918+ * pointless, so avoid doing that.
919919 */
920− if (!pci_dev->skip_bus_pm || pm_suspend_via_firmware())
920+ if (!(pci_dev->skip_bus_pm && pm_suspend_no_platform()))
921921 pci_pm_default_resume_early(pci_dev);
922922
923923 pci_fixup_device(pci_fixup_resume_early, pci_dev);
include/linux/suspend.h+24−2
@@ -209,8 +209,9 @@ extern int suspend_valid_only_mem(suspend_state_t state); · 208 unmodified lines
209209
210210 extern unsigned int pm_suspend_global_flags;
211211
212−#define PM_SUSPEND_FLAG_FW_SUSPEND (1 << 0)
213−#define PM_SUSPEND_FLAG_FW_RESUME (1 << 1)
212+#define PM_SUSPEND_FLAG_FW_SUSPEND BIT(0)
213+#define PM_SUSPEND_FLAG_FW_RESUME BIT(1)
214+#define PM_SUSPEND_FLAG_NO_PLATFORM BIT(2)
214215
215216 static inline void pm_suspend_clear_flags(void)
216217 {
@@ -227,6 +228,11 @@ static inline void pm_set_resume_via_firmware(void) · 10 unmodified lines
227228 pm_suspend_global_flags |= PM_SUSPEND_FLAG_FW_RESUME;
228229 }
229230
231+static inline void pm_set_suspend_no_platform(void)
232+{
233+ pm_suspend_global_flags |= PM_SUSPEND_FLAG_NO_PLATFORM;
234+}
235+
230236 /**
231237 * pm_suspend_via_firmware - Check if platform firmware will suspend the system.
232238 *
@@ -268,6 +274,22 @@ static inline bool pm_resume_via_firmware(void) · 35 unmodified lines
268274 return !!(pm_suspend_global_flags & PM_SUSPEND_FLAG_FW_RESUME);
269275 }
270276
277+/**
278+ * pm_suspend_no_platform - Check if platform may change device power states.
279+ *
280+ * To be called during system-wide power management transitions to sleep states
281+ * or during the subsequent system-wide transitions back to the working state.
282+ *
283+ * Return 'true' if the power states of devices remain under full control of the
284+ * kernel throughout the system-wide suspend and resume cycle in progress (that
285+ * is, if a device is put into a certain power state during suspend, it can be
286+ * expected to remain in that state during resume).
287+ */
288+static inline bool pm_suspend_no_platform(void)
289+{
290+ return !!(pm_suspend_global_flags & PM_SUSPEND_FLAG_NO_PLATFORM);
291+}
292+
271293 /* Suspend-to-idle state machnine. */
272294 enum s2idle_states {
273295 S2IDLE_STATE_NONE, /* Not suspended/suspending. */
kernel/power/suspend.c+3−0
@@ -493,6 +493,9 @@ int suspend_devices_and_enter(suspend_state_t state) · 492 unmodified lines
493493
494494 pm_suspend_target_state = state;
495495
496+ if (state == PM_SUSPEND_TO_IDLE)
497+ pm_set_suspend_no_platform();
498+
496499 error = platform_suspend_begin(state);
497500 if (error)
498501 goto Close;