Commit 462e58f2 authored by Ben Greear's avatar Ben Greear Committed by John W. Linville

ath9k: Gather and report IRQ sync_cause errors.

Report all defined sync_cause errors in debugfs
to aid with debugging.

Use a macro to print out the interrupts file contents
to decrease code duplication.
Signed-off-by: default avatarBen Greear <greearb@candelatech.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 24a0731e
...@@ -136,6 +136,7 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) ...@@ -136,6 +136,7 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
} }
if (sync_cause) { if (sync_cause) {
ath9k_debug_sync_cause(common, sync_cause);
fatal_int = fatal_int =
(sync_cause & (sync_cause &
(AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR))
......
...@@ -306,6 +306,8 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) ...@@ -306,6 +306,8 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
ar9003_mci_get_isr(ah, masked); ar9003_mci_get_isr(ah, masked);
if (sync_cause) { if (sync_cause) {
ath9k_debug_sync_cause(common, sync_cause);
if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);
REG_WRITE(ah, AR_RC, 0); REG_WRITE(ah, AR_RC, 0);
......
...@@ -380,63 +380,75 @@ static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, ...@@ -380,63 +380,75 @@ static ssize_t read_file_interrupt(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[512];
unsigned int len = 0; unsigned int len = 0;
int rv;
int mxlen = 4000;
char *buf = kmalloc(mxlen, GFP_KERNEL);
if (!buf)
return -ENOMEM;
#define PR_IS(a, s) \
do { \
len += snprintf(buf + len, mxlen - len, \
"%21s: %10u\n", a, \
sc->debug.stats.istats.s); \
} while (0)
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
len += snprintf(buf + len, sizeof(buf) - len, PR_IS("RXLP", rxlp);
"%8s: %10u\n", "RXLP", sc->debug.stats.istats.rxlp); PR_IS("RXHP", rxhp);
len += snprintf(buf + len, sizeof(buf) - len, PR_IS("WATHDOG", bb_watchdog);
"%8s: %10u\n", "RXHP", sc->debug.stats.istats.rxhp);
len += snprintf(buf + len, sizeof(buf) - len,
"%8s: %10u\n", "WATCHDOG",
sc->debug.stats.istats.bb_watchdog);
} else { } else {
len += snprintf(buf + len, sizeof(buf) - len, PR_IS("RX", rxok);
"%8s: %10u\n", "RX", sc->debug.stats.istats.rxok);
} }
len += snprintf(buf + len, sizeof(buf) - len, PR_IS("RXEOL", rxeol);
"%8s: %10u\n", "RXEOL", sc->debug.stats.istats.rxeol); PR_IS("RXORN", rxorn);
len += snprintf(buf + len, sizeof(buf) - len, PR_IS("TX", txok);
"%8s: %10u\n", "RXORN", sc->debug.stats.istats.rxorn); PR_IS("TXURN", txurn);
len += snprintf(buf + len, sizeof(buf) - len, PR_IS("MIB", mib);
"%8s: %10u\n", "TX", sc->debug.stats.istats.txok); PR_IS("RXPHY", rxphyerr);
len += snprintf(buf + len, sizeof(buf) - len, PR_IS("RXKCM", rx_keycache_miss);
"%8s: %10u\n", "TXURN", sc->debug.stats.istats.txurn); PR_IS("SWBA", swba);
len += snprintf(buf + len, sizeof(buf) - len, PR_IS("BMISS", bmiss);
"%8s: %10u\n", "MIB", sc->debug.stats.istats.mib); PR_IS("BNR", bnr);
len += snprintf(buf + len, sizeof(buf) - len, PR_IS("CST", cst);
"%8s: %10u\n", "RXPHY", sc->debug.stats.istats.rxphyerr); PR_IS("GTT", gtt);
len += snprintf(buf + len, sizeof(buf) - len, PR_IS("TIM", tim);
"%8s: %10u\n", "RXKCM", sc->debug.stats.istats.rx_keycache_miss); PR_IS("CABEND", cabend);
len += snprintf(buf + len, sizeof(buf) - len, PR_IS("DTIMSYNC", dtimsync);
"%8s: %10u\n", "SWBA", sc->debug.stats.istats.swba); PR_IS("DTIM", dtim);
len += snprintf(buf + len, sizeof(buf) - len, PR_IS("TSFOOR", tsfoor);
"%8s: %10u\n", "BMISS", sc->debug.stats.istats.bmiss); PR_IS("TOTAL", total);
len += snprintf(buf + len, sizeof(buf) - len,
"%8s: %10u\n", "BNR", sc->debug.stats.istats.bnr); len += snprintf(buf + len, mxlen - len,
len += snprintf(buf + len, sizeof(buf) - len, "SYNC_CAUSE stats:\n");
"%8s: %10u\n", "CST", sc->debug.stats.istats.cst);
len += snprintf(buf + len, sizeof(buf) - len, PR_IS("Sync-All", sync_cause_all);
"%8s: %10u\n", "GTT", sc->debug.stats.istats.gtt); PR_IS("RTC-IRQ", sync_rtc_irq);
len += snprintf(buf + len, sizeof(buf) - len, PR_IS("MAC-IRQ", sync_mac_irq);
"%8s: %10u\n", "TIM", sc->debug.stats.istats.tim); PR_IS("EEPROM-Illegal-Access", eeprom_illegal_access);
len += snprintf(buf + len, sizeof(buf) - len, PR_IS("APB-Timeout", apb_timeout);
"%8s: %10u\n", "CABEND", sc->debug.stats.istats.cabend); PR_IS("PCI-Mode-Conflict", pci_mode_conflict);
len += snprintf(buf + len, sizeof(buf) - len, PR_IS("HOST1-Fatal", host1_fatal);
"%8s: %10u\n", "DTIMSYNC", sc->debug.stats.istats.dtimsync); PR_IS("HOST1-Perr", host1_perr);
len += snprintf(buf + len, sizeof(buf) - len, PR_IS("TRCV-FIFO-Perr", trcv_fifo_perr);
"%8s: %10u\n", "DTIM", sc->debug.stats.istats.dtim); PR_IS("RADM-CPL-EP", radm_cpl_ep);
len += snprintf(buf + len, sizeof(buf) - len, PR_IS("RADM-CPL-DLLP-Abort", radm_cpl_dllp_abort);
"%8s: %10u\n", "TSFOOR", sc->debug.stats.istats.tsfoor); PR_IS("RADM-CPL-TLP-Abort", radm_cpl_tlp_abort);
len += snprintf(buf + len, sizeof(buf) - len, PR_IS("RADM-CPL-ECRC-Err", radm_cpl_ecrc_err);
"%8s: %10u\n", "TOTAL", sc->debug.stats.istats.total); PR_IS("RADM-CPL-Timeout", radm_cpl_timeout);
PR_IS("Local-Bus-Timeout", local_timeout);
PR_IS("PM-Access", pm_access);
if (len > sizeof(buf)) PR_IS("MAC-Awake", mac_awake);
len = sizeof(buf); PR_IS("MAC-Asleep", mac_asleep);
PR_IS("MAC-Sleep-Access", mac_sleep_access);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
if (len > mxlen)
len = mxlen;
rv = simple_read_from_buffer(user_buf, count, ppos, buf, len);
kfree(buf);
return rv;
} }
static const struct file_operations fops_interrupt = { static const struct file_operations fops_interrupt = {
......
...@@ -60,6 +60,7 @@ struct ath_buf; ...@@ -60,6 +60,7 @@ struct ath_buf;
* @tsfoor: TSF out of range, indicates that the corrected TSF received * @tsfoor: TSF out of range, indicates that the corrected TSF received
* from a beacon differs from the PCU's internal TSF by more than a * from a beacon differs from the PCU's internal TSF by more than a
* (programmable) threshold * (programmable) threshold
* @local_timeout: Internal bus timeout.
*/ */
struct ath_interrupt_stats { struct ath_interrupt_stats {
u32 total; u32 total;
...@@ -85,8 +86,30 @@ struct ath_interrupt_stats { ...@@ -85,8 +86,30 @@ struct ath_interrupt_stats {
u32 dtim; u32 dtim;
u32 bb_watchdog; u32 bb_watchdog;
u32 tsfoor; u32 tsfoor;
/* Sync-cause stats */
u32 sync_cause_all;
u32 sync_rtc_irq;
u32 sync_mac_irq;
u32 eeprom_illegal_access;
u32 apb_timeout;
u32 pci_mode_conflict;
u32 host1_fatal;
u32 host1_perr;
u32 trcv_fifo_perr;
u32 radm_cpl_ep;
u32 radm_cpl_dllp_abort;
u32 radm_cpl_tlp_abort;
u32 radm_cpl_ecrc_err;
u32 radm_cpl_timeout;
u32 local_timeout;
u32 pm_access;
u32 mac_awake;
u32 mac_asleep;
u32 mac_sleep_access;
}; };
/** /**
* struct ath_tx_stats - Statistics about TX * struct ath_tx_stats - Statistics about TX
* @tx_pkts_all: No. of total frames transmitted, including ones that * @tx_pkts_all: No. of total frames transmitted, including ones that
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
#include "rc.h" #include "rc.h"
#include "ar9003_mac.h" #include "ar9003_mac.h"
#include "ar9003_mci.h" #include "ar9003_mci.h"
#include "debug.h"
#include "ath9k.h"
static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type); static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type);
...@@ -83,6 +85,53 @@ static void ath9k_hw_ani_cache_ini_regs(struct ath_hw *ah) ...@@ -83,6 +85,53 @@ static void ath9k_hw_ani_cache_ini_regs(struct ath_hw *ah)
/* Helper Functions */ /* Helper Functions */
/********************/ /********************/
#ifdef CONFIG_ATH9K_DEBUGFS
void ath9k_debug_sync_cause(struct ath_common *common, u32 sync_cause)
{
struct ath_softc *sc = common->priv;
if (sync_cause)
sc->debug.stats.istats.sync_cause_all++;
if (sync_cause & AR_INTR_SYNC_RTC_IRQ)
sc->debug.stats.istats.sync_rtc_irq++;
if (sync_cause & AR_INTR_SYNC_MAC_IRQ)
sc->debug.stats.istats.sync_mac_irq++;
if (sync_cause & AR_INTR_SYNC_EEPROM_ILLEGAL_ACCESS)
sc->debug.stats.istats.eeprom_illegal_access++;
if (sync_cause & AR_INTR_SYNC_APB_TIMEOUT)
sc->debug.stats.istats.apb_timeout++;
if (sync_cause & AR_INTR_SYNC_PCI_MODE_CONFLICT)
sc->debug.stats.istats.pci_mode_conflict++;
if (sync_cause & AR_INTR_SYNC_HOST1_FATAL)
sc->debug.stats.istats.host1_fatal++;
if (sync_cause & AR_INTR_SYNC_HOST1_PERR)
sc->debug.stats.istats.host1_perr++;
if (sync_cause & AR_INTR_SYNC_TRCV_FIFO_PERR)
sc->debug.stats.istats.trcv_fifo_perr++;
if (sync_cause & AR_INTR_SYNC_RADM_CPL_EP)
sc->debug.stats.istats.radm_cpl_ep++;
if (sync_cause & AR_INTR_SYNC_RADM_CPL_DLLP_ABORT)
sc->debug.stats.istats.radm_cpl_dllp_abort++;
if (sync_cause & AR_INTR_SYNC_RADM_CPL_TLP_ABORT)
sc->debug.stats.istats.radm_cpl_tlp_abort++;
if (sync_cause & AR_INTR_SYNC_RADM_CPL_ECRC_ERR)
sc->debug.stats.istats.radm_cpl_ecrc_err++;
if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT)
sc->debug.stats.istats.radm_cpl_timeout++;
if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT)
sc->debug.stats.istats.local_timeout++;
if (sync_cause & AR_INTR_SYNC_PM_ACCESS)
sc->debug.stats.istats.pm_access++;
if (sync_cause & AR_INTR_SYNC_MAC_AWAKE)
sc->debug.stats.istats.mac_awake++;
if (sync_cause & AR_INTR_SYNC_MAC_ASLEEP)
sc->debug.stats.istats.mac_asleep++;
if (sync_cause & AR_INTR_SYNC_MAC_SLEEP_ACCESS)
sc->debug.stats.istats.mac_sleep_access++;
}
#endif
static void ath9k_hw_set_clockrate(struct ath_hw *ah) static void ath9k_hw_set_clockrate(struct ath_hw *ah)
{ {
struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
......
...@@ -956,6 +956,12 @@ bool ath9k_hw_check_alive(struct ath_hw *ah); ...@@ -956,6 +956,12 @@ bool ath9k_hw_check_alive(struct ath_hw *ah);
bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode); bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);
#ifdef CONFIG_ATH9K_DEBUGFS
void ath9k_debug_sync_cause(struct ath_common *common, u32 sync_cause);
#else
static void ath9k_debug_sync_cause(struct ath_common *common, u32 sync_cause) {}
#endif
/* Generic hw timer primitives */ /* Generic hw timer primitives */
struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
void (*trigger)(void *), void (*trigger)(void *),
......
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