1 Linux Power Management Support 2 3This document briefly describes how to use power management with your 4Linux system and how to add power management support to Linux drivers. 5 6APM or ACPI? 7------------ 8If you have a relatively recent x86 mobile, desktop, or server system, 9odds are it supports either Advanced Power Management (APM) or 10Advanced Configuration and Power Interface (ACPI). ACPI is the newer 11of the two technologies and puts power management in the hands of the 12operating system, allowing for more intelligent power management than 13is possible with BIOS controlled APM. 14 15The best way to determine which, if either, your system supports is to 16build a kernel with both ACPI and APM enabled (as of 2.3.x ACPI is 17enabled by default). If a working ACPI implementation is found, the 18ACPI driver will override and disable APM, otherwise the APM driver 19will be used. 20 21No, sorry, you cannot have both ACPI and APM enabled and running at 22once. Some people with broken ACPI or broken APM implementations 23would like to use both to get a full set of working features, but you 24simply cannot mix and match the two. Only one power management 25interface can be in control of the machine at once. Think about it.. 26 27User-space Daemons 28------------------ 29Both APM and ACPI rely on user-space daemons, apmd and acpid 30respectively, to be completely functional. Obtain both of these 31daemons from your Linux distribution or from the Internet (see below) 32and be sure that they are started sometime in the system boot process. 33Go ahead and start both. If ACPI or APM is not available on your 34system the associated daemon will exit gracefully. 35 36 apmd: http://worldvisions.ca/~apenwarr/apmd/ 37 acpid: http://acpid.sf.net/ 38 39Driver Interface -- OBSOLETE, DO NOT USE! 40----------------************************* 41 42Note: pm_register(), pm_access(), pm_dev_idle() and friends are 43obsolete. Please do not use them. Instead you should properly hook 44your driver into the driver model, and use its suspend()/resume() 45callbacks to do this kind of stuff. 46 47If you are writing a new driver or maintaining an old driver, it 48should include power management support. Without power management 49support, a single driver may prevent a system with power management 50capabilities from ever being able to suspend (safely). 51 52Overview: 531) Register each instance of a device with "pm_register" 542) Call "pm_access" before accessing the hardware. 55 (this will ensure that the hardware is awake and ready) 563) Your "pm_callback" is called before going into a 57 suspend state (ACPI D1-D3) or after resuming (ACPI D0) 58 from a suspend. 594) Call "pm_dev_idle" when the device is not being used 60 (optional but will improve device idle detection) 615) When unloaded, unregister the device with "pm_unregister" 62 63/* 64 * Description: Register a device with the power-management subsystem 65 * 66 * Parameters: 67 * type - device type (PCI device, system device, ...) 68 * id - instance number or unique identifier 69 * cback - request handler callback (suspend, resume, ...) 70 * 71 * Returns: Registered PM device or NULL on error 72 * 73 * Examples: 74 * dev = pm_register(PM_SYS_DEV, PM_SYS_VGA, vga_callback); 75 * 76 * struct pci_dev *pci_dev = pci_find_dev(...); 77 * dev = pm_register(PM_PCI_DEV, PM_PCI_ID(pci_dev), callback); 78 */ 79struct pm_dev *pm_register(pm_dev_t type, unsigned long id, pm_callback cback); 80 81/* 82 * Description: Unregister a device with the power management subsystem 83 * 84 * Parameters: 85 * dev - PM device previously returned from pm_register 86 */ 87void pm_unregister(struct pm_dev *dev); 88 89/* 90 * Description: Unregister all devices with a matching callback function 91 * 92 * Parameters: 93 * cback - previously registered request callback 94 * 95 * Notes: Provided for easier porting from old APM interface 96 */ 97void pm_unregister_all(pm_callback cback); 98 99/* 100 * Power management request callback 101 * 102 * Parameters: 103 * dev - PM device previously returned from pm_register 104 * rqst - request type 105 * data - data, if any, associated with the request 106 * 107 * Returns: 0 if the request is successful 108 * EINVAL if the request is not supported 109 * EBUSY if the device is now busy and cannot handle the request 110 * ENOMEM if the device was unable to handle the request due to memory 111 * 112 * Details: The device request callback will be called before the 113 * device/system enters a suspend state (ACPI D1-D3) or 114 * or after the device/system resumes from suspend (ACPI D0). 115 * For PM_SUSPEND, the ACPI D-state being entered is passed 116 * as the "data" argument to the callback. The device 117 * driver should save (PM_SUSPEND) or restore (PM_RESUME) 118 * device context when the request callback is called. 119 * 120 * Once a driver returns 0 (success) from a suspend 121 * request, it should not process any further requests or 122 * access the device hardware until a call to "pm_access" is made. 123 */ 124typedef int (*pm_callback)(struct pm_dev *dev, pm_request_t rqst, void *data); 125 126Driver Details 127-------------- 128This is just a quick Q&A as a stopgap until a real driver writers' 129power management guide is available. 130 131Q: When is a device suspended? 132 133Devices can be suspended based on direct user request (eg. laptop lid 134closes), system power policy (eg. sleep after 30 minutes of console 135inactivity), or device power policy (eg. power down device after 5 136minutes of inactivity) 137 138Q: Must a driver honor a suspend request? 139 140No, a driver can return -EBUSY from a suspend request and this 141will stop the system from suspending. When a suspend request 142fails, all suspended devices are resumed and the system continues 143to run. Suspend can be retried at a later time. 144 145Q: Can the driver block suspend/resume requests? 146 147Yes, a driver can delay its return from a suspend or resume 148request until the device is ready to handle requests. It 149is advantageous to return as quickly as possible from a 150request as suspend/resume are done serially. 151 152Q: What context is a suspend/resume initiated from? 153 154A suspend or resume is initiated from a kernel thread context. 155It is safe to block, allocate memory, initiate requests 156or anything else you can do within the kernel. 157 158Q: Will requests continue to arrive after a suspend? 159 160Possibly. It is the driver's responsibility to queue(*), 161fail, or drop any requests that arrive after returning 162success to a suspend request. It is important that the 163driver not access its device until after it receives 164a resume request as the device's bus may no longer 165be active. 166 167(*) If a driver queues requests for processing after 168 resume be aware that the device, network, etc. 169 might be in a different state than at suspend time. 170 It's probably better to drop requests unless 171 the driver is a storage device. 172 173Q: Do I have to manage bus-specific power management registers 174 175No. It is the responsibility of the bus driver to manage 176PCI, USB, etc. power management registers. The bus driver 177or the power management subsystem will also enable any 178wake-on functionality that the device has. 179 180Q: So, really, what do I need to do to support suspend/resume? 181 182You need to save any device context that would 183be lost if the device was powered off and then restore 184it at resume time. When ACPI is active, there are 185three levels of device suspend states; D1, D2, and D3. 186(The suspend state is passed as the "data" argument 187to the device callback.) With D3, the device is powered 188off and loses all context, D1 and D2 are shallower power 189states and require less device context to be saved. To 190play it safe, just save everything at suspend and restore 191everything at resume. 192 193Q: Where do I store device context for suspend? 194 195Anywhere in memory, kmalloc a buffer or store it 196in the device descriptor. You are guaranteed that the 197contents of memory will be restored and accessible 198before resume, even when the system suspends to disk. 199 200Q: What do I need to do for ACPI vs. APM vs. etc? 201 202Drivers need not be aware of the specific power management 203technology that is active. They just need to be aware 204of when the overlying power management system requests 205that they suspend or resume. 206 207Q: What about device dependencies? 208 209When a driver registers a device, the power management 210subsystem uses the information provided to build a 211tree of device dependencies (eg. USB device X is on 212USB controller Y which is on PCI bus Z) When power 213management wants to suspend a device, it first sends 214a suspend request to its driver, then the bus driver, 215and so on up to the system bus. Device resumes 216proceed in the opposite direction. 217 218Q: Who do I contact for additional information about 219 enabling power management for my specific driver/device? 220 221ACPI Development mailing list: linux-acpi@vger.kernel.org 222 223System Interface -- OBSOLETE, DO NOT USE! 224----------------************************* 225If you are providing new power management support to Linux (ie. 226adding support for something like APM or ACPI), you should 227communicate with drivers through the existing generic power 228management interface. 229 230/* 231 * Send a request to all devices 232 * 233 * Parameters: 234 * rqst - request type 235 * data - data, if any, associated with the request 236 * 237 * Returns: 0 if the request is successful 238 * See "pm_callback" return for errors 239 * 240 * Details: Walk list of registered devices and call pm_send 241 * for each until complete or an error is encountered. 242 * If an error is encountered for a suspend request, 243 * return all devices to the state they were in before 244 * the suspend request. 245 */ 246int pm_send_all(pm_request_t rqst, void *data); 247 248/* 249 * Find a matching device 250 * 251 * Parameters: 252 * type - device type (PCI device, system device, or 0 to match all devices) 253 * from - previous match or NULL to start from the beginning 254 * 255 * Returns: Matching device or NULL if none found 256 */ 257struct pm_dev *pm_find(pm_dev_t type, struct pm_dev *from); 258