diff options
| -rw-r--r-- | drivers/acpi/bus.c | 10 | ||||
| -rw-r--r-- | drivers/acpi/power.c | 36 |
2 files changed, 34 insertions, 12 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 9628652e080c..e0596954290b 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
| @@ -237,6 +237,16 @@ static int __acpi_bus_get_power(struct acpi_device *device, int *state) | |||
| 237 | } else if (result == ACPI_STATE_D3_HOT) { | 237 | } else if (result == ACPI_STATE_D3_HOT) { |
| 238 | result = ACPI_STATE_D3; | 238 | result = ACPI_STATE_D3; |
| 239 | } | 239 | } |
| 240 | |||
| 241 | /* | ||
| 242 | * If we were unsure about the device parent's power state up to this | ||
| 243 | * point, the fact that the device is in D0 implies that the parent has | ||
| 244 | * to be in D0 too. | ||
| 245 | */ | ||
| 246 | if (device->parent && device->parent->power.state == ACPI_STATE_UNKNOWN | ||
| 247 | && result == ACPI_STATE_D0) | ||
| 248 | device->parent->power.state = ACPI_STATE_D0; | ||
| 249 | |||
| 240 | *state = result; | 250 | *state = result; |
| 241 | 251 | ||
| 242 | out: | 252 | out: |
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index fc1803414629..40e38a06ba85 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 | } |
| @@ -462,7 +473,7 @@ int acpi_power_resource_register_device(struct device *dev, acpi_handle handle) | |||
| 462 | return ret; | 473 | return ret; |
| 463 | 474 | ||
| 464 | no_power_resource: | 475 | no_power_resource: |
| 465 | printk(KERN_WARNING PREFIX "Invalid Power Resource to register!"); | 476 | printk(KERN_DEBUG PREFIX "Invalid Power Resource to register!"); |
| 466 | return -ENODEV; | 477 | return -ENODEV; |
| 467 | } | 478 | } |
| 468 | EXPORT_SYMBOL_GPL(acpi_power_resource_register_device); | 479 | EXPORT_SYMBOL_GPL(acpi_power_resource_register_device); |
| @@ -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); |
