The branch main has been updated by bz: URL: https://cgit.FreeBSD.org/src/commit/?id=9592f563c36bd207d98f1b3a13839b88d5760d97
commit 9592f563c36bd207d98f1b3a13839b88d5760d97 Author: Bjoern A. Zeeb <[email protected]> AuthorDate: 2026-01-03 20:10:00 +0000 Commit: Bjoern A. Zeeb <[email protected]> CommitDate: 2026-03-05 13:44:02 +0000 LinuxKPI: 802.11: split (*bss_info_changed) up for more modern drivers With the advent of MLO some of the updates (*bss_info_changed) would have done are not per-link. This had (*vif_cfg_changed) and (*link_conf_changed) introduced which are used by iwlwifi, rtw89, select mt76 drivers, and ath12k currently it seems. A driver normally only supports on or the other set. Factor out the call to (*bss_info_changed) into an internal function. There split the options up depending on whether they are for the vif or a link and leave a fallback to (*bss_info_changed) for older drivers. Add the mac80211 ops implementations for the two new calls along with a currently unused backup option for (*bss_info_changed) for each as I assume we will eventually call the directly rather than from the internal wrapper function. Sponsored by: The FreeBSD Foundation MFC after: 3 days --- sys/compat/linuxkpi/common/src/linux_80211.c | 75 ++++++++++++++++++---- sys/compat/linuxkpi/common/src/linux_80211.h | 4 ++ .../linuxkpi/common/src/linux_80211_macops.c | 70 ++++++++++++++++++-- 3 files changed, 128 insertions(+), 21 deletions(-) diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c index 799ecb245661..c003075ae601 100644 --- a/sys/compat/linuxkpi/common/src/linux_80211.c +++ b/sys/compat/linuxkpi/common/src/linux_80211.c @@ -2242,6 +2242,53 @@ lkpi_remove_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif) free(lchanctx, M_LKPI80211); } +/* -------------------------------------------------------------------------- */ + +/* Any other options belong here? Check more drivers. */ +#define BSS_CHANGED_VIF_CFG_BITS \ + (BSS_CHANGED_SSID | BSS_CHANGED_IDLE | BSS_CHANGED_PS | BSS_CHANGED_ASSOC | \ + BSS_CHANGED_ARP_FILTER | BSS_CHANGED_MLD_VALID_LINKS | BSS_CHANGED_MLD_TTLM) + +static void +lkpi_bss_info_change(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + enum ieee80211_bss_changed bss_changed) +{ + struct lkpi_vif *lvif; + enum ieee80211_bss_changed vif_cfg_bits, link_info_bits; + + if (ieee80211_vif_is_mld(vif)) { + TODO("This likely needs a subset only; split up into 3 parts."); + } + + /* Nothing to do? */ + if (bss_changed == 0) + return; + + /* + * If the vif is not known to the driver there is nothing to notifiy for. + * We MUST NOT check for !lvif_bss_synched here (the reasonable it seems) + * as we need to execute the update(s) or we will have follow-up issues. + */ + lvif = VIF_TO_LVIF(vif); + if (!lvif->added_to_drv) + return; + + /* + * With the advent of MLO bss_conf got split up into vif and link + * change notfications, while historically it was one. + * We now need to support all possible models. + */ + vif_cfg_bits = bss_changed & BSS_CHANGED_VIF_CFG_BITS; + if (vif_cfg_bits != 0) + lkpi_80211_mo_vif_cfg_changed(hw, vif, vif_cfg_bits, false); + + link_info_bits = bss_changed & ~(BSS_CHANGED_VIF_CFG_BITS); + if (link_info_bits != 0) + lkpi_80211_mo_link_info_changed(hw, vif, &vif->bss_conf, + link_info_bits, 0, false); + + lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, bss_changed); +} /* -------------------------------------------------------------------------- */ @@ -2457,7 +2504,7 @@ lkpi_sta_scan_to_auth(struct ieee80211vap *vap, enum ieee80211_state nstate, int /* RATES */ IMPROVE("bss info: not all needs to come now and rates are missing"); - lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, bss_changed); + lkpi_bss_info_change(hw, vif, bss_changed); /* * Given ni and lsta are 1:1 from alloc to free we can assert that @@ -2791,7 +2838,7 @@ lkpi_sta_assoc_to_run(struct ieee80211vap *vap, enum ieee80211_state nstate, int } bss_changed |= lkpi_update_dtim_tsf(vif, ni, vap, __func__, __LINE__); - lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, bss_changed); + lkpi_bss_info_change(hw, vif, bss_changed); /* - change_chanctx (if needed) * - event_callback @@ -2851,7 +2898,7 @@ lkpi_sta_assoc_to_run(struct ieee80211vap *vap, enum ieee80211_state nstate, int bss_changed = 0; bss_changed |= lkpi_update_dtim_tsf(vif, ni, vap, __func__, __LINE__); - lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, bss_changed); + lkpi_bss_info_change(hw, vif, bss_changed); /* Prepare_multicast && configure_filter. */ lkpi_update_mcast_filter(vap->iv_ic); @@ -3289,7 +3336,7 @@ lkpi_sta_auth_to_scan(struct ieee80211vap *vap, enum ieee80211_state nstate, int /* XXX BSS_CHANGED_???? */ vif->bss_conf.dtim_period = 0; /* go back to 0. */ bss_changed |= BSS_CHANGED_BEACON_INFO; - lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, bss_changed); + lkpi_bss_info_change(hw, vif, bss_changed); LKPI_80211_LVIF_LOCK(lvif); /* Remove ni reference for this cache of lsta. */ @@ -3653,7 +3700,7 @@ lkpi_wme_update(struct lkpi_hw *lhw, struct ieee80211vap *vap, bool planned) struct chanAccParams chp; struct wmeParams wmeparr[WME_NUM_AC]; struct ieee80211_tx_queue_params txqp; - enum ieee80211_bss_changed changed; + enum ieee80211_bss_changed bss_changed; int error; uint16_t ac; @@ -3704,11 +3751,11 @@ lkpi_wme_update(struct lkpi_hw *lhw, struct ieee80211vap *vap, bool planned) ic_printf(ic, "%s: conf_tx ac %u failed %d\n", __func__, ac, error); } - changed = BSS_CHANGED_QOS; + bss_changed = BSS_CHANGED_QOS; if (!planned) - lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, changed); + lkpi_bss_info_change(hw, vif, bss_changed); - return (changed); + return (bss_changed); } #endif @@ -3774,7 +3821,7 @@ lkpi_iv_sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, * locking, see if queue_work() is fast enough. */ bss_changed = lkpi_update_dtim_tsf(vif, ni, ni->ni_vap, __func__, __LINE__); - lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, bss_changed); + lkpi_bss_info_change(hw, vif, bss_changed); } /* @@ -3820,7 +3867,7 @@ lkpi_ic_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], struct ieee80211vap *vap; struct ieee80211_vif *vif; struct ieee80211_tx_queue_params txqp; - enum ieee80211_bss_changed changed; + enum ieee80211_bss_changed bss_changed; struct sysctl_oid *node; size_t len; int error, i; @@ -3937,8 +3984,8 @@ lkpi_ic_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], LKPI_80211_LHW_LVIF_UNLOCK(lhw); /* Set bss_info. */ - changed = 0; - lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, changed); + bss_changed = 0; + lkpi_bss_info_change(hw, vif, bss_changed); /* Configure tx queues (conf_tx), default WME & send BSS_CHANGED_QOS. */ IMPROVE("Hardcoded values; to fix see 802.11-2016, 9.4.2.29 EDCA Parameter Set element"); @@ -3956,8 +4003,8 @@ lkpi_ic_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], __func__, ac, error); } wiphy_unlock(hw->wiphy); - changed = BSS_CHANGED_QOS; - lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, changed); + bss_changed = BSS_CHANGED_QOS; + lkpi_bss_info_change(hw, vif, bss_changed); /* Force MC init. */ lkpi_update_mcast_filter(ic); diff --git a/sys/compat/linuxkpi/common/src/linux_80211.h b/sys/compat/linuxkpi/common/src/linux_80211.h index 3d25ab4a857b..8ae5c3d13d2d 100644 --- a/sys/compat/linuxkpi/common/src/linux_80211.h +++ b/sys/compat/linuxkpi/common/src/linux_80211.h @@ -469,6 +469,10 @@ void lkpi_80211_mo_change_chanctx(struct ieee80211_hw *, struct ieee80211_chanctx_conf *, uint32_t); void lkpi_80211_mo_remove_chanctx(struct ieee80211_hw *, struct ieee80211_chanctx_conf *); +void lkpi_80211_mo_vif_cfg_changed(struct ieee80211_hw *, struct ieee80211_vif *, + uint64_t, bool); +void lkpi_80211_mo_link_info_changed(struct ieee80211_hw *, struct ieee80211_vif *, + struct ieee80211_bss_conf *, uint64_t, uint8_t, bool); void lkpi_80211_mo_bss_info_changed(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_bss_conf *, uint64_t); int lkpi_80211_mo_conf_tx(struct ieee80211_hw *, struct ieee80211_vif *, diff --git a/sys/compat/linuxkpi/common/src/linux_80211_macops.c b/sys/compat/linuxkpi/common/src/linux_80211_macops.c index 634cffddea9e..42067e36c953 100644 --- a/sys/compat/linuxkpi/common/src/linux_80211_macops.c +++ b/sys/compat/linuxkpi/common/src/linux_80211_macops.c @@ -546,24 +546,80 @@ lkpi_80211_mo_remove_chanctx(struct ieee80211_hw *hw, } void -lkpi_80211_mo_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_bss_conf *conf, uint64_t changed) +lkpi_80211_mo_vif_cfg_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + uint64_t vif_cfg_bits, bool fallback) +{ + struct lkpi_hw *lhw; + + might_sleep(); + /* XXX-FINISH all callers for lockdep_assert_wiphy(hw->wiphy); */ + + lhw = HW_TO_LHW(hw); + if (lhw->ops->vif_cfg_changed == NULL && + lhw->ops->bss_info_changed == NULL) + return; + + if (vif_cfg_bits == 0) + return; + + LKPI_80211_TRACE_MO("hw %p vif %p vif_cfg_bits %#jx", hw, vif, (uintmax_t)vif_cfg_bits); + if (lhw->ops->link_info_changed != NULL) + lhw->ops->vif_cfg_changed(hw, vif, vif_cfg_bits); + else if (fallback) + lhw->ops->bss_info_changed(hw, vif, &vif->bss_conf, vif_cfg_bits); +} + +void +lkpi_80211_mo_link_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *conf, uint64_t link_info_bits, uint8_t link_id, + bool fallback) { struct lkpi_hw *lhw; + might_sleep(); + /* XXX-FINISH all callers for lockdep_assert_wiphy(hw->wiphy); */ + lhw = HW_TO_LHW(hw); if (lhw->ops->link_info_changed == NULL && lhw->ops->bss_info_changed == NULL) return; - if (changed == 0) + if (link_info_bits == 0) return; - LKPI_80211_TRACE_MO("hw %p vif %p conf %p changed %#jx", hw, vif, conf, (uintmax_t)changed); + if (!ieee80211_vif_link_active(vif, link_id)) + return; + + LKPI_80211_TRACE_MO("hw %p vif %p conf %p link_info_bits %#jx", hw, vif, conf, (uintmax_t)link_info_bits); if (lhw->ops->link_info_changed != NULL) - lhw->ops->link_info_changed(hw, vif, conf, changed); - else - lhw->ops->bss_info_changed(hw, vif, conf, changed); + lhw->ops->link_info_changed(hw, vif, conf, link_info_bits); + else if (fallback) + lhw->ops->bss_info_changed(hw, vif, conf, link_info_bits); +} + +/* + * This is basically obsolete but one caller. + * The functionality is now split between lkpi_80211_mo_link_info_changed() and + * lkpi_80211_mo_vif_cfg_changed(). Those functions have a flag whether to call + * the (*bss_info_changed) fallback or not. See lkpi_bss_info_change(). + */ +void +lkpi_80211_mo_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *conf, uint64_t bss_changed) +{ + struct lkpi_hw *lhw; + + /* XXX-FINISH all callers for lockdep_assert_wiphy(hw->wiphy); */ + + lhw = HW_TO_LHW(hw); + if (lhw->ops->bss_info_changed == NULL) + return; + + if (bss_changed == 0) + return; + + LKPI_80211_TRACE_MO("hw %p vif %p conf %p changed %#jx", hw, vif, conf, (uintmax_t)bss_changed); + lhw->ops->bss_info_changed(hw, vif, conf, bss_changed); } int
