From: Greg Kroah-Hartman Date: Fri, 14 May 2021 15:39:21 +0000 (+0200) Subject: 5.4-stable patches X-Git-Tag: v5.4.120~97 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=672da97426af27f8986e6392f3319cba30072f92;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: pm-runtime-fix-unpaired-parent-child_count-for-force_resume.patch --- 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 index 00000000000..8b17a964d19 --- /dev/null +++ b/queue-5.4/pm-runtime-fix-unpaired-parent-child_count-for-force_resume.patch @@ -0,0 +1,110 @@ +From c745253e2a691a40c66790defe85c104a887e14a Mon Sep 17 00:00:00 2001 +From: Tony Lindgren +Date: Wed, 5 May 2021 14:09:15 +0300 +Subject: PM: runtime: Fix unpaired parent child_count for force_resume + +From: Tony Lindgren + +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 +Reviewed-by: Ulf Hansson +Tested-by: Tomi Valkeinen +Cc: 4.16+ # 4.16+ +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman +--- + 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; diff --git a/queue-5.4/series b/queue-5.4/series index 788a53d053d..1605f97c83c 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -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