From: "Rafael J. Wysocki" <rjw@sisk.pl>
To: Len Brown <lenb@kernel.org>
Cc: Alan Stern <stern@rowland.harvard.edu>,
Pavel Machek <pavel@ucw.cz>,
Johannes Berg <johannes@sipsolutions.net>,
pm list <linux-pm@lists.linux-foundation.org>,
ACPI Devel Maling List <linux-acpi@vger.kernel.org>,
Adrian Bunk <bunk@kernel.org>
Subject: [PATCH 4/8] Suspend: Testing facility (rev. 2)
Date: Mon, 19 Nov 2007 23:41:19 +0100 [thread overview]
Message-ID: <200711192341.20857.rjw@sisk.pl> (raw)
In-Reply-To: <200711192332.15078.rjw@sisk.pl>
From: Rafael J. Wysocki <rjw@sisk.pl>
Introduce sysfs attribute /sys/power/pm_test allowing one to test the suspend
core code. Namely, writing one of the strings:
freezer
devices
platform
processors
core
to this file causes the suspend code to work in one of the test modes defined as
follows:
freezer
- test the freezing of processes
devices
- test the freezing of processes and suspending of devices
platform
- test the freezing of processes, suspending of devices and platform global
control methods(*)
processors
- test the freezing of processes, suspending of devices, platform global
control methods and the disabling of nonboot CPUs
core
- test the freezing of processes, suspending of devices, platform global
control methods, the disabling of nonboot CPUs and suspending of
platform/system devices
(*) These are ACPI global control methods on ACPI systems
Then, if a suspend is started by normal means, the suspend core will perform
its normal operations up to the point indicated by given test level. Next, it
will wait for 5 seconds and carry out the resume operations needed to transition
the system back to the fully functional state.
Writing "none" to /sys/power/pm_test turns the testing off.
When open for reading, /sys/power/pm_test contains a space-separated list of all
available tests (including "none" that represents the normal functionality) in
which the current test level is indicated by square brackets.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
---
kernel/power/main.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++-----
kernel/power/power.h | 18 ++++++++
2 files changed, 118 insertions(+), 9 deletions(-)
Index: linux-2.6/kernel/power/main.c
===================================================================
--- linux-2.6.orig/kernel/power/main.c
+++ linux-2.6/kernel/power/main.c
@@ -28,6 +28,80 @@ BLOCKING_NOTIFIER_HEAD(pm_chain_head);
DEFINE_MUTEX(pm_mutex);
+#ifdef CONFIG_PM_DEBUG
+int pm_test_level = TEST_NONE;
+
+static int suspend_test(int level)
+{
+ if (pm_test_level == level) {
+ printk(KERN_INFO "suspend debug: Waiting for 5 seconds.\n");
+ mdelay(5000);
+ return 1;
+ }
+ return 0;
+}
+
+static const char * const pm_tests[__TEST_AFTER_LAST] = {
+ [TEST_NONE] = "none",
+ [TEST_CORE] = "core",
+ [TEST_CPUS] = "processors",
+ [TEST_PLATFORM] = "platform",
+ [TEST_DEVICES] = "devices",
+ [TEST_FREEZER] = "freezer",
+};
+
+static ssize_t pm_test_show(struct kset *kset, char *buf)
+{
+ char *s = buf;
+ int level;
+
+ for (level = TEST_FIRST; level <= TEST_MAX; level++)
+ if (pm_tests[level]) {
+ if (level == pm_test_level)
+ s += sprintf(s, "[%s] ", pm_tests[level]);
+ else
+ s += sprintf(s, "%s ", pm_tests[level]);
+ }
+
+ if (s != buf)
+ /* convert the last space to a newline */
+ *(s-1) = '\n';
+
+ return (s - buf);
+}
+
+static ssize_t pm_test_store(struct kset *kset, const char *buf, size_t n)
+{
+ const char * const *s;
+ int level;
+ char *p;
+ int len;
+ int error = -EINVAL;
+
+ p = memchr(buf, '\n', n);
+ len = p ? p - buf : n;
+
+ mutex_lock(&pm_mutex);
+
+ level = TEST_FIRST;
+ for (s = &pm_tests[level]; level <= TEST_MAX; s++, level++)
+ if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) {
+ pm_test_level = level;
+ error = 0;
+ break;
+ }
+
+ mutex_unlock(&pm_mutex);
+
+ return error ? error : n;
+}
+
+power_attr(pm_test);
+#else /* !CONFIG_PM_DEBUG */
+static inline int suspend_test(int level) { return 0; }
+#endif /* !CONFIG_PM_DEBUG */
+
+
#ifdef CONFIG_SUSPEND
/* This is just an arbitrary number */
@@ -133,7 +207,10 @@ static int suspend_enter(suspend_state_t
printk(KERN_ERR "Some devices failed to power down\n");
goto Done;
}
- error = suspend_ops->enter(state);
+
+ if (!suspend_test(TEST_CORE))
+ error = suspend_ops->enter(state);
+
device_power_up();
Done:
arch_suspend_enable_irqs();
@@ -164,16 +241,25 @@ int suspend_devices_and_enter(suspend_st
printk(KERN_ERR "Some devices failed to suspend\n");
goto Resume_console;
}
+
+ if (suspend_test(TEST_DEVICES))
+ goto Resume_devices;
+
if (suspend_ops->prepare) {
error = suspend_ops->prepare();
if (error)
goto Resume_devices;
}
+
+ if (suspend_test(TEST_PLATFORM))
+ goto Finish;
+
error = disable_nonboot_cpus();
- if (!error)
+ if (!error && !suspend_test(TEST_CPUS))
suspend_enter(state);
enable_nonboot_cpus();
+ Finish:
if (suspend_ops->finish)
suspend_ops->finish();
Resume_devices:
@@ -240,12 +326,17 @@ static int enter_state(suspend_state_t s
printk("done.\n");
pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]);
- if ((error = suspend_prepare()))
+ error = suspend_prepare();
+ if (error)
goto Unlock;
+ if (suspend_test(TEST_FREEZER))
+ goto Finish;
+
pr_debug("PM: Entering %s sleep\n", pm_states[state]);
error = suspend_devices_and_enter(state);
+ Finish:
pr_debug("PM: Finishing wakeup.\n");
suspend_finish();
Unlock:
@@ -363,18 +454,18 @@ pm_trace_store(struct kset *kset, const
}
power_attr(pm_trace);
+#endif /* CONFIG_PM_TRACE */
static struct attribute * g[] = {
&state_attr.attr,
+#ifdef CONFIG_PM_TRACE
&pm_trace_attr.attr,
+#endif
+#ifdef CONFIG_PM_DEBUG
+ &pm_test_attr.attr,
+#endif
NULL,
};
-#else
-static struct attribute * g[] = {
- &state_attr.attr,
- NULL,
-};
-#endif /* CONFIG_PM_TRACE */
static struct attribute_group attr_group = {
.attrs = g,
Index: linux-2.6/kernel/power/power.h
===================================================================
--- linux-2.6.orig/kernel/power/power.h
+++ linux-2.6/kernel/power/power.h
@@ -190,3 +190,21 @@ int restore_highmem(void);
static inline unsigned int count_highmem_pages(void) { return 0; }
static inline int restore_highmem(void) { return 0; }
#endif
+
+/*
+ * Suspend test levels
+ */
+enum {
+ /* keep first */
+ TEST_NONE,
+ TEST_CORE,
+ TEST_CPUS,
+ TEST_PLATFORM,
+ TEST_DEVICES,
+ TEST_FREEZER,
+ /* keep last */
+ __TEST_AFTER_LAST
+};
+
+#define TEST_FIRST TEST_NONE
+#define TEST_MAX (__TEST_AFTER_LAST - 1)
-
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2007-11-19 22:40 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-11-19 22:32 [PATCH 0/8] Suspend/hibernation patches for 2.6.25 Rafael J. Wysocki
2007-11-19 22:33 ` [PATCH 1/8] ACPI: Fix mismerge in acpi_hibernation_finish Rafael J. Wysocki
2007-11-19 22:33 ` Rafael J. Wysocki
2007-11-19 22:36 ` [PATCH 2/8] Hibernation: Move function prototypes to header Rafael J. Wysocki
2007-11-19 22:36 ` Rafael J. Wysocki
2007-11-19 22:38 ` [PATCH 3/8] Hibernation: Add PM_RESTORE_PREPARE and PM_POST_RESTORE notifiers (rev. 2) Rafael J. Wysocki
2007-11-19 22:38 ` Rafael J. Wysocki
2007-11-19 22:41 ` Rafael J. Wysocki [this message]
2007-11-19 22:41 ` [PATCH 4/8] Suspend: Testing facility " Rafael J. Wysocki
2007-11-19 22:42 ` [PATCH 5/8] Hibernation: New testing " Rafael J. Wysocki
2007-11-19 22:42 ` Rafael J. Wysocki
2007-11-19 22:43 ` [PATCH 6/8] PM: Suspend/hibernation debug documentation update " Rafael J. Wysocki
2007-11-19 22:43 ` Rafael J. Wysocki
2007-11-19 22:46 ` [PATCH 7/8] PM: Make PM_TRACE more architecture independent Rafael J. Wysocki
2007-11-19 22:46 ` Rafael J. Wysocki
2007-11-19 22:49 ` [PATCH 8/8] PM: Convert PM notifiers to out-of-line code Rafael J. Wysocki
2007-11-19 22:49 ` Rafael J. Wysocki
2007-11-20 6:41 ` [PATCH 0/8] Suspend/hibernation patches for 2.6.25 Len Brown
2007-11-20 23:59 ` Rafael J. Wysocki
2007-11-21 1:13 ` Len Brown
2007-11-21 1:13 ` Len Brown
2007-11-20 23:59 ` Rafael J. Wysocki
2007-11-20 6:41 ` 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=200711192341.20857.rjw@sisk.pl \
--to=rjw@sisk.pl \
--cc=bunk@kernel.org \
--cc=johannes@sipsolutions.net \
--cc=lenb@kernel.org \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-pm@lists.linux-foundation.org \
--cc=pavel@ucw.cz \
--cc=stern@rowland.harvard.edu \
/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.