[PATCH v2] media: s5p_cec: release IRQ before deleting the adapter

From: Myeonghun Pak

Date: Mon Oct 19 2026 - 19:09:30 EST


cec_unregister_adapter() can free cec->adap while a queued IRQ thread
still reports transmit or receive events through it. The managed IRQ
remains registered until devres cleanup, which also unmaps the registers
before releasing the IRQ.

Use request_threaded_irq() and free_irq() to release the IRQ before
unregistering the adapter. Request it after the register mapping and
adapter initialization, and free it on adapter registration failure.

Fixes: 1bcbf6f4b6b0 ("[media] cec: s5p-cec: Add s5p-cec driver")
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, W=1.
No hardware runtime testing.

Changes in v2:
- Use request_threaded_irq() and free_irq() instead of the managed IRQ
API, as suggested by Marek Szyprowski.
- Preserve notifier teardown before releasing the IRQ in remove.

Based on mainline 0fcb05b72344f40806cbe810de8872f1698bf053.

drivers/media/cec/platform/s5p/s5p_cec.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/media/cec/platform/s5p/s5p_cec.c b/drivers/media/cec/platform/s5p/s5p_cec.c
index 4a92d3230f661e5f33137eaf81418d5fa529f812..9ce37f2c9ea87b2d385c7eea86bdcd7bf9d642f6 100644
--- a/drivers/media/cec/platform/s5p/s5p_cec.c
+++ b/drivers/media/cec/platform/s5p/s5p_cec.c
@@ -199,11 +199,6 @@ static int s5p_cec_probe(struct platform_device *pdev)
if (cec->irq < 0)
return cec->irq;

- ret = devm_request_threaded_irq(dev, cec->irq, s5p_cec_irq_handler,
- s5p_cec_irq_handler_thread, 0, pdev->name, cec);
- if (ret)
- return ret;
-
cec->clk = devm_clk_get(dev, "hdmicec");
if (IS_ERR(cec->clk))
return PTR_ERR(cec->clk);
@@ -231,16 +226,24 @@ static int s5p_cec_probe(struct platform_device *pdev)
goto err_delete_adapter;
}

- ret = cec_register_adapter(cec->adap, &pdev->dev);
+ ret = request_threaded_irq(cec->irq, s5p_cec_irq_handler,
+ s5p_cec_irq_handler_thread, 0, pdev->name, cec);
if (ret)
goto err_notifier;

+ ret = cec_register_adapter(cec->adap, &pdev->dev);
+ if (ret)
+ goto err_free_irq;
+
platform_set_drvdata(pdev, cec);
pm_runtime_enable(dev);

dev_dbg(dev, "successfully probed\n");
return 0;

+err_free_irq:
+ free_irq(cec->irq, cec);
+
err_notifier:
cec_notifier_cec_adap_unregister(cec->notifier, cec->adap);

@@ -254,6 +257,7 @@ static void s5p_cec_remove(struct platform_device *pdev)
struct s5p_cec_dev *cec = platform_get_drvdata(pdev);

cec_notifier_cec_adap_unregister(cec->notifier, cec->adap);
+ free_irq(cec->irq, cec);
cec_unregister_adapter(cec->adap);
pm_runtime_disable(&pdev->dev);
}