From nobody Sun Sep 22 05:35:48 2024 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C814CC43217 for ; Mon, 21 Mar 2022 07:23:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344887AbiCUHZU (ORCPT ); Mon, 21 Mar 2022 03:25:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57486 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344851AbiCUHYv (ORCPT ); Mon, 21 Mar 2022 03:24:51 -0400 Received: from mailgw01.mediatek.com (unknown [60.244.123.138]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CDE6017A9B for ; Mon, 21 Mar 2022 00:23:25 -0700 (PDT) X-UUID: 8da1b630f8e2458086593c2a2f1c7418-20220321 X-UUID: 8da1b630f8e2458086593c2a2f1c7418-20220321 Received: from mtkcas11.mediatek.inc [(172.21.101.40)] by mailgw01.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1124122286; Mon, 21 Mar 2022 15:23:22 +0800 Received: from mtkcas10.mediatek.inc (172.21.101.39) by mtkmbs07n1.mediatek.inc (172.21.101.16) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 21 Mar 2022 15:23:21 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkcas10.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 21 Mar 2022 15:23:20 +0800 From: Rex-BC Chen To: CC: , , , , , , , , , , , , , Rex-BC Chen Subject: [PATCH V2] drm/mediatek: Add vblank register/unregister callback functions Date: Mon, 21 Mar 2022 15:23:20 +0800 Message-ID: <20220321072320.15019-1-rex-bc.chen@mediatek.com> X-Mailer: git-send-email 2.18.0 MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" We encountered a kernel panic issue that callback data will be NULL when it's using in ovl irq handler. There is a timing issue between mtk_disp_ovl_irq_handler() and mtk_ovl_disable_vblank(). To resolve this issue, we use the flow to register/unregister vblank cb: - Register callback function and callback data when crtc creates. - Unregister callback function and callback data when crtc destroies. With this solution, we can assure callback data will not be NULL when vblank is disable. Fixes: 9b0704988b15 ("drm/mediatek: Register vblank callback function") Signed-off-by: Rex-BC Chen Reviewed-by: jason-jh.lin Reviewed-by: CK Hu ---- V2: 1. Change title to "Add vblank register/unregister callback functions". ---- --- drivers/gpu/drm/mediatek/mtk_disp_drv.h | 16 +++++++----- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 22 ++++++++++++---- drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 20 +++++++++----- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 14 +++++++++- drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 4 +++ drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 29 ++++++++++++++++----- 6 files changed, 80 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/medi= atek/mtk_disp_drv.h index 86c3068894b1..974462831133 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h +++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h @@ -76,9 +76,11 @@ void mtk_ovl_layer_off(struct device *dev, unsigned int = idx, void mtk_ovl_start(struct device *dev); void mtk_ovl_stop(struct device *dev); unsigned int mtk_ovl_supported_rotations(struct device *dev); -void mtk_ovl_enable_vblank(struct device *dev, - void (*vblank_cb)(void *), - void *vblank_cb_data); +void mtk_ovl_register_vblank_cb(struct device *dev, + void (*vblank_cb)(void *), + void *vblank_cb_data); +void mtk_ovl_unregister_vblank_cb(struct device *dev); +void mtk_ovl_enable_vblank(struct device *dev); void mtk_ovl_disable_vblank(struct device *dev); =20 void mtk_rdma_bypass_shadow(struct device *dev); @@ -93,9 +95,11 @@ void mtk_rdma_layer_config(struct device *dev, unsigned = int idx, struct cmdq_pkt *cmdq_pkt); void mtk_rdma_start(struct device *dev); void mtk_rdma_stop(struct device *dev); -void mtk_rdma_enable_vblank(struct device *dev, - void (*vblank_cb)(void *), - void *vblank_cb_data); +void mtk_rdma_register_vblank_cb(struct device *dev, + void (*vblank_cb)(void *), + void *vblank_cb_data); +void mtk_rdma_unregister_vblank_cb(struct device *dev); +void mtk_rdma_enable_vblank(struct device *dev); void mtk_rdma_disable_vblank(struct device *dev); =20 #endif diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/medi= atek/mtk_disp_ovl.c index 2146299e5f52..1fa1bbac9f9c 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -96,14 +96,28 @@ static irqreturn_t mtk_disp_ovl_irq_handler(int irq, vo= id *dev_id) return IRQ_HANDLED; } =20 -void mtk_ovl_enable_vblank(struct device *dev, - void (*vblank_cb)(void *), - void *vblank_cb_data) +void mtk_ovl_register_vblank_cb(struct device *dev, + void (*vblank_cb)(void *), + void *vblank_cb_data) { struct mtk_disp_ovl *ovl =3D dev_get_drvdata(dev); =20 ovl->vblank_cb =3D vblank_cb; ovl->vblank_cb_data =3D vblank_cb_data; +} + +void mtk_ovl_unregister_vblank_cb(struct device *dev) +{ + struct mtk_disp_ovl *ovl =3D dev_get_drvdata(dev); + + ovl->vblank_cb =3D NULL; + ovl->vblank_cb_data =3D NULL; +} + +void mtk_ovl_enable_vblank(struct device *dev) +{ + struct mtk_disp_ovl *ovl =3D dev_get_drvdata(dev); + writel(0x0, ovl->regs + DISP_REG_OVL_INTSTA); writel_relaxed(OVL_FME_CPL_INT, ovl->regs + DISP_REG_OVL_INTEN); } @@ -112,8 +126,6 @@ void mtk_ovl_disable_vblank(struct device *dev) { struct mtk_disp_ovl *ovl =3D dev_get_drvdata(dev); =20 - ovl->vblank_cb =3D NULL; - ovl->vblank_cb_data =3D NULL; writel_relaxed(0x0, ovl->regs + DISP_REG_OVL_INTEN); } =20 diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/med= iatek/mtk_disp_rdma.c index d41a3970b944..943780fc7bf6 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c @@ -94,24 +94,32 @@ static void rdma_update_bits(struct device *dev, unsign= ed int reg, writel(tmp, rdma->regs + reg); } =20 -void mtk_rdma_enable_vblank(struct device *dev, - void (*vblank_cb)(void *), - void *vblank_cb_data) +void mtk_rdma_register_vblank_cb(struct device *dev, + void (*vblank_cb)(void *), + void *vblank_cb_data) { struct mtk_disp_rdma *rdma =3D dev_get_drvdata(dev); =20 rdma->vblank_cb =3D vblank_cb; rdma->vblank_cb_data =3D vblank_cb_data; - rdma_update_bits(dev, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT, - RDMA_FRAME_END_INT); } =20 -void mtk_rdma_disable_vblank(struct device *dev) +void mtk_rdma_unregister_vblank_cb(struct device *dev) { struct mtk_disp_rdma *rdma =3D dev_get_drvdata(dev); =20 rdma->vblank_cb =3D NULL; rdma->vblank_cb_data =3D NULL; +} + +void mtk_rdma_enable_vblank(struct device *dev) +{ + rdma_update_bits(dev, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT, + RDMA_FRAME_END_INT); +} + +void mtk_rdma_disable_vblank(struct device *dev) +{ rdma_update_bits(dev, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT, 0); } =20 diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/medi= atek/mtk_drm_crtc.c index d661edf7e0fe..e42a9bfa0ecb 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -152,6 +152,7 @@ static void mtk_drm_cmdq_pkt_destroy(struct cmdq_pkt *p= kt) static void mtk_drm_crtc_destroy(struct drm_crtc *crtc) { struct mtk_drm_crtc *mtk_crtc =3D to_mtk_crtc(crtc); + int i; =20 mtk_mutex_put(mtk_crtc->mutex); #if IS_REACHABLE(CONFIG_MTK_CMDQ) @@ -162,6 +163,14 @@ static void mtk_drm_crtc_destroy(struct drm_crtc *crtc) mtk_crtc->cmdq_client.chan =3D NULL; } #endif + + for (i =3D 0; i < mtk_crtc->ddp_comp_nr; i++) { + struct mtk_ddp_comp *comp; + + comp =3D mtk_crtc->ddp_comp[i]; + mtk_ddp_comp_unregister_vblank_cb(comp); + } + drm_crtc_cleanup(crtc); } =20 @@ -616,7 +625,7 @@ static int mtk_drm_crtc_enable_vblank(struct drm_crtc *= crtc) struct mtk_drm_crtc *mtk_crtc =3D to_mtk_crtc(crtc); struct mtk_ddp_comp *comp =3D mtk_crtc->ddp_comp[0]; =20 - mtk_ddp_comp_enable_vblank(comp, mtk_crtc_ddp_irq, &mtk_crtc->base); + mtk_ddp_comp_enable_vblank(comp); =20 return 0; } @@ -916,6 +925,9 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, if (comp->funcs->ctm_set) has_ctm =3D true; } + + mtk_ddp_comp_register_vblank_cb(comp, mtk_crtc_ddp_irq, + &mtk_crtc->base); } =20 for (i =3D 0; i < mtk_crtc->ddp_comp_nr; i++) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/= mediatek/mtk_drm_ddp_comp.c index b4b682bc1991..028cf76b9531 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c @@ -297,6 +297,8 @@ static const struct mtk_ddp_comp_funcs ddp_ovl =3D { .config =3D mtk_ovl_config, .start =3D mtk_ovl_start, .stop =3D mtk_ovl_stop, + .register_vblank_cb =3D mtk_ovl_register_vblank_cb, + .unregister_vblank_cb =3D mtk_ovl_unregister_vblank_cb, .enable_vblank =3D mtk_ovl_enable_vblank, .disable_vblank =3D mtk_ovl_disable_vblank, .supported_rotations =3D mtk_ovl_supported_rotations, @@ -321,6 +323,8 @@ static const struct mtk_ddp_comp_funcs ddp_rdma =3D { .config =3D mtk_rdma_config, .start =3D mtk_rdma_start, .stop =3D mtk_rdma_stop, + .register_vblank_cb =3D mtk_rdma_register_vblank_cb, + .unregister_vblank_cb =3D mtk_rdma_unregister_vblank_cb, .enable_vblank =3D mtk_rdma_enable_vblank, .disable_vblank =3D mtk_rdma_disable_vblank, .layer_nr =3D mtk_rdma_layer_nr, diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/= mediatek/mtk_drm_ddp_comp.h index 4c6a98662305..b83f24cb045f 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h @@ -48,9 +48,11 @@ struct mtk_ddp_comp_funcs { unsigned int bpc, struct cmdq_pkt *cmdq_pkt); void (*start)(struct device *dev); void (*stop)(struct device *dev); - void (*enable_vblank)(struct device *dev, - void (*vblank_cb)(void *), - void *vblank_cb_data); + void (*register_vblank_cb)(struct device *dev, + void (*vblank_cb)(void *), + void *vblank_cb_data); + void (*unregister_vblank_cb)(struct device *dev); + void (*enable_vblank)(struct device *dev); void (*disable_vblank)(struct device *dev); unsigned int (*supported_rotations)(struct device *dev); unsigned int (*layer_nr)(struct device *dev); @@ -111,12 +113,25 @@ static inline void mtk_ddp_comp_stop(struct mtk_ddp_c= omp *comp) comp->funcs->stop(comp->dev); } =20 -static inline void mtk_ddp_comp_enable_vblank(struct mtk_ddp_comp *comp, - void (*vblank_cb)(void *), - void *vblank_cb_data) +static inline void mtk_ddp_comp_register_vblank_cb(struct mtk_ddp_comp *co= mp, + void (*vblank_cb)(void *), + void *vblank_cb_data) +{ + if (comp->funcs && comp->funcs->register_vblank_cb) + comp->funcs->register_vblank_cb(comp->dev, vblank_cb, + vblank_cb_data); +} + +static inline void mtk_ddp_comp_unregister_vblank_cb(struct mtk_ddp_comp *= comp) +{ + if (comp->funcs && comp->funcs->unregister_vblank_cb) + comp->funcs->unregister_vblank_cb(comp->dev); +} + +static inline void mtk_ddp_comp_enable_vblank(struct mtk_ddp_comp *comp) { if (comp->funcs && comp->funcs->enable_vblank) - comp->funcs->enable_vblank(comp->dev, vblank_cb, vblank_cb_data); + comp->funcs->enable_vblank(comp->dev); } =20 static inline void mtk_ddp_comp_disable_vblank(struct mtk_ddp_comp *comp) --=20 2.18.0