svn commit: r250865 - head/sys/dev/ath

Adrian Chadd adrian at FreeBSD.org
Tue May 21 18:02:55 UTC 2013


Author: adrian
Date: Tue May 21 18:02:54 2013
New Revision: 250865
URL: http://svnweb.freebsd.org/changeset/base/250865

Log:
  Enable the use of TDMA on an 802.11n channel (with aggregation disabled,
  of course.)
  
  There's a few things that needed to happen:
  
  * In case someone decides to set the beacon transmission rate to be
    at an MCS rate, use the MCS-aware version of the duration calculation
    to figure out how long the received beacon frame was.
  
  * If TxOP enforcing is available on the hardware and we're doing TDMA,
    enable it after a reset and set the TDMA guard interval to zero.
    This seems to behave fine.
  
  TODO:
  
  * Although I haven't yet seen packet loss, the PHY errors that would be
    triggered (specifically Transmit-Override-Receive) aren't enabled
    by the 11n HAL.  I'll have to do some work to enable these PHY errors
    for debugging.
  
  What broke:
  
  * My recent changes to the TX queue handling has resulted in the driver
    not keeping the hardware queue properly filled when doing non-aggregate
    traffic.  I have a patch to commit soon which fixes this situation
    (albeit by reminding me about how my ath driver locking isn't working
    out, sigh.)
  
    So if you want to test this without updating to the next set of patches
    that I commit, just bump the sysctl dev.ath.X.hwq_limit from 2 to 32.
  
  Tested:
  
  * AR5416 <-> AR5416, with ampdu disabled, HT40, 5GHz, MCS12+Short-GI.
    I saw 30mbit/sec in both directions using a bidirectional UDP test.

Modified:
  head/sys/dev/ath/if_ath.c
  head/sys/dev/ath/if_ath_tdma.c
  head/sys/dev/ath/if_athvar.h

Modified: head/sys/dev/ath/if_ath.c
==============================================================================
--- head/sys/dev/ath/if_ath.c	Tue May 21 18:00:47 2013	(r250864)
+++ head/sys/dev/ath/if_ath.c	Tue May 21 18:02:54 2013	(r250865)
@@ -670,6 +670,7 @@ ath_attach(u_int16_t devid, struct ath_s
 	sc->sc_hastsfadd = ath_hal_hastsfadjust(ah);
 	sc->sc_rxslink = ath_hal_self_linked_final_rxdesc(ah);
 	sc->sc_rxtsf32 = ath_hal_has_long_rxdesc_tsf(ah);
+	sc->sc_hasenforcetxop = ath_hal_hasenforcetxop(ah);
 	if (ath_hal_hasfastframes(ah))
 		ic->ic_caps |= IEEE80211_C_FF;
 	wmodes = ath_hal_getwirelessmodes(ah);
@@ -1586,6 +1587,15 @@ ath_resume(struct ath_softc *sc)
 	/* Let spectral at in case spectral is enabled */
 	ath_spectral_enable(sc, ic->ic_curchan);
 
+	/*
+	 * If we're doing TDMA, enforce the TXOP limitation for chips that
+	 * support it.
+	 */
+	if (sc->sc_hasenforcetxop && sc->sc_tdma)
+		ath_hal_setenforcetxop(sc->sc_ah, 1);
+	else
+		ath_hal_setenforcetxop(sc->sc_ah, 0);
+
 	/* Restore the LED configuration */
 	ath_led_config(sc);
 	ath_hal_setledstate(ah, HAL_LED_INIT);
@@ -2034,6 +2044,15 @@ ath_init(void *arg)
 	ath_spectral_enable(sc, ic->ic_curchan);
 
 	/*
+	 * If we're doing TDMA, enforce the TXOP limitation for chips that
+	 * support it.
+	 */
+	if (sc->sc_hasenforcetxop && sc->sc_tdma)
+		ath_hal_setenforcetxop(sc->sc_ah, 1);
+	else
+		ath_hal_setenforcetxop(sc->sc_ah, 0);
+
+	/*
 	 * Likewise this is set during reset so update
 	 * state cached in the driver.
 	 */
@@ -2348,6 +2367,15 @@ ath_reset(struct ifnet *ifp, ATH_RESET_T
 	/* Let spectral at in case spectral is enabled */
 	ath_spectral_enable(sc, ic->ic_curchan);
 
+	/*
+	 * If we're doing TDMA, enforce the TXOP limitation for chips that
+	 * support it.
+	 */
+	if (sc->sc_hasenforcetxop && sc->sc_tdma)
+		ath_hal_setenforcetxop(sc->sc_ah, 1);
+	else
+		ath_hal_setenforcetxop(sc->sc_ah, 0);
+
 	if (ath_startrecv(sc) != 0)	/* restart recv */
 		if_printf(ifp, "%s: unable to start recv logic\n", __func__);
 	/*
@@ -4869,6 +4897,15 @@ ath_chan_set(struct ath_softc *sc, struc
 		ath_spectral_enable(sc, chan);
 
 		/*
+		 * If we're doing TDMA, enforce the TXOP limitation for chips
+		 * that support it.
+		 */
+		if (sc->sc_hasenforcetxop && sc->sc_tdma)
+			ath_hal_setenforcetxop(sc->sc_ah, 1);
+		else
+			ath_hal_setenforcetxop(sc->sc_ah, 0);
+
+		/*
 		 * Re-enable rx framework.
 		 */
 		if (ath_startrecv(sc) != 0) {

Modified: head/sys/dev/ath/if_ath_tdma.c
==============================================================================
--- head/sys/dev/ath/if_ath_tdma.c	Tue May 21 18:00:47 2013	(r250864)
+++ head/sys/dev/ath/if_ath_tdma.c	Tue May 21 18:02:54 2013	(r250865)
@@ -277,9 +277,19 @@ ath_tdma_config(struct ath_softc *sc, st
 		rix = ath_tx_findrix(sc, tp->ucastrate);
 	else
 		rix = ath_tx_findrix(sc, tp->mcastrate);
-	/* XXX short preamble assumed */
-	sc->sc_tdmaguard = ath_hal_computetxtime(ah, sc->sc_currates,
-		ifp->if_mtu + IEEE80211_MAXOVERHEAD, rix, AH_TRUE);
+
+	/*
+	 * If the chip supports enforcing TxOP on transmission,
+	 * we can just delete the guard window.  It isn't at all required.
+	 */
+	if (sc->sc_hasenforcetxop) {
+		sc->sc_tdmaguard = 0;
+	} else {
+		/* XXX short preamble assumed */
+		/* XXX non-11n rate assumed */
+		sc->sc_tdmaguard = ath_hal_computetxtime(ah, sc->sc_currates,
+			ifp->if_mtu + IEEE80211_MAXOVERHEAD, rix, AH_TRUE);
+	}
 
 	ath_hal_intrset(ah, 0);
 
@@ -392,8 +402,35 @@ ath_tdma_update(struct ieee80211_node *n
 	 * the packet just received.
 	 */
 	rix = rt->rateCodeToIndex[rs->rs_rate];
-	txtime = ath_hal_computetxtime(ah, rt, rs->rs_datalen, rix,
-	    rt->info[rix].shortPreamble);
+
+	/*
+	 * To calculate the packet duration for legacy rates, we
+	 * only need the rix and preamble.
+	 *
+	 * For 11n non-aggregate frames, we also need the channel
+	 * width and short/long guard interval.
+	 *
+	 * For 11n aggregate frames, the required hacks are a little
+	 * more subtle.  You need to figure out the frame duration
+	 * for each frame, including the delimiters.  However, when
+	 * a frame isn't received successfully, we won't hear it
+	 * (unless you enable reception of CRC errored frames), so
+	 * your duration calculation is going to be off.
+	 *
+	 * However, we can assume that the beacon frames won't be
+	 * transmitted as aggregate frames, so we should be okay.
+	 * Just add a check to ensure that we aren't handed something
+	 * bad.
+	 *
+	 * For ath_hal_pkt_txtime() - for 11n rates, shortPreamble is
+	 * actually short guard interval. For legacy rates,
+	 * it's short preamble.
+	 */
+	txtime = ath_hal_pkt_txtime(ah, rt, rs->rs_datalen,
+	    rix,
+	    !! (rs->rs_flags & HAL_RX_2040),
+	    (rix & 0x80) ?
+	      (! (rs->rs_flags & HAL_RX_GI)) : rt->info[rix].shortPreamble);
 	/* NB: << 9 is to cvt to TU and /2 */
 	nextslot = (rstamp - txtime) + (sc->sc_tdmabintval << 9);
 

Modified: head/sys/dev/ath/if_athvar.h
==============================================================================
--- head/sys/dev/ath/if_athvar.h	Tue May 21 18:00:47 2013	(r250864)
+++ head/sys/dev/ath/if_athvar.h	Tue May 21 18:02:54 2013	(r250865)
@@ -627,7 +627,8 @@ struct ath_softc {
 	 */
 	u_int32_t		sc_use_ent  : 1,
 				sc_rx_stbc  : 1,
-				sc_tx_stbc  : 1;
+				sc_tx_stbc  : 1,
+				sc_hasenforcetxop : 1; /* support enforce TxOP */
 
 
 	int			sc_cabq_enable;	/* Enable cabq transmission */
@@ -1256,6 +1257,14 @@ void	ath_intr(void *);
 	ath_hal_setcapability(_ah, HAL_CAP_INTMIT, \
 	HAL_CAP_INTMIT_ENABLE, _v, NULL)
 
+#define	ath_hal_hasenforcetxop(_ah) \
+	(ath_hal_getcapability(_ah, HAL_CAP_ENFORCE_TXOP, 0, NULL) == HAL_OK)
+#define	ath_hal_getenforcetxop(_ah) \
+	(ath_hal_getcapability(_ah, HAL_CAP_ENFORCE_TXOP, 1, NULL) == HAL_OK)
+#define	ath_hal_setenforcetxop(_ah, _v) \
+	ath_hal_setcapability(_ah, HAL_CAP_ENFORCE_TXOP, 1, _v, NULL)
+
+
 /* EDMA definitions */
 #define	ath_hal_hasedma(_ah) \
 	(ath_hal_getcapability(_ah, HAL_CAP_ENHANCED_DMA_SUPPORT,	\


More information about the svn-src-head mailing list