ath9k: Fix the 'xmit' debugfs file
The 'xmit' debugfs file has become big and unwieldy, fix multiple issues with its usage: * Store TX counters/statistics only for the 4 Access Categories. Use IEEE80211_NUM_ACS instead of ATH9K_NUM_TX_QUEUES. * Move various utility macros to debug.h, they can be reused elsewhere. * Remove tx_complete_poll_work_seen. * Remove code that accesses various internal queue-specific variables without any locking whatsoever. HW/SW queue details will be handled in a subsequent patch. * Do not print internal values like txq_headidx and txq_headidx. They were mostly unused anyway, considering code like: PRX("txq_tailidx: ", txq_headidx); * Handle 'txprocdesc' for EDMA too. Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>hifive-unleashed-5.1
parent
bea843c738
commit
78ef731ce5
|
@ -725,7 +725,6 @@ struct ath_softc {
|
||||||
struct ath9k_debug debug;
|
struct ath9k_debug debug;
|
||||||
spinlock_t nodes_lock;
|
spinlock_t nodes_lock;
|
||||||
struct list_head nodes; /* basically, stations */
|
struct list_head nodes; /* basically, stations */
|
||||||
unsigned int tx_complete_poll_work_seen;
|
|
||||||
#endif
|
#endif
|
||||||
struct ath_beacon_config cur_beacon_conf;
|
struct ath_beacon_config cur_beacon_conf;
|
||||||
struct delayed_work tx_complete_work;
|
struct delayed_work tx_complete_work;
|
||||||
|
|
|
@ -512,62 +512,19 @@ static const struct file_operations fops_interrupt = {
|
||||||
.llseek = default_llseek,
|
.llseek = default_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PR_QNUM(_n) sc->tx.txq_map[_n]->axq_qnum
|
|
||||||
#define PR(str, elem) \
|
|
||||||
do { \
|
|
||||||
len += snprintf(buf + len, size - len, \
|
|
||||||
"%s%13u%11u%10u%10u\n", str, \
|
|
||||||
sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].elem, \
|
|
||||||
sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].elem, \
|
|
||||||
sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].elem, \
|
|
||||||
sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].elem); \
|
|
||||||
if (len >= size) \
|
|
||||||
goto done; \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
#define PRX(str, elem) \
|
|
||||||
do { \
|
|
||||||
len += snprintf(buf + len, size - len, \
|
|
||||||
"%s%13u%11u%10u%10u\n", str, \
|
|
||||||
(unsigned int)(sc->tx.txq_map[IEEE80211_AC_BE]->elem), \
|
|
||||||
(unsigned int)(sc->tx.txq_map[IEEE80211_AC_BK]->elem), \
|
|
||||||
(unsigned int)(sc->tx.txq_map[IEEE80211_AC_VI]->elem), \
|
|
||||||
(unsigned int)(sc->tx.txq_map[IEEE80211_AC_VO]->elem)); \
|
|
||||||
if (len >= size) \
|
|
||||||
goto done; \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
#define PRQLE(str, elem) \
|
|
||||||
do { \
|
|
||||||
len += snprintf(buf + len, size - len, \
|
|
||||||
"%s%13i%11i%10i%10i\n", str, \
|
|
||||||
list_empty(&sc->tx.txq_map[IEEE80211_AC_BE]->elem), \
|
|
||||||
list_empty(&sc->tx.txq_map[IEEE80211_AC_BK]->elem), \
|
|
||||||
list_empty(&sc->tx.txq_map[IEEE80211_AC_VI]->elem), \
|
|
||||||
list_empty(&sc->tx.txq_map[IEEE80211_AC_VO]->elem)); \
|
|
||||||
if (len >= size) \
|
|
||||||
goto done; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
|
static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
|
||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
struct ath_softc *sc = file->private_data;
|
struct ath_softc *sc = file->private_data;
|
||||||
char *buf;
|
char *buf;
|
||||||
unsigned int len = 0, size = 8000;
|
unsigned int len = 0, size = 2048;
|
||||||
int i;
|
|
||||||
ssize_t retval = 0;
|
ssize_t retval = 0;
|
||||||
char tmp[32];
|
|
||||||
|
|
||||||
buf = kzalloc(size, GFP_KERNEL);
|
buf = kzalloc(size, GFP_KERNEL);
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
len += sprintf(buf, "Num-Tx-Queues: %i tx-queues-setup: 0x%x"
|
len += sprintf(buf, "%30s %10s%10s%10s\n\n",
|
||||||
" poll-work-seen: %u\n"
|
|
||||||
"%30s %10s%10s%10s\n\n",
|
|
||||||
ATH9K_NUM_TX_QUEUES, sc->tx.txqsetup,
|
|
||||||
sc->tx_complete_poll_work_seen,
|
|
||||||
"BE", "BK", "VI", "VO");
|
"BE", "BK", "VI", "VO");
|
||||||
|
|
||||||
PR("MPDUs Queued: ", queued);
|
PR("MPDUs Queued: ", queued);
|
||||||
|
@ -587,62 +544,11 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
|
||||||
PR("DELIM Underrun: ", delim_underrun);
|
PR("DELIM Underrun: ", delim_underrun);
|
||||||
PR("TX-Pkts-All: ", tx_pkts_all);
|
PR("TX-Pkts-All: ", tx_pkts_all);
|
||||||
PR("TX-Bytes-All: ", tx_bytes_all);
|
PR("TX-Bytes-All: ", tx_bytes_all);
|
||||||
PR("hw-put-tx-buf: ", puttxbuf);
|
PR("HW-put-tx-buf: ", puttxbuf);
|
||||||
PR("hw-tx-start: ", txstart);
|
PR("HW-tx-start: ", txstart);
|
||||||
PR("hw-tx-proc-desc: ", txprocdesc);
|
PR("HW-tx-proc-desc: ", txprocdesc);
|
||||||
PR("TX-Failed: ", txfailed);
|
PR("TX-Failed: ", txfailed);
|
||||||
len += snprintf(buf + len, size - len,
|
|
||||||
"%s%11p%11p%10p%10p\n", "txq-memory-address:",
|
|
||||||
sc->tx.txq_map[IEEE80211_AC_BE],
|
|
||||||
sc->tx.txq_map[IEEE80211_AC_BK],
|
|
||||||
sc->tx.txq_map[IEEE80211_AC_VI],
|
|
||||||
sc->tx.txq_map[IEEE80211_AC_VO]);
|
|
||||||
if (len >= size)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
PRX("axq-qnum: ", axq_qnum);
|
|
||||||
PRX("axq-depth: ", axq_depth);
|
|
||||||
PRX("axq-ampdu_depth: ", axq_ampdu_depth);
|
|
||||||
PRX("axq-stopped ", stopped);
|
|
||||||
PRX("tx-in-progress ", axq_tx_inprogress);
|
|
||||||
PRX("pending-frames ", pending_frames);
|
|
||||||
PRX("txq_headidx: ", txq_headidx);
|
|
||||||
PRX("txq_tailidx: ", txq_headidx);
|
|
||||||
|
|
||||||
PRQLE("axq_q empty: ", axq_q);
|
|
||||||
PRQLE("axq_acq empty: ", axq_acq);
|
|
||||||
for (i = 0; i < ATH_TXFIFO_DEPTH; i++) {
|
|
||||||
snprintf(tmp, sizeof(tmp) - 1, "txq_fifo[%i] empty: ", i);
|
|
||||||
PRQLE(tmp, txq_fifo[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print out more detailed queue-info */
|
|
||||||
for (i = 0; i <= IEEE80211_AC_BK; i++) {
|
|
||||||
struct ath_txq *txq = &(sc->tx.txq[i]);
|
|
||||||
struct ath_atx_ac *ac;
|
|
||||||
struct ath_atx_tid *tid;
|
|
||||||
if (len >= size)
|
|
||||||
goto done;
|
|
||||||
spin_lock_bh(&txq->axq_lock);
|
|
||||||
if (!list_empty(&txq->axq_acq)) {
|
|
||||||
ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac,
|
|
||||||
list);
|
|
||||||
len += snprintf(buf + len, size - len,
|
|
||||||
"txq[%i] first-ac: %p sched: %i\n",
|
|
||||||
i, ac, ac->sched);
|
|
||||||
if (list_empty(&ac->tid_q) || (len >= size))
|
|
||||||
goto done_for;
|
|
||||||
tid = list_first_entry(&ac->tid_q, struct ath_atx_tid,
|
|
||||||
list);
|
|
||||||
len += snprintf(buf + len, size - len,
|
|
||||||
" first-tid: %p sched: %i paused: %i\n",
|
|
||||||
tid, tid->sched, tid->paused);
|
|
||||||
}
|
|
||||||
done_for:
|
|
||||||
spin_unlock_bh(&txq->axq_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
|
||||||
if (len > size)
|
if (len > size)
|
||||||
len = size;
|
len = size;
|
||||||
|
|
||||||
|
|
|
@ -179,6 +179,21 @@ struct ath_tx_stats {
|
||||||
u32 txfailed;
|
u32 txfailed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Various utility macros to print TX/Queue counters.
|
||||||
|
*/
|
||||||
|
#define PR_QNUM(_n) sc->tx.txq_map[_n]->axq_qnum
|
||||||
|
#define TXSTATS sc->debug.stats.txstats
|
||||||
|
#define PR(str, elem) \
|
||||||
|
do { \
|
||||||
|
len += snprintf(buf + len, size - len, \
|
||||||
|
"%s%13u%11u%10u%10u\n", str, \
|
||||||
|
TXSTATS[PR_QNUM(IEEE80211_AC_BE)].elem, \
|
||||||
|
TXSTATS[PR_QNUM(IEEE80211_AC_BK)].elem, \
|
||||||
|
TXSTATS[PR_QNUM(IEEE80211_AC_VI)].elem, \
|
||||||
|
TXSTATS[PR_QNUM(IEEE80211_AC_VO)].elem); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
#define RX_STAT_INC(c) (sc->debug.stats.rxstats.c++)
|
#define RX_STAT_INC(c) (sc->debug.stats.rxstats.c++)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -227,7 +242,7 @@ struct ath_rx_stats {
|
||||||
|
|
||||||
struct ath_stats {
|
struct ath_stats {
|
||||||
struct ath_interrupt_stats istats;
|
struct ath_interrupt_stats istats;
|
||||||
struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES];
|
struct ath_tx_stats txstats[IEEE80211_NUM_ACS];
|
||||||
struct ath_rx_stats rxstats;
|
struct ath_rx_stats rxstats;
|
||||||
struct ath_dfs_stats dfs_stats;
|
struct ath_dfs_stats dfs_stats;
|
||||||
u32 reset[__RESET_TYPE_MAX];
|
u32 reset[__RESET_TYPE_MAX];
|
||||||
|
|
|
@ -27,9 +27,6 @@ void ath_tx_complete_poll_work(struct work_struct *work)
|
||||||
struct ath_txq *txq;
|
struct ath_txq *txq;
|
||||||
int i;
|
int i;
|
||||||
bool needreset = false;
|
bool needreset = false;
|
||||||
#ifdef CONFIG_ATH9K_DEBUGFS
|
|
||||||
sc->tx_complete_poll_work_seen++;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
|
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
|
||||||
if (ATH_TXQ_SETUP(sc, i)) {
|
if (ATH_TXQ_SETUP(sc, i)) {
|
||||||
|
|
|
@ -1953,7 +1953,6 @@ static int ath9k_get_et_sset_count(struct ieee80211_hw *hw,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PR_QNUM(_n) (sc->tx.txq_map[_n]->axq_qnum)
|
|
||||||
#define AWDATA(elem) \
|
#define AWDATA(elem) \
|
||||||
do { \
|
do { \
|
||||||
data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].elem; \
|
data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].elem; \
|
||||||
|
|
|
@ -2319,6 +2319,8 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
|
||||||
|
|
||||||
ath_txq_lock(sc, txq);
|
ath_txq_lock(sc, txq);
|
||||||
|
|
||||||
|
TX_STAT_INC(txq->axq_qnum, txprocdesc);
|
||||||
|
|
||||||
if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
|
if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
|
||||||
ath_txq_unlock(sc, txq);
|
ath_txq_unlock(sc, txq);
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue