From: Greg Kroah-Hartman Date: Sat, 20 Mar 2021 10:52:59 +0000 (+0100) Subject: 4.14-stable patches X-Git-Tag: v4.4.263~95 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9a3b1dd3e871dd81896d205432919033260a2293;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: revert-pm-runtime-update-device-status-before-letting-suppliers-suspend.patch --- 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 index 00000000000..5dbb660ac46 --- /dev/null +++ b/queue-4.14/revert-pm-runtime-update-device-status-before-letting-suppliers-suspend.patch @@ -0,0 +1,113 @@ +From 0cab893f409c53634d0d818fa414641cbcdb0dab Mon Sep 17 00:00:00 2001 +From: "Rafael J. Wysocki" +Date: Fri, 19 Mar 2021 15:47:25 +0100 +Subject: Revert "PM: runtime: Update device status before letting suppliers suspend" + +From: Rafael J. Wysocki + +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 +Cc: 4.10+ # 4.10+ +Signed-off-by: Rafael J. Wysocki +Reviewed-by: Ulf Hansson +Signed-off-by: Greg Kroah-Hartman +--- + 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); + } diff --git a/queue-4.14/series b/queue-4.14/series index 290f7788b37..f52928951ce 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -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