git: c78d70298ede - main - iwn: fix TX QoS AC -> TID mapping for A-MPDU selection
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 19 Oct 2026 00:36:27 UTC
The branch main has been updated by adrian:
URL: https://cgit.FreeBSD.org/src/commit/?id=c78d70298edef4c599b503536d193caeb8204784
commit c78d70298edef4c599b503536d193caeb8204784
Author: Adrian Chadd <adrian@FreeBSD.org>
AuthorDate: 2026-10-19 00:34:46 +0000
Commit: Adrian Chadd <adrian@FreeBSD.org>
CommitDate: 2026-10-19 00:34:46 +0000
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
---
sys/dev/iwn/if_iwn.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/sys/dev/iwn/if_iwn.c b/sys/dev/iwn/if_iwn.c
index 7fc013704253..0a5e608c8071 100644
--- a/sys/dev/iwn/if_iwn.c
+++ b/sys/dev/iwn/if_iwn.c
@@ -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);