From: "Rafael J. Wysocki" <rjw@sisk.pl>
To: Alan Stern <stern@rowland.harvard.edu>
Cc: Linux-pm mailing list <linux-pm@lists.linux-foundation.org>,
Kevin Hilman <khilman@deeprootsystems.com>,
Partha Basak <p-basak2@ti.com>,
linux-omap@vger.kernel.org
Subject: Re: [PATCH] PM: add synchronous runtime interface for interrupt handlers
Date: Thu, 30 Sep 2010 22:15:59 +0200 [thread overview]
Message-ID: <201009302215.59937.rjw@sisk.pl> (raw)
In-Reply-To: <Pine.LNX.4.44L0.1009301420520.1314-100000@iolanthe.rowland.org>
Hi,
On Thursday, September 30, 2010, Alan Stern wrote:
> This patch (as1431) adds a synchronous runtime-PM interface suitable
> for use in interrupt handlers. Four new helper functions are defined:
>
> pm_runtime_suspend_irq(), pm_runtime_resume_irq(),
> pm_runtime_get_sync_irq(), pm_runtime_put_sync_irq(),
>
> together with pm_runtime_callbacks_in_irq(), which subsystems use to
> tell the PM core that the runtime callbacks should be invoked with
> interrupts disabled.
>
> Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
>
> ---
>
> In the end it turned out that a new RPM_IRQ call flag was needed along
> with the callbacks_in_irq flag in dev_pm_info. The latter is required
> for the reasons I explained before, and RPM_IRQ tells the core whether
> or not it must leave interrupts disabled while waiting for a concurrent
> state change.
>
> Kevin, this should be good enough to satisfy all your needs. How does
> it look?
>
> Alan Stern
>
>
> Index: usb-2.6/include/linux/pm.h
> ===================================================================
> --- usb-2.6.orig/include/linux/pm.h
> +++ usb-2.6/include/linux/pm.h
> @@ -485,6 +485,7 @@ struct dev_pm_info {
> unsigned int run_wake:1;
> unsigned int runtime_auto:1;
> unsigned int no_callbacks:1;
> + unsigned int callbacks_in_irq:1;
I kind of don't like this name. What about irq_safe ?
> unsigned int use_autosuspend:1;
> unsigned int timer_autosuspends:1;
> enum rpm_request request;
> Index: usb-2.6/include/linux/pm_runtime.h
> ===================================================================
> --- usb-2.6.orig/include/linux/pm_runtime.h
> +++ usb-2.6/include/linux/pm_runtime.h
> @@ -21,6 +21,7 @@
> #define RPM_GET_PUT 0x04 /* Increment/decrement the
> usage_count */
> #define RPM_AUTO 0x08 /* Use autosuspend_delay */
> +#define RPM_IRQ 0x10 /* Don't enable interrupts */
>
> #ifdef CONFIG_PM_RUNTIME
>
> @@ -40,6 +41,7 @@ extern int pm_generic_runtime_idle(struc
> extern int pm_generic_runtime_suspend(struct device *dev);
> extern int pm_generic_runtime_resume(struct device *dev);
> extern void pm_runtime_no_callbacks(struct device *dev);
> +extern void pm_runtime_callbacks_in_irq(struct device *dev);
Perhaps this one can be called pm_runtime_irq_safe() in analogy to the struct
member?
> extern void __pm_runtime_use_autosuspend(struct device *dev, bool use);
> extern void pm_runtime_set_autosuspend_delay(struct device *dev, int delay);
> extern unsigned long pm_runtime_autosuspend_expiration(struct device *dev);
> @@ -123,6 +125,7 @@ static inline int pm_generic_runtime_idl
> static inline int pm_generic_runtime_suspend(struct device *dev) { return 0; }
> static inline int pm_generic_runtime_resume(struct device *dev) { return 0; }
> static inline void pm_runtime_no_callbacks(struct device *dev) {}
> +static inline void pm_runtime_callbacks_in_irq(struct device *dev) {}
>
> static inline void pm_runtime_mark_last_busy(struct device *dev) {}
> static inline void __pm_runtime_use_autosuspend(struct device *dev,
> @@ -144,6 +147,11 @@ static inline int pm_runtime_suspend(str
> return __pm_runtime_suspend(dev, 0);
> }
>
> +static inline int pm_runtime_suspend_irq(struct device *dev)
> +{
> + return __pm_runtime_suspend(dev, RPM_IRQ);
> +}
> +
> static inline int pm_runtime_autosuspend(struct device *dev)
> {
> return __pm_runtime_suspend(dev, RPM_AUTO);
> @@ -154,6 +162,11 @@ static inline int pm_runtime_resume(stru
> return __pm_runtime_resume(dev, 0);
> }
>
> +static inline int pm_runtime_resume_irq(struct device *dev)
> +{
> + return __pm_runtime_resume(dev, RPM_IRQ);
> +}
> +
> static inline int pm_request_idle(struct device *dev)
> {
> return __pm_runtime_idle(dev, RPM_ASYNC);
> @@ -179,6 +192,11 @@ static inline int pm_runtime_get_sync(st
> return __pm_runtime_resume(dev, RPM_GET_PUT);
> }
>
> +static inline int pm_runtime_get_sync_irq(struct device *dev)
> +{
> + return __pm_runtime_resume(dev, RPM_GET_PUT | RPM_IRQ);
> +}
> +
> static inline int pm_runtime_put(struct device *dev)
> {
> return __pm_runtime_idle(dev, RPM_GET_PUT | RPM_ASYNC);
> @@ -195,6 +213,11 @@ static inline int pm_runtime_put_sync(st
> return __pm_runtime_idle(dev, RPM_GET_PUT);
> }
>
> +static inline int pm_runtime_put_sync_irq(struct device *dev)
> +{
> + return __pm_runtime_idle(dev, RPM_GET_PUT | RPM_IRQ);
> +}
> +
> static inline int pm_runtime_put_sync_autosuspend(struct device *dev)
> {
> return __pm_runtime_suspend(dev, RPM_GET_PUT | RPM_AUTO);
> Index: usb-2.6/drivers/base/power/runtime.c
> ===================================================================
> --- usb-2.6.orig/drivers/base/power/runtime.c
> +++ usb-2.6/drivers/base/power/runtime.c
> @@ -170,10 +170,13 @@ static int rpm_idle(struct device *dev,
> __releases(&dev->power.lock) __acquires(&dev->power.lock)
> {
> int retval;
> + int (*func)(struct device *dev);
>
> retval = rpm_check_suspend_allowed(dev);
> if (retval < 0)
> ; /* Conditions are wrong. */
> + else if ((rpmflags & RPM_IRQ) && !dev->power.callbacks_in_irq)
> + retval = -EWOULDBLOCK;
>
> /* Idle notifications are allowed only in the RPM_ACTIVE state. */
> else if (dev->power.runtime_status != RPM_ACTIVE)
> @@ -214,25 +217,27 @@ static int rpm_idle(struct device *dev,
>
> dev->power.idle_notification = true;
>
> - if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_idle) {
> - spin_unlock_irq(&dev->power.lock);
> -
> - dev->bus->pm->runtime_idle(dev);
> -
> - spin_lock_irq(&dev->power.lock);
> - } else if (dev->type && dev->type->pm && dev->type->pm->runtime_idle) {
> - spin_unlock_irq(&dev->power.lock);
> + func = NULL;
> + if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_idle)
> + func = dev->bus->pm->runtime_idle;
> + else if (dev->type && dev->type->pm && dev->type->pm->runtime_idle)
> + func = dev->type->pm->runtime_idle;
> + else if (dev->class && dev->class->pm && dev->class->pm->runtime_idle)
> + func = dev->class->pm->runtime_idle;
> + if (func) {
> + if (dev->power.callbacks_in_irq) {
> + spin_unlock(&dev->power.lock);
Hmm. This looks rather complicated. I don't really feel good about this
change. It seems to me that it might be better to actually implement
the _irq() helpers from scratch. I think I'll try to do that.
Overall, it looks like there's some overlap between RPM_IRQ and
power.callbacks_in_irq, where the latter may influence the behavior of the
helpers even if RPM_IRQ is unset.
I think we should return error code if RPM_IRQ is used, but
power.callbacks_in_irq is not set. If RPM_IRQ is not set, but
power.callbacks_in_irq is set, we should fall back to the normal behavior
(ie. do not avoid sleeping).
That's why I think it's better to change the name of power.callbacks_in_irq
to power.irq_safe.
Also I think we should refuse to set power.callbacks_in_irq for a device
whose partent (1) doesn't have power.callbacks_in_irq and (2) doesn't
have power.ignore_children set , and (3) doesn't have power.disable_depth > 0.
Then, once we've set power.callbacks_in_irq for a device, we should take
this into consideration when trying to change the parent's settings.
There probably is more subtelties like this, but I can't see them at the moment.
Thanks,
Rafael
next prev parent reply other threads:[~2010-09-30 20:17 UTC|newest]
Thread overview: 67+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-09-24 0:05 runtime_pm_get_sync() from ISR with IRQs disabled? Kevin Hilman
2010-09-24 15:13 ` [linux-pm] " Alan Stern
2010-09-24 18:54 ` Kevin Hilman
2010-09-24 20:04 ` Rafael J. Wysocki
2010-09-27 13:57 ` Alan Stern
2010-09-27 20:00 ` Rafael J. Wysocki
2010-09-27 20:39 ` Alan Stern
2010-09-27 21:09 ` Rafael J. Wysocki
2010-09-28 14:55 ` Alan Stern
2010-09-28 18:19 ` Rafael J. Wysocki
2010-09-30 18:25 ` [PATCH] PM: add synchronous runtime interface for interrupt handlers Alan Stern
2010-09-30 20:15 ` Rafael J. Wysocki [this message]
2010-09-30 21:42 ` Alan Stern
2010-09-30 22:41 ` Rafael J. Wysocki
2010-10-01 14:28 ` Alan Stern
2010-10-01 21:23 ` Rafael J. Wysocki
2010-10-02 14:12 ` Alan Stern
2010-10-02 22:06 ` Rafael J. Wysocki
2010-10-03 15:52 ` Alan Stern
2010-10-03 20:33 ` Rafael J. Wysocki
2010-10-05 21:44 ` Kevin Hilman
2010-10-06 15:58 ` Alan Stern
2010-10-06 19:33 ` Rafael J. Wysocki
2010-10-06 19:35 ` Kevin Hilman
2010-10-06 20:28 ` Alan Stern
2010-10-06 21:47 ` Rafael J. Wysocki
2010-10-07 15:26 ` Alan Stern
2010-10-07 16:52 ` Kevin Hilman
2010-10-07 17:35 ` Alan Stern
2010-10-07 21:11 ` Rafael J. Wysocki
2010-10-07 23:15 ` Kevin Hilman
2010-10-07 23:37 ` Rafael J. Wysocki
2010-10-07 23:55 ` Kevin Hilman
2010-10-08 16:22 ` Alan Stern
2010-10-08 21:04 ` Kevin Hilman
2010-10-08 19:57 ` Rafael J. Wysocki
2010-10-08 16:18 ` Alan Stern
2010-10-08 19:53 ` Rafael J. Wysocki
2010-10-09 11:09 ` [linux-pm] " Rafael J. Wysocki
2010-10-11 17:00 ` Alan Stern
2010-10-11 22:30 ` Rafael J. Wysocki
2010-11-19 15:45 ` [PATCH ver. 2] " Alan Stern
2010-11-20 12:56 ` Rafael J. Wysocki
2010-11-20 16:59 ` Alan Stern
2010-11-20 19:41 ` [linux-pm] " Alan Stern
2010-11-21 23:45 ` Rafael J. Wysocki
2010-11-21 23:41 ` Rafael J. Wysocki
2010-11-22 15:38 ` Alan Stern
2010-11-22 23:01 ` Rafael J. Wysocki
2010-11-23 3:19 ` Alan Stern
2010-11-23 22:51 ` Rafael J. Wysocki
2010-11-24 0:11 ` Kevin Hilman
2010-11-24 16:43 ` Alan Stern
2010-11-24 18:03 ` Kevin Hilman
2010-11-24 14:56 ` Alan Stern
2010-11-24 20:33 ` Rafael J. Wysocki
2010-11-25 15:52 ` [PATCH ver. 3] " Alan Stern
2010-11-25 18:58 ` [linux-pm] " Oliver Neukum
2010-11-25 20:03 ` Rafael J. Wysocki
2010-11-26 22:23 ` Rafael J. Wysocki
2010-10-06 23:51 ` [PATCH] " Kevin Hilman
2010-09-30 22:02 ` Rafael J. Wysocki
2010-10-01 14:12 ` Alan Stern
2010-10-01 21:14 ` Rafael J. Wysocki
2010-09-27 21:11 ` [linux-pm] runtime_pm_get_sync() from ISR with IRQs disabled? Kevin Hilman
2010-09-24 20:27 ` Alan Stern
2010-09-24 21:52 ` Kevin Hilman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=201009302215.59937.rjw@sisk.pl \
--to=rjw@sisk.pl \
--cc=khilman@deeprootsystems.com \
--cc=linux-omap@vger.kernel.org \
--cc=linux-pm@lists.linux-foundation.org \
--cc=p-basak2@ti.com \
--cc=stern@rowland.harvard.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).