drm/mediatek: Add spinlock for setting vblank event in atomic_begin
authorJason-JH.Lin <jason-jh.lin@mediatek.com>
Wed, 20 Sep 2023 09:06:58 +0000 (17:06 +0800)
committerChun-Kuang Hu <chunkuang.hu@kernel.org>
Sun, 26 Nov 2023 00:26:07 +0000 (00:26 +0000)
Add spinlock protection to avoid race condition on vblank event
between mtk_drm_crtc_atomic_begin() and mtk_drm_finish_page_flip().

Fixes: 119f5173628a ("drm/mediatek: Add DRM Driver for Mediatek SoC MT8173.")
Signed-off-by: Jason-JH.Lin <jason-jh.lin@mediatek.com>
Suggested-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
Reviewed-by: Fei Shao <fshao@chromium.org>
Tested-by: Fei Shao <fshao@chromium.org>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: CK Hu <ck.hu@mediatek.com>
Link: https://patchwork.kernel.org/project/dri-devel/patch/20230920090658.31181-1-jason-jh.lin@mediatek.com/
Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
drivers/gpu/drm/mediatek/mtk_drm_crtc.c

index c277b9fae950206d818edcbaab963a83b77615d5..0a7d60c191b80f18460886efcbe594b591d85996 100644 (file)
@@ -788,6 +788,7 @@ static void mtk_drm_crtc_atomic_begin(struct drm_crtc *crtc,
                                                                          crtc);
        struct mtk_crtc_state *mtk_crtc_state = to_mtk_crtc_state(crtc_state);
        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
+       unsigned long flags;
 
        if (mtk_crtc->event && mtk_crtc_state->base.event)
                DRM_ERROR("new event while there is still a pending event\n");
@@ -795,7 +796,11 @@ static void mtk_drm_crtc_atomic_begin(struct drm_crtc *crtc,
        if (mtk_crtc_state->base.event) {
                mtk_crtc_state->base.event->pipe = drm_crtc_index(crtc);
                WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
+               spin_lock_irqsave(&crtc->dev->event_lock, flags);
                mtk_crtc->event = mtk_crtc_state->base.event;
+               spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+
                mtk_crtc_state->base.event = NULL;
        }
 }