Commit fec247c0 authored by Sujith's avatar Sujith Committed by John W. Linville

ath9k: Add debug counters for TX

Location: ath9k/phy#/xmit
Signed-off-by: default avatarSujith <Sujith.Manoharan@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 0ee9c13c
...@@ -237,7 +237,6 @@ struct ath_txq { ...@@ -237,7 +237,6 @@ struct ath_txq {
spinlock_t axq_lock; spinlock_t axq_lock;
u32 axq_depth; u32 axq_depth;
u8 axq_aggr_depth; u8 axq_aggr_depth;
u32 axq_totalqueued;
bool stopped; bool stopped;
bool axq_tx_inprogress; bool axq_tx_inprogress;
struct ath_buf *axq_linkbuf; struct ath_buf *axq_linkbuf;
......
...@@ -486,6 +486,83 @@ static const struct file_operations fops_wiphy = { ...@@ -486,6 +486,83 @@ static const struct file_operations fops_wiphy = {
.owner = THIS_MODULE .owner = THIS_MODULE
}; };
#define PR(str, elem) \
do { \
len += snprintf(buf + len, size - len, \
"%s%13u%11u%10u%10u\n", str, \
sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_BE]].elem, \
sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_BK]].elem, \
sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_VI]].elem, \
sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_VO]].elem); \
} while(0)
static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
char *buf;
unsigned int len = 0, size = 2048;
ssize_t retval = 0;
buf = kzalloc(size, GFP_KERNEL);
if (buf == NULL)
return 0;
len += sprintf(buf, "%30s %10s%10s%10s\n\n", "BE", "BK", "VI", "VO");
PR("MPDUs Queued: ", queued);
PR("MPDUs Completed: ", completed);
PR("Aggregates: ", a_aggr);
PR("AMPDUs Queued: ", a_queued);
PR("AMPDUs Completed:", a_completed);
PR("AMPDUs Retried: ", a_retries);
PR("AMPDUs XRetried: ", a_xretries);
PR("FIFO Underrun: ", fifo_underrun);
PR("TXOP Exceeded: ", xtxop);
PR("TXTIMER Expiry: ", timer_exp);
PR("DESC CFG Error: ", desc_cfg_err);
PR("DATA Underrun: ", data_underrun);
PR("DELIM Underrun: ", delim_underrun);
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
kfree(buf);
return retval;
}
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
struct ath_buf *bf)
{
struct ath_desc *ds = bf->bf_desc;
if (bf_isampdu(bf)) {
if (bf_isxretried(bf))
TX_STAT_INC(txq->axq_qnum, a_xretries);
else
TX_STAT_INC(txq->axq_qnum, a_completed);
} else {
TX_STAT_INC(txq->axq_qnum, completed);
}
if (ds->ds_txstat.ts_status & ATH9K_TXERR_FIFO)
TX_STAT_INC(txq->axq_qnum, fifo_underrun);
if (ds->ds_txstat.ts_status & ATH9K_TXERR_XTXOP)
TX_STAT_INC(txq->axq_qnum, xtxop);
if (ds->ds_txstat.ts_status & ATH9K_TXERR_TIMER_EXPIRED)
TX_STAT_INC(txq->axq_qnum, timer_exp);
if (ds->ds_txstat.ts_flags & ATH9K_TX_DESC_CFG_ERR)
TX_STAT_INC(txq->axq_qnum, desc_cfg_err);
if (ds->ds_txstat.ts_flags & ATH9K_TX_DATA_UNDERRUN)
TX_STAT_INC(txq->axq_qnum, data_underrun);
if (ds->ds_txstat.ts_flags & ATH9K_TX_DELIM_UNDERRUN)
TX_STAT_INC(txq->axq_qnum, delim_underrun);
}
static const struct file_operations fops_xmit = {
.read = read_file_xmit,
.open = ath9k_debugfs_open,
.owner = THIS_MODULE
};
int ath9k_init_debug(struct ath_softc *sc) int ath9k_init_debug(struct ath_softc *sc)
{ {
...@@ -529,6 +606,13 @@ int ath9k_init_debug(struct ath_softc *sc) ...@@ -529,6 +606,13 @@ int ath9k_init_debug(struct ath_softc *sc)
if (!sc->debug.debugfs_wiphy) if (!sc->debug.debugfs_wiphy)
goto err; goto err;
sc->debug.debugfs_xmit = debugfs_create_file("xmit",
S_IRUSR,
sc->debug.debugfs_phy,
sc, &fops_xmit);
if (!sc->debug.debugfs_xmit)
goto err;
return 0; return 0;
err: err:
ath9k_exit_debug(sc); ath9k_exit_debug(sc);
...@@ -537,6 +621,7 @@ err: ...@@ -537,6 +621,7 @@ err:
void ath9k_exit_debug(struct ath_softc *sc) void ath9k_exit_debug(struct ath_softc *sc)
{ {
debugfs_remove(sc->debug.debugfs_xmit);
debugfs_remove(sc->debug.debugfs_wiphy); debugfs_remove(sc->debug.debugfs_wiphy);
debugfs_remove(sc->debug.debugfs_rcstat); debugfs_remove(sc->debug.debugfs_rcstat);
debugfs_remove(sc->debug.debugfs_interrupt); debugfs_remove(sc->debug.debugfs_interrupt);
......
...@@ -35,6 +35,15 @@ enum ATH_DEBUG { ...@@ -35,6 +35,15 @@ enum ATH_DEBUG {
#define DBG_DEFAULT (ATH_DBG_FATAL) #define DBG_DEFAULT (ATH_DBG_FATAL)
struct ath_txq;
struct ath_buf;
#ifdef CONFIG_ATH9K_DEBUG
#define TX_STAT_INC(q, c) sc->debug.stats.txstats[q].c++
#else
#define TX_STAT_INC(q, c) do { } while (0)
#endif
#ifdef CONFIG_ATH9K_DEBUG #ifdef CONFIG_ATH9K_DEBUG
/** /**
...@@ -87,9 +96,45 @@ struct ath_rc_stats { ...@@ -87,9 +96,45 @@ struct ath_rc_stats {
u8 per; u8 per;
}; };
/**
* struct ath_tx_stats - Statistics about TX
* @queued: Total MPDUs (non-aggr) queued
* @completed: Total MPDUs (non-aggr) completed
* @a_aggr: Total no. of aggregates queued
* @a_queued: Total AMPDUs queued
* @a_completed: Total AMPDUs completed
* @a_retries: No. of AMPDUs retried (SW)
* @a_xretries: No. of AMPDUs dropped due to xretries
* @fifo_underrun: FIFO underrun occurrences
Valid only for:
- non-aggregate condition.
- first packet of aggregate.
* @xtxop: No. of frames filtered because of TXOP limit
* @timer_exp: Transmit timer expiry
* @desc_cfg_err: Descriptor configuration errors
* @data_urn: TX data underrun errors
* @delim_urn: TX delimiter underrun errors
*/
struct ath_tx_stats {
u32 queued;
u32 completed;
u32 a_aggr;
u32 a_queued;
u32 a_completed;
u32 a_retries;
u32 a_xretries;
u32 fifo_underrun;
u32 xtxop;
u32 timer_exp;
u32 desc_cfg_err;
u32 data_underrun;
u32 delim_underrun;
};
struct ath_stats { struct ath_stats {
struct ath_interrupt_stats istats; struct ath_interrupt_stats istats;
struct ath_rc_stats rcstats[RATE_TABLE_SIZE]; struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES];
}; };
struct ath9k_debug { struct ath9k_debug {
...@@ -100,6 +145,7 @@ struct ath9k_debug { ...@@ -100,6 +145,7 @@ struct ath9k_debug {
struct dentry *debugfs_interrupt; struct dentry *debugfs_interrupt;
struct dentry *debugfs_rcstat; struct dentry *debugfs_rcstat;
struct dentry *debugfs_wiphy; struct dentry *debugfs_wiphy;
struct dentry *debugfs_xmit;
struct ath_stats stats; struct ath_stats stats;
}; };
...@@ -110,6 +156,8 @@ int ath9k_debug_create_root(void); ...@@ -110,6 +156,8 @@ int ath9k_debug_create_root(void);
void ath9k_debug_remove_root(void); void ath9k_debug_remove_root(void);
void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb); void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb);
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
struct ath_buf *bf);
void ath_debug_stat_retries(struct ath_softc *sc, int rix, void ath_debug_stat_retries(struct ath_softc *sc, int rix,
int xretries, int retries, u8 per); int xretries, int retries, u8 per);
...@@ -148,6 +196,12 @@ static inline void ath_debug_stat_rc(struct ath_softc *sc, ...@@ -148,6 +196,12 @@ static inline void ath_debug_stat_rc(struct ath_softc *sc,
{ {
} }
static inline void ath_debug_stat_tx(struct ath_softc *sc,
struct ath_txq *txq,
struct ath_buf *bf)
{
}
static inline void ath_debug_stat_retries(struct ath_softc *sc, int rix, static inline void ath_debug_stat_retries(struct ath_softc *sc, int rix,
int xretries, int retries, u8 per) int xretries, int retries, u8 per)
{ {
......
...@@ -59,6 +59,7 @@ static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq, ...@@ -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 ath_atx_tid *tid,
struct list_head *bf_head); struct list_head *bf_head);
static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
struct ath_txq *txq,
struct list_head *bf_q, struct list_head *bf_q,
int txok, int sendbar); int txok, int sendbar);
static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, 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, ...@@ -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); ath_tx_update_baw(sc, tid, bf->bf_seqno);
spin_unlock(&txq->axq_lock); 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); spin_lock(&txq->axq_lock);
} }
...@@ -220,13 +221,15 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, ...@@ -220,13 +221,15 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
tid->baw_tail = tid->baw_head; 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 sk_buff *skb;
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
bf->bf_state.bf_type |= BUF_RETRY; bf->bf_state.bf_type |= BUF_RETRY;
bf->bf_retries++; bf->bf_retries++;
TX_STAT_INC(txq->axq_qnum, a_retries);
skb = bf->bf_mpdu; skb = bf->bf_mpdu;
hdr = (struct ieee80211_hdr *)skb->data; hdr = (struct ieee80211_hdr *)skb->data;
...@@ -328,7 +331,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, ...@@ -328,7 +331,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
if (!(tid->state & AGGR_CLEANUP) && if (!(tid->state & AGGR_CLEANUP) &&
ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) { ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) {
if (bf->bf_retries < ATH_MAX_SW_RETRIES) { if (bf->bf_retries < ATH_MAX_SW_RETRIES) {
ath_tx_set_retry(sc, bf); ath_tx_set_retry(sc, txq, bf);
txpending = 1; txpending = 1;
} else { } else {
bf->bf_state.bf_type |= BUF_XRETRY; 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, ...@@ -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_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 { } else {
/* retry the un-acked ones */ /* retry the un-acked ones */
if (bf->bf_next == NULL && bf_last->bf_stale) { 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, ...@@ -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; bf->bf_state.bf_type |= BUF_XRETRY;
ath_tx_rc_status(bf, ds, nbad, ath_tx_rc_status(bf, ds, nbad,
0, false); 0, false);
ath_tx_complete_buf(sc, bf, &bf_head, ath_tx_complete_buf(sc, bf, txq,
0, 0); &bf_head, 0, 0);
break; break;
} }
...@@ -569,6 +572,7 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, ...@@ -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, static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
struct ath_txq *txq,
struct ath_atx_tid *tid, struct ath_atx_tid *tid,
struct list_head *bf_q) struct list_head *bf_q)
{ {
...@@ -633,6 +637,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, ...@@ -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_desc->ds_link = bf->bf_daddr;
} }
bf_prev = bf; bf_prev = bf;
} while (!list_empty(&tid->buf_q)); } while (!list_empty(&tid->buf_q));
bf_first->bf_al = al; bf_first->bf_al = al;
...@@ -655,7 +660,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, ...@@ -655,7 +660,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
INIT_LIST_HEAD(&bf_q); 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; * 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, ...@@ -686,6 +691,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
txq->axq_aggr_depth++; txq->axq_aggr_depth++;
ath_tx_txqaddbuf(sc, txq, &bf_q); ath_tx_txqaddbuf(sc, txq, &bf_q);
TX_STAT_INC(txq->axq_qnum, a_aggr);
} while (txq->axq_depth < ATH_AGGR_MIN_QDEPTH && } while (txq->axq_depth < ATH_AGGR_MIN_QDEPTH &&
status != ATH_AGGR_BAW_CLOSED); status != ATH_AGGR_BAW_CLOSED);
...@@ -737,7 +743,7 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) ...@@ -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); list_move_tail(&bf->list, &bf_head);
ath_tx_update_baw(sc, txtid, bf->bf_seqno); 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); spin_unlock_bh(&txq->axq_lock);
...@@ -859,7 +865,6 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) ...@@ -859,7 +865,6 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
spin_lock_init(&txq->axq_lock); spin_lock_init(&txq->axq_lock);
txq->axq_depth = 0; txq->axq_depth = 0;
txq->axq_aggr_depth = 0; txq->axq_aggr_depth = 0;
txq->axq_totalqueued = 0;
txq->axq_linkbuf = NULL; txq->axq_linkbuf = NULL;
txq->axq_tx_inprogress = false; txq->axq_tx_inprogress = false;
sc->tx.txqsetup |= 1<<qnum; sc->tx.txqsetup |= 1<<qnum;
...@@ -1025,7 +1030,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) ...@@ -1025,7 +1030,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
if (bf_isampdu(bf)) if (bf_isampdu(bf))
ath_tx_complete_aggr(sc, txq, bf, &bf_head, 0); ath_tx_complete_aggr(sc, txq, bf, &bf_head, 0);
else 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); spin_lock_bh(&txq->axq_lock);
...@@ -1176,7 +1181,6 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, ...@@ -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); list_splice_tail_init(head, &txq->axq_q);
txq->axq_depth++; txq->axq_depth++;
txq->axq_totalqueued++;
txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list); txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list);
DPRINTF(sc, ATH_DBG_QUEUE, DPRINTF(sc, ATH_DBG_QUEUE,
...@@ -1224,6 +1228,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, ...@@ -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 = list_first_entry(bf_head, struct ath_buf, list);
bf->bf_state.bf_type |= BUF_AMPDU; 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: * 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, ...@@ -1270,6 +1275,7 @@ static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq,
bf->bf_lastbf = bf; bf->bf_lastbf = bf;
ath_buf_set_rate(sc, bf); ath_buf_set_rate(sc, bf);
ath_tx_txqaddbuf(sc, txq, bf_head); 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, 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, ...@@ -1283,6 +1289,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
bf->bf_nframes = 1; bf->bf_nframes = 1;
ath_buf_set_rate(sc, bf); ath_buf_set_rate(sc, bf);
ath_tx_txqaddbuf(sc, txq, bf_head); 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) 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, ...@@ -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, static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
struct ath_txq *txq,
struct list_head *bf_q, struct list_head *bf_q,
int txok, int sendbar) int txok, int sendbar)
{ {
...@@ -1815,7 +1823,6 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, ...@@ -1815,7 +1823,6 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
unsigned long flags; unsigned long flags;
int tx_flags = 0; int tx_flags = 0;
if (sendbar) if (sendbar)
tx_flags = ATH_TX_BAR; tx_flags = ATH_TX_BAR;
...@@ -1828,6 +1835,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, ...@@ -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); dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE);
ath_tx_complete(sc, skb, tx_flags); 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 * 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) ...@@ -2015,7 +2023,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
if (bf_isampdu(bf)) if (bf_isampdu(bf))
ath_tx_complete_aggr(sc, txq, bf, &bf_head, txok); ath_tx_complete_aggr(sc, txq, bf, &bf_head, txok);
else 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); ath_wake_mac80211_queue(sc, txq);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment