Skip to content

Commit

Permalink
ath9k: Add debug counters for TX
Browse files Browse the repository at this point in the history
Location: ath9k/phy#/xmit

Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Sujith authored and John W. Linville committed Jul 29, 2009
1 parent 0ee9c13 commit fec247c
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 14 deletions.
1 change: 0 additions & 1 deletion drivers/net/wireless/ath/ath9k/ath9k.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,6 @@ struct ath_txq {
spinlock_t axq_lock;
u32 axq_depth;
u8 axq_aggr_depth;
u32 axq_totalqueued;
bool stopped;
bool axq_tx_inprogress;
struct ath_buf *axq_linkbuf;
Expand Down
85 changes: 85 additions & 0 deletions drivers/net/wireless/ath/ath9k/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,83 @@ static const struct file_operations fops_wiphy = {
.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)
{
Expand Down Expand Up @@ -529,6 +606,13 @@ int ath9k_init_debug(struct ath_softc *sc)
if (!sc->debug.debugfs_wiphy)
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;
err:
ath9k_exit_debug(sc);
Expand All @@ -537,6 +621,7 @@ int ath9k_init_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_rcstat);
debugfs_remove(sc->debug.debugfs_interrupt);
Expand Down
54 changes: 54 additions & 0 deletions drivers/net/wireless/ath/ath9k/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,15 @@ enum ATH_DEBUG {

#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

/**
Expand Down Expand Up @@ -87,9 +96,45 @@ struct ath_rc_stats {
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_interrupt_stats istats;
struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES];
};

struct ath9k_debug {
Expand All @@ -100,6 +145,7 @@ struct ath9k_debug {
struct dentry *debugfs_interrupt;
struct dentry *debugfs_rcstat;
struct dentry *debugfs_wiphy;
struct dentry *debugfs_xmit;
struct ath_stats stats;
};

Expand All @@ -110,6 +156,8 @@ int ath9k_debug_create_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_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,
int xretries, int retries, u8 per);

Expand Down Expand Up @@ -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,
int xretries, int retries, u8 per)
{
Expand Down
34 changes: 21 additions & 13 deletions drivers/net/wireless/ath/ath9k/xmit.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -212,21 +213,23 @@ 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);
}

tid->seq_next = tid->seq_start;
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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
}

Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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,
Expand All @@ -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)
Expand Down Expand Up @@ -1808,14 +1815,14 @@ 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)
{
struct sk_buff *skb = bf->bf_mpdu;
unsigned long flags;
int tx_flags = 0;


if (sendbar)
tx_flags = ATH_TX_BAR;

Expand All @@ -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
Expand Down Expand Up @@ -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);

Expand Down

0 comments on commit fec247c

Please sign in to comment.