All of lore.kernel.org
 help / color / mirror / Atom feed
From: Frank Li <Frank.li@oss.nxp.com>
To: "Zhipeng Wang (OSS)" <zhipeng.wang_1@oss.nxp.com>
Cc: Thomas Gleixner <tglx@kernel.org>, Marc Zyngier <maz@kernel.org>,
	Frank Li <frank.li@nxp.com>,
	Sascha Hauer <s.hauer@pengutronix.de>,
	Pengutronix Kernel Team <kernel@pengutronix.de>,
	Fabio Estevam <festevam@gmail.com>,
	Jindong Yue <jindong.yue@nxp.com>,
	Xuegang Liu <xuegang.liu@nxp.com>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	"imx@lists.linux.dev" <imx@lists.linux.dev>,
	"linux-arm-kernel@lists.infradead.org"
	<linux-arm-kernel@lists.infradead.org>
Subject: Re: [PATCH v4 5/5] irqchip/imx-irqsteer: Allow building as module
Date: Thu, 20 Aug 2026 11:53:08 -0500	[thread overview]
Message-ID: <aocw9Gy4dsWLV_qi@SMW015318> (raw)
In-Reply-To: <AMBPR04MB12334895C9AD42BFCD085EAB9EBA42@AMBPR04MB12334.eurprd04.prod.outlook.com>

On Thu, Aug 20, 2026 at 09:53:13AM +0000, Zhipeng Wang (OSS) wrote:
>
>
>
> NXP Confidential

Please remove this tags,  It is public mail list. Everyone can see context.

Frank

