aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/power.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/power.c')
-rw-r--r--drivers/acpi/power.c730
1 files changed, 395 insertions, 335 deletions
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 6e7b9d523812..b820528a5fa3 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -41,6 +41,7 @@
41#include <linux/types.h> 41#include <linux/types.h>
42#include <linux/slab.h> 42#include <linux/slab.h>
43#include <linux/pm_runtime.h> 43#include <linux/pm_runtime.h>
44#include <linux/sysfs.h>
44#include <acpi/acpi_bus.h> 45#include <acpi/acpi_bus.h>
45#include <acpi/acpi_drivers.h> 46#include <acpi/acpi_drivers.h>
46#include "sleep.h" 47#include "sleep.h"
@@ -58,88 +59,121 @@ ACPI_MODULE_NAME("power");
58#define ACPI_POWER_RESOURCE_STATE_ON 0x01 59#define ACPI_POWER_RESOURCE_STATE_ON 0x01
59#define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF 60#define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF
60 61
61static int acpi_power_add(struct acpi_device *device); 62struct acpi_power_dependent_device {
62static int acpi_power_remove(struct acpi_device *device, int type); 63 struct list_head node;
63 64 struct acpi_device *adev;
64static const struct acpi_device_id power_device_ids[] = { 65 struct work_struct work;
65 {ACPI_POWER_HID, 0},
66 {"", 0},
67};
68MODULE_DEVICE_TABLE(acpi, power_device_ids);
69
70#ifdef CONFIG_PM_SLEEP
71static int acpi_power_resume(struct device *dev);
72#endif
73static SIMPLE_DEV_PM_OPS(acpi_power_pm, NULL, acpi_power_resume);
74
75static struct acpi_driver acpi_power_driver = {
76 .name = "power",
77 .class = ACPI_POWER_CLASS,
78 .ids = power_device_ids,
79 .ops = {
80 .add = acpi_power_add,
81 .remove = acpi_power_remove,
82 },
83 .drv.pm = &acpi_power_pm,
84};
85
86/*
87 * A power managed device
88 * A device may rely on multiple power resources.
89 * */
90struct acpi_power_managed_device {
91 struct device *dev; /* The physical device */
92 acpi_handle *handle;
93};
94
95struct acpi_power_resource_device {
96 struct acpi_power_managed_device *device;
97 struct acpi_power_resource_device *next;
98}; 66};
99 67
100struct acpi_power_resource { 68struct acpi_power_resource {
101 struct acpi_device * device; 69 struct acpi_device device;
102 acpi_bus_id name; 70 struct list_head list_node;
71 struct list_head dependent;
72 char *name;
103 u32 system_level; 73 u32 system_level;
104 u32 order; 74 u32 order;
105 unsigned int ref_count; 75 unsigned int ref_count;
106 struct mutex resource_lock; 76 struct mutex resource_lock;
77};
107 78
108 /* List of devices relying on this power resource */ 79struct acpi_power_resource_entry {
109 struct acpi_power_resource_device *devices; 80 struct list_head node;
110 struct mutex devices_lock; 81 struct acpi_power_resource *resource;
111}; 82};
112 83
113static struct list_head acpi_power_resource_list; 84static LIST_HEAD(acpi_power_resource_list);
85static DEFINE_MUTEX(power_resource_list_lock);
114 86
115/* -------------------------------------------------------------------------- 87/* --------------------------------------------------------------------------
116 Power Resource Management 88 Power Resource Management
117 -------------------------------------------------------------------------- */ 89 -------------------------------------------------------------------------- */
118 90
119static int 91static inline
120acpi_power_get_context(acpi_handle handle, 92struct acpi_power_resource *to_power_resource(struct acpi_device *device)
121 struct acpi_power_resource **resource)
122{ 93{
123 int result = 0; 94 return container_of(device, struct acpi_power_resource, device);
124 struct acpi_device *device = NULL; 95}
96
97static struct acpi_power_resource *acpi_power_get_context(acpi_handle handle)
98{
99 struct acpi_device *device;
125 100
101 if (acpi_bus_get_device(handle, &device))
102 return NULL;
126 103
127 if (!resource) 104 return to_power_resource(device);
128 return -ENODEV; 105}
129 106
130 result = acpi_bus_get_device(handle, &device); 107static int acpi_power_resources_list_add(acpi_handle handle,
131 if (result) { 108 struct list_head *list)
132 printk(KERN_WARNING PREFIX "Getting context [%p]\n", handle); 109{
133 return result; 110 struct acpi_power_resource *resource = acpi_power_get_context(handle);
134 } 111 struct acpi_power_resource_entry *entry;
135 112
136 *resource = acpi_driver_data(device); 113 if (!resource || !list)
137 if (!*resource) 114 return -EINVAL;
138 return -ENODEV; 115
116 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
117 if (!entry)
118 return -ENOMEM;
119
120 entry->resource = resource;
121 if (!list_empty(list)) {
122 struct acpi_power_resource_entry *e;
139 123
124 list_for_each_entry(e, list, node)
125 if (e->resource->order > resource->order) {
126 list_add_tail(&entry->node, &e->node);
127 return 0;
128 }
129 }
130 list_add_tail(&entry->node, list);
140 return 0; 131 return 0;
141} 132}
142 133
134void acpi_power_resources_list_free(struct list_head *list)
135{
136 struct acpi_power_resource_entry *entry, *e;
137
138 list_for_each_entry_safe(entry, e, list, node) {
139 list_del(&entry->node);
140 kfree(entry);
141 }
142}
143
144int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
145 struct list_head *list)
146{
147 unsigned int i;
148 int err = 0;
149
150 for (i = start; i < package->package.count; i++) {
151 union acpi_object *element = &package->package.elements[i];
152 acpi_handle rhandle;
153
154 if (element->type != ACPI_TYPE_LOCAL_REFERENCE) {
155 err = -ENODATA;
156 break;
157 }
158 rhandle = element->reference.handle;
159 if (!rhandle) {
160 err = -ENODEV;
161 break;
162 }
163 err = acpi_add_power_resource(rhandle);
164 if (err)
165 break;
166
167 err = acpi_power_resources_list_add(rhandle, list);
168 if (err)
169 break;
170 }
171 if (err)
172 acpi_power_resources_list_free(list);
173
174 return err;
175}
176
143static int acpi_power_get_state(acpi_handle handle, int *state) 177static int acpi_power_get_state(acpi_handle handle, int *state)
144{ 178{
145 acpi_status status = AE_OK; 179 acpi_status status = AE_OK;
@@ -167,31 +201,23 @@ static int acpi_power_get_state(acpi_handle handle, int *state)
167 return 0; 201 return 0;
168} 202}
169 203
170static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) 204static int acpi_power_get_list_state(struct list_head *list, int *state)
171{ 205{
206 struct acpi_power_resource_entry *entry;
172 int cur_state; 207 int cur_state;
173 int i = 0;
174 208
175 if (!list || !state) 209 if (!list || !state)
176 return -EINVAL; 210 return -EINVAL;
177 211
178 /* The state of the list is 'on' IFF all resources are 'on'. */ 212 /* The state of the list is 'on' IFF all resources are 'on'. */
179 213 list_for_each_entry(entry, list, node) {
180 for (i = 0; i < list->count; i++) { 214 struct acpi_power_resource *resource = entry->resource;
181 struct acpi_power_resource *resource; 215 acpi_handle handle = resource->device.handle;
182 acpi_handle handle = list->handles[i];
183 int result; 216 int result;
184 217
185 result = acpi_power_get_context(handle, &resource);
186 if (result)
187 return result;
188
189 mutex_lock(&resource->resource_lock); 218 mutex_lock(&resource->resource_lock);
190
191 result = acpi_power_get_state(handle, &cur_state); 219 result = acpi_power_get_state(handle, &cur_state);
192
193 mutex_unlock(&resource->resource_lock); 220 mutex_unlock(&resource->resource_lock);
194
195 if (result) 221 if (result)
196 return result; 222 return result;
197 223
@@ -203,54 +229,52 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
203 cur_state ? "on" : "off")); 229 cur_state ? "on" : "off"));
204 230
205 *state = cur_state; 231 *state = cur_state;
206
207 return 0; 232 return 0;
208} 233}
209 234
210/* Resume the device when all power resources in _PR0 are on */ 235static void acpi_power_resume_dependent(struct work_struct *work)
211static void acpi_power_on_device(struct acpi_power_managed_device *device)
212{ 236{
213 struct acpi_device *acpi_dev; 237 struct acpi_power_dependent_device *dep;
214 acpi_handle handle = device->handle; 238 struct acpi_device_physical_node *pn;
239 struct acpi_device *adev;
215 int state; 240 int state;
216 241
217 if (acpi_bus_get_device(handle, &acpi_dev)) 242 dep = container_of(work, struct acpi_power_dependent_device, work);
243 adev = dep->adev;
244 if (acpi_power_get_inferred_state(adev, &state))
218 return; 245 return;
219 246
220 if(acpi_power_get_inferred_state(acpi_dev, &state)) 247 if (state > ACPI_STATE_D0)
221 return; 248 return;
222 249
223 if (state == ACPI_STATE_D0 && pm_runtime_suspended(device->dev)) 250 mutex_lock(&adev->physical_node_lock);
224 pm_request_resume(device->dev); 251
252 list_for_each_entry(pn, &adev->physical_node_list, node)
253 pm_request_resume(pn->dev);
254
255 list_for_each_entry(pn, &adev->power_dependent, node)
256 pm_request_resume(pn->dev);
257
258 mutex_unlock(&adev->physical_node_lock);
225} 259}
226 260
227static int __acpi_power_on(struct acpi_power_resource *resource) 261static int __acpi_power_on(struct acpi_power_resource *resource)
228{ 262{
229 acpi_status status = AE_OK; 263 acpi_status status = AE_OK;
230 264
231 status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL); 265 status = acpi_evaluate_object(resource->device.handle, "_ON", NULL, NULL);
232 if (ACPI_FAILURE(status)) 266 if (ACPI_FAILURE(status))
233 return -ENODEV; 267 return -ENODEV;
234 268
235 /* Update the power resource's _device_ power state */
236 resource->device->power.state = ACPI_STATE_D0;
237
238 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned on\n", 269 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned on\n",
239 resource->name)); 270 resource->name));
240 271
241 return 0; 272 return 0;
242} 273}
243 274
244static int acpi_power_on(acpi_handle handle) 275static int acpi_power_on(struct acpi_power_resource *resource)
245{ 276{
246 int result = 0; 277 int result = 0;;
247 bool resume_device = false;
248 struct acpi_power_resource *resource = NULL;
249 struct acpi_power_resource_device *device_list;
250
251 result = acpi_power_get_context(handle, &resource);
252 if (result)
253 return result;
254 278
255 mutex_lock(&resource->resource_lock); 279 mutex_lock(&resource->resource_lock);
256 280
@@ -260,39 +284,38 @@ static int acpi_power_on(acpi_handle handle)
260 resource->name)); 284 resource->name));
261 } else { 285 } else {
262 result = __acpi_power_on(resource); 286 result = __acpi_power_on(resource);
263 if (result) 287 if (result) {
264 resource->ref_count--; 288 resource->ref_count--;
265 else 289 } else {
266 resume_device = true; 290 struct acpi_power_dependent_device *dep;
291
292 list_for_each_entry(dep, &resource->dependent, node)
293 schedule_work(&dep->work);
294 }
267 } 295 }
268 296
269 mutex_unlock(&resource->resource_lock); 297 mutex_unlock(&resource->resource_lock);
270 298
271 if (!resume_device) 299 return result;
272 return result; 300}
273
274 mutex_lock(&resource->devices_lock);
275 301
276 device_list = resource->devices; 302static int __acpi_power_off(struct acpi_power_resource *resource)
277 while (device_list) { 303{
278 acpi_power_on_device(device_list->device); 304 acpi_status status;
279 device_list = device_list->next;
280 }
281 305
282 mutex_unlock(&resource->devices_lock); 306 status = acpi_evaluate_object(resource->device.handle, "_OFF",
307 NULL, NULL);
308 if (ACPI_FAILURE(status))
309 return -ENODEV;
283 310
284 return result; 311 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned off\n",
312 resource->name));
313 return 0;
285} 314}
286 315
287static int acpi_power_off(acpi_handle handle) 316static int acpi_power_off(struct acpi_power_resource *resource)
288{ 317{
289 int result = 0; 318 int result = 0;
290 acpi_status status = AE_OK;
291 struct acpi_power_resource *resource = NULL;
292
293 result = acpi_power_get_context(handle, &resource);
294 if (result)
295 return result;
296 319
297 mutex_lock(&resource->resource_lock); 320 mutex_lock(&resource->resource_lock);
298 321
@@ -307,19 +330,10 @@ static int acpi_power_off(acpi_handle handle)
307 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 330 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
308 "Power resource [%s] still in use\n", 331 "Power resource [%s] still in use\n",
309 resource->name)); 332 resource->name));
310 goto unlock;
311 }
312
313 status = acpi_evaluate_object(resource->device->handle, "_OFF", NULL, NULL);
314 if (ACPI_FAILURE(status)) {
315 result = -ENODEV;
316 } else { 333 } else {
317 /* Update the power resource's _device_ power state */ 334 result = __acpi_power_off(resource);
318 resource->device->power.state = ACPI_STATE_D3; 335 if (result)
319 336 resource->ref_count++;
320 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
321 "Power resource [%s] turned off\n",
322 resource->name));
323 } 337 }
324 338
325 unlock: 339 unlock:
@@ -328,148 +342,202 @@ static int acpi_power_off(acpi_handle handle)
328 return result; 342 return result;
329} 343}
330 344
331static void __acpi_power_off_list(struct acpi_handle_list *list, int num_res) 345static int acpi_power_off_list(struct list_head *list)
332{ 346{
333 int i; 347 struct acpi_power_resource_entry *entry;
348 int result = 0;
334 349
335 for (i = num_res - 1; i >= 0 ; i--) 350 list_for_each_entry_reverse(entry, list, node) {
336 acpi_power_off(list->handles[i]); 351 result = acpi_power_off(entry->resource);
337} 352 if (result)
353 goto err;
354 }
355 return 0;
338 356
339static void acpi_power_off_list(struct acpi_handle_list *list) 357 err:
340{ 358 list_for_each_entry_continue(entry, list, node)
341 __acpi_power_off_list(list, list->count); 359 acpi_power_on(entry->resource);
360
361 return result;
342} 362}
343 363
344static int acpi_power_on_list(struct acpi_handle_list *list) 364static int acpi_power_on_list(struct list_head *list)
345{ 365{
366 struct acpi_power_resource_entry *entry;
346 int result = 0; 367 int result = 0;
347 int i;
348 368
349 for (i = 0; i < list->count; i++) { 369 list_for_each_entry(entry, list, node) {
350 result = acpi_power_on(list->handles[i]); 370 result = acpi_power_on(entry->resource);
351 if (result) { 371 if (result)
352 __acpi_power_off_list(list, i); 372 goto err;
353 break;
354 }
355 } 373 }
374 return 0;
375
376 err:
377 list_for_each_entry_continue_reverse(entry, list, node)
378 acpi_power_off(entry->resource);
356 379
357 return result; 380 return result;
358} 381}
359 382
360static void __acpi_power_resource_unregister_device(struct device *dev, 383static void acpi_power_add_dependent(struct acpi_power_resource *resource,
361 acpi_handle res_handle) 384 struct acpi_device *adev)
362{ 385{
363 struct acpi_power_resource *resource = NULL; 386 struct acpi_power_dependent_device *dep;
364 struct acpi_power_resource_device *prev, *curr;
365 387
366 if (acpi_power_get_context(res_handle, &resource)) 388 mutex_lock(&resource->resource_lock);
367 return; 389
390 list_for_each_entry(dep, &resource->dependent, node)
391 if (dep->adev == adev)
392 goto out;
393
394 dep = kzalloc(sizeof(*dep), GFP_KERNEL);
395 if (!dep)
396 goto out;
397
398 dep->adev = adev;
399 INIT_WORK(&dep->work, acpi_power_resume_dependent);
400 list_add_tail(&dep->node, &resource->dependent);
368 401
369 mutex_lock(&resource->devices_lock); 402 out:
370 prev = NULL; 403 mutex_unlock(&resource->resource_lock);
371 curr = resource->devices; 404}
372 while (curr) { 405
373 if (curr->device->dev == dev) { 406static void acpi_power_remove_dependent(struct acpi_power_resource *resource,
374 if (!prev) 407 struct acpi_device *adev)
375 resource->devices = curr->next; 408{
376 else 409 struct acpi_power_dependent_device *dep;
377 prev->next = curr->next; 410 struct work_struct *work = NULL;
378 411
379 kfree(curr); 412 mutex_lock(&resource->resource_lock);
413
414 list_for_each_entry(dep, &resource->dependent, node)
415 if (dep->adev == adev) {
416 list_del(&dep->node);
417 work = &dep->work;
380 break; 418 break;
381 } 419 }
382 420
383 prev = curr; 421 mutex_unlock(&resource->resource_lock);
384 curr = curr->next; 422
423 if (work) {
424 cancel_work_sync(work);
425 kfree(dep);
385 } 426 }
386 mutex_unlock(&resource->devices_lock);
387} 427}
388 428
389/* Unlink dev from all power resources in _PR0 */ 429static struct attribute *attrs[] = {
390void acpi_power_resource_unregister_device(struct device *dev, acpi_handle handle) 430 NULL,
391{ 431};
392 struct acpi_device *acpi_dev;
393 struct acpi_handle_list *list;
394 int i;
395 432
396 if (!dev || !handle) 433static struct attribute_group attr_groups[] = {
397 return; 434 [ACPI_STATE_D0] = {
435 .name = "power_resources_D0",
436 .attrs = attrs,
437 },
438 [ACPI_STATE_D1] = {
439 .name = "power_resources_D1",
440 .attrs = attrs,
441 },
442 [ACPI_STATE_D2] = {
443 .name = "power_resources_D2",
444 .attrs = attrs,
445 },
446 [ACPI_STATE_D3_HOT] = {
447 .name = "power_resources_D3hot",
448 .attrs = attrs,
449 },
450};
398 451
399 if (acpi_bus_get_device(handle, &acpi_dev)) 452static void acpi_power_hide_list(struct acpi_device *adev, int state)
453{
454 struct acpi_device_power_state *ps = &adev->power.states[state];
455 struct acpi_power_resource_entry *entry;
456
457 if (list_empty(&ps->resources))
400 return; 458 return;
401 459
402 list = &acpi_dev->power.states[ACPI_STATE_D0].resources; 460 list_for_each_entry_reverse(entry, &ps->resources, node) {
461 struct acpi_device *res_dev = &entry->resource->device;
403 462
404 for (i = 0; i < list->count; i++) 463 sysfs_remove_link_from_group(&adev->dev.kobj,
405 __acpi_power_resource_unregister_device(dev, 464 attr_groups[state].name,
406 list->handles[i]); 465 dev_name(&res_dev->dev));
466 }
467 sysfs_remove_group(&adev->dev.kobj, &attr_groups[state]);
407} 468}
408EXPORT_SYMBOL_GPL(acpi_power_resource_unregister_device);
409 469
410static int __acpi_power_resource_register_device( 470static void acpi_power_expose_list(struct acpi_device *adev, int state)
411 struct acpi_power_managed_device *powered_device, acpi_handle handle)
412{ 471{
413 struct acpi_power_resource *resource = NULL; 472 struct acpi_device_power_state *ps = &adev->power.states[state];
414 struct acpi_power_resource_device *power_resource_device; 473 struct acpi_power_resource_entry *entry;
415 int result; 474 int ret;
416
417 result = acpi_power_get_context(handle, &resource);
418 if (result)
419 return result;
420 475
421 power_resource_device = kzalloc( 476 if (list_empty(&ps->resources))
422 sizeof(*power_resource_device), GFP_KERNEL); 477 return;
423 if (!power_resource_device)
424 return -ENOMEM;
425 478
426 power_resource_device->device = powered_device; 479 ret = sysfs_create_group(&adev->dev.kobj, &attr_groups[state]);
480 if (ret)
481 return;
427 482
428 mutex_lock(&resource->devices_lock); 483 list_for_each_entry(entry, &ps->resources, node) {
429 power_resource_device->next = resource->devices; 484 struct acpi_device *res_dev = &entry->resource->device;
430 resource->devices = power_resource_device;
431 mutex_unlock(&resource->devices_lock);
432 485
433 return 0; 486 ret = sysfs_add_link_to_group(&adev->dev.kobj,
487 attr_groups[state].name,
488 &res_dev->dev.kobj,
489 dev_name(&res_dev->dev));
490 if (ret) {
491 acpi_power_hide_list(adev, state);
492 break;
493 }
494 }
434} 495}
435 496
436/* Link dev to all power resources in _PR0 */ 497void acpi_power_add_remove_device(struct acpi_device *adev, bool add)
437int acpi_power_resource_register_device(struct device *dev, acpi_handle handle)
438{ 498{
439 struct acpi_device *acpi_dev; 499 struct acpi_device_power_state *ps;
440 struct acpi_handle_list *list; 500 struct acpi_power_resource_entry *entry;
441 struct acpi_power_managed_device *powered_device; 501 int state;
442 int i, ret;
443 502
444 if (!dev || !handle) 503 if (!adev->power.flags.power_resources)
445 return -ENODEV; 504 return;
446 505
447 ret = acpi_bus_get_device(handle, &acpi_dev); 506 ps = &adev->power.states[ACPI_STATE_D0];
448 if (ret || !acpi_dev->power.flags.power_resources) 507 list_for_each_entry(entry, &ps->resources, node) {
449 return -ENODEV; 508 struct acpi_power_resource *resource = entry->resource;
450 509
451 powered_device = kzalloc(sizeof(*powered_device), GFP_KERNEL); 510 if (add)
452 if (!powered_device) 511 acpi_power_add_dependent(resource, adev);
453 return -ENOMEM; 512 else
513 acpi_power_remove_dependent(resource, adev);
514 }
454 515
455 powered_device->dev = dev; 516 for (state = ACPI_STATE_D0; state <= ACPI_STATE_D3_HOT; state++) {
456 powered_device->handle = handle; 517 if (add)
518 acpi_power_expose_list(adev, state);
519 else
520 acpi_power_hide_list(adev, state);
521 }
522}
457 523
458 list = &acpi_dev->power.states[ACPI_STATE_D0].resources; 524int acpi_power_min_system_level(struct list_head *list)
525{
526 struct acpi_power_resource_entry *entry;
527 int system_level = 5;
459 528
460 for (i = 0; i < list->count; i++) { 529 list_for_each_entry(entry, list, node) {
461 ret = __acpi_power_resource_register_device(powered_device, 530 struct acpi_power_resource *resource = entry->resource;
462 list->handles[i]);
463 531
464 if (ret) { 532 if (system_level > resource->system_level)
465 acpi_power_resource_unregister_device(dev, handle); 533 system_level = resource->system_level;
466 break;
467 }
468 } 534 }
469 535 return system_level;
470 return ret;
471} 536}
472EXPORT_SYMBOL_GPL(acpi_power_resource_register_device); 537
538/* --------------------------------------------------------------------------
539 Device Power Management
540 -------------------------------------------------------------------------- */
473 541
474/** 542/**
475 * acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in 543 * acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in
@@ -542,7 +610,7 @@ int acpi_device_sleep_wake(struct acpi_device *dev,
542 */ 610 */
543int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) 611int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
544{ 612{
545 int i, err = 0; 613 int err = 0;
546 614
547 if (!dev || !dev->wakeup.flags.valid) 615 if (!dev || !dev->wakeup.flags.valid)
548 return -EINVAL; 616 return -EINVAL;
@@ -552,24 +620,17 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
552 if (dev->wakeup.prepare_count++) 620 if (dev->wakeup.prepare_count++)
553 goto out; 621 goto out;
554 622
555 /* Open power resource */ 623 err = acpi_power_on_list(&dev->wakeup.resources);
556 for (i = 0; i < dev->wakeup.resources.count; i++) { 624 if (err) {
557 int ret = acpi_power_on(dev->wakeup.resources.handles[i]); 625 dev_err(&dev->dev, "Cannot turn wakeup power resources on\n");
558 if (ret) { 626 dev->wakeup.flags.valid = 0;
559 printk(KERN_ERR PREFIX "Transition power state\n"); 627 } else {
560 dev->wakeup.flags.valid = 0; 628 /*
561 err = -ENODEV; 629 * Passing 3 as the third argument below means the device may be
562 goto err_out; 630 * put into arbitrary power state afterward.
563 } 631 */
632 err = acpi_device_sleep_wake(dev, 1, sleep_state, 3);
564 } 633 }
565
566 /*
567 * Passing 3 as the third argument below means the device may be placed
568 * in arbitrary power state afterwards.
569 */
570 err = acpi_device_sleep_wake(dev, 1, sleep_state, 3);
571
572 err_out:
573 if (err) 634 if (err)
574 dev->wakeup.prepare_count = 0; 635 dev->wakeup.prepare_count = 0;
575 636
@@ -586,7 +647,7 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
586 */ 647 */
587int acpi_disable_wakeup_device_power(struct acpi_device *dev) 648int acpi_disable_wakeup_device_power(struct acpi_device *dev)
588{ 649{
589 int i, err = 0; 650 int err = 0;
590 651
591 if (!dev || !dev->wakeup.flags.valid) 652 if (!dev || !dev->wakeup.flags.valid)
592 return -EINVAL; 653 return -EINVAL;
@@ -607,15 +668,10 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
607 if (err) 668 if (err)
608 goto out; 669 goto out;
609 670
610 /* Close power resource */ 671 err = acpi_power_off_list(&dev->wakeup.resources);
611 for (i = 0; i < dev->wakeup.resources.count; i++) { 672 if (err) {
612 int ret = acpi_power_off(dev->wakeup.resources.handles[i]); 673 dev_err(&dev->dev, "Cannot turn wakeup power resources off\n");
613 if (ret) { 674 dev->wakeup.flags.valid = 0;
614 printk(KERN_ERR PREFIX "Transition power state\n");
615 dev->wakeup.flags.valid = 0;
616 err = -ENODEV;
617 goto out;
618 }
619 } 675 }
620 676
621 out: 677 out:
@@ -623,14 +679,9 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
623 return err; 679 return err;
624} 680}
625 681
626/* --------------------------------------------------------------------------
627 Device Power Management
628 -------------------------------------------------------------------------- */
629
630int acpi_power_get_inferred_state(struct acpi_device *device, int *state) 682int acpi_power_get_inferred_state(struct acpi_device *device, int *state)
631{ 683{
632 int result = 0; 684 int result = 0;
633 struct acpi_handle_list *list = NULL;
634 int list_state = 0; 685 int list_state = 0;
635 int i = 0; 686 int i = 0;
636 687
@@ -642,8 +693,9 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state)
642 * required for a given D-state are 'on'. 693 * required for a given D-state are 'on'.
643 */ 694 */
644 for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3_HOT; i++) { 695 for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3_HOT; i++) {
645 list = &device->power.states[i].resources; 696 struct list_head *list = &device->power.states[i].resources;
646 if (list->count < 1) 697
698 if (list_empty(list))
647 continue; 699 continue;
648 700
649 result = acpi_power_get_list_state(list, &list_state); 701 result = acpi_power_get_list_state(list, &list_state);
@@ -662,7 +714,7 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state)
662 714
663int acpi_power_on_resources(struct acpi_device *device, int state) 715int acpi_power_on_resources(struct acpi_device *device, int state)
664{ 716{
665 if (!device || state < ACPI_STATE_D0 || state > ACPI_STATE_D3) 717 if (!device || state < ACPI_STATE_D0 || state > ACPI_STATE_D3_HOT)
666 return -EINVAL; 718 return -EINVAL;
667 719
668 return acpi_power_on_list(&device->power.states[state].resources); 720 return acpi_power_on_list(&device->power.states[state].resources);
@@ -675,7 +727,7 @@ int acpi_power_transition(struct acpi_device *device, int state)
675 if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD)) 727 if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD))
676 return -EINVAL; 728 return -EINVAL;
677 729
678 if (device->power.state == state) 730 if (device->power.state == state || !device->flags.power_manageable)
679 return 0; 731 return 0;
680 732
681 if ((device->power.state < ACPI_STATE_D0) 733 if ((device->power.state < ACPI_STATE_D0)
@@ -703,118 +755,126 @@ int acpi_power_transition(struct acpi_device *device, int state)
703 return result; 755 return result;
704} 756}
705 757
706/* -------------------------------------------------------------------------- 758static void acpi_release_power_resource(struct device *dev)
707 Driver Interface 759{
708 -------------------------------------------------------------------------- */ 760 struct acpi_device *device = to_acpi_device(dev);
761 struct acpi_power_resource *resource;
762
763 resource = container_of(device, struct acpi_power_resource, device);
764
765 mutex_lock(&power_resource_list_lock);
766 list_del(&resource->list_node);
767 mutex_unlock(&power_resource_list_lock);
768
769 acpi_free_ids(device);
770 kfree(resource);
771}
709 772
710static int acpi_power_add(struct acpi_device *device) 773static ssize_t acpi_power_in_use_show(struct device *dev,
774 struct device_attribute *attr,
775 char *buf) {
776 struct acpi_power_resource *resource;
777
778 resource = to_power_resource(to_acpi_device(dev));
779 return sprintf(buf, "%u\n", !!resource->ref_count);
780}
781static DEVICE_ATTR(resource_in_use, 0444, acpi_power_in_use_show, NULL);
782
783static void acpi_power_sysfs_remove(struct acpi_device *device)
711{ 784{
712 int result = 0, state; 785 device_remove_file(&device->dev, &dev_attr_resource_in_use);
713 acpi_status status = AE_OK; 786}
714 struct acpi_power_resource *resource = NULL; 787
788int acpi_add_power_resource(acpi_handle handle)
789{
790 struct acpi_power_resource *resource;
791 struct acpi_device *device = NULL;
715 union acpi_object acpi_object; 792 union acpi_object acpi_object;
716 struct acpi_buffer buffer = { sizeof(acpi_object), &acpi_object }; 793 struct acpi_buffer buffer = { sizeof(acpi_object), &acpi_object };
794 acpi_status status;
795 int state, result = -ENODEV;
717 796
797 acpi_bus_get_device(handle, &device);
798 if (device)
799 return 0;
718 800
719 if (!device) 801 resource = kzalloc(sizeof(*resource), GFP_KERNEL);
720 return -EINVAL;
721
722 resource = kzalloc(sizeof(struct acpi_power_resource), GFP_KERNEL);
723 if (!resource) 802 if (!resource)
724 return -ENOMEM; 803 return -ENOMEM;
725 804
726 resource->device = device; 805 device = &resource->device;
806 acpi_init_device_object(device, handle, ACPI_BUS_TYPE_POWER,
807 ACPI_STA_DEFAULT);
727 mutex_init(&resource->resource_lock); 808 mutex_init(&resource->resource_lock);
728 mutex_init(&resource->devices_lock); 809 INIT_LIST_HEAD(&resource->dependent);
729 strcpy(resource->name, device->pnp.bus_id); 810 resource->name = device->pnp.bus_id;
730 strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); 811 strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
731 strcpy(acpi_device_class(device), ACPI_POWER_CLASS); 812 strcpy(acpi_device_class(device), ACPI_POWER_CLASS);
732 device->driver_data = resource; 813 device->power.state = ACPI_STATE_UNKNOWN;
733 814
734 /* Evalute the object to get the system level and resource order. */ 815 /* Evalute the object to get the system level and resource order. */
735 status = acpi_evaluate_object(device->handle, NULL, NULL, &buffer); 816 status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
736 if (ACPI_FAILURE(status)) { 817 if (ACPI_FAILURE(status))
737 result = -ENODEV; 818 goto err;
738 goto end; 819
739 }
740 resource->system_level = acpi_object.power_resource.system_level; 820 resource->system_level = acpi_object.power_resource.system_level;
741 resource->order = acpi_object.power_resource.resource_order; 821 resource->order = acpi_object.power_resource.resource_order;
742 822
743 result = acpi_power_get_state(device->handle, &state); 823 result = acpi_power_get_state(handle, &state);
744 if (result) 824 if (result)
745 goto end; 825 goto err;
746
747 switch (state) {
748 case ACPI_POWER_RESOURCE_STATE_ON:
749 device->power.state = ACPI_STATE_D0;
750 break;
751 case ACPI_POWER_RESOURCE_STATE_OFF:
752 device->power.state = ACPI_STATE_D3;
753 break;
754 default:
755 device->power.state = ACPI_STATE_UNKNOWN;
756 break;
757 }
758 826
759 printk(KERN_INFO PREFIX "%s [%s] (%s)\n", acpi_device_name(device), 827 printk(KERN_INFO PREFIX "%s [%s] (%s)\n", acpi_device_name(device),
760 acpi_device_bid(device), state ? "on" : "off"); 828 acpi_device_bid(device), state ? "on" : "off");
761 829
762 end: 830 device->flags.match_driver = true;
831 result = acpi_device_add(device, acpi_release_power_resource);
763 if (result) 832 if (result)
764 kfree(resource); 833 goto err;
765 834
766 return result; 835 if (!device_create_file(&device->dev, &dev_attr_resource_in_use))
767} 836 device->remove = acpi_power_sysfs_remove;
768
769static int acpi_power_remove(struct acpi_device *device, int type)
770{
771 struct acpi_power_resource *resource;
772
773 if (!device)
774 return -EINVAL;
775
776 resource = acpi_driver_data(device);
777 if (!resource)
778 return -EINVAL;
779
780 kfree(resource);
781 837
838 mutex_lock(&power_resource_list_lock);
839 list_add(&resource->list_node, &acpi_power_resource_list);
840 mutex_unlock(&power_resource_list_lock);
841 acpi_device_add_finalize(device);
782 return 0; 842 return 0;
843
844 err:
845 acpi_release_power_resource(&device->dev);
846 return result;
783} 847}
784 848
785#ifdef CONFIG_PM_SLEEP 849#ifdef CONFIG_ACPI_SLEEP
786static int acpi_power_resume(struct device *dev) 850void acpi_resume_power_resources(void)
787{ 851{
788 int result = 0, state;
789 struct acpi_device *device;
790 struct acpi_power_resource *resource; 852 struct acpi_power_resource *resource;
791 853
792 if (!dev) 854 mutex_lock(&power_resource_list_lock);
793 return -EINVAL;
794 855
795 device = to_acpi_device(dev); 856 list_for_each_entry(resource, &acpi_power_resource_list, list_node) {
796 resource = acpi_driver_data(device); 857 int result, state;
797 if (!resource)
798 return -EINVAL;
799 858
800 mutex_lock(&resource->resource_lock); 859 mutex_lock(&resource->resource_lock);
801 860
802 result = acpi_power_get_state(device->handle, &state); 861 result = acpi_power_get_state(resource->device.handle, &state);
803 if (result) 862 if (result)
804 goto unlock; 863 continue;
805 864
806 if (state == ACPI_POWER_RESOURCE_STATE_OFF && resource->ref_count) 865 if (state == ACPI_POWER_RESOURCE_STATE_OFF
807 result = __acpi_power_on(resource); 866 && resource->ref_count) {
867 dev_info(&resource->device.dev, "Turning ON\n");
868 __acpi_power_on(resource);
869 } else if (state == ACPI_POWER_RESOURCE_STATE_ON
870 && !resource->ref_count) {
871 dev_info(&resource->device.dev, "Turning OFF\n");
872 __acpi_power_off(resource);
873 }
808 874
809 unlock: 875 mutex_unlock(&resource->resource_lock);
810 mutex_unlock(&resource->resource_lock); 876 }
811 877
812 return result; 878 mutex_unlock(&power_resource_list_lock);
813} 879}
814#endif 880#endif
815
816int __init acpi_power_init(void)
817{
818 INIT_LIST_HEAD(&acpi_power_resource_list);
819 return acpi_bus_register_driver(&acpi_power_driver);
820}