1 // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
2 /*
3 *
4 * (C) COPYRIGHT 2019-2021 ARM Limited. All rights reserved.
5 *
6 * This program is free software and is provided to you under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation, and any use by you of this program is subject to the terms
9 * of such GNU license.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you can access it online at
18 * http://www.gnu.org/licenses/gpl-2.0.html.
19 *
20 */
21
22 #include "mali_kbase_csf_tl_reader.h"
23
24 #include "mali_kbase_csf_trace_buffer.h"
25 #include "mali_kbase_reset_gpu.h"
26
27 #include "tl/mali_kbase_tlstream.h"
28 #include "tl/mali_kbase_tl_serialize.h"
29 #include "tl/mali_kbase_tracepoints.h"
30
31 #include "mali_kbase_pm.h"
32 #include "mali_kbase_hwaccess_time.h"
33
34 #include <linux/gcd.h>
35 #include <linux/math64.h>
36 #include <asm/arch_timer.h>
37
38 #if IS_ENABLED(CONFIG_DEBUG_FS)
39 #include "tl/mali_kbase_timeline_priv.h"
40 #include <linux/debugfs.h>
41
42 #if (KERNEL_VERSION(4, 7, 0) > LINUX_VERSION_CODE)
43 #define DEFINE_DEBUGFS_ATTRIBUTE DEFINE_SIMPLE_ATTRIBUTE
44 #endif
45 #endif
46
47 /* Name of the CSFFW timeline tracebuffer. */
48 #define KBASE_CSFFW_TRACEBUFFER_NAME "timeline"
49 /* Name of the timeline header metatadata */
50 #define KBASE_CSFFW_TIMELINE_HEADER_NAME "timeline_header"
51
52 /**
53 * struct kbase_csffw_tl_message - CSFFW timeline message.
54 *
55 * @msg_id: Message ID.
56 * @timestamp: Timestamp of the event.
57 * @cycle_counter: Cycle number of the event.
58 *
59 * Contain fields that are common for all CSFFW timeline messages.
60 */
61 struct kbase_csffw_tl_message {
62 u32 msg_id;
63 u64 timestamp;
64 u64 cycle_counter;
65 } __packed __aligned(4);
66
67 #if IS_ENABLED(CONFIG_DEBUG_FS)
kbase_csf_tl_debugfs_poll_interval_read(void * data,u64 * val)68 static int kbase_csf_tl_debugfs_poll_interval_read(void *data, u64 *val)
69 {
70 struct kbase_device *kbdev = (struct kbase_device *)data;
71 struct kbase_csf_tl_reader *self = &kbdev->timeline->csf_tl_reader;
72
73 *val = self->timer_interval;
74
75 return 0;
76 }
77
kbase_csf_tl_debugfs_poll_interval_write(void * data,u64 val)78 static int kbase_csf_tl_debugfs_poll_interval_write(void *data, u64 val)
79 {
80 struct kbase_device *kbdev = (struct kbase_device *)data;
81 struct kbase_csf_tl_reader *self = &kbdev->timeline->csf_tl_reader;
82
83 if (val > KBASE_CSF_TL_READ_INTERVAL_MAX || val < KBASE_CSF_TL_READ_INTERVAL_MIN) {
84 return -EINVAL;
85 }
86
87 self->timer_interval = (u32)val;
88
89 return 0;
90 }
91
92 DEFINE_DEBUGFS_ATTRIBUTE(kbase_csf_tl_poll_interval_fops,
93 kbase_csf_tl_debugfs_poll_interval_read,
94 kbase_csf_tl_debugfs_poll_interval_write, "%llu\n");
95
96
kbase_csf_tl_reader_debugfs_init(struct kbase_device * kbdev)97 void kbase_csf_tl_reader_debugfs_init(struct kbase_device *kbdev)
98 {
99 debugfs_create_file("csf_tl_poll_interval_in_ms", S_IRUGO | S_IWUSR,
100 kbdev->debugfs_instr_directory, kbdev,
101 &kbase_csf_tl_poll_interval_fops);
102
103 }
104 #endif
105
106 /**
107 * get_cpu_gpu_time() - Get current CPU and GPU timestamps.
108 *
109 * @kbdev: Kbase device.
110 * @cpu_ts: Output CPU timestamp.
111 * @gpu_ts: Output GPU timestamp.
112 * @gpu_cycle: Output GPU cycle counts.
113 */
get_cpu_gpu_time(struct kbase_device * kbdev,u64 * cpu_ts,u64 * gpu_ts,u64 * gpu_cycle)114 static void get_cpu_gpu_time(
115 struct kbase_device *kbdev,
116 u64 *cpu_ts,
117 u64 *gpu_ts,
118 u64 *gpu_cycle)
119 {
120 struct timespec64 ts;
121
122 kbase_pm_context_active(kbdev);
123 kbase_backend_get_gpu_time(kbdev, gpu_cycle, gpu_ts, &ts);
124 kbase_pm_context_idle(kbdev);
125
126 if (cpu_ts)
127 *cpu_ts = ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec;
128 }
129
130
131 /**
132 * kbase_ts_converter_init() - Initialize system timestamp converter.
133 *
134 * @self: System Timestamp Converter instance.
135 * @kbdev: Kbase device pointer
136 *
137 * Return: Zero on success, -1 otherwise.
138 */
kbase_ts_converter_init(struct kbase_ts_converter * self,struct kbase_device * kbdev)139 static int kbase_ts_converter_init(
140 struct kbase_ts_converter *self,
141 struct kbase_device *kbdev)
142 {
143 u64 cpu_ts = 0;
144 u64 gpu_ts = 0;
145 u64 freq;
146 u64 common_factor;
147
148 get_cpu_gpu_time(kbdev, &cpu_ts, &gpu_ts, NULL);
149 freq = arch_timer_get_cntfrq();
150
151 if (!freq) {
152 dev_warn(kbdev->dev, "arch_timer_get_rate() is zero!");
153 return -1;
154 }
155
156 common_factor = gcd(NSEC_PER_SEC, freq);
157
158 self->multiplier = div64_u64(NSEC_PER_SEC, common_factor);
159 self->divisor = div64_u64(freq, common_factor);
160 self->offset =
161 cpu_ts - div64_u64(gpu_ts * self->multiplier, self->divisor);
162
163 return 0;
164 }
165
166 /**
167 * kbase_ts_converter_convert() - Convert GPU timestamp to CPU timestamp.
168 *
169 * @self: System Timestamp Converter instance.
170 * @gpu_ts: System timestamp value to converter.
171 *
172 * Return: The CPU timestamp.
173 */
174 static void __maybe_unused
kbase_ts_converter_convert(const struct kbase_ts_converter * self,u64 * gpu_ts)175 kbase_ts_converter_convert(const struct kbase_ts_converter *self, u64 *gpu_ts)
176 {
177 u64 old_gpu_ts = *gpu_ts;
178 *gpu_ts = div64_u64(old_gpu_ts * self->multiplier, self->divisor) +
179 self->offset;
180 }
181
182 /**
183 * tl_reader_overflow_notify() - Emit stream overflow tracepoint.
184 *
185 * @self: CSFFW TL Reader instance.
186 * @msg_buf_start: Start of the message.
187 * @msg_buf_end: End of the message buffer.
188 */
tl_reader_overflow_notify(const struct kbase_csf_tl_reader * self,u8 * const msg_buf_start,u8 * const msg_buf_end)189 static void tl_reader_overflow_notify(
190 const struct kbase_csf_tl_reader *self,
191 u8 *const msg_buf_start,
192 u8 *const msg_buf_end)
193 {
194 struct kbase_device *kbdev = self->kbdev;
195 struct kbase_csffw_tl_message message = {0};
196
197 /* Reuse the timestamp and cycle count from current event if possible */
198 if (msg_buf_start + sizeof(message) <= msg_buf_end)
199 memcpy(&message, msg_buf_start, sizeof(message));
200
201 KBASE_TLSTREAM_TL_KBASE_CSFFW_TLSTREAM_OVERFLOW(
202 kbdev, message.timestamp, message.cycle_counter);
203 }
204
205 /**
206 * tl_reader_overflow_check() - Check if an overflow has happened
207 *
208 * @self: CSFFW TL Reader instance.
209 * @event_id: Incoming event id.
210 *
211 * Return: True, if an overflow has happened, False otherwise.
212 */
tl_reader_overflow_check(struct kbase_csf_tl_reader * self,u16 event_id)213 static bool tl_reader_overflow_check(
214 struct kbase_csf_tl_reader *self,
215 u16 event_id)
216 {
217 struct kbase_device *kbdev = self->kbdev;
218 bool has_overflow = false;
219
220 /* 0 is a special event_id and reserved for the very first tracepoint
221 * after reset, we should skip overflow check when reset happened.
222 */
223 if (event_id != 0) {
224 has_overflow = self->got_first_event
225 && self->expected_event_id != event_id;
226
227 if (has_overflow)
228 dev_warn(kbdev->dev,
229 "CSFFW overflow, event_id: %u, expected: %u.",
230 event_id, self->expected_event_id);
231 }
232
233 self->got_first_event = true;
234 self->expected_event_id = event_id + 1;
235 /* When event_id reaches its max value, it skips 0 and wraps to 1. */
236 if (self->expected_event_id == 0)
237 self->expected_event_id++;
238
239 return has_overflow;
240 }
241
242 /**
243 * tl_reader_reset() - Reset timeline tracebuffer reader state machine.
244 *
245 * @self: CSFFW TL Reader instance.
246 *
247 * Reset the reader to the default state, i.e. set all the
248 * mutable fields to zero.
249 */
tl_reader_reset(struct kbase_csf_tl_reader * self)250 static void tl_reader_reset(struct kbase_csf_tl_reader *self)
251 {
252 self->got_first_event = false;
253 self->is_active = false;
254 self->expected_event_id = 0;
255 self->tl_header.btc = 0;
256 }
257
258
kbase_csf_tl_reader_flush_buffer(struct kbase_csf_tl_reader * self)259 int kbase_csf_tl_reader_flush_buffer(struct kbase_csf_tl_reader *self)
260 {
261 int ret = 0;
262 struct kbase_device *kbdev = self->kbdev;
263 struct kbase_tlstream *stream = self->stream;
264
265 u8 *read_buffer = self->read_buffer;
266 const size_t read_buffer_size = sizeof(self->read_buffer);
267
268 u32 bytes_read;
269 u8 *csffw_data_begin;
270 u8 *csffw_data_end;
271 u8 *csffw_data_it;
272
273 unsigned long flags;
274
275 spin_lock_irqsave(&self->read_lock, flags);
276
277 /* If not running, early exit. */
278 if (!self->is_active) {
279 spin_unlock_irqrestore(&self->read_lock, flags);
280 return -EBUSY;
281 }
282
283
284 /* Copying the whole buffer in a single shot. We assume
285 * that the buffer will not contain partially written messages.
286 */
287 bytes_read = kbase_csf_firmware_trace_buffer_read_data(
288 self->trace_buffer, read_buffer, read_buffer_size);
289 csffw_data_begin = read_buffer;
290 csffw_data_end = read_buffer + bytes_read;
291
292 for (csffw_data_it = csffw_data_begin;
293 csffw_data_it < csffw_data_end;) {
294 u32 event_header;
295 u16 event_id;
296 u16 event_size;
297 unsigned long acq_flags;
298 char *buffer;
299
300 /* Can we safely read event_id? */
301 if (csffw_data_it + sizeof(event_header) > csffw_data_end) {
302 dev_warn(
303 kbdev->dev,
304 "Unable to parse CSFFW tracebuffer event header.");
305 ret = -EBUSY;
306 break;
307 }
308
309 /* Read and parse the event header. */
310 memcpy(&event_header, csffw_data_it, sizeof(event_header));
311 event_id = (event_header >> 0) & 0xFFFF;
312 event_size = (event_header >> 16) & 0xFFFF;
313 csffw_data_it += sizeof(event_header);
314
315 /* Detect if an overflow has happened. */
316 if (tl_reader_overflow_check(self, event_id))
317 tl_reader_overflow_notify(self,
318 csffw_data_it,
319 csffw_data_end);
320
321 /* Can we safely read the message body? */
322 if (csffw_data_it + event_size > csffw_data_end) {
323 dev_warn(kbdev->dev,
324 "event_id: %u, can't read with event_size: %u.",
325 event_id, event_size);
326 ret = -EBUSY;
327 break;
328 }
329
330 /* Convert GPU timestamp to CPU timestamp. */
331 {
332 struct kbase_csffw_tl_message *msg =
333 (struct kbase_csffw_tl_message *) csffw_data_it;
334 kbase_ts_converter_convert(&self->ts_converter,
335 &msg->timestamp);
336 }
337
338 /* Copy the message out to the tl_stream. */
339 buffer = kbase_tlstream_msgbuf_acquire(
340 stream, event_size, &acq_flags);
341 kbasep_serialize_bytes(buffer, 0, csffw_data_it, event_size);
342 kbase_tlstream_msgbuf_release(stream, acq_flags);
343 csffw_data_it += event_size;
344 }
345
346 spin_unlock_irqrestore(&self->read_lock, flags);
347 return ret;
348 }
349
kbasep_csf_tl_reader_read_callback(struct timer_list * timer)350 static void kbasep_csf_tl_reader_read_callback(struct timer_list *timer)
351 {
352 struct kbase_csf_tl_reader *self =
353 container_of(timer, struct kbase_csf_tl_reader, read_timer);
354
355 int rcode;
356
357 kbase_csf_tl_reader_flush_buffer(self);
358
359 rcode = mod_timer(&self->read_timer,
360 jiffies + msecs_to_jiffies(self->timer_interval));
361
362 CSTD_UNUSED(rcode);
363 }
364
365 /**
366 * tl_reader_init_late() - Late CSFFW TL Reader initialization.
367 *
368 * @self: CSFFW TL Reader instance.
369 * @kbdev: Kbase device.
370 *
371 * Late initialization is done once at kbase_csf_tl_reader_start() time.
372 * This is because the firmware image is not parsed
373 * by the kbase_csf_tl_reader_init() time.
374 *
375 * Return: Zero on success, -1 otherwise.
376 */
tl_reader_init_late(struct kbase_csf_tl_reader * self,struct kbase_device * kbdev)377 static int tl_reader_init_late(
378 struct kbase_csf_tl_reader *self,
379 struct kbase_device *kbdev)
380 {
381 struct firmware_trace_buffer *tb;
382 size_t hdr_size = 0;
383 const char *hdr = NULL;
384
385 if (self->kbdev)
386 return 0;
387
388 tb = kbase_csf_firmware_get_trace_buffer(
389 kbdev, KBASE_CSFFW_TRACEBUFFER_NAME);
390 hdr = kbase_csf_firmware_get_timeline_metadata(
391 kbdev, KBASE_CSFFW_TIMELINE_HEADER_NAME, &hdr_size);
392
393 if (!tb) {
394 dev_warn(
395 kbdev->dev,
396 "'%s' tracebuffer is not present in the firmware image.",
397 KBASE_CSFFW_TRACEBUFFER_NAME);
398 return -1;
399 }
400
401 if (!hdr) {
402 dev_warn(
403 kbdev->dev,
404 "'%s' timeline metadata is not present in the firmware image.",
405 KBASE_CSFFW_TIMELINE_HEADER_NAME);
406 return -1;
407 }
408
409 if (kbase_ts_converter_init(&self->ts_converter, kbdev)) {
410 return -1;
411 }
412
413 self->kbdev = kbdev;
414 self->trace_buffer = tb;
415 self->tl_header.data = hdr;
416 self->tl_header.size = hdr_size;
417
418 return 0;
419 }
420
421 /**
422 * tl_reader_update_enable_bit() - Update the first bit of a CSFFW tracebuffer.
423 *
424 * @self: CSFFW TL Reader instance.
425 * @value: The value to set.
426 *
427 * Update the first bit of a CSFFW tracebufer and then reset the GPU.
428 * This is to make these changes visible to the MCU.
429 *
430 * Return: 0 on success, or negative error code for failure.
431 */
tl_reader_update_enable_bit(struct kbase_csf_tl_reader * self,bool value)432 static int tl_reader_update_enable_bit(
433 struct kbase_csf_tl_reader *self,
434 bool value)
435 {
436 int err = 0;
437
438 err = kbase_csf_firmware_trace_buffer_update_trace_enable_bit(
439 self->trace_buffer, 0, value);
440
441 return err;
442 }
443
kbase_csf_tl_reader_init(struct kbase_csf_tl_reader * self,struct kbase_tlstream * stream)444 void kbase_csf_tl_reader_init(struct kbase_csf_tl_reader *self,
445 struct kbase_tlstream *stream)
446 {
447 self->timer_interval = KBASE_CSF_TL_READ_INTERVAL_DEFAULT;
448
449 kbase_timer_setup(&self->read_timer,
450 kbasep_csf_tl_reader_read_callback);
451
452 self->stream = stream;
453
454 /* This will be initialized by tl_reader_init_late() */
455 self->kbdev = NULL;
456 self->trace_buffer = NULL;
457 self->tl_header.data = NULL;
458 self->tl_header.size = 0;
459
460 spin_lock_init(&self->read_lock);
461
462 tl_reader_reset(self);
463 }
464
kbase_csf_tl_reader_term(struct kbase_csf_tl_reader * self)465 void kbase_csf_tl_reader_term(struct kbase_csf_tl_reader *self)
466 {
467 del_timer_sync(&self->read_timer);
468 }
469
kbase_csf_tl_reader_start(struct kbase_csf_tl_reader * self,struct kbase_device * kbdev)470 int kbase_csf_tl_reader_start(struct kbase_csf_tl_reader *self,
471 struct kbase_device *kbdev)
472 {
473 int rcode;
474
475 /* If already running, early exit. */
476 if (self->is_active)
477 return 0;
478
479 if (tl_reader_init_late(self, kbdev)) {
480 #if IS_ENABLED(CONFIG_MALI_BIFROST_NO_MALI)
481 dev_warn(
482 kbdev->dev,
483 "CSFFW timeline is not available for MALI_BIFROST_NO_MALI builds!");
484 return 0;
485 #else
486 return -EINVAL;
487 #endif
488 }
489
490 tl_reader_reset(self);
491
492 self->is_active = true;
493 /* Set bytes to copy to the header size. This is to trigger copying
494 * of the header to the user space.
495 */
496 self->tl_header.btc = self->tl_header.size;
497
498 /* Enable the tracebuffer on the CSFFW side. */
499 rcode = tl_reader_update_enable_bit(self, true);
500 if (rcode != 0)
501 return rcode;
502
503 rcode = mod_timer(&self->read_timer,
504 jiffies + msecs_to_jiffies(self->timer_interval));
505
506 return 0;
507 }
508
kbase_csf_tl_reader_stop(struct kbase_csf_tl_reader * self)509 void kbase_csf_tl_reader_stop(struct kbase_csf_tl_reader *self)
510 {
511 unsigned long flags;
512
513 /* If is not running, early exit. */
514 if (!self->is_active)
515 return;
516
517 /* Disable the tracebuffer on the CSFFW side. */
518 tl_reader_update_enable_bit(self, false);
519
520 del_timer_sync(&self->read_timer);
521
522 spin_lock_irqsave(&self->read_lock, flags);
523
524 tl_reader_reset(self);
525
526 spin_unlock_irqrestore(&self->read_lock, flags);
527 }
528
kbase_csf_tl_reader_reset(struct kbase_csf_tl_reader * self)529 void kbase_csf_tl_reader_reset(struct kbase_csf_tl_reader *self)
530 {
531 kbase_csf_tl_reader_flush_buffer(self);
532 }
533