drivers/base/power/main.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-)
On Tuesday, November 18, 2025 9:31:08 AM CET Rose Wu wrote:
> Hi,
>
> On Mon, 2025-11-17 at 19:57 +0100, Rafael J. Wysocki wrote:
> >
> > Make two changes to address this problem.
> >
> > First, reorder device_suspend_late() to only disable runtime PM for a
> > device if the power.is_late_suspended flag is going to be set for it.
> > In all of the other cases, disabling runtime PM for the device is not
> > in fact necessary.
> >
> > Second, make device_resume_early() only enable runtime PM for the
> > devices with the power.is_late_suspended flag set.
> >
>
> My concern is with the error path in device_suspend_late().
> If a device fails its dpm_run_callback(), it appears that its
> power.is_late_suspended flag is not set, potentially leaving its runtime
> PM disabled during the resume sequence.
Right, pm_runtime_enable() is missing in the error path after calling
dpm_run_callback().
---
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Runtime PM should only be enabled in device_resume_early() if it has
been disabled for the given device by device_suspend_late(). Otherwise,
it may cause runtime PM callbacks to run prematurely in some cases
which leads to further functional issues.
Make two changes to address this problem.
First, reorder device_suspend_late() to only disable runtime PM for a
device when it is going to look for the device's callback. In all of
the other cases, disabling runtime PM for the device is not in fact
necessary. However, if the device's callback returns an error and the
power.is_late_suspended flag is not going to be set, enable runtime
PM so it only remains disabled when power.is_late_suspended is set.
Second, make device_resume_early() only enable runtime PM for the
devices with the power.is_late_suspended flag set.
Fixes: 443046d1ad66 ("PM: sleep: Make suspend of devices more asynchronous")
Reported-by: Rose Wu <ya-jou.wu@mediatek.com>
Closes: https://lore.kernel.org/linux-pm/70b25dca6f8c2756d78f076f4a7dee7edaaffc33.camel@mediatek.com/
Cc: 6.16+ <stable@vger.kernel.org> # 6.16+
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
v1 -> v2: Add pm_runtime_enable() to device_suspend_late() error path (Rose).
---
drivers/base/power/main.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -941,11 +941,11 @@ Run:
Skip:
dev->power.is_late_suspended = false;
+ pm_runtime_enable(dev);
Out:
TRACE_RESUME(error);
- pm_runtime_enable(dev);
complete_all(&dev->power.completion);
if (error) {
@@ -1630,12 +1630,6 @@ static void device_suspend_late(struct d
TRACE_DEVICE(dev);
TRACE_SUSPEND(0);
- /*
- * Disable runtime PM for the device without checking if there is a
- * pending resume request for it.
- */
- __pm_runtime_disable(dev, false);
-
dpm_wait_for_subordinate(dev, async);
if (READ_ONCE(async_error))
@@ -1649,6 +1643,12 @@ static void device_suspend_late(struct d
if (dev->power.syscore || dev->power.direct_complete)
goto Complete;
+ /*
+ * Disable runtime PM for the device without checking if there is a
+ * pending resume request for it.
+ */
+ __pm_runtime_disable(dev, false);
+
if (dev->pm_domain) {
info = "late power domain ";
callback = pm_late_early_op(&dev->pm_domain->ops, state);
@@ -1679,6 +1679,7 @@ Run:
WRITE_ONCE(async_error, error);
dpm_save_failed_dev(dev_name(dev));
pm_dev_err(dev, state, async ? " async late" : " late", error);
+ pm_runtime_enable(dev);
goto Complete;
}
dpm_propagate_wakeup_to_parent(dev);
On Tue, 18 Nov 2025 at 12:48, Rafael J. Wysocki <rafael@kernel.org> wrote:
>
> On Tuesday, November 18, 2025 9:31:08 AM CET Rose Wu wrote:
> > Hi,
> >
> > On Mon, 2025-11-17 at 19:57 +0100, Rafael J. Wysocki wrote:
> > >
> > > Make two changes to address this problem.
> > >
> > > First, reorder device_suspend_late() to only disable runtime PM for a
> > > device if the power.is_late_suspended flag is going to be set for it.
> > > In all of the other cases, disabling runtime PM for the device is not
> > > in fact necessary.
> > >
> > > Second, make device_resume_early() only enable runtime PM for the
> > > devices with the power.is_late_suspended flag set.
> > >
> >
> > My concern is with the error path in device_suspend_late().
> > If a device fails its dpm_run_callback(), it appears that its
> > power.is_late_suspended flag is not set, potentially leaving its runtime
> > PM disabled during the resume sequence.
>
> Right, pm_runtime_enable() is missing in the error path after calling
> dpm_run_callback().
>
> ---
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> Runtime PM should only be enabled in device_resume_early() if it has
> been disabled for the given device by device_suspend_late(). Otherwise,
> it may cause runtime PM callbacks to run prematurely in some cases
> which leads to further functional issues.
>
> Make two changes to address this problem.
>
> First, reorder device_suspend_late() to only disable runtime PM for a
> device when it is going to look for the device's callback. In all of
> the other cases, disabling runtime PM for the device is not in fact
> necessary. However, if the device's callback returns an error and the
> power.is_late_suspended flag is not going to be set, enable runtime
> PM so it only remains disabled when power.is_late_suspended is set.
>
> Second, make device_resume_early() only enable runtime PM for the
> devices with the power.is_late_suspended flag set.
>
> Fixes: 443046d1ad66 ("PM: sleep: Make suspend of devices more asynchronous")
> Reported-by: Rose Wu <ya-jou.wu@mediatek.com>
> Closes: https://lore.kernel.org/linux-pm/70b25dca6f8c2756d78f076f4a7dee7edaaffc33.camel@mediatek.com/
> Cc: 6.16+ <stable@vger.kernel.org> # 6.16+
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
>
> v1 -> v2: Add pm_runtime_enable() to device_suspend_late() error path (Rose).
>
> ---
> drivers/base/power/main.c | 15 ++++++++-------
> 1 file changed, 8 insertions(+), 7 deletions(-)
>
> --- a/drivers/base/power/main.c
> +++ b/drivers/base/power/main.c
> @@ -941,11 +941,11 @@ Run:
>
> Skip:
> dev->power.is_late_suspended = false;
> + pm_runtime_enable(dev);
>
> Out:
> TRACE_RESUME(error);
>
> - pm_runtime_enable(dev);
> complete_all(&dev->power.completion);
>
> if (error) {
> @@ -1630,12 +1630,6 @@ static void device_suspend_late(struct d
> TRACE_DEVICE(dev);
> TRACE_SUSPEND(0);
>
> - /*
> - * Disable runtime PM for the device without checking if there is a
> - * pending resume request for it.
> - */
> - __pm_runtime_disable(dev, false);
> -
> dpm_wait_for_subordinate(dev, async);
>
> if (READ_ONCE(async_error))
> @@ -1649,6 +1643,12 @@ static void device_suspend_late(struct d
> if (dev->power.syscore || dev->power.direct_complete)
> goto Complete;
>
> + /*
> + * Disable runtime PM for the device without checking if there is a
> + * pending resume request for it.
> + */
> + __pm_runtime_disable(dev, false);
> +
Moving this here means we are going to keep runtime pm enabled for
syscore devices during system wide suspend/resume. That's quite a
change in behaviour for a fix for a regression, I think. Not saying
that it can't work though.
Although, perhaps better to call __pm_runtime_disable() a few lines
earlier and use a separate flag to track that we need to call
pm_runtime_enable() in device_resume_early()?
> if (dev->pm_domain) {
> info = "late power domain ";
> callback = pm_late_early_op(&dev->pm_domain->ops, state);
> @@ -1679,6 +1679,7 @@ Run:
> WRITE_ONCE(async_error, error);
> dpm_save_failed_dev(dev_name(dev));
> pm_dev_err(dev, state, async ? " async late" : " late", error);
> + pm_runtime_enable(dev);
> goto Complete;
> }
> dpm_propagate_wakeup_to_parent(dev);
>
>
>
Kind regards
Uffe
On Tue, Nov 18, 2025 at 1:18 PM Ulf Hansson <ulf.hansson@linaro.org> wrote:
>
> On Tue, 18 Nov 2025 at 12:48, Rafael J. Wysocki <rafael@kernel.org> wrote:
> >
> > On Tuesday, November 18, 2025 9:31:08 AM CET Rose Wu wrote:
> > > Hi,
> > >
> > > On Mon, 2025-11-17 at 19:57 +0100, Rafael J. Wysocki wrote:
> > > >
> > > > Make two changes to address this problem.
> > > >
> > > > First, reorder device_suspend_late() to only disable runtime PM for a
> > > > device if the power.is_late_suspended flag is going to be set for it.
> > > > In all of the other cases, disabling runtime PM for the device is not
> > > > in fact necessary.
> > > >
> > > > Second, make device_resume_early() only enable runtime PM for the
> > > > devices with the power.is_late_suspended flag set.
> > > >
> > >
> > > My concern is with the error path in device_suspend_late().
> > > If a device fails its dpm_run_callback(), it appears that its
> > > power.is_late_suspended flag is not set, potentially leaving its runtime
> > > PM disabled during the resume sequence.
> >
> > Right, pm_runtime_enable() is missing in the error path after calling
> > dpm_run_callback().
> >
> > ---
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >
> > Runtime PM should only be enabled in device_resume_early() if it has
> > been disabled for the given device by device_suspend_late(). Otherwise,
> > it may cause runtime PM callbacks to run prematurely in some cases
> > which leads to further functional issues.
> >
> > Make two changes to address this problem.
> >
> > First, reorder device_suspend_late() to only disable runtime PM for a
> > device when it is going to look for the device's callback. In all of
> > the other cases, disabling runtime PM for the device is not in fact
> > necessary. However, if the device's callback returns an error and the
> > power.is_late_suspended flag is not going to be set, enable runtime
> > PM so it only remains disabled when power.is_late_suspended is set.
> >
> > Second, make device_resume_early() only enable runtime PM for the
> > devices with the power.is_late_suspended flag set.
> >
> > Fixes: 443046d1ad66 ("PM: sleep: Make suspend of devices more asynchronous")
> > Reported-by: Rose Wu <ya-jou.wu@mediatek.com>
> > Closes: https://lore.kernel.org/linux-pm/70b25dca6f8c2756d78f076f4a7dee7edaaffc33.camel@mediatek.com/
> > Cc: 6.16+ <stable@vger.kernel.org> # 6.16+
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > ---
> >
> > v1 -> v2: Add pm_runtime_enable() to device_suspend_late() error path (Rose).
> >
> > ---
> > drivers/base/power/main.c | 15 ++++++++-------
> > 1 file changed, 8 insertions(+), 7 deletions(-)
> >
> > --- a/drivers/base/power/main.c
> > +++ b/drivers/base/power/main.c
> > @@ -941,11 +941,11 @@ Run:
> >
> > Skip:
> > dev->power.is_late_suspended = false;
> > + pm_runtime_enable(dev);
> >
> > Out:
> > TRACE_RESUME(error);
> >
> > - pm_runtime_enable(dev);
> > complete_all(&dev->power.completion);
> >
> > if (error) {
> > @@ -1630,12 +1630,6 @@ static void device_suspend_late(struct d
> > TRACE_DEVICE(dev);
> > TRACE_SUSPEND(0);
> >
> > - /*
> > - * Disable runtime PM for the device without checking if there is a
> > - * pending resume request for it.
> > - */
> > - __pm_runtime_disable(dev, false);
> > -
> > dpm_wait_for_subordinate(dev, async);
> >
> > if (READ_ONCE(async_error))
> > @@ -1649,6 +1643,12 @@ static void device_suspend_late(struct d
> > if (dev->power.syscore || dev->power.direct_complete)
> > goto Complete;
> >
> > + /*
> > + * Disable runtime PM for the device without checking if there is a
> > + * pending resume request for it.
> > + */
> > + __pm_runtime_disable(dev, false);
> > +
>
> Moving this here means we are going to keep runtime pm enabled for
> syscore devices during system wide suspend/resume. That's quite a
> change in behaviour for a fix for a regression, I think. Not saying
> that it can't work though.
syscore devices can be a special case, but I thought it wouldn't be
necessary to special-case them.
Do you actually know about any of them needing special casing?
> Although, perhaps better to call __pm_runtime_disable() a few lines
> earlier and use a separate flag to track that we need to call
> pm_runtime_enable() in device_resume_early()?
I don't think it is necessary or even useful to introduce new flags for this.
On Tue, 18 Nov 2025 at 13:26, Rafael J. Wysocki <rafael@kernel.org> wrote:
>
> On Tue, Nov 18, 2025 at 1:18 PM Ulf Hansson <ulf.hansson@linaro.org> wrote:
> >
> > On Tue, 18 Nov 2025 at 12:48, Rafael J. Wysocki <rafael@kernel.org> wrote:
> > >
> > > On Tuesday, November 18, 2025 9:31:08 AM CET Rose Wu wrote:
> > > > Hi,
> > > >
> > > > On Mon, 2025-11-17 at 19:57 +0100, Rafael J. Wysocki wrote:
> > > > >
> > > > > Make two changes to address this problem.
> > > > >
> > > > > First, reorder device_suspend_late() to only disable runtime PM for a
> > > > > device if the power.is_late_suspended flag is going to be set for it.
> > > > > In all of the other cases, disabling runtime PM for the device is not
> > > > > in fact necessary.
> > > > >
> > > > > Second, make device_resume_early() only enable runtime PM for the
> > > > > devices with the power.is_late_suspended flag set.
> > > > >
> > > >
> > > > My concern is with the error path in device_suspend_late().
> > > > If a device fails its dpm_run_callback(), it appears that its
> > > > power.is_late_suspended flag is not set, potentially leaving its runtime
> > > > PM disabled during the resume sequence.
> > >
> > > Right, pm_runtime_enable() is missing in the error path after calling
> > > dpm_run_callback().
> > >
> > > ---
> > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > >
> > > Runtime PM should only be enabled in device_resume_early() if it has
> > > been disabled for the given device by device_suspend_late(). Otherwise,
> > > it may cause runtime PM callbacks to run prematurely in some cases
> > > which leads to further functional issues.
> > >
> > > Make two changes to address this problem.
> > >
> > > First, reorder device_suspend_late() to only disable runtime PM for a
> > > device when it is going to look for the device's callback. In all of
> > > the other cases, disabling runtime PM for the device is not in fact
> > > necessary. However, if the device's callback returns an error and the
> > > power.is_late_suspended flag is not going to be set, enable runtime
> > > PM so it only remains disabled when power.is_late_suspended is set.
> > >
> > > Second, make device_resume_early() only enable runtime PM for the
> > > devices with the power.is_late_suspended flag set.
> > >
> > > Fixes: 443046d1ad66 ("PM: sleep: Make suspend of devices more asynchronous")
> > > Reported-by: Rose Wu <ya-jou.wu@mediatek.com>
> > > Closes: https://lore.kernel.org/linux-pm/70b25dca6f8c2756d78f076f4a7dee7edaaffc33.camel@mediatek.com/
> > > Cc: 6.16+ <stable@vger.kernel.org> # 6.16+
> > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > ---
> > >
> > > v1 -> v2: Add pm_runtime_enable() to device_suspend_late() error path (Rose).
> > >
> > > ---
> > > drivers/base/power/main.c | 15 ++++++++-------
> > > 1 file changed, 8 insertions(+), 7 deletions(-)
> > >
> > > --- a/drivers/base/power/main.c
> > > +++ b/drivers/base/power/main.c
> > > @@ -941,11 +941,11 @@ Run:
> > >
> > > Skip:
> > > dev->power.is_late_suspended = false;
> > > + pm_runtime_enable(dev);
> > >
> > > Out:
> > > TRACE_RESUME(error);
> > >
> > > - pm_runtime_enable(dev);
> > > complete_all(&dev->power.completion);
> > >
> > > if (error) {
> > > @@ -1630,12 +1630,6 @@ static void device_suspend_late(struct d
> > > TRACE_DEVICE(dev);
> > > TRACE_SUSPEND(0);
> > >
> > > - /*
> > > - * Disable runtime PM for the device without checking if there is a
> > > - * pending resume request for it.
> > > - */
> > > - __pm_runtime_disable(dev, false);
> > > -
> > > dpm_wait_for_subordinate(dev, async);
> > >
> > > if (READ_ONCE(async_error))
> > > @@ -1649,6 +1643,12 @@ static void device_suspend_late(struct d
> > > if (dev->power.syscore || dev->power.direct_complete)
> > > goto Complete;
> > >
> > > + /*
> > > + * Disable runtime PM for the device without checking if there is a
> > > + * pending resume request for it.
> > > + */
> > > + __pm_runtime_disable(dev, false);
> > > +
> >
> > Moving this here means we are going to keep runtime pm enabled for
> > syscore devices during system wide suspend/resume. That's quite a
> > change in behaviour for a fix for a regression, I think. Not saying
> > that it can't work though.
>
> syscore devices can be a special case, but I thought it wouldn't be
> necessary to special-case them.
>
> Do you actually know about any of them needing special casing?
There are a couple of clocksource drivers, cpuidle-psci,
cpuidle-riscv-sbi and a usb driver that marks their devices as syscore
devices.
It *probably* works to keep runtime pm enabled for all of them, but I
am not sure.
>
> > Although, perhaps better to call __pm_runtime_disable() a few lines
> > earlier and use a separate flag to track that we need to call
> > pm_runtime_enable() in device_resume_early()?
>
> I don't think it is necessary or even useful to introduce new flags for this.
Kind regards
Uffe
On Tue, Nov 18, 2025 at 1:49 PM Ulf Hansson <ulf.hansson@linaro.org> wrote:
>
> On Tue, 18 Nov 2025 at 13:26, Rafael J. Wysocki <rafael@kernel.org> wrote:
> >
> > On Tue, Nov 18, 2025 at 1:18 PM Ulf Hansson <ulf.hansson@linaro.org> wrote:
> > >
> > > On Tue, 18 Nov 2025 at 12:48, Rafael J. Wysocki <rafael@kernel.org> wrote:
> > > >
> > > > On Tuesday, November 18, 2025 9:31:08 AM CET Rose Wu wrote:
> > > > > Hi,
> > > > >
> > > > > On Mon, 2025-11-17 at 19:57 +0100, Rafael J. Wysocki wrote:
> > > > > >
> > > > > > Make two changes to address this problem.
> > > > > >
> > > > > > First, reorder device_suspend_late() to only disable runtime PM for a
> > > > > > device if the power.is_late_suspended flag is going to be set for it.
> > > > > > In all of the other cases, disabling runtime PM for the device is not
> > > > > > in fact necessary.
> > > > > >
> > > > > > Second, make device_resume_early() only enable runtime PM for the
> > > > > > devices with the power.is_late_suspended flag set.
> > > > > >
> > > > >
> > > > > My concern is with the error path in device_suspend_late().
> > > > > If a device fails its dpm_run_callback(), it appears that its
> > > > > power.is_late_suspended flag is not set, potentially leaving its runtime
> > > > > PM disabled during the resume sequence.
> > > >
> > > > Right, pm_runtime_enable() is missing in the error path after calling
> > > > dpm_run_callback().
> > > >
> > > > ---
> > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > >
> > > > Runtime PM should only be enabled in device_resume_early() if it has
> > > > been disabled for the given device by device_suspend_late(). Otherwise,
> > > > it may cause runtime PM callbacks to run prematurely in some cases
> > > > which leads to further functional issues.
> > > >
> > > > Make two changes to address this problem.
> > > >
> > > > First, reorder device_suspend_late() to only disable runtime PM for a
> > > > device when it is going to look for the device's callback. In all of
> > > > the other cases, disabling runtime PM for the device is not in fact
> > > > necessary. However, if the device's callback returns an error and the
> > > > power.is_late_suspended flag is not going to be set, enable runtime
> > > > PM so it only remains disabled when power.is_late_suspended is set.
> > > >
> > > > Second, make device_resume_early() only enable runtime PM for the
> > > > devices with the power.is_late_suspended flag set.
> > > >
> > > > Fixes: 443046d1ad66 ("PM: sleep: Make suspend of devices more asynchronous")
> > > > Reported-by: Rose Wu <ya-jou.wu@mediatek.com>
> > > > Closes: https://lore.kernel.org/linux-pm/70b25dca6f8c2756d78f076f4a7dee7edaaffc33.camel@mediatek.com/
> > > > Cc: 6.16+ <stable@vger.kernel.org> # 6.16+
> > > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > ---
> > > >
> > > > v1 -> v2: Add pm_runtime_enable() to device_suspend_late() error path (Rose).
> > > >
> > > > ---
> > > > drivers/base/power/main.c | 15 ++++++++-------
> > > > 1 file changed, 8 insertions(+), 7 deletions(-)
> > > >
> > > > --- a/drivers/base/power/main.c
> > > > +++ b/drivers/base/power/main.c
> > > > @@ -941,11 +941,11 @@ Run:
> > > >
> > > > Skip:
> > > > dev->power.is_late_suspended = false;
> > > > + pm_runtime_enable(dev);
> > > >
> > > > Out:
> > > > TRACE_RESUME(error);
> > > >
> > > > - pm_runtime_enable(dev);
> > > > complete_all(&dev->power.completion);
> > > >
> > > > if (error) {
> > > > @@ -1630,12 +1630,6 @@ static void device_suspend_late(struct d
> > > > TRACE_DEVICE(dev);
> > > > TRACE_SUSPEND(0);
> > > >
> > > > - /*
> > > > - * Disable runtime PM for the device without checking if there is a
> > > > - * pending resume request for it.
> > > > - */
> > > > - __pm_runtime_disable(dev, false);
> > > > -
> > > > dpm_wait_for_subordinate(dev, async);
> > > >
> > > > if (READ_ONCE(async_error))
> > > > @@ -1649,6 +1643,12 @@ static void device_suspend_late(struct d
> > > > if (dev->power.syscore || dev->power.direct_complete)
> > > > goto Complete;
> > > >
> > > > + /*
> > > > + * Disable runtime PM for the device without checking if there is a
> > > > + * pending resume request for it.
> > > > + */
> > > > + __pm_runtime_disable(dev, false);
> > > > +
> > >
> > > Moving this here means we are going to keep runtime pm enabled for
> > > syscore devices during system wide suspend/resume. That's quite a
> > > change in behaviour for a fix for a regression, I think. Not saying
> > > that it can't work though.
> >
> > syscore devices can be a special case, but I thought it wouldn't be
> > necessary to special-case them.
> >
> > Do you actually know about any of them needing special casing?
>
> There are a couple of clocksource drivers, cpuidle-psci,
> cpuidle-riscv-sbi and a usb driver that marks their devices as syscore
> devices.
>
> It *probably* works to keep runtime pm enabled for all of them, but I
> am not sure.
Well, all of the syscore devices with enabled runtime PM are potentially buggy.
Anyway, please see the v3:
https://lore.kernel.org/linux-pm/5941318.DvuYhMxLoT@rafael.j.wysocki/
© 2016 - 2025 Red Hat, Inc.