50c3d1d6c041c96e794af716d557eac9fa8498e7
[linux-3.10.git] / drivers / misc / tegra-profiler / debug.c
1 /*
2  * drivers/misc/tegra-profiler/debug.c
3  *
4  * Copyright (c) 2015, NVIDIA CORPORATION.  All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  */
16
17 #include <linux/module.h>
18 #include <asm/irq_regs.h>
19
20 #include <linux/tegra_profiler.h>
21
22 #include "debug.h"
23 #include "hrt.h"
24 #include "tegra.h"
25 #include "comm.h"
26
27 #ifdef QM_DEBUG_SAMPLES_ENABLE
28
29 static inline void
30 init_sample(struct quadd_record_data *record, struct pt_regs *regs)
31 {
32         unsigned int flags;
33         struct quadd_debug_data *s = &record->debug;
34
35         record->magic = QUADD_RECORD_MAGIC;
36         record->record_type = QUADD_RECORD_TYPE_DEBUG;
37
38         if (!regs)
39                 regs = get_irq_regs();
40
41         if (!regs)
42                 s->user_mode = 0;
43         else
44                 s->user_mode = user_mode(regs) ? 1 : 0;
45
46         s->cpu = quadd_get_processor_id(regs, &flags);
47
48         s->lp_mode = flags & QUADD_CPUMODE_TEGRA_POWER_CLUSTER_LP ? 1 : 0;
49         s->thumb_mode = flags & QUADD_CPUMODE_THUMB ? 1 : 0;
50
51         s->reserved = 0;
52
53         s->pid = 0;
54         s->time = quadd_get_time();
55
56         s->extra_value[0] = 0;
57         s->extra_value[1] = 0;
58
59         s->extra_length = 0;
60 }
61
62 void qm_debug_handler_sample(struct pt_regs *regs)
63 {
64         struct quadd_record_data record;
65         struct quadd_debug_data *s = &record.debug;
66
67         init_sample(&record, regs);
68
69         s->type = QM_DEBUG_SAMPLE_TYPE_TIMER_HANDLE;
70
71         quadd_put_sample_this_cpu(&record, NULL, 0);
72 }
73
74 void qm_debug_timer_forward(struct pt_regs *regs, u64 period)
75 {
76         struct quadd_record_data record;
77         struct quadd_debug_data *s = &record.debug;
78
79         init_sample(&record, regs);
80
81         s->type = QM_DEBUG_SAMPLE_TYPE_TIMER_FORWARD;
82
83         quadd_put_sample_this_cpu(&record, NULL, 0);
84 }
85
86 void qm_debug_timer_start(struct pt_regs *regs, u64 period)
87 {
88         struct quadd_record_data record;
89         struct quadd_debug_data *s = &record.debug;
90
91         init_sample(&record, regs);
92
93         s->type = QM_DEBUG_SAMPLE_TYPE_TIMER_START;
94
95         quadd_put_sample_this_cpu(&record, NULL, 0);
96 }
97
98 void qm_debug_timer_cancel(void)
99 {
100         struct quadd_record_data record;
101         struct quadd_debug_data *s = &record.debug;
102
103         init_sample(&record, NULL);
104
105         s->type = QM_DEBUG_SAMPLE_TYPE_TIMER_CANCEL;
106
107         quadd_put_sample_this_cpu(&record, NULL, 0);
108 }
109
110 void
111 qm_debug_task_sched_in(pid_t prev_pid, pid_t current_pid, int prev_nr_active)
112 {
113         struct quadd_iovec vec;
114         struct quadd_record_data record;
115         struct quadd_debug_data *s = &record.debug;
116
117         init_sample(&record, NULL);
118
119         s->type = QM_DEBUG_SAMPLE_TYPE_SCHED_IN;
120
121         s->extra_value[0] = prev_pid;
122         s->extra_value[1] = current_pid;
123
124         vec.base = &prev_nr_active;
125         vec.len = s->extra_length = sizeof(prev_nr_active);
126
127         quadd_put_sample_this_cpu(&record, &vec, 1);
128 }
129
130 void qm_debug_read_counter(int event_id, u32 prev_val, u32 val)
131 {
132         struct quadd_iovec vec;
133         struct quadd_record_data record;
134         struct quadd_debug_data *s = &record.debug;
135
136         init_sample(&record, NULL);
137
138         s->type = QM_DEBUG_SAMPLE_TYPE_READ_COUNTER;
139
140         s->extra_value[0] = event_id;
141         s->extra_value[1] = prev_val;
142
143         vec.base = &val;
144         vec.len = s->extra_length = sizeof(val);
145
146         quadd_put_sample_this_cpu(&record, &vec, 1);
147 }
148
149 void qm_debug_start_source(int source_type)
150 {
151         struct quadd_record_data record;
152         struct quadd_debug_data *s = &record.debug;
153
154         init_sample(&record, NULL);
155
156         s->type = QM_DEBUG_SAMPLE_TYPE_SOURCE_START;
157         s->extra_value[0] = source_type;
158
159         quadd_put_sample_this_cpu(&record, NULL, 0);
160 }
161
162 void qm_debug_stop_source(int source_type)
163 {
164         struct quadd_record_data record;
165         struct quadd_debug_data *s = &record.debug;
166
167         init_sample(&record, NULL);
168
169         s->type = QM_DEBUG_SAMPLE_TYPE_SOURCE_STOP;
170         s->extra_value[0] = source_type;
171
172         quadd_put_sample_this_cpu(&record, NULL, 0);
173 }
174
175 #endif  /* QM_DEBUG_SAMPLES_ENABLE */