aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-26 00:25:17 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-26 00:25:17 -0500
commitc41b3810c09e60664433548c5218cc6ece6a8903 (patch)
treecf9d822e3216d57a0ba3a184e9d586ad7bdf370c /drivers/acpi
parent556f12f602ac0a18a82ca83e9f8e8547688fc633 (diff)
parent4383822020c54c21eb2eb939a3233b44a51e8ca0 (diff)
Merge tag 'pm+acpi-fixes-3.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull ACPI and power management fixes from Rafael Wysocki: - Fixes for blackfin and microblaze build problems introduced by the removal of global pm_idle. From Lars-Peter Clausen. - OPP core build fix from Shawn Guo. - Error condition check fix for the new imx6q-cpufreq driver from Wei Yongjun. - Fix for an AER driver crash related to the lack of APEI initialization for acpi=off. From Rafael J Wysocki. - Fix for a USB breakage on Thinkpad T430 related to ACPI power resources and PCI wakeup from Rafael J. Wysocki. * tag 'pm+acpi-fixes-3.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: ACPI / PM: Take unusual configurations of power resources into account imx6q-cpufreq: fix return value check in imx6q_cpufreq_probe() PM / OPP: fix condition for empty of_init_opp_table() ACPI / APEI: Fix crash in apei_hest_parse() for acpi=off microblaze idle: Fix compile error blackfin idle: Fix compile error
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/apei/hest.c5
-rw-r--r--drivers/acpi/internal.h2
-rw-r--r--drivers/acpi/power.c112
-rw-r--r--drivers/acpi/scan.c9
4 files changed, 95 insertions, 33 deletions
diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c
index 7f00cf38098f..f5ef5d54e4ac 100644
--- a/drivers/acpi/apei/hest.c
+++ b/drivers/acpi/apei/hest.c
@@ -89,7 +89,7 @@ int apei_hest_parse(apei_hest_func_t func, void *data)
89 struct acpi_hest_header *hest_hdr; 89 struct acpi_hest_header *hest_hdr;
90 int i, rc, len; 90 int i, rc, len;
91 91
92 if (hest_disable) 92 if (hest_disable || !hest_tab)
93 return -EINVAL; 93 return -EINVAL;
94 94
95 hest_hdr = (struct acpi_hest_header *)(hest_tab + 1); 95 hest_hdr = (struct acpi_hest_header *)(hest_tab + 1);
@@ -216,9 +216,6 @@ void __init acpi_hest_init(void)
216 return; 216 return;
217 } 217 }
218 218
219 if (acpi_disabled)
220 goto err;
221
222 status = acpi_get_table(ACPI_SIG_HEST, 0, 219 status = acpi_get_table(ACPI_SIG_HEST, 0,
223 (struct acpi_table_header **)&hest_tab); 220 (struct acpi_table_header **)&hest_tab);
224 if (status == AE_NOT_FOUND) 221 if (status == AE_NOT_FOUND)
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index c8b70b5b2814..3c94a732b4b3 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -71,7 +71,7 @@ int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
71 struct list_head *list); 71 struct list_head *list);
72int acpi_add_power_resource(acpi_handle handle); 72int acpi_add_power_resource(acpi_handle handle);
73void acpi_power_add_remove_device(struct acpi_device *adev, bool add); 73void acpi_power_add_remove_device(struct acpi_device *adev, bool add);
74int acpi_power_min_system_level(struct list_head *list); 74int acpi_power_wakeup_list_init(struct list_head *list, int *system_level);
75int acpi_device_sleep_wake(struct acpi_device *dev, 75int acpi_device_sleep_wake(struct acpi_device *dev,
76 int enable, int sleep_state, int dev_state); 76 int enable, int sleep_state, int dev_state);
77int acpi_power_get_inferred_state(struct acpi_device *device, int *state); 77int acpi_power_get_inferred_state(struct acpi_device *device, int *state);
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index b820528a5fa3..34f5ef11d427 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -73,6 +73,7 @@ struct acpi_power_resource {
73 u32 system_level; 73 u32 system_level;
74 u32 order; 74 u32 order;
75 unsigned int ref_count; 75 unsigned int ref_count;
76 bool wakeup_enabled;
76 struct mutex resource_lock; 77 struct mutex resource_lock;
77}; 78};
78 79
@@ -272,11 +273,9 @@ static int __acpi_power_on(struct acpi_power_resource *resource)
272 return 0; 273 return 0;
273} 274}
274 275
275static int acpi_power_on(struct acpi_power_resource *resource) 276static int acpi_power_on_unlocked(struct acpi_power_resource *resource)
276{ 277{
277 int result = 0;; 278 int result = 0;
278
279 mutex_lock(&resource->resource_lock);
280 279
281 if (resource->ref_count++) { 280 if (resource->ref_count++) {
282 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 281 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -293,9 +292,16 @@ static int acpi_power_on(struct acpi_power_resource *resource)
293 schedule_work(&dep->work); 292 schedule_work(&dep->work);
294 } 293 }
295 } 294 }
295 return result;
296}
296 297
297 mutex_unlock(&resource->resource_lock); 298static int acpi_power_on(struct acpi_power_resource *resource)
299{
300 int result;
298 301
302 mutex_lock(&resource->resource_lock);
303 result = acpi_power_on_unlocked(resource);
304 mutex_unlock(&resource->resource_lock);
299 return result; 305 return result;
300} 306}
301 307
@@ -313,17 +319,15 @@ static int __acpi_power_off(struct acpi_power_resource *resource)
313 return 0; 319 return 0;
314} 320}
315 321
316static int acpi_power_off(struct acpi_power_resource *resource) 322static int acpi_power_off_unlocked(struct acpi_power_resource *resource)
317{ 323{
318 int result = 0; 324 int result = 0;
319 325
320 mutex_lock(&resource->resource_lock);
321
322 if (!resource->ref_count) { 326 if (!resource->ref_count) {
323 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 327 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
324 "Power resource [%s] already off", 328 "Power resource [%s] already off",
325 resource->name)); 329 resource->name));
326 goto unlock; 330 return 0;
327 } 331 }
328 332
329 if (--resource->ref_count) { 333 if (--resource->ref_count) {
@@ -335,10 +339,16 @@ static int acpi_power_off(struct acpi_power_resource *resource)
335 if (result) 339 if (result)
336 resource->ref_count++; 340 resource->ref_count++;
337 } 341 }
342 return result;
343}
338 344
339 unlock: 345static int acpi_power_off(struct acpi_power_resource *resource)
340 mutex_unlock(&resource->resource_lock); 346{
347 int result;
341 348
349 mutex_lock(&resource->resource_lock);
350 result = acpi_power_off_unlocked(resource);
351 mutex_unlock(&resource->resource_lock);
342 return result; 352 return result;
343} 353}
344 354
@@ -521,18 +531,35 @@ void acpi_power_add_remove_device(struct acpi_device *adev, bool add)
521 } 531 }
522} 532}
523 533
524int acpi_power_min_system_level(struct list_head *list) 534int acpi_power_wakeup_list_init(struct list_head *list, int *system_level_p)
525{ 535{
526 struct acpi_power_resource_entry *entry; 536 struct acpi_power_resource_entry *entry;
527 int system_level = 5; 537 int system_level = 5;
528 538
529 list_for_each_entry(entry, list, node) { 539 list_for_each_entry(entry, list, node) {
530 struct acpi_power_resource *resource = entry->resource; 540 struct acpi_power_resource *resource = entry->resource;
541 acpi_handle handle = resource->device.handle;
542 int result;
543 int state;
531 544
545 mutex_lock(&resource->resource_lock);
546
547 result = acpi_power_get_state(handle, &state);
548 if (result) {
549 mutex_unlock(&resource->resource_lock);
550 return result;
551 }
552 if (state == ACPI_POWER_RESOURCE_STATE_ON) {
553 resource->ref_count++;
554 resource->wakeup_enabled = true;
555 }
532 if (system_level > resource->system_level) 556 if (system_level > resource->system_level)
533 system_level = resource->system_level; 557 system_level = resource->system_level;
558
559 mutex_unlock(&resource->resource_lock);
534 } 560 }
535 return system_level; 561 *system_level_p = system_level;
562 return 0;
536} 563}
537 564
538/* -------------------------------------------------------------------------- 565/* --------------------------------------------------------------------------
@@ -610,6 +637,7 @@ int acpi_device_sleep_wake(struct acpi_device *dev,
610 */ 637 */
611int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) 638int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
612{ 639{
640 struct acpi_power_resource_entry *entry;
613 int err = 0; 641 int err = 0;
614 642
615 if (!dev || !dev->wakeup.flags.valid) 643 if (!dev || !dev->wakeup.flags.valid)
@@ -620,17 +648,31 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
620 if (dev->wakeup.prepare_count++) 648 if (dev->wakeup.prepare_count++)
621 goto out; 649 goto out;
622 650
623 err = acpi_power_on_list(&dev->wakeup.resources); 651 list_for_each_entry(entry, &dev->wakeup.resources, node) {
624 if (err) { 652 struct acpi_power_resource *resource = entry->resource;
625 dev_err(&dev->dev, "Cannot turn wakeup power resources on\n"); 653
626 dev->wakeup.flags.valid = 0; 654 mutex_lock(&resource->resource_lock);
627 } else { 655
628 /* 656 if (!resource->wakeup_enabled) {
629 * Passing 3 as the third argument below means the device may be 657 err = acpi_power_on_unlocked(resource);
630 * put into arbitrary power state afterward. 658 if (!err)
631 */ 659 resource->wakeup_enabled = true;
632 err = acpi_device_sleep_wake(dev, 1, sleep_state, 3); 660 }
661
662 mutex_unlock(&resource->resource_lock);
663
664 if (err) {
665 dev_err(&dev->dev,
666 "Cannot turn wakeup power resources on\n");
667 dev->wakeup.flags.valid = 0;
668 goto out;
669 }
633 } 670 }
671 /*
672 * Passing 3 as the third argument below means the device may be
673 * put into arbitrary power state afterward.
674 */
675 err = acpi_device_sleep_wake(dev, 1, sleep_state, 3);
634 if (err) 676 if (err)
635 dev->wakeup.prepare_count = 0; 677 dev->wakeup.prepare_count = 0;
636 678
@@ -647,6 +689,7 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
647 */ 689 */
648int acpi_disable_wakeup_device_power(struct acpi_device *dev) 690int acpi_disable_wakeup_device_power(struct acpi_device *dev)
649{ 691{
692 struct acpi_power_resource_entry *entry;
650 int err = 0; 693 int err = 0;
651 694
652 if (!dev || !dev->wakeup.flags.valid) 695 if (!dev || !dev->wakeup.flags.valid)
@@ -668,10 +711,25 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
668 if (err) 711 if (err)
669 goto out; 712 goto out;
670 713
671 err = acpi_power_off_list(&dev->wakeup.resources); 714 list_for_each_entry(entry, &dev->wakeup.resources, node) {
672 if (err) { 715 struct acpi_power_resource *resource = entry->resource;
673 dev_err(&dev->dev, "Cannot turn wakeup power resources off\n"); 716
674 dev->wakeup.flags.valid = 0; 717 mutex_lock(&resource->resource_lock);
718
719 if (resource->wakeup_enabled) {
720 err = acpi_power_off_unlocked(resource);
721 if (!err)
722 resource->wakeup_enabled = false;
723 }
724
725 mutex_unlock(&resource->resource_lock);
726
727 if (err) {
728 dev_err(&dev->dev,
729 "Cannot turn wakeup power resources off\n");
730 dev->wakeup.flags.valid = 0;
731 break;
732 }
675 } 733 }
676 734
677 out: 735 out:
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 4be408756adc..5e7e991717d7 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1002,7 +1002,14 @@ static int acpi_bus_extract_wakeup_device_power_package(acpi_handle handle,
1002 if (!list_empty(&wakeup->resources)) { 1002 if (!list_empty(&wakeup->resources)) {
1003 int sleep_state; 1003 int sleep_state;
1004 1004
1005 sleep_state = acpi_power_min_system_level(&wakeup->resources); 1005 err = acpi_power_wakeup_list_init(&wakeup->resources,
1006 &sleep_state);
1007 if (err) {
1008 acpi_handle_warn(handle, "Retrieving current states "
1009 "of wakeup power resources failed\n");
1010 acpi_power_resources_list_free(&wakeup->resources);
1011 goto out;
1012 }
1006 if (sleep_state < wakeup->sleep_state) { 1013 if (sleep_state < wakeup->sleep_state) {
1007 acpi_handle_warn(handle, "Overriding _PRW sleep state " 1014 acpi_handle_warn(handle, "Overriding _PRW sleep state "
1008 "(S%d) by S%d from power resources\n", 1015 "(S%d) by S%d from power resources\n",