Skip to content

Commit

Permalink
[PATCH] PM: Add pm_trace switch
Browse files Browse the repository at this point in the history
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 <[email protected]>
Acked-by: Pavel Machek <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
rjwysocki authored and Linus Torvalds committed Sep 26, 2006
1 parent 7d145aa commit c5c6ba4
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 10 deletions.
15 changes: 15 additions & 0 deletions Documentation/power/interface.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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.
24 changes: 14 additions & 10 deletions include/linux/resume-trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
30 changes: 30 additions & 0 deletions kernel/power/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <linux/pm.h>
#include <linux/console.h>
#include <linux/cpu.h>
#include <linux/resume-trace.h>

#include "power.h"

Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit c5c6ba4

Please sign in to comment.