git: 8891c45563f8 - main - LinuxKPI: 802.11: use an sx lock to protect the list of vifs

From: Bjoern A. Zeeb <bz_at_FreeBSD.org>
Date: Fri, 15 Apr 2022 15:56:54 UTC
The branch main has been updated by bz:

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

commit 8891c45563f8d3b657a876197c66e00e75214909
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2022-04-15 14:22:43 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2022-04-15 15:54:03 +0000

    LinuxKPI: 802.11: use an sx lock to protect the list of vifs
    
    Use an sx lock to protect the list of vifs.  We could use the
    linux mutex compat for this but our current implementation may
    re-acquire the lock recursively so allow this.  The change is
    mainly motivated by the fact that some callers may sleep in the
    interator function called.  Recursiveness is needed because we
    see find_sta_by_ifaddr() being called from an iterator function
    from iterate_interfaces().
    
    Sponsored by:   The FreeBSD Foundation
    MFC after:      3 days
---
 sys/compat/linuxkpi/common/src/linux_80211.c | 22 ++++++++++++----------
 sys/compat/linuxkpi/common/src/linux_80211.h |  4 ++++
 2 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c
index e5a4aee842eb..286c40d7de4f 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211.c
@@ -2261,9 +2261,9 @@ lkpi_ic_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ],
 		return (NULL);
 	}
 
-	LKPI_80211_LHW_LOCK(lhw);
+	LKPI_80211_LHW_LVIF_LOCK(lhw);
 	TAILQ_INSERT_TAIL(&lhw->lvif_head, lvif, lvif_entry);
-	LKPI_80211_LHW_UNLOCK(lhw);
+	LKPI_80211_LHW_LVIF_UNLOCK(lhw);
 
 	/* Set bss_info. */
 	changed = 0;
@@ -2329,9 +2329,9 @@ lkpi_ic_vap_delete(struct ieee80211vap *vap)
 	lhw = ic->ic_softc;
 	hw = LHW_TO_HW(lhw);
 
-	LKPI_80211_LHW_LOCK(lhw);
+	LKPI_80211_LHW_LVIF_LOCK(lhw);
 	TAILQ_REMOVE(&lhw->lvif_head, lvif, lvif_entry);
-	LKPI_80211_LHW_UNLOCK(lhw);
+	LKPI_80211_LHW_LVIF_UNLOCK(lhw);
 	lkpi_80211_mo_remove_interface(hw, vif);
 
 	ieee80211_ratectl_deinit(vap);
@@ -3240,6 +3240,7 @@ linuxkpi_ieee80211_alloc_hw(size_t priv_len, const struct ieee80211_ops *ops)
 	lhw->ops = ops;
 
 	mtx_init(&lhw->mtx, "lhw", NULL, MTX_DEF | MTX_RECURSE);
+	sx_init_flags(&lhw->lvif_sx, "lhw-lvif", SX_RECURSE | SX_DUPOK);
 	TAILQ_INIT(&lhw->lvif_head);
 
 	/*
@@ -3273,6 +3274,7 @@ linuxkpi_ieee80211_iffree(struct ieee80211_hw *hw)
 	lhw->ic = NULL;
 
 	/* Cleanup more of lhw here or in wiphy_free()? */
+	sx_destroy(&lhw->lvif_sx);
 	mtx_destroy(&lhw->mtx);
 	IMPROVE();
 }
@@ -3497,7 +3499,7 @@ linuxkpi_ieee80211_iterate_interfaces(struct ieee80211_hw *hw,
 	nin_drv = (flags & IEEE80211_IFACE_SKIP_SDATA_NOT_IN_DRIVER) != 0;
 
 	if (atomic)
-		LKPI_80211_LHW_LOCK(lhw);
+		LKPI_80211_LHW_LVIF_LOCK(lhw);
 	TAILQ_FOREACH(lvif, &lhw->lvif_head, lvif_entry) {
 		struct ieee80211vap *vap;
 
@@ -3530,7 +3532,7 @@ linuxkpi_ieee80211_iterate_interfaces(struct ieee80211_hw *hw,
 			iterfunc(arg, vif->addr, vif);
 	}
 	if (atomic)
-		LKPI_80211_LHW_UNLOCK(lhw);
+		LKPI_80211_LHW_LVIF_UNLOCK(lhw);
 }
 
 void
@@ -3568,7 +3570,7 @@ linuxkpi_ieee80211_iterate_stations_atomic(struct ieee80211_hw *hw,
 
 	lhw = HW_TO_LHW(hw);
 
-	LKPI_80211_LHW_LOCK(lhw);
+	LKPI_80211_LHW_LVIF_LOCK(lhw);
 	TAILQ_FOREACH(lvif, &lhw->lvif_head, lvif_entry) {
 
 		LKPI_80211_LVIF_LOCK(lvif);
@@ -3580,7 +3582,7 @@ linuxkpi_ieee80211_iterate_stations_atomic(struct ieee80211_hw *hw,
 		}
 		LKPI_80211_LVIF_UNLOCK(lvif);
 	}
-	LKPI_80211_LHW_UNLOCK(lhw);
+	LKPI_80211_LHW_LVIF_UNLOCK(lhw);
 }
 
 int
@@ -3974,7 +3976,7 @@ linuxkpi_ieee80211_find_sta_by_ifaddr(struct ieee80211_hw *hw,
 	lhw = wiphy_priv(hw->wiphy);
 	sta = NULL;
 
-	LKPI_80211_LHW_LOCK(lhw);
+	LKPI_80211_LHW_LVIF_LOCK(lhw);
 	TAILQ_FOREACH(lvif, &lhw->lvif_head, lvif_entry) {
 
 		/* XXX-BZ check our address from the vif. */
@@ -3987,7 +3989,7 @@ linuxkpi_ieee80211_find_sta_by_ifaddr(struct ieee80211_hw *hw,
 		if (sta != NULL)
 			break;
 	}
-	LKPI_80211_LHW_UNLOCK(lhw);
+	LKPI_80211_LHW_LVIF_UNLOCK(lhw);
 
 	if (sta != NULL) {
 		lsta = STA_TO_LSTA(sta);
diff --git a/sys/compat/linuxkpi/common/src/linux_80211.h b/sys/compat/linuxkpi/common/src/linux_80211.h
index fabc90e07a87..bdcdb3fbf455 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.h
+++ b/sys/compat/linuxkpi/common/src/linux_80211.h
@@ -140,6 +140,7 @@ struct lkpi_hw {	/* name it mac80211_sc? */
 	struct lkpi_radiotap_rx_hdr	rtap_rx;
 
 	TAILQ_HEAD(, lkpi_vif)		lvif_head;
+	struct sx			lvif_sx;
 
 	struct mtx			mtx;
 
@@ -179,6 +180,9 @@ struct lkpi_wiphy {
 #define	LKPI_80211_LHW_UNLOCK_ASSERT(_lhw) \
     mtx_assert(&(_lhw)->mtx, MA_NOTOWNED)
 
+#define	LKPI_80211_LHW_LVIF_LOCK(_lhw)	sx_xlock(&(_lhw)->lvif_sx)
+#define	LKPI_80211_LHW_LVIF_UNLOCK(_lhw) sx_xunlock(&(_lhw)->lvif_sx)
+
 #define	LKPI_80211_LVIF_LOCK(_lvif)	mtx_lock(&(_lvif)->mtx)
 #define	LKPI_80211_LVIF_UNLOCK(_lvif)	mtx_unlock(&(_lvif)->mtx)