aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorSam Leffler <sam@FreeBSD.org>2005-03-30 20:13:08 +0000
committerSam Leffler <sam@FreeBSD.org>2005-03-30 20:13:08 +0000
commitc4c3cb462dce8b32a4faee3349e12d06d61def27 (patch)
tree5d12516500557614395db3b525cd48c30d9e0c68 /sys
parentcc60079bc7f2a31621309c30a3775febaf53ad63 (diff)
Notes
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ath/if_ath.c84
-rw-r--r--sys/dev/ath/if_athioctl.h2
-rw-r--r--sys/dev/ath/if_athvar.h13
3 files changed, 70 insertions, 29 deletions
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
index a51c053591300..0cbc708fa72aa 100644
--- a/sys/dev/ath/if_ath.c
+++ b/sys/dev/ath/if_ath.c
@@ -2999,9 +2999,17 @@ static int
ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf,
struct mbuf *m0)
{
+#define CTS_DURATION \
+ ath_hal_computetxtime(ah, rt, IEEE80211_ACK_LEN, cix, AH_TRUE)
+#define updateCTSForBursting(_ah, _ds, _txq) \
+ ath_hal_updateCTSForBursting(_ah, _ds, \
+ _txq->axq_linkbuf != NULL ? _txq->axq_linkbuf->bf_desc : NULL, \
+ _txq->axq_lastdsWithCTS, _txq->axq_gatingds, \
+ txopLimit, CTS_DURATION)
struct ieee80211com *ic = &sc->sc_ic;
struct ath_hal *ah = sc->sc_ah;
struct ifnet *ifp = &sc->sc_if;
+ const struct chanAccParams *cap = &ic->ic_wme.wme_chanParams;
int i, error, iswep, ismcast, keyix, hdrlen, pktlen, try0;
u_int8_t rix, txrate, ctsrate;
u_int8_t cix = 0xff; /* NB: silence compiler */
@@ -3014,6 +3022,7 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf
HAL_BOOL shortPreamble;
struct ath_node *an;
struct mbuf *m;
+ u_int pri;
wh = mtod(m0, struct ieee80211_frame *);
iswep = wh->i_fc[1] & IEEE80211_FC1_WEP;
@@ -3160,9 +3169,9 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf
/* NB: force all management frames to highest queue */
if (ni->ni_flags & IEEE80211_NODE_QOS) {
/* NB: force all management frames to highest queue */
- txq = sc->sc_ac2q[WME_AC_VO];
+ pri = WME_AC_VO;
} else
- txq = sc->sc_ac2q[WME_AC_BE];
+ pri = WME_AC_BE;
flags |= HAL_TXDESC_INTREQ; /* force interrupt */
break;
case IEEE80211_FC0_TYPE_CTL:
@@ -3176,9 +3185,9 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf
/* NB: force all ctl frames to highest queue */
if (ni->ni_flags & IEEE80211_NODE_QOS) {
/* NB: force all ctl frames to highest queue */
- txq = sc->sc_ac2q[WME_AC_VO];
+ pri = WME_AC_VO;
} else
- txq = sc->sc_ac2q[WME_AC_BE];
+ pri = WME_AC_BE;
flags |= HAL_TXDESC_INTREQ; /* force interrupt */
break;
case IEEE80211_FC0_TYPE_DATA:
@@ -3193,14 +3202,13 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf
* Default all non-QoS traffic to the background queue.
*/
if (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS) {
- u_int pri = M_WME_GETAC(m0);
- txq = sc->sc_ac2q[pri];
- if (ic->ic_wme.wme_wmeChanParams.cap_wmeParams[pri].wmep_noackPolicy) {
+ pri = M_WME_GETAC(m0);
+ if (cap->cap_wmeParams[pri].wmep_noackPolicy) {
flags |= HAL_TXDESC_NOACK;
sc->sc_stats.ast_tx_noack++;
}
} else
- txq = sc->sc_ac2q[WME_AC_BE];
+ pri = WME_AC_BE;
break;
default:
if_printf(ifp, "bogus frame type 0x%x (%s)\n",
@@ -3209,6 +3217,7 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf
m_freem(m0);
return EIO;
}
+ txq = sc->sc_ac2q[pri];
/*
* When servicing one or more stations in power-save mode
@@ -3398,27 +3407,44 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf
__func__, i, ds->ds_link, ds->ds_data,
ds->ds_ctl0, ds->ds_ctl1, ds->ds_hw[0], ds->ds_hw[1]);
}
-#if 0
- if ((flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA)) &&
- !ath_hal_updateCTSForBursting(ah, ds
- , txq->axq_linkbuf != NULL ?
- txq->axq_linkbuf->bf_desc : NULL
- , txq->axq_lastdsWithCTS
- , txq->axq_gatingds
- , IEEE80211_TXOP_TO_US(ic->ic_chanParams.cap_wmeParams[skb->priority].wmep_txopLimit)
- , ath_hal_computetxtime(ah, rt, IEEE80211_ACK_LEN, cix, AH_TRUE))) {
- ATH_TXQ_LOCK(txq);
- txq->axq_lastdsWithCTS = ds;
- /* set gating Desc to final desc */
- txq->axq_gatingds = (struct ath_desc *)txq->axq_link;
- ATH_TXQ_UNLOCK(txq);
- }
-#endif
/*
* Insert the frame on the outbound list and
* pass it on to the hardware.
*/
ATH_TXQ_LOCK(txq);
+ if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA)) {
+ u_int32_t txopLimit = IEEE80211_TXOP_TO_US(
+ cap->cap_wmeParams[pri].wmep_txopLimit);
+ /*
+ * When bursting, potentially extend the CTS duration
+ * of a previously queued frame to cover this frame
+ * and not exceed the txopLimit. If that can be done
+ * then disable RTS/CTS on this frame since it's now
+ * covered (burst extension). Otherwise we must terminate
+ * the burst before this frame goes out so as not to
+ * violate the WME parameters. All this is complicated
+ * as we need to update the state of packets on the
+ * (live) hardware queue. The logic is buried in the hal
+ * because it's highly chip-specific.
+ */
+ if (txopLimit != 0) {
+ sc->sc_stats.ast_tx_ctsburst++;
+ if (updateCTSForBursting(ah, ds0, txq) == 0) {
+ /*
+ * This frame was not covered by RTS/CTS from
+ * the previous frame in the burst; update the
+ * descriptor pointers so this frame is now
+ * treated as the last frame for extending a
+ * burst.
+ */
+ txq->axq_lastdsWithCTS = ds0;
+ /* set gating Desc to final desc */
+ txq->axq_gatingds =
+ (struct ath_desc *)txq->axq_link;
+ } else
+ sc->sc_stats.ast_tx_ctsext++;
+ }
+ }
ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
if (txq->axq_link == NULL) {
ath_hal_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
@@ -3443,6 +3469,8 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf
if (txq != sc->sc_cabq)
ath_hal_txstart(ah, txq->axq_qnum);
return 0;
+#undef updateCTSForBursting
+#undef CTS_DURATION
}
/*
@@ -3454,7 +3482,7 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
struct ath_hal *ah = sc->sc_ah;
struct ieee80211com *ic = &sc->sc_ic;
struct ath_buf *bf;
- struct ath_desc *ds;
+ struct ath_desc *ds, *ds0;
struct ieee80211_node *ni;
struct ath_node *an;
int sr, lr, pri;
@@ -3473,7 +3501,7 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
ATH_TXQ_UNLOCK(txq);
break;
}
- /* only the last descriptor is needed */
+ ds0 = &bf->bf_desc[0];
ds = &bf->bf_desc[bf->bf_nseg - 1];
status = ath_hal_txprocdesc(ah, ds);
#ifdef AR_DEBUG
@@ -3484,12 +3512,10 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
ATH_TXQ_UNLOCK(txq);
break;
}
-#if 0
- if (bf->bf_desc == txq->axq_lastdsWithCTS)
+ if (ds0 == txq->axq_lastdsWithCTS)
txq->axq_lastdsWithCTS = NULL;
if (ds == txq->axq_gatingds)
txq->axq_gatingds = NULL;
-#endif
ATH_TXQ_REMOVE_HEAD(txq, bf_list);
ATH_TXQ_UNLOCK(txq);
diff --git a/sys/dev/ath/if_athioctl.h b/sys/dev/ath/if_athioctl.h
index 6a4a4597473c9..3e7ec733fa46e 100644
--- a/sys/dev/ath/if_athioctl.h
+++ b/sys/dev/ath/if_athioctl.h
@@ -75,6 +75,8 @@ struct ath_stats {
u_int32_t ast_tx_shortpre;/* tx frames with short preamble */
u_int32_t ast_tx_altrate; /* tx frames with alternate rate */
u_int32_t ast_tx_protect; /* tx frames with protection */
+ u_int32_t ast_tx_ctsburst;/* tx frames with cts and bursting */
+ u_int32_t ast_tx_ctsext; /* tx frames with cts extension */
u_int32_t ast_rx_nombuf; /* rx setup failed 'cuz no mbuf */
u_int32_t ast_rx_busdma; /* rx setup failed for dma resrcs */
u_int32_t ast_rx_orn; /* rx failed 'cuz of desc overrun */
diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h
index 28c6ee6cf55de..d1ebb4f62e8d7 100644
--- a/sys/dev/ath/if_athvar.h
+++ b/sys/dev/ath/if_athvar.h
@@ -124,6 +124,19 @@ struct ath_txq {
u_int32_t *axq_link; /* link ptr in last TX desc */
STAILQ_HEAD(, ath_buf) axq_q; /* transmit queue */
struct mtx axq_lock; /* lock on q and link */
+ /*
+ * State for patching up CTS when bursting.
+ */
+ struct ath_buf *axq_linkbuf; /* va of last buffer */
+ struct ath_desc *axq_lastdsWithCTS;
+ /* first desc of last descriptor
+ * that contains CTS
+ */
+ struct ath_desc *axq_gatingds; /* final desc of the gating desc
+ * that determines whether
+ * lastdsWithCTS has been DMA'ed
+ * or not
+ */
};
#define ATH_TXQ_LOCK_INIT(_sc, _tq) \