aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/vithar/kbase/src/common/mali_kbase_jm.h
blob: 4cc9f6f5d193a0c0251018343b45ea76027027a7 (plain) (blame)
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
/*
 *
 * (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_

#if BASE_HW_ISSUE_8401
#include <kbase/src/common/mali_kbase_8401_workaround.h>
#endif

/**
 * @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)
{
	OSK_ASSERT( kbdev != NULL );
	OSK_ASSERT( 0 <= js && js < kbdev->nr_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.
 * - the slot is not blocked (due to PRLAM-5713 workaround)
 */
static INLINE mali_bool kbasep_jm_is_submit_slots_free(kbase_device *kbdev, int js, kbase_context *kctx)
{
	OSK_ASSERT( kbdev != NULL );
	OSK_ASSERT( 0 <= js && js < kbdev->nr_job_slots  );
	
	if (osk_atomic_get(&kbdev->reset_gpu) != KBASE_RESET_GPU_NOT_PENDING)
	{
		/* The GPU is being reset - so prevent submission */
		return MALI_FALSE;
	}

#if BASE_HW_ISSUE_5713
	return (mali_bool)( !kbdev->jm_slots[js].submission_blocked_for_soft_stop
	                    && kbasep_jm_is_js_free(kbdev, js, kctx)
	                    && kbdev->jm_slots[js].submitted_nr < (BASE_JM_SUBMIT_SLOTS-2) );
#else
	return (mali_bool)( kbasep_jm_is_js_free(kbdev, js, kctx)
	                    && kbdev->jm_slots[js].submitted_nr < (BASE_JM_SUBMIT_SLOTS-2) );
#endif
}

/**
 * Initialize a submit slot
 */
static INLINE void kbasep_jm_init_submit_slot(  kbase_jm_slot *slot )
{
	slot->submitted_nr = 0;
	slot->submitted_head = 0;
#if BASE_HW_ISSUE_5713
	slot->submission_blocked_for_soft_stop = MALI_FALSE;
#endif
}

/**
 * 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;

	OSK_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... */
	OSK_ASSERT(katom);

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

	OSK_PRINT_INFO( OSK_BASE_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++;
	OSK_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] 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_jd_atom *atom )
{
	/* Query the set of workaround jobs here */
#if BASE_HW_ISSUE_8401
	if ( kbasep_8401_is_workaround_job( atom ) != MALI_FALSE )
	{
		return MALI_TRUE;
	}
#else
	CSTD_UNUSED(atom);
#endif

	/* 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
 *  - This is to access the kbase_context::as_nr
 *  - In any case, the kbase_js code that calls this function will always have
 * this lock held.
 * - it must hold kbdev->jm_slots[ \a s ].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, kbasep_js_tick *end_timestamp);

/**
 * @brief Obtain the lock for a job slot.
 *
 * This function also returns the structure for the specified job slot to simplify the code
 *
 * @param[in] kbdev     Kbase device pointer
 * @param[in] js        The job slot number to lock
 *
 * @return  The job slot structure
 */
static INLINE kbase_jm_slot *kbase_job_slot_lock(kbase_device *kbdev, int js)
{
#if BASE_HW_ISSUE_7347
	osk_spinlock_irq_lock(&kbdev->jm_slot_lock);
#else
	osk_spinlock_irq_lock(&kbdev->jm_slots[js].lock);
#endif
	return &kbdev->jm_slots[js];
}

/**
 * @brief Release the lock for a job slot
 *
 * @param[in] kbdev     Kbase device pointer
 * @param[in] js        The job slot number to unlock
 */
static INLINE void kbase_job_slot_unlock(kbase_device *kbdev, int js)
{
#if BASE_HW_ISSUE_7347
	osk_spinlock_irq_unlock(&kbdev->jm_slot_lock);
#else
	osk_spinlock_irq_unlock(&kbdev->jm_slots[js].lock);
#endif
}

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

#endif /* _KBASE_JM_H_ */