From: "Rafael J. Wysocki" <rjw@sisk.pl>
To: linux-pm@lists.linux-foundation.org
Cc: ACPI Devel Maling List <linux-acpi@vger.kernel.org>,
Jesse Barnes <jbarnes@virtuousgeek.org>,
Henrique de Moraes Holschuh <hmh@hmh.eng.br>,
Linux PCI <linux-pci@vger.kernel.org>,
ykzhao <yakui.zhao@intel.com>
Subject: [RFC][PATCH 4/4 replacement] ACPI PM: Replace wakeup.prepared with reference counter
Date: Sat, 5 Sep 2009 00:05:28 +0200 [thread overview]
Message-ID: <200909050005.28792.rjw@sisk.pl> (raw)
In-Reply-To: <200909050003.46520.rjw@sisk.pl>
From: Rafael J. Wysocki <rjw@sisk.pl>
The wakeup.prepared flag is used for marking devices that have the
wake-up power already enabled, so that the wake-up power is not
enabled twice in a row for the same device. This assumes, however,
that device wake-up power will only be enabled once, while the device
is being prepared for a system-wide sleep transition, and the second
attempt is made by acpi_enable_wakeup_device_prep().
With the upcoming PCI wake-up rework this assumption will not hold
any more for PCI bridges and the root bridge whose wake-up power
may be enabled as a result of wake-up enable propagation from other
devices (eg. add-on devices that are not associated with any GPEs).
Thus, there may be many attempts to enable wake-up power on a PCI
bridge or the root bridge during a system power state transition
and it's better to replace wakeup.prepared with a reference counter.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
drivers/acpi/power.c | 58 ++++++++++++++++++++++++++++--------------------
drivers/acpi/scan.c | 1
drivers/acpi/wakeup.c | 4 +--
include/acpi/acpi_bus.h | 2 -
4 files changed, 39 insertions(+), 26 deletions(-)
Index: linux-2.6/drivers/acpi/scan.c
===================================================================
--- linux-2.6.orig/drivers/acpi/scan.c
+++ linux-2.6/drivers/acpi/scan.c
@@ -782,6 +782,7 @@ static int acpi_bus_get_wakeup_device_fl
kfree(buffer.pointer);
device->wakeup.flags.valid = 1;
+ device->wakeup.prepare_count = 0;
/* Call _PSW/_DSW object to disable its ability to wake the sleeping
* system for the ACPI device with the _PRW object.
* The _PSW object is depreciated in ACPI 3.0 and is replaced by _DSW.
Index: linux-2.6/include/acpi/acpi_bus.h
===================================================================
--- linux-2.6.orig/include/acpi/acpi_bus.h
+++ linux-2.6/include/acpi/acpi_bus.h
@@ -248,7 +248,6 @@ struct acpi_device_perf {
/* Wakeup Management */
struct acpi_device_wakeup_flags {
u8 valid:1; /* Can successfully enable wakeup? */
- u8 prepared:1; /* Has the wake-up capability been enabled? */
u8 run_wake:1; /* Run-Wake GPE devices */
};
@@ -263,6 +262,7 @@ struct acpi_device_wakeup {
struct acpi_handle_list resources;
struct acpi_device_wakeup_state state;
struct acpi_device_wakeup_flags flags;
+ int prepare_count;
};
/* Device */
Index: linux-2.6/drivers/acpi/power.c
===================================================================
--- linux-2.6.orig/drivers/acpi/power.c
+++ linux-2.6/drivers/acpi/power.c
@@ -44,6 +44,8 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
+#include "sleep.h"
+
#define _COMPONENT ACPI_POWER_COMPONENT
ACPI_MODULE_NAME("power");
#define ACPI_POWER_CLASS "power_resource"
@@ -361,17 +363,15 @@ int acpi_device_sleep_wake(struct acpi_d
*/
int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
{
- int i, err;
+ int i, err = 0;
if (!dev || !dev->wakeup.flags.valid)
return -EINVAL;
- /*
- * Do not execute the code below twice in a row without calling
- * acpi_disable_wakeup_device_power() in between for the same device
- */
- if (dev->wakeup.flags.prepared)
- return 0;
+ mutex_lock(&acpi_device_lock);
+
+ if (dev->wakeup.prepare_count++)
+ goto out;
/* Open power resource */
for (i = 0; i < dev->wakeup.resources.count; i++) {
@@ -379,7 +379,8 @@ int acpi_enable_wakeup_device_power(stru
if (ret) {
printk(KERN_ERR PREFIX "Transition power state\n");
dev->wakeup.flags.valid = 0;
- return -ENODEV;
+ err = -ENODEV;
+ goto err_out;
}
}
@@ -388,9 +389,13 @@ int acpi_enable_wakeup_device_power(stru
* in arbitrary power state afterwards.
*/
err = acpi_device_sleep_wake(dev, 1, sleep_state, 3);
- if (!err)
- dev->wakeup.flags.prepared = 1;
+ err_out:
+ if (err)
+ dev->wakeup.prepare_count = 0;
+
+ out:
+ mutex_unlock(&acpi_device_lock);
return err;
}
@@ -402,35 +407,42 @@ int acpi_enable_wakeup_device_power(stru
*/
int acpi_disable_wakeup_device_power(struct acpi_device *dev)
{
- int i, ret;
+ int i, err = 0;
if (!dev || !dev->wakeup.flags.valid)
return -EINVAL;
+ mutex_lock(&acpi_device_lock);
+
+ if (--dev->wakeup.prepare_count > 0)
+ goto out;
+
/*
- * Do not execute the code below twice in a row without calling
- * acpi_enable_wakeup_device_power() in between for the same device
+ * Executing the code below even if prepare_count is already zero when
+ * the function is called may be useful, for example for initialisation.
*/
- if (!dev->wakeup.flags.prepared)
- return 0;
+ if (dev->wakeup.prepare_count < 0)
+ dev->wakeup.prepare_count = 0;
- dev->wakeup.flags.prepared = 0;
-
- ret = acpi_device_sleep_wake(dev, 0, 0, 0);
- if (ret)
- return ret;
+ err = acpi_device_sleep_wake(dev, 0, 0, 0);
+ if (err)
+ goto out;
/* Close power resource */
for (i = 0; i < dev->wakeup.resources.count; i++) {
- ret = acpi_power_off_device(dev->wakeup.resources.handles[i], dev);
+ int ret = acpi_power_off_device(
+ dev->wakeup.resources.handles[i], dev);
if (ret) {
printk(KERN_ERR PREFIX "Transition power state\n");
dev->wakeup.flags.valid = 0;
- return -ENODEV;
+ err = -ENODEV;
+ goto out;
}
}
- return ret;
+ out:
+ mutex_unlock(&acpi_device_lock);
+ return err;
}
/* --------------------------------------------------------------------------
Index: linux-2.6/drivers/acpi/wakeup.c
===================================================================
--- linux-2.6.orig/drivers/acpi/wakeup.c
+++ linux-2.6/drivers/acpi/wakeup.c
@@ -68,7 +68,7 @@ void acpi_enable_wakeup_device(u8 sleep_
/* If users want to disable run-wake GPE,
* we only disable it for wake and leave it for runtime
*/
- if ((!dev->wakeup.state.enabled && !dev->wakeup.flags.prepared)
+ if ((!dev->wakeup.state.enabled && !dev->wakeup.prepare_count)
|| sleep_state > (u32) dev->wakeup.sleep_state) {
if (dev->wakeup.flags.run_wake) {
/* set_gpe_type will disable GPE, leave it like that */
@@ -100,7 +100,7 @@ void acpi_disable_wakeup_device(u8 sleep
if (!dev->wakeup.flags.valid)
continue;
- if ((!dev->wakeup.state.enabled && !dev->wakeup.flags.prepared)
+ if ((!dev->wakeup.state.enabled && !dev->wakeup.prepare_count)
|| sleep_state > (u32) dev->wakeup.sleep_state) {
if (dev->wakeup.flags.run_wake) {
acpi_set_gpe_type(dev->wakeup.gpe_device,
next prev parent reply other threads:[~2009-09-04 22:05 UTC|newest]
Thread overview: 53+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-08-29 22:41 [PATCH] ACPI / PM: Allow PCI root bridges to wake up the system Rafael J. Wysocki
2009-08-31 19:41 ` [linux-pm] " Rafael J. Wysocki
2009-08-31 21:24 ` [RFC][PATCH update] " Rafael J. Wysocki
2009-08-31 21:24 ` Rafael J. Wysocki
2009-09-01 13:25 ` Matthew Garrett
2009-09-01 13:25 ` Matthew Garrett
2009-09-01 19:03 ` Rafael J. Wysocki
2009-09-01 22:41 ` [linux-pm] " Rafael J. Wysocki
2009-09-03 22:02 ` [RFC][PATCH 0/4] PCI/ACPI PM: Propagate wake-up enable upstream Rafael J. Wysocki
2009-09-03 22:03 ` [RFC][PATCH 1/4] PCI PM: Simplify PCI wake-up code Rafael J. Wysocki
2009-09-03 22:03 ` Rafael J. Wysocki
2009-09-03 22:04 ` [RFC][PATCH 2/4] PCI/ACPI PM: Rework some debug messages Rafael J. Wysocki
2009-09-03 22:04 ` Rafael J. Wysocki
2009-09-03 22:05 ` [RFC][PATCH 3/4] PCI PM: Introduce device flag wakeup_prepared Rafael J. Wysocki
2009-09-03 22:05 ` Rafael J. Wysocki
2009-09-03 22:07 ` [RFC][PATCH 4/4] PCI/ACPI PM: Propagate wake-up enable for devices w/o ACPI support Rafael J. Wysocki
2009-09-04 2:13 ` ykzhao
2009-09-04 14:39 ` Rafael J. Wysocki
2009-09-04 14:56 ` Matthew Garrett
2009-09-04 14:56 ` Matthew Garrett
2009-09-04 22:00 ` Rafael J. Wysocki
2009-09-04 22:06 ` Matthew Garrett
2009-09-04 22:06 ` Matthew Garrett
2009-09-04 22:21 ` Rafael J. Wysocki
2009-09-04 22:21 ` Rafael J. Wysocki
2009-09-04 22:00 ` Rafael J. Wysocki
2009-09-04 14:39 ` Rafael J. Wysocki
2009-09-04 2:13 ` ykzhao
2009-09-04 22:03 ` [linux-pm] " Rafael J. Wysocki
2009-09-04 22:05 ` [RFC][PATCH 4/4 replacement] ACPI PM: Replace wakeup.prepared with reference counter Rafael J. Wysocki
2009-09-04 22:05 ` Rafael J. Wysocki [this message]
2009-09-04 22:06 ` [RFC][PATCH 5] PCI/ACPI PM: Propagate wake-up enable for devices w/o ACPI support Rafael J. Wysocki
2009-09-04 22:06 ` Rafael J. Wysocki
2009-09-04 22:03 ` [RFC][PATCH 4/4] " Rafael J. Wysocki
2009-09-03 22:07 ` Rafael J. Wysocki
2009-09-08 21:11 ` [PATCH 0/5 update] PCI / ACPI PM: Propagate wake-up enable upstream Rafael J. Wysocki
2009-09-08 21:11 ` Rafael J. Wysocki
2009-09-08 21:12 ` [PATCH 1/5] PCI PM: Simplify PCI wake-up code Rafael J. Wysocki
2009-09-08 21:12 ` Rafael J. Wysocki
2009-09-09 21:20 ` Jesse Barnes
2009-09-09 21:20 ` Jesse Barnes
2009-09-08 21:13 ` [PATCH 2/5] PCI / ACPI PM: Rework some debug messages Rafael J. Wysocki
2009-09-08 21:13 ` Rafael J. Wysocki
2009-09-08 21:14 ` [PATCH 3/5] PCI PM: Introduce device flag wakeup_prepared Rafael J. Wysocki
2009-09-08 21:14 ` Rafael J. Wysocki
2009-09-08 21:15 ` [PATCH 4/5] ACPI PM: Replace wakeup.prepared with reference counter Rafael J. Wysocki
2009-09-08 21:15 ` Rafael J. Wysocki
2009-09-08 21:16 ` [PATCH 5/5] PCI / ACPI PM: Propagate wake-up enable for devices w/o ACPI support Rafael J. Wysocki
2009-09-08 21:16 ` Rafael J. Wysocki
2009-09-03 22:02 ` [RFC][PATCH 0/4] PCI/ACPI PM: Propagate wake-up enable upstream Rafael J. Wysocki
2009-09-01 22:41 ` [RFC][PATCH update] ACPI / PM: Allow PCI root bridges to wake up the system Rafael J. Wysocki
2009-09-01 19:03 ` Rafael J. Wysocki
2009-08-31 19:41 ` [PATCH] " 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=200909050005.28792.rjw@sisk.pl \
--to=rjw@sisk.pl \
--cc=hmh@hmh.eng.br \
--cc=jbarnes@virtuousgeek.org \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=linux-pm@lists.linux-foundation.org \
--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.