Bound the TXDATA chunk to half the tx_bytes depth

a2e8e5c batched TXDATA writes into 64-byte chunks and broke ACKs outright --
"no ACK after 20 tries".  My regression, and CLAUDE.md warns about exactly
this: tx_bytes is 16 deep and BBARegisterFile silently drops bytes when
w_rdy is low, because SPI cannot back-pressure.

Within a single transaction the bytes arrive back-to-back at EXI speed, far
faster than TXFrameDrain starts consuming, so a 64-byte chunk overran the FIFO,
the frame went out truncated, and no valid ACK ever reached the host.
Byte-by-byte worked only because the per-byte EXI overhead happened to pace
the drain -- which is also why it was slow.

Chunk is now 8, half the FIFO depth: it cannot overflow even if the drain
consumes nothing for the whole transaction, while still cutting a 60-byte ACK
from ~60 transactions to 8.  Noted in both the source and CLAUDE.md not to
raise it without deepening tx_bytes or giving the TX path real back-pressure.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-10-09 19:16:28 +02:00
parent a2e8e5ceaf
commit 1e370deb49
2 changed files with 34 additions and 14 deletions
+14 -4
View File
@@ -246,10 +246,20 @@ Details and the recovery ladder are in `gc_bba_test/README.md`. Key points:
veth and the frames go nowhere).
- **Stop-and-wait is load-bearing** — see the RBFI note; one frame in flight
means the ring is never contended.
- `bba_tx_bytes()` streams in 64-byte chunks, ONE EXI transaction each. Writing
byte-by-byte cost a full EXI_Lock/Select/Deselect/Unlock per byte — ~60
transactions per ACK — and that latency, not any transmit failure, is what
made ~⅓ of blocks retry (`txto=0` on hardware: TI always set).
- `bba_tx_bytes()` streams in **8-byte** chunks, one EXI transaction each.
Writing byte-by-byte cost a full EXI_Lock/Select/Deselect/Unlock per byte —
~60 transactions per ACK — and that latency, not any transmit failure, is
what made ~⅓ of blocks retry (`txto=0` on hardware: TI always set).
⚠️ **The chunk size is bounded by `tx_bytes`, which is 16 deep.** Within one
transaction the bytes arrive back-to-back at EXI speed, far faster than
`TXFrameDrain` starts consuming, and `BBARegisterFile` silently drops bytes
when `w_rdy` is low because SPI cannot back-pressure. A 64-byte chunk
overran the FIFO, the frame went out truncated and the host saw no valid ACK
at all. Byte-by-byte only worked because the per-byte EXI overhead happened
to pace the drain. 8 is half the FIFO depth, so it cannot overflow even if
the drain consumes nothing for a whole transaction. **Do not raise it
without deepening `tx_bytes` or giving the TX path real back-pressure.**
### ⚠️ OPEN: ring descriptor sometimes lands at page offset +1