diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/sleep.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 88561029cca8..1cc02ca2af2a 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
@@ -716,8 +716,9 @@ int acpi_suspend(u32 acpi_state) | |||
716 | * @dev: device to examine; its driver model wakeup flags control | 716 | * @dev: device to examine; its driver model wakeup flags control |
717 | * whether it should be able to wake up the system | 717 | * whether it should be able to wake up the system |
718 | * @d_min_p: used to store the upper limit of allowed states range | 718 | * @d_min_p: used to store the upper limit of allowed states range |
719 | * Return value: preferred power state of the device on success, -ENODEV on | 719 | * @d_max_in: specify the lowest allowed states |
720 | * failure (ie. if there's no 'struct acpi_device' for @dev) | 720 | * Return value: preferred power state of the device on success, -ENODEV |
721 | * (ie. if there's no 'struct acpi_device' for @dev) or -EINVAL on failure | ||
721 | * | 722 | * |
722 | * Find the lowest power (highest number) ACPI device power state that | 723 | * Find the lowest power (highest number) ACPI device power state that |
723 | * device @dev can be in while the system is in the sleep state represented | 724 | * device @dev can be in while the system is in the sleep state represented |
@@ -732,13 +733,15 @@ int acpi_suspend(u32 acpi_state) | |||
732 | * via @wake. | 733 | * via @wake. |
733 | */ | 734 | */ |
734 | 735 | ||
735 | int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) | 736 | int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in) |
736 | { | 737 | { |
737 | acpi_handle handle = DEVICE_ACPI_HANDLE(dev); | 738 | acpi_handle handle = DEVICE_ACPI_HANDLE(dev); |
738 | struct acpi_device *adev; | 739 | struct acpi_device *adev; |
739 | char acpi_method[] = "_SxD"; | 740 | char acpi_method[] = "_SxD"; |
740 | unsigned long long d_min, d_max; | 741 | unsigned long long d_min, d_max; |
741 | 742 | ||
743 | if (d_max_in < ACPI_STATE_D0 || d_max_in > ACPI_STATE_D3) | ||
744 | return -EINVAL; | ||
742 | if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) { | 745 | if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) { |
743 | printk(KERN_DEBUG "ACPI handle has no context!\n"); | 746 | printk(KERN_DEBUG "ACPI handle has no context!\n"); |
744 | return -ENODEV; | 747 | return -ENODEV; |
@@ -746,8 +749,10 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) | |||
746 | 749 | ||
747 | acpi_method[2] = '0' + acpi_target_sleep_state; | 750 | acpi_method[2] = '0' + acpi_target_sleep_state; |
748 | /* | 751 | /* |
749 | * If the sleep state is S0, we will return D3, but if the device has | 752 | * If the sleep state is S0, the lowest limit from ACPI is D3, |
750 | * _S0W, we will use the value from _S0W | 753 | * but if the device has _S0W, we will use the value from _S0W |
754 | * as the lowest limit from ACPI. Finally, we will constrain | ||
755 | * the lowest limit with the specified one. | ||
751 | */ | 756 | */ |
752 | d_min = ACPI_STATE_D0; | 757 | d_min = ACPI_STATE_D0; |
753 | d_max = ACPI_STATE_D3; | 758 | d_max = ACPI_STATE_D3; |
@@ -791,8 +796,17 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) | |||
791 | } | 796 | } |
792 | } | 797 | } |
793 | 798 | ||
799 | if (d_max_in < d_min) | ||
800 | return -EINVAL; | ||
794 | if (d_min_p) | 801 | if (d_min_p) |
795 | *d_min_p = d_min; | 802 | *d_min_p = d_min; |
803 | /* constrain d_max with specified lowest limit (max number) */ | ||
804 | if (d_max > d_max_in) { | ||
805 | for (d_max = d_max_in; d_max > d_min; d_max--) { | ||
806 | if (adev->power.states[d_max].flags.valid) | ||
807 | break; | ||
808 | } | ||
809 | } | ||
796 | return d_max; | 810 | return d_max; |
797 | } | 811 | } |
798 | #endif /* CONFIG_PM */ | 812 | #endif /* CONFIG_PM */ |