From: "Alex Bennée" <alex.bennee@linaro.org>
To: Wadim Mueller <wafgo01@gmail.com>
Cc: qemu-devel@nongnu.org, qemu-arm@nongnu.org,
"Peter Maydell" <peter.maydell@linaro.org>,
"Philippe Mathieu-Daudé" <philmd@mailo.com>,
"Bin Meng" <bmeng.cn@gmail.com>,
"Paolo Bonzini" <pbonzini@redhat.com>,
"Fabiano Rosas" <farosas@suse.de>
Subject: Re: [RFC PATCH v2 03/14] hw/sd/sdhci: complete non-interrupt ADMA descriptor chains in one pass
Date: Mon, 24 Aug 2026 16:53:23 +0100 [thread overview]
Message-ID: <87v78zqzv0.fsf@draig.linaro.org> (raw)
In-Reply-To: <20260820124824.618671-4-wafgo01@gmail.com> (Wadim Mueller's message of "Thu, 20 Aug 2026 14:48:03 +0200")
Wadim Mueller <wafgo01@gmail.com> writes:
> sdhci_do_adma() returns to the main loop after every descriptor and relies
> on a timer re-entry to pick up the next one. For a descriptor chain whose
> entries do not request an interrupt this makes the transfer rate depend
> from the virtual clock rather than on the guest's programming, which
> significantly slows down large transfers and makes guest-visible timing
> depend on host timer behaviour.
>
> Keep processing the chain in the same invocation while no descriptor asks
> for an interrupt and the transfer has not finished, and only fall back to
> the deferred path when the guest actually requested a notification.
>
> A qtest reproducer is added later in this series.
>
> Signed-off-by: Wadim Mueller <wafgo01@gmail.com>
> ---
> This patch can be dropped once Bin Meng's SDHCI series
> https://patchwork.ozlabs.org/project/qemu-devel/list/?series=515264
> (which needs series=513930 applied first) is merged - it covers the
> same AM64x failure, see
> https://lore.kernel.org/qemu-devel/20260810124519.34501-1-wafgo01@gmail.com/
> It is included here only so that the series works on actual master.
>
> hw/sd/sdhci-internal.h | 9 +++++++++
> hw/sd/sdhci.c | 23 +++++++++++++++++++++--
> 2 files changed, 30 insertions(+), 2 deletions(-)
>
> diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
> index 4aeed120bf..e6ce12617e 100644
> --- a/hw/sd/sdhci-internal.h
> +++ b/hw/sd/sdhci-internal.h
> @@ -277,6 +277,15 @@ FIELD(SDHC_MAXCURR, V18_VDD2, 32, 8); /* since v4.20 */
> #define SDHC_INSERTION_DELAY (NANOSECONDS_PER_SECOND)
> #define SDHC_TRANSFER_DELAY 100
> #define SDHC_ADMA_DESCS_PER_DELAY 5
> +/*
> + * Upper bound on ADMA2 descriptors handled in a single sdhci_do_adma()
> + * call, as a safety valve against a malformed or circular descriptor
> + * list. A well-formed transfer terminates far below this via END or
> + * blkcnt == 0 (even a 4 GiB transfer built from 64 KiB TRAN descriptors
> + * is only ~64K descriptors); the bound merely guarantees the loop makes
> + * a decision instead of spinning forever.
> + */
> +#define SDHC_ADMA_MAX_DESCRIPTORS (1 << 20)
> #define SDHC_CMD_RESPONSE (3 << 0)
>
> enum {
> diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
> index e58a610397..9a5dd1d93f 100644
> --- a/hw/sd/sdhci.c
> +++ b/hw/sd/sdhci.c
> @@ -780,7 +780,6 @@ static void sdhci_do_adma(SDHCIState *s)
> const MemTxAttrs attrs = { .memory = true };
> ADMADescr dscr = {};
> MemTxResult res = MEMTX_ERROR;
> - int i;
>
> if (s->trnmod & SDHC_TRNS_BLK_CNT_EN && !s->blkcnt) {
> /* Stop Multiple Transfer */
> @@ -788,7 +787,27 @@ static void sdhci_do_adma(SDHCIState *s)
> return;
> }
>
> - for (i = 0; i < SDHC_ADMA_DESCS_PER_DELAY; ++i) {
> + /*
> + * Process the descriptor chain to completion (END or blkcnt == 0),
> + * yielding to the guest only for a descriptor carrying the INT
> + * attribute (a DMA-boundary interrupt, handled at the end of the loop).
> + *
> + * Historically at most SDHC_ADMA_DESCS_PER_DELAY descriptors were
> + * handled per call before rescheduling SDHC_TRANSFER_DELAY ns later on
> + * QEMU_CLOCK_VIRTUAL. That pacing is only needed so a guest can observe
> + * the intermediate DMA-interrupt state; a bulk transfer that requests
> + * no interrupt does not need slicing, and throttling it across many
> + * virtual-clock round-trips can make it race a guest-side transfer
> + * timeout. Run such chains to completion in one call instead.
> + *
> + * SDHC_ADMA_MAX_DESCRIPTORS bounds the loop so a malformed or circular
> + * chain cannot spin here forever; on overflow, break to the reschedule
> + * path so the main loop stays responsive.
Hmm SDHC_ADMA_MAX_DESCRIPTORS is (1 << 20) which seems an awful lot to
handle in dma session especially if this is a guest controlled thing.
> + */
> + for (unsigned int adma_descs = 0; ; adma_descs++) {
> + if (adma_descs >= SDHC_ADMA_MAX_DESCRIPTORS) {
> + break;
> + }
Seems an odd formulation when you have the for loop construct already.
Although I see sdhci_do_adma already has multiple exit paths that skip
the final timer reset so it is hard to follow the control flow anyway.
I wonder if there is a better way to structure this logic so its easier
to see where irq's are set, transfers ended and timers scheduled for
continuation?
> s->admaerr &= ~SDHC_ADMAERR_LENGTH_MISMATCH;
>
> get_adma_description(s, &dscr);
--
Alex Bennée
Virtualisation Tech Lead @ Linaro
next prev parent reply other threads:[~2026-08-24 15:54 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-20 12:48 [RFC PATCH v2 00/14] hw/arm: add TI AM64x SoC and am64-virt machine Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 01/14] hw/i2c/omap_i2c: add a dedicated CONFIG_OMAP_I2C symbol Wadim Mueller
2026-08-24 15:39 ` Alex Bennée
2026-08-20 12:48 ` [RFC PATCH v2 02/14] hw/i2c/omap_i2c: implement soft reset and NACK reporting Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 03/14] hw/sd/sdhci: complete non-interrupt ADMA descriptor chains in one pass Wadim Mueller
2026-08-24 15:53 ` Alex Bennée [this message]
2026-08-20 12:48 ` [RFC PATCH v2 04/14] hw/char: add TI AM64x UART model Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 05/14] hw/timer: add TI K3 DMTimer model Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 06/14] hw/misc: add TI K3 CTRL_MMR, GTC, DDRSS, SDHCI PHY and TRNG models Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 07/14] hw/misc: add TI RAT (region address translation) model Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 08/14] hw/misc: add TI mailbox (IPC) model Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 09/14] hw/misc: add TI K3 secure proxy model Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 10/14] hw/misc: add TI DMSC (TI-SCI system controller) model Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 11/14] hw/arm: add TI K3 combined boot image parser Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 12/14] hw/arm: add TI AM64x SoC model Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 13/14] hw/arm: add the am64-virt machine Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 14/14] tests: add AM64x unit, qtest and functional tests Wadim Mueller
2026-08-20 16:25 ` Alex Bennée
2026-08-22 21:04 ` Wadim Mueller
2026-08-24 15:39 ` Alex Bennée
2026-08-21 10:26 ` [RFC PATCH v2 00/14] hw/arm: add TI AM64x SoC and am64-virt machine Alex Bennée
2026-08-22 21:06 ` Wadim Mueller
2026-08-21 16:35 ` Nick Huang
2026-08-22 21:07 ` Wadim Mueller
2026-08-22 5:22 ` Bin Meng
2026-08-22 21:13 ` Wadim Mueller
2026-08-24 11:51 ` Nick Huang
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=87v78zqzv0.fsf@draig.linaro.org \
--to=alex.bennee@linaro.org \
--cc=bmeng.cn@gmail.com \
--cc=farosas@suse.de \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=philmd@mailo.com \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=wafgo01@gmail.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