All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Rafael J. Wysocki" <rjw@sisk.pl>
To: ACPI Devel Maling List <linux-acpi@vger.kernel.org>
Cc: Alan Stern <stern@rowland.harvard.edu>,
	Andi Kleen <andi@firstfloor.org>,
	Jesse Barnes <jbarnes@virtuousgeek.org>,
	pm list <linux-pm@lists.linux-foundation.org>,
	Zhang Rui <rui.zhang@intel.com>,
	Zhao Yakui <yakui.zhao@intel.com>, Pavel Machek <pavel@suse.cz>
Subject: [PATCH 5/9] ACPI: Introduce acpi_device_sleep_wake function
Date: Wed, 2 Jul 2008 00:06:51 +0200	[thread overview]
Message-ID: <200807020006.52838.rjw@sisk.pl> (raw)
In-Reply-To: <200807012356.26669.rjw@sisk.pl>

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

ACPI: Introduce acpi_device_sleep_wake function

The currect ACPI code attempts to execute _PSW at three different
places and in one of them only it tries to execute _DSW before _PSW,
which is inconsistent with the other two cases.

Move the execution of _DSW and _PSW into a separate function called
acpi_device_sleep_wake() and call it wherever appropriate instead of
executing _DSW and/or _PSW directly.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@suse.cz>
---
 drivers/acpi/power.c        |  118 ++++++++++++++++++++++++++++++--------------
 drivers/acpi/scan.c         |   42 ++-------------
 drivers/acpi/sleep/wakeup.c |    2 
 include/acpi/acpi_drivers.h |    4 +
 4 files changed, 92 insertions(+), 74 deletions(-)

Index: linux-next/drivers/acpi/power.c
===================================================================
--- linux-next.orig/drivers/acpi/power.c
+++ linux-next/drivers/acpi/power.c
@@ -292,69 +292,115 @@ static int acpi_power_off_device(acpi_ha
 	return 0;
 }
 
+/**
+ * acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in
+ *                          ACPI 3.0) _PSW (Power State Wake)
+ * @dev: Device to handle.
+ * @enable: 0 - disable, 1 - enable the wake capabilities of the device.
+ * @sleep_state: Target sleep state of the system.
+ * @dev_state: Target power state of the device.
+ *
+ * Execute _DSW (Device Sleep Wake) or (deprecated in ACPI 3.0) _PSW (Power
+ * State Wake) for the device, if present.  On failure reset the device's
+ * wakeup.flags.valid flag.
+ *
+ * RETURN VALUE:
+ * 0 if either _DSW or _PSW has been successfully executed
+ * 0 if neither _DSW nor _PSW has been found
+ * -ENODEV if the execution of either _DSW or _PSW has failed
+ */
+int acpi_device_sleep_wake(struct acpi_device *dev,
+                           int enable, int sleep_state, int dev_state)
+{
+	union acpi_object in_arg[3];
+	struct acpi_object_list arg_list = { 3, in_arg };
+	acpi_status status = AE_OK;
+
+	/*
+	 * Try to execute _DSW first.
+	 *
+	 * Three agruments are needed for the _DSW object:
+	 * Argument 0: enable/disable the wake capabilities
+	 * Argument 1: target system state
+	 * Argument 2: target device state
+	 * When _DSW object is called to disable the wake capabilities, maybe
+	 * the first argument is filled. The values of the other two agruments
+	 * are meaningless.
+	 */
+	in_arg[0].type = ACPI_TYPE_INTEGER;
+	in_arg[0].integer.value = enable;
+	in_arg[1].type = ACPI_TYPE_INTEGER;
+	in_arg[1].integer.value = sleep_state;
+	in_arg[2].type = ACPI_TYPE_INTEGER;
+	in_arg[2].integer.value = dev_state;
+	status = acpi_evaluate_object(dev->handle, "_DSW", &arg_list, NULL);
+	if (ACPI_SUCCESS(status)) {
+		return 0;
+	} else if (status != AE_NOT_FOUND) {
+		printk(KERN_ERR PREFIX "_DSW execution failed\n");
+		dev->wakeup.flags.valid = 0;
+		return -ENODEV;
+	}
+
+	/* Execute _PSW */
+	arg_list.count = 1;
+	in_arg[0].integer.value = enable;
+	status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL);
+	if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
+		printk(KERN_ERR PREFIX "_PSW execution failed\n");
+		dev->wakeup.flags.valid = 0;
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
 /*
  * Prepare a wakeup device, two steps (Ref ACPI 2.0:P229):
  * 1. Power on the power resources required for the wakeup device 
- * 2. Enable _PSW (power state wake) for the device if present
+ * 2. Execute _DSW (Device Sleep Wake) or (deprecated in ACPI 3.0) _PSW (Power
+ *    State Wake) for the device, if present
  */
