aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/power.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-01-17 08:11:07 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-01-17 08:11:07 -0500
commite88c9c603b2ad0cd0fbe90afedba3f1becbbeb79 (patch)
tree55b9f2e2af6547cbb1eab54371a674356a12ba87 /drivers/acpi/power.c
parentef85bdbec444b42775a18580c6bfe1307a63ef0f (diff)
ACPI: Take power resource initialization errors into account
Some ACPI power resource initialization errors, like memory allocation errors, are not taken into account appropriately in some cases, which may lead to a device having an incomplete list of power resources that one of its power states depends on, for one example. Rework the power resource initialization and namespace scanning code so that power resource initialization errors are treated more seriously. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/power.c')
-rw-r--r--drivers/acpi/power.c44
1 files changed, 25 insertions, 19 deletions
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 4b93c97aff9f..1600f753fafe 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -97,18 +97,18 @@ static struct acpi_power_resource *acpi_power_get_context(acpi_handle handle)
97 return container_of(device, struct acpi_power_resource, device); 97 return container_of(device, struct acpi_power_resource, device);
98} 98}
99 99
100static void acpi_power_resources_list_add(acpi_handle handle, 100static int acpi_power_resources_list_add(acpi_handle handle,
101 struct list_head *list) 101 struct list_head *list)
102{ 102{
103 struct acpi_power_resource *resource = acpi_power_get_context(handle); 103 struct acpi_power_resource *resource = acpi_power_get_context(handle);
104 struct acpi_power_resource_entry *entry; 104 struct acpi_power_resource_entry *entry;
105 105
106 if (!resource || !list) 106 if (!resource || !list)
107 return; 107 return -EINVAL;
108 108
109 entry = kzalloc(sizeof(*entry), GFP_KERNEL); 109 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
110 if (!entry) 110 if (!entry)
111 return; 111 return -ENOMEM;
112 112
113 entry->resource = resource; 113 entry->resource = resource;
114 if (!list_empty(list)) { 114 if (!list_empty(list)) {
@@ -117,10 +117,11 @@ static void acpi_power_resources_list_add(acpi_handle handle,
117 list_for_each_entry(e, list, node) 117 list_for_each_entry(e, list, node)
118 if (e->resource->order > resource->order) { 118 if (e->resource->order > resource->order) {
119 list_add_tail(&entry->node, &e->node); 119 list_add_tail(&entry->node, &e->node);
120 return; 120 return 0;
121 } 121 }
122 } 122 }
123 list_add_tail(&entry->node, list); 123 list_add_tail(&entry->node, list);
124 return 0;
124} 125}
125 126
126void acpi_power_resources_list_free(struct list_head *list) 127void acpi_power_resources_list_free(struct list_head *list)
@@ -133,33 +134,37 @@ void acpi_power_resources_list_free(struct list_head *list)
133 } 134 }
134} 135}
135 136
136acpi_status acpi_extract_power_resources(union acpi_object *package, 137int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
137 unsigned int start, 138 struct list_head *list)
138 struct list_head *list)
139{ 139{
140 acpi_status status = AE_OK;
141 unsigned int i; 140 unsigned int i;
141 int err = 0;
142 142
143 for (i = start; i < package->package.count; i++) { 143 for (i = start; i < package->package.count; i++) {
144 union acpi_object *element = &package->package.elements[i]; 144 union acpi_object *element = &package->package.elements[i];
145 acpi_handle rhandle; 145 acpi_handle rhandle;
146 146
147 if (element->type != ACPI_TYPE_LOCAL_REFERENCE) { 147 if (element->type != ACPI_TYPE_LOCAL_REFERENCE) {
148 status = AE_BAD_DATA; 148 err = -ENODATA;
149 break; 149 break;
150 } 150 }
151 rhandle = element->reference.handle; 151 rhandle = element->reference.handle;
152 if (!rhandle) { 152 if (!rhandle) {
153 status = AE_NULL_ENTRY; 153 err = -ENODEV;
154 break; 154 break;
155 } 155 }
156 acpi_add_power_resource(rhandle); 156 err = acpi_add_power_resource(rhandle);
157 acpi_power_resources_list_add(rhandle, list); 157 if (err)
158 break;
159
160 err = acpi_power_resources_list_add(rhandle, list);
161 if (err)
162 break;
158 } 163 }
159 if (ACPI_FAILURE(status)) 164 if (err)
160 acpi_power_resources_list_free(list); 165 acpi_power_resources_list_free(list);
161 166
162 return status; 167 return err;
163} 168}
164 169
165static int acpi_power_get_state(acpi_handle handle, int *state) 170static int acpi_power_get_state(acpi_handle handle, int *state)
@@ -662,7 +667,7 @@ static void acpi_release_power_resource(struct device *dev)
662 kfree(resource); 667 kfree(resource);
663} 668}
664 669
665void acpi_add_power_resource(acpi_handle handle) 670int acpi_add_power_resource(acpi_handle handle)
666{ 671{
667 struct acpi_power_resource *resource; 672 struct acpi_power_resource *resource;
668 struct acpi_device *device = NULL; 673 struct acpi_device *device = NULL;
@@ -673,11 +678,11 @@ void acpi_add_power_resource(acpi_handle handle)
673 678
674 acpi_bus_get_device(handle, &device); 679 acpi_bus_get_device(handle, &device);
675 if (device) 680 if (device)
676 return; 681 return 0;
677 682
678 resource = kzalloc(sizeof(*resource), GFP_KERNEL); 683 resource = kzalloc(sizeof(*resource), GFP_KERNEL);
679 if (!resource) 684 if (!resource)
680 return; 685 return -ENOMEM;
681 686
682 device = &resource->device; 687 device = &resource->device;
683 acpi_init_device_object(device, handle, ACPI_BUS_TYPE_POWER, 688 acpi_init_device_object(device, handle, ACPI_BUS_TYPE_POWER,
@@ -712,10 +717,11 @@ void acpi_add_power_resource(acpi_handle handle)
712 mutex_lock(&power_resource_list_lock); 717 mutex_lock(&power_resource_list_lock);
713 list_add(&resource->list_node, &acpi_power_resource_list); 718 list_add(&resource->list_node, &acpi_power_resource_list);
714 mutex_unlock(&power_resource_list_lock); 719 mutex_unlock(&power_resource_list_lock);
715 return; 720 return 0;
716 721
717 err: 722 err:
718 acpi_release_power_resource(&device->dev); 723 acpi_release_power_resource(&device->dev);
724 return result;
719} 725}
720 726
721#ifdef CONFIG_ACPI_SLEEP 727#ifdef CONFIG_ACPI_SLEEP