Index: if_ath_tdma.c =================================================================== --- if_ath_tdma.c (revision 250777) +++ if_ath_tdma.c (working copy) @@ -277,10 +277,20 @@ 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); ath_beaconq_config(sc); /* setup h/w beacon q */ @@ -392,8 +402,35 @@ * 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); Index: if_athvar.h =================================================================== --- if_athvar.h (revision 250783) +++ if_athvar.h (working copy) @@ -627,7 +627,8 @@ */ 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 @@ 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, \ Index: if_ath.c =================================================================== --- if_ath.c (revision 250795) +++ if_ath.c (working copy) @@ -670,6 +670,7 @@ 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 @@ /* 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_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 @@ /* 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_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) {