diff options
author | Adrian Salido <salidoa@google.com> | 2023-03-23 20:00:31 -0700 |
---|---|---|
committer | TreeHugger Robot <treehugger-gerrit@google.com> | 2023-03-29 05:38:47 +0000 |
commit | d8489ee7e1f513aac18694effe0b969f0a0bd60e (patch) | |
tree | 81f929169de6fdf5c1566a2fa9d59ce3706ab00b | |
parent | 0e3483072e06933dbc2266112d739bf36b324e67 (diff) | |
download | display-d8489ee7e1f513aac18694effe0b969f0a0bd60e.tar.gz |
drm: samsung: move commit work to crtc state
The private object is global for all devices so it's possible that
commits on different crtc could cause previous private objects to be
removed and cause use-after-free issues.
To avoid this, move commit work to happen within crtc. Since we are
already using per crtc/decon worker, it won't be possible to get ahead
in this case.
Bug: 263674548
Test: perform empty atomic commits after non-blocking one on crtc
Change-Id: Ie648a2e7069290cd3168ed2d847b97e176f8a2ee
Signed-off-by: Adrian Salido <salidoa@google.com>
-rw-r--r-- | samsung/exynos_drm_drv.c | 28 | ||||
-rw-r--r-- | samsung/exynos_drm_drv.h | 5 |
2 files changed, 11 insertions, 22 deletions
diff --git a/samsung/exynos_drm_drv.c b/samsung/exynos_drm_drv.c index 5405fe7..f28fb15 100644 --- a/samsung/exynos_drm_drv.c +++ b/samsung/exynos_drm_drv.c @@ -515,10 +515,11 @@ static void commit_tail(struct drm_atomic_state *old_state) static void commit_kthread_work(struct kthread_work *work) { - struct exynos_drm_priv_state *exynos_priv_state = - container_of(work, struct exynos_drm_priv_state, commit_work); - struct drm_atomic_state *old_state = exynos_priv_state->old_state; + struct exynos_drm_crtc_state *old_exynos_crtc_state = + container_of(work, struct exynos_drm_crtc_state, commit_work); + struct drm_atomic_state *old_state = old_exynos_crtc_state->base.state; + BUG_ON(!old_state); commit_tail(old_state); } @@ -530,8 +531,7 @@ static void commit_work(struct work_struct *work) commit_tail(old_state); } -static void exynos_atomic_queue_work(struct drm_atomic_state *old_state, bool nonblock, - struct kthread_work *work) +static void exynos_atomic_queue_work(struct drm_atomic_state *old_state) { struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; @@ -544,10 +544,10 @@ static void exynos_atomic_queue_work(struct drm_atomic_state *old_state, bool no * TODO: can work be split per display? */ for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) { - struct exynos_drm_crtc *exynos_crtc = - container_of(crtc, struct exynos_drm_crtc, base); - struct decon_device *decon = exynos_crtc->ctx; + struct decon_device *decon = crtc_to_decon(crtc); + struct kthread_work *work = &to_exynos_crtc_state(old_crtc_state)->commit_work; + kthread_init_work(work, commit_kthread_work); kthread_queue_work(&decon->worker, work); return; @@ -560,7 +560,6 @@ static void exynos_atomic_queue_work(struct drm_atomic_state *old_state, bool no int exynos_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state, bool nonblock) { - struct exynos_drm_priv_state *exynos_priv_state; struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; int i, ret; @@ -590,15 +589,6 @@ int exynos_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state, if (ret) goto err; - exynos_priv_state = exynos_drm_get_priv_state(state); - if (IS_ERR(exynos_priv_state)) { - ret = PTR_ERR(exynos_priv_state); - goto err; - } - - kthread_init_work(&exynos_priv_state->commit_work, commit_kthread_work); - exynos_priv_state->old_state = state; - ret = drm_atomic_helper_prepare_planes(dev, state); if (ret) goto err; @@ -639,7 +629,7 @@ int exynos_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state, if (!nonblock) commit_tail(state); else - exynos_atomic_queue_work(state, nonblock, &exynos_priv_state->commit_work); + exynos_atomic_queue_work(state); err: DPU_ATRACE_END("exynos_atomic_commit"); diff --git a/samsung/exynos_drm_drv.h b/samsung/exynos_drm_drv.h index 88ea0b8..5e03ef9 100644 --- a/samsung/exynos_drm_drv.h +++ b/samsung/exynos_drm_drv.h @@ -278,6 +278,8 @@ struct exynos_drm_crtc_state { struct drm_rect partial_region; struct drm_property_blob *partial; bool needs_reconfigure; + + struct kthread_work commit_work; }; static inline struct exynos_drm_crtc_state * @@ -336,9 +338,6 @@ struct exynos_drm_pending_histogram_event { struct exynos_drm_priv_state { struct drm_private_state base; - struct drm_atomic_state *old_state; - struct kthread_work commit_work; - unsigned int available_win_mask; }; |