* [PATCH v5] i2c: imx: mark I2C adapter when hardware is powered down
@ 2026-05-25 3:04 Carlos Song (OSS)
2026-06-23 20:10 ` Andi Shyti
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Carlos Song (OSS) @ 2026-05-25 3:04 UTC (permalink / raw)
To: o.rempel, kernel, andi.shyti, s.hauer, festevam, carlos.song, haibo.chen
Cc: linux-i2c, imx, linux-arm-kernel, linux-kernel, stable
From: Carlos Song <carlos.song@nxp.com>
On some i.MX platforms, certain I2C client drivers keep a periodic
workqueue which continues to trigger I2C transfers.
During system suspend/resume, there exists a time window between:
- suspend_noirq and the system entering suspend
- the system starting to resume and resume_noirq
In this window, the I2C controller resources such as clock and pinctrl
may already be disabled or not yet restored.
If a workqueue triggers an I2C transfer in this period, the driver
attempts to access I2C registers while the hardware resources are
unavailable, which may lead to system hang.
Mark the I2C adapter as suspended during noirq suspend and block new
transfers until resume, ensuring that I2C transfers are only issued
when hardware resources are available.
Fixes: 358025ac091e ("i2c: imx: make controller available until system suspend_noirq() and from resume_noirq()")
Cc: stable@vger.kernel.org
Signed-off-by: Carlos Song <carlos.song@nxp.com>
---
Change for v5:
- Remake commit log including the issue detail from Mukesh's
suggestion.
Change for v4:
- Restore hrtimer when pm_runtime_force_suspend failed when slave mode
enabled.
Change for v3:
- Add hrtimer_cancel in i2c_imx_suspend_noirq to cancel slave_timer for
safe suspend in i2c slave mode.
Change for v2:
- Call i2c_mark_adapter_suspended() before pm_runtime_force_suspend()
to prevent potential deadlock if a transfer is active during suspend.
- Roll back with i2c_mark_adapter_resumed() if pm_runtime_force_suspend()
fails.
---
drivers/i2c/busses/i2c-imx.c | 45 ++++++++++++++++++++++++++++++++++--
1 file changed, 43 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 28313d0fad37..73317ddd5f02 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -1922,6 +1922,47 @@ static int i2c_imx_runtime_resume(struct device *dev)
return 0;
}
+static int __maybe_unused i2c_imx_suspend_noirq(struct device *dev)
+{
+ struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev);
+ int ret;
+
+ i2c_mark_adapter_suspended(&i2c_imx->adapter);
+
+ /*
+ * Cancel the slave timer before powering down to prevent
+ * i2c_imx_slave_timeout() from accessing hardware registers
+ * while the clock is disabled.
+ */
+ hrtimer_cancel(&i2c_imx->slave_timer);
+
+ ret = pm_runtime_force_suspend(dev);
+ if (ret) {
+ i2c_mark_adapter_resumed(&i2c_imx->adapter);
+ if (i2c_imx->slave) {
+ hrtimer_forward_now(&i2c_imx->slave_timer, I2C_IMX_CHECK_DELAY);
+ hrtimer_restart(&i2c_imx->slave_timer);
+ }
+ return ret;
+ }
+
+ return 0;
+}
+
+static int __maybe_unused i2c_imx_resume_noirq(struct device *dev)
+{
+ struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev);
+ int ret;
+
+ ret = pm_runtime_force_resume(dev);
+ if (ret)
+ return ret;
+
+ i2c_mark_adapter_resumed(&i2c_imx->adapter);
+
+ return 0;
+}
+
static int i2c_imx_suspend(struct device *dev)
{
/*
@@ -1955,8 +1996,8 @@ static int i2c_imx_resume(struct device *dev)
}
static const struct dev_pm_ops i2c_imx_pm_ops = {
- NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
- pm_runtime_force_resume)
+ NOIRQ_SYSTEM_SLEEP_PM_OPS(i2c_imx_suspend_noirq,
+ i2c_imx_resume_noirq)
SYSTEM_SLEEP_PM_OPS(i2c_imx_suspend, i2c_imx_resume)
RUNTIME_PM_OPS(i2c_imx_runtime_suspend, i2c_imx_runtime_resume, NULL)
};
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v5] i2c: imx: mark I2C adapter when hardware is powered down
2026-05-25 3:04 [PATCH v5] i2c: imx: mark I2C adapter when hardware is powered down Carlos Song (OSS)
@ 2026-06-23 20:10 ` Andi Shyti
2026-06-25 7:15 ` Oleksij Rempel
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Andi Shyti @ 2026-06-23 20:10 UTC (permalink / raw)
To: Carlos Song (OSS)
Cc: o.rempel, kernel, s.hauer, festevam, carlos.song, haibo.chen,
linux-i2c, imx, linux-arm-kernel, linux-kernel, stable
Hi Oleksij,
Any chance you can give this a review?
Thanks,
Andi
On Mon, May 25, 2026 at 11:04:00AM +0800, Carlos Song (OSS) wrote:
> From: Carlos Song <carlos.song@nxp.com>
>
> On some i.MX platforms, certain I2C client drivers keep a periodic
> workqueue which continues to trigger I2C transfers.
>
> During system suspend/resume, there exists a time window between:
> - suspend_noirq and the system entering suspend
> - the system starting to resume and resume_noirq
>
> In this window, the I2C controller resources such as clock and pinctrl
> may already be disabled or not yet restored.
>
> If a workqueue triggers an I2C transfer in this period, the driver
> attempts to access I2C registers while the hardware resources are
> unavailable, which may lead to system hang.
>
> Mark the I2C adapter as suspended during noirq suspend and block new
> transfers until resume, ensuring that I2C transfers are only issued
> when hardware resources are available.
>
> Fixes: 358025ac091e ("i2c: imx: make controller available until system suspend_noirq() and from resume_noirq()")
> Cc: stable@vger.kernel.org
> Signed-off-by: Carlos Song <carlos.song@nxp.com>
> ---
> Change for v5:
> - Remake commit log including the issue detail from Mukesh's
> suggestion.
> Change for v4:
> - Restore hrtimer when pm_runtime_force_suspend failed when slave mode
> enabled.
> Change for v3:
> - Add hrtimer_cancel in i2c_imx_suspend_noirq to cancel slave_timer for
> safe suspend in i2c slave mode.
> Change for v2:
> - Call i2c_mark_adapter_suspended() before pm_runtime_force_suspend()
> to prevent potential deadlock if a transfer is active during suspend.
> - Roll back with i2c_mark_adapter_resumed() if pm_runtime_force_suspend()
> fails.
> ---
> drivers/i2c/busses/i2c-imx.c | 45 ++++++++++++++++++++++++++++++++++--
> 1 file changed, 43 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
> index 28313d0fad37..73317ddd5f02 100644
> --- a/drivers/i2c/busses/i2c-imx.c
> +++ b/drivers/i2c/busses/i2c-imx.c
> @@ -1922,6 +1922,47 @@ static int i2c_imx_runtime_resume(struct device *dev)
> return 0;
> }
>
> +static int __maybe_unused i2c_imx_suspend_noirq(struct device *dev)
> +{
> + struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev);
> + int ret;
> +
> + i2c_mark_adapter_suspended(&i2c_imx->adapter);
> +
> + /*
> + * Cancel the slave timer before powering down to prevent
> + * i2c_imx_slave_timeout() from accessing hardware registers
> + * while the clock is disabled.
> + */
> + hrtimer_cancel(&i2c_imx->slave_timer);
> +
> + ret = pm_runtime_force_suspend(dev);
> + if (ret) {
> + i2c_mark_adapter_resumed(&i2c_imx->adapter);
> + if (i2c_imx->slave) {
> + hrtimer_forward_now(&i2c_imx->slave_timer, I2C_IMX_CHECK_DELAY);
> + hrtimer_restart(&i2c_imx->slave_timer);
> + }
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static int __maybe_unused i2c_imx_resume_noirq(struct device *dev)
> +{
> + struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev);
> + int ret;
> +
> + ret = pm_runtime_force_resume(dev);
> + if (ret)
> + return ret;
> +
> + i2c_mark_adapter_resumed(&i2c_imx->adapter);
> +
> + return 0;
> +}
> +
> static int i2c_imx_suspend(struct device *dev)
> {
> /*
> @@ -1955,8 +1996,8 @@ static int i2c_imx_resume(struct device *dev)
> }
>
> static const struct dev_pm_ops i2c_imx_pm_ops = {
> - NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
> - pm_runtime_force_resume)
> + NOIRQ_SYSTEM_SLEEP_PM_OPS(i2c_imx_suspend_noirq,
> + i2c_imx_resume_noirq)
> SYSTEM_SLEEP_PM_OPS(i2c_imx_suspend, i2c_imx_resume)
> RUNTIME_PM_OPS(i2c_imx_runtime_suspend, i2c_imx_runtime_resume, NULL)
> };
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v5] i2c: imx: mark I2C adapter when hardware is powered down
2026-05-25 3:04 [PATCH v5] i2c: imx: mark I2C adapter when hardware is powered down Carlos Song (OSS)
2026-06-23 20:10 ` Andi Shyti
@ 2026-06-25 7:15 ` Oleksij Rempel
2026-07-14 13:54 ` Frank Li
2026-07-28 15:35 ` Andi Shyti
3 siblings, 0 replies; 5+ messages in thread
From: Oleksij Rempel @ 2026-06-25 7:15 UTC (permalink / raw)
To: Carlos Song (OSS)
Cc: kernel, andi.shyti, s.hauer, festevam, carlos.song, haibo.chen,
linux-i2c, imx, linux-arm-kernel, linux-kernel, stable
On Mon, May 25, 2026 at 11:04:00AM +0800, Carlos Song (OSS) wrote:
> From: Carlos Song <carlos.song@nxp.com>
>
> On some i.MX platforms, certain I2C client drivers keep a periodic
> workqueue which continues to trigger I2C transfers.
>
> During system suspend/resume, there exists a time window between:
> - suspend_noirq and the system entering suspend
> - the system starting to resume and resume_noirq
>
> In this window, the I2C controller resources such as clock and pinctrl
> may already be disabled or not yet restored.
>
> If a workqueue triggers an I2C transfer in this period, the driver
> attempts to access I2C registers while the hardware resources are
> unavailable, which may lead to system hang.
>
> Mark the I2C adapter as suspended during noirq suspend and block new
> transfers until resume, ensuring that I2C transfers are only issued
> when hardware resources are available.
>
> Fixes: 358025ac091e ("i2c: imx: make controller available until system suspend_noirq() and from resume_noirq()")
> Cc: stable@vger.kernel.org
> Signed-off-by: Carlos Song <carlos.song@nxp.com>
Acked-by: Oleksij Rempel <o.rempel@pengutronix.de>
Thank you!
Best Regards,
Oleksij
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v5] i2c: imx: mark I2C adapter when hardware is powered down
2026-05-25 3:04 [PATCH v5] i2c: imx: mark I2C adapter when hardware is powered down Carlos Song (OSS)
2026-06-23 20:10 ` Andi Shyti
2026-06-25 7:15 ` Oleksij Rempel
@ 2026-07-14 13:54 ` Frank Li
2026-07-28 15:35 ` Andi Shyti
3 siblings, 0 replies; 5+ messages in thread
From: Frank Li @ 2026-07-14 13:54 UTC (permalink / raw)
To: Carlos Song (OSS)
Cc: o.rempel, kernel, andi.shyti, s.hauer, festevam, carlos.song,
haibo.chen, linux-i2c, imx, linux-arm-kernel, linux-kernel,
stable
On Mon, May 25, 2026 at 11:04:00AM +0800, Carlos Song (OSS) wrote:
> From: Carlos Song <carlos.song@nxp.com>
>
> On some i.MX platforms, certain I2C client drivers keep a periodic
> workqueue which continues to trigger I2C transfers.
>
> During system suspend/resume, there exists a time window between:
> - suspend_noirq and the system entering suspend
> - the system starting to resume and resume_noirq
>
> In this window, the I2C controller resources such as clock and pinctrl
> may already be disabled or not yet restored.
>
> If a workqueue triggers an I2C transfer in this period, the driver
> attempts to access I2C registers while the hardware resources are
> unavailable, which may lead to system hang.
>
> Mark the I2C adapter as suspended during noirq suspend and block new
> transfers until resume, ensuring that I2C transfers are only issued
> when hardware resources are available.
>
> Fixes: 358025ac091e ("i2c: imx: make controller available until system suspend_noirq() and from resume_noirq()")
> Cc: stable@vger.kernel.org
> Signed-off-by: Carlos Song <carlos.song@nxp.com>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> Change for v5:
> - Remake commit log including the issue detail from Mukesh's
> suggestion.
> Change for v4:
> - Restore hrtimer when pm_runtime_force_suspend failed when slave mode
> enabled.
> Change for v3:
> - Add hrtimer_cancel in i2c_imx_suspend_noirq to cancel slave_timer for
> safe suspend in i2c slave mode.
> Change for v2:
> - Call i2c_mark_adapter_suspended() before pm_runtime_force_suspend()
> to prevent potential deadlock if a transfer is active during suspend.
> - Roll back with i2c_mark_adapter_resumed() if pm_runtime_force_suspend()
> fails.
> ---
> drivers/i2c/busses/i2c-imx.c | 45 ++++++++++++++++++++++++++++++++++--
> 1 file changed, 43 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
> index 28313d0fad37..73317ddd5f02 100644
> --- a/drivers/i2c/busses/i2c-imx.c
> +++ b/drivers/i2c/busses/i2c-imx.c
> @@ -1922,6 +1922,47 @@ static int i2c_imx_runtime_resume(struct device *dev)
> return 0;
> }
>
> +static int __maybe_unused i2c_imx_suspend_noirq(struct device *dev)
> +{
> + struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev);
> + int ret;
> +
> + i2c_mark_adapter_suspended(&i2c_imx->adapter);
> +
> + /*
> + * Cancel the slave timer before powering down to prevent
> + * i2c_imx_slave_timeout() from accessing hardware registers
> + * while the clock is disabled.
> + */
> + hrtimer_cancel(&i2c_imx->slave_timer);
> +
> + ret = pm_runtime_force_suspend(dev);
> + if (ret) {
> + i2c_mark_adapter_resumed(&i2c_imx->adapter);
> + if (i2c_imx->slave) {
> + hrtimer_forward_now(&i2c_imx->slave_timer, I2C_IMX_CHECK_DELAY);
> + hrtimer_restart(&i2c_imx->slave_timer);
> + }
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static int __maybe_unused i2c_imx_resume_noirq(struct device *dev)
> +{
> + struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev);
> + int ret;
> +
> + ret = pm_runtime_force_resume(dev);
> + if (ret)
> + return ret;
> +
> + i2c_mark_adapter_resumed(&i2c_imx->adapter);
> +
> + return 0;
> +}
> +
> static int i2c_imx_suspend(struct device *dev)
> {
> /*
> @@ -1955,8 +1996,8 @@ static int i2c_imx_resume(struct device *dev)
> }
>
> static const struct dev_pm_ops i2c_imx_pm_ops = {
> - NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
> - pm_runtime_force_resume)
> + NOIRQ_SYSTEM_SLEEP_PM_OPS(i2c_imx_suspend_noirq,
> + i2c_imx_resume_noirq)
> SYSTEM_SLEEP_PM_OPS(i2c_imx_suspend, i2c_imx_resume)
> RUNTIME_PM_OPS(i2c_imx_runtime_suspend, i2c_imx_runtime_resume, NULL)
> };
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v5] i2c: imx: mark I2C adapter when hardware is powered down
2026-05-25 3:04 [PATCH v5] i2c: imx: mark I2C adapter when hardware is powered down Carlos Song (OSS)
` (2 preceding siblings ...)
2026-07-14 13:54 ` Frank Li
@ 2026-07-28 15:35 ` Andi Shyti
3 siblings, 0 replies; 5+ messages in thread
From: Andi Shyti @ 2026-07-28 15:35 UTC (permalink / raw)
To: Carlos Song (OSS)
Cc: o.rempel, kernel, s.hauer, festevam, carlos.song, haibo.chen,
linux-i2c, imx, linux-arm-kernel, linux-kernel, stable
Hi Carlos,
On Mon, May 25, 2026 at 11:04:00AM +0800, Carlos Song (OSS) wrote:
> From: Carlos Song <carlos.song@nxp.com>
>
> On some i.MX platforms, certain I2C client drivers keep a periodic
> workqueue which continues to trigger I2C transfers.
>
> During system suspend/resume, there exists a time window between:
> - suspend_noirq and the system entering suspend
> - the system starting to resume and resume_noirq
>
> In this window, the I2C controller resources such as clock and pinctrl
> may already be disabled or not yet restored.
>
> If a workqueue triggers an I2C transfer in this period, the driver
> attempts to access I2C registers while the hardware resources are
> unavailable, which may lead to system hang.
>
> Mark the I2C adapter as suspended during noirq suspend and block new
> transfers until resume, ensuring that I2C transfers are only issued
> when hardware resources are available.
>
> Fixes: 358025ac091e ("i2c: imx: make controller available until system suspend_noirq() and from resume_noirq()")
> Cc: stable@vger.kernel.org
> Signed-off-by: Carlos Song <carlos.song@nxp.com>
merged to i2c/i2c-fixes.
Thanks,
Andi
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-07-28 15:35 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-05-25 3:04 [PATCH v5] i2c: imx: mark I2C adapter when hardware is powered down Carlos Song (OSS)
2026-06-23 20:10 ` Andi Shyti
2026-06-25 7:15 ` Oleksij Rempel
2026-07-14 13:54 ` Frank Li
2026-07-28 15:35 ` Andi Shyti
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®