From owner-svn-src-all@FreeBSD.ORG Tue May 21 18:02:55 2013 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 9AC70C47; Tue, 21 May 2013 18:02:55 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 7CF56209; Tue, 21 May 2013 18:02:55 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.6/8.14.6) with ESMTP id r4LI2tSh094277; Tue, 21 May 2013 18:02:55 GMT (envelope-from adrian@svn.freebsd.org) Received: (from adrian@localhost) by svn.freebsd.org (8.14.6/8.14.5/Submit) id r4LI2sIi094273; Tue, 21 May 2013 18:02:54 GMT (envelope-from adrian@svn.freebsd.org) Message-Id: <201305211802.r4LI2sIi094273@svn.freebsd.org> From: Adrian Chadd Date: Tue, 21 May 2013 18:02:54 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r250865 - head/sys/dev/ath X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 21 May 2013 18:02:55 -0000 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, \