mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Len Brown <lenb@kernel.org>
To: linux-acpi@vger.kernel.org, linux-pm@lists.linux-foundation.org
Cc: linux-kernel@vger.kernel.org, "Rafael J. Wysocki" <rjw@sisk.pl>
Subject: [PATCH 06/15] ACPI / PM: Make __acpi_bus_get_power() cover D3cold correctly
Date: Mon,  4 Jun 2012 01:39:57 -0400	[thread overview]
Message-ID: <38c92fff988d518fe80dc23d0d44d66bd7e47ddd.1338786831.git.len.brown@intel.com> (raw)
In-Reply-To: <1338788406-29981-1-git-send-email-lenb@kernel.org>
In-Reply-To: <c5971456964290da7e98222892797b71ef793e62.1338786831.git.len.brown@intel.com>

From: "Rafael J. Wysocki" <rjw@sisk.pl>

After recent changes of the ACPI device power states definitions, if
power resources are not used for the device's power management, the
state returned by __acpi_bus_get_power() cannot exceed D3hot, because
the return values of _PSC are 0 through 3.  However, if the _PR3
method is not present for the device and _PS3 returns 3, we have to
assume that the device is in D3cold, so the value returned by
__acpi_bus_get_power() in that case should be 4.

Similarly, acpi_power_get_inferred_state() should take the power
resources for the D3hot state into account in general, so that it
can return 3 if those resources are "on" or 4 (D3cold) otherwise.

Fix the the above two issues and make sure that if both _PSC and
_PR3 are present for the device, the power resources listed by _PR3
will be used to determine if the number 3 returned by _PSC is meant
to represent D3cold or D3hot.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
 drivers/acpi/bus.c   | 51 +++++++++++++++++++++++++++++----------------------
 drivers/acpi/power.c |  2 +-
 2 files changed, 30 insertions(+), 23 deletions(-)

diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index a41be56..adceafd 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -202,37 +202,44 @@ static const char *state_string(int state)
 
 static int __acpi_bus_get_power(struct acpi_device *device, int *state)
 {
-	int result = 0;
-	acpi_status status = 0;
-	unsigned long long psc = 0;
+	int result = ACPI_STATE_UNKNOWN;
 
 	if (!device || !state)
 		return -EINVAL;
 
-	*state = ACPI_STATE_UNKNOWN;
-
-	if (device->flags.power_manageable) {
-		/*
-		 * Get the device's power state either directly (via _PSC) or
-		 * indirectly (via power resources).
-		 */
-		if (device->power.flags.power_resources) {
-			result = acpi_power_get_inferred_state(device, state);
-			if (result)
-				return result;
-		} else if (device->power.flags.explicit_get) {
-			status = acpi_evaluate_integer(device->handle, "_PSC",
-						       NULL, &psc);
-			if (ACPI_FAILURE(status))
-				return -ENODEV;
-			*state = (int)psc;
-		}
-	} else {
+	if (!device->flags.power_manageable) {
 		/* TBD: Non-recursive algorithm for walking up hierarchy. */
 		*state = device->parent ?
 			device->parent->power.state : ACPI_STATE_D0;
+		goto out;
+	}
+
+	/*
+	 * Get the device's power state either directly (via _PSC) or
+	 * indirectly (via power resources).
+	 */
+	if (device->power.flags.explicit_get) {
+		unsigned long long psc;
+		acpi_status status = acpi_evaluate_integer(device->handle,
+							   "_PSC", NULL, &psc);
+		if (ACPI_FAILURE(status))
+			return -ENODEV;
+
+		result = psc;
+	}
+	/* The test below covers ACPI_STATE_UNKNOWN too. */
+	if (result <= ACPI_STATE_D2) {
+	  ; /* Do nothing. */
+	} else if (device->power.flags.power_resources) {
+		int error = acpi_power_get_inferred_state(device, &result);
+		if (error)
+			return error;
+	} else if (result == ACPI_STATE_D3_HOT) {
+		result = ACPI_STATE_D3;
 	}
+	*state = result;
 
+ out:
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is %s\n",
 			  device->pnp.bus_id, state_string(*state)));
 
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 0500f71..dd6d6a3 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -631,7 +631,7 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state)
 	 * We know a device's inferred power state when all the resources
 	 * required for a given D-state are 'on'.
 	 */
-	for (i = ACPI_STATE_D0; i < ACPI_STATE_D3_HOT; i++) {
+	for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3_HOT; i++) {
 		list = &device->power.states[i].resources;
 		if (list->count < 1)
 			continue;
-- 
1.7.11.rc0.100.g5498c5f


  parent reply	other threads:[~2012-06-04  5:40 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-06-04  5:39 ACPI & Power Management Patches for Linux 3.5-rc1 Len Brown
2012-06-04  5:39 ` [PATCH 01/15] ACPI battery: only refresh the sysfs files when pertinent information changes Len Brown
2012-06-04  5:39   ` [PATCH 02/15] ACPI: Ignore invalid _PSS entries, but use valid ones Len Brown
2012-06-04  5:39   ` [PATCH 03/15] ACPI / PM: Generate wakeup events on fixed power button Len Brown
2012-06-04  5:39   ` [PATCH 04/15] rtc-cmos / PM: report wakeup event on ACPI RTC alarm Len Brown
2012-06-04  5:39   ` [PATCH 05/15] ACPI / PM: Fix error messages in drivers/acpi/bus.c Len Brown
2012-06-04  5:39   ` Len Brown [this message]
2012-06-04  5:39   ` [PATCH 07/15] ACPI / PM: Make acpi_pm_device_sleep_state() follow the specification Len Brown
2012-06-04  5:39   ` [PATCH 08/15] acpi_video: fix leaking PCI references Len Brown
2012-06-04  5:40   ` [PATCH 09/15] acpi_video: Intel video is not always i915 Len Brown
2012-06-04  5:40   ` [PATCH 10/15] gma500: don't register the ACPI video bus Len Brown
2012-06-04  5:40   ` [PATCH 11/15] ACPI video: use after input_unregister_device() Len Brown
2012-06-04  5:40   ` [PATCH 12/15] tools/power turbostat: fix un-intended affinity of forked program Len Brown
2012-06-04  5:40   ` [PATCH 13/15] tools/power turbostat: fix IVB support Len Brown
2012-06-04  5:40   ` [PATCH 14/15] drivers: acpi: Fix dependency for ACPI_HOTPLUG_CPU Len Brown
2012-06-04  5:40   ` [PATCH 15/15] ACPI: fix acpi_bus.h build warnings when ACPI is not enabled Len Brown

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=38c92fff988d518fe80dc23d0d44d66bd7e47ddd.1338786831.git.len.brown@intel.com \
    --to=lenb@kernel.org \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@lists.linux-foundation.org \
    --cc=rjw@sisk.pl \
    /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

all inboxes | Powered by JetHome®