git: 4d29178e7154 - main - iwx: tag RX frames as A_MPDU RX; tag A-MSDU frames appropriately
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 21 Nov 2025 07:11:05 UTC
The branch main has been updated by adrian:
URL: https://cgit.FreeBSD.org/src/commit/?id=4d29178e715449c25b94f115946dc4e021f41cdb
commit 4d29178e715449c25b94f115946dc4e021f41cdb
Author: Adrian Chadd <adrian@FreeBSD.org>
AuthorDate: 2025-11-16 04:26:22 +0000
Commit: Adrian Chadd <adrian@FreeBSD.org>
CommitDate: 2025-11-21 07:09:47 +0000
iwx: tag RX frames as A_MPDU RX; tag A-MSDU frames appropriately
* tag packets for 11n/11ac associated nodes with A_MPDU so they
get passed into the reordering logic
* tag A-MSDU frames with AMSDU and AMSDU_MORE so they don't get
dropped due to duplicate sequence numbers.
Note: I haven't yet elicited A-MSDU in A-MPDU to fully test this,
but I do see the net80211 reordering logic kick in (which you can
see via wlanstats -i wlan0 -o ampdu 1).
I've checked with Johannes Berg at Intel (who maintains the linux
iwlwifi stuff); he replied saying none of the firmware versions are
doing AMPDU reorder offloading.
Differential Revision: https://reviews.freebsd.org/D53781
Locally tested:
* AX210, STA mode, > 200mbit bidirectional traffic testing on
5GHz VHT/40.
---
sys/dev/iwx/if_iwx.c | 62 +++++++++++++++++++++++++++-------------------------
1 file changed, 32 insertions(+), 30 deletions(-)
diff --git a/sys/dev/iwx/if_iwx.c b/sys/dev/iwx/if_iwx.c
index e317ff9e271c..3c953e522973 100644
--- a/sys/dev/iwx/if_iwx.c
+++ b/sys/dev/iwx/if_iwx.c
@@ -4607,37 +4607,39 @@ iwx_rx_mpdu_mq(struct iwx_softc *sc, struct mbuf *m, void *pktdata,
pad = 1;
}
-// /*
-// * Hardware de-aggregates A-MSDUs and copies the same MAC header
-// * in place for each subframe. But it leaves the 'A-MSDU present'
-// * bit set in the frame header. We need to clear this bit ourselves.
-// * (XXX This workaround is not required on AX200/AX201 devices that
-// * have been tested by me, but it's unclear when this problem was
-// * fixed in the hardware. It definitely affects the 9k generation.
-// * Leaving this in place for now since some 9k/AX200 hybrids seem
-// * to exist that we may eventually add support for.)
-// *
-// * And we must allow the same CCMP PN for subframes following the
-// * first subframe. Otherwise they would be discarded as replays.
-// */
+ /* If it's a HT node then perform re-order processing */
+ if (ni->ni_flags & IEEE80211_NODE_HT)
+ m->m_flags |= M_AMPDU;
+
+ /*
+ * Hardware de-aggregates A-MSDUs and copies the same MAC header
+ * in place for each subframe. But it leaves the 'A-MSDU present'
+ * bit set in the frame header. We need to clear this bit ourselves.
+ * (XXX This workaround is not required on AX200/AX201 devices that
+ * have been tested by me, but it's unclear when this problem was
+ * fixed in the hardware. It definitely affects the 9k generation.
+ * Leaving this in place for now since some 9k/AX200 hybrids seem
+ * to exist that we may eventually add support for.)
+ *
+ * And we must allow the same CCMP PN for subframes following the
+ * first subframe. Otherwise they would be discarded as replays.
+ */
if (desc->mac_flags2 & IWX_RX_MPDU_MFLG2_AMSDU) {
- DPRINTF(("%s: === IWX_RX_MPDU_MFLG2_AMSDU\n", __func__));
-// struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);
-// uint8_t subframe_idx = (desc->amsdu_info &
-// IWX_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK);
-// if (subframe_idx > 0)
-// rxi.rxi_flags |= IEEE80211_RXI_HWDEC_SAME_PN;
-// if (ieee80211_has_qos(wh) && ieee80211_has_addr4(wh) &&
-// m->m_len >= sizeof(struct ieee80211_qosframe_addr4)) {
-// struct ieee80211_qosframe_addr4 *qwh4 = mtod(m,
-// struct ieee80211_qosframe_addr4 *);
-// qwh4->i_qos[0] &= htole16(~IEEE80211_QOS_AMSDU);
-// } else if (ieee80211_has_qos(wh) &&
-// m->m_len >= sizeof(struct ieee80211_qosframe)) {
-// struct ieee80211_qosframe *qwh = mtod(m,
-// struct ieee80211_qosframe *);
-// qwh->i_qos[0] &= htole16(~IEEE80211_QOS_AMSDU);
-// }
+ struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);
+ uint8_t subframe_idx = (desc->amsdu_info &
+ IWX_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK);
+ uint8_t *qos;
+
+ rxs.c_pktflags |= IEEE80211_RX_F_AMSDU;
+ if (subframe_idx > 0)
+ rxs.c_pktflags |= IEEE80211_RX_F_AMSDU_MORE;
+
+ /* XXX should keep driver statistics about this */
+ IWX_DPRINTF(sc, IWX_DEBUG_AMPDU_MGMT,
+ "%s: === IWX_RX_MPDU_MFLG2_AMSDU\n", __func__);
+
+ qos = ieee80211_getqos(wh);
+ qos[0] &= ~IEEE80211_QOS_AMSDU;
}
/*