Add mutex to protect crtc enable and disable routines. The
tilcdc_crtc_disable() function waits for frame done interrupt, the
internal data will get out of sync, should another enable arrive while
waiting for the interrupt.

Signed-off-by: Jyri Sarha <jsarha at ti.com>
---
 drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c 
b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
index f9e3da9..ac0a63e 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
@@ -31,6 +31,7 @@ struct tilcdc_crtc {
        const struct tilcdc_panel_info *info;
        struct drm_pending_vblank_event *event;
        bool enabled;
+       struct mutex enable_lock;
        wait_queue_head_t frame_done_wq;
        bool frame_done;
        spinlock_t irq_lock;
@@ -153,8 +154,10 @@ static void tilcdc_crtc_enable(struct drm_crtc *crtc)
        struct drm_device *dev = crtc->dev;
        struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);

+       mutex_lock(&tilcdc_crtc->enable_lock);
+
        if (tilcdc_crtc->enabled)
-               return;
+               goto out;

        pm_runtime_get_sync(dev->dev);

@@ -169,6 +172,8 @@ static void tilcdc_crtc_enable(struct drm_crtc *crtc)
        drm_crtc_vblank_on(crtc);

        tilcdc_crtc->enabled = true;
+out:
+       mutex_unlock(&tilcdc_crtc->enable_lock);
 }

 void tilcdc_crtc_disable(struct drm_crtc *crtc)
@@ -177,8 +182,10 @@ void tilcdc_crtc_disable(struct drm_crtc *crtc)
        struct drm_device *dev = crtc->dev;
        struct tilcdc_drm_private *priv = dev->dev_private;

+       mutex_lock(&tilcdc_crtc->enable_lock);
+
        if (!tilcdc_crtc->enabled)
-               return;
+               goto out;

        tilcdc_crtc->frame_done = false;
        tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE);
@@ -218,6 +225,8 @@ void tilcdc_crtc_disable(struct drm_crtc *crtc)
        tilcdc_crtc->last_vblank = ktime_set(0, 0);

        tilcdc_crtc->enabled = false;
+out:
+       mutex_unlock(&tilcdc_crtc->enable_lock);
 }

 static bool tilcdc_crtc_is_on(struct drm_crtc *crtc)
@@ -819,6 +828,8 @@ struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev)
        drm_flip_work_init(&tilcdc_crtc->unref_work,
                        "unref", unref_worker);

+       mutex_init(&tilcdc_crtc->enable_lock);
+
        spin_lock_init(&tilcdc_crtc->irq_lock);
        INIT_WORK(&tilcdc_crtc->recover_work, tilcdc_crtc_recover_work);

-- 
1.9.1

Reply via email to