From b6ef0f8ac8983da0777fffffd92fa1713a1b221e Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Tue, 26 Mar 2013 04:52:16 +0000 Subject: [PATCH] Convert the CABQ queue code over to use the HAL link pointer method instead of axq_link. This (among a bunch of uncommitted work) is required for EDMA chips to correctly transmit frames on the CABQ. Tested: * AR9280, hostap mode * AR9380/AR9580, hostap mode (staggered beacons) TODO: * This code only really gets called when burst beacons are used; it glues multiple CABQ queues together when sending to the hardware. * More thorough bursted beacon testing! (first requires some work with the beacon queue code for bursted beacons, as that currently uses the link pointer and will fail on EDMA chips.) --- sys/dev/ath/if_ath_beacon.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/sys/dev/ath/if_ath_beacon.c b/sys/dev/ath/if_ath_beacon.c index e847f9361fd5..0da019df6143 100644 --- a/sys/dev/ath/if_ath_beacon.c +++ b/sys/dev/ath/if_ath_beacon.c @@ -632,7 +632,7 @@ ath_beacon_generate(struct ath_softc *sc, struct ieee80211vap *vap) /* NB: only at DTIM */ ATH_TXQ_LOCK(&avp->av_mcastq); if (nmcastq) { - struct ath_buf *bfm; + struct ath_buf *bfm, *bfc_last; /* * Move frames from the s/w mcast q to the h/w cab q. @@ -645,16 +645,23 @@ ath_beacon_generate(struct ath_softc *sc, struct ieee80211vap *vap) * MORE data bit set on the last frame of each * intermediary VAP (ie, only clear the MORE * bit of the last frame on the last vap?) - * - * XXX TODO: once we append this, what happens - * to cabq->axq_link? It'll point at the avp - * mcastq link pointer, so things should be OK. - * Just double-check this is what actually happens. */ bfm = TAILQ_FIRST(&avp->av_mcastq.axq_q); ATH_TXQ_LOCK(cabq); - if (cabq->axq_link != NULL) - *cabq->axq_link = bfm->bf_daddr; + + /* + * If there's already a frame on the CABQ, we + * need to link to the end of the last frame. + * We can't use axq_link here because + * EDMA descriptors require some recalculation + * (checksum) to occur. + */ + bfc_last = ATH_TXQ_LAST(cabq, axq_q_s); + if (bfc_last != NULL) { + ath_hal_settxdesclink(sc->sc_ah, + bfc_last->bf_lastds, + bfm->bf_daddr); + } ath_txqmove(cabq, &avp->av_mcastq); ATH_TXQ_UNLOCK(cabq); /*