# DF-4191 — `sdhci_start_data` mishandles `bus_dmamap_load() == EINPROGRESS`: deferred `sdhci_adma2_getaddr` stays armed against the live ADMA2 descriptor table

File: `sys/dev/disk/sdhci/sdhci.c` (pass 2, GLM 5.3). **Speculative** —
hardware-gated (no SDHCI controller emulation in stock QEMU), verified by
source-level trace; the defensive fix is compile-proven (module build).

## The claim (source trace)

`sdhci_start_data()` loads the ADMA2 map with `BUS_DMA_WAITOK`
(`sys/dev/disk/sdhci/sdhci.c:1326-1328`). On DragonFly/amd64,
`bus_dmamap_load()` can return **EINPROGRESS** when the map needs bounce pages
(data buffer above `BUS_SPACE_MAXADDR_32BIT`) and the bounce pool is
temporarily exhausted (`sys/platform/pc64/x86_64/busdma_machdep.c:644-657`:
map queued on `bounce_map_waitinglist`, `map->callback`/`map->buf` saved,
error returned to caller).

`sdhci_start_data()` treats **any** non-zero error identically
(`sdhci.c:1329-1340`): prints "Dma load for ADMA2 fail: %d" and **falls back
to PIO for this request** — but the deferred load still owns
`slot->adma2_map` and will later re-run `_bus_dmamap_load_buffer` with the
saved `map->buf` (the request's `data->data`, freed after the bio completes)
and fire `sdhci_adma2_getaddr(slot)` (`sdhci.c:598-630`), which **rewrites the
shared `slot->adma2_descs` descriptor table** — while an unrelated later
request may be mid-ADMA2-transfer using that same table (next request reloads
the same map, which is still on the waiting list → map double-enqueue as
well). Additionally `sdhci_finish_data()` skips `bus_dmamap_unload()` for the
PIO fallback (`sdhci.c:1413-1425` gated on `SDHCI_USE_ADMA2`), leaving the map
attached to a stale buffer.

Impact if realized: (a) ADMA2 descriptor table rewritten mid-DMA → controller
fetches descriptors pointing at the *previous* request's (freed) buffer
addresses → device DMA into/out of stale kernel memory (memory corruption /
info leak); (b) busdma waiting-list corruption from re-loading a queued map.

Preconditions: ADMA2 enabled (whitelisted controllers — `sdhci_pci.c:100-128`,
`sdhci_acpi.c:147,170-171`, or `hw.sdhci.adma2_test=1`), host RAM > 4 GB so
mmcsd bounce is needed for the 32-bit-limited tag, and transient bounce-page
exhaustion at that instant. Narrow but real window; card I/O load influences
the timing.

## Why not reproduced

The audit guest has no SDHCI controller (QEMU does not emulate one), and the
bug requires physical bounce-page pressure interacting with live hardware
DMA — not reproducible in the harness meaningfully better than the trace.
Classified `untested` / `speculative` accordingly.

## Fix

`fix.diff` (defensive): treat `EINPROGRESS` as a hard failure of the command
(set `slot->curcmd->error = MMC_ERR_INVALID`, drop `SDHCI_USE_ADMA2`, return)
instead of continuing in PIO with the deferred load armed.
Compile-validated: `sdhci.ko` module builds with the fix under `-Werror` on
the guest's `/usr/src` copy (`sdhci_module_build.log`, `MAKE_RC=0`).
