]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 14 May 2021 15:39:21 +0000 (17:39 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 14 May 2021 15:39:21 +0000 (17:39 +0200)
added patches:
pm-runtime-fix-unpaired-parent-child_count-for-force_resume.patch

queue-5.4/pm-runtime-fix-unpaired-parent-child_count-for-force_resume.patch [new file with mode: 0644]
queue-5.4/series

diff --git a/queue-5.4/pm-runtime-fix-unpaired-parent-child_count-for-force_resume.patch b/queue-5.4/pm-runtime-fix-unpaired-parent-child_count-for-force_resume.patch
new file mode 100644 (file)
index 0000000..8b17a96
--- /dev/null
@@ -0,0 +1,110 @@
+From c745253e2a691a40c66790defe85c104a887e14a Mon Sep 17 00:00:00 2001
+From: Tony Lindgren <tony@atomide.com>
+Date: Wed, 5 May 2021 14:09:15 +0300
+Subject: PM: runtime: Fix unpaired parent child_count for force_resume
+
+From: Tony Lindgren <tony@atomide.com>
+
+commit c745253e2a691a40c66790defe85c104a887e14a upstream.
+
+As pm_runtime_need_not_resume() relies also on usage_count, it can return
+a different value in pm_runtime_force_suspend() compared to when called in
+pm_runtime_force_resume(). Different return values can happen if anything
+calls PM runtime functions in between, and causes the parent child_count
+to increase on every resume.
+
+So far I've seen the issue only for omapdrm that does complicated things
+with PM runtime calls during system suspend for legacy reasons:
+
+omap_atomic_commit_tail() for omapdrm.0
+ dispc_runtime_get()
+  wakes up 58000000.dss as it's the dispc parent
+   dispc_runtime_resume()
+    rpm_resume() increases parent child_count
+ dispc_runtime_put() won't idle, PM runtime suspend blocked
+pm_runtime_force_suspend() for 58000000.dss, !pm_runtime_need_not_resume()
+ __update_runtime_status()
+system suspended
+pm_runtime_force_resume() for 58000000.dss, pm_runtime_need_not_resume()
+ pm_runtime_enable() only called because of pm_runtime_need_not_resume()
+omap_atomic_commit_tail() for omapdrm.0
+ dispc_runtime_get()
+  wakes up 58000000.dss as it's the dispc parent
+   dispc_runtime_resume()
+    rpm_resume() increases parent child_count
+ dispc_runtime_put() won't idle, PM runtime suspend blocked
+...
+rpm_suspend for 58000000.dss but parent child_count is now unbalanced
+
+Let's fix the issue by adding a flag for needs_force_resume and use it in
+pm_runtime_force_resume() instead of pm_runtime_need_not_resume().
+
+Additionally omapdrm system suspend could be simplified later on to avoid
+lots of unnecessary PM runtime calls and the complexity it adds. The
+driver can just use internal functions that are shared between the PM
+runtime and system suspend related functions.
+
+Fixes: 4918e1f87c5f ("PM / runtime: Rework pm_runtime_force_suspend/resume()")
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
+Tested-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+Cc: 4.16+ <stable@vger.kernel.org> # 4.16+
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/power/runtime.c |   10 +++++++---
+ include/linux/pm.h           |    1 +
+ 2 files changed, 8 insertions(+), 3 deletions(-)
+
+--- a/drivers/base/power/runtime.c
++++ b/drivers/base/power/runtime.c
+@@ -1610,6 +1610,7 @@ void pm_runtime_init(struct device *dev)
+       dev->power.request_pending = false;
+       dev->power.request = RPM_REQ_NONE;
+       dev->power.deferred_resume = false;
++      dev->power.needs_force_resume = 0;
+       INIT_WORK(&dev->power.work, pm_runtime_work);
+       dev->power.timer_expires = 0;
+@@ -1777,10 +1778,12 @@ int pm_runtime_force_suspend(struct devi
+        * its parent, but set its status to RPM_SUSPENDED anyway in case this
+        * function will be called again for it in the meantime.
+        */
+-      if (pm_runtime_need_not_resume(dev))
++      if (pm_runtime_need_not_resume(dev)) {
+               pm_runtime_set_suspended(dev);
+-      else
++      } else {
+               __update_runtime_status(dev, RPM_SUSPENDED);
++              dev->power.needs_force_resume = 1;
++      }
+       return 0;
+@@ -1807,7 +1810,7 @@ int pm_runtime_force_resume(struct devic
+       int (*callback)(struct device *);
+       int ret = 0;
+-      if (!pm_runtime_status_suspended(dev) || pm_runtime_need_not_resume(dev))
++      if (!pm_runtime_status_suspended(dev) || !dev->power.needs_force_resume)
+               goto out;
+       /*
+@@ -1826,6 +1829,7 @@ int pm_runtime_force_resume(struct devic
+       pm_runtime_mark_last_busy(dev);
+ out:
++      dev->power.needs_force_resume = 0;
+       pm_runtime_enable(dev);
+       return ret;
+ }
+--- a/include/linux/pm.h
++++ b/include/linux/pm.h
+@@ -608,6 +608,7 @@ struct dev_pm_info {
+       unsigned int            idle_notification:1;
+       unsigned int            request_pending:1;
+       unsigned int            deferred_resume:1;
++      unsigned int            needs_force_resume:1;
+       unsigned int            runtime_auto:1;
+       bool                    ignore_children:1;
+       unsigned int            no_callbacks:1;
index 788a53d053d7835eba4dd031d9a72aec4af2d399..1605f97c83cee42d6910ccc366570cacdfec7f07 100644 (file)
@@ -2,3 +2,4 @@ tpm-fix-error-return-code-in-tpm2_get_cc_attrs_tbl.patch
 tpm-tpm_tis-extend-locality-handling-to-tpm2-in-tpm_tis_gen_interrupt.patch
 tpm-tpm_tis-reserve-locality-in-tpm_tis_resume.patch
 kvm-x86-mmu-remove-the-defunct-update_pte-paging-hook.patch
+pm-runtime-fix-unpaired-parent-child_count-for-force_resume.patch