From b9a48aa76c72fb4d0990425f82fdeb4fdff2b2b1 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Thu, 19 Oct 2017 13:48:40 +0200 Subject: drm/etnaviv: fix GPU vs sync point race If the FE is restarted before the sync point event is cleared, the GPU might trigger a completion IRQ for the next sync point, corrupting the state of the currently running worker. Signed-off-by: Lucas Stach Reviewed-by: Philipp Zabel Reviewed-by: Christian Gmeiner --- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index 968cbc2be9c4..23b16d9746f9 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -1484,22 +1484,18 @@ out_pm_put: return ret; } -static void etnaviv_process_sync_point(struct etnaviv_gpu *gpu, - struct etnaviv_event *event) -{ - u32 addr = gpu_read(gpu, VIVS_FE_DMA_ADDRESS); - - event->sync_point(gpu, event); - etnaviv_gpu_start_fe(gpu, addr + 2, 2); -} - static void sync_point_worker(struct work_struct *work) { struct etnaviv_gpu *gpu = container_of(work, struct etnaviv_gpu, sync_point_work); + struct etnaviv_event *event = &gpu->event[gpu->sync_point_event]; + u32 addr = gpu_read(gpu, VIVS_FE_DMA_ADDRESS); - etnaviv_process_sync_point(gpu, &gpu->event[gpu->sync_point_event]); + event->sync_point(gpu, event); event_free(gpu, gpu->sync_point_event); + + /* restart FE last to avoid GPU and IRQ racing against this worker */ + etnaviv_gpu_start_fe(gpu, addr + 2, 2); } /* -- cgit v1.2.1