diff options
Diffstat (limited to 'drivers/acpi/power.c')
| -rw-r--r-- | drivers/acpi/power.c | 74 |
1 files changed, 48 insertions, 26 deletions
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 4ab21cb1c8c..a1718e56103 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c | |||
| @@ -54,6 +54,14 @@ ACPI_MODULE_NAME("power"); | |||
| 54 | #define ACPI_POWER_RESOURCE_STATE_OFF 0x00 | 54 | #define ACPI_POWER_RESOURCE_STATE_OFF 0x00 |
| 55 | #define ACPI_POWER_RESOURCE_STATE_ON 0x01 | 55 | #define ACPI_POWER_RESOURCE_STATE_ON 0x01 |
| 56 | #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF | 56 | #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF |
| 57 | |||
| 58 | #ifdef MODULE_PARAM_PREFIX | ||
| 59 | #undef MODULE_PARAM_PREFIX | ||
| 60 | #endif | ||
| 61 | #define MODULE_PARAM_PREFIX "acpi." | ||
| 62 | int acpi_power_nocheck; | ||
| 63 | module_param_named(power_nocheck, acpi_power_nocheck, bool, 000); | ||
| 64 | |||
| 57 | static int acpi_power_add(struct acpi_device *device); | 65 | static int acpi_power_add(struct acpi_device *device); |
| 58 | static int acpi_power_remove(struct acpi_device *device, int type); | 66 | static int acpi_power_remove(struct acpi_device *device, int type); |
| 59 | static int acpi_power_resume(struct acpi_device *device); | 67 | static int acpi_power_resume(struct acpi_device *device); |
| @@ -128,16 +136,16 @@ acpi_power_get_context(acpi_handle handle, | |||
| 128 | return 0; | 136 | return 0; |
| 129 | } | 137 | } |
| 130 | 138 | ||
| 131 | static int acpi_power_get_state(struct acpi_power_resource *resource, int *state) | 139 | static int acpi_power_get_state(acpi_handle handle, int *state) |
| 132 | { | 140 | { |
| 133 | acpi_status status = AE_OK; | 141 | acpi_status status = AE_OK; |
| 134 | unsigned long sta = 0; | 142 | unsigned long long sta = 0; |
| 135 | 143 | ||
| 136 | 144 | ||
| 137 | if (!resource || !state) | 145 | if (!handle || !state) |
| 138 | return -EINVAL; | 146 | return -EINVAL; |
| 139 | 147 | ||
| 140 | status = acpi_evaluate_integer(resource->device->handle, "_STA", NULL, &sta); | 148 | status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); |
| 141 | if (ACPI_FAILURE(status)) | 149 | if (ACPI_FAILURE(status)) |
| 142 | return -ENODEV; | 150 | return -ENODEV; |
| 143 | 151 | ||
| @@ -145,7 +153,7 @@ static int acpi_power_get_state(struct acpi_power_resource *resource, int *state | |||
| 145 | ACPI_POWER_RESOURCE_STATE_OFF; | 153 | ACPI_POWER_RESOURCE_STATE_OFF; |
| 146 | 154 | ||
| 147 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n", | 155 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n", |
| 148 | resource->name, state ? "on" : "off")); | 156 | acpi_ut_get_node_name(handle), state ? "on" : "off")); |
| 149 | 157 | ||
| 150 | return 0; | 158 | return 0; |
| 151 | } | 159 | } |
| @@ -153,7 +161,6 @@ static int acpi_power_get_state(struct acpi_power_resource *resource, int *state | |||
| 153 | static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) | 161 | static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) |
| 154 | { | 162 | { |
| 155 | int result = 0, state1; | 163 | int result = 0, state1; |
| 156 | struct acpi_power_resource *resource = NULL; | ||
| 157 | u32 i = 0; | 164 | u32 i = 0; |
| 158 | 165 | ||
| 159 | 166 | ||
| @@ -161,12 +168,15 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) | |||
| 161 | return -EINVAL; | 168 | return -EINVAL; |
| 162 | 169 | ||
| 163 | /* The state of the list is 'on' IFF all resources are 'on'. */ | 170 | /* The state of the list is 'on' IFF all resources are 'on'. */ |
| 171 | /* */ | ||
| 164 | 172 | ||
| 165 | for (i = 0; i < list->count; i++) { | 173 | for (i = 0; i < list->count; i++) { |
| 166 | result = acpi_power_get_context(list->handles[i], &resource); | 174 | /* |
| 167 | if (result) | 175 | * The state of the power resource can be obtained by |
| 168 | return result; | 176 | * using the ACPI handle. In such case it is unnecessary to |
| 169 | result = acpi_power_get_state(resource, &state1); | 177 | * get the Power resource first and then get its state again. |
| 178 | */ | ||
| 179 | result = acpi_power_get_state(list->handles[i], &state1); | ||
| 170 | if (result) | 180 | if (result) |
| 171 | return result; | 181 | return result; |
| 172 | 182 | ||
| @@ -226,12 +236,18 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev) | |||
| 226 | if (ACPI_FAILURE(status)) | 236 | if (ACPI_FAILURE(status)) |
| 227 | return -ENODEV; | 237 | return -ENODEV; |
| 228 | 238 | ||
| 229 | result = acpi_power_get_state(resource, &state); | 239 | if (!acpi_power_nocheck) { |
| 230 | if (result) | 240 | /* |
| 231 | return result; | 241 | * If acpi_power_nocheck is set, it is unnecessary to check |
| 232 | if (state != ACPI_POWER_RESOURCE_STATE_ON) | 242 | * the power state after power transition. |
| 233 | return -ENOEXEC; | 243 | */ |
| 234 | 244 | result = acpi_power_get_state(resource->device->handle, | |
| 245 | &state); | ||
| 246 | if (result) | ||
| 247 | return result; | ||
| 248 | if (state != ACPI_POWER_RESOURCE_STATE_ON) | ||
| 249 | return -ENOEXEC; | ||
| 250 | } | ||
| 235 | /* Update the power resource's _device_ power state */ | 251 | /* Update the power resource's _device_ power state */ |
| 236 | resource->device->power.state = ACPI_STATE_D0; | 252 | resource->device->power.state = ACPI_STATE_D0; |
| 237 | 253 | ||
| @@ -277,11 +293,17 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev) | |||
| 277 | if (ACPI_FAILURE(status)) | 293 | if (ACPI_FAILURE(status)) |
| 278 | return -ENODEV; | 294 | return -ENODEV; |
| 279 | 295 | ||
| 280 | result = acpi_power_get_state(resource, &state); | 296 | if (!acpi_power_nocheck) { |
| 281 | if (result) | 297 | /* |
| 282 | return result; | 298 | * If acpi_power_nocheck is set, it is unnecessary to check |
| 283 | if (state != ACPI_POWER_RESOURCE_STATE_OFF) | 299 | * the power state after power transition. |
| 284 | return -ENOEXEC; | 300 | */ |
| 301 | result = acpi_power_get_state(handle, &state); | ||
| 302 | if (result) | ||
| 303 | return result; | ||
| 304 | if (state != ACPI_POWER_RESOURCE_STATE_OFF) | ||
| 305 | return -ENOEXEC; | ||
| 306 | } | ||
| 285 | 307 | ||
| 286 | /* Update the power resource's _device_ power state */ | 308 | /* Update the power resource's _device_ power state */ |
| 287 | resource->device->power.state = ACPI_STATE_D3; | 309 | resource->device->power.state = ACPI_STATE_D3; |
| @@ -555,7 +577,7 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset) | |||
| 555 | if (!resource) | 577 | if (!resource) |
| 556 | goto end; | 578 | goto end; |
| 557 | 579 | ||
| 558 | result = acpi_power_get_state(resource, &state); | 580 | result = acpi_power_get_state(resource->device->handle, &state); |
| 559 | if (result) | 581 | if (result) |
| 560 | goto end; | 582 | goto end; |
| 561 | 583 | ||
| @@ -657,7 +679,7 @@ static int acpi_power_add(struct acpi_device *device) | |||
| 657 | strcpy(resource->name, device->pnp.bus_id); | 679 | strcpy(resource->name, device->pnp.bus_id); |
| 658 | strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); | 680 | strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); |
| 659 | strcpy(acpi_device_class(device), ACPI_POWER_CLASS); | 681 | strcpy(acpi_device_class(device), ACPI_POWER_CLASS); |
| 660 | acpi_driver_data(device) = resource; | 682 | device->driver_data = resource; |
| 661 | 683 | ||
| 662 | /* Evalute the object to get the system level and resource order. */ | 684 | /* Evalute the object to get the system level and resource order. */ |
| 663 | status = acpi_evaluate_object(device->handle, NULL, NULL, &buffer); | 685 | status = acpi_evaluate_object(device->handle, NULL, NULL, &buffer); |
| @@ -668,7 +690,7 @@ static int acpi_power_add(struct acpi_device *device) | |||
| 668 | resource->system_level = acpi_object.power_resource.system_level; | 690 | resource->system_level = acpi_object.power_resource.system_level; |
| 669 | resource->order = acpi_object.power_resource.resource_order; | 691 | resource->order = acpi_object.power_resource.resource_order; |
| 670 | 692 | ||
| 671 | result = acpi_power_get_state(resource, &state); | 693 | result = acpi_power_get_state(device->handle, &state); |
| 672 | if (result) | 694 | if (result) |
| 673 | goto end; | 695 | goto end; |
| 674 | 696 | ||
| @@ -733,9 +755,9 @@ static int acpi_power_resume(struct acpi_device *device) | |||
| 733 | if (!device || !acpi_driver_data(device)) | 755 | if (!device || !acpi_driver_data(device)) |
| 734 | return -EINVAL; | 756 | return -EINVAL; |
| 735 | 757 | ||
| 736 | resource = (struct acpi_power_resource *)acpi_driver_data(device); | 758 | resource = acpi_driver_data(device); |
| 737 | 759 | ||
| 738 | result = acpi_power_get_state(resource, &state); | 760 | result = acpi_power_get_state(device->handle, &state); |
| 739 | if (result) | 761 | if (result) |
| 740 | return result; | 762 | return result; |
| 741 | 763 | ||