-int acpi_enable_wakeup_device_power(struct acpi_device *dev)
+int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
 {
-	union acpi_object arg = { ACPI_TYPE_INTEGER };
-	struct acpi_object_list arg_list = { 1, &arg };
-	acpi_status status = AE_OK;
 	int i;
-	int ret = 0;
 
 	if (!dev || !dev->wakeup.flags.valid)
-		return -1;
+		return -EINVAL;
 
-	arg.integer.value = 1;
 	/* Open power resource */
 	for (i = 0; i < dev->wakeup.resources.count; i++) {
-		ret = acpi_power_on(dev->wakeup.resources.handles[i], dev);
+		int ret = acpi_power_on(dev->wakeup.resources.handles[i], dev);
 		if (ret) {
 			printk(KERN_ERR PREFIX "Transition power state\n");
 			dev->wakeup.flags.valid = 0;
-			return -1;
+			return -ENODEV;
 		}
 	}
 
-	/* Execute PSW */
-	status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL);
-	if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
-		printk(KERN_ERR PREFIX "Evaluate _PSW\n");
-		dev->wakeup.flags.valid = 0;
-		ret = -1;
-	}
-
-	return ret;
+	/*
+	 * Passing 3 as the third argument below means the device may be placed
+	 * in arbitrary power state afterwards.
+	 */
+	return acpi_device_sleep_wake(dev, 1, sleep_state, 3);
 }
 
 /*
  * Shutdown a wakeup device, counterpart of above method
- * 1. Disable _PSW (power state wake)
+ * 1. Execute _DSW (Device Sleep Wake) or (deprecated in ACPI 3.0) _PSW (Power
+ *    State Wake) for the device, if present
  * 2. Shutdown down the power resources
  */
 int acpi_disable_wakeup_device_power(struct acpi_device *dev)
 {
-	union acpi_object arg = { ACPI_TYPE_INTEGER };
-	struct acpi_object_list arg_list = { 1, &arg };
-	acpi_status status = AE_OK;
-	int i;
-	int ret = 0;
-
+	int i, ret;
 
 	if (!dev || !dev->wakeup.flags.valid)
-		return -1;
+		return -EINVAL;
 
-	arg.integer.value = 0;
-	/* Execute PSW */
-	status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL);
-	if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
-		printk(KERN_ERR PREFIX "Evaluate _PSW\n");
-		dev->wakeup.flags.valid = 0;
-		return -1;
-	}
+	ret = acpi_device_sleep_wake(dev, 0, 0, 0);
+	if (ret)
+		return ret;
 
 	/* Close power resource */
 	for (i = 0; i < dev->wakeup.resources.count; i++) {
@@ -362,7 +408,7 @@ int acpi_disable_wakeup_device_power(str
 		if (ret) {
 			printk(KERN_ERR PREFIX "Transition power state\n");
 			dev->wakeup.flags.valid = 0;
-			return -1;
+			return -ENODEV;
 		}
 	}
 
Index: linux-next/drivers/acpi/sleep/wakeup.c
===================================================================
--- linux-next.orig/drivers/acpi/sleep/wakeup.c
+++ linux-next/drivers/acpi/sleep/wakeup.c
@@ -42,7 +42,7 @@ void acpi_enable_wakeup_device_prep(u8 s
 			continue;
 
 		spin_unlock(&acpi_device_lock);
-		acpi_enable_wakeup_device_power(dev);
+		acpi_enable_wakeup_device_power(dev, sleep_state);
 		spin_lock(&acpi_device_lock);
 	}
 	spin_unlock(&acpi_device_lock);
Index: linux-next/include/acpi/acpi_drivers.h
===================================================================
--- linux-next.orig/include/acpi/acpi_drivers.h
+++ linux-next/include/acpi/acpi_drivers.h
@@ -87,7 +87,9 @@ struct pci_bus *pci_acpi_scan_root(struc
    -------------------------------------------------------------------------- */
 
 #ifdef CONFIG_ACPI_POWER
-int acpi_enable_wakeup_device_power(struct acpi_device *dev);
+int acpi_device_sleep_wake(struct acpi_device *dev,
+                           int enable, int sleep_state, int dev_state);
+int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state);
 int acpi_disable_wakeup_device_power(struct acpi_device *dev);
 int acpi_power_get_inferred_state(struct acpi_device *device);
 int acpi_power_transition(struct acpi_device *device, int state);
Index: linux-next/drivers/acpi/scan.c
===================================================================
--- linux-next.orig/drivers/acpi/scan.c
+++ linux-next/drivers/acpi/scan.c
@@ -703,9 +703,7 @@ static int acpi_bus_get_wakeup_device_fl
 	acpi_status status = 0;
 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 	union acpi_object *package = NULL;
-	union acpi_object in_arg[3];
-	struct acpi_object_list arg_list = { 3, in_arg };
-	acpi_status psw_status = AE_OK;
+	int psw_error;
 
 	struct acpi_device_id button_device_ids[] = {
 		{"PNP0C0D", 0},
@@ -737,39 +735,11 @@ static int acpi_bus_get_wakeup_device_fl
 	 * So it is necessary to call _DSW object first. Only when it is not
 	 * present will the _PSW object used.
 	 */
-	/*
-	 * Three agruments are needed for the _DSW object.
-	 * Argument 0: enable/disable the wake capabilities
-	 * When _DSW object is called to disable the wake capabilities, maybe
-	 * the first argument is filled. The value of the other two agruments
-	 * is meaningless.
-	 */
-	in_arg[0].type = ACPI_TYPE_INTEGER;
-	in_arg[0].integer.value = 0;
-	in_arg[1].type = ACPI_TYPE_INTEGER;
-	in_arg[1].integer.value = 0;
-	in_arg[2].type = ACPI_TYPE_INTEGER;
-	in_arg[2].integer.value = 0;
-	psw_status = acpi_evaluate_object(device->handle, "_DSW",
-						&arg_list, NULL);
-	if (ACPI_FAILURE(psw_status) && (psw_status != AE_NOT_FOUND))
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "error in evaluate _DSW\n"));
-	/*
-	 * When the _DSW object is not present, OSPM will call _PSW object.
-	 */
-	if (psw_status == AE_NOT_FOUND) {
-		/*
-		 * Only one agruments is required for the _PSW object.
-		 * agrument 0: enable/disable the wake capabilities
-		 */
-		arg_list.count = 1;
-		in_arg[0].integer.value = 0;
-		psw_status = acpi_evaluate_object(device->handle, "_PSW",
-						&arg_list, NULL);
-		if (ACPI_FAILURE(psw_status) && (psw_status != AE_NOT_FOUND))
-			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "error in "
-						"evaluate _PSW\n"));
-	}
+	psw_error = acpi_device_sleep_wake(device, 0, 0, 0);
+	if (psw_error)
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+				"error in _DSW or _PSW evaluation\n"));
+
 	/* Power button, Lid switch always enable wakeup */
 	if (!acpi_match_device_ids(device, button_device_ids))
 		device->wakeup.flags.run_wake = 1;

  parent reply	other threads:[~2008-07-01 22:14 UTC|newest]

