|
@@ -59,6 +59,7 @@ static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq,
|
|
|
struct ath_atx_tid *tid,
|
|
|
struct list_head *bf_head);
|
|
|
static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
|
|
|
+ struct ath_txq *txq,
|
|
|
struct list_head *bf_q,
|
|
|
int txok, int sendbar);
|
|
|
static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
|
|
@@ -212,7 +213,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
|
|
|
ath_tx_update_baw(sc, tid, bf->bf_seqno);
|
|
|
|
|
|
spin_unlock(&txq->axq_lock);
|
|
|
- ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
|
|
|
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, 0, 0);
|
|
|
spin_lock(&txq->axq_lock);
|
|
|
}
|
|
|
|
|
@@ -220,13 +221,15 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
|
|
|
tid->baw_tail = tid->baw_head;
|
|
|
}
|
|
|
|
|
|
-static void ath_tx_set_retry(struct ath_softc *sc, struct ath_buf *bf)
|
|
|
+static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
|
|
|
+ struct ath_buf *bf)
|
|
|
{
|
|
|
struct sk_buff *skb;
|
|
|
struct ieee80211_hdr *hdr;
|
|
|
|
|
|
bf->bf_state.bf_type |= BUF_RETRY;
|
|
|
bf->bf_retries++;
|
|
|
+ TX_STAT_INC(txq->axq_qnum, a_retries);
|
|
|
|
|
|
skb = bf->bf_mpdu;
|
|
|
hdr = (struct ieee80211_hdr *)skb->data;
|
|
@@ -328,7 +331,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
|
|
if (!(tid->state & AGGR_CLEANUP) &&
|
|
|
ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) {
|
|
|
if (bf->bf_retries < ATH_MAX_SW_RETRIES) {
|
|
|
- ath_tx_set_retry(sc, bf);
|
|
|
+ ath_tx_set_retry(sc, txq, bf);
|
|
|
txpending = 1;
|
|
|
} else {
|
|
|
bf->bf_state.bf_type |= BUF_XRETRY;
|
|
@@ -375,7 +378,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
|
|
ath_tx_rc_status(bf, ds, nbad, txok, false);
|
|
|
}
|
|
|
|
|
|
- ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar);
|
|
|
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, !txfail, sendbar);
|
|
|
} else {
|
|
|
/* retry the un-acked ones */
|
|
|
if (bf->bf_next == NULL && bf_last->bf_stale) {
|
|
@@ -395,8 +398,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
|
|
bf->bf_state.bf_type |= BUF_XRETRY;
|
|
|
ath_tx_rc_status(bf, ds, nbad,
|
|
|
0, false);
|
|
|
- ath_tx_complete_buf(sc, bf, &bf_head,
|
|
|
- 0, 0);
|
|
|
+ ath_tx_complete_buf(sc, bf, txq,
|
|
|
+ &bf_head, 0, 0);
|
|
|
break;
|
|
|
}
|
|
|
|
|
@@ -569,6 +572,7 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
|
|
|
}
|
|
|
|
|
|
static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
|
|
|
+ struct ath_txq *txq,
|
|
|
struct ath_atx_tid *tid,
|
|
|
struct list_head *bf_q)
|
|
|
{
|
|
@@ -633,6 +637,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
|
|
|
bf_prev->bf_desc->ds_link = bf->bf_daddr;
|
|
|
}
|
|
|
bf_prev = bf;
|
|
|
+
|
|
|
} while (!list_empty(&tid->buf_q));
|
|
|
|
|
|
bf_first->bf_al = al;
|
|
@@ -655,7 +660,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
|
|
|
|
|
INIT_LIST_HEAD(&bf_q);
|
|
|
|
|
|
- status = ath_tx_form_aggr(sc, tid, &bf_q);
|
|
|
+ status = ath_tx_form_aggr(sc, txq, tid, &bf_q);
|
|
|
|
|
|
/*
|
|
|
* no frames picked up to be aggregated;
|
|
@@ -686,6 +691,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
|
|
|
|
|
txq->axq_aggr_depth++;
|
|
|
ath_tx_txqaddbuf(sc, txq, &bf_q);
|
|
|
+ TX_STAT_INC(txq->axq_qnum, a_aggr);
|
|
|
|
|
|
} while (txq->axq_depth < ATH_AGGR_MIN_QDEPTH &&
|
|
|
status != ATH_AGGR_BAW_CLOSED);
|
|
@@ -737,7 +743,7 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
|
|
|
}
|
|
|
list_move_tail(&bf->list, &bf_head);
|
|
|
ath_tx_update_baw(sc, txtid, bf->bf_seqno);
|
|
|
- ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
|
|
|
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, 0, 0);
|
|
|
}
|
|
|
spin_unlock_bh(&txq->axq_lock);
|
|
|
|
|
@@ -859,7 +865,6 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
|
|
|
spin_lock_init(&txq->axq_lock);
|
|
|
txq->axq_depth = 0;
|
|
|
txq->axq_aggr_depth = 0;
|
|
|
- txq->axq_totalqueued = 0;
|
|
|
txq->axq_linkbuf = NULL;
|
|
|
txq->axq_tx_inprogress = false;
|
|
|
sc->tx.txqsetup |= 1<<qnum;
|
|
@@ -1025,7 +1030,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
|
|
|
if (bf_isampdu(bf))
|
|
|
ath_tx_complete_aggr(sc, txq, bf, &bf_head, 0);
|
|
|
else
|
|
|
- ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
|
|
|
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, 0, 0);
|
|
|
}
|
|
|
|
|
|
spin_lock_bh(&txq->axq_lock);
|
|
@@ -1176,7 +1181,6 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
|
|
|
|
|
|
list_splice_tail_init(head, &txq->axq_q);
|
|
|
txq->axq_depth++;
|
|
|
- txq->axq_totalqueued++;
|
|
|
txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list);
|
|
|
|
|
|
DPRINTF(sc, ATH_DBG_QUEUE,
|
|
@@ -1224,6 +1228,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
|
|
|
|
|
|
bf = list_first_entry(bf_head, struct ath_buf, list);
|
|
|
bf->bf_state.bf_type |= BUF_AMPDU;
|
|
|
+ TX_STAT_INC(txctl->txq->axq_qnum, a_queued);
|
|
|
|
|
|
/*
|
|
|
* Do not queue to h/w when any of the following conditions is true:
|
|
@@ -1270,6 +1275,7 @@ static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq,
|
|
|
bf->bf_lastbf = bf;
|
|
|
ath_buf_set_rate(sc, bf);
|
|
|
ath_tx_txqaddbuf(sc, txq, bf_head);
|
|
|
+ TX_STAT_INC(txq->axq_qnum, queued);
|
|
|
}
|
|
|
|
|
|
static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
|
|
@@ -1283,6 +1289,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
|
|
|
bf->bf_nframes = 1;
|
|
|
ath_buf_set_rate(sc, bf);
|
|
|
ath_tx_txqaddbuf(sc, txq, bf_head);
|
|
|
+ TX_STAT_INC(txq->axq_qnum, queued);
|
|
|
}
|
|
|
|
|
|
static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
|
|
@@ -1808,6 +1815,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
|
|
|
}
|
|
|
|
|
|
static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
|
|
|
+ struct ath_txq *txq,
|
|
|
struct list_head *bf_q,
|
|
|
int txok, int sendbar)
|
|
|
{
|
|
@@ -1815,7 +1823,6 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
|
|
|
unsigned long flags;
|
|
|
int tx_flags = 0;
|
|
|
|
|
|
-
|
|
|
if (sendbar)
|
|
|
tx_flags = ATH_TX_BAR;
|
|
|
|
|
@@ -1828,6 +1835,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
|
|
|
|
|
|
dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE);
|
|
|
ath_tx_complete(sc, skb, tx_flags);
|
|
|
+ ath_debug_stat_tx(sc, txq, bf);
|
|
|
|
|
|
/*
|
|
|
* Return the list of ath_buf of this mpdu to free queue
|
|
@@ -2015,7 +2023,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
|
|
|
if (bf_isampdu(bf))
|
|
|
ath_tx_complete_aggr(sc, txq, bf, &bf_head, txok);
|
|
|
else
|
|
|
- ath_tx_complete_buf(sc, bf, &bf_head, txok, 0);
|
|
|
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, txok, 0);
|
|
|
|
|
|
ath_wake_mac80211_queue(sc, txq);
|
|
|
|