[linux-pm] [PATCH 02/13] PM: Add early suspend api.

Rafael J. Wysocki rjw at sisk.pl
Sat Feb 7 12:53:29 PST 2009


On Thursday 05 February 2009, Arve Hjønnevåg wrote:
> Signed-off-by: Arve Hjønnevåg <arve at android.com>
> ---
>  Documentation/power/early-suspend.txt |   26 +++++++++++++++
>  include/linux/earlysuspend.h          |   55 +++++++++++++++++++++++++++++++++
>  2 files changed, 81 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/power/early-suspend.txt
>  create mode 100755 include/linux/earlysuspend.h
> 
> diff --git a/Documentation/power/early-suspend.txt b/Documentation/power/early-suspend.txt
> new file mode 100644
> index 0000000..8286d3a
> --- /dev/null
> +++ b/Documentation/power/early-suspend.txt
> @@ -0,0 +1,26 @@
> +Early-suspend
> +=============
> +
> +The early-suspend api allows drivers to get notified when user-space writes to 
> +/sys/power/request_state to indicate that the user visible sleep state should 
> +change. A level controls what order the handlers are called in. Suspend 
> +handlers are called in low to high level order, resume handlers are called in 
> +the opposite order. 

I don't really understand this description, sorry.

In particular, what values can be written to /sys/power/request_state, what
their meaning is and what's supposed to happen if someone writes one of these
values to this file?

> +
> +Four levels are defined:
> +EARLY_SUSPEND_LEVEL_BLANK_SCREEN:
> +  On suspend the screen should be turned off but the framebuffer must still be
> +  accessible. On resume the screen can be turned back on.

What exactly is the meaning of "suspend" here?

> +EARLY_SUSPEND_LEVEL_STOP_DRAWING:
> +  On suspend this level notifies user-space that it should stop accessing the 
> +  framebuffer and it waits for it to complete. On resume it notifies user-space 
> +  that it should resume screen access.
> +  Two methods are provided, console switch or a sysfs interface.

How exactly is the notification supposed to happen?

> +EARLY_SUSPEND_LEVEL_DISABLE_FB:
> +  Turn off the framebuffer on suspend and back on on resume.
> +
> +EARLY_SUSPEND_LEVEL_STOP_INPUT:
> +  On suspend turn off input devices that are not capable of wakeup or where
> +  wakeup is disabled. On resume turn the same devices back on.

This always happens during suspend-resume.  How is this different from the
usual suspend-resume behaviour?

> diff --git a/include/linux/earlysuspend.h b/include/linux/earlysuspend.h
> new file mode 100755
> index 0000000..1587a3f
> --- /dev/null
> +++ b/include/linux/earlysuspend.h
> @@ -0,0 +1,55 @@
> +/* include/linux/earlysuspend.h
> + *
> + * Copyright (C) 2007-2008 Google, Inc.
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#ifndef _LINUX_EARLYSUSPEND_H
> +#define _LINUX_EARLYSUSPEND_H
> +
> +#include <linux/list.h>
> +
> +/* The early_suspend structure defines suspend and resume hooks to be called
> + * when the user visible sleep state of the system changes, and a level to
> + * control the order. They can be used to turn off the screen and input
> + * devices that are not used for wakeup.
> + * Suspend handlers are called in low to high level order, resume handlers are
> + * called in the opposite order. If, when calling register_early_suspend,
> + * the suspend handlers have already been called without a matching call to the
> + * resume handlers, the suspend handler will be called directly from
> + * register_early_suspend. This direct call can violate the normal level order.
> + */
> +enum {
> +	EARLY_SUSPEND_LEVEL_BLANK_SCREEN = 50,
> +	EARLY_SUSPEND_LEVEL_STOP_INPUT = 75,
> +	EARLY_SUSPEND_LEVEL_STOP_DRAWING = 100,
> +	EARLY_SUSPEND_LEVEL_DISABLE_FB = 150,
> +};
> +struct early_suspend {
> +#ifdef CONFIG_HAS_EARLYSUSPEND
> +	struct list_head link;
> +	int level;
> +	void (*suspend)(struct early_suspend *h);
> +	void (*resume)(struct early_suspend *h);
> +#endif
> +};

Does this mean addional suspend-resume callbacks for device drivers?

If so, how are they different from the "standard" suspend-resume callbacks?

Also, what about bus types that carry out some suspend-resume operations
for their devices, like PCI?  Your early callbacks don't seem to take the
bus type part into account.

> +#ifdef CONFIG_HAS_EARLYSUSPEND
> +void register_early_suspend(struct early_suspend *handler);
> +void unregister_early_suspend(struct early_suspend *handler);
> +#else
> +#define register_early_suspend(handler) do { } while (0)
> +#define unregister_early_suspend(handler) do { } while (0)
> +#endif
> +
> +#endif
> +

My understanding of the 'early suspend' idea is that it is a mechanism allowing
us to place some devices selectively into low power states before the actual
suspend happens.  However, this is exactly the same as runtime power
management on demand, with an interface allowing user space to put devices into
low power states.

Now, in my opinion, runtime power management should be implemented on the
bus type level, since bus types differ from each other by power management
requirements, mechanisms that can be used and hardware interfaces.

I have some prototype patches for PCI runtime PM in the works.  I didn't
intend to post them just yet, since I'm considering them as work in progress.
Still, I can do that if you think it would be useful.

Thanks,
Rafael


More information about the linux-pm mailing list