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

From: Kamal Dasu

Date: Fri Nov 06 2026 - 12:34:00 EST


On Mon, Nov 2, 2026 at 2:20 AM Shawn Lin <shawn.lin@xxxxxxxxx> wrote:
>
> 在 2026/10/31 星期六 2:10, Kamal Dasu 写道:
> > From: Ulf Hansson <ulf.hansson@xxxxxxxxxxxxxxxx>
> >
> > 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.
> >
> > The property only makes sense together with keep-power-in-suspend, as the
> > card would otherwise be powered off and system suspend is refused. Warn
> > about that while parsing the DT properties, to flag the misconfiguration
> > upfront. While at it, claim the host around the reset in mmc_resume(), as
> > it sends commands to the card.
> >
> > Signed-off-by: Ulf Hansson <ulf.hansson@xxxxxxxxxxxxxxxx>
> > Co-developed-by: Kamal Dasu <kamal.dasu@xxxxxxxxxxxx>
> > Signed-off-by: Kamal Dasu <kamal.dasu@xxxxxxxxxxxx>
> > ---
> > drivers/mmc/core/host.c | 13 +++++++++++++
> > drivers/mmc/core/mmc.c | 8 ++++++++
> > include/linux/mmc/host.h | 1 +
> > 3 files changed, 22 insertions(+)
> >
> > diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
> > index 8e9e61839198..8b38ff45d20f 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,11 @@ 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 (!(host->pm_caps & MMC_PM_KEEP_POWER))
> > + dev_warn(dev, "reset-card-at-resume without keep-power-in-suspend, system suspend will fail\n");
>
> No strong opinion on this log, but we set MMC_PM_KEEP_POWER if
> reset-card-at-resume is present anyway, could the suspend fail?
>

Yes, it can due to user error in mentioning both variables. Two
different things are involved here:
- host->pm_caps is the static capability. mmc_of_parse() only sets
MMC_PM_KEEP_POWER there when "keep-power-in-suspend" is in DT.
- host->pm_flags is the per-suspend request. mmc_host_class_prepare()
sets MMC_PM_KEEP_POWER there via mmc_set_host_pm_flags() when
MMC_CAP2_RESET_AT_RESUME is set.

mmc_set_host_pm_flags() returns -EINVAL if the requested flags are not a
subset of pm_caps. So with reset-card-at-resume but without
keep-power-in-suspend, prepare() fails and system suspend is refused.

The warning is there to flag that misconfiguration once at probe time,
instead of the user finding out from a failing first suspend. I'd prefer
to keep it, but I can drop it if you or Ulf feel strongly.

Sashiko (https://sashiko.dev, patchset 98989) flagged one issue on this
patch: mmc_resume() ignores the return value of _mmc_hw_reset(). If
mmc_init_card() fails after the reset, mmc_resume() still returns 0, so
mmc_bus_resume() never prints its "error during resume" warning and the
card stays marked runtime-active and unsuspended.

I think it's worth propagating the error, as _mmc_resume() does:

int err = 0;
...
if (mmc_card_keep_power(host) &&
host->caps2 & MMC_CAP2_RESET_AT_RESUME) {
mmc_claim_host(host);
- _mmc_hw_reset(host);
+ err = _mmc_hw_reset(host);
mmc_release_host(host);
}

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

Ulf are you OK with me folding this into 6/6 for the next version ?

Kamal

> > + }
> > 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 026003ba507d..a9e3cf7ae039 100644
> > --- a/drivers/mmc/core/mmc.c
> > +++ b/drivers/mmc/core/mmc.c
> > @@ -2320,6 +2320,14 @@ 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_claim_host(host);
> > + _mmc_hw_reset(host);
> > + mmc_release_host(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..3c0ea74e3e35 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 BIT(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 */
>

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