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.c45
1 files changed, 38 insertions, 7 deletions
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index e0bcfb642b52..93eac53b5110 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -684,7 +684,8 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state)
684 } 684 }
685 } 685 }
686 686
687 *state = ACPI_STATE_D3_COLD; 687 *state = device->power.states[ACPI_STATE_D3_COLD].flags.valid ?
688 ACPI_STATE_D3_COLD : ACPI_STATE_D3_HOT;
688 return 0; 689 return 0;
689} 690}
690 691
@@ -710,8 +711,6 @@ int acpi_power_transition(struct acpi_device *device, int state)
710 || (device->power.state > ACPI_STATE_D3_COLD)) 711 || (device->power.state > ACPI_STATE_D3_COLD))
711 return -ENODEV; 712 return -ENODEV;
712 713
713 /* TBD: Resources must be ordered. */
714
715 /* 714 /*
716 * First we reference all power resources required in the target list 715 * First we reference all power resources required in the target list
717 * (e.g. so the device doesn't lose power while transitioning). Then, 716 * (e.g. so the device doesn't lose power while transitioning). Then,
@@ -761,6 +760,25 @@ static void acpi_power_sysfs_remove(struct acpi_device *device)
761 device_remove_file(&device->dev, &dev_attr_resource_in_use); 760 device_remove_file(&device->dev, &dev_attr_resource_in_use);
762} 761}
763 762
763static void acpi_power_add_resource_to_list(struct acpi_power_resource *resource)
764{
765 mutex_lock(&power_resource_list_lock);
766
767 if (!list_empty(&acpi_power_resource_list)) {
768 struct acpi_power_resource *r;
769
770 list_for_each_entry(r, &acpi_power_resource_list, list_node)
771 if (r->order > resource->order) {
772 list_add_tail(&resource->list_node, &r->list_node);
773 goto out;
774 }
775 }
776 list_add_tail(&resource->list_node, &acpi_power_resource_list);
777
778 out:
779 mutex_unlock(&power_resource_list_lock);
780}
781
764int acpi_add_power_resource(acpi_handle handle) 782int acpi_add_power_resource(acpi_handle handle)
765{ 783{
766 struct acpi_power_resource *resource; 784 struct acpi_power_resource *resource;
@@ -811,9 +829,7 @@ int acpi_add_power_resource(acpi_handle handle)
811 if (!device_create_file(&device->dev, &dev_attr_resource_in_use)) 829 if (!device_create_file(&device->dev, &dev_attr_resource_in_use))
812 device->remove = acpi_power_sysfs_remove; 830 device->remove = acpi_power_sysfs_remove;
813 831
814 mutex_lock(&power_resource_list_lock); 832 acpi_power_add_resource_to_list(resource);
815 list_add(&resource->list_node, &acpi_power_resource_list);
816 mutex_unlock(&power_resource_list_lock);
817 acpi_device_add_finalize(device); 833 acpi_device_add_finalize(device);
818 return 0; 834 return 0;
819 835
@@ -844,7 +860,22 @@ void acpi_resume_power_resources(void)
844 && resource->ref_count) { 860 && resource->ref_count) {
845 dev_info(&resource->device.dev, "Turning ON\n"); 861 dev_info(&resource->device.dev, "Turning ON\n");
846 __acpi_power_on(resource); 862 __acpi_power_on(resource);
847 } else if (state == ACPI_POWER_RESOURCE_STATE_ON 863 }
864
865 mutex_unlock(&resource->resource_lock);
866 }
867 list_for_each_entry_reverse(resource, &acpi_power_resource_list, list_node) {
868 int result, state;
869
870 mutex_lock(&resource->resource_lock);
871
872 result = acpi_power_get_state(resource->device.handle, &state);
873 if (result) {
874 mutex_unlock(&resource->resource_lock);
875 continue;
876 }
877
878 if (state == ACPI_POWER_RESOURCE_STATE_ON
848 && !resource->ref_count) { 879 && !resource->ref_count) {
849 dev_info(&resource->device.dev, "Turning OFF\n"); 880 dev_info(&resource->device.dev, "Turning OFF\n");
850 __acpi_power_off(resource); 881 __acpi_power_off(resource);