public inbox for linux-acpi@vger.kernel.org
 help / color / mirror / Atom feed
From: David Brownell <david-b@pacbell.net>
To: linux-acpi@vger.kernel.org
Cc: linux-pm@lists.linux-foundation.org
Subject: [RESEND patch 2.6.25] ACPI uses device_may_wakeup() policy inputs
Date: Fri, 18 Apr 2008 21:18:04 -0700	[thread overview]
Message-ID: <200804182118.05228.david-b@pacbell.net> (raw)
In-Reply-To: <200803201422.55014.david-b@pacbell.net>

This imports the driver model device.power.may_wakeup flags to ACPI,
using it to *REPLACE* the /proc/acpi/wakeup flags for some devices.
It depends on the previous patch making device.power.can_wakeup behave.
It does that by:

 - Implementing platform_enable_wakeup(), which is currently invoked only
   by pci_enable_wake().  When that's called -- probably in the driver
   suspend() call -- it updates acpi_device.wakeup.state.enabled flag in
   the same way writing to /proc/acpi/wakeup updates it.
   
 - Updating the usage of the corresponding ACPI flags when turning on
   wakeup power domains and GPEs.

THIS PATCH NEEDS MORE ATTENTION because of the way the ACPI method
invocations have been changing, e.g. the 1.0 vs 2.0 sequencing.

Right now it's not clear to me whether the GPEs are always enabled at
the right time, and for that matter whether the rules haven't changed
so that drivers can no longer effectively control those settings from
suspend() unless acpi_new_pts_ordering is in effect.

ACPI systems see behavioral changes as follows:

   * Wakeup-aware PCI drivers no longer need to have someone override the
     initial system config by writing to /proc/acpi/wakeup; existing calls
     to pci_enable_wake() suffice.  For wakeup-unaware drivers, it's still
     not clearly safe to enable wakeup in /proc/acpi/wakeup.

   * Non-PCI frameworks (as for PS2 serial ports) could call the platform
     hook like PCI does, supporting wakeup-aware drivers.

   * The /sys/devices/.../power/wakeup flags are a different kind of manual
     override.  They _disable_ wakeup for broken hardware or drivers, rather
     than _enabling_ it in the hope that unmodified drivers won't break when
     their hardware triggers wakeup events.

NOT YET SIGNED-OFF ... primarily because of the confusion about
the order in which ACPI methods get called during entry to suspend
states.  Presumably one of the "new style" PM methods calls will
now always work for drivers wanting to enable wakeup methods...

---
 drivers/acpi/sleep/main.c   |    2 +-
 drivers/acpi/sleep/wakeup.c |   44 ++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 43 insertions(+), 3 deletions(-)

