Linux MultiMedia Card development
 help / color / mirror / Atom feed
From: Shawn Lin <shawn.lin@rock-chips.com>
To: Ulf Hansson <ulfh@kernel.org>
Cc: Jaehoon Chung <jh80.chung@samsung.com>,
	Marek Szyprowski <m.szyprowski@samsung.com>,
	linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org,
	Shawn Lin <shawn.lin@rock-chips.com>
Subject: [PATCH 0/4] mmc: dw_mmc: replace three fallback timers with a single watchdog
Date: Thu, 27 Aug 2026 15:58:02 +0800	[thread overview]
Message-ID: <1787817486-137277-1-git-send-email-shawn.lin@rock-chips.com> (raw)


The driver carries three fallback timers (cmd11_timer, cto_timer,
dto_timer) added piecemeal after the hardware failed in the field.
dto_timer exists because Synopsys confirmed that the DTO interrupt can
be lost entirely, leaving no hardware fallback and blocking the request
forever without software help (57e104864bc4); cto_timer came later,
when Rockchip's reworked sample circuit was root-caused to swallow both
CMD_DONE and response-timeout interrupts across their whole dwmmc
family (03de19212ea3); cmd11_timer papered over voltage-switch hangs
that reproduced reliably when ejecting/inserting UHS cards on rk3288
(5c935165da79).

Because each callback races against the very interrupt it supplements,
all three grew the same copy-pasted defenses: re-read MINTSTS in case
the interrupt is merely late, check whether pending_events has been set
meanwhile, validate host->state against the leg being guarded, and only
then synthesize the missed event -- with timer_delete_sync() calls from
softirq context eventually needed just to contain them.  Meanwhile the
special cases keep piling up: the EXTENDED_TMOUT quirk makes the DTO
story differ per platform, fault injection can post DATA_ERROR ahead of
any real completion, and every future change has to reason about up to
three timers at once.

The observation enabling the cleanup is that command, data and
voltage-switch legs run strictly serially within a request, so a single
hrtimer suffices.  Under irq_lock it records which pending_events bits
are awaited along with a snapshot of host->state (dw_mci_wd_arm()),
and producers clear that awaited mask instead of deleting any timer
(dw_mci_wd_deliver()).  On expiry the one callback classifies what
expired by comparing the awaited set against the named
DW_MCI_WD_{CMD,DATA}_EVENTS masks, keeps the old MINTSTS latency check
but re-arms instead of going passive so an interrupt lost for good
can no longer wedge the request forever, and only then synthesizes
exactly what its predecessor would have (RTO + command complete, or
DRTO + data error/complete).  The per-leg deadlines -- CTO formula,
DRTO formula, 500ms CMD11 budget -- are carried over unchanged.

Apart from three behavioral deltas called out in the individual commit
messages as well -- a single surviving watch during voltage switch
instead of two timers racing, a stuck CMD11 aborting after exactly
500ms instead of racing min(cto_ms, 500ms) with -ETIMEDOUT unchanged,
and bounded recovery from interrupt-latency peaks instead of an
unbounded hang -- no functional change is intended.

Tested on Rockchip platforms with SD card and eMMC (rv1126/rk3568/
rk3576 boards): normal IO, suspend/resume and card removal during
transfer.  Compile tested on every variant consuming dw_mmc.h.

Next steps: first split dw_mci_work_func() into per-state handlers to
make the transitions explicit, then go further in the sdhci direction:
shrink the eight-state machine, drop the redundant completed_events
bookkeeping, and end up where other host drivers already are: one state
machine, one timer, no separate event flags.



Shawn Lin (4):
  mmc: dw_mmc: add central watchdog and convert CTO onto it
  mmc: dw_mmc: convert DTO onto the central watchdog
  mmc: dw_mmc: absorb CMD11 timeout into the central watchdog
  mmc: dw_mmc: expose the watchdog state in debugfs

 drivers/mmc/host/dw_mmc.c | 316 +++++++++++++++++++++++-----------------------
 drivers/mmc/host/dw_mmc.h |  15 ++-
 2 files changed, 165 insertions(+), 166 deletions(-)

-- 
2.7.4


             reply	other threads:[~2026-08-27  8:13 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-27  7:58 Shawn Lin [this message]
2026-08-27  7:58 ` [PATCH 1/4] mmc: dw_mmc: add central watchdog and convert CTO onto it Shawn Lin
2026-08-27  7:58 ` [PATCH 2/4] mmc: dw_mmc: convert DTO onto the central watchdog Shawn Lin
2026-08-27  7:58 ` [PATCH 3/4] mmc: dw_mmc: absorb CMD11 timeout into " Shawn Lin
2026-08-27  7:58 ` [PATCH 4/4] mmc: dw_mmc: expose the watchdog state in debugfs Shawn Lin
2026-09-10 16:05 ` [PATCH 0/4] mmc: dw_mmc: replace three fallback timers with a single watchdog Ulf Hansson

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=1787817486-137277-1-git-send-email-shawn.lin@rock-chips.com \
    --to=shawn.lin@rock-chips.com \
    --cc=jh80.chung@samsung.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mmc@vger.kernel.org \
    --cc=m.szyprowski@samsung.com \
    --cc=ulfh@kernel.org \
    /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