public inbox for linux-pm@vger.kernel.org
 help / color / mirror / Atom feed
* [RFC] Power Management API (rev 1)
@ 2005-04-17 21:35 Adam Belay
  2005-04-20 15:59 ` Pavel Machek
  0 siblings, 1 reply; 4+ messages in thread
From: Adam Belay @ 2005-04-17 21:35 UTC (permalink / raw)
  To: Linux-pm mailing list

[-- Attachment #1: Type: text/plain, Size: 8468 bytes --]


Hi all,

I've made some revisions to my new power management API.  I would
appreciate any suggestions or comments.

Thanks,
Adam


Summary:

"*update" is called during a change in system state.  It will change the
values of the minimum and maximum state (and anything else).  The PM
subsystem will then iterate the tree and mark each state that is
available.

I've attempted to add some methods to "struct power_policy".

The system state flags have been changed.  Any comments?

"struct power_resource" may need to support more than on and off.  Maybe
not?


Changes:

(me)
- added "available" to power states
- added concept of min and max power state in power devices
- fixed a few typos
- revised device state flags
- style changes and cleanups
- added some real content to "struct power_policy"
- system state flag changes
- added "pm_change_system_state"
- added "pm_current_system_state"
- added kobject to power resources

Suggested by David Brownell:
- revised system state flags
- pass actual system state structure instead of int



/*
 *  pm.h - the Power Management Interface
 *
 */

#ifndef _LINUX_PM_H
#define _LINUX_PM_H

#ifdef __KERNEL__

#include <linux/config.h>
#include <linux/list.h>
#include <asm/atomic.h>

struct device;

struct power_resource;
struct power_driver;
struct power_policy;
struct power_device;


/*
 * Global System Power States
 *
 * Reflect the status of the overall system.
 */

struct system_power_state {
	unsigned int state;
	unsigned int flags;

	struct list_head state_list;
};

extern int pm_register_system_state(struct system_power_state *state);
extern void pm_unregister_system_state(struct system_power_state *state);

extern struct system_power_state *
pm_get_system_state_data(unsigned int state);

extern struct system_power_state * pm_current_system_state(void);
extern int pm_change_system_state(struct system_power_state *new);

/* System State Flags */

/* a generalization of the state ---> */
/* system is usable and active */
#define PM_SYSTEM_STATE_RUNNING		0x00000001
/* system is not usable, but still mostly running */ 
#define PM_SYSTEM_STATE_SLEEPING	0x00000002
/* system not running, but some context is being retained */
#define PM_SYSTEM_STATE_SUSPENDED	0x00000004
/* system not running, power is not being used to retain context */
#define PM_SYSTEM_STATE_OFF		0x00000008
/* no wake devices, no power _at_ _all_, completely off */
#define PM_SYSTEM_STATE_NOPOWER		0x00000010

/* information about where context has been saved ---> */
#define PM_SYSTEM_CONTEXT_RAM		0x00000100
#define PM_SYSTEM_CONTEXT_NONVOLATILE	0x00000200

/* hints for the policy intentions of the state --->
 * These hints are optional and describe the general intentions of the
 * platform's designer.  The actual policy may be a combination of these hints
 * and the user's preferences */
/* no, or very little, power management */
#define PM_SYSTEM_POLICY_MAX_PERFORMACE	0x00001000
/* favor performance, but save power where it won't interrupt the user */
#define PM_SYSTEM_POLICY_ADAPTIVE	0x00002000
/* save as much power as possible while maintaining necessary functionality */
#define PM_SYSTEM_POLICY_MAX_SAVINGS	0x00004000
/* turn off everything non-critical, we're almost out of power */
#define PM_SYSTEM_POLICY_EMERGENCY	0x00008000

/* PM features supported at the state ---> */
/* the state capable of runtime power management */
#define PM_SYSTEM_FEATURE_RUNTIME	0x00010000
/* the state can be waken to a higher state */
#define PM_SYSTEM_FEATURE_WAKE		0x00020000

/* the policy manager will really damage things if it refuses or delays our requests */
#define PM_SYSTEM_FLAG_NOPOLICY		0x10000000


/*
 * Power Resources
 *
 * Power resources represent the physical requirements of "power devices".
 * (e.g. clocks, power planes, etc.)  Only define a power resource if your
 * PM protocol allows specific control of the resource.  If not, it can be
 * a characteristic only represented by the power state.
 */

struct power_resource_ops {
	unsigned int (*get) (struct power_resource *power);
	int (*update) (struct power_resource *power,
		       struct system_power_state *state);
	int (*on) (struct power_resource *power);
	int (*off) (struct power_resource *power);
};

struct power_resource {
	char * name;
	struct kobject kobj;

	int enabled;
	struct list_head deps;
	struct power_resource_ops *ops;

	struct power_device *domain;
	unsigned int max_domain_state;
	unsigned int max_system_state;
};

extern int pm_register_resource(struct power_resource *res);
extern void pm_unregister_resource(struct power_resource *res);

extern int pm_enable_resource(struct power_resource *res);
extern int pm_disable_resource(struct power_resource *res);
extern int pm_available_resource(struct power_resource *res);


/*
 * Power States
 *
 * These are used to define device-specific power states.
 */

struct power_state {
	char * name;
	int available;

	unsigned int state;
	unsigned int flags;
	unsigned int power_consumption; /* in mW */
	unsigned int max_domain_state;

	struct list_head state_list;
	struct list_head deps;
};

extern void pm_add_state(struct power_device *dev, struct power_state *state);
extern void pm_remove_state(struct power_state *state);

/* power state flags --->
 * as always, these are optional */

/* device actually works */
#define PM_DEVICE_STATE_USABLE			0x00000001
/* device is still mostly on, but saving some power and not usable */
#define PM_DEVICE_STATE_SLEEPING		0x00000002
/* device is mostly off, and most context is lost */
#define PM_DEVICE_STATE_SUSPENDED		0x00000004
/* device is totally off */
#define PM_DEVICE_STATE_OFF			0x00000008

#define PM_DEVICE_STATE_MASK			0xffff0000 /* bus-specific values */


struct power_dependency {
	struct power_resource * res;
	struct list_head state_list;
	struct list_head device_list;
};

extern struct power_dependency * 
pm_alloc_dependency(struct power_resource * res);
extern void pm_add_dependency(struct power_state * state,
			      struct power_dependency * dep);
extern void pm_remove_dependency(struct power_dependency * dep);


/*
 * Power Devices
 *
 * Power devices are the core building block of a system's power management
 * topology.  They may require power resources, but the primary dependency
 * relationships are represented by a tree of "power devices".  This tree
 * is based on a power domain (or container) model.
 */

struct power_device {
	char			* name;
	struct kobject		kobj;

	unsigned int		state;
	unsigned int		min_state;
	unsigned int		max_state;
	struct list_head	states;

	struct list_head	child_list;
	struct list_head	children;
	struct power_device	* domain;

	struct device		* dev;

	struct power_driver	* controller;
	struct power_policy	* policy;

	void 			* policy_data;

	int			wake_enabled;
	unsigned int		max_wake_state;
	struct list_head	wake_deps;
};

extern int pm_register_device(struct power_device *power);
extern void pm_unregister_device(struct power_device *power);

extern unsigned int pm_get_state(struct power_device *power);
extern int pm_set_state(struct power_device *power, unsigned int state);
extern int pm_available_state(struct power_device *power, unsigned int state,
			      unsigned int system_state);

extern struct power_state *
pm_get_state_data(struct power_device *power, unsigned int state);
extern int pm_add_wake_dependency(struct power_device *power,
				  struct power_dependency *dep);


/*
 * Power Drivers
 *
 * Power drivers provide information about a power device's current state and
 * mechanisms for changing that state.
 */

struct power_driver {
	char * name;

	int  (*attach)	(struct power_device * power);
	void (*detach)	(struct power_device * power);
	int  (*update)	(struct power_device * power,
			 struct system_power_state *state);
	int  (*get)	(struct power_device * power, unsigned int state);
	int  (*set)	(struct power_device * power, unsigned int state);
};

extern int pm_bind_power_driver(struct power_device *power,
				struct power_driver *drv);
extern void pm_unbind_power_driver(struct power_device *power);


/*
 * Power Management Policy
 *
 * Makes power management related decisions on a per "power device" basis.
 */

struct power_policy {
	(*requirements_changed)	(struct power_device * dev,
				 unsigned int new_max_state);

	(*prepare_transition)	(struct power_device * dev,
				 struct system_power_state * new);
	(*apply_transition)	(struct power_device * dev,
				 struct system_power_state * new);
};




[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC] Power Management API (rev 1)
  2005-04-17 21:35 [RFC] Power Management API (rev 1) Adam Belay
@ 2005-04-20 15:59 ` Pavel Machek
  2005-04-23  7:23   ` Adam Belay
  0 siblings, 1 reply; 4+ messages in thread
From: Pavel Machek @ 2005-04-20 15:59 UTC (permalink / raw)
  To: Adam Belay; +Cc: Linux-pm mailing list

[-- Attachment #1: Type: text/plain, Size: 2036 bytes --]

Hi!

> I've made some revisions to my new power management API.  I would
> appreciate any suggestions or comments.


> /*
>  *  pm.h - the Power Management Interface
>  *
>  */
> 
> #ifndef _LINUX_PM_H
> #define _LINUX_PM_H
> 
> #ifdef __KERNEL__
> 
> #include <linux/config.h>
> #include <linux/list.h>
> #include <asm/atomic.h>
> 
> struct device;
> 
> struct power_resource;
> struct power_driver;
> struct power_policy;
> struct power_device;
> 
> 
> /*
>  * Global System Power States
>  *
>  * Reflect the status of the overall system.
>  */
> 
> struct system_power_state {
> 	unsigned int state;

We already have int system_state... How is this different?

Please move the defines near here, and preferably add type-checking
for sparse.

> 	unsigned int flags;
> 
> 	struct list_head state_list;
> };
> 
> extern int pm_register_system_state(struct system_power_state *state);
> extern void pm_unregister_system_state(struct system_power_state *state);
> 
> extern struct system_power_state *
> pm_get_system_state_data(unsigned int state);

Having "unsigned int state" is asking for trouble.

> /*
>  * Power States
>  *
>  * These are used to define device-specific power states.
>  */
> 
> struct power_state {
> 	char * name;
> 	int available;
> 
> 	unsigned int state;
> 	unsigned int flags;

Are they same type as system_power_state.state? This should be clear,
and type-checked by sparse. Otherwise people will get it wrong.


> /*
>  * Power Devices
>  *
>  * Power devices are the core building block of a system's power management
>  * topology.  They may require power resources, but the primary dependency
>  * relationships are represented by a tree of "power devices".  This tree
>  * is based on a power domain (or container) model.
>  */
> 
> struct power_device {
> 	char			* name;
> 	struct kobject		kobj;
> 
> 	unsigned int		state;
> 	unsigned int		min_state;
> 	unsigned int		max_state;

Third "state"... Are they same type? Different?

							Pavel
-- 
Boycott Kodak -- for their patent abuse against Java.

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC] Power Management API (rev 1)
  2005-04-20 15:59 ` Pavel Machek
