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

Reply via email to