Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 19 Feb 2025 12:17:58 GMT
From:      "Bjoern A. Zeeb" <bz@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: a8f735a66130 - main - LinuxKPI: 802.11: switch vif station list to a linux list
Message-ID:  <202502191217.51JCHwRi013917@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by bz:

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

commit a8f735a66130aa737999fad9b3246159099dc9eb
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2025-01-25 23:39:53 +0000
Commit:     Bjoern A. Zeeb <bz@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(). */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202502191217.51JCHwRi013917>