* [PATCH v4 1/7] mmc: sdhci-esdhc-imx: remove unnecessary mmc_card_wake_sdio_irq check for tuning save/restore
2026-07-03 10:42 [PATCH v4 0/7] mmc: sdhci-esdhc-imx: fix SDIO suspend/resume issues ziniu.wang_1
@ 2026-07-03 10:42 ` ziniu.wang_1
2026-07-05 8:48 ` Adrian Hunter
2026-07-03 10:42 ` [PATCH v4 2/7] mmc: sdhci-esdhc-imx: restore DLL override for DDR modes on resume ziniu.wang_1
` (5 subsequent siblings)
6 siblings, 1 reply; 15+ messages in thread
From: ziniu.wang_1 @ 2026-07-03 10:42 UTC (permalink / raw)
To: adrian.hunter, ulfh, haibo.chen, Frank.Li
Cc: s.hauer, kernel, festevam, imx, linux-mmc, s32, linux-arm-kernel,
linux-kernel
From: Luke Wang <ziniu.wang_1@nxp.com>
The tuning save/restore during system PM is conditioned on
mmc_card_wake_sdio_irq(), but this check is unrelated to whether
tuning values need to be preserved. The actual requirement is that
the card keeps power during suspend and the controller is a uSDHC.
SDIO devices using out-of-band GPIO wakeup maintain power during
suspend but do not set the SDIO IRQ wake flag. In this case the
tuning delay values are not saved/restored.
Remove the unnecessary mmc_card_wake_sdio_irq() condition from both
the suspend save and resume restore paths.
Fixes: c63d25cdc59a ("mmc: sdhci-esdhc-imx: Save tuning value when card stays powered in suspend")
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Reviewed-by: Haibo Chen <haibo.chen@nxp.com>
Signed-off-by: Luke Wang <ziniu.wang_1@nxp.com>
---
drivers/mmc/host/sdhci-esdhc-imx.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 18ecddd6df6f..6526d65538de 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -2064,8 +2064,7 @@ static int sdhci_esdhc_suspend(struct device *dev)
* to save the tuning delay value just in case the usdhc
* lost power during system PM.
*/
- if (mmc_card_keep_power(host->mmc) && mmc_card_wake_sdio_irq(host->mmc) &&
- esdhc_is_usdhc(imx_data))
+ if (mmc_card_keep_power(host->mmc) && esdhc_is_usdhc(imx_data))
sdhc_esdhc_tuning_save(host);
if (device_may_wakeup(dev)) {
@@ -2124,8 +2123,7 @@ static int sdhci_esdhc_resume(struct device *dev)
* restore the saved tuning delay value for the device which keep
* power during system PM.
*/
- if (mmc_card_keep_power(host->mmc) && mmc_card_wake_sdio_irq(host->mmc) &&
- esdhc_is_usdhc(imx_data))
+ if (mmc_card_keep_power(host->mmc) && esdhc_is_usdhc(imx_data))
sdhc_esdhc_tuning_restore(host);
pm_runtime_put_autosuspend(dev);
--
2.34.1
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH v4 1/7] mmc: sdhci-esdhc-imx: remove unnecessary mmc_card_wake_sdio_irq check for tuning save/restore
2026-07-03 10:42 ` [PATCH v4 1/7] mmc: sdhci-esdhc-imx: remove unnecessary mmc_card_wake_sdio_irq check for tuning save/restore ziniu.wang_1
@ 2026-07-05 8:48 ` Adrian Hunter
0 siblings, 0 replies; 15+ messages in thread
From: Adrian Hunter @ 2026-07-05 8:48 UTC (permalink / raw)
To: ziniu.wang_1, ulfh, haibo.chen, Frank.Li
Cc: s.hauer, kernel, festevam, imx, linux-mmc, s32, linux-arm-kernel,
linux-kernel
On 03/07/2026 13:42, ziniu.wang_1@oss.nxp.com wrote:
> From: Luke Wang <ziniu.wang_1@nxp.com>
>
> The tuning save/restore during system PM is conditioned on
> mmc_card_wake_sdio_irq(), but this check is unrelated to whether
> tuning values need to be preserved. The actual requirement is that
> the card keeps power during suspend and the controller is a uSDHC.
>
> SDIO devices using out-of-band GPIO wakeup maintain power during
> suspend but do not set the SDIO IRQ wake flag. In this case the
> tuning delay values are not saved/restored.
>
> Remove the unnecessary mmc_card_wake_sdio_irq() condition from both
> the suspend save and resume restore paths.
>
> Fixes: c63d25cdc59a ("mmc: sdhci-esdhc-imx: Save tuning value when card stays powered in suspend")
> Reviewed-by: Frank Li <Frank.Li@nxp.com>
> Reviewed-by: Haibo Chen <haibo.chen@nxp.com>
> Signed-off-by: Luke Wang <ziniu.wang_1@nxp.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
> ---
> drivers/mmc/host/sdhci-esdhc-imx.c | 6 ++----
> 1 file changed, 2 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 18ecddd6df6f..6526d65538de 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -2064,8 +2064,7 @@ static int sdhci_esdhc_suspend(struct device *dev)
> * to save the tuning delay value just in case the usdhc
> * lost power during system PM.
> */
> - if (mmc_card_keep_power(host->mmc) && mmc_card_wake_sdio_irq(host->mmc) &&
> - esdhc_is_usdhc(imx_data))
> + if (mmc_card_keep_power(host->mmc) && esdhc_is_usdhc(imx_data))
> sdhc_esdhc_tuning_save(host);
>
> if (device_may_wakeup(dev)) {
> @@ -2124,8 +2123,7 @@ static int sdhci_esdhc_resume(struct device *dev)
> * restore the saved tuning delay value for the device which keep
> * power during system PM.
> */
> - if (mmc_card_keep_power(host->mmc) && mmc_card_wake_sdio_irq(host->mmc) &&
> - esdhc_is_usdhc(imx_data))
> + if (mmc_card_keep_power(host->mmc) && esdhc_is_usdhc(imx_data))
> sdhc_esdhc_tuning_restore(host);
>
> pm_runtime_put_autosuspend(dev);
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v4 2/7] mmc: sdhci-esdhc-imx: restore DLL override for DDR modes on resume
2026-07-03 10:42 [PATCH v4 0/7] mmc: sdhci-esdhc-imx: fix SDIO suspend/resume issues ziniu.wang_1
2026-07-03 10:42 ` [PATCH v4 1/7] mmc: sdhci-esdhc-imx: remove unnecessary mmc_card_wake_sdio_irq check for tuning save/restore ziniu.wang_1
@ 2026-07-03 10:42 ` ziniu.wang_1
2026-07-05 8:49 ` Adrian Hunter
2026-07-03 10:42 ` [PATCH v4 3/7] mmc: sdhci-esdhc-imx: restore pinctrl before restoring ios timing " ziniu.wang_1
` (4 subsequent siblings)
6 siblings, 1 reply; 15+ messages in thread
From: ziniu.wang_1 @ 2026-07-03 10:42 UTC (permalink / raw)
To: adrian.hunter, ulfh, haibo.chen, Frank.Li
Cc: s.hauer, kernel, festevam, imx, linux-mmc, s32, linux-arm-kernel,
linux-kernel
From: Luke Wang <ziniu.wang_1@nxp.com>
sdhci_esdhc_imx_hwinit() unconditionally clears ESDHC_DLL_CTRL by
writing zero. For SDIO devices that keep power during system suspend
and operate in DDR mode, the card remains in DDR timing while the host
DLL override configuration is lost.
Extract the DLL override setup from esdhc_set_uhs_signaling() into
a helper esdhc_set_dll_override(), and call it on the resume path
when the card kept power and is using a DDR timing mode.
Fixes: 676a83855614 ("mmc: host: sdhci-esdhc-imx: refactor the system PM logic")
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Reviewed-by: Haibo Chen <haibo.chen@nxp.com>
Signed-off-by: Luke Wang <ziniu.wang_1@nxp.com>
---
drivers/mmc/host/sdhci-esdhc-imx.c | 39 +++++++++++++++++++++---------
1 file changed, 28 insertions(+), 11 deletions(-)
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 6526d65538de..7230d70e02ae 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -1349,6 +1349,23 @@ static int esdhc_change_pinstate(struct sdhci_host *host,
return pinctrl_select_state(imx_data->pinctrl, pinctrl);
}
+static void esdhc_set_dll_override(struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
+ struct esdhc_platform_data *boarddata = &imx_data->boarddata;
+ u32 v;
+
+ if (!boarddata->delay_line)
+ return;
+
+ v = boarddata->delay_line << ESDHC_DLL_OVERRIDE_VAL_SHIFT |
+ (1 << ESDHC_DLL_OVERRIDE_EN_SHIFT);
+ if (is_imx53_esdhc(imx_data))
+ v <<= 1;
+ writel(v, host->ioaddr + ESDHC_DLL_CTRL);
+}
+
/*
* For HS400 eMMC, there is a data_strobe line. This signal is generated
* by the device and used for data output and CRC status response output
@@ -1404,7 +1421,6 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
u32 m;
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
- struct esdhc_platform_data *boarddata = &imx_data->boarddata;
/* disable ddr mode and disable HS400 mode */
m = readl(host->ioaddr + ESDHC_MIX_CTRL);
@@ -1425,15 +1441,7 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
m |= ESDHC_MIX_CTRL_DDREN;
writel(m, host->ioaddr + ESDHC_MIX_CTRL);
imx_data->is_ddr = 1;
- if (boarddata->delay_line) {
- u32 v;
- v = boarddata->delay_line <<
- ESDHC_DLL_OVERRIDE_VAL_SHIFT |
- (1 << ESDHC_DLL_OVERRIDE_EN_SHIFT);
- if (is_imx53_esdhc(imx_data))
- v <<= 1;
- writel(v, host->ioaddr + ESDHC_DLL_CTRL);
- }
+ esdhc_set_dll_override(host);
break;
case MMC_TIMING_MMC_HS400:
m |= ESDHC_MIX_CTRL_DDREN | ESDHC_MIX_CTRL_HS400_EN;
@@ -2123,9 +2131,18 @@ static int sdhci_esdhc_resume(struct device *dev)
* restore the saved tuning delay value for the device which keep
* power during system PM.
*/
- if (mmc_card_keep_power(host->mmc) && esdhc_is_usdhc(imx_data))
+ if (mmc_card_keep_power(host->mmc) && esdhc_is_usdhc(imx_data)) {
sdhc_esdhc_tuning_restore(host);
+ /*
+ * Restore DLL override for DDR modes. hwinit unconditionally
+ * clears ESDHC_DLL_CTRL, but the card is still in DDR mode.
+ */
+ if (host->timing == MMC_TIMING_UHS_DDR50 ||
+ host->timing == MMC_TIMING_MMC_DDR52)
+ esdhc_set_dll_override(host);
+ }
+
pm_runtime_put_autosuspend(dev);
return ret;
--
2.34.1
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH v4 2/7] mmc: sdhci-esdhc-imx: restore DLL override for DDR modes on resume
2026-07-03 10:42 ` [PATCH v4 2/7] mmc: sdhci-esdhc-imx: restore DLL override for DDR modes on resume ziniu.wang_1
@ 2026-07-05 8:49 ` Adrian Hunter
0 siblings, 0 replies; 15+ messages in thread
From: Adrian Hunter @ 2026-07-05 8:49 UTC (permalink / raw)
To: ziniu.wang_1, ulfh, haibo.chen, Frank.Li
Cc: s.hauer, kernel, festevam, imx, linux-mmc, s32, linux-arm-kernel,
linux-kernel
On 03/07/2026 13:42, ziniu.wang_1@oss.nxp.com wrote:
> From: Luke Wang <ziniu.wang_1@nxp.com>
>
> sdhci_esdhc_imx_hwinit() unconditionally clears ESDHC_DLL_CTRL by
> writing zero. For SDIO devices that keep power during system suspend
> and operate in DDR mode, the card remains in DDR timing while the host
> DLL override configuration is lost.
>
> Extract the DLL override setup from esdhc_set_uhs_signaling() into
> a helper esdhc_set_dll_override(), and call it on the resume path
> when the card kept power and is using a DDR timing mode.
>
> Fixes: 676a83855614 ("mmc: host: sdhci-esdhc-imx: refactor the system PM logic")
> Reviewed-by: Frank Li <Frank.Li@nxp.com>
> Reviewed-by: Haibo Chen <haibo.chen@nxp.com>
> Signed-off-by: Luke Wang <ziniu.wang_1@nxp.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
> ---
> drivers/mmc/host/sdhci-esdhc-imx.c | 39 +++++++++++++++++++++---------
> 1 file changed, 28 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 6526d65538de..7230d70e02ae 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -1349,6 +1349,23 @@ static int esdhc_change_pinstate(struct sdhci_host *host,
> return pinctrl_select_state(imx_data->pinctrl, pinctrl);
> }
>
> +static void esdhc_set_dll_override(struct sdhci_host *host)
> +{
> + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> + struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
> + struct esdhc_platform_data *boarddata = &imx_data->boarddata;
> + u32 v;
> +
> + if (!boarddata->delay_line)
> + return;
> +
> + v = boarddata->delay_line << ESDHC_DLL_OVERRIDE_VAL_SHIFT |
> + (1 << ESDHC_DLL_OVERRIDE_EN_SHIFT);
> + if (is_imx53_esdhc(imx_data))
> + v <<= 1;
> + writel(v, host->ioaddr + ESDHC_DLL_CTRL);
> +}
> +
> /*
> * For HS400 eMMC, there is a data_strobe line. This signal is generated
> * by the device and used for data output and CRC status response output
> @@ -1404,7 +1421,6 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
> u32 m;
> struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
> - struct esdhc_platform_data *boarddata = &imx_data->boarddata;
>
> /* disable ddr mode and disable HS400 mode */
> m = readl(host->ioaddr + ESDHC_MIX_CTRL);
> @@ -1425,15 +1441,7 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
> m |= ESDHC_MIX_CTRL_DDREN;
> writel(m, host->ioaddr + ESDHC_MIX_CTRL);
> imx_data->is_ddr = 1;
> - if (boarddata->delay_line) {
> - u32 v;
> - v = boarddata->delay_line <<
> - ESDHC_DLL_OVERRIDE_VAL_SHIFT |
> - (1 << ESDHC_DLL_OVERRIDE_EN_SHIFT);
> - if (is_imx53_esdhc(imx_data))
> - v <<= 1;
> - writel(v, host->ioaddr + ESDHC_DLL_CTRL);
> - }
> + esdhc_set_dll_override(host);
> break;
> case MMC_TIMING_MMC_HS400:
> m |= ESDHC_MIX_CTRL_DDREN | ESDHC_MIX_CTRL_HS400_EN;
> @@ -2123,9 +2131,18 @@ static int sdhci_esdhc_resume(struct device *dev)
> * restore the saved tuning delay value for the device which keep
> * power during system PM.
> */
> - if (mmc_card_keep_power(host->mmc) && esdhc_is_usdhc(imx_data))
> + if (mmc_card_keep_power(host->mmc) && esdhc_is_usdhc(imx_data)) {
> sdhc_esdhc_tuning_restore(host);
>
> + /*
> + * Restore DLL override for DDR modes. hwinit unconditionally
> + * clears ESDHC_DLL_CTRL, but the card is still in DDR mode.
> + */
> + if (host->timing == MMC_TIMING_UHS_DDR50 ||
> + host->timing == MMC_TIMING_MMC_DDR52)
> + esdhc_set_dll_override(host);
> + }
> +
> pm_runtime_put_autosuspend(dev);
>
> return ret;
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v4 3/7] mmc: sdhci-esdhc-imx: restore pinctrl before restoring ios timing on resume
2026-07-03 10:42 [PATCH v4 0/7] mmc: sdhci-esdhc-imx: fix SDIO suspend/resume issues ziniu.wang_1
2026-07-03 10:42 ` [PATCH v4 1/7] mmc: sdhci-esdhc-imx: remove unnecessary mmc_card_wake_sdio_irq check for tuning save/restore ziniu.wang_1
2026-07-03 10:42 ` [PATCH v4 2/7] mmc: sdhci-esdhc-imx: restore DLL override for DDR modes on resume ziniu.wang_1
@ 2026-07-03 10:42 ` ziniu.wang_1
2026-07-03 11:12 ` sashiko-bot
2026-07-05 8:14 ` Adrian Hunter
2026-07-03 10:42 ` [PATCH v4 4/7] mmc: sdhci-esdhc-imx: disable irq during suspend to fix unhandled interrupt ziniu.wang_1
` (3 subsequent siblings)
6 siblings, 2 replies; 15+ messages in thread
From: ziniu.wang_1 @ 2026-07-03 10:42 UTC (permalink / raw)
To: adrian.hunter, ulfh, haibo.chen, Frank.Li
Cc: s.hauer, kernel, festevam, imx, linux-mmc, s32, linux-arm-kernel,
linux-kernel
From: Luke Wang <ziniu.wang_1@nxp.com>
SDIO devices such as WiFi may keep power during suspend, so the MMC
core skips full card re-initialization on resume and directly restores
the host controller's ios timing to match the card. For DDR mode,
pm_runtime_force_resume() sets DDR_EN before the pin configuration is
restored from sleep state.
This is related to the SoC IP integration: switching pinctrl setting
(changing alt from GPIO to USDHC) impacts the internal loopback path.
If pinctrl configures the pad to GPIO function, once DDR_EN is set, the
DLL delay will be fixed based on the GPIO function loopback path. When
the pinctrl is later changed to USDHC function, the internal loopback
path changes, making the original fixed sample point no longer suitable
for the current loopback path. This causes persistent read CRC errors on
subsequent data transfers.
SD/eMMC running in DDR mode are unaffected as they are fully
re-initialized from legacy timing after resume.
Fix this by restoring the pinctrl state based on current timing mode
using esdhc_change_pinstate() before pm_runtime_force_resume(). This
ensures the correct pin configuration (e.g., 100/200MHz for UHS modes)
is applied before DDR_EN is set. Only restore for non-wakeup devices
since wakeup devices kept their active pin state during suspend.
Fixes: 676a83855614 ("mmc: host: sdhci-esdhc-imx: refactor the system PM logic")
Reviewed-by: Haibo Chen <haibo.chen@nxp.com>
Signed-off-by: Luke Wang <ziniu.wang_1@nxp.com>
---
drivers/mmc/host/sdhci-esdhc-imx.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 7230d70e02ae..3b1e63425a19 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -2113,6 +2113,12 @@ static int sdhci_esdhc_resume(struct device *dev)
struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
int ret;
+ if (!device_may_wakeup(dev)) {
+ ret = esdhc_change_pinstate(host, host->timing);
+ if (ret)
+ dev_warn(dev, "Failed to restore pinctrl state\n");
+ }
+
pm_runtime_force_resume(dev);
ret = mmc_gpio_set_cd_wake(host->mmc, false);
--
2.34.1
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH v4 3/7] mmc: sdhci-esdhc-imx: restore pinctrl before restoring ios timing on resume
2026-07-03 10:42 ` [PATCH v4 3/7] mmc: sdhci-esdhc-imx: restore pinctrl before restoring ios timing " ziniu.wang_1
@ 2026-07-03 11:12 ` sashiko-bot
2026-07-05 8:14 ` Adrian Hunter
1 sibling, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-07-03 11:12 UTC (permalink / raw)
To: ziniu.wang_1; +Cc: Frank.Li, imx
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
New issues:
- [Medium] The patch introduces unconditional kernel log spam ('Failed to restore pinctrl state') on every system resume for devices lacking high-speed pinctrl states.
Pre-existing issues:
- [High] This problem wasn't introduced by this patch, but devices with a 'sleep' pinctrl state but lacking high-speed states ('100mhz'/'200mhz') fail to exit sleep state on resume.
--
commit 831a40635a59ef0e713e681b7fa2933e80e52391
Author: Luke Wang <ziniu.wang_1@nxp.com>
mmc: sdhci-esdhc-imx: restore pinctrl before restoring ios timing on resume
SDIO devices such as WiFi may keep power during suspend, so the MMC
core skips full card re-initialization on resume and directly restores
the host controller's ios timing to match the card. For DDR mode,
pm_runtime_force_resume() sets DDR_EN before the pin configuration is
restored from sleep state.
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 7230d70e02ae1..3b1e63425a193 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -2113,6 +2113,12 @@ static int sdhci_esdhc_resume(struct device *dev)
> struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
> int ret;
>
> + if (!device_may_wakeup(dev)) {
> + ret = esdhc_change_pinstate(host, host->timing);
> + if (ret)
> + dev_warn(dev, "Failed to restore pinctrl state\n");
[Severity: Medium]
Does this new dev_warn() cause log spam on every system resume for devices
without high-speed pinctrl states?
If a board doesn't define the optional pins_100mhz or pins_200mhz states,
esdhc_change_pinstate() returns -EINVAL:
drivers/mmc/host/sdhci-esdhc-imx.c:esdhc_change_pinstate() {
...
if (IS_ERR(imx_data->pinctrl) ||
IS_ERR(imx_data->pins_100mhz) ||
IS_ERR(imx_data->pins_200mhz))
return -EINVAL;
...
}
This means standard SD setups without UHS pins will unconditionally see this
warning on every system resume.
[Severity: High]
This is a pre-existing issue, but does this early return in
esdhc_change_pinstate() prevent restoring the default pin state when high-speed
pins are not defined?
If esdhc_change_pinstate() returns early with -EINVAL, the default pin state
is never restored for legacy timings:
drivers/mmc/host/sdhci-esdhc-imx.c:esdhc_change_pinstate() {
...
switch (uhs) {
...
default:
/* back to default state for other legacy timing */
return pinctrl_select_default_state(mmc_dev(host->mmc));
}
...
}
For devices with a sleep pinctrl state but lacking high-speed states,
they would fail to exit the sleep state on resume, leaving the pins in a
low-power configuration and potentially making the device unusable.
> + }
> +
> pm_runtime_force_resume(dev);
>
> ret = mmc_gpio_set_cd_wake(host->mmc, false);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260703104208.3426374-1-ziniu.wang_1@oss.nxp.com?part=3
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH v4 3/7] mmc: sdhci-esdhc-imx: restore pinctrl before restoring ios timing on resume
2026-07-03 10:42 ` [PATCH v4 3/7] mmc: sdhci-esdhc-imx: restore pinctrl before restoring ios timing " ziniu.wang_1
2026-07-03 11:12 ` sashiko-bot
@ 2026-07-05 8:14 ` Adrian Hunter
1 sibling, 0 replies; 15+ messages in thread
From: Adrian Hunter @ 2026-07-05 8:14 UTC (permalink / raw)
To: ziniu.wang_1, ulfh, haibo.chen, Frank.Li
Cc: s.hauer, kernel, festevam, imx, linux-mmc, s32, linux-arm-kernel,
linux-kernel
On 03/07/2026 13:42, ziniu.wang_1@oss.nxp.com wrote:
> From: Luke Wang <ziniu.wang_1@nxp.com>
>
> SDIO devices such as WiFi may keep power during suspend, so the MMC
> core skips full card re-initialization on resume and directly restores
> the host controller's ios timing to match the card. For DDR mode,
> pm_runtime_force_resume() sets DDR_EN before the pin configuration is
> restored from sleep state.
>
> This is related to the SoC IP integration: switching pinctrl setting
> (changing alt from GPIO to USDHC) impacts the internal loopback path.
> If pinctrl configures the pad to GPIO function, once DDR_EN is set, the
> DLL delay will be fixed based on the GPIO function loopback path. When
> the pinctrl is later changed to USDHC function, the internal loopback
> path changes, making the original fixed sample point no longer suitable
> for the current loopback path. This causes persistent read CRC errors on
> subsequent data transfers.
>
> SD/eMMC running in DDR mode are unaffected as they are fully
> re-initialized from legacy timing after resume.
>
> Fix this by restoring the pinctrl state based on current timing mode
> using esdhc_change_pinstate() before pm_runtime_force_resume(). This
> ensures the correct pin configuration (e.g., 100/200MHz for UHS modes)
> is applied before DDR_EN is set. Only restore for non-wakeup devices
> since wakeup devices kept their active pin state during suspend.
>
> Fixes: 676a83855614 ("mmc: host: sdhci-esdhc-imx: refactor the system PM logic")
> Reviewed-by: Haibo Chen <haibo.chen@nxp.com>
> Signed-off-by: Luke Wang <ziniu.wang_1@nxp.com>
> ---
> drivers/mmc/host/sdhci-esdhc-imx.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 7230d70e02ae..3b1e63425a19 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -2113,6 +2113,12 @@ static int sdhci_esdhc_resume(struct device *dev)
> struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
> int ret;
>
> + if (!device_may_wakeup(dev)) {
> + ret = esdhc_change_pinstate(host, host->timing);
> + if (ret)
> + dev_warn(dev, "Failed to restore pinctrl state\n");
Sashiko has a point about this dev_warn(). See its first comment in:
https://sashiko.dev/#/patchset/20260703104208.3426374-1-ziniu.wang_1%40oss.nxp.com?part=3
> + }
> +
> pm_runtime_force_resume(dev);
>
> ret = mmc_gpio_set_cd_wake(host->mmc, false);
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v4 4/7] mmc: sdhci-esdhc-imx: disable irq during suspend to fix unhandled interrupt
2026-07-03 10:42 [PATCH v4 0/7] mmc: sdhci-esdhc-imx: fix SDIO suspend/resume issues ziniu.wang_1
` (2 preceding siblings ...)
2026-07-03 10:42 ` [PATCH v4 3/7] mmc: sdhci-esdhc-imx: restore pinctrl before restoring ios timing " ziniu.wang_1
@ 2026-07-03 10:42 ` ziniu.wang_1
2026-07-05 8:30 ` Adrian Hunter
2026-07-03 10:42 ` [PATCH v4 5/7] mmc: sdhci-esdhc-imx: use pm_runtime_resume_and_get() in suspend ziniu.wang_1
` (2 subsequent siblings)
6 siblings, 1 reply; 15+ messages in thread
From: ziniu.wang_1 @ 2026-07-03 10:42 UTC (permalink / raw)
To: adrian.hunter, ulfh, haibo.chen, Frank.Li
Cc: s.hauer, kernel, festevam, imx, linux-mmc, s32, linux-arm-kernel,
linux-kernel
From: Luke Wang <ziniu.wang_1@nxp.com>
When using WIFI out-of-band wakeup, an "irq xxx: nobody cared" warning
occurs. This happens because the usdhc interrupt is not disabled during
system suspend when device_may_wakeup() returns false.
The sequence of events leading to this issue:
1. System enters suspend without disabling usdhc interrupt
(because device_may_wakeup() returns false for usdhc device)
2. WIFI out-of-band wakeup triggers system resume via GPIO interrupt
3. WIFI sends a Card interrupt before usdhc has fully resumed
4. usdhc is still in runtime suspend state and cannot handle the
interrupt properly
5. The unhandled interrupt triggers "nobody cared" warning
Fix this by unconditionally disabling the usdhc interrupt during suspend
and re-enabling it during resume, regardless of the wakeup capability.
This ensures no interrupts are processed during the suspend/resume
transition.
Fixes: 676a83855614 ("mmc: host: sdhci-esdhc-imx: refactor the system PM logic")
Reviewed-by: Haibo Chen <haibo.chen@nxp.com>
Signed-off-by: Luke Wang <ziniu.wang_1@nxp.com>
---
drivers/mmc/host/sdhci-esdhc-imx.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 3b1e63425a19..ade99dabdb5f 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -2075,9 +2075,10 @@ static int sdhci_esdhc_suspend(struct device *dev)
if (mmc_card_keep_power(host->mmc) && esdhc_is_usdhc(imx_data))
sdhc_esdhc_tuning_save(host);
+ /* The irqs of imx are not shared. It is safe to disable */
+ disable_irq(host->irq);
+
if (device_may_wakeup(dev)) {
- /* The irqs of imx are not shared. It is safe to disable */
- disable_irq(host->irq);
ret = sdhci_enable_irq_wakeups(host);
if (!ret)
dev_warn(dev, "Failed to enable irq wakeup\n");
@@ -2128,10 +2129,10 @@ static int sdhci_esdhc_resume(struct device *dev)
/* re-initialize hw state in case it's lost in low power mode */
sdhci_esdhc_imx_hwinit(host);
- if (host->irq_wake_enabled) {
+ if (host->irq_wake_enabled)
sdhci_disable_irq_wakeups(host);
- enable_irq(host->irq);
- }
+
+ enable_irq(host->irq);
/*
* restore the saved tuning delay value for the device which keep
--
2.34.1
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH v4 4/7] mmc: sdhci-esdhc-imx: disable irq during suspend to fix unhandled interrupt
2026-07-03 10:42 ` [PATCH v4 4/7] mmc: sdhci-esdhc-imx: disable irq during suspend to fix unhandled interrupt ziniu.wang_1
@ 2026-07-05 8:30 ` Adrian Hunter
0 siblings, 0 replies; 15+ messages in thread
From: Adrian Hunter @ 2026-07-05 8:30 UTC (permalink / raw)
To: ziniu.wang_1, ulfh, haibo.chen, Frank.Li
Cc: s.hauer, kernel, festevam, imx, linux-mmc, s32, linux-arm-kernel,
linux-kernel
On 03/07/2026 13:42, ziniu.wang_1@oss.nxp.com wrote:
> From: Luke Wang <ziniu.wang_1@nxp.com>
>
> When using WIFI out-of-band wakeup, an "irq xxx: nobody cared" warning
> occurs. This happens because the usdhc interrupt is not disabled during
> system suspend when device_may_wakeup() returns false.
>
> The sequence of events leading to this issue:
> 1. System enters suspend without disabling usdhc interrupt
> (because device_may_wakeup() returns false for usdhc device)
> 2. WIFI out-of-band wakeup triggers system resume via GPIO interrupt
> 3. WIFI sends a Card interrupt before usdhc has fully resumed
> 4. usdhc is still in runtime suspend state and cannot handle the
> interrupt properly
> 5. The unhandled interrupt triggers "nobody cared" warning
>
> Fix this by unconditionally disabling the usdhc interrupt during suspend
> and re-enabling it during resume, regardless of the wakeup capability.
> This ensures no interrupts are processed during the suspend/resume
> transition.
>
> Fixes: 676a83855614 ("mmc: host: sdhci-esdhc-imx: refactor the system PM logic")
> Reviewed-by: Haibo Chen <haibo.chen@nxp.com>
> Signed-off-by: Luke Wang <ziniu.wang_1@nxp.com>
> ---
> drivers/mmc/host/sdhci-esdhc-imx.c | 11 ++++++-----
> 1 file changed, 6 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 3b1e63425a19..ade99dabdb5f 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -2075,9 +2075,10 @@ static int sdhci_esdhc_suspend(struct device *dev)
> if (mmc_card_keep_power(host->mmc) && esdhc_is_usdhc(imx_data))
> sdhc_esdhc_tuning_save(host);
>
> + /* The irqs of imx are not shared. It is safe to disable */
> + disable_irq(host->irq);
Pre-existing, but IRQ stays disabled even if there is an error later on
> +
> if (device_may_wakeup(dev)) {
> - /* The irqs of imx are not shared. It is safe to disable */
> - disable_irq(host->irq);
> ret = sdhci_enable_irq_wakeups(host);
> if (!ret)
> dev_warn(dev, "Failed to enable irq wakeup\n");
> @@ -2128,10 +2129,10 @@ static int sdhci_esdhc_resume(struct device *dev)
> /* re-initialize hw state in case it's lost in low power mode */
> sdhci_esdhc_imx_hwinit(host);
>
> - if (host->irq_wake_enabled) {
> + if (host->irq_wake_enabled)
> sdhci_disable_irq_wakeups(host);
> - enable_irq(host->irq);
> - }
> +
> + enable_irq(host->irq);
Is it OK to enable interrupts before sdhc_esdhc_tuning_restore()
and esdhc_set_dll_override() ?
>
> /*
> * restore the saved tuning delay value for the device which keep
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v4 5/7] mmc: sdhci-esdhc-imx: use pm_runtime_resume_and_get() in suspend
2026-07-03 10:42 [PATCH v4 0/7] mmc: sdhci-esdhc-imx: fix SDIO suspend/resume issues ziniu.wang_1
` (3 preceding siblings ...)
2026-07-03 10:42 ` [PATCH v4 4/7] mmc: sdhci-esdhc-imx: disable irq during suspend to fix unhandled interrupt ziniu.wang_1
@ 2026-07-03 10:42 ` ziniu.wang_1
2026-07-03 11:18 ` sashiko-bot
2026-07-03 10:42 ` [PATCH v4 6/7] mmc: sdhci-esdhc-imx: make non-fatal errors non-blocking " ziniu.wang_1
2026-07-03 10:42 ` [PATCH v4 7/7] mmc: sdhci-esdhc-imx: fix resume error handling ziniu.wang_1
6 siblings, 1 reply; 15+ messages in thread
From: ziniu.wang_1 @ 2026-07-03 10:42 UTC (permalink / raw)
To: adrian.hunter, ulfh, haibo.chen, Frank.Li
Cc: s.hauer, kernel, festevam, imx, linux-mmc, s32, linux-arm-kernel,
linux-kernel
From: Luke Wang <ziniu.wang_1@nxp.com>
Replace pm_runtime_get_sync() with pm_runtime_resume_and_get() to
simplify error handling. pm_runtime_resume_and_get() automatically
drops the usage counter on failure, avoiding the need for a separate
pm_runtime_put_noidle() call. If it fails, the device is unclocked and
accessing hardware registers would cause a kernel panic, so return the
error immediately.
Signed-off-by: Luke Wang <ziniu.wang_1@nxp.com>
---
drivers/mmc/host/sdhci-esdhc-imx.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index ade99dabdb5f..30aef7bc1fc6 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -2059,7 +2059,9 @@ static int sdhci_esdhc_suspend(struct device *dev)
* 2, make sure the pm_runtime_force_resume() in sdhci_esdhc_resume() really
* invoke its ->runtime_resume callback (needs_force_resume = 1).
*/
- pm_runtime_get_sync(dev);
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret)
+ return ret;
if ((imx_data->socdata->flags & ESDHC_FLAG_STATE_LOST_IN_LPMODE) &&
(host->tuning_mode != SDHCI_TUNING_MODE_1)) {
--
2.34.1
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH v4 5/7] mmc: sdhci-esdhc-imx: use pm_runtime_resume_and_get() in suspend
2026-07-03 10:42 ` [PATCH v4 5/7] mmc: sdhci-esdhc-imx: use pm_runtime_resume_and_get() in suspend ziniu.wang_1
@ 2026-07-03 11:18 ` sashiko-bot
0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-07-03 11:18 UTC (permalink / raw)
To: ziniu.wang_1; +Cc: imx, Frank.Li
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Unchecked `pm_runtime_get_sync()` in `sdhci_esdhc_imx_remove()` can lead to unclocked hardware register access and a kernel panic.
--
commit 27f08d0dd0a0d98186f1636e70aa4e0a00112c22
Author: Luke Wang <ziniu.wang_1@nxp.com>
mmc: sdhci-esdhc-imx: use pm_runtime_resume_and_get() in suspend
This patch replaces a call to pm_runtime_get_sync() with
pm_runtime_resume_and_get() during device suspend to simplify error handling.
It ensures that if the resume fails, the driver returns immediately instead
of proceeding to access unclocked hardware registers which would cause a
kernel panic.
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index ade99dabdb5fd..30aef7bc1fc67 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -2059,7 +2059,9 @@ static int sdhci_esdhc_suspend(struct device *dev)
> * 2, make sure the pm_runtime_force_resume() in sdhci_esdhc_resume() really
> * invoke its ->runtime_resume callback (needs_force_resume = 1).
> */
> - pm_runtime_get_sync(dev);
> + ret = pm_runtime_resume_and_get(dev);
> + if (ret)
> + return ret;
[Severity: High]
This is a pre-existing issue, and not a bug introduced by this patch, but
since you are fixing unchecked runtime PM calls here, could a similar panic
happen during device removal?
Looking at sdhci_esdhc_imx_remove(), there is an unchecked call to
pm_runtime_get_sync() right before reading from the hardware:
sdhci_esdhc_imx_remove() {
...
pm_runtime_get_sync(&pdev->dev);
dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
...
}
If the runtime resume fails in the removal path, the clocks would remain
disabled.
Would the subsequent readl() trigger a bus fault for the same reason?
Should we add error handling or switch to pm_runtime_resume_and_get() in
sdhci_esdhc_imx_remove() as well?
>
> if ((imx_data->socdata->flags & ESDHC_FLAG_STATE_LOST_IN_LPMODE) &&
> (host->tuning_mode != SDHCI_TUNING_MODE_1)) {
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260703104208.3426374-1-ziniu.wang_1@oss.nxp.com?part=5
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v4 6/7] mmc: sdhci-esdhc-imx: make non-fatal errors non-blocking in suspend
2026-07-03 10:42 [PATCH v4 0/7] mmc: sdhci-esdhc-imx: fix SDIO suspend/resume issues ziniu.wang_1
` (4 preceding siblings ...)
2026-07-03 10:42 ` [PATCH v4 5/7] mmc: sdhci-esdhc-imx: use pm_runtime_resume_and_get() in suspend ziniu.wang_1
@ 2026-07-03 10:42 ` ziniu.wang_1
2026-07-03 10:42 ` [PATCH v4 7/7] mmc: sdhci-esdhc-imx: fix resume error handling ziniu.wang_1
6 siblings, 0 replies; 15+ messages in thread
From: ziniu.wang_1 @ 2026-07-03 10:42 UTC (permalink / raw)
To: adrian.hunter, ulfh, haibo.chen, Frank.Li
Cc: s.hauer, kernel, festevam, imx, linux-mmc, s32, linux-arm-kernel,
linux-kernel
From: Luke Wang <ziniu.wang_1@nxp.com>
Make pinctrl_pm_select_sleep_state() and mmc_gpio_set_cd_wake() failures
non-fatal in the suspend path. These failures only mean slightly higher
power consumption or missing CD wakeup capability, but should not block
system suspend.
Also change the function to always return 0 on the success path instead
of propagating non-fatal warning return values.
Signed-off-by: Luke Wang <ziniu.wang_1@nxp.com>
---
drivers/mmc/host/sdhci-esdhc-imx.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 30aef7bc1fc6..6920f0425508 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -2095,10 +2095,12 @@ static int sdhci_esdhc_suspend(struct device *dev)
*/
ret = pinctrl_pm_select_sleep_state(dev);
if (ret)
- return ret;
+ dev_warn(dev, "Failed to select sleep pinctrl state\n");
}
ret = mmc_gpio_set_cd_wake(host->mmc, true);
+ if (ret)
+ dev_warn(dev, "Failed to enable cd wake\n");
/*
* Make sure invoke runtime_suspend to gate off clock.
@@ -2106,7 +2108,7 @@ static int sdhci_esdhc_suspend(struct device *dev)
*/
pm_runtime_force_suspend(dev);
- return ret;
+ return 0;
}
static int sdhci_esdhc_resume(struct device *dev)
--
2.34.1
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH v4 7/7] mmc: sdhci-esdhc-imx: fix resume error handling
2026-07-03 10:42 [PATCH v4 0/7] mmc: sdhci-esdhc-imx: fix SDIO suspend/resume issues ziniu.wang_1
` (5 preceding siblings ...)
2026-07-03 10:42 ` [PATCH v4 6/7] mmc: sdhci-esdhc-imx: make non-fatal errors non-blocking " ziniu.wang_1
@ 2026-07-03 10:42 ` ziniu.wang_1
2026-07-03 11:32 ` sashiko-bot
6 siblings, 1 reply; 15+ messages in thread
From: ziniu.wang_1 @ 2026-07-03 10:42 UTC (permalink / raw)
To: adrian.hunter, ulfh, haibo.chen, Frank.Li
Cc: s.hauer, kernel, festevam, imx, linux-mmc, s32, linux-arm-kernel,
linux-kernel
From: Luke Wang <ziniu.wang_1@nxp.com>
Check pm_runtime_force_resume() return value in resume. If it fails
(clock enable failure), return immediately since accessing hardware
registers on an unclocked device would cause a kernel panic.
The early return intentionally skips enable_irq() and
sdhci_disable_irq_wakeups() because the IRQ handler reads
SDHCI_INT_STATUS, which would also fault without clocks. The PM runtime
usage counter leak only affects this already-broken device instance and
is an acceptable tradeoff to preserve system stability.
Remove the return value check for mmc_gpio_set_cd_wake(host->mmc, false)
since disable_irq_wake() called internally always returns 0.
Also return 0 explicitly on the success path instead of propagating
stale return values.
Signed-off-by: Luke Wang <ziniu.wang_1@nxp.com>
---
drivers/mmc/host/sdhci-esdhc-imx.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 6920f0425508..586a1debf098 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -2124,12 +2124,12 @@ static int sdhci_esdhc_resume(struct device *dev)
dev_warn(dev, "Failed to restore pinctrl state\n");
}
- pm_runtime_force_resume(dev);
-
- ret = mmc_gpio_set_cd_wake(host->mmc, false);
+ ret = pm_runtime_force_resume(dev);
if (ret)
return ret;
+ mmc_gpio_set_cd_wake(host->mmc, false);
+
/* re-initialize hw state in case it's lost in low power mode */
sdhci_esdhc_imx_hwinit(host);
@@ -2156,7 +2156,7 @@ static int sdhci_esdhc_resume(struct device *dev)
pm_runtime_put_autosuspend(dev);
- return ret;
+ return 0;
}
static int sdhci_esdhc_runtime_suspend(struct device *dev)
--
2.34.1
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH v4 7/7] mmc: sdhci-esdhc-imx: fix resume error handling
2026-07-03 10:42 ` [PATCH v4 7/7] mmc: sdhci-esdhc-imx: fix resume error handling ziniu.wang_1
@ 2026-07-03 11:32 ` sashiko-bot
0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-07-03 11:32 UTC (permalink / raw)
To: ziniu.wang_1; +Cc: Frank.Li, imx
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
New issues:
- [High] The early return on `pm_runtime_force_resume()` failure intentionally skips software teardowns, leading to permanent resource leaks and IRQ depth nesting.
- [High] The patch's error handling fails to prevent a kernel panic, as the panic is simply deferred to the MMC child device resume.
Pre-existing issues:
- [High] `sdhci_esdhc_imx_remove()` ignores the return value of `pm_runtime_get_sync()`, leading to a kernel panic on device removal if clocks fail to enable.
--
commit 2ca3586c0fc9237c4716073c7d74f73e6e520449
Author: Luke Wang <ziniu.wang_1@nxp.com>
mmc: sdhci-esdhc-imx: fix resume error handling
This commit checks the return value of pm_runtime_force_resume() in
sdhci_esdhc_resume(). If it fails, the code returns immediately,
intentionally skipping some software teardown steps to prevent accessing
unclocked hardware registers which would cause a kernel panic.
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 6920f0425508d..586a1debf0981 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -2124,12 +2124,12 @@ static int sdhci_esdhc_resume(struct device *dev)
> dev_warn(dev, "Failed to restore pinctrl state\n");
> }
>
> - pm_runtime_force_resume(dev);
> -
> - ret = mmc_gpio_set_cd_wake(host->mmc, false);
> + ret = pm_runtime_force_resume(dev);
> + if (ret)
> + return ret;
[Severity: High]
If pm_runtime_force_resume() fails and we return early here, doesn't this
skip re-enabling the IRQ?
Since sdhci_esdhc_suspend() calls disable_irq(), skipping enable_irq()
leaves the interrupt permanently disabled and results in kernel warnings
due to an unbalanced wake depth on subsequent suspend cycles.
[Severity: High]
Does this early return actually prevent the kernel panic?
The PM core does not stop resuming child devices when a parent fails.
When the MMC class device resumes, it unblocks the block queue and calls
down into mmc_power_up(), which will access the unclocked
SDHCI_HOST_CONTROL register because __mmc_claim_host() ignores the
pm_runtime_get_sync() failure.
Should the code set host->flags |= SDHCI_DEVICE_DEAD before returning
the error so the MMC core is prevented from attempting to access the
unclocked hardware?
> +
> + mmc_gpio_set_cd_wake(host->mmc, false);
> +
> /* re-initialize hw state in case it's lost in low power mode */
> sdhci_esdhc_imx_hwinit(host);
>
[ ... ]
[Severity: High]
This isn't a bug introduced by this patch, but I noticed a similar issue in
sdhci_esdhc_imx_remove():
drivers/mmc/host/sdhci-esdhc-imx.c:sdhci_esdhc_imx_remove() {
...
pm_runtime_get_sync(&pdev->dev);
dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
...
}
Since the return value of pm_runtime_get_sync() is ignored before accessing
hardware registers, could this also cause a synchronous external abort
on device removal if the clocks fail to enable?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260703104208.3426374-1-ziniu.wang_1@oss.nxp.com?part=7
^ permalink raw reply [flat|nested] 15+ messages in thread