git: 658a3f12e5ed - releng/14.0 - LinuxKPI: 802.11: move ieee80211_chanctx_conf into lkpi private struct

From: Bjoern A. Zeeb <bz_at_FreeBSD.org>
Date: Mon, 09 Oct 2023 23:16:26 UTC
The branch releng/14.0 has been updated by bz:

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

commit 658a3f12e5edfa91c92df907290dace26c9f1d7b
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2023-09-25 16:57:23 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2023-10-09 23:14:54 +0000

    LinuxKPI: 802.11: move ieee80211_chanctx_conf into lkpi private struct
    
    Factor out ieee80211_chanctx_conf into struct lkpi_chanctx in order to
    keep local state as well.  In first instance that is added_to_drv
    only.  For now we stay single-chanctx only but this paves the path
    to make it a list.
    Use the new information to implement ieee80211_iter_chan_contexts_atomic().
    
    Sponsored by:   The FreeBSD Foundation
    Approved by:    re (gjb)
    
    (cherry picked from commit c5e257985085bd987b1dddffd0455c2230df2d1d)
    (cherry picked from commit b6628a233e8e6407a504172a562ba14a66c7e7da)
---
 sys/compat/linuxkpi/common/src/linux_80211.c       | 46 +++++++++++++++++++---
 sys/compat/linuxkpi/common/src/linux_80211.h       |  9 +++++
 .../linuxkpi/common/src/linux_80211_macops.c       |  8 ++++
 3 files changed, 57 insertions(+), 6 deletions(-)

diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c
index 8df51f2630ff..816fe3ab7646 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211.c
@@ -917,6 +917,7 @@ static int
 lkpi_sta_scan_to_auth(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
 {
 	struct linuxkpi_ieee80211_channel *chan;
+	struct lkpi_chanctx *lchanctx;
 	struct ieee80211_chanctx_conf *conf;
 	struct lkpi_hw *lhw;
 	struct ieee80211_hw *hw;
@@ -948,11 +949,13 @@ lkpi_sta_scan_to_auth(struct ieee80211vap *vap, enum ieee80211_state nstate, int
 	/* Add chanctx (or if exists, change it). */
 	if (vif->chanctx_conf != NULL) {
 		conf = vif->chanctx_conf;
+		lchanctx = CHANCTX_CONF_TO_LCHANCTX(conf);
 		IMPROVE("diff changes for changed, working on live copy, rcu");
 	} else {
 		/* Keep separate alloc as in Linux this is rcu managed? */
-		conf = malloc(sizeof(*conf) + hw->chanctx_data_size,
+		lchanctx = malloc(sizeof(*lchanctx) + hw->chanctx_data_size,
 		    M_LKPI80211, M_WAITOK | M_ZERO);
+		conf = &lchanctx->conf;
 	}
 
 	conf->rx_chains_dynamic = 1;
@@ -997,7 +1000,8 @@ lkpi_sta_scan_to_auth(struct ieee80211vap *vap, enum ieee80211_state nstate, int
 			error = 0;
 		if (error != 0) {
 			lkpi_80211_mo_remove_chanctx(hw, conf);
-			free(conf, M_LKPI80211);
+			lchanctx = CHANCTX_CONF_TO_LCHANCTX(conf);
+			free(lchanctx, M_LKPI80211);
 			goto out;
 		}
 	}
@@ -1169,6 +1173,7 @@ lkpi_sta_auth_to_scan(struct ieee80211vap *vap, enum ieee80211_state nstate, int
 
 	/* Take the chan ctx down. */
 	if (vif->chanctx_conf != NULL) {
+		struct lkpi_chanctx *lchanctx;
 		struct ieee80211_chanctx_conf *conf;
 
 		conf = vif->chanctx_conf;
@@ -1178,7 +1183,8 @@ lkpi_sta_auth_to_scan(struct ieee80211vap *vap, enum ieee80211_state nstate, int
 
 		/* Remove chan ctx. */
 		lkpi_80211_mo_remove_chanctx(hw, conf);
-		free(conf, M_LKPI80211);
+		lchanctx = CHANCTX_CONF_TO_LCHANCTX(conf);
+		free(lchanctx, M_LKPI80211);
 	}
 
 out:
@@ -1446,6 +1452,7 @@ _lkpi_sta_assoc_to_down(struct ieee80211vap *vap, enum ieee80211_state nstate, i
 
 	/* Take the chan ctx down. */
 	if (vif->chanctx_conf != NULL) {
+		struct lkpi_chanctx *lchanctx;
 		struct ieee80211_chanctx_conf *conf;
 
 		conf = vif->chanctx_conf;
@@ -1455,7 +1462,8 @@ _lkpi_sta_assoc_to_down(struct ieee80211vap *vap, enum ieee80211_state nstate, i
 
 		/* Remove chan ctx. */
 		lkpi_80211_mo_remove_chanctx(hw, conf);
-		free(conf, M_LKPI80211);
+		lchanctx = CHANCTX_CONF_TO_LCHANCTX(conf);
+		free(lchanctx, M_LKPI80211);
 	}
 
 	error = EALREADY;
@@ -1905,6 +1913,7 @@ lkpi_sta_run_to_init(struct ieee80211vap *vap, enum ieee80211_state nstate, int
 
 	/* Take the chan ctx down. */
 	if (vif->chanctx_conf != NULL) {
+		struct lkpi_chanctx *lchanctx;
 		struct ieee80211_chanctx_conf *conf;
 
 		conf = vif->chanctx_conf;
@@ -1914,7 +1923,8 @@ lkpi_sta_run_to_init(struct ieee80211vap *vap, enum ieee80211_state nstate, int
 
 		/* Remove chan ctx. */
 		lkpi_80211_mo_remove_chanctx(hw, conf);
-		free(conf, M_LKPI80211);
+		lchanctx = CHANCTX_CONF_TO_LCHANCTX(conf);
+		free(lchanctx, M_LKPI80211);
 	}
 
 	error = EALREADY;
@@ -3948,8 +3958,32 @@ linuxkpi_ieee80211_iterate_chan_contexts(struct ieee80211_hw *hw,
 	void *),
     void *arg)
 {
+	struct lkpi_hw *lhw;
+	struct lkpi_vif *lvif;
+	struct ieee80211_vif *vif;
+	struct lkpi_chanctx *lchanctx;
 
-	UNIMPLEMENTED;
+	KASSERT(hw != NULL && iterfunc != NULL,
+	    ("%s: hw %p iterfunc %p arg %p\n", __func__, hw, iterfunc, arg));
+
+	lhw = HW_TO_LHW(hw);
+
+	IMPROVE("lchanctx should be its own list somewhere");
+
+	LKPI_80211_LHW_LVIF_LOCK(lhw);
+	TAILQ_FOREACH(lvif, &lhw->lvif_head, lvif_entry) {
+
+		vif = LVIF_TO_VIF(lvif);
+		if (vif->chanctx_conf == NULL)
+			continue;
+
+		lchanctx = CHANCTX_CONF_TO_LCHANCTX(vif->chanctx_conf);
+		if (!lchanctx->added_to_drv)
+			continue;
+
+		iterfunc(hw, &lchanctx->conf, arg);
+	}
+	LKPI_80211_LHW_LVIF_UNLOCK(lhw);
 }
 
 void
diff --git a/sys/compat/linuxkpi/common/src/linux_80211.h b/sys/compat/linuxkpi/common/src/linux_80211.h
index 22a5f5a6377c..93c1e2873206 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.h
+++ b/sys/compat/linuxkpi/common/src/linux_80211.h
@@ -210,6 +210,15 @@ struct lkpi_hw {	/* name it mac80211_sc? */
 #define	LHW_TO_HW(_lhw)		(&(_lhw)->hw)
 #define	HW_TO_LHW(_hw)		container_of(_hw, struct lkpi_hw, hw)
 
+struct lkpi_chanctx {
+	bool				added_to_drv;	/* Managed by MO */
+	struct ieee80211_chanctx_conf	conf __aligned(CACHE_LINE_SIZE);
+};
+#define	LCHANCTX_TO_CHANCTX_CONF(_lchanctx)		\
+    (&(_lchanctx)->conf)
+#define	CHANCTX_CONF_TO_LCHANCTX(_conf)			\
+    container_of(_conf, struct lkpi_chanctx, conf)
+
 struct lkpi_wiphy {
 	const struct cfg80211_ops	*ops;
 
diff --git a/sys/compat/linuxkpi/common/src/linux_80211_macops.c b/sys/compat/linuxkpi/common/src/linux_80211_macops.c
index b3b53d23f62e..8f75b1bdf8b1 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211_macops.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211_macops.c
@@ -490,6 +490,7 @@ lkpi_80211_mo_add_chanctx(struct ieee80211_hw *hw,
     struct ieee80211_chanctx_conf *chanctx_conf)
 {
 	struct lkpi_hw *lhw;
+	struct lkpi_chanctx *lchanctx;
 	int error;
 
 	lhw = HW_TO_LHW(hw);
@@ -500,6 +501,10 @@ lkpi_80211_mo_add_chanctx(struct ieee80211_hw *hw,
 
 	LKPI_80211_TRACE_MO("hw %p chanctx_conf %p", hw, chanctx_conf);
 	error = lhw->ops->add_chanctx(hw, chanctx_conf);
+	if (error == 0) {
+		lchanctx = CHANCTX_CONF_TO_LCHANCTX(chanctx_conf);
+		lchanctx->added_to_drv = true;
+	}
 
 out:
 	return (error);
@@ -524,6 +529,7 @@ lkpi_80211_mo_remove_chanctx(struct ieee80211_hw *hw,
     struct ieee80211_chanctx_conf *chanctx_conf)
 {
 	struct lkpi_hw *lhw;
+	struct lkpi_chanctx *lchanctx;
 
 	lhw = HW_TO_LHW(hw);
 	if (lhw->ops->remove_chanctx == NULL)
@@ -531,6 +537,8 @@ lkpi_80211_mo_remove_chanctx(struct ieee80211_hw *hw,
 
 	LKPI_80211_TRACE_MO("hw %p chanctx_conf %p", hw, chanctx_conf);
 	lhw->ops->remove_chanctx(hw, chanctx_conf);
+	lchanctx = CHANCTX_CONF_TO_LCHANCTX(chanctx_conf);
+	lchanctx->added_to_drv = false;
 }
 
 void