public inbox for linux-pm@vger.kernel.org
 help / color / mirror / Atom feed
* [RFC] Driver States
@ 2005-03-27 22:42 Adam Belay
       [not found] ` <1111963367.3503.152.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
  0 siblings, 1 reply; 10+ messages in thread
From: Adam Belay @ 2005-03-27 22:42 UTC (permalink / raw)
  To: Patrick Mochel, Greg KH, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-pm-qjLDD68F18O7TbgM5vRIOg

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

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



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



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

end of thread, other threads:[~2005-04-08 10:31 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-03-27 22:42 [RFC] Driver States Adam Belay
     [not found] ` <1111963367.3503.152.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2005-03-28 16:29   ` Jordan Crouse
     [not found]     ` <20050328092925.2c2736de-aftB2sG12IhaqnLngUycEA@public.gmane.org>
2005-04-01  4:01       ` David Brownell
2005-03-28 17:20   ` apm_console_blank() Jordan Crouse
     [not found]     ` <20050328102035.5fcd9a61-aftB2sG12IhaqnLngUycEA@public.gmane.org>
2005-03-29 18:51       ` apm_console_blank() Pavel Machek
2005-03-30  5:57   ` [RFC] Driver States Patrick Mochel
     [not found]     ` <Pine.LNX.4.50.0503292155120.26543-100000-x8k/2hhmB0w5etPau2IXcQ@public.gmane.org>
2005-03-30 22:45       ` Adam Belay
2005-04-05  9:24         ` Pavel Machek
2005-04-06 19:51           ` Adam Belay
2005-04-08 10:31             ` Pavel Machek

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