18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (c) 2007-2008 Bruno Randolf <bruno@thinktube.com> 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * This file is free software: you may copy, redistribute and/or modify it 58c2ecf20Sopenharmony_ci * under the terms of the GNU General Public License as published by the 68c2ecf20Sopenharmony_ci * Free Software Foundation, either version 2 of the License, or (at your 78c2ecf20Sopenharmony_ci * option) any later version. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * This file is distributed in the hope that it will be useful, but 108c2ecf20Sopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of 118c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 128c2ecf20Sopenharmony_ci * General Public License for more details. 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * You should have received a copy of the GNU General Public License 158c2ecf20Sopenharmony_ci * along with this program. If not, see <http://www.gnu.org/licenses/>. 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci * This file incorporates work covered by the following copyright and 198c2ecf20Sopenharmony_ci * permission notice: 208c2ecf20Sopenharmony_ci * 218c2ecf20Sopenharmony_ci * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting 228c2ecf20Sopenharmony_ci * Copyright (c) 2004-2005 Atheros Communications, Inc. 238c2ecf20Sopenharmony_ci * Copyright (c) 2006 Devicescape Software, Inc. 248c2ecf20Sopenharmony_ci * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com> 258c2ecf20Sopenharmony_ci * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu> 268c2ecf20Sopenharmony_ci * 278c2ecf20Sopenharmony_ci * All rights reserved. 288c2ecf20Sopenharmony_ci * 298c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 308c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions 318c2ecf20Sopenharmony_ci * are met: 328c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 338c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer, 348c2ecf20Sopenharmony_ci * without modification. 358c2ecf20Sopenharmony_ci * 2. Redistributions in binary form must reproduce at minimum a disclaimer 368c2ecf20Sopenharmony_ci * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 378c2ecf20Sopenharmony_ci * redistribution must be conditioned upon including a substantially 388c2ecf20Sopenharmony_ci * similar Disclaimer requirement for further binary redistribution. 398c2ecf20Sopenharmony_ci * 3. Neither the names of the above-listed copyright holders nor the names 408c2ecf20Sopenharmony_ci * of any contributors may be used to endorse or promote products derived 418c2ecf20Sopenharmony_ci * from this software without specific prior written permission. 428c2ecf20Sopenharmony_ci * 438c2ecf20Sopenharmony_ci * Alternatively, this software may be distributed under the terms of the 448c2ecf20Sopenharmony_ci * GNU General Public License ("GPL") version 2 as published by the Free 458c2ecf20Sopenharmony_ci * Software Foundation. 468c2ecf20Sopenharmony_ci * 478c2ecf20Sopenharmony_ci * NO WARRANTY 488c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 498c2ecf20Sopenharmony_ci * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 508c2ecf20Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 518c2ecf20Sopenharmony_ci * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 528c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 538c2ecf20Sopenharmony_ci * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 548c2ecf20Sopenharmony_ci * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 558c2ecf20Sopenharmony_ci * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 568c2ecf20Sopenharmony_ci * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 578c2ecf20Sopenharmony_ci * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 588c2ecf20Sopenharmony_ci * THE POSSIBILITY OF SUCH DAMAGES. 598c2ecf20Sopenharmony_ci */ 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci#include <linux/export.h> 648c2ecf20Sopenharmony_ci#include <linux/moduleparam.h> 658c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 688c2ecf20Sopenharmony_ci#include <linux/list.h> 698c2ecf20Sopenharmony_ci#include "debug.h" 708c2ecf20Sopenharmony_ci#include "ath5k.h" 718c2ecf20Sopenharmony_ci#include "reg.h" 728c2ecf20Sopenharmony_ci#include "base.h" 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistatic unsigned int ath5k_debug; 758c2ecf20Sopenharmony_cimodule_param_named(debug, ath5k_debug, uint, 0); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci/* debugfs: registers */ 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistruct reg { 818c2ecf20Sopenharmony_ci const char *name; 828c2ecf20Sopenharmony_ci int addr; 838c2ecf20Sopenharmony_ci}; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci#define REG_STRUCT_INIT(r) { #r, r } 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci/* just a few random registers, might want to add more */ 888c2ecf20Sopenharmony_cistatic const struct reg regs[] = { 898c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_CR), 908c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_RXDP), 918c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_CFG), 928c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_IER), 938c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_BCR), 948c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_RTSD0), 958c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_RTSD1), 968c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_TXCFG), 978c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_RXCFG), 988c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_RXJLA), 998c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_MIBC), 1008c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_TOPS), 1018c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_RXNOFRM), 1028c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_TXNOFRM), 1038c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_RPGTO), 1048c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_RFCNT), 1058c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_MISC), 1068c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_QCUDCU_CLKGT), 1078c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_ISR), 1088c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_PISR), 1098c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_SISR0), 1108c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_SISR1), 1118c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_SISR2), 1128c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_SISR3), 1138c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_SISR4), 1148c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_IMR), 1158c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_PIMR), 1168c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_SIMR0), 1178c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_SIMR1), 1188c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_SIMR2), 1198c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_SIMR3), 1208c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_SIMR4), 1218c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_DCM_ADDR), 1228c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_DCCFG), 1238c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_CCFG), 1248c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_CPC0), 1258c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_CPC1), 1268c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_CPC2), 1278c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_CPC3), 1288c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_CPCOVF), 1298c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_RESET_CTL), 1308c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_SLEEP_CTL), 1318c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_INTPEND), 1328c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_SFR), 1338c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_PCICFG), 1348c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_GPIOCR), 1358c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_GPIODO), 1368c2ecf20Sopenharmony_ci REG_STRUCT_INIT(AR5K_SREV), 1378c2ecf20Sopenharmony_ci}; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_cistatic void *reg_start(struct seq_file *seq, loff_t *pos) 1408c2ecf20Sopenharmony_ci{ 1418c2ecf20Sopenharmony_ci return *pos < ARRAY_SIZE(regs) ? (void *)®s[*pos] : NULL; 1428c2ecf20Sopenharmony_ci} 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cistatic void reg_stop(struct seq_file *seq, void *p) 1458c2ecf20Sopenharmony_ci{ 1468c2ecf20Sopenharmony_ci /* nothing to do */ 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_cistatic void *reg_next(struct seq_file *seq, void *p, loff_t *pos) 1508c2ecf20Sopenharmony_ci{ 1518c2ecf20Sopenharmony_ci ++*pos; 1528c2ecf20Sopenharmony_ci return *pos < ARRAY_SIZE(regs) ? (void *)®s[*pos] : NULL; 1538c2ecf20Sopenharmony_ci} 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_cistatic int reg_show(struct seq_file *seq, void *p) 1568c2ecf20Sopenharmony_ci{ 1578c2ecf20Sopenharmony_ci struct ath5k_hw *ah = seq->private; 1588c2ecf20Sopenharmony_ci struct reg *r = p; 1598c2ecf20Sopenharmony_ci seq_printf(seq, "%-25s0x%08x\n", r->name, 1608c2ecf20Sopenharmony_ci ath5k_hw_reg_read(ah, r->addr)); 1618c2ecf20Sopenharmony_ci return 0; 1628c2ecf20Sopenharmony_ci} 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_cistatic const struct seq_operations registers_sops = { 1658c2ecf20Sopenharmony_ci .start = reg_start, 1668c2ecf20Sopenharmony_ci .next = reg_next, 1678c2ecf20Sopenharmony_ci .stop = reg_stop, 1688c2ecf20Sopenharmony_ci .show = reg_show 1698c2ecf20Sopenharmony_ci}; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ciDEFINE_SEQ_ATTRIBUTE(registers); 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci/* debugfs: beacons */ 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_cistatic ssize_t read_file_beacon(struct file *file, char __user *user_buf, 1768c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 1778c2ecf20Sopenharmony_ci{ 1788c2ecf20Sopenharmony_ci struct ath5k_hw *ah = file->private_data; 1798c2ecf20Sopenharmony_ci char buf[500]; 1808c2ecf20Sopenharmony_ci unsigned int len = 0; 1818c2ecf20Sopenharmony_ci unsigned int v; 1828c2ecf20Sopenharmony_ci u64 tsf; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci v = ath5k_hw_reg_read(ah, AR5K_BEACON); 1858c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 1868c2ecf20Sopenharmony_ci "%-24s0x%08x\tintval: %d\tTIM: 0x%x\n", 1878c2ecf20Sopenharmony_ci "AR5K_BEACON", v, v & AR5K_BEACON_PERIOD, 1888c2ecf20Sopenharmony_ci (v & AR5K_BEACON_TIM) >> AR5K_BEACON_TIM_S); 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\n", 1918c2ecf20Sopenharmony_ci "AR5K_LAST_TSTP", ath5k_hw_reg_read(ah, AR5K_LAST_TSTP)); 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\n\n", 1948c2ecf20Sopenharmony_ci "AR5K_BEACON_CNT", ath5k_hw_reg_read(ah, AR5K_BEACON_CNT)); 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci v = ath5k_hw_reg_read(ah, AR5K_TIMER0); 1978c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n", 1988c2ecf20Sopenharmony_ci "AR5K_TIMER0 (TBTT)", v, v); 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci v = ath5k_hw_reg_read(ah, AR5K_TIMER1); 2018c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n", 2028c2ecf20Sopenharmony_ci "AR5K_TIMER1 (DMA)", v, v >> 3); 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci v = ath5k_hw_reg_read(ah, AR5K_TIMER2); 2058c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n", 2068c2ecf20Sopenharmony_ci "AR5K_TIMER2 (SWBA)", v, v >> 3); 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci v = ath5k_hw_reg_read(ah, AR5K_TIMER3); 2098c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n", 2108c2ecf20Sopenharmony_ci "AR5K_TIMER3 (ATIM)", v, v); 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci tsf = ath5k_hw_get_tsf64(ah); 2138c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 2148c2ecf20Sopenharmony_ci "TSF\t\t0x%016llx\tTU: %08x\n", 2158c2ecf20Sopenharmony_ci (unsigned long long)tsf, TSF_TO_TU(tsf)); 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci if (len > sizeof(buf)) 2188c2ecf20Sopenharmony_ci len = sizeof(buf); 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci return simple_read_from_buffer(user_buf, count, ppos, buf, len); 2218c2ecf20Sopenharmony_ci} 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_cistatic ssize_t write_file_beacon(struct file *file, 2248c2ecf20Sopenharmony_ci const char __user *userbuf, 2258c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 2268c2ecf20Sopenharmony_ci{ 2278c2ecf20Sopenharmony_ci struct ath5k_hw *ah = file->private_data; 2288c2ecf20Sopenharmony_ci char buf[20]; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci count = min_t(size_t, count, sizeof(buf) - 1); 2318c2ecf20Sopenharmony_ci if (copy_from_user(buf, userbuf, count)) 2328c2ecf20Sopenharmony_ci return -EFAULT; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci buf[count] = '\0'; 2358c2ecf20Sopenharmony_ci if (strncmp(buf, "disable", 7) == 0) { 2368c2ecf20Sopenharmony_ci AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); 2378c2ecf20Sopenharmony_ci pr_info("debugfs disable beacons\n"); 2388c2ecf20Sopenharmony_ci } else if (strncmp(buf, "enable", 6) == 0) { 2398c2ecf20Sopenharmony_ci AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); 2408c2ecf20Sopenharmony_ci pr_info("debugfs enable beacons\n"); 2418c2ecf20Sopenharmony_ci } 2428c2ecf20Sopenharmony_ci return count; 2438c2ecf20Sopenharmony_ci} 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_cistatic const struct file_operations fops_beacon = { 2468c2ecf20Sopenharmony_ci .read = read_file_beacon, 2478c2ecf20Sopenharmony_ci .write = write_file_beacon, 2488c2ecf20Sopenharmony_ci .open = simple_open, 2498c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 2508c2ecf20Sopenharmony_ci .llseek = default_llseek, 2518c2ecf20Sopenharmony_ci}; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci/* debugfs: reset */ 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_cistatic ssize_t write_file_reset(struct file *file, 2578c2ecf20Sopenharmony_ci const char __user *userbuf, 2588c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 2598c2ecf20Sopenharmony_ci{ 2608c2ecf20Sopenharmony_ci struct ath5k_hw *ah = file->private_data; 2618c2ecf20Sopenharmony_ci ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "debug file triggered reset\n"); 2628c2ecf20Sopenharmony_ci ieee80211_queue_work(ah->hw, &ah->reset_work); 2638c2ecf20Sopenharmony_ci return count; 2648c2ecf20Sopenharmony_ci} 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_cistatic const struct file_operations fops_reset = { 2678c2ecf20Sopenharmony_ci .write = write_file_reset, 2688c2ecf20Sopenharmony_ci .open = simple_open, 2698c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 2708c2ecf20Sopenharmony_ci .llseek = noop_llseek, 2718c2ecf20Sopenharmony_ci}; 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci/* debugfs: debug level */ 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_cistatic const struct { 2778c2ecf20Sopenharmony_ci enum ath5k_debug_level level; 2788c2ecf20Sopenharmony_ci const char *name; 2798c2ecf20Sopenharmony_ci const char *desc; 2808c2ecf20Sopenharmony_ci} dbg_info[] = { 2818c2ecf20Sopenharmony_ci { ATH5K_DEBUG_RESET, "reset", "reset and initialization" }, 2828c2ecf20Sopenharmony_ci { ATH5K_DEBUG_INTR, "intr", "interrupt handling" }, 2838c2ecf20Sopenharmony_ci { ATH5K_DEBUG_MODE, "mode", "mode init/setup" }, 2848c2ecf20Sopenharmony_ci { ATH5K_DEBUG_XMIT, "xmit", "basic xmit operation" }, 2858c2ecf20Sopenharmony_ci { ATH5K_DEBUG_BEACON, "beacon", "beacon handling" }, 2868c2ecf20Sopenharmony_ci { ATH5K_DEBUG_CALIBRATE, "calib", "periodic calibration" }, 2878c2ecf20Sopenharmony_ci { ATH5K_DEBUG_TXPOWER, "txpower", "transmit power setting" }, 2888c2ecf20Sopenharmony_ci { ATH5K_DEBUG_LED, "led", "LED management" }, 2898c2ecf20Sopenharmony_ci { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" }, 2908c2ecf20Sopenharmony_ci { ATH5K_DEBUG_DMA, "dma", "dma start/stop" }, 2918c2ecf20Sopenharmony_ci { ATH5K_DEBUG_ANI, "ani", "adaptive noise immunity" }, 2928c2ecf20Sopenharmony_ci { ATH5K_DEBUG_DESC, "desc", "descriptor chains" }, 2938c2ecf20Sopenharmony_ci { ATH5K_DEBUG_ANY, "all", "show all debug levels" }, 2948c2ecf20Sopenharmony_ci}; 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_cistatic ssize_t read_file_debug(struct file *file, char __user *user_buf, 2978c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 2988c2ecf20Sopenharmony_ci{ 2998c2ecf20Sopenharmony_ci struct ath5k_hw *ah = file->private_data; 3008c2ecf20Sopenharmony_ci char buf[700]; 3018c2ecf20Sopenharmony_ci unsigned int len = 0; 3028c2ecf20Sopenharmony_ci unsigned int i; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 3058c2ecf20Sopenharmony_ci "DEBUG LEVEL: 0x%08x\n\n", ah->debug.level); 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(dbg_info) - 1; i++) { 3088c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 3098c2ecf20Sopenharmony_ci "%10s %c 0x%08x - %s\n", dbg_info[i].name, 3108c2ecf20Sopenharmony_ci ah->debug.level & dbg_info[i].level ? '+' : ' ', 3118c2ecf20Sopenharmony_ci dbg_info[i].level, dbg_info[i].desc); 3128c2ecf20Sopenharmony_ci } 3138c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 3148c2ecf20Sopenharmony_ci "%10s %c 0x%08x - %s\n", dbg_info[i].name, 3158c2ecf20Sopenharmony_ci ah->debug.level == dbg_info[i].level ? '+' : ' ', 3168c2ecf20Sopenharmony_ci dbg_info[i].level, dbg_info[i].desc); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci if (len > sizeof(buf)) 3198c2ecf20Sopenharmony_ci len = sizeof(buf); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci return simple_read_from_buffer(user_buf, count, ppos, buf, len); 3228c2ecf20Sopenharmony_ci} 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_cistatic ssize_t write_file_debug(struct file *file, 3258c2ecf20Sopenharmony_ci const char __user *userbuf, 3268c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 3278c2ecf20Sopenharmony_ci{ 3288c2ecf20Sopenharmony_ci struct ath5k_hw *ah = file->private_data; 3298c2ecf20Sopenharmony_ci unsigned int i; 3308c2ecf20Sopenharmony_ci char buf[20]; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci count = min_t(size_t, count, sizeof(buf) - 1); 3338c2ecf20Sopenharmony_ci if (copy_from_user(buf, userbuf, count)) 3348c2ecf20Sopenharmony_ci return -EFAULT; 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci buf[count] = '\0'; 3378c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(dbg_info); i++) { 3388c2ecf20Sopenharmony_ci if (strncmp(buf, dbg_info[i].name, 3398c2ecf20Sopenharmony_ci strlen(dbg_info[i].name)) == 0) { 3408c2ecf20Sopenharmony_ci ah->debug.level ^= dbg_info[i].level; /* toggle bit */ 3418c2ecf20Sopenharmony_ci break; 3428c2ecf20Sopenharmony_ci } 3438c2ecf20Sopenharmony_ci } 3448c2ecf20Sopenharmony_ci return count; 3458c2ecf20Sopenharmony_ci} 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_cistatic const struct file_operations fops_debug = { 3488c2ecf20Sopenharmony_ci .read = read_file_debug, 3498c2ecf20Sopenharmony_ci .write = write_file_debug, 3508c2ecf20Sopenharmony_ci .open = simple_open, 3518c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 3528c2ecf20Sopenharmony_ci .llseek = default_llseek, 3538c2ecf20Sopenharmony_ci}; 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci/* debugfs: antenna */ 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_cistatic ssize_t read_file_antenna(struct file *file, char __user *user_buf, 3598c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 3608c2ecf20Sopenharmony_ci{ 3618c2ecf20Sopenharmony_ci struct ath5k_hw *ah = file->private_data; 3628c2ecf20Sopenharmony_ci char buf[700]; 3638c2ecf20Sopenharmony_ci unsigned int len = 0; 3648c2ecf20Sopenharmony_ci unsigned int i; 3658c2ecf20Sopenharmony_ci unsigned int v; 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "antenna mode\t%d\n", 3688c2ecf20Sopenharmony_ci ah->ah_ant_mode); 3698c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "default antenna\t%d\n", 3708c2ecf20Sopenharmony_ci ah->ah_def_ant); 3718c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "tx antenna\t%d\n", 3728c2ecf20Sopenharmony_ci ah->ah_tx_ant); 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "\nANTENNA\t\tRX\tTX\n"); 3758c2ecf20Sopenharmony_ci for (i = 1; i < ARRAY_SIZE(ah->stats.antenna_rx); i++) { 3768c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 3778c2ecf20Sopenharmony_ci "[antenna %d]\t%d\t%d\n", 3788c2ecf20Sopenharmony_ci i, ah->stats.antenna_rx[i], ah->stats.antenna_tx[i]); 3798c2ecf20Sopenharmony_ci } 3808c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "[invalid]\t%d\t%d\n", 3818c2ecf20Sopenharmony_ci ah->stats.antenna_rx[0], ah->stats.antenna_tx[0]); 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci v = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA); 3848c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 3858c2ecf20Sopenharmony_ci "\nAR5K_DEFAULT_ANTENNA\t0x%08x\n", v); 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci v = ath5k_hw_reg_read(ah, AR5K_STA_ID1); 3888c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 3898c2ecf20Sopenharmony_ci "AR5K_STA_ID1_DEFAULT_ANTENNA\t%d\n", 3908c2ecf20Sopenharmony_ci (v & AR5K_STA_ID1_DEFAULT_ANTENNA) != 0); 3918c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 3928c2ecf20Sopenharmony_ci "AR5K_STA_ID1_DESC_ANTENNA\t%d\n", 3938c2ecf20Sopenharmony_ci (v & AR5K_STA_ID1_DESC_ANTENNA) != 0); 3948c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 3958c2ecf20Sopenharmony_ci "AR5K_STA_ID1_RTS_DEF_ANTENNA\t%d\n", 3968c2ecf20Sopenharmony_ci (v & AR5K_STA_ID1_RTS_DEF_ANTENNA) != 0); 3978c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 3988c2ecf20Sopenharmony_ci "AR5K_STA_ID1_SELFGEN_DEF_ANT\t%d\n", 3998c2ecf20Sopenharmony_ci (v & AR5K_STA_ID1_SELFGEN_DEF_ANT) != 0); 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci v = ath5k_hw_reg_read(ah, AR5K_PHY_AGCCTL); 4028c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 4038c2ecf20Sopenharmony_ci "\nAR5K_PHY_AGCCTL_OFDM_DIV_DIS\t%d\n", 4048c2ecf20Sopenharmony_ci (v & AR5K_PHY_AGCCTL_OFDM_DIV_DIS) != 0); 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci v = ath5k_hw_reg_read(ah, AR5K_PHY_RESTART); 4078c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 4088c2ecf20Sopenharmony_ci "AR5K_PHY_RESTART_DIV_GC\t\t%x\n", 4098c2ecf20Sopenharmony_ci (v & AR5K_PHY_RESTART_DIV_GC) >> AR5K_PHY_RESTART_DIV_GC_S); 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci v = ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ANT_DIV); 4128c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 4138c2ecf20Sopenharmony_ci "AR5K_PHY_FAST_ANT_DIV_EN\t%d\n", 4148c2ecf20Sopenharmony_ci (v & AR5K_PHY_FAST_ANT_DIV_EN) != 0); 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci v = ath5k_hw_reg_read(ah, AR5K_PHY_ANT_SWITCH_TABLE_0); 4178c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 4188c2ecf20Sopenharmony_ci "\nAR5K_PHY_ANT_SWITCH_TABLE_0\t0x%08x\n", v); 4198c2ecf20Sopenharmony_ci v = ath5k_hw_reg_read(ah, AR5K_PHY_ANT_SWITCH_TABLE_1); 4208c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 4218c2ecf20Sopenharmony_ci "AR5K_PHY_ANT_SWITCH_TABLE_1\t0x%08x\n", v); 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci if (len > sizeof(buf)) 4248c2ecf20Sopenharmony_ci len = sizeof(buf); 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci return simple_read_from_buffer(user_buf, count, ppos, buf, len); 4278c2ecf20Sopenharmony_ci} 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_cistatic ssize_t write_file_antenna(struct file *file, 4308c2ecf20Sopenharmony_ci const char __user *userbuf, 4318c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 4328c2ecf20Sopenharmony_ci{ 4338c2ecf20Sopenharmony_ci struct ath5k_hw *ah = file->private_data; 4348c2ecf20Sopenharmony_ci unsigned int i; 4358c2ecf20Sopenharmony_ci char buf[20]; 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci count = min_t(size_t, count, sizeof(buf) - 1); 4388c2ecf20Sopenharmony_ci if (copy_from_user(buf, userbuf, count)) 4398c2ecf20Sopenharmony_ci return -EFAULT; 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci buf[count] = '\0'; 4428c2ecf20Sopenharmony_ci if (strncmp(buf, "diversity", 9) == 0) { 4438c2ecf20Sopenharmony_ci ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT); 4448c2ecf20Sopenharmony_ci pr_info("debug: enable diversity\n"); 4458c2ecf20Sopenharmony_ci } else if (strncmp(buf, "fixed-a", 7) == 0) { 4468c2ecf20Sopenharmony_ci ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_A); 4478c2ecf20Sopenharmony_ci pr_info("debug: fixed antenna A\n"); 4488c2ecf20Sopenharmony_ci } else if (strncmp(buf, "fixed-b", 7) == 0) { 4498c2ecf20Sopenharmony_ci ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_B); 4508c2ecf20Sopenharmony_ci pr_info("debug: fixed antenna B\n"); 4518c2ecf20Sopenharmony_ci } else if (strncmp(buf, "clear", 5) == 0) { 4528c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ah->stats.antenna_rx); i++) { 4538c2ecf20Sopenharmony_ci ah->stats.antenna_rx[i] = 0; 4548c2ecf20Sopenharmony_ci ah->stats.antenna_tx[i] = 0; 4558c2ecf20Sopenharmony_ci } 4568c2ecf20Sopenharmony_ci pr_info("debug: cleared antenna stats\n"); 4578c2ecf20Sopenharmony_ci } 4588c2ecf20Sopenharmony_ci return count; 4598c2ecf20Sopenharmony_ci} 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_cistatic const struct file_operations fops_antenna = { 4628c2ecf20Sopenharmony_ci .read = read_file_antenna, 4638c2ecf20Sopenharmony_ci .write = write_file_antenna, 4648c2ecf20Sopenharmony_ci .open = simple_open, 4658c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 4668c2ecf20Sopenharmony_ci .llseek = default_llseek, 4678c2ecf20Sopenharmony_ci}; 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci/* debugfs: misc */ 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_cistatic ssize_t read_file_misc(struct file *file, char __user *user_buf, 4728c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 4738c2ecf20Sopenharmony_ci{ 4748c2ecf20Sopenharmony_ci struct ath5k_hw *ah = file->private_data; 4758c2ecf20Sopenharmony_ci char buf[700]; 4768c2ecf20Sopenharmony_ci unsigned int len = 0; 4778c2ecf20Sopenharmony_ci u32 filt = ath5k_hw_get_rx_filter(ah); 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "bssid-mask: %pM\n", 4808c2ecf20Sopenharmony_ci ah->bssidmask); 4818c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "filter-flags: 0x%x ", 4828c2ecf20Sopenharmony_ci filt); 4838c2ecf20Sopenharmony_ci if (filt & AR5K_RX_FILTER_UCAST) 4848c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, " UCAST"); 4858c2ecf20Sopenharmony_ci if (filt & AR5K_RX_FILTER_MCAST) 4868c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, " MCAST"); 4878c2ecf20Sopenharmony_ci if (filt & AR5K_RX_FILTER_BCAST) 4888c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, " BCAST"); 4898c2ecf20Sopenharmony_ci if (filt & AR5K_RX_FILTER_CONTROL) 4908c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, " CONTROL"); 4918c2ecf20Sopenharmony_ci if (filt & AR5K_RX_FILTER_BEACON) 4928c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, " BEACON"); 4938c2ecf20Sopenharmony_ci if (filt & AR5K_RX_FILTER_PROM) 4948c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, " PROM"); 4958c2ecf20Sopenharmony_ci if (filt & AR5K_RX_FILTER_XRPOLL) 4968c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, " XRPOLL"); 4978c2ecf20Sopenharmony_ci if (filt & AR5K_RX_FILTER_PROBEREQ) 4988c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, " PROBEREQ"); 4998c2ecf20Sopenharmony_ci if (filt & AR5K_RX_FILTER_PHYERR_5212) 5008c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, " PHYERR-5212"); 5018c2ecf20Sopenharmony_ci if (filt & AR5K_RX_FILTER_RADARERR_5212) 5028c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, " RADARERR-5212"); 5038c2ecf20Sopenharmony_ci if (filt & AR5K_RX_FILTER_PHYERR_5211) 5048c2ecf20Sopenharmony_ci snprintf(buf + len, sizeof(buf) - len, " PHYERR-5211"); 5058c2ecf20Sopenharmony_ci if (filt & AR5K_RX_FILTER_RADARERR_5211) 5068c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, " RADARERR-5211"); 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "\nopmode: %s (%d)\n", 5098c2ecf20Sopenharmony_ci ath_opmode_to_string(ah->opmode), ah->opmode); 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci if (len > sizeof(buf)) 5128c2ecf20Sopenharmony_ci len = sizeof(buf); 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci return simple_read_from_buffer(user_buf, count, ppos, buf, len); 5158c2ecf20Sopenharmony_ci} 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_cistatic const struct file_operations fops_misc = { 5188c2ecf20Sopenharmony_ci .read = read_file_misc, 5198c2ecf20Sopenharmony_ci .open = simple_open, 5208c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 5218c2ecf20Sopenharmony_ci}; 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci/* debugfs: frameerrors */ 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_cistatic ssize_t read_file_frameerrors(struct file *file, char __user *user_buf, 5278c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 5288c2ecf20Sopenharmony_ci{ 5298c2ecf20Sopenharmony_ci struct ath5k_hw *ah = file->private_data; 5308c2ecf20Sopenharmony_ci struct ath5k_statistics *st = &ah->stats; 5318c2ecf20Sopenharmony_ci char buf[700]; 5328c2ecf20Sopenharmony_ci unsigned int len = 0; 5338c2ecf20Sopenharmony_ci int i; 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 5368c2ecf20Sopenharmony_ci "RX\n---------------------\n"); 5378c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "CRC\t%u\t(%u%%)\n", 5388c2ecf20Sopenharmony_ci st->rxerr_crc, 5398c2ecf20Sopenharmony_ci st->rx_all_count > 0 ? 5408c2ecf20Sopenharmony_ci st->rxerr_crc * 100 / st->rx_all_count : 0); 5418c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "PHY\t%u\t(%u%%)\n", 5428c2ecf20Sopenharmony_ci st->rxerr_phy, 5438c2ecf20Sopenharmony_ci st->rx_all_count > 0 ? 5448c2ecf20Sopenharmony_ci st->rxerr_phy * 100 / st->rx_all_count : 0); 5458c2ecf20Sopenharmony_ci for (i = 0; i < 32; i++) { 5468c2ecf20Sopenharmony_ci if (st->rxerr_phy_code[i]) 5478c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 5488c2ecf20Sopenharmony_ci " phy_err[%u]\t%u\n", 5498c2ecf20Sopenharmony_ci i, st->rxerr_phy_code[i]); 5508c2ecf20Sopenharmony_ci } 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "FIFO\t%u\t(%u%%)\n", 5538c2ecf20Sopenharmony_ci st->rxerr_fifo, 5548c2ecf20Sopenharmony_ci st->rx_all_count > 0 ? 5558c2ecf20Sopenharmony_ci st->rxerr_fifo * 100 / st->rx_all_count : 0); 5568c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "decrypt\t%u\t(%u%%)\n", 5578c2ecf20Sopenharmony_ci st->rxerr_decrypt, 5588c2ecf20Sopenharmony_ci st->rx_all_count > 0 ? 5598c2ecf20Sopenharmony_ci st->rxerr_decrypt * 100 / st->rx_all_count : 0); 5608c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "MIC\t%u\t(%u%%)\n", 5618c2ecf20Sopenharmony_ci st->rxerr_mic, 5628c2ecf20Sopenharmony_ci st->rx_all_count > 0 ? 5638c2ecf20Sopenharmony_ci st->rxerr_mic * 100 / st->rx_all_count : 0); 5648c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "process\t%u\t(%u%%)\n", 5658c2ecf20Sopenharmony_ci st->rxerr_proc, 5668c2ecf20Sopenharmony_ci st->rx_all_count > 0 ? 5678c2ecf20Sopenharmony_ci st->rxerr_proc * 100 / st->rx_all_count : 0); 5688c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "jumbo\t%u\t(%u%%)\n", 5698c2ecf20Sopenharmony_ci st->rxerr_jumbo, 5708c2ecf20Sopenharmony_ci st->rx_all_count > 0 ? 5718c2ecf20Sopenharmony_ci st->rxerr_jumbo * 100 / st->rx_all_count : 0); 5728c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "[RX all\t%u]\n", 5738c2ecf20Sopenharmony_ci st->rx_all_count); 5748c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "RX-all-bytes\t%u\n", 5758c2ecf20Sopenharmony_ci st->rx_bytes_count); 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 5788c2ecf20Sopenharmony_ci "\nTX\n---------------------\n"); 5798c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "retry\t%u\t(%u%%)\n", 5808c2ecf20Sopenharmony_ci st->txerr_retry, 5818c2ecf20Sopenharmony_ci st->tx_all_count > 0 ? 5828c2ecf20Sopenharmony_ci st->txerr_retry * 100 / st->tx_all_count : 0); 5838c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "FIFO\t%u\t(%u%%)\n", 5848c2ecf20Sopenharmony_ci st->txerr_fifo, 5858c2ecf20Sopenharmony_ci st->tx_all_count > 0 ? 5868c2ecf20Sopenharmony_ci st->txerr_fifo * 100 / st->tx_all_count : 0); 5878c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "filter\t%u\t(%u%%)\n", 5888c2ecf20Sopenharmony_ci st->txerr_filt, 5898c2ecf20Sopenharmony_ci st->tx_all_count > 0 ? 5908c2ecf20Sopenharmony_ci st->txerr_filt * 100 / st->tx_all_count : 0); 5918c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "[TX all\t%u]\n", 5928c2ecf20Sopenharmony_ci st->tx_all_count); 5938c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "TX-all-bytes\t%u\n", 5948c2ecf20Sopenharmony_ci st->tx_bytes_count); 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci if (len > sizeof(buf)) 5978c2ecf20Sopenharmony_ci len = sizeof(buf); 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci return simple_read_from_buffer(user_buf, count, ppos, buf, len); 6008c2ecf20Sopenharmony_ci} 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_cistatic ssize_t write_file_frameerrors(struct file *file, 6038c2ecf20Sopenharmony_ci const char __user *userbuf, 6048c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 6058c2ecf20Sopenharmony_ci{ 6068c2ecf20Sopenharmony_ci struct ath5k_hw *ah = file->private_data; 6078c2ecf20Sopenharmony_ci struct ath5k_statistics *st = &ah->stats; 6088c2ecf20Sopenharmony_ci char buf[20]; 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci count = min_t(size_t, count, sizeof(buf) - 1); 6118c2ecf20Sopenharmony_ci if (copy_from_user(buf, userbuf, count)) 6128c2ecf20Sopenharmony_ci return -EFAULT; 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci buf[count] = '\0'; 6158c2ecf20Sopenharmony_ci if (strncmp(buf, "clear", 5) == 0) { 6168c2ecf20Sopenharmony_ci st->rxerr_crc = 0; 6178c2ecf20Sopenharmony_ci st->rxerr_phy = 0; 6188c2ecf20Sopenharmony_ci st->rxerr_fifo = 0; 6198c2ecf20Sopenharmony_ci st->rxerr_decrypt = 0; 6208c2ecf20Sopenharmony_ci st->rxerr_mic = 0; 6218c2ecf20Sopenharmony_ci st->rxerr_proc = 0; 6228c2ecf20Sopenharmony_ci st->rxerr_jumbo = 0; 6238c2ecf20Sopenharmony_ci st->rx_all_count = 0; 6248c2ecf20Sopenharmony_ci st->txerr_retry = 0; 6258c2ecf20Sopenharmony_ci st->txerr_fifo = 0; 6268c2ecf20Sopenharmony_ci st->txerr_filt = 0; 6278c2ecf20Sopenharmony_ci st->tx_all_count = 0; 6288c2ecf20Sopenharmony_ci pr_info("debug: cleared frameerrors stats\n"); 6298c2ecf20Sopenharmony_ci } 6308c2ecf20Sopenharmony_ci return count; 6318c2ecf20Sopenharmony_ci} 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_cistatic const struct file_operations fops_frameerrors = { 6348c2ecf20Sopenharmony_ci .read = read_file_frameerrors, 6358c2ecf20Sopenharmony_ci .write = write_file_frameerrors, 6368c2ecf20Sopenharmony_ci .open = simple_open, 6378c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 6388c2ecf20Sopenharmony_ci .llseek = default_llseek, 6398c2ecf20Sopenharmony_ci}; 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci/* debugfs: ani */ 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_cistatic ssize_t read_file_ani(struct file *file, char __user *user_buf, 6458c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 6468c2ecf20Sopenharmony_ci{ 6478c2ecf20Sopenharmony_ci struct ath5k_hw *ah = file->private_data; 6488c2ecf20Sopenharmony_ci struct ath5k_statistics *st = &ah->stats; 6498c2ecf20Sopenharmony_ci struct ath5k_ani_state *as = &ah->ani_state; 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci char buf[700]; 6528c2ecf20Sopenharmony_ci unsigned int len = 0; 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 6558c2ecf20Sopenharmony_ci "HW has PHY error counters:\t%s\n", 6568c2ecf20Sopenharmony_ci ah->ah_capabilities.cap_has_phyerr_counters ? 6578c2ecf20Sopenharmony_ci "yes" : "no"); 6588c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 6598c2ecf20Sopenharmony_ci "HW max spur immunity level:\t%d\n", 6608c2ecf20Sopenharmony_ci as->max_spur_level); 6618c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 6628c2ecf20Sopenharmony_ci "\nANI state\n--------------------------------------------\n"); 6638c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "operating mode:\t\t\t"); 6648c2ecf20Sopenharmony_ci switch (as->ani_mode) { 6658c2ecf20Sopenharmony_ci case ATH5K_ANI_MODE_OFF: 6668c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "OFF\n"); 6678c2ecf20Sopenharmony_ci break; 6688c2ecf20Sopenharmony_ci case ATH5K_ANI_MODE_MANUAL_LOW: 6698c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 6708c2ecf20Sopenharmony_ci "MANUAL LOW\n"); 6718c2ecf20Sopenharmony_ci break; 6728c2ecf20Sopenharmony_ci case ATH5K_ANI_MODE_MANUAL_HIGH: 6738c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 6748c2ecf20Sopenharmony_ci "MANUAL HIGH\n"); 6758c2ecf20Sopenharmony_ci break; 6768c2ecf20Sopenharmony_ci case ATH5K_ANI_MODE_AUTO: 6778c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "AUTO\n"); 6788c2ecf20Sopenharmony_ci break; 6798c2ecf20Sopenharmony_ci default: 6808c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 6818c2ecf20Sopenharmony_ci "??? (not good)\n"); 6828c2ecf20Sopenharmony_ci break; 6838c2ecf20Sopenharmony_ci } 6848c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 6858c2ecf20Sopenharmony_ci "noise immunity level:\t\t%d\n", 6868c2ecf20Sopenharmony_ci as->noise_imm_level); 6878c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 6888c2ecf20Sopenharmony_ci "spur immunity level:\t\t%d\n", 6898c2ecf20Sopenharmony_ci as->spur_level); 6908c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 6918c2ecf20Sopenharmony_ci "firstep level:\t\t\t%d\n", 6928c2ecf20Sopenharmony_ci as->firstep_level); 6938c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 6948c2ecf20Sopenharmony_ci "OFDM weak signal detection:\t%s\n", 6958c2ecf20Sopenharmony_ci as->ofdm_weak_sig ? "on" : "off"); 6968c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 6978c2ecf20Sopenharmony_ci "CCK weak signal detection:\t%s\n", 6988c2ecf20Sopenharmony_ci as->cck_weak_sig ? "on" : "off"); 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 7018c2ecf20Sopenharmony_ci "\nMIB INTERRUPTS:\t\t%u\n", 7028c2ecf20Sopenharmony_ci st->mib_intr); 7038c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 7048c2ecf20Sopenharmony_ci "beacon RSSI average:\t%d\n", 7058c2ecf20Sopenharmony_ci (int)ewma_beacon_rssi_read(&ah->ah_beacon_rssi_avg)); 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci#define CC_PRINT(_struct, _field) \ 7088c2ecf20Sopenharmony_ci _struct._field, \ 7098c2ecf20Sopenharmony_ci _struct.cycles > 0 ? \ 7108c2ecf20Sopenharmony_ci _struct._field * 100 / _struct.cycles : 0 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 7138c2ecf20Sopenharmony_ci "profcnt tx\t\t%u\t(%d%%)\n", 7148c2ecf20Sopenharmony_ci CC_PRINT(as->last_cc, tx_frame)); 7158c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 7168c2ecf20Sopenharmony_ci "profcnt rx\t\t%u\t(%d%%)\n", 7178c2ecf20Sopenharmony_ci CC_PRINT(as->last_cc, rx_frame)); 7188c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 7198c2ecf20Sopenharmony_ci "profcnt busy\t\t%u\t(%d%%)\n", 7208c2ecf20Sopenharmony_ci CC_PRINT(as->last_cc, rx_busy)); 7218c2ecf20Sopenharmony_ci#undef CC_PRINT 7228c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, "profcnt cycles\t\t%u\n", 7238c2ecf20Sopenharmony_ci as->last_cc.cycles); 7248c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 7258c2ecf20Sopenharmony_ci "listen time\t\t%d\tlast: %d\n", 7268c2ecf20Sopenharmony_ci as->listen_time, as->last_listen); 7278c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 7288c2ecf20Sopenharmony_ci "OFDM errors\t\t%u\tlast: %u\tsum: %u\n", 7298c2ecf20Sopenharmony_ci as->ofdm_errors, as->last_ofdm_errors, 7308c2ecf20Sopenharmony_ci as->sum_ofdm_errors); 7318c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 7328c2ecf20Sopenharmony_ci "CCK errors\t\t%u\tlast: %u\tsum: %u\n", 7338c2ecf20Sopenharmony_ci as->cck_errors, as->last_cck_errors, 7348c2ecf20Sopenharmony_ci as->sum_cck_errors); 7358c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 7368c2ecf20Sopenharmony_ci "AR5K_PHYERR_CNT1\t%x\t(=%d)\n", 7378c2ecf20Sopenharmony_ci ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1), 7388c2ecf20Sopenharmony_ci ATH5K_ANI_OFDM_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX - 7398c2ecf20Sopenharmony_ci ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1))); 7408c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 7418c2ecf20Sopenharmony_ci "AR5K_PHYERR_CNT2\t%x\t(=%d)\n", 7428c2ecf20Sopenharmony_ci ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2), 7438c2ecf20Sopenharmony_ci ATH5K_ANI_CCK_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX - 7448c2ecf20Sopenharmony_ci ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2))); 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci if (len > sizeof(buf)) 7478c2ecf20Sopenharmony_ci len = sizeof(buf); 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci return simple_read_from_buffer(user_buf, count, ppos, buf, len); 7508c2ecf20Sopenharmony_ci} 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_cistatic ssize_t write_file_ani(struct file *file, 7538c2ecf20Sopenharmony_ci const char __user *userbuf, 7548c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 7558c2ecf20Sopenharmony_ci{ 7568c2ecf20Sopenharmony_ci struct ath5k_hw *ah = file->private_data; 7578c2ecf20Sopenharmony_ci char buf[20]; 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_ci count = min_t(size_t, count, sizeof(buf) - 1); 7608c2ecf20Sopenharmony_ci if (copy_from_user(buf, userbuf, count)) 7618c2ecf20Sopenharmony_ci return -EFAULT; 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci buf[count] = '\0'; 7648c2ecf20Sopenharmony_ci if (strncmp(buf, "sens-low", 8) == 0) { 7658c2ecf20Sopenharmony_ci ath5k_ani_init(ah, ATH5K_ANI_MODE_MANUAL_HIGH); 7668c2ecf20Sopenharmony_ci } else if (strncmp(buf, "sens-high", 9) == 0) { 7678c2ecf20Sopenharmony_ci ath5k_ani_init(ah, ATH5K_ANI_MODE_MANUAL_LOW); 7688c2ecf20Sopenharmony_ci } else if (strncmp(buf, "ani-off", 7) == 0) { 7698c2ecf20Sopenharmony_ci ath5k_ani_init(ah, ATH5K_ANI_MODE_OFF); 7708c2ecf20Sopenharmony_ci } else if (strncmp(buf, "ani-on", 6) == 0) { 7718c2ecf20Sopenharmony_ci ath5k_ani_init(ah, ATH5K_ANI_MODE_AUTO); 7728c2ecf20Sopenharmony_ci } else if (strncmp(buf, "noise-low", 9) == 0) { 7738c2ecf20Sopenharmony_ci ath5k_ani_set_noise_immunity_level(ah, 0); 7748c2ecf20Sopenharmony_ci } else if (strncmp(buf, "noise-high", 10) == 0) { 7758c2ecf20Sopenharmony_ci ath5k_ani_set_noise_immunity_level(ah, 7768c2ecf20Sopenharmony_ci ATH5K_ANI_MAX_NOISE_IMM_LVL); 7778c2ecf20Sopenharmony_ci } else if (strncmp(buf, "spur-low", 8) == 0) { 7788c2ecf20Sopenharmony_ci ath5k_ani_set_spur_immunity_level(ah, 0); 7798c2ecf20Sopenharmony_ci } else if (strncmp(buf, "spur-high", 9) == 0) { 7808c2ecf20Sopenharmony_ci ath5k_ani_set_spur_immunity_level(ah, 7818c2ecf20Sopenharmony_ci ah->ani_state.max_spur_level); 7828c2ecf20Sopenharmony_ci } else if (strncmp(buf, "fir-low", 7) == 0) { 7838c2ecf20Sopenharmony_ci ath5k_ani_set_firstep_level(ah, 0); 7848c2ecf20Sopenharmony_ci } else if (strncmp(buf, "fir-high", 8) == 0) { 7858c2ecf20Sopenharmony_ci ath5k_ani_set_firstep_level(ah, ATH5K_ANI_MAX_FIRSTEP_LVL); 7868c2ecf20Sopenharmony_ci } else if (strncmp(buf, "ofdm-off", 8) == 0) { 7878c2ecf20Sopenharmony_ci ath5k_ani_set_ofdm_weak_signal_detection(ah, false); 7888c2ecf20Sopenharmony_ci } else if (strncmp(buf, "ofdm-on", 7) == 0) { 7898c2ecf20Sopenharmony_ci ath5k_ani_set_ofdm_weak_signal_detection(ah, true); 7908c2ecf20Sopenharmony_ci } else if (strncmp(buf, "cck-off", 7) == 0) { 7918c2ecf20Sopenharmony_ci ath5k_ani_set_cck_weak_signal_detection(ah, false); 7928c2ecf20Sopenharmony_ci } else if (strncmp(buf, "cck-on", 6) == 0) { 7938c2ecf20Sopenharmony_ci ath5k_ani_set_cck_weak_signal_detection(ah, true); 7948c2ecf20Sopenharmony_ci } 7958c2ecf20Sopenharmony_ci return count; 7968c2ecf20Sopenharmony_ci} 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_cistatic const struct file_operations fops_ani = { 7998c2ecf20Sopenharmony_ci .read = read_file_ani, 8008c2ecf20Sopenharmony_ci .write = write_file_ani, 8018c2ecf20Sopenharmony_ci .open = simple_open, 8028c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 8038c2ecf20Sopenharmony_ci .llseek = default_llseek, 8048c2ecf20Sopenharmony_ci}; 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci/* debugfs: queues etc */ 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_cistatic ssize_t read_file_queue(struct file *file, char __user *user_buf, 8108c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 8118c2ecf20Sopenharmony_ci{ 8128c2ecf20Sopenharmony_ci struct ath5k_hw *ah = file->private_data; 8138c2ecf20Sopenharmony_ci char buf[700]; 8148c2ecf20Sopenharmony_ci unsigned int len = 0; 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci struct ath5k_txq *txq; 8178c2ecf20Sopenharmony_ci struct ath5k_buf *bf, *bf0; 8188c2ecf20Sopenharmony_ci int i, n; 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 8218c2ecf20Sopenharmony_ci "available txbuffers: %d\n", ah->txbuf_len); 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ah->txqs); i++) { 8248c2ecf20Sopenharmony_ci txq = &ah->txqs[i]; 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 8278c2ecf20Sopenharmony_ci "%02d: %ssetup\n", i, txq->setup ? "" : "not "); 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_ci if (!txq->setup) 8308c2ecf20Sopenharmony_ci continue; 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci n = 0; 8338c2ecf20Sopenharmony_ci spin_lock_bh(&txq->lock); 8348c2ecf20Sopenharmony_ci list_for_each_entry_safe(bf, bf0, &txq->q, list) 8358c2ecf20Sopenharmony_ci n++; 8368c2ecf20Sopenharmony_ci spin_unlock_bh(&txq->lock); 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 8398c2ecf20Sopenharmony_ci " len: %d bufs: %d\n", txq->txq_len, n); 8408c2ecf20Sopenharmony_ci len += scnprintf(buf + len, sizeof(buf) - len, 8418c2ecf20Sopenharmony_ci " stuck: %d\n", txq->txq_stuck); 8428c2ecf20Sopenharmony_ci } 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci if (len > sizeof(buf)) 8458c2ecf20Sopenharmony_ci len = sizeof(buf); 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci return simple_read_from_buffer(user_buf, count, ppos, buf, len); 8488c2ecf20Sopenharmony_ci} 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_cistatic ssize_t write_file_queue(struct file *file, 8518c2ecf20Sopenharmony_ci const char __user *userbuf, 8528c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 8538c2ecf20Sopenharmony_ci{ 8548c2ecf20Sopenharmony_ci struct ath5k_hw *ah = file->private_data; 8558c2ecf20Sopenharmony_ci char buf[20]; 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_ci count = min_t(size_t, count, sizeof(buf) - 1); 8588c2ecf20Sopenharmony_ci if (copy_from_user(buf, userbuf, count)) 8598c2ecf20Sopenharmony_ci return -EFAULT; 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci buf[count] = '\0'; 8628c2ecf20Sopenharmony_ci if (strncmp(buf, "start", 5) == 0) 8638c2ecf20Sopenharmony_ci ieee80211_wake_queues(ah->hw); 8648c2ecf20Sopenharmony_ci else if (strncmp(buf, "stop", 4) == 0) 8658c2ecf20Sopenharmony_ci ieee80211_stop_queues(ah->hw); 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_ci return count; 8688c2ecf20Sopenharmony_ci} 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_cistatic const struct file_operations fops_queue = { 8728c2ecf20Sopenharmony_ci .read = read_file_queue, 8738c2ecf20Sopenharmony_ci .write = write_file_queue, 8748c2ecf20Sopenharmony_ci .open = simple_open, 8758c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 8768c2ecf20Sopenharmony_ci .llseek = default_llseek, 8778c2ecf20Sopenharmony_ci}; 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_ci/* debugfs: eeprom */ 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_cistruct eeprom_private { 8828c2ecf20Sopenharmony_ci u16 *buf; 8838c2ecf20Sopenharmony_ci int len; 8848c2ecf20Sopenharmony_ci}; 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_cistatic int open_file_eeprom(struct inode *inode, struct file *file) 8878c2ecf20Sopenharmony_ci{ 8888c2ecf20Sopenharmony_ci struct eeprom_private *ep; 8898c2ecf20Sopenharmony_ci struct ath5k_hw *ah = inode->i_private; 8908c2ecf20Sopenharmony_ci bool res; 8918c2ecf20Sopenharmony_ci int i, ret; 8928c2ecf20Sopenharmony_ci u32 eesize; /* NB: in 16-bit words */ 8938c2ecf20Sopenharmony_ci u16 val, *buf; 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci /* Get eeprom size */ 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci res = ath5k_hw_nvram_read(ah, AR5K_EEPROM_SIZE_UPPER, &val); 8988c2ecf20Sopenharmony_ci if (!res) 8998c2ecf20Sopenharmony_ci return -EACCES; 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci if (val == 0) { 9028c2ecf20Sopenharmony_ci eesize = AR5K_EEPROM_INFO_MAX + AR5K_EEPROM_INFO_BASE; 9038c2ecf20Sopenharmony_ci } else { 9048c2ecf20Sopenharmony_ci eesize = (val & AR5K_EEPROM_SIZE_UPPER_MASK) << 9058c2ecf20Sopenharmony_ci AR5K_EEPROM_SIZE_ENDLOC_SHIFT; 9068c2ecf20Sopenharmony_ci ath5k_hw_nvram_read(ah, AR5K_EEPROM_SIZE_LOWER, &val); 9078c2ecf20Sopenharmony_ci eesize = eesize | val; 9088c2ecf20Sopenharmony_ci } 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ci if (eesize > 4096) 9118c2ecf20Sopenharmony_ci return -EINVAL; 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ci /* Create buffer and read in eeprom */ 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_ci buf = vmalloc(array_size(eesize, 2)); 9168c2ecf20Sopenharmony_ci if (!buf) { 9178c2ecf20Sopenharmony_ci ret = -ENOMEM; 9188c2ecf20Sopenharmony_ci goto err; 9198c2ecf20Sopenharmony_ci } 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci for (i = 0; i < eesize; ++i) { 9228c2ecf20Sopenharmony_ci if (!ath5k_hw_nvram_read(ah, i, &val)) { 9238c2ecf20Sopenharmony_ci ret = -EIO; 9248c2ecf20Sopenharmony_ci goto freebuf; 9258c2ecf20Sopenharmony_ci } 9268c2ecf20Sopenharmony_ci buf[i] = val; 9278c2ecf20Sopenharmony_ci } 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci /* Create private struct and assign to file */ 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci ep = kmalloc(sizeof(*ep), GFP_KERNEL); 9328c2ecf20Sopenharmony_ci if (!ep) { 9338c2ecf20Sopenharmony_ci ret = -ENOMEM; 9348c2ecf20Sopenharmony_ci goto freebuf; 9358c2ecf20Sopenharmony_ci } 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_ci ep->buf = buf; 9388c2ecf20Sopenharmony_ci ep->len = eesize * 2; 9398c2ecf20Sopenharmony_ci 9408c2ecf20Sopenharmony_ci file->private_data = (void *)ep; 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_ci return 0; 9438c2ecf20Sopenharmony_ci 9448c2ecf20Sopenharmony_cifreebuf: 9458c2ecf20Sopenharmony_ci vfree(buf); 9468c2ecf20Sopenharmony_cierr: 9478c2ecf20Sopenharmony_ci return ret; 9488c2ecf20Sopenharmony_ci 9498c2ecf20Sopenharmony_ci} 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_cistatic ssize_t read_file_eeprom(struct file *file, char __user *user_buf, 9528c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 9538c2ecf20Sopenharmony_ci{ 9548c2ecf20Sopenharmony_ci struct eeprom_private *ep = file->private_data; 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci return simple_read_from_buffer(user_buf, count, ppos, ep->buf, ep->len); 9578c2ecf20Sopenharmony_ci} 9588c2ecf20Sopenharmony_ci 9598c2ecf20Sopenharmony_cistatic int release_file_eeprom(struct inode *inode, struct file *file) 9608c2ecf20Sopenharmony_ci{ 9618c2ecf20Sopenharmony_ci struct eeprom_private *ep = file->private_data; 9628c2ecf20Sopenharmony_ci 9638c2ecf20Sopenharmony_ci vfree(ep->buf); 9648c2ecf20Sopenharmony_ci kfree(ep); 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_ci return 0; 9678c2ecf20Sopenharmony_ci} 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_cistatic const struct file_operations fops_eeprom = { 9708c2ecf20Sopenharmony_ci .open = open_file_eeprom, 9718c2ecf20Sopenharmony_ci .read = read_file_eeprom, 9728c2ecf20Sopenharmony_ci .release = release_file_eeprom, 9738c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 9748c2ecf20Sopenharmony_ci}; 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_civoid 9788c2ecf20Sopenharmony_ciath5k_debug_init_device(struct ath5k_hw *ah) 9798c2ecf20Sopenharmony_ci{ 9808c2ecf20Sopenharmony_ci struct dentry *phydir; 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci ah->debug.level = ath5k_debug; 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_ci phydir = debugfs_create_dir("ath5k", ah->hw->wiphy->debugfsdir); 9858c2ecf20Sopenharmony_ci if (!phydir) 9868c2ecf20Sopenharmony_ci return; 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci debugfs_create_file("debug", 0600, phydir, ah, &fops_debug); 9898c2ecf20Sopenharmony_ci debugfs_create_file("registers", 0400, phydir, ah, ®isters_fops); 9908c2ecf20Sopenharmony_ci debugfs_create_file("beacon", 0600, phydir, ah, &fops_beacon); 9918c2ecf20Sopenharmony_ci debugfs_create_file("reset", 0200, phydir, ah, &fops_reset); 9928c2ecf20Sopenharmony_ci debugfs_create_file("antenna", 0600, phydir, ah, &fops_antenna); 9938c2ecf20Sopenharmony_ci debugfs_create_file("misc", 0400, phydir, ah, &fops_misc); 9948c2ecf20Sopenharmony_ci debugfs_create_file("eeprom", 0400, phydir, ah, &fops_eeprom); 9958c2ecf20Sopenharmony_ci debugfs_create_file("frameerrors", 0600, phydir, ah, &fops_frameerrors); 9968c2ecf20Sopenharmony_ci debugfs_create_file("ani", 0600, phydir, ah, &fops_ani); 9978c2ecf20Sopenharmony_ci debugfs_create_file("queue", 0600, phydir, ah, &fops_queue); 9988c2ecf20Sopenharmony_ci debugfs_create_bool("32khz_clock", 0600, phydir, 9998c2ecf20Sopenharmony_ci &ah->ah_use_32khz_clock); 10008c2ecf20Sopenharmony_ci} 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ci/* functions used in other places */ 10038c2ecf20Sopenharmony_ci 10048c2ecf20Sopenharmony_civoid 10058c2ecf20Sopenharmony_ciath5k_debug_dump_bands(struct ath5k_hw *ah) 10068c2ecf20Sopenharmony_ci{ 10078c2ecf20Sopenharmony_ci unsigned int b, i; 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_ci if (likely(!(ah->debug.level & ATH5K_DEBUG_DUMPBANDS))) 10108c2ecf20Sopenharmony_ci return; 10118c2ecf20Sopenharmony_ci 10128c2ecf20Sopenharmony_ci for (b = 0; b < NUM_NL80211_BANDS; b++) { 10138c2ecf20Sopenharmony_ci struct ieee80211_supported_band *band = &ah->sbands[b]; 10148c2ecf20Sopenharmony_ci char bname[6]; 10158c2ecf20Sopenharmony_ci switch (band->band) { 10168c2ecf20Sopenharmony_ci case NL80211_BAND_2GHZ: 10178c2ecf20Sopenharmony_ci strcpy(bname, "2 GHz"); 10188c2ecf20Sopenharmony_ci break; 10198c2ecf20Sopenharmony_ci case NL80211_BAND_5GHZ: 10208c2ecf20Sopenharmony_ci strcpy(bname, "5 GHz"); 10218c2ecf20Sopenharmony_ci break; 10228c2ecf20Sopenharmony_ci default: 10238c2ecf20Sopenharmony_ci printk(KERN_DEBUG "Band not supported: %d\n", 10248c2ecf20Sopenharmony_ci band->band); 10258c2ecf20Sopenharmony_ci return; 10268c2ecf20Sopenharmony_ci } 10278c2ecf20Sopenharmony_ci printk(KERN_DEBUG "Band %s: channels %d, rates %d\n", bname, 10288c2ecf20Sopenharmony_ci band->n_channels, band->n_bitrates); 10298c2ecf20Sopenharmony_ci printk(KERN_DEBUG " channels:\n"); 10308c2ecf20Sopenharmony_ci for (i = 0; i < band->n_channels; i++) 10318c2ecf20Sopenharmony_ci printk(KERN_DEBUG " %3d %d %.4x %.4x\n", 10328c2ecf20Sopenharmony_ci ieee80211_frequency_to_channel( 10338c2ecf20Sopenharmony_ci band->channels[i].center_freq), 10348c2ecf20Sopenharmony_ci band->channels[i].center_freq, 10358c2ecf20Sopenharmony_ci band->channels[i].hw_value, 10368c2ecf20Sopenharmony_ci band->channels[i].flags); 10378c2ecf20Sopenharmony_ci printk(KERN_DEBUG " rates:\n"); 10388c2ecf20Sopenharmony_ci for (i = 0; i < band->n_bitrates; i++) 10398c2ecf20Sopenharmony_ci printk(KERN_DEBUG " %4d %.4x %.4x %.4x\n", 10408c2ecf20Sopenharmony_ci band->bitrates[i].bitrate, 10418c2ecf20Sopenharmony_ci band->bitrates[i].hw_value, 10428c2ecf20Sopenharmony_ci band->bitrates[i].flags, 10438c2ecf20Sopenharmony_ci band->bitrates[i].hw_value_short); 10448c2ecf20Sopenharmony_ci } 10458c2ecf20Sopenharmony_ci} 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_cistatic inline void 10488c2ecf20Sopenharmony_ciath5k_debug_printrxbuf(struct ath5k_buf *bf, int done, 10498c2ecf20Sopenharmony_ci struct ath5k_rx_status *rs) 10508c2ecf20Sopenharmony_ci{ 10518c2ecf20Sopenharmony_ci struct ath5k_desc *ds = bf->desc; 10528c2ecf20Sopenharmony_ci struct ath5k_hw_all_rx_desc *rd = &ds->ud.ds_rx; 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_ci printk(KERN_DEBUG "R (%p %llx) %08x %08x %08x %08x %08x %08x %c\n", 10558c2ecf20Sopenharmony_ci ds, (unsigned long long)bf->daddr, 10568c2ecf20Sopenharmony_ci ds->ds_link, ds->ds_data, 10578c2ecf20Sopenharmony_ci rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1, 10588c2ecf20Sopenharmony_ci rd->rx_stat.rx_status_0, rd->rx_stat.rx_status_1, 10598c2ecf20Sopenharmony_ci !done ? ' ' : (rs->rs_status == 0) ? '*' : '!'); 10608c2ecf20Sopenharmony_ci} 10618c2ecf20Sopenharmony_ci 10628c2ecf20Sopenharmony_civoid 10638c2ecf20Sopenharmony_ciath5k_debug_printrxbuffs(struct ath5k_hw *ah) 10648c2ecf20Sopenharmony_ci{ 10658c2ecf20Sopenharmony_ci struct ath5k_desc *ds; 10668c2ecf20Sopenharmony_ci struct ath5k_buf *bf; 10678c2ecf20Sopenharmony_ci struct ath5k_rx_status rs = {}; 10688c2ecf20Sopenharmony_ci int status; 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_ci if (likely(!(ah->debug.level & ATH5K_DEBUG_DESC))) 10718c2ecf20Sopenharmony_ci return; 10728c2ecf20Sopenharmony_ci 10738c2ecf20Sopenharmony_ci printk(KERN_DEBUG "rxdp %x, rxlink %p\n", 10748c2ecf20Sopenharmony_ci ath5k_hw_get_rxdp(ah), ah->rxlink); 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_ci spin_lock_bh(&ah->rxbuflock); 10778c2ecf20Sopenharmony_ci list_for_each_entry(bf, &ah->rxbuf, list) { 10788c2ecf20Sopenharmony_ci ds = bf->desc; 10798c2ecf20Sopenharmony_ci status = ah->ah_proc_rx_desc(ah, ds, &rs); 10808c2ecf20Sopenharmony_ci if (!status) 10818c2ecf20Sopenharmony_ci ath5k_debug_printrxbuf(bf, status == 0, &rs); 10828c2ecf20Sopenharmony_ci } 10838c2ecf20Sopenharmony_ci spin_unlock_bh(&ah->rxbuflock); 10848c2ecf20Sopenharmony_ci} 10858c2ecf20Sopenharmony_ci 10868c2ecf20Sopenharmony_civoid 10878c2ecf20Sopenharmony_ciath5k_debug_printtxbuf(struct ath5k_hw *ah, struct ath5k_buf *bf) 10888c2ecf20Sopenharmony_ci{ 10898c2ecf20Sopenharmony_ci struct ath5k_desc *ds = bf->desc; 10908c2ecf20Sopenharmony_ci struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212; 10918c2ecf20Sopenharmony_ci struct ath5k_tx_status ts = {}; 10928c2ecf20Sopenharmony_ci int done; 10938c2ecf20Sopenharmony_ci 10948c2ecf20Sopenharmony_ci if (likely(!(ah->debug.level & ATH5K_DEBUG_DESC))) 10958c2ecf20Sopenharmony_ci return; 10968c2ecf20Sopenharmony_ci 10978c2ecf20Sopenharmony_ci done = ah->ah_proc_tx_desc(ah, bf->desc, &ts); 10988c2ecf20Sopenharmony_ci 10998c2ecf20Sopenharmony_ci printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x " 11008c2ecf20Sopenharmony_ci "%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link, 11018c2ecf20Sopenharmony_ci ds->ds_data, td->tx_ctl.tx_control_0, td->tx_ctl.tx_control_1, 11028c2ecf20Sopenharmony_ci td->tx_ctl.tx_control_2, td->tx_ctl.tx_control_3, 11038c2ecf20Sopenharmony_ci td->tx_stat.tx_status_0, td->tx_stat.tx_status_1, 11048c2ecf20Sopenharmony_ci done ? ' ' : (ts.ts_status == 0) ? '*' : '!'); 11058c2ecf20Sopenharmony_ci} 1106