Re: [PATCH v3 2/2] mmc: core: Add MMC_CAP2_NO_POWEROFF_SUSPEND host capability

From: Ulf Hansson

Date: Mon Jul 27 2026 - 11:53:38 EST


On Wed, Jul 22, 2026 at 11:14 PM Kamal Dasu <kamal.dasu@xxxxxxxxxxxx> wrote:
>
> On some platforms, firmware accesses the (e)MMC card directly during
> resume from Suspend-to-DRAM, before the kernel's own resume path has
> run, in order to load boot code. This requires the card to remain
> powered and responsive throughout suspend: putting it to sleep,
> sending it a power-off notification, or removing its supply is not
> safe, since firmware needs to talk to a live card.
>

A lot better description, thanks for the update!

> Add MMC_CAP2_NO_POWEROFF_SUSPEND, settable via the new
> "no-mmc-poweroff-suspend" DT property. In _mmc_suspend(), when this
> capability is set, skip the poweroff-notify/sleep/power-off sequence
> entirely: just deselect the card and mark it suspended. At resume,
> _mmc_resume() already unconditionally calls mmc_power_up() and
> mmc_init_card(), so the card gets fully re-initialized regardless of
> what firmware may have done to it in the meantime.

That's not entirely correct as mmc_power_up() will in this case bail
out early, as "host->ios.power_mode == MMC_POWER_ON".

That said, we probably need to call mmc_power_off() in _mmc_resume()
before we start the re-initialization of the card, or what do you
think?

>
> Reported-by: Florian Fainelli <florian.fainelli@xxxxxxxxxxxx>
> Closes: https://lore.kernel.org/r/20260413180551.3683969-1-florian.fainelli@xxxxxxxxxxxx/
> Signed-off-by: Kamal Dasu <kamal.dasu@xxxxxxxxxxxx>

Kind regards
Uffe

> ---
> Changes in v3:
> - Reworked _mmc_suspend() to skip poweroff-notify/sleep/power-off
> entirely, not just SLEEP, per Ulf.
> - Renamed to MMC_CAP2_NO_POWEROFF_SUSPEND/no-mmc-poweroff-suspend.
>
> Changes in v2:
> - Replaced the card-level MMC_QUIRK_BROKEN_SLEEP quirk with a host
> capability, per Ulf.
> - Added Reported-by/Closes crediting Florian.
>
> drivers/mmc/core/host.c | 2 ++
> drivers/mmc/core/mmc.c | 15 +++++++++++++++
> include/linux/mmc/host.h | 1 +
> 3 files changed, 18 insertions(+)
>
> diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
> index b7ce3137d452..35fd0be99c58 100644
> --- a/drivers/mmc/core/host.c
> +++ b/drivers/mmc/core/host.c
> @@ -400,6 +400,8 @@ int mmc_of_parse(struct mmc_host *host)
> if (device_property_read_bool(dev, "no-mmc-hs400"))
> host->caps2 &= ~(MMC_CAP2_HS400_1_8V | MMC_CAP2_HS400_1_2V |
> MMC_CAP2_HS400_ES);
> + if (device_property_read_bool(dev, "no-mmc-poweroff-suspend"))
> + host->caps2 |= MMC_CAP2_NO_POWEROFF_SUSPEND;
>
> /* Must be after "non-removable" check */
> if (device_property_read_u32(dev, "fixed-emmc-driver-type", &drv_type) == 0) {
> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> index 05444ecf3909..27a559e6fcc0 100644
> --- a/drivers/mmc/core/mmc.c
> +++ b/drivers/mmc/core/mmc.c
> @@ -2157,6 +2157,21 @@ static int _mmc_suspend(struct mmc_host *host, enum mmc_poweroff_type pm_type)
> goto out;
> }
>
> + /*
> + * Some platforms need the card to stay powered and responsive
> + * throughout suspend, since firmware accesses it directly during
> + * resume, before the kernel's own resume path has run. Just
> + * deselect it and leave power alone; mmc_init_card() will fully
> + * re-initialize the card once the kernel resumes.
> + */
> + if (host->caps2 & MMC_CAP2_NO_POWEROFF_SUSPEND) {
> + if (!mmc_host_is_spi(host))
> + err = mmc_deselect_cards(host);
> + if (!err)
> + mmc_card_set_suspended(host->card);
> + goto out;
> + }
> +
> if (mmc_card_can_poweroff_notify(host->card) &&
> mmc_host_can_poweroff_notify(host, pm_type))
> err = mmc_poweroff_notify(host->card, notify_type);
> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
> index ba84f02c2a10..e082aab8f4c4 100644
> --- a/include/linux/mmc/host.h
> +++ b/include/linux/mmc/host.h
> @@ -463,6 +463,7 @@ struct mmc_host {
> #define MMC_CAP2_CRYPTO 0
> #endif
> #define MMC_CAP2_ALT_GPT_TEGRA (1 << 28) /* Host with eMMC that has GPT entry at a non-standard location */
> +#define MMC_CAP2_NO_POWEROFF_SUSPEND (1 << 29) /* Card must stay powered across suspend */
>
> bool uhs2_sd_tran; /* UHS-II flag for SD_TRAN state */
> bool uhs2_app_cmd; /* UHS-II flag for APP command */
> --
> 2.34.1
>