iwn: fix TX QoS AC -> TID mapping for A-MPDU selection

Map the packet QoS value to a TID before looking it up in the
per node + TID AMPDU state array.

The TX A-MPDU state used to be per-AC, but I changed it to be
per-TID because it /is/ negotiated per-TID.  However this is
not aligned correctly and A-MPDU on eg the voice queue would
cause a mismatch and thus packets to get dropped.

(TIDs 8..15 are special and session based, not traffic QoS based.)

I noticed this because "ssh host" failed after a while, but
"telnet host 22" succeeded.  It turned out that frames weren't
making it to the driver transmit path and I traced it
back to being dropped here.  Traffic worked for a while until
A-MPDU TX was negotiated, and then all traffic on a TID
would fail until the 802.11 association was re-established.

Locally tested:

* iwn 6205, STA mode - forced traffic into VO AC/TID

MFC after: 1 week

Differential Revision:	https://reviews.freebsd.org/D60848
This commit is contained in:
Adrian Chadd committed 2026-10-18 17:34:46 -07:00
1 parent 5bf3e2a141
commit c78d70298e
1 file changed
+11 -1
+11 -1
View File
@@ -4587,9 +4587,19 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
* anyway ourselves (and should stub out / warn / etc.)
*/
/*
* Ok, this is a bit "fun" and could do with some cleanup.
* 'ac' here is (mostly) the AC, not TID. It's actually used
* as the destination txq.
*
* For A-MPDU enabled queues, 'ac' becomes the private queue
* allocated for this TID. However, ni_tx_ampdu[] is now per
* TID, not per AC. So a little twisty logic is done here.
*/
ac = M_WME_GETAC(m);
if (m->m_flags & M_AMPDU_MPDU) {
struct ieee80211_tx_ampdu *tap = &ni->ni_tx_ampdu[ac];
struct ieee80211_tx_ampdu *tap =
&ni->ni_tx_ampdu[WME_AC_TO_TID(ac)];
if (!IEEE80211_AMPDU_RUNNING(tap))
return (EINVAL);