The branch main has been updated by bz:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=a8f735a66130aa737999fad9b3246159099dc9eb

commit a8f735a66130aa737999fad9b3246159099dc9eb
Author:     Bjoern A. Zeeb <b...@freebsd.org>
AuthorDate: 2025-01-25 23:39:53 +0000
Commit:     Bjoern A. Zeeb <b...@freebsd.org>
CommitDate: 2025-02-19 12:16:15 +0000

    LinuxKPI: 802.11: switch vif station list to a linux list
    
    We ran into problems with locking the VIF for the lsta tailq on and
    off.  Switch from a native tailq to the LinuxKPI list.
    This allows us to implement the "rcu" part in
    linuxkpi_ieee80211_iterate_keys() which we could not before.
    Further using either rcu or the wiphy lock we no longer run into
    problems with the lock not being sleepable.
    The last case was rtw89 debugfs which was doing a sleepable alloc
    in the iterator callback of linuxkpi_ieee80211_iterate_stations_atomic().
    
    Sponsored by:   The FreeBSD Foundation
    MFC after:      3 days
---
 sys/compat/linuxkpi/common/src/linux_80211.c | 60 ++++++++++++++--------------
 sys/compat/linuxkpi/common/src/linux_80211.h |  9 ++++-
 2 files changed, 38 insertions(+), 31 deletions(-)

diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c 
b/sys/compat/linuxkpi/common/src/linux_80211.c
index 95c7507fc34e..1bce8f9f54b5 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211.c
@@ -74,6 +74,7 @@
 #include <net/mac80211.h>
 
 #include <linux/workqueue.h>
+#include <linux/rculist.h>
 #include "linux_80211.h"
 
 #define        LKPI_80211_WME
@@ -294,7 +295,7 @@ lkpi_80211_dump_stas(SYSCTL_HANDLER_ARGS)
        sbuf_new_for_sysctl(&s, NULL, 1024, req);
 
        wiphy_lock(hw->wiphy);
-       TAILQ_FOREACH(lsta, &lvif->lsta_head, lsta_entry) {
+       list_for_each_entry(lsta, &lvif->lsta_list, lsta_list) {
                sta = LSTA_TO_STA(lsta);
 
                sbuf_putc(&s, '\n');
@@ -463,12 +464,11 @@ lkpi_lsta_remove(struct lkpi_sta *lsta, struct lkpi_vif 
*lvif)
 {
 
 
-       LKPI_80211_LVIF_LOCK(lvif);
-       KASSERT(lsta->lsta_entry.tqe_prev != NULL,
-           ("%s: lsta %p lsta_entry.tqe_prev %p ni %p\n", __func__,
-           lsta, lsta->lsta_entry.tqe_prev, lsta->ni));
-       TAILQ_REMOVE(&lvif->lsta_head, lsta, lsta_entry);
-       LKPI_80211_LVIF_UNLOCK(lvif);
+       wiphy_lock(lsta->hw->wiphy);
+       KASSERT(!list_empty(&lsta->lsta_list),
+           ("%s: lsta %p ni %p\n", __func__, lsta, lsta->ni));
+       list_del_init(&lsta->lsta_list);
+       wiphy_unlock(lsta->hw->wiphy);
 }
 
 static struct lkpi_sta *
@@ -488,6 +488,7 @@ lkpi_lsta_alloc(struct ieee80211vap *vap, const uint8_t 
mac[IEEE80211_ADDR_LEN],
        if (lsta == NULL)
                return (NULL);
 
+       lsta->hw = hw;
        lsta->added_to_drv = false;
        lsta->state = IEEE80211_STA_NOTEXIST;
        /*
@@ -1773,10 +1774,10 @@ lkpi_sta_scan_to_auth(struct ieee80211vap *vap, enum 
ieee80211_state nstate, int
        lsta->txq_ready = true;
        LKPI_80211_LSTA_TXQ_UNLOCK(lsta);
 
-       LKPI_80211_LVIF_LOCK(lvif);
+       wiphy_lock(hw->wiphy);
        /* Insert the [l]sta into the list of known stations. */
-       TAILQ_INSERT_TAIL(&lvif->lsta_head, lsta, lsta_entry);
-       LKPI_80211_LVIF_UNLOCK(lvif);
+       list_add_tail(&lsta->lsta_list, &lvif->lsta_list);
+       wiphy_unlock(hw->wiphy);
 
        /* Add (or adjust) sta and change state (from NOTEXIST) to NONE. */
        KASSERT(lsta != NULL, ("%s: ni %p lsta is NULL\n", __func__, ni));
@@ -3297,7 +3298,7 @@ lkpi_ic_vap_create(struct ieee80211com *ic, const char 
name[IFNAMSIZ],
 
        lvif = malloc(len, M_80211_VAP, M_WAITOK | M_ZERO);
        mtx_init(&lvif->mtx, "lvif", NULL, MTX_DEF);
-       TAILQ_INIT(&lvif->lsta_head);
+       INIT_LIST_HEAD(&lvif->lsta_list);
        lvif->lvif_bss = NULL;
        lvif->lvif_bss_synched = false;
        vap = LVIF_TO_VAP(lvif);
@@ -5751,11 +5752,12 @@ linuxkpi_ieee80211_iterate_keys(struct ieee80211_hw *hw,
        lvif = VIF_TO_LVIF(vif);
 
        if (rcu) {
+               rcu_read_lock_held();           /* XXX-BZ is this correct? */
+
                if (vif == NULL) {
                        TODO();
                } else {
-                       IMPROVE("We do not actually match the RCU code");
-                       TAILQ_FOREACH(lsta, &lvif->lsta_head, lsta_entry) {
+                       list_for_each_entry_rcu(lsta, &lvif->lsta_list, 
lsta_list) {
                                for (ieee80211_keyix keyix = 0; keyix < 
nitems(lsta->kc);
                                    keyix++)
                                        lkpi_ieee80211_iterate_keys(hw, vif,
@@ -5770,7 +5772,7 @@ linuxkpi_ieee80211_iterate_keys(struct ieee80211_hw *hw,
                if (vif == NULL) {
                        TODO();
                } else {
-                       TAILQ_FOREACH(lsta, &lvif->lsta_head, lsta_entry) {
+                       list_for_each_entry(lsta, &lvif->lsta_list, lsta_list) {
                                for (ieee80211_keyix keyix = 0; keyix < 
nitems(lsta->kc);
                                    keyix++)
                                        lkpi_ieee80211_iterate_keys(hw, vif,
@@ -5831,14 +5833,14 @@ linuxkpi_ieee80211_iterate_stations_atomic(struct 
ieee80211_hw *hw,
        LKPI_80211_LHW_LVIF_LOCK(lhw);
        TAILQ_FOREACH(lvif, &lhw->lvif_head, lvif_entry) {
 
-               LKPI_80211_LVIF_LOCK(lvif);
-               TAILQ_FOREACH(lsta, &lvif->lsta_head, lsta_entry) {
+               rcu_read_lock();
+               list_for_each_entry_rcu(lsta, &lvif->lsta_list, lsta_list) {
                        if (!lsta->added_to_drv)
                                continue;
                        sta = LSTA_TO_STA(lsta);
                        iterfunc(arg, sta);
                }
-               LKPI_80211_LVIF_UNLOCK(lvif);
+               rcu_read_unlock();
        }
        LKPI_80211_LHW_LVIF_UNLOCK(lhw);
 }
@@ -6605,14 +6607,14 @@ lkpi_find_lsta_by_ni(struct lkpi_vif *lvif, struct 
ieee80211_node *ni)
 {
        struct lkpi_sta *lsta, *temp;
 
-       LKPI_80211_LVIF_LOCK(lvif);
-       TAILQ_FOREACH_SAFE(lsta, &lvif->lsta_head, lsta_entry, temp) {
+       rcu_read_lock();
+       list_for_each_entry_rcu(lsta, &lvif->lsta_list, lsta_list) {
                if (lsta->ni == ni) {
-                       LKPI_80211_LVIF_UNLOCK(lvif);
+                       rcu_read_unlock();
                        return (lsta);
                }
        }
-       LKPI_80211_LVIF_UNLOCK(lvif);
+       rcu_read_unlock();
 
        return (NULL);
 }
@@ -6622,20 +6624,20 @@ struct ieee80211_sta *
 linuxkpi_ieee80211_find_sta(struct ieee80211_vif *vif, const u8 *peer)
 {
        struct lkpi_vif *lvif;
-       struct lkpi_sta *lsta, *temp;
+       struct lkpi_sta *lsta;
        struct ieee80211_sta *sta;
 
        lvif = VIF_TO_LVIF(vif);
 
-       LKPI_80211_LVIF_LOCK(lvif);
-       TAILQ_FOREACH_SAFE(lsta, &lvif->lsta_head, lsta_entry, temp) {
+       rcu_read_lock();
+       list_for_each_entry_rcu(lsta, &lvif->lsta_list, lsta_list) {
                sta = LSTA_TO_STA(lsta);
                if (IEEE80211_ADDR_EQ(sta->addr, peer)) {
-                       LKPI_80211_LVIF_UNLOCK(lvif);
+                       rcu_read_unlock();
                        return (sta);
                }
        }
-       LKPI_80211_LVIF_UNLOCK(lvif);
+       rcu_read_unlock();
        return (NULL);
 }
 
@@ -7175,8 +7177,8 @@ lkpi_ieee80211_wake_queues(struct ieee80211_hw *hw, int 
hwq)
 #endif
                                lvif->hw_queue_stopped[ac] = false;
 
-                               LKPI_80211_LVIF_LOCK(lvif);
-                               TAILQ_FOREACH(lsta, &lvif->lsta_head, 
lsta_entry) {
+                               rcu_read_lock();
+                               list_for_each_entry_rcu(lsta, &lvif->lsta_list, 
lsta_list) {
                                        struct ieee80211_sta *sta;
 
                                        sta = LSTA_TO_STA(lsta);
@@ -7199,7 +7201,7 @@ lkpi_ieee80211_wake_queues(struct ieee80211_hw *hw, int 
hwq)
                                                lkpi_80211_mo_wake_tx_queue(hw, 
sta->txq[tid]);
                                        }
                                }
-                               LKPI_80211_LVIF_UNLOCK(lvif);
+                               rcu_read_unlock();
                        }
                }
        }
diff --git a/sys/compat/linuxkpi/common/src/linux_80211.h 
b/sys/compat/linuxkpi/common/src/linux_80211.h
index 40b11ebfef13..b17e6072066c 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.h
+++ b/sys/compat/linuxkpi/common/src/linux_80211.h
@@ -126,6 +126,8 @@ struct lkpi_radiotap_rx_hdr {
         (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |                      \
         (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE))
 
+struct lkpi_hw;
+
 struct lkpi_txq {
        TAILQ_ENTRY(lkpi_txq)   txq_entry;
 
@@ -142,8 +144,9 @@ struct lkpi_txq {
 
 
 struct lkpi_sta {
-        TAILQ_ENTRY(lkpi_sta)  lsta_entry;
+       struct list_head        lsta_list;
        struct ieee80211_node   *ni;
+       struct ieee80211_hw     *hw;            /* back pointer f. locking. */
 
        /* Deferred TX path. */
        /* Eventually we might want to migrate this into net80211 entirely. */
@@ -164,6 +167,7 @@ struct lkpi_sta {
 #define        STA_TO_LSTA(_sta)       container_of(_sta, struct lkpi_sta, sta)
 #define        LSTA_TO_STA(_lsta)      (&(_lsta)->sta)
 
+/* Either protected by wiphy lock or rcu for the list. */
 struct lkpi_vif {
         TAILQ_ENTRY(lkpi_vif)  lvif_entry;
        struct ieee80211vap     iv_vap;
@@ -179,7 +183,8 @@ struct lkpi_vif {
                                    enum ieee80211_state, int);
        struct ieee80211_node * (*iv_update_bss)(struct ieee80211vap *,
                                    struct ieee80211_node *);
-       TAILQ_HEAD(, lkpi_sta)  lsta_head;
+       struct list_head        lsta_list;
+
        struct lkpi_sta         *lvif_bss;
        bool                    lvif_bss_synched;
        bool                    added_to_drv;                   /* Driver 
knows; i.e. we called add_interface(). */

Reply via email to