aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/sleep.c
diff options
context:
space:
mode:
authorHuang Ying <ying.huang@intel.com>2012-06-22 22:23:48 -0400
committerBjorn Helgaas <bhelgaas@google.com>2012-06-23 12:41:09 -0400
commitee85f543710dd56ce526cb44e39191f32972e5ad (patch)
tree13009358f0260d39c106b6708d6bb49f1d73279f /drivers/acpi/sleep.c
parentcfaf025112d3856637ff34a767ef785ef5cf2ca9 (diff)
ACPI/PM: specify lowest allowed state for device sleep state
Lower device sleep state can save more power, but has more exit latency too. Sometimes, to satisfy some power QoS and other requirement, we need to constrain the lowest device sleep state. In this patch, a parameter to specify lowest allowed state for acpi_pm_device_sleep_state is added. So that the caller can enforce the constraint via the parameter. This is needed by PCIe D3cold support, where the lowest power state allowed may be D3_HOT instead of default D3_COLD. CC: Len Brown <lenb@kernel.org> CC: linux-acpi@vger.kernel.org Reviewed-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Huang Ying <ying.huang@intel.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/acpi/sleep.c')
-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 */