diff options
Diffstat (limited to 'drivers/acpi/power.c')
-rw-r--r-- | drivers/acpi/power.c | 91 |
1 files changed, 33 insertions, 58 deletions
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index b12933fd2e56..29803857a2ef 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c | |||
@@ -58,27 +58,6 @@ ACPI_MODULE_NAME("power"); | |||
58 | #define ACPI_POWER_RESOURCE_STATE_ON 0x01 | 58 | #define ACPI_POWER_RESOURCE_STATE_ON 0x01 |
59 | #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF | 59 | #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF |
60 | 60 | ||
61 | static inline int acpi_power_add(struct acpi_device *device) { return 0; } | ||
62 | |||
63 | static const struct acpi_device_id power_device_ids[] = { | ||
64 | {ACPI_POWER_HID, 0}, | ||
65 | {"", 0}, | ||
66 | }; | ||
67 | MODULE_DEVICE_TABLE(acpi, power_device_ids); | ||
68 | |||
69 | #ifdef CONFIG_PM_SLEEP | ||
70 | static int acpi_power_resume(struct device *dev); | ||
71 | #endif | ||
72 | static SIMPLE_DEV_PM_OPS(acpi_power_pm, NULL, acpi_power_resume); | ||
73 | |||
74 | static struct acpi_driver acpi_power_driver = { | ||
75 | .name = "power", | ||
76 | .class = ACPI_POWER_CLASS, | ||
77 | .ids = power_device_ids, | ||
78 | .ops.add = acpi_power_add, | ||
79 | .drv.pm = &acpi_power_pm, | ||
80 | }; | ||
81 | |||
82 | struct acpi_power_dependent_device { | 61 | struct acpi_power_dependent_device { |
83 | struct list_head node; | 62 | struct list_head node; |
84 | struct acpi_device *adev; | 63 | struct acpi_device *adev; |
@@ -87,6 +66,7 @@ struct acpi_power_dependent_device { | |||
87 | 66 | ||
88 | struct acpi_power_resource { | 67 | struct acpi_power_resource { |
89 | struct acpi_device device; | 68 | struct acpi_device device; |
69 | struct list_head list_node; | ||
90 | struct list_head dependent; | 70 | struct list_head dependent; |
91 | char *name; | 71 | char *name; |
92 | u32 system_level; | 72 | u32 system_level; |
@@ -95,7 +75,8 @@ struct acpi_power_resource { | |||
95 | struct mutex resource_lock; | 75 | struct mutex resource_lock; |
96 | }; | 76 | }; |
97 | 77 | ||
98 | static struct list_head acpi_power_resource_list; | 78 | static LIST_HEAD(acpi_power_resource_list); |
79 | static DEFINE_MUTEX(power_resource_list_lock); | ||
99 | 80 | ||
100 | /* -------------------------------------------------------------------------- | 81 | /* -------------------------------------------------------------------------- |
101 | Power Resource Management | 82 | Power Resource Management |
@@ -643,8 +624,13 @@ static void acpi_release_power_resource(struct device *dev) | |||
643 | struct acpi_device *device = to_acpi_device(dev); | 624 | struct acpi_device *device = to_acpi_device(dev); |
644 | struct acpi_power_resource *resource; | 625 | struct acpi_power_resource *resource; |
645 | 626 | ||
646 | acpi_free_ids(device); | ||
647 | resource = container_of(device, struct acpi_power_resource, device); | 627 | resource = container_of(device, struct acpi_power_resource, device); |
628 | |||
629 | mutex_lock(&power_resource_list_lock); | ||
630 | list_del(&resource->list_node); | ||
631 | mutex_unlock(&power_resource_list_lock); | ||
632 | |||
633 | acpi_free_ids(device); | ||
648 | kfree(resource); | 634 | kfree(resource); |
649 | } | 635 | } |
650 | 636 | ||
@@ -677,14 +663,14 @@ void acpi_add_power_resource(acpi_handle handle) | |||
677 | /* Evalute the object to get the system level and resource order. */ | 663 | /* Evalute the object to get the system level and resource order. */ |
678 | status = acpi_evaluate_object(handle, NULL, NULL, &buffer); | 664 | status = acpi_evaluate_object(handle, NULL, NULL, &buffer); |
679 | if (ACPI_FAILURE(status)) | 665 | if (ACPI_FAILURE(status)) |
680 | goto out; | 666 | goto err; |
681 | 667 | ||
682 | resource->system_level = acpi_object.power_resource.system_level; | 668 | resource->system_level = acpi_object.power_resource.system_level; |
683 | resource->order = acpi_object.power_resource.resource_order; | 669 | resource->order = acpi_object.power_resource.resource_order; |
684 | 670 | ||
685 | result = acpi_power_get_state(handle, &state); | 671 | result = acpi_power_get_state(handle, &state); |
686 | if (result) | 672 | if (result) |
687 | goto out; | 673 | goto err; |
688 | 674 | ||
689 | switch (state) { | 675 | switch (state) { |
690 | case ACPI_POWER_RESOURCE_STATE_ON: | 676 | case ACPI_POWER_RESOURCE_STATE_ON: |
@@ -702,51 +688,40 @@ void acpi_add_power_resource(acpi_handle handle) | |||
702 | 688 | ||
703 | device->flags.match_driver = true; | 689 | device->flags.match_driver = true; |
704 | result = acpi_device_register(device, acpi_release_power_resource); | 690 | result = acpi_device_register(device, acpi_release_power_resource); |
705 | |||
706 | out: | ||
707 | if (result) | 691 | if (result) |
708 | acpi_release_power_resource(&device->dev); | 692 | goto err; |
709 | 693 | ||
694 | mutex_lock(&power_resource_list_lock); | ||
695 | list_add(&resource->list_node, &acpi_power_resource_list); | ||
696 | mutex_unlock(&power_resource_list_lock); | ||
710 | return; | 697 | return; |
711 | } | ||
712 | 698 | ||
713 | /* -------------------------------------------------------------------------- | 699 | err: |
714 | Driver Interface | 700 | acpi_release_power_resource(&device->dev); |
715 | -------------------------------------------------------------------------- */ | 701 | } |
716 | 702 | ||
717 | #ifdef CONFIG_PM_SLEEP | 703 | #ifdef CONFIG_ACPI_SLEEP |
718 | static int acpi_power_resume(struct device *dev) | 704 | void acpi_resume_power_resources(void) |
719 | { | 705 | { |
720 | int result = 0, state; | ||
721 | struct acpi_device *device; | ||
722 | struct acpi_power_resource *resource; | 706 | struct acpi_power_resource *resource; |
723 | 707 | ||
724 | if (!dev) | 708 | mutex_lock(&power_resource_list_lock); |
725 | return -EINVAL; | ||
726 | 709 | ||
727 | device = to_acpi_device(dev); | 710 | list_for_each_entry(resource, &acpi_power_resource_list, list_node) { |
728 | resource = acpi_driver_data(device); | 711 | int result, state; |
729 | if (!resource) | ||
730 | return -EINVAL; | ||
731 | |||
732 | mutex_lock(&resource->resource_lock); | ||
733 | 712 | ||
734 | result = acpi_power_get_state(device->handle, &state); | 713 | mutex_lock(&resource->resource_lock); |
735 | if (result) | ||
736 | goto unlock; | ||
737 | 714 | ||
738 | if (state == ACPI_POWER_RESOURCE_STATE_OFF && resource->ref_count) | 715 | result = acpi_power_get_state(resource->device.handle, &state); |
739 | result = __acpi_power_on(resource); | 716 | if (!result && state == ACPI_POWER_RESOURCE_STATE_OFF |
717 | && resource->ref_count) { | ||
718 | dev_info(&resource->device.dev, "Turning ON\n"); | ||
719 | __acpi_power_on(resource); | ||
720 | } | ||
740 | 721 | ||
741 | unlock: | 722 | mutex_unlock(&resource->resource_lock); |
742 | mutex_unlock(&resource->resource_lock); | 723 | } |
743 | 724 | ||
744 | return result; | 725 | mutex_unlock(&power_resource_list_lock); |
745 | } | 726 | } |
746 | #endif | 727 | #endif |
747 | |||
748 | int __init acpi_power_init(void) | ||
749 | { | ||
750 | INIT_LIST_HEAD(&acpi_power_resource_list); | ||
751 | return acpi_bus_register_driver(&acpi_power_driver); | ||
752 | } | ||