git: 1b6b652128d5 - stable/13 - LinuxKPI: 80211: scanning code updates

From: Bjoern A. Zeeb <bz_at_FreeBSD.org>
Date: Wed, 21 Sep 2022 14:01:27 UTC
The branch stable/13 has been updated by bz:

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

commit 1b6b652128d5b3836a87f7f569f0f7084b0c2809
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2022-09-03 23:40:51 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2022-09-21 11:46:46 +0000

    LinuxKPI: 80211: scanning code updates
    
    For consistency rename LKPI_SCAN_RUNNING adding a LHW_ prefix.
    Add a local flag LKPI_LHW_SCAN_HW mirroring the net80211
    IEEE80211_FEXT_SCAN_OFFLOAD flag.
    Slightly simplify the code.
    Overload (*ic_scan_curchan) and (*ic_scan_mindwell) so that we can
    call the net80211 implementation in case of software scan but skip it
    in case of full-offload scans.
    Also add a bandaid to our (*ic_set_channel) implementation to not siwtch
    channels if we have an active hw_scan running.
    
    Obtained from:  bz/wireless-dev
    Sponsored by:   The FreeBSD Foundation (partially)
    
    (cherry picked from commit a486fbbd7876bed81d738a32274953c89906edb5)
---
 sys/compat/linuxkpi/common/src/linux_80211.c       | 61 +++++++++++++++++-----
 sys/compat/linuxkpi/common/src/linux_80211.h       |  8 ++-
 .../linuxkpi/common/src/linux_80211_macops.c       |  6 +--
 3 files changed, 57 insertions(+), 18 deletions(-)

diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c
index b23b2b3f774b..3381218b2623 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211.c
@@ -797,7 +797,7 @@ lkpi_stop_hw_scan(struct lkpi_hw *lhw, struct ieee80211_vif *vif)
 	struct ieee80211_hw *hw;
 	int error;
 
-	if ((lhw->scan_flags & LKPI_SCAN_RUNNING) == 0)
+	if ((lhw->scan_flags & LKPI_LHW_SCAN_RUNNING) == 0)
 		return;
 
 	hw = LHW_TO_HW(lhw);
@@ -812,7 +812,7 @@ lkpi_stop_hw_scan(struct lkpi_hw *lhw, struct ieee80211_vif *vif)
 	LKPI_80211_LHW_UNLOCK(lhw);
 	IEEE80211_LOCK(lhw->ic);
 
-	if ((lhw->scan_flags & LKPI_SCAN_RUNNING) != 0)
+	if ((lhw->scan_flags & LKPI_LHW_SCAN_RUNNING) != 0)
 		ic_printf(lhw->ic, "%s: failed to cancel scan: %d (%p, %p)\n",
 		    __func__, error, lhw, vif);
 }
@@ -2514,7 +2514,7 @@ lkpi_ic_scan_start(struct ieee80211com *ic)
 	int error;
 
 	lhw = ic->ic_softc;
-	if ((lhw->scan_flags & LKPI_SCAN_RUNNING) != 0) {
+	if ((lhw->scan_flags & LKPI_LHW_SCAN_RUNNING) != 0) {
 		/* A scan is still running. */
 		return;
 	}
@@ -2527,7 +2527,9 @@ lkpi_ic_scan_start(struct ieee80211com *ic)
 	}
 
 	hw = LHW_TO_HW(lhw);
