aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_jm.h
blob: 6bd70865984cf737b9fbfd034c81de96aa2cf215 (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
/*
 *
 * (C) COPYRIGHT 2011-2012 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.
 *
 */



/**
 * @file mali_kbase_jm.h
 * Job Manager Low-level APIs.
 */

#ifndef _KBASE_JM_H_
#define _KBASE_JM_H_

#include <kbase/src/common/mali_kbase_8401_workaround.h>
#include <kbase/src/common/mali_kbase_hw.h>
#include <linux/atomic.h>

/**
 * @addtogroup base_api
 * @{
 */

/**
 * @addtogroup base_kbase_api
 * @{
 */

/**
 * @addtogroup kbase_jm Job Manager Low-level APIs
 * @{
 *
 */

static INLINE int kbasep_jm_is_js_free(kbase_device *kbdev, int js, kbase_context *kctx)
{
	KBASE_DEBUG_ASSERT(kbdev != NULL);
	KBASE_DEBUG_ASSERT(0 <= js && js < kbdev->gpu_props.num_job_slots);

	return !kbase_reg_read(kbdev, JOB_SLOT_REG(js, JSn_COMMAND_NEXT), kctx);
}

/**
 * This checks that:
 * - there is enough space in the GPU's buffers (JSn_NEXT and JSn_HEAD registers) to accomodate the job.
 * - there is enough space to track the job in a our Submit Slots. Note that we have to maintain space to
 *   requeue one job in case the next registers on the hardware need to be cleared.
 */
static INLINE mali_bool kbasep_jm_is_submit_slots_free(kbase_device *kbdev, int js, kbase_context *kctx)
{
	KBASE_DEBUG_ASSERT(kbdev != NULL);
	KBASE_DEBUG_ASSERT(0 <= js && js < kbdev->gpu_props.num_job_slots);

	if (atomic_read(&kbdev->reset_gpu) != KBASE_RESET_GPU_NOT_PENDING) {
		/* The GPU is being reset - so prevent submission */
		return MALI_FALSE;
	}

	return (mali_bool) (kbasep_jm_is_js_free(kbdev, js, kctx)
			    && kbdev->jm_slots[js].submitted_nr < (BASE_JM_SUBMIT_SLOTS - 2));
}

/**
 * Initialize a submit slot
 */
static INLINE void kbasep_jm_init_submit_slot(kbase_jm_slot *slot)
{
	slot->submitted_nr = 0;
	slot->submitted_head = 0;
}

/**
 * Find the atom at the idx'th element in the queue without removing it, starting at the head with idx==0.
 */
static INLINE kbase_jd_atom *kbasep_jm_peek_idx_submit_slot(kbase_jm_slot *slot, u8 idx)
{
	u8 pos;
	kbase_jd_atom *katom;

	KBASE_DEBUG_ASSERT(idx < BASE_JM_SUBMIT_SLOTS);

	pos = (slot->submitted_head + idx) & BASE_JM_SUBMIT_SLOTS_MASK;
	katom = slot->submitted[pos];

	return katom;
}

/**
 * Pop front of the submitted
 */
static INLINE kbase_jd_atom *kbasep_jm_dequeue_submit_slot(kbase_jm_slot *slot)
{
	u8 pos;
	kbase_jd_atom *katom;

	pos = slot->submitted_head & BASE_JM_SUBMIT_SLOTS_MASK;
	katom = slot->submitted[pos];
	slot->submitted[pos] = NULL;	/* Just to catch bugs... */
	KBASE_DEBUG_ASSERT(katom);

	/* rotate the buffers */
	slot->submitted_head = (slot->submitted_head + 1) & BASE_JM_SUBMIT_SLOTS_MASK;
	slot->submitted_nr--;

	KBASE_DEBUG_PRINT_INFO(KBASE_JM, "katom %p new head %u", (void *)katom, (unsigned int)slot->submitted_head);

	return katom;
}

/* Pop back of the submitted queue (unsubmit a job)
 */
static INLINE kbase_jd_atom *kbasep_jm_dequeue_tail_submit_slot(kbase_jm_slot *slot)
{
	u8 pos;

	slot->submitted_nr--;

	pos = (slot->submitted_head + slot->submitted_nr) & BASE_JM_SUBMIT_SLOTS_MASK;

	return slot->submitted[pos];
}

static INLINE u8 kbasep_jm_nr_jobs_submitted(kbase_jm_slot *slot)
{
	return slot->submitted_nr;
}

/**
 * Push back of the submitted
 */
static INLINE void kbasep_jm_enqueue_submit_slot(kbase_jm_slot *slot, kbase_jd_atom *katom)
{
	u8 nr;
	u8 pos;
	nr = slot->submitted_nr++;
	KBASE_DEBUG_ASSERT(nr < BASE_JM_SUBMIT_SLOTS);

	pos = (slot->submitted_head + nr) & BASE_JM_SUBMIT_SLOTS_MASK;
	slot->submitted[pos] = katom;
}

/**
 * @brief Query whether a job peeked/dequeued from the submit slots is a
 * 'dummy' job that is used for hardware workaround purposes.
 *
 * Any time a job is peeked/dequeued from the submit slots, this should be
 * queried on that job.
 *
 * If a \a atom is indicated as being a dummy job, then you <b>must not attempt
 * to use \a atom</b>. This is because its members will not necessarily be
 * initialized, and so could lead to a fault if they were used.
 *
 * @param[in] kbdev kbase device pointer
 * @param[in] atom The atom to query
 *
 * @return    MALI_TRUE if \a atom is for a dummy job, in which case you must not
 *            attempt to use it.
 * @return    MALI_FALSE otherwise, and \a atom is safe to use.
 */
static INLINE mali_bool kbasep_jm_is_dummy_workaround_job(kbase_device *kbdev, kbase_jd_atom *atom)
{
	/* Query the set of workaround jobs here */
	if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8401)) {
		if (kbasep_8401_is_workaround_job(atom) != MALI_FALSE)
			return MALI_TRUE;
	}

	/* This job is not a workaround job, so it will be processed as normal */
	return MALI_FALSE;
}

/**
 * @brief Submit a job to a certain job-slot
 *
 * The caller must check kbasep_jm_is_submit_slots_free() != MALI_FALSE before calling this.
 *
 * The following locking conditions are made on the caller:
 * - it must hold the kbasep_js_device_data::runpoool_irq::lock
 */
void kbase_job_submit_nolock(kbase_device *kbdev, kbase_jd_atom *katom, int js);

/**
 * @brief Complete the head job on a particular job-slot
 */
void kbase_job_done_slot(kbase_device *kbdev, int s, u32 completion_code, u64 job_tail, ktime_t *end_timestamp);

	  /** @} *//* end group kbase_jm */
	  /** @} *//* end group base_kbase_api */
	  /** @} *//* end group base_api */

#endif				/* _KBASE_JM_H_ */