netboot: stop the TI poll turning a slow ACK into a missed deadline
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>
This commit is contained in:
@@ -182,7 +182,17 @@ static int send_ack(u16 seq)
|
||||
* out (TI only means TXFrameDrain handed it to the W5100), and if it did
|
||||
* not, the host's retransmit covers it. Blocking longer here would only
|
||||
* slow the common case to protect against the rare one. */
|
||||
for (i = 0; i < 200; i++) {
|
||||
/* Poll a FEW times, not 200. 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 burned on the ONE path the host
|
||||
* is waiting on -- and it only burns them when TI is slow, which is
|
||||
* exactly when the host is closest to timing out. That turns a slow
|
||||
* transmit into a missed deadline instead of just a slow one.
|
||||
*
|
||||
* TI is not needed for correctness here: the host retransmits anything
|
||||
* it does not get an ACK for, and the GC re-ACKs duplicates. A handful
|
||||
* of polls is enough to count genuine failures in txto. */
|
||||
for (i = 0; i < 8; i++) {
|
||||
ir = bba_r8(REG_IR);
|
||||
if (ir >= 0 && (ir & IR_TI))
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user