aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase.h
blob: 8044a93cda26086d491c002aef63b4ebde3e0495 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
/*
 *
 * (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved.
 *
 * This program is free software and is provided to you under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation, and any use by you of this program is subject to the terms
 * of such GNU licence.
 *
 * A copy of the licence is included with the program, and can also be obtained
 * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA  02110-1301, USA.
 *
 */



#ifndef _KBASE_H_
#define _KBASE_H_

#include <malisw/mali_malisw.h>

#include <kbase/mali_kbase_debug.h>

#include <asm/page.h>

#include <linux/atomic.h>
#include <linux/highmem.h>
#include <linux/hrtimer.h>
#include <linux/ktime.h>
#include <linux/list.h>
#include <linux/mm_types.h>
#include <linux/mutex.h>
#include <linux/rwsem.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/vmalloc.h>
#include <linux/wait.h>
#include <linux/workqueue.h>

#include <kbase/mali_base_kernel.h>
#include <kbase/src/common/mali_kbase_uku.h>
#include <kbase/src/linux/mali_kbase_linux.h>

#include "mali_kbase_pm.h"
#include "mali_kbase_mem_lowlevel.h"
#include "mali_kbase_defs.h"
#include "mali_kbase_trace_timeline.h"
#include "mali_kbase_js.h"
#include "mali_kbase_mem.h"
#include "mali_kbase_security.h"
#include "mali_kbase_utility.h"

#include "mali_kbase_cpuprops.h"
#include "mali_kbase_gpuprops.h"
#ifdef CONFIG_GPU_TRACEPOINTS
#include <trace/events/gpu.h>
#endif
/**
 * @page page_base_kernel_main Kernel-side Base (KBase) APIs
 *
 * The Kernel-side Base (KBase) APIs are divided up as follows:
 * - @subpage page_kbase_js_policy
 */

/**
 * @defgroup base_kbase_api Kernel-side Base (KBase) APIs
 */

kbase_device *kbase_device_alloc(void);
/* note: configuration attributes member of kbdev needs to have been setup before calling kbase_device_init */
mali_error kbase_device_init(kbase_device * const kbdev);
void kbase_device_term(kbase_device *kbdev);
void kbase_device_free(kbase_device *kbdev);
int kbase_device_has_feature(kbase_device *kbdev, u32 feature);
kbase_midgard_type kbase_device_get_type(kbase_device *kbdev);
struct kbase_device *kbase_find_device(int minor);	/* Only needed for gator integration */

/**
 * Ensure that all IRQ handlers have completed execution
 *
 * @param kbdev     The kbase device
 */
void kbase_synchronize_irqs(kbase_device *kbdev);

kbase_context *kbase_create_context(kbase_device *kbdev);
void kbase_destroy_context(kbase_context *kctx);
mali_error kbase_context_set_create_flags(kbase_context *kctx, u32 flags);

mali_error kbase_instr_hwcnt_setup(kbase_context *kctx, kbase_uk_hwcnt_setup *setup);
mali_error kbase_instr_hwcnt_enable(kbase_context *kctx, kbase_uk_hwcnt_setup *setup);
mali_error kbase_instr_hwcnt_disable(kbase_context *kctx);
mali_error kbase_instr_hwcnt_clear(kbase_context *kctx);
mali_error kbase_instr_hwcnt_dump(kbase_context *kctx);
mali_error kbase_instr_hwcnt_dump_irq(kbase_context *kctx);
mali_bool kbase_instr_hwcnt_dump_complete(kbase_context *kctx, mali_bool * const success);
void kbase_instr_hwcnt_suspend(kbase_device *kbdev);
void kbase_instr_hwcnt_resume(kbase_device *kbdev);

void kbasep_cache_clean_worker(struct work_struct *data);
void kbase_clean_caches_done(kbase_device *kbdev);

/**
 * The GPU has completed performance count sampling successfully.
 */
void kbase_instr_hwcnt_sample_done(kbase_device *kbdev);

mali_error kbase_create_os_context(kbase_os_context * const osctx);
void kbase_destroy_os_context(kbase_os_context *osctx);

mali_error kbase_jd_init(kbase_context *kctx);
void kbase_jd_exit(kbase_context *kctx);
mali_error kbase_jd_submit(kbase_context *kctx, const kbase_uk_job_submit *user_bag);
void kbase_jd_done(kbase_jd_atom *katom, int slot_nr, ktime_t *end_timestamp,
                   kbasep_js_atom_done_code done_code);
void kbase_jd_cancel(kbase_device *kbdev, kbase_jd_atom *katom);
void kbase_jd_zap_context(kbase_context *kctx);
mali_bool jd_done_nolock(kbase_jd_atom *katom);
void kbase_jd_free_external_resources(kbase_jd_atom *katom);

