Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 3 Mar 2008 23:44:40 GMT
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 136772 for review
Message-ID:  <200803032344.m23NieOD012134@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=136772

Change 136772 by sam@sam_ebb on 2008/03/03 23:44:02

	Fix power save mcast frame handling:
	o mark per-vap mcastq w/ the proper qnum so it's handled correctly
	  by ath_tx_handoff
	o mark frames with MORE_DATA as they are queued; this can result
	  in 1 frame being wrongly marked in very pathological cases but is
	  hard to avoid unless we want to calculate the air time coverage
	  for q'd frames to figure out where the hardware will cutoff our
	  bursting; in the case of a frame going out wrongly marked with
	  MORE_DATA this should just result in PS stations staying awake
	  for the remainder of the beacon interval (or less depending on
	  their implementation)

Affected files ...

.. //depot/projects/vap/sys/dev/ath/if_ath.c#38 edit
.. //depot/projects/vap/sys/dev/ath/if_athvar.h#18 edit

Differences ...

==== //depot/projects/vap/sys/dev/ath/if_ath.c#38 (text+ko) ====

@@ -906,8 +906,7 @@
 			 */
 			sc->sc_stagbeacons = 1;
 		}
-		STAILQ_INIT(&avp->av_mcastq.axq_q);
-		ATH_TXQ_LOCK_INIT(sc, &avp->av_mcastq);
+		ath_txq_init(sc, &avp->av_mcastq, ATH_TXQ_SWQ);
 	}
 
 	ic->ic_opmode = ic_opmode;
@@ -4407,8 +4406,8 @@
 	 * to avoid possible races.
 	 */
 	ATH_TXQ_LOCK(txq);
-	ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
 	if (txq->axq_qnum != ATH_TXQ_SWQ) {
+		ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
 		if (txq->axq_link == NULL) {
 			ath_hal_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
 			DPRINTF(sc, ATH_DEBUG_XMIT,
@@ -4425,8 +4424,20 @@
 		txq->axq_link = &bf->bf_desc[bf->bf_nseg - 1].ds_link;
 		ath_hal_txstart(ah, txq->axq_qnum);
 	} else {
-		if (txq->axq_link != NULL)
+		if (txq->axq_link != NULL) {
+			struct ath_buf *last = ATH_TXQ_LAST(txq);
+			struct ieee80211_frame *wh;
+
+			/* mark previous frame */
+			wh = mtod(last->bf_m, struct ieee80211_frame *);
+			wh->i_fc[1] |= IEEE80211_FC1_MORE_DATA;
+			bus_dmamap_sync(sc->sc_dmat, last->bf_dmamap,
+			    BUS_DMASYNC_PREWRITE);
+
+			/* link descriptor */
 			*txq->axq_link = bf->bf_daddr;
+		}
+		ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
 		txq->axq_link = &bf->bf_desc[bf->bf_nseg - 1].ds_link;
 	}
 	ATH_TXQ_UNLOCK(txq);
@@ -4620,10 +4631,8 @@
 	 * queue (to prevent out of order delivery) multicast
 	 * frames must be buffered until after the beacon.
 	 */
-	if (ismcast && (vap->iv_ps_sta || avp->av_mcastq.axq_depth)) {
+	if (ismcast && (vap->iv_ps_sta || avp->av_mcastq.axq_depth))
 		txq = &avp->av_mcastq;
-		/* XXX? more bit in 802.11 frame header */
-	}
 
 	/*
 	 * Calculate miscellaneous flags.

==== //depot/projects/vap/sys/dev/ath/if_athvar.h#18 (text+ko) ====

@@ -180,6 +180,10 @@
 	STAILQ_REMOVE_HEAD(&(_tq)->axq_q, _field); \
 	(_tq)->axq_depth--; \
 } while (0)
+/* NB: this does not do the "head empty check" that STAILQ_LAST does */
+#define	ATH_TXQ_LAST(_tq) \
+	((struct ath_buf *)(void *) \
+	 ((char *)((_tq)->axq_q.stqh_last) - __offsetof(struct ath_buf, bf_list)))
 
 struct ath_vap {
 	struct ieee80211vap av_vap;	/* base class */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200803032344.m23NieOD012134>