Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 27 Sep 2005 22:40:32 GMT
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 84401 for review
Message-ID:  <200509272240.j8RMeWdH052342@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=84401

Change 84401 by sam@sam_ebb on 2005/09/27 22:39:33

	stuff

Affected files ...

.. //depot/projects/wifi/sys/dev/ath/if_ath.c#105 edit
.. //depot/projects/wifi/sys/dev/ath/if_athioctl.h#9 edit
.. //depot/projects/wifi/sys/dev/ath/if_athvar.h#44 edit

Differences ...

==== //depot/projects/wifi/sys/dev/ath/if_ath.c#105 (text+ko) ====

@@ -816,10 +816,25 @@
 ath_bmiss_proc(void *arg, int pending)
 {
 	struct ath_softc *sc = arg;
+	struct ieee80211com *ic = &sc->sc_ic;
+	u_int64_t lastrx = sc->sc_lastrx;
+	u_int64_t tsf = ath_hal_gettsf64(sc->sc_ah);
 
-	DPRINTF(sc, ATH_DEBUG_ANY, "%s: pending %u\n", __func__, pending);
+	DPRINTF(sc, ATH_DEBUG_BEACON,
+	    "%s: tsf %llu lastrx %lld (%llu) bmiss %u\n",
+	    __func__, tsf, tsf - lastrx, lastrx, ic->ic_bmisstimeout*1024);
 
-	ieee80211_beacon_miss(&sc->sc_ic);
+	/*
+	 * Workaround phantom bmiss interrupts by sanity-checking
+	 * the time of our last rx'd frame.  If it is within the
+	 * beacon miss interval then ignore the interrupt.  If it's
+	 * truly a bmiss we'll get another interrupt soon and that'll
+	 * be dispatched up for processing.
+	 */
+	if (tsf - lastrx > ic->ic_bmisstimeout*1024)
+		ieee80211_beacon_miss(&sc->sc_ic);
+	else
+		sc->sc_stats.ast_bmiss_phantom++;
 }
 
 static u_int
@@ -893,6 +908,8 @@
 	 * state cached in the driver.
 	 */
 	sc->sc_diversity = ath_hal_getdiversity(ah);
+	sc->sc_calinterval = 1;
+	sc->sc_caltries = 0;
 
 	/*
 	 * Setup the hardware after reset: the key cache
@@ -1043,6 +1060,8 @@
 			__func__, status);
 	ath_update_txpow(sc);		/* update tx power state */
 	sc->sc_diversity = ath_hal_getdiversity(ah);
