hc
2024-05-16 8d2a02b24d66aa359e83eebc1ed3c0f85367a1cb
kernel/drivers/gpu/arm/bifrost/mali_kbase_sync_file.c
....@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
22 /*
33 *
4
- * (C) COPYRIGHT 2012-2021 ARM Limited. All rights reserved.
4
+ * (C) COPYRIGHT 2012-2022 ARM Limited. All rights reserved.
55 *
66 * This program is free software and is provided to you under the terms of the
77 * GNU General Public License version 2 as published by the Free Software
....@@ -21,9 +21,6 @@
2121
2222 /*
2323 * Code for supporting explicit Linux fences (CONFIG_SYNC_FILE)
24
- * Introduced in kernel 4.9.
25
- * Android explicit fences (CONFIG_SYNC) can be used for older kernels
26
- * (see mali_kbase_sync_android.c)
2724 */
2825
2926 #include <linux/sched.h>
....@@ -112,10 +109,13 @@
112109 struct dma_fence *fence = sync_file_get_fence(fd);
113110 #endif
114111
112
+ lockdep_assert_held(&katom->kctx->jctx.lock);
113
+
115114 if (!fence)
116115 return -ENOENT;
117116
118117 kbase_fence_fence_in_set(katom, fence);
118
+ katom->dma_fence.fence_cb_added = false;
119119
120120 return 0;
121121 }
....@@ -167,36 +167,31 @@
167167 struct dma_fence_cb *cb)
168168 #endif
169169 {
170
- struct kbase_fence_cb *kcb = container_of(cb,
171
- struct kbase_fence_cb,
172
- fence_cb);
173
- struct kbase_jd_atom *katom = kcb->katom;
170
+ struct kbase_jd_atom *katom = container_of(cb, struct kbase_jd_atom,
171
+ dma_fence.fence_cb);
174172 struct kbase_context *kctx = katom->kctx;
175173
176174 /* Cancel atom if fence is erroneous */
175
+ if (dma_fence_is_signaled(katom->dma_fence.fence_in) &&
177176 #if (KERNEL_VERSION(4, 11, 0) <= LINUX_VERSION_CODE || \
178177 (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE && \
179178 KERNEL_VERSION(4, 9, 68) <= LINUX_VERSION_CODE))
180
- if (dma_fence_is_signaled(kcb->fence) && kcb->fence->error < 0)
179
+ katom->dma_fence.fence_in->error < 0)
181180 #else
182
- if (dma_fence_is_signaled(kcb->fence) && kcb->fence->status < 0)
181
+ katom->dma_fence.fence_in->status < 0)
183182 #endif
184183 katom->event_code = BASE_JD_EVENT_JOB_CANCELLED;
185184
186
- if (kbase_fence_dep_count_dec_and_test(katom)) {
187
- /* We take responsibility of handling this */
188
- kbase_fence_dep_count_set(katom, -1);
189185
190
- /* To prevent a potential deadlock we schedule the work onto the
191
- * job_done_wq workqueue
192
- *
193
- * The issue is that we may signal the timeline while holding
194
- * kctx->jctx.lock and the callbacks are run synchronously from
195
- * sync_timeline_signal. So we simply defer the work.
196
- */
197
- INIT_WORK(&katom->work, kbase_sync_fence_wait_worker);
198
- queue_work(kctx->jctx.job_done_wq, &katom->work);
199
- }
186
+ /* To prevent a potential deadlock we schedule the work onto the
187
+ * job_done_wq workqueue
188
+ *
189
+ * The issue is that we may signal the timeline while holding
190
+ * kctx->jctx.lock and the callbacks are run synchronously from
191
+ * sync_timeline_signal. So we simply defer the work.
192
+ */
193
+ INIT_WORK(&katom->work, kbase_sync_fence_wait_worker);
194
+ queue_work(kctx->jctx.job_done_wq, &katom->work);
200195 }
201196
202197 int kbase_sync_fence_in_wait(struct kbase_jd_atom *katom)
....@@ -208,53 +203,77 @@
208203 struct dma_fence *fence;
209204 #endif
210205
211
- fence = kbase_fence_in_get(katom);
206
+ lockdep_assert_held(&katom->kctx->jctx.lock);
207
+
208
+ fence = katom->dma_fence.fence_in;
212209 if (!fence)
213210 return 0; /* no input fence to wait for, good to go! */
214211
215
- kbase_fence_dep_count_set(katom, 1);
212
+ err = dma_fence_add_callback(fence, &katom->dma_fence.fence_cb,
213
+ kbase_fence_wait_callback);
214
+ if (err == -ENOENT) {
215
+ int fence_status = dma_fence_get_status(fence);
216216
217
- err = kbase_fence_add_callback(katom, fence, kbase_fence_wait_callback);
218
-
219
- kbase_fence_put(fence);
220
-
221
- if (likely(!err)) {
222
- /* Test if the callbacks are already triggered */
223
- if (kbase_fence_dep_count_dec_and_test(katom)) {
224
- kbase_fence_free_callbacks(katom);
225
- kbase_fence_dep_count_set(katom, -1);
226
- return 0; /* Already signaled, good to go right now */
217
+ if (fence_status == 1) {
218
+ /* Fence is already signaled with no error. The completion
219
+ * for FENCE_WAIT softjob can be done right away.
220
+ */
221
+ return 0;
227222 }
228223
229
- /* Callback installed, so we just need to wait for it... */
230
- } else {
231
- /* Failure */
232
- kbase_fence_free_callbacks(katom);
233
- kbase_fence_dep_count_set(katom, -1);
224
+ /* Fence shouldn't be in not signaled state */
225
+ if (!fence_status) {
226
+ struct kbase_sync_fence_info info;
234227
235
- katom->event_code = BASE_JD_EVENT_JOB_CANCELLED;
228
+ kbase_sync_fence_in_info_get(katom, &info);
236229
237
- /* We should cause the dependent jobs in the bag to be failed,
238
- * to do this we schedule the work queue to complete this job
230
+ dev_warn(katom->kctx->kbdev->dev,
231
+ "Unexpected status for fence %s of ctx:%d_%d atom:%d",
232
+ info.name, katom->kctx->tgid, katom->kctx->id,
233
+ kbase_jd_atom_id(katom->kctx, katom));
234
+ }
235
+
236
+ /* If fence is signaled with an error, then the FENCE_WAIT softjob is
237
+ * considered to be failed.
239238 */
240
- INIT_WORK(&katom->work, kbase_sync_fence_wait_worker);
241
- queue_work(katom->kctx->jctx.job_done_wq, &katom->work);
242239 }
243240
244
- return 1; /* completion to be done later by callback/worker */
241
+ if (unlikely(err)) {
242
+ /* We should cause the dependent jobs in the bag to be failed. */
243
+ katom->event_code = BASE_JD_EVENT_JOB_CANCELLED;
244
+
245
+ /* The completion for FENCE_WAIT softjob can be done right away. */
246
+ return 0;
247
+ }
248
+
249
+ /* Callback was successfully installed */
250
+ katom->dma_fence.fence_cb_added = true;
251
+
252
+ /* Completion to be done later by callback/worker */
253
+ return 1;
245254 }
246255
247256 void kbase_sync_fence_in_cancel_wait(struct kbase_jd_atom *katom)
248257 {
249
- if (!kbase_fence_free_callbacks(katom)) {
250
- /* The wait wasn't cancelled -
251
- * leave the cleanup for kbase_fence_wait_callback
252
- */
253
- return;
254
- }
258
+ lockdep_assert_held(&katom->kctx->jctx.lock);
255259
256
- /* Take responsibility of completion */
257
- kbase_fence_dep_count_set(katom, -1);
260
+ if (katom->dma_fence.fence_cb_added) {
261
+ if (!dma_fence_remove_callback(katom->dma_fence.fence_in,
262
+ &katom->dma_fence.fence_cb)) {
263
+ /* The callback is already removed so leave the cleanup
264
+ * for kbase_fence_wait_callback.
265
+ */
266
+ return;
267
+ }
268
+ } else {
269
+ struct kbase_sync_fence_info info;
270
+
271
+ kbase_sync_fence_in_info_get(katom, &info);
272
+ dev_warn(katom->kctx->kbdev->dev,
273
+ "Callback was not added earlier for fence %s of ctx:%d_%d atom:%d",
274
+ info.name, katom->kctx->tgid, katom->kctx->id,
275
+ kbase_jd_atom_id(katom->kctx, katom));
276
+ }
258277
259278 /* Wait was cancelled - zap the atoms */
260279 katom->event_code = BASE_JD_EVENT_JOB_CANCELLED;
....@@ -262,7 +281,7 @@
262281 kbasep_remove_waiting_soft_job(katom);
263282 kbase_finish_soft_job(katom);
264283
265
- if (jd_done_nolock(katom, NULL))
284
+ if (kbase_jd_done_nolock(katom, true))
266285 kbase_js_sched_all(katom->kctx->kbdev);
267286 }
268287
....@@ -273,8 +292,29 @@
273292
274293 void kbase_sync_fence_in_remove(struct kbase_jd_atom *katom)
275294 {
276
- kbase_fence_free_callbacks(katom);
295
+ lockdep_assert_held(&katom->kctx->jctx.lock);
296
+
297
+ if (katom->dma_fence.fence_cb_added) {
298
+ bool removed = dma_fence_remove_callback(katom->dma_fence.fence_in,
299
+ &katom->dma_fence.fence_cb);
300
+
301
+ /* Here it is expected that the callback should have already been removed
302
+ * previously either by kbase_sync_fence_in_cancel_wait() or when the fence
303
+ * was signaled and kbase_sync_fence_wait_worker() was called.
304
+ */
305
+ if (removed) {
306
+ struct kbase_sync_fence_info info;
307
+
308
+ kbase_sync_fence_in_info_get(katom, &info);
309
+ dev_warn(katom->kctx->kbdev->dev,
310
+ "Callback was not removed earlier for fence %s of ctx:%d_%d atom:%d",
311
+ info.name, katom->kctx->tgid, katom->kctx->id,
312
+ kbase_jd_atom_id(katom->kctx, katom));
313
+ }
314
+ }
315
+
277316 kbase_fence_in_remove(katom);
317
+ katom->dma_fence.fence_cb_added = false;
278318 }
279319 #endif /* !MALI_USE_CSF */
280320
....@@ -288,7 +328,7 @@
288328 {
289329 info->fence = fence;
290330
291
- /* translate into CONFIG_SYNC status:
331
+ /* Translate into the following status, with support for error handling:
292332 * < 0 : error
293333 * 0 : active
294334 * 1 : signaled
....@@ -309,10 +349,7 @@
309349 info->status = 0; /* still active (unsignaled) */
310350 }
311351
312
-#if (KERNEL_VERSION(4, 8, 0) > LINUX_VERSION_CODE)
313
- scnprintf(info->name, sizeof(info->name), "%u#%u",
314
- fence->context, fence->seqno);
315
-#elif (KERNEL_VERSION(5, 1, 0) > LINUX_VERSION_CODE)
352
+#if (KERNEL_VERSION(5, 1, 0) > LINUX_VERSION_CODE)
316353 scnprintf(info->name, sizeof(info->name), "%llu#%u",
317354 fence->context, fence->seqno);
318355 #else