Skip to contentSkip to conversation

Some Thoughts on Device Power Management

RFC Adam Belay 3 participants 4 messages Oct 5, 2005 – Oct 6, 2005

lore
Share & tools
lore

Adam Belay

author
#0 lore raw

Hi All,

I've been considering strategies for improving runtime power management, selective suspends, and device power management in general. Here are some of my ideas. I would appreciate any comments or suggestions.

suspend() and resume() need to be improved.
===========================================

- the current logical state should be clear and available (e.g. it's difficult to determine when to resume from FREEZE or SUSPEND.)

- I'm not sure what's currently in pm_message_t, but it would nice if the driver could be provided a reason for the state change request. (e.g. userspace requested this change, the system is being suspended, emergency power accounting issue, etc.)

- We need to specify global system states. suspend/resume should be aware of the current global system state and the target global system state.

- it should be possible to call suspend() more than once. (e.g. FREEZE followed by SUSPEND) No action should be taken if the current state is equal to the requested state.

- resume should always take us back to the ON state.

We need to add start() and stop() to "struct device_driver".
============================================================
start() would enable the logical functionality of the device stop() would disable the logical functionality of the device

ACPI has had this feature in its driver model for a while now. It seems clear to me that the driver core should provide this functionality for the following reason:

A device can either be operational or disabled. At least three different entry points are concerned with controlling this logical state.

1.) suspend/resume
2.) probe/remove
3.) driver-specific runtime power management

In addition some drivers will also need to start/stop devices from the following entry points:

4.) parent change required because of child logical state changes 5.) device class requests (e.g. ifconfig eth0 down)

It seems like it would be useful for the driver core to track the current logical device state. We could even create an iterative algorithm that "starts" parents up the tree when a child is started. In general, adding start() and stop() would allow us to centralize logical state transition code and simplify drivers.

It should be easy for device drivers to manipulate physical power states.
=========================================================================

We can use an API like the following to represent and manipulate power resources.

struct pm_state {
char *name; /* a human-readable name */
unsigned int state; /* an index value */
unsigned int state_type; /* a PMSTATE_TYPE */
};

enum {
PMSTATE_TYPE_ON, /* functional, most current, no latency */
PMSTATE_TYPE_STANDBY, /* not functional, less current, more latency */
PMSTATE_TYPE_OFF, /* not functional, least current, most latency */
};

struct pm_device {
struct kobject kobj;
struct semaphore sem; /* protects power state etc. */
struct pm_interface *intf; /* specifies the type of pm device */
struct pm_device *parent; /* the power container */
struct device *dev; /* the physical device if any */

struct pm_state *state; /* the active power state */

char pm_id[PM_ID_SIZE]; /* kobject name */

void (*release) (struct device * dev);
};

struct pm_interface {
const char *name; /* a unique name for this PM protocol */

struct pm_attribute *pm_attrs; /* default group of attributes */

int (*enter_state) (struct pm_device *dev,
struct pm_state *state); /* enters a given state */
};

extern int pm_register_device(struct pm_device *dev);
extern void pm_unregister_device(struct pm_device *dev); extern struct pm_state * __pm_get_state(struct pm_device *dev); extern int __pm_set_state(struct pm_device *dev, struct pm_state *state); extern int pm_set_state(struct pm_device *dev, struct pm_state *state);

extern struct pm_device * pm_get_device(struct pm_device *dev); extern void pm_put_device(struct pm_device *dev);

In this case we would create objects in sysfs under a power subsystem. Devices could then symlink to these objects.

PCI power management needs to be overhauled.
============================================

- pci_save_state() isn't necessary. This information is already contained in "struct pci_dev".

- pci_restore_state() should be more careful and not write to read-only registers.

- We may need logic to enable ASPM when using PCI express hardware.

- PCI Bus power management isn't supported at all.

- PCI could attach to the power object model proposed above.

- PCI wake support needs to be usable for runtime power management.

ACPI needs better driver model integration.
===========================================

- ACPI devices have power states too. We need to show them.

- ACPI power resources could be represented with the power object code.

Thanks,
Adam

#1 lore raw
Quoted 6 lines · Adam Belay

Hi All,

I've been considering strategies for improving runtime power management, selective suspends, and device power management in general. Here are some of my ideas. I would appreciate any comments or suggestions.

If you want to improve power management, write some code, not "yet another useless roadmap". Thanks.
Pavel

PS: Alan wrote some nice pieces for runtime power management, what about helping him?

Signature · 1 line
if you have sharp zaurus hardware you don't need... you know my address
author
#2 lore raw
Quoted 11 lines · Pavel Machek
Quoted 6 lines · Adam Belay

Hi All,

I've been considering strategies for improving runtime power management, selective suspends, and device power management in general. Here are some of my ideas. I would appreciate any comments or suggestions.

