~ubuntu-branches/ubuntu/karmic/linux-ports/karmic

« back to all changes in this revision

Viewing changes to kernel/trace/trace_power.c

  • Committer: Bazaar Package Importer
  • Author(s): Luke Yelavich, Luke Yelavich, Michael Casadevall, Tim Gardner, Upstream Kernel Changes
  • Date: 2009-05-06 18:18:55 UTC
  • Revision ID: james.westby@ubuntu.com-20090506181855-t00baeevpnvd9o7a
Tags: 2.6.30-1.1
[ Luke Yelavich ]
* initial release for karmic
* SAUCE: rebase-ports - adjust for the karmic ports kernel
* SAUCE: rebase-ports - also remove abi dirs/files on rebase
* Update configs after rebase against mainline Jaunty tree
* [Config] Disable CONFIG_BLK_DEV_UB and CONFIG_USB_LIBUSUAL as per
  mainline jaunty
* forward-port patch to drbd for powerpc compilation
* [Config] disable CONFIG_LENOVO_SL_LAPTOP for i386 due to FTBFS
* add .o files found in arch/powerpc/lib to all powerpc kernel header
  packages
* [Config] enable CONFIG_DRM_I915_KMS for i386 as per karmic mainline

[ Michael Casadevall ]

* Disable kgdb on sparc64
* [sparc] [Config] Disable GPIO LEDS
* [ia64] Rename -ia64-generic to -ia64 in line with other architectures
* Correct kernel image path for sparc builds
* [hppa] Fix HPPA config files to build modules for all udebian

Rebase on top of karmic mainline 2.6.30-1.1

[ Tim Gardner ]

* [Config] armel: disable staging drivers, fixes FTBS
* [Config] armel imx51: Disable CONFIG_MTD_NAND_MXC, fixes FTBS

[ Upstream Kernel Changes ]

* mpt2sas: Change reset_type enum to avoid namespace collision.
  Submitted upstream.

* Initial release after rebasing against v2.6.30-rc3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * ring buffer based C-state tracer
 
3
 *
 
4
 * Arjan van de Ven <arjan@linux.intel.com>
 
5
 * Copyright (C) 2008 Intel Corporation
 
6
 *
 
7
 * Much is borrowed from trace_boot.c which is
 
8
 * Copyright (C) 2008 Frederic Weisbecker <fweisbec@gmail.com>
 
9
 *
 
10
 */
 
11
 
 
12
#include <linux/init.h>
 
13
#include <linux/debugfs.h>
 
14
#include <trace/power.h>
 
15
#include <linux/kallsyms.h>
 
16
#include <linux/module.h>
 
17
 
 
18
#include "trace.h"
 
19
#include "trace_output.h"
 
20
 
 
21
static struct trace_array *power_trace;
 
22
static int __read_mostly trace_power_enabled;
 
23
 
 
24
static void probe_power_start(struct power_trace *it, unsigned int type,
 
25
                                unsigned int level)
 
26
{
 
27
        if (!trace_power_enabled)
 
28
                return;
 
29
 
 
30
        memset(it, 0, sizeof(struct power_trace));
 
31
        it->state = level;
 
32
        it->type = type;
 
33
        it->stamp = ktime_get();
 
34
}
 
35
 
 
36
 
 
37
static void probe_power_end(struct power_trace *it)
 
38
{
 
39
        struct ring_buffer_event *event;
 
40
        struct trace_power *entry;
 
41
        struct trace_array_cpu *data;
 
42
        struct trace_array *tr = power_trace;
 
43
 
 
44
        if (!trace_power_enabled)
 
45
                return;
 
46
 
 
47
        preempt_disable();
 
48
        it->end = ktime_get();
 
49
        data = tr->data[smp_processor_id()];
 
50
 
 
51
        event = trace_buffer_lock_reserve(tr, TRACE_POWER,
 
52
                                          sizeof(*entry), 0, 0);
 
53
        if (!event)
 
54
                goto out;
 
55
        entry   = ring_buffer_event_data(event);
 
56
        entry->state_data = *it;
 
57
        trace_buffer_unlock_commit(tr, event, 0, 0);
 
58
 out:
 
59
        preempt_enable();
 
60
}
 
61
 
 
62
static void probe_power_mark(struct power_trace *it, unsigned int type,
 
63
                                unsigned int level)
 
64
{
 
65
        struct ring_buffer_event *event;
 
66
        struct trace_power *entry;
 
67
        struct trace_array_cpu *data;
 
68
        struct trace_array *tr = power_trace;
 
69
 
 
70
        if (!trace_power_enabled)
 
71
                return;
 
72
 
 
73
        memset(it, 0, sizeof(struct power_trace));
 
74
        it->state = level;
 
75
        it->type = type;
 
76
        it->stamp = ktime_get();
 
77
        preempt_disable();
 
78
        it->end = it->stamp;
 
79
        data = tr->data[smp_processor_id()];
 
80
 
 
81
        event = trace_buffer_lock_reserve(tr, TRACE_POWER,
 
82
                                          sizeof(*entry), 0, 0);
 
83
        if (!event)
 
84
                goto out;
 
85
        entry   = ring_buffer_event_data(event);
 
86
        entry->state_data = *it;
 
87
        trace_buffer_unlock_commit(tr, event, 0, 0);
 
88
 out:
 
89
        preempt_enable();
 
90
}
 
