svn commit: r347140 - in head/sys/dev/ath: . ath_rate/amrr ath_rate/onoe ath_rate/sample

Adrian Chadd adrian at FreeBSD.org
Sun May 5 04:56:40 UTC 2019


Author: adrian
Date: Sun May  5 04:56:37 2019
New Revision: 347140
URL: https://svnweb.freebsd.org/changeset/base/347140

Log:
  [ath] [ath_rate] Fix ANI calibration during non-ACTIVE states; start poking at rate control
  
  These are some fun issues I've found with my upstairs wifi link at such a ridiculous
  low signal level (like, < 5dB.)
  
  * Add per-station tx/rx rssi statistics, in potential preparation to use that
    in the RX rate control.
  
  * Call the rate control on each received frame to let it potentially use
    it as a hint for what rates to potentially use.  It's a no-op right now.
  
  * Do ANI calibration during scan as well. The ath_newstate() call was disabling the
    ANI timer and only re-enabling it during transitions to _RUN.  This has the
    unfortunate side-effect that if ANI deafened the NIC because of interference
    and it disassociated, it wouldn't be reset and the scan would never hear beacons.
  
  The ANI configuration is stored at least globally on some HALs and per-channel
  on others.  Because of this a NIC reset wouldn't help; the ANI parameters would
  simply be programmed back in.
  
  Now, I have a feeling I also need to do this during AUTH/ASSOC too and maybe,
  if I'm feeling clever, I need to reset the ANI parameters on a given channel
  during a transition through INIT or if the VAP is destroyed/re-created.
  However for now this gets me out of the immediate weeds with connectivity
  upstairs (and thus I /can/ commit); I'll keep chipping away at tidying this
  stuff up in subsequent commits.
  
  Tested:
  
  * AR9344 (Wasp), 2G STA mode

Modified:
  head/sys/dev/ath/ath_rate/amrr/amrr.c
  head/sys/dev/ath/ath_rate/onoe/onoe.c
  head/sys/dev/ath/ath_rate/sample/sample.c
  head/sys/dev/ath/if_ath.c
  head/sys/dev/ath/if_ath_rx.c
  head/sys/dev/ath/if_ath_tx_edma.c
  head/sys/dev/ath/if_athrate.h
  head/sys/dev/ath/if_athvar.h

Modified: head/sys/dev/ath/ath_rate/amrr/amrr.c
==============================================================================
--- head/sys/dev/ath/ath_rate/amrr/amrr.c	Sun May  5 04:14:17 2019	(r347139)
+++ head/sys/dev/ath/ath_rate/amrr/amrr.c	Sun May  5 04:56:37 2019	(r347140)
@@ -196,6 +196,11 @@ ath_rate_newassoc(struct ath_softc *sc, struct ath_nod
 		ath_rate_ctl_start(sc, &an->an_node);
 }
 
+void
+ath_rate_update_rx_rssi(struct ath_softc *sc, struct ath_node *an, int rssi)
+{
+}
+
 static void 
 node_reset(struct amrr_node *amn)
 {

Modified: head/sys/dev/ath/ath_rate/onoe/onoe.c
==============================================================================
--- head/sys/dev/ath/ath_rate/onoe/onoe.c	Sun May  5 04:14:17 2019	(r347139)
+++ head/sys/dev/ath/ath_rate/onoe/onoe.c	Sun May  5 04:56:37 2019	(r347140)
@@ -189,6 +189,12 @@ ath_rate_newassoc(struct ath_softc *sc, struct ath_nod
 		ath_rate_ctl_start(sc, &an->an_node);
 }
 
+void
+ath_rate_update_rx_rssi(struct ath_softc *sc, struct ath_node *an, int rssi)
+{
+}
+
+
 static void
 ath_rate_update(struct ath_softc *sc, struct ieee80211_node *ni, int rate)
 {

Modified: head/sys/dev/ath/ath_rate/sample/sample.c
==============================================================================
--- head/sys/dev/ath/ath_rate/sample/sample.c	Sun May  5 04:14:17 2019	(r347139)
+++ head/sys/dev/ath/ath_rate/sample/sample.c	Sun May  5 04:56:37 2019	(r347140)
@@ -1019,6 +1019,12 @@ ath_rate_newassoc(struct ath_softc *sc, struct ath_nod
 		ath_rate_ctl_reset(sc, &an->an_node);
 }
 
+void
+ath_rate_update_rx_rssi(struct ath_softc *sc, struct ath_node *an, int rssi)
+{
+}
+
+
 static const struct txschedule *mrr_schedules[IEEE80211_MODE_MAX+2] = {
 	NULL,		/* IEEE80211_MODE_AUTO */
 	series_11a,	/* IEEE80211_MODE_11A */

Modified: head/sys/dev/ath/if_ath.c
==============================================================================
--- head/sys/dev/ath/if_ath.c	Sun May  5 04:14:17 2019	(r347139)
+++ head/sys/dev/ath/if_ath.c	Sun May  5 04:56:37 2019	(r347140)
@@ -3882,6 +3882,10 @@ ath_node_alloc(struct ieee80211vap *vap, const uint8_t
 	/* XXX setup ath_tid */
 	ath_tx_tid_init(sc, an);
 
+	an->an_node_stats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER;
+	an->an_node_stats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER;
+	an->an_node_stats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER;
+
 	DPRINTF(sc, ATH_DEBUG_NODE, "%s: %6D: an %p\n", __func__, mac, ":", an);
 	return &an->an_node;
 }
@@ -4493,6 +4497,8 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *
 			sc->sc_stats.ast_tx_rssi = ts->ts_rssi;
 			ATH_RSSI_LPF(sc->sc_halstats.ns_avgtxrssi,
 				ts->ts_rssi);
+			ATH_RSSI_LPF(ATH_NODE(ni)->an_node_stats.ns_avgtxrssi,
+				ts->ts_rssi);
 		}
 		ATH_TXQ_UNLOCK(txq);
 
@@ -5435,6 +5441,16 @@ ath_calibrate(void *arg)
 				__func__, sc->sc_curchan->ic_freq);
 			sc->sc_stats.ast_per_calfail++;
 		}
