It's not permissible to look at plane->state from interrupt context,
since doing that would need the irq handler to acquire the
plane->mutex lock.

The other problem is that if we pipeline updates using the new
nonblocking atomic helpers new state gets commit before the irq
handler fires, resulting in a lost event.

Fix both issues by caching the necessary values in vop_win, protected
by dev->event_lock.

Cc: Tomeu Vizoso <tomeu.vizoso at collabora.com>
Cc: Mark yao <mark.yao at rock-chips.com>
Tested-by: Tomeu Vizoso <tomeu.vizoso at collabora.com>
Reviewed-by: Tomeu Vizoso <tomeu.vizoso at collabora.com>
Signed-off-by: Daniel Vetter <daniel.vetter at intel.com>
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 957a6b4917c8..94eaeec29b6b 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -98,7 +98,9 @@ struct vop_win {
        const struct vop_win_data *data;
        struct vop *vop;

-       struct vop_plane_state state;
+       /* protected by dev->event_lock */
+       bool enable;
+       dma_addr_t yrgb_mst;
 };

 struct vop {
@@ -112,6 +114,8 @@ struct vop {
        bool vsync_work_pending;
        struct completion dsp_hold_completion;
        struct completion wait_update_complete;
+
+       /* protected by dev->event_lock */
        struct drm_pending_vblank_event *event;

        const struct vop_data *data;
@@ -652,6 +656,11 @@ static void vop_plane_atomic_disable(struct drm_plane 
*plane,
        if (!old_state->crtc)
                return;

+       spin_lock_irq(&plane->dev->event_lock);
+       vop_win->enable = false;
+       vop_win->yrgb_mst = 0;
+       spin_unlock_irq(&plane->dev->event_lock);
+
        spin_lock(&vop->reg_lock);

        VOP_WIN_SET(vop, win, enable, 0);
@@ -686,7 +695,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
        /*
         * can't update plane when vop is disabled.
         */
-       if (!crtc)
+       if (WARN_ON(!crtc))
                return;

        if (WARN_ON(!vop->is_enabled))
@@ -715,6 +724,11 @@ static void vop_plane_atomic_update(struct drm_plane 
*plane,
        offset += (src->y1 >> 16) * fb->pitches[0];
        vop_plane_state->yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0];

+       spin_lock_irq(&plane->dev->event_lock);
+       vop_win->enable = true;
+       vop_win->yrgb_mst = vop_plane_state->yrgb_mst;
+       spin_unlock_irq(&plane->dev->event_lock);
+
        spin_lock(&vop->reg_lock);

        VOP_WIN_SET(vop, win, format, vop_plane_state->format);
@@ -1074,16 +1088,14 @@ static const struct drm_crtc_funcs vop_crtc_funcs = {

 static bool vop_win_pending_is_complete(struct vop_win *vop_win)
 {
-       struct drm_plane *plane = &vop_win->base;
-       struct vop_plane_state *state = to_vop_plane_state(plane->state);
        dma_addr_t yrgb_mst;

-       if (!state->enable)
+       if (!vop_win->enable)
                return VOP_WIN_GET(vop_win->vop, vop_win->data, enable) == 0;

        yrgb_mst = VOP_WIN_GET_YRGBADDR(vop_win->vop, vop_win->data);

-       return yrgb_mst == state->yrgb_mst;
+       return yrgb_mst == vop_win->yrgb_mst;
 }

 static void vop_handle_vblank(struct vop *vop)
-- 
2.8.1

Reply via email to