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 >