diff options
| -rw-r--r-- | drivers/acpi/device_pm.c | 158 |
1 files changed, 92 insertions, 66 deletions
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index afc808e93855..fd363b57a596 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c | |||
| @@ -403,44 +403,37 @@ EXPORT_SYMBOL(acpi_bus_can_wakeup); | |||
| 403 | * @dev: Device whose preferred target power state to return. | 403 | * @dev: Device whose preferred target power state to return. |
| 404 | * @adev: ACPI device node corresponding to @dev. | 404 | * @adev: ACPI device node corresponding to @dev. |
| 405 | * @target_state: System state to match the resultant device state. | 405 | * @target_state: System state to match the resultant device state. |
| 406 | * @d_max_in: Deepest low-power state to take into consideration. | 406 | * @d_min_p: Location to store the highest power state available to the device. |
| 407 | * @d_min_p: Location to store the upper limit of the allowed states range. | 407 | * @d_max_p: Location to store the lowest power state available to the device. |
| 408 | * Return value: Preferred power state of the device on success, -ENODEV | ||
| 409 | * (if there's no 'struct acpi_device' for @dev) or -EINVAL on failure | ||
| 410 | * | 408 | * |
| 411 | * Find the lowest power (highest number) ACPI device power state that the | 409 | * Find the lowest power (highest number) and highest power (lowest number) ACPI |
| 412 | * device can be in while the system is in the state represented by | 410 | * device power states that the device can be in while the system is in the |
| 413 | * @target_state. If @d_min_p is set, the highest power (lowest number) device | 411 | * state represented by @target_state. Store the integer numbers representing |
| 414 | * power state that @dev can be in for the given system sleep state is stored | 412 | * those stats in the memory locations pointed to by @d_max_p and @d_min_p, |
| 415 | * at the location pointed to by it. | 413 | * respectively. |
| 416 | * | 414 | * |
| 417 | * Callers must ensure that @dev and @adev are valid pointers and that @adev | 415 | * Callers must ensure that @dev and @adev are valid pointers and that @adev |
| 418 | * actually corresponds to @dev before using this function. | 416 | * actually corresponds to @dev before using this function. |
| 417 | * | ||
| 418 | * Returns 0 on success or -ENODATA when one of the ACPI methods fails or | ||
| 419 | * returns a value that doesn't make sense. The memory locations pointed to by | ||
| 420 | * @d_max_p and @d_min_p are only modified on success. | ||
| 419 | */ | 421 | */ |
| 420 | static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev, | 422 | static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev, |
| 421 | u32 target_state, int d_max_in, int *d_min_p) | 423 | u32 target_state, int *d_min_p, int *d_max_p) |
| 422 | { | 424 | { |
| 423 | char acpi_method[] = "_SxD"; | 425 | char method[] = { '_', 'S', '0' + target_state, 'D', '\0' }; |
| 424 | unsigned long long d_min, d_max; | 426 | acpi_handle handle = adev->handle; |
| 427 | unsigned long long ret; | ||
| 428 | int d_min, d_max; | ||
| 425 | bool wakeup = false; | 429 | bool wakeup = false; |
| 430 | acpi_status status; | ||
| 426 | 431 | ||
| 427 | if (d_max_in < ACPI_STATE_D0 || d_max_in > ACPI_STATE_D3_COLD) | ||
| 428 | return -EINVAL; | ||
| 429 | |||
| 430 | if (d_max_in > ACPI_STATE_D3_HOT) { | ||
| 431 | enum pm_qos_flags_status stat; | ||
| 432 | |||
| 433 | stat = dev_pm_qos_flags(dev, PM_QOS_FLAG_NO_POWER_OFF); | ||
| 434 | if (stat == PM_QOS_FLAGS_ALL) | ||
| 435 | d_max_in = ACPI_STATE_D3_HOT; | ||
| 436 | } | ||
| 437 | |||
| 438 | acpi_method[2] = '0' + target_state; | ||
| 439 | /* | 432 | /* |
| 440 | * If the sleep state is S0, the lowest limit from ACPI is D3, | 433 | * If the system state is S0, the lowest power state the device can be |
| 441 | * but if the device has _S0W, we will use the value from _S0W | 434 | * in is D3cold, unless the device has _S0W and is supposed to signal |
| 442 | * as the lowest limit from ACPI. Finally, we will constrain | 435 | * wakeup, in which case the return value of _S0W has to be used as the |
| 443 | * the lowest limit with the specified one. | 436 | * lowest power state available to the device. |
| 444 | */ | 437 | */ |
| 445 | d_min = ACPI_STATE_D0; | 438 | d_min = ACPI_STATE_D0; |
| 446 | d_max = ACPI_STATE_D3_COLD; | 439 | d_max = ACPI_STATE_D3_COLD; |
| @@ -449,12 +442,30 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev, | |||
| 449 | * If present, _SxD methods return the minimum D-state (highest power | 442 | * If present, _SxD methods return the minimum D-state (highest power |
| 450 | * state) we can use for the corresponding S-states. Otherwise, the | 443 | * state) we can use for the corresponding S-states. Otherwise, the |
| 451 | * minimum D-state is D0 (ACPI 3.x). | 444 | * minimum D-state is D0 (ACPI 3.x). |
| 452 | * | ||
| 453 | * NOTE: We rely on acpi_evaluate_integer() not clobbering the integer | ||
| 454 | * provided -- that's our fault recovery, we ignore retval. | ||
| 455 | */ | 445 | */ |
| 456 | if (target_state > ACPI_STATE_S0) { | 446 | if (target_state > ACPI_STATE_S0) { |
| 457 | acpi_evaluate_integer(adev->handle, acpi_method, NULL, &d_min); | 447 | /* |
| 448 | * We rely on acpi_evaluate_integer() not clobbering the integer | ||
| 449 | * provided if AE_NOT_FOUND is returned. | ||
| 450 | */ | ||
| 451 | ret = d_min; | ||
| 452 | status = acpi_evaluate_integer(handle, method, NULL, &ret); | ||
| 453 | if ((ACPI_FAILURE(status) && status != AE_NOT_FOUND) | ||
| 454 | || ret > ACPI_STATE_D3_COLD) | ||
| 455 | return -ENODATA; | ||
| 456 | |||
| 457 | /* | ||
| 458 | * We need to handle legacy systems where D3hot and D3cold are | ||
| 459 | * the same and 3 is returned in both cases, so fall back to | ||
| 460 | * D3cold if D3hot is not a valid state. | ||
| 461 | */ | ||
| 462 | if (!adev->power.states[ret].flags.valid) { | ||
| 463 | if (ret == ACPI_STATE_D3_HOT) | ||
| 464 | ret = ACPI_STATE_D3_COLD; | ||
| 465 | else | ||
| 466 | return -ENODATA; | ||
| 467 | } | ||
| 468 | d_min = ret; | ||
| 458 | wakeup = device_may_wakeup(dev) && adev->wakeup.flags.valid | 469 | wakeup = device_may_wakeup(dev) && adev->wakeup.flags.valid |
| 459 | && adev->wakeup.sleep_state >= target_state; | 470 | && adev->wakeup.sleep_state >= target_state; |
| 460 | } else if (dev_pm_qos_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP) != | 471 | } else if (dev_pm_qos_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP) != |
| @@ -470,36 +481,29 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev, | |||
| 470 | * can wake the system. _S0W may be valid, too. | 481 | * can wake the system. _S0W may be valid, too. |
| 471 | */ | 482 | */ |
| 472 | if (wakeup) { | 483 | if (wakeup) { |
| 473 | acpi_status status; | 484 | method[3] = 'W'; |
| 474 | 485 | status = acpi_evaluate_integer(handle, method, NULL, &ret); | |
| 475 | acpi_method[3] = 'W'; | 486 | if (status == AE_NOT_FOUND) { |
| 476 | status = acpi_evaluate_integer(adev->handle, acpi_method, NULL, | 487 | if (target_state > ACPI_STATE_S0) |
| 477 | &d_max); | ||
| 478 | if (ACPI_FAILURE(status)) { | ||
| 479 | if (target_state != ACPI_STATE_S0 || | ||
| 480 | status != AE_NOT_FOUND) | ||
| 481 | d_max = d_min; | 488 | d_max = d_min; |
| 482 | } else if (d_max < d_min) { | 489 | } else if (ACPI_SUCCESS(status) && ret <= ACPI_STATE_D3_COLD) { |
| 483 | /* Warn the user of the broken DSDT */ | 490 | /* Fall back to D3cold if ret is not a valid state. */ |
| 484 | printk(KERN_WARNING "ACPI: Wrong value from %s\n", | 491 | if (!adev->power.states[ret].flags.valid) |
| 485 | acpi_method); | 492 | ret = ACPI_STATE_D3_COLD; |
| 486 | /* Sanitize it */ | 493 | |
| 487 | d_min = d_max; | 494 | d_max = ret > d_min ? ret : d_min; |
| 495 | } else { | ||
| 496 | return -ENODATA; | ||
| 488 | } | 497 | } |
| 489 | } | 498 | } |
| 490 | 499 | ||
| 491 | if (d_max_in < d_min) | ||
| 492 | return -EINVAL; | ||
| 493 | if (d_min_p) | 500 | if (d_min_p) |
| 494 | *d_min_p = d_min; | 501 | *d_min_p = d_min; |
| 495 | /* constrain d_max with specified lowest limit (max number) */ | 502 | |
| 496 | if (d_max > d_max_in) { | 503 | if (d_max_p) |
| 497 | for (d_max = d_max_in; d_max > d_min; d_max--) { | 504 | *d_max_p = d_max; |
| 498 | if (adev->power.states[d_max].flags.valid) | 505 | |
| 499 | break; | 506 | return 0; |
| 500 | } | ||
| 501 | } | ||
| 502 | return d_max; | ||
| 503 | } | 507 | } |
| 504 | 508 | ||
| 505 | /** | 509 | /** |
| @@ -508,7 +512,8 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev, | |||
| 508 | * @d_min_p: Location to store the upper limit of the allowed states range. | 512 | * @d_min_p: Location to store the upper limit of the allowed states range. |
| 509 | * @d_max_in: Deepest low-power state to take into consideration. | 513 | * @d_max_in: Deepest low-power state to take into consideration. |
| 510 | * Return value: Preferred power state of the device on success, -ENODEV | 514 | * Return value: Preferred power state of the device on success, -ENODEV |
| 511 | * (if there's no 'struct acpi_device' for @dev) or -EINVAL on failure | 515 | * if there's no 'struct acpi_device' for @dev, -EINVAL if @d_max_in is |
| 516 | * incorrect, or -ENODATA on ACPI method failure. | ||
| 512 | * | 517 | * |
| 513 | * The caller must ensure that @dev is valid before using this function. | 518 | * The caller must ensure that @dev is valid before using this function. |
| 514 | */ | 519 | */ |
| @@ -516,14 +521,39 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in) | |||
| 516 | { | 521 | { |
| 517 | acpi_handle handle = DEVICE_ACPI_HANDLE(dev); | 522 | acpi_handle handle = DEVICE_ACPI_HANDLE(dev); |
| 518 | struct acpi_device *adev; | 523 | struct acpi_device *adev; |
| 524 | int ret, d_max; | ||
| 525 | |||
| 526 | if (d_max_in < ACPI_STATE_D0 || d_max_in > ACPI_STATE_D3_COLD) | ||
| 527 | return -EINVAL; | ||
| 528 | |||
| 529 | if (d_max_in > ACPI_STATE_D3_HOT) { | ||
| 530 | enum pm_qos_flags_status stat; | ||
| 531 | |||
| 532 | stat = dev_pm_qos_flags(dev, PM_QOS_FLAG_NO_POWER_OFF); | ||
| 533 | if (stat == PM_QOS_FLAGS_ALL) | ||
| 534 | d_max_in = ACPI_STATE_D3_HOT; | ||
| 535 | } | ||
| 519 | 536 | ||
| 520 | if (!handle || acpi_bus_get_device(handle, &adev)) { | 537 | if (!handle || acpi_bus_get_device(handle, &adev)) { |
| 521 | dev_dbg(dev, "ACPI handle without context in %s!\n", __func__); | 538 | dev_dbg(dev, "ACPI handle without context in %s!\n", __func__); |
| 522 | return -ENODEV; | 539 | return -ENODEV; |
| 523 | } | 540 | } |
| 524 | 541 | ||
| 525 | return acpi_dev_pm_get_state(dev, adev, acpi_target_system_state(), | 542 | ret = acpi_dev_pm_get_state(dev, adev, acpi_target_system_state(), |
| 526 | d_max_in, d_min_p); | 543 | d_min_p, &d_max); |
| 544 | if (ret) | ||
| 545 | return ret; | ||
| 546 | |||
| 547 | if (d_max_in < *d_min_p) | ||
| 548 | return -EINVAL; | ||
| 549 | |||
| 550 | if (d_max > d_max_in) { | ||
| 551 | for (d_max = d_max_in; d_max > *d_min_p; d_max--) { | ||
| 552 | if (adev->power.states[d_max].flags.valid) | ||
| 553 | break; | ||
| 554 | } | ||
| 555 | } | ||
| 556 | return d_max; | ||
| 527 | } | 557 | } |
| 528 | EXPORT_SYMBOL(acpi_pm_device_sleep_state); | 558 | EXPORT_SYMBOL(acpi_pm_device_sleep_state); |
| 529 | 559 | ||
| @@ -674,17 +704,13 @@ struct acpi_device *acpi_dev_pm_get_node(struct device *dev) | |||
| 674 | static int acpi_dev_pm_low_power(struct device *dev, struct acpi_device *adev, | 704 | static int acpi_dev_pm_low_power(struct device *dev, struct acpi_device *adev, |
| 675 | u32 system_state) | 705 | u32 system_state) |
| 676 | { | 706 | { |
| 677 | int power_state; | 707 | int ret, state; |
| 678 | 708 | ||
| 679 | if (!acpi_device_power_manageable(adev)) | 709 | if (!acpi_device_power_manageable(adev)) |
| 680 | return 0; | 710 | return 0; |
| 681 | 711 | ||
| 682 | power_state = acpi_dev_pm_get_state(dev, adev, system_state, | 712 | ret = acpi_dev_pm_get_state(dev, adev, system_state, NULL, &state); |
| 683 | ACPI_STATE_D3_COLD, NULL); | 713 | return ret ? ret : acpi_device_set_power(adev, state); |
| 684 | if (power_state < ACPI_STATE_D0 || power_state > ACPI_STATE_D3_COLD) | ||
| 685 | return -EIO; | ||
| 686 | |||
| 687 | return acpi_device_set_power(adev, power_state); | ||
| 688 | } | 714 | } |
| 689 | 715 | ||
| 690 | /** | 716 | /** |
