Re: [PATCH v10 6/6] mmc: core: Add support for resetting an eMMC at system resume

From: Kamal Dasu

Date: Tue Oct 27 2026 - 16:01:32 EST


On Tue, Oct 27, 2026 at 11:21 AM Shawn Lin <shawn.lin@xxxxxxxxx> wrote:
>
> 在 2026/10/27 星期二 22:40, Ulf Hansson 写道:
> > The DT property reset-card-at-resume specifies that we need to make a reset
> > of an eMMC card at system resume, assuming it also has stayed powered on
> > during system suspend.
> >
> > To implement support for this, let's start by parsing for the new DT
> > property and set the new bit MMC_CAP2_RESET_AT_RESUME if it's found. Based
> > on the property, we must also set MMC_PM_KEEP_POWER in the pm_flags for the
> > host, to keep the eMMC powered on during system suspend.
> >
> > Finally, to manage the actual reset during system resume, let's extend
> > mmc_resume() to support the needed behaviour.
> >
>
> Reviewed-by: Shawn Lin <shawn.lin@xxxxxxxxxxxxxx>
>
> > Signed-off-by: Ulf Hansson <ulf.hansson@xxxxxxxxxxxxxxxx>
> > ---
> > drivers/mmc/core/host.c | 10 ++++++++++
> > drivers/mmc/core/mmc.c | 5 +++++
> > include/linux/mmc/host.h | 1 +
> > 3 files changed, 16 insertions(+)
> >
> > diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
> > index 8e9e61839198..e3daf4026cba 100644
> > --- a/drivers/mmc/core/host.c
> > +++ b/drivers/mmc/core/host.c
> > @@ -48,6 +48,14 @@ static int mmc_host_class_prepare(struct device *dev)
> > if (host->bus_ops->pre_suspend)
> > return host->bus_ops->pre_suspend(host);
> >
> > + /*
> > + * If it's required to make a reset of the card at system resume, this
> > + * indirectly also means that we must keep the card powered on during
> > + * system suspend.
> > + */
> > + if (host->caps2 & MMC_CAP2_RESET_AT_RESUME)
> > + return mmc_set_host_pm_flags(host, MMC_PM_KEEP_POWER);
> > +
> > return 0;
> > }
> >
> > @@ -375,6 +383,8 @@ int mmc_of_parse(struct mmc_host *host)
> > host->pm_caps |= MMC_PM_KEEP_POWER;
> > if (device_property_read_bool(dev, "wakeup-source"))
> > host->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
> > + if (device_property_read_bool(dev, "reset-card-at-resume"))
> > + host->caps2 |= MMC_CAP2_RESET_AT_RESUME;
> > if (device_property_read_bool(dev, "mmc-ddr-3_3v"))
> > host->caps |= MMC_CAP_3_3V_DDR;
> > if (device_property_read_bool(dev, "mmc-ddr-1_8v"))
> > diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> > index d4bf0f25bd74..908d5cad304b 100644
> > --- a/drivers/mmc/core/mmc.c
> > +++ b/drivers/mmc/core/mmc.c
> > @@ -2315,6 +2315,11 @@ static int mmc_resume(struct mmc_host *host)
> > }
> >
> > pm_runtime_enable(&host->card->dev);
> > +
> > + if (mmc_card_keep_power(host) &&
> > + host->caps2 & MMC_CAP2_RESET_AT_RESUME)
> > + _mmc_hw_reset(host);
> > +
> > host->pm_flags &= ~MMC_PM_KEEP_POWER;
> > return 0;
> > }
> > diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
> > index 032c018650e0..552873da7987 100644
> > --- a/include/linux/mmc/host.h
> > +++ b/include/linux/mmc/host.h
> > @@ -430,6 +430,7 @@ struct mmc_host {
> > u32 caps2; /* More host capabilities */
> >
> > #define MMC_CAP2_BOOTPART_NOACC (1 << 0) /* Boot partition no access */
> > +#define MMC_CAP2_RESET_AT_RESUME (1 << 1) /* Reset the card at system resume */
> > #define MMC_CAP2_FULL_PWR_CYCLE (1 << 2) /* Can do full power cycle */
> > #define MMC_CAP2_FULL_PWR_CYCLE_IN_SUSPEND (1 << 3) /* Can do full power cycle in suspend */
> > #define MMC_CAP2_HS200_1_8V_SDR (1 << 5) /* can support */
>

Hi Ulf,

While testing this series I get a burst of WARN_ON(!host->claimed)
backtraces at system resume (29 of them) when both properties are set:

WARNING: drivers/mmc/core/core.c:351 at mmc_start_request+0xd0/0xe8
Call trace:
mmc_start_request+0xd0/0xe8
mmc_wait_for_req+0x70/0xf8
mmc_wait_for_cmd+0x7c/0xb8
__mmc_switch+0xec/0x258
mmc_init_card+0x14f0/0x1cc0
_mmc_hw_reset+0x68/0xa8
mmc_resume+0x80/0xa8
mmc_bus_resume+0x2c/0x80
dpm_run_callback+0x6c/0x280

WARNING: drivers/mmc/core/core.c:637 at mmc_wait_for_cmd+0xa0/0xb8
(same path, via __mmc_send_status and __mmc_switch)

_mmc_hw_reset() ends up in mmc_init_card(), which sends commands and
requires the host to be claimed. mmc_resume() calls it without
claiming, unlike _mmc_resume() and the callers of mmc_hw_reset(). The
reset does complete, but it runs unserialized against other users of
the host.

This fixes it for me, with no warnings left:

--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -2317,8 +2317,11 @@ static int mmc_resume(struct mmc_host *host)
pm_runtime_enable(&host->card->dev);

if (mmc_card_keep_power(host) &&
- host->caps2 & MMC_CAP2_RESET_AT_RESUME)
+ host->caps2 & MMC_CAP2_RESET_AT_RESUME) {
+ mmc_claim_host(host);
_mmc_hw_reset(host);
+ mmc_release_host(host);
+ }

host->pm_flags &= ~MMC_PM_KEEP_POWER;
return 0;


Regards
Kamal

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature