瀏覽代碼

[PATCH] PM: Add pm_trace switch

Add the pm_trace attribute in /sys/power which has to be explicitly set to
one to really enable the "PM tracing" code compiled in when CONFIG_PM_TRACE
is set (which modifies the machine's CMOS clock in unpredictable ways).

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Rafael J. Wysocki 18 年之前
父節點
當前提交
c5c6ba4e08
共有 3 個文件被更改,包括 59 次插入10 次删除
  1. 15 0
      Documentation/power/interface.txt
  2. 14 10
      include/linux/resume-trace.h
  3. 30 0
      kernel/power/main.c

+ 15 - 0
Documentation/power/interface.txt

@@ -52,3 +52,18 @@ suspend image will be as small as possible.
 
 
 Reading from this file will display the current image size limit, which
 Reading from this file will display the current image size limit, which
 is set to 500 MB by default.
 is set to 500 MB by default.
+
+/sys/power/pm_trace controls the code which saves the last PM event point in
+the RTC across reboots, so that you can debug a machine that just hangs
+during suspend (or more commonly, during resume).  Namely, the RTC is only
+used to save the last PM event point if this file contains '1'.  Initially it
+contains '0' which may be changed to '1' by writing a string representing a
+nonzero integer into it.
+
+To use this debugging feature you should attempt to suspend the machine, then
+reboot it and run
+
+	dmesg -s 1000000 | grep 'hash matches'
+
+CAUTION: Using it will cause your machine's real-time (CMOS) clock to be
+set to a random invalid time after a resume.

+ 14 - 10
include/linux/resume-trace.h

@@ -3,21 +3,25 @@
 
 
 #ifdef CONFIG_PM_TRACE
 #ifdef CONFIG_PM_TRACE
 
 
+extern int pm_trace_enabled;
+
 struct device;
 struct device;
 extern void set_trace_device(struct device *);
 extern void set_trace_device(struct device *);
 extern void generate_resume_trace(void *tracedata, unsigned int user);
 extern void generate_resume_trace(void *tracedata, unsigned int user);
 
 
 #define TRACE_DEVICE(dev) set_trace_device(dev)
 #define TRACE_DEVICE(dev) set_trace_device(dev)
-#define TRACE_RESUME(user) do {				\
-	void *tracedata;				\
-	asm volatile("movl $1f,%0\n"			\
-		".section .tracedata,\"a\"\n"		\
-		"1:\t.word %c1\n"			\
-		"\t.long %c2\n"				\
-		".previous"				\
-		:"=r" (tracedata)			\
-		: "i" (__LINE__), "i" (__FILE__));	\
-	generate_resume_trace(tracedata, user);		\
+#define TRACE_RESUME(user) do {					\
+	if (pm_trace_enabled) {					\
+		void *tracedata;				\
+		asm volatile("movl $1f,%0\n"			\
+			".section .tracedata,\"a\"\n"		\
+			"1:\t.word %c1\n"			\
+			"\t.long %c2\n"				\
+			".previous"				\
+			:"=r" (tracedata)			\
+			: "i" (__LINE__), "i" (__FILE__));	\
+		generate_resume_trace(tracedata, user);		\
+	}							\
 } while (0)
 } while (0)
 
 
 #else
 #else

+ 30 - 0
kernel/power/main.c

@@ -17,6 +17,7 @@
 #include <linux/pm.h>
 #include <linux/pm.h>
 #include <linux/console.h>
 #include <linux/console.h>
 #include <linux/cpu.h>
 #include <linux/cpu.h>
+#include <linux/resume-trace.h>
 
 
 #include "power.h"
 #include "power.h"
 
 
@@ -281,10 +282,39 @@ static ssize_t state_store(struct subsystem * subsys, const char * buf, size_t n
 
 
 power_attr(state);
 power_attr(state);
 
 
+#ifdef CONFIG_PM_TRACE
+int pm_trace_enabled;
+
+static ssize_t pm_trace_show(struct subsystem * subsys, char * buf)
+{
+	return sprintf(buf, "%d\n", pm_trace_enabled);
+}
+
+static ssize_t
+pm_trace_store(struct subsystem * subsys, const char * buf, size_t n)
+{
+	int val;
+
+	if (sscanf(buf, "%d", &val) == 1) {
+		pm_trace_enabled = !!val;
+		return n;
+	}
+	return -EINVAL;
+}
+
+power_attr(pm_trace);
+
+static struct attribute * g[] = {
+	&state_attr.attr,
+	&pm_trace_attr.attr,
+	NULL,
+};
+#else
 static struct attribute * g[] = {
 static struct attribute * g[] = {
 	&state_attr.attr,
 	&state_attr.attr,
 	NULL,
 	NULL,
 };
 };
+#endif /* CONFIG_PM_TRACE */
 
 
 static struct attribute_group attr_group = {
 static struct attribute_group attr_group = {
 	.attrs = g,
 	.attrs = g,