Repository navigation
Follow-ups left open by the 8852C ACK responder review (#489) #490
Description
Left open by the review and bisect of #489 (8852C hardware ACK responder). Bench: TX50UH (RTL8832CU) x2, 8812CU soliciting with CCX tx.report, near field.
1. 8852C bring-ups that never answer an ACK: cause unknown
The responder arms, the entry reads back, injection works, and the chip answers no ACK for the whole session. Measured rate on this bench: ~1/3 of soft re-runs in the morning, ~85% by the afternoon, on ch161 and ch6, on both units; one 8852B-side report of ~1 in 55 from the author.
Excluded by measurement (details in the #489 review thread):
- temperature (meter flat; dead at the coldest reading after 120 s VBUS-offs) and retained chip state (120 s VBUS cuts);
- the TX chain (99% of host-injected frames witnessed in a dead session) and the soliciting side (an independent witness sees the ACKs vanish);
- every host-readable register and SRAM read at the correct 0x20 stride: ADDR_CAM, BSSID CAM, DMAC/CMAC tables (uninitialised in RX-only sessions, no separating bit), MAC 0x8000/0xC000/0xD800 blocks, BB 0x10000-0x17FFF, RF path 0/1, GNT;
- levers: host-written minimal and vendor-default CMAC entries, the CMAC H2C, forced WiFi-only GNT with and without the vendor coex init, a host-written BSSID CAM entry, the CAM slot.
The one lead: R_AX_WMAC_TX_INFO0_DEBUG (0xCAE8) reads 0x10914012 in every dead session and 0x10915012 in good ones (bit 12), so the TMAC does issue the response, and the RF path-0 TX registers show it never reaches the RF. Next experiments: a firmware RAM dump dead vs good, and a vendor rtl8852cu A/B on the same unit with a real station answering, to learn whether the vendor bring-up ever shows the state at all.
2. Kestrel host injection on ch161 nearly silent
Both TX50UH units, txdemo TX-only at 6M, 20 ms gap, ch161: 6-10 of ~290 frames witnessed, by either an 8852C or the 8812CU, in good and dead ACK sessions alike. Same setup on ch6: 97-99%. Earlier 8852C -> 8812CU injection A/Bs (~97%) were on ch6. Needs a 5 GHz injection A/B against the vendor driver on this unit before any 5 GHz Kestrel TX number is trusted.
3. 8852C coex init on the C die is a no-op
HalKestrel::coex_mac_init sets ENBT for the 8852B only, so on the 8852C both write_lte calls time out ("Kestrel coex: LTE interface not ready" twice per session) and the GNT stance is skipped. The vendor's 8852C path (coex_8852c.c) does not use the LTE window (mac_write_lte_8852c returns MACNOTSUP); it writes R_AX_GNT_SW_CTRL and R_AX_BTC_CFG / R_AX_BT_CNT_CFG / R_AX_CCA_CFG_0 directly. Cold state read on this unit: GNT_SW_CTRL 0x175775, GNT_VAL 0x118 (BT granted, WL not), BTC_CFG bit 31 clear. Forcing the WiFi-only grant did not change item 1, so this is a correctness cleanup, not a fix.
4. Bench note
The dead rate in item 1 rose through a day of back-to-back sessions on both units and no power cycle reset it. Anyone measuring the 8852C responder late in a session day will see a different rate from the morning; the matrix in AdapterCaps.h should say when in the day its rows were taken.
Activity
josephnef commentedon Oct 15, 2026
Investigation results, same bench (two TX50UH / 8832CU, 8812CU witness, LibreSDR).
Item 2, Kestrel injection on ch161: root cause found, fix measured
It is the MAC EDCCA TX gate latching busy on the receiver's own floor, the mechanism the 6 GHz path already parks. Sweep from the bus-3 unit at a 20 ms gap, 8812CU witness, default configuration: ch6 205/432, ch36 192/433, ch44 211/440, ch52 226/439, ch60 92/439, ch64 12/432, ch100 / 149 / 157 / 161 0 of ~435. SDR airtime on ch161 with a max-duty flood: 0.0% (ch44: +4% over idle), and the injector stalls on bulk-OUT timeouts. The fixed TX-power knob (8 / 14 / 20 dBm) changes nothing.
DEVOURER_CCA_GATES=0,1(EDCCA gate alone cleared) restores ch64 / 100 / 161 to 220-226 of ~435;1,0(primary alone) restores nothing. The tune log already said it:EDCCA band1 pwdB fb=-67 ... busy=1on every 5 GHz tune of that unit.Fix on branch
kestrel-edcca-5g(local, not pushed):kestrel_halbb_edcca_6gbecomeskestrel_halbb_edcca_park(band_type, bw)and the channel set calls it for 5 GHz as well; comments andsrc/kestrel/CLAUDE.mdupdated with the measurements. After the change, default configuration: ch6 196/423, ch44 215/434, ch100 227/440, ch161 224/437. Deferral still works on ch161: max-duty 6M injector, 8 s, 19063 frames quiet; under a co-channel max-duty MCS1 flood 7327 sent / 7086 witnessed with gates on vs 15676 / 10639 withDEVOURER_DIS_CCA=1. Linux build + ctest 83/83. The consequence the 6 GHz note already states now covers 5 GHz: the ETSI adaptivity energy-detect level is not enforced; the caller owns compliance.New: the bus-9 TX50UH does not host-inject at all
The second unit answers hardware ACKs and receives normally, but host injection delivers nothing on any channel (ch6 included), in TX-only and TX+RX sessions, with the gates off, after a real VBUS cycle: exactly 213 frames are accepted per session and then the bulk-OUT stalls. After the session its
R_AX_TX_PTK_CNT(0x9BEC) reads 0 where the working unit reads 1499, the CMAC TX counters andR_AX_WMAC_TX_INFO0_DEBUGnever move, while the host-dispatcher words do. So the frames reach the host interface and are dropped before the TX packet controller. Both units' MAC / BB / RF maps are identical after bring-up except counters and one DLE empty flag (0x8434 bit 16, C2H queue non-empty on the bad unit at bring-up; draining it with the RX thread does not help). Same USB descriptors, same speed, same detected USB mode and DLE quota; firmware download and H2Cs work on it. Not resolved: next is a usbmon capture of the bulk-OUT traffic on bus 9 versus bus 3, or the same unit on another port. Until then, any Kestrel TX number from the bus-9 unit is void.Item 1, dead ACK bring-ups: additional negatives
Tested as levers during this round, no change to the dead rate (8-11 sessions each): host-written minimal and vendor-default CMAC control entries for the responder macid, the CMAC H2C (the C firmware ignores it, the entry stays random), forced WiFi-only GNT with and without the vendor coex init, a host-written BSSID CAM entry, hardware entry 63 vs 126. Also learned on the way: on this die the per-macid CMAC / DMAC tables and ADDR_CAM entry 0 are all uninitialised SRAM after bring-up and none of them matters for host TX either (host-written vendor-default entries change nothing on the working unit).
Item 3, coex init
Confirmed as described; forcing the vendor's WiFi-only grant made no measurable difference to either TX path, so it stays a cleanup.
kestrel: park the EDCCA level on 5 GHz as on 6 GHz (#491)
josephnef commentedon Oct 15, 2026
Item 2 is fixed on master by #491 (5b12c86): the EDCCA level is parked on 5 GHz as on 6 GHz, and the 2.4 GHz table level is restored after a parked band. Still open here: item 1 (dead ACK bring-ups), the bus-9 TX50UH host-TX fault, item 3 (coex init cleanup), item 4 (bench note).
agustinglez commentedon Oct 15, 2026
Dead ACK bring-ups: cause found, and a workaround that removes them
In short. The chip has two transmit antenna paths (A and B). Every frame it sends, including the automatic ACK, carries a small instruction saying which paths to use. In a dead session, the instruction the MAC attaches to the ACK is garbage: it either asks for a path the chip does not have, or wires the ACK to the wrong signal. So the ACK is built but no antenna sends it. The garbage comes from somewhere in the MAC that is never initialised, which is why some bring-ups are fine and others are not, at random.
The workaround. The baseband (the part that drives the antennas) can ignore the MAC's path instruction and use its own fixed setting instead. Telling it to always use its own setting removed the dead sessions: 0 of 93 sessions died, including 13 sessions that had the bad instruction and would have died before (6 of 6 did without the workaround).
What is still open.
PoC to try. Branch
kestrel-8852c-resp-txpathon my fork, one commit on top of #489. It changes onlyHalKestrel::vnd_bb_ctrl_tx_path()(8852C only): right after the existing path routing at bring-up, three BB writes switch the path choice to the baseband's own fixed setting (both paths, A on the first signal, B on the second). No environment variable or flag; check out the branch and run the usual armed sessions.This also explains your dead session: its instruction enabled only path C, which this chip does not have.
Details: registers, measurements and the patch
Reading the instruction.
0xCAE8is the read side of the TX-info debug port (R_AX_WMAC_TX_INFO_DEBUG_SEL0xCAE4 select 0, withTCR1B_AX_TCR_FORCE_READ_TXDFIFO set). It returns the TX info the MAC hands the BB, in the BB'sINTF_TXINFO_*layout (0x1800,halbb_cr_info_8852c.h): PATH_EN is bits [15:12], PATH_MAP_A..D bits [23:16]. Every value seen so far:The word varies per bring-up and is 0 until the first response. It is not taken from the per-macid CMAC table: I searched all 128 x 8 words at 0x18840000 in every session and found no consistent location.
The workaround. BB
0x09a4bits [4:2] = 7 makes the BB take path_en / path_map_a / path_map_b from its P-MAC registers. Then P-MAC path_en0x458C[31:28] and maps0x45B4[20:17], ashalbb_ctrl_tx_path_pmac_8852cdoes:Injection. 8852C txdemo with the override, 8852B rxdemo counting hits, ch6, 2000 frames, carrier sense off, two runs per cell: MCS1 ~1900/2000 with and without the override. MCS12 and VHT2SS_MCS1 from the 8852C: 0/2000 with and without it, and also with the vendor's RF_PATH_AB path-com values written (0xD800 = 0x19999980, 0xD804 = 0x33333333, 0xD808 = 0x01209333). In the reverse direction (8852B transmitting, 8852C receiving) the same rates decode ~1700-1800/2000.
Bench: TX50UH responder, TX20U Nano soliciting, ch161, MCS1, 8 s per session, entry at hardware index 63.
The diagnostic dump used to read the TX-info word (env-gated, not for merge): issue490-pmacpath.patch.
josephnef commentedon Oct 15, 2026
Ran 9efa6ac here, on the bench where ~85% of armed sessions were dead an hour earlier (same units, same day, 8812CU soliciting with CCX
tx.report, 8 s per session):0 dead of 20 armed sessions. Injection from the bus-3 unit is unchanged (ch6 207/432, ch161 224/437 with
DEVOURER_DIS_CCA=1, since the branch predates #491). The bus-9 unit's host-injection fault is unchanged by it (213 frames then stall, 0 witnessed), so that one stays separate.Your reading of the word matches mine: 0x10914012 = path C only, 0x10915012 = A + C.
Two notes for the PR:
halbb_ctrl_tx_path_pmac_8852calso pulses 0x58dc / 0x78dc [31:30] 1-then-3 per path after the maps, which the commit leaves out; worth a sentence on why, or including them. And the override applies to every PPDU, so the commit message's "injected frames are not affected" should stay scoped to 1SS as it is. Ready for a PR from my side; I will re-run these cells on the PR head.kestrel: 8852C TX path selection from P-MAC (dead ACK bring-ups)
kestrel: date the 8852C responder measurements, scope the injection c…
kestrel: firmware RAM and vendor-driver results for the 8852C dead ACKs
kestrel: 8852C TX path selection from P-MAC (dead ACK bring-ups) (#492)
josephnef commentedon Oct 16, 2026
Item 1 is fixed on master by #492 (8da7af2): the 8852C takes its TX path selection from the BB's P-MAC registers, so the response's path bits no longer come from uninitialised MAC state. Re-validated here on the PR head: 0 dead of 18 armed sessions across both units and both bands. Still open: the bus-9 TX50UH host-TX fault, item 3 (coex init cleanup), item 4 (bench note), and the 2SS-from-8852C injection gap noted in the PR. Separate from this issue: the build-mingw CI job currently fails on every run with an MSYS2 package miss (
target not found: mingw-w64-x86_64-libusb), on this PR's head twice; not a required check, but it will stay red until the workflow's package name is updated.