+	sc->sc_calinterval = 1;
+	sc->sc_caltries = 0;
 	if (ath_startrecv(sc) != 0)	/* restart recv */
 		if_printf(ifp, "%s: unable to start recv logic\n", __func__);
 	/*
@@ -1449,7 +1468,7 @@
 			STAILQ_REMOVE_HEAD(&sc->sc_txbuf, bf_list);
 		ATH_TXBUF_UNLOCK(sc);
 		if (bf == NULL) {
-			DPRINTF(sc, ATH_DEBUG_ANY, "%s: out of xmit buffers\n",
+			DPRINTF(sc, ATH_DEBUG_XMIT, "%s: out of xmit buffers\n",
 				__func__);
 			sc->sc_stats.ast_tx_qstop++;
 			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
@@ -1465,7 +1484,7 @@
 			 * No data frames go out unless we're associated.
 			 */
 			if (ic->ic_state != IEEE80211_S_RUN) {
-				DPRINTF(sc, ATH_DEBUG_ANY,
+				DPRINTF(sc, ATH_DEBUG_XMIT,
 				    "%s: discard data packet, state %s\n",
 				    __func__,
 				    ieee80211_state_name[ic->ic_state]);
@@ -1556,7 +1575,7 @@
 			 */
 			m = ieee80211_encap(ic, m, ni);
 			if (m == NULL) {
-				DPRINTF(sc, ATH_DEBUG_ANY,
+				DPRINTF(sc, ATH_DEBUG_XMIT,
 					"%s: encapsulation failure\n",
 					__func__);
 				sc->sc_stats.ast_tx_encap++;
@@ -1570,7 +1589,7 @@
 			 */
 			if ((m->m_flags & M_FRAG) && 
 			    !ath_txfrag_setup(sc, &frags, m, ni)) {
-				DPRINTF(sc, ATH_DEBUG_ANY,
+				DPRINTF(sc, ATH_DEBUG_XMIT,
 				    "%s: out of txfrag buffers\n", __func__);
 				ic->ic_stats.is_tx_nobuf++;	/* XXX */
 				goto bad;
@@ -1639,7 +1658,7 @@
 			 * XXX check sta power-save state?
 			 */
 			if (ic->ic_state != IEEE80211_S_RUN) {
-				DPRINTF(sc, ATH_DEBUG_ANY,
+				DPRINTF(sc, ATH_DEBUG_XMIT,
 				    "%s: flush fragmented packet, state %s\n",
 				    __func__,
 				    ieee80211_state_name[ic->ic_state]);
@@ -3105,13 +3124,14 @@
 	struct mbuf *m;
 	struct ieee80211_node *ni;
 	struct ath_node *an;
-	int len, type;
+	int len, type, ngood;
 	u_int phyerr;
 	HAL_STATUS status;
 
 	NET_LOCK_GIANT();		/* XXX */
 
 	DPRINTF(sc, ATH_DEBUG_RX_PROC, "%s: pending %u\n", __func__, npending);
+	ngood = 0;
 	do {
 		bf = STAILQ_FIRST(&sc->sc_rxbuf);
 		if (bf == NULL) {		/* NB: shouldn't happen */
@@ -3126,7 +3146,7 @@
 		m = bf->bf_m;
 		if (m == NULL) {		/* NB: shouldn't happen */
 			if_printf(ifp, "%s: no mbuf!\n", __func__);
-			continue;
+			break;
 		}
 		/* XXX sync descriptor memory */
 		/*
@@ -3358,12 +3378,24 @@
 			} else if (ticks - sc->sc_ledevent >= sc->sc_ledidle)
 				ath_led_event(sc, ATH_LED_POLL);
 		}
+		/*
+		 * Arrange to update the last rx timestamp only for
+		 * data frames; this avoids false positives caused by
+		 * hearing beacon frames from ap's on the same channel.
+		 * If the only frames we receive are management frames
+		 * when we take a bmiss then we can probably cope with
+		 * falling back to the state machine as we're not busy.
+		 */
+		if (type == IEEE80211_FC0_TYPE_DATA)
+			ngood++;
 rx_next:
 		STAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list);
 	} while (ath_rxbuf_init(sc, bf) == 0);
 
 	/* rx signal state monitoring */
 	ath_hal_rxmonitor(ah, &sc->sc_halstats, &sc->sc_curchan);
+	if (ngood)
+		sc->sc_lastrx = ath_hal_gettsf64(ah);
 
 	NET_UNLOCK_GIANT();		/* XXX */
 #undef PA2DESC
@@ -4198,7 +4230,7 @@
 /*
  * Process completed xmit descriptors from the specified queue.
  */
-static void
+static int
 ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
 {
 	struct ath_hal *ah = sc->sc_ah;
@@ -4207,13 +4239,14 @@
 	struct ath_desc *ds, *ds0;
 	struct ieee80211_node *ni;
 	struct ath_node *an;
-	int sr, lr, pri;
+	int sr, lr, pri, nacked;
 	HAL_STATUS status;
 
 	DPRINTF(sc, ATH_DEBUG_TX_PROC, "%s: tx queue %u head %p link %p\n",
 		__func__, txq->axq_qnum,
 		(caddr_t)(uintptr_t) ath_hal_gettxbuf(sc->sc_ah, txq->axq_qnum),
 		txq->axq_link);
+	nacked = 0;
 	for (;;) {
 		ATH_TXQ_LOCK(txq);
 		txq->axq_intrcnt = 0;	/* reset periodic desc intr count */
@@ -4276,8 +4309,15 @@
 			 * Hand the descriptor to the rate control algorithm.
 			 */
 			if ((ds->ds_txstat.ts_status & HAL_TXERR_FILT) == 0 &&
-			    (bf->bf_flags & HAL_TXDESC_NOACK) == 0)
+			    (bf->bf_flags & HAL_TXDESC_NOACK) == 0) {
+				/*
+				 * If frame was ack'd update the last rx time
+				 * used to workaround phantom bmiss interrupts.
+				 */
+				if (ds->ds_txstat.ts_status == 0)
+					nacked++;
 				ath_rate_tx_complete(sc, an, ds, ds0);
+			}
 			/*
 			 * Reclaim reference to node.
 			 *
@@ -4303,6 +4343,7 @@
 	 */
 	if (txq->axq_depth <= 1)
 		ath_ff_stageq_flush(sc, txq, ath_ff_always);
+	return nacked;
 }
 
 static __inline int
@@ -4323,8 +4364,8 @@
 	struct ath_softc *sc = arg;
 	struct ifnet *ifp = sc->sc_ifp;
 
-	if (txqactive(sc->sc_ah, 0))
-		ath_tx_processq(sc, &sc->sc_txq[0]);
+	if (txqactive(sc->sc_ah, 0) && ath_tx_processq(sc, &sc->sc_txq[0]))
+		sc->sc_lastrx = ath_hal_gettsf64(sc->sc_ah);
 	if (txqactive(sc->sc_ah, sc->sc_cabq->axq_qnum))
 		ath_tx_processq(sc, sc->sc_cabq);
 	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
@@ -4345,20 +4386,24 @@
 {
 	struct ath_softc *sc = arg;
 	struct ifnet *ifp = sc->sc_ifp;
+	int nacked;
 
 	/*
 	 * Process each active queue.
 	 */
+	nacked = 0;
 	if (txqactive(sc->sc_ah, 0))
-		ath_tx_processq(sc, &sc->sc_txq[0]);
+		nacked += ath_tx_processq(sc, &sc->sc_txq[0]);
 	if (txqactive(sc->sc_ah, 1))
-		ath_tx_processq(sc, &sc->sc_txq[1]);
+		nacked += ath_tx_processq(sc, &sc->sc_txq[1]);
 	if (txqactive(sc->sc_ah, 2))
-		ath_tx_processq(sc, &sc->sc_txq[2]);
+		nacked += ath_tx_processq(sc, &sc->sc_txq[2]);
 	if (txqactive(sc->sc_ah, 3))
-		ath_tx_processq(sc, &sc->sc_txq[3]);
+		nacked += ath_tx_processq(sc, &sc->sc_txq[3]);
 	if (txqactive(sc->sc_ah, sc->sc_cabq->axq_qnum))
 		ath_tx_processq(sc, sc->sc_cabq);
+	if (nacked)
+		sc->sc_lastrx = ath_hal_gettsf64(sc->sc_ah);
 
 	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 	ifp->if_timer = 0;
@@ -4377,14 +4422,17 @@
 {
 	struct ath_softc *sc = arg;
 	struct ifnet *ifp = sc->sc_ifp;
-	int i;
+	int i, nacked;
 
 	/*
 	 * Process each active queue.
 	 */
+	nacked = 0;
 	for (i = 0; i < HAL_NUM_TX_QUEUES; i++)
 		if (ATH_TXQ_SETUP(sc, i) && txqactive(sc->sc_ah, i))
-			ath_tx_processq(sc, &sc->sc_txq[i]);
+			nacked += ath_tx_processq(sc, &sc->sc_txq[i]);
+	if (nacked)
+		sc->sc_lastrx = ath_hal_gettsf64(sc->sc_ah);
 
 	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 	ifp->if_timer = 0;
@@ -4630,6 +4678,8 @@
 		sc->sc_curchan = hchan;
 		ath_update_txpow(sc);		/* update tx power state */
 		sc->sc_diversity = ath_hal_getdiversity(ah);
+		sc->sc_calinterval = 1;
+		sc->sc_caltries = 0;
 
 		/*
 		 * Re-enable rx framework.
@@ -4663,27 +4713,50 @@
 {
 	struct ath_softc *sc = arg;
 	struct ath_hal *ah = sc->sc_ah;
+	HAL_BOOL iqCalDone;
 
 	sc->sc_stats.ast_per_cal++;
 
-	DPRINTF(sc, ATH_DEBUG_CALIBRATE, "%s: channel %u/%x\n",
-		__func__, sc->sc_curchan.channel, sc->sc_curchan.channelFlags);
-
 	if (ath_hal_getrfgain(ah) == HAL_RFGAIN_NEED_CHANGE) {
 		/*
 		 * Rfgain is out of bounds, reset the chip
 		 * to load new gain values.
 		 */
 		sc->sc_stats.ast_per_rfgain++;
+		DPRINTF(sc, ATH_DEBUG_CALIBRATE,
+			"%s: rfgain change\n", __func__);
 		ath_reset(sc->sc_ifp);
 	}
-	if (!ath_hal_calibrate(ah, &sc->sc_curchan)) {
+	if (!ath_hal_calibrate(ah, &sc->sc_curchan, &iqCalDone)) {
 		DPRINTF(sc, ATH_DEBUG_ANY,
 			"%s: calibration of channel %u failed\n",
 			__func__, sc->sc_curchan.channel);
 		sc->sc_stats.ast_per_calfail++;
 	}
-	callout_reset(&sc->sc_cal_ch, ath_calinterval * hz, ath_calibrate, sc);
+	/*
+	 * Poll more frequently when the IQ calibration is in
+	 * progress to speedup loading the final settings. 
+	 * We temper this aggressive polling with an exponential
+	 * back off after 4 tries up to ath_calinterval.
+	 */
+	if (iqCalDone || sc->sc_calinterval >= ath_calinterval) {
+		sc->sc_caltries = 0;
+		sc->sc_calinterval = ath_calinterval;
+	} else if (sc->sc_caltries > 4) {
+		sc->sc_caltries = 0;
+		sc->sc_calinterval <<= 1;
+		if (sc->sc_calinterval > ath_calinterval)
+			sc->sc_calinterval = ath_calinterval;
+	}
+	KASSERT(0 < sc->sc_calinterval && sc->sc_calinterval <= ath_calinterval,
+		("bad calibration interval %u", sc->sc_calinterval));
+
+	DPRINTF(sc, ATH_DEBUG_CALIBRATE,
+		"%s: next +%u (%siqCalDone tries %u)\n", __func__,
+		sc->sc_calinterval, iqCalDone ? "" : "!", sc->sc_caltries);
+	sc->sc_caltries++;
+	callout_reset(&sc->sc_cal_ch, sc->sc_calinterval * hz,
+		ath_calibrate, sc);
 }
 
 static void
@@ -4880,7 +4953,7 @@
 	 */
 	if (nstate == IEEE80211_S_RUN) {
 		/* start periodic recalibration timer */
-		callout_reset(&sc->sc_cal_ch, ath_calinterval * hz,
+		callout_reset(&sc->sc_cal_ch, sc->sc_calinterval * hz,
 			ath_calibrate, sc);
 	}
 bad:
@@ -5535,6 +5608,33 @@
 	return !ath_hal_settpc(sc->sc_ah, tpc) ? EINVAL : 0;
 }
 
+static int
+ath_sysctl_rfkill(SYSCTL_HANDLER_ARGS)
+{
+	struct ath_softc *sc = arg1;
+	u_int rfkill = ath_hal_getrfkill(sc->sc_ah);
+	int error;
+
+	error = sysctl_handle_int(oidp, &rfkill, 0, req);
+	if (error || !req->newptr)
+		return error;
+	return !ath_hal_setrfkill(sc->sc_ah, rfkill) ? EINVAL : 0;
+}
+
+static int
+ath_sysctl_rfsilent(SYSCTL_HANDLER_ARGS)
+{
+	struct ath_softc *sc = arg1;
+	u_int rfsilent;
+	int error;
+
+	ath_hal_getrfsilent(sc->sc_ah, &rfsilent);
+	error = sysctl_handle_int(oidp, &rfsilent, 0, req);
+	if (error || !req->newptr)
+		return error;
+	return !ath_hal_setrfsilent(sc->sc_ah, rfsilent) ? EINVAL : 0;
+}
+
 static void
 ath_sysctlattach(struct ath_softc *sc)
 {
@@ -5610,6 +5710,14 @@
 			"fftxqmax", CTLFLAG_RW, &sc->sc_fftxqmax, 0,
 			"max queued frames before tail drop");
 	}
+	if (ath_hal_hasrfsilent(ah)) {
+		SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+			"rfsilent", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+			ath_sysctl_rfsilent, "I", "h/w RF silent config");
+		SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+			"rfkill", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+			ath_sysctl_rfkill, "I", "enable/disable RF kill switch");
+	}
 }
 
 static void

==== //depot/projects/wifi/sys/dev/ath/if_athioctl.h#9 (text+ko) ====

@@ -46,6 +46,7 @@
 	u_int32_t	ast_watchdog;	/* device reset by watchdog */
 	u_int32_t	ast_hardware;	/* fatal hardware error interrupts */
 	u_int32_t	ast_bmiss;	/* beacon miss interrupts */
+	u_int32_t	ast_bmiss_phantom;/* beacon miss interrupts */
 	u_int32_t	ast_bstuck;	/* beacon stuck interrupts */
 	u_int32_t	ast_rxorn;	/* rx overrun interrupts */
 	u_int32_t	ast_rxeol;	/* rx eol interrupts */
@@ -110,6 +111,7 @@
 	u_int32_t	ast_ff_rx;	/* fast frames rx'd */
 	u_int32_t	ast_ff_flush;	/* fast frames flushed from staging q */
 	u_int32_t	ast_tx_qfull;	/* tx dropped 'cuz of queue limit */
+	u_int32_t	ast_pad[32];
 };
 
 #define	SIOCGATHSTATS	_IOWR('i', 137, struct ifreq)

==== //depot/projects/wifi/sys/dev/ath/if_athvar.h#44 (text+ko) ====

@@ -289,6 +289,7 @@
 	struct task		sc_rxorntask;	/* rxorn int processing */
 	u_int8_t		sc_defant;	/* current default antenna */
 	u_int8_t		sc_rxotherant;	/* rx's on non-default antenna*/
+	u_int64_t		sc_lastrx;	/* tsf at last rx'd frame */
 
 	struct ath_descdma	sc_txdma;	/* TX descriptors */
 	ath_bufhead		sc_txbuf;	/* transmit buffer */
@@ -315,6 +316,8 @@
 	} sc_updateslot;			/* slot time update fsm */
 
 	struct callout		sc_cal_ch;	/* callout handle for cals */
+	int			sc_calinterval;	/* current polling interval */
+	int			sc_caltries;	/* cals at current interval */
 	HAL_NODE_STATS		sc_halstats;	/* station-mode rssi stats */
 };
 #define	sc_tx_th		u_tx_rt.th
@@ -411,8 +414,8 @@
 	((*(_ah)->ah_startTxDma)((_ah), (_q)))
 #define	ath_hal_setchannel(_ah, _chan) \
 	((*(_ah)->ah_setChannel)((_ah), (_chan)))
-#define	ath_hal_calibrate(_ah, _chan) \
-	((*(_ah)->ah_perCalibration)((_ah), (_chan)))
+#define	ath_hal_calibrate(_ah, _chan, _iqcal) \
+	((*(_ah)->ah_perCalibration)((_ah), (_chan), (_iqcal)))
 #define	ath_hal_setledstate(_ah, _state) \
 	((*(_ah)->ah_setLedState)((_ah), (_state)))
 #define	ath_hal_beaconinit(_ah, _nextb, _bperiod) \
@@ -528,6 +531,16 @@
 #endif
 #define	ath_hal_hasfastframes(_ah) \
 	(ath_hal_getcapability(_ah, HAL_CAP_FASTFRAME, 0, NULL) == HAL_OK)
+#define	ath_hal_hasrfsilent(_ah) \
+	(ath_hal_getcapability(_ah, HAL_CAP_RFSILENT, 0, NULL) == HAL_OK)
+#define	ath_hal_getrfkill(_ah) \
+	(ath_hal_getcapability(_ah, HAL_CAP_RFSILENT, 1, NULL) == HAL_OK)
+#define	ath_hal_setrfkill(_ah, _onoff) \
+	ath_hal_setcapability(_ah, HAL_CAP_RFSILENT, 1, _onoff, NULL)
+#define	ath_hal_getrfsilent(_ah, _prfsilent) \
+	(ath_hal_getcapability(_ah, HAL_CAP_RFSILENT, 2, _prfsilent) == HAL_OK)
+#define	ath_hal_setrfsilent(_ah, _rfsilent) \
+	ath_hal_setcapability(_ah, HAL_CAP_RFSILENT, 2, _rfsilent, NULL)
 
 #define	ath_hal_setuprxdesc(_ah, _ds, _size, _intreq) \
 	((*(_ah)->ah_setupRxDesc)((_ah), (_ds), (_size), (_intreq)))



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200509272240.j8RMeWdH052342>