From: Greg Kroah-Hartman Date: Sun, 26 Jan 2020 09:00:15 +0000 (+0100) Subject: 4.14-stable patches X-Git-Tag: v5.4.15~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9bbd4eeb4438b2bd8a955295f0ff6497da37614e;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: pci-pm-skip-devices-in-d0-for-suspend-to-idle.patch --- diff --git a/queue-4.14/pci-pm-skip-devices-in-d0-for-suspend-to-idle.patch b/queue-4.14/pci-pm-skip-devices-in-d0-for-suspend-to-idle.patch new file mode 100644 index 00000000000..4339f478ba7 --- /dev/null +++ b/queue-4.14/pci-pm-skip-devices-in-d0-for-suspend-to-idle.patch @@ -0,0 +1,120 @@ +From 3e26c5feed2add218046ecf91bab3cfa9bf762a6 Mon Sep 17 00:00:00 2001 +From: "Rafael J. Wysocki" +Date: Thu, 13 Jun 2019 23:59:45 +0200 +Subject: PCI: PM: Skip devices in D0 for suspend-to-idle + +From: Rafael J. Wysocki + +commit 3e26c5feed2add218046ecf91bab3cfa9bf762a6 upstream. + +Commit d491f2b75237 ("PCI: PM: Avoid possible suspend-to-idle issue") +attempted to avoid a problem with devices whose drivers want them to +stay in D0 over suspend-to-idle and resume, but it did not go as far +as it should with that. + +Namely, first of all, the power state of a PCI bridge with a +downstream device in D0 must be D0 (based on the PCI PM spec r1.2, +sec 6, table 6-1, if the bridge is not in D0, there can be no PCI +transactions on its secondary bus), but that is not actively enforced +during system-wide PM transitions, so use the skip_bus_pm flag +introduced by commit d491f2b75237 for that. + +Second, the configuration of devices left in D0 (whatever the reason) +during suspend-to-idle need not be changed and attempting to put them +into D0 again by force is pointless, so explicitly avoid doing that. + +Fixes: d491f2b75237 ("PCI: PM: Avoid possible suspend-to-idle issue") +Reported-by: Kai-Heng Feng +Signed-off-by: Rafael J. Wysocki +Reviewed-by: Mika Westerberg +Tested-by: Kai-Heng Feng +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/pci-driver.c | 47 +++++++++++++++++++++++++++++++++++------------ + 1 file changed, 35 insertions(+), 12 deletions(-) + +--- a/drivers/pci/pci-driver.c ++++ b/drivers/pci/pci-driver.c +@@ -526,7 +526,6 @@ static void pci_pm_default_resume_early( + pci_power_up(pci_dev); + pci_restore_state(pci_dev); + pci_pme_restore(pci_dev); +- pci_fixup_device(pci_fixup_resume_early, pci_dev); + } + + /* +@@ -805,23 +804,37 @@ static int pci_pm_suspend_noirq(struct d + + if (pci_dev->skip_bus_pm) { + /* +- * The function is running for the second time in a row without ++ * Either the device is a bridge with a child in D0 below it, or ++ * the function is running for the second time in a row without + * going through full resume, which is possible only during +- * suspend-to-idle in a spurious wakeup case. Moreover, the +- * device was originally left in D0, so its power state should +- * not be changed here and the device register values saved +- * originally should be restored on resume again. ++ * suspend-to-idle in a spurious wakeup case. The device should ++ * be in D0 at this point, but if it is a bridge, it may be ++ * necessary to save its state. + */ +- pci_dev->state_saved = true; +- } else if (pci_dev->state_saved) { +- if (pci_dev->current_state == PCI_D0) +- pci_dev->skip_bus_pm = true; +- } else { ++ if (!pci_dev->state_saved) ++ pci_save_state(pci_dev); ++ } else if (!pci_dev->state_saved) { + pci_save_state(pci_dev); + if (pci_power_manageable(pci_dev)) + pci_prepare_to_sleep(pci_dev); + } + ++ if (pci_dev->current_state == PCI_D0) { ++ pci_dev->skip_bus_pm = true; ++ /* ++ * Per PCI PM r1.2, table 6-1, a bridge must be in D0 if any ++ * downstream device is in D0, so avoid changing the power state ++ * of the parent bridge by setting the skip_bus_pm flag for it. ++ */ ++ if (pci_dev->bus->self) ++ pci_dev->bus->self->skip_bus_pm = true; ++ } ++ ++ if (pci_dev->skip_bus_pm && !pm_suspend_via_firmware()) { ++ dev_dbg(dev, "PCI PM: Skipped\n"); ++ goto Fixup; ++ } ++ + pci_pm_set_unknown_state(pci_dev); + + /* +@@ -848,7 +861,16 @@ static int pci_pm_resume_noirq(struct de + struct device_driver *drv = dev->driver; + int error = 0; + +- pci_pm_default_resume_early(pci_dev); ++ /* ++ * In the suspend-to-idle case, devices left in D0 during suspend will ++ * stay in D0, so it is not necessary to restore or update their ++ * configuration here and attempting to put them into D0 again may ++ * confuse some firmware, so avoid doing that. ++ */ ++ if (!pci_dev->skip_bus_pm || pm_suspend_via_firmware()) ++ pci_pm_default_resume_early(pci_dev); ++ ++ pci_fixup_device(pci_fixup_resume_early, pci_dev); + + if (pci_has_legacy_pm_support(pci_dev)) + return pci_legacy_resume_early(dev); +@@ -1119,6 +1141,7 @@ static int pci_pm_restore_noirq(struct d + } + + pci_pm_default_resume_early(pci_dev); ++ pci_fixup_device(pci_fixup_resume_early, pci_dev); + + if (pci_has_legacy_pm_support(pci_dev)) + return pci_legacy_resume_early(dev); diff --git a/queue-4.14/series b/queue-4.14/series index ff79eaa69b6..0edd59c17fc 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -219,6 +219,7 @@ serial-stm32-add-support-of-tc-bit-status-check.patch serial-stm32-fix-wakeup-source-initialization.patch misc-sgi-xp-properly-initialize-buf-in-xpc_get_rsvd_.patch pci-pm-avoid-possible-suspend-to-idle-issue.patch +pci-pm-skip-devices-in-d0-for-suspend-to-idle.patch iommu-use-right-function-to-get-group-for-device.patch signal-cifs-fix-cifs_put_tcp_session-to-call-send_si.patch inet-frags-call-inet_frags_fini-after-unregister_per.patch