git: 9592f563c36b - main - LinuxKPI: 802.11: split (*bss_info_changed) up for more modern drivers
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 05 Mar 2026 13:44:35 UTC
The branch main has been updated by bz:
URL: https://cgit.FreeBSD.org/src/commit/?id=9592f563c36bd207d98f1b3a13839b88d5760d97
commit 9592f563c36bd207d98f1b3a13839b88d5760d97
Author: Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2026-01-03 20:10:00 +0000
Commit: Bjoern A. Zeeb <bz@FreeBSD.org>
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