From: Kamal Dasu <kamal.dasu@broadcom.com>
To: Ulf Hansson <ulfh@kernel.org>
Cc: Kamal Dasu <kamal.dasu@broadcom.com>,
Florian Fainelli <florian.fainelli@broadcom.com>,
Wolfram Sang <wsa+renesas@sang-engineering.com>,
Oleksij Rempel <o.rempel@pengutronix.de>,
Avri Altman <avri.altman@sandisk.com>,
Pedro Demarchi Gomes <pedrodemargomes@gmail.com>,
Erick Shepherd <erick.shepherd@ni.com>,
Adrian Hunter <adrian.hunter@intel.com>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
linux-mmc@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: [PATCH v5 2/2] mmc: core: Honor keep-power-in-suspend for (e)MMC in suspend/resume
Date: Wed, 29 Jul 2026 16:14:20 -0400 [thread overview]
Message-ID: <20260729201420.4047677-3-kamal.dasu@broadcom.com> (raw)
In-Reply-To: <20260729201420.4047677-1-kamal.dasu@broadcom.com>
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.
keep-power-in-suspend / MMC_PM_KEEP_POWER already exist for this
purpose, but are only consumed in the SDIO suspend/resume path
(mmc_sdio_suspend()/mmc_sdio_resume()), gated on a per-function
runtime request via sdio_set_host_pm_flags(). (e)MMC has no
equivalent function-driver layer to make that request, and the
requirement here is a fixed platform characteristic rather than a
per-cycle one, so _mmc_suspend() checks host->pm_caps directly
instead of pm_flags.
When pm_caps has MMC_PM_KEEP_POWER set and pm_type is
MMC_POWEROFF_SUSPEND, skip the poweroff-notify/sleep/power-off
sequence entirely: deselect the card, reset the host to its initial
bus state the same way _mmc_hw_reset() does for a non-power-cycle
reset, mark the card suspended, and set host->pm_flags |=
MMC_PM_KEEP_POWER.
Setting MMC_PM_KEEP_POWER in host->pm_flags during suspend ensures
that host controller resume handlers are aware that card power was
preserved across suspend, allowing them to perform a soft resume
sequence instead of assuming power was lost. Clear this flag in
_mmc_resume() upon completion.
Only set pm_flags and mark the card suspended after
mmc_deselect_cards() succeeds. If it fails, the card is never marked
suspended, so _mmc_resume() takes its early "not suspended" exit and
never reaches the code that clears MMC_PM_KEEP_POWER -- setting the
flag unconditionally would leak it for the remainder of uptime.
The pm_type check matters because _mmc_suspend() is also called for
shutdown, driver unbind, and undervoltage, none of which are
guaranteed a subsequent _mmc_resume() call, so those still need the
normal power-off path.
Reported-by: Florian Fainelli <florian.fainelli@broadcom.com>
Closes: https://lore.kernel.org/r/20260413180551.3683969-1-florian.fainelli@broadcom.com/
Signed-off-by: Kamal Dasu <kamal.dasu@broadcom.com>
---
Changes in v5:
- Only set host->pm_flags |= MMC_PM_KEEP_POWER after
mmc_deselect_cards() succeeds, instead of unconditionally before
it. Otherwise, if the deselect fails, the card is never marked
suspended, _mmc_resume() takes its early exit, and the flag never
gets cleared -- leaking it for the rest of uptime.
Changes in v4:
- Gated the fast path on pm_type == MMC_POWEROFF_SUSPEND; it was
previously unconditional, so it wrongly skipped the required
power-off/notify handling during shutdown, unbind and
undervoltage as well.
- Reset the host to its initial bus state (mmc_set_clock() +
mmc_set_initial_state(), matching _mmc_hw_reset()'s non-power-
cycle path) before marking the card suspended.
- Set/clear host->pm_flags |= MMC_PM_KEEP_POWER around the suspend/
resume, mirroring the SDIO convention, so host controller resume
handlers can tell power was preserved and perform a soft resume
sequence instead of assuming power was lost.
- Dropped MMC_CAP2_NO_POWEROFF_SUSPEND and the no-mmc-poweroff-
suspend DT property entirely. Reuse keep-power-in-suspend /
MMC_PM_KEEP_POWER instead, per Krzysztof's point that the new
property described the same contract as the existing one.
_mmc_suspend() now checks host->pm_caps directly rather than
pm_flags, since (e)MMC has no per-function driver to make the
dynamic sdio_set_host_pm_flags()-style request SDIO uses.
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/mmc.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 05444ecf3909..7cbe65532726 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -2157,6 +2157,35 @@ static int _mmc_suspend(struct mmc_host *host, enum mmc_poweroff_type pm_type)
goto out;
}
+ /*
+ * Keep the card powered across an actual suspend; shutdown, unbind
+ * and undervoltage still need the normal power-off path below,
+ * since they aren't guaranteed a subsequent _mmc_resume().
+ *
+ * Check pm_caps, not pm_flags: unlike SDIO, (e)MMC has no
+ * per-function driver to request this via
+ * sdio_set_host_pm_flags(), so it's a fixed platform trait here.
+ *
+ * Set MMC_PM_KEEP_POWER in pm_flags so host controller drivers
+ * know card power was preserved during suspend and perform a
+ * soft resume sequence.
+ *
+ * Reset the host to its initial bus state like _mmc_hw_reset()
+ * does.
+ */
+ if (pm_type == MMC_POWEROFF_SUSPEND &&
+ (host->pm_caps & MMC_PM_KEEP_POWER)) {
+ if (!mmc_host_is_spi(host))
+ err = mmc_deselect_cards(host);
+ if (!err) {
+ host->pm_flags |= MMC_PM_KEEP_POWER;
+ mmc_set_clock(host, host->f_init);
+ mmc_set_initial_state(host);
+ 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);
@@ -2220,6 +2249,7 @@ static int _mmc_resume(struct mmc_host *host)
mmc_power_up(host, host->card->ocr);
err = mmc_init_card(host, host->card->ocr, host->card);
mmc_card_clr_suspended(host->card);
+ host->pm_flags &= ~MMC_PM_KEEP_POWER;
out:
mmc_release_host(host);
--
2.34.1
next prev parent reply other threads:[~2026-07-29 20:14 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-29 20:14 [PATCH v5 0/2] mmc: core: Keep the card powered across suspend when firmware needs it live Kamal Dasu
2026-07-29 20:14 ` [PATCH v5 1/2] dt-bindings: mmc: Extend keep-power-in-suspend beyond SDIO Kamal Dasu
2026-07-29 20:23 ` sashiko-bot
2026-07-29 20:14 ` Kamal Dasu [this message]
2026-07-29 20:29 ` [PATCH v5 2/2] mmc: core: Honor keep-power-in-suspend for (e)MMC in suspend/resume sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260729201420.4047677-3-kamal.dasu@broadcom.com \
--to=kamal.dasu@broadcom.com \
--cc=adrian.hunter@intel.com \
--cc=avri.altman@sandisk.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=erick.shepherd@ni.com \
--cc=florian.fainelli@broadcom.com \
--cc=krzk+dt@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mmc@vger.kernel.org \
--cc=o.rempel@pengutronix.de \
--cc=pedrodemargomes@gmail.com \
--cc=robh@kernel.org \
--cc=ulfh@kernel.org \
--cc=wsa+renesas@sang-engineering.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.