mali_error kbase_job_slot_init(kbase_device *kbdev);
void kbase_job_slot_halt(kbase_device *kbdev);
void kbase_job_slot_term(kbase_device *kbdev);
void kbase_job_done(kbase_device *kbdev, u32 done);
void kbase_job_zap_context(kbase_context *kctx);

void kbase_job_slot_softstop(kbase_device *kbdev, int js, kbase_jd_atom *target_katom);
void kbase_job_slot_hardstop(kbase_context *kctx, int js, kbase_jd_atom *target_katom);

void kbase_event_post(kbase_context *ctx, kbase_jd_atom *event);
int kbase_event_dequeue(kbase_context *ctx, base_jd_event_v2 *uevent);
int kbase_event_pending(kbase_context *ctx);
mali_error kbase_event_init(kbase_context *kctx);
void kbase_event_close(kbase_context *kctx);
void kbase_event_cleanup(kbase_context *kctx);
void kbase_event_wakeup(kbase_context *kctx);

int kbase_process_soft_job(kbase_jd_atom *katom);
mali_error kbase_prepare_soft_job(kbase_jd_atom *katom);
void kbase_finish_soft_job(kbase_jd_atom *katom);
void kbase_cancel_soft_job(kbase_jd_atom *katom);
void kbase_resume_suspended_soft_jobs(kbase_device *kbdev);

/* api used internally for register access. Contains validation and tracing */
void kbase_reg_write(kbase_device *kbdev, u16 offset, u32 value, kbase_context *kctx);
u32 kbase_reg_read(kbase_device *kbdev, u16 offset, kbase_context *kctx);
void kbase_device_trace_register_access(kbase_context *kctx, kbase_reg_access_type type, u16 reg_offset, u32 reg_value);
void kbase_device_trace_buffer_install(kbase_context *kctx, u32 *tb, size_t size);
void kbase_device_trace_buffer_uninstall(kbase_context *kctx);

/* api to be ported per OS, only need to do the raw register access */
void kbase_os_reg_write(kbase_device *kbdev, u16 offset, u32 value);
u32 kbase_os_reg_read(kbase_device *kbdev, u16 offset);

/** Report a GPU fault.
 *
 * This function is called from the interrupt handler when a GPU fault occurs.
 * It reports the details of the fault using KBASE_DEBUG_PRINT_WARN.
 *
 * @param kbdev     The kbase device that the GPU fault occurred from.
 * @param multiple  Zero if only GPU_FAULT was raised, non-zero if MULTIPLE_GPU_FAULTS was also set
 */
void kbase_report_gpu_fault(kbase_device *kbdev, int multiple);

/** Kill all jobs that are currently running from a context
 *
 * This is used in response to a page fault to remove all jobs from the faulting context from the hardware.
 *
 * @param kctx      The context to kill jobs from
 */
void kbase_job_kill_jobs_from_context(kbase_context *kctx);

/**
 * GPU interrupt handler
 *
 * This function is called from the interrupt handler when a GPU irq is to be handled.
 *
 * @param kbdev The kbase device to handle an IRQ for
 * @param val   The value of the GPU IRQ status register which triggered the call
 */
void kbase_gpu_interrupt(kbase_device *kbdev, u32 val);

/**
 * Prepare for resetting the GPU.
 * This function just soft-stops all the slots to ensure that as many jobs as possible are saved.
 *
 * The function returns a boolean which should be interpreted as follows:
 * - MALI_TRUE - Prepared for reset, kbase_reset_gpu should be called.
 * - MALI_FALSE - Another thread is performing a reset, kbase_reset_gpu should not be called.
 *
 * @return See description
 */
mali_bool kbase_prepare_to_reset_gpu(kbase_device *kbdev);

/**
 * Pre-locked version of @a kbase_prepare_to_reset_gpu.
 *
 * Identical to @a kbase_prepare_to_reset_gpu, except that the
 * kbasep_js_device_data::runpool_irq::lock is externally locked.
 *
 * @see kbase_prepare_to_reset_gpu
 */
mali_bool kbase_prepare_to_reset_gpu_locked(kbase_device *kbdev);

/** Reset the GPU
 *
 * This function should be called after kbase_prepare_to_reset_gpu iff it returns MALI_TRUE.
 * It should never be called without a corresponding call to kbase_prepare_to_reset_gpu.
 *
 * After this function is called (or not called if kbase_prepare_to_reset_gpu returned MALI_FALSE),
 * the caller should wait for kbdev->reset_waitq to be signalled to know when the reset has completed.
 */
void kbase_reset_gpu(kbase_device *kbdev);

/**
 * Pre-locked version of @a kbase_reset_gpu.
 *
 * Identical to @a kbase_reset_gpu, except that the
 * kbasep_js_device_data::runpool_irq::lock is externally locked.
 *
 * @see kbase_reset_gpu
 */
