From 1fcbd6d000def5bd7c6099b2a3e74bc30b7cd752 Mon Sep 17 00:00:00 2001 From: Ao Xu Date: Mon, 12 Apr 2021 15:38:45 +0900 Subject: [PATCH] amlogic: drm: don't call irq in crtc init stage 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 Signed-off-by: Sihyun, Park Signed-off-by: Seung-Woo Kim --- drivers/amlogic/drm/meson_crtc.c | 13 ++----------- drivers/amlogic/drm/meson_crtc.h | 4 +--- drivers/amlogic/drm/meson_drv.c | 15 ++------------- drivers/amlogic/drm/meson_vpu.c | 35 +++++++---------------------------- 4 files changed, 12 insertions(+), 55 deletions(-) diff --git a/drivers/amlogic/drm/meson_crtc.c b/drivers/amlogic/drm/meson_crtc.c index 011f871..05e79bd 100644 --- a/drivers/amlogic/drm/meson_crtc.c +++ b/drivers/amlogic/drm/meson_crtc.c @@ -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) diff --git a/drivers/amlogic/drm/meson_crtc.h b/drivers/amlogic/drm/meson_crtc.h index d97dd7b..7370177 100644 --- a/drivers/amlogic/drm/meson_crtc.h +++ b/drivers/amlogic/drm/meson_crtc.h @@ -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; diff --git a/drivers/amlogic/drm/meson_drv.c b/drivers/amlogic/drm/meson_drv.c index bfa6893..f94d45b 100644 --- a/drivers/amlogic/drm/meson_drv.c +++ b/drivers/amlogic/drm/meson_drv.c @@ -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; diff --git a/drivers/amlogic/drm/meson_vpu.c b/drivers/amlogic/drm/meson_vpu.c index ca025a8..83caebe 100644 --- a/drivers/amlogic/drm/meson_vpu.c +++ b/drivers/amlogic/drm/meson_vpu.c @@ -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)); -- 2.7.4