amlogic: drm: don't call irq in crtc init stage 37/259137/1
authorAo Xu <ao.xu@amlogic.com>
Mon, 12 Apr 2021 06:38:45 +0000 (15:38 +0900)
committerSeung-Woo Kim <sw0312.kim@samsung.com>
Tue, 1 Jun 2021 11:17:49 +0000 (20:17 +0900)
vblank_disable_fn and am_meson_vpu_irq exist deadlock.
Disable vblank_disable_fn to avoid spin_lock_irqsave to
resolve the deadlock issue.

Change-Id: I59b454d2c2c0535f2e786e3beb4ca31c124483b0
Signed-off-by: Ao Xu <ao.xu@amlogic.com>
Signed-off-by: Sihyun, Park <shwan.park@samsung.com>
Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
drivers/amlogic/drm/meson_crtc.c
drivers/amlogic/drm/meson_crtc.h
drivers/amlogic/drm/meson_drv.c
drivers/amlogic/drm/meson_vpu.c

index 011f871..05e79bd 100644 (file)
@@ -97,7 +97,6 @@ static bool am_meson_crtc_mode_fixup(struct drm_crtc *crtc,
 
 static void am_meson_crtc_enable(struct drm_crtc *crtc)
 {
-       unsigned long flags;
        char *name;
        enum vmode_e mode;
        struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
@@ -124,16 +123,12 @@ static void am_meson_crtc_enable(struct drm_crtc *crtc)
        update_vout_viu();
        memcpy(&pipeline->mode, adjusted_mode,
                sizeof(struct drm_display_mode));
-       spin_lock_irqsave(&amcrtc->vblank_irq_lock, flags);
-       amcrtc->vblank_enable = 1;
-       spin_unlock_irqrestore(&amcrtc->vblank_irq_lock, flags);
-       enable_irq(amcrtc->vblank_irq);
+       enable_irq(amcrtc->irq);
 }
 
 static void am_meson_crtc_disable(struct drm_crtc *crtc)
 {
        struct am_meson_crtc *amcrtc = to_am_meson_crtc(crtc);
-       unsigned long flags;
 
        DRM_INFO("%s\n", __func__);
        if (crtc->state->event && !crtc->state->active) {
@@ -143,11 +138,7 @@ static void am_meson_crtc_disable(struct drm_crtc *crtc)
                crtc->state->event = NULL;
        }
 
-       spin_lock_irqsave(&amcrtc->vblank_irq_lock, flags);
-       amcrtc->vblank_enable = 0;
-       spin_unlock_irqrestore(&amcrtc->vblank_irq_lock, flags);
-
-       disable_irq(amcrtc->vblank_irq);
+       disable_irq(amcrtc->irq);
 }
 
 static void am_meson_crtc_commit(struct drm_crtc *crtc)
index d97dd7b..7370177 100644 (file)
@@ -46,9 +46,7 @@ struct am_meson_crtc {
 
        struct drm_pending_vblank_event *event;
 
-       unsigned int vblank_irq;
-       spinlock_t vblank_irq_lock;/*atomic*/
-       u32 vblank_enable;
+       unsigned int irq;
 
        struct dentry *crtc_debugfs_dir;
 
index bfa6893..f94d45b 100644 (file)
@@ -95,23 +95,11 @@ EXPORT_SYMBOL(am_meson_unregister_crtc_funcs);
 
 static int am_meson_enable_vblank(struct drm_device *dev, unsigned int crtc)
 {
-       struct meson_drm *priv = dev->dev_private;
-
-       if (crtc >= MESON_MAX_CRTC)
-               return -EBADFD;
-
-       priv->crtc_funcs[crtc]->enable_vblank(priv->crtc);
        return 0;
 }
 
 static void am_meson_disable_vblank(struct drm_device *dev, unsigned int crtc)
 {
-       struct meson_drm *priv = dev->dev_private;
-
-       if (crtc >= MESON_MAX_CRTC)
-               return;
-
-       priv->crtc_funcs[crtc]->disable_vblank(priv->crtc);
 }
 
 static void am_meson_load(struct drm_device *dev)
@@ -271,7 +259,8 @@ static int am_meson_drm_bind(struct device *dev)
        drm->mode_config.funcs = &meson_mode_config_funcs;
        drm->mode_config.allow_fb_modifiers = true;
        /*
-        * irq will init in each crtc, just mark the enable flag here.
+        * enable drm irq mode.
+        * - with irq_enabled = true, we can use the vblank feature.
         */
        drm->irq_enabled = true;
 
index ca025a8..83caebe 100644 (file)
@@ -291,10 +291,10 @@ static int am_meson_crtc_loader_protect(struct drm_crtc *crtc, bool on)
        DRM_INFO("%s  %d\n", __func__, on);
 
        if (on) {
-               enable_irq(amcrtc->vblank_irq);
+               enable_irq(amcrtc->irq);
                drm_crtc_vblank_on(crtc);
        } else {
-               disable_irq(amcrtc->vblank_irq);
+               disable_irq(amcrtc->irq);
                drm_crtc_vblank_off(crtc);
        }
 
@@ -303,24 +303,11 @@ static int am_meson_crtc_loader_protect(struct drm_crtc *crtc, bool on)
 
 static int am_meson_crtc_enable_vblank(struct drm_crtc *crtc)
 {
-       unsigned long flags;
-       struct am_meson_crtc *amcrtc = to_am_meson_crtc(crtc);
-
-       spin_lock_irqsave(&amcrtc->vblank_irq_lock, flags);
-       amcrtc->vblank_enable = true;
-       spin_unlock_irqrestore(&amcrtc->vblank_irq_lock, flags);
-
        return 0;
 }
 
 static void am_meson_crtc_disable_vblank(struct drm_crtc *crtc)
 {
-       unsigned long flags;
-       struct am_meson_crtc *amcrtc = to_am_meson_crtc(crtc);
-
-       spin_lock_irqsave(&amcrtc->vblank_irq_lock, flags);
-       amcrtc->vblank_enable = false;
-       spin_unlock_irqrestore(&amcrtc->vblank_irq_lock, flags);
 }
 
 const struct meson_crtc_funcs meson_private_crtc_funcs = {
@@ -369,15 +356,9 @@ void am_meson_crtc_handle_vsync(struct am_meson_crtc *amcrtc)
 
 void am_meson_crtc_irq(struct meson_drm *priv)
 {
-       unsigned long flags;
        struct am_meson_crtc *amcrtc = to_am_meson_crtc(priv->crtc);
 
-       spin_lock_irqsave(&amcrtc->vblank_irq_lock, flags);
-       if (amcrtc->vblank_enable) {
-               osd_drm_vsync_isr_handler();
-               am_meson_crtc_handle_vsync(amcrtc);
-       }
-       spin_unlock_irqrestore(&amcrtc->vblank_irq_lock, flags);
+       am_meson_crtc_handle_vsync(amcrtc);
 }
 
 static irqreturn_t am_meson_vpu_irq(int irq, void *arg)
@@ -484,17 +465,15 @@ static int am_meson_vpu_bind(struct device *dev,
                dev_err(dev, "cannot find irq for vpu\n");
                return irq;
        }
-       amcrtc->vblank_irq = (unsigned int)irq;
-
-       spin_lock_init(&amcrtc->vblank_irq_lock);
-       amcrtc->vblank_enable = false;
+       amcrtc->irq = (unsigned int)irq;
 
-       ret = devm_request_irq(dev, amcrtc->vblank_irq, am_meson_vpu_irq,
+       ret = devm_request_irq(dev, amcrtc->irq, am_meson_vpu_irq,
                IRQF_SHARED, dev_name(dev), drm_dev);
        if (ret)
                return ret;
 
-       disable_irq(amcrtc->vblank_irq);
+       /* IRQ is initially disabled; it gets enabled in crtc_enable */
+       disable_irq(amcrtc->irq);
 
        INIT_DELAYED_WORK(&osd_dwork, mem_free_work);
        schedule_delayed_work(&osd_dwork, msecs_to_jiffies(60 * 1000));