Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 18 Mar 2012 22:27:43 -0700
From:      Adrian Chadd <adrian@freebsd.org>
To:        bug-followup@freebsd.org, Vincent Hoffman <vince@unsane.co.uk>
Cc:        freebsd-wireless@freebsd.org
Subject:   Re: kern/166190: [ath] TX hangs and frames stuck in TX queue
Message-ID:  <CAJ-Vmom6TDaRORRQ=w5h8RhVi1OBRL14jqjvMokyf2M83Q4Wrw@mail.gmail.com>
In-Reply-To: <CAJ-VmonBjFcop0765vDvd8jyOcijhWcCK6CYgMC97nuqcpvi=Q@mail.gmail.com>
References:  <201203170440.q2H4esnb099802@freefall.freebsd.org> <CAJ-VmonBjFcop0765vDvd8jyOcijhWcCK6CYgMC97nuqcpvi=Q@mail.gmail.com>

index | next in thread | previous in thread | raw e-mail

[-- Attachment #1 --]
Hi Vincent,

Please try this patch and let me know how it behaves.

Thanks,



Adrian

[-- Attachment #2 --]
Index: sys/dev/ath/if_ath_debug.c
===================================================================
--- sys/dev/ath/if_ath_debug.c	(revision 233089)
+++ sys/dev/ath/if_ath_debug.c	(working copy)
@@ -135,19 +135,23 @@
 	printf("Q%u[%3u]", qnum, ix);
 	while (bf != NULL) {
 		for (i = 0, ds = bf->bf_desc; i < bf->bf_nseg; i++, ds++) {
-			printf(" (DS.V:%p DS.P:%p) L:%08x D:%08x F:%04x%s\n"
-			       "        TXF: %04x Seq: %d swtry: %d ADDBAW?: %d DOBAW?: %d\n"
-			       "        %08x %08x %08x %08x %08x %08x\n",
+			printf(" (DS.V:%p DS.P:%p) L:%08x D:%08x F:%04x%s\n",
 			    ds, (const struct ath_desc *)bf->bf_daddr + i,
 			    ds->ds_link, ds->ds_data, bf->bf_txflags,
-			    !done ? "" : (ts->ts_status == 0) ? " *" : " !",
+			    !done ? "" : (ts->ts_status == 0) ? " *" : " !");
+			printf("        TXF: %04x Seq: %d swtry: %d ADDBAW?: %d DOBAW?: %d\n",
 			    bf->bf_state.bfs_flags,
 			    bf->bf_state.bfs_seqno,
 			    bf->bf_state.bfs_retries,
 			    bf->bf_state.bfs_addedbaw,
-			    bf->bf_state.bfs_dobaw,
+			    bf->bf_state.bfs_dobaw);
+			printf("        SEQNO_ASSIGNED: %d, NEED_SEQNO: %d\n",
+			    bf->bf_state.bfs_seqno_assigned,
+			    bf->bf_state.bfs_need_seqno);
+			printf("        %08x %08x %08x %08x %08x %08x\n",
 			    ds->ds_ctl0, ds->ds_ctl1,
-			    ds->ds_hw[0], ds->ds_hw[1], ds->ds_hw[2], ds->ds_hw[3]);
+			    ds->ds_hw[0], ds->ds_hw[1],
+			    ds->ds_hw[2], ds->ds_hw[3]);
 			if (ah->ah_magic == 0x20065416) {
 				printf("        %08x %08x %08x %08x %08x %08x %08x %08x\n",
 				    ds->ds_hw[4], ds->ds_hw[5], ds->ds_hw[6],
Index: sys/dev/ath/if_athvar.h
===================================================================
--- sys/dev/ath/if_athvar.h	(revision 233089)
+++ sys/dev/ath/if_athvar.h	(working copy)
@@ -215,6 +215,8 @@
 		int bfs_ismrr:1;	/* do multi-rate TX retry */
 		int bfs_doprot:1;	/* do RTS/CTS based protection */
 		int bfs_doratelookup:1;	/* do rate lookup before each TX */
+		int bfs_need_seqno:1;	/* need to assign a seqno for aggregation */
+		int bfs_seqno_assigned:1;	/* seqno has been assigned */
 		int bfs_nfl;		/* next fragment length */
 
 		/*
Index: sys/dev/ath/if_ath_tx_ht.c
===================================================================
--- sys/dev/ath/if_ath_tx_ht.c	(revision 233089)
+++ sys/dev/ath/if_ath_tx_ht.c	(working copy)
@@ -644,7 +644,7 @@
 ath_tx_form_aggr(struct ath_softc *sc, struct ath_node *an, struct ath_tid *tid,
     ath_bufhead *bf_q)
 {
-	//struct ieee80211_node *ni = &an->an_node;
+	struct ieee80211_node *ni = &an->an_node;
 	struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL;
 	int nframes = 0;
 	uint16_t aggr_limit = 0, al = 0, bpad = 0, al_delta, h_baw;
@@ -652,6 +652,7 @@
 	int status = ATH_AGGR_DONE;
 	int prev_frames = 0;	/* XXX for AR5416 burst, not done here */
 	int prev_al = 0;	/* XXX also for AR5416 burst */
+	int seqno;
 
 	ATH_TXQ_LOCK_ASSERT(sc->sc_ac2q[tid->ac]);
 
@@ -707,16 +708,6 @@
 		 */
 
 		/*
-		 * If the packet has a sequence number, do not
-		 * step outside of the block-ack window.
-		 */
-		if (! BAW_WITHIN(tap->txa_start, tap->txa_wnd,
-		    SEQNO(bf->bf_state.bfs_seqno))) {
-		    status = ATH_AGGR_BAW_CLOSED;
-		    break;
-		}
-
-		/*
 		 * XXX TODO: AR5416 has an 8K aggregation size limit
 		 * when RTS is enabled, and RTS is required for dual-stream
 		 * rates.
@@ -744,6 +735,58 @@
 		}
 
 		/*
+		 * TODO: If it's _before_ the BAW left edge, complain very loudly.
+		 * This means something (else) has slid the left edge along
+		 * before we got a chance to be TXed.
+		 */
+
+		/*
+		 * Check if we have space in the BAW for this frame before
+		 * we add it.
+		 *
+		 * see ath_tx_xmit_aggr() for more info.
+		 */
+		if (bf->bf_state.bfs_dobaw) {
+			if (! BAW_WITHIN(tap->txa_start, tap->txa_wnd,
+			    ni->ni_txseqs[bf->bf_state.bfs_tid])) {
+				status = ATH_AGGR_BAW_CLOSED;
+				break;
+			}
+			/* XXX check for bfs_need_seqno? */
+			if (! bf->bf_state.bfs_seqno_assigned) {
+				seqno = ath_tx_tid_seqno_assign(sc, ni, bf, bf->bf_m);
+				if (seqno < 0) {
+					device_printf(sc->sc_dev,
+					    "%s: bf=%p, huh, seqno=-1?\n",
+					    __func__,
+					    bf);
+					/* XXX what can we even do here? */
+				}
+				/* Flush seqno update to RAM */
+				/*
+				 * XXX This is required because the dmasetup
+				 * XXX is done early rather than at dispatch
+				 * XXX time. Ew, we should fix this!
+				 */
+				bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap,
+				    BUS_DMASYNC_PREWRITE);
+			}
+		}
+
+		/*
+		 * If the packet has a sequence number, do not
+		 * step outside of the block-ack window.
+		 */
+		if (! BAW_WITHIN(tap->txa_start, tap->txa_wnd,
+		    SEQNO(bf->bf_state.bfs_seqno))) {
+			device_printf(sc->sc_dev,
+			    "%s: bf=%p, seqno=%d, outside?!\n",
+			    __func__, bf, SEQNO(bf->bf_state.bfs_seqno));
+			status = ATH_AGGR_BAW_CLOSED;
+			break;
+		}
+
+		/*
 		 * this packet is part of an aggregate.
 		 */
 		ATH_TXQ_REMOVE(tid, bf, bf_list);
Index: sys/dev/ath/if_ath_tx.c
===================================================================
--- sys/dev/ath/if_ath_tx.c	(revision 233089)
+++ sys/dev/ath/if_ath_tx.c	(working copy)
@@ -109,8 +109,6 @@
     int tid);
 static int ath_tx_ampdu_running(struct ath_softc *sc, struct ath_node *an,
     int tid);
-static ieee80211_seq ath_tx_tid_seqno_assign(struct ath_softc *sc,
-    struct ieee80211_node *ni, struct ath_buf *bf, struct mbuf *m0);
 static int ath_tx_action_frame_override_queue(struct ath_softc *sc,
     struct ieee80211_node *ni, struct mbuf *m0, int *tid);
 
@@ -1376,7 +1374,7 @@
 	int ismcast;
 	const struct ieee80211_frame *wh;
 	int is_ampdu, is_ampdu_tx, is_ampdu_pending;
-	ieee80211_seq seqno;
+	//ieee80211_seq seqno;
 	uint8_t type, subtype;
 
 	/*
@@ -1428,8 +1426,9 @@
 	is_ampdu_pending = ath_tx_ampdu_pending(sc, ATH_NODE(ni), tid);
 	is_ampdu = is_ampdu_tx | is_ampdu_pending;
 
-	DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: tid=%d, ac=%d, is_ampdu=%d\n",
-	    __func__, tid, pri, is_ampdu);
+	DPRINTF(sc, ATH_DEBUG_SW_TX,
+	    "%s: bf=%p, tid=%d, ac=%d, is_ampdu=%d\n",
+	    __func__, bf, tid, pri, is_ampdu);
 
 	/* Multicast frames go onto the software multicast queue */
 	if (ismcast)
@@ -1447,6 +1446,9 @@
 	/* Do the generic frame setup */
 	/* XXX should just bzero the bf_state? */
 	bf->bf_state.bfs_dobaw = 0;
+	bf->bf_state.bfs_seqno_assigned = 0;
+	bf->bf_state.bfs_need_seqno = 0;
+	bf->bf_state.bfs_seqno = -1;	/* XXX debugging */
 
 	/* A-MPDU TX? Manually set sequence number */
 	/* Don't do it whilst pending; the net80211 layer still assigns them */
@@ -1459,19 +1461,27 @@
 		 * don't get a sequence number from the current
 		 * TID and thus mess with the BAW.
 		 */
-		seqno = ath_tx_tid_seqno_assign(sc, ni, bf, m0);
+		//seqno = ath_tx_tid_seqno_assign(sc, ni, bf, m0);
 		if (IEEE80211_QOS_HAS_SEQ(wh) &&
 		    subtype != IEEE80211_FC0_SUBTYPE_QOS_NULL) {
 			bf->bf_state.bfs_dobaw = 1;
+			bf->bf_state.bfs_need_seqno = 1;
 		}
 		ATH_TXQ_UNLOCK(txq);
+	} else {
+		/* No AMPDU TX, we've been assigned a sequence number. */
+		if (IEEE80211_QOS_HAS_SEQ(wh)) {
+			bf->bf_state.bfs_seqno_assigned = 1;
+			bf->bf_state.bfs_seqno =
+			    M_SEQNO_GET(m0) << IEEE80211_SEQ_SEQ_SHIFT;
+		}
 	}
 
 	/*
 	 * If needed, the sequence number has been assigned.
 	 * Squirrel it away somewhere easy to get to.
 	 */
-	bf->bf_state.bfs_seqno = M_SEQNO_GET(m0) << IEEE80211_SEQ_SEQ_SHIFT;
+	//bf->bf_state.bfs_seqno = M_SEQNO_GET(m0) << IEEE80211_SEQ_SEQ_SHIFT;
 
 	/* Is ampdu pending? fetch the seqno and print it out */
 	if (is_ampdu_pending)
@@ -1488,6 +1498,10 @@
 	/* At this point m0 could have changed! */
 	m0 = bf->bf_m;
 
+	DPRINTF(sc, ATH_DEBUG_SW_TX,
+	    "%s: DONE: bf=%p, tid=%d, ac=%d, is_ampdu=%d, dobaw=%d, seqno=%d\n",
+	    __func__, bf, tid, pri, is_ampdu, bf->bf_state.bfs_dobaw, M_SEQNO_GET(m0));
+
 #if 1
 	/*
 	 * If it's a multicast frame, do a direct-dispatch to the
@@ -1506,6 +1520,8 @@
 	 * reached.)
 	 */
 	if (txq == &avp->av_mcastq) {
+		DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL,
+		    "%s: bf=%p: mcastq: TX'ing\n", __func__, bf);
 		ATH_TXQ_LOCK(txq);
 		ath_tx_xmit_normal(sc, txq, bf);
 		ATH_TXQ_UNLOCK(txq);
@@ -1518,6 +1534,8 @@
 		ATH_TXQ_UNLOCK(txq);
 	} else {
 		/* add to software queue */
+		DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL,
+		    "%s: bf=%p: swq: TX'ing\n", __func__, bf);
 		ath_tx_swq(sc, ni, txq, bf);
 	}
 #else
@@ -1966,26 +1984,51 @@
 	if (bf->bf_state.bfs_isretried)
 		return;
 
+	/*
+	 * If this occurs we're in a lot of trouble.  We should try to
+	 * recover from this without the session hanging?
+	 */
+	if (! bf->bf_state.bfs_seqno_assigned) {
+		device_printf(sc->sc_dev,
+		    "%s: bf=%p, seqno_assigned is 0?!\n", __func__, bf);
+		return;
+	}
+
 	tap = ath_tx_get_tx_tid(an, tid->tid);
 
 	if (bf->bf_state.bfs_addedbaw)
 		device_printf(sc->sc_dev,
-		    "%s: re-added? tid=%d, seqno %d; window %d:%d; "
+		    "%s: re-added? bf=%p, tid=%d, seqno %d; window %d:%d; "
 		    "baw head=%d tail=%d\n",
-		    __func__, tid->tid, SEQNO(bf->bf_state.bfs_seqno),
+		    __func__, bf, tid->tid, SEQNO(bf->bf_state.bfs_seqno),
 		    tap->txa_start, tap->txa_wnd, tid->baw_head,
 		    tid->baw_tail);
 
 	/*
+	 * Verify that the given sequence number is not outside of the
+	 * BAW.  Complain loudly if that's the case.
+	 */
+	if (! BAW_WITHIN(tap->txa_start, tap->txa_wnd,
+	    SEQNO(bf->bf_state.bfs_seqno))) {
+		device_printf(sc->sc_dev,
+		    "%s: bf=%p: outside of BAW?? tid=%d, seqno %d; window %d:%d; "
+		    "baw head=%d tail=%d\n",
+		    __func__, bf, tid->tid, SEQNO(bf->bf_state.bfs_seqno),
+		    tap->txa_start, tap->txa_wnd, tid->baw_head,
+		    tid->baw_tail);
+
+	}
+
+	/*
 	 * ni->ni_txseqs[] is the currently allocated seqno.
 	 * the txa state contains the current baw start.
 	 */
 	index  = ATH_BA_INDEX(tap->txa_start, SEQNO(bf->bf_state.bfs_seqno));
 	cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
 	DPRINTF(sc, ATH_DEBUG_SW_TX_BAW,
-	    "%s: tid=%d, seqno %d; window %d:%d; index=%d cindex=%d "
+	    "%s: bf=%p, tid=%d, seqno %d; window %d:%d; index=%d cindex=%d "
 	    "baw head=%d tail=%d\n",
-	    __func__, tid->tid, SEQNO(bf->bf_state.bfs_seqno),
+	    __func__, bf, tid->tid, SEQNO(bf->bf_state.bfs_seqno),
 	    tap->txa_start, tap->txa_wnd, index, cindex, tid->baw_head,
 	    tid->baw_tail);
 
@@ -2088,9 +2131,9 @@
 	cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
 
 	DPRINTF(sc, ATH_DEBUG_SW_TX_BAW,
-	    "%s: tid=%d, baw=%d:%d, seqno=%d, index=%d, cindex=%d, "
+	    "%s: bf=%p: tid=%d, baw=%d:%d, seqno=%d, index=%d, cindex=%d, "
 	    "baw head=%d, tail=%d\n",
-	    __func__, tid->tid, tap->txa_start, tap->txa_wnd, seqno, index,
+	    __func__, bf, tid->tid, tap->txa_start, tap->txa_wnd, seqno, index,
 	    cindex, tid->baw_head, tid->baw_tail);
 
 	/*
@@ -2171,11 +2214,42 @@
 }
 
 /*
+ * Return whether a sequence number is actually required.
+ *
+ * A sequence number must only be allocated at the time that a frame
+ * is considered for addition to the BAW/aggregate and being TXed.
+ * The sequence number must not be allocated before the frame
+ * is added to the BAW (protected by the same lock instance)
+ * otherwise a the multi-entrant TX path may result in a later seqno
+ * being added to the BAW first.  The subsequent addition of the
+ * earlier seqno would then not go into the BAW as it's now outside
+ * of said BAW.
+ *
+ * This routine is used by ath_tx_start() to mark whether the frame
+ * should get a sequence number before adding it to the BAW.
+ *
+ * Then the actual aggregate TX routines will check whether this
+ * flag is set and if the frame needs to go into the BAW, it'll
+ * have a sequence number allocated for it.
+ */
+#if 0
+static int
+ath_tx_seqno_required(struct ath_softc *sc, struct ieee80211_node *ni,
+    struct ath_buf *bf, struct mbuf *m0)
+{
+}
+#endif
+
+/*
  * Assign a sequence number manually to the given frame.
  *
  * This should only be called for A-MPDU TX frames.
+ *
+ * If this is called after the initial frame setup, make sure you've flushed
+ * the DMA map or you'll risk sending stale data to the NIC.  This routine
+ * updates the actual frame contents with the relevant seqno.
  */
-static ieee80211_seq
+int
 ath_tx_tid_seqno_assign(struct ath_softc *sc, struct ieee80211_node *ni,
     struct ath_buf *bf, struct mbuf *m0)
 {
@@ -2188,9 +2262,23 @@
 	wh = mtod(m0, struct ieee80211_frame *);
 	pri = M_WME_GETAC(m0);			/* honor classification */
 	tid = WME_AC_TO_TID(pri);
-	DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: pri=%d, tid=%d, qos has seq=%d\n",
-	    __func__, pri, tid, IEEE80211_QOS_HAS_SEQ(wh));
+	DPRINTF(sc, ATH_DEBUG_SW_TX,
+	    "%s: bf=%p, pri=%d, tid=%d, qos has seq=%d\n",
+	    __func__, bf, pri, tid, IEEE80211_QOS_HAS_SEQ(wh));
 
+	if (! bf->bf_state.bfs_need_seqno) {
+		device_printf(sc->sc_dev, "%s: bf=%p: need_seqno not set?!\n",
+		    __func__, bf);
+		return -1;
+	}
+	/* XXX check for bfs_need_seqno? */
+	if (bf->bf_state.bfs_seqno_assigned) {
+		device_printf(sc->sc_dev,
+		    "%s: bf=%p: seqno already assigned (%d)?!\n",
+		    __func__, bf, SEQNO(bf->bf_state.bfs_seqno));
+		return bf->bf_state.bfs_seqno >> IEEE80211_SEQ_SEQ_SHIFT;
+	}
+
 	/* XXX Is it a control frame? Ignore */
 
 	/* Does the packet require a sequence number? */
@@ -2217,9 +2305,14 @@
 	}
 	*(uint16_t *)&wh->i_seq[0] = htole16(seqno << IEEE80211_SEQ_SEQ_SHIFT);
 	M_SEQNO_SET(m0, seqno);
