aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/ath/if_ath.c37
-rw-r--r--sys/dev/ath/if_ath_tdma.c47
-rw-r--r--sys/dev/ath/if_athvar.h11
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, \