+		/*
+		 * XXX TODO: get the NF calibration results from the HAL.
+		 * If we failed NF cal then schedule a hard reset to potentially
+		 * un-freeze the PHY.
+		 *
+		 * Note we have to be careful here to not get stuck in an
+		 * infinite NIC restart.  Ideally we'd not restart if we
+		 * failed the first NF cal - that /can/ fail sometimes in
+		 * a noisy environment.
+		 */
 		if (shortCal)
 			sc->sc_lastshortcal = ticks;
 	}
@@ -6090,6 +6106,17 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_
 			taskqueue_block(sc->sc_tq);
 			sc->sc_beacons = 0;
 		}
+
+		/*
+		 * For at least STA mode we likely should clear the ANI
+		 * and NF calibration state and allow the NIC/HAL to figure
+		 * out optimal parameters at runtime.  Otherwise if we
+		 * disassociate due to interference / deafness it may persist
+		 * when we reconnect.
+		 *
+		 * Note: may need to do this for other states too, not just
+		 * _S_INIT.
+		 */
 #ifdef IEEE80211_SUPPORT_TDMA
 		ath_hal_setcca(ah, AH_TRUE);
 #endif
@@ -6119,9 +6146,39 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_
 			}
 			ATH_UNLOCK(sc);
 		}
+
+		/*
+		 * Note - the ANI/calibration timer isn't re-enabled during
+		 * network sleep for now.  One unfortunate side-effect is that
+		 * the PHY/airtime statistics aren't gathered on the channel
+		 * but I haven't yet tested to see if reading those registers
+		 * CAN occur during network sleep.
+		 *
+		 * This should be revisited in a future commit, even if it's
+		 * just to split out the airtime polling from ANI/calibration.
+		 */
 	} else if (nstate == IEEE80211_S_SCAN) {
 		/* Quiet time handling - ensure we resync */
 		memset(&avp->quiet_ie, 0, sizeof(avp->quiet_ie));
+
+		/*
+		 * If we're in scan mode then startpcureceive() is
+		 * hopefully being called with "reset ANI" for this channel;
+		 * but once we attempt to reassociate we program in the previous
+		 * ANI values and.. not do any calibration until we're running.
+		 * This may mean we stay deaf unless we can associate successfully.
+		 *
+		 * So do kick off the cal timer to get NF/ANI going.
+		 */
+		ATH_LOCK(sc);
+		if (ath_longcalinterval != 0) {
+			/* start periodic recalibration timer */
+			callout_reset(&sc->sc_cal_ch, 1, ath_calibrate, sc);
+		} else {
+			DPRINTF(sc, ATH_DEBUG_CALIBRATE,
+			    "%s: calibration disabled\n", __func__);
+		}
+		ATH_UNLOCK(sc);
 	}
 bad:
 	ieee80211_free_node(ni);