@ 2005-04-23  7:23   ` Adam Belay
  2005-04-26  3:04     ` Nigel Cunningham
  0 siblings, 1 reply; 4+ messages in thread
From: Adam Belay @ 2005-04-23  7:23 UTC (permalink / raw)
  To: Pavel Machek; +Cc: Adam Belay, Linux-pm mailing list

[-- Attachment #1: Type: text/plain, Size: 502 bytes --]

On Wed, Apr 20, 2005 at 05:59:56PM +0200, Pavel Machek wrote:
-->snip
> 
> We already have int system_state... How is this different?
> 
-->snip
> 
> Having "unsigned int state" is asking for trouble.
> 
-->snip
> 
> Are they same type as system_power_state.state? This should be clear,
> and type-checked by sparse. Otherwise people will get it wrong.
> 
> 

Hi Pavel,

I appreciate the suggestions.  I'm currently making some revisions.  I'll
clarify things further once they're ready.

Thanks,
Adam

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC] Power Management API (rev 1)
  2005-04-23  7:23   ` Adam Belay
@ 2005-04-26  3:04     ` Nigel Cunningham
  0 siblings, 0 replies; 4+ messages in thread
From: Nigel Cunningham @ 2005-04-26  3:04 UTC (permalink / raw)
  To: Adam Belay; +Cc: Adam Belay, Linux-pm mailing list, Pavel Machek

[-- Attachment #1: Type: text/plain, Size: 442 bytes --]

Hi Adam.

Thanks for all of your work so far. It looks good. Please accept my
apologies for not giving feedback yet - I've been drowning in other
things for a few weeks. I'll eagerly await your next revision.

Regards,

Nigel
-- 
Nigel Cunningham
Software Engineer, Canberra, Australia
http://www.cyclades.com
Bus: +61 (2) 6291 9554; Hme: +61 (2) 6292 8028;  Mob: +61 (417) 100 574

Maintainer of Suspend2 Kernel Patches http://suspend2.net


[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2005-04-26  3:04 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-04-17 21:35 [RFC] Power Management API (rev 1) Adam Belay
2005-04-20 15:59 ` Pavel Machek
2005-04-23  7:23   ` Adam Belay
2005-04-26  3:04     ` Nigel Cunningham

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox