diff options
| -rw-r--r-- | drivers/acpi/power.c | 34 |
1 files changed, 23 insertions, 11 deletions
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index fc1803414629..cc2a2dcff336 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c | |||
| @@ -107,6 +107,7 @@ struct acpi_power_resource { | |||
| 107 | 107 | ||
| 108 | /* List of devices relying on this power resource */ | 108 | /* List of devices relying on this power resource */ |
| 109 | struct acpi_power_resource_device *devices; | 109 | struct acpi_power_resource_device *devices; |
| 110 | struct mutex devices_lock; | ||
| 110 | }; | 111 | }; |
| 111 | 112 | ||
| 112 | static struct list_head acpi_power_resource_list; | 113 | static struct list_head acpi_power_resource_list; |
| @@ -225,7 +226,6 @@ static void acpi_power_on_device(struct acpi_power_managed_device *device) | |||
| 225 | 226 | ||
| 226 | static int __acpi_power_on(struct acpi_power_resource *resource) | 227 | static int __acpi_power_on(struct acpi_power_resource *resource) |
| 227 | { | 228 | { |
| 228 | struct acpi_power_resource_device *device_list = resource->devices; | ||
| 229 | acpi_status status = AE_OK; | 229 | acpi_status status = AE_OK; |
| 230 | 230 | ||
| 231 | status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL); | 231 | status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL); |
| @@ -238,19 +238,15 @@ static int __acpi_power_on(struct acpi_power_resource *resource) | |||
| 238 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned on\n", | 238 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned on\n", |
| 239 | resource->name)); | 239 | resource->name)); |
| 240 | 240 | ||
| 241 | while (device_list) { | ||
| 242 | acpi_power_on_device(device_list->device); | ||
| 243 | |||
| 244 | device_list = device_list->next; | ||
| 245 | } | ||
| 246 | |||
| 247 | return 0; | 241 | return 0; |
| 248 | } | 242 | } |
| 249 | 243 | ||
| 250 | static int acpi_power_on(acpi_handle handle) | 244 | static int acpi_power_on(acpi_handle handle) |
| 251 | { | 245 | { |
| 252 | int result = 0; | 246 | int result = 0; |
| 247 | bool resume_device = false; | ||
| 253 | struct acpi_power_resource *resource = NULL; | 248 | struct acpi_power_resource *resource = NULL; |
| 249 | struct acpi_power_resource_device *device_list; | ||
| 254 | 250 | ||
| 255 | result = acpi_power_get_context(handle, &resource); | 251 | result = acpi_power_get_context(handle, &resource); |
| 256 | if (result) | 252 | if (result) |
| @@ -266,10 +262,25 @@ static int acpi_power_on(acpi_handle handle) | |||
| 266 | result = __acpi_power_on(resource); | 262 | result = __acpi_power_on(resource); |
| 267 | if (result) | 263 | if (result) |
| 268 | resource->ref_count--; | 264 | resource->ref_count--; |
| 265 | else | ||
| 266 | resume_device = true; | ||
| 269 | } | 267 | } |
| 270 | 268 | ||
| 271 | mutex_unlock(&resource->resource_lock); | 269 | mutex_unlock(&resource->resource_lock); |
| 272 | 270 | ||
| 271 | if (!resume_device) | ||
| 272 | return result; | ||
| 273 | |||
| 274 | mutex_lock(&resource->devices_lock); | ||
| 275 | |||
| 276 | device_list = resource->devices; | ||
| 277 | while (device_list) { | ||
| 278 | acpi_power_on_device(device_list->device); | ||
| 279 | device_list = device_list->next; | ||
| 280 | } | ||
| 281 | |||
| 282 | mutex_unlock(&resource->devices_lock); | ||
| 283 | |||
| 273 | return result; | 284 | return result; |
| 274 | } | 285 | } |
| 275 | 286 | ||
| @@ -355,7 +366,7 @@ static void __acpi_power_resource_unregister_device(struct device *dev, | |||
| 355 | if (acpi_power_get_context(res_handle, &resource)) | 366 | if (acpi_power_get_context(res_handle, &resource)) |
| 356 | return; | 367 | return; |
| 357 | 368 | ||
| 358 | mutex_lock(&resource->resource_lock); | 369 | mutex_lock(&resource->devices_lock); |
| 359 | prev = NULL; | 370 | prev = NULL; |
| 360 | curr = resource->devices; | 371 | curr = resource->devices; |
| 361 | while (curr) { | 372 | while (curr) { |
| @@ -372,7 +383,7 @@ static void __acpi_power_resource_unregister_device(struct device *dev, | |||
| 372 | prev = curr; | 383 | prev = curr; |
| 373 | curr = curr->next; | 384 | curr = curr->next; |
| 374 | } | 385 | } |
| 375 | mutex_unlock(&resource->resource_lock); | 386 | mutex_unlock(&resource->devices_lock); |
| 376 | } | 387 | } |
| 377 | 388 | ||
| 378 | /* Unlink dev from all power resources in _PR0 */ | 389 | /* Unlink dev from all power resources in _PR0 */ |
| @@ -414,10 +425,10 @@ static int __acpi_power_resource_register_device( | |||
| 414 | 425 | ||
| 415 | power_resource_device->device = powered_device; | 426 | power_resource_device->device = powered_device; |
| 416 | 427 | ||
| 417 | mutex_lock(&resource->resource_lock); | 428 | mutex_lock(&resource->devices_lock); |
| 418 | power_resource_device->next = resource->devices; | 429 | power_resource_device->next = resource->devices; |
| 419 | resource->devices = power_resource_device; | 430 | resource->devices = power_resource_device; |
| 420 | mutex_unlock(&resource->resource_lock); | 431 | mutex_unlock(&resource->devices_lock); |
| 421 | 432 | ||
| 422 | return 0; | 433 | return 0; |
| 423 | } | 434 | } |
| @@ -721,6 +732,7 @@ static int acpi_power_add(struct acpi_device *device) | |||
| 721 | 732 | ||
| 722 | resource->device = device; | 733 | resource->device = device; |
| 723 | mutex_init(&resource->resource_lock); | 734 | mutex_init(&resource->resource_lock); |
| 735 | mutex_init(&resource->devices_lock); | ||
| 724 | strcpy(resource->name, device->pnp.bus_id); | 736 | strcpy(resource->name, device->pnp.bus_id); |
| 725 | strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); | 737 | strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); |
| 726 | strcpy(acpi_device_class(device), ACPI_POWER_CLASS); | 738 | strcpy(acpi_device_class(device), ACPI_POWER_CLASS); |
