From: "Arve Hjønnevåg" <arve@android.com>
To: Paul Walmsley <paul@pwsan.com>
Cc: "Greg Kroah-Hartman" <gregkh@suse.de>,
"Sven Neumann" <s.neumann@raumfeld.com>,
"Jesse Barnes" <jbarnes@virtuousgeek.org>,
linux-kernel@vger.kernel.org,
"Dmitry Torokhov" <dmitry.torokhov@gmail.com>,
"Tero Saarni" <tero.saarni@gmail.com>,
linux-input@vger.kernel.org, linux-pm@lists.linux-foundation.org,
"Liam Girdwood" <lrg@slimlogic.co.uk>,
"Alexey Dobriyan" <adobriyan@gmail.com>,
"Matthew Garrett" <mjg@redhat.com>,
"Len Brown" <len.brown@intel.com>,
"Jacob Pan" <jacob.jun.pan@linux.intel.com>,
"Daniel Mack" <daniel@caiaq.de>,
"Oleg Nesterov" <oleg@redhat.com>,
linux-omap@vger.kernel.org,
"Linus Walleij" <linus.walleij@stericsson.com>,
"Daniel Walker" <dwalker@codeaurora.org>,
"Theodore Ts'o" <tytso@mit.edu>,
"Márton Németh" <nm127@freemail.hu>,
"Brian Swetland" <swetland@goo>
Subject: Re: [PATCH 0/8] Suspend block api (version 6)
Date: Tue, 25 May 2010 16:08:00 -0700 [thread overview]
Message-ID: <AANLkTilj79bWWIxg-g6OmLtk37zaAdjntoJAfZPBivAV@mail.gmail.com> (raw)
In-Reply-To: <alpine.DEB.2.00.1005250050060.13376@utopia.booyaka.com>
On Tue, May 25, 2010 at 2:41 AM, Paul Walmsley <paul@pwsan.com> wrote:
> Hello Arve,
>
> I regret the delay in responding.
>
> On Mon, 17 May 2010, Arve Hjønnevåg wrote:
>
>> On Mon, May 17, 2010 at 7:26 PM, Paul Walmsley <paul@pwsan.com> wrote:
>> > On Fri, 14 May 2010, Arve Hjønnevåg wrote:
>> >> On Fri, May 14, 2010 at 1:27 PM, Paul Walmsley <paul@pwsan.com> wrote:
>> >> > On Mon, 3 May 2010, Arve Hjønnevåg wrote:
>> >> >
>> >> >> No, suspend blockers are mostly used to ensure wakeup events are not
>> >> >> ignored, and to ensure tasks triggered by these wakeup events
>> >> >> complete.
>> >> >
>> >> > Standard Linux systems don't need these,
>> >>
>> >> If you don't want to lose wakeup events they do. Standard Linux systems
>> >> support suspend, but since they usually don't have a lot of wakeup
>> >> events you don't run into a lot of problems.
>> >
>> > Sorry, I don't follow. What causes wakeup events to be lost? Is it the
>> > current opportunistic suspend governor? On OMAP Linux systems, as far as
>> > I know, we don't lose any wakeup events.
>> >
>> Have you used suspend?
>
> I see. You are referring to wakeup event loss/delay caused by the full
> system suspend process (e.g., kernel/power/suspend.c:enter_state()
> onwards[1]), correct? This message addresses this at the end of the mail.
>
>> >> > because the scheduler just keeps the system running as long as there
>> >> > is work to be done.
>> >>
>> >> That is only true if you never use suspend.
>> >
>> > If, instead of the current Android opportunistic suspend governor, the
>> > system entered suspend from pm_idle(), wouldn't that keep the system
>> > running as long as there is work to done?
>> >
>> How do you know if the work being done while suspending is work that
>> is needed to suspend or work that should abort suspend?
>
> Consider a suspending system in which all "untrusted" processes have been
> placed into TASK_INTERRUPTIBLE state and have had their timers
> disabled.[2] The only remaining work to do on the system is work that
> needs to be done as part of the suspend process, or work that is part of a
> "trusted" process or the kernel. If the suspend needs to be aborted due
> to the arrival of an event, this can be handled as part of the standard
> suspend process (described below).
>
That means modifying all kernel code that would use suspend blockers
to abort suspend by returning an error from suspend instead. How is
this better than using suspend blockers?
>> When should the system wake up?
>
> I suspect that I am misunderstanding your question, but the system should
> wake up the same way it does now: when a wakeup interrupt arrives (either
> from the next scheduled timer expiration, or from some external device).
>
That is not how the system wakes up from suspend now. The monotonic
clock stops, and timers are ignored.
>> > As far as I can see, it's the current Android opportunistic suspend
>> > governor design in patch 1 that causes the system to enter suspend even
>> > when there is work to be done, since it will try to suspend even when the
>> > system is out of the idle loop.
>>
>> It does not matter how you enter suspend. Without opportunistic suspend,
>> once you tell the kernel that you want to suspend, you cannot abort.
>
> Any driver should be able to abort suspend by returning an error from its
> struct device_driver/struct dev_pm_ops suspend function. Consider this
Yes a driver can abort, but the user space code that initiated suspend cannot.
> partial callgraph for full system suspend, from [3], [4]:
>
> kernel/power/suspend.c: enter_state() ->
> kernel/power/suspend.c: suspend_devices_and_enter() ->
> drivers/base/power/main.c: dpm_suspend_start() ->
> drivers/base/power/main.c: dpm_suspend() ->
> drivers/base/power/main.c: device_suspend() ->
> drivers/base/power/main.c: __device_suspend() ->
> drivers/base/power/main.c: pm_op() ->
> drivers/base/power/main.c: ops->suspend()
>
> If ops->suspend() returns an error, it's ultimately passed back to
> suspend_devices_and_enter(), which aborts the suspend[5].
>
> In this context, the main change that should be necessary is for
> driver/subsystem suspend functions to return an error when there are
> events pending. For example, as an alternative to the Android series'
> evdev.c patch[6], the evdev.c suspend function could return an error such
> as -EBUSY if events are currently queued (example below).
>
> Aborting suspend in the event of driver activity seems like the right
> thing to do in a system that attempts to enter full system suspend while
> idle. But it is not the current expected Linux behavior, which also seems
> useful. Any abort-suspend-if-busy behavior should be configurable. One
> way would be to add a sysfs file for each driver/subsystem: perhaps
> something like 'abort_suspend_if_busy'. The default value would be zero
> to preserve the current behavior. Systems that wish to use opportunistic
> suspend could write a one to some or all of those files.
>
> An untested, purely illustrative example, based on evdev.c, is at the end
> of this message. It's not meant to be functional; it's just meant to
> demonstrate the basic idea in code form.
>
Do you think this is simpler than using a suspend blocker?
> ...
>
> Like suspend-blockers, adding abort_suspend_if_busy support would require
> changes throughout many drivers and subsystems. However, unlike
> suspend-blockers, the above abort_suspend_if_busy approach would not
> introduce any new APIs[7], nor would it change the default suspend
> behavior of the system.
>
Opportunistic suspend does not change the default behaviour either.
Your proposal requires that all the drivers that would block suspend
using a suspend blocker, now block suspend without the help of the
suspend blocker api.
> As an aside, it seems that Android shouldn't currently need this if it's
> possible to pause "untrusted" processes and timers[8], since current
Your proposal to "pause"processes by putting them in
TASK_INTERRUPTIBLE state and stop their timers does not work. It is
effectivly the same ase freezing them, since if you "paused" it while
it was busy, a wakeup event cannot unpause it.
> shipping Android hardware can enter the same system low power state both
> with and without full system suspend[9]. But this could be useful for
> non-Android systems that still wish to use an idle-loop based,
> opportunistic full system suspend.
>
>
> regards,
>
> - Paul
>
>
> 1. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=kernel/power/suspend.c;h=56e7dbb8b996db295b4fc7cdf1b5f11a0409cb0c;hb=7e125f7b9cbfce4101191b8076d606c517a73066#l258
>
> 2. Section B4 of Paul Walmsley E-mail to the linux-pm mailing list,
> dated Mon May 17 19:39:44 CDT 2010:
> https://lists.linux-foundation.org/pipermail/linux-pm/2010-May/025663.html
>
> 3. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=kernel/power/suspend.c;h=56e7dbb8b996db295b4fc7cdf1b5f11a0409cb0c;hb=7e125f7b9cbfce4101191b8076d606c517a73066#l258
>
> 4. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/base/power/main.c;h=941fcb87e52a12765df2aaa2e2ab21267693af9f;hb=7e125f7b9cbfce4101191b8076d606c517a73066#l1062
>
> 5. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=kernel/power/suspend.c;h=56e7dbb8b996db295b4fc7cdf1b5f11a0409cb0c;hb=7e125f7b9cbfce4101191b8076d606c517a73066#l207
>
> 6. Arve Hjønnevåg E-mail to the linux-pm mailing list, dated Fri May 21
> 15:46:54 PDT 2010:
> https://lists.linux-foundation.org/pipermail/linux-pm/2010-May/025747.html
>
> 7. Paul Walmsley E-mail to the linux-pm mailing list, dated Thu May 13
> 23:13:50 PDT 2010:
> https://lists.linux-foundation.org/pipermail/linux-pm/2010-May/025524.html
>
> 8. Paul Walmsley E-mail to the linux-pm mailing list, dated Mon May 17
> 18:39:44 PDT 2010:
> https://lists.linux-foundation.org/pipermail/linux-pm/2010-May/025663.html
>
> 9. Arve Hjønnevåg E-mail to the linux-pm mailing list, dated Mon, May 17
> 20:06:33 PDT 2010:
> https://lists.linux-foundation.org/pipermail/linux-pm/2010-May/025668.html
>
>
>
> --------------------------------------------------------------------------------------
>
> evdev.c abort_suspend_if_idle experiment:
>
> ---
> drivers/input/evdev.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 files changed, 63 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
> index 2ee6c7a..23eaad1 100644
> --- a/drivers/input/evdev.c
> +++ b/drivers/input/evdev.c
> @@ -20,8 +20,16 @@
> #include <linux/input.h>
> #include <linux/major.h>
> #include <linux/device.h>
> +#include <linux/pm.h>
> #include "input-compat.h"
>
> +/*
> + * abort_suspend_if_busy: set to 1 to prevent suspend as long as there
> + * is an event in the queue; set to 0 to allow suspend at any time.
> + * XXX Intended to be read from sysfs or the input subsystem.
> + */
> +static int abort_suspend_if_busy;
> +
> struct evdev {
> int exist;
> int open;
> @@ -118,6 +126,36 @@ static int evdev_flush(struct file *file, fl_owner_t id)
> return retval;
> }
>
> +static int evdev_suspend(struct device *dev)
> +{
> + struct evdev *evdev = container_of(dev, struct evdev, dev);
> + struct evdev_client *client;
> + int ret = 0;
> +
> + if (!abort_suspend_if_busy)
> + return 0;
> +
> + rcu_read_lock();
> +
> + client = rcu_dereference(evdev->grab);
> + if (client) {
> + if (client->head != client->tail)
> + ret = -EBUSY;
> + } else {
> + list_for_each_entry_rcu(client, &evdev->client_list, node) {
> + if (client->head != client->tail) {
> + ret = -EBUSY;
> + break;
> + }
> + }
> + }
> +
> + rcu_read_unlock();
> +
> + return ret;
> +}
> +
> +
> static void evdev_free(struct device *dev)
> {
> struct evdev *evdev = container_of(dev, struct evdev, dev);
> @@ -787,6 +825,21 @@ static void evdev_cleanup(struct evdev *evdev)
> }
> }
>
> +static const struct dev_pm_ops evdev_pm_ops = {
> + .suspend = &evdev_suspend,
> +};
> +
> +static char *evdev_devnode(struct device *dev, mode_t *mode)
> +{
> + return kasprintf(GFP_KERNEL, "input/%s", dev_name(dev));
> +}
> +
> +static struct class evdev_class = {
> + .name = "evdev",
> + .devnode = evdev_devnode,
> + .pm = &evdev_pm_ops,
> +};
> +
> /*
> * Create new evdev device. Note that input core serializes calls
> * to connect and disconnect so we don't need to lock evdev_table here.
> @@ -826,7 +879,7 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
> evdev->handle.private = evdev;
>
> evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor);
> - evdev->dev.class = &input_class;
> + evdev->dev.class = &evdev_class;
> evdev->dev.parent = &dev->dev;
> evdev->dev.release = evdev_free;
> device_initialize(&evdev->dev);
> @@ -883,12 +936,21 @@ static struct input_handler evdev_handler = {
>
> static int __init evdev_init(void)
> {
> + int err;
> +
> + err = class_register(&input_class);
> + if (err) {
> + printk(KERN_ERR "evdev: unable to register evdev class\n");
> + return err;
> + }
> +
> return input_register_handler(&evdev_handler);
> }
>
> static void __exit evdev_exit(void)
> {
> input_unregister_handler(&evdev_handler);
> + class_unregister(&evdev_class);
> }
>
> module_init(evdev_init);
> --
> 1.7.1.GIT
--
Arve Hjønnevåg
next prev parent reply other threads:[~2010-05-25 23:08 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <1272667021-21312-1-git-send-email-arve@android.com>
[not found] ` <1272667021-21312-2-git-send-email-arve@android.com>
[not found] ` <1272667021-21312-3-git-send-email-arve@android.com>
[not found] ` <1272667021-21312-4-git-send-email-arve@android.com>
[not found] ` <1272667021-21312-5-git-send-email-arve@android.com>
[not found] ` <1272667021-21312-6-git-send-email-arve@android.com>
[not found] ` <1272667021-21312-7-git-send-email-arve@android.com>
2010-04-30 22:37 ` [PATCH 7/8] Input: Block suspend while event queue is not empty Arve Hjønnevåg
[not found] ` <87wrvl5479.fsf@deeprootsystems.com>
[not found] ` <20100503180741.GB2098@rakim.wolfsonmicro.main>
[not found] ` <201005032318.35383.rjw@sisk.pl>
[not found] ` <87sk68r1zh.fsf@deeprootsystems.com>
[not found] ` <s2qd6200be21005031709r28420f0ezf3cf286517ee9114@mail.gmail.com>
2010-05-14 20:27 ` [PATCH 0/8] Suspend block api (version 6) Paul Walmsley
2010-05-14 22:18 ` Arve Hjønnevåg
2010-05-15 2:25 ` Alan Stern
2010-05-15 4:02 ` Arve Hjønnevåg
2010-05-15 21:25 ` Alan Stern
2010-05-17 4:54 ` Arve Hjønnevåg
2010-05-18 2:26 ` Paul Walmsley
2010-05-18 3:21 ` Arve Hjønnevåg
2010-05-18 7:03 ` Henrik Rydberg
2010-05-18 19:39 ` Rafael J. Wysocki
2010-05-25 9:41 ` Paul Walmsley
2010-05-25 23:08 ` Arve Hjønnevåg [this message]
2010-05-26 7:23 ` Linus WALLEIJ
2010-05-26 16:01 ` Alan Stern
2010-05-27 7:46 ` Linus WALLEIJ
2010-05-27 8:04 ` Florian Mickler
2010-05-27 8:40 ` Arve Hjønnevåg
2010-05-27 15:33 ` Alan Stern
2010-05-28 11:54 ` Linus WALLEIJ
2010-05-20 23:37 ` David Brownell
2010-05-25 16:51 ` Dmitry Torokhov
2010-05-25 18:25 ` Alan Stern
2010-05-25 18:33 ` Dmitry Torokhov
2010-05-25 22:05 ` Arve Hjønnevåg
2010-05-25 22:28 ` Dmitry Torokhov
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=AANLkTilj79bWWIxg-g6OmLtk37zaAdjntoJAfZPBivAV@mail.gmail.com \
--to=arve@android.com \
--cc=adobriyan@gmail.com \
--cc=daniel@caiaq.de \
--cc=dmitry.torokhov@gmail.com \
--cc=dwalker@codeaurora.org \
--cc=gregkh@suse.de \
--cc=jacob.jun.pan@linux.intel.com \
--cc=jbarnes@virtuousgeek.org \
--cc=len.brown@intel.com \
--cc=linus.walleij@stericsson.com \
--cc=linux-input@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-omap@vger.kernel.org \
--cc=linux-pm@lists.linux-foundation.org \
--cc=lrg@slimlogic.co.uk \
--cc=mjg@redhat.com \
--cc=nm127@freemail.hu \
--cc=oleg@redhat.com \
--cc=paul@pwsan.com \
--cc=s.neumann@raumfeld.com \
--cc=swetland@goo \
--cc=tero.saarni@gmail.com \
--cc=tytso@mit.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).