Patch "PM / wakeirq: Fix dedicated wakeirq for drivers not using autosuspend" has been added to the 4.9-stable tree
Subsystems (5)
This is a note to let you know that I've just added the patch titled
PM / wakeirq: Fix dedicated wakeirq for drivers not using autosuspend
to the 4.9-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
pm-wakeirq-fix-dedicated-wakeirq-for-drivers-not-using-autosuspend.patch
and it can be found in the queue-4.9 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
bed570307ed78f21b77cb04a1df781dee4a8f05aMon Sep 17 00:00:00 2001
From: Tony Lindgren <[email protected]>
Date: Mon, 5 Dec 2016 16:38:16 -0800
Subject: PM / wakeirq: Fix dedicated wakeirq for drivers not using autosuspend
From: Tony Lindgren <[email protected]>
commit bed570307ed78f21b77cb04a1df781dee4a8f05a upstream.
I noticed some wakeirq flakeyness with consumer drivers not using autosuspend. For drivers not using autosuspend, the wakeirq may never get unmasked in rpm_suspend() because of irq desc->depth.
We are configuring dedicated wakeirqs to start with IRQ_NOAUTOEN as we naturally don't want them running until rpm_suspend() is called.
However, when a consumer driver initially calls pm_runtime_get(), we now wrongly start with disable_irq_nosync() call on the dedicated wakeirq that is disabled to start with.
This causes desc->depth to toggle between 1 and 2 instead of the usual 0 and 1. This can prevent enable_irq() from unmasking the wakeirq as that only happens at desc->depth 1.
This does not necessarily show up with drivers using autosuspend as there is time for disable_irq_nosync() before rpm_suspend() gets called after the autosuspend timeout.
Let's fix the issue by adding wirq->status that lazily gets set on the first rpm_suspend(). We also need PM runtime core private functions for dev_pm_enable_wake_irq_check() and dev_pm_disable_wake_irq_check() so we can enable the dedicated wakeirq on the first rpm_suspend().
While at it, let's also fix the comments for dev_pm_enable_wake_irq() and dev_pm_disable_wake_irq(). Those can still be used by the consumer drivers as needed because the IRQ core manages the interrupt usecount for us.
--- drivers/base/power/power.h | 19 ++++++++++ drivers/base/power/runtime.c | 8 ++-- drivers/base/power/wakeirq.c | 76 +++++++++++++++++++++++++++++++++++++------ 3 files changed, 88 insertions(+), 15 deletions(-)
drivers/base/power/power.h +18 -1
@@ -21,14 +21,22 @@ extern void pm_runtime_init(struct devicextern void pm_runtime_reinit (struct device *dev);extern void pm_runtime_remove (struct device *dev); +#define WAKE_IRQ_DEDICATED_ALLOCATED BIT(0) +#define WAKE_IRQ_DEDICATED_MANAGED BIT(1) +#define WAKE_IRQ_DEDICATED_MASK (WAKE_IRQ_DEDICATED_ALLOCATED | \ + WAKE_IRQ_DEDICATED_MANAGED) +struct wake_irq {struct device *dev; +unsigned int status;int irq; -bool dedicated_irq:1 ; };extern void dev_pm_arm_wake_irq (struct wake_irq *wirq);extern void dev_pm_disarm_wake_irq (struct wake_irq *wirq); +extern void dev_pm_enable_wake_irq_check (struct device *dev, +bool can_change_status); +extern void dev_pm_disable_wake_irq_check (struct device *dev);#ifdef CONFIG_PM_SLEEP
@@ -104,6 +112,15 @@ static inline void dev_pm_disarm_wake_ir { } +static inline void dev_pm_enable_wake_irq_check (struct device *dev, +bool can_change_status) +{ +} + +static inline void dev_pm_disable_wake_irq_check (struct device *dev) +{ +} +#endif #ifdef CONFIG_PM_SLEEP
drivers/base/power/runtime.c +4 -4
@@ -515,7 +515,7 @@ static int rpm_suspend(struct device *de callback =RPM_GET_CALLBACK (dev, runtime_suspend); -dev_pm_enable_wake_irq (dev); +dev_pm_enable_wake_irq_check (dev, true); retval =rpm_callback (callback, dev);if (retval) goto fail;
@@ -554,7 +554,7 @@ static int rpm_suspend(struct device *dereturn retval; fail: -dev_pm_disable_wake_irq (dev); +dev_pm_disable_wake_irq_check (dev);__update_runtime_status (dev,RPM_ACTIVE ); dev->power.deferred_resume = false;wake_up_all (&dev->power.wait_queue);
@@ -737,12 +737,12 @@ static int rpm_resume(struct device *dev callback =RPM_GET_CALLBACK (dev, runtime_resume); -dev_pm_disable_wake_irq (dev); +dev_pm_disable_wake_irq_check (dev); retval =rpm_callback (callback, dev);if (retval) {__update_runtime_status (dev,RPM_SUSPENDED );pm_runtime_cancel_pending (dev); -dev_pm_enable_wake_irq (dev); +dev_pm_enable_wake_irq_check (dev, false); }else { no_callback:__update_runtime_status (dev,RPM_ACTIVE );
drivers/base/power/wakeirq.c +66 -10
123 lines not on this page · raw message
Patches currently in stable-queue which might be from [email protected] are
queue-4.9/pm-wakeirq-fix-dedicated-wakeirq-for-drivers-not-using-autosuspend.patch queue-4.9/usb-musb-fix-trying-to-free-already-free-irq-4.patch