91
 
 
92
static int tracing_power_register(void)
 
93
{
 
94
        int ret;
 
95
 
 
96
        ret = register_trace_power_start(probe_power_start);
 
97
        if (ret) {
 
98
                pr_info("power trace: Couldn't activate tracepoint"
 
99
                        " probe to trace_power_start\n");
 
100
                return ret;
 
101
        }
 
102
        ret = register_trace_power_end(probe_power_end);
 
103
        if (ret) {
 
104
                pr_info("power trace: Couldn't activate tracepoint"
 
105
                        " probe to trace_power_end\n");
 
106
                goto fail_start;
 
107
        }
 
108
        ret = register_trace_power_mark(probe_power_mark);
 
109
        if (ret) {
 
110
                pr_info("power trace: Couldn't activate tracepoint"
 
111
                        " probe to trace_power_mark\n");
 
112
                goto fail_end;
 
113
        }
 
114
        return ret;
 
115
fail_end:
 
116
        unregister_trace_power_end(probe_power_end);
 
117
fail_start:
 
118
        unregister_trace_power_start(probe_power_start);
 
119
        return ret;
 
120
}
 
121
 
 
122
static void start_power_trace(struct trace_array *tr)
 
123
{
 
124
        trace_power_enabled = 1;
 
125
}
 
126
 
 
127
static void stop_power_trace(struct trace_array *tr)
 
128
{
 
129
        trace_power_enabled = 0;
 
130
}
 
131
 
 
132
static void power_trace_reset(struct trace_array *tr)
 
133
{
 
134
        trace_power_enabled = 0;
 
135
        unregister_trace_power_start(probe_power_start);
 
136
        unregister_trace_power_end(probe_power_end);
 
137
        unregister_trace_power_mark(probe_power_mark);
 
138
}
 
139
 
 
140
 
 
141
static int power_trace_init(struct trace_array *tr)
 
142
{
 
143
        int cpu;
 
144
        power_trace = tr;
 
145
 
 
146
        trace_power_enabled = 1;
 
147
        tracing_power_register();
 
148
 
 
149
        for_each_cpu(cpu, cpu_possible_mask)
 
150
                tracing_reset(tr, cpu);
 
151
        return 0;
 
152
}
 
153
 
 
154
static enum print_line_t power_print_line(struct trace_iterator *iter)
 
155
{
 
156
        int ret = 0;
 
157
        struct trace_entry *entry = iter->ent;
 
158
        struct trace_power *field ;
 
159
        struct power_trace *it;
 
160
        struct trace_seq *s = &iter->seq;
 
161
        struct timespec stamp;
 
162
        struct timespec duration;
 
163
 
 
164
        trace_assign_type(field, entry);
 
165
        it = &field->state_data;
 
166
        stamp = ktime_to_timespec(it->stamp);
 
167
        duration = ktime_to_timespec(ktime_sub(it->end, it->stamp));
 
168
 
 
169
        if (entry->type == TRACE_POWER) {
 
170
                if (it->type == POWER_CSTATE)
 
171
                        ret = trace_seq_printf(s, "[%5ld.%09ld] CSTATE: Going to C%i on cpu %i for %ld.%09ld\n",
 
172
                                          stamp.tv_sec,
 
173
                                          stamp.tv_nsec,
 
174
                                          it->state, iter->cpu,
 
175
                                          duration.tv_sec,
 
176
                                          duration.tv_nsec);
 
177
                if (it->type == POWER_PSTATE)
 
178
                        ret = trace_seq_printf(s, "[%5ld.%09ld] PSTATE: Going to P%i on cpu %i\n",
 
179
                                          stamp.tv_sec,
 
180
                                          stamp.tv_nsec,
 
181
                                          it->state, iter->cpu);
 
182
                if (!ret)
 
183
                        return TRACE_TYPE_PARTIAL_LINE;
 
184
                return TRACE_TYPE_HANDLED;
 
185
        }
 
186
        return TRACE_TYPE_UNHANDLED;
 
187
}
 
188
 
 
189
static void power_print_header(struct seq_file *s)
 
190
{
 
191
        seq_puts(s, "#   TIMESTAMP      STATE  EVENT\n");
 
192
        seq_puts(s, "#       |            |      |\n");
 
193
}
 
194
 
 
195
static struct tracer power_tracer __read_mostly =
 
196
{
 
197
        .name           = "power",
 
198
        .init           = power_trace_init,
 
199
        .start          = start_power_trace,
 
200
        .stop           = stop_power_trace,
 
201
        .reset          = power_trace_reset,
 
202
        .print_line     = power_print_line,
 
203
        .print_header   = power_print_header,
 
204
};
 
205
 
 
206
static int init_power_trace(void)
 
207
{
 
208
        return register_tracer(&power_tracer);
 
209
}
 
210
device_initcall(init_power_trace);