Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
mariux64
/
linux
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
2
Pull requests
0
Actions
Projects
0
Wiki
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security
Insights
Files
181c007
Breadcrumbs
linux
/
drivers
/
net
/
wireless
/
ath
/
ath9k
/
debug.c
Blame
Blame
Latest commit
History
History
1415 lines (1207 loc) · 39.8 KB
Breadcrumbs
linux
/
drivers
/
net
/
wireless
/
ath
/
ath9k
/
debug.c
Top
File metadata and controls
Code
Blame
1415 lines (1207 loc) · 39.8 KB
Raw
/* * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <linux/slab.h> #include <linux/vmalloc.h> #include <linux/export.h> #include <asm/unaligned.h> #include "ath9k.h" #define REG_WRITE_D(_ah, _reg, _val) \ ath9k_hw_common(_ah)->ops->write((_ah), (_val), (_reg)) #define REG_READ_D(_ah, _reg) \ ath9k_hw_common(_ah)->ops->read((_ah), (_reg)) void ath9k_debug_sync_cause(struct ath_softc *sc, u32 sync_cause) { 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++; } static ssize_t ath9k_debugfs_read_buf(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { u8 *buf = file->private_data; return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); } static int ath9k_debugfs_release_buf(struct inode *inode, struct file *file) { vfree(file->private_data); return 0; } #ifdef CONFIG_ATH_DEBUG static ssize_t read_file_debug(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; struct ath_common *common = ath9k_hw_common(sc->sc_ah); char buf[32]; unsigned int len; len = sprintf(buf, "0x%08x\n", common->debug_mask); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } static ssize_t write_file_debug(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; struct ath_common *common = ath9k_hw_common(sc->sc_ah); unsigned long mask; char buf[32]; ssize_t len; len = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, len)) return -EFAULT; buf[len] = '\0'; if (kstrtoul(buf, 0, &mask)) return -EINVAL; common->debug_mask = mask; return count; } static const struct file_operations fops_debug = { .read = read_file_debug, .write = write_file_debug, .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; #endif #define DMA_BUF_LEN 1024 static ssize_t read_file_ani(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_hw *ah = sc->sc_ah; unsigned int len = 0; const unsigned int size = 1024; ssize_t retval = 0; char *buf; int i; struct { const char *name; unsigned int val; } ani_info[] = { { "ANI RESET", ah->stats.ast_ani_reset }, { "OFDM LEVEL", ah->ani.ofdmNoiseImmunityLevel }, { "CCK LEVEL", ah->ani.cckNoiseImmunityLevel }, { "SPUR UP", ah->stats.ast_ani_spurup }, { "SPUR DOWN", ah->stats.ast_ani_spurup }, { "OFDM WS-DET ON", ah->stats.ast_ani_ofdmon }, { "OFDM WS-DET OFF", ah->stats.ast_ani_ofdmoff }, { "MRC-CCK ON", ah->stats.ast_ani_ccklow }, { "MRC-CCK OFF", ah->stats.ast_ani_cckhigh }, { "FIR-STEP UP", ah->stats.ast_ani_stepup }, { "FIR-STEP DOWN", ah->stats.ast_ani_stepdown }, { "INV LISTENTIME", ah->stats.ast_ani_lneg_or_lzero }, { "OFDM ERRORS", ah->stats.ast_ani_ofdmerrs }, { "CCK ERRORS", ah->stats.ast_ani_cckerrs }, }; buf = kzalloc(size, GFP_KERNEL); if (buf == NULL) return -ENOMEM; len += scnprintf(buf + len, size - len, "%15s: %s\n", "ANI", common->disable_ani ? "DISABLED" : "ENABLED"); if (common->disable_ani) goto exit; for (i = 0; i < ARRAY_SIZE(ani_info); i++) len += scnprintf(buf + len, size - len, "%15s: %u\n", ani_info[i].name, ani_info[i].val); exit: if (len > size) len = size; retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); kfree(buf); return retval; } static ssize_t write_file_ani(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; struct ath_common *common = ath9k_hw_common(sc->sc_ah); unsigned long ani; char buf[32]; ssize_t len; len = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, len)) return -EFAULT; buf[len] = '\0'; if (kstrtoul(buf, 0, &ani)) return -EINVAL; if (ani > 1) return -EINVAL; common->disable_ani = !ani; if (common->disable_ani) { clear_bit(ATH_OP_ANI_RUN, &common->op_flags); ath_stop_ani(sc); } else { ath_check_ani(sc); } return count; } static const struct file_operations fops_ani = { .read = read_file_ani, .write = write_file_ani, .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT static ssize_t read_file_bt_ant_diversity(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; struct ath_common *common = ath9k_hw_common(sc->sc_ah); char buf[32]; unsigned int len; len = sprintf(buf, "%d\n", common->bt_ant_diversity); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } static ssize_t write_file_bt_ant_diversity(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath9k_hw_capabilities *pCap = &sc->sc_ah->caps; unsigned long bt_ant_diversity; char buf[32]; ssize_t len; len = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, len)) return -EFAULT; if (!(pCap->hw_caps & ATH9K_HW_CAP_BT_ANT_DIV)) goto exit; buf[len] = '\0'; if (kstrtoul(buf, 0, &bt_ant_diversity)) return -EINVAL; common->bt_ant_diversity = !!bt_ant_diversity; ath9k_ps_wakeup(sc); ath9k_hw_set_bt_ant_diversity(sc->sc_ah, common->bt_ant_diversity); ath_dbg(common, CONFIG, "Enable WLAN/BT RX Antenna diversity: %d\n", common->bt_ant_diversity); ath9k_ps_restore(sc); exit: return count; } static const struct file_operations fops_bt_ant_diversity = { .read = read_file_bt_ant_diversity, .write = write_file_bt_ant_diversity, .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; #endif void ath9k_debug_stat_ant(struct ath_softc *sc, struct ath_hw_antcomb_conf *div_ant_conf, int main_rssi_avg, int alt_rssi_avg) { struct ath_antenna_stats *as_main = &sc->debug.stats.ant_stats[ANT_MAIN]; struct ath_antenna_stats *as_alt = &sc->debug.stats.ant_stats[ANT_ALT]; as_main->lna_attempt_cnt[div_ant_conf->main_lna_conf]++; as_alt->lna_attempt_cnt[div_ant_conf->alt_lna_conf]++; as_main->rssi_avg = main_rssi_avg; as_alt->rssi_avg = alt_rssi_avg; } static ssize_t read_file_antenna_diversity(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; struct ath_hw *ah = sc->sc_ah; struct ath9k_hw_capabilities *pCap = &ah->caps; struct ath_antenna_stats *as_main = &sc->debug.stats.ant_stats[ANT_MAIN]; struct ath_antenna_stats *as_alt = &sc->debug.stats.ant_stats[ANT_ALT]; struct ath_hw_antcomb_conf div_ant_conf; unsigned int len = 0; const unsigned int size = 1024; ssize_t retval = 0; char *buf; static const char *lna_conf_str[4] = { "LNA1_MINUS_LNA2", "LNA2", "LNA1", "LNA1_PLUS_LNA2" }; buf = kzalloc(size, GFP_KERNEL); if (buf == NULL) return -ENOMEM; if (!(pCap->hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)) { len += scnprintf(buf + len, size - len, "%s\n", "Antenna Diversity Combining is disabled"); goto exit; } ath9k_ps_wakeup(sc); ath9k_hw_antdiv_comb_conf_get(ah, &div_ant_conf); len += scnprintf(buf + len, size - len, "Current MAIN config : %s\n", lna_conf_str[div_ant_conf.main_lna_conf]); len += scnprintf(buf + len, size - len, "Current ALT config : %s\n", lna_conf_str[div_ant_conf.alt_lna_conf]); len += scnprintf(buf + len, size - len, "Average MAIN RSSI : %d\n", as_main->rssi_avg); len += scnprintf(buf + len, size - len, "Average ALT RSSI : %d\n\n", as_alt->rssi_avg); ath9k_ps_restore(sc); len += scnprintf(buf + len, size - len, "Packet Receive Cnt:\n"); len += scnprintf(buf + len, size - len, "-------------------\n"); len += scnprintf(buf + len, size - len, "%30s%15s\n", "MAIN", "ALT"); len += scnprintf(buf + len, size - len, "%-14s:%15d%15d\n", "TOTAL COUNT", as_main->recv_cnt, as_alt->recv_cnt); len += scnprintf(buf + len, size - len, "%-14s:%15d%15d\n", "LNA1", as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1], as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1]); len += scnprintf(buf + len, size - len, "%-14s:%15d%15d\n", "LNA2", as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA2], as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA2]); len += scnprintf(buf + len, size - len, "%-14s:%15d%15d\n", "LNA1 + LNA2", as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2], as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2]); len += scnprintf(buf + len, size - len, "%-14s:%15d%15d\n", "LNA1 - LNA2", as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2], as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2]); len += scnprintf(buf + len, size - len, "\nLNA Config Attempts:\n"); len += scnprintf(buf + len, size - len, "--------------------\n"); len += scnprintf(buf + len, size - len, "%30s%15s\n", "MAIN", "ALT"); len += scnprintf(buf + len, size - len, "%-14s:%15d%15d\n", "LNA1", as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1], as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1]); len += scnprintf(buf + len, size - len, "%-14s:%15d%15d\n", "LNA2", as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA2], as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA2]); len += scnprintf(buf + len, size - len, "%-14s:%15d%15d\n", "LNA1 + LNA2", as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2], as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2]); len += scnprintf(buf + len, size - len, "%-14s:%15d%15d\n", "LNA1 - LNA2", as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2], as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2]); exit: if (len > size) len = size; retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); kfree(buf); return retval; } static const struct file_operations fops_antenna_diversity = { .read = read_file_antenna_diversity, .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; static int read_file_dma(struct seq_file *file, void *data) { struct ieee80211_hw *hw = dev_get_drvdata(file->private); struct ath_softc *sc = hw->priv; struct ath_hw *ah = sc->sc_ah; u32 val[ATH9K_NUM_DMA_DEBUG_REGS]; int i, qcuOffset = 0, dcuOffset = 0; u32 *qcuBase = &val[0], *dcuBase = &val[4]; ath9k_ps_wakeup(sc); REG_WRITE_D(ah, AR_MACMISC, ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) | (AR_MACMISC_MISC_OBS_BUS_1 << AR_MACMISC_MISC_OBS_BUS_MSB_S))); seq_puts(file, "Raw DMA Debug values:\n"); for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) { if (i % 4 == 0) seq_puts(file, "\n"); val[i] = REG_READ_D(ah, AR_DMADBG_0 + (i * sizeof(u32))); seq_printf(file, "%d: %08x ", i, val[i]); } seq_puts(file, "\n\n"); seq_puts(file, "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n"); for (i = 0; i < ATH9K_NUM_QUEUES; i++, qcuOffset += 4, dcuOffset += 5) { if (i == 8) { qcuOffset = 0; qcuBase++; } if (i == 6) { dcuOffset = 0; dcuBase++; } seq_printf(file, "%2d %2x %1x %2x %2x\n", i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset, (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3), (val[2] & (0x7 << (i * 3))) >> (i * 3), (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset); } seq_puts(file, "\n"); seq_printf(file, "qcu_stitch state: %2x qcu_fetch state: %2x\n", (val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22); seq_printf(file, "qcu_complete state: %2x dcu_complete state: %2x\n", (val[3] & 0x1c000000) >> 26, (val[6] & 0x3)); seq_printf(file, "dcu_arb state: %2x dcu_fp state: %2x\n", (val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27); seq_printf(file, "chan_idle_dur: %3d chan_idle_dur_valid: %1d\n", (val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10); seq_printf(file, "txfifo_valid_0: %1d txfifo_valid_1: %1d\n", (val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12); seq_printf(file, "txfifo_dcu_num_0: %2d txfifo_dcu_num_1: %2d\n", (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17); seq_printf(file, "pcu observe: 0x%x\n", REG_READ_D(ah, AR_OBS_BUS_1)); seq_printf(file, "AR_CR: 0x%x\n", REG_READ_D(ah, AR_CR)); ath9k_ps_restore(sc); return 0; } void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status) { if (status) sc->debug.stats.istats.total++; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { if (status & ATH9K_INT_RXLP) sc->debug.stats.istats.rxlp++; if (status & ATH9K_INT_RXHP) sc->debug.stats.istats.rxhp++; if (status & ATH9K_INT_BB_WATCHDOG) sc->debug.stats.istats.bb_watchdog++; } else { if (status & ATH9K_INT_RX) sc->debug.stats.istats.rxok++; } if (status & ATH9K_INT_RXEOL) sc->debug.stats.istats.rxeol++; if (status & ATH9K_INT_RXORN) sc->debug.stats.istats.rxorn++; if (status & ATH9K_INT_TX) sc->debug.stats.istats.txok++; if (status & ATH9K_INT_TXURN) sc->debug.stats.istats.txurn++; if (status & ATH9K_INT_RXPHY) sc->debug.stats.istats.rxphyerr++; if (status & ATH9K_INT_RXKCM) sc->debug.stats.istats.rx_keycache_miss++; if (status & ATH9K_INT_SWBA) sc->debug.stats.istats.swba++; if (status & ATH9K_INT_BMISS) sc->debug.stats.istats.bmiss++; if (status & ATH9K_INT_BNR) sc->debug.stats.istats.bnr++; if (status & ATH9K_INT_CST) sc->debug.stats.istats.cst++; if (status & ATH9K_INT_GTT) sc->debug.stats.istats.gtt++; if (status & ATH9K_INT_TIM) sc->debug.stats.istats.tim++; if (status & ATH9K_INT_CABEND) sc->debug.stats.istats.cabend++; if (status & ATH9K_INT_DTIMSYNC) sc->debug.stats.istats.dtimsync++; if (status & ATH9K_INT_DTIM) sc->debug.stats.istats.dtim++; if (status & ATH9K_INT_TSFOOR) sc->debug.stats.istats.tsfoor++; if (status & ATH9K_INT_MCI) sc->debug.stats.istats.mci++; if (status & ATH9K_INT_GENTIMER) sc->debug.stats.istats.gen_timer++; } static int read_file_interrupt(struct seq_file *file, void *data) { struct ieee80211_hw *hw = dev_get_drvdata(file->private); struct ath_softc *sc = hw->priv; #define PR_IS(a, s) \ do { \ seq_printf(file, "%21s: %10u\n", a, \ sc->debug.stats.istats.s); \ } while (0) if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { PR_IS("RXLP", rxlp); PR_IS("RXHP", rxhp); PR_IS("WATHDOG", bb_watchdog); } else { PR_IS("RX", rxok); } PR_IS("RXEOL", rxeol); PR_IS("RXORN", rxorn); PR_IS("TX", txok); PR_IS("TXURN", txurn); PR_IS("MIB", mib); PR_IS("RXPHY", rxphyerr); PR_IS("RXKCM", rx_keycache_miss); PR_IS("SWBA", swba); PR_IS("BMISS", bmiss); PR_IS("BNR", bnr); PR_IS("CST", cst); PR_IS("GTT", gtt); PR_IS("TIM", tim); PR_IS("CABEND", cabend); PR_IS("DTIMSYNC", dtimsync); PR_IS("DTIM", dtim); PR_IS("TSFOOR", tsfoor); PR_IS("MCI", mci); PR_IS("GENTIMER", gen_timer); PR_IS("TOTAL", total); seq_puts(file, "SYNC_CAUSE stats:\n"); PR_IS("Sync-All", sync_cause_all); PR_IS("RTC-IRQ", sync_rtc_irq); PR_IS("MAC-IRQ", sync_mac_irq); PR_IS("EEPROM-Illegal-Access", eeprom_illegal_access); PR_IS("APB-Timeout", apb_timeout); PR_IS("PCI-Mode-Conflict", pci_mode_conflict); PR_IS("HOST1-Fatal", host1_fatal); PR_IS("HOST1-Perr", host1_perr); PR_IS("TRCV-FIFO-Perr", trcv_fifo_perr); PR_IS("RADM-CPL-EP", radm_cpl_ep); PR_IS("RADM-CPL-DLLP-Abort", radm_cpl_dllp_abort); PR_IS("RADM-CPL-TLP-Abort", radm_cpl_tlp_abort); PR_IS("RADM-CPL-ECRC-Err", radm_cpl_ecrc_err); PR_IS("RADM-CPL-Timeout", radm_cpl_timeout); PR_IS("Local-Bus-Timeout", local_timeout); PR_IS("PM-Access", pm_access); PR_IS("MAC-Awake", mac_awake); PR_IS("MAC-Asleep", mac_asleep); PR_IS("MAC-Sleep-Access", mac_sleep_access); return 0; } static int read_file_xmit(struct seq_file *file, void *data) { struct ieee80211_hw *hw = dev_get_drvdata(file->private); struct ath_softc *sc = hw->priv; seq_printf(file, "%30s %10s%10s%10s\n\n", "BE", "BK", "VI", "VO"); PR("MPDUs Queued: ", queued); PR("MPDUs Completed: ", completed); PR("MPDUs XRetried: ", xretries); PR("Aggregates: ", a_aggr); PR("AMPDUs Queued HW:", a_queued_hw); PR("AMPDUs Queued SW:", a_queued_sw); PR("AMPDUs Completed:", a_completed); PR("AMPDUs Retried: ", a_retries); PR("AMPDUs XRetried: ", a_xretries); PR("TXERR Filtered: ", txerr_filtered); 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); PR("TX-Pkts-All: ", tx_pkts_all); PR("TX-Bytes-All: ", tx_bytes_all); PR("HW-put-tx-buf: ", puttxbuf); PR("HW-tx-start: ", txstart); PR("HW-tx-proc-desc: ", txprocdesc); PR("TX-Failed: ", txfailed); return 0; } static void print_queue(struct ath_softc *sc, struct ath_txq *txq, struct seq_file *file) { ath_txq_lock(sc, txq); seq_printf(file, "%s: %d ", "qnum", txq->axq_qnum); seq_printf(file, "%s: %2d ", "qdepth", txq->axq_depth); seq_printf(file, "%s: %2d ", "ampdu-depth", txq->axq_ampdu_depth); seq_printf(file, "%s: %3d ", "pending", txq->pending_frames); seq_printf(file, "%s: %d\n", "stopped", txq->stopped); ath_txq_unlock(sc, txq); } static int read_file_queues(struct seq_file *file, void *data) { struct ieee80211_hw *hw = dev_get_drvdata(file->private); struct ath_softc *sc = hw->priv; struct ath_txq *txq; int i; static const char *qname[4] = { "VO", "VI", "BE", "BK" }; for (i = 0; i < IEEE80211_NUM_ACS; i++) { txq = sc->tx.txq_map[i]; seq_printf(file, "(%s): ", qname[i]); print_queue(sc, txq, file); } seq_puts(file, "(CAB): "); print_queue(sc, sc->beacon.cabq, file); return 0; } static int read_file_misc(struct seq_file *file, void *data) { struct ieee80211_hw *hw = dev_get_drvdata(file->private); struct ath_softc *sc = hw->priv; struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath9k_vif_iter_data iter_data; struct ath_chanctx *ctx; unsigned int reg; u32 rxfilter, i; seq_printf(file, "BSSID: %pM\n", common->curbssid); seq_printf(file, "BSSID-MASK: %pM\n", common->bssidmask); seq_printf(file, "OPMODE: %s\n", ath_opmode_to_string(sc->sc_ah->opmode)); ath9k_ps_wakeup(sc); rxfilter = ath9k_hw_getrxfilter(sc->sc_ah); ath9k_ps_restore(sc); seq_printf(file, "RXFILTER: 0x%x", rxfilter); if (rxfilter & ATH9K_RX_FILTER_UCAST) seq_puts(file, " UCAST"); if (rxfilter & ATH9K_RX_FILTER_MCAST) seq_puts(file, " MCAST"); if (rxfilter & ATH9K_RX_FILTER_BCAST) seq_puts(file, " BCAST"); if (rxfilter & ATH9K_RX_FILTER_CONTROL) seq_puts(file, " CONTROL"); if (rxfilter & ATH9K_RX_FILTER_BEACON) seq_puts(file, " BEACON"); if (rxfilter & ATH9K_RX_FILTER_PROM) seq_puts(file, " PROM"); if (rxfilter & ATH9K_RX_FILTER_PROBEREQ) seq_puts(file, " PROBEREQ"); if (rxfilter & ATH9K_RX_FILTER_PHYERR) seq_puts(file, " PHYERR"); if (rxfilter & ATH9K_RX_FILTER_MYBEACON) seq_puts(file, " MYBEACON"); if (rxfilter & ATH9K_RX_FILTER_COMP_BAR) seq_puts(file, " COMP_BAR"); if (rxfilter & ATH9K_RX_FILTER_PSPOLL) seq_puts(file, " PSPOLL"); if (rxfilter & ATH9K_RX_FILTER_PHYRADAR) seq_puts(file, " PHYRADAR"); if (rxfilter & ATH9K_RX_FILTER_MCAST_BCAST_ALL) seq_puts(file, " MCAST_BCAST_ALL"); if (rxfilter & ATH9K_RX_FILTER_CONTROL_WRAPPER) seq_puts(file, " CONTROL_WRAPPER"); seq_puts(file, "\n"); reg = sc->sc_ah->imask; seq_printf(file, "INTERRUPT-MASK: 0x%x", reg); if (reg & ATH9K_INT_SWBA) seq_puts(file, " SWBA"); if (reg & ATH9K_INT_BMISS) seq_puts(file, " BMISS"); if (reg & ATH9K_INT_CST) seq_puts(file, " CST"); if (reg & ATH9K_INT_RX) seq_puts(file, " RX"); if (reg & ATH9K_INT_RXHP) seq_puts(file, " RXHP"); if (reg & ATH9K_INT_RXLP) seq_puts(file, " RXLP"); if (reg & ATH9K_INT_BB_WATCHDOG) seq_puts(file, " BB_WATCHDOG"); seq_puts(file, "\n"); i = 0; ath_for_each_chanctx(sc, ctx) { if (list_empty(&ctx->vifs)) continue; ath9k_calculate_iter_data(sc, ctx, &iter_data); seq_printf(file, "VIFS: CTX %i(%i) AP: %i STA: %i MESH: %i WDS: %i", i++, (int)(ctx->assigned), iter_data.naps, iter_data.nstations, iter_data.nmeshes, iter_data.nwds); seq_printf(file, " ADHOC: %i OCB: %i TOTAL: %hi BEACON-VIF: %hi\n", iter_data.nadhocs, iter_data.nocbs, sc->cur_chan->nvifs, sc->nbcnvifs); } return 0; } static int read_file_reset(struct seq_file *file, void *data) { struct ieee80211_hw *hw = dev_get_drvdata(file->private); struct ath_softc *sc = hw->priv; static const char * const reset_cause[__RESET_TYPE_MAX] = { [RESET_TYPE_BB_HANG] = "Baseband Hang", [RESET_TYPE_BB_WATCHDOG] = "Baseband Watchdog", [RESET_TYPE_FATAL_INT] = "Fatal HW Error", [RESET_TYPE_TX_ERROR] = "TX HW error", [RESET_TYPE_TX_GTT] = "Transmit timeout", [RESET_TYPE_TX_HANG] = "TX Path Hang", [RESET_TYPE_PLL_HANG] = "PLL RX Hang", [RESET_TYPE_MAC_HANG] = "MAC Hang", [RESET_TYPE_BEACON_STUCK] = "Stuck Beacon", [RESET_TYPE_MCI] = "MCI Reset", [RESET_TYPE_CALIBRATION] = "Calibration error", [RESET_TX_DMA_ERROR] = "Tx DMA stop error", [RESET_RX_DMA_ERROR] = "Rx DMA stop error", }; int i; for (i = 0; i < ARRAY_SIZE(reset_cause); i++) { if (!reset_cause[i]) continue; seq_printf(file, "%17s: %2d\n", reset_cause[i], sc->debug.stats.reset[i]); } return 0; } void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, struct ath_tx_status *ts, struct ath_txq *txq, unsigned int flags) { int qnum = txq->axq_qnum; TX_STAT_INC(qnum, tx_pkts_all); sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len; if (bf_isampdu(bf)) { if (flags & ATH_TX_ERROR) TX_STAT_INC(qnum, a_xretries); else TX_STAT_INC(qnum, a_completed); } else { if (ts->ts_status & ATH9K_TXERR_XRETRY) TX_STAT_INC(qnum, xretries); else TX_STAT_INC(qnum, completed); } if (ts->ts_status & ATH9K_TXERR_FILT) TX_STAT_INC(qnum, txerr_filtered); if (ts->ts_status & ATH9K_TXERR_FIFO) TX_STAT_INC(qnum, fifo_underrun); if (ts->ts_status & ATH9K_TXERR_XTXOP) TX_STAT_INC(qnum, xtxop); if (ts->ts_status & ATH9K_TXERR_TIMER_EXPIRED) TX_STAT_INC(qnum, timer_exp); if (ts->ts_flags & ATH9K_TX_DESC_CFG_ERR) TX_STAT_INC(qnum, desc_cfg_err); if (ts->ts_flags & ATH9K_TX_DATA_UNDERRUN) TX_STAT_INC(qnum, data_underrun); if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN) TX_STAT_INC(qnum, delim_underrun); } void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) { ath9k_cmn_debug_stat_rx(&sc->debug.stats.rxstats, rs); } static ssize_t read_file_regidx(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; char buf[32]; unsigned int len; len = sprintf(buf, "0x%08x\n", sc->debug.regidx); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } static ssize_t write_file_regidx(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; unsigned long regidx; char buf[32]; ssize_t len; len = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, len)) return -EFAULT; buf[len] = '\0'; if (kstrtoul(buf, 0, ®idx)) return -EINVAL; sc->debug.regidx = regidx; return count; } static const struct file_operations fops_regidx = { .read = read_file_regidx, .write = write_file_regidx, .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; static ssize_t read_file_regval(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; struct ath_hw *ah = sc->sc_ah; char buf[32]; unsigned int len; u32 regval; ath9k_ps_wakeup(sc); regval = REG_READ_D(ah, sc->debug.regidx); ath9k_ps_restore(sc); len = sprintf(buf, "0x%08x\n", regval); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } static ssize_t write_file_regval(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; struct ath_hw *ah = sc->sc_ah; unsigned long regval; char buf[32]; ssize_t len; len = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, len)) return -EFAULT; buf[len] = '\0'; if (kstrtoul(buf, 0, ®val)) return -EINVAL; ath9k_ps_wakeup(sc); REG_WRITE_D(ah, sc->debug.regidx, regval); ath9k_ps_restore(sc); return count; } static const struct file_operations fops_regval = { .read = read_file_regval, .write = write_file_regval, .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; #define REGDUMP_LINE_SIZE 20 static int open_file_regdump(struct inode *inode, struct file *file) { struct ath_softc *sc = inode->i_private; unsigned int len = 0; u8 *buf; int i, j = 0; unsigned long num_regs, regdump_len, max_reg_offset; const struct reg_hole { u32 start; u32 end; } reg_hole_list[] = { {0x0200, 0x07fc}, {0x0c00, 0x0ffc}, {0x2000, 0x3ffc}, {0x4100, 0x6ffc}, {0x705c, 0x7ffc}, {0x0000, 0x0000} }; max_reg_offset = AR_SREV_9300_20_OR_LATER(sc->sc_ah) ? 0x8800 : 0xb500; num_regs = max_reg_offset / 4 + 1; regdump_len = num_regs * REGDUMP_LINE_SIZE + 1; buf = vmalloc(regdump_len); if (!buf) return -ENOMEM; ath9k_ps_wakeup(sc); for (i = 0; i < num_regs; i++) { if (reg_hole_list[j].start == i << 2) { i = reg_hole_list[j].end >> 2; j++; continue; } len += scnprintf(buf + len, regdump_len - len, "0x%06x 0x%08x\n", i << 2, REG_READ(sc->sc_ah, i << 2)); } ath9k_ps_restore(sc); file->private_data = buf; return 0; } static const struct file_operations fops_regdump = { .open = open_file_regdump, .read = ath9k_debugfs_read_buf, .release = ath9k_debugfs_release_buf, .owner = THIS_MODULE, .llseek = default_llseek,/* read accesses f_pos */ }; static int read_file_dump_nfcal(struct seq_file *file, void *data) { struct ieee80211_hw *hw = dev_get_drvdata(file->private); struct ath_softc *sc = hw->priv; struct ath_hw *ah = sc->sc_ah; struct ath9k_nfcal_hist *h = sc->cur_chan->caldata.nfCalHist; struct ath_common *common = ath9k_hw_common(ah); struct ieee80211_conf *conf = &common->hw->conf; u32 i, j; u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; u8 nread; seq_printf(file, "Channel Noise Floor : %d\n", ah->noise); seq_puts(file, "Chain | privNF | # Readings | NF Readings\n"); for (i = 0; i < NUM_NF_READINGS; i++) { if (!(chainmask & (1 << i)) || ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf))) continue; nread = AR_PHY_CCA_FILTERWINDOW_LENGTH - h[i].invalidNFcount; seq_printf(file, " %d\t %d\t %d\t\t", i, h[i].privNF, nread); for (j = 0; j < nread; j++) seq_printf(file, " %d", h[i].nfCalBuffer[j]); seq_puts(file, "\n"); } return 0; } static int open_file_dump_nfcal(struct inode *inode, struct file *f) { return single_open(f, read_file_dump_nfcal, inode->i_private); } static const struct file_operations fops_dump_nfcal = { .read = seq_read, .open = open_file_dump_nfcal, .owner = THIS_MODULE, .llseek = seq_lseek, .release = single_release, }; #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT static ssize_t read_file_btcoex(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; u32 len = 0, size = 1500; char *buf; size_t retval; buf = kzalloc(size, GFP_KERNEL); if (buf == NULL) return -ENOMEM; if (!sc->sc_ah->common.btcoex_enabled) { len = scnprintf(buf, size, "%s\n", "BTCOEX is disabled"); goto exit; } len = ath9k_dump_btcoex(sc, buf, size); exit: retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); kfree(buf); return retval; } static const struct file_operations fops_btcoex = { .read = read_file_btcoex, .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; #endif #ifdef CONFIG_ATH9K_DYNACK static ssize_t read_file_ackto(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; struct ath_hw *ah = sc->sc_ah; char buf[32]; unsigned int len; len = sprintf(buf, "%u %c\n", ah->dynack.ackto, (ah->dynack.enabled) ? 'A' : 'S'); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } static const struct file_operations fops_ackto = { .read = read_file_ackto, .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; #endif #ifdef CONFIG_ATH9K_WOW static ssize_t read_file_wow(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; unsigned int len = 0, size = 32; ssize_t retval; char *buf; buf = kzalloc(size, GFP_KERNEL); if (!buf) return -ENOMEM; len += scnprintf(buf + len, size - len, "WOW: %s\n", sc->force_wow ? "ENABLED" : "DISABLED"); if (len > size) len = size; retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); kfree(buf); return retval; } static ssize_t write_file_wow(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; unsigned long val; char buf[32]; ssize_t len; len = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, len)) return -EFAULT; buf[len] = '\0'; if (kstrtoul(buf, 0, &val)) return -EINVAL; if (val != 1) return -EINVAL; if (!sc->force_wow) { sc->force_wow = true; ath9k_init_wow(sc->hw); } return count; } static const struct file_operations fops_wow = { .read = read_file_wow, .write = write_file_wow, .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; #endif static ssize_t read_file_tpc(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; struct ath_hw *ah = sc->sc_ah; unsigned int len = 0, size = 32; ssize_t retval; char *buf; buf = kzalloc(size, GFP_KERNEL); if (!buf) return -ENOMEM; len += scnprintf(buf + len, size - len, "%s\n", ah->tpc_enabled ? "ENABLED" : "DISABLED"); if (len > size) len = size; retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); kfree(buf); return retval; } static ssize_t write_file_tpc(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; struct ath_hw *ah = sc->sc_ah; unsigned long val; char buf[32]; ssize_t len; bool tpc_enabled; len = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, len)) return -EFAULT; buf[len] = '\0'; if (kstrtoul(buf, 0, &val)) return -EINVAL; if (val < 0 || val > 1) return -EINVAL; tpc_enabled = !!val; if (tpc_enabled != ah->tpc_enabled) { ah->tpc_enabled = tpc_enabled; mutex_lock(&sc->mutex); ath9k_set_txpower(sc, NULL); mutex_unlock(&sc->mutex); } return count; } static const struct file_operations fops_tpc = { .read = read_file_tpc, .write = write_file_tpc, .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; /* Ethtool support for get-stats */ #define AMKSTR(nm) #nm "_BE", #nm "_BK", #nm "_VI", #nm "_VO" static const char ath9k_gstrings_stats[][ETH_GSTRING_LEN] = { "tx_pkts_nic", "tx_bytes_nic", "rx_pkts_nic", "rx_bytes_nic", AMKSTR(d_tx_pkts), AMKSTR(d_tx_bytes), AMKSTR(d_tx_mpdus_queued), AMKSTR(d_tx_mpdus_completed), AMKSTR(d_tx_mpdu_xretries), AMKSTR(d_tx_aggregates), AMKSTR(d_tx_ampdus_queued_hw), AMKSTR(d_tx_ampdus_queued_sw), AMKSTR(d_tx_ampdus_completed), AMKSTR(d_tx_ampdu_retries), AMKSTR(d_tx_ampdu_xretries), AMKSTR(d_tx_fifo_underrun), AMKSTR(d_tx_op_exceeded), AMKSTR(d_tx_timer_expiry), AMKSTR(d_tx_desc_cfg_err), AMKSTR(d_tx_data_underrun), AMKSTR(d_tx_delim_underrun), "d_rx_crc_err", "d_rx_decrypt_crc_err", "d_rx_phy_err", "d_rx_mic_err", "d_rx_pre_delim_crc_err", "d_rx_post_delim_crc_err", "d_rx_decrypt_busy_err", "d_rx_phyerr_radar", "d_rx_phyerr_ofdm_timing", "d_rx_phyerr_cck_timing", }; #define ATH9K_SSTATS_LEN ARRAY_SIZE(ath9k_gstrings_stats) void ath9k_get_et_strings(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 sset, u8 *data) { if (sset == ETH_SS_STATS) memcpy(data, *ath9k_gstrings_stats, sizeof(ath9k_gstrings_stats)); } int ath9k_get_et_sset_count(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int sset) { if (sset == ETH_SS_STATS) return ATH9K_SSTATS_LEN; return 0; } #define AWDATA(elem) \ do { \ data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].elem; \ data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].elem; \ data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].elem; \ data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].elem; \ } while (0) #define AWDATA_RX(elem) \ do { \ data[i++] = sc->debug.stats.rxstats.elem; \ } while (0) void ath9k_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ethtool_stats *stats, u64 *data) { struct ath_softc *sc = hw->priv; int i = 0; data[i++] = (sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].tx_pkts_all + sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].tx_pkts_all + sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].tx_pkts_all + sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].tx_pkts_all); data[i++] = (sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].tx_bytes_all + sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].tx_bytes_all + sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].tx_bytes_all + sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].tx_bytes_all); AWDATA_RX(rx_pkts_all); AWDATA_RX(rx_bytes_all); AWDATA(tx_pkts_all); AWDATA(tx_bytes_all); AWDATA(queued); AWDATA(completed); AWDATA(xretries); AWDATA(a_aggr); AWDATA(a_queued_hw); AWDATA(a_queued_sw); AWDATA(a_completed); AWDATA(a_retries); AWDATA(a_xretries); AWDATA(fifo_underrun); AWDATA(xtxop); AWDATA(timer_exp); AWDATA(desc_cfg_err); AWDATA(data_underrun); AWDATA(delim_underrun); AWDATA_RX(crc_err); AWDATA_RX(decrypt_crc_err); AWDATA_RX(phy_err); AWDATA_RX(mic_err); AWDATA_RX(pre_delim_crc_err); AWDATA_RX(post_delim_crc_err); AWDATA_RX(decrypt_busy_err); AWDATA_RX(phy_err_stats[ATH9K_PHYERR_RADAR]); AWDATA_RX(phy_err_stats[ATH9K_PHYERR_OFDM_TIMING]); AWDATA_RX(phy_err_stats[ATH9K_PHYERR_CCK_TIMING]); WARN_ON(i != ATH9K_SSTATS_LEN); } void ath9k_deinit_debug(struct ath_softc *sc) { ath9k_cmn_spectral_deinit_debug(&sc->spec_priv); } int ath9k_init_debug(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); struct ath_softc *sc = (struct ath_softc *) common->priv; sc->debug.debugfs_phy = debugfs_create_dir("ath9k", sc->hw->wiphy->debugfsdir); if (!sc->debug.debugfs_phy) return -ENOMEM; #ifdef CONFIG_ATH_DEBUG debugfs_create_file("debug", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_debug); #endif ath9k_dfs_init_debug(sc); ath9k_tx99_init_debug(sc); ath9k_cmn_spectral_init_debug(&sc->spec_priv, sc->debug.debugfs_phy); debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy, read_file_dma); debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy, read_file_interrupt); debugfs_create_devm_seqfile(sc->dev, "xmit", sc->debug.debugfs_phy, read_file_xmit); debugfs_create_devm_seqfile(sc->dev, "queues", sc->debug.debugfs_phy, read_file_queues); debugfs_create_u32("qlen_bk", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, &sc->tx.txq_max_pending[IEEE80211_AC_BK]); debugfs_create_u32("qlen_be", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, &sc->tx.txq_max_pending[IEEE80211_AC_BE]); debugfs_create_u32("qlen_vi", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, &sc->tx.txq_max_pending[IEEE80211_AC_VI]); debugfs_create_u32("qlen_vo", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, &sc->tx.txq_max_pending[IEEE80211_AC_VO]); debugfs_create_devm_seqfile(sc->dev, "misc", sc->debug.debugfs_phy, read_file_misc); debugfs_create_devm_seqfile(sc->dev, "reset", sc->debug.debugfs_phy, read_file_reset); ath9k_cmn_debug_recv(sc->debug.debugfs_phy, &sc->debug.stats.rxstats); ath9k_cmn_debug_phy_err(sc->debug.debugfs_phy, &sc->debug.stats.rxstats); debugfs_create_u8("rx_chainmask", S_IRUSR, sc->debug.debugfs_phy, &ah->rxchainmask); debugfs_create_u8("tx_chainmask", S_IRUSR, sc->debug.debugfs_phy, &ah->txchainmask); debugfs_create_file("ani", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_ani); debugfs_create_bool("paprd", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, &sc->sc_ah->config.enable_paprd); debugfs_create_file("regidx", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_regidx); debugfs_create_file("regval", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_regval); debugfs_create_bool("ignore_extcca", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, &ah->config.cwm_ignore_extcca); debugfs_create_file("regdump", S_IRUSR, sc->debug.debugfs_phy, sc, &fops_regdump); debugfs_create_devm_seqfile(sc->dev, "dump_nfcal", sc->debug.debugfs_phy, read_file_dump_nfcal); ath9k_cmn_debug_base_eeprom(sc->debug.debugfs_phy, sc->sc_ah); ath9k_cmn_debug_modal_eeprom(sc->debug.debugfs_phy, sc->sc_ah); debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask); debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, &sc->sc_ah->gpio_val); debugfs_create_file("antenna_diversity", S_IRUSR, sc->debug.debugfs_phy, sc, &fops_antenna_diversity); #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT debugfs_create_file("bt_ant_diversity", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_bt_ant_diversity); debugfs_create_file("btcoex", S_IRUSR, sc->debug.debugfs_phy, sc, &fops_btcoex); #endif #ifdef CONFIG_ATH9K_WOW debugfs_create_file("wow", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_wow); #endif #ifdef CONFIG_ATH9K_DYNACK debugfs_create_file("ack_to", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_ackto); #endif debugfs_create_file("tpc", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_tpc); return 0; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
You can’t perform that action at this time.