linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Huang Ying <ying.huang@intel.com>
To: Bjorn Helgaas <bhelgaas@google.com>
Cc: ming.m.lin@intel.com, linux-kernel@vger.kernel.org,
	linux-pm@vger.kernel.org, "Rafael J. Wysocki" <rjw@sisk.pl>,
	Huang Ying <ying.huang@intel.com>,
	Zheng Yan <zheng.z.yan@intel.com>
Subject: [RFC v2 4/5] ACPI, PM, Specify lowest allowed state for device sleep state
Date: Fri,  4 May 2012 16:13:40 +0800	[thread overview]
Message-ID: <1336119221-21146-5-git-send-email-ying.huang@intel.com> (raw)
In-Reply-To: <1336119221-21146-1-git-send-email-ying.huang@intel.com>

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.

Signed-off-by: Huang Ying <ying.huang@intel.com>
---
 drivers/acpi/sleep.c       |   18 +++++++++++++++---
 drivers/pci/pci-acpi.c     |    3 ++-
 drivers/pnp/pnpacpi/core.c |    4 ++--
 include/acpi/acpi_bus.h    |    6 +++---
 4 files changed, 22 insertions(+), 9 deletions(-)

--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -677,6 +677,7 @@ int acpi_suspend(u32 acpi_state)
  *	@dev: device to examine; its driver model wakeup flags control
  *		whether it should be able to wake up the system
  *	@d_min_p: used to store the upper limit of allowed states range
