/Documentation/power/devices.txt
https://bitbucket.org/evzijst/gittest · Plain Text · 319 lines · 242 code · 77 blank · 0 comment · 0 complexity · c958c72c105ee0dcbd0f4da3ecf08786 MD5 · raw file
- Device Power Management
- Device power management encompasses two areas - the ability to save
- state and transition a device to a low-power state when the system is
- entering a low-power state; and the ability to transition a device to
- a low-power state while the system is running (and independently of
- any other power management activity).
- Methods
- The methods to suspend and resume devices reside in struct bus_type:
- struct bus_type {
- ...
- int (*suspend)(struct device * dev, pm_message_t state);
- int (*resume)(struct device * dev);
- };
- Each bus driver is responsible implementing these methods, translating
- the call into a bus-specific request and forwarding the call to the
- bus-specific drivers. For example, PCI drivers implement suspend() and
- resume() methods in struct pci_driver. The PCI core is simply
- responsible for translating the pointers to PCI-specific ones and
- calling the low-level driver.
- This is done to a) ease transition to the new power management methods
- and leverage the existing PM code in various bus drivers; b) allow
- buses to implement generic and default PM routines for devices, and c)
- make the flow of execution obvious to the reader.
- System Power Management
- When the system enters a low-power state, the device tree is walked in
- a depth-first fashion to transition each device into a low-power
- state. The ordering of the device tree is guaranteed by the order in
- which devices get registered - children are never registered before
- their ancestors, and devices are placed at the back of the list when
- registered. By walking the list in reverse order, we are guaranteed to
- suspend devices in the proper order.
- Devices are suspended once with interrupts enabled. Drivers are
- expected to stop I/O transactions, save device state, and place the
- device into a low-power state. Drivers may sleep, allocate memory,
- etc. at will.
- Some devices are broken and will inevitably have problems powering
- down or disabling themselves with interrupts enabled. For these
- special cases, they may return -EAGAIN. This will put the device on a
- list to be taken care of later. When interrupts are disabled, before
- we enter the low-power state, their drivers are called again to put
- their device to sleep.
- On resume, the devices that returned -EAGAIN will be called to power
- themselves back on with interrupts disabled. Once interrupts have been
- re-enabled, the rest of the drivers will be called to resume their
- devices. On resume, a driver is responsible for powering back on each
- device, restoring state, and re-enabling I/O transactions for that
- device.
- System devices follow a slightly different API, which can be found in
- include/linux/sysdev.h
- drivers/base/sys.c
- System devices will only be suspended with interrupts disabled, and
- after all other devices have been suspended. On resume, they will be
- resumed before any other devices, and also with interrupts disabled.
- Runtime Power Management
- Many devices are able to dynamically power down while the system is
- still running. This feature is useful for devices that are not being
- used, and can offer significant power savings on a running system.
- In each device's directory, there is a 'power' directory, which
- contains at least a 'state' file. Reading from this file displays what
- power state the device is currently in. Writing to this file initiates
- a transition to the specified power state, which must be a decimal in
- the range 1-3, inclusive; or 0 for 'On'.
- The PM core will call the ->suspend() method in the bus_type object
- that the device belongs to if the specified state is not 0, or
- ->resume() if it is.
- Nothing will happen if the specified state is the same state the
- device is currently in.
- If the device is already in a low-power state, and the specified state
- is another, but different, low-power state, the ->resume() method will
- first be called to power the device back on, then ->suspend() will be
- called again with the new state.
- The driver is responsible for saving the working state of the device
- and putting it into the low-power state specified. If this was
- successful, it returns 0, and the device's power_state field is
- updated.
- The driver must take care to know whether or not it is able to
- properly resume the device, including all step of reinitialization
- necessary. (This is the hardest part, and the one most protected by
- NDA'd documents).
- The driver must also take care not to suspend a device that is
- currently in use. It is their responsibility to provide their own
- exclusion mechanisms.
- The runtime power transition happens with interrupts enabled. If a
- device cannot support being powered down with interrupts, it may
- return -EAGAIN (as it would during a system power management
- transition), but it will _not_ be called again, and the transaction
- will fail.
- There is currently no way to know what states a device or driver
- supports a priori. This will change in the future.
- pm_message_t meaning
- pm_message_t has two fields. event ("major"), and flags. If driver
- does not know event code, it aborts the request, returning error. Some
- drivers may need to deal with special cases based on the actual type
- of suspend operation being done at the system level. This is why
- there are flags.
- Event codes are:
- ON -- no need to do anything except special cases like broken
- HW.
- # NOTIFICATION -- pretty much same as ON?
- FREEZE -- stop DMA and interrupts, and be prepared to reinit HW from
- scratch. That probably means stop accepting upstream requests, the
- actual policy of what to do with them beeing specific to a given
- driver. It's acceptable for a network driver to just drop packets
- while a block driver is expected to block the queue so no request is
- lost. (Use IDE as an example on how to do that). FREEZE requires no
- power state change, and it's expected for drivers to be able to
- quickly transition back to operating state.
- SUSPEND -- like FREEZE, but also put hardware into low-power state. If
- there's need to distinguish several levels of sleep, additional flag
- is probably best way to do that.
- Transitions are only from a resumed state to a suspended state, never
- between 2 suspended states. (ON -> FREEZE or ON -> SUSPEND can happen,
- FREEZE -> SUSPEND or SUSPEND -> FREEZE can not).
- All events are:
- [NOTE NOTE NOTE: If you are driver author, you should not care; you
- should only look at event, and ignore flags.]
- #Prepare for suspend -- userland is still running but we are going to
- #enter suspend state. This gives drivers chance to load firmware from
- #disk and store it in memory, or do other activities taht require
- #operating userland, ability to kmalloc GFP_KERNEL, etc... All of these
- #are forbiden once the suspend dance is started.. event = ON, flags =
- #PREPARE_TO_SUSPEND
- Apm standby -- prepare for APM event. Quiesce devices to make life
- easier for APM BIOS. event = FREEZE, flags = APM_STANDBY
- Apm suspend -- same as APM_STANDBY, but it we should probably avoid
- spinning down disks. event = FREEZE, flags = APM_SUSPEND
- System halt, reboot -- quiesce devices to make life easier for BIOS. event
- = FREEZE, flags = SYSTEM_HALT or SYSTEM_REBOOT
- System shutdown -- at least disks need to be spun down, or data may be
- lost. Quiesce devices, just to make life easier for BIOS. event =
- FREEZE, flags = SYSTEM_SHUTDOWN
- Kexec -- turn off DMAs and put hardware into some state where new
- kernel can take over. event = FREEZE, flags = KEXEC
- Powerdown at end of swsusp -- very similar to SYSTEM_SHUTDOWN, except wake
- may need to be enabled on some devices. This actually has at least 3
- subtypes, system can reboot, enter S4 and enter S5 at the end of
- swsusp. event = FREEZE, flags = SWSUSP and one of SYSTEM_REBOOT,
- SYSTEM_SHUTDOWN, SYSTEM_S4
- Suspend to ram -- put devices into low power state. event = SUSPEND,
- flags = SUSPEND_TO_RAM
- Freeze for swsusp snapshot -- stop DMA and interrupts. No need to put
- devices into low power mode, but you must be able to reinitialize
- device from scratch in resume method. This has two flavors, its done
- once on suspending kernel, once on resuming kernel. event = FREEZE,
- flags = DURING_SUSPEND or DURING_RESUME
- Device detach requested from /sys -- deinitialize device; proably same as
- SYSTEM_SHUTDOWN, I do not understand this one too much. probably event
- = FREEZE, flags = DEV_DETACH.
- #These are not really events sent:
- #
- #System fully on -- device is working normally; this is probably never
- #passed to suspend() method... event = ON, flags = 0
- #
- #Ready after resume -- userland is now running, again. Time to free any
- #memory you ate during prepare to suspend... event = ON, flags =
- #READY_AFTER_RESUME
- #
- Driver Detach Power Management
- The kernel now supports the ability to place a device in a low-power
- state when it is detached from its driver, which happens when its
- module is removed.
- Each device contains a 'detach_state' file in its sysfs directory
- which can be used to control this state. Reading from this file
- displays what the current detach state is set to. This is 0 (On) by
- default. A user may write a positive integer value to this file in the
- range of 1-4 inclusive.
- A value of 1-3 will indicate the device should be placed in that
- low-power state, which will cause ->suspend() to be called for that
- device. A value of 4 indicates that the device should be shutdown, so
- ->shutdown() will be called for that device.
- The driver is responsible for reinitializing the device when the
- module is re-inserted during it's ->probe() (or equivalent) method.
- The driver core will not call any extra functions when binding the
- device to the driver.
- pm_message_t meaning
- pm_message_t has two fields. event ("major"), and flags. If driver
- does not know event code, it aborts the request, returning error. Some
- drivers may need to deal with special cases based on the actual type
- of suspend operation being done at the system level. This is why
- there are flags.
- Event codes are:
- ON -- no need to do anything except special cases like broken
- HW.
- # NOTIFICATION -- pretty much same as ON?
- FREEZE -- stop DMA and interrupts, and be prepared to reinit HW from
- scratch. That probably means stop accepting upstream requests, the
- actual policy of what to do with them being specific to a given
- driver. It's acceptable for a network driver to just drop packets
- while a block driver is expected to block the queue so no request is
- lost. (Use IDE as an example on how to do that). FREEZE requires no
- power state change, and it's expected for drivers to be able to
- quickly transition back to operating state.
- SUSPEND -- like FREEZE, but also put hardware into low-power state. If
- there's need to distinguish several levels of sleep, additional flag
- is probably best way to do that.
- Transitions are only from a resumed state to a suspended state, never
- between 2 suspended states. (ON -> FREEZE or ON -> SUSPEND can happen,
- FREEZE -> SUSPEND or SUSPEND -> FREEZE can not).
- All events are:
- [NOTE NOTE NOTE: If you are driver author, you should not care; you
- should only look at event, and ignore flags.]
- #Prepare for suspend -- userland is still running but we are going to
- #enter suspend state. This gives drivers chance to load firmware from
- #disk and store it in memory, or do other activities taht require
- #operating userland, ability to kmalloc GFP_KERNEL, etc... All of these
- #are forbiden once the suspend dance is started.. event = ON, flags =
- #PREPARE_TO_SUSPEND
- Apm standby -- prepare for APM event. Quiesce devices to make life
- easier for APM BIOS. event = FREEZE, flags = APM_STANDBY
- Apm suspend -- same as APM_STANDBY, but it we should probably avoid
- spinning down disks. event = FREEZE, flags = APM_SUSPEND
- System halt, reboot -- quiesce devices to make life easier for BIOS. event
- = FREEZE, flags = SYSTEM_HALT or SYSTEM_REBOOT
- System shutdown -- at least disks need to be spun down, or data may be
- lost. Quiesce devices, just to make life easier for BIOS. event =
- FREEZE, flags = SYSTEM_SHUTDOWN
- Kexec -- turn off DMAs and put hardware into some state where new
- kernel can take over. event = FREEZE, flags = KEXEC
- Powerdown at end of swsusp -- very similar to SYSTEM_SHUTDOWN, except wake
- may need to be enabled on some devices. This actually has at least 3
- subtypes, system can reboot, enter S4 and enter S5 at the end of
- swsusp. event = FREEZE, flags = SWSUSP and one of SYSTEM_REBOOT,
- SYSTEM_SHUTDOWN, SYSTEM_S4
- Suspend to ram -- put devices into low power state. event = SUSPEND,
- flags = SUSPEND_TO_RAM
- Freeze for swsusp snapshot -- stop DMA and interrupts. No need to put
- devices into low power mode, but you must be able to reinitialize
- device from scratch in resume method. This has two flavors, its done
- once on suspending kernel, once on resuming kernel. event = FREEZE,
- flags = DURING_SUSPEND or DURING_RESUME
- Device detach requested from /sys -- deinitialize device; proably same as
- SYSTEM_SHUTDOWN, I do not understand this one too much. probably event
- = FREEZE, flags = DEV_DETACH.
- #These are not really events sent:
- #
- #System fully on -- device is working normally; this is probably never
- #passed to suspend() method... event = ON, flags = 0
- #
- #Ready after resume -- userland is now running, again. Time to free any
- #memory you ate during prepare to suspend... event = ON, flags =
- #READY_AFTER_RESUME
- #