diff options
author | Lucas Stach <l.stach@pengutronix.de> | 2017-10-19 14:48:40 +0300 |
---|---|---|
committer | Lucas Stach <l.stach@pengutronix.de> | 2018-01-02 19:00:53 +0300 |
commit | b9a48aa76c72fb4d0990425f82fdeb4fdff2b2b1 (patch) | |
tree | e3ed5c14ed2f81a3f5b5c6d7f34e0a3dbc5f9ba0 /drivers/gpu/drm/etnaviv | |
parent | 49b82c389d2a40eaef1355aaa35868b367aec9d1 (diff) | |
download | linux-b9a48aa76c72fb4d0990425f82fdeb4fdff2b2b1.tar.xz |
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 <l.stach@pengutronix.de>
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: Christian Gmeiner <christian.gmeiner@gmail.com>
Diffstat (limited to 'drivers/gpu/drm/etnaviv')
-rw-r--r-- | drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 16 |
1 files changed, 6 insertions, 10 deletions
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); } /* |