> > -----Original Message-----
> > From: Frank Li (OSS) <frank.li@oss.nxp.com>
> > Sent: 2026年8月19日 23:17
> > To: Zhipeng Wang (OSS) <zhipeng.wang_1@oss.nxp.com>
> > Cc: Thomas Gleixner <tglx@kernel.org>; Marc Zyngier <maz@kernel.org>;
> > Frank Li <frank.li@nxp.com>; Sascha Hauer <s.hauer@pengutronix.de>;
> > Pengutronix Kernel Team <kernel@pengutronix.de>; Fabio Estevam
> > <festevam@gmail.com>; Jindong Yue <jindong.yue@nxp.com>; Xuegang Liu
> > <xuegang.liu@nxp.com>; linux-kernel@vger.kernel.org; imx@lists.linux.dev;
> > linux-arm-kernel@lists.infradead.org
> > Subject: Re: [PATCH v4 5/5] irqchip/imx-irqsteer: Allow building as module
> >
> > On Wed, Aug 19, 2026 at 06:05:43PM +0900, Zhipeng.wang_1@oss.nxp.com
> > wrote:
> > > 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().
> > >
> > > Now that the driver can be unloaded and reloaded, 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;
> >
> > devm_clk_get_enable() will do prepare() and enable(). tear down also do
> > unprepare() and disable()
> >
> > To avoid both devm_clk() and runtime pm suspend both unprepare and
> > disable() clock to make wrong clock refererence.
> >
> > need in remove function
> >
> >     /*
> >      * Resume the device so runtime_resume() re-enables the clock.
> >      * devm cleanup (clk_disable_unprepare) runs after .remove() returns,
> >      * so the clock will be enabled and the disable is safe.
> >      */
> >     pm_runtime_resume_and_get(dev);
> >
> >     /* devm_clk_get_enable and devm_pm_runtime_enable clean up
> > automatically */
> >
> > Frank
> >
> Hi Frank,
>
> Thanks for catching the clock reference-count underflow — you're right.
>
> With devm_clk_get_enabled() doing prepare+enable and the devres teardown
> doing unprepare+disable, having runtime suspend also drop the enable count
> means the clock can be disabled/unprepared twice (once by runtime PM on the
> suspend path, once by devres on unbind), underflowing the reference count.
>
> I've applied your suggestion in remove():
>
>         /*
>          * 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);
>
> What will change in the next version:
>   - The series is split per tglx's request: the PM/devres rework, the
>     module-enable change, and the irqdomain helper cleanup are now
>     separate patches rather than one blob.
>
>   - Fabio's IRQ-count validation patch, which carries the same
>     Fixes: 28528fca4908 tag, is folded into the series.
>
> Thomas suggested collecting the patches that carry
> Fixes: 28528fca4908 ("irqchip/imx-irqsteer: Add multi output interrupts
> support") into a single series. This standalone fix carries that same tag:
>
>     [PATCH] irqchip/imx-irqsteer: Call chained_irq_exit() on the handler error path
>     https://lore.kernel.org/all/20260807072626.1231517-1-Zhipeng.wang_1@oss.nxp.com/
>
> What's your view on it?
>
> Thanks,
> Zhipeng
>
> > >  - 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.
> > >
> > > With the clock, runtime PM and IRQ domain all owned by devres,
> > > remove() and the probe() error path only have to dispose of the parent
> > > IRQ mappings.
> > >
> > > 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 | 36
> > > +++++++++++++++++-------------
> > >  2 files changed, 22 insertions(+), 16 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 a9909ecb6fef..a60cc527e619 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>
> > > @@ -193,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");
> > > @@ -226,12 +227,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); @@
> > > -271,12 +266,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;
> > >  }
> > >
> > > @@ -293,8 +297,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
> > > @@ -324,7 +326,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;
> > >  }
> > > @@ -334,7 +336,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;
> > > @@ -357,6 +359,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 = {
> > > @@ -367,4 +370,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
> > >
> > >

  parent reply	other threads:[~2026-08-20 16:53 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-19  9:05 [PATCH v4 0/5] irqchip/imx-irqsteer: Allow building as module Zhipeng.wang_1
2026-08-19  9:05 ` [PATCH v4 1/5] genirq/irqdomain: Add devm_irq_domain_create_linear() Zhipeng.wang_1
2026-08-19 14:23   ` Frank Li
2026-08-19 16:27   ` Thomas Gleixner
2026-08-19  9:05 ` [PATCH v4 2/5] irqchip/imx-irqsteer: Use devm to manage the IRQ domain Zhipeng.wang_1
2026-08-19 14:24   ` Frank Li
2026-08-19 16:28     ` Thomas Gleixner
2026-08-19  9:05 ` [PATCH v4 3/5] irqchip/imx-irqsteer: Dispose of parent IRQ mappings in remove() Zhipeng.wang_1
2026-08-19  9:18   ` sashiko-bot
2026-08-19 14:25   ` Frank Li
2026-08-19  9:05 ` [PATCH v4 4/5] irqchip/imx-irqsteer: Mask all interrupts in probe() Zhipeng.wang_1
2026-08-19  9:25   ` sashiko-bot
2026-08-19 14:40     ` Frank Li
2026-08-19 15:02       ` Fabio Estevam
2026-08-19 16:30         ` Frank Li
2026-08-19 16:37           ` Fabio Estevam
2026-08-19  9:05 ` [PATCH v4 5/5] irqchip/imx-irqsteer: Allow building as module Zhipeng.wang_1
2026-08-19  9:24   ` sashiko-bot
2026-08-19 15:17   ` Frank Li
2026-08-20  9:53     ` Zhipeng Wang (OSS)
2026-08-20 15:20       ` Frank Li
2026-08-20 16:53       ` Frank Li [this message]
2026-08-19 16:30   ` Thomas Gleixner
2026-08-19 16:20 ` [PATCH v4 0/5] " Thomas Gleixner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aocw9Gy4dsWLV_qi@SMW015318 \
    --to=frank.li@oss.nxp.com \
    --cc=festevam@gmail.com \
    --cc=frank.li@nxp.com \
    --cc=imx@lists.linux.dev \
    --cc=jindong.yue@nxp.com \
    --cc=kernel@pengutronix.de \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=maz@kernel.org \
    --cc=s.hauer@pengutronix.de \
    --cc=tglx@kernel.org \
    --cc=xuegang.liu@nxp.com \
    --cc=zhipeng.wang_1@oss.nxp.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.