• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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