From owner-dev-commits-src-all@freebsd.org Sat Mar 13 07:35:43 2021 Return-Path: Delivered-To: dev-commits-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 1C1CA56C440; Sat, 13 Mar 2021 07:35:43 +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 "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4DyDxV6W8vz4WBB; Sat, 13 Mar 2021 07:35:42 +0000 (UTC) (envelope-from git@FreeBSD.org) 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 D20EE26CB5; Sat, 13 Mar 2021 07:35:42 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 12D7Zgsw062295; Sat, 13 Mar 2021 07:35:42 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 12D7ZgQf062294; Sat, 13 Mar 2021 07:35:42 GMT (envelope-from git) Date: Sat, 13 Mar 2021 07:35:42 GMT Message-Id: <202103130735.12D7ZgQf062294@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Adrian Chadd Subject: git: fb3edd4f3ff8 - main - [ath] do a cold reset if TSFOOR triggers MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: adrian X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: fb3edd4f3ff89f5883b8309ff71ff4a426279c85 Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-all@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for all branches of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 13 Mar 2021 07:35:43 -0000 The branch main has been updated by adrian: URL: https://cgit.FreeBSD.org/src/commit/?id=fb3edd4f3ff89f5883b8309ff71ff4a426279c85 commit fb3edd4f3ff89f5883b8309ff71ff4a426279c85 Author: Adrian Chadd AuthorDate: 2021-03-13 07:30:25 +0000 Commit: Adrian Chadd CommitDate: 2021-03-13 07:30:25 +0000 [ath] do a cold reset if TSFOOR triggers TSFOOR happens if a beacon with a given TSF isn't received within the programmed/expected TSF value, plus/minus a fudge range. (OOR == out of range.) If this happens then it could be because the baseband/mac is stuck, or the baseband is deaf. So, do a cold reset and resync the beacon to try and unstick the hardware. It also happens when a bad AP decides to err, slew its TSF because they themselves are resetting and they don't preserve the TSF "well." This has fixed a bunch of weird corner cases on my 2GHz AP radio upstairs here where it occasionally goes deaf due to how much 2GHz noise is up here (and ANI gets a little sideways) and this unsticks the station VAP. For AP modes a hung baseband/mac usually ends up as a stuck beacon and those have been addressed for a long time by just resetting the hardware. But similar hangs in station mode didn't have a similar recovery mechanism. Tested: * AR9380, STA mode, 2GHz/5GHz * AR9580, STA mode, 5GHz * QCA9344 SoC w/ on-board wifi (TL-WDR4300/3600 devices); 2GHz STA mode --- sys/dev/ath/if_ath.c | 50 ++++++++++++++++++++++++++++++++++++++++++----- sys/dev/ath/if_athioctl.h | 1 + sys/dev/ath/if_athvar.h | 1 + 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 0ef10e529dd5..698b8d1a2853 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -165,6 +165,7 @@ static void ath_parent(struct ieee80211com *); static void ath_fatal_proc(void *, int); static void ath_bmiss_vap(struct ieee80211vap *); static void ath_bmiss_proc(void *, int); +static void ath_tsfoor_proc(void *, int); static void ath_key_update_begin(struct ieee80211vap *); static void ath_key_update_end(struct ieee80211vap *); static void ath_update_mcast_hw(struct ath_softc *); @@ -761,6 +762,7 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) TASK_INIT(&sc->sc_rxtask, 0, sc->sc_rx.recv_tasklet, sc); TASK_INIT(&sc->sc_bmisstask, 0, ath_bmiss_proc, sc); + TASK_INIT(&sc->sc_tsfoortask, 0, ath_tsfoor_proc, sc); TASK_INIT(&sc->sc_bstucktask,0, ath_bstuck_proc, sc); TASK_INIT(&sc->sc_resettask,0, ath_reset_proc, sc); TASK_INIT(&sc->sc_txqtask, 0, ath_txq_sched_tasklet, sc); @@ -2333,13 +2335,18 @@ ath_intr(void *arg) sc->sc_stats.ast_rxorn++; } if (status & HAL_INT_TSFOOR) { - /* out of range beacon - wake the chip up, - * but don't modify self-gen frame config */ - device_printf(sc->sc_dev, "%s: TSFOOR\n", __func__); - sc->sc_syncbeacon = 1; + /* + * out of range beacon - wake the chip up, + * but don't modify self-gen frame config. + * Do a full reset to clear any potential stuck + * PHY/MAC that generated this condition. + */ + sc->sc_stats.ast_tsfoor++; ATH_LOCK(sc); ath_power_setpower(sc, HAL_PM_AWAKE, 0); ATH_UNLOCK(sc); + taskqueue_enqueue(sc->sc_tq, &sc->sc_tsfoortask); + device_printf(sc->sc_dev, "%s: TSFOOR\n", __func__); } if (status & HAL_INT_MCI) { ath_btcoex_mci_intr(sc); @@ -2483,7 +2490,7 @@ ath_bmiss_proc(void *arg, int pending) ath_beacon_miss(sc); /* - * Do a reset upon any becaon miss event. + * Do a reset upon any beacon miss event. * * It may be a non-recognised RX clear hang which needs a reset * to clear. @@ -2505,6 +2512,39 @@ ath_bmiss_proc(void *arg, int pending) ATH_UNLOCK(sc); } +/* + * Handle a TSF out of range interrupt in STA mode. + * + * This may be due to a partially deaf looking radio, so + * do a full reset just in case it is indeed deaf and + * resync the beacon. + */ +static void +ath_tsfoor_proc(void *arg, int pending) +{ + struct ath_softc *sc = arg; + + DPRINTF(sc, ATH_DEBUG_ANY, "%s: pending %u\n", __func__, pending); + + ATH_LOCK(sc); + ath_power_set_power_state(sc, HAL_PM_AWAKE); + ATH_UNLOCK(sc); + + /* + * Do a full reset after any TSFOOR. It's possible that + * we've gone deaf or partially deaf (eg due to calibration + * failures) and this should clean things up a bit. + */ + ath_reset(sc, ATH_RESET_NOLOSS, HAL_RESET_FORCE_COLD); + + /* Force a beacon resync, in case they've drifted */ + sc->sc_syncbeacon = 1; + + ATH_LOCK(sc); + ath_power_restore_power_state(sc); + ATH_UNLOCK(sc); +} + /* * Handle TKIP MIC setup to deal hardware that doesn't do MIC * calcs together with WME. If necessary disable the crypto diff --git a/sys/dev/ath/if_athioctl.h b/sys/dev/ath/if_athioctl.h index fec48bb4c890..5043cd8ab467 100644 --- a/sys/dev/ath/if_athioctl.h +++ b/sys/dev/ath/if_athioctl.h @@ -177,6 +177,7 @@ struct ath_stats { u_int32_t ast_tx_nodeq_overflow; /* node sw queue overflow */ u_int32_t ast_tx_ldpc; /* TX LDPC frame */ u_int32_t ast_tx_stbc; /* TX STBC frame */ + u_int32_t ast_tsfoor; /* TSFOOR interrupts */ u_int32_t ast_pad[10]; }; diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h index 7817fe667281..1d2f842197cd 100644 --- a/sys/dev/ath/if_athvar.h +++ b/sys/dev/ath/if_athvar.h @@ -784,6 +784,7 @@ struct ath_softc { /* recent tx frames/antenna */ struct ath_txq *sc_cabq; /* tx q for cab frames */ struct task sc_bmisstask; /* bmiss int processing */ + struct task sc_tsfoortask; /* TSFOOR int processing */ struct task sc_bstucktask; /* stuck beacon processing */ struct task sc_resettask; /* interface reset task */ struct task sc_fataltask; /* fatal task */