e6e611b9f415a374b63ec2c03c408247e2bca053
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / arm / midgard / mali_kbase_js_ctx_attr.c
1 /*
2  *
3  * (C) COPYRIGHT 2012-2015 ARM Limited. All rights reserved.
4  *
5  * This program is free software and is provided to you under the terms of the
6  * GNU General Public License version 2 as published by the Free Software
7  * Foundation, and any use by you of this program is subject to the terms
8  * of such GNU licence.
9  *
10  * A copy of the licence is included with the program, and can also be obtained
11  * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
12  * Boston, MA  02110-1301, USA.
13  *
14  */
15
16
17
18
19 #include <mali_kbase.h>
20 #include <mali_kbase_config.h>
21
22 /*
23  * Private functions follow
24  */
25
26 /**
27  * @brief Check whether a ctx has a certain attribute, and if so, retain that
28  * attribute on the runpool.
29  *
30  * Requires:
31  * - jsctx mutex
32  * - runpool_irq spinlock
33  * - ctx is scheduled on the runpool
34  *
35  * @return true indicates a change in ctx attributes state of the runpool.
36  * In this state, the scheduler might be able to submit more jobs than
37  * previously, and so the caller should ensure kbasep_js_try_run_next_job_nolock()
38  * or similar is called sometime later.
39  * @return false indicates no change in ctx attributes state of the runpool.
40  */
41 static bool kbasep_js_ctx_attr_runpool_retain_attr(struct kbase_device *kbdev, struct kbase_context *kctx, enum kbasep_js_ctx_attr attribute)
42 {
43         struct kbasep_js_device_data *js_devdata;
44         struct kbasep_js_kctx_info *js_kctx_info;
45         bool runpool_state_changed = false;
46
47         KBASE_DEBUG_ASSERT(kbdev != NULL);
48         KBASE_DEBUG_ASSERT(kctx != NULL);
49         KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT);
50         js_devdata = &kbdev->js_data;
51         js_kctx_info = &kctx->jctx.sched_info;
52
53         lockdep_assert_held(&js_kctx_info->ctx.jsctx_mutex);
54         lockdep_assert_held(&kbdev->js_data.runpool_irq.lock);
55
56         KBASE_DEBUG_ASSERT(js_kctx_info->ctx.is_scheduled != false);
57
58         if (kbasep_js_ctx_attr_is_attr_on_ctx(kctx, attribute) != false) {
59                 KBASE_DEBUG_ASSERT(js_devdata->runpool_irq.ctx_attr_ref_count[attribute] < S8_MAX);
60                 ++(js_devdata->runpool_irq.ctx_attr_ref_count[attribute]);
61
62                 if (js_devdata->runpool_irq.ctx_attr_ref_count[attribute] == 1) {
63                         /* First refcount indicates a state change */
64                         runpool_state_changed = true;
65                         KBASE_TRACE_ADD(kbdev, JS_CTX_ATTR_NOW_ON_RUNPOOL, kctx, NULL, 0u, attribute);
66                 }
67         }
68
69         return runpool_state_changed;
70 }
71
72 /**
73  * @brief Check whether a ctx has a certain attribute, and if so, release that
74  * attribute on the runpool.
75  *
76  * Requires:
77  * - jsctx mutex
78  * - runpool_irq spinlock
79  * - ctx is scheduled on the runpool
80  *
81  * @return true indicates a change in ctx attributes state of the runpool.
82  * In this state, the scheduler might be able to submit more jobs than
83  * previously, and so the caller should ensure kbasep_js_try_run_next_job_nolock()
84  * or similar is called sometime later.
85  * @return false indicates no change in ctx attributes state of the runpool.
86  */
87 static bool kbasep_js_ctx_attr_runpool_release_attr(struct kbase_device *kbdev, struct kbase_context *kctx, enum kbasep_js_ctx_attr attribute)
88 {
89         struct kbasep_js_device_data *js_devdata;
90         struct kbasep_js_kctx_info *js_kctx_info;
91         bool runpool_state_changed = false;
92
93         KBASE_DEBUG_ASSERT(kbdev != NULL);
94         KBASE_DEBUG_ASSERT(kctx != NULL);
95         KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT);
96         js_devdata = &kbdev->js_data;
97         js_kctx_info = &kctx->jctx.sched_info;
98
99         lockdep_assert_held(&js_kctx_info->ctx.jsctx_mutex);
100         lockdep_assert_held(&kbdev->js_data.runpool_irq.lock);
101         KBASE_DEBUG_ASSERT(js_kctx_info->ctx.is_scheduled != false);
102
103         if (kbasep_js_ctx_attr_is_attr_on_ctx(kctx, attribute) != false) {
104                 KBASE_DEBUG_ASSERT(js_devdata->runpool_irq.ctx_attr_ref_count[attribute] > 0);
105                 --(js_devdata->runpool_irq.ctx_attr_ref_count[attribute]);
106
107                 if (js_devdata->runpool_irq.ctx_attr_ref_count[attribute] == 0) {
108                         /* Last de-refcount indicates a state change */
109                         runpool_state_changed = true;
110                         KBASE_TRACE_ADD(kbdev, JS_CTX_ATTR_NOW_OFF_RUNPOOL, kctx, NULL, 0u, attribute);
111                 }
112         }
113
114         return runpool_state_changed;
115 }
116
117 /**
118  * @brief Retain a certain attribute on a ctx, also retaining it on the runpool
119  * if the context is scheduled.
120  *
121  * Requires:
122  * - jsctx mutex
123  * - If the context is scheduled, then runpool_irq spinlock must also be held
124  *
125  * @return true indicates a change in ctx attributes state of the runpool.
126  * This may allow the scheduler to submit more jobs than previously.
127  * @return false indicates no change in ctx attributes state of the runpool.
128  */
129 static bool kbasep_js_ctx_attr_ctx_retain_attr(struct kbase_device *kbdev, struct kbase_context *kctx, enum kbasep_js_ctx_attr attribute)
130 {
131         struct kbasep_js_kctx_info *js_kctx_info;
132         bool runpool_state_changed = false;
133
134         KBASE_DEBUG_ASSERT(kbdev != NULL);
135         KBASE_DEBUG_ASSERT(kctx != NULL);
136         KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT);
137         js_kctx_info = &kctx->jctx.sched_info;
138
139         lockdep_assert_held(&kbdev->js_data.runpool_irq.lock);
140         lockdep_assert_held(&js_kctx_info->ctx.jsctx_mutex);
141         KBASE_DEBUG_ASSERT(js_kctx_info->ctx.ctx_attr_ref_count[attribute] < U32_MAX);
142
143         ++(js_kctx_info->ctx.ctx_attr_ref_count[attribute]);
144
145         if (js_kctx_info->ctx.is_scheduled != false && js_kctx_info->ctx.ctx_attr_ref_count[attribute] == 1) {
146                 /* Only ref-count the attribute on the runpool for the first time this contexts sees this attribute */
147                 KBASE_TRACE_ADD(kbdev, JS_CTX_ATTR_NOW_ON_CTX, kctx, NULL, 0u, attribute);
148                 runpool_state_changed = kbasep_js_ctx_attr_runpool_retain_attr(kbdev, kctx, attribute);
149         }
150
151         return runpool_state_changed;
152 }
153
154 /*
155  * @brief Release a certain attribute on a ctx, also releasing it from the runpool
156  * if the context is scheduled.
157  *
158  * Requires:
159  * - jsctx mutex
160  * - If the context is scheduled, then runpool_irq spinlock must also be held
161  *
162  * @return true indicates a change in ctx attributes state of the runpool.
163  * This may allow the scheduler to submit more jobs than previously.
164  * @return false indicates no change in ctx attributes state of the runpool.
165  */
166 static bool kbasep_js_ctx_attr_ctx_release_attr(struct kbase_device *kbdev, struct kbase_context *kctx, enum kbasep_js_ctx_attr attribute)
167 {
168         struct kbasep_js_kctx_info *js_kctx_info;
169         bool runpool_state_changed = false;
170
171         KBASE_DEBUG_ASSERT(kbdev != NULL);
172         KBASE_DEBUG_ASSERT(kctx != NULL);
173         KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT);
174         js_kctx_info = &kctx->jctx.sched_info;
175
176         lockdep_assert_held(&js_kctx_info->ctx.jsctx_mutex);
177         KBASE_DEBUG_ASSERT(js_kctx_info->ctx.ctx_attr_ref_count[attribute] > 0);
178
179         if (js_kctx_info->ctx.is_scheduled != false && js_kctx_info->ctx.ctx_attr_ref_count[attribute] == 1) {
180                 lockdep_assert_held(&kbdev->js_data.runpool_irq.lock);
181                 /* Only de-ref-count the attribute on the runpool when this is the last ctx-reference to it */
182                 runpool_state_changed = kbasep_js_ctx_attr_runpool_release_attr(kbdev, kctx, attribute);
183                 KBASE_TRACE_ADD(kbdev, JS_CTX_ATTR_NOW_OFF_CTX, kctx, NULL, 0u, attribute);
184         }
185
186         /* De-ref must happen afterwards, because kbasep_js_ctx_attr_runpool_release() needs to check it too */
187         --(js_kctx_info->ctx.ctx_attr_ref_count[attribute]);
188
189         return runpool_state_changed;
190 }
191
192 /*
193  * More commonly used public functions
194  */
195
196 void kbasep_js_ctx_attr_set_initial_attrs(struct kbase_device *kbdev, struct kbase_context *kctx)
197 {
198         struct kbasep_js_kctx_info *js_kctx_info;
199         bool runpool_state_changed = false;
200
201         KBASE_DEBUG_ASSERT(kbdev != NULL);
202         KBASE_DEBUG_ASSERT(kctx != NULL);
203         js_kctx_info = &kctx->jctx.sched_info;
204
205         if ((js_kctx_info->ctx.flags & KBASE_CTX_FLAG_SUBMIT_DISABLED) != false) {
206                 /* This context never submits, so don't track any scheduling attributes */
207                 return;
208         }
209
210         /* Transfer attributes held in the context flags for contexts that have submit enabled */
211
212         /* ... More attributes can be added here ... */
213
214         /* The context should not have been scheduled yet, so ASSERT if this caused
215          * runpool state changes (note that other threads *can't* affect the value
216          * of runpool_state_changed, due to how it's calculated) */
217         KBASE_DEBUG_ASSERT(runpool_state_changed == false);
218         CSTD_UNUSED(runpool_state_changed);
219 }
220
221 void kbasep_js_ctx_attr_runpool_retain_ctx(struct kbase_device *kbdev, struct kbase_context *kctx)
222 {
223         bool runpool_state_changed;
224         int i;
225
226         /* Retain any existing attributes */
227         for (i = 0; i < KBASEP_JS_CTX_ATTR_COUNT; ++i) {
228                 if (kbasep_js_ctx_attr_is_attr_on_ctx(kctx, (enum kbasep_js_ctx_attr) i) != false) {
229                         /* The context is being scheduled in, so update the runpool with the new attributes */
230                         runpool_state_changed = kbasep_js_ctx_attr_runpool_retain_attr(kbdev, kctx, (enum kbasep_js_ctx_attr) i);
231
232                         /* We don't need to know about state changed, because retaining a
233                          * context occurs on scheduling it, and that itself will also try
234                          * to run new atoms */
235                         CSTD_UNUSED(runpool_state_changed);
236                 }
237         }
238 }
239
240 bool kbasep_js_ctx_attr_runpool_release_ctx(struct kbase_device *kbdev, struct kbase_context *kctx)
241 {
242         bool runpool_state_changed = false;
243         int i;
244
245         /* Release any existing attributes */
246         for (i = 0; i < KBASEP_JS_CTX_ATTR_COUNT; ++i) {
247                 if (kbasep_js_ctx_attr_is_attr_on_ctx(kctx, (enum kbasep_js_ctx_attr) i) != false) {
248                         /* The context is being scheduled out, so update the runpool on the removed attributes */
249                         runpool_state_changed |= kbasep_js_ctx_attr_runpool_release_attr(kbdev, kctx, (enum kbasep_js_ctx_attr) i);
250                 }
251         }
252
253         return runpool_state_changed;
254 }
255
256 void kbasep_js_ctx_attr_ctx_retain_atom(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *katom)
257 {
258         bool runpool_state_changed = false;
259         base_jd_core_req core_req;
260
261         KBASE_DEBUG_ASSERT(katom);
262         core_req = katom->core_req;
263
264         if (core_req & BASE_JD_REQ_ONLY_COMPUTE)
265                 runpool_state_changed |= kbasep_js_ctx_attr_ctx_retain_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_COMPUTE);
266         else
267                 runpool_state_changed |= kbasep_js_ctx_attr_ctx_retain_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_NON_COMPUTE);
268
269         if ((core_req & (BASE_JD_REQ_CS | BASE_JD_REQ_ONLY_COMPUTE | BASE_JD_REQ_T)) != 0 && (core_req & (BASE_JD_REQ_COHERENT_GROUP | BASE_JD_REQ_SPECIFIC_COHERENT_GROUP)) == 0) {
270                 /* Atom that can run on slot1 or slot2, and can use all cores */
271                 runpool_state_changed |= kbasep_js_ctx_attr_ctx_retain_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES);
272         }
273
274         /* We don't need to know about state changed, because retaining an
275          * atom occurs on adding it, and that itself will also try to run
276          * new atoms */
277         CSTD_UNUSED(runpool_state_changed);
278 }
279
280 bool kbasep_js_ctx_attr_ctx_release_atom(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbasep_js_atom_retained_state *katom_retained_state)
281 {
282         bool runpool_state_changed = false;
283         base_jd_core_req core_req;
284
285         KBASE_DEBUG_ASSERT(katom_retained_state);
286         core_req = katom_retained_state->core_req;
287
288         /* No-op for invalid atoms */
289         if (kbasep_js_atom_retained_state_is_valid(katom_retained_state) == false)
290                 return false;
291
292         if (core_req & BASE_JD_REQ_ONLY_COMPUTE)
293                 runpool_state_changed |= kbasep_js_ctx_attr_ctx_release_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_COMPUTE);
294         else
295                 runpool_state_changed |= kbasep_js_ctx_attr_ctx_release_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_NON_COMPUTE);
296
297         if ((core_req & (BASE_JD_REQ_CS | BASE_JD_REQ_ONLY_COMPUTE | BASE_JD_REQ_T)) != 0 && (core_req & (BASE_JD_REQ_COHERENT_GROUP | BASE_JD_REQ_SPECIFIC_COHERENT_GROUP)) == 0) {
298                 /* Atom that can run on slot1 or slot2, and can use all cores */
299                 runpool_state_changed |= kbasep_js_ctx_attr_ctx_release_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES);
300         }
301
302         return runpool_state_changed;
303 }