The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH v5 0/9] irqchip/imx-irqsteer: Allow building as module
@ 2026-08-21 10:10 Zhipeng.wang_1
  2026-08-21 10:10 ` [PATCH v5 1/9] irqchip/imx-irqsteer: Call chained_irq_exit() on the handler error path Zhipeng.wang_1
                   ` (8 more replies)
  0 siblings, 9 replies; 15+ messages in thread
From: Zhipeng.wang_1 @ 2026-08-21 10:10 UTC (permalink / raw)
  To: Thomas Gleixner, Marc Zyngier, Frank Li
  Cc: Radu Rendec, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Jindong Yue, xuegang.liu, linux-kernel, imx, linux-arm-kernel

From: Zhipeng Wang <zhipeng.wang_1@nxp.com>

Thomas, apologies for the scattered irqsteer patches over the past
weeks. As you asked, this version consolidates everything related to
fixing this into one coherent series: the three separate series/patches
(including Fabio's, which conflicted with mine) are now merged here, the
overlapping runtime-PM work is reconciled, and the patches are split by
concern. No more piecemeal postings.

This series makes the i.MX IRQSTEER driver buildable as a module, along
with the pre-existing bug fixes that become reachable once the driver
can be unbound and reloaded.

What was previously scattered across three series/patches is now one
series:

 - The three patches carrying Fixes: 28528fca4908 ("irqchip/imx-irqsteer:
   Add multi output interrupts support") are now collected here: the
   parent-IRQ-domain leak fix (devm-managed domain), Fabio's IRQ-count
   validation, and the standalone chained_irq_exit() fix that was
   previously sent on its own.
 - Fabio Estevam's IRQ-count validation patch is folded in with his
   authorship preserved; it supersedes the ordering that previously
   validated the count after the domain was created.
 - The clock/runtime-PM rework, the module enablement, and the irqdomain
   helper cleanup are split into separate patches per Thomas' request,
   rather than bundled into one change.

Patch overview:

 1. Call chained_irq_exit() on the handler error path - balances the
    chained IRQ enter/exit on the error path.
 2. Use devm to manage the IRQ domain - devm_irq_domain_instantiate()
    fixes the domain leak on the probe() sanity-check error path.
 3. Validate IRQ count before creating domain (Fabio) - validate before
    allocating so no domain is leaked and no dangling host_data is left.
 4. Dispose of parent IRQ mappings in remove() - only the parent output
    mappings need explicit disposal now that the domain is devres-owned.
 5. Mask all interrupts in probe() - avoid an interrupt storm on reload
    from stale CHANMASK state, without touching registers in remove()
    while runtime-suspended.
 6. Let devres own the clock and runtime PM - devm_clk_get_enabled() +
    devm_pm_runtime_set_active_enabled(). remove() calls
    pm_runtime_resume_and_get() so the devres clock teardown stays
    balanced when the device was runtime-suspended (Frank Li).
 7. Allow building as module - tristate Kconfig + module_platform_driver().
 8. genirq/irqdomain: Add devm_irq_domain_create_linear() - a reusable
    devres helper.
 9. Use devm_irq_domain_create_linear() - switch the driver to the new
    helper.

Changes in v5:
 - Consolidate the three previously-scattered series/patches into one
   series (Thomas Gleixner): the standalone chained_irq_exit() fix and
   Fabio's IRQ-count validation patch are now included here.
 - Fold in Fabio's IRQ-count validation patch with authorship preserved;
   validate the count before creating the domain.
 - remove() calls pm_runtime_resume_and_get() so the devres clock
   teardown does not underflow the clock enable count when the device is
   runtime-suspended (Frank Li).
 - Fabio's "Convert to devm_pm_runtime_enable()" patch
   (https://lore.kernel.org/lkml/20260817190621.335492-1-festevam@gmail.com/)
   is superseded by patch 6, which uses
   devm_pm_runtime_set_active_enabled() (as Frank suggested) and also
   lets devres own the clock; it is credited with Suggested-by.

Changes in v4:
 - New patch: add devm_irq_domain_create_linear() (Frank Li).
 - Use the new devm helper to manage the domain instead of hand-rolling
   an err_domain label; remove() drops irq_domain_remove() (Frank Li).
 - Dispose of the parent mappings only; the child mapping disposal loop
   is removed (Frank Li).
 - Mask interrupts in probe() only; the remove() masking, which could
   touch registers while runtime-suspended, is dropped (Frank Li).

Changes in v3:
 - Split the single v2 patch into separate patches.
 - Add the probe() error-path fix (Sashiko AI).
 - Add CHANMASK masking in probe() (Sashiko AI).
 - Let devres own the clock and runtime PM via devm_clk_get_enabled()
   and devm_pm_runtime_set_active_enabled() (Frank Li).

v4: https://lore.kernel.org/r/20260819090543.585131-1-Zhipeng.wang_1@oss.nxp.com
v3: https://lore.kernel.org/r/20260807072346.1222389-1-Zhipeng.wang_1@oss.nxp.com
v2: https://lore.kernel.org/r/20260728092219.525449-1-Zhipeng.wang_1@oss.nxp.com
v1: https://lore.kernel.org/r/20260724090136.3595894-1-Zhipeng.wang_1@oss.nxp.com
chained_irq_exit() standalone patch:
https://lore.kernel.org/all/20260807072626.1231517-1-Zhipeng.wang_1@oss.nxp.com/

Fabio Estevam (1):
  irqchip/imx-irqsteer: Validate IRQ count before creating domain

Jindong Yue (1):
  irqchip/imx-irqsteer: Allow building as module

Zhipeng Wang (7):
  irqchip/imx-irqsteer: Call chained_irq_exit() on the handler error
    path
  irqchip/imx-irqsteer: Use devm to manage the IRQ domain
  irqchip/imx-irqsteer: Dispose of parent IRQ mappings in remove()
  irqchip/imx-irqsteer: Mask all interrupts in probe()
  irqchip/imx-irqsteer: Let devres own the clock and runtime PM
  genirq/irqdomain: Add devm_irq_domain_create_linear()
  irqchip/imx-irqsteer: Use devm_irq_domain_create_linear()

 drivers/irqchip/Kconfig            |  2 +-
 drivers/irqchip/irq-imx-irqsteer.c | 70 +++++++++++++++++++-----------
 include/linux/irqdomain.h          | 30 +++++++++++++
 3 files changed, 76 insertions(+), 26 deletions(-)


base-commit: bd5f485f3f026225b86573e559af0b7254ef4184
-- 
2.34.1


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

* [PATCH v5 1/9] irqchip/imx-irqsteer: Call chained_irq_exit() on the handler error path
  2026-08-21 10:10 [PATCH v5 0/9] irqchip/imx-irqsteer: Allow building as module Zhipeng.wang_1
@ 2026-08-21 10:10 ` Zhipeng.wang_1
  2026-08-21 14:15   ` Frank Li
  2026-08-21 10:10 ` [PATCH v5 2/9] irqchip/imx-irqsteer: Use devm to manage the IRQ domain Zhipeng.wang_1
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 15+ messages in thread
From: Zhipeng.wang_1 @ 2026-08-21 10:10 UTC (permalink / raw)
  To: Thomas Gleixner, Marc Zyngier, Frank Li
  Cc: Radu Rendec, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Jindong Yue, xuegang.liu, linux-kernel, imx, linux-arm-kernel

From: Zhipeng Wang <zhipeng.wang_1@nxp.com>

A chained handler must pair every chained_irq_enter() with a
chained_irq_exit() before returning, so that the parent interrupt's flow
control is completed (EOI for fasteoi parents, unmask for level-triggered
parents). Skipping it leaves the parent interrupt unacknowledged, blocking
further interrupts multiplexed through that line.

When imx_irqsteer_get_hwirq_base() fails, the handler returned early
without calling chained_irq_exit(). Route the error path through the
existing chained_irq_exit() so the parent interrupt is always completed
before returning.

Fixes: 28528fca4908 ("irqchip/imx-irqsteer: Add multi output interrupts support")
Signed-off-by: Zhipeng Wang <zhipeng.wang_1@nxp.com>
---
 drivers/irqchip/irq-imx-irqsteer.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-imx-irqsteer.c b/drivers/irqchip/irq-imx-irqsteer.c
index 87b07f517be3..1b8d0c8eedb9 100644
--- a/drivers/irqchip/irq-imx-irqsteer.c
+++ b/drivers/irqchip/irq-imx-irqsteer.c
@@ -154,7 +154,7 @@ static void imx_irqsteer_irq_handler(struct irq_desc *desc)
 	if (hwirq < 0) {
 		pr_warn("%s: unable to get hwirq base for irq %d\n",
 			__func__, irq);
-		return;
+		goto out;
 	}
 
 	for (i = 0; i < 2; i++, hwirq += 32) {
@@ -172,6 +172,7 @@ static void imx_irqsteer_irq_handler(struct irq_desc *desc)
 			generic_handle_domain_irq(data->domain, pos + hwirq);
 	}
 
+out:
 	chained_irq_exit(irq_desc_get_chip(desc), desc);
 }
 

base-commit: bd5f485f3f026225b86573e559af0b7254ef4184
-- 
2.34.1


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

* [PATCH v5 2/9] irqchip/imx-irqsteer: Use devm to manage the IRQ domain
  2026-08-21 10:10 [PATCH v5 0/9] irqchip/imx-irqsteer: Allow building as module Zhipeng.wang_1
  2026-08-21 10:10 ` [PATCH v5 1/9] irqchip/imx-irqsteer: Call chained_irq_exit() on the handler error path Zhipeng.wang_1
@ 2026-08-21 10:10 ` Zhipeng.wang_1
  2026-08-21 10:10 ` [PATCH v5 3/9] irqchip/imx-irqsteer: Validate IRQ count before creating domain Zhipeng.wang_1
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Zhipeng.wang_1 @ 2026-08-21 10:10 UTC (permalink / raw)
  To: Thomas Gleixner, Marc Zyngier, Frank Li
  Cc: Radu Rendec, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Jindong Yue, xuegang.liu, linux-kernel, imx, linux-arm-kernel

From: Zhipeng Wang <zhipeng.wang_1@nxp.com>

probe() creates the IRQ domain with irq_domain_create_linear() and only
tears it down on the remove() path. On the probe() error path after the
domain has been created (the fsl,num-irqs sanity check), the single
error label just calls clk_disable_unprepare() and returns, leaking the
freshly created domain. The domain-creation failure path happens to
share the same label correctly only because the domain is NULL there.

Create the domain with devm_irq_domain_instantiate() so it is removed
automatically on unbind and on any probe() failure after it has been
created. This fixes the leak on the sanity-check error path and lets
remove() drop its explicit irq_domain_remove().

Fixes: 28528fca4908 ("irqchip/imx-irqsteer: Add multi output interrupts support")
Signed-off-by: Zhipeng Wang <zhipeng.wang_1@nxp.com>
---
 drivers/irqchip/irq-imx-irqsteer.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/irqchip/irq-imx-irqsteer.c b/drivers/irqchip/irq-imx-irqsteer.c
index 1b8d0c8eedb9..c1df84551efa 100644
--- a/drivers/irqchip/irq-imx-irqsteer.c
+++ b/drivers/irqchip/irq-imx-irqsteer.c
@@ -237,11 +237,18 @@ static int imx_irqsteer_probe(struct platform_device *pdev)
 	if (irqsteer_has_chanctrl(data->devtype_data))
 		writel_relaxed(BIT(data->channel), data->regs + CHANCTRL);
 
-	data->domain = irq_domain_create_linear(dev_fwnode(&pdev->dev), data->reg_num * 32,
-						&imx_irqsteer_domain_ops, data);
-	if (!data->domain) {
+	struct irq_domain_info info = {
+		.fwnode		= dev_fwnode(&pdev->dev),
+		.size		= data->reg_num * 32,
+		.hwirq_max	= data->reg_num * 32,
+		.ops		= &imx_irqsteer_domain_ops,
+		.host_data	= data,
+	};
+
+	data->domain = devm_irq_domain_instantiate(&pdev->dev, &info);
+	if (IS_ERR(data->domain)) {
 		dev_err(&pdev->dev, "failed to create IRQ domain\n");
-		ret = -ENOMEM;
+		ret = PTR_ERR(data->domain);
 		goto out;
 	}
 	irq_domain_set_pm_device(data->domain, &pdev->dev);
@@ -285,8 +292,6 @@ static void imx_irqsteer_remove(struct platform_device *pdev)
 						 NULL, NULL);
 	}
 
-	irq_domain_remove(irqsteer_data->domain);
-
 	clk_disable_unprepare(irqsteer_data->ipg_clk);
 }
 
-- 
2.34.1


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

* [PATCH v5 3/9] irqchip/imx-irqsteer: Validate IRQ count before creating domain
  2026-08-21 10:10 [PATCH v5 0/9] irqchip/imx-irqsteer: Allow building as module Zhipeng.wang_1
  2026-08-21 10:10 ` [PATCH v5 1/9] irqchip/imx-irqsteer: Call chained_irq_exit() on the handler error path Zhipeng.wang_1
  2026-08-21 10:10 ` [PATCH v5 2/9] irqchip/imx-irqsteer: Use devm to manage the IRQ domain Zhipeng.wang_1
@ 2026-08-21 10:10 ` Zhipeng.wang_1
  2026-08-21 14:24   ` Frank Li
  2026-08-21 10:10 ` [PATCH v5 4/9] irqchip/imx-irqsteer: Dispose of parent IRQ mappings in remove() Zhipeng.wang_1
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 15+ messages in thread
From: Zhipeng.wang_1 @ 2026-08-21 10:10 UTC (permalink / raw)
  To: Thomas Gleixner, Marc Zyngier, Frank Li
  Cc: Radu Rendec, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Jindong Yue, xuegang.liu, linux-kernel, imx, linux-arm-kernel

From: Fabio Estevam <festevam@nabladev.com>

The IRQ count is validated after creating the IRQ domain. If it is
invalid, probe returns without removing the domain, leaving its host
data pointing at devm-managed memory that is freed on probe failure.

Validate the count before allocating resources to avoid the leak and
dangling pointer.

Fixes: 28528fca4908 ("irqchip/imx-irqsteer: Add multi output interrupts support")
Signed-off-by: Fabio Estevam <festevam@nabladev.com>
Signed-off-by: Zhipeng Wang <zhipeng.wang_1@nxp.com>
---
 drivers/irqchip/irq-imx-irqsteer.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/irqchip/irq-imx-irqsteer.c b/drivers/irqchip/irq-imx-irqsteer.c
index c1df84551efa..571324de8bd1 100644
--- a/drivers/irqchip/irq-imx-irqsteer.c
+++ b/drivers/irqchip/irq-imx-irqsteer.c
@@ -218,6 +218,8 @@ static int imx_irqsteer_probe(struct platform_device *pdev)
 	 */
 	data->irq_count = DIV_ROUND_UP(irqs_num, 64);
 	data->reg_num = irqs_num / 32;
+	if (!data->irq_count || data->irq_count > CHAN_MAX_OUTPUT_INT)
+		return -EINVAL;
 
 	if (IS_ENABLED(CONFIG_PM)) {
 		data->saved_reg = devm_kzalloc(&pdev->dev,
@@ -253,11 +255,6 @@ static int imx_irqsteer_probe(struct platform_device *pdev)
 	}
 	irq_domain_set_pm_device(data->domain, &pdev->dev);
 
-	if (!data->irq_count || data->irq_count > CHAN_MAX_OUTPUT_INT) {
-		ret = -EINVAL;
-		goto out;
-	}
-
 	for (i = 0; i < data->irq_count; i++) {
 		data->irq[i] = irq_of_parse_and_map(np, i);
 		if (!data->irq[i])
-- 
2.34.1


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

* [PATCH v5 4/9] irqchip/imx-irqsteer: Dispose of parent IRQ mappings in remove()
  2026-08-21 10:10 [PATCH v5 0/9] irqchip/imx-irqsteer: Allow building as module Zhipeng.wang_1
                   ` (2 preceding siblings ...)
  2026-08-21 10:10 ` [PATCH v5 3/9] irqchip/imx-irqsteer: Validate IRQ count before creating domain Zhipeng.wang_1
@ 2026-08-21 10:10 ` Zhipeng.wang_1
  2026-08-21 10:10 ` [PATCH v5 5/9] irqchip/imx-irqsteer: Mask all interrupts in probe() Zhipeng.wang_1
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Zhipeng.wang_1 @ 2026-08-21 10:10 UTC (permalink / raw)
  To: Thomas Gleixner, Marc Zyngier, Frank Li
  Cc: Radu Rendec, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Jindong Yue, xuegang.liu, linux-kernel, imx, linux-arm-kernel

From: Zhipeng Wang <zhipeng.wang_1@nxp.com>

probe() maps the parent output interrupts with irq_of_parse_and_map(),
but remove() only unchains the handlers and never disposes of those
mappings, leaking them on unbind. The child mappings handed out by the
domain are freed by their consumers and, together with the domain, are
now torn down by devres, so remove() only has to dispose of the parent
mappings it created itself.

Dispose of the parent mappings alongside the chained-handler teardown.

Fixes: 0136afa08967 ("irqchip: Add driver for imx-irqsteer controller")
Signed-off-by: Zhipeng Wang <zhipeng.wang_1@nxp.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/irqchip/irq-imx-irqsteer.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/irqchip/irq-imx-irqsteer.c b/drivers/irqchip/irq-imx-irqsteer.c
index 571324de8bd1..071ab1ac1fe9 100644
--- a/drivers/irqchip/irq-imx-irqsteer.c
+++ b/drivers/irqchip/irq-imx-irqsteer.c
@@ -287,6 +287,7 @@ static void imx_irqsteer_remove(struct platform_device *pdev)
 
 		irq_set_chained_handler_and_data(irqsteer_data->irq[i],
 						 NULL, NULL);
+		irq_dispose_mapping(irqsteer_data->irq[i]);
 	}
 
 	clk_disable_unprepare(irqsteer_data->ipg_clk);
-- 
2.34.1


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

* [PATCH v5 5/9] irqchip/imx-irqsteer: Mask all interrupts in probe()
  2026-08-21 10:10 [PATCH v5 0/9] irqchip/imx-irqsteer: Allow building as module Zhipeng.wang_1
                   ` (3 preceding siblings ...)
  2026-08-21 10:10 ` [PATCH v5 4/9] irqchip/imx-irqsteer: Dispose of parent IRQ mappings in remove() Zhipeng.wang_1
@ 2026-08-21 10:10 ` Zhipeng.wang_1
  2026-08-21 10:10 ` [PATCH v5 6/9] irqchip/imx-irqsteer: Let devres own the clock and runtime PM Zhipeng.wang_1
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Zhipeng.wang_1 @ 2026-08-21 10:10 UTC (permalink / raw)
  To: Thomas Gleixner, Marc Zyngier, Frank Li
  Cc: Radu Rendec, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Jindong Yue, xuegang.liu, linux-kernel, imx, linux-arm-kernel

From: Zhipeng Wang <zhipeng.wang_1@nxp.com>

probe() sets up the chained handlers without first masking the input
interrupts. For a built-in driver this happened to be harmless because
CHANMASK resets to all-masked, but once the driver can be unloaded and
reloaded a child interrupt left unmasked at unload time survives in
hardware. On the next probe() the parent interrupts are re-mapped and
unmasked before the new domain is ready, so a still-asserted line
immediately storms the parent with no handler to service it.

Mask all interrupts in probe() before wiring up the chained handlers.
CHANMASK uses inverted polarity (a set bit enables the interrupt), so
masking means writing zero. This mirrors the sibling NXP chained mux
irq-imx-intmux.c, which masks all sources at probe() time.

Masking is only done in probe(), not in remove(): the next probe()
quiesces the hardware before it re-maps and unmasks the parent
interrupts, which is the only window in which a stale line could storm.
Masking in remove() would also mean touching CHANMASK while the device
may already be runtime-suspended with the clock gated.

Signed-off-by: Zhipeng Wang <zhipeng.wang_1@nxp.com>
---
 drivers/irqchip/irq-imx-irqsteer.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/irqchip/irq-imx-irqsteer.c b/drivers/irqchip/irq-imx-irqsteer.c
index 071ab1ac1fe9..b63bf957ab88 100644
--- a/drivers/irqchip/irq-imx-irqsteer.c
+++ b/drivers/irqchip/irq-imx-irqsteer.c
@@ -239,6 +239,14 @@ static int imx_irqsteer_probe(struct platform_device *pdev)
 	if (irqsteer_has_chanctrl(data->devtype_data))
 		writel_relaxed(BIT(data->channel), data->regs + CHANCTRL);
 
+	/*
+	 * Mask all interrupts before wiring up the chained handlers. CHANMASK
+	 * has inverted polarity (a set bit enables the interrupt), so writing
+	 * zero masks the source.
+	 */
+	for (i = 0; i < data->reg_num; i++)
+		writel_relaxed(0, data->regs + CHANMASK(i, data->reg_num));
+
 	struct irq_domain_info info = {
 		.fwnode		= dev_fwnode(&pdev->dev),
 		.size		= data->reg_num * 32,
-- 
2.34.1


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

* [PATCH v5 6/9] irqchip/imx-irqsteer: Let devres own the clock and runtime PM
  2026-08-21 10:10 [PATCH v5 0/9] irqchip/imx-irqsteer: Allow building as module Zhipeng.wang_1
                   ` (4 preceding siblings ...)
  2026-08-21 10:10 ` [PATCH v5 5/9] irqchip/imx-irqsteer: Mask all interrupts in probe() Zhipeng.wang_1
@ 2026-08-21 10:10 ` Zhipeng.wang_1
  2026-08-21 10:10 ` [PATCH v5 7/9] irqchip/imx-irqsteer: Allow building as module Zhipeng.wang_1
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Zhipeng.wang_1 @ 2026-08-21 10:10 UTC (permalink / raw)
  To: Thomas Gleixner, Marc Zyngier, Frank Li
  Cc: Radu Rendec, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Jindong Yue, xuegang.liu, linux-kernel, imx, linux-arm-kernel

From: Zhipeng Wang <zhipeng.wang_1@nxp.com>

In preparation for making the driver unbindable/reloadable, let the
driver core own the clock and runtime PM lifetime so that the probe()
error path and remove() do not have to hand-balance them:

 - acquire the clock with devm_clk_get_enabled() instead of a bare
   devm_clk_get() followed by a manual clk_prepare_enable(), so it is
   prepared/enabled for the device lifetime and released on unbind;
 - keep only clk_enable()/clk_disable() in the runtime PM callbacks,
   since prepare/unprepare is now handled once by devres;
 - enable runtime PM with devm_pm_runtime_set_active_enabled(), which
   marks the device active (matching the enabled clock) and disables
   runtime PM on unbind.

The device may be runtime-suspended at unbind time (autosuspend), in
which case the runtime suspend callback has already dropped the clock
enable count. The devres clk_disable_unprepare() that runs after
remove() would then underflow the enable count. Resume the device in
remove() so the clock is enabled when devres tears it down, keeping the
count balanced.

With the clock and runtime PM owned by devres, remove() and the probe()
error path only have to dispose of the parent IRQ mappings.

Suggested-by: Fabio Estevam <festevam@nabladev.com>
Signed-off-by: Zhipeng Wang <zhipeng.wang_1@nxp.com>
---
 drivers/irqchip/irq-imx-irqsteer.c | 37 +++++++++++++++++++-----------
 1 file changed, 23 insertions(+), 14 deletions(-)

diff --git a/drivers/irqchip/irq-imx-irqsteer.c b/drivers/irqchip/irq-imx-irqsteer.c
index b63bf957ab88..c2f58787f9a8 100644
--- a/drivers/irqchip/irq-imx-irqsteer.c
+++ b/drivers/irqchip/irq-imx-irqsteer.c
@@ -194,7 +194,7 @@ static int imx_irqsteer_probe(struct platform_device *pdev)
 		return PTR_ERR(data->regs);
 	}
 
-	data->ipg_clk = devm_clk_get(&pdev->dev, "ipg");
+	data->ipg_clk = devm_clk_get_enabled(&pdev->dev, "ipg");
 	if (IS_ERR(data->ipg_clk))
 		return dev_err_probe(&pdev->dev, PTR_ERR(data->ipg_clk),
 				     "failed to get ipg clk\n");
@@ -229,12 +229,6 @@ static int imx_irqsteer_probe(struct platform_device *pdev)
 			return -ENOMEM;
 	}
 
-	ret = clk_prepare_enable(data->ipg_clk);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to enable ipg clk: %d\n", ret);
-		return ret;
-	}
-
 	/* steer all IRQs into configured channel */
 	if (irqsteer_has_chanctrl(data->devtype_data))
 		writel_relaxed(BIT(data->channel), data->regs + CHANCTRL);
@@ -275,12 +269,21 @@ static int imx_irqsteer_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, data);
 
-	pm_runtime_set_active(&pdev->dev);
-	pm_runtime_enable(&pdev->dev);
+	ret = devm_pm_runtime_set_active_enabled(&pdev->dev);
+	if (ret)
+		goto err_irq;
 
 	return 0;
+
+err_irq:
+	for (i = 0; i < data->irq_count; i++) {
+		if (!data->irq[i])
+			break;
+
+		irq_set_chained_handler_and_data(data->irq[i], NULL, NULL);
+		irq_dispose_mapping(data->irq[i]);
+	}
 out:
-	clk_disable_unprepare(data->ipg_clk);
 	return ret;
 }
 
@@ -289,6 +292,14 @@ static void imx_irqsteer_remove(struct platform_device *pdev)
 	struct irqsteer_data *irqsteer_data = platform_get_drvdata(pdev);
 	int i;
 
+	/*
+	 * The device may be runtime-suspended here, in which case the
+	 * runtime suspend callback has already dropped the clock enable
+	 * count. Resume it so the devres clk_disable_unprepare(), which
+	 * runs after remove(), finds the clock enabled and stays balanced.
+	 */
+	pm_runtime_resume_and_get(&pdev->dev);
+
 	for (i = 0; i < irqsteer_data->irq_count; i++) {
 		if (!irqsteer_data->irq[i])
 			break;
@@ -297,8 +308,6 @@ static void imx_irqsteer_remove(struct platform_device *pdev)
 						 NULL, NULL);
 		irq_dispose_mapping(irqsteer_data->irq[i]);
 	}
-
-	clk_disable_unprepare(irqsteer_data->ipg_clk);
 }
 
 #ifdef CONFIG_PM
@@ -328,7 +337,7 @@ static int imx_irqsteer_suspend(struct device *dev)
 	struct irqsteer_data *irqsteer_data = dev_get_drvdata(dev);
 
 	imx_irqsteer_save_regs(irqsteer_data);
-	clk_disable_unprepare(irqsteer_data->ipg_clk);
+	clk_disable(irqsteer_data->ipg_clk);
 
 	return 0;
 }
@@ -338,7 +347,7 @@ static int imx_irqsteer_resume(struct device *dev)
 	struct irqsteer_data *irqsteer_data = dev_get_drvdata(dev);
 	int ret;
 
-	ret = clk_prepare_enable(irqsteer_data->ipg_clk);
+	ret = clk_enable(irqsteer_data->ipg_clk);
 	if (ret) {
 		dev_err(dev, "failed to enable ipg clk: %d\n", ret);
 		return ret;
-- 
2.34.1


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

* [PATCH v5 7/9] irqchip/imx-irqsteer: Allow building as module
  2026-08-21 10:10 [PATCH v5 0/9] irqchip/imx-irqsteer: Allow building as module Zhipeng.wang_1
                   ` (5 preceding siblings ...)
  2026-08-21 10:10 ` [PATCH v5 6/9] irqchip/imx-irqsteer: Let devres own the clock and runtime PM Zhipeng.wang_1
@ 2026-08-21 10:10 ` Zhipeng.wang_1
  2026-08-21 10:10 ` [PATCH v5 8/9] genirq/irqdomain: Add devm_irq_domain_create_linear() Zhipeng.wang_1
  2026-08-21 10:10 ` [PATCH v5 9/9] irqchip/imx-irqsteer: Use devm_irq_domain_create_linear() Zhipeng.wang_1
  8 siblings, 0 replies; 15+ messages in thread
From: Zhipeng.wang_1 @ 2026-08-21 10:10 UTC (permalink / raw)
  To: Thomas Gleixner, Marc Zyngier, Frank Li
  Cc: Radu Rendec, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Jindong Yue, xuegang.liu, linux-kernel, imx, linux-arm-kernel

From: Jindong Yue <jindong.yue@nxp.com>

Make the driver buildable as a module by turning the Kconfig symbol into
a tristate and using module_platform_driver() instead of
builtin_platform_driver(), and add the MODULE_DEVICE_TABLE() and module
metadata needed for autoloading.

The clock, runtime PM and IRQ domain are already owned by devres, so no
further teardown is needed to support unbind and reload.

Signed-off-by: Jindong Yue <jindong.yue@nxp.com>
Signed-off-by: Zhipeng Wang <zhipeng.wang_1@nxp.com>
---
 drivers/irqchip/Kconfig            | 2 +-
 drivers/irqchip/irq-imx-irqsteer.c | 7 ++++++-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 20b77fbc51ee..105108d2e6ff 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -555,7 +555,7 @@ config CSKY_APB_INTC
 	  the controller's register.
 
 config IMX_IRQSTEER
-	bool "i.MX IRQSTEER support"
+	tristate "i.MX IRQSTEER support"
 	depends on ARCH_MXC || ARCH_S32 || COMPILE_TEST
 	default y if ARCH_MXC || ARCH_S32
 	select IRQ_DOMAIN
diff --git a/drivers/irqchip/irq-imx-irqsteer.c b/drivers/irqchip/irq-imx-irqsteer.c
index c2f58787f9a8..dad09e095ed1 100644
--- a/drivers/irqchip/irq-imx-irqsteer.c
+++ b/drivers/irqchip/irq-imx-irqsteer.c
@@ -10,6 +10,7 @@
 #include <linux/irqchip/chained_irq.h>
 #include <linux/irqdomain.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
 #include <linux/platform_device.h>
@@ -370,6 +371,7 @@ static const struct of_device_id imx_irqsteer_dt_ids[] = {
 	{ .compatible = "nxp,s32n79-irqsteer",	.data = &s32n79_data },
 	{},
 };
+MODULE_DEVICE_TABLE(of, imx_irqsteer_dt_ids);
 
 static struct platform_driver imx_irqsteer_driver = {
 	.driver = {
@@ -380,4 +382,7 @@ static struct platform_driver imx_irqsteer_driver = {
 	.probe		= imx_irqsteer_probe,
 	.remove		= imx_irqsteer_remove,
 };
-builtin_platform_driver(imx_irqsteer_driver);
+module_platform_driver(imx_irqsteer_driver);
+
+MODULE_DESCRIPTION("i.MX IRQSTEER interrupt multiplexer/remapper driver");
+MODULE_LICENSE("GPL");
-- 
2.34.1


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

* [PATCH v5 8/9] genirq/irqdomain: Add devm_irq_domain_create_linear()
  2026-08-21 10:10 [PATCH v5 0/9] irqchip/imx-irqsteer: Allow building as module Zhipeng.wang_1
                   ` (6 preceding siblings ...)
  2026-08-21 10:10 ` [PATCH v5 7/9] irqchip/imx-irqsteer: Allow building as module Zhipeng.wang_1
@ 2026-08-21 10:10 ` Zhipeng.wang_1
  2026-08-21 10:10 ` [PATCH v5 9/9] irqchip/imx-irqsteer: Use devm_irq_domain_create_linear() Zhipeng.wang_1
  8 siblings, 0 replies; 15+ messages in thread
From: Zhipeng.wang_1 @ 2026-08-21 10:10 UTC (permalink / raw)
  To: Thomas Gleixner, Marc Zyngier, Frank Li
  Cc: Radu Rendec, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Jindong Yue, xuegang.liu, linux-kernel, imx, linux-arm-kernel

From: Zhipeng Wang <zhipeng.wang_1@nxp.com>

irq_domain_create_linear() has no devres-managed counterpart, so a
driver that wants a linear revmap domain tied to the device lifetime has
to open-code an irq_domain_info and call devm_irq_domain_instantiate()
directly.

Add devm_irq_domain_create_linear() as the devres-managed sibling of
irq_domain_create_linear(): it builds the same linear-revmap
irq_domain_info and hands it to devm_irq_domain_instantiate(), so the
domain is removed when the owning device is unbound. The return
convention matches irq_domain_create_linear() (NULL on failure).

Signed-off-by: Zhipeng Wang <zhipeng.wang_1@nxp.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
---
 include/linux/irqdomain.h | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 73c25d40846c..b6b360cb6525 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -457,6 +457,36 @@ static inline struct irq_domain *irq_domain_create_linear(struct fwnode_handle *
 	return IS_ERR(d) ? NULL : d;
 }
 
+/**
+ * devm_irq_domain_create_linear - Allocate and register a linear revmap
+ *				   irq_domain tied to the device lifetime.
+ * @dev:	Device that owns the domain. The domain is removed via devres
+ *		when the device is unbound.
+ * @fwnode:	pointer to interrupt controller's FW node.
+ * @size:	Number of interrupts in the domain.
+ * @ops:	map/unmap domain callbacks
+ * @host_data:	Controller private data pointer
+ *
+ * Returns: Newly created irq_domain, or NULL on failure.
+ */
+static inline struct irq_domain *devm_irq_domain_create_linear(struct device *dev,
+							       struct fwnode_handle *fwnode,
+							       unsigned int size,
+							       const struct irq_domain_ops *ops,
+							       void *host_data)
+{
+	const struct irq_domain_info info = {
+		.fwnode		= fwnode,
+		.size		= size,
+		.hwirq_max	= size,
+		.ops		= ops,
+		.host_data	= host_data,
+	};
+	struct irq_domain *d = devm_irq_domain_instantiate(dev, &info);
+
+	return IS_ERR(d) ? NULL : d;
+}
+
 static inline struct irq_domain *irq_domain_create_tree(struct fwnode_handle *fwnode,
 							const struct irq_domain_ops *ops,
 							void *host_data)
-- 
2.34.1


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

* [PATCH v5 9/9] irqchip/imx-irqsteer: Use devm_irq_domain_create_linear()
  2026-08-21 10:10 [PATCH v5 0/9] irqchip/imx-irqsteer: Allow building as module Zhipeng.wang_1
                   ` (7 preceding siblings ...)
  2026-08-21 10:10 ` [PATCH v5 8/9] genirq/irqdomain: Add devm_irq_domain_create_linear() Zhipeng.wang_1
@ 2026-08-21 10:10 ` Zhipeng.wang_1
  8 siblings, 0 replies; 15+ messages in thread
From: Zhipeng.wang_1 @ 2026-08-21 10:10 UTC (permalink / raw)
  To: Thomas Gleixner, Marc Zyngier, Frank Li
  Cc: Radu Rendec, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Jindong Yue, xuegang.liu, linux-kernel, imx, linux-arm-kernel

From: Zhipeng Wang <zhipeng.wang_1@nxp.com>

The driver open-codes an irq_domain_info and calls
devm_irq_domain_instantiate() only to get a linear revmap domain tied to
the device lifetime. Use the new devm_irq_domain_create_linear() helper
instead. No functional change.

Signed-off-by: Zhipeng Wang <zhipeng.wang_1@nxp.com>
---
 drivers/irqchip/irq-imx-irqsteer.c | 16 +++++-----------
 1 file changed, 5 insertions(+), 11 deletions(-)

diff --git a/drivers/irqchip/irq-imx-irqsteer.c b/drivers/irqchip/irq-imx-irqsteer.c
index dad09e095ed1..ff20f6220784 100644
--- a/drivers/irqchip/irq-imx-irqsteer.c
+++ b/drivers/irqchip/irq-imx-irqsteer.c
@@ -242,18 +242,12 @@ static int imx_irqsteer_probe(struct platform_device *pdev)
 	for (i = 0; i < data->reg_num; i++)
 		writel_relaxed(0, data->regs + CHANMASK(i, data->reg_num));
 
-	struct irq_domain_info info = {
-		.fwnode		= dev_fwnode(&pdev->dev),
-		.size		= data->reg_num * 32,
-		.hwirq_max	= data->reg_num * 32,
-		.ops		= &imx_irqsteer_domain_ops,
-		.host_data	= data,
-	};
-
-	data->domain = devm_irq_domain_instantiate(&pdev->dev, &info);
-	if (IS_ERR(data->domain)) {
+	data->domain = devm_irq_domain_create_linear(&pdev->dev, dev_fwnode(&pdev->dev),
+						     data->reg_num * 32,
+						     &imx_irqsteer_domain_ops, data);
+	if (!data->domain) {
 		dev_err(&pdev->dev, "failed to create IRQ domain\n");
-		ret = PTR_ERR(data->domain);
+		ret = -ENOMEM;
 		goto out;
 	}
 	irq_domain_set_pm_device(data->domain, &pdev->dev);
-- 
2.34.1


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

* Re: [PATCH v5 1/9] irqchip/imx-irqsteer: Call chained_irq_exit() on the handler error path
  2026-08-21 10:10 ` [PATCH v5 1/9] irqchip/imx-irqsteer: Call chained_irq_exit() on the handler error path Zhipeng.wang_1
@ 2026-08-21 14:15   ` Frank Li
  0 siblings, 0 replies; 15+ messages in thread
From: Frank Li @ 2026-08-21 14:15 UTC (permalink / raw)
  To: Zhipeng.wang_1
  Cc: Thomas Gleixner, Marc Zyngier, Frank Li, Radu Rendec,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Jindong Yue,
	xuegang.liu, linux-kernel, imx, linux-arm-kernel

On Fri, Aug 21, 2026 at 07:10:31PM +0900, Zhipeng.wang_1@oss.nxp.com wrote:
> From: Zhipeng Wang <zhipeng.wang_1@nxp.com>
>
> A chained handler must pair every chained_irq_enter() with a
> chained_irq_exit() before returning, so that the parent interrupt's flow
> control is completed (EOI for fasteoi parents, unmask for level-triggered
> parents). Skipping it leaves the parent interrupt unacknowledged, blocking
> further interrupts multiplexed through that line.
>
> When imx_irqsteer_get_hwirq_base() fails, the handler returned early
> without calling chained_irq_exit(). Route the error path through the
> existing chained_irq_exit() so the parent interrupt is always completed
> before returning.
>
> Fixes: 28528fca4908 ("irqchip/imx-irqsteer: Add multi output interrupts support")
> Signed-off-by: Zhipeng Wang <zhipeng.wang_1@nxp.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/irqchip/irq-imx-irqsteer.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/irqchip/irq-imx-irqsteer.c b/drivers/irqchip/irq-imx-irqsteer.c
> index 87b07f517be3..1b8d0c8eedb9 100644
> --- a/drivers/irqchip/irq-imx-irqsteer.c
> +++ b/drivers/irqchip/irq-imx-irqsteer.c
> @@ -154,7 +154,7 @@ static void imx_irqsteer_irq_handler(struct irq_desc *desc)
>  	if (hwirq < 0) {
>  		pr_warn("%s: unable to get hwirq base for irq %d\n",
>  			__func__, irq);
> -		return;
> +		goto out;
>  	}
>
>  	for (i = 0; i < 2; i++, hwirq += 32) {
> @@ -172,6 +172,7 @@ static void imx_irqsteer_irq_handler(struct irq_desc *desc)
>  			generic_handle_domain_irq(data->domain, pos + hwirq);
>  	}
>
> +out:
>  	chained_irq_exit(irq_desc_get_chip(desc), desc);
>  }
>
>
> base-commit: bd5f485f3f026225b86573e559af0b7254ef4184
> --
> 2.34.1
>
>

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

* Re: [PATCH v5 3/9] irqchip/imx-irqsteer: Validate IRQ count before creating domain
  2026-08-21 10:10 ` [PATCH v5 3/9] irqchip/imx-irqsteer: Validate IRQ count before creating domain Zhipeng.wang_1
@ 2026-08-21 14:24   ` Frank Li
  2026-08-24  9:38     ` Zhipeng Wang (OSS)
  0 siblings, 1 reply; 15+ messages in thread
From: Frank Li @ 2026-08-21 14:24 UTC (permalink / raw)
  To: Zhipeng.wang_1
  Cc: Thomas Gleixner, Marc Zyngier, Frank Li, Radu Rendec,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Jindong Yue,
	xuegang.liu, linux-kernel, imx, linux-arm-kernel

On Fri, Aug 21, 2026 at 07:10:33PM +0900, Zhipeng.wang_1@oss.nxp.com wrote:
> From: Fabio Estevam <festevam@nabladev.com>
>
> The IRQ count is validated after creating the IRQ domain. If it is
> invalid, probe returns without removing the domain, leaving its host
> data pointing at devm-managed memory that is freed on probe failure.
>
> Validate the count before allocating resources to avoid the leak and
> dangling pointer.
>
> Fixes: 28528fca4908 ("irqchip/imx-irqsteer: Add multi output interrupts support")
> Signed-off-by: Fabio Estevam <festevam@nabladev.com>
> Signed-off-by: Zhipeng Wang <zhipeng.wang_1@nxp.com>
> ---

This patch should be second patch.  After move to second patch, some error
handle will be nice to have.

your 3 patch needn't because no error after it. change to devm_ version
will be improvement patch and put after new API added.

Frank


>  drivers/irqchip/irq-imx-irqsteer.c | 7 ++-----
>  1 file changed, 2 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/irqchip/irq-imx-irqsteer.c b/drivers/irqchip/irq-imx-irqsteer.c
> index c1df84551efa..571324de8bd1 100644
> --- a/drivers/irqchip/irq-imx-irqsteer.c
> +++ b/drivers/irqchip/irq-imx-irqsteer.c
> @@ -218,6 +218,8 @@ static int imx_irqsteer_probe(struct platform_device *pdev)
>  	 */
>  	data->irq_count = DIV_ROUND_UP(irqs_num, 64);
>  	data->reg_num = irqs_num / 32;
> +	if (!data->irq_count || data->irq_count > CHAN_MAX_OUTPUT_INT)
> +		return -EINVAL;
>
>  	if (IS_ENABLED(CONFIG_PM)) {
>  		data->saved_reg = devm_kzalloc(&pdev->dev,
> @@ -253,11 +255,6 @@ static int imx_irqsteer_probe(struct platform_device *pdev)
>  	}
>  	irq_domain_set_pm_device(data->domain, &pdev->dev);
>
> -	if (!data->irq_count || data->irq_count > CHAN_MAX_OUTPUT_INT) {
> -		ret = -EINVAL;
> -		goto out;
> -	}
> -
>  	for (i = 0; i < data->irq_count; i++) {
>  		data->irq[i] = irq_of_parse_and_map(np, i);
>  		if (!data->irq[i])
> --
> 2.34.1
>
>

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

* RE: [PATCH v5 3/9] irqchip/imx-irqsteer: Validate IRQ count before creating domain
  2026-08-21 14:24   ` Frank Li
@ 2026-08-24  9:38     ` Zhipeng Wang (OSS)
  2026-08-24 12:49       ` Fabio Estevam
  0 siblings, 1 reply; 15+ messages in thread
From: Zhipeng Wang (OSS) @ 2026-08-24  9:38 UTC (permalink / raw)
  To: Frank Li (OSS), Zhipeng Wang (OSS)
  Cc: Thomas Gleixner, Marc Zyngier, Frank Li, Radu Rendec,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Jindong Yue,
	Xuegang Liu, linux-kernel@vger.kernel.org, imx@lists.linux.dev,
	linux-arm-kernel@lists.infradead.org

> On Fri, Aug 21, 2026 at 07:10:33PM +0900, Zhipeng.wang_1@oss.nxp.com
> wrote:
> > From: Fabio Estevam <festevam@nabladev.com>
> >
> > The IRQ count is validated after creating the IRQ domain. If it is
> > invalid, probe returns without removing the domain, leaving its host
> > data pointing at devm-managed memory that is freed on probe failure.
> >
> > Validate the count before allocating resources to avoid the leak and
> > dangling pointer.
> >
> > Fixes: 28528fca4908 ("irqchip/imx-irqsteer: Add multi output
> > interrupts support")
> > Signed-off-by: Fabio Estevam <festevam@nabladev.com>
> > Signed-off-by: Zhipeng Wang <zhipeng.wang_1@nxp.com>
> > ---
> 
> This patch should be second patch.  After move to second patch, some error
> handle will be nice to have.
> 
> your 3 patch needn't because no error after it. change to devm_ version will be
> improvement patch and put after new API added.
> 
> Frank
> 
Hi Frank,

Makes sense, I'll restructure it that way for the next version:

 - Move Fabio's IRQ-count validation up so the count is validated before
   the domain is created, and add proper error handling there.
 - Since the invalid count is then rejected before the domain exists,
   the domain leak can no longer happen, so managing the domain with
   devm is no longer a fix. I'll drop its Fixes tag and reframe it as an
   improvement.
 - Move that devm conversion after the new devm_irq_domain_create_linear()
   helper, together with the other cleanup.

Thanks for the review.

Zhipeng
> 
> >  drivers/irqchip/irq-imx-irqsteer.c | 7 ++-----
> >  1 file changed, 2 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/irqchip/irq-imx-irqsteer.c
> > b/drivers/irqchip/irq-imx-irqsteer.c
> > index c1df84551efa..571324de8bd1 100644
> > --- a/drivers/irqchip/irq-imx-irqsteer.c
> > +++ b/drivers/irqchip/irq-imx-irqsteer.c
> > @@ -218,6 +218,8 @@ static int imx_irqsteer_probe(struct platform_device
> *pdev)
> >  	 */
> >  	data->irq_count = DIV_ROUND_UP(irqs_num, 64);
> >  	data->reg_num = irqs_num / 32;
> > +	if (!data->irq_count || data->irq_count > CHAN_MAX_OUTPUT_INT)
> > +		return -EINVAL;
> >
> >  	if (IS_ENABLED(CONFIG_PM)) {
> >  		data->saved_reg = devm_kzalloc(&pdev->dev, @@ -253,11 +255,6
> @@
> > static int imx_irqsteer_probe(struct platform_device *pdev)
> >  	}
> >  	irq_domain_set_pm_device(data->domain, &pdev->dev);
> >
> > -	if (!data->irq_count || data->irq_count > CHAN_MAX_OUTPUT_INT) {
> > -		ret = -EINVAL;
> > -		goto out;
> > -	}
> > -
> >  	for (i = 0; i < data->irq_count; i++) {
> >  		data->irq[i] = irq_of_parse_and_map(np, i);
> >  		if (!data->irq[i])
> > --
> > 2.34.1
> >
> >

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

* Re: [PATCH v5 3/9] irqchip/imx-irqsteer: Validate IRQ count before creating domain
  2026-08-24  9:38     ` Zhipeng Wang (OSS)
@ 2026-08-24 12:49       ` Fabio Estevam
  2026-08-26  3:26         ` Zhipeng Wang (OSS)
  0 siblings, 1 reply; 15+ messages in thread
From: Fabio Estevam @ 2026-08-24 12:49 UTC (permalink / raw)
  To: Zhipeng Wang (OSS)
  Cc: Frank Li (OSS), Thomas Gleixner, Marc Zyngier, Frank Li,
	Radu Rendec, Sascha Hauer, Pengutronix Kernel Team, Jindong Yue,
	Xuegang Liu, linux-kernel@vger.kernel.org, imx@lists.linux.dev,
	linux-arm-kernel@lists.infradead.org

Hi Zhipeng,

On Mon, Aug 24, 2026 at 6:38 AM Zhipeng Wang (OSS)
<zhipeng.wang_1@oss.nxp.com> wrote:

> Hi Frank,
>
> Makes sense, I'll restructure it that way for the next version:
>
>  - Move Fabio's IRQ-count validation up so the count is validated before
>    the domain is created, and add proper error handling there.
>  - Since the invalid count is then rejected before the domain exists,
>    the domain leak can no longer happen, so managing the domain with
>    devm is no longer a fix. I'll drop its Fixes tag and reframe it as an
>    improvement.
>  - Move that devm conversion after the new devm_irq_domain_create_linear()
>    helper, together with the other cleanup.

My motivation for sending [PATCH v4 1/2] irqchip/imx-irqsteer: Convert
to devm_pm_runtime_enable()
https://lore.kernel.org/lkml/aoXZf2z-50H8rimI@lizhi-Precision-Tower-5810/
was the "Unbalanced pm_runtime_enable!"
error during driver unbinding.

This was seen on kernel 6.18, so I would like this error fixed in your
series with a Fixes tag, so stable kernels like 6.18 can be fixed.

Thanks

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

* RE: [PATCH v5 3/9] irqchip/imx-irqsteer: Validate IRQ count before creating domain
  2026-08-24 12:49       ` Fabio Estevam
@ 2026-08-26  3:26         ` Zhipeng Wang (OSS)
  0 siblings, 0 replies; 15+ messages in thread
From: Zhipeng Wang (OSS) @ 2026-08-26  3:26 UTC (permalink / raw)
  To: Fabio Estevam, Zhipeng Wang (OSS)
  Cc: Frank Li (OSS), Thomas Gleixner, Marc Zyngier, Frank Li,
	Radu Rendec, Sascha Hauer, Pengutronix Kernel Team, Jindong Yue,
	Xuegang Liu, linux-kernel@vger.kernel.org, imx@lists.linux.dev,
	linux-arm-kernel@lists.infradead.org

> Subject: Re: [PATCH v5 3/9] irqchip/imx-irqsteer: Validate IRQ count before
> creating domain
> 
> Hi Zhipeng,
> 
> On Mon, Aug 24, 2026 at 6:38 AM Zhipeng Wang (OSS)
> <zhipeng.wang_1@oss.nxp.com> wrote:
> 
> > Hi Frank,
> >
> > Makes sense, I'll restructure it that way for the next version:
> >
> >  - Move Fabio's IRQ-count validation up so the count is validated before
> >    the domain is created, and add proper error handling there.
> >  - Since the invalid count is then rejected before the domain exists,
> >    the domain leak can no longer happen, so managing the domain with
> >    devm is no longer a fix. I'll drop its Fixes tag and reframe it as an
> >    improvement.
> >  - Move that devm conversion after the new
> devm_irq_domain_create_linear()
> >    helper, together with the other cleanup.
> 
> My motivation for sending [PATCH v4 1/2] irqchip/imx-irqsteer: Convert to
> devm_pm_runtime_enable()
> https://lore.kernel.org/lkml/aoXZf2z-50H8rimI@lizhi-Precision-Tower-5810/
> was the "Unbalanced pm_runtime_enable!"
> error during driver unbinding.
> 
> This was seen on kernel 6.18, so I would like this error fixed in your series with
> a Fixes tag, so stable kernels like 6.18 can be fixed.
> 
> Thanks

Agreed. For v6 I've pulled the "Unbalanced pm_runtime_enable!" fix out
into its own patch so it can be backported on its own:

  irqchip/imx-irqsteer: Convert to devm_pm_runtime_set_active_enabled()
  Fixes: 4730d2233311 ("irqchip/imx-irqsteer: Add runtime PM support")

It only touches runtime PM (no clock rework), so it applies cleanly to
6.18. It uses devm_pm_runtime_set_active_enabled() to disable runtime PM
on unbind, and keeps the

  if (!pm_runtime_status_suspended(&pdev->dev))
      clk_disable_unprepare(...);

guard in remove() so the clock reference count does not underflow when
the device is unbound while runtime-suspended, as in your patch.

The clock devres rework (devm_clk_get_enabled() etc.) is a separate
improvement patch later in the series, so it does not get in the way of
the stable backport.

Compared to v5, I also moved devm_pm_runtime_set_active_enabled() before
the IRQ domain is created, so its failure path just needs to bail out
instead of unwinding the domain and the parent IRQ mappings by hand.
This drops the err_irq label and keeps the patch minimal, matching your
original structure.

Thanks,
Zhipeng

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

end of thread, other threads:[~2026-08-26  3:26 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-21 10:10 [PATCH v5 0/9] irqchip/imx-irqsteer: Allow building as module Zhipeng.wang_1
2026-08-21 10:10 ` [PATCH v5 1/9] irqchip/imx-irqsteer: Call chained_irq_exit() on the handler error path Zhipeng.wang_1
2026-08-21 14:15   ` Frank Li
2026-08-21 10:10 ` [PATCH v5 2/9] irqchip/imx-irqsteer: Use devm to manage the IRQ domain Zhipeng.wang_1
2026-08-21 10:10 ` [PATCH v5 3/9] irqchip/imx-irqsteer: Validate IRQ count before creating domain Zhipeng.wang_1
2026-08-21 14:24   ` Frank Li
2026-08-24  9:38     ` Zhipeng Wang (OSS)
2026-08-24 12:49       ` Fabio Estevam
2026-08-26  3:26         ` Zhipeng Wang (OSS)
2026-08-21 10:10 ` [PATCH v5 4/9] irqchip/imx-irqsteer: Dispose of parent IRQ mappings in remove() Zhipeng.wang_1
2026-08-21 10:10 ` [PATCH v5 5/9] irqchip/imx-irqsteer: Mask all interrupts in probe() Zhipeng.wang_1
2026-08-21 10:10 ` [PATCH v5 6/9] irqchip/imx-irqsteer: Let devres own the clock and runtime PM Zhipeng.wang_1
2026-08-21 10:10 ` [PATCH v5 7/9] irqchip/imx-irqsteer: Allow building as module Zhipeng.wang_1
2026-08-21 10:10 ` [PATCH v5 8/9] genirq/irqdomain: Add devm_irq_domain_create_linear() Zhipeng.wang_1
2026-08-21 10:10 ` [PATCH v5 9/9] irqchip/imx-irqsteer: Use devm_irq_domain_create_linear() Zhipeng.wang_1

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