Dynamic power management may require devices and drivers to transition between various physical and logical states. I would like to start a discussion on how these might be defined at the bus, driver, and class levels. Bus Level ========= At the bus level, there are two state attributes, power and enable/disable. Enable/disable may mean different things on different buses, but they generally refer to resource decoding. A device can only be enabled during a non-off power state. A possible API: struct bus_type { char * name; struct subsystem subsys; struct kset drivers; struct kset devices; struct bus_attribute * bus_attrs; struct device_attribute * dev_attrs; struct driver_attribute * drv_attrs; int (*match)(struct device * dev, struct device_driver * drv); int (*hotplug) (struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size); int (*suspend)(struct device * dev, pm_message_t state); int (*resume)(struct device * dev); int (*enable)(struct device * dev); int (*disable)(struct device * dev); }; Driver Level ============ At the driver level there are two areas of interest, physical and logical state. There is an additional concern of transitioning between these states multiple times. Because a driver acts as a bridge between physical and logical components, I think separating these steps seems natural. A possible API: struct device_driver { char * name; struct bus_type * bus; struct semaphore unload_sem; struct kobject kobj; struct list_head devices; struct module * owner; int (*attach) (struct device * dev); int (*start) (struct device * dev); int (*open) (struct device * dev); int (*close) (struct device * dev); void (*stop) (struct device * dev); void (*detach) (struct device * dev); void (*shutdown) (struct device * dev); int (*suspend) (struct device * dev, u32 state, u32 level); int (*resume) (struct device * dev, u32 level); }; *attach - allocates data structures, creates sysfs entries, prepares driver to handle the hardware. *start - Sets up device resources and configures the hardware. Loads firmware, etc. (physical) *open - engages the hardware, and makes it usable by the class device. (logical and physical) *close - disengages the hardware, and stops class level access (logical and physical) *stop - physically disables the hardware (physical) *detach - tears down the driver and releases it from the "struct device" The idea behind *attach and *detach is to move code that would only need to be called once out of *probe and *remove. A table could be defined that indicates what should be called for each power level transition. *suspend and *resume could handle any extra steps (ex. saving state). As an example, *start and *stop may only be called when power is going to be lost entirely. Additional states are class specific and would only be used after *open is called. Class Level =========== At the class level, we could have a simple start/stop mechanism. A possible API: struct class_device { struct list_head node; struct kobject kobj; struct class * class; struct device * dev; void * class_data; char class_id[BUS_ID_SIZE]; int (*attach) (struct device * dev); int (*start) (struct device * dev); void (*stop) (struct device * dev); void (*detach) (struct device * dev); }; *attach - allocates data structures, creates sysfs entries, prepares class to handle the device. *start - start the logical class device, accept userspace interaction *stop - stop the logical class device, deny userspace interaction *detach - tear down the class driver's bindings with this class device These are just rough ideas. I look forward to any comments or alternative approaches. Thanks, Adam