mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/3] drm/mediatek: Fixes: Stale pointer usage and device leak
@ 2025-09-24 10:37 AngeloGioacchino Del Regno
  2025-09-24 10:37 ` [PATCH 1/3] drm/mediatek: mtk_dp: Fix hdmi codec and phy driver unregistration AngeloGioacchino Del Regno
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: AngeloGioacchino Del Regno @ 2025-09-24 10:37 UTC (permalink / raw)
  To: chunkuang.hu
  Cc: p.zabel, airlied, simona, matthias.bgg,
	angelogioacchino.delregno, dmitry.osipenko, granquet,
	rex-bc.chen, ck.hu, amergnat, djkurtz, littlecvr, bibby.hsieh,
	dri-devel, linux-mediatek, linux-kernel, linux-arm-kernel,
	kernel

A while ago I've found some issues in drm/mediatek and fixed those
but then forgot to send all of the fixes as I was progressing on more.

For whatever reason, I couldn't continue with more fixes and eventually
forgot to send what I had.
Recent series reminded me about those, which we're carrying in the
Collabora MediaTek integration kernel since .. forever, and are tested
on all of the MTK boards that we have in the lab, including MT8173,
MT8183, MT8192, MT8195, MT8188, MT8186 Chromebooks and Genio boards.

The mtk_dp fix was sent months ago, but got ignored - it's included
in this series again anyway.

AngeloGioacchino Del Regno (3):
  drm/mediatek: mtk_dp: Fix hdmi codec and phy driver unregistration
  drm/mediatek: mtk_disp_ovl: Enable/disable interrupt on bind/unbind
  drm/mediatek: mtk_disp_rdma: Enable/disable interrupt on bind/unbind

 drivers/gpu/drm/mediatek/mtk_disp_ovl.c  | 20 +++++++++-----
 drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 34 ++++++++++++++----------
 drivers/gpu/drm/mediatek/mtk_dp.c        | 30 ++++++++++++++++++---
 3 files changed, 59 insertions(+), 25 deletions(-)

-- 
2.51.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/3] drm/mediatek: mtk_dp: Fix hdmi codec and phy driver unregistration
  2025-09-24 10:37 [PATCH 0/3] drm/mediatek: Fixes: Stale pointer usage and device leak AngeloGioacchino Del Regno
@ 2025-09-24 10:37 ` AngeloGioacchino Del Regno
  2025-09-25  1:09   ` Dmitry Baryshkov
  2025-09-24 10:37 ` [PATCH 2/3] drm/mediatek: mtk_disp_ovl: Enable/disable interrupt on bind/unbind AngeloGioacchino Del Regno
  2025-09-24 10:37 ` [PATCH 3/3] drm/mediatek: mtk_disp_rdma: " AngeloGioacchino Del Regno
  2 siblings, 1 reply; 11+ messages in thread
From: AngeloGioacchino Del Regno @ 2025-09-24 10:37 UTC (permalink / raw)
  To: chunkuang.hu
  Cc: p.zabel, airlied, simona, matthias.bgg,
	angelogioacchino.delregno, dmitry.osipenko, granquet,
	rex-bc.chen, ck.hu, amergnat, djkurtz, littlecvr, bibby.hsieh,
	dri-devel, linux-mediatek, linux-kernel, linux-arm-kernel,
	kernel

During probe, this driver is registering two platform devices: one
for the HDMI Codec driver and one for the DisplayPort PHY driver.

In the probe function, none of the error cases are unregistering
any of the two platform devices and this may cause registration
of multiple instances of those in case this driver returns one or
more probe deferral(s) in the "wrong" spots.

In order to fix this, add devm actions to unregister those and
remove the manual calls to platform_device_unregister in the
mtk_dp_remove() function, as those would otherwise be redundant.

Fixes: e71a8ebbe086 ("drm/mediatek: dp: Audio support for MT8195")
Fixes: caf2ae486742 ("drm/mediatek: dp: Add support for embedded DisplayPort aux-bus")
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
 drivers/gpu/drm/mediatek/mtk_dp.c | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c
index bef6eeb30d3e..9b374b8d079e 100644
--- a/drivers/gpu/drm/mediatek/mtk_dp.c
+++ b/drivers/gpu/drm/mediatek/mtk_dp.c
@@ -2650,6 +2650,13 @@ static const struct hdmi_codec_ops mtk_dp_audio_codec_ops = {
 	.hook_plugged_cb = mtk_dp_audio_hook_plugged_cb,
 };
 
+static void mtk_dp_unregister_pdevs(void *data)
+{
+	struct platform_device *ext_pdev = data;
+
+	platform_device_unregister(ext_pdev);
+}
+
 static int mtk_dp_register_audio_driver(struct device *dev)
 {
 	struct mtk_dp *mtk_dp = dev_get_drvdata(dev);
@@ -2660,18 +2667,29 @@ static int mtk_dp_register_audio_driver(struct device *dev)
 		.data = mtk_dp,
 		.no_capture_mute = 1,
 	};
+	int ret;
 
 	mtk_dp->audio_pdev = platform_device_register_data(dev,
 							   HDMI_CODEC_DRV_NAME,
 							   PLATFORM_DEVID_AUTO,
 							   &codec_data,
 							   sizeof(codec_data));
-	return PTR_ERR_OR_ZERO(mtk_dp->audio_pdev);
+	if (IS_ERR(mtk_dp->audio_pdev))
+		return PTR_ERR(mtk_dp->audio_pdev);
+
+	ret = devm_add_action_or_reset(dev, mtk_dp_unregister_pdevs, mtk_dp->phy_dev);
+	if (ret) {
+		platform_device_unregister(mtk_dp->audio_pdev);
+		return dev_err_probe(dev, ret,
+				     "Failed to add codec unregister devm action");
+	}
+	return 0;
 }
 
 static int mtk_dp_register_phy(struct mtk_dp *mtk_dp)
 {
 	struct device *dev = mtk_dp->dev;
+	int ret;
 
 	mtk_dp->phy_dev = platform_device_register_data(dev, "mediatek-dp-phy",
 							PLATFORM_DEVID_AUTO,
@@ -2681,6 +2699,13 @@ static int mtk_dp_register_phy(struct mtk_dp *mtk_dp)
 		return dev_err_probe(dev, PTR_ERR(mtk_dp->phy_dev),
 				     "Failed to create device mediatek-dp-phy\n");
 
+	ret = devm_add_action_or_reset(dev, mtk_dp_unregister_pdevs, mtk_dp->phy_dev);
+	if (ret) {
+		platform_device_unregister(mtk_dp->phy_dev);
+		return dev_err_probe(dev, ret,
+				     "Failed to add phy unregister devm action");
+	}
+
 	mtk_dp_get_calibration_data(mtk_dp);
 
 	mtk_dp->phy = devm_phy_get(&mtk_dp->phy_dev->dev, "dp");
@@ -2850,9 +2875,6 @@ static void mtk_dp_remove(struct platform_device *pdev)
 	pm_runtime_disable(&pdev->dev);
 	if (mtk_dp->data->bridge_type != DRM_MODE_CONNECTOR_eDP)
 		timer_delete_sync(&mtk_dp->debounce_timer);
-	platform_device_unregister(mtk_dp->phy_dev);
-	if (mtk_dp->audio_pdev)
-		platform_device_unregister(mtk_dp->audio_pdev);
 }
 
 #ifdef CONFIG_PM_SLEEP
-- 
2.51.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 2/3] drm/mediatek: mtk_disp_ovl: Enable/disable interrupt on bind/unbind
  2025-09-24 10:37 [PATCH 0/3] drm/mediatek: Fixes: Stale pointer usage and device leak AngeloGioacchino Del Regno
  2025-09-24 10:37 ` [PATCH 1/3] drm/mediatek: mtk_dp: Fix hdmi codec and phy driver unregistration AngeloGioacchino Del Regno
@ 2025-09-24 10:37 ` AngeloGioacchino Del Regno
  2025-10-28  9:55   ` CK Hu (胡俊光)
  2025-09-24 10:37 ` [PATCH 3/3] drm/mediatek: mtk_disp_rdma: " AngeloGioacchino Del Regno
  2 siblings, 1 reply; 11+ messages in thread
From: AngeloGioacchino Del Regno @ 2025-09-24 10:37 UTC (permalink / raw)
  To: chunkuang.hu
  Cc: p.zabel, airlied, simona, matthias.bgg,
	angelogioacchino.delregno, dmitry.osipenko, granquet,
	rex-bc.chen, ck.hu, amergnat, djkurtz, littlecvr, bibby.hsieh,
	dri-devel, linux-mediatek, linux-kernel, linux-arm-kernel,
	kernel

The OVL driver is installing an ISR in the probe function but, if
the component is not bound yet, the interrupt handler may call the
vblank_cb ahead of time (while probing other drivers) or too late
(while removing other drivers), possibly accessing memory that it
should not try to access by reusing stale pointers.

In order to fix this, add a new `irq` member to struct mtk_disp_ovl
and then set the NOAUTOEN flag to the irq before installing the ISR
to manually call enable_irq() and disable_irq() in the bind and
unbind callbacks respectively.

Fixes: 119f5173628a ("drm/mediatek: Add DRM Driver for Mediatek SoC MT8173.")
Link: https://lore.kernel.org/r/20250402083628.20111-5-angelogioacchino.delregno@collabora.com
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
 drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index e0236353d499..8e20b45411fc 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -161,6 +161,7 @@ struct mtk_disp_ovl {
 	struct drm_crtc			*crtc;
 	struct clk			*clk;
 	void __iomem			*regs;
+	int				irq;
 	struct cmdq_client_reg		cmdq_reg;
 	const struct mtk_disp_ovl_data	*data;
 	void				(*vblank_cb)(void *data);
@@ -594,12 +595,18 @@ void mtk_ovl_bgclr_in_off(struct device *dev)
 static int mtk_disp_ovl_bind(struct device *dev, struct device *master,
 			     void *data)
 {
+	struct mtk_disp_ovl *priv = dev_get_drvdata(dev);
+
+	enable_irq(priv->irq);
 	return 0;
 }
 
 static void mtk_disp_ovl_unbind(struct device *dev, struct device *master,
 				void *data)
 {
+	struct mtk_disp_ovl *priv = dev_get_drvdata(dev);
+
+	disable_irq(priv->irq);
 }
 
 static const struct component_ops mtk_disp_ovl_component_ops = {
@@ -611,16 +618,15 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct mtk_disp_ovl *priv;
-	int irq;
 	int ret;
 
 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
-		return irq;
+	priv->irq = platform_get_irq(pdev, 0);
+	if (priv->irq < 0)
+		return priv->irq;
 
 	priv->clk = devm_clk_get(dev, NULL);
 	if (IS_ERR(priv->clk))
@@ -640,10 +646,10 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
 	priv->data = of_device_get_match_data(dev);
 	platform_set_drvdata(pdev, priv);
 
-	ret = devm_request_irq(dev, irq, mtk_disp_ovl_irq_handler,
-			       IRQF_TRIGGER_NONE, dev_name(dev), priv);
+	ret = devm_request_irq(dev, priv->irq, mtk_disp_ovl_irq_handler,
+			       IRQF_NO_AUTOEN, dev_name(dev), priv);
 	if (ret < 0)
-		return dev_err_probe(dev, ret, "Failed to request irq %d\n", irq);
+		return dev_err_probe(dev, ret, "Failed to request irq %d\n", priv->irq);
 
 	pm_runtime_enable(dev);
 
-- 
2.51.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 3/3] drm/mediatek: mtk_disp_rdma: Enable/disable interrupt on bind/unbind
  2025-09-24 10:37 [PATCH 0/3] drm/mediatek: Fixes: Stale pointer usage and device leak AngeloGioacchino Del Regno
  2025-09-24 10:37 ` [PATCH 1/3] drm/mediatek: mtk_dp: Fix hdmi codec and phy driver unregistration AngeloGioacchino Del Regno
  2025-09-24 10:37 ` [PATCH 2/3] drm/mediatek: mtk_disp_ovl: Enable/disable interrupt on bind/unbind AngeloGioacchino Del Regno
@ 2025-09-24 10:37 ` AngeloGioacchino Del Regno
  2025-10-28  9:49   ` CK Hu (胡俊光)
  2 siblings, 1 reply; 11+ messages in thread
From: AngeloGioacchino Del Regno @ 2025-09-24 10:37 UTC (permalink / raw)
  To: chunkuang.hu
  Cc: p.zabel, airlied, simona, matthias.bgg,
	angelogioacchino.delregno, dmitry.osipenko, granquet,
	rex-bc.chen, ck.hu, amergnat, djkurtz, littlecvr, bibby.hsieh,
	dri-devel, linux-mediatek, linux-kernel, linux-arm-kernel,
	kernel

The RDMA driver is installing an ISR in the probe function but, if
the component is not bound yet, the interrupt handler may call the
vblank_cb ahead of time (while probing other drivers) or too late
(while removing other drivers), possibly accessing memory that it
should not try to access by reusing stale pointers.

In order to fix this, like done in the OVL driver, add a new `irq`
member to struct mtk_disp_ovl and then set the NOAUTOEN flag to
the irq before installing the ISR to manually disable and clear
the hwirqs with register writes, and enable_irq() and disable_irq()
in the bind and unbind callbacks respectively.

Fixes: 119f5173628a ("drm/mediatek: Add DRM Driver for Mediatek SoC MT8173.")
Link: https://lore.kernel.org/r/20250402083628.20111-6-angelogioacchino.delregno@collabora.com
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
 drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 34 ++++++++++++++----------
 1 file changed, 20 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
index c9d41d75e7f2..9fd9bb1ee544 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
@@ -81,6 +81,7 @@ struct mtk_disp_rdma_data {
 struct mtk_disp_rdma {
 	struct clk			*clk;
 	void __iomem			*regs;
+	int				irq;
 	struct cmdq_client_reg		cmdq_reg;
 	const struct mtk_disp_rdma_data	*data;
 	void				(*vblank_cb)(void *data);
@@ -295,13 +296,23 @@ void mtk_rdma_layer_config(struct device *dev, unsigned int idx,
 static int mtk_disp_rdma_bind(struct device *dev, struct device *master,
 			      void *data)
 {
-	return 0;
+	struct mtk_disp_rdma *priv = dev_get_drvdata(dev);
+
+	/* Disable and clear pending interrupts */
+	writel(0x0, priv->regs + DISP_REG_RDMA_INT_ENABLE);
+	writel(0x0, priv->regs + DISP_REG_RDMA_INT_STATUS);
+
+	enable_irq(priv->irq);
 
+	return 0;
 }
 
 static void mtk_disp_rdma_unbind(struct device *dev, struct device *master,
 				 void *data)
 {
+	struct mtk_disp_rdma *priv = dev_get_drvdata(dev);
+
+	disable_irq(priv->irq);
 }
 
 static const struct component_ops mtk_disp_rdma_component_ops = {
@@ -313,16 +324,15 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct mtk_disp_rdma *priv;
-	int irq;
 	int ret;
 
 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
-		return irq;
+	priv->irq = platform_get_irq(pdev, 0);
+	if (priv->irq < 0)
+		return priv->irq;
 
 	priv->clk = devm_clk_get(dev, NULL);
 	if (IS_ERR(priv->clk))
@@ -345,21 +355,17 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev)
 	if (ret && (ret != -EINVAL))
 		return dev_err_probe(dev, ret, "Failed to get rdma fifo size\n");
 
-	/* Disable and clear pending interrupts */
-	writel(0x0, priv->regs + DISP_REG_RDMA_INT_ENABLE);
-	writel(0x0, priv->regs + DISP_REG_RDMA_INT_STATUS);
-
-	ret = devm_request_irq(dev, irq, mtk_disp_rdma_irq_handler,
-			       IRQF_TRIGGER_NONE, dev_name(dev), priv);
-	if (ret < 0)
-		return dev_err_probe(dev, ret, "Failed to request irq %d\n", irq);
-
 	priv->data = of_device_get_match_data(dev);
 
 	platform_set_drvdata(pdev, priv);
 
 	pm_runtime_enable(dev);
 
+	ret = devm_request_irq(dev, priv->irq, mtk_disp_rdma_irq_handler,
+			       IRQF_NO_AUTOEN, dev_name(dev), priv);
+	if (ret < 0)
+		return dev_err_probe(dev, ret, "Failed to request irq %d\n", priv->irq);
+
 	ret = component_add(dev, &mtk_disp_rdma_component_ops);
 	if (ret) {
 		pm_runtime_disable(dev);
-- 
2.51.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/3] drm/mediatek: mtk_dp: Fix hdmi codec and phy driver unregistration
  2025-09-24 10:37 ` [PATCH 1/3] drm/mediatek: mtk_dp: Fix hdmi codec and phy driver unregistration AngeloGioacchino Del Regno
@ 2025-09-25  1:09   ` Dmitry Baryshkov
  2025-09-25 13:57     ` AngeloGioacchino Del Regno
  0 siblings, 1 reply; 11+ messages in thread
From: Dmitry Baryshkov @ 2025-09-25  1:09 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno
  Cc: chunkuang.hu, p.zabel, airlied, simona, matthias.bgg,
	dmitry.osipenko, granquet, rex-bc.chen, ck.hu, amergnat, djkurtz,
	littlecvr, bibby.hsieh, dri-devel, linux-mediatek, linux-kernel,
	linux-arm-kernel, kernel

On Wed, Sep 24, 2025 at 12:37:06PM +0200, AngeloGioacchino Del Regno wrote:
> During probe, this driver is registering two platform devices: one
> for the HDMI Codec driver and one for the DisplayPort PHY driver.
> 
> In the probe function, none of the error cases are unregistering
> any of the two platform devices and this may cause registration
> of multiple instances of those in case this driver returns one or
> more probe deferral(s) in the "wrong" spots.
> 
> In order to fix this, add devm actions to unregister those and
> remove the manual calls to platform_device_unregister in the
> mtk_dp_remove() function, as those would otherwise be redundant.
> 
> Fixes: e71a8ebbe086 ("drm/mediatek: dp: Audio support for MT8195")
> Fixes: caf2ae486742 ("drm/mediatek: dp: Add support for embedded DisplayPort aux-bus")
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_dp.c | 30 ++++++++++++++++++++++++++----
>  1 file changed, 26 insertions(+), 4 deletions(-)
> 

You can save yourself from all these troubles if you store the
registered device at  connector->hdmi_audio.codec_pdev (see
drm_connector_cleanup()).

And of course, you might use DRM_BRIDGE_OP_DP_AUDIO in order to reduce
code duplication.

-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/3] drm/mediatek: mtk_dp: Fix hdmi codec and phy driver unregistration
  2025-09-25  1:09   ` Dmitry Baryshkov
@ 2025-09-25 13:57     ` AngeloGioacchino Del Regno
  0 siblings, 0 replies; 11+ messages in thread
From: AngeloGioacchino Del Regno @ 2025-09-25 13:57 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: chunkuang.hu, p.zabel, airlied, simona, matthias.bgg,
	dmitry.osipenko, granquet, rex-bc.chen, ck.hu, amergnat, djkurtz,
	littlecvr, bibby.hsieh, dri-devel, linux-mediatek, linux-kernel,
	linux-arm-kernel, kernel

Il 25/09/25 03:09, Dmitry Baryshkov ha scritto:
> On Wed, Sep 24, 2025 at 12:37:06PM +0200, AngeloGioacchino Del Regno wrote:
>> During probe, this driver is registering two platform devices: one
>> for the HDMI Codec driver and one for the DisplayPort PHY driver.
>>
>> In the probe function, none of the error cases are unregistering
>> any of the two platform devices and this may cause registration
>> of multiple instances of those in case this driver returns one or
>> more probe deferral(s) in the "wrong" spots.
>>
>> In order to fix this, add devm actions to unregister those and
>> remove the manual calls to platform_device_unregister in the
>> mtk_dp_remove() function, as those would otherwise be redundant.
>>
>> Fixes: e71a8ebbe086 ("drm/mediatek: dp: Audio support for MT8195")
>> Fixes: caf2ae486742 ("drm/mediatek: dp: Add support for embedded DisplayPort aux-bus")
>> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
>> ---
>>   drivers/gpu/drm/mediatek/mtk_dp.c | 30 ++++++++++++++++++++++++++----
>>   1 file changed, 26 insertions(+), 4 deletions(-)
>>
> 
> You can save yourself from all these troubles if you store the
> registered device at  connector->hdmi_audio.codec_pdev (see
> drm_connector_cleanup()).
> 
> And of course, you might use DRM_BRIDGE_OP_DP_AUDIO in order to reduce
> code duplication.
> 

Fair point. Noted! Thanks! :-D

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 3/3] drm/mediatek: mtk_disp_rdma: Enable/disable interrupt on bind/unbind
  2025-09-24 10:37 ` [PATCH 3/3] drm/mediatek: mtk_disp_rdma: " AngeloGioacchino Del Regno
@ 2025-10-28  9:49   ` CK Hu (胡俊光)
  2025-10-28 15:49     ` AngeloGioacchino Del Regno
  0 siblings, 1 reply; 11+ messages in thread
From: CK Hu (胡俊光) @ 2025-10-28  9:49 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, chunkuang.hu
  Cc: Alexandre Mergnat, simona, dmitry.osipenko, kernel,
	linux-mediatek, dri-devel, linux-kernel, djkurtz, granquet,
	p.zabel, Bibby Hsieh (謝濟遠),
	airlied, linux-arm-kernel, matthias.bgg, littlecvr,
	Rex-BC Chen (陳柏辰)

On Wed, 2025-09-24 at 12:37 +0200, AngeloGioacchino Del Regno wrote:
> External email : Please do not click links or open attachments until you have verified the sender or the content.
> 
> 
> The RDMA driver is installing an ISR in the probe function but, if
> the component is not bound yet, the interrupt handler may call the
> vblank_cb ahead of time (while probing other drivers) or too late
> (while removing other drivers), possibly accessing memory that it
> should not try to access by reusing stale pointers.
> 
> In order to fix this, like done in the OVL driver, add a new `irq`
> member to struct mtk_disp_ovl and then set the NOAUTOEN flag to
> the irq before installing the ISR to manually disable and clear
> the hwirqs with register writes, and enable_irq() and disable_irq()
> in the bind and unbind callbacks respectively.
> 
> Fixes: 119f5173628a ("drm/mediatek: Add DRM Driver for Mediatek SoC MT8173.")
> Link: https://lore.kernel.org/r/20250402083628.20111-6-angelogioacchino.delregno@collabora.com
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 34 ++++++++++++++----------
>  1 file changed, 20 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
> index c9d41d75e7f2..9fd9bb1ee544 100644
> --- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
> @@ -81,6 +81,7 @@ struct mtk_disp_rdma_data {
>  struct mtk_disp_rdma {
>         struct clk                      *clk;
>         void __iomem                    *regs;
> +       int                             irq;
>         struct cmdq_client_reg          cmdq_reg;
>         const struct mtk_disp_rdma_data *data;
>         void                            (*vblank_cb)(void *data);
> @@ -295,13 +296,23 @@ void mtk_rdma_layer_config(struct device *dev, unsigned int idx,
>  static int mtk_disp_rdma_bind(struct device *dev, struct device *master,
>                               void *data)
>  {
> -       return 0;
> +       struct mtk_disp_rdma *priv = dev_get_drvdata(dev);
> +
> +       /* Disable and clear pending interrupts */
> +       writel(0x0, priv->regs + DISP_REG_RDMA_INT_ENABLE);
> +       writel(0x0, priv->regs + DISP_REG_RDMA_INT_STATUS);
> +
> +       enable_irq(priv->irq);
> 
> +       return 0;
>  }
> 
>  static void mtk_disp_rdma_unbind(struct device *dev, struct device *master,
>                                  void *data)
>  {
> +       struct mtk_disp_rdma *priv = dev_get_drvdata(dev);
> +
> +       disable_irq(priv->irq);
>  }
> 
>  static const struct component_ops mtk_disp_rdma_component_ops = {
> @@ -313,16 +324,15 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev)
>  {
>         struct device *dev = &pdev->dev;
>         struct mtk_disp_rdma *priv;
> -       int irq;
>         int ret;
> 
>         priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
>         if (!priv)
>                 return -ENOMEM;
> 
> -       irq = platform_get_irq(pdev, 0);
> -       if (irq < 0)
> -               return irq;
> +       priv->irq = platform_get_irq(pdev, 0);
> +       if (priv->irq < 0)
> +               return priv->irq;
> 
>         priv->clk = devm_clk_get(dev, NULL);
>         if (IS_ERR(priv->clk))
> @@ -345,21 +355,17 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev)
>         if (ret && (ret != -EINVAL))
>                 return dev_err_probe(dev, ret, "Failed to get rdma fifo size\n");
> 
> -       /* Disable and clear pending interrupts */
> -       writel(0x0, priv->regs + DISP_REG_RDMA_INT_ENABLE);
> -       writel(0x0, priv->regs + DISP_REG_RDMA_INT_STATUS);

Pending interrupt is cleared here, and interrupt is disabled here.
So the problem you mention would not happen.

Regards,
CK

> -
> -       ret = devm_request_irq(dev, irq, mtk_disp_rdma_irq_handler,
> -                              IRQF_TRIGGER_NONE, dev_name(dev), priv);
> -       if (ret < 0)
> -               return dev_err_probe(dev, ret, "Failed to request irq %d\n", irq);
> -
>         priv->data = of_device_get_match_data(dev);
> 
>         platform_set_drvdata(pdev, priv);
> 
>         pm_runtime_enable(dev);
> 
> +       ret = devm_request_irq(dev, priv->irq, mtk_disp_rdma_irq_handler,
> +                              IRQF_NO_AUTOEN, dev_name(dev), priv);
> +       if (ret < 0)
> +               return dev_err_probe(dev, ret, "Failed to request irq %d\n", priv->irq);
> +
>         ret = component_add(dev, &mtk_disp_rdma_component_ops);
>         if (ret) {
>                 pm_runtime_disable(dev);
> --
> 2.51.0
> 
> 


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 2/3] drm/mediatek: mtk_disp_ovl: Enable/disable interrupt on bind/unbind
  2025-09-24 10:37 ` [PATCH 2/3] drm/mediatek: mtk_disp_ovl: Enable/disable interrupt on bind/unbind AngeloGioacchino Del Regno
@ 2025-10-28  9:55   ` CK Hu (胡俊光)
  2025-10-28 15:51     ` AngeloGioacchino Del Regno
  0 siblings, 1 reply; 11+ messages in thread
From: CK Hu (胡俊光) @ 2025-10-28  9:55 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, chunkuang.hu
  Cc: Alexandre Mergnat, simona, dmitry.osipenko, kernel,
	linux-mediatek, dri-devel, linux-kernel, djkurtz, granquet,
	p.zabel, Bibby Hsieh (謝濟遠),
	airlied, linux-arm-kernel, matthias.bgg, littlecvr,
	Rex-BC Chen (陳柏辰)

On Wed, 2025-09-24 at 12:37 +0200, AngeloGioacchino Del Regno wrote:
> External email : Please do not click links or open attachments until you have verified the sender or the content.
> 
> 
> The OVL driver is installing an ISR in the probe function but, if
> the component is not bound yet, the interrupt handler may call the
> vblank_cb ahead of time (while probing other drivers) or too late
> (while removing other drivers), possibly accessing memory that it
> should not try to access by reusing stale pointers.
> 
> In order to fix this, add a new `irq` member to struct mtk_disp_ovl
> and then set the NOAUTOEN flag to the irq before installing the ISR
> to manually call enable_irq() and disable_irq() in the bind and
> unbind callbacks respectively.
> 
> Fixes: 119f5173628a ("drm/mediatek: Add DRM Driver for Mediatek SoC MT8173.")
> Link: https://lore.kernel.org/r/20250402083628.20111-5-angelogioacchino.delregno@collabora.com
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 20 +++++++++++++-------
>  1 file changed, 13 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> index e0236353d499..8e20b45411fc 100644
> --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> @@ -161,6 +161,7 @@ struct mtk_disp_ovl {
>         struct drm_crtc                 *crtc;
>         struct clk                      *clk;
>         void __iomem                    *regs;
> +       int                             irq;
>         struct cmdq_client_reg          cmdq_reg;
>         const struct mtk_disp_ovl_data  *data;
>         void                            (*vblank_cb)(void *data);
> @@ -594,12 +595,18 @@ void mtk_ovl_bgclr_in_off(struct device *dev)
>  static int mtk_disp_ovl_bind(struct device *dev, struct device *master,
>                              void *data)
>  {
> +       struct mtk_disp_ovl *priv = dev_get_drvdata(dev);
> +
> +       enable_irq(priv->irq);
>         return 0;
>  }
> 
>  static void mtk_disp_ovl_unbind(struct device *dev, struct device *master,
>                                 void *data)
>  {
> +       struct mtk_disp_ovl *priv = dev_get_drvdata(dev);
> +
> +       disable_irq(priv->irq);
>  }
> 
>  static const struct component_ops mtk_disp_ovl_component_ops = {
> @@ -611,16 +618,15 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
>  {
>         struct device *dev = &pdev->dev;
>         struct mtk_disp_ovl *priv;
> -       int irq;
>         int ret;
> 
>         priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
>         if (!priv)
>                 return -ENOMEM;
> 
> -       irq = platform_get_irq(pdev, 0);
> -       if (irq < 0)
> -               return irq;
> +       priv->irq = platform_get_irq(pdev, 0);
> +       if (priv->irq < 0)
> +               return priv->irq;
> 
>         priv->clk = devm_clk_get(dev, NULL);
>         if (IS_ERR(priv->clk))
> @@ -640,10 +646,10 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
>         priv->data = of_device_get_match_data(dev);
>         platform_set_drvdata(pdev, priv);
> 
> -       ret = devm_request_irq(dev, irq, mtk_disp_ovl_irq_handler,
> -                              IRQF_TRIGGER_NONE, dev_name(dev), priv);
> +       ret = devm_request_irq(dev, priv->irq, mtk_disp_ovl_irq_handler,
> +                              IRQF_NO_AUTOEN, dev_name(dev), priv);

RDMA driver would clear pending interrupt and disable interrupt before request irq.
I would like the hardware would be in idle state when probe.
So OVL should do like RDMA.

Regards,
CK

>         if (ret < 0)
> -               return dev_err_probe(dev, ret, "Failed to request irq %d\n", irq);
> +               return dev_err_probe(dev, ret, "Failed to request irq %d\n", priv->irq);
> 
>         pm_runtime_enable(dev);
> 
> --
> 2.51.0
> 


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 3/3] drm/mediatek: mtk_disp_rdma: Enable/disable interrupt on bind/unbind
  2025-10-28  9:49   ` CK Hu (胡俊光)
@ 2025-10-28 15:49     ` AngeloGioacchino Del Regno
  2025-12-30 15:05       ` Chun-Kuang Hu
  0 siblings, 1 reply; 11+ messages in thread
From: AngeloGioacchino Del Regno @ 2025-10-28 15:49 UTC (permalink / raw)
  To: CK Hu (胡俊光), chunkuang.hu
  Cc: Alexandre Mergnat, simona, dmitry.osipenko, kernel,
	linux-mediatek, dri-devel, linux-kernel, djkurtz, granquet,
	p.zabel, Bibby Hsieh (謝濟遠),
	airlied, linux-arm-kernel, matthias.bgg, littlecvr,
	Rex-BC Chen (陳柏辰)

Il 28/10/25 10:49, CK Hu (胡俊光) ha scritto:
> On Wed, 2025-09-24 at 12:37 +0200, AngeloGioacchino Del Regno wrote:
>> External email : Please do not click links or open attachments until you have verified the sender or the content.
>>
>>
>> The RDMA driver is installing an ISR in the probe function but, if
>> the component is not bound yet, the interrupt handler may call the
>> vblank_cb ahead of time (while probing other drivers) or too late
>> (while removing other drivers), possibly accessing memory that it
>> should not try to access by reusing stale pointers.
>>
>> In order to fix this, like done in the OVL driver, add a new `irq`
>> member to struct mtk_disp_ovl and then set the NOAUTOEN flag to
>> the irq before installing the ISR to manually disable and clear
>> the hwirqs with register writes, and enable_irq() and disable_irq()
>> in the bind and unbind callbacks respectively.
>>
>> Fixes: 119f5173628a ("drm/mediatek: Add DRM Driver for Mediatek SoC MT8173.")
>> Link: https://lore.kernel.org/r/20250402083628.20111-6-angelogioacchino.delregno@collabora.com
>> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
>> ---
>>   drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 34 ++++++++++++++----------
>>   1 file changed, 20 insertions(+), 14 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
>> index c9d41d75e7f2..9fd9bb1ee544 100644
>> --- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
>> +++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
>> @@ -81,6 +81,7 @@ struct mtk_disp_rdma_data {
>>   struct mtk_disp_rdma {
>>          struct clk                      *clk;
>>          void __iomem                    *regs;
>> +       int                             irq;
>>          struct cmdq_client_reg          cmdq_reg;
>>          const struct mtk_disp_rdma_data *data;
>>          void                            (*vblank_cb)(void *data);
>> @@ -295,13 +296,23 @@ void mtk_rdma_layer_config(struct device *dev, unsigned int idx,
>>   static int mtk_disp_rdma_bind(struct device *dev, struct device *master,
>>                                void *data)
>>   {
>> -       return 0;
>> +       struct mtk_disp_rdma *priv = dev_get_drvdata(dev);
>> +
>> +       /* Disable and clear pending interrupts */
>> +       writel(0x0, priv->regs + DISP_REG_RDMA_INT_ENABLE);
>> +       writel(0x0, priv->regs + DISP_REG_RDMA_INT_STATUS);
>> +
>> +       enable_irq(priv->irq);
>>
>> +       return 0;
>>   }
>>
>>   static void mtk_disp_rdma_unbind(struct device *dev, struct device *master,
>>                                   void *data)
>>   {
>> +       struct mtk_disp_rdma *priv = dev_get_drvdata(dev);
>> +
>> +       disable_irq(priv->irq);
>>   }
>>
>>   static const struct component_ops mtk_disp_rdma_component_ops = {
>> @@ -313,16 +324,15 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev)
>>   {
>>          struct device *dev = &pdev->dev;
>>          struct mtk_disp_rdma *priv;
>> -       int irq;
>>          int ret;
>>
>>          priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
>>          if (!priv)
>>                  return -ENOMEM;
>>
>> -       irq = platform_get_irq(pdev, 0);
>> -       if (irq < 0)
>> -               return irq;
>> +       priv->irq = platform_get_irq(pdev, 0);
>> +       if (priv->irq < 0)
>> +               return priv->irq;
>>
>>          priv->clk = devm_clk_get(dev, NULL);
>>          if (IS_ERR(priv->clk))
>> @@ -345,21 +355,17 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev)
>>          if (ret && (ret != -EINVAL))
>>                  return dev_err_probe(dev, ret, "Failed to get rdma fifo size\n");
>>
>> -       /* Disable and clear pending interrupts */
>> -       writel(0x0, priv->regs + DISP_REG_RDMA_INT_ENABLE);
>> -       writel(0x0, priv->regs + DISP_REG_RDMA_INT_STATUS);
> 
> Pending interrupt is cleared here, and interrupt is disabled here.
> So the problem you mention would not happen.
> 

When unbinding the component, the interrupt is not cleared nor disabled.

If there is any pending interrupt while unbinding (or if the HW raises an interrupt
after rdma gets unbound) the ISR will produce a use-after-free issue.

I wrote this after experiencing the issue that I described in the commit message,
didn't just go and casually write code.

I also want to remind you that use-after-free may also be a security concern.

Regards,
Angelo

> Regards,
> CK
> 
>> -
>> -       ret = devm_request_irq(dev, irq, mtk_disp_rdma_irq_handler,
>> -                              IRQF_TRIGGER_NONE, dev_name(dev), priv);
>> -       if (ret < 0)
>> -               return dev_err_probe(dev, ret, "Failed to request irq %d\n", irq);
>> -
>>          priv->data = of_device_get_match_data(dev);
>>
>>          platform_set_drvdata(pdev, priv);
>>
>>          pm_runtime_enable(dev);
>>
>> +       ret = devm_request_irq(dev, priv->irq, mtk_disp_rdma_irq_handler,
>> +                              IRQF_NO_AUTOEN, dev_name(dev), priv);
>> +       if (ret < 0)
>> +               return dev_err_probe(dev, ret, "Failed to request irq %d\n", priv->irq);
>> +
>>          ret = component_add(dev, &mtk_disp_rdma_component_ops);
>>          if (ret) {
>>                  pm_runtime_disable(dev);
>> --
>> 2.51.0
>>
>>
> 



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 2/3] drm/mediatek: mtk_disp_ovl: Enable/disable interrupt on bind/unbind
  2025-10-28  9:55   ` CK Hu (胡俊光)
@ 2025-10-28 15:51     ` AngeloGioacchino Del Regno
  0 siblings, 0 replies; 11+ messages in thread
From: AngeloGioacchino Del Regno @ 2025-10-28 15:51 UTC (permalink / raw)
  To: CK Hu (胡俊光), chunkuang.hu
  Cc: Alexandre Mergnat, simona, dmitry.osipenko, kernel,
	linux-mediatek, dri-devel, linux-kernel, djkurtz, granquet,
	p.zabel, Bibby Hsieh (謝濟遠),
	airlied, linux-arm-kernel, matthias.bgg, littlecvr,
	Rex-BC Chen (陳柏辰)

Il 28/10/25 10:55, CK Hu (胡俊光) ha scritto:
> On Wed, 2025-09-24 at 12:37 +0200, AngeloGioacchino Del Regno wrote:
>> External email : Please do not click links or open attachments until you have verified the sender or the content.
>>
>>
>> The OVL driver is installing an ISR in the probe function but, if
>> the component is not bound yet, the interrupt handler may call the
>> vblank_cb ahead of time (while probing other drivers) or too late
>> (while removing other drivers), possibly accessing memory that it
>> should not try to access by reusing stale pointers.
>>
>> In order to fix this, add a new `irq` member to struct mtk_disp_ovl
>> and then set the NOAUTOEN flag to the irq before installing the ISR
>> to manually call enable_irq() and disable_irq() in the bind and
>> unbind callbacks respectively.
>>
>> Fixes: 119f5173628a ("drm/mediatek: Add DRM Driver for Mediatek SoC MT8173.")
>> Link: https://lore.kernel.org/r/20250402083628.20111-5-angelogioacchino.delregno@collabora.com
>> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
>> ---
>>   drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 20 +++++++++++++-------
>>   1 file changed, 13 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
>> index e0236353d499..8e20b45411fc 100644
>> --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
>> +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
>> @@ -161,6 +161,7 @@ struct mtk_disp_ovl {
>>          struct drm_crtc                 *crtc;
>>          struct clk                      *clk;
>>          void __iomem                    *regs;
>> +       int                             irq;
>>          struct cmdq_client_reg          cmdq_reg;
>>          const struct mtk_disp_ovl_data  *data;
>>          void                            (*vblank_cb)(void *data);
>> @@ -594,12 +595,18 @@ void mtk_ovl_bgclr_in_off(struct device *dev)
>>   static int mtk_disp_ovl_bind(struct device *dev, struct device *master,
>>                               void *data)
>>   {
>> +       struct mtk_disp_ovl *priv = dev_get_drvdata(dev);
>> +
>> +       enable_irq(priv->irq);
>>          return 0;
>>   }
>>
>>   static void mtk_disp_ovl_unbind(struct device *dev, struct device *master,
>>                                  void *data)
>>   {
>> +       struct mtk_disp_ovl *priv = dev_get_drvdata(dev);
>> +
>> +       disable_irq(priv->irq);
>>   }
>>
>>   static const struct component_ops mtk_disp_ovl_component_ops = {
>> @@ -611,16 +618,15 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
>>   {
>>          struct device *dev = &pdev->dev;
>>          struct mtk_disp_ovl *priv;
>> -       int irq;
>>          int ret;
>>
>>          priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
>>          if (!priv)
>>                  return -ENOMEM;
>>
>> -       irq = platform_get_irq(pdev, 0);
>> -       if (irq < 0)
>> -               return irq;
>> +       priv->irq = platform_get_irq(pdev, 0);
>> +       if (priv->irq < 0)
>> +               return priv->irq;
>>
>>          priv->clk = devm_clk_get(dev, NULL);
>>          if (IS_ERR(priv->clk))
>> @@ -640,10 +646,10 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
>>          priv->data = of_device_get_match_data(dev);
>>          platform_set_drvdata(pdev, priv);
>>
>> -       ret = devm_request_irq(dev, irq, mtk_disp_ovl_irq_handler,
>> -                              IRQF_TRIGGER_NONE, dev_name(dev), priv);
>> +       ret = devm_request_irq(dev, priv->irq, mtk_disp_ovl_irq_handler,
>> +                              IRQF_NO_AUTOEN, dev_name(dev), priv);
> 
> RDMA driver would clear pending interrupt and disable interrupt before request irq.
> I would like the hardware would be in idle state when probe.
> So OVL should do like RDMA.
> 

As I commented on RDMA - that won't work. After unbinding components, only the
bind() op will be executed, not probe(), so the interrupt will not be reset in
HW, and while re-binding other components, IRQs will come and produce a kernel
panic (in the best scenario, eh!) for use-after-free.

Regards,
Angelo

> Regards,
> CK
> 
>>          if (ret < 0)
>> -               return dev_err_probe(dev, ret, "Failed to request irq %d\n", irq);
>> +               return dev_err_probe(dev, ret, "Failed to request irq %d\n", priv->irq);
>>
>>          pm_runtime_enable(dev);
>>
>> --
>> 2.51.0
>>
> 



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 3/3] drm/mediatek: mtk_disp_rdma: Enable/disable interrupt on bind/unbind
  2025-10-28 15:49     ` AngeloGioacchino Del Regno
@ 2025-12-30 15:05       ` Chun-Kuang Hu
  0 siblings, 0 replies; 11+ messages in thread
From: Chun-Kuang Hu @ 2025-12-30 15:05 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno
  Cc: CK Hu (胡俊光),
	chunkuang.hu, Alexandre Mergnat, simona, dmitry.osipenko, kernel,
	linux-mediatek, dri-devel, linux-kernel, djkurtz, granquet,
	p.zabel, Bibby Hsieh (謝濟遠),
	airlied, linux-arm-kernel, matthias.bgg, littlecvr,
	Rex-BC Chen (陳柏辰)

AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> 於
2025年10月28日週二 下午3:49寫道:
>
> Il 28/10/25 10:49, CK Hu (胡俊光) ha scritto:
> > On Wed, 2025-09-24 at 12:37 +0200, AngeloGioacchino Del Regno wrote:
> >> External email : Please do not click links or open attachments until you have verified the sender or the content.
> >>
> >>
> >> The RDMA driver is installing an ISR in the probe function but, if
> >> the component is not bound yet, the interrupt handler may call the
> >> vblank_cb ahead of time (while probing other drivers) or too late
> >> (while removing other drivers), possibly accessing memory that it
> >> should not try to access by reusing stale pointers.
> >>
> >> In order to fix this, like done in the OVL driver, add a new `irq`
> >> member to struct mtk_disp_ovl and then set the NOAUTOEN flag to
> >> the irq before installing the ISR to manually disable and clear
> >> the hwirqs with register writes, and enable_irq() and disable_irq()
> >> in the bind and unbind callbacks respectively.
> >>
> >> Fixes: 119f5173628a ("drm/mediatek: Add DRM Driver for Mediatek SoC MT8173.")
> >> Link: https://lore.kernel.org/r/20250402083628.20111-6-angelogioacchino.delregno@collabora.com
> >> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> >> ---
> >>   drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 34 ++++++++++++++----------
> >>   1 file changed, 20 insertions(+), 14 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
> >> index c9d41d75e7f2..9fd9bb1ee544 100644
> >> --- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
> >> +++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
> >> @@ -81,6 +81,7 @@ struct mtk_disp_rdma_data {
> >>   struct mtk_disp_rdma {
> >>          struct clk                      *clk;
> >>          void __iomem                    *regs;
> >> +       int                             irq;
> >>          struct cmdq_client_reg          cmdq_reg;
> >>          const struct mtk_disp_rdma_data *data;
> >>          void                            (*vblank_cb)(void *data);
> >> @@ -295,13 +296,23 @@ void mtk_rdma_layer_config(struct device *dev, unsigned int idx,
> >>   static int mtk_disp_rdma_bind(struct device *dev, struct device *master,
> >>                                void *data)
> >>   {
> >> -       return 0;
> >> +       struct mtk_disp_rdma *priv = dev_get_drvdata(dev);
> >> +
> >> +       /* Disable and clear pending interrupts */
> >> +       writel(0x0, priv->regs + DISP_REG_RDMA_INT_ENABLE);
> >> +       writel(0x0, priv->regs + DISP_REG_RDMA_INT_STATUS);
> >> +
> >> +       enable_irq(priv->irq);
> >>
> >> +       return 0;
> >>   }
> >>
> >>   static void mtk_disp_rdma_unbind(struct device *dev, struct device *master,
> >>                                   void *data)
> >>   {
> >> +       struct mtk_disp_rdma *priv = dev_get_drvdata(dev);
> >> +
> >> +       disable_irq(priv->irq);
> >>   }
> >>
> >>   static const struct component_ops mtk_disp_rdma_component_ops = {
> >> @@ -313,16 +324,15 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev)
> >>   {
> >>          struct device *dev = &pdev->dev;
> >>          struct mtk_disp_rdma *priv;
> >> -       int irq;
> >>          int ret;
> >>
> >>          priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> >>          if (!priv)
> >>                  return -ENOMEM;
> >>
> >> -       irq = platform_get_irq(pdev, 0);
> >> -       if (irq < 0)
> >> -               return irq;
> >> +       priv->irq = platform_get_irq(pdev, 0);
> >> +       if (priv->irq < 0)
> >> +               return priv->irq;
> >>
> >>          priv->clk = devm_clk_get(dev, NULL);
> >>          if (IS_ERR(priv->clk))
> >> @@ -345,21 +355,17 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev)
> >>          if (ret && (ret != -EINVAL))
> >>                  return dev_err_probe(dev, ret, "Failed to get rdma fifo size\n");
> >>
> >> -       /* Disable and clear pending interrupts */
> >> -       writel(0x0, priv->regs + DISP_REG_RDMA_INT_ENABLE);
> >> -       writel(0x0, priv->regs + DISP_REG_RDMA_INT_STATUS);
> >
> > Pending interrupt is cleared here, and interrupt is disabled here.
> > So the problem you mention would not happen.
> >
>
> When unbinding the component, the interrupt is not cleared nor disabled.
>
> If there is any pending interrupt while unbinding (or if the HW raises an interrupt
> after rdma gets unbound) the ISR will produce a use-after-free issue.

In mtk_drm_kms_deinit(), it call drm_atomic_helper_shutdown() before
component_unbind_all().
I think hardware should be disabled when drm_atomic_helper_shutdown().
If hardware is not disabled, we should find out the reason.
I like a symmetry design. After bind all sub driver, then enable
hardware. disable hardware before unbind sub driver.
This assume that hardware is disabled when boot up.
If the hardware is enabled in bootloader stage, the tricky way is to
disable interrupt before request irq in probe.

Regards,
Chun-Kuang.

>
> I wrote this after experiencing the issue that I described in the commit message,
> didn't just go and casually write code.
>
> I also want to remind you that use-after-free may also be a security concern.
>
> Regards,
> Angelo
>
> > Regards,
> > CK
> >
> >> -
> >> -       ret = devm_request_irq(dev, irq, mtk_disp_rdma_irq_handler,
> >> -                              IRQF_TRIGGER_NONE, dev_name(dev), priv);
> >> -       if (ret < 0)
> >> -               return dev_err_probe(dev, ret, "Failed to request irq %d\n", irq);
> >> -
> >>          priv->data = of_device_get_match_data(dev);
> >>
> >>          platform_set_drvdata(pdev, priv);
> >>
> >>          pm_runtime_enable(dev);
> >>
> >> +       ret = devm_request_irq(dev, priv->irq, mtk_disp_rdma_irq_handler,
> >> +                              IRQF_NO_AUTOEN, dev_name(dev), priv);
> >> +       if (ret < 0)
> >> +               return dev_err_probe(dev, ret, "Failed to request irq %d\n", priv->irq);
> >> +
> >>          ret = component_add(dev, &mtk_disp_rdma_component_ops);
> >>          if (ret) {
> >>                  pm_runtime_disable(dev);
> >> --
> >> 2.51.0
> >>
> >>
> >
>
>

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2025-12-30 15:05 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-09-24 10:37 [PATCH 0/3] drm/mediatek: Fixes: Stale pointer usage and device leak AngeloGioacchino Del Regno
2025-09-24 10:37 ` [PATCH 1/3] drm/mediatek: mtk_dp: Fix hdmi codec and phy driver unregistration AngeloGioacchino Del Regno
2025-09-25  1:09   ` Dmitry Baryshkov
2025-09-25 13:57     ` AngeloGioacchino Del Regno
2025-09-24 10:37 ` [PATCH 2/3] drm/mediatek: mtk_disp_ovl: Enable/disable interrupt on bind/unbind AngeloGioacchino Del Regno
2025-10-28  9:55   ` CK Hu (胡俊光)
2025-10-28 15:51     ` AngeloGioacchino Del Regno
2025-09-24 10:37 ` [PATCH 3/3] drm/mediatek: mtk_disp_rdma: " AngeloGioacchino Del Regno
2025-10-28  9:49   ` CK Hu (胡俊光)
2025-10-28 15:49     ` AngeloGioacchino Del Regno
2025-12-30 15:05       ` Chun-Kuang Hu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®