The branch main has been updated by bz: URL: https://cgit.FreeBSD.org/src/commit/?id=f68ebebd8ae469e344f10ed2f3c4d9d983a29f41
commit f68ebebd8ae469e344f10ed2f3c4d9d983a29f41 Author: Bjoern A. Zeeb <[email protected]> AuthorDate: 2026-03-05 09:58:28 +0000 Commit: Bjoern A. Zeeb <[email protected]> CommitDate: 2026-03-05 13:44:02 +0000 LinuxKPI: 802.11: change teardown order of disassoc and sta rm In lkpi_sta_auth_to_scan() we remove the sta from the firmware for everything supporting (*sta_state). We used to run into issues here with iwlwifi in that we had to use a specific order: set vif->cfg.assoc = false, .aid = 0, then remove the sta, and then send the mac update as otherwise we would either have the sta silently removed (if we run (*bss_info_change) first and fail then or silently not have the sta removed and upon sta add we would trigger the fw crash. The order of events seem to have changed now and especially BE200 (iwlwifi/mld) is picky about this and would crash the firmware with something like: iwlwifi0: 0x20103311 | ADVANCED_SYSASSERT iwlwifi0: 0x00000000 | umac branchlink1 iwlwifi0: 0xC00808AA | umac branchlink2 iwlwifi0: 0xD00D6E90 | umac interruptlink1 iwlwifi0: 0x0108C504 | umac interruptlink2 iwlwifi0: 0x00000000 | umac data1 (link_id? seen weird values there though) iwlwifi0: 0x00000006 | umac data2 (fw_sta_id) iwlwifi0: 0x00000001 | umac data3 if it would still think we were assoc. So the new order is as one would have expected initially: set assoc = false, aid = 0; do the remaining bss_conf (vif/link) changes and issue the (*vif_cfg_changed) / (*link_info_changed) or for older drivers (*bss_info_changed). That will tell the mac we are no longer associated. And only then remove the sta from the firmware. Update the comment there along so we do have the paper trail as to when and why this changed. Tested on: BE200, AX210 (11ac) Tested on: AX200. 9260, 8265, 3165 (11a) Sponsored by: The FreeBSD Foundation MFC after: 3 days --- sys/compat/linuxkpi/common/src/linux_80211.c | 57 +++++++++++++++------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c index c003075ae601..63f92b8afb2b 100644 --- a/sys/compat/linuxkpi/common/src/linux_80211.c +++ b/sys/compat/linuxkpi/common/src/linux_80211.c @@ -3281,24 +3281,27 @@ lkpi_sta_auth_to_scan(struct ieee80211vap *vap, enum ieee80211_state nstate, int bss_changed = 0; /* - * Start updating bss info (bss_info_changed) (assoc, aid, ..). + * Start updating bss info (*bss_info_changed) (assoc, aid, ..). * - * One would expect this to happen when going off AUTHORIZED. - * See comment there; removes the sta from fw if not careful - * (bss_info_changed() change is executed right away). + * One would expect this to happen when going off AUTHORIZED but + * not so. * - * We need to do this now, before sta changes to IEEE80211_STA_NOTEXIST - * as otherwise drivers (iwlwifi at least) will silently not remove - * the sta from the firmware and when we will add a new one trigger - * a fw assert. + * Immediately issuing the (*bss_info_changed) used to also remove the + * sta from firmware for iwlwifi; or we have problems with the sta + * silently not being removed and then crash upon the next sta add. + * Neither seems to be the case or a problem still. * - * The order which works best so far avoiding early removal or silent - * non-removal seems to be (for iwlwifi::mld-mac80211.c cases; - * the iwlwifi:mac80211.c case still to be tested): - * 1) lkpi_disassoc(): set vif->cfg.assoc = false (aid=0 side effect here) - * 2) call the last sta_state update -> IEEE80211_STA_NOTEXIST - * (removes the sta given assoc is false) - * 3) add the remaining BSS_CHANGED changes and call bss_info_changed() + * Contrary for BE200 (iwlwifi/mld) if we do not issue the + * (*vif_cfg_change) to tell FW that we are no longer assoc + * it will crash now upon sta rm. So the order now is as we once + * expected it: + * + * 1) lkpi_disassoc(): set vif->cfg.assoc = false and .aid=0 + * 2) add the remaining BSS_CHANGED changes and call (*bss_info_changed) + * (which may be split up into (*vif_cfg_change) and + * (*link_info_changed) for more modern drivers). + * 3) call the last sta_state update -> IEEE80211_STA_NOTEXIST + * (removes the sta given assoc is false) and tidy up our lists. * 4) call unassign_vif_chanctx * 5) call lkpi_hw_conf_idle * 6) call remove_chanctx @@ -3310,6 +3313,18 @@ lkpi_sta_auth_to_scan(struct ieee80211vap *vap, enum ieee80211_state nstate, int lkpi_lsta_dump(lsta, ni, __func__, __LINE__); + IMPROVE("Any bss_info changes to announce?"); + vif->bss_conf.qos = false; + bss_changed |= BSS_CHANGED_QOS; + vif->cfg.ssid_len = 0; + memset(vif->cfg.ssid, '\0', sizeof(vif->cfg.ssid)); + bss_changed |= BSS_CHANGED_BSSID; + vif->bss_conf.use_short_preamble = false; + /* XXX BSS_CHANGED_???? */ + vif->bss_conf.dtim_period = 0; /* go back to 0. */ + bss_changed |= BSS_CHANGED_BEACON_INFO; + lkpi_bss_info_change(hw, vif, bss_changed); + /* Adjust sta and change state (from NONE) to NOTEXIST. */ KASSERT(lsta != NULL, ("%s: ni %p lsta is NULL\n", __func__, ni)); KASSERT(lsta->state == IEEE80211_STA_NONE, ("%s: lsta %p state not " @@ -3326,18 +3341,6 @@ lkpi_sta_auth_to_scan(struct ieee80211vap *vap, enum ieee80211_state nstate, int lkpi_lsta_dump(lsta, ni, __func__, __LINE__); - IMPROVE("Any bss_info changes to announce?"); - vif->bss_conf.qos = false; - bss_changed |= BSS_CHANGED_QOS; - vif->cfg.ssid_len = 0; - memset(vif->cfg.ssid, '\0', sizeof(vif->cfg.ssid)); - bss_changed |= BSS_CHANGED_BSSID; - vif->bss_conf.use_short_preamble = false; - /* XXX BSS_CHANGED_???? */ - vif->bss_conf.dtim_period = 0; /* go back to 0. */ - bss_changed |= BSS_CHANGED_BEACON_INFO; - lkpi_bss_info_change(hw, vif, bss_changed); - LKPI_80211_LVIF_LOCK(lvif); /* Remove ni reference for this cache of lsta. */ lvif->lvif_bss = NULL;