If you want to improve power management, write some code, not "yet another useless roadmap". Thanks.
Pavel

Hi Pavel,

This document was more than a roadmap, it makes references to specific implementation strategies. Nonetheless, you do bring up a good point. I actually do have some code for many of the ideas I mentioned. I'm hoping to have a functional example soon.

Thanks,
Adam

Quoted 3 lines

PS: Alan wrote some nice pieces for runtime power management, what about helping him?

I agree, a notion of power states is a step forward for runtime power management. I need to look at Alan's code more carefully, but, as I understand, it's a little different from my proposal.

My intention was to seperate logical driver states (a given level of functionality) and physical power states. Device drivers are responsible for manipulating physical device states, but the driver model manages logical states and their dependencies.

I think comparing these strategies would be a useful discussion.

#3 lore raw
In reply to Adam Belay
Quoted 19 lines · Adam Belay

We need to add start() and stop() to "struct device_driver".
============================================================
start() would enable the logical functionality of the device stop() would disable the logical functionality of the device

ACPI has had this feature in its driver model for a while now. It seems clear to me that the driver core should provide this functionality for the following reason:

A device can either be operational or disabled. At least three different entry points are concerned with controlling this logical state.

1.) suspend/resume
2.) probe/remove
3.) driver-specific runtime power management

In addition some drivers will also need to start/stop devices from the following entry points:

Quoted 8 lines

4.) parent change required because of child logical state changes 5.) device class requests (e.g. ifconfig eth0 down)

It seems like it would be useful for the driver core to track the current logical device state. We could even create an iterative algorithm that "starts" parents up the tree when a child is started. In general, adding start() and stop() would allow us to centralize logical state transition code and simplify drivers.

I don't see the need for this. A few types of devices, like network interfaces, can benefit from the On/Off distinction. Most devices/drivers can't. Either they're always on, or else their off state is the same as their suspended or unbound state.

Quoted 11 lines

It should be easy for device drivers to manipulate physical power states.
=========================================================================

We can use an API like the following to represent and manipulate power resources.

struct pm_state {
char *name; /* a human-readable name */
unsigned int state; /* an index value */
unsigned int state_type; /* a PMSTATE_TYPE */
};

The name is enough. There's no need for state or state_type.

Quoted 5 lines

enum {
PMSTATE_TYPE_ON, /* functional, most current, no latency */
PMSTATE_TYPE_STANDBY, /* not functional, less current, more latency */
PMSTATE_TYPE_OFF, /* not functional, least current, most latency */
};

This isn't needed (who would use it?) and it's incomplete. For instance, PCI has two states between ON and OFF.

Quoted 7 lines

struct pm_device {
struct kobject kobj;
struct semaphore sem; /* protects power state etc. */
struct pm_interface *intf; /* specifies the type of pm device */
struct pm_device *parent; /* the power container */
struct device *dev; /* the physical device if any */

Quoted 6 lines

struct pm_state *state; /* the active power state */

char pm_id[PM_ID_SIZE]; /* kobject name */

void (*release) (struct device * dev);
};

Who needs a new pm_device? Would there ever be a struct pm_device that wasn't part of a struct device (or maybe a class_device)?

Quoted 15 lines

struct pm_interface {
const char *name; /* a unique name for this PM protocol */

struct pm_attribute *pm_attrs; /* default group of attributes */

int (*enter_state) (struct pm_device *dev,
struct pm_state *state); /* enters a given state */
};

extern int pm_register_device(struct pm_device *dev);
extern void pm_unregister_device(struct pm_device *dev); extern struct pm_state * __pm_get_state(struct pm_device *dev); extern int __pm_set_state(struct pm_device *dev, struct pm_state *state); extern int pm_set_state(struct pm_device *dev, struct pm_state *state);

Quoted 5 lines

extern struct pm_device * pm_get_device(struct pm_device *dev); extern void pm_put_device(struct pm_device *dev);

In this case we would create objects in sysfs under a power subsystem. Devices could then symlink to these objects.

Ditto for the rest of this. It's a lot of overhead that would serve no useful purpose.

Quoted 9 lines

PCI power management needs to be overhauled.
============================================

- pci_save_state() isn't necessary. This information is already contained in "struct pci_dev".

- pci_restore_state() should be more careful and not write to read-only registers.

Quoted 7 lines

- We may need logic to enable ASPM when using PCI express hardware.

- PCI Bus power management isn't supported at all.

- PCI could attach to the power object model proposed above.

- PCI wake support needs to be usable for runtime power management.

This is a separate issue, more properly discussed on a PCI mailing list.

Quoted 6 lines

ACPI needs better driver model integration.
===========================================

- ACPI devices have power states too. We need to show them.

- ACPI power resources could be represented with the power object code.

What's the difference between an ACPI device and a regular device?

Alan Stern