xref: /OK3568_Linux_fs/kernel/drivers/gpu/arm/bifrost/tl/mali_kbase_timeline.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
2 /*
3  *
4  * (C) COPYRIGHT 2015-2023 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_timeline.h"
23 #include "mali_kbase_timeline_priv.h"
24 #include "mali_kbase_tracepoints.h"
25 
26 #include <mali_kbase.h>
27 #include <linux/atomic.h>
28 #include <linux/file.h>
29 #include <linux/mutex.h>
30 #include <linux/spinlock.h>
31 #include <linux/string.h>
32 #include <linux/stringify.h>
33 #include <linux/timer.h>
34 #include <linux/wait.h>
35 #include <linux/delay.h>
36 
37 /* The period of autoflush checker execution in milliseconds. */
38 #define AUTOFLUSH_INTERVAL 1000 /* ms */
39 
40 /*****************************************************************************/
41 
42 /* These values are used in mali_kbase_tracepoints.h
43  * to retrieve the streams from a kbase_timeline instance.
44  */
45 const size_t __obj_stream_offset =
46 	offsetof(struct kbase_timeline, streams)
47 	+ sizeof(struct kbase_tlstream) * TL_STREAM_TYPE_OBJ;
48 
49 const size_t __aux_stream_offset =
50 	offsetof(struct kbase_timeline, streams)
51 	+ sizeof(struct kbase_tlstream) * TL_STREAM_TYPE_AUX;
52 
53 /**
54  * kbasep_timeline_autoflush_timer_callback - autoflush timer callback
55  * @timer:  Timer list
56  *
57  * Timer is executed periodically to check if any of the stream contains
58  * buffer ready to be submitted to user space.
59  */
kbasep_timeline_autoflush_timer_callback(struct timer_list * timer)60 static void kbasep_timeline_autoflush_timer_callback(struct timer_list *timer)
61 {
62 	enum tl_stream_type stype;
63 	int                 rcode;
64 	struct kbase_timeline *timeline =
65 		container_of(timer, struct kbase_timeline, autoflush_timer);
66 
67 	CSTD_UNUSED(timer);
68 
69 	for (stype = (enum tl_stream_type)0; stype < TL_STREAM_TYPE_COUNT;
70 			stype++) {
71 		struct kbase_tlstream *stream = &timeline->streams[stype];
72 
73 		int af_cnt = atomic_read(&stream->autoflush_counter);
74 
75 		/* Check if stream contain unflushed data. */
76 		if (af_cnt < 0)
77 			continue;
78 
79 		/* Check if stream should be flushed now. */
80 		if (af_cnt != atomic_cmpxchg(
81 					&stream->autoflush_counter,
82 					af_cnt,
83 					af_cnt + 1))
84 			continue;
85 		if (!af_cnt)
86 			continue;
87 
88 		/* Autoflush this stream. */
89 		kbase_tlstream_flush_stream(stream);
90 	}
91 
92 	if (atomic_read(&timeline->autoflush_timer_active))
93 		rcode = mod_timer(
94 				&timeline->autoflush_timer,
95 				jiffies + msecs_to_jiffies(AUTOFLUSH_INTERVAL));
96 	CSTD_UNUSED(rcode);
97 }
98 
99 
100 
101 /*****************************************************************************/
102 
kbase_timeline_init(struct kbase_timeline ** timeline,atomic_t * timeline_flags)103 int kbase_timeline_init(struct kbase_timeline **timeline,
104 		atomic_t *timeline_flags)
105 {
106 	enum tl_stream_type i;
107 	struct kbase_timeline *result;
108 #if MALI_USE_CSF
109 	struct kbase_tlstream *csffw_stream;
110 #endif
111 
112 	if (!timeline || !timeline_flags)
113 		return -EINVAL;
114 
115 	result = vzalloc(sizeof(*result));
116 	if (!result)
117 		return -ENOMEM;
118 
119 	mutex_init(&result->reader_lock);
120 	init_waitqueue_head(&result->event_queue);
121 
122 	/* Prepare stream structures. */
123 	for (i = 0; i < TL_STREAM_TYPE_COUNT; i++)
124 		kbase_tlstream_init(&result->streams[i], i,
125 			&result->event_queue);
126 
127 	/* Initialize the kctx list */
128 	mutex_init(&result->tl_kctx_list_lock);
129 	INIT_LIST_HEAD(&result->tl_kctx_list);
130 
131 	/* Initialize autoflush timer. */
132 	atomic_set(&result->autoflush_timer_active, 0);
133 	kbase_timer_setup(&result->autoflush_timer,
134 			  kbasep_timeline_autoflush_timer_callback);
135 	result->timeline_flags = timeline_flags;
136 
137 #if MALI_USE_CSF
138 	csffw_stream = &result->streams[TL_STREAM_TYPE_CSFFW];
139 	kbase_csf_tl_reader_init(&result->csf_tl_reader, csffw_stream);
140 #endif
141 
142 	*timeline = result;
143 	return 0;
144 }
145 
kbase_timeline_term(struct kbase_timeline * timeline)146 void kbase_timeline_term(struct kbase_timeline *timeline)
147 {
148 	enum tl_stream_type i;
149 
150 	if (!timeline)
151 		return;
152 
153 #if MALI_USE_CSF
154 	kbase_csf_tl_reader_term(&timeline->csf_tl_reader);
155 #endif
156 
157 	WARN_ON(!list_empty(&timeline->tl_kctx_list));
158 
159 	for (i = (enum tl_stream_type)0; i < TL_STREAM_TYPE_COUNT; i++)
160 		kbase_tlstream_term(&timeline->streams[i]);
161 
162 	vfree(timeline);
163 }
164 
165 #ifdef CONFIG_MALI_BIFROST_DEVFREQ
kbase_tlstream_current_devfreq_target(struct kbase_device * kbdev)166 static void kbase_tlstream_current_devfreq_target(struct kbase_device *kbdev)
167 {
168 	struct devfreq *devfreq = kbdev->devfreq;
169 
170 	/* Devfreq initialization failure isn't a fatal error, so devfreq might
171 	 * be null.
172 	 */
173 	if (devfreq) {
174 		unsigned long cur_freq = 0;
175 
176 		mutex_lock(&devfreq->lock);
177 		cur_freq = devfreq->last_status.current_frequency;
178 		KBASE_TLSTREAM_AUX_DEVFREQ_TARGET(kbdev, (u64)cur_freq);
179 		mutex_unlock(&devfreq->lock);
180 	}
181 }
182 #endif /* CONFIG_MALI_BIFROST_DEVFREQ */
183 
kbase_timeline_acquire(struct kbase_device * kbdev,u32 flags)184 int kbase_timeline_acquire(struct kbase_device *kbdev, u32 flags)
185 {
186 	int err = 0;
187 	u32 timeline_flags = TLSTREAM_ENABLED | flags;
188 	struct kbase_timeline *timeline;
189 	int rcode;
190 
191 	if (WARN_ON(!kbdev) || WARN_ON(flags & ~BASE_TLSTREAM_FLAGS_MASK))
192 		return -EINVAL;
193 
194 	timeline = kbdev->timeline;
195 	if (WARN_ON(!timeline))
196 		return -EFAULT;
197 
198 	if (atomic_cmpxchg(timeline->timeline_flags, 0, timeline_flags))
199 		return -EBUSY;
200 
201 #if MALI_USE_CSF
202 	if (flags & BASE_TLSTREAM_ENABLE_CSFFW_TRACEPOINTS) {
203 		err = kbase_csf_tl_reader_start(&timeline->csf_tl_reader, kbdev);
204 		if (err) {
205 			atomic_set(timeline->timeline_flags, 0);
206 			return err;
207 		}
208 	}
209 #endif
210 
211 	/* Reset and initialize header streams. */
212 	kbase_tlstream_reset(&timeline->streams[TL_STREAM_TYPE_OBJ_SUMMARY]);
213 
214 	timeline->obj_header_btc = obj_desc_header_size;
215 	timeline->aux_header_btc = aux_desc_header_size;
216 
217 #if !MALI_USE_CSF
218 	/* If job dumping is enabled, readjust the software event's
219 	 * timeout as the default value of 3 seconds is often
220 	 * insufficient.
221 	 */
222 	if (flags & BASE_TLSTREAM_JOB_DUMPING_ENABLED) {
223 		dev_info(kbdev->dev,
224 			 "Job dumping is enabled, readjusting the software event's timeout\n");
225 		atomic_set(&kbdev->js_data.soft_job_timeout_ms, 1800000);
226 	}
227 #endif /* !MALI_USE_CSF */
228 
229 	/* Summary stream was cleared during acquire.
230 	 * Create static timeline objects that will be
231 	 * read by client.
232 	 */
233 	kbase_create_timeline_objects(kbdev);
234 
235 #ifdef CONFIG_MALI_BIFROST_DEVFREQ
236 	/* Devfreq target tracepoints are only fired when the target
237 	 * changes, so we won't know the current target unless we
238 	 * send it now.
239 	 */
240 	kbase_tlstream_current_devfreq_target(kbdev);
241 #endif /* CONFIG_MALI_BIFROST_DEVFREQ */
242 
243 	/* Start the autoflush timer.
244 	 * We must do this after creating timeline objects to ensure we
245 	 * don't auto-flush the streams which will be reset during the
246 	 * summarization process.
247 	 */
248 	atomic_set(&timeline->autoflush_timer_active, 1);
249 	rcode = mod_timer(&timeline->autoflush_timer,
250 			  jiffies + msecs_to_jiffies(AUTOFLUSH_INTERVAL));
251 	CSTD_UNUSED(rcode);
252 
253 	timeline->last_acquire_time = ktime_get_raw();
254 
255 	return err;
256 }
257 
kbase_timeline_release(struct kbase_timeline * timeline)258 void kbase_timeline_release(struct kbase_timeline *timeline)
259 {
260 	ktime_t elapsed_time;
261 	s64 elapsed_time_ms, time_to_sleep;
262 
263 	if (WARN_ON(!timeline) || WARN_ON(!atomic_read(timeline->timeline_flags)))
264 		return;
265 
266 	/* Get the amount of time passed since the timeline was acquired and ensure
267 	 * we sleep for long enough such that it has been at least
268 	 * TIMELINE_HYSTERESIS_TIMEOUT_MS amount of time between acquire and release.
269 	 * This prevents userspace from spamming acquire and release too quickly.
270 	 */
271 	elapsed_time = ktime_sub(ktime_get_raw(), timeline->last_acquire_time);
272 	elapsed_time_ms = ktime_to_ms(elapsed_time);
273 	time_to_sleep = (elapsed_time_ms < 0 ? TIMELINE_HYSTERESIS_TIMEOUT_MS :
274 					       TIMELINE_HYSTERESIS_TIMEOUT_MS - elapsed_time_ms);
275 	if (time_to_sleep > 0)
276 		msleep_interruptible(time_to_sleep);
277 
278 #if MALI_USE_CSF
279 	kbase_csf_tl_reader_stop(&timeline->csf_tl_reader);
280 #endif
281 
282 	/* Stop autoflush timer before releasing access to streams. */
283 	atomic_set(&timeline->autoflush_timer_active, 0);
284 	del_timer_sync(&timeline->autoflush_timer);
285 
286 	atomic_set(timeline->timeline_flags, 0);
287 }
288 
kbase_timeline_streams_flush(struct kbase_timeline * timeline)289 int kbase_timeline_streams_flush(struct kbase_timeline *timeline)
290 {
291 	enum tl_stream_type stype;
292 	bool has_bytes = false;
293 	size_t nbytes = 0;
294 
295 	if (WARN_ON(!timeline))
296 		return -EINVAL;
297 
298 #if MALI_USE_CSF
299 	{
300 		int ret = kbase_csf_tl_reader_flush_buffer(&timeline->csf_tl_reader);
301 
302 		if (ret > 0)
303 			has_bytes = true;
304 	}
305 #endif
306 
307 	for (stype = 0; stype < TL_STREAM_TYPE_COUNT; stype++) {
308 		nbytes = kbase_tlstream_flush_stream(&timeline->streams[stype]);
309 		if (nbytes > 0)
310 			has_bytes = true;
311 	}
312 	return has_bytes ? 0 : -EIO;
313 }
314 
kbase_timeline_streams_body_reset(struct kbase_timeline * timeline)315 void kbase_timeline_streams_body_reset(struct kbase_timeline *timeline)
316 {
317 	kbase_tlstream_reset(
318 			&timeline->streams[TL_STREAM_TYPE_OBJ]);
319 	kbase_tlstream_reset(
320 			&timeline->streams[TL_STREAM_TYPE_AUX]);
321 #if MALI_USE_CSF
322 	kbase_tlstream_reset(
323 			&timeline->streams[TL_STREAM_TYPE_CSFFW]);
324 #endif
325 }
326 
kbase_timeline_pre_kbase_context_destroy(struct kbase_context * kctx)327 void kbase_timeline_pre_kbase_context_destroy(struct kbase_context *kctx)
328 {
329 	struct kbase_device *const kbdev = kctx->kbdev;
330 	struct kbase_timeline *timeline = kbdev->timeline;
331 
332 	/* Remove the context from the list to ensure we don't try and
333 	 * summarize a context that is being destroyed.
334 	 *
335 	 * It's unsafe to try and summarize a context being destroyed as the
336 	 * locks we might normally attempt to acquire, and the data structures
337 	 * we would normally attempt to traverse could already be destroyed.
338 	 *
339 	 * In the case where the tlstream is acquired between this pre destroy
340 	 * call and the post destroy call, we will get a context destroy
341 	 * tracepoint without the corresponding context create tracepoint,
342 	 * but this will not affect the correctness of the object model.
343 	 */
344 	mutex_lock(&timeline->tl_kctx_list_lock);
345 	list_del_init(&kctx->tl_kctx_list_node);
346 	mutex_unlock(&timeline->tl_kctx_list_lock);
347 }
348 
kbase_timeline_post_kbase_context_create(struct kbase_context * kctx)349 void kbase_timeline_post_kbase_context_create(struct kbase_context *kctx)
350 {
351 	struct kbase_device *const kbdev = kctx->kbdev;
352 	struct kbase_timeline *timeline = kbdev->timeline;
353 
354 	/* On context create, add the context to the list to ensure it is
355 	 * summarized when timeline is acquired
356 	 */
357 	mutex_lock(&timeline->tl_kctx_list_lock);
358 
359 	list_add(&kctx->tl_kctx_list_node, &timeline->tl_kctx_list);
360 
361 	/* Fire the tracepoints with the lock held to ensure the tracepoints
362 	 * are either fired before or after the summarization,
363 	 * never in parallel with it. If fired in parallel, we could get
364 	 * duplicate creation tracepoints.
365 	 */
366 #if MALI_USE_CSF
367 	KBASE_TLSTREAM_TL_KBASE_NEW_CTX(
368 		kbdev, kctx->id, kbdev->gpu_props.props.raw_props.gpu_id);
369 #endif
370 	/* Trace with the AOM tracepoint even in CSF for dumping */
371 	KBASE_TLSTREAM_TL_NEW_CTX(kbdev, kctx, kctx->id, 0);
372 
373 	mutex_unlock(&timeline->tl_kctx_list_lock);
374 }
375 
kbase_timeline_post_kbase_context_destroy(struct kbase_context * kctx)376 void kbase_timeline_post_kbase_context_destroy(struct kbase_context *kctx)
377 {
378 	struct kbase_device *const kbdev = kctx->kbdev;
379 
380 	/* Trace with the AOM tracepoint even in CSF for dumping */
381 	KBASE_TLSTREAM_TL_DEL_CTX(kbdev, kctx);
382 #if MALI_USE_CSF
383 	KBASE_TLSTREAM_TL_KBASE_DEL_CTX(kbdev, kctx->id);
384 #endif
385 
386 	/* Flush the timeline stream, so the user can see the termination
387 	 * tracepoints being fired.
388 	 * The "if" statement below is for optimization. It is safe to call
389 	 * kbase_timeline_streams_flush when timeline is disabled.
390 	 */
391 	if (atomic_read(&kbdev->timeline_flags) != 0)
392 		kbase_timeline_streams_flush(kbdev->timeline);
393 }
394 
395 #if MALI_UNIT_TEST
kbase_timeline_stats(struct kbase_timeline * timeline,u32 * bytes_collected,u32 * bytes_generated)396 void kbase_timeline_stats(struct kbase_timeline *timeline,
397 		u32 *bytes_collected, u32 *bytes_generated)
398 {
399 	enum tl_stream_type stype;
400 
401 	KBASE_DEBUG_ASSERT(bytes_collected);
402 
403 	/* Accumulate bytes generated per stream  */
404 	*bytes_generated = 0;
405 	for (stype = (enum tl_stream_type)0; stype < TL_STREAM_TYPE_COUNT;
406 			stype++)
407 		*bytes_generated += atomic_read(
408 			&timeline->streams[stype].bytes_generated);
409 
410 	*bytes_collected = atomic_read(&timeline->bytes_collected);
411 }
412 #endif /* MALI_UNIT_TEST */
413