drm/rockchip: vop: add vop enable/disable mutex lock
authorFinley Xiao <finley.xiao@rock-chips.com>
Tue, 9 May 2017 13:31:31 +0000 (21:31 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Thu, 11 May 2017 06:47:09 +0000 (14:47 +0800)
It may disable vop_crtc when waiting for line flag, in this case,
we would not get line flag any more. So the lock should be added
to prevent rockchip_wait_line_flag() from vop_crtc_disable();

Change-Id: I312fd46e64006bf69e3c57f54513230b90866e21
Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
drivers/gpu/drm/rockchip/rockchip_drm_vop.c

index 096f7aa0666b222057d87d27a839d9fc20635177..3871ca7c17a59ae3c9f3aaa96167d32bf9a315f7 100644 (file)
@@ -194,6 +194,8 @@ struct vop {
        spinlock_t reg_lock;
        /* lock vop irq reg */
        spinlock_t irq_lock;
+       /* mutex vop enable and disable */
+       struct mutex vop_lock;
 
        unsigned int irq;
 
@@ -844,6 +846,7 @@ static void vop_crtc_disable(struct drm_crtc *crtc)
 {
        struct vop *vop = to_vop(crtc);
 
+       mutex_lock(&vop->vop_lock);
        drm_crtc_vblank_off(crtc);
 
        /*
@@ -882,6 +885,7 @@ static void vop_crtc_disable(struct drm_crtc *crtc)
        clk_disable_unprepare(vop->dclk);
        clk_disable_unprepare(vop->aclk);
        clk_disable_unprepare(vop->hclk);
+       mutex_unlock(&vop->vop_lock);
 }
 
 static void vop_plane_destroy(struct drm_plane *plane)
@@ -1505,6 +1509,7 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
        u16 vact_end = vact_st + vdisplay;
        uint32_t val;
 
+       mutex_lock(&vop->vop_lock);
        vop_initial(crtc);
 
        val = BIT(DCLK_INVERT);
@@ -1619,6 +1624,7 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
 
        enable_irq(vop->irq);
        drm_crtc_vblank_on(crtc);
+       mutex_unlock(&vop->vop_lock);
 }
 
 static int vop_zpos_cmp(const void *a, const void *b)
@@ -2401,15 +2407,22 @@ int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
 {
        struct vop *vop = to_vop(crtc);
        unsigned long jiffies_left;
+       int ret = 0;
 
        if (!crtc || !vop->is_enabled)
                return -ENODEV;
 
-       if (line_num > crtc->mode.vtotal || mstimeout <= 0)
-               return -EINVAL;
+       mutex_lock(&vop->vop_lock);
+
+       if (line_num > crtc->mode.vtotal || mstimeout <= 0) {
+               ret = -EINVAL;
+               goto out;
+       }
 
-       if (vop_line_flag_irq_is_enabled(vop))
-               return -EBUSY;
+       if (vop_line_flag_irq_is_enabled(vop)) {
+               ret = -EBUSY;
+               goto out;
+       }
 
        reinit_completion(&vop->line_flag_completion);
        vop_line_flag_irq_enable(vop, line_num);
@@ -2420,10 +2433,14 @@ int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
 
        if (jiffies_left == 0) {
                dev_err(vop->dev, "Timeout waiting for IRQ\n");
-               return -ETIMEDOUT;
+               ret = -ETIMEDOUT;
+               goto out;
        }
 
-       return 0;
+out:
+       mutex_unlock(&vop->vop_lock);
+
+       return ret;
 }
 EXPORT_SYMBOL(rockchip_drm_wait_line_flag);
 
@@ -2499,6 +2516,7 @@ static int vop_bind(struct device *dev, struct device *master, void *data)
 
        spin_lock_init(&vop->reg_lock);
        spin_lock_init(&vop->irq_lock);
+       mutex_init(&vop->vop_lock);
 
        mutex_init(&vop->vsync_mutex);