git: fc9369abef6b - main - LinuxKPI: 802.11: do not leak BA sessions when tearing down state
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 24 Feb 2026 22:09:10 UTC
The branch main has been updated by bz:
URL: https://cgit.FreeBSD.org/src/commit/?id=fc9369abef6b6993e79b08de832e1d49f81a17b9
commit fc9369abef6b6993e79b08de832e1d49f81a17b9
Author: Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2026-02-24 12:55:48 +0000
Commit: Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2026-02-24 22:06:18 +0000
LinuxKPI: 802.11: do not leak BA sessions when tearing down state
In certain cases we may tear down state of a node with 'ongoing'
BA sessions. This can trigger a firmware crash with iwlwifi as
reported in [1] when trying to remove the sta from the firmware.
0x2010303A | ADVANCED_SYSASSERT
..
0x00000000 | umac data1 (sta id=0)
..
0x0088030C | last host cmd (STA_RM)
[1] https://lists.freebsd.org/archives/freebsd-wireless/2025-November/003901.html
I hit the same problem while running regression tests after
reworking some LinuxKPI 802.11 sta state machine bits.
Add the missing calls to lkpi_sta_run_to_assoc() and lkpi_sta_run_to_init()
to make sure (through net80211) we call (*ampdu_action) with
IEEE80211_AMPDU_RX_STOP to avoid the firmware crash.
Note: this specific patch was not excessively tested. The upcoming
change to the state machine including this fix has seen more testing
but also only needed the change in one place.
The reason for putting this in upfront is to document the case well.
Reported by: Mohammad Amin (the.madamin20 gmail.com) [1]
Sponsored by: The FreeBSSD Foundation
MFC after: 3 days
---
sys/compat/linuxkpi/common/src/linux_80211.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c
index 0b732cb691c6..e80cf9436b3a 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211.c
@@ -3256,6 +3256,7 @@ lkpi_sta_run_to_assoc(struct ieee80211vap *vap, enum ieee80211_state nstate, int
#if 0
enum ieee80211_bss_changed bss_changed;
#endif
+ struct ieee80211_rx_ampdu *rap;
int error;
lhw = vap->iv_ic->ic_softc;
@@ -3311,6 +3312,16 @@ lkpi_sta_run_to_assoc(struct ieee80211vap *vap, enum ieee80211_state nstate, int
goto outni;
}
+ /* Stop any BA sessions if still active. */
+ for (int rapn = 0; rapn < WME_NUM_TID; rapn++) {
+ rap = &ni->ni_rx_ampdu[rapn];
+
+ if ((rap->rxa_flags & IEEE80211_AGGR_RUNNING) == 0)
+ continue;
+
+ vap->iv_ic->ic_ampdu_rx_stop(ni, rap);
+ }
+
IEEE80211_UNLOCK(vap->iv_ic);
/* Ensure the packets get out. */
@@ -3412,6 +3423,7 @@ lkpi_sta_run_to_init(struct ieee80211vap *vap, enum ieee80211_state nstate, int
struct ieee80211_sta *sta;
struct ieee80211_prep_tx_info prep_tx_info;
enum ieee80211_bss_changed bss_changed;
+ struct ieee80211_rx_ampdu *rap;
int error;
lhw = vap->iv_ic->ic_softc;
@@ -3467,6 +3479,16 @@ lkpi_sta_run_to_init(struct ieee80211vap *vap, enum ieee80211_state nstate, int
goto outni;
}
+ /* Stop any BA sessions if still active. */
+ for (int rapn = 0; rapn < WME_NUM_TID; rapn++) {
+ rap = &ni->ni_rx_ampdu[rapn];
+
+ if ((rap->rxa_flags & IEEE80211_AGGR_RUNNING) == 0)
+ continue;
+
+ vap->iv_ic->ic_ampdu_rx_stop(ni, rap);
+ }
+
IEEE80211_UNLOCK(vap->iv_ic);
/* Ensure the packets get out. */