]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 26 Jan 2020 09:00:15 +0000 (10:00 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 26 Jan 2020 09:00:15 +0000 (10:00 +0100)
added patches:
pci-pm-skip-devices-in-d0-for-suspend-to-idle.patch

queue-4.14/pci-pm-skip-devices-in-d0-for-suspend-to-idle.patch [new file with mode: 0644]
queue-4.14/series

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 (file)
index 0000000..4339f47
--- /dev/null
@@ -0,0 +1,120 @@
+From 3e26c5feed2add218046ecf91bab3cfa9bf762a6 Mon Sep 17 00:00:00 2001
+From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
+Date: Thu, 13 Jun 2019 23:59:45 +0200
+Subject: PCI: PM: Skip devices in D0 for suspend-to-idle
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+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 <kai.heng.feng@canonical.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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);
index ff79eaa69b6d0e41d95c6a19b38b9457470a8e0a..0edd59c17fc76812dbf57c74021c311f4a7de00b 100644 (file)
@@ -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