]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 20 Mar 2021 10:52:59 +0000 (11:52 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 20 Mar 2021 10:52:59 +0000 (11:52 +0100)
added patches:
revert-pm-runtime-update-device-status-before-letting-suppliers-suspend.patch

queue-4.14/revert-pm-runtime-update-device-status-before-letting-suppliers-suspend.patch [new file with mode: 0644]
queue-4.14/series

diff --git a/queue-4.14/revert-pm-runtime-update-device-status-before-letting-suppliers-suspend.patch b/queue-4.14/revert-pm-runtime-update-device-status-before-letting-suppliers-suspend.patch
new file mode 100644 (file)
index 0000000..5dbb660
--- /dev/null
@@ -0,0 +1,113 @@
+From 0cab893f409c53634d0d818fa414641cbcdb0dab Mon Sep 17 00:00:00 2001
+From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
+Date: Fri, 19 Mar 2021 15:47:25 +0100
+Subject: Revert "PM: runtime: Update device status before letting suppliers suspend"
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+commit 0cab893f409c53634d0d818fa414641cbcdb0dab upstream.
+
+Revert commit 44cc89f76464 ("PM: runtime: Update device status
+before letting suppliers suspend") that introduced a race condition
+into __rpm_callback() which allowed a concurrent rpm_resume() to
+run and resume the device prematurely after its status had been
+changed to RPM_SUSPENDED by __rpm_callback().
+
+Fixes: 44cc89f76464 ("PM: runtime: Update device status before letting suppliers suspend")
+Link: https://lore.kernel.org/linux-pm/24dfb6fc-5d54-6ee2-9195-26428b7ecf8a@intel.com/
+Reported-by: Adrian Hunter <adrian.hunter@intel.com>
+Cc: 4.10+ <stable@vger.kernel.org> # 4.10+
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/power/runtime.c |   62 +++++++++++++++++--------------------------
+ 1 file changed, 25 insertions(+), 37 deletions(-)
+
+--- a/drivers/base/power/runtime.c
++++ b/drivers/base/power/runtime.c
+@@ -306,22 +306,22 @@ static void rpm_put_suppliers(struct dev
+ static int __rpm_callback(int (*cb)(struct device *), struct device *dev)
+       __releases(&dev->power.lock) __acquires(&dev->power.lock)
+ {
+-      bool use_links = dev->power.links_count > 0;
+-      bool get = false;
+       int retval, idx;
+-      bool put;
++      bool use_links = dev->power.links_count > 0;
+       if (dev->power.irq_safe) {
+               spin_unlock(&dev->power.lock);
+-      } else if (!use_links) {
+-              spin_unlock_irq(&dev->power.lock);
+       } else {
+-              get = dev->power.runtime_status == RPM_RESUMING;
+-
+               spin_unlock_irq(&dev->power.lock);
+-              /* Resume suppliers if necessary. */
+-              if (get) {
++              /*
++               * Resume suppliers if necessary.
++               *
++               * The device's runtime PM status cannot change until this
++               * routine returns, so it is safe to read the status outside of
++               * the lock.
++               */
++              if (use_links && dev->power.runtime_status == RPM_RESUMING) {
+                       idx = device_links_read_lock();
+                       retval = rpm_get_suppliers(dev);
+@@ -336,36 +336,24 @@ static int __rpm_callback(int (*cb)(stru
+       if (dev->power.irq_safe) {
+               spin_lock(&dev->power.lock);
+-              return retval;
+-      }
+-
+-      spin_lock_irq(&dev->power.lock);
+-
+-      if (!use_links)
+-              return retval;
+-
+-      /*
+-       * If the device is suspending and the callback has returned success,
+-       * drop the usage counters of the suppliers that have been reference
+-       * counted on its resume.
+-       *
+-       * Do that if the resume fails too.
+-       */
+-      put = dev->power.runtime_status == RPM_SUSPENDING && !retval;
+-      if (put)
+-              __update_runtime_status(dev, RPM_SUSPENDED);
+-      else
+-              put = get && retval;
+-
+-      if (put) {
+-              spin_unlock_irq(&dev->power.lock);
+-
+-              idx = device_links_read_lock();
++      } else {
++              /*
++               * If the device is suspending and the callback has returned
++               * success, drop the usage counters of the suppliers that have
++               * been reference counted on its resume.
++               *
++               * Do that if resume fails too.
++               */
++              if (use_links
++                  && ((dev->power.runtime_status == RPM_SUSPENDING && !retval)
++                  || (dev->power.runtime_status == RPM_RESUMING && retval))) {
++                      idx = device_links_read_lock();
+-fail:
+-              rpm_put_suppliers(dev);
++ fail:
++                      rpm_put_suppliers(dev);
+-              device_links_read_unlock(idx);
++                      device_links_read_unlock(idx);
++              }
+               spin_lock_irq(&dev->power.lock);
+       }
index 290f7788b37c39b9606fc42ec529b9f6fba7406e..f52928951cef31d704fd2a6894e69757e44a1275 100644 (file)
@@ -6,3 +6,4 @@ bpf-simplify-alu_limit-masking-for-pointer-arithmetic.patch
 bpf-add-sanity-check-for-upper-ptr_limit.patch
 net-dsa-b53-support-setting-learning-on-port.patch
 bpf-prohibit-alu-ops-for-pointer-types-not-defining-ptr_limit.patch
+revert-pm-runtime-update-device-status-before-letting-suppliers-suspend.patch