Thread overview: 62+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-07-01 21:56 [PATCH 0/9] PCI PM: Handling of PCI devices wake-up functionality (rev. 3) Rafael J. Wysocki
2008-07-01 22:00 ` [PATCH 1/9] PCI ACPI: Remove acpi_platform_enable_wakeup Rafael J. Wysocki
2008-07-01 22:00 ` Rafael J. Wysocki
2008-07-01 22:03 ` [PATCH 2/9] ACPI: Introduce acpi_bus_power_manageable function Rafael J. Wysocki
2008-07-01 22:03 ` Rafael J. Wysocki
2008-07-01 22:04 ` [PATCH 3/9] PCI: Introduce platform_pci_power_manageable function Rafael J. Wysocki
2008-07-01 22:04 ` Rafael J. Wysocki
2008-07-01 22:05 ` [PATCH 4/9] PCI: Rework pci_set_power_state function (rev. 3) Rafael J. Wysocki
2008-07-01 22:05 ` Rafael J. Wysocki
2008-07-01 22:06 ` [PATCH 5/9] ACPI: Introduce acpi_device_sleep_wake function Rafael J. Wysocki
2008-07-01 22:06 ` Rafael J. Wysocki [this message]
2008-07-01 22:07 ` [PATCH 6/9] ACPI: Introduce new device wakeup flag 'prepared' Rafael J. Wysocki
2008-07-01 22:07 ` Rafael J. Wysocki
2008-07-01 22:08 ` [PATCH 7/9] PCI ACPI: Rework PCI handling of wake-up (rev. 4) Rafael J. Wysocki
2008-07-01 22:08 ` Rafael J. Wysocki
2008-07-02  7:30   ` Zhao Yakui
2008-07-02  7:30   ` Zhao Yakui
2008-07-02 10:16     ` Rafael J. Wysocki
2008-07-02 10:16     ` Rafael J. Wysocki
2008-07-01 22:09 ` [PATCH 8/9] PCI PM: Introduce pci_prepare_to_sleep and pci_back_from_sleep Rafael J. Wysocki
2008-07-01 22:09 ` Rafael J. Wysocki
2008-07-01 22:10 ` [PATCH 9/9] PCI: Simplify PCI device PM code (rev. 4) Rafael J. Wysocki
2008-07-01 22:10 ` Rafael J. Wysocki
2008-07-03 12:04 ` [PATCH 0/9] PCI PM: Handling of PCI devices wake-up functionality (rev. 3) Rafael J. Wysocki
2008-07-07  1:30 ` [PATCH 0/8] PCI PM: Handling of PCI devices wake-up functionality (rev. 4) Rafael J. Wysocki
2008-07-07  1:30   ` [PATCH 1/8] ACPI: Introduce acpi_bus_power_manageable function Rafael J. Wysocki
2008-07-07  1:30   ` Rafael J. Wysocki
2008-07-07  1:32   ` [PATCH 2/8] PCI: Introduce platform_pci_power_manageable function Rafael J. Wysocki
2008-07-07  1:32   ` Rafael J. Wysocki
2008-07-07  1:32   ` [PATCH 3/8] PCI: Rework pci_set_power_state function (rev. 4) Rafael J. Wysocki
2008-07-07  1:32   ` Rafael J. Wysocki
2008-07-07  1:33   ` [PATCH 4/8] ACPI: Introduce acpi_device_sleep_wake function Rafael J. Wysocki
2008-07-07  1:33   ` Rafael J. Wysocki
2008-07-07  1:34   ` [PATCH 5/8] ACPI: Introduce new device wakeup flag 'prepared' Rafael J. Wysocki
2008-07-07 14:08     ` Pavel Machek
2008-07-07 14:08     ` Pavel Machek
2008-07-07  1:34   ` Rafael J. Wysocki
2008-07-07  1:34   ` [PATCH 6/8] PCI ACPI: Rework PCI handling of wake-up (rev. 5) Rafael J. Wysocki
2008-07-07  1:34   ` Rafael J. Wysocki
2008-07-11 20:30     ` Pavel Machek
2008-07-11 20:30     ` Pavel Machek
2008-07-07  1:35   ` [PATCH 7/8] PCI PM: Introduce pci_prepare_to_sleep and pci_back_from_sleep Rafael J. Wysocki
2008-07-11 20:31     ` Pavel Machek
2008-07-11 20:31     ` Pavel Machek
2008-07-07  1:35   ` Rafael J. Wysocki
2008-07-07  1:36   ` [PATCH 8/8] PCI: Simplify PCI device PM code (rev. 4) Rafael J. Wysocki
2008-07-11 20:37     ` Pavel Machek
2008-07-11 20:37     ` Pavel Machek
2008-07-11 20:45       ` Rafael J. Wysocki
2008-07-11 20:45       ` Rafael J. Wysocki
2008-07-11 20:49         ` Pavel Machek
2008-07-11 20:49         ` Pavel Machek
2008-07-07  1:36   ` Rafael J. Wysocki
2008-07-08  0:49   ` [PATCH 0/8] PCI PM: Handling of PCI devices wake-up functionality " Jesse Barnes
2008-07-08 14:42     ` Rafael J. Wysocki
2008-07-08 14:42     ` Rafael J. Wysocki
2008-07-13 20:45   ` PCI PM: Fix pci_prepare_to_sleep Rafael J. Wysocki
2008-07-13 20:45   ` Rafael J. Wysocki
2008-07-14 21:27     ` Jesse Barnes
2008-07-14 21:40       ` Rafael J. Wysocki
2008-07-14 21:40       ` Rafael J. Wysocki
2008-07-07  1:30 ` [PATCH 0/8] PCI PM: Handling of PCI devices wake-up functionality (rev. 4) 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=200807020006.52838.rjw@sisk.pl \
    --to=rjw@sisk.pl \
    --cc=andi@firstfloor.org \
    --cc=jbarnes@virtuousgeek.org \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-pm@lists.linux-foundation.org \
    --cc=pavel@suse.cz \
    --cc=rui.zhang@intel.com \
    --cc=stern@rowland.harvard.edu \
    --cc=yakui.zhao@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.