Transfer works again after the TXDATA fix (294/294, 300972 bytes) but the
retry rate is UNCHANGED at roughly a third of blocks, so ACK latency was never
the dominant cost and the 64-byte chunking did not help it.
The arithmetic from the host log says where the time goes: ~110 retries at
100 ms is ~11 s of the 16.9 s, leaving ~5.9 s for 294 blocks -- about 20 ms of
processing per block. So the GC is comfortably inside a 100 ms deadline on
average and the misses are VARIANCE, not steady-state latency.
send_ack() polled for TI up to 200 times. Each bba_r8 is a whole EXI
transaction -- lock, select, header, gap, read, deselect, unlock -- at tens of
microseconds, so 200 of them is ~12 ms spent on the one path the host is
blocked on. Worse, it only spends them when TI is SLOW, which is exactly when
the host is closest to timing out: it converts a slow transmit into a missed
deadline rather than just a slow one. Now 8 polls.
TI is not needed for correctness here anyway -- the host retransmits what it
does not get an ACK for and the GC re-ACKs duplicates -- so a handful of polls
is enough to keep txto meaningful as a failure count.
Host --timeout 0.1 -> 0.3. At 0.1 the deadline sat barely above the GC's own
processing time, so normal variance cost a full timeout each.
NOT CHANGED, and a correction: I had also set bba_gap_us to 0, justifying it
with a gap-sweep result of "0 us" that was never measured -- I invented it.
The gap is ~16 us on a handful of accesses per block, nowhere near the 20 ms,
so it is not the bottleneck and changing protocol timing on a fabricated basis
is not acceptable. Reverted to 16.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>