cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

debug.c (33275B)


      1/*
      2 * Copyright (c) 2007-2008 Bruno Randolf <bruno@thinktube.com>
      3 *
      4 *  This file is free software: you may copy, redistribute and/or modify it
      5 *  under the terms of the GNU General Public License as published by the
      6 *  Free Software Foundation, either version 2 of the License, or (at your
      7 *  option) any later version.
      8 *
      9 *  This file is distributed in the hope that it will be useful, but
     10 *  WITHOUT ANY WARRANTY; without even the implied warranty of
     11 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12 *  General Public License for more details.
     13 *
     14 *  You should have received a copy of the GNU General Public License
     15 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
     16 *
     17 *
     18 * This file incorporates work covered by the following copyright and
     19 * permission notice:
     20 *
     21 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
     22 * Copyright (c) 2004-2005 Atheros Communications, Inc.
     23 * Copyright (c) 2006 Devicescape Software, Inc.
     24 * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
     25 * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
     26 *
     27 * All rights reserved.
     28 *
     29 * Redistribution and use in source and binary forms, with or without
     30 * modification, are permitted provided that the following conditions
     31 * are met:
     32 * 1. Redistributions of source code must retain the above copyright
     33 *    notice, this list of conditions and the following disclaimer,
     34 *    without modification.
     35 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
     36 *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
     37 *    redistribution must be conditioned upon including a substantially
     38 *    similar Disclaimer requirement for further binary redistribution.
     39 * 3. Neither the names of the above-listed copyright holders nor the names
     40 *    of any contributors may be used to endorse or promote products derived
     41 *    from this software without specific prior written permission.
     42 *
     43 * Alternatively, this software may be distributed under the terms of the
     44 * GNU General Public License ("GPL") version 2 as published by the Free
     45 * Software Foundation.
     46 *
     47 * NO WARRANTY
     48 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     49 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     50 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
     51 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
     52 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
     53 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     54 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     55 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
     56 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     57 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     58 * THE POSSIBILITY OF SUCH DAMAGES.
     59 */
     60
     61#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
     62
     63#include <linux/export.h>
     64#include <linux/moduleparam.h>
     65#include <linux/vmalloc.h>
     66
     67#include <linux/seq_file.h>
     68#include <linux/list.h>
     69#include "debug.h"
     70#include "ath5k.h"
     71#include "reg.h"
     72#include "base.h"
     73
     74static unsigned int ath5k_debug;
     75module_param_named(debug, ath5k_debug, uint, 0);
     76
     77
     78/* debugfs: registers */
     79
     80struct reg {
     81	const char *name;
     82	int addr;
     83};
     84
     85#define REG_STRUCT_INIT(r) { #r, r }
     86
     87/* just a few random registers, might want to add more */
     88static const struct reg regs[] = {
     89	REG_STRUCT_INIT(AR5K_CR),
     90	REG_STRUCT_INIT(AR5K_RXDP),
     91	REG_STRUCT_INIT(AR5K_CFG),
     92	REG_STRUCT_INIT(AR5K_IER),
     93	REG_STRUCT_INIT(AR5K_BCR),
     94	REG_STRUCT_INIT(AR5K_RTSD0),
     95	REG_STRUCT_INIT(AR5K_RTSD1),
     96	REG_STRUCT_INIT(AR5K_TXCFG),
     97	REG_STRUCT_INIT(AR5K_RXCFG),
     98	REG_STRUCT_INIT(AR5K_RXJLA),
     99	REG_STRUCT_INIT(AR5K_MIBC),
    100	REG_STRUCT_INIT(AR5K_TOPS),
    101	REG_STRUCT_INIT(AR5K_RXNOFRM),
    102	REG_STRUCT_INIT(AR5K_TXNOFRM),
    103	REG_STRUCT_INIT(AR5K_RPGTO),
    104	REG_STRUCT_INIT(AR5K_RFCNT),
    105	REG_STRUCT_INIT(AR5K_MISC),
    106	REG_STRUCT_INIT(AR5K_QCUDCU_CLKGT),
    107	REG_STRUCT_INIT(AR5K_ISR),
    108	REG_STRUCT_INIT(AR5K_PISR),
    109	REG_STRUCT_INIT(AR5K_SISR0),
    110	REG_STRUCT_INIT(AR5K_SISR1),
    111	REG_STRUCT_INIT(AR5K_SISR2),
    112	REG_STRUCT_INIT(AR5K_SISR3),
    113	REG_STRUCT_INIT(AR5K_SISR4),
    114	REG_STRUCT_INIT(AR5K_IMR),
    115	REG_STRUCT_INIT(AR5K_PIMR),
    116	REG_STRUCT_INIT(AR5K_SIMR0),
    117	REG_STRUCT_INIT(AR5K_SIMR1),
    118	REG_STRUCT_INIT(AR5K_SIMR2),
    119	REG_STRUCT_INIT(AR5K_SIMR3),
    120	REG_STRUCT_INIT(AR5K_SIMR4),
    121	REG_STRUCT_INIT(AR5K_DCM_ADDR),
    122	REG_STRUCT_INIT(AR5K_DCCFG),
    123	REG_STRUCT_INIT(AR5K_CCFG),
    124	REG_STRUCT_INIT(AR5K_CPC0),
    125	REG_STRUCT_INIT(AR5K_CPC1),
    126	REG_STRUCT_INIT(AR5K_CPC2),
    127	REG_STRUCT_INIT(AR5K_CPC3),
    128	REG_STRUCT_INIT(AR5K_CPCOVF),
    129	REG_STRUCT_INIT(AR5K_RESET_CTL),
    130	REG_STRUCT_INIT(AR5K_SLEEP_CTL),
    131	REG_STRUCT_INIT(AR5K_INTPEND),
    132	REG_STRUCT_INIT(AR5K_SFR),
    133	REG_STRUCT_INIT(AR5K_PCICFG),
    134	REG_STRUCT_INIT(AR5K_GPIOCR),
    135	REG_STRUCT_INIT(AR5K_GPIODO),
    136	REG_STRUCT_INIT(AR5K_SREV),
    137};
    138
    139static void *reg_start(struct seq_file *seq, loff_t *pos)
    140{
    141	return *pos < ARRAY_SIZE(regs) ? (void *)&regs[*pos] : NULL;
    142}
    143
    144static void reg_stop(struct seq_file *seq, void *p)
    145{
    146	/* nothing to do */
    147}
    148
    149static void *reg_next(struct seq_file *seq, void *p, loff_t *pos)
    150{
    151	++*pos;
    152	return *pos < ARRAY_SIZE(regs) ? (void *)&regs[*pos] : NULL;
    153}
    154
    155static int reg_show(struct seq_file *seq, void *p)
    156{
    157	struct ath5k_hw *ah = seq->private;
    158	struct reg *r = p;
    159	seq_printf(seq, "%-25s0x%08x\n", r->name,
    160		ath5k_hw_reg_read(ah, r->addr));
    161	return 0;
    162}
    163
    164static const struct seq_operations registers_sops = {
    165	.start = reg_start,
    166	.next  = reg_next,
    167	.stop  = reg_stop,
    168	.show  = reg_show
    169};
    170
    171DEFINE_SEQ_ATTRIBUTE(registers);
    172
    173/* debugfs: beacons */
    174
    175static ssize_t read_file_beacon(struct file *file, char __user *user_buf,
    176				   size_t count, loff_t *ppos)
    177{
    178	struct ath5k_hw *ah = file->private_data;
    179	char buf[500];
    180	unsigned int len = 0;
    181	unsigned int v;
    182	u64 tsf;
    183
    184	v = ath5k_hw_reg_read(ah, AR5K_BEACON);
    185	len += scnprintf(buf + len, sizeof(buf) - len,
    186		"%-24s0x%08x\tintval: %d\tTIM: 0x%x\n",
    187		"AR5K_BEACON", v, v & AR5K_BEACON_PERIOD,
    188		(v & AR5K_BEACON_TIM) >> AR5K_BEACON_TIM_S);
    189
    190	len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\n",
    191		"AR5K_LAST_TSTP", ath5k_hw_reg_read(ah, AR5K_LAST_TSTP));
    192
    193	len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\n\n",
    194		"AR5K_BEACON_CNT", ath5k_hw_reg_read(ah, AR5K_BEACON_CNT));
    195
    196	v = ath5k_hw_reg_read(ah, AR5K_TIMER0);
    197	len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
    198		"AR5K_TIMER0 (TBTT)", v, v);
    199
    200	v = ath5k_hw_reg_read(ah, AR5K_TIMER1);
    201	len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
    202		"AR5K_TIMER1 (DMA)", v, v >> 3);
    203
    204	v = ath5k_hw_reg_read(ah, AR5K_TIMER2);
    205	len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
    206		"AR5K_TIMER2 (SWBA)", v, v >> 3);
    207
    208	v = ath5k_hw_reg_read(ah, AR5K_TIMER3);
    209	len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
    210		"AR5K_TIMER3 (ATIM)", v, v);
    211
    212	tsf = ath5k_hw_get_tsf64(ah);
    213	len += scnprintf(buf + len, sizeof(buf) - len,
    214		"TSF\t\t0x%016llx\tTU: %08x\n",
    215		(unsigned long long)tsf, TSF_TO_TU(tsf));
    216
    217	if (len > sizeof(buf))
    218		len = sizeof(buf);
    219
    220	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
    221}
    222
    223static ssize_t write_file_beacon(struct file *file,
    224				 const char __user *userbuf,
    225				 size_t count, loff_t *ppos)
    226{
    227	struct ath5k_hw *ah = file->private_data;
    228	char buf[20];
    229
    230	count = min_t(size_t, count, sizeof(buf) - 1);
    231	if (copy_from_user(buf, userbuf, count))
    232		return -EFAULT;
    233
    234	buf[count] = '\0';
    235	if (strncmp(buf, "disable", 7) == 0) {
    236		AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
    237		pr_info("debugfs disable beacons\n");
    238	} else if (strncmp(buf, "enable", 6) == 0) {
    239		AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
    240		pr_info("debugfs enable beacons\n");
    241	}
    242	return count;
    243}
    244
    245static const struct file_operations fops_beacon = {
    246	.read = read_file_beacon,
    247	.write = write_file_beacon,
    248	.open = simple_open,
    249	.owner = THIS_MODULE,
    250	.llseek = default_llseek,
    251};
    252
    253
    254/* debugfs: reset */
    255
    256static ssize_t write_file_reset(struct file *file,
    257				 const char __user *userbuf,
    258				 size_t count, loff_t *ppos)
    259{
    260	struct ath5k_hw *ah = file->private_data;
    261	ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "debug file triggered reset\n");
    262	ieee80211_queue_work(ah->hw, &ah->reset_work);
    263	return count;
    264}
    265
    266static const struct file_operations fops_reset = {
    267	.write = write_file_reset,
    268	.open = simple_open,
    269	.owner = THIS_MODULE,
    270	.llseek = noop_llseek,
    271};
    272
    273
    274/* debugfs: debug level */
    275
    276static const struct {
    277	enum ath5k_debug_level level;
    278	const char *name;
    279	const char *desc;
    280} dbg_info[] = {
    281	{ ATH5K_DEBUG_RESET,	"reset",	"reset and initialization" },
    282	{ ATH5K_DEBUG_INTR,	"intr",		"interrupt handling" },
    283	{ ATH5K_DEBUG_MODE,	"mode",		"mode init/setup" },
    284	{ ATH5K_DEBUG_XMIT,	"xmit",		"basic xmit operation" },
    285	{ ATH5K_DEBUG_BEACON,	"beacon",	"beacon handling" },
    286	{ ATH5K_DEBUG_CALIBRATE, "calib",	"periodic calibration" },
    287	{ ATH5K_DEBUG_TXPOWER,	"txpower",	"transmit power setting" },
    288	{ ATH5K_DEBUG_LED,	"led",		"LED management" },
    289	{ ATH5K_DEBUG_DUMPBANDS, "dumpbands",	"dump bands" },
    290	{ ATH5K_DEBUG_DMA,	"dma",		"dma start/stop" },
    291	{ ATH5K_DEBUG_ANI,	"ani",		"adaptive noise immunity" },
    292	{ ATH5K_DEBUG_DESC,	"desc",		"descriptor chains" },
    293	{ ATH5K_DEBUG_ANY,	"all",		"show all debug levels" },
    294};
    295
    296static ssize_t read_file_debug(struct file *file, char __user *user_buf,
    297				   size_t count, loff_t *ppos)
    298{
    299	struct ath5k_hw *ah = file->private_data;
    300	char buf[700];
    301	unsigned int len = 0;
    302	unsigned int i;
    303
    304	len += scnprintf(buf + len, sizeof(buf) - len,
    305		"DEBUG LEVEL: 0x%08x\n\n", ah->debug.level);
    306
    307	for (i = 0; i < ARRAY_SIZE(dbg_info) - 1; i++) {
    308		len += scnprintf(buf + len, sizeof(buf) - len,
    309			"%10s %c 0x%08x - %s\n", dbg_info[i].name,
    310			ah->debug.level & dbg_info[i].level ? '+' : ' ',
    311			dbg_info[i].level, dbg_info[i].desc);
    312	}
    313	len += scnprintf(buf + len, sizeof(buf) - len,
    314		"%10s %c 0x%08x - %s\n", dbg_info[i].name,
    315		ah->debug.level == dbg_info[i].level ? '+' : ' ',
    316		dbg_info[i].level, dbg_info[i].desc);
    317
    318	if (len > sizeof(buf))
    319		len = sizeof(buf);
    320
    321	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
    322}
    323
    324static ssize_t write_file_debug(struct file *file,
    325				 const char __user *userbuf,
    326				 size_t count, loff_t *ppos)
    327{
    328	struct ath5k_hw *ah = file->private_data;
    329	unsigned int i;
    330	char buf[20];
    331
    332	count = min_t(size_t, count, sizeof(buf) - 1);
    333	if (copy_from_user(buf, userbuf, count))
    334		return -EFAULT;
    335
    336	buf[count] = '\0';
    337	for (i = 0; i < ARRAY_SIZE(dbg_info); i++) {
    338		if (strncmp(buf, dbg_info[i].name,
    339					strlen(dbg_info[i].name)) == 0) {
    340			ah->debug.level ^= dbg_info[i].level; /* toggle bit */
    341			break;
    342		}
    343	}
    344	return count;
    345}
    346
    347static const struct file_operations fops_debug = {
    348	.read = read_file_debug,
    349	.write = write_file_debug,
    350	.open = simple_open,
    351	.owner = THIS_MODULE,
    352	.llseek = default_llseek,
    353};
    354
    355
    356/* debugfs: antenna */
    357
    358static ssize_t read_file_antenna(struct file *file, char __user *user_buf,
    359				   size_t count, loff_t *ppos)
    360{
    361	struct ath5k_hw *ah = file->private_data;
    362	char buf[700];
    363	unsigned int len = 0;
    364	unsigned int i;
    365	unsigned int v;
    366
    367	len += scnprintf(buf + len, sizeof(buf) - len, "antenna mode\t%d\n",
    368		ah->ah_ant_mode);
    369	len += scnprintf(buf + len, sizeof(buf) - len, "default antenna\t%d\n",
    370		ah->ah_def_ant);
    371	len += scnprintf(buf + len, sizeof(buf) - len, "tx antenna\t%d\n",
    372		ah->ah_tx_ant);
    373
    374	len += scnprintf(buf + len, sizeof(buf) - len, "\nANTENNA\t\tRX\tTX\n");
    375	for (i = 1; i < ARRAY_SIZE(ah->stats.antenna_rx); i++) {
    376		len += scnprintf(buf + len, sizeof(buf) - len,
    377			"[antenna %d]\t%d\t%d\n",
    378			i, ah->stats.antenna_rx[i], ah->stats.antenna_tx[i]);
    379	}
    380	len += scnprintf(buf + len, sizeof(buf) - len, "[invalid]\t%d\t%d\n",
    381			ah->stats.antenna_rx[0], ah->stats.antenna_tx[0]);
    382
    383	v = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
    384	len += scnprintf(buf + len, sizeof(buf) - len,
    385			"\nAR5K_DEFAULT_ANTENNA\t0x%08x\n", v);
    386
    387	v = ath5k_hw_reg_read(ah, AR5K_STA_ID1);
    388	len += scnprintf(buf + len, sizeof(buf) - len,
    389		"AR5K_STA_ID1_DEFAULT_ANTENNA\t%d\n",
    390		(v & AR5K_STA_ID1_DEFAULT_ANTENNA) != 0);
    391	len += scnprintf(buf + len, sizeof(buf) - len,
    392		"AR5K_STA_ID1_DESC_ANTENNA\t%d\n",
    393		(v & AR5K_STA_ID1_DESC_ANTENNA) != 0);
    394	len += scnprintf(buf + len, sizeof(buf) - len,
    395		"AR5K_STA_ID1_RTS_DEF_ANTENNA\t%d\n",
    396		(v & AR5K_STA_ID1_RTS_DEF_ANTENNA) != 0);
    397	len += scnprintf(buf + len, sizeof(buf) - len,
    398		"AR5K_STA_ID1_SELFGEN_DEF_ANT\t%d\n",
    399		(v & AR5K_STA_ID1_SELFGEN_DEF_ANT) != 0);
    400
    401	v = ath5k_hw_reg_read(ah, AR5K_PHY_AGCCTL);
    402	len += scnprintf(buf + len, sizeof(buf) - len,
    403		"\nAR5K_PHY_AGCCTL_OFDM_DIV_DIS\t%d\n",
    404		(v & AR5K_PHY_AGCCTL_OFDM_DIV_DIS) != 0);
    405
    406	v = ath5k_hw_reg_read(ah, AR5K_PHY_RESTART);
    407	len += scnprintf(buf + len, sizeof(buf) - len,
    408		"AR5K_PHY_RESTART_DIV_GC\t\t%x\n",
    409		(v & AR5K_PHY_RESTART_DIV_GC) >> AR5K_PHY_RESTART_DIV_GC_S);
    410
    411	v = ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ANT_DIV);
    412	len += scnprintf(buf + len, sizeof(buf) - len,
    413		"AR5K_PHY_FAST_ANT_DIV_EN\t%d\n",
    414		(v & AR5K_PHY_FAST_ANT_DIV_EN) != 0);
    415
    416	v = ath5k_hw_reg_read(ah, AR5K_PHY_ANT_SWITCH_TABLE_0);
    417	len += scnprintf(buf + len, sizeof(buf) - len,
    418			"\nAR5K_PHY_ANT_SWITCH_TABLE_0\t0x%08x\n", v);
    419	v = ath5k_hw_reg_read(ah, AR5K_PHY_ANT_SWITCH_TABLE_1);
    420	len += scnprintf(buf + len, sizeof(buf) - len,
    421			"AR5K_PHY_ANT_SWITCH_TABLE_1\t0x%08x\n", v);
    422
    423	if (len > sizeof(buf))
    424		len = sizeof(buf);
    425
    426	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
    427}
    428
    429static ssize_t write_file_antenna(struct file *file,
    430				 const char __user *userbuf,
    431				 size_t count, loff_t *ppos)
    432{
    433	struct ath5k_hw *ah = file->private_data;
    434	unsigned int i;
    435	char buf[20];
    436
    437	count = min_t(size_t, count, sizeof(buf) - 1);
    438	if (copy_from_user(buf, userbuf, count))
    439		return -EFAULT;
    440
    441	buf[count] = '\0';
    442	if (strncmp(buf, "diversity", 9) == 0) {
    443		ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT);
    444		pr_info("debug: enable diversity\n");
    445	} else if (strncmp(buf, "fixed-a", 7) == 0) {
    446		ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_A);
    447		pr_info("debug: fixed antenna A\n");
    448	} else if (strncmp(buf, "fixed-b", 7) == 0) {
    449		ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_B);
    450		pr_info("debug: fixed antenna B\n");
    451	} else if (strncmp(buf, "clear", 5) == 0) {
    452		for (i = 0; i < ARRAY_SIZE(ah->stats.antenna_rx); i++) {
    453			ah->stats.antenna_rx[i] = 0;
    454			ah->stats.antenna_tx[i] = 0;
    455		}
    456		pr_info("debug: cleared antenna stats\n");
    457	}
    458	return count;
    459}
    460
    461static const struct file_operations fops_antenna = {
    462	.read = read_file_antenna,
    463	.write = write_file_antenna,
    464	.open = simple_open,
    465	.owner = THIS_MODULE,
    466	.llseek = default_llseek,
    467};
    468
    469/* debugfs: misc */
    470
    471static ssize_t read_file_misc(struct file *file, char __user *user_buf,
    472				   size_t count, loff_t *ppos)
    473{
    474	struct ath5k_hw *ah = file->private_data;
    475	char buf[700];
    476	unsigned int len = 0;
    477	u32 filt = ath5k_hw_get_rx_filter(ah);
    478
    479	len += scnprintf(buf + len, sizeof(buf) - len, "bssid-mask: %pM\n",
    480			ah->bssidmask);
    481	len += scnprintf(buf + len, sizeof(buf) - len, "filter-flags: 0x%x ",
    482			filt);
    483	if (filt & AR5K_RX_FILTER_UCAST)
    484		len += scnprintf(buf + len, sizeof(buf) - len, " UCAST");
    485	if (filt & AR5K_RX_FILTER_MCAST)
    486		len += scnprintf(buf + len, sizeof(buf) - len, " MCAST");
    487	if (filt & AR5K_RX_FILTER_BCAST)
    488		len += scnprintf(buf + len, sizeof(buf) - len, " BCAST");
    489	if (filt & AR5K_RX_FILTER_CONTROL)
    490		len += scnprintf(buf + len, sizeof(buf) - len, " CONTROL");
    491	if (filt & AR5K_RX_FILTER_BEACON)
    492		len += scnprintf(buf + len, sizeof(buf) - len, " BEACON");
    493	if (filt & AR5K_RX_FILTER_PROM)
    494		len += scnprintf(buf + len, sizeof(buf) - len, " PROM");
    495	if (filt & AR5K_RX_FILTER_XRPOLL)
    496		len += scnprintf(buf + len, sizeof(buf) - len, " XRPOLL");
    497	if (filt & AR5K_RX_FILTER_PROBEREQ)
    498		len += scnprintf(buf + len, sizeof(buf) - len, " PROBEREQ");
    499	if (filt & AR5K_RX_FILTER_PHYERR_5212)
    500		len += scnprintf(buf + len, sizeof(buf) - len, " PHYERR-5212");
    501	if (filt & AR5K_RX_FILTER_RADARERR_5212)
    502		len += scnprintf(buf + len, sizeof(buf) - len, " RADARERR-5212");
    503	if (filt & AR5K_RX_FILTER_PHYERR_5211)
    504		snprintf(buf + len, sizeof(buf) - len, " PHYERR-5211");
    505	if (filt & AR5K_RX_FILTER_RADARERR_5211)
    506		len += scnprintf(buf + len, sizeof(buf) - len, " RADARERR-5211");
    507
    508	len += scnprintf(buf + len, sizeof(buf) - len, "\nopmode: %s (%d)\n",
    509			ath_opmode_to_string(ah->opmode), ah->opmode);
    510
    511	if (len > sizeof(buf))
    512		len = sizeof(buf);
    513
    514	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
    515}
    516
    517static const struct file_operations fops_misc = {
    518	.read = read_file_misc,
    519	.open = simple_open,
    520	.owner = THIS_MODULE,
    521};
    522
    523
    524/* debugfs: frameerrors */
    525
    526static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf,
    527				   size_t count, loff_t *ppos)
    528{
    529	struct ath5k_hw *ah = file->private_data;
    530	struct ath5k_statistics *st = &ah->stats;
    531	char buf[700];
    532	unsigned int len = 0;
    533	int i;
    534
    535	len += scnprintf(buf + len, sizeof(buf) - len,
    536			"RX\n---------------------\n");
    537	len += scnprintf(buf + len, sizeof(buf) - len, "CRC\t%u\t(%u%%)\n",
    538			st->rxerr_crc,
    539			st->rx_all_count > 0 ?
    540				st->rxerr_crc * 100 / st->rx_all_count : 0);
    541	len += scnprintf(buf + len, sizeof(buf) - len, "PHY\t%u\t(%u%%)\n",
    542			st->rxerr_phy,
    543			st->rx_all_count > 0 ?
    544				st->rxerr_phy * 100 / st->rx_all_count : 0);
    545	for (i = 0; i < 32; i++) {
    546		if (st->rxerr_phy_code[i])
    547			len += scnprintf(buf + len, sizeof(buf) - len,
    548				" phy_err[%u]\t%u\n",
    549				i, st->rxerr_phy_code[i]);
    550	}
    551
    552	len += scnprintf(buf + len, sizeof(buf) - len, "FIFO\t%u\t(%u%%)\n",
    553			st->rxerr_fifo,
    554			st->rx_all_count > 0 ?
    555				st->rxerr_fifo * 100 / st->rx_all_count : 0);
    556	len += scnprintf(buf + len, sizeof(buf) - len, "decrypt\t%u\t(%u%%)\n",
    557			st->rxerr_decrypt,
    558			st->rx_all_count > 0 ?
    559				st->rxerr_decrypt * 100 / st->rx_all_count : 0);
    560	len += scnprintf(buf + len, sizeof(buf) - len, "MIC\t%u\t(%u%%)\n",
    561			st->rxerr_mic,
    562			st->rx_all_count > 0 ?
    563				st->rxerr_mic * 100 / st->rx_all_count : 0);
    564	len += scnprintf(buf + len, sizeof(buf) - len, "process\t%u\t(%u%%)\n",
    565			st->rxerr_proc,
    566			st->rx_all_count > 0 ?
    567				st->rxerr_proc * 100 / st->rx_all_count : 0);
    568	len += scnprintf(buf + len, sizeof(buf) - len, "jumbo\t%u\t(%u%%)\n",
    569			st->rxerr_jumbo,
    570			st->rx_all_count > 0 ?
    571				st->rxerr_jumbo * 100 / st->rx_all_count : 0);
    572	len += scnprintf(buf + len, sizeof(buf) - len, "[RX all\t%u]\n",
    573			st->rx_all_count);
    574	len += scnprintf(buf + len, sizeof(buf) - len, "RX-all-bytes\t%u\n",
    575			st->rx_bytes_count);
    576
    577	len += scnprintf(buf + len, sizeof(buf) - len,
    578			"\nTX\n---------------------\n");
    579	len += scnprintf(buf + len, sizeof(buf) - len, "retry\t%u\t(%u%%)\n",
    580			st->txerr_retry,
    581			st->tx_all_count > 0 ?
    582				st->txerr_retry * 100 / st->tx_all_count : 0);
    583	len += scnprintf(buf + len, sizeof(buf) - len, "FIFO\t%u\t(%u%%)\n",
    584			st->txerr_fifo,
    585			st->tx_all_count > 0 ?
    586				st->txerr_fifo * 100 / st->tx_all_count : 0);
    587	len += scnprintf(buf + len, sizeof(buf) - len, "filter\t%u\t(%u%%)\n",
    588			st->txerr_filt,
    589			st->tx_all_count > 0 ?
    590				st->txerr_filt * 100 / st->tx_all_count : 0);
    591	len += scnprintf(buf + len, sizeof(buf) - len, "[TX all\t%u]\n",
    592			st->tx_all_count);
    593	len += scnprintf(buf + len, sizeof(buf) - len, "TX-all-bytes\t%u\n",
    594			st->tx_bytes_count);
    595
    596	if (len > sizeof(buf))
    597		len = sizeof(buf);
    598
    599	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
    600}
    601
    602static ssize_t write_file_frameerrors(struct file *file,
    603				 const char __user *userbuf,
    604				 size_t count, loff_t *ppos)
    605{
    606	struct ath5k_hw *ah = file->private_data;
    607	struct ath5k_statistics *st = &ah->stats;
    608	char buf[20];
    609
    610	count = min_t(size_t, count, sizeof(buf) - 1);
    611	if (copy_from_user(buf, userbuf, count))
    612		return -EFAULT;
    613
    614	buf[count] = '\0';
    615	if (strncmp(buf, "clear", 5) == 0) {
    616		st->rxerr_crc = 0;
    617		st->rxerr_phy = 0;
    618		st->rxerr_fifo = 0;
    619		st->rxerr_decrypt = 0;
    620		st->rxerr_mic = 0;
    621		st->rxerr_proc = 0;
    622		st->rxerr_jumbo = 0;
    623		st->rx_all_count = 0;
    624		st->txerr_retry = 0;
    625		st->txerr_fifo = 0;
    626		st->txerr_filt = 0;
    627		st->tx_all_count = 0;
    628		pr_info("debug: cleared frameerrors stats\n");
    629	}
    630	return count;
    631}
    632
    633static const struct file_operations fops_frameerrors = {
    634	.read = read_file_frameerrors,
    635	.write = write_file_frameerrors,
    636	.open = simple_open,
    637	.owner = THIS_MODULE,
    638	.llseek = default_llseek,
    639};
    640
    641
    642/* debugfs: ani */
    643
    644static ssize_t read_file_ani(struct file *file, char __user *user_buf,
    645				   size_t count, loff_t *ppos)
    646{
    647	struct ath5k_hw *ah = file->private_data;
    648	struct ath5k_statistics *st = &ah->stats;
    649	struct ath5k_ani_state *as = &ah->ani_state;
    650
    651	char buf[700];
    652	unsigned int len = 0;
    653
    654	len += scnprintf(buf + len, sizeof(buf) - len,
    655			"HW has PHY error counters:\t%s\n",
    656			ah->ah_capabilities.cap_has_phyerr_counters ?
    657			"yes" : "no");
    658	len += scnprintf(buf + len, sizeof(buf) - len,
    659			"HW max spur immunity level:\t%d\n",
    660			as->max_spur_level);
    661	len += scnprintf(buf + len, sizeof(buf) - len,
    662		"\nANI state\n--------------------------------------------\n");
    663	len += scnprintf(buf + len, sizeof(buf) - len, "operating mode:\t\t\t");
    664	switch (as->ani_mode) {
    665	case ATH5K_ANI_MODE_OFF:
    666		len += scnprintf(buf + len, sizeof(buf) - len, "OFF\n");
    667		break;
    668	case ATH5K_ANI_MODE_MANUAL_LOW:
    669		len += scnprintf(buf + len, sizeof(buf) - len,
    670			"MANUAL LOW\n");
    671		break;
    672	case ATH5K_ANI_MODE_MANUAL_HIGH:
    673		len += scnprintf(buf + len, sizeof(buf) - len,
    674			"MANUAL HIGH\n");
    675		break;
    676	case ATH5K_ANI_MODE_AUTO:
    677		len += scnprintf(buf + len, sizeof(buf) - len, "AUTO\n");
    678		break;
    679	default:
    680		len += scnprintf(buf + len, sizeof(buf) - len,
    681			"??? (not good)\n");
    682		break;
    683	}
    684	len += scnprintf(buf + len, sizeof(buf) - len,
    685			"noise immunity level:\t\t%d\n",
    686			as->noise_imm_level);
    687	len += scnprintf(buf + len, sizeof(buf) - len,
    688			"spur immunity level:\t\t%d\n",
    689			as->spur_level);
    690	len += scnprintf(buf + len, sizeof(buf) - len,
    691			"firstep level:\t\t\t%d\n",
    692			as->firstep_level);
    693	len += scnprintf(buf + len, sizeof(buf) - len,
    694			"OFDM weak signal detection:\t%s\n",
    695			as->ofdm_weak_sig ? "on" : "off");
    696	len += scnprintf(buf + len, sizeof(buf) - len,
    697			"CCK weak signal detection:\t%s\n",
    698			as->cck_weak_sig ? "on" : "off");
    699
    700	len += scnprintf(buf + len, sizeof(buf) - len,
    701			"\nMIB INTERRUPTS:\t\t%u\n",
    702			st->mib_intr);
    703	len += scnprintf(buf + len, sizeof(buf) - len,
    704			"beacon RSSI average:\t%d\n",
    705			(int)ewma_beacon_rssi_read(&ah->ah_beacon_rssi_avg));
    706
    707#define CC_PRINT(_struct, _field) \
    708	_struct._field, \
    709	_struct.cycles > 0 ? \
    710	_struct._field * 100 / _struct.cycles : 0
    711
    712	len += scnprintf(buf + len, sizeof(buf) - len,
    713			"profcnt tx\t\t%u\t(%d%%)\n",
    714			CC_PRINT(as->last_cc, tx_frame));
    715	len += scnprintf(buf + len, sizeof(buf) - len,
    716			"profcnt rx\t\t%u\t(%d%%)\n",
    717			CC_PRINT(as->last_cc, rx_frame));
    718	len += scnprintf(buf + len, sizeof(buf) - len,
    719			"profcnt busy\t\t%u\t(%d%%)\n",
    720			CC_PRINT(as->last_cc, rx_busy));
    721#undef CC_PRINT
    722	len += scnprintf(buf + len, sizeof(buf) - len, "profcnt cycles\t\t%u\n",
    723			as->last_cc.cycles);
    724	len += scnprintf(buf + len, sizeof(buf) - len,
    725			"listen time\t\t%d\tlast: %d\n",
    726			as->listen_time, as->last_listen);
    727	len += scnprintf(buf + len, sizeof(buf) - len,
    728			"OFDM errors\t\t%u\tlast: %u\tsum: %u\n",
    729			as->ofdm_errors, as->last_ofdm_errors,
    730			as->sum_ofdm_errors);
    731	len += scnprintf(buf + len, sizeof(buf) - len,
    732			"CCK errors\t\t%u\tlast: %u\tsum: %u\n",
    733			as->cck_errors, as->last_cck_errors,
    734			as->sum_cck_errors);
    735	len += scnprintf(buf + len, sizeof(buf) - len,
    736			"AR5K_PHYERR_CNT1\t%x\t(=%d)\n",
    737			ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1),
    738			ATH5K_ANI_OFDM_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX -
    739			ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1)));
    740	len += scnprintf(buf + len, sizeof(buf) - len,
    741			"AR5K_PHYERR_CNT2\t%x\t(=%d)\n",
    742			ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2),
    743			ATH5K_ANI_CCK_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX -
    744			ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2)));
    745
    746	if (len > sizeof(buf))
    747		len = sizeof(buf);
    748
    749	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
    750}
    751
    752static ssize_t write_file_ani(struct file *file,
    753				 const char __user *userbuf,
    754				 size_t count, loff_t *ppos)
    755{
    756	struct ath5k_hw *ah = file->private_data;
    757	char buf[20];
    758
    759	count = min_t(size_t, count, sizeof(buf) - 1);
    760	if (copy_from_user(buf, userbuf, count))
    761		return -EFAULT;
    762
    763	buf[count] = '\0';
    764	if (strncmp(buf, "sens-low", 8) == 0) {
    765		ath5k_ani_init(ah, ATH5K_ANI_MODE_MANUAL_HIGH);
    766	} else if (strncmp(buf, "sens-high", 9) == 0) {
    767		ath5k_ani_init(ah, ATH5K_ANI_MODE_MANUAL_LOW);
    768	} else if (strncmp(buf, "ani-off", 7) == 0) {
    769		ath5k_ani_init(ah, ATH5K_ANI_MODE_OFF);
    770	} else if (strncmp(buf, "ani-on", 6) == 0) {
    771		ath5k_ani_init(ah, ATH5K_ANI_MODE_AUTO);
    772	} else if (strncmp(buf, "noise-low", 9) == 0) {
    773		ath5k_ani_set_noise_immunity_level(ah, 0);
    774	} else if (strncmp(buf, "noise-high", 10) == 0) {
    775		ath5k_ani_set_noise_immunity_level(ah,
    776						   ATH5K_ANI_MAX_NOISE_IMM_LVL);
    777	} else if (strncmp(buf, "spur-low", 8) == 0) {
    778		ath5k_ani_set_spur_immunity_level(ah, 0);
    779	} else if (strncmp(buf, "spur-high", 9) == 0) {
    780		ath5k_ani_set_spur_immunity_level(ah,
    781						  ah->ani_state.max_spur_level);
    782	} else if (strncmp(buf, "fir-low", 7) == 0) {
    783		ath5k_ani_set_firstep_level(ah, 0);
    784	} else if (strncmp(buf, "fir-high", 8) == 0) {
    785		ath5k_ani_set_firstep_level(ah, ATH5K_ANI_MAX_FIRSTEP_LVL);
    786	} else if (strncmp(buf, "ofdm-off", 8) == 0) {
    787		ath5k_ani_set_ofdm_weak_signal_detection(ah, false);
    788	} else if (strncmp(buf, "ofdm-on", 7) == 0) {
    789		ath5k_ani_set_ofdm_weak_signal_detection(ah, true);
    790	} else if (strncmp(buf, "cck-off", 7) == 0) {
    791		ath5k_ani_set_cck_weak_signal_detection(ah, false);
    792	} else if (strncmp(buf, "cck-on", 6) == 0) {
    793		ath5k_ani_set_cck_weak_signal_detection(ah, true);
    794	}
    795	return count;
    796}
    797
    798static const struct file_operations fops_ani = {
    799	.read = read_file_ani,
    800	.write = write_file_ani,
    801	.open = simple_open,
    802	.owner = THIS_MODULE,
    803	.llseek = default_llseek,
    804};
    805
    806
    807/* debugfs: queues etc */
    808
    809static ssize_t read_file_queue(struct file *file, char __user *user_buf,
    810				   size_t count, loff_t *ppos)
    811{
    812	struct ath5k_hw *ah = file->private_data;
    813	char buf[700];
    814	unsigned int len = 0;
    815
    816	struct ath5k_txq *txq;
    817	struct ath5k_buf *bf, *bf0;
    818	int i, n;
    819
    820	len += scnprintf(buf + len, sizeof(buf) - len,
    821			"available txbuffers: %d\n", ah->txbuf_len);
    822
    823	for (i = 0; i < ARRAY_SIZE(ah->txqs); i++) {
    824		txq = &ah->txqs[i];
    825
    826		len += scnprintf(buf + len, sizeof(buf) - len,
    827			"%02d: %ssetup\n", i, txq->setup ? "" : "not ");
    828
    829		if (!txq->setup)
    830			continue;
    831
    832		n = 0;
    833		spin_lock_bh(&txq->lock);
    834		list_for_each_entry_safe(bf, bf0, &txq->q, list)
    835			n++;
    836		spin_unlock_bh(&txq->lock);
    837
    838		len += scnprintf(buf + len, sizeof(buf) - len,
    839				"  len: %d bufs: %d\n", txq->txq_len, n);
    840		len += scnprintf(buf + len, sizeof(buf) - len,
    841				"  stuck: %d\n", txq->txq_stuck);
    842	}
    843
    844	if (len > sizeof(buf))
    845		len = sizeof(buf);
    846
    847	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
    848}
    849
    850static ssize_t write_file_queue(struct file *file,
    851				 const char __user *userbuf,
    852				 size_t count, loff_t *ppos)
    853{
    854	struct ath5k_hw *ah = file->private_data;
    855	char buf[20];
    856
    857	count = min_t(size_t, count, sizeof(buf) - 1);
    858	if (copy_from_user(buf, userbuf, count))
    859		return -EFAULT;
    860
    861	buf[count] = '\0';
    862	if (strncmp(buf, "start", 5) == 0)
    863		ieee80211_wake_queues(ah->hw);
    864	else if (strncmp(buf, "stop", 4) == 0)
    865		ieee80211_stop_queues(ah->hw);
    866
    867	return count;
    868}
    869
    870
    871static const struct file_operations fops_queue = {
    872	.read = read_file_queue,
    873	.write = write_file_queue,
    874	.open = simple_open,
    875	.owner = THIS_MODULE,
    876	.llseek = default_llseek,
    877};
    878
    879/* debugfs: eeprom */
    880
    881struct eeprom_private {
    882	u16 *buf;
    883	int len;
    884};
    885
    886static int open_file_eeprom(struct inode *inode, struct file *file)
    887{
    888	struct eeprom_private *ep;
    889	struct ath5k_hw *ah = inode->i_private;
    890	bool res;
    891	int i, ret;
    892	u32 eesize;	/* NB: in 16-bit words */
    893	u16 val, *buf;
    894
    895	/* Get eeprom size */
    896
    897	res = ath5k_hw_nvram_read(ah, AR5K_EEPROM_SIZE_UPPER, &val);
    898	if (!res)
    899		return -EACCES;
    900
    901	if (val == 0) {
    902		eesize = AR5K_EEPROM_INFO_MAX + AR5K_EEPROM_INFO_BASE;
    903	} else {
    904		eesize = (val & AR5K_EEPROM_SIZE_UPPER_MASK) <<
    905			AR5K_EEPROM_SIZE_ENDLOC_SHIFT;
    906		ath5k_hw_nvram_read(ah, AR5K_EEPROM_SIZE_LOWER, &val);
    907		eesize = eesize | val;
    908	}
    909
    910	if (eesize > 4096)
    911		return -EINVAL;
    912
    913	/* Create buffer and read in eeprom */
    914
    915	buf = vmalloc(array_size(eesize, 2));
    916	if (!buf) {
    917		ret = -ENOMEM;
    918		goto err;
    919	}
    920
    921	for (i = 0; i < eesize; ++i) {
    922		if (!ath5k_hw_nvram_read(ah, i, &val)) {
    923			ret = -EIO;
    924			goto freebuf;
    925		}
    926		buf[i] = val;
    927	}
    928
    929	/* Create private struct and assign to file */
    930
    931	ep = kmalloc(sizeof(*ep), GFP_KERNEL);
    932	if (!ep) {
    933		ret = -ENOMEM;
    934		goto freebuf;
    935	}
    936
    937	ep->buf = buf;
    938	ep->len = eesize * 2;
    939
    940	file->private_data = (void *)ep;
    941
    942	return 0;
    943
    944freebuf:
    945	vfree(buf);
    946err:
    947	return ret;
    948
    949}
    950
    951static ssize_t read_file_eeprom(struct file *file, char __user *user_buf,
    952				   size_t count, loff_t *ppos)
    953{
    954	struct eeprom_private *ep = file->private_data;
    955
    956	return simple_read_from_buffer(user_buf, count, ppos, ep->buf, ep->len);
    957}
    958
    959static int release_file_eeprom(struct inode *inode, struct file *file)
    960{
    961	struct eeprom_private *ep = file->private_data;
    962
    963	vfree(ep->buf);
    964	kfree(ep);
    965
    966	return 0;
    967}
    968
    969static const struct file_operations fops_eeprom = {
    970	.open = open_file_eeprom,
    971	.read = read_file_eeprom,
    972	.release = release_file_eeprom,
    973	.owner = THIS_MODULE,
    974};
    975
    976
    977void
    978ath5k_debug_init_device(struct ath5k_hw *ah)
    979{
    980	struct dentry *phydir;
    981
    982	ah->debug.level = ath5k_debug;
    983
    984	phydir = debugfs_create_dir("ath5k", ah->hw->wiphy->debugfsdir);
    985	if (!phydir)
    986		return;
    987
    988	debugfs_create_file("debug", 0600, phydir, ah, &fops_debug);
    989	debugfs_create_file("registers", 0400, phydir, ah, &registers_fops);
    990	debugfs_create_file("beacon", 0600, phydir, ah, &fops_beacon);
    991	debugfs_create_file("reset", 0200, phydir, ah, &fops_reset);
    992	debugfs_create_file("antenna", 0600, phydir, ah, &fops_antenna);
    993	debugfs_create_file("misc", 0400, phydir, ah, &fops_misc);
    994	debugfs_create_file("eeprom", 0400, phydir, ah, &fops_eeprom);
    995	debugfs_create_file("frameerrors", 0600, phydir, ah, &fops_frameerrors);
    996	debugfs_create_file("ani", 0600, phydir, ah, &fops_ani);
    997	debugfs_create_file("queue", 0600, phydir, ah, &fops_queue);
    998	debugfs_create_bool("32khz_clock", 0600, phydir,
    999			    &ah->ah_use_32khz_clock);
   1000}
   1001
   1002/* functions used in other places */
   1003
   1004void
   1005ath5k_debug_dump_bands(struct ath5k_hw *ah)
   1006{
   1007	unsigned int b, i;
   1008
   1009	if (likely(!(ah->debug.level & ATH5K_DEBUG_DUMPBANDS)))
   1010		return;
   1011
   1012	for (b = 0; b < NUM_NL80211_BANDS; b++) {
   1013		struct ieee80211_supported_band *band = &ah->sbands[b];
   1014		char bname[6];
   1015		switch (band->band) {
   1016		case NL80211_BAND_2GHZ:
   1017			strcpy(bname, "2 GHz");
   1018			break;
   1019		case NL80211_BAND_5GHZ:
   1020			strcpy(bname, "5 GHz");
   1021			break;
   1022		default:
   1023			printk(KERN_DEBUG "Band not supported: %d\n",
   1024				band->band);
   1025			return;
   1026		}
   1027		printk(KERN_DEBUG "Band %s: channels %d, rates %d\n", bname,
   1028				band->n_channels, band->n_bitrates);
   1029		printk(KERN_DEBUG " channels:\n");
   1030		for (i = 0; i < band->n_channels; i++)
   1031			printk(KERN_DEBUG "  %3d %d %.4x %.4x\n",
   1032					ieee80211_frequency_to_channel(
   1033						band->channels[i].center_freq),
   1034					band->channels[i].center_freq,
   1035					band->channels[i].hw_value,
   1036					band->channels[i].flags);
   1037		printk(KERN_DEBUG " rates:\n");
   1038		for (i = 0; i < band->n_bitrates; i++)
   1039			printk(KERN_DEBUG "  %4d %.4x %.4x %.4x\n",
   1040					band->bitrates[i].bitrate,
   1041					band->bitrates[i].hw_value,
   1042					band->bitrates[i].flags,
   1043					band->bitrates[i].hw_value_short);
   1044	}
   1045}
   1046
   1047static inline void
   1048ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done,
   1049		       struct ath5k_rx_status *rs)
   1050{
   1051	struct ath5k_desc *ds = bf->desc;
   1052	struct ath5k_hw_all_rx_desc *rd = &ds->ud.ds_rx;
   1053
   1054	printk(KERN_DEBUG "R (%p %llx) %08x %08x %08x %08x %08x %08x %c\n",
   1055		ds, (unsigned long long)bf->daddr,
   1056		ds->ds_link, ds->ds_data,
   1057		rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1,
   1058		rd->rx_stat.rx_status_0, rd->rx_stat.rx_status_1,
   1059		!done ? ' ' : (rs->rs_status == 0) ? '*' : '!');
   1060}
   1061
   1062void
   1063ath5k_debug_printrxbuffs(struct ath5k_hw *ah)
   1064{
   1065	struct ath5k_desc *ds;
   1066	struct ath5k_buf *bf;
   1067	struct ath5k_rx_status rs = {};
   1068	int status;
   1069
   1070	if (likely(!(ah->debug.level & ATH5K_DEBUG_DESC)))
   1071		return;
   1072
   1073	printk(KERN_DEBUG "rxdp %x, rxlink %p\n",
   1074		ath5k_hw_get_rxdp(ah), ah->rxlink);
   1075
   1076	spin_lock_bh(&ah->rxbuflock);
   1077	list_for_each_entry(bf, &ah->rxbuf, list) {
   1078		ds = bf->desc;
   1079		status = ah->ah_proc_rx_desc(ah, ds, &rs);
   1080		if (!status)
   1081			ath5k_debug_printrxbuf(bf, status == 0, &rs);
   1082	}
   1083	spin_unlock_bh(&ah->rxbuflock);
   1084}
   1085
   1086void
   1087ath5k_debug_printtxbuf(struct ath5k_hw *ah, struct ath5k_buf *bf)
   1088{
   1089	struct ath5k_desc *ds = bf->desc;
   1090	struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212;
   1091	struct ath5k_tx_status ts = {};
   1092	int done;
   1093
   1094	if (likely(!(ah->debug.level & ATH5K_DEBUG_DESC)))
   1095		return;
   1096
   1097	done = ah->ah_proc_tx_desc(ah, bf->desc, &ts);
   1098
   1099	printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x "
   1100		"%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link,
   1101		ds->ds_data, td->tx_ctl.tx_control_0, td->tx_ctl.tx_control_1,
   1102		td->tx_ctl.tx_control_2, td->tx_ctl.tx_control_3,
   1103		td->tx_stat.tx_status_0, td->tx_stat.tx_status_1,
   1104		done ? ' ' : (ts.ts_status == 0) ? '*' : '!');
   1105}