mirror of https://gitee.com/openkylin/linux.git
[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>
This commit is contained in:
parent
7d145aa3ab
commit
c5c6ba4e08
|
@ -52,3 +52,18 @@ suspend image will be as small as possible.
|
|||
|
||||
Reading from this file will display the current image size limit, which
|
||||
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.
|
||||
|
|
|
@ -3,21 +3,25 @@
|
|||
|
||||
#ifdef CONFIG_PM_TRACE
|
||||
|
||||
extern int pm_trace_enabled;
|
||||
|
||||
struct device;
|
||||
extern void set_trace_device(struct device *);
|
||||
extern void generate_resume_trace(void *tracedata, unsigned int user);
|
||||
|
||||
#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)
|
||||
|
||||
#else
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <linux/pm.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/resume-trace.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);
|
||||
|
||||
#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[] = {
|
||||
&state_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
#endif /* CONFIG_PM_TRACE */
|
||||
|
||||
static struct attribute_group attr_group = {
|
||||
.attrs = g,
|
||||
|
|
Loading…
Reference in New Issue