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 v9 0/3] mmc: core: Keep the card powered across suspend when firmware needs it live
Date: Tue, 11 Aug 2026 12:38:07 -0400 [thread overview]
Message-ID: <20260811163810.1599747-1-kamal.dasu@broadcom.com> (raw)
This is v9.
Background: on brcmstb boards with a Kioxia 016G01 eMMC, firmware
accesses the card directly during resume from Suspend-to-DRAM, before
the kernel's own resume path runs, in order to load boot code using
hard wired logic that is not field updatable. The card needs to stay
powered and responsive for that access to succeed, and since it is
never power-cycled, it also needs to be reset before the kernel
reuses it after resume.
Changes in v9:
- Sashiko's AI review found two more High severity issues in the
same shutdown/undervoltage fallback added in v8:
* Calling mmc_select_card() straight after finding the card
still marked suspended assumed the card would respond to
CMD7 as-is, but that's exactly the assumption
reset-card-at-resume exists to distrust -- firmware may have
left the card unable to decode commands at whatever
clock/timing was negotiated before suspend. A CMD7 timeout
there hit "goto out" and skipped the power-off sequence
entirely, the same failure mode this fallback was added to
close in v8. Fixed by resetting the host to its initial bus
state before mmc_select_card(), the same way _mmc_resume()
already does before touching the card.
* Even with that reset, mmc_select_card() can still legitimately
fail (card genuinely gone). The code still unconditionally
"goto out" in that case, skipping mmc_power_off() entirely --
but mmc_power_off() is host/regulator-side only and doesn't
need a responsive card, so there's no reason a select failure
should leave the supply on indefinitely for a shutdown or
undervoltage event, or leave pm_flags/suspended state stuck
retrying the same failing select on every later call. Fixed
by falling through to mmc_power_off() directly on select
failure instead of aborting.
- Patches 1/3 and 2/3 are unchanged from v8.
Changes in v8:
- Sashiko's AI review of v7 found a High severity issue on patch
3/3: the keep-power fast path marks the card suspended without
powering it off, but the pre-existing early exit at the top of
_mmc_suspend() for an already-suspended card doesn't account for
that -- a shutdown, unbind or undervoltage event landing before
the card's next real access (which is what lazily triggers
_mmc_resume() via runtime PM) would hit that early exit and
silently skip mmc_poweroff_notify()/mmc_power_off() entirely.
Fixed by reselecting the card and continuing into the normal
power-off sequence in that case, instead of a bare early exit.
- Sashiko also flagged a Low severity gap on patch 2/3: nothing in
the schema enforced reset-card-at-resume's own stated pairing
with keep-power-in-suspend, so a DT could set it alone and still
pass dt_binding_check. Rob Herring asked for this to be addressed
on the list. Added a dependencies entry for it.
- Patch 1/3 is unchanged from v7.
Changes in v7:
- Sashiko's AI review of v6 found two real, complementary bugs from
treating keep-power-in-suspend and reset-card-at-resume as fully
independent in the driver: keep-power-in-suspend without
reset-card-at-resume left mmc_power_up() no-oping on resume,
which hangs on real hardware (confirmed); reset-card-at-resume
without keep-power-in-suspend drove the clock and bus lines ahead
of mmc_power_up() while the card's supply was still off from a
normal power-off. Patch 3/3 now requires both capabilities
together for the suspend fast path, and gates the resume-side
reset on pm_flags (only ever set when the fast path actually ran)
rather than the raw capability. Verified on hardware: the
previously-hanging combination now falls through safely to a
normal power-off/power-on cycle, and the paired-capability case
(brcmstb's actual configuration) is unaffected.
- Patches 1/3 and 2/3 gained Krzysztof's Reviewed-by; their content
is otherwise unchanged from v6.
Changes in v6:
- Split keeping the card powered and needing a reset before reuse
into two independent DT properties, per Ulf: extending
keep-power-in-suspend beyond SDIO (patch 1) no longer carries any
brcmstb-specific rationale, and a new reset-card-at-resume
property (patch 2) covers that instead. brcmstb sets both; SDIO's
existing keep-power-in-suspend users are unaffected.
- Patch 3 (the driver patch) reflects the split: the
mmc_set_clock()/mmc_set_initial_state() reset moved out of the
suspend-side fast path and into _mmc_resume(), gated on the new
MMC_CAP2_RESET_AT_RESUME, matching reset-card-at-resume's name
and description.
- Also per Ulf (raised on v4, applies equally to v5): dropped the
mention of sdio_set_host_pm_flags() and how Linux's SDIO stack
happens to expose this at runtime from the binding description --
that's a software implementation detail, not a hardware/platform
description.
Changes in v5:
- Patch 1: added Krzysztof's Reviewed-by.
- Patch 2: 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:
- Dropped the no-mmc-poweroff-suspend DT property and
MMC_CAP2_NO_POWEROFF_SUSPEND host capability entirely. Krzysztof
pointed out they described exactly the same contract as the
existing keep-power-in-suspend property (don't power off the card
across suspend/resume). Extended keep-power-in-suspend's scope
beyond SDIO instead, and reworked _mmc_suspend() to check
host->pm_caps & MMC_PM_KEEP_POWER directly rather than adding a
new capability.
- 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.
- Set/clear host->pm_flags |= MMC_PM_KEEP_POWER around the suspend/
resume, mirroring the SDIO convention, so host drivers can tell
power was preserved if they need to.
Changes in v3:
- Reworked the fix in _mmc_suspend() (drivers/mmc/core/mmc.c) to
skip the poweroff-notify/sleep/power-off sequence entirely.
- Renamed no-mmc-sleep/MMC_CAP2_NO_SLEEP_CMD to
no-mmc-poweroff-suspend/MMC_CAP2_NO_POWEROFF_SUSPEND.
Changes in v2:
- Replaced v1's card-level MMC_QUIRK_BROKEN_SLEEP quirk with a host
capability and matching DT property, per Ulf's suggestion.
- Added Reported-by/Closes tags crediting Florian.
Kamal Dasu (3):
dt-bindings: mmc: Extend keep-power-in-suspend beyond SDIO
dt-bindings: mmc: Add reset-card-at-resume property
mmc: core: Honor keep-power-in-suspend and reset-card-at-resume
for (e)MMC
.../bindings/mmc/mmc-controller-common.yaml | 10 +++-
drivers/mmc/core/host.c | 2 +
drivers/mmc/core/mmc.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++
include/linux/mmc/host.h | 1 +
4 files changed, 108 insertions(+), 3 deletions(-)
--
2.34.1
next reply other threads:[~2026-08-11 16:38 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-11 16:38 Kamal Dasu [this message]
2026-08-11 16:38 ` [PATCH v9 1/3] dt-bindings: mmc: Extend keep-power-in-suspend beyond SDIO Kamal Dasu
2026-08-11 16:38 ` [PATCH v9 2/3] dt-bindings: mmc: Add reset-card-at-resume property Kamal Dasu
2026-08-11 16:38 ` [PATCH v9 3/3] mmc: core: Honor keep-power-in-suspend and reset-card-at-resume for (e)MMC Kamal Dasu
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=20260811163810.1599747-1-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox