Index | Thread | Search

From:
Peter Hessler <phessler@theapt.org>
Subject:
Re: qwx background scan and roaming support
To:
tech@openbsd.org
Date:
Fri, 25 Jul 2025 09:10:51 +0200

Download raw body.

Thread
tested on x13s.  OK

On 2025 Jul 24 (Thu) at 15:46:42 +0200 (+0200), Stefan Sperling wrote:
:Add background scan and roaming support to qwx.
:
:This patch sits on top of the previous diffs I sent today, which
:have been now committed.
:
:M  sys/dev/ic/qwx.c          |  107+  4-
:M  sys/dev/ic/qwxvar.h       |    2+  0-
:M  sys/dev/pci/if_qwx_pci.c  |    2+  0-
:
:3 files changed, 111 insertions(+), 4 deletions(-)
:
:commit - 25fdf95e122e33891e7ad3898002cfe29d094cc1
:commit + 3c01a782bb3d337863a438d785bb8fdfb8751d1c
:blob - f9996b63e8d39f993fea116ca38ca8179b471f61
:blob + 83c3f17a6a14062c7b61e273e5eabb7a12fc3943
:--- sys/dev/ic/qwx.c
:+++ sys/dev/ic/qwx.c
:@@ -163,7 +163,7 @@ void qwx_vif_free_all(struct qwx_softc *);
: void qwx_dp_stop_shadow_timers(struct qwx_softc *);
: void qwx_ce_stop_shadow_timers(struct qwx_softc *);
: 
:-int qwx_scan(struct qwx_softc *);
:+int qwx_scan(struct qwx_softc *, int);
: void qwx_scan_abort(struct qwx_softc *);
: int qwx_auth(struct qwx_softc *);
: int qwx_deauth(struct qwx_softc *);
:@@ -373,6 +373,7 @@ qwx_stop(struct ifnet *ifp)
: 	task_del(systq, &sc->init_task);
: 	qwx_del_task(sc, sc->sc_nswq, &sc->newstate_task);
: 	qwx_del_task(sc, systq, &sc->setkey_task);
:+	qwx_del_task(sc, systq, &sc->bgscan_task);
: 	refcnt_finalize(&sc->task_refs, "qwxstop");
: 
: 	qwx_setkey_clear(sc);
:@@ -868,6 +869,76 @@ qwx_setkey_task(void *arg)
: }
: 
: void
:+qwx_clear_hwkeys(struct qwx_softc *sc, struct ath11k_peer *peer)
:+{
:+	struct qwx_vif *arvif = TAILQ_FIRST(&sc->vif_list); /* XXX */
:+	uint8_t pdev_id = 0; /* TODO: derive pdev ID somehow? */
:+	struct wmi_vdev_install_key_arg arg =  {
:+		.vdev_id = arvif->vdev_id,
:+		.key_len = 0,
:+		.key_data = NULL,
:+		.key_cipher = WMI_CIPHER_NONE,
:+		.key_flags = 0,
:+	};
:+	int k_id = 0, ret;
:+
:+	arg.macaddr = peer->addr;
:+
:+	for (k_id = 0; k_id <= WMI_MAX_KEY_INDEX; k_id++) {
:+		arg.key_idx = k_id;
:+
:+		sc->install_key_done = 0;
:+		ret = qwx_wmi_vdev_install_key(sc, &arg, pdev_id);
:+		if (ret) {
:+			printf("%s: delete key %d failed: error %d\n",
:+			    sc->sc_dev.dv_xname, k_id, ret);
:+			continue;
:+		}
:+
:+		while (!sc->install_key_done) {
:+			ret = tsleep_nsec(&sc->install_key_done, 0,
:+			    "qwxinstkey", SEC_TO_NSEC(1));
:+			if (ret) {
:+				printf("%s: delete key %d timeout\n",
:+				    sc->sc_dev.dv_xname, k_id);
:+			}
:+		}
:+	}
:+}
:+
:+void
:+qwx_clear_pn_replay_config(struct qwx_softc *sc, struct ath11k_peer *peer)
:+{
:+	struct ath11k_hal_reo_cmd cmd = {0};
:+	struct dp_rx_tid *rx_tid;
:+	uint8_t tid;
:+	int ret = 0;
:+
:+	cmd.flag |= HAL_REO_CMD_FLG_NEED_STATUS;
:+	cmd.upd0 |= HAL_REO_CMD_UPD0_PN |
:+		    HAL_REO_CMD_UPD0_PN_SIZE |
:+		    HAL_REO_CMD_UPD0_PN_VALID |
:+		    HAL_REO_CMD_UPD0_PN_CHECK |
:+		    HAL_REO_CMD_UPD0_SVLD;
:+
:+	for (tid = 0; tid < IEEE80211_NUM_TID; tid++) {
:+		rx_tid = &peer->rx_tid[tid];
:+		if (!rx_tid->active)
:+			continue;
:+		cmd.addr_lo = rx_tid->paddr & 0xffffffff;
:+		cmd.addr_hi = (rx_tid->paddr >> 32);
:+		ret = qwx_dp_tx_send_reo_cmd(sc, rx_tid,
:+		    HAL_REO_CMD_UPDATE_RX_QUEUE, &cmd, NULL);
:+		if (ret) {
:+			printf("%s: failed to configure rx tid %d queue "
:+			    "for pn replay detection %d\n",
:+			    sc->sc_dev.dv_xname, tid, ret);
:+			break;
:+		}
:+	}
:+}
:+
:+void
: qwx_setkey_clear(struct qwx_softc *sc)
: {
: 	struct ieee80211com *ic = &sc->sc_ic;
:@@ -910,6 +981,8 @@ qwx_newstate(struct ieee80211com *ic, enum ieee80211_s
: #endif
: 		qwx_del_task(sc, systq, &sc->setkey_task);
: 		qwx_setkey_clear(sc);
:+
:+		qwx_del_task(sc, systq, &sc->bgscan_task);
: #if 0
: 		qwx_del_task(sc, systq, &sc->bgscan_done_task);
: #endif
:@@ -991,7 +1064,7 @@ qwx_newstate_task(void *arg)
: 
: 	case IEEE80211_S_SCAN:
: next_scan:
:-		err = qwx_scan(sc);
:+		err = qwx_scan(sc, 0);
: 		if (err)
: 			break;
: 		if (ifp->if_flags & IFF_DEBUG)
:@@ -25242,7 +25315,7 @@ qwx_start_scan(struct qwx_softc *sc, struct scan_req_p
: #define ATH11K_MAC_SCAN_CMD_EVT_OVERHEAD		200 /* in msecs */
: 
: int
:-qwx_scan(struct qwx_softc *sc)
:+qwx_scan(struct qwx_softc *sc, int bgscan)
: {
: 	struct ieee80211com *ic = &sc->sc_ic;
: 	struct qwx_vif *arvif = TAILQ_FIRST(&sc->vif_list);
:@@ -25406,7 +25479,7 @@ qwx_scan(struct qwx_softc *sc)
: #ifdef notyet
: 		spin_unlock_bh(&ar->data_lock);
: #endif
:-	} else {
:+	} else if (!bgscan) {
: 		/*
: 		 * The current mode might have been fixed during association.
: 		 * Ensure all channels get scanned.
:@@ -25474,6 +25547,31 @@ qwx_scan_abort(struct qwx_softc *sc)
: #endif
: }
: 
:+void
:+qwx_bgscan_task(void *arg)
:+{
:+	struct qwx_softc *sc = arg;
:+	struct ieee80211com *ic = &sc->sc_ic;
:+
:+	if (ic->ic_state == IEEE80211_S_RUN &&
:+	    sc->scan.state == ATH11K_SCAN_IDLE &&
:+	    !test_bit(ATH11K_FLAG_CRASH_FLUSH, sc->sc_flags))
:+		qwx_scan(sc, 1);
:+
:+	refcnt_rele_wake(&sc->task_refs);
:+}
:+
:+int
:+qwx_bgscan(struct ieee80211com *ic)
:+{
:+	struct ifnet *ifp = &ic->ic_if;
:+	struct qwx_softc *sc = ifp->if_softc;
:+
:+	qwx_add_task(sc, systq, &sc->bgscan_task);
:+
:+	return 0;
:+}
:+
: /*
:  * Find a pdev which corresponds to a given channel.
:  * This doesn't exactly match the semantics of the Linux driver
:@@ -25627,6 +25725,9 @@ qwx_deauth(struct qwx_softc *sc)
: 		return ret;
: 	}
: 
:+	qwx_clear_pn_replay_config(sc, peer);
:+	qwx_clear_hwkeys(sc, peer);
:+
: 	ret = qwx_mac_station_remove(sc, arvif, pdev_id, peer);
: 	if (ret)
: 		return ret;
:@@ -25839,6 +25940,7 @@ qwx_run(struct qwx_softc *sc)
: 		return ret;
: 	}
: 
:+	sc->ops.irq_enable(sc);
: 	return 0;
: }
: 
:@@ -25896,6 +25998,7 @@ qwx_attach(struct qwx_softc *sc)
: 	task_set(&sc->init_task, qwx_init_task, sc);
: 	task_set(&sc->newstate_task, qwx_newstate_task, sc);
: 	task_set(&sc->setkey_task, qwx_setkey_task, sc);
:+	task_set(&sc->bgscan_task, qwx_bgscan_task, sc);
: 	timeout_set_proc(&sc->scan.timeout, qwx_scan_timeout, sc);
: #if NBPFILTER > 0
: 	qwx_radiotap_attach(sc);
:blob - 1c1bb17d9afd88820f08059e05be0a0f75a1435e
:blob + 54f93cf120d314f92ed89b11c2dd917c7b7f7f64
:--- sys/dev/ic/qwxvar.h
:+++ sys/dev/ic/qwxvar.h
:@@ -1841,6 +1841,7 @@ struct qwx_softc {
: 	} scan;
: 	u_int			scan_channel;
: 	struct qwx_survey_info	survey[IEEE80211_CHAN_MAX];
:+	struct task		bgscan_task;
: 
: 	int			attached;
: 	struct {
:@@ -1986,6 +1987,7 @@ int	qwx_media_change(struct ifnet *);
: void	qwx_init_task(void *);
: int	qwx_newstate(struct ieee80211com *, enum ieee80211_state, int);
: void	qwx_newstate_task(void *);
:+int	qwx_bgscan(struct ieee80211com *);
: 
: struct qwx_node {
: 	struct ieee80211_node ni;
:blob - fa91ce71bb49994fb8f625b56c9cf1d5487c2524
:blob + 017b9c18bde30549eaa3cda9de590652da021227
:--- sys/dev/pci/if_qwx_pci.c
:+++ sys/dev/pci/if_qwx_pci.c
:@@ -1119,6 +1119,8 @@ unsupported_wcn6855_soc:
: 	ic->ic_updateedca = qwx_updateedca;
: 	ic->ic_updatedtim = qwx_updatedtim;
: #endif
:+	ic->ic_bgscan_start = qwx_bgscan;
:+
: 	/*
: 	 * We cannot read the MAC address without loading the
: 	 * firmware from disk. Postpone until mountroot is done.
:

-- 
Health nuts are going to feel stupid someday, lying in hospitals dying
of nothing.
		-- Redd Foxx