|
@@ -266,6 +266,35 @@ static int acpi_power_off_device(acpi_handle handle)
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
+static void __acpi_power_off_list(struct acpi_handle_list *list, int num_res)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = num_res - 1; i >= 0 ; i--)
|
|
|
+ acpi_power_off_device(list->handles[i]);
|
|
|
+}
|
|
|
+
|
|
|
+static void acpi_power_off_list(struct acpi_handle_list *list)
|
|
|
+{
|
|
|
+ __acpi_power_off_list(list, list->count);
|
|
|
+}
|
|
|
+
|
|
|
+static int acpi_power_on_list(struct acpi_handle_list *list)
|
|
|
+{
|
|
|
+ int result = 0;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < list->count; i++) {
|
|
|
+ result = acpi_power_on(list->handles[i]);
|
|
|
+ if (result) {
|
|
|
+ __acpi_power_off_list(list, i);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in
|
|
|
* ACPI 3.0) _PSW (Power State Wake)
|
|
@@ -458,10 +487,7 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state)
|
|
|
|
|
|
int acpi_power_transition(struct acpi_device *device, int state)
|
|
|
{
|
|
|
- int result = 0;
|
|
|
- struct acpi_handle_list *cl = NULL; /* Current Resources */
|
|
|
- struct acpi_handle_list *tl = NULL; /* Target Resources */
|
|
|
- int i = 0;
|
|
|
+ int result;
|
|
|
|
|
|
if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3))
|
|
|
return -EINVAL;
|
|
@@ -473,37 +499,20 @@ int acpi_power_transition(struct acpi_device *device, int state)
|
|
|
|| (device->power.state > ACPI_STATE_D3))
|
|
|
return -ENODEV;
|
|
|
|
|
|
- cl = &device->power.states[device->power.state].resources;
|
|
|
- tl = &device->power.states[state].resources;
|
|
|
-
|
|
|
/* TBD: Resources must be ordered. */
|
|
|
|
|
|
/*
|
|
|
* First we reference all power resources required in the target list
|
|
|
- * (e.g. so the device doesn't lose power while transitioning).
|
|
|
+ * (e.g. so the device doesn't lose power while transitioning). Then,
|
|
|
+ * we dereference all power resources used in the current list.
|
|
|
*/
|
|
|
- for (i = 0; i < tl->count; i++) {
|
|
|
- result = acpi_power_on(tl->handles[i]);
|
|
|
- if (result)
|
|
|
- goto end;
|
|
|
- }
|
|
|
+ result = acpi_power_on_list(&device->power.states[state].resources);
|
|
|
+ if (!result)
|
|
|
+ acpi_power_off_list(
|
|
|
+ &device->power.states[device->power.state].resources);
|
|
|
|
|
|
- /*
|
|
|
- * Then we dereference all power resources used in the current list.
|
|
|
- */
|
|
|
- for (i = 0; i < cl->count; i++) {
|
|
|
- result = acpi_power_off_device(cl->handles[i]);
|
|
|
- if (result)
|
|
|
- goto end;
|
|
|
- }
|
|
|
-
|
|
|
- end:
|
|
|
- if (result)
|
|
|
- device->power.state = ACPI_STATE_UNKNOWN;
|
|
|
- else {
|
|
|
- /* We shouldn't change the state till all above operations succeed */
|
|
|
- device->power.state = state;
|
|
|
- }
|
|
|
+ /* We shouldn't change the state unless the above operations succeed. */
|
|
|
+ device->power.state = result ? ACPI_STATE_UNKNOWN : state;
|
|
|
|
|
|
return result;
|
|
|
}
|