Skip to content

Commit 7b6f9ec

Browse files
committed
drm/panthor: Fix sync-only jobs
A sync-only job is meant to provide a synchronization point on a queue, so we can't return a NULL fence there, we have to add a signal operation to the command stream which executes after all other previously submitted jobs are done. v2: - Fixed a UAF bug - Added R-bs Fixes: de85488 ("drm/panthor: Add the scheduler logical block") Signed-off-by: Boris Brezillon <[email protected]> Reviewed-by: Liviu Dudau <[email protected]> Reviewed-by: Steven Price <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 1a9a714 commit 7b6f9ec

File tree

2 files changed

+38
-11
lines changed

2 files changed

+38
-11
lines changed

drivers/gpu/drm/panthor/panthor_sched.c

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,16 @@ struct panthor_queue {
458458
/** @seqno: Sequence number of the last initialized fence. */
459459
atomic64_t seqno;
460460

461+
/**
462+
* @last_fence: Fence of the last submitted job.
463+
*
464+
* We return this fence when we get an empty command stream.
465+
* This way, we are guaranteed that all earlier jobs have completed
466+
* when drm_sched_job::s_fence::finished without having to feed
467+
* the CS ring buffer with a dummy job that only signals the fence.
468+
*/
469+
struct dma_fence *last_fence;
470+
461471
/**
462472
* @in_flight_jobs: List containing all in-flight jobs.
463473
*
@@ -829,6 +839,9 @@ static void group_free_queue(struct panthor_group *group, struct panthor_queue *
829839
panthor_kernel_bo_destroy(queue->ringbuf);
830840
panthor_kernel_bo_destroy(queue->iface.mem);
831841

842+
/* Release the last_fence we were holding, if any. */
843+
dma_fence_put(queue->fence_ctx.last_fence);
844+
832845
kfree(queue);
833846
}
834847

@@ -2784,9 +2797,6 @@ static void group_sync_upd_work(struct work_struct *work)
27842797

27852798
spin_lock(&queue->fence_ctx.lock);
27862799
list_for_each_entry_safe(job, job_tmp, &queue->fence_ctx.in_flight_jobs, node) {
2787-
if (!job->call_info.size)
2788-
continue;
2789-
27902800
if (syncobj->seqno < job->done_fence->seqno)
27912801
break;
27922802

@@ -2865,11 +2875,14 @@ queue_run_job(struct drm_sched_job *sched_job)
28652875
static_assert(sizeof(call_instrs) % 64 == 0,
28662876
"call_instrs is not aligned on a cacheline");
28672877

2868-
/* Stream size is zero, nothing to do => return a NULL fence and let
2869-
* drm_sched signal the parent.
2878+
/* Stream size is zero, nothing to do except making sure all previously
2879+
* submitted jobs are done before we signal the
2880+
* drm_sched_job::s_fence::finished fence.
28702881
*/
2871-
if (!job->call_info.size)
2872-
return NULL;
2882+
if (!job->call_info.size) {
2883+
job->done_fence = dma_fence_get(queue->fence_ctx.last_fence);
2884+
return dma_fence_get(job->done_fence);
2885+
}
28732886

28742887
ret = pm_runtime_resume_and_get(ptdev->base.dev);
28752888
if (drm_WARN_ON(&ptdev->base, ret))
@@ -2928,6 +2941,10 @@ queue_run_job(struct drm_sched_job *sched_job)
29282941
}
29292942
}
29302943

2944+
/* Update the last fence. */
2945+
dma_fence_put(queue->fence_ctx.last_fence);
2946+
queue->fence_ctx.last_fence = dma_fence_get(job->done_fence);
2947+
29312948
done_fence = dma_fence_get(job->done_fence);
29322949

29332950
out_unlock:
@@ -3378,10 +3395,15 @@ panthor_job_create(struct panthor_file *pfile,
33783395
goto err_put_job;
33793396
}
33803397

3381-
job->done_fence = kzalloc(sizeof(*job->done_fence), GFP_KERNEL);
3382-
if (!job->done_fence) {
3383-
ret = -ENOMEM;
3384-
goto err_put_job;
3398+
/* Empty command streams don't need a fence, they'll pick the one from
3399+
* the previously submitted job.
3400+
*/
3401+
if (job->call_info.size) {
3402+
job->done_fence = kzalloc(sizeof(*job->done_fence), GFP_KERNEL);
3403+
if (!job->done_fence) {
3404+
ret = -ENOMEM;
3405+
goto err_put_job;
3406+
}
33853407
}
33863408

33873409
ret = drm_sched_job_init(&job->base,

include/uapi/drm/panthor_drm.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,9 @@ struct drm_panthor_queue_submit {
802802
* Must be 64-bit/8-byte aligned (the size of a CS instruction)
803803
*
804804
* Can be zero if stream_addr is zero too.
805+
*
806+
* When the stream size is zero, the queue submit serves as a
807+
* synchronization point.
805808
*/
806809
__u32 stream_size;
807810

@@ -822,6 +825,8 @@ struct drm_panthor_queue_submit {
822825
* ensure the GPU doesn't get garbage when reading the indirect command
823826
* stream buffers. If you want the cache flush to happen
824827
* unconditionally, pass a zero here.
828+
*
829+
* Ignored when stream_size is zero.
825830
*/
826831
__u32 latest_flush;
827832

0 commit comments

Comments
 (0)