+	bf->bf_state.bfs_seqno = seqno << IEEE80211_SEQ_SEQ_SHIFT;
+	bf->bf_state.bfs_seqno_assigned = 1;
 
 	/* Return so caller can do something with it if needed */
-	DPRINTF(sc, ATH_DEBUG_SW_TX, "%s:  -> seqno=%d\n", __func__, seqno);
+	DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: bf=%p:  -> seqno=%d\n",
+	    __func__,
+	    bf,
+	    seqno);
 	return seqno;
 }
 
@@ -2231,9 +2324,11 @@
 static void
 ath_tx_xmit_aggr(struct ath_softc *sc, struct ath_node *an, struct ath_buf *bf)
 {
+	struct ieee80211_node *ni = &an->an_node;
 	struct ath_tid *tid = &an->an_tid[bf->bf_state.bfs_tid];
 	struct ath_txq *txq = bf->bf_state.bfs_txq;
 	struct ieee80211_tx_ampdu *tap;
+	int seqno;
 
 	ATH_TXQ_LOCK_ASSERT(txq);
 
@@ -2245,10 +2340,63 @@
 		return;
 	}
 
+	/*
+	 * TODO: If it's _before_ the BAW left edge, complain very loudly.
+	 * This means something (else) has slid the left edge along
+	 * before we got a chance to be TXed.
+	 */
+
+	/*
+	 * Is there space in this BAW for another frame?
+	 * If not, don't bother trying to schedule it; just
+	 * throw it back on the queue.
+	 *
+	 * If we allocate the sequence number before we add
+	 * it to the BAW, we risk racing with another TX
+	 * thread that gets in a frame into the BAW with
+	 * seqno greater than ours.  We'd then fail the
+	 * below check and throw the frame on the tail of
+	 * the queue.  The sender would then have a hole.
+	 *
+	 * XXX again, we're protecting ni->ni_txseqs[tid]
+	 * behind this hardware TXQ lock, like the rest of
+	 * the TIDs that map to it.  Ugh.
+	 */
+	if (bf->bf_state.bfs_dobaw) {
+		if (! BAW_WITHIN(tap->txa_start, tap->txa_wnd,
+		    ni->ni_txseqs[bf->bf_state.bfs_tid])) {
+			ATH_TXQ_INSERT_TAIL(tid, bf, bf_list);
+			ath_tx_tid_sched(sc, tid);
+			return;
+		}
+		if (! bf->bf_state.bfs_seqno_assigned) {
+			seqno = ath_tx_tid_seqno_assign(sc, ni, bf, bf->bf_m);
+			if (seqno < 0) {
+				device_printf(sc->sc_dev,
+				    "%s: bf=%p, huh, seqno=-1?\n",
+				    __func__,
+				    bf);
+				/* XXX what can we even do here? */
+			}
+			/* Flush seqno update to RAM */
+			/*
+			 * XXX This is required because the dmasetup
+			 * XXX is done early rather than at dispatch
+			 * XXX time. Ew, we should fix this!
+			 */
+			bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap,
+			    BUS_DMASYNC_PREWRITE);
+		}
+	}
+
 	/* outside baw? queue */
 	if (bf->bf_state.bfs_dobaw &&
 	    (! BAW_WITHIN(tap->txa_start, tap->txa_wnd,
 	    SEQNO(bf->bf_state.bfs_seqno)))) {
+		device_printf(sc->sc_dev,
+		    "%s: bf=%p, shouldn't be outside BAW now?!\n",
+		    __func__,
+		    bf);
 		ATH_TXQ_INSERT_TAIL(tid, bf, bf_list);
 		ath_tx_tid_sched(sc, tid);
 		return;
@@ -2303,8 +2451,8 @@
 	tid = ath_tx_gettid(sc, m0);
 	atid = &an->an_tid[tid];
 
-	DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: bf=%p, pri=%d, tid=%d, qos=%d\n",
-	    __func__, bf, pri, tid, IEEE80211_QOS_HAS_SEQ(wh));
+	DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: bf=%p, pri=%d, tid=%d, qos=%d, seqno=%d\n",
+	    __func__, bf, pri, tid, IEEE80211_QOS_HAS_SEQ(wh), SEQNO(bf->bf_state.bfs_seqno));
 
 	/* Set local packet state, used to queue packets to hardware */
 	bf->bf_state.bfs_tid = tid;
@@ -2320,34 +2468,34 @@
 	ATH_TXQ_LOCK(txq);
 	if (atid->paused) {
 		/* TID is paused, queue */
-		DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: paused\n", __func__);
+		DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: bf=%p: paused\n", __func__, bf);
 		ATH_TXQ_INSERT_TAIL(atid, bf, bf_list);
 	} else if (ath_tx_ampdu_pending(sc, an, tid)) {
 		/* AMPDU pending; queue */
-		DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: pending\n", __func__);
+		DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: bf=%p: pending\n", __func__, bf);
 		ATH_TXQ_INSERT_TAIL(atid, bf, bf_list);
 		/* XXX sched? */
 	} else if (ath_tx_ampdu_running(sc, an, tid)) {
 		/* AMPDU running, attempt direct dispatch if possible */
 		if (txq->axq_depth < sc->sc_hwq_limit) {
+			DPRINTF(sc, ATH_DEBUG_SW_TX,
+			    "%s: bf=%p: xmit_aggr\n",
+			    __func__, bf);
 			ath_tx_xmit_aggr(sc, an, bf);
-			DPRINTF(sc, ATH_DEBUG_SW_TX,
-			    "%s: xmit_aggr\n",
-			    __func__);
 		} else {
 			DPRINTF(sc, ATH_DEBUG_SW_TX,
-			    "%s: ampdu; swq'ing\n",
-			    __func__);
+			    "%s: bf=%p: ampdu; swq'ing\n",
+			    __func__, bf);
 			ATH_TXQ_INSERT_TAIL(atid, bf, bf_list);
 			ath_tx_tid_sched(sc, atid);
 		}
 	} else if (txq->axq_depth < sc->sc_hwq_limit) {
 		/* AMPDU not running, attempt direct dispatch */
-		DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: xmit_normal\n", __func__);
+		DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: bf=%p: xmit_normal\n", __func__, bf);
 		ath_tx_xmit_normal(sc, txq, bf);
 	} else {
 		/* Busy; queue */
-		DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: swq'ing\n", __func__);
+		DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: bf=%p: swq'ing\n", __func__, bf);
 		ATH_TXQ_INSERT_TAIL(atid, bf, bf_list);
 		ath_tx_tid_sched(sc, atid);
 	}
@@ -2478,11 +2626,11 @@
 
 		if (t == 0) {
 			device_printf(sc->sc_dev,
-			    "%s: node %p: tid %d: txq_depth=%d, "
+			    "%s: node %p: bf=%p: tid %d: txq_depth=%d, "
 			    "txq_aggr_depth=%d, sched=%d, paused=%d, "
 			    "hwq_depth=%d, incomp=%d, baw_head=%d, "
 			    "baw_tail=%d txa_start=%d, ni_txseqs=%d\n",
-			     __func__, ni, tid->tid, txq->axq_depth,
+			     __func__, ni, bf, tid->tid, txq->axq_depth,
 			     txq->axq_aggr_depth, tid->sched, tid->paused,
 			     tid->hwq_depth, tid->incomp, tid->baw_head,
 			     tid->baw_tail, tap == NULL ? -1 : tap->txa_start,
@@ -2493,7 +2641,7 @@
 			    mtod(bf->bf_m, const uint8_t *),
 			    bf->bf_m->m_len, 0, -1);
 
-			t = 1;
+			//t = 1;
 		}
 
 
Index: sys/dev/ath/if_ath_tx.h
===================================================================
--- sys/dev/ath/if_ath_tx.h	(revision 233089)
+++ sys/dev/ath/if_ath_tx.h	(working copy)
@@ -109,6 +109,8 @@
     struct ath_tid *tid, struct ath_buf *bf);
 extern struct ieee80211_tx_ampdu * ath_tx_get_tx_tid(struct ath_node *an,
     int tid);
+extern int ath_tx_tid_seqno_assign(struct ath_softc *sc,
+    struct ieee80211_node *ni, struct ath_buf *bf, struct mbuf *m0);
 
 /* TX addba handling */
 extern	int ath_addba_request(struct ieee80211_node *ni,
help

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAJ-Vmom6TDaRORRQ=w5h8RhVi1OBRL14jqjvMokyf2M83Q4Wrw>