From nobody Fri Aug 29 13:19:03 2025 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4cCzPM5qf3z65VnQ; Fri, 29 Aug 2025 13:19:03 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R12" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4cCzPM4jm4z3VVn; Fri, 29 Aug 2025 13:19:03 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1756473543; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=re8mbvtjWo4h2cHX2Ur3GMwJDo+nJIWre2DMCZz9TUI=; b=bZAJbgojunnKFmrG5A8ElskK1jS0/7iZSaE4UyGf7sRbfPVW1Auma3sSN0nH5gzbI6xVE0 AZwKuEI+DuFz/crkvuv7iKjj6bdsoqU0uD1pJQkdR66znFIEHVdRXMAMuiVZWxIMM4mDo2 6NKrsir+KxX9KXvLiemJ5qNwVLOv7L1IWgCogtlaym2Got5pDGbcQpSDFUs63GMF7TUR+Y huVkTVKTaNkqVkk7J1ohwdML9dZNDqBaxq6zFj+3HSZvUEOeb25wnGRYgqWNzVx+FO7Ctk N5sfAULYoOdr0K9g9NqYi62qMYjsz/+0+du5wRUR9jC7cEutRC7mSafBfk/yBA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1756473543; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=re8mbvtjWo4h2cHX2Ur3GMwJDo+nJIWre2DMCZz9TUI=; b=xIvNyIJRbzHgTfwl0+ysof2kRUrn/xNg/igx/c/QA5vunrXuyLeu2EU4AOLs4H0c3J2SjI 8utjV2rd+KzZPZlbo+h7gXoYVbb3fBBwO22qgX3pSnh7PxbV6QnmOy8j3FfdqPXe8N2tvE HmUeXP+crw4azVbP0UK/zy/bQDGzRmOix72a+ZV9HzU+za61zr8hJfujI4QGIdRHcePIhk 8qCiYBnxU/lZiBvPsy1tdelCOvDb9V5ySwz7+1WDjc1Ej3bgvUXkOSV40GnU0WVo53sxLe 8kBmX4BrtPQoATjZnyZMI/DXout9HQxHr7OrSKhh5Pa5F122KoPVyNHggeVqqg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1756473543; a=rsa-sha256; cv=none; b=DR01Kq/237Kp3+s19rA2KJOppG8yzXn00VWi+ft5Nr/NNvhS2u/jXDlg7Jfr72z+SpGDYz Pr7Oe9GOWuaAz0dsf5QhuOsZfVV6jbXrdbu7ZEBmsUA2cYw6PAVOuOKIyAS+EKpKDA4jMR z2bJ0Seom2v0vKJfu/Rs46+KO8MLZHP4Zr84uFPpmr0xTY7pQiadtpCKBbydA7T4pDk0JY A2tjwhKNAEcetjhKvkb27oT5JdDgnqCEzHAbYGuJuBJ4lkUMpUX7c1SyY3hylosruXUCXS 2EF12WX+n5lUTMfOz3DvU7lc3ccM4lFOeTrw/oBlhFbIjuO3iEzLcTl773kJJw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4cCzPM4JM8zh8Z; Fri, 29 Aug 2025 13:19:03 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 57TDJ3f1072359; Fri, 29 Aug 2025 13:19:03 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 57TDJ3Za072356; Fri, 29 Aug 2025 13:19:03 GMT (envelope-from git) Date: Fri, 29 Aug 2025 13:19:03 GMT Message-Id: <202508291319.57TDJ3Za072356@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: "Bjoern A. Zeeb" Subject: git: ad4ddc83ebf8 - main - LinuxKPI: 802.11: sort the fallback to software scan for rtw88 List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: bz X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: ad4ddc83ebf8c1edd7aa6add2e5cb71eaa6bcec1 Auto-Submitted: auto-generated The branch main has been updated by bz: URL: https://cgit.FreeBSD.org/src/commit/?id=ad4ddc83ebf8c1edd7aa6add2e5cb71eaa6bcec1 commit ad4ddc83ebf8c1edd7aa6add2e5cb71eaa6bcec1 Author: Bjoern A. Zeeb AuthorDate: 2025-08-28 21:34:01 +0000 Commit: Bjoern A. Zeeb CommitDate: 2025-08-29 13:18:43 +0000 LinuxKPI: 802.11: sort the fallback to software scan for rtw88 In the special case hardware scan fails to start, we cancel the scan with net80211 and cleanup our part. In that case we now sleep and wait for a wakeup. The wakeup was moved to a different callback function to serve both cases (hw scan cancelled, and hw scan failed). In the very special case the hardware scan fails with a return code of 1, we need to start a software scan. I cannot fully imagine this ever worked well (some rtw88 chipsets are using this). The trouble is that the cancael_scan runs in a taskq in net80211 and by the time we tried to start the new scan, the old one was not fully cleaned up and finished (or could have been restarted in case we enable bgscan). So defer starting the software scan to the taskq as well and it will run once the previous finished. The RTW8821ce I tested with seemed a lot more happy. Sponsored by: The FreeBSD Foundation MFC after: 3 days --- sys/compat/linuxkpi/common/src/linux_80211.c | 99 ++++++++++++++++++++++------ sys/compat/linuxkpi/common/src/linux_80211.h | 1 + 2 files changed, 81 insertions(+), 19 deletions(-) diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c index 55d84789e05a..ad3e6c043c94 100644 --- a/sys/compat/linuxkpi/common/src/linux_80211.c +++ b/sys/compat/linuxkpi/common/src/linux_80211.c @@ -173,6 +173,7 @@ const struct cfg80211_ops linuxkpi_mac80211cfgops = { static struct lkpi_sta *lkpi_find_lsta_by_ni(struct lkpi_vif *, struct ieee80211_node *); #endif +static void lkpi_sw_scan_task(void *, int); static void lkpi_80211_txq_tx_one(struct lkpi_sta *, struct mbuf *); static void lkpi_80211_txq_task(void *, int); static void lkpi_80211_lhw_rxq_task(void *, int); @@ -3856,6 +3857,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); + TASK_INIT(&lvif->sw_scan_task, 0, lkpi_sw_scan_task, lvif); INIT_LIST_HEAD(&lvif->lsta_list); lvif->lvif_bss = NULL; refcount_init(&lvif->nt_unlocked, 0); @@ -4094,6 +4096,8 @@ lkpi_ic_vap_delete(struct ieee80211vap *vap) /* Clear up per-VIF/VAP sysctls. */ sysctl_ctx_free(&lvif->sysctl_ctx); + ieee80211_draintask(ic, &lvif->sw_scan_task); + LKPI_80211_LHW_LVIF_LOCK(lhw); TAILQ_REMOVE(&lhw->lvif_head, lvif, lvif_entry); LKPI_80211_LHW_LVIF_UNLOCK(lhw); @@ -4485,7 +4489,7 @@ lkpi_ic_scan_start(struct ieee80211com *ic) if (!is_hw_scan) { /* 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); @@ -4498,6 +4502,8 @@ sw_scan: lkpi_update_mcast_filter(ic); + TRACE_SCAN(vap->iv_ic, "Starting SW_SCAN: scan_flags %b", + lhw->scan_flags, LKPI_LHW_SCAN_BITS); lkpi_80211_mo_sw_scan_start(hw, vif, vif->addr); /* net80211::scan_start() handled PS for us. */ IMPROVE(); @@ -4752,6 +4758,9 @@ sw_scan: error = lkpi_80211_mo_hw_scan(hw, vif, hw_req); if (error != 0) { + bool scan_done; + int e; + TRACE_SCAN(ic, "hw_scan failed; scan_flags %b, error %d", lhw->scan_flags, LKPI_LHW_SCAN_BITS, error); ieee80211_cancel_scan(vap); @@ -4770,14 +4779,35 @@ sw_scan: * So we cannot rely on that behaviour and have to check * and balance between both code paths. */ + e = 0; + scan_done = true; LKPI_80211_LHW_SCAN_LOCK(lhw); if ((lhw->scan_flags & LKPI_LHW_SCAN_RUNNING) != 0) { + free(lhw->hw_req, M_LKPI80211); lhw->hw_req = NULL; + /* + * The ieee80211_cancel_scan() above runs in a + * taskq and it may take ages for the previous + * scan to clear; starting a new one right away + * we run into the problem that the old one is + * still active. + */ + e = msleep(lhw, &lhw->scan_mtx, 0, "lhwscanstop", hz); + scan_done = (lhw->scan_flags & LKPI_LHW_SCAN_RUNNING) != 0; + + /* + * Now we can clear running if no one else did. + */ lhw->scan_flags &= ~LKPI_LHW_SCAN_RUNNING; } LKPI_80211_LHW_SCAN_UNLOCK(lhw); lkpi_update_mcast_filter(ic); + if (!scan_done) { + ic_printf(ic, "ERROR: %s: timeout/error to wait " + "for ieee80211_cancel_scan: %d\n", __func__, e); + return; + } /* * XXX-SIGH magic number. @@ -4785,33 +4815,59 @@ sw_scan: * not possible. Fall back to sw scan in that case. */ if (error == 1) { - LKPI_80211_LHW_SCAN_LOCK(lhw); - lhw->scan_flags &= ~LKPI_LHW_SCAN_HW; - LKPI_80211_LHW_SCAN_UNLOCK(lhw); /* - * XXX If we clear this now and later a driver - * thinks it * can do a hw_scan again, we will - * currently not re-enable it? + * We need to put this into some defered context + * the net80211 scan may not be done yet + * (ic_flags & IEEE80211_F_SCAN) and we cannot + * wait here; if we do scan_curchan_task always + * runs after our timeout to finalize the scan. */ - vap->iv_flags_ext &= ~IEEE80211_FEXT_SCAN_OFFLOAD; - ieee80211_start_scan(vap, - IEEE80211_SCAN_ACTIVE | - IEEE80211_SCAN_NOPICK | - IEEE80211_SCAN_ONCE, - IEEE80211_SCAN_FOREVER, - ss->ss_mindwell ? ss->ss_mindwell : msecs_to_ticks(20), - ss->ss_maxdwell ? ss->ss_maxdwell : msecs_to_ticks(200), - vap->iv_des_nssid, vap->iv_des_ssid); - goto sw_scan; + ieee80211_runtask(ic, &lvif->sw_scan_task); + return; } ic_printf(ic, "ERROR: %s: hw_scan returned %d\n", __func__, error); - ieee80211_cancel_scan(vap); } } } +static void +lkpi_sw_scan_task(void *arg, int pending __unused) +{ + struct lkpi_hw *lhw; + struct lkpi_vif *lvif; + struct ieee80211vap *vap; + struct ieee80211_scan_state *ss; + + lvif = arg; + vap = LVIF_TO_VAP(lvif); + lhw = vap->iv_ic->ic_softc; + ss = vap->iv_ic->ic_scan; + + LKPI_80211_LHW_SCAN_LOCK(lhw); + /* + * We will re-enable this at scan_end calling lkpi_enable_hw_scan(). + * IEEE80211_FEXT_SCAN_OFFLOAD will be cleared by lkpi_ic_scan_start. + */ + lhw->scan_flags &= ~LKPI_LHW_SCAN_HW; + LKPI_80211_LHW_SCAN_UNLOCK(lhw); + + TRACE_SCAN(vap->iv_ic, "Triggering SW_SCAN: pending %d, scan_flags %b", + pending, lhw->scan_flags, LKPI_LHW_SCAN_BITS); + + /* + * This will call ic_scan_start() and we will get into the right path + * unless other scans started in between. + */ + ieee80211_start_scan(vap, + IEEE80211_SCAN_ONCE, + msecs_to_ticks(10000), /* 10000 ms (=~ 50 chan * 200 ms) */ + ss->ss_mindwell ? ss->ss_mindwell : msecs_to_ticks(20), + ss->ss_maxdwell ? ss->ss_maxdwell : msecs_to_ticks(200), + vap->iv_des_nssid, vap->iv_des_ssid); +} + static void lkpi_ic_scan_end(struct ieee80211com *ic) { @@ -4855,6 +4911,10 @@ lkpi_ic_scan_end(struct ieee80211com *ic) * switched to swscan, re-enable hw_scan if available. */ lkpi_enable_hw_scan(lhw); + + LKPI_80211_LHW_SCAN_LOCK(lhw); + wakeup(lhw); + LKPI_80211_LHW_SCAN_UNLOCK(lhw); } static void @@ -6973,7 +7033,8 @@ linuxkpi_ieee80211_scan_completed(struct ieee80211_hw *hw, free(lhw->hw_req, M_LKPI80211); lhw->hw_req = NULL; lhw->scan_flags &= ~LKPI_LHW_SCAN_RUNNING; - wakeup(lhw); + /* The wakeup(lhw) will be called from lkpi_ic_scan_end(). */ + /* wakeup(lhw); */ LKPI_80211_LHW_SCAN_UNLOCK(lhw); return; diff --git a/sys/compat/linuxkpi/common/src/linux_80211.h b/sys/compat/linuxkpi/common/src/linux_80211.h index 8d3cda23946a..2b93eab03c27 100644 --- a/sys/compat/linuxkpi/common/src/linux_80211.h +++ b/sys/compat/linuxkpi/common/src/linux_80211.h @@ -201,6 +201,7 @@ struct lkpi_vif { struct mbuf *, int, const struct ieee80211_rx_stats *, int, int); + struct task sw_scan_task; struct list_head lsta_list;