void kbase_reset_gpu_locked(kbase_device *kbdev);

/** Returns the name associated with a Mali exception code
 *
 * @param[in] exception_code  exception code
 * @return name associated with the exception code
 */
const char *kbase_exception_name(u32 exception_code);

/**
 * Check whether a system suspend is in progress, or has already been suspended
 *
 * The caller should ensure that either kbdev->pm.active_count_lock is held, or
 * a dmb was executed recently (to ensure the value is most
 * up-to-date). However, without a lock the value could change afterwards.
 *
 * @return MALI_FALSE if a suspend is not in progress
 * @return !=MALI_FALSE otherwise
 */
static INLINE mali_bool kbase_pm_is_suspending(struct kbase_device *kbdev) {
	return kbdev->pm.suspending;
}

/**
 * Return the atom's ID, as was originally supplied by userspace in
 * base_jd_atom_v2::atom_number
 */
static INLINE int kbase_jd_atom_id(kbase_context *kctx, kbase_jd_atom *katom)
{
	int result;
	KBASE_DEBUG_ASSERT(kctx);
	KBASE_DEBUG_ASSERT(katom);
	KBASE_DEBUG_ASSERT(katom->kctx == kctx);

	result = katom - &kctx->jctx.atoms[0];
	KBASE_DEBUG_ASSERT(result >= 0 && result <= BASE_JD_ATOM_COUNT);
	return result;
}

#if KBASE_TRACE_ENABLE != 0
/** Add trace values about a job-slot
 *
 * @note Any functions called through this macro will still be evaluated in
 * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any
 * functions called to get the parameters supplied to this macro must:
 * - be static or static inline
 * - must just return 0 and have no other statements present in the body.
 */
#define KBASE_TRACE_ADD_SLOT(kbdev, code, ctx, katom, gpu_addr, jobslot) \
	kbasep_trace_add(kbdev, KBASE_TRACE_CODE(code), ctx, katom, gpu_addr, \
			KBASE_TRACE_FLAG_JOBSLOT, 0, jobslot, 0)

/** Add trace values about a job-slot, with info
 *
 * @note Any functions called through this macro will still be evaluated in
 * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any
 * functions called to get the parameters supplied to this macro must:
 * - be static or static inline
 * - must just return 0 and have no other statements present in the body.
 */
#define KBASE_TRACE_ADD_SLOT_INFO(kbdev, code, ctx, katom, gpu_addr, jobslot, info_val) \
	kbasep_trace_add(kbdev, KBASE_TRACE_CODE(code), ctx, katom, gpu_addr, \
			KBASE_TRACE_FLAG_JOBSLOT, 0, jobslot, info_val)

/** Add trace values about a ctx refcount
 *
 * @note Any functions called through this macro will still be evaluated in
 * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any
 * functions called to get the parameters supplied to this macro must:
 * - be static or static inline
 * - must just return 0 and have no other statements present in the body.
 */
#define KBASE_TRACE_ADD_REFCOUNT(kbdev, code, ctx, katom, gpu_addr, refcount) \
	kbasep_trace_add(kbdev, KBASE_TRACE_CODE(code), ctx, katom, gpu_addr, \
			KBASE_TRACE_FLAG_REFCOUNT, refcount, 0, 0)
/** Add trace values about a ctx refcount, and info
 *
 * @note Any functions called through this macro will still be evaluated in
 * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any
 * functions called to get the parameters supplied to this macro must:
 * - be static or static inline
 * - must just return 0 and have no other statements present in the body.
 */
#define KBASE_TRACE_ADD_REFCOUNT_INFO(kbdev, code, ctx, katom, gpu_addr, refcount, info_val) \
	kbasep_trace_add(kbdev, KBASE_TRACE_CODE(code), ctx, katom, gpu_addr, \
			KBASE_TRACE_FLAG_REFCOUNT, refcount, 0, info_val)

/** Add trace values (no slot or refcount)
 *
 * @note Any functions called through this macro will still be evaluated in
 * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any
 * functions called to get the parameters supplied to this macro must:
 * - be static or static inline
 * - must just return 0 and have no other statements present in the body.
 */
#define KBASE_TRACE_ADD(kbdev, code, ctx, katom, gpu_addr, info_val)     \
	kbasep_trace_add(kbdev, KBASE_TRACE_CODE(code), ctx, katom, gpu_addr, \
			0, 0, 0, info_val)

/** Clear the trace */
#define KBASE_TRACE_CLEAR(kbdev) \
	kbasep_trace_clear(kbdev)

/** Dump the slot trace */
#define KBASE_TRACE_DUMP(kbdev) \
	kbasep_trace_dump(kbdev)