Modified: head/sys/dev/ath/if_ath_rx.c
==============================================================================
--- head/sys/dev/ath/if_ath_rx.c	Sun May  5 04:14:17 2019	(r347139)
+++ head/sys/dev/ath/if_ath_rx.c	Sun May  5 04:56:37 2019	(r347140)
@@ -363,6 +363,11 @@ ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *
 	ATH_VAP(vap)->av_recv_mgmt(ni, m, subtype, rxs, rssi, nf);
 	switch (subtype) {
 	case IEEE80211_FC0_SUBTYPE_BEACON:
+		/*
+		 * Always update the per-node beacon RSSI if we're hearing
+		 * beacons from that node.
+		 */
+		ATH_RSSI_LPF(ATH_NODE(ni)->an_node_stats.ns_avgbrssi, rssi);
 
 		/*
 		 * Only do the following processing if it's for
@@ -946,6 +951,21 @@ rx_accept:
 			m->m_flags |= M_AMPDU;
 
 		/*
+		 * Inform rate control about the received RSSI.
+		 * It can then use this information to potentially drastically
+		 * alter the available rate based on the RSSI estimate.
+		 *
+		 * This is super important when associating to a far away station;
+		 * you don't want to waste time trying higher rates at some low
+		 * packet exchange rate (like during DHCP) just to establish
+		 * that higher MCS rates aren't available.
+		 */
+		ATH_RSSI_LPF(ATH_NODE(ni)->an_node_stats.ns_avgrssi,
+		    rs->rs_rssi);
+		ath_rate_update_rx_rssi(sc, ATH_NODE(ni),
+		    ATH_RSSI(ATH_NODE(ni)->an_node_stats.ns_avgrssi));
+
+		/*
 		 * Sending station is known, dispatch directly.
 		 */
 		(void) ieee80211_add_rx_params(m, &rxs);
@@ -973,7 +993,7 @@ rx_accept:
 	 */
 
 	/*
-	 * Track rx rssi and do any rx antenna management.
+	 * Track legacy station RX rssi and do any rx antenna management.
 	 */
 	ATH_RSSI_LPF(sc->sc_halstats.ns_avgrssi, rs->rs_rssi);
 	if (sc->sc_diversity) {

Modified: head/sys/dev/ath/if_ath_tx_edma.c
==============================================================================
--- head/sys/dev/ath/if_ath_tx_edma.c	Sun May  5 04:14:17 2019	(r347139)
+++ head/sys/dev/ath/if_ath_tx_edma.c	Sun May  5 04:56:37 2019	(r347140)
@@ -1012,6 +1012,8 @@ ath_edma_tx_processq(struct ath_softc *sc, int dosched
 			sc->sc_stats.ast_tx_rssi = ts.ts_rssi;
 			ATH_RSSI_LPF(sc->sc_halstats.ns_avgtxrssi,
 			    ts.ts_rssi);
+			ATH_RSSI_LPF(ATH_NODE(ni)->an_node_stats.ns_avgtxrssi,
+			    ts.ts_rssi);
 		}
 
 		/* Handle frame completion and rate control update */

Modified: head/sys/dev/ath/if_athrate.h
==============================================================================
--- head/sys/dev/ath/if_athrate.h	Sun May  5 04:14:17 2019	(r347139)
+++ head/sys/dev/ath/if_athrate.h	Sun May  5 04:56:37 2019	(r347140)
@@ -157,6 +157,12 @@ void	ath_rate_tx_complete(struct ath_softc *, struct a
 		int pktlen, int nframes, int nbad);
 
 /*
+ * Update rate control with a per-packet receive RSSI value.
+ */
+void	ath_rate_update_rx_rssi(struct ath_softc *, struct ath_node *,
+		int rssi);
+
+/*
  * Fetch the global rate control statistics.
  */
 int	ath_rate_fetch_stats(struct ath_softc *sc, struct ath_rateioctl *rs);

Modified: head/sys/dev/ath/if_athvar.h
==============================================================================
--- head/sys/dev/ath/if_athvar.h	Sun May  5 04:14:17 2019	(r347139)
+++ head/sys/dev/ath/if_athvar.h	Sun May  5 04:56:37 2019	(r347140)
@@ -204,6 +204,7 @@ struct ath_node {
 					   node */
 	int			clrdmask;	/* has clrdmask been set */
 	uint32_t	an_leak_count;	/* How many frames to leak during pause */
+	HAL_NODE_STATS	an_node_stats;	/* HAL node stats for this node */
 	/* variable-length rate control state follows */
 };
 #define	ATH_NODE(ni)	((struct ath_node *)(ni))


More information about the svn-src-all mailing list