diff options
Diffstat (limited to 'drivers/acpi/power.c')
-rw-r--r-- | drivers/acpi/power.c | 40 |
1 files changed, 28 insertions, 12 deletions
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 215ecd097408..40e38a06ba85 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c | |||
@@ -67,7 +67,9 @@ static const struct acpi_device_id power_device_ids[] = { | |||
67 | }; | 67 | }; |
68 | MODULE_DEVICE_TABLE(acpi, power_device_ids); | 68 | MODULE_DEVICE_TABLE(acpi, power_device_ids); |
69 | 69 | ||
70 | #ifdef CONFIG_PM_SLEEP | ||
70 | static int acpi_power_resume(struct device *dev); | 71 | static int acpi_power_resume(struct device *dev); |
72 | #endif | ||
71 | static SIMPLE_DEV_PM_OPS(acpi_power_pm, NULL, acpi_power_resume); | 73 | static SIMPLE_DEV_PM_OPS(acpi_power_pm, NULL, acpi_power_resume); |
72 | 74 | ||
73 | static struct acpi_driver acpi_power_driver = { | 75 | static struct acpi_driver acpi_power_driver = { |
@@ -105,6 +107,7 @@ struct acpi_power_resource { | |||
105 | 107 | ||
106 | /* List of devices relying on this power resource */ | 108 | /* List of devices relying on this power resource */ |
107 | struct acpi_power_resource_device *devices; | 109 | struct acpi_power_resource_device *devices; |
110 | struct mutex devices_lock; | ||
108 | }; | 111 | }; |
109 | 112 | ||
110 | static struct list_head acpi_power_resource_list; | 113 | static struct list_head acpi_power_resource_list; |
@@ -223,7 +226,6 @@ static void acpi_power_on_device(struct acpi_power_managed_device *device) | |||
223 | 226 | ||
224 | static int __acpi_power_on(struct acpi_power_resource *resource) | 227 | static int __acpi_power_on(struct acpi_power_resource *resource) |
225 | { | 228 | { |
226 | struct acpi_power_resource_device *device_list = resource->devices; | ||
227 | acpi_status status = AE_OK; | 229 | acpi_status status = AE_OK; |
228 | 230 | ||
229 | status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL); | 231 | status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL); |
@@ -236,19 +238,15 @@ static int __acpi_power_on(struct acpi_power_resource *resource) | |||
236 | 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", |
237 | resource->name)); | 239 | resource->name)); |
238 | 240 | ||
239 | while (device_list) { | ||
240 | acpi_power_on_device(device_list->device); | ||
241 | |||
242 | device_list = device_list->next; | ||
243 | } | ||
244 | |||
245 | return 0; | 241 | return 0; |
246 | } | 242 | } |
247 | 243 | ||
248 | static int acpi_power_on(acpi_handle handle) | 244 | static int acpi_power_on(acpi_handle handle) |
249 | { | 245 | { |
250 | int result = 0; | 246 | int result = 0; |
247 | bool resume_device = false; | ||
251 | struct acpi_power_resource *resource = NULL; | 248 | struct acpi_power_resource *resource = NULL; |
249 | struct acpi_power_resource_device *device_list; | ||
252 | 250 | ||
253 | result = acpi_power_get_context(handle, &resource); | 251 | result = acpi_power_get_context(handle, &resource); |
254 | if (result) | 252 | if (result) |
@@ -264,10 +262,25 @@ static int acpi_power_on(acpi_handle handle) | |||
264 | result = __acpi_power_on(resource); | 262 | result = __acpi_power_on(resource); |
265 | if (result) | 263 | if (result) |
266 | resource->ref_count--; | 264 | resource->ref_count--; |
265 | else | ||
266 | resume_device = true; | ||
267 | } | 267 | } |
268 | 268 | ||
269 | mutex_unlock(&resource->resource_lock); | 269 | mutex_unlock(&resource->resource_lock); |
270 | 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 | |||
271 | return result; | 284 | return result; |
272 | } | 285 | } |
273 | 286 | ||
@@ -353,7 +366,7 @@ static void __acpi_power_resource_unregister_device(struct device *dev, | |||
353 | if (acpi_power_get_context(res_handle, &resource)) | 366 | if (acpi_power_get_context(res_handle, &resource)) |
354 | return; | 367 | return; |
355 | 368 | ||
356 | mutex_lock(&resource->resource_lock); | 369 | mutex_lock(&resource->devices_lock); |
357 | prev = NULL; | 370 | prev = NULL; |
358 | curr = resource->devices; | 371 | curr = resource->devices; |
359 | while (curr) { | 372 | while (curr) { |
@@ -370,7 +383,7 @@ static void __acpi_power_resource_unregister_device(struct device *dev, | |||
370 | prev = curr; | 383 | prev = curr; |
371 | curr = curr->next; | 384 | curr = curr->next; |
372 | } | 385 | } |
373 | mutex_unlock(&resource->resource_lock); | 386 | mutex_unlock(&resource->devices_lock); |
374 | } | 387 | } |
375 | 388 | ||
376 | /* Unlink dev from all power resources in _PR0 */ | 389 | /* Unlink dev from all power resources in _PR0 */ |
@@ -412,10 +425,10 @@ static int __acpi_power_resource_register_device( | |||
412 | 425 | ||
413 | power_resource_device->device = powered_device; | 426 | power_resource_device->device = powered_device; |
414 | 427 | ||
415 | mutex_lock(&resource->resource_lock); | 428 | mutex_lock(&resource->devices_lock); |
416 | power_resource_device->next = resource->devices; | 429 | power_resource_device->next = resource->devices; |
417 | resource->devices = power_resource_device; | 430 | resource->devices = power_resource_device; |
418 | mutex_unlock(&resource->resource_lock); | 431 | mutex_unlock(&resource->devices_lock); |
419 | 432 | ||
420 | return 0; | 433 | return 0; |
421 | } | 434 | } |
@@ -460,7 +473,7 @@ int acpi_power_resource_register_device(struct device *dev, acpi_handle handle) | |||
460 | return ret; | 473 | return ret; |
461 | 474 | ||
462 | no_power_resource: | 475 | no_power_resource: |
463 | printk(KERN_WARNING PREFIX "Invalid Power Resource to register!"); | 476 | printk(KERN_DEBUG PREFIX "Invalid Power Resource to register!"); |
464 | return -ENODEV; | 477 | return -ENODEV; |
465 | } | 478 | } |
466 | EXPORT_SYMBOL_GPL(acpi_power_resource_register_device); | 479 | EXPORT_SYMBOL_GPL(acpi_power_resource_register_device); |
@@ -719,6 +732,7 @@ static int acpi_power_add(struct acpi_device *device) | |||
719 | 732 | ||
720 | resource->device = device; | 733 | resource->device = device; |
721 | mutex_init(&resource->resource_lock); | 734 | mutex_init(&resource->resource_lock); |
735 | mutex_init(&resource->devices_lock); | ||
722 | strcpy(resource->name, device->pnp.bus_id); | 736 | strcpy(resource->name, device->pnp.bus_id); |
723 | strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); | 737 | strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); |
724 | strcpy(acpi_device_class(device), ACPI_POWER_CLASS); | 738 | strcpy(acpi_device_class(device), ACPI_POWER_CLASS); |
@@ -775,6 +789,7 @@ static int acpi_power_remove(struct acpi_device *device, int type) | |||
775 | return 0; | 789 | return 0; |
776 | } | 790 | } |
777 | 791 | ||
792 | #ifdef CONFIG_PM_SLEEP | ||
778 | static int acpi_power_resume(struct device *dev) | 793 | static int acpi_power_resume(struct device *dev) |
779 | { | 794 | { |
780 | int result = 0, state; | 795 | int result = 0, state; |
@@ -803,6 +818,7 @@ static int acpi_power_resume(struct device *dev) | |||
803 | 818 | ||
804 | return result; | 819 | return result; |
805 | } | 820 | } |
821 | #endif | ||
806 | 822 | ||
807 | int __init acpi_power_init(void) | 823 | int __init acpi_power_init(void) |
808 | { | 824 | { |