aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/bus.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2010-11-24 18:09:15 -0500
committerLen Brown <len.brown@intel.com>2011-01-12 04:48:45 -0500
commit25eed40720fc9005c63a1f436e5f8a78836c26ff (patch)
tree2c927e50d57c2e456d9ceaa575c1bb774627ee10 /drivers/acpi/bus.c
parentade3e7fef794781c0798d0cf0f046123842ba550 (diff)
ACPI / PM: Add function for updating device power state consistently
Add function acpi_bus_update_power() for reading the actual power state of an ACPI device and updating its device->power.state field in such a way that its power resources' reference counters will remain consistent with that field. For this purpose introduce __acpi_bus_set_power() setting the power state of an ACPI device without updating its device->power.state field and make acpi_bus_set_power() and acpi_bus_update_power() use it (acpi_bus_set_power() retains the current behavior for now). Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/bus.c')
-rw-r--r--drivers/acpi/bus.c90
1 files changed, 61 insertions, 29 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 453451090502..19decee72e92 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -255,44 +255,17 @@ int acpi_bus_get_power(acpi_handle handle, int *state)
255EXPORT_SYMBOL(acpi_bus_get_power); 255EXPORT_SYMBOL(acpi_bus_get_power);
256 256
257 257
258int acpi_bus_set_power(acpi_handle handle, int state) 258static int __acpi_bus_set_power(struct acpi_device *device, int state)
259{ 259{
260 int result = 0; 260 int result = 0;
261 acpi_status status = AE_OK; 261 acpi_status status = AE_OK;
262 struct acpi_device *device = NULL;
263 char object_name[5] = { '_', 'P', 'S', '0' + state, '\0' }; 262 char object_name[5] = { '_', 'P', 'S', '0' + state, '\0' };
264 263
265 264 if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3))
266 result = acpi_bus_get_device(handle, &device);
267 if (result)
268 return result;
269
270 if ((state < ACPI_STATE_D0) || (state > ACPI_STATE_D3))
271 return -EINVAL; 265 return -EINVAL;
272 266
273 /* Make sure this is a valid target state */ 267 /* Make sure this is a valid target state */
274 268
275 if (!device->flags.power_manageable) {
276 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable\n",
277 kobject_name(&device->dev.kobj)));
278 return -ENODEV;
279 }
280 /*
281 * Get device's current power state
282 */
283 if (!acpi_power_nocheck) {
284 /*
285 * Maybe the incorrect power state is returned on the bogus
286 * bios, which is different with the real power state.
287 * For example: the bios returns D0 state and the real power
288 * state is D3. OS expects to set the device to D0 state. In
289 * such case if OS uses the power state returned by the BIOS,
290 * the device can't be transisted to the correct power state.
291 * So if the acpi_power_nocheck is set, it is unnecessary to
292 * get the power state by calling acpi_bus_get_power.
293 */
294 acpi_bus_get_power(device->handle, &device->power.state);
295 }
296 if ((state == device->power.state) && !device->flags.force_power_state) { 269 if ((state == device->power.state) && !device->flags.force_power_state) {
297 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", 270 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n",
298 state)); 271 state));
@@ -362,6 +335,42 @@ int acpi_bus_set_power(acpi_handle handle, int state)
362 return result; 335 return result;
363} 336}
364 337
338
339int acpi_bus_set_power(acpi_handle handle, int state)
340{
341 struct acpi_device *device;
342 int result;
343
344 result = acpi_bus_get_device(handle, &device);
345 if (result)
346 return result;
347
348 if (!device->flags.power_manageable) {
349 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
350 "Device [%s] is not power manageable\n",
351 dev_name(&device->dev)));
352 return -ENODEV;
353 }
354
355 /*
356 * Get device's current power state
357 */
358 if (!acpi_power_nocheck) {
359 /*
360 * Maybe the incorrect power state is returned on the bogus
361 * bios, which is different with the real power state.
362 * For example: the bios returns D0 state and the real power
363 * state is D3. OS expects to set the device to D0 state. In
364 * such case if OS uses the power state returned by the BIOS,
365 * the device can't be transisted to the correct power state.
366 * So if the acpi_power_nocheck is set, it is unnecessary to
367 * get the power state by calling acpi_bus_get_power.
368 */
369 __acpi_bus_get_power(device, &device->power.state);
370 }
371
372 return __acpi_bus_set_power(device, state);
373}
365EXPORT_SYMBOL(acpi_bus_set_power); 374EXPORT_SYMBOL(acpi_bus_set_power);
366 375
367 376
@@ -389,6 +398,29 @@ int acpi_bus_init_power(struct acpi_device *device)
389} 398}
390 399
391 400
401int acpi_bus_update_power(acpi_handle handle, int *state_p)
402{
403 struct acpi_device *device;
404 int state;
405 int result;
406
407 result = acpi_bus_get_device(handle, &device);
408 if (result)
409 return result;
410
411 result = __acpi_bus_get_power(device, &state);
412 if (result)
413 return result;
414
415 result = __acpi_bus_set_power(device, state);
416 if (!result && state_p)
417 *state_p = state;
418
419 return result;
420}
421EXPORT_SYMBOL_GPL(acpi_bus_update_power);
422
423
392bool acpi_bus_power_manageable(acpi_handle handle) 424bool acpi_bus_power_manageable(acpi_handle handle)
393{ 425{
394 struct acpi_device *device; 426 struct acpi_device *device;