diff options
author | Len Brown <len.brown@intel.com> | 2012-03-30 16:21:26 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2012-03-30 16:21:26 -0400 |
commit | ec612fcf43e09f5e05d37baf4d3f138b3fcc2f3d (patch) | |
tree | 67e4709b760582bdca00e596a2ea68bafb4ccc09 | |
parent | 73f05330497b98c45d157b7d0c60673798bb4c3b (diff) | |
parent | b24e5098853653554baf6ec975b9e855f3d6e5c0 (diff) |
Merge branch 'd3' into release
Conflicts:
drivers/acpi/sleep.c
This was a text conflict between
a2ef5c4fd44ce3922435139393b89f2cce47f576
(ACPI: Move module parameter gts and bfs to sleep.c)
which added #include <linux/module.h>
and
b24e5098853653554baf6ec975b9e855f3d6e5c0
(ACPI, PCI: Move acpi_dev_run_wake() to ACPI core)
which added #include <linux/pm_runtime.h>
The resolution was to take them both.
Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r-- | drivers/acpi/power.c | 166 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 7 | ||||
-rw-r--r-- | drivers/acpi/sleep.c | 35 | ||||
-rw-r--r-- | drivers/pci/pci-acpi.c | 40 | ||||
-rw-r--r-- | include/acpi/acpi_bus.h | 7 |
5 files changed, 216 insertions, 39 deletions
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 9ac2a9fa90ff..7049a7d27c4f 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c | |||
@@ -40,9 +40,11 @@ | |||
40 | #include <linux/init.h> | 40 | #include <linux/init.h> |
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 <acpi/acpi_bus.h> | 44 | #include <acpi/acpi_bus.h> |
44 | #include <acpi/acpi_drivers.h> | 45 | #include <acpi/acpi_drivers.h> |
45 | #include "sleep.h" | 46 | #include "sleep.h" |
47 | #include "internal.h" | ||
46 | 48 | ||
47 | #define PREFIX "ACPI: " | 49 | #define PREFIX "ACPI: " |
48 | 50 | ||
@@ -77,6 +79,20 @@ static struct acpi_driver acpi_power_driver = { | |||
77 | }, | 79 | }, |
78 | }; | 80 | }; |
79 | 81 | ||
82 | /* | ||
83 | * A power managed device | ||
84 | * A device may rely on multiple power resources. | ||
85 | * */ | ||
86 | struct acpi_power_managed_device { | ||
87 | struct device *dev; /* The physical device */ | ||
88 | acpi_handle *handle; | ||
89 | }; | ||
90 | |||
91 | struct acpi_power_resource_device { | ||
92 | struct acpi_power_managed_device *device; | ||
93 | struct acpi_power_resource_device *next; | ||
94 | }; | ||
95 | |||
80 | struct acpi_power_resource { | 96 | struct acpi_power_resource { |
81 | struct acpi_device * device; | 97 | struct acpi_device * device; |
82 | acpi_bus_id name; | 98 | acpi_bus_id name; |
@@ -84,6 +100,9 @@ struct acpi_power_resource { | |||
84 | u32 order; | 100 | u32 order; |
85 | unsigned int ref_count; | 101 | unsigned int ref_count; |
86 | struct mutex resource_lock; | 102 | struct mutex resource_lock; |
103 | |||
104 | /* List of devices relying on this power resource */ | ||
105 | struct acpi_power_resource_device *devices; | ||
87 | }; | 106 | }; |
88 | 107 | ||
89 | static struct list_head acpi_power_resource_list; | 108 | static struct list_head acpi_power_resource_list; |
@@ -183,8 +202,26 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) | |||
183 | return 0; | 202 | return 0; |
184 | } | 203 | } |
185 | 204 | ||
205 | /* Resume the device when all power resources in _PR0 are on */ | ||
206 | static void acpi_power_on_device(struct acpi_power_managed_device *device) | ||
207 | { | ||
208 | struct acpi_device *acpi_dev; | ||
209 | acpi_handle handle = device->handle; | ||
210 | int state; | ||
211 | |||
212 | if (acpi_bus_get_device(handle, &acpi_dev)) | ||
213 | return; | ||
214 | |||
215 | if(acpi_power_get_inferred_state(acpi_dev, &state)) | ||
216 | return; | ||
217 | |||
218 | if (state == ACPI_STATE_D0 && pm_runtime_suspended(device->dev)) | ||
219 | pm_request_resume(device->dev); | ||
220 | } | ||
221 | |||
186 | static int __acpi_power_on(struct acpi_power_resource *resource) | 222 | static int __acpi_power_on(struct acpi_power_resource *resource) |
187 | { | 223 | { |
224 | struct acpi_power_resource_device *device_list = resource->devices; | ||
188 | acpi_status status = AE_OK; | 225 | acpi_status status = AE_OK; |
189 | 226 | ||
190 | status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL); | 227 | status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL); |
@@ -197,6 +234,12 @@ static int __acpi_power_on(struct acpi_power_resource *resource) | |||
197 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned on\n", | 234 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned on\n", |
198 | resource->name)); | 235 | resource->name)); |
199 | 236 | ||
237 | while (device_list) { | ||
238 | acpi_power_on_device(device_list->device); | ||
239 | |||
240 | device_list = device_list->next; | ||
241 | } | ||
242 | |||
200 | return 0; | 243 | return 0; |
201 | } | 244 | } |
202 | 245 | ||
@@ -299,6 +342,125 @@ static int acpi_power_on_list(struct acpi_handle_list *list) | |||
299 | return result; | 342 | return result; |
300 | } | 343 | } |
301 | 344 | ||
345 | static void __acpi_power_resource_unregister_device(struct device *dev, | ||
346 | acpi_handle res_handle) | ||
347 | { | ||
348 | struct acpi_power_resource *resource = NULL; | ||
349 | struct acpi_power_resource_device *prev, *curr; | ||
350 | |||
351 | if (acpi_power_get_context(res_handle, &resource)) | ||
352 | return; | ||
353 | |||
354 | mutex_lock(&resource->resource_lock); | ||
355 | prev = NULL; | ||
356 | curr = resource->devices; | ||
357 | while (curr) { | ||
358 | if (curr->device->dev == dev) { | ||
359 | if (!prev) | ||
360 | resource->devices = curr->next; | ||
361 | else | ||
362 | prev->next = curr->next; | ||
363 | |||
364 | kfree(curr); | ||
365 | break; | ||
366 | } | ||
367 | |||
368 | prev = curr; | ||
369 | curr = curr->next; | ||
370 | } | ||
371 | mutex_unlock(&resource->resource_lock); | ||
372 | } | ||
373 | |||
374 | /* Unlink dev from all power resources in _PR0 */ | ||
375 | void acpi_power_resource_unregister_device(struct device *dev, acpi_handle handle) | ||
376 | { | ||
377 | struct acpi_device *acpi_dev; | ||
378 | struct acpi_handle_list *list; | ||
379 | int i; | ||
380 | |||
381 | if (!dev || !handle) | ||
382 | return; | ||
383 | |||
384 | if (acpi_bus_get_device(handle, &acpi_dev)) | ||
385 | return; | ||
386 | |||
387 | list = &acpi_dev->power.states[ACPI_STATE_D0].resources; | ||
388 | |||
389 | for (i = 0; i < list->count; i++) | ||
390 | __acpi_power_resource_unregister_device(dev, | ||
391 | list->handles[i]); | ||
392 | } | ||
393 | |||
394 | static int __acpi_power_resource_register_device( | ||
395 | struct acpi_power_managed_device *powered_device, acpi_handle handle) | ||
396 | { | ||
397 | struct acpi_power_resource *resource = NULL; | ||
398 | struct acpi_power_resource_device *power_resource_device; | ||
399 | int result; | ||
400 | |||
401 | result = acpi_power_get_context(handle, &resource); | ||
402 | if (result) | ||
403 | return result; | ||
404 | |||
405 | power_resource_device = kzalloc( | ||
406 | sizeof(*power_resource_device), GFP_KERNEL); | ||
407 | if (!power_resource_device) | ||
408 | return -ENOMEM; | ||
409 | |||
410 | power_resource_device->device = powered_device; | ||
411 | |||
412 | mutex_lock(&resource->resource_lock); | ||
413 | power_resource_device->next = resource->devices; | ||
414 | resource->devices = power_resource_device; | ||
415 | mutex_unlock(&resource->resource_lock); | ||
416 | |||
417 | return 0; | ||
418 | } | ||
419 | |||
420 | /* Link dev to all power resources in _PR0 */ | ||
421 | int acpi_power_resource_register_device(struct device *dev, acpi_handle handle) | ||
422 | { | ||
423 | struct acpi_device *acpi_dev; | ||
424 | struct acpi_handle_list *list; | ||
425 | struct acpi_power_managed_device *powered_device; | ||
426 | int i, ret; | ||
427 | |||
428 | if (!dev || !handle) | ||
429 | return -ENODEV; | ||
430 | |||
431 | ret = acpi_bus_get_device(handle, &acpi_dev); | ||
432 | if (ret) | ||
433 | goto no_power_resource; | ||
434 | |||
435 | if (!acpi_dev->power.flags.power_resources) | ||
436 | goto no_power_resource; | ||
437 | |||
438 | powered_device = kzalloc(sizeof(*powered_device), GFP_KERNEL); | ||
439 | if (!powered_device) | ||
440 | return -ENOMEM; | ||
441 | |||
442 | powered_device->dev = dev; | ||
443 | powered_device->handle = handle; | ||
444 | |||
445 | list = &acpi_dev->power.states[ACPI_STATE_D0].resources; | ||
446 | |||
447 | for (i = 0; i < list->count; i++) { | ||
448 | ret = __acpi_power_resource_register_device(powered_device, | ||
449 | list->handles[i]); | ||
450 | |||
451 | if (ret) { | ||
452 | acpi_power_resource_unregister_device(dev, handle); | ||
453 | break; | ||
454 | } | ||
455 | } | ||
456 | |||
457 | return ret; | ||
458 | |||
459 | no_power_resource: | ||
460 | printk(KERN_WARNING PREFIX "Invalid Power Resource to register!"); | ||
461 | return -ENODEV; | ||
462 | } | ||
463 | |||
302 | /** | 464 | /** |
303 | * acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in | 465 | * acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in |
304 | * ACPI 3.0) _PSW (Power State Wake) | 466 | * ACPI 3.0) _PSW (Power State Wake) |
@@ -500,14 +662,14 @@ int acpi_power_transition(struct acpi_device *device, int state) | |||
500 | { | 662 | { |
501 | int result; | 663 | int result; |
502 | 664 | ||
503 | if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3)) | 665 | if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD)) |
504 | return -EINVAL; | 666 | return -EINVAL; |
505 | 667 | ||
506 | if (device->power.state == state) | 668 | if (device->power.state == state) |
507 | return 0; | 669 | return 0; |
508 | 670 | ||
509 | if ((device->power.state < ACPI_STATE_D0) | 671 | if ((device->power.state < ACPI_STATE_D0) |
510 | || (device->power.state > ACPI_STATE_D3)) | 672 | || (device->power.state > ACPI_STATE_D3_COLD)) |
511 | return -ENODEV; | 673 | return -ENODEV; |
512 | 674 | ||
513 | /* TBD: Resources must be ordered. */ | 675 | /* TBD: Resources must be ordered. */ |
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 5d24a17aa854..767e2dcb9616 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -884,6 +884,13 @@ static int acpi_bus_get_power_flags(struct acpi_device *device) | |||
884 | acpi_bus_add_power_resource(ps->resources.handles[j]); | 884 | acpi_bus_add_power_resource(ps->resources.handles[j]); |
885 | } | 885 | } |
886 | 886 | ||
887 | /* The exist of _PR3 indicates D3Cold support */ | ||
888 | if (i == ACPI_STATE_D3) { | ||
889 | status = acpi_get_handle(device->handle, object_name, &handle); | ||
890 | if (ACPI_SUCCESS(status)) | ||
891 | device->power.states[ACPI_STATE_D3_COLD].flags.valid = 1; | ||
892 | } | ||
893 | |||
887 | /* Evaluate "_PSx" to see if we can do explicit sets */ | 894 | /* Evaluate "_PSx" to see if we can do explicit sets */ |
888 | object_name[2] = 'S'; | 895 | object_name[2] = 'S'; |
889 | status = acpi_get_handle(device->handle, object_name, &handle); | 896 | status = acpi_get_handle(device->handle, object_name, &handle); |
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index acf81fe86b53..1d661b5c3287 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/reboot.h> | 18 | #include <linux/reboot.h> |
19 | #include <linux/acpi.h> | 19 | #include <linux/acpi.h> |
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/pm_runtime.h> | ||
21 | 22 | ||
22 | #include <asm/io.h> | 23 | #include <asm/io.h> |
23 | 24 | ||
@@ -753,6 +754,40 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) | |||
753 | 754 | ||
754 | #ifdef CONFIG_PM_SLEEP | 755 | #ifdef CONFIG_PM_SLEEP |
755 | /** | 756 | /** |
757 | * acpi_pm_device_run_wake - Enable/disable wake-up for given device. | ||
758 | * @phys_dev: Device to enable/disable the platform to wake-up the system for. | ||
759 | * @enable: Whether enable or disable the wake-up functionality. | ||
760 | * | ||
761 | * Find the ACPI device object corresponding to @pci_dev and try to | ||
762 | * enable/disable the GPE associated with it. | ||
763 | */ | ||
764 | int acpi_pm_device_run_wake(struct device *phys_dev, bool enable) | ||
765 | { | ||
766 | struct acpi_device *dev; | ||
767 | acpi_handle handle; | ||
768 | |||
769 | if (!device_run_wake(phys_dev)) | ||
770 | return -EINVAL; | ||
771 | |||
772 | handle = DEVICE_ACPI_HANDLE(phys_dev); | ||
773 | if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &dev))) { | ||
774 | dev_dbg(phys_dev, "ACPI handle has no context in %s!\n", | ||
775 | __func__); | ||
776 | return -ENODEV; | ||
777 | } | ||
778 | |||
779 | if (enable) { | ||
780 | acpi_enable_wakeup_device_power(dev, ACPI_STATE_S0); | ||
781 | acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number); | ||
782 | } else { | ||
783 | acpi_disable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number); | ||
784 | acpi_disable_wakeup_device_power(dev); | ||
785 | } | ||
786 | |||
787 | return 0; | ||
788 | } | ||
789 | |||
790 | /** | ||
756 | * acpi_pm_device_sleep_wake - enable or disable the system wake-up | 791 | * acpi_pm_device_sleep_wake - enable or disable the system wake-up |
757 | * capability of given device | 792 | * capability of given device |
758 | * @dev: device to handle | 793 | * @dev: device to handle |
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 060fd22a1103..0f150f271c2a 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
@@ -277,40 +277,6 @@ static int acpi_pci_sleep_wake(struct pci_dev *dev, bool enable) | |||
277 | return 0; | 277 | return 0; |
278 | } | 278 | } |
279 | 279 | ||
280 | /** | ||
281 | * acpi_dev_run_wake - Enable/disable wake-up for given device. | ||
282 | * @phys_dev: Device to enable/disable the platform to wake-up the system for. | ||
283 | * @enable: Whether enable or disable the wake-up functionality. | ||
284 | * | ||
285 | * Find the ACPI device object corresponding to @pci_dev and try to | ||
286 | * enable/disable the GPE associated with it. | ||
287 | */ | ||
288 | static int acpi_dev_run_wake(struct device *phys_dev, bool enable) | ||
289 | { | ||
290 | struct acpi_device *dev; | ||
291 | acpi_handle handle; | ||
292 | |||
293 | if (!device_run_wake(phys_dev)) | ||
294 | return -EINVAL; | ||
295 | |||
296 | handle = DEVICE_ACPI_HANDLE(phys_dev); | ||
297 | if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &dev))) { | ||
298 | dev_dbg(phys_dev, "ACPI handle has no context in %s!\n", | ||
299 | __func__); | ||
300 | return -ENODEV; | ||
301 | } | ||
302 | |||
303 | if (enable) { | ||
304 | acpi_enable_wakeup_device_power(dev, ACPI_STATE_S0); | ||
305 | acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number); | ||
306 | } else { | ||
307 | acpi_disable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number); | ||
308 | acpi_disable_wakeup_device_power(dev); | ||
309 | } | ||
310 | |||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | static void acpi_pci_propagate_run_wake(struct pci_bus *bus, bool enable) | 280 | static void acpi_pci_propagate_run_wake(struct pci_bus *bus, bool enable) |
315 | { | 281 | { |
316 | while (bus->parent) { | 282 | while (bus->parent) { |
@@ -318,14 +284,14 @@ static void acpi_pci_propagate_run_wake(struct pci_bus *bus, bool enable) | |||
318 | 284 | ||
319 | if (bridge->pme_interrupt) | 285 | if (bridge->pme_interrupt) |
320 | return; | 286 | return; |
321 | if (!acpi_dev_run_wake(&bridge->dev, enable)) | 287 | if (!acpi_pm_device_run_wake(&bridge->dev, enable)) |
322 | return; | 288 | return; |
323 | bus = bus->parent; | 289 | bus = bus->parent; |
324 | } | 290 | } |
325 | 291 | ||
326 | /* We have reached the root bus. */ | 292 | /* We have reached the root bus. */ |
327 | if (bus->bridge) | 293 | if (bus->bridge) |
328 | acpi_dev_run_wake(bus->bridge, enable); | 294 | acpi_pm_device_run_wake(bus->bridge, enable); |
329 | } | 295 | } |
330 | 296 | ||
331 | static int acpi_pci_run_wake(struct pci_dev *dev, bool enable) | 297 | static int acpi_pci_run_wake(struct pci_dev *dev, bool enable) |
@@ -333,7 +299,7 @@ static int acpi_pci_run_wake(struct pci_dev *dev, bool enable) | |||
333 | if (dev->pme_interrupt) | 299 | if (dev->pme_interrupt) |
334 | return 0; | 300 | return 0; |
335 | 301 | ||
336 | if (!acpi_dev_run_wake(&dev->dev, enable)) | 302 | if (!acpi_pm_device_run_wake(&dev->dev, enable)) |
337 | return 0; | 303 | return 0; |
338 | 304 | ||
339 | acpi_pci_propagate_run_wake(dev->bus, enable); | 305 | acpi_pci_propagate_run_wake(dev->bus, enable); |
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 6cd5b6403a7b..f1c8ca60e824 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
@@ -323,6 +323,8 @@ int acpi_bus_set_power(acpi_handle handle, int state); | |||
323 | int acpi_bus_update_power(acpi_handle handle, int *state_p); | 323 | int acpi_bus_update_power(acpi_handle handle, int *state_p); |
324 | bool acpi_bus_power_manageable(acpi_handle handle); | 324 | bool acpi_bus_power_manageable(acpi_handle handle); |
325 | bool acpi_bus_can_wakeup(acpi_handle handle); | 325 | bool acpi_bus_can_wakeup(acpi_handle handle); |
326 | int acpi_power_resource_register_device(struct device *dev, acpi_handle handle); | ||
327 | void acpi_power_resource_unregister_device(struct device *dev, acpi_handle handle); | ||
326 | #ifdef CONFIG_ACPI_PROC_EVENT | 328 | #ifdef CONFIG_ACPI_PROC_EVENT |
327 | int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data); | 329 | int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data); |
328 | int acpi_bus_generate_proc_event4(const char *class, const char *bid, u8 type, int data); | 330 | int acpi_bus_generate_proc_event4(const char *class, const char *bid, u8 type, int data); |
@@ -392,8 +394,13 @@ static inline int acpi_pm_device_sleep_state(struct device *d, int *p) | |||
392 | #endif | 394 | #endif |
393 | 395 | ||
394 | #ifdef CONFIG_PM_SLEEP | 396 | #ifdef CONFIG_PM_SLEEP |
397 | int acpi_pm_device_run_wake(struct device *, bool); | ||
395 | int acpi_pm_device_sleep_wake(struct device *, bool); | 398 | int acpi_pm_device_sleep_wake(struct device *, bool); |
396 | #else | 399 | #else |
400 | static inline int acpi_pm_device_run_wake(struct device *dev, bool enable) | ||
401 | { | ||
402 | return -ENODEV; | ||
403 | } | ||
397 | static inline int acpi_pm_device_sleep_wake(struct device *dev, bool enable) | 404 | static inline int acpi_pm_device_sleep_wake(struct device *dev, bool enable) |
398 | { | 405 | { |
399 | return -ENODEV; | 406 | return -ENODEV; |