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
This commit is contained in:
Bjoern A. Zeeb
2026-01-03 20:10:00 +00:00
parent fa41408d60
commit 9592f563c3
3 changed files with 128 additions and 21 deletions
+61 -14
View File
@@ -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);
@@ -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 *,
@@ -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