[PATCH 3/3] ASoC: mediatek: mt8196: Keep the AFE IRQ within its resource lifetime

From: Myeonghun Pak

Date: Sun Oct 11 2026 - 18:25:48 EST


The managed AFE IRQ is requested before the regmap is allocated. The
handler can therefore run before its regmap exists, and devres releases
the regmap before joining the IRQ. The remove callback also suspends the
AFE and disables its clocks before devres releases the IRQ.

Request the IRQ after initializing the regmap and before enabling MCU
IRQ routing. A failed request then takes the existing runtime PM unwind
without enabling that routing. Release the IRQ at the start of removal
before the explicit clock shutdown, using the IRQ number saved at probe.
The regmap's managed lifetime also encloses the IRQ on probe errors.

This issue was found by static analysis.

Fixes: 57513aabfe5b ("ASoC: mediatek: mt8196: add platform driver")
Assisted-by: LLM
Co-developed-by: Ijae Kim <ae878000@xxxxxxxxx>
Signed-off-by: Ijae Kim <ae878000@xxxxxxxxx>
Signed-off-by: Myeonghun Pak <mhun512@xxxxxxxxx>
---
Compile-tested with Clang 22.1.2, W=1 (arm64).

sound/soc/mediatek/mt8196/mt8196-afe-common.h | 1 +
sound/soc/mediatek/mt8196/mt8196-afe-pcm.c | 18 ++++++++++++------
2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/sound/soc/mediatek/mt8196/mt8196-afe-common.h b/sound/soc/mediatek/mt8196/mt8196-afe-common.h
index 4951a6f32abb..ce5d586721db 100644
--- a/sound/soc/mediatek/mt8196/mt8196-afe-common.h
+++ b/sound/soc/mediatek/mt8196/mt8196-afe-common.h
@@ -186,6 +186,7 @@ struct clk;
struct mtk_base_afe;

struct mt8196_afe_private {
+ int irq_id;
struct clk **clk;
/* dai */
void *dai_priv[MT8196_DAI_NUM];
diff --git a/sound/soc/mediatek/mt8196/mt8196-afe-pcm.c b/sound/soc/mediatek/mt8196/mt8196-afe-pcm.c
index a1ae8322d8b6..39d9103bd5e7 100644
--- a/sound/soc/mediatek/mt8196/mt8196-afe-pcm.c
+++ b/sound/soc/mediatek/mt8196/mt8196-afe-pcm.c
@@ -2393,12 +2393,7 @@ static int mt8196_afe_pcm_dev_probe(struct platform_device *pdev)
irq_id = platform_get_irq(pdev, 0);
if (irq_id < 0)
return dev_err_probe(dev, irq_id, "no irq found");
-
- ret = devm_request_irq(dev, irq_id, mt8196_afe_irq_handler,
- IRQF_TRIGGER_NONE,
- "Afe_ISR_Handle", afe);
- if (ret)
- return dev_err_probe(dev, ret, "could not request_irq for Afe_ISR_Handle\n");
+ afe_priv->irq_id = irq_id;

/* init sub_dais */
INIT_LIST_HEAD(&afe->sub_dais);
@@ -2453,6 +2448,14 @@ static int mt8196_afe_pcm_dev_probe(struct platform_device *pdev)
goto err_pm_put;
}

+ ret = devm_request_irq(dev, irq_id, mt8196_afe_irq_handler,
+ IRQF_TRIGGER_NONE,
+ "Afe_ISR_Handle", afe);
+ if (ret) {
+ dev_err_probe(dev, ret, "could not request_irq for Afe_ISR_Handle\n");
+ goto err_pm_put;
+ }
+
regmap_read(afe->regmap, AFE_IRQ_MCU_EN, &tmp_reg);
regmap_write(afe->regmap, AFE_IRQ_MCU_EN, 0xffffffff);
regmap_read(afe->regmap, AFE_IRQ_MCU_EN, &tmp_reg);
@@ -2482,8 +2485,11 @@ err_pm_put:
static void mt8196_afe_pcm_dev_remove(struct platform_device *pdev)
{
struct mtk_base_afe *afe = platform_get_drvdata(pdev);
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
struct device *dev = &pdev->dev;

+ devm_free_irq(dev, afe_priv->irq_id, afe);
+
if (!pm_runtime_status_suspended(dev))
mt8196_afe_runtime_suspend(dev);