From: "Rafael J. Wysocki" <rjw@sisk.pl>
To: Kevin Hilman <khilman@ti.com>
Cc: Alan Stern <stern@rowland.harvard.edu>,
Linux-pm mailing list <linux-pm@lists.linux-foundation.org>,
linux-omap@vger.kernel.org, Magnus Damm <magnus.damm@gmail.com>,
Paul Walmsley <paul@pwsan.com>
Subject: Re: [linux-pm] calling runtime PM from system PM methods
Date: Mon, 6 Jun 2011 20:29:36 +0200 [thread overview]
Message-ID: <201106062029.36389.rjw@sisk.pl> (raw)
In-Reply-To: <87lixkyxa8.fsf@ti.com>
Hi,
Sorry for the delay. After returning from Japan I found my cable modem
basically dead, so I have no Internet access from home at the moment, which is
a bit inconvenient, so to speak.
On Thursday, June 02, 2011, Kevin Hilman wrote:
> Alan Stern <stern@rowland.harvard.edu> writes:
>
> > On Wed, 1 Jun 2011, Kevin Hilman wrote:
> >
> >> In the process of experimenting with other solutions, I found an
> >> interesting discovery:
> >>
> >> In the driver's ->suspend() hook, I did something like this:
> >>
> >> priv->forced_suspend = false;
> >> if (!pm_runtime_suspended(dev)) {
> >> pm_runtime_put_sync(dev);
> >> priv->forced_suspend = true;
> >> }
> >>
> >> and in the resume hook I did this:
> >>
> >> if (priv->forced_suspend)
> >> pm_runtime_get_sync(dev);
> >>
> >> Even after disabling runtime PM from userspace via
> >> /sys/devices/.../power/control, the ->suspend() hook triggered an actual
> >> transition. This is because pm_runtime_forbid() just uses the usage
> >> counter, so the _put_sync() in the ->suspend callback decrements the
> >> counter and triggers an rpm_idle(). Is this expected behavior?
> >
> > Not really. In fact it is a bug in your experimental code -- you are
> > decrementing the usage counter in a context where you did not
> > previously increment it. In principle, the counter might already be 0
> > when the suspend hook runs.
> >
> > Yes, it is indeed possible for a device to be active while the usage
> > counter is 0. For example (assuming the counter is initially 0), this
> > will happen if you call
> >
> > pm_runtime_get_sync(dev);
> > pm_runtime_put_noidle(dev);
> >
> > or even if you simply call
> >
> > pm_runtime_resume(dev);
> >
> > Of course, the drivers you're talking about may never do this. Still,
> > it's a logical mistake to do a *_put without previously doing a *_get.
>
> OK. I was trying to catch that by checking pm_runtime_suspended(), but
> now see that that cannot work in general.
>
> The problem I'm trying to solve is how (or whether) I can use runtime PM
> from the system PM methods, specifically in the case where runtime PM
> has been disabled from userspace (or pm_runtime_forbid() has been
> called.)
We discussed this exact issue with Magnus and Paul during LinuxCon Japan
and the answer to it is that you can't.
Apart from the problem with user space disabling runtime PM, there is
a problem with subsystem callbacks, which accidentally doesn't apply to
the platform bus type. Namely, calling pm_runtime_suspend() or
pm_runtime_put_sync() from a driver's .suspend() routine will result in
the subsystem's .runtime_suspend() routine being called, which is incorrect,
because the driver's .suspend() routine itself is called by the subsystem's
.suspend() routine. So, if one attempted to call pm_runtime_suspend() from
a driver's .suspend(), we'd get:
(subsystem)->suspend() => (driver)->suspend() => pm_runtime_suspend() =>
(subsystem)->runtime_suspend() ...
However, the driver cannot assume that the subsystem's .runtime_suspend()
may always be called from withing its .suspend(). In fact, for many subsystems
this will cause interesting breakage to occur.
> In a nutshell, what I'm after is for any pm_runtime_forbid() calls to be
> cancelled during system PM, thus allowing pending runtime PM events to
> occur during system PM.
>
> Basically, what I have is several drivers who don't really need suspend
> hooks if runtime PM is enabled, because they use runtime PM on a per
> transaction basis, handle all the HW stuff in the runtime PM callbacks,
> and from a HW perspective, there is no difference in power state between
> runtime and static suspend. These devices are already runtime suspended
> when the system PM callbacks run, so there is nothing for the system PM
> callbacks to do.
Well, I'm not quite sure this is the case. You have to remember that
system suspend can happen at any time, so even if your runtime PM is used
around transactions, it theoretically is possible for system suspend to
happen while one of the transactions is in progress (unless you can guarantee
that the transactions can't be preempted).
> If pm_runtime_forbid() has been called, but then a system suspend is
> initiated, we'd like these devices to actually suspend, meaning allowing
> any pending runtime PM transitions to happen during system suspend.
> In order to force/trick/pursuade the device to to this, something like
> this works:
>
> static int omap_i2c_suspend(struct device *dev)
> {
> if (dev->power.runtime_auto == false)
> pm_runtime_put_sync(dev);
This is incorrect (see above).
> return 0;
> }
>
> static int omap_i2c_resume(struct device *dev)
> {
> if (dev->power.runtime_auto == false)
> pm_runtime_get_sync(dev);
Likewise.
> return 0;
> }
>
> Yes, this does a put without a get, but when runtime_auto == true,
> there was an implicit _get_noresume() done by the runtime PM core.
>
> Possibly a cleaner way, but one that would force the driver to keep
> addiional state would be something like
>
> suspend (or prepare):
>
> if (dev->power.runtime_auto == false) {
> priv->rpm_forced = true;
> pm_runtime_allow(dev);
> }
>
> resume (or complete):
>
> if (priv->rpm_forced)
> pm_runtime_forbid(dev);
>
> If this is acceptable, I'd probably implement this at the device power
> domain level instead of having to have every driver do this.
While it is tempting to try to get away with only two PM callbacks per
driver instead of four (or even more), it generally is not doable, simply
because driver callbacks are not executed directly by the core.
The only way to address the problem of code duplication between .suspend()
and .runtime_suspend() callbacks (and analogously for resume) I see at the
moment is to make those callbacks execute common routines.
Thanks,
Rafael
next prev parent reply other threads:[~2011-06-06 18:28 UTC|newest]
Thread overview: 58+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-06-02 0:05 calling runtime PM from system PM methods Kevin Hilman
2011-06-02 14:18 ` [linux-pm] " Alan Stern
2011-06-02 17:10 ` Kevin Hilman
2011-06-02 18:38 ` Alan Stern
2011-06-06 18:29 ` Rafael J. Wysocki [this message]
2011-06-06 19:16 ` Alan Stern
2011-06-06 22:25 ` Kevin Hilman
2011-06-07 13:55 ` Alan Stern
2011-06-07 21:32 ` Rafael J. Wysocki
2011-06-07 22:34 ` Kevin Hilman
2011-06-08 22:50 ` Kevin Hilman
2011-06-09 5:29 ` Magnus Damm
2011-06-09 13:56 ` Alan Stern
2011-06-10 14:36 ` Mark Brown
2011-06-10 14:51 ` Alan Stern
2011-06-10 15:21 ` Mark Brown
2011-06-10 15:45 ` Alan Stern
2011-06-10 15:57 ` Mark Brown
2011-06-10 17:17 ` Alan Stern
2011-06-10 17:31 ` Mark Brown
2011-06-10 18:38 ` Rafael J. Wysocki
2011-06-10 18:42 ` Mark Brown
2011-06-10 20:27 ` Rafael J. Wysocki
2011-06-10 21:27 ` Alan Stern
2011-06-11 11:42 ` Mark Brown
2011-06-11 20:56 ` Rafael J. Wysocki
2011-06-13 12:22 ` [linux-pm] " Mark Brown
2011-06-10 18:49 ` Rafael J. Wysocki
2011-06-10 18:54 ` Mark Brown
2011-06-10 20:45 ` Rafael J. Wysocki
2011-06-10 23:52 ` Kevin Hilman
2011-06-11 16:42 ` Alan Stern
2011-06-11 22:46 ` Rafael J. Wysocki
2011-06-12 15:59 ` Alan Stern
2011-06-12 18:27 ` Rafael J. Wysocki
2011-06-15 21:54 ` Kevin Hilman
2011-06-16 0:01 ` Rafael J. Wysocki
2011-06-16 1:17 ` Kevin Hilman
2011-06-16 14:27 ` Alan Stern
2011-06-16 22:48 ` Rafael J. Wysocki
2011-06-17 19:47 ` Rafael J. Wysocki
2011-06-17 20:04 ` Alan Stern
2011-06-17 21:29 ` Rafael J. Wysocki
2011-06-18 11:08 ` Rafael J. Wysocki
2011-06-18 15:31 ` Alan Stern
2011-06-18 21:01 ` Rafael J. Wysocki
2011-06-18 23:57 ` Rafael J. Wysocki
2011-06-19 1:42 ` Alan Stern
2011-06-19 14:04 ` Rafael J. Wysocki
2011-06-19 15:01 ` Alan Stern
2011-06-19 19:36 ` Rafael J. Wysocki
2011-06-20 14:39 ` Alan Stern
2011-06-20 19:53 ` Rafael J. Wysocki
2011-06-16 22:30 ` Rafael J. Wysocki
2011-06-10 23:14 ` Kevin Hilman
2011-06-11 16:27 ` Alan Stern
2011-06-11 23:13 ` Rafael J. Wysocki
2011-06-06 18:01 ` Rafael J. Wysocki
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=201106062029.36389.rjw@sisk.pl \
--to=rjw@sisk.pl \
--cc=khilman@ti.com \
--cc=linux-omap@vger.kernel.org \
--cc=linux-pm@lists.linux-foundation.org \
--cc=magnus.damm@gmail.com \
--cc=paul@pwsan.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).