Subject: PNP power management API for drivers
To: None <tech-kern@netbsd.org>
From: Joerg Sonnenberger <joerg@britannica.bec.de>
List: tech-kern
Date: 10/05/2007 22:08:09
--jI8keyz6grp/JLjh
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi all,
attached text is a proposal for the power management API for drivers. It
is not complete and not final. It is based on what our drivers currently
do and to a certain degree what I expect them to need in the short term.
Please keep that in mind when asking about extensions. I want to keep
the interface simple. It is easier to extend it later then to dumb it
down.

Joerg

--jI8keyz6grp/JLjh
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="PNP-API.txt"

Proposal for the second iteration of the PNP device API
-------------------------------------------------------

Part 1: device-specific part

bool pnp_device_register(dev_t, bool (*suspend)(dev_t),
    bool (*resume)(dev_t));
void pnp_device_deregister(dev_t);

This enables power management for a device. The two hooks are
responsible for saving and restoring the device state. If the device
class doesn't handle it, they should also put the device explicitly into
a quiescence state.

This functions also trigger registration for the bus part and the
deregistration for bus and device class.


Part 2: bus-specific part

bool pnp_bus_register(dev_t self, bool (*register_child)(dev_t, dev_t),
    void (*deregister_child)(dev_t, dev_t));

void *device_pnp_bus_private(dev_t);
bool device_pnp_bus_suspend(dev_t);
bool device_pnp_bus_resume(dev_t);

void device_pnp_bus_register(dev_t, void *, bool (*suspend)(dev_t),
    bool (*resume)(dev_t))
void device_pnp_bus_deregister(dev_t);

When a device registers the PNP handler and the parent has registerd
itself as bus handler the register_child and deregister_child callbacks
are called. The device_pnp_bus_register stores a reference to private
memory and the callbacks, deregister resets them. It is an explicit
error to call device_pnp_bus_private without calling bus_register first.
Caling bus_suspend and bus_resume is ok, NULL is handled as nop.


Part 3: device class

bool pnp_CLASS_register(dev_t, ...);

void device_pnp_class_register(dev_t, void *, bool (*suspend)(dev_t),
    bool (*resume)(dev_t), void (*deregister)(dev_t));
void device_pnp_class_deregister(dev_t);

The class-specific PNP handlers are called explicitly with the necessary
support data. For example, the network device drivers pass in the ifnet
pointer.

Depending on the class and the policy, this can directly call the resume
functions and should be called as last step in the initialisation of the
driver.

Call graphs:
attach:
	pnp_device_register
		(parent) child register
	[pnp_bus_register]
	[pnp_CLASS_register]

detach:
	pnp_device_register
		(parent) child deregister
		device_pnp_class_deregister
			(class) deregister

suspend:
	(class) suspend
	(device) suspend
	(parent) child suspend

resume:
	(parent) child resume
	(device) resume
	(class) resume


Other notes:

- The common PNP code keeps track of the device states, e.g. which of
each handlers are called.

- The bus handlers will be extended at a later point to distinguish
different levels of suspended (e.g. D1-D3hot, D3cold) and device
properties will be used to modify the policy.

--jI8keyz6grp/JLjh--