--- g26.orig/drivers/acpi/sleep/main.c	2008-02-24 02:07:57.000000000 -0800
+++ g26/drivers/acpi/sleep/main.c	2008-02-24 02:08:04.000000000 -0800
@@ -470,7 +470,7 @@ int acpi_pm_device_sleep_state(struct de
 	 * can wake the system.  _S0W may be valid, too.
 	 */
 	if (acpi_target_sleep_state == ACPI_STATE_S0 ||
-	    (device_may_wakeup(dev) && adev->wakeup.state.enabled &&
+	    (device_may_wakeup(dev) &&
 	     adev->wakeup.sleep_state <= acpi_target_sleep_state)) {
 		acpi_status status;
 
--- g26.orig/drivers/acpi/sleep/wakeup.c	2008-02-24 02:03:27.000000000 -0800
+++ g26/drivers/acpi/sleep/wakeup.c	2008-02-24 02:08:04.000000000 -0800
@@ -35,12 +35,22 @@ void acpi_enable_wakeup_device_prep(u8 s
 		struct acpi_device *dev = container_of(node,
 						       struct acpi_device,
 						       wakeup_list);
+		struct device *ldev;
 
 		if (!dev->wakeup.flags.valid ||
 		    !dev->wakeup.state.enabled ||
 		    (sleep_state > (u32) dev->wakeup.sleep_state))
 			continue;
 
+		ldev = acpi_get_physical_device(dev->handle);
+		if (ldev) {
+			int flag = device_may_wakeup(ldev);
+
+			put_device(ldev);
+			if (!flag)
+				continue;
+		}
+
 		spin_unlock(&acpi_device_lock);
 		acpi_enable_wakeup_device_power(dev);
 		spin_lock(&acpi_device_lock);
@@ -57,8 +67,8 @@ void acpi_enable_wakeup_device(u8 sleep_
 {
 	struct list_head *node, *next;
 
-	/* 
-	 * Caution: this routine must be invoked when interrupt is disabled 
+	/*
+	 * Caution: this routine must be invoked when interrupt is disabled
 	 * Refer ACPI2.0: P212
 	 */
 	ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device");
@@ -107,6 +117,7 @@ void acpi_disable_wakeup_device(u8 sleep
 	list_for_each_safe(node, next, &acpi_wakeup_device_list) {
 		struct acpi_device *dev =
 			container_of(node, struct acpi_device, wakeup_list);
+		struct device *ldev;
 
 		if (!dev->wakeup.flags.valid)
 			continue;
@@ -125,6 +136,15 @@ void acpi_disable_wakeup_device(u8 sleep
 			continue;
 		}
 
+		ldev = acpi_get_physical_device(dev->handle);
+		if (ldev) {
+			int flag = device_may_wakeup(ldev);
+
+			put_device(ldev);
+			if (!flag)
+				continue;
+		}
+
 		spin_unlock(&acpi_device_lock);
 		acpi_disable_wakeup_device_power(dev);
 		/* Never disable run-wake GPE */
@@ -139,6 +159,24 @@ void acpi_disable_wakeup_device(u8 sleep
 	spin_unlock(&acpi_device_lock);
 }
 
+static int acpi_platform_enable_wakeup(struct device *dev, int is_on)
+{
+	struct acpi_device	*adev;
+	int			status;
+
+	if (!device_can_wakeup(dev))
+		return -EINVAL;
+	if (is_on && !device_may_wakeup(dev))
+		return -EINVAL;
+
+	status = acpi_bus_get_device(DEVICE_ACPI_HANDLE(dev), &adev);
+	if (status < 0)
+		return status;
+
+	adev->wakeup.state.enabled = !!is_on;
+	return 0;
+}
+
 static int __init acpi_wakeup_device_init(void)
 {
 	struct list_head *node, *next;
@@ -146,6 +184,8 @@ static int __init acpi_wakeup_device_ini
 	if (acpi_disabled)
 		return 0;
 
+	platform_enable_wakeup = acpi_platform_enable_wakeup;
+
 	spin_lock(&acpi_device_lock);
 	list_for_each_safe(node, next, &acpi_wakeup_device_list) {
 		struct acpi_device *dev = container_of(node,

  reply	other threads:[~2008-04-19  4:18 UTC|newest]

Thread overview: 57+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-03-20 21:08 [patch 2.6.25-rc6 0/7] misc pm wake patches David Brownell
2008-03-20 21:09 ` [patch 2.6.25-rc6 1/7] crosslink ACPI and "real" device nodes David Brownell
2008-03-21  6:43   ` Zhao Yakui
2008-03-21  7:31     ` David Brownell
2008-03-21  8:34       ` Zhao Yakui
2008-03-21  9:04         ` David Brownell
2008-03-20 21:10 ` [patch 2.6.25-rc6 2/7] acpi_pm_device_sleep_state() cleanup David Brownell
2008-03-24 16:30   ` [linux-pm] " Pavel Machek
2008-04-19  4:11   ` [RESEND patch 2.6.25] " David Brownell
2008-04-29 20:33   ` [RE-RESEND patch 2.6.25-git] " David Brownell
2008-04-29 21:49     ` Rafael J. Wysocki
2008-04-29 22:12       ` David Brownell
2008-04-30 12:07         ` Rafael J. Wysocki
2008-03-20 21:12 ` [patch 2.6.25-rc6 3/7] pci_choose_state() cleanup and fixes David Brownell
2008-03-20 22:37   ` Rafael J. Wysocki
2008-03-20 23:03     ` David Brownell
2008-03-21  0:22       ` Rafael J. Wysocki
2008-03-21  0:55         ` [linux-pm] " Alan Stern
2008-03-21  1:47           ` Rafael J. Wysocki
2008-03-21  8:15             ` David Brownell
2008-03-21 16:23               ` Rafael J. Wysocki
2008-03-22 17:55                 ` David Brownell
2008-03-22 18:11                   ` Rafael J. Wysocki
2008-03-22 18:29                     ` David Brownell
2008-03-21  7:53         ` David Brownell
2008-03-21 16:38           ` Rafael J. Wysocki
2008-03-22 17:49             ` David Brownell
2008-03-22 18:34               ` Rafael J. Wysocki
2008-04-14  4:59                 ` David Brownell
2008-03-20 21:15 ` [patch 2.6.25-rc6 4/7] USB uses pci_choose_state() David Brownell
2008-03-20 21:20 ` [patch 2.6.25-rc6 5/7] ACPI sets up device.power.can_wakeup flags David Brownell
2008-03-21  7:43   ` Zhao Yakui
2008-04-19  4:14   ` [RESEND patch 2.6.25] " David Brownell
2008-04-22  2:48     ` Zhang Rui
2008-03-20 21:22 ` [patch 2.6.25-rc6 6/7] ACPI uses device_may_wakeup() policy inputs David Brownell
2008-04-19  4:18   ` David Brownell [this message]
2008-04-22  2:42     ` [RESEND patch 2.6.25] " Zhang Rui
2008-04-26 19:29       ` David Brownell
2008-04-22 13:30     ` Zhao Yakui
2008-04-26 19:37       ` David Brownell
2008-04-28 12:48         ` Zhao Yakui
2008-04-28  8:50           ` Zhang Rui
2008-04-28 13:43             ` [linux-pm] " Alan Stern
2008-04-29 23:38               ` David Brownell
2008-04-30 13:58                 ` Alan Stern
2008-05-14 14:56                   ` Pavel Machek
2008-04-28 22:28             ` David Brownell
2008-04-28 21:35           ` Henrique de Moraes Holschuh
2008-04-28 22:20             ` David Brownell
2008-04-28 22:54               ` Henrique de Moraes Holschuh
2008-04-29  0:20                 ` David Brownell
2008-04-29 20:32               ` David Brownell
2008-04-28 22:24           ` David Brownell
2008-04-28 22:26           ` David Brownell
2008-03-20 21:25 ` [patch 2.6.25-rc6 7/7] PCI set up device.power.can_wakeup flags David Brownell
2008-03-20 21:53   ` [linux-pm] " Alan Stern
2008-03-20 22:22     ` David Brownell

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=200804182118.05228.david-b@pacbell.net \
    --to=david-b@pacbell.net \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-pm@lists.linux-foundation.org \
    /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