aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/sleep.c24
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
735int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) 736int 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 */