aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/power.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2011-01-06 17:38:57 -0500
committerLen Brown <len.brown@intel.com>2011-01-12 05:05:39 -0500
commitd0515d9fec68bace144fda57a69f4268fb875209 (patch)
tree5191b7e21adefacc8fdd8c5b45ae1fcdd03a5aa8 /drivers/acpi/power.c
parent36237fa0a711c309a38d7a7a9aed727e0eb76449 (diff)
ACPI / PM: Check status of power resources under mutexes
It certainly is not a good idea to execute _ON or _OFF and _STA for the same power resource at the same time which may happen in some circumstances in theory. To prevent that from happening, read the power state of each power resource under its mutex, as that will prevent the state from being changed at the same time. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/power.c')
-rw-r--r--drivers/acpi/power.c33
1 files changed, 20 insertions, 13 deletions
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index ac02af419b32..9ac2a9fa90ff 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -145,9 +145,8 @@ static int acpi_power_get_state(acpi_handle handle, int *state)
145 145
146static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) 146static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
147{ 147{
148 int result = 0, state1; 148 int cur_state;
149 u32 i = 0; 149 int i = 0;
150
151 150
152 if (!list || !state) 151 if (!list || !state)
153 return -EINVAL; 152 return -EINVAL;
@@ -155,25 +154,33 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
155 /* The state of the list is 'on' IFF all resources are 'on'. */ 154 /* The state of the list is 'on' IFF all resources are 'on'. */
156 155
157 for (i = 0; i < list->count; i++) { 156 for (i = 0; i < list->count; i++) {
158 /* 157 struct acpi_power_resource *resource;
159 * The state of the power resource can be obtained by 158 acpi_handle handle = list->handles[i];
160 * using the ACPI handle. In such case it is unnecessary to 159 int result;
161 * get the Power resource first and then get its state again. 160
162 */ 161 result = acpi_power_get_context(handle, &resource);
163 result = acpi_power_get_state(list->handles[i], &state1);
164 if (result) 162 if (result)
165 return result; 163 return result;
166 164
167 *state = state1; 165 mutex_lock(&resource->resource_lock);
168 166
169 if (*state != ACPI_POWER_RESOURCE_STATE_ON) 167 result = acpi_power_get_state(handle, &cur_state);
168
169 mutex_unlock(&resource->resource_lock);
170
171 if (result)
172 return result;
173
174 if (cur_state != ACPI_POWER_RESOURCE_STATE_ON)
170 break; 175 break;
171 } 176 }
172 177
173 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource list is %s\n", 178 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource list is %s\n",
174 *state ? "on" : "off")); 179 cur_state ? "on" : "off"));
175 180
176 return result; 181 *state = cur_state;
182
183 return 0;
177} 184}
178 185
179static int __acpi_power_on(struct acpi_power_resource *resource) 186static int __acpi_power_on(struct acpi_power_resource *resource)