blob: 203708cc24f2007d08b3794b80b1ae57c44c21c4 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
2 * Copyright (C) 2018 MediaTek Inc.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <asm/page.h>
15#include "interface.h"
16#include "met_drv.h"
17
18#ifdef CONFIG_GPU_TRACEPOINTS
19#include <trace/events/gpu.h>
20
21#define show_secs_from_ns(ns) \
22 ({ \
23 u64 t = ns + (NSEC_PER_USEC / 2); \
24 do_div(t, NSEC_PER_SEC); \
25 t; \
26 })
27
28#define show_usecs_from_ns(ns) \
29 ({ \
30 u64 t = ns + (NSEC_PER_USEC / 2) ; \
31 u32 rem; \
32 do_div(t, NSEC_PER_USEC); \
33 rem = do_div(t, USEC_PER_SEC); \
34 })
35
36static int event_gpu_registered;
37static int event_gpu_enabled;
38
39noinline void gpu_sched_switch(const char *gpu_name, u64 timestamp,
40 u32 next_ctx_id, s32 next_prio, u32 next_job_id)
41{
42 MET_TRACE("gpu_name=%s ts=%llu.%06lu next_ctx_id=%lu next_prio=%ld next_job_id=%lu\n",
43 gpu_name,
44 (unsigned long long)show_secs_from_ns(timestamp),
45 (unsigned long)show_usecs_from_ns(timestamp),
46 (unsigned long)next_ctx_id, (long)next_prio, (unsigned long)next_job_id);
47}
48
49MET_DEFINE_PROBE(gpu_sched_switch, TP_PROTO(const char *gpu_name, u64 timestamp,
50 u32 next_ctx_id, s32 next_prio, u32 next_job_id))
51{
52 gpu_sched_switch(gpu_name, timestamp, next_ctx_id, next_prio, next_job_id);
53}
54
55noinline void gpu_job_enqueue(u32 ctx_id, u32 job_id, const char *type)
56{
57 MET_TRACE("ctx_id=%lu job_id=%lu type=%s",
58 (unsigned long)ctx_id, (unsigned long)job_id, type);
59}
60
61MET_DEFINE_PROBE(gpu_job_enqueue, TP_PROTO(u32 ctx_id, u32 job_id, const char *type))
62{
63 gpu_job_enqueue(ctx_id, job_id, type);
64}
65#endif
66
67
68#ifdef MET_EVENT_POWER_SUPPORT
69#include "met_power.h"
70#include "met_kernel_symbol.h"
71
72static int event_power_registered;
73static int event_power_enabled;
74
75const char *
76met_trace_print_symbols_seq(char* pclass_name, unsigned long val,
77 const struct trace_print_flags *symbol_array)
78{
79 int i;
80 size_t new_fsize=0;
81 char _buf[32];
82 const char *ret = pclass_name;
83
84 for (i = 0; symbol_array[i].name; i++) {
85
86 if (val != symbol_array[i].mask)
87 continue;
88
89 new_fsize = sprintf(pclass_name, symbol_array[i].name, strlen(symbol_array[i].name));
90 break;
91 }
92
93 if (new_fsize == 0) {
94 snprintf(_buf, 32, "0x%lx", val);
95 new_fsize = sprintf(pclass_name, _buf, strlen(_buf));
96 }
97
98 return ret;
99}
100
101#define __print_symbolic(pclass_name, value, symbol_array...) \
102 ({ \
103 static const struct trace_print_flags symbols[] = \
104 { symbol_array, { -1, NULL }}; \
105 met_trace_print_symbols_seq(pclass_name, value, symbols); \
106 })
107
108#ifdef pm_qos_update_request
109#undef pm_qos_update_request
110#endif
111void pm_qos_update_request(int pm_qos_class, s32 value, char *owner)
112{
113 char class_name[64];
114 MET_TRACE("pm_qos_class=%s value=%d owner=%s\n",
115 __print_symbolic(class_name, pm_qos_class,
116 { _PM_QOS_CPU_DMA_LATENCY, "CPU_DMA_LATENCY" },
117 { _PM_QOS_NETWORK_LATENCY, "NETWORK_LATENCY" },
118 { _PM_QOS_NETWORK_THROUGHPUT, "NETWORK_THROUGHPUT" }),
119 value, owner);
120}
121//#endif
122
123#ifdef pm_qos_update_target
124#undef pm_qos_update_target
125#endif
126void pm_qos_update_target(unsigned int action, int prev_value, int curr_value)
127{
128 char class_name[64];
129
130 MET_TRACE("action=%s prev_value=%d curr_value=%d\n",
131 __print_symbolic(class_name, action,
132 { _PM_QOS_ADD_REQ, "ADD_REQ" },
133 { _PM_QOS_UPDATE_REQ, "UPDATE_REQ" },
134 { _PM_QOS_REMOVE_REQ, "REMOVE_REQ" }),
135 prev_value, curr_value);
136}
137#endif
138//#endif
139
140static int reset_driver_stat(void)
141{
142#ifdef CONFIG_GPU_TRACEPOINTS
143 event_gpu_enabled = 0;
144#endif
145#ifdef MET_EVENT_POWER_SUPPORT
146 event_power_enabled = 0;
147#endif
148
149 met_trace_event.mode = 0;
150 return 0;
151}
152
153
154
155static void met_event_start(void)
156{
157#ifdef CONFIG_GPU_TRACEPOINTS
158 /* register trace event for gpu */
159 do {
160 if (!event_gpu_enabled)
161 break;
162 if (MET_REGISTER_TRACE(gpu_sched_switch)) {
163 pr_debug("can not register callback of gpu_sched_switch\n");
164 break;
165 }
166 if (MET_REGISTER_TRACE(gpu_job_enqueue)) {
167 pr_debug("can not register callback of gpu_job_enqueue\n");
168 MET_UNREGISTER_TRACE(gpu_sched_switch);
169 break;
170 }
171 event_gpu_registered = 1;
172 } while (0);
173#endif
174
175#ifdef MET_EVENT_POWER_SUPPORT
176 /* register trace event for power */
177 do {
178 if (!event_power_enabled)
179 break;
180 if (met_reg_event_power_symbol)
181 if (met_reg_event_power_symbol()) {
182 pr_debug("can not register callback of met_reg_event_power\n");
183 break;
184 }
185 event_power_registered = 1;
186 } while (0);
187#endif
188
189}
190
191static void met_event_stop(void)
192{
193#ifdef CONFIG_GPU_TRACEPOINTS
194 /* unregister trace event for gpu */
195 if (event_gpu_registered) {
196 MET_UNREGISTER_TRACE(gpu_job_enqueue);
197 MET_UNREGISTER_TRACE(gpu_sched_switch);
198 event_gpu_registered = 0;
199 }
200#endif
201
202#ifdef MET_EVENT_POWER_SUPPORT
203 /* unregister trace event for power */
204 if (event_power_registered) {
205 if (met_unreg_event_power_symbol)
206 met_unreg_event_power_symbol();
207 event_power_registered = 0;
208 }
209#endif
210}
211
212static int met_event_process_argument(const char *arg, int len)
213{
214 int ret = -1;
215
216#ifdef CONFIG_GPU_TRACEPOINTS
217 if (strcasecmp(arg, "gpu") == 0) {
218 event_gpu_enabled = 1;
219 met_trace_event.mode = 1;
220 ret = 0;
221 }
222#endif
223#ifdef MET_EVENT_POWER_SUPPORT
224 if (strcasecmp(arg, "power") == 0) {
225 event_power_enabled = 1;
226 met_trace_event.mode = 1;
227 ret = 0;
228 }
229#endif
230 return ret;
231}
232
233static const char help[] = "\b"
234#ifdef CONFIG_GPU_TRACEPOINTS
235 " --event=gpu output gpu trace events\n"
236#endif
237#ifdef MET_EVENT_POWER_SUPPORT
238 " --event=power output pmqos trace events\n"
239#endif
240 ;
241
242static int met_event_print_help(char *buf, int len)
243{
244 return snprintf(buf, PAGE_SIZE, help);
245}
246
247static const char header[] =
248 "met-info [000] 0.0: met_ftrace_event:"
249#ifdef CONFIG_GPU_TRACEPOINTS
250 " gpu:gpu_sched_switch gpu:gpu_job_enqueue"
251#endif
252#ifdef MET_EVENT_POWER_SUPPORT
253 " power:pm_qos_update_request power:pm_qos_update_target"
254#endif
255 "\n";
256
257static int met_event_print_header(char *buf, int len)
258{
259 int ret;
260
261 ret = snprintf(buf, PAGE_SIZE, header);
262 return ret;
263}
264
265struct metdevice met_trace_event = {
266 .name = "event",
267 .type = MET_TYPE_PMU,
268 .start = met_event_start,
269 .stop = met_event_stop,
270 .reset = reset_driver_stat,
271 .process_argument = met_event_process_argument,
272 .print_help = met_event_print_help,
273 .print_header = met_event_print_header,
274};