+ *	@d_max_in: specify the lowest allowed states
  *	Return value: preferred power state of the device on success, -ENODEV on
  *		failure (ie. if there's no 'struct acpi_device' for @dev)
  *
@@ -693,7 +694,7 @@ int acpi_suspend(u32 acpi_state)
  *	via @wake.
  */
 
-int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p)
+int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in)
 {
 	acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
 	struct acpi_device *adev;
@@ -704,11 +705,14 @@ int acpi_pm_device_sleep_state(struct de
 		printk(KERN_DEBUG "ACPI handle has no context!\n");
 		return -ENODEV;
 	}
+	d_max_in = clamp_t(int, d_max_in, ACPI_STATE_D0, ACPI_STATE_D3);
 
 	acpi_method[2] = '0' + acpi_target_sleep_state;
 	/*
-	 * If the sleep state is S0, we will return D3, but if the device has
-	 * _S0W, we will use the value from _S0W
+	 * If the sleep state is S0, the lowest limit from ACPI is D3,
+	 * but if the device has _S0W, we will use the value from _S0W
+	 * as the lowest limit from ACPI.  Finally, we will constrain
+	 * the lowest limit with the specified one.
 	 */
 	d_min = ACPI_STATE_D0;
 	d_max = ACPI_STATE_D3;
@@ -754,6 +758,14 @@ int acpi_pm_device_sleep_state(struct de
 
 	if (d_min_p)
 		*d_min_p = d_min;
+	/* constrain d_max with specified lowest limit (max number) */
+	if (d_max > d_max_in) {
+		d_max = d_max_in;
+		for (;d_max > d_min; d_max--) {
+			if (adev->power.states[d_max].flags.valid)
+				break;
+		}
+	}
 	return d_max;
 }
 #endif /* CONFIG_PM */
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -189,7 +189,8 @@ static pci_power_t acpi_pci_choose_state
 {
 	int acpi_state;
 
-	acpi_state = acpi_pm_device_sleep_state(&pdev->dev, NULL);
+	acpi_state = acpi_pm_device_sleep_state(&pdev->dev, NULL,
+						ACPI_STATE_D3);
 	if (acpi_state < 0)
 		return PCI_POWER_ERROR;
 
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -170,8 +170,8 @@ static int pnpacpi_suspend(struct pnp_de
 	}
 
 	if (acpi_bus_power_manageable(handle)) {
-		int power_state = acpi_pm_device_sleep_state(&dev->dev, NULL);
-
+		int power_state = acpi_pm_device_sleep_state(&dev->dev, NULL,
+							     ACPI_STATE_D3);
 		if (power_state < 0)
 			power_state = (state.event == PM_EVENT_ON) ?
 					ACPI_STATE_D0 : ACPI_STATE_D3;
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -383,13 +383,13 @@ int acpi_enable_wakeup_device_power(stru
 int acpi_disable_wakeup_device_power(struct acpi_device *dev);
 
 #ifdef CONFIG_PM
-int acpi_pm_device_sleep_state(struct device *, int *);
+int acpi_pm_device_sleep_state(struct device *, int *, int);
 #else
-static inline int acpi_pm_device_sleep_state(struct device *d, int *p)
+static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m)
 {
 	if (p)
 		*p = ACPI_STATE_D0;
-	return ACPI_STATE_D3;
+	return m == ACPI_STATE_D3 ? m : ACPI_STATE_D0;
 }
 #endif
 

  parent reply	other threads:[~2012-05-04  8:14 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-05-04  8:13 [RFC v2 0/5] PCIe, Add PCIe runtime D3cold support Huang Ying
2012-05-04  8:13 ` [RFC v2 1/5] PM, Runtime, Add power_must_be_on flag Huang Ying
2012-05-04 19:37   ` Rafael J. Wysocki
2012-05-05  5:15     ` huang ying
2012-05-07 20:33       ` Rafael J. Wysocki
2012-05-04 19:50   ` Bjorn Helgaas
2012-05-05  5:59     ` huang ying
2012-05-07 20:37       ` Rafael J. Wysocki
2012-05-04  8:13 ` [RFC v2 2/5] PM, Add sysfs file power_off to control device power off policy Huang Ying
2012-05-04 19:33   ` Rafael J. Wysocki
2012-05-05  6:29     ` huang ying
2012-05-07 20:53       ` Rafael J. Wysocki
2012-05-08  1:44         ` Huang Ying
2012-05-08 21:34           ` Rafael J. Wysocki
2012-05-09  6:46             ` Huang Ying
2012-05-09 10:38               ` Rafael J. Wysocki
2012-05-10  0:55                 ` Huang Ying
2012-05-10 14:48                   ` Alan Stern
2012-05-10 19:03                     ` Rafael J. Wysocki
2012-05-04 19:50   ` Bjorn Helgaas
2012-05-04 21:00     ` Rafael J. Wysocki
2012-05-05  6:36     ` huang ying
2012-05-04  8:13 ` [RFC v2 3/5] PCIe, Add runtime PM support to PCIe port Huang Ying
2012-05-04 19:43   ` Rafael J. Wysocki
2012-05-05  6:46     ` huang ying
2012-05-07 21:00       ` Rafael J. Wysocki
2012-05-11  7:57         ` Huang Ying
2012-05-11 18:44           ` Rafael J. Wysocki
2012-05-04 19:50   ` Bjorn Helgaas
2012-05-04 20:55     ` Rafael J. Wysocki
2012-05-05  6:54       ` huang ying
2012-05-07 21:06         ` Rafael J. Wysocki
2012-05-05  6:53     ` huang ying
2012-05-04  8:13 ` Huang Ying [this message]
2012-05-04 20:10   ` [RFC v2 4/5] ACPI, PM, Specify lowest allowed state for device sleep state Rafael J. Wysocki
2012-05-05  7:25     ` huang ying
2012-05-07 21:15       ` Rafael J. Wysocki
2012-05-08  1:49         ` Huang Ying
2012-05-04  8:13 ` [RFC v2 5/5] PCIe, Add PCIe runtime D3cold support Huang Ying
2012-05-04 19:51   ` Bjorn Helgaas
2012-05-05  7:34     ` huang ying
2012-05-04 20:50   ` Rafael J. Wysocki
2012-05-05  8:08     ` huang ying
2012-05-07 21:22       ` Rafael J. Wysocki
2012-05-08  2:22         ` Huang Ying
2012-05-08  8:34           ` Huang Ying
2012-05-10 19:28             ` Rafael J. Wysocki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1336119221-21146-5-git-send-email-ying.huang@intel.com \
    --to=ying.huang@intel.com \
    --cc=bhelgaas@google.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=ming.m.lin@intel.com \
    --cc=rjw@sisk.pl \
    --cc=zheng.z.yan@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).