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

Ulf Hansson <[email protected]> Mon, 27 Jul 2026 17:42:05 +0200
Newsgroups org.kernel.vger.linux-mmc,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel
Message-ID <CAPx+jO9kvStHxc+ccSne-S-NA=CzH-wEf9H+Beejyv7BGi4uoQ@mail.gmail.com>
On Wed, Jul 22, 2026 at 11:14=E2=80=AFPM Kamal Dasu <[email protected]=
m> 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 =3D=3D 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 <[email protected]>
> Closes: https://lore.kernel.org/r/20260413180551.3683969-1-florian.fainel=
[email protected]/
> Signed-off-by: Kamal Dasu <[email protected]>

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 &=3D ~(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 |=3D MMC_CAP2_NO_POWEROFF_SUSPEND;
>
>         /* Must be after "non-removable" check */
>         if (device_property_read_u32(dev, "fixed-emmc-driver-type", &drv_=
type) =3D=3D 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, enu=
m 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 =3D 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 =3D 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 ha=
s 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_TRA=
N state */
>         bool                    uhs2_app_cmd;   /* UHS-II flag for APP co=
mmand */
> --
> 2.34.1
>