-	if ((vap->iv_flags_ext & IEEE80211_FEXT_SCAN_OFFLOAD) == 0) {
+	if ((lhw->scan_flags & LKPI_LHW_SCAN_HW) == 0) {
+		/* If hw_scan is cleared clear FEXT_SCAN_OFFLOAD too. */
+		vap->iv_flags_ext &= ~IEEE80211_FEXT_SCAN_OFFLOAD;
 sw_scan:
 		lvif = VAP_TO_LVIF(vap);
 		vif = LVIF_TO_VIF(lvif);
@@ -2670,7 +2672,7 @@ sw_scan:
 			 * not possible.  Fall back to sw scan in that case.
 			 */
 			if (error == 1) {
-				vap->iv_flags_ext &= ~IEEE80211_FEXT_SCAN_OFFLOAD;
+				lhw->scan_flags &= ~LKPI_LHW_SCAN_HW;
 				ieee80211_start_scan(vap,
 				    IEEE80211_SCAN_ACTIVE |
 				    IEEE80211_SCAN_NOPICK |
@@ -2692,26 +2694,25 @@ static void
 lkpi_ic_scan_end(struct ieee80211com *ic)
 {
 	struct lkpi_hw *lhw;
-	struct ieee80211_scan_state *ss;
-	struct ieee80211vap *vap;
 
 	lhw = ic->ic_softc;
-	if ((lhw->scan_flags & LKPI_SCAN_RUNNING) == 0) {
+	if ((lhw->scan_flags & LKPI_LHW_SCAN_RUNNING) == 0) {
 		return;
 	}
 
-	ss = ic->ic_scan;
-	vap = ss->ss_vap;
-	if (vap->iv_flags_ext & IEEE80211_FEXT_SCAN_OFFLOAD) {
-		/* Nothing to do. */
-	} else {
+	if ((lhw->scan_flags & LKPI_LHW_SCAN_HW) == 0) {
+		struct ieee80211_scan_state *ss;
+		struct ieee80211vap *vap;
 		struct ieee80211_hw *hw;
 		struct lkpi_vif *lvif;
 		struct ieee80211_vif *vif;
 
+		ss = ic->ic_scan;
+		vap = ss->ss_vap;
 		hw = LHW_TO_HW(lhw);
 		lvif = VAP_TO_LVIF(vap);
 		vif = LVIF_TO_VIF(lvif);
+
 		lkpi_80211_mo_sw_scan_complete(hw, vif);
 
 		/* Send PS to stop buffering if n80211 does not for us? */
@@ -2721,6 +2722,27 @@ lkpi_ic_scan_end(struct ieee80211com *ic)
 	}
 }
 
+static void
+lkpi_ic_scan_curchan(struct ieee80211_scan_state *ss,
+    unsigned long maxdwell)
+{
+	struct lkpi_hw *lhw;
+
+	lhw = ss->ss_ic->ic_softc;
+	if ((lhw->scan_flags & LKPI_LHW_SCAN_HW) == 0)
+		lhw->ic_scan_curchan(ss, maxdwell);
+}
+
+static void
+lkpi_ic_scan_mindwell(struct ieee80211_scan_state *ss)
+{
+	struct lkpi_hw *lhw;
+
+	lhw = ss->ss_ic->ic_softc;
+	if ((lhw->scan_flags & LKPI_LHW_SCAN_HW) == 0)
+		lhw->ic_scan_mindwell(ss);
+}
+
 static void
 lkpi_ic_set_channel(struct ieee80211com *ic)
 {
@@ -2736,6 +2758,11 @@ lkpi_ic_set_channel(struct ieee80211com *ic)
 	if (lhw->ops->config == NULL)
 		return;
 
+	/* If we have a hw_scan running do not switch channels. */
+	if ((lhw->scan_flags & (LKPI_LHW_SCAN_RUNNING|LKPI_LHW_SCAN_HW)) ==
+	    (LKPI_LHW_SCAN_RUNNING|LKPI_LHW_SCAN_HW))
+		return;
+
 	c = ic->ic_curchan;
 	if (c == NULL || c == IEEE80211_CHAN_ANYC) {
 		ic_printf(ic, "%s: c %p ops->config %p\n", __func__,
@@ -3482,6 +3509,7 @@ linuxkpi_ieee80211_ifattach(struct ieee80211_hw *hw)
 		 * the flag.
 		 */
 		ic->ic_flags_ext |= IEEE80211_FEXT_SCAN_OFFLOAD;
+		lhw->scan_flags |= LKPI_LHW_SCAN_HW;
 	}
 
 #ifdef __notyet__
@@ -3540,6 +3568,11 @@ linuxkpi_ieee80211_ifattach(struct ieee80211_hw *hw)
 	ic->ic_getradiocaps = lkpi_ic_getradiocaps;
 	ic->ic_wme.wme_update = lkpi_ic_wme_update;
 
+	lhw->ic_scan_curchan = ic->ic_scan_curchan;
+	ic->ic_scan_curchan = lkpi_ic_scan_curchan;
+	lhw->ic_scan_mindwell = ic->ic_scan_mindwell;
+	ic->ic_scan_mindwell = lkpi_ic_scan_mindwell;
+
 	lhw->ic_node_alloc = ic->ic_node_alloc;
 	ic->ic_node_alloc = lkpi_ic_node_alloc;
 	lhw->ic_node_init = ic->ic_node_init;
@@ -3781,7 +3814,7 @@ linuxkpi_ieee80211_scan_completed(struct ieee80211_hw *hw,
 	LKPI_80211_LHW_LOCK(lhw);
 	free(lhw->hw_req, M_LKPI80211);
 	lhw->hw_req = NULL;
-	lhw->scan_flags &= ~LKPI_SCAN_RUNNING;
+	lhw->scan_flags &= ~LKPI_LHW_SCAN_RUNNING;
 	wakeup(lhw);
 	LKPI_80211_LHW_UNLOCK(lhw);
 
diff --git a/sys/compat/linuxkpi/common/src/linux_80211.h b/sys/compat/linuxkpi/common/src/linux_80211.h
index c6958cf834e3..65e78ba0fc08 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.h
+++ b/sys/compat/linuxkpi/common/src/linux_80211.h
@@ -144,6 +144,11 @@ struct lkpi_hw {	/* name it mac80211_sc? */
 
 	struct mtx			mtx;
 
+	/* Scan functions we overload to handle depending on scan mode. */
+	void                    (*ic_scan_curchan)(struct ieee80211_scan_state *,
+				    unsigned long);
+	void                    (*ic_scan_mindwell)(struct ieee80211_scan_state *);
+
 	/* Node functions we overload to sync state. */
 	struct ieee80211_node *	(*ic_node_alloc)(struct ieee80211vap *,
 				    const uint8_t [IEEE80211_ADDR_LEN]);
@@ -153,7 +158,8 @@ struct lkpi_hw {	/* name it mac80211_sc? */
 
 #define	LKPI_MAC80211_DRV_STARTED	0x00000001
 	uint32_t			sc_flags;
-#define	LKPI_SCAN_RUNNING		0x00000001
+#define	LKPI_LHW_SCAN_RUNNING		0x00000001
+#define	LKPI_LHW_SCAN_HW		0x00000002
 	uint32_t			scan_flags;
 
 	int				supbands;	/* Number of supported bands. */
diff --git a/sys/compat/linuxkpi/common/src/linux_80211_macops.c b/sys/compat/linuxkpi/common/src/linux_80211_macops.c
index 12cffc11481e..547b94be66c2 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211_macops.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211_macops.c
@@ -205,10 +205,10 @@ lkpi_80211_mo_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		goto out;
 	}
 
-	lhw->scan_flags |= LKPI_SCAN_RUNNING;
+	lhw->scan_flags |= LKPI_LHW_SCAN_RUNNING;
 	error = lhw->ops->hw_scan(hw, vif, sr);
 	if (error != 0)
-		lhw->scan_flags &= ~LKPI_SCAN_RUNNING;
+		lhw->scan_flags &= ~LKPI_LHW_SCAN_RUNNING;
 
 out:
 	return (error);
@@ -236,7 +236,7 @@ lkpi_80211_mo_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vi
 		return;
 
 	lhw->ops->sw_scan_complete(hw, vif);
-	lhw->scan_flags &= ~LKPI_SCAN_RUNNING;
+	lhw->scan_flags &= ~LKPI_LHW_SCAN_RUNNING;
 }
 
 void