diff options
-rw-r--r-- | sys/dev/ath/if_ath.c | 37 | ||||
-rw-r--r-- | sys/dev/ath/if_ath_tdma.c | 47 | ||||
-rw-r--r-- | sys/dev/ath/if_athvar.h | 11 |
3 files changed, 89 insertions, 6 deletions
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 4744d75ade55..6f5d9bf3fe11 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -670,6 +670,7 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) 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_TYPE reset_type) /* 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, struct ieee80211_channel *chan) 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) { diff --git a/sys/dev/ath/if_ath_tdma.c b/sys/dev/ath/if_ath_tdma.c index 1d9a95f0be2b..c075d01849a1 100644 --- a/sys/dev/ath/if_ath_tdma.c +++ b/sys/dev/ath/if_ath_tdma.c @@ -277,9 +277,19 @@ ath_tdma_config(struct ath_softc *sc, struct ieee80211vap *vap) 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 *ni, * 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); diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h index 02f6432dd7fd..f7d262eab027 100644 --- a/sys/dev/ath/if_athvar.h +++ b/sys/dev/ath/if_athvar.h @@ -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, \ |