ath9k: Add debug counters for TX
Location: ath9k/phy#/xmit Signed-off-by: Sujith <Sujith.Manoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
0ee9c13c7c
commit
fec247c0d5
|
@ -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 = {
|
||||||
.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)
|
||||||
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:
|
||||||
|
|
||||||
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 {
|
||||||
|
|
||||||
#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 {
|
||||||
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 {
|
||||||
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);
|
||||||
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,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
|
|
||||||
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,
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
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)
|
||||||
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)
|
||||||
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,
|
||||||
|
|
||||||
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,
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
|
|
||||||
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)
|
||||||
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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue