All of lore.kernel.org
 help / color / mirror / Atom feed
From: Adam Belay <abelay-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
To: Patrick Mochel
	<mochel-og82NyAXoxR0I81aPRRTmR2eb7JE58TQ@public.gmane.org>,
	Greg KH <greg-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org>,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-pm-qjLDD68F18O7TbgM5vRIOg@public.gmane.org
Subject: [RFC] Driver States
Date: Sun, 27 Mar 2005 17:42:47 -0500	[thread overview]
Message-ID: <1111963367.3503.152.camel@localhost.localdomain> (raw)

[-- 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 --]



WARNING: multiple messages have this Message-ID (diff)
From: Adam Belay <abelay@novell.com>
To: Patrick Mochel <mochel@digitalimplant.org>,
	Greg KH <greg@kroah.com>,
	linux-kernel@vger.kernel.org, linux-pm@lists.osdl.org
Subject: [RFC] Driver States
Date: Sun, 27 Mar 2005 17:42:47 -0500	[thread overview]
Message-ID: <1111963367.3503.152.camel@localhost.localdomain> (raw)

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



             reply	other threads:[~2005-03-27 22:42 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-03-27 22:42 Adam Belay [this message]
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
2005-03-30  5:57     ` Patrick Mochel
     [not found]     ` <Pine.LNX.4.50.0503292155120.26543-100000-x8k/2hhmB0w5etPau2IXcQ@public.gmane.org>
2005-03-30 22:45       ` Adam Belay
2005-03-30 22:45         ` Adam Belay
2005-04-05  9:24         ` Pavel Machek
2005-04-05  9:24           ` [linux-pm] " Pavel Machek
2005-04-06 19:51           ` Adam Belay
2005-04-06 19:51             ` [linux-pm] " Adam Belay
2005-04-08 10:31             ` Pavel Machek
2005-04-08 10:31               ` [linux-pm] " Pavel Machek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1111963367.3503.152.camel@localhost.localdomain \
    --to=abelay-et1tbqhtxzrqt0dzr+alfa@public.gmane.org \
    --cc=greg-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org \
    --cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-pm-qjLDD68F18O7TbgM5vRIOg@public.gmane.org \
    --cc=mochel-og82NyAXoxR0I81aPRRTmR2eb7JE58TQ@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.