The missing 4-way handshake is ath10k's rx_confused latch: one split A-MSDU disables data RX for the life of the firmware
scope: device:google-taimen · severity: finding · confidence: proven · subsystem: radio
The question — two-thirds-of-associations-never-get-keys proved that
most successful associations never get a 4-way handshake, and left exactly one
fork open: does the AP’s EAPOL msg 1/4 never arrive, or does our msg 2/4 never
leave the chip? The wpa_supplicant -d instrument was installed to answer it.
The answer — msg 1/4 never arrives, and the reason is in our own driver. Counted on the failing boot of 2026-09-01:
associations: 69key negotiations: 2RX EAPOL-Key frames: 0IEEE 802.1X RX: 4 (the two that worked, msg 1/4 and 3/4)ath10k_htt_rx_in_ord_ind() pops an in-order indication into an on-stack list
and hands it to ath10k_htt_rx_extract_amsdu(). The WCN3990 may split one
A-MSDU across two consecutive indications; the extractor then runs off the
end of the list without finding a last-MSDU marker and returns -EAGAIN. The
switch treats that as impossible:
case -EAGAIN: fallthrough; default: /* Should not happen. */ ath10k_warn(ar, "failed to extract amsdu: %d\n", ret); htt->rx_confused = true;rx_confused is cleared in exactly one place, ath10k_htt_rx_alloc(), so
only a firmware restart ever clears it. While set, both the handler and
ath10k_htt_rx_in_ord_ind() return -EIO at their first line. All data RX
is dead from that moment until the module is reloaded.
Management frames go through WMI and are untouched, which is what makes this so hard to see: the station keeps associating perfectly. Only data is lost, and the first data frame of any connection is EAPOL msg 1/4 – so every association from then on reaches ASSOCIATED and times out. ath10k logs one warning, ever.
The correlation, over eight days. Nine failed to extract amsdu: -11
events. Not one is followed by a successful key negotiation within nineteen
minutes. Five were ended only by a reboot; four “recovered” after 19 minutes
to 9 hours, which is the AP or the supplicant giving up and something else
restarting the firmware. The decisive arm:
modprobe -r ath10k_snoc && modprobe ath10k_snoc -> 1 association, keys completed in the same secondWhat this rules out
- The AP. During the failure the supplicant alternated 5 GHz (5180) and 2.4 GHz (2472) and associated successfully on both, got keys on neither.
- The channel or the regulatory domain. phy0 sits at
country 99by design – that is patch 0056’sregd_override=0x67world SKU doing its job, and the country is meant to come from the beacon country IE. Beacon hints were confirmed to have cleared no-IR on channels 12-13, and association still failed. Do not spend a session on the regdomain for this symptom. - A band or a signal problem. Both bands, identical behaviour.
- The key-install-timeout path.
install key timed outhas never fired.
The fix — upstream RFC by Richard Acayan, 2026-02-09, “wifi: ath10k: make
in-order rx amsdu buffers persistent”, which moves the list into driver state so
a split A-MSDU completes on the next indication instead of latching. Carried as
aport patch 0202 with his authorship. It is an RFC with review replies that
have not been read; read the thread before posting a Tested-by.
How to check it is really running — strings the module on the phone, not
the source: the patched ath10k_core.ko contains
split amsdu did not resume immediately. Confirm ath10k is absent from
modules-initfs.mainline (it is), so the loaded copy really came from
/lib/modules and not the boot image.
What is NOT yet proven — the patched path has not been exercised. As of the
first boot on it: 2 associations, 2 key negotiations, 0 amsdu failures. The
proof is the next failed to extract amsdu: RX must survive it. Until one
occurs, this fix is installed and verified present, not demonstrated. Pair the
counts again after a few days – the ratio is the signal, never the count.