/** PRIVATE - do not use directly. Use KBASE_TRACE_ADD() instead */
void kbasep_trace_add(kbase_device *kbdev, kbase_trace_code code, void *ctx, kbase_jd_atom *katom, u64 gpu_addr, u8 flags, int refcount, int jobslot, u32 info_val);
/** PRIVATE - do not use directly. Use KBASE_TRACE_CLEAR() instead */
void kbasep_trace_clear(kbase_device *kbdev);
#else
#ifdef CONFIG_MALI_SYSTEM_TRACE
/* Dispatch kbase trace events as system trace events */
#include <kbase/src/linux/mali_linux_kbase_trace.h>
#define KBASE_TRACE_ADD_SLOT( kbdev, code, ctx, katom, gpu_addr, jobslot )\
	trace_mali_##code(jobslot, 0)

#define KBASE_TRACE_ADD_SLOT_INFO( kbdev, code, ctx, katom, gpu_addr, jobslot, info_val )\
	trace_mali_##code(jobslot, info_val)

#define KBASE_TRACE_ADD_REFCOUNT( kbdev, code, ctx, katom, gpu_addr, refcount )\
	trace_mali_##code(refcount, 0)

#define KBASE_TRACE_ADD_REFCOUNT_INFO( kbdev, code, ctx, katom, gpu_addr, refcount, info_val )\
	trace_mali_##code(refcount, info_val)

#define KBASE_TRACE_ADD( kbdev, code, ctx, katom, gpu_addr, info_val )\
	trace_mali_##code(gpu_addr, info_val)

#define KBASE_TRACE_CLEAR( kbdev )\
	do{\
		CSTD_UNUSED(kbdev);\
		CSTD_NOP(0);\
	}while(0)
#define KBASE_TRACE_DUMP( kbdev )\
	do{\
		CSTD_UNUSED(kbdev);\
		CSTD_NOP(0);\
	}while(0)

#else /* CONFIG_MALI_SYSTEM_TRACE */
#define KBASE_TRACE_ADD_SLOT( kbdev, code, ctx, katom, gpu_addr, jobslot )\
	do{\
		CSTD_UNUSED(kbdev);\
		CSTD_NOP(code);\
		CSTD_UNUSED(ctx);\
		CSTD_UNUSED(katom);\
		CSTD_UNUSED(gpu_addr);\
		CSTD_UNUSED(jobslot);\
	} while (0)

#define KBASE_TRACE_ADD_SLOT_INFO(kbdev, code, ctx, katom, gpu_addr, jobslot, info_val)\
	do {\
		CSTD_UNUSED(kbdev);\
		CSTD_NOP(code);\
		CSTD_UNUSED(ctx);\
		CSTD_UNUSED(katom);\
		CSTD_UNUSED(gpu_addr);\
		CSTD_UNUSED(jobslot);\
		CSTD_UNUSED(info_val);\
		CSTD_NOP(0);\
	} while (0)

#define KBASE_TRACE_ADD_REFCOUNT(kbdev, code, ctx, katom, gpu_addr, refcount)\
	do {\
		CSTD_UNUSED(kbdev);\
		CSTD_NOP(code);\
		CSTD_UNUSED(ctx);\
		CSTD_UNUSED(katom);\
		CSTD_UNUSED(gpu_addr);\
		CSTD_UNUSED(refcount);\
		CSTD_NOP(0);\
	} while (0)

#define KBASE_TRACE_ADD_REFCOUNT_INFO(kbdev, code, ctx, katom, gpu_addr, refcount, info_val)\
	do {\
		CSTD_UNUSED(kbdev);\
		CSTD_NOP(code);\
		CSTD_UNUSED(ctx);\
		CSTD_UNUSED(katom);\
		CSTD_UNUSED(gpu_addr);\
		CSTD_UNUSED(info_val);\
		CSTD_NOP(0);\
	} while (0)

#define KBASE_TRACE_ADD(kbdev, code, subcode, ctx, katom, val)\
	do {\
		CSTD_UNUSED(kbdev);\
		CSTD_NOP(code);\
		CSTD_UNUSED(subcode);\
		CSTD_UNUSED(ctx);\
		CSTD_UNUSED(katom);\
		CSTD_UNUSED(val);\
		CSTD_NOP(0);\
	}while(0)

#define KBASE_TRACE_CLEAR( kbdev )\
	do{\
		CSTD_UNUSED(kbdev);\
		CSTD_NOP(0);\
	}while(0)
#define KBASE_TRACE_DUMP( kbdev )\
	do{\
		CSTD_UNUSED(kbdev);\
		CSTD_NOP(0);\
	}while(0)
#endif /* CONFIG_MALI_SYSTEM_TRACE */
#endif
/** PRIVATE - do not use directly. Use KBASE_TRACE_DUMP() instead */
void kbasep_trace_dump(kbase_device *kbdev);
#endif