diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 05034a6d1be3..055416881dc6 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -1706,7 +1706,7 @@ ath_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, * available because we checked above. */ avp->av_bcbuf = TAILQ_FIRST(&sc->sc_bbuf); - TAILQ_REMOVE(&sc->sc_bbuf, avp->av_bcbuf, bf_list); + ATH_BUF_TAILQ_REMOVE(&sc->sc_bbuf, avp->av_bcbuf, bf_list); if (opmode != IEEE80211_M_IBSS || !sc->sc_hasveol) { /* * Assign the vap to a beacon xmit slot. As above @@ -3181,9 +3181,9 @@ _ath_getbuf_locked(struct ath_softc *sc, ath_buf_type_t btype) if (bf != NULL && (bf->bf_flags & ATH_BUF_BUSY) == 0) { if (btype == ATH_BUFTYPE_MGMT) - TAILQ_REMOVE(&sc->sc_txbuf_mgmt, bf, bf_list); + ATH_BUF_TAILQ_REMOVE(&sc->sc_txbuf_mgmt, bf, bf_list); else { - TAILQ_REMOVE(&sc->sc_txbuf, bf, bf_list); + ATH_BUF_TAILQ_REMOVE(&sc->sc_txbuf, bf, bf_list); sc->sc_txbuf_cnt--; /* @@ -3221,6 +3221,9 @@ _ath_getbuf_locked(struct ath_softc *sc, ath_buf_type_t btype) bf->bf_next = NULL; /* XXX just to be sure */ bf->bf_last = NULL; /* XXX again, just to be sure */ bf->bf_comp = NULL; /* XXX again, just to be sure */ + bf->bf_getbuf_file = NULL; bf->bf_getbuf_line = 0; + bf->bf_tracebuf_file = NULL; bf->bf_tracebuf_line = 0; + bf->bf_add_file = NULL; bf->bf_add_line = 0; bzero(&bf->bf_state, sizeof(bf->bf_state)); /* @@ -3258,6 +3261,7 @@ ath_buf_clone(struct ath_softc *sc, struct ath_buf *bf) ATH_BUFTYPE_MGMT : ATH_BUFTYPE_NORMAL); if (tbf == NULL) return NULL; /* XXX failure? Why? */ + ATH_BUF_SET_GETBUF(tbf); /* Copy basics */ tbf->bf_next = NULL; @@ -3265,6 +3269,7 @@ ath_buf_clone(struct ath_softc *sc, struct ath_buf *bf) tbf->bf_flags = bf->bf_flags & ATH_BUF_FLAGS_CLONE; tbf->bf_status = bf->bf_status; tbf->bf_m = bf->bf_m; + ATH_BUF_SET_TRACEBUF(tbf); tbf->bf_node = bf->bf_node; KASSERT((bf->bf_node != NULL), ("%s: bf_node=NULL!", __func__)); /* will be setup by the chain/setup function */ @@ -3293,10 +3298,14 @@ ath_buf_clone(struct ath_softc *sc, struct ath_buf *bf) bf->bf_m = NULL; bf->bf_node = NULL; + ATH_BUF_SET_TRACEBUF(bf); /* Copy state */ memcpy(&tbf->bf_state, &bf->bf_state, sizeof(bf->bf_state)); + /* Mark this buffer as having been cloned for debugging */ + bf->bf_flags |= ATH_BUF_WAS_CLONED; + return tbf; } @@ -3438,6 +3447,7 @@ ath_transmit(struct ieee80211com *ic, struct mbuf *m) retval = ENOBUFS; goto finish; } + ATH_BUF_SET_GETBUF(bf); /* * At this point we have a buffer; so we need to free it @@ -3490,6 +3500,8 @@ ath_transmit(struct ieee80211com *ic, struct mbuf *m) struct ath_buf *fbf = bf; struct ath_buf *n_fbf = NULL; struct mbuf *fm = m->m_nextpkt; + bf->bf_flags |= ATH_BUF_WAS_FRAG; + ATH_BUF_SET_TRACEBUF(bf); /* * We need to walk the list of fragments and set @@ -3530,6 +3542,7 @@ ath_transmit(struct ieee80211com *ic, struct mbuf *m) reclaim: bf->bf_m = NULL; bf->bf_node = NULL; + ATH_BUF_SET_TRACEBUF(bf); ATH_TXBUF_LOCK(sc); ath_returnbuf_head(sc, bf); /* @@ -3570,8 +3583,9 @@ ath_transmit(struct ieee80211com *ic, struct mbuf *m) } m = next; bf = TAILQ_FIRST(&frags); + ATH_BUF_SET_TRACEBUF(bf); KASSERT(bf != NULL, ("no buf for txfrag")); - TAILQ_REMOVE(&frags, bf, bf_list); + ATH_BUF_TAILQ_REMOVE(&frags, bf, bf_list); goto nextfrag; } @@ -4795,9 +4809,9 @@ ath_returnbuf_tail(struct ath_softc *sc, struct ath_buf *bf) ATH_TXBUF_LOCK_ASSERT(sc); if (bf->bf_flags & ATH_BUF_MGMT) - TAILQ_INSERT_TAIL(&sc->sc_txbuf_mgmt, bf, bf_list); + ATH_BUF_TAILQ_INSERT_TAIL(&sc->sc_txbuf_mgmt, bf, bf_list); else { - TAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list); + ATH_BUF_TAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list); sc->sc_txbuf_cnt++; if (sc->sc_txbuf_cnt > ath_txbuf) { device_printf(sc->sc_dev, @@ -4816,9 +4830,9 @@ ath_returnbuf_head(struct ath_softc *sc, struct ath_buf *bf) ATH_TXBUF_LOCK_ASSERT(sc); if (bf->bf_flags & ATH_BUF_MGMT) - TAILQ_INSERT_HEAD(&sc->sc_txbuf_mgmt, bf, bf_list); + ATH_BUF_TAILQ_INSERT_HEAD(&sc->sc_txbuf_mgmt, bf, bf_list); else { - TAILQ_INSERT_HEAD(&sc->sc_txbuf, bf, bf_list); + ATH_BUF_TAILQ_INSERT_HEAD(&sc->sc_txbuf, bf, bf_list); sc->sc_txbuf_cnt++; if (sc->sc_txbuf_cnt > ATH_TXBUF) { device_printf(sc->sc_dev, @@ -4951,6 +4965,7 @@ ath_tx_freebuf(struct ath_softc *sc, struct ath_buf *bf, int status) bf->bf_node = NULL; bf->bf_m = NULL; + ATH_BUF_SET_TRACEBUF(bf); /* Free the buffer, it's not needed any longer */ ath_freebuf(sc, bf); diff --git a/sys/dev/ath/if_ath_beacon.c b/sys/dev/ath/if_ath_beacon.c index 15a32806841d..9bd65bd48778 100644 --- a/sys/dev/ath/if_ath_beacon.c +++ b/sys/dev/ath/if_ath_beacon.c @@ -894,7 +894,7 @@ ath_beacon_return(struct ath_softc *sc, struct ath_buf *bf) ieee80211_free_node(bf->bf_node); bf->bf_node = NULL; } - TAILQ_INSERT_TAIL(&sc->sc_bbuf, bf, bf_list); + ATH_BUF_TAILQ_INSERT_TAIL(&sc->sc_bbuf, bf, bf_list); } /* diff --git a/sys/dev/ath/if_ath_descdma.c b/sys/dev/ath/if_ath_descdma.c index 5066b79dd6c5..57278d456592 100644 --- a/sys/dev/ath/if_ath_descdma.c +++ b/sys/dev/ath/if_ath_descdma.c @@ -295,7 +295,7 @@ ath_descdma_setup(struct ath_softc *sc, return error; } bf->bf_lastds = bf->bf_desc; /* Just an initial value */ - TAILQ_INSERT_TAIL(head, bf, bf_list); + ATH_BUF_TAILQ_INSERT_TAIL(head, bf, bf_list); } /* @@ -371,7 +371,7 @@ ath_descdma_setup_rx_edma(struct ath_softc *sc, ath_descdma_cleanup(sc, dd, head); return error; } - TAILQ_INSERT_TAIL(head, bf, bf_list); + ATH_BUF_TAILQ_INSERT_TAIL(head, bf, bf_list); } return 0; fail3: diff --git a/sys/dev/ath/if_ath_rx.c b/sys/dev/ath/if_ath_rx.c index cd22d9c683dc..88fe91569348 100644 --- a/sys/dev/ath/if_ath_rx.c +++ b/sys/dev/ath/if_ath_rx.c @@ -1136,7 +1136,7 @@ ath_rx_proc(struct ath_softc *sc, int resched) */ /* XXX make debug msg */ device_printf(sc->sc_dev, "%s: no mbuf!\n", __func__); - TAILQ_REMOVE(&sc->sc_rxbuf, bf, bf_list); + ATH_BUF_TAILQ_REMOVE(&sc->sc_rxbuf, bf, bf_list); goto rx_proc_next; } ds = bf->bf_desc; @@ -1174,7 +1174,7 @@ ath_rx_proc(struct ath_softc *sc, int resched) if (status == HAL_EINPROGRESS) break; - TAILQ_REMOVE(&sc->sc_rxbuf, bf, bf_list); + ATH_BUF_TAILQ_REMOVE(&sc->sc_rxbuf, bf, bf_list); npkts++; /* @@ -1193,7 +1193,7 @@ ath_rx_proc(struct ath_softc *sc, int resched) */ ret = 0; if (sc->sc_rxedma[HAL_RX_QUEUE_HP].m_holdbf != NULL) { - TAILQ_INSERT_TAIL(&sc->sc_rxbuf, + ATH_BUF_TAILQ_INSERT_TAIL(&sc->sc_rxbuf, sc->sc_rxedma[HAL_RX_QUEUE_HP].m_holdbf, bf_list); ret = ath_rxbuf_init(sc, @@ -1363,7 +1363,7 @@ ath_legacy_flush_rxholdbf(struct ath_softc *sc) if (bf->bf_m != NULL) m_freem(bf->bf_m); bf->bf_m = NULL; - TAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list); + ATH_BUF_TAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list); (void) ath_rxbuf_init(sc, bf); } sc->sc_rxedma[HAL_RX_QUEUE_HP].m_holdbf = NULL; @@ -1373,7 +1373,7 @@ ath_legacy_flush_rxholdbf(struct ath_softc *sc) if (bf->bf_m != NULL) m_freem(bf->bf_m); bf->bf_m = NULL; - TAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list); + ATH_BUF_TAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list); (void) ath_rxbuf_init(sc, bf); } sc->sc_rxedma[HAL_RX_QUEUE_LP].m_holdbf = NULL; diff --git a/sys/dev/ath/if_ath_rx_edma.c b/sys/dev/ath/if_ath_rx_edma.c index fb25fb77b062..ef691850e264 100644 --- a/sys/dev/ath/if_ath_rx_edma.c +++ b/sys/dev/ath/if_ath_rx_edma.c @@ -492,7 +492,7 @@ ath_edma_recv_proc_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype, * queue. */ re->m_fifo[re->m_fifo_head] = NULL; - TAILQ_INSERT_TAIL(&sc->sc_rx_rxlist[qtype], bf, bf_list); + ATH_BUF_TAILQ_INSERT_TAIL(&sc->sc_rx_rxlist[qtype], bf, bf_list); /* Bump the descriptor FIFO stats */ INCR(re->m_fifo_head, re->m_fifolen); @@ -532,13 +532,13 @@ ath_edma_flush_deferred_queue(struct ath_softc *sc) /* Free in one set, inside the lock */ while (! TAILQ_EMPTY(&sc->sc_rx_rxlist[HAL_RX_QUEUE_LP])) { bf = TAILQ_FIRST(&sc->sc_rx_rxlist[HAL_RX_QUEUE_LP]); - TAILQ_REMOVE(&sc->sc_rx_rxlist[HAL_RX_QUEUE_LP], bf, bf_list); + ATH_BUF_TAILQ_REMOVE(&sc->sc_rx_rxlist[HAL_RX_QUEUE_LP], bf, bf_list); /* Free the buffer/mbuf */ ath_edma_rxbuf_free(sc, bf); } while (! TAILQ_EMPTY(&sc->sc_rx_rxlist[HAL_RX_QUEUE_HP])) { bf = TAILQ_FIRST(&sc->sc_rx_rxlist[HAL_RX_QUEUE_HP]); - TAILQ_REMOVE(&sc->sc_rx_rxlist[HAL_RX_QUEUE_HP], bf, bf_list); + ATH_BUF_TAILQ_REMOVE(&sc->sc_rx_rxlist[HAL_RX_QUEUE_HP], bf, bf_list); /* Free the buffer/mbuf */ ath_edma_rxbuf_free(sc, bf); } @@ -603,7 +603,7 @@ ath_edma_recv_proc_deferred_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype, ATH_RX_LOCK(sc); while (! TAILQ_EMPTY(&rxlist)) { bf = TAILQ_FIRST(&rxlist); - TAILQ_REMOVE(&rxlist, bf, bf_list); + ATH_BUF_TAILQ_REMOVE(&rxlist, bf, bf_list); /* Free the buffer/mbuf */ ath_edma_rxbuf_free(sc, bf); } @@ -768,7 +768,7 @@ ath_edma_rxbuf_alloc(struct ath_softc *sc) } /* Remove it from the free list */ - TAILQ_REMOVE(&sc->sc_rxbuf, bf, bf_list); + ATH_BUF_TAILQ_REMOVE(&sc->sc_rxbuf, bf, bf_list); /* Assign RX mbuf to it */ error = ath_edma_rxbuf_init(sc, bf); @@ -778,7 +778,7 @@ ath_edma_rxbuf_alloc(struct ath_softc *sc) __func__, bf, error); - TAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list); + ATH_BUF_TAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list); return (NULL); } @@ -802,7 +802,7 @@ ath_edma_rxbuf_free(struct ath_softc *sc, struct ath_buf *bf) } /* XXX lock? */ - TAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list); + ATH_BUF_TAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list); } /* diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c index 1559b66a7c7d..6ac127904af4 100644 --- a/sys/dev/ath/if_ath_tx.c +++ b/sys/dev/ath/if_ath_tx.c @@ -260,7 +260,7 @@ ath_txfrag_cleanup(struct ath_softc *sc, TAILQ_FOREACH_SAFE(bf, frags, bf_list, next) { /* NB: bf assumed clean */ - TAILQ_REMOVE(frags, bf, bf_list); + ATH_BUF_TAILQ_REMOVE(frags, bf, bf_list); ath_returnbuf_head(sc, bf); ieee80211_node_decref(ni); } @@ -288,8 +288,10 @@ ath_txfrag_setup(struct ath_softc *sc, ath_bufhead *frags, ath_txfrag_cleanup(sc, frags, ni); break; } + ATH_BUF_SET_GETBUF(bf); (void) ieee80211_ref_node(ni); - TAILQ_INSERT_TAIL(frags, bf, bf_list); + ATH_BUF_TAILQ_INSERT_TAIL(frags, bf, bf_list); + bf->bf_flags |= ATH_BUF_WAS_FRAG; } ATH_TXBUF_UNLOCK(sc); @@ -302,6 +304,8 @@ ath_tx_dmasetup(struct ath_softc *sc, struct ath_buf *bf, struct mbuf *m0) struct mbuf *m; int error; + ATH_BUF_SET_TRACEBUF(bf); + /* * Load the DMA map so any coalescing is done. This * also calculates the number of descriptors we need. @@ -314,6 +318,7 @@ ath_tx_dmasetup(struct ath_softc *sc, struct ath_buf *bf, struct mbuf *m0) bf->bf_nseg = ATH_MAX_SCATTER + 1; } else if (error != 0) { sc->sc_stats.ast_tx_busdma++; + ATH_BUF_SET_TRACEBUF(bf); ieee80211_free_mbuf(m0); return error; } @@ -327,6 +332,7 @@ ath_tx_dmasetup(struct ath_softc *sc, struct ath_buf *bf, struct mbuf *m0) m = m_collapse(m0, M_NOWAIT, ATH_MAX_SCATTER); if (m == NULL) { ieee80211_free_mbuf(m0); + ATH_BUF_SET_TRACEBUF(bf); sc->sc_stats.ast_tx_nombuf++; return ENOMEM; } @@ -337,6 +343,7 @@ ath_tx_dmasetup(struct ath_softc *sc, struct ath_buf *bf, struct mbuf *m0) if (error != 0) { sc->sc_stats.ast_tx_busdma++; ieee80211_free_mbuf(m0); + ATH_BUF_SET_TRACEBUF(bf); return error; } KASSERT(bf->bf_nseg <= ATH_MAX_SCATTER, @@ -344,12 +351,14 @@ ath_tx_dmasetup(struct ath_softc *sc, struct ath_buf *bf, struct mbuf *m0) } else if (bf->bf_nseg == 0) { /* null packet, discard */ sc->sc_stats.ast_tx_nodata++; ieee80211_free_mbuf(m0); + ATH_BUF_SET_TRACEBUF(bf); return EIO; } DPRINTF(sc, ATH_DEBUG_XMIT, "%s: m %p len %u\n", __func__, m0, m0->m_pkthdr.len); bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, BUS_DMASYNC_PREWRITE); bf->bf_m = m0; + ATH_BUF_SET_TRACEBUF(bf); return 0; } @@ -1507,6 +1516,8 @@ ath_tx_xmit_normal(struct ath_softc *sc, struct ath_txq *txq, ATH_TX_LOCK_ASSERT(sc); + ATH_BUF_SET_TRACEBUF(bf); + /* * For now, just enable CLRDMASK. ath_tx_xmit_normal() does * set a completion handler however it doesn't (yet) properly @@ -1577,6 +1588,8 @@ ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni, */ ATH_TX_LOCK_ASSERT(sc); + ATH_BUF_SET_TRACEBUF(bf); + wh = mtod(m0, struct ieee80211_frame *); iswep = wh->i_fc[1] & IEEE80211_FC1_PROTECTED; ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); @@ -1591,6 +1604,7 @@ ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni, /* Handle encryption twiddling if needed */ if (! ath_tx_tag_crypto(sc, ni, m0, iswep, isfrag, &hdrlen, &pktlen, &keyix)) { + ATH_BUF_SET_TRACEBUF(bf); ieee80211_free_mbuf(m0); return EIO; } @@ -1708,6 +1722,7 @@ ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni, wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__); /* XXX statistic */ /* XXX free tx dmamap */ + ATH_BUF_SET_TRACEBUF(bf); ieee80211_free_mbuf(m0); return EIO; } @@ -1764,6 +1779,7 @@ ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni, "%s: discard frame, ACK required w/ TDMA\n", __func__); sc->sc_stats.ast_tdma_ack++; /* XXX free tx dmamap */ + ATH_BUF_SET_TRACEBUF(bf); ieee80211_free_mbuf(m0); return EIO; } @@ -1806,6 +1822,8 @@ ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni, flags |= HAL_TXDESC_HWTS; #endif + ATH_BUF_SET_TRACEBUF(bf); + /* * Determine if a tx interrupt should be generated for * this descriptor. We take a tx interrupt to reap @@ -1883,6 +1901,8 @@ ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni, bf->bf_state.bfs_ctsduration = 0; bf->bf_state.bfs_ismrr = ismrr; + ATH_BUF_SET_TRACEBUF(bf); + return 0; } @@ -1916,6 +1936,8 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, ATH_TX_LOCK_ASSERT(sc); + ATH_BUF_SET_TRACEBUF(bf); + /* * Determine the target hardware queue. * @@ -1958,6 +1980,7 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { if (sc->sc_cabq->axq_depth + sc->sc_cabq->fifo.axq_depth > sc->sc_txq_mcastq_maxdepth) { + ATH_BUF_SET_TRACEBUF(bf); sc->sc_stats.ast_tx_mcastq_overflow++; m_freem(m0); return (ENOBUFS); @@ -1986,6 +2009,7 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, ATH_NODE(ni)->an_swq_depth > sc->sc_txq_node_psq_maxdepth) { sc->sc_stats.ast_tx_node_psq_overflow++; + ATH_BUF_SET_TRACEBUF(bf); m_freem(m0); return (ENOBUFS); } @@ -2003,6 +2027,8 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, bf->bf_state.bfs_tx_queue = txq->axq_qnum; bf->bf_state.bfs_pri = pri; + ATH_BUF_SET_TRACEBUF(bf); + #if 1 /* * When servicing one or more stations in power-save mode @@ -2068,10 +2094,10 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, __func__, tid, M_SEQNO_GET(m0)); /* This also sets up the DMA map; crypto; frame parameters, etc */ + ATH_BUF_SET_TRACEBUF(bf); r = ath_tx_normal_setup(sc, ni, bf, m0, txq); - if (r != 0) - goto done; + return (r); /* At this point m0 could have changed! */ m0 = bf->bf_m; @@ -2109,8 +2135,10 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, ath_tx_xmit_normal(sc, txq, bf); } else if (ath_tx_should_swq_frame(sc, ATH_NODE(ni), m0, &queue_to_head)) { + ATH_BUF_SET_TRACEBUF(bf); ath_tx_swq(sc, ni, txq, queue_to_head, bf); } else { + ATH_BUF_SET_TRACEBUF(bf); bf->bf_state.bfs_txflags |= HAL_TXDESC_CLRDMASK; ath_tx_xmit_normal(sc, txq, bf); } @@ -2128,7 +2156,6 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, ath_tx_leak_count_update(sc, tid, bf); ath_tx_xmit_normal(sc, txq, bf); #endif -done: return 0; } @@ -2155,6 +2182,7 @@ ath_tx_raw_start(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_node *an = ATH_NODE(ni); ATH_TX_LOCK_ASSERT(sc); + ATH_BUF_SET_TRACEBUF(bf); wh = mtod(m0, struct ieee80211_frame *); ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); @@ -2477,6 +2505,7 @@ ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, error = ENOBUFS; goto bad; } + ATH_BUF_SET_GETBUF(bf); ATH_KTR(sc, ATH_KTR_TX, 3, "ath_raw_xmit: m=%p, params=%p, bf=%p\n", m, params, bf); @@ -3122,6 +3151,7 @@ ath_tx_swq(struct ath_softc *sc, struct ieee80211_node *ni, struct mbuf *m0 = bf->bf_m; ATH_TX_LOCK_ASSERT(sc); + ATH_BUF_SET_TRACEBUF(bf); /* Fetch the TID - non-QoS frames get assigned to TID 16 */ wh = mtod(m0, struct ieee80211_frame *); @@ -3148,6 +3178,7 @@ ath_tx_swq(struct ath_softc *sc, struct ieee80211_node *ni, * leak a single frame. */ if (! ath_tx_tid_can_tx_or_sched(sc, atid)) { + ATH_BUF_SET_TRACEBUF(bf); /* TID is paused, queue */ DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: paused\n", __func__); /* @@ -3159,11 +3190,13 @@ ath_tx_swq(struct ath_softc *sc, struct ieee80211_node *ni, else ATH_TID_INSERT_TAIL(atid, bf, bf_list); } else if (ath_tx_ampdu_pending(sc, an, tid)) { + ATH_BUF_SET_TRACEBUF(bf); /* AMPDU pending; queue */ DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: pending\n", __func__); ATH_TID_INSERT_TAIL(atid, bf, bf_list); /* XXX sched? */ } else if (ath_tx_ampdu_running(sc, an, tid)) { + ATH_BUF_SET_TRACEBUF(bf); /* * AMPDU running, queue single-frame if the hardware queue * isn't busy. @@ -3198,8 +3231,12 @@ ath_tx_swq(struct ath_softc *sc, struct ieee80211_node *ni, */ /* XXX TXQ locking */ if (txq->axq_depth + txq->fifo.axq_depth == 0) { + ATH_BUF_SET_TRACEBUF(bf); + + /* Note: bf changes here */ bf = ATH_TID_FIRST(atid); ATH_TID_REMOVE(atid, bf, bf_list); + ATH_BUF_SET_TRACEBUF(bf); /* * Ensure it's definitely treated as a non-AMPDU @@ -3219,6 +3256,7 @@ ath_tx_swq(struct ath_softc *sc, struct ieee80211_node *ni, "%s: ampdu; swq'ing\n", __func__); + ATH_BUF_SET_TRACEBUF(bf); ath_tx_tid_sched(sc, atid); } /* @@ -3238,6 +3276,7 @@ ath_tx_swq(struct ath_softc *sc, struct ieee80211_node *ni, } else if ((txq->axq_depth + txq->fifo.axq_depth < sc->sc_hwq_limit_nonaggr) && (txq->axq_aggr_depth < sc->sc_hwq_limit_aggr)) { /* AMPDU not running, attempt direct dispatch */ + ATH_BUF_SET_TRACEBUF(bf); DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: xmit_normal\n", __func__); /* See if clrdmask needs to be set */ ath_tx_update_clrdmask(sc, atid, bf); @@ -3255,6 +3294,7 @@ ath_tx_swq(struct ath_softc *sc, struct ieee80211_node *ni, ath_tx_xmit_normal(sc, txq, bf); } else { /* Busy; queue */ + ATH_BUF_SET_TRACEBUF(bf); DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: swq'ing\n", __func__); ATH_TID_INSERT_TAIL(atid, bf, bf_list); ath_tx_tid_sched(sc, atid); @@ -3572,7 +3612,7 @@ ath_tx_tid_filt_comp_aggr(struct ath_softc *sc, struct ath_tid *tid, tid->tid, bf, SEQNO(bf->bf_state.bfs_seqno)); - TAILQ_INSERT_TAIL(bf_q, bf, bf_list); + ATH_BUF_TAILQ_INSERT_TAIL(bf_q, bf, bf_list); goto next; } @@ -3593,7 +3633,7 @@ ath_tx_tid_filt_comp_aggr(struct ath_softc *sc, struct ath_tid *tid, DPRINTF(sc, ATH_DEBUG_SW_TX_FILT, "%s: tid=%d, buffer couldn't be cloned! (%p) seqno=%d\n", __func__, tid->tid, bf, SEQNO(bf->bf_state.bfs_seqno)); - TAILQ_INSERT_TAIL(bf_q, bf, bf_list); + ATH_BUF_TAILQ_INSERT_TAIL(bf_q, bf, bf_list); } else { ath_tx_tid_filt_comp_buf(sc, tid, nbf); } @@ -3819,7 +3859,7 @@ ath_tx_tid_drain_pkt(struct ath_softc *sc, struct ath_node *an, bf->bf_next = NULL; /* Insert on the free queue to be freed by the caller */ - TAILQ_INSERT_TAIL(bf_cq, bf, bf_list); + ATH_BUF_TAILQ_INSERT_TAIL(bf_cq, bf, bf_list); } static void @@ -4110,7 +4150,7 @@ ath_tx_node_flush(struct ath_softc *sc, struct ath_node *an) /* Handle completed frames */ while ((bf = TAILQ_FIRST(&bf_cq)) != NULL) { - TAILQ_REMOVE(&bf_cq, bf, bf_list); + ATH_BUF_TAILQ_REMOVE(&bf_cq, bf, bf_list); ath_tx_default_comp(sc, bf, 0); } } @@ -4141,7 +4181,7 @@ ath_tx_txq_drain(struct ath_softc *sc, struct ath_txq *txq) ATH_TX_UNLOCK(sc); while ((bf = TAILQ_FIRST(&bf_cq)) != NULL) { - TAILQ_REMOVE(&bf_cq, bf, bf_list); + ATH_BUF_TAILQ_REMOVE(&bf_cq, bf, bf_list); ath_tx_default_comp(sc, bf, 0); } } @@ -4332,7 +4372,7 @@ ath_tx_tid_cleanup_frame(struct ath_softc *sc, struct ath_node *an, /* * Add it to the list to free. */ - TAILQ_INSERT_TAIL(bf_cq, bf, bf_list); + ATH_BUF_TAILQ_INSERT_TAIL(bf_cq, bf, bf_list); /* * Now advance to the next frame in the aggregate. @@ -4640,7 +4680,7 @@ ath_tx_retry_subframe(struct ath_softc *sc, struct ath_buf *bf, bf->bf_state.bfs_ndelim = 0; /* ??? needed? */ bf->bf_state.bfs_nframes = 1; - TAILQ_INSERT_TAIL(bf_q, bf, bf_list); + ATH_BUF_TAILQ_INSERT_TAIL(bf_q, bf, bf_list); return 0; } @@ -4684,14 +4724,14 @@ ath_tx_comp_aggr_error(struct ath_softc *sc, struct ath_buf *bf_first, if (ath_tx_retry_subframe(sc, bf, &bf_q)) { drops++; bf->bf_next = NULL; - TAILQ_INSERT_TAIL(&bf_cq, bf, bf_list); + ATH_BUF_TAILQ_INSERT_TAIL(&bf_cq, bf, bf_list); } bf = bf_next; } /* Prepend all frames to the beginning of the queue */ while ((bf = TAILQ_LAST(&bf_q, ath_bufhead_s)) != NULL) { - TAILQ_REMOVE(&bf_q, bf, bf_list); + ATH_BUF_TAILQ_REMOVE(&bf_q, bf, bf_list); ATH_TID_INSERT_HEAD(tid, bf, bf_list); } @@ -4722,7 +4762,7 @@ ath_tx_comp_aggr_error(struct ath_softc *sc, struct ath_buf *bf_first, /* Complete frames which errored out */ while ((bf = TAILQ_FIRST(&bf_cq)) != NULL) { - TAILQ_REMOVE(&bf_cq, bf, bf_list); + ATH_BUF_TAILQ_REMOVE(&bf_cq, bf, bf_list); ath_tx_default_comp(sc, bf, 0); } } @@ -5038,13 +5078,13 @@ ath_tx_aggr_comp_aggr(struct ath_softc *sc, struct ath_buf *bf_first, "%s: wasn't added: seqno %d\n", __func__, SEQNO(bf->bf_state.bfs_seqno)); bf->bf_next = NULL; - TAILQ_INSERT_TAIL(&bf_cq, bf, bf_list); + ATH_BUF_TAILQ_INSERT_TAIL(&bf_cq, bf, bf_list); } else { sc->sc_stats.ast_tx_aggr_fail++; if (ath_tx_retry_subframe(sc, bf, &bf_q)) { drops++; bf->bf_next = NULL; - TAILQ_INSERT_TAIL(&bf_cq, bf, bf_list); + ATH_BUF_TAILQ_INSERT_TAIL(&bf_cq, bf, bf_list); } nbad++; } @@ -5093,7 +5133,7 @@ ath_tx_aggr_comp_aggr(struct ath_softc *sc, struct ath_buf *bf_first, /* Prepend all frames to the beginning of the queue */ while ((bf = TAILQ_LAST(&bf_q, ath_bufhead_s)) != NULL) { - TAILQ_REMOVE(&bf_q, bf, bf_list); + ATH_BUF_TAILQ_REMOVE(&bf_q, bf, bf_list); ATH_TID_INSERT_HEAD(atid, bf, bf_list); } @@ -5127,7 +5167,7 @@ ath_tx_aggr_comp_aggr(struct ath_softc *sc, struct ath_buf *bf_first, /* Do deferred completion */ while ((bf = TAILQ_FIRST(&bf_cq)) != NULL) { - TAILQ_REMOVE(&bf_cq, bf, bf_list); + ATH_BUF_TAILQ_REMOVE(&bf_cq, bf, bf_list); ath_tx_default_comp(sc, bf, 0); } } @@ -6083,7 +6123,7 @@ ath_addba_stop(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap) /* Handle completing frames and fail them */ while ((bf = TAILQ_FIRST(&bf_cq)) != NULL) { - TAILQ_REMOVE(&bf_cq, bf, bf_list); + ATH_BUF_TAILQ_REMOVE(&bf_cq, bf, bf_list); ath_tx_default_comp(sc, bf, 1); } @@ -6136,7 +6176,7 @@ ath_tx_node_reassoc(struct ath_softc *sc, struct ath_node *an) /* Handle completing frames and fail them */ while ((bf = TAILQ_FIRST(&bf_cq)) != NULL) { - TAILQ_REMOVE(&bf_cq, bf, bf_list); + ATH_BUF_TAILQ_REMOVE(&bf_cq, bf, bf_list); ath_tx_default_comp(sc, bf, 1); } } diff --git a/sys/dev/ath/if_ath_tx_edma.c b/sys/dev/ath/if_ath_tx_edma.c index 86977b7a1df2..f203420cc4b9 100644 --- a/sys/dev/ath/if_ath_tx_edma.c +++ b/sys/dev/ath/if_ath_tx_edma.c @@ -209,7 +209,7 @@ ath_tx_edma_push_staging_list(struct ath_softc *sc, struct ath_txq *txq, ATH_TXQ_REMOVE(txq, bf, bf_list); /* Queue it into our staging list */ - TAILQ_INSERT_TAIL(&sq, bf, bf_list); + ATH_BUF_TAILQ_INSERT_TAIL(&sq, bf, bf_list); /* Ensure the flags are cleared */ bf->bf_flags &= ~(ATH_BUF_FIFOPTR | ATH_BUF_FIFOEND); diff --git a/sys/dev/ath/if_ath_tx_ht.c b/sys/dev/ath/if_ath_tx_ht.c index e7ee029fecf0..472a290f001e 100644 --- a/sys/dev/ath/if_ath_tx_ht.c +++ b/sys/dev/ath/if_ath_tx_ht.c @@ -946,7 +946,7 @@ ath_tx_form_aggr(struct ath_softc *sc, struct ath_node *an, * on the software TXQ any longer) to our * aggregate frame list. */ - TAILQ_INSERT_TAIL(bf_q, bf, bf_list); + ATH_BUF_TAILQ_INSERT_TAIL(bf_q, bf, bf_list); nframes ++; /* Completion handler */ diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h index 96c4318d5987..105b84d8c1b6 100644 --- a/sys/dev/ath/if_athvar.h +++ b/sys/dev/ath/if_athvar.h @@ -310,6 +310,16 @@ struct ath_buf { int32_t bfs_rc_maxpktlen; /* max packet length/bucket from ratectrl or -1 */ struct ath_rc_series bfs_rc[ATH_RC_NUM]; /* non-11n TX series */ } bf_state; + + /* Debugging for tracking where buffers were last deleted */ + const char *bf_add_file; + uint32_t bf_add_line; + const char *bf_rm_file; + uint32_t bf_rm_line; + const char *bf_getbuf_file; + uint32_t bf_getbuf_line; + const char *bf_tracebuf_file; + uint32_t bf_tracebuf_line; }; typedef TAILQ_HEAD(ath_bufhead_s, ath_buf) ath_bufhead; @@ -318,6 +328,8 @@ typedef TAILQ_HEAD(ath_bufhead_s, ath_buf) ath_bufhead; #define ATH_BUF_FIFOEND 0x00000004 #define ATH_BUF_FIFOPTR 0x00000008 #define ATH_BUF_TOA_PROBE 0x00000010 /* ToD/ToA exchange probe */ +#define ATH_BUF_WAS_CLONED 0x00000100 /* buffer was cloned */ +#define ATH_BUF_WAS_FRAG 0x00000200 /* buffer was part of an 802.11 txfrag */ #define ATH_BUF_FLAGS_CLONE (ATH_BUF_MGMT | ATH_BUF_TOA_PROBE) @@ -416,19 +428,67 @@ struct ath_txq { #define ATH_NODE_UNLOCK_ASSERT(_an) mtx_assert(&(_an)->an_mtx, \ MA_NOTOWNED) +#define _ATH_BUF_SET_GETBUF(_bf, _ff, _ll) \ + do { \ + (_bf)->bf_getbuf_file = (_ff); \ + (_bf)->bf_getbuf_line = (_ll); \ + } while (0) +#define ATH_BUF_SET_GETBUF(_bf) _ATH_BUF_SET_GETBUF((_bf), __FILE__, __LINE__) + +#define _ATH_BUF_SET_TRACEBUF(_bf, _ff, _ll) \ + do { \ + (_bf)->bf_tracebuf_file = (_ff); \ + (_bf)->bf_tracebuf_line = (_ll); \ + } while (0) +#define ATH_BUF_SET_TRACEBUF(_bf) _ATH_BUF_SET_TRACEBUF((_bf), __FILE__, __LINE__) + +#define ATH_BUF_TAILQ_REMOVE(_tq, _bf, _field) \ + _ATH_BUF_TAILQ_REMOVE(_tq, _bf, _field, __FILE__, __LINE__) +#define ATH_BUF_TAILQ_INSERT_HEAD(_tq, _bf, _field) \ + _ATH_BUF_TAILQ_INSERT_HEAD(_tq, _bf, _field, __FILE__, __LINE__) +#define ATH_BUF_TAILQ_INSERT_TAIL(_tq, _bf, _field) \ + _ATH_BUF_TAILQ_INSERT_TAIL(_tq, _bf, _field, __FILE__, __LINE__) + +#define _ATH_BUF_TAILQ_INSERT_HEAD(_tq, _bf, _field, _ff, _ll) \ + do { \ + (_bf)->bf_add_file = _ff; \ + (_bf)->bf_add_line = _ll; \ + (_bf)->bf_rm_file = NULL; \ + (_bf)->bf_rm_line = 0; \ + TAILQ_INSERT_HEAD(_tq, _bf, _field); \ + } while (0) + +#define _ATH_BUF_TAILQ_INSERT_TAIL(_tq, _bf, _field, _ff, _ll) \ + do { \ + (_bf)->bf_add_file = _ff; \ + (_bf)->bf_add_line = _ll; \ + (_bf)->bf_rm_file = NULL; \ + (_bf)->bf_rm_line = 0; \ + TAILQ_INSERT_TAIL(_tq, _bf, _field); \ + } while (0) + +#define _ATH_BUF_TAILQ_REMOVE(_tq, _bf, _field, _ff, _ll) \ + do { \ + (_bf)->bf_add_file = NULL; \ + (_bf)->bf_add_line = 0; \ + (_bf)->bf_rm_file = (_ff); \ + (_bf)->bf_rm_line = (_ll); \ + TAILQ_REMOVE(_tq, _bf, _field); \ +} while (0) + /* * These are for the hardware queue. */ #define ATH_TXQ_INSERT_HEAD(_tq, _elm, _field) do { \ - TAILQ_INSERT_HEAD(&(_tq)->axq_q, (_elm), _field); \ + ATH_BUF_TAILQ_INSERT_HEAD(&(_tq)->axq_q, (_elm), _field); \ (_tq)->axq_depth++; \ } while (0) #define ATH_TXQ_INSERT_TAIL(_tq, _elm, _field) do { \ - TAILQ_INSERT_TAIL(&(_tq)->axq_q, (_elm), _field); \ + ATH_BUF_TAILQ_INSERT_TAIL(&(_tq)->axq_q, (_elm), _field); \ (_tq)->axq_depth++; \ } while (0) #define ATH_TXQ_REMOVE(_tq, _elm, _field) do { \ - TAILQ_REMOVE(&(_tq)->axq_q, _elm, _field); \ + ATH_BUF_TAILQ_REMOVE(&(_tq)->axq_q, _elm, _field); \ (_tq)->axq_depth--; \ } while (0) #define ATH_TXQ_FIRST(_tq) TAILQ_FIRST(&(_tq)->axq_q) @@ -438,17 +498,17 @@ struct ath_txq { * These are for the TID software queue. */ #define ATH_TID_INSERT_HEAD(_tq, _elm, _field) do { \ - TAILQ_INSERT_HEAD(&(_tq)->tid_q, (_elm), _field); \ + ATH_BUF_TAILQ_INSERT_HEAD(&(_tq)->tid_q, (_elm), _field); \ (_tq)->axq_depth++; \ (_tq)->an->an_swq_depth++; \ } while (0) #define ATH_TID_INSERT_TAIL(_tq, _elm, _field) do { \ - TAILQ_INSERT_TAIL(&(_tq)->tid_q, (_elm), _field); \ + ATH_BUF_TAILQ_INSERT_TAIL(&(_tq)->tid_q, (_elm), _field); \ (_tq)->axq_depth++; \ (_tq)->an->an_swq_depth++; \ } while (0) #define ATH_TID_REMOVE(_tq, _elm, _field) do { \ - TAILQ_REMOVE(&(_tq)->tid_q, _elm, _field); \ + ATH_BUF_TAILQ_REMOVE(&(_tq)->tid_q, _elm, _field); \ (_tq)->axq_depth--; \ (_tq)->an->an_swq_depth--; \ } while (0) @@ -459,17 +519,17 @@ struct ath_txq { * These are for the TID filtered frame queue */ #define ATH_TID_FILT_INSERT_HEAD(_tq, _elm, _field) do { \ - TAILQ_INSERT_HEAD(&(_tq)->filtq.tid_q, (_elm), _field); \ + ATH_BUF_TAILQ_INSERT_HEAD(&(_tq)->filtq.tid_q, (_elm), _field); \ (_tq)->axq_depth++; \ (_tq)->an->an_swq_depth++; \ } while (0) #define ATH_TID_FILT_INSERT_TAIL(_tq, _elm, _field) do { \ - TAILQ_INSERT_TAIL(&(_tq)->filtq.tid_q, (_elm), _field); \ + ATH_BUF_TAILQ_INSERT_TAIL(&(_tq)->filtq.tid_q, (_elm), _field); \ (_tq)->axq_depth++; \ (_tq)->an->an_swq_depth++; \ } while (0) #define ATH_TID_FILT_REMOVE(_tq, _elm, _field) do { \ - TAILQ_REMOVE(&(_tq)->filtq.tid_q, _elm, _field); \ + ATH_BUF_TAILQ_REMOVE(&(_tq)->filtq.tid_q, _elm, _field); \ (_tq)->axq_depth--; \ (_tq)->an->an_swq_depth--; \ } while (0)