| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | Linux Power Management Support | 
|  | 2 |  | 
|  | 3 | This document briefly describes how to use power management with your | 
|  | 4 | Linux system and how to add power management support to Linux drivers. | 
|  | 5 |  | 
|  | 6 | APM or ACPI? | 
|  | 7 | ------------ | 
|  | 8 | If you have a relatively recent x86 mobile, desktop, or server system, | 
|  | 9 | odds are it supports either Advanced Power Management (APM) or | 
|  | 10 | Advanced Configuration and Power Interface (ACPI).  ACPI is the newer | 
|  | 11 | of the two technologies and puts power management in the hands of the | 
|  | 12 | operating system, allowing for more intelligent power management than | 
|  | 13 | is possible with BIOS controlled APM. | 
|  | 14 |  | 
|  | 15 | The best way to determine which, if either, your system supports is to | 
|  | 16 | build a kernel with both ACPI and APM enabled (as of 2.3.x ACPI is | 
|  | 17 | enabled by default).  If a working ACPI implementation is found, the | 
|  | 18 | ACPI driver will override and disable APM, otherwise the APM driver | 
|  | 19 | will be used. | 
|  | 20 |  | 
| Matt LaPlante | 84eb8d0 | 2006-10-03 22:53:09 +0200 | [diff] [blame] | 21 | No, sorry, you cannot have both ACPI and APM enabled and running at | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 22 | once.  Some people with broken ACPI or broken APM implementations | 
|  | 23 | would like to use both to get a full set of working features, but you | 
| Matt LaPlante | 84eb8d0 | 2006-10-03 22:53:09 +0200 | [diff] [blame] | 24 | simply cannot mix and match the two.  Only one power management | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 25 | interface can be in control of the machine at once.  Think about it.. | 
|  | 26 |  | 
|  | 27 | User-space Daemons | 
|  | 28 | ------------------ | 
|  | 29 | Both APM and ACPI rely on user-space daemons, apmd and acpid | 
|  | 30 | respectively, to be completely functional.  Obtain both of these | 
|  | 31 | daemons from your Linux distribution or from the Internet (see below) | 
|  | 32 | and be sure that they are started sometime in the system boot process. | 
|  | 33 | Go ahead and start both.  If ACPI or APM is not available on your | 
|  | 34 | system the associated daemon will exit gracefully. | 
|  | 35 |  | 
|  | 36 | apmd:   http://worldvisions.ca/~apenwarr/apmd/ | 
|  | 37 | acpid:  http://acpid.sf.net/ | 
|  | 38 |  | 
|  | 39 | Driver Interface -- OBSOLETE, DO NOT USE! | 
|  | 40 | ----------------************************* | 
| Pavel Machek | f4f9eb0 | 2005-09-13 01:25:46 -0700 | [diff] [blame] | 41 |  | 
|  | 42 | Note: pm_register(), pm_access(), pm_dev_idle() and friends are | 
|  | 43 | obsolete. Please do not use them. Instead you should properly hook | 
|  | 44 | your driver into the driver model, and use its suspend()/resume() | 
|  | 45 | callbacks to do this kind of stuff. | 
|  | 46 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 47 | If you are writing a new driver or maintaining an old driver, it | 
|  | 48 | should include power management support.  Without power management | 
|  | 49 | support, a single driver may prevent a system with power management | 
|  | 50 | capabilities from ever being able to suspend (safely). | 
|  | 51 |  | 
|  | 52 | Overview: | 
|  | 53 | 1) Register each instance of a device with "pm_register" | 
|  | 54 | 2) Call "pm_access" before accessing the hardware. | 
|  | 55 | (this will ensure that the hardware is awake and ready) | 
|  | 56 | 3) Your "pm_callback" is called before going into a | 
|  | 57 | suspend state (ACPI D1-D3) or after resuming (ACPI D0) | 
|  | 58 | from a suspend. | 
|  | 59 | 4) Call "pm_dev_idle" when the device is not being used | 
|  | 60 | (optional but will improve device idle detection) | 
|  | 61 | 5) 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 | */ | 
|  | 79 | struct 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 | */ | 
|  | 87 | void 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 | */ | 
|  | 97 | void 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 | 
| Matt LaPlante | 84eb8d0 | 2006-10-03 22:53:09 +0200 | [diff] [blame] | 109 | *          EBUSY if the device is now busy and cannot handle the request | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | */ | 
|  | 124 | typedef int (*pm_callback)(struct pm_dev *dev, pm_request_t rqst, void *data); | 
|  | 125 |  | 
|  | 126 | Driver Details | 
|  | 127 | -------------- | 
|  | 128 | This is just a quick Q&A as a stopgap until a real driver writers' | 
|  | 129 | power management guide is available. | 
|  | 130 |  | 
|  | 131 | Q: When is a device suspended? | 
|  | 132 |  | 
|  | 133 | Devices can be suspended based on direct user request (eg. laptop lid | 
|  | 134 | closes), system power policy (eg.  sleep after 30 minutes of console | 
|  | 135 | inactivity), or device power policy (eg. power down device after 5 | 
|  | 136 | minutes of inactivity) | 
|  | 137 |  | 
|  | 138 | Q: Must a driver honor a suspend request? | 
|  | 139 |  | 
|  | 140 | No, a driver can return -EBUSY from a suspend request and this | 
|  | 141 | will stop the system from suspending.  When a suspend request | 
|  | 142 | fails, all suspended devices are resumed and the system continues | 
|  | 143 | to run.  Suspend can be retried at a later time. | 
|  | 144 |  | 
|  | 145 | Q: Can the driver block suspend/resume requests? | 
|  | 146 |  | 
|  | 147 | Yes, a driver can delay its return from a suspend or resume | 
|  | 148 | request until the device is ready to handle requests.  It | 
|  | 149 | is advantageous to return as quickly as possible from a | 
|  | 150 | request as suspend/resume are done serially. | 
|  | 151 |  | 
|  | 152 | Q: What context is a suspend/resume initiated from? | 
|  | 153 |  | 
|  | 154 | A suspend or resume is initiated from a kernel thread context. | 
|  | 155 | It is safe to block, allocate memory, initiate requests | 
|  | 156 | or anything else you can do within the kernel. | 
|  | 157 |  | 
|  | 158 | Q: Will requests continue to arrive after a suspend? | 
|  | 159 |  | 
|  | 160 | Possibly.  It is the driver's responsibility to queue(*), | 
|  | 161 | fail, or drop any requests that arrive after returning | 
|  | 162 | success to a suspend request.  It is important that the | 
|  | 163 | driver not access its device until after it receives | 
|  | 164 | a resume request as the device's bus may no longer | 
|  | 165 | be 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 |  | 
|  | 173 | Q: Do I have to manage bus-specific power management registers | 
|  | 174 |  | 
|  | 175 | No.  It is the responsibility of the bus driver to manage | 
|  | 176 | PCI, USB, etc. power management registers.  The bus driver | 
|  | 177 | or the power management subsystem will also enable any | 
|  | 178 | wake-on functionality that the device has. | 
|  | 179 |  | 
|  | 180 | Q: So, really, what do I need to do to support suspend/resume? | 
|  | 181 |  | 
|  | 182 | You need to save any device context that would | 
|  | 183 | be lost if the device was powered off and then restore | 
|  | 184 | it at resume time.  When ACPI is active, there are | 
|  | 185 | three levels of device suspend states; D1, D2, and D3. | 
|  | 186 | (The suspend state is passed as the "data" argument | 
|  | 187 | to the device callback.)  With D3, the device is powered | 
|  | 188 | off and loses all context, D1 and D2 are shallower power | 
|  | 189 | states and require less device context to be saved.  To | 
|  | 190 | play it safe, just save everything at suspend and restore | 
|  | 191 | everything at resume. | 
|  | 192 |  | 
|  | 193 | Q: Where do I store device context for suspend? | 
|  | 194 |  | 
|  | 195 | Anywhere in memory, kmalloc a buffer or store it | 
|  | 196 | in the device descriptor.  You are guaranteed that the | 
|  | 197 | contents of memory will be restored and accessible | 
|  | 198 | before resume, even when the system suspends to disk. | 
|  | 199 |  | 
|  | 200 | Q: What do I need to do for ACPI vs. APM vs. etc? | 
|  | 201 |  | 
|  | 202 | Drivers need not be aware of the specific power management | 
|  | 203 | technology that is active.  They just need to be aware | 
|  | 204 | of when the overlying power management system requests | 
|  | 205 | that they suspend or resume. | 
|  | 206 |  | 
|  | 207 | Q: What about device dependencies? | 
|  | 208 |  | 
|  | 209 | When a driver registers a device, the power management | 
|  | 210 | subsystem uses the information provided to build a | 
|  | 211 | tree of device dependencies (eg. USB device X is on | 
|  | 212 | USB controller Y which is on PCI bus Z)  When power | 
|  | 213 | management wants to suspend a device, it first sends | 
|  | 214 | a suspend request to its driver, then the bus driver, | 
|  | 215 | and so on up to the system bus.  Device resumes | 
|  | 216 | proceed in the opposite direction. | 
|  | 217 |  | 
|  | 218 | Q: Who do I contact for additional information about | 
|  | 219 | enabling power management for my specific driver/device? | 
|  | 220 |  | 
| Len Brown | 036d25f | 2006-01-06 16:19:26 -0500 | [diff] [blame] | 221 | ACPI Development mailing list: linux-acpi@vger.kernel.org | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 222 |  | 
|  | 223 | System Interface -- OBSOLETE, DO NOT USE! | 
|  | 224 | ----------------************************* | 
|  | 225 | If you are providing new power management support to Linux (ie. | 
|  | 226 | adding support for something like APM or ACPI), you should | 
|  | 227 | communicate with drivers through the existing generic power | 
|  | 228 | management 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 | */ | 
|  | 246 | int 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 | */ | 
|  | 257 | struct pm_dev *pm_find(pm_dev_t type, struct pm_dev *from); |