Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2007-2008 Bruno Randolf <bruno@thinktube.com>
0003  *
0004  *  This file is free software: you may copy, redistribute and/or modify it
0005  *  under the terms of the GNU General Public License as published by the
0006  *  Free Software Foundation, either version 2 of the License, or (at your
0007  *  option) any later version.
0008  *
0009  *  This file is distributed in the hope that it will be useful, but
0010  *  WITHOUT ANY WARRANTY; without even the implied warranty of
0011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012  *  General Public License for more details.
0013  *
0014  *  You should have received a copy of the GNU General Public License
0015  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
0016  *
0017  *
0018  * This file incorporates work covered by the following copyright and
0019  * permission notice:
0020  *
0021  * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
0022  * Copyright (c) 2004-2005 Atheros Communications, Inc.
0023  * Copyright (c) 2006 Devicescape Software, Inc.
0024  * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
0025  * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
0026  *
0027  * All rights reserved.
0028  *
0029  * Redistribution and use in source and binary forms, with or without
0030  * modification, are permitted provided that the following conditions
0031  * are met:
0032  * 1. Redistributions of source code must retain the above copyright
0033  *    notice, this list of conditions and the following disclaimer,
0034  *    without modification.
0035  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
0036  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
0037  *    redistribution must be conditioned upon including a substantially
0038  *    similar Disclaimer requirement for further binary redistribution.
0039  * 3. Neither the names of the above-listed copyright holders nor the names
0040  *    of any contributors may be used to endorse or promote products derived
0041  *    from this software without specific prior written permission.
0042  *
0043  * Alternatively, this software may be distributed under the terms of the
0044  * GNU General Public License ("GPL") version 2 as published by the Free
0045  * Software Foundation.
0046  *
0047  * NO WARRANTY
0048  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0049  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0050  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
0051  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
0052  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
0053  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0054  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0055  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
0056  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0057  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
0058  * THE POSSIBILITY OF SUCH DAMAGES.
0059  */
0060 
0061 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0062 
0063 #include <linux/export.h>
0064 #include <linux/moduleparam.h>
0065 #include <linux/vmalloc.h>
0066 
0067 #include <linux/seq_file.h>
0068 #include <linux/list.h>
0069 #include "debug.h"
0070 #include "ath5k.h"
0071 #include "reg.h"
0072 #include "base.h"
0073 
0074 static unsigned int ath5k_debug;
0075 module_param_named(debug, ath5k_debug, uint, 0);
0076 
0077 
0078 /* debugfs: registers */
0079 
0080 struct reg {
0081     const char *name;
0082     int addr;
0083 };
0084 
0085 #define REG_STRUCT_INIT(r) { #r, r }
0086 
0087 /* just a few random registers, might want to add more */
0088 static const struct reg regs[] = {
0089     REG_STRUCT_INIT(AR5K_CR),
0090     REG_STRUCT_INIT(AR5K_RXDP),
0091     REG_STRUCT_INIT(AR5K_CFG),
0092     REG_STRUCT_INIT(AR5K_IER),
0093     REG_STRUCT_INIT(AR5K_BCR),
0094     REG_STRUCT_INIT(AR5K_RTSD0),
0095     REG_STRUCT_INIT(AR5K_RTSD1),
0096     REG_STRUCT_INIT(AR5K_TXCFG),
0097     REG_STRUCT_INIT(AR5K_RXCFG),
0098     REG_STRUCT_INIT(AR5K_RXJLA),
0099     REG_STRUCT_INIT(AR5K_MIBC),
0100     REG_STRUCT_INIT(AR5K_TOPS),
0101     REG_STRUCT_INIT(AR5K_RXNOFRM),
0102     REG_STRUCT_INIT(AR5K_TXNOFRM),
0103     REG_STRUCT_INIT(AR5K_RPGTO),
0104     REG_STRUCT_INIT(AR5K_RFCNT),
0105     REG_STRUCT_INIT(AR5K_MISC),
0106     REG_STRUCT_INIT(AR5K_QCUDCU_CLKGT),
0107     REG_STRUCT_INIT(AR5K_ISR),
0108     REG_STRUCT_INIT(AR5K_PISR),
0109     REG_STRUCT_INIT(AR5K_SISR0),
0110     REG_STRUCT_INIT(AR5K_SISR1),
0111     REG_STRUCT_INIT(AR5K_SISR2),
0112     REG_STRUCT_INIT(AR5K_SISR3),
0113     REG_STRUCT_INIT(AR5K_SISR4),
0114     REG_STRUCT_INIT(AR5K_IMR),
0115     REG_STRUCT_INIT(AR5K_PIMR),
0116     REG_STRUCT_INIT(AR5K_SIMR0),
0117     REG_STRUCT_INIT(AR5K_SIMR1),
0118     REG_STRUCT_INIT(AR5K_SIMR2),
0119     REG_STRUCT_INIT(AR5K_SIMR3),
0120     REG_STRUCT_INIT(AR5K_SIMR4),
0121     REG_STRUCT_INIT(AR5K_DCM_ADDR),
0122     REG_STRUCT_INIT(AR5K_DCCFG),
0123     REG_STRUCT_INIT(AR5K_CCFG),
0124     REG_STRUCT_INIT(AR5K_CPC0),
0125     REG_STRUCT_INIT(AR5K_CPC1),
0126     REG_STRUCT_INIT(AR5K_CPC2),
0127     REG_STRUCT_INIT(AR5K_CPC3),
0128     REG_STRUCT_INIT(AR5K_CPCOVF),
0129     REG_STRUCT_INIT(AR5K_RESET_CTL),
0130     REG_STRUCT_INIT(AR5K_SLEEP_CTL),
0131     REG_STRUCT_INIT(AR5K_INTPEND),
0132     REG_STRUCT_INIT(AR5K_SFR),
0133     REG_STRUCT_INIT(AR5K_PCICFG),
0134     REG_STRUCT_INIT(AR5K_GPIOCR),
0135     REG_STRUCT_INIT(AR5K_GPIODO),
0136     REG_STRUCT_INIT(AR5K_SREV),
0137 };
0138 
0139 static void *reg_start(struct seq_file *seq, loff_t *pos)
0140 {
0141     return *pos < ARRAY_SIZE(regs) ? (void *)&regs[*pos] : NULL;
0142 }
0143 
0144 static void reg_stop(struct seq_file *seq, void *p)
0145 {
0146     /* nothing to do */
0147 }
0148 
0149 static void *reg_next(struct seq_file *seq, void *p, loff_t *pos)
0150 {
0151     ++*pos;
0152     return *pos < ARRAY_SIZE(regs) ? (void *)&regs[*pos] : NULL;
0153 }
0154 
0155 static int reg_show(struct seq_file *seq, void *p)
0156 {
0157     struct ath5k_hw *ah = seq->private;
0158     struct reg *r = p;
0159     seq_printf(seq, "%-25s0x%08x\n", r->name,
0160         ath5k_hw_reg_read(ah, r->addr));
0161     return 0;
0162 }
0163 
0164 static const struct seq_operations registers_sops = {
0165     .start = reg_start,
0166     .next  = reg_next,
0167     .stop  = reg_stop,
0168     .show  = reg_show
0169 };
0170 
0171 DEFINE_SEQ_ATTRIBUTE(registers);
0172 
0173 /* debugfs: beacons */
0174 
0175 static ssize_t read_file_beacon(struct file *file, char __user *user_buf,
0176                    size_t count, loff_t *ppos)
0177 {
0178     struct ath5k_hw *ah = file->private_data;
0179     char buf[500];
0180     unsigned int len = 0;
0181     unsigned int v;
0182     u64 tsf;
0183 
0184     v = ath5k_hw_reg_read(ah, AR5K_BEACON);
0185     len += scnprintf(buf + len, sizeof(buf) - len,
0186         "%-24s0x%08x\tintval: %d\tTIM: 0x%x\n",
0187         "AR5K_BEACON", v, v & AR5K_BEACON_PERIOD,
0188         (v & AR5K_BEACON_TIM) >> AR5K_BEACON_TIM_S);
0189 
0190     len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\n",
0191         "AR5K_LAST_TSTP", ath5k_hw_reg_read(ah, AR5K_LAST_TSTP));
0192 
0193     len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\n\n",
0194         "AR5K_BEACON_CNT", ath5k_hw_reg_read(ah, AR5K_BEACON_CNT));
0195 
0196     v = ath5k_hw_reg_read(ah, AR5K_TIMER0);
0197     len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
0198         "AR5K_TIMER0 (TBTT)", v, v);
0199 
0200     v = ath5k_hw_reg_read(ah, AR5K_TIMER1);
0201     len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
0202         "AR5K_TIMER1 (DMA)", v, v >> 3);
0203 
0204     v = ath5k_hw_reg_read(ah, AR5K_TIMER2);
0205     len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
0206         "AR5K_TIMER2 (SWBA)", v, v >> 3);
0207 
0208     v = ath5k_hw_reg_read(ah, AR5K_TIMER3);
0209     len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
0210         "AR5K_TIMER3 (ATIM)", v, v);
0211 
0212     tsf = ath5k_hw_get_tsf64(ah);
0213     len += scnprintf(buf + len, sizeof(buf) - len,
0214         "TSF\t\t0x%016llx\tTU: %08x\n",
0215         (unsigned long long)tsf, TSF_TO_TU(tsf));
0216 
0217     if (len > sizeof(buf))
0218         len = sizeof(buf);
0219 
0220     return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0221 }
0222 
0223 static ssize_t write_file_beacon(struct file *file,
0224                  const char __user *userbuf,
0225                  size_t count, loff_t *ppos)
0226 {
0227     struct ath5k_hw *ah = file->private_data;
0228     char buf[20];
0229 
0230     count = min_t(size_t, count, sizeof(buf) - 1);
0231     if (copy_from_user(buf, userbuf, count))
0232         return -EFAULT;
0233 
0234     buf[count] = '\0';
0235     if (strncmp(buf, "disable", 7) == 0) {
0236         AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
0237         pr_info("debugfs disable beacons\n");
0238     } else if (strncmp(buf, "enable", 6) == 0) {
0239         AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
0240         pr_info("debugfs enable beacons\n");
0241     }
0242     return count;
0243 }
0244 
0245 static const struct file_operations fops_beacon = {
0246     .read = read_file_beacon,
0247     .write = write_file_beacon,
0248     .open = simple_open,
0249     .owner = THIS_MODULE,
0250     .llseek = default_llseek,
0251 };
0252 
0253 
0254 /* debugfs: reset */
0255 
0256 static ssize_t write_file_reset(struct file *file,
0257                  const char __user *userbuf,
0258                  size_t count, loff_t *ppos)
0259 {
0260     struct ath5k_hw *ah = file->private_data;
0261     ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "debug file triggered reset\n");
0262     ieee80211_queue_work(ah->hw, &ah->reset_work);
0263     return count;
0264 }
0265 
0266 static const struct file_operations fops_reset = {
0267     .write = write_file_reset,
0268     .open = simple_open,
0269     .owner = THIS_MODULE,
0270     .llseek = noop_llseek,
0271 };
0272 
0273 
0274 /* debugfs: debug level */
0275 
0276 static const struct {
0277     enum ath5k_debug_level level;
0278     const char *name;
0279     const char *desc;
0280 } dbg_info[] = {
0281     { ATH5K_DEBUG_RESET,    "reset",    "reset and initialization" },
0282     { ATH5K_DEBUG_INTR, "intr",     "interrupt handling" },
0283     { ATH5K_DEBUG_MODE, "mode",     "mode init/setup" },
0284     { ATH5K_DEBUG_XMIT, "xmit",     "basic xmit operation" },
0285     { ATH5K_DEBUG_BEACON,   "beacon",   "beacon handling" },
0286     { ATH5K_DEBUG_CALIBRATE, "calib",   "periodic calibration" },
0287     { ATH5K_DEBUG_TXPOWER,  "txpower",  "transmit power setting" },
0288     { ATH5K_DEBUG_LED,  "led",      "LED management" },
0289     { ATH5K_DEBUG_DUMPBANDS, "dumpbands",   "dump bands" },
0290     { ATH5K_DEBUG_DMA,  "dma",      "dma start/stop" },
0291     { ATH5K_DEBUG_ANI,  "ani",      "adaptive noise immunity" },
0292     { ATH5K_DEBUG_DESC, "desc",     "descriptor chains" },
0293     { ATH5K_DEBUG_ANY,  "all",      "show all debug levels" },
0294 };
0295 
0296 static ssize_t read_file_debug(struct file *file, char __user *user_buf,
0297                    size_t count, loff_t *ppos)
0298 {
0299     struct ath5k_hw *ah = file->private_data;
0300     char buf[700];
0301     unsigned int len = 0;
0302     unsigned int i;
0303 
0304     len += scnprintf(buf + len, sizeof(buf) - len,
0305         "DEBUG LEVEL: 0x%08x\n\n", ah->debug.level);
0306 
0307     for (i = 0; i < ARRAY_SIZE(dbg_info) - 1; i++) {
0308         len += scnprintf(buf + len, sizeof(buf) - len,
0309             "%10s %c 0x%08x - %s\n", dbg_info[i].name,
0310             ah->debug.level & dbg_info[i].level ? '+' : ' ',
0311             dbg_info[i].level, dbg_info[i].desc);
0312     }
0313     len += scnprintf(buf + len, sizeof(buf) - len,
0314         "%10s %c 0x%08x - %s\n", dbg_info[i].name,
0315         ah->debug.level == dbg_info[i].level ? '+' : ' ',
0316         dbg_info[i].level, dbg_info[i].desc);
0317 
0318     if (len > sizeof(buf))
0319         len = sizeof(buf);
0320 
0321     return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0322 }
0323 
0324 static ssize_t write_file_debug(struct file *file,
0325                  const char __user *userbuf,
0326                  size_t count, loff_t *ppos)
0327 {
0328     struct ath5k_hw *ah = file->private_data;
0329     unsigned int i;
0330     char buf[20];
0331 
0332     count = min_t(size_t, count, sizeof(buf) - 1);
0333     if (copy_from_user(buf, userbuf, count))
0334         return -EFAULT;
0335 
0336     buf[count] = '\0';
0337     for (i = 0; i < ARRAY_SIZE(dbg_info); i++) {
0338         if (strncmp(buf, dbg_info[i].name,
0339                     strlen(dbg_info[i].name)) == 0) {
0340             ah->debug.level ^= dbg_info[i].level; /* toggle bit */
0341             break;
0342         }
0343     }
0344     return count;
0345 }
0346 
0347 static const struct file_operations fops_debug = {
0348     .read = read_file_debug,
0349     .write = write_file_debug,
0350     .open = simple_open,
0351     .owner = THIS_MODULE,
0352     .llseek = default_llseek,
0353 };
0354 
0355 
0356 /* debugfs: antenna */
0357 
0358 static ssize_t read_file_antenna(struct file *file, char __user *user_buf,
0359                    size_t count, loff_t *ppos)
0360 {
0361     struct ath5k_hw *ah = file->private_data;
0362     char buf[700];
0363     unsigned int len = 0;
0364     unsigned int i;
0365     unsigned int v;
0366 
0367     len += scnprintf(buf + len, sizeof(buf) - len, "antenna mode\t%d\n",
0368         ah->ah_ant_mode);
0369     len += scnprintf(buf + len, sizeof(buf) - len, "default antenna\t%d\n",
0370         ah->ah_def_ant);
0371     len += scnprintf(buf + len, sizeof(buf) - len, "tx antenna\t%d\n",
0372         ah->ah_tx_ant);
0373 
0374     len += scnprintf(buf + len, sizeof(buf) - len, "\nANTENNA\t\tRX\tTX\n");
0375     for (i = 1; i < ARRAY_SIZE(ah->stats.antenna_rx); i++) {
0376         len += scnprintf(buf + len, sizeof(buf) - len,
0377             "[antenna %d]\t%d\t%d\n",
0378             i, ah->stats.antenna_rx[i], ah->stats.antenna_tx[i]);
0379     }
0380     len += scnprintf(buf + len, sizeof(buf) - len, "[invalid]\t%d\t%d\n",
0381             ah->stats.antenna_rx[0], ah->stats.antenna_tx[0]);
0382 
0383     v = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
0384     len += scnprintf(buf + len, sizeof(buf) - len,
0385             "\nAR5K_DEFAULT_ANTENNA\t0x%08x\n", v);
0386 
0387     v = ath5k_hw_reg_read(ah, AR5K_STA_ID1);
0388     len += scnprintf(buf + len, sizeof(buf) - len,
0389         "AR5K_STA_ID1_DEFAULT_ANTENNA\t%d\n",
0390         (v & AR5K_STA_ID1_DEFAULT_ANTENNA) != 0);
0391     len += scnprintf(buf + len, sizeof(buf) - len,
0392         "AR5K_STA_ID1_DESC_ANTENNA\t%d\n",
0393         (v & AR5K_STA_ID1_DESC_ANTENNA) != 0);
0394     len += scnprintf(buf + len, sizeof(buf) - len,
0395         "AR5K_STA_ID1_RTS_DEF_ANTENNA\t%d\n",
0396         (v & AR5K_STA_ID1_RTS_DEF_ANTENNA) != 0);
0397     len += scnprintf(buf + len, sizeof(buf) - len,
0398         "AR5K_STA_ID1_SELFGEN_DEF_ANT\t%d\n",
0399         (v & AR5K_STA_ID1_SELFGEN_DEF_ANT) != 0);
0400 
0401     v = ath5k_hw_reg_read(ah, AR5K_PHY_AGCCTL);
0402     len += scnprintf(buf + len, sizeof(buf) - len,
0403         "\nAR5K_PHY_AGCCTL_OFDM_DIV_DIS\t%d\n",
0404         (v & AR5K_PHY_AGCCTL_OFDM_DIV_DIS) != 0);
0405 
0406     v = ath5k_hw_reg_read(ah, AR5K_PHY_RESTART);
0407     len += scnprintf(buf + len, sizeof(buf) - len,
0408         "AR5K_PHY_RESTART_DIV_GC\t\t%x\n",
0409         (v & AR5K_PHY_RESTART_DIV_GC) >> AR5K_PHY_RESTART_DIV_GC_S);
0410 
0411     v = ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ANT_DIV);
0412     len += scnprintf(buf + len, sizeof(buf) - len,
0413         "AR5K_PHY_FAST_ANT_DIV_EN\t%d\n",
0414         (v & AR5K_PHY_FAST_ANT_DIV_EN) != 0);
0415 
0416     v = ath5k_hw_reg_read(ah, AR5K_PHY_ANT_SWITCH_TABLE_0);
0417     len += scnprintf(buf + len, sizeof(buf) - len,
0418             "\nAR5K_PHY_ANT_SWITCH_TABLE_0\t0x%08x\n", v);
0419     v = ath5k_hw_reg_read(ah, AR5K_PHY_ANT_SWITCH_TABLE_1);
0420     len += scnprintf(buf + len, sizeof(buf) - len,
0421             "AR5K_PHY_ANT_SWITCH_TABLE_1\t0x%08x\n", v);
0422 
0423     if (len > sizeof(buf))
0424         len = sizeof(buf);
0425 
0426     return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0427 }
0428 
0429 static ssize_t write_file_antenna(struct file *file,
0430                  const char __user *userbuf,
0431                  size_t count, loff_t *ppos)
0432 {
0433     struct ath5k_hw *ah = file->private_data;
0434     unsigned int i;
0435     char buf[20];
0436 
0437     count = min_t(size_t, count, sizeof(buf) - 1);
0438     if (copy_from_user(buf, userbuf, count))
0439         return -EFAULT;
0440 
0441     buf[count] = '\0';
0442     if (strncmp(buf, "diversity", 9) == 0) {
0443         ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT);
0444         pr_info("debug: enable diversity\n");
0445     } else if (strncmp(buf, "fixed-a", 7) == 0) {
0446         ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_A);
0447         pr_info("debug: fixed antenna A\n");
0448     } else if (strncmp(buf, "fixed-b", 7) == 0) {
0449         ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_B);
0450         pr_info("debug: fixed antenna B\n");
0451     } else if (strncmp(buf, "clear", 5) == 0) {
0452         for (i = 0; i < ARRAY_SIZE(ah->stats.antenna_rx); i++) {
0453             ah->stats.antenna_rx[i] = 0;
0454             ah->stats.antenna_tx[i] = 0;
0455         }
0456         pr_info("debug: cleared antenna stats\n");
0457     }
0458     return count;
0459 }
0460 
0461 static const struct file_operations fops_antenna = {
0462     .read = read_file_antenna,
0463     .write = write_file_antenna,
0464     .open = simple_open,
0465     .owner = THIS_MODULE,
0466     .llseek = default_llseek,
0467 };
0468 
0469 /* debugfs: misc */
0470 
0471 static ssize_t read_file_misc(struct file *file, char __user *user_buf,
0472                    size_t count, loff_t *ppos)
0473 {
0474     struct ath5k_hw *ah = file->private_data;
0475     char buf[700];
0476     unsigned int len = 0;
0477     u32 filt = ath5k_hw_get_rx_filter(ah);
0478 
0479     len += scnprintf(buf + len, sizeof(buf) - len, "bssid-mask: %pM\n",
0480             ah->bssidmask);
0481     len += scnprintf(buf + len, sizeof(buf) - len, "filter-flags: 0x%x ",
0482             filt);
0483     if (filt & AR5K_RX_FILTER_UCAST)
0484         len += scnprintf(buf + len, sizeof(buf) - len, " UCAST");
0485     if (filt & AR5K_RX_FILTER_MCAST)
0486         len += scnprintf(buf + len, sizeof(buf) - len, " MCAST");
0487     if (filt & AR5K_RX_FILTER_BCAST)
0488         len += scnprintf(buf + len, sizeof(buf) - len, " BCAST");
0489     if (filt & AR5K_RX_FILTER_CONTROL)
0490         len += scnprintf(buf + len, sizeof(buf) - len, " CONTROL");
0491     if (filt & AR5K_RX_FILTER_BEACON)
0492         len += scnprintf(buf + len, sizeof(buf) - len, " BEACON");
0493     if (filt & AR5K_RX_FILTER_PROM)
0494         len += scnprintf(buf + len, sizeof(buf) - len, " PROM");
0495     if (filt & AR5K_RX_FILTER_XRPOLL)
0496         len += scnprintf(buf + len, sizeof(buf) - len, " XRPOLL");
0497     if (filt & AR5K_RX_FILTER_PROBEREQ)
0498         len += scnprintf(buf + len, sizeof(buf) - len, " PROBEREQ");
0499     if (filt & AR5K_RX_FILTER_PHYERR_5212)
0500         len += scnprintf(buf + len, sizeof(buf) - len, " PHYERR-5212");
0501     if (filt & AR5K_RX_FILTER_RADARERR_5212)
0502         len += scnprintf(buf + len, sizeof(buf) - len, " RADARERR-5212");
0503     if (filt & AR5K_RX_FILTER_PHYERR_5211)
0504         snprintf(buf + len, sizeof(buf) - len, " PHYERR-5211");
0505     if (filt & AR5K_RX_FILTER_RADARERR_5211)
0506         len += scnprintf(buf + len, sizeof(buf) - len, " RADARERR-5211");
0507 
0508     len += scnprintf(buf + len, sizeof(buf) - len, "\nopmode: %s (%d)\n",
0509             ath_opmode_to_string(ah->opmode), ah->opmode);
0510 
0511     if (len > sizeof(buf))
0512         len = sizeof(buf);
0513 
0514     return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0515 }
0516 
0517 static const struct file_operations fops_misc = {
0518     .read = read_file_misc,
0519     .open = simple_open,
0520     .owner = THIS_MODULE,
0521 };
0522 
0523 
0524 /* debugfs: frameerrors */
0525 
0526 static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf,
0527                    size_t count, loff_t *ppos)
0528 {
0529     struct ath5k_hw *ah = file->private_data;
0530     struct ath5k_statistics *st = &ah->stats;
0531     char buf[700];
0532     unsigned int len = 0;
0533     int i;
0534 
0535     len += scnprintf(buf + len, sizeof(buf) - len,
0536             "RX\n---------------------\n");
0537     len += scnprintf(buf + len, sizeof(buf) - len, "CRC\t%u\t(%u%%)\n",
0538             st->rxerr_crc,
0539             st->rx_all_count > 0 ?
0540                 st->rxerr_crc * 100 / st->rx_all_count : 0);
0541     len += scnprintf(buf + len, sizeof(buf) - len, "PHY\t%u\t(%u%%)\n",
0542             st->rxerr_phy,
0543             st->rx_all_count > 0 ?
0544                 st->rxerr_phy * 100 / st->rx_all_count : 0);
0545     for (i = 0; i < 32; i++) {
0546         if (st->rxerr_phy_code[i])
0547             len += scnprintf(buf + len, sizeof(buf) - len,
0548                 " phy_err[%u]\t%u\n",
0549                 i, st->rxerr_phy_code[i]);
0550     }
0551 
0552     len += scnprintf(buf + len, sizeof(buf) - len, "FIFO\t%u\t(%u%%)\n",
0553             st->rxerr_fifo,
0554             st->rx_all_count > 0 ?
0555                 st->rxerr_fifo * 100 / st->rx_all_count : 0);
0556     len += scnprintf(buf + len, sizeof(buf) - len, "decrypt\t%u\t(%u%%)\n",
0557             st->rxerr_decrypt,
0558             st->rx_all_count > 0 ?
0559                 st->rxerr_decrypt * 100 / st->rx_all_count : 0);
0560     len += scnprintf(buf + len, sizeof(buf) - len, "MIC\t%u\t(%u%%)\n",
0561             st->rxerr_mic,
0562             st->rx_all_count > 0 ?
0563                 st->rxerr_mic * 100 / st->rx_all_count : 0);
0564     len += scnprintf(buf + len, sizeof(buf) - len, "process\t%u\t(%u%%)\n",
0565             st->rxerr_proc,
0566             st->rx_all_count > 0 ?
0567                 st->rxerr_proc * 100 / st->rx_all_count : 0);
0568     len += scnprintf(buf + len, sizeof(buf) - len, "jumbo\t%u\t(%u%%)\n",
0569             st->rxerr_jumbo,
0570             st->rx_all_count > 0 ?
0571                 st->rxerr_jumbo * 100 / st->rx_all_count : 0);
0572     len += scnprintf(buf + len, sizeof(buf) - len, "[RX all\t%u]\n",
0573             st->rx_all_count);
0574     len += scnprintf(buf + len, sizeof(buf) - len, "RX-all-bytes\t%u\n",
0575             st->rx_bytes_count);
0576 
0577     len += scnprintf(buf + len, sizeof(buf) - len,
0578             "\nTX\n---------------------\n");
0579     len += scnprintf(buf + len, sizeof(buf) - len, "retry\t%u\t(%u%%)\n",
0580             st->txerr_retry,
0581             st->tx_all_count > 0 ?
0582                 st->txerr_retry * 100 / st->tx_all_count : 0);
0583     len += scnprintf(buf + len, sizeof(buf) - len, "FIFO\t%u\t(%u%%)\n",
0584             st->txerr_fifo,
0585             st->tx_all_count > 0 ?
0586                 st->txerr_fifo * 100 / st->tx_all_count : 0);
0587     len += scnprintf(buf + len, sizeof(buf) - len, "filter\t%u\t(%u%%)\n",
0588             st->txerr_filt,
0589             st->tx_all_count > 0 ?
0590                 st->txerr_filt * 100 / st->tx_all_count : 0);
0591     len += scnprintf(buf + len, sizeof(buf) - len, "[TX all\t%u]\n",
0592             st->tx_all_count);
0593     len += scnprintf(buf + len, sizeof(buf) - len, "TX-all-bytes\t%u\n",
0594             st->tx_bytes_count);
0595 
0596     if (len > sizeof(buf))
0597         len = sizeof(buf);
0598 
0599     return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0600 }
0601 
0602 static ssize_t write_file_frameerrors(struct file *file,
0603                  const char __user *userbuf,
0604                  size_t count, loff_t *ppos)
0605 {
0606     struct ath5k_hw *ah = file->private_data;
0607     struct ath5k_statistics *st = &ah->stats;
0608     char buf[20];
0609 
0610     count = min_t(size_t, count, sizeof(buf) - 1);
0611     if (copy_from_user(buf, userbuf, count))
0612         return -EFAULT;
0613 
0614     buf[count] = '\0';
0615     if (strncmp(buf, "clear", 5) == 0) {
0616         st->rxerr_crc = 0;
0617         st->rxerr_phy = 0;
0618         st->rxerr_fifo = 0;
0619         st->rxerr_decrypt = 0;
0620         st->rxerr_mic = 0;
0621         st->rxerr_proc = 0;
0622         st->rxerr_jumbo = 0;
0623         st->rx_all_count = 0;
0624         st->txerr_retry = 0;
0625         st->txerr_fifo = 0;
0626         st->txerr_filt = 0;
0627         st->tx_all_count = 0;
0628         pr_info("debug: cleared frameerrors stats\n");
0629     }
0630     return count;
0631 }
0632 
0633 static const struct file_operations fops_frameerrors = {
0634     .read = read_file_frameerrors,
0635     .write = write_file_frameerrors,
0636     .open = simple_open,
0637     .owner = THIS_MODULE,
0638     .llseek = default_llseek,
0639 };
0640 
0641 
0642 /* debugfs: ani */
0643 
0644 static ssize_t read_file_ani(struct file *file, char __user *user_buf,
0645                    size_t count, loff_t *ppos)
0646 {
0647     struct ath5k_hw *ah = file->private_data;
0648     struct ath5k_statistics *st = &ah->stats;
0649     struct ath5k_ani_state *as = &ah->ani_state;
0650 
0651     char buf[700];
0652     unsigned int len = 0;
0653 
0654     len += scnprintf(buf + len, sizeof(buf) - len,
0655             "HW has PHY error counters:\t%s\n",
0656             ah->ah_capabilities.cap_has_phyerr_counters ?
0657             "yes" : "no");
0658     len += scnprintf(buf + len, sizeof(buf) - len,
0659             "HW max spur immunity level:\t%d\n",
0660             as->max_spur_level);
0661     len += scnprintf(buf + len, sizeof(buf) - len,
0662         "\nANI state\n--------------------------------------------\n");
0663     len += scnprintf(buf + len, sizeof(buf) - len, "operating mode:\t\t\t");
0664     switch (as->ani_mode) {
0665     case ATH5K_ANI_MODE_OFF:
0666         len += scnprintf(buf + len, sizeof(buf) - len, "OFF\n");
0667         break;
0668     case ATH5K_ANI_MODE_MANUAL_LOW:
0669         len += scnprintf(buf + len, sizeof(buf) - len,
0670             "MANUAL LOW\n");
0671         break;
0672     case ATH5K_ANI_MODE_MANUAL_HIGH:
0673         len += scnprintf(buf + len, sizeof(buf) - len,
0674             "MANUAL HIGH\n");
0675         break;
0676     case ATH5K_ANI_MODE_AUTO:
0677         len += scnprintf(buf + len, sizeof(buf) - len, "AUTO\n");
0678         break;
0679     default:
0680         len += scnprintf(buf + len, sizeof(buf) - len,
0681             "??? (not good)\n");
0682         break;
0683     }
0684     len += scnprintf(buf + len, sizeof(buf) - len,
0685             "noise immunity level:\t\t%d\n",
0686             as->noise_imm_level);
0687     len += scnprintf(buf + len, sizeof(buf) - len,
0688             "spur immunity level:\t\t%d\n",
0689             as->spur_level);
0690     len += scnprintf(buf + len, sizeof(buf) - len,
0691             "firstep level:\t\t\t%d\n",
0692             as->firstep_level);
0693     len += scnprintf(buf + len, sizeof(buf) - len,
0694             "OFDM weak signal detection:\t%s\n",
0695             as->ofdm_weak_sig ? "on" : "off");
0696     len += scnprintf(buf + len, sizeof(buf) - len,
0697             "CCK weak signal detection:\t%s\n",
0698             as->cck_weak_sig ? "on" : "off");
0699 
0700     len += scnprintf(buf + len, sizeof(buf) - len,
0701             "\nMIB INTERRUPTS:\t\t%u\n",
0702             st->mib_intr);
0703     len += scnprintf(buf + len, sizeof(buf) - len,
0704             "beacon RSSI average:\t%d\n",
0705             (int)ewma_beacon_rssi_read(&ah->ah_beacon_rssi_avg));
0706 
0707 #define CC_PRINT(_struct, _field) \
0708     _struct._field, \
0709     _struct.cycles > 0 ? \
0710     _struct._field * 100 / _struct.cycles : 0
0711 
0712     len += scnprintf(buf + len, sizeof(buf) - len,
0713             "profcnt tx\t\t%u\t(%d%%)\n",
0714             CC_PRINT(as->last_cc, tx_frame));
0715     len += scnprintf(buf + len, sizeof(buf) - len,
0716             "profcnt rx\t\t%u\t(%d%%)\n",
0717             CC_PRINT(as->last_cc, rx_frame));
0718     len += scnprintf(buf + len, sizeof(buf) - len,
0719             "profcnt busy\t\t%u\t(%d%%)\n",
0720             CC_PRINT(as->last_cc, rx_busy));
0721 #undef CC_PRINT
0722     len += scnprintf(buf + len, sizeof(buf) - len, "profcnt cycles\t\t%u\n",
0723             as->last_cc.cycles);
0724     len += scnprintf(buf + len, sizeof(buf) - len,
0725             "listen time\t\t%d\tlast: %d\n",
0726             as->listen_time, as->last_listen);
0727     len += scnprintf(buf + len, sizeof(buf) - len,
0728             "OFDM errors\t\t%u\tlast: %u\tsum: %u\n",
0729             as->ofdm_errors, as->last_ofdm_errors,
0730             as->sum_ofdm_errors);
0731     len += scnprintf(buf + len, sizeof(buf) - len,
0732             "CCK errors\t\t%u\tlast: %u\tsum: %u\n",
0733             as->cck_errors, as->last_cck_errors,
0734             as->sum_cck_errors);
0735     len += scnprintf(buf + len, sizeof(buf) - len,
0736             "AR5K_PHYERR_CNT1\t%x\t(=%d)\n",
0737             ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1),
0738             ATH5K_ANI_OFDM_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX -
0739             ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1)));
0740     len += scnprintf(buf + len, sizeof(buf) - len,
0741             "AR5K_PHYERR_CNT2\t%x\t(=%d)\n",
0742             ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2),
0743             ATH5K_ANI_CCK_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX -
0744             ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2)));
0745 
0746     if (len > sizeof(buf))
0747         len = sizeof(buf);
0748 
0749     return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0750 }
0751 
0752 static ssize_t write_file_ani(struct file *file,
0753                  const char __user *userbuf,
0754                  size_t count, loff_t *ppos)
0755 {
0756     struct ath5k_hw *ah = file->private_data;
0757     char buf[20];
0758 
0759     count = min_t(size_t, count, sizeof(buf) - 1);
0760     if (copy_from_user(buf, userbuf, count))
0761         return -EFAULT;
0762 
0763     buf[count] = '\0';
0764     if (strncmp(buf, "sens-low", 8) == 0) {
0765         ath5k_ani_init(ah, ATH5K_ANI_MODE_MANUAL_HIGH);
0766     } else if (strncmp(buf, "sens-high", 9) == 0) {
0767         ath5k_ani_init(ah, ATH5K_ANI_MODE_MANUAL_LOW);
0768     } else if (strncmp(buf, "ani-off", 7) == 0) {
0769         ath5k_ani_init(ah, ATH5K_ANI_MODE_OFF);
0770     } else if (strncmp(buf, "ani-on", 6) == 0) {
0771         ath5k_ani_init(ah, ATH5K_ANI_MODE_AUTO);
0772     } else if (strncmp(buf, "noise-low", 9) == 0) {
0773         ath5k_ani_set_noise_immunity_level(ah, 0);
0774     } else if (strncmp(buf, "noise-high", 10) == 0) {
0775         ath5k_ani_set_noise_immunity_level(ah,
0776                            ATH5K_ANI_MAX_NOISE_IMM_LVL);
0777     } else if (strncmp(buf, "spur-low", 8) == 0) {
0778         ath5k_ani_set_spur_immunity_level(ah, 0);
0779     } else if (strncmp(buf, "spur-high", 9) == 0) {
0780         ath5k_ani_set_spur_immunity_level(ah,
0781                           ah->ani_state.max_spur_level);
0782     } else if (strncmp(buf, "fir-low", 7) == 0) {
0783         ath5k_ani_set_firstep_level(ah, 0);
0784     } else if (strncmp(buf, "fir-high", 8) == 0) {
0785         ath5k_ani_set_firstep_level(ah, ATH5K_ANI_MAX_FIRSTEP_LVL);
0786     } else if (strncmp(buf, "ofdm-off", 8) == 0) {
0787         ath5k_ani_set_ofdm_weak_signal_detection(ah, false);
0788     } else if (strncmp(buf, "ofdm-on", 7) == 0) {
0789         ath5k_ani_set_ofdm_weak_signal_detection(ah, true);
0790     } else if (strncmp(buf, "cck-off", 7) == 0) {
0791         ath5k_ani_set_cck_weak_signal_detection(ah, false);
0792     } else if (strncmp(buf, "cck-on", 6) == 0) {
0793         ath5k_ani_set_cck_weak_signal_detection(ah, true);
0794     }
0795     return count;
0796 }
0797 
0798 static const struct file_operations fops_ani = {
0799     .read = read_file_ani,
0800     .write = write_file_ani,
0801     .open = simple_open,
0802     .owner = THIS_MODULE,
0803     .llseek = default_llseek,
0804 };
0805 
0806 
0807 /* debugfs: queues etc */
0808 
0809 static ssize_t read_file_queue(struct file *file, char __user *user_buf,
0810                    size_t count, loff_t *ppos)
0811 {
0812     struct ath5k_hw *ah = file->private_data;
0813     char buf[700];
0814     unsigned int len = 0;
0815 
0816     struct ath5k_txq *txq;
0817     struct ath5k_buf *bf, *bf0;
0818     int i, n;
0819 
0820     len += scnprintf(buf + len, sizeof(buf) - len,
0821             "available txbuffers: %d\n", ah->txbuf_len);
0822 
0823     for (i = 0; i < ARRAY_SIZE(ah->txqs); i++) {
0824         txq = &ah->txqs[i];
0825 
0826         len += scnprintf(buf + len, sizeof(buf) - len,
0827             "%02d: %ssetup\n", i, txq->setup ? "" : "not ");
0828 
0829         if (!txq->setup)
0830             continue;
0831 
0832         n = 0;
0833         spin_lock_bh(&txq->lock);
0834         list_for_each_entry_safe(bf, bf0, &txq->q, list)
0835             n++;
0836         spin_unlock_bh(&txq->lock);
0837 
0838         len += scnprintf(buf + len, sizeof(buf) - len,
0839                 "  len: %d bufs: %d\n", txq->txq_len, n);
0840         len += scnprintf(buf + len, sizeof(buf) - len,
0841                 "  stuck: %d\n", txq->txq_stuck);
0842     }
0843 
0844     if (len > sizeof(buf))
0845         len = sizeof(buf);
0846 
0847     return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0848 }
0849 
0850 static ssize_t write_file_queue(struct file *file,
0851                  const char __user *userbuf,
0852                  size_t count, loff_t *ppos)
0853 {
0854     struct ath5k_hw *ah = file->private_data;
0855     char buf[20];
0856 
0857     count = min_t(size_t, count, sizeof(buf) - 1);
0858     if (copy_from_user(buf, userbuf, count))
0859         return -EFAULT;
0860 
0861     buf[count] = '\0';
0862     if (strncmp(buf, "start", 5) == 0)
0863         ieee80211_wake_queues(ah->hw);
0864     else if (strncmp(buf, "stop", 4) == 0)
0865         ieee80211_stop_queues(ah->hw);
0866 
0867     return count;
0868 }
0869 
0870 
0871 static const struct file_operations fops_queue = {
0872     .read = read_file_queue,
0873     .write = write_file_queue,
0874     .open = simple_open,
0875     .owner = THIS_MODULE,
0876     .llseek = default_llseek,
0877 };
0878 
0879 /* debugfs: eeprom */
0880 
0881 struct eeprom_private {
0882     u16 *buf;
0883     int len;
0884 };
0885 
0886 static int open_file_eeprom(struct inode *inode, struct file *file)
0887 {
0888     struct eeprom_private *ep;
0889     struct ath5k_hw *ah = inode->i_private;
0890     bool res;
0891     int i, ret;
0892     u32 eesize; /* NB: in 16-bit words */
0893     u16 val, *buf;
0894 
0895     /* Get eeprom size */
0896 
0897     res = ath5k_hw_nvram_read(ah, AR5K_EEPROM_SIZE_UPPER, &val);
0898     if (!res)
0899         return -EACCES;
0900 
0901     if (val == 0) {
0902         eesize = AR5K_EEPROM_INFO_MAX + AR5K_EEPROM_INFO_BASE;
0903     } else {
0904         eesize = (val & AR5K_EEPROM_SIZE_UPPER_MASK) <<
0905             AR5K_EEPROM_SIZE_ENDLOC_SHIFT;
0906         ath5k_hw_nvram_read(ah, AR5K_EEPROM_SIZE_LOWER, &val);
0907         eesize = eesize | val;
0908     }
0909 
0910     if (eesize > 4096)
0911         return -EINVAL;
0912 
0913     /* Create buffer and read in eeprom */
0914 
0915     buf = vmalloc(array_size(eesize, 2));
0916     if (!buf) {
0917         ret = -ENOMEM;
0918         goto err;
0919     }
0920 
0921     for (i = 0; i < eesize; ++i) {
0922         if (!ath5k_hw_nvram_read(ah, i, &val)) {
0923             ret = -EIO;
0924             goto freebuf;
0925         }
0926         buf[i] = val;
0927     }
0928 
0929     /* Create private struct and assign to file */
0930 
0931     ep = kmalloc(sizeof(*ep), GFP_KERNEL);
0932     if (!ep) {
0933         ret = -ENOMEM;
0934         goto freebuf;
0935     }
0936 
0937     ep->buf = buf;
0938     ep->len = eesize * 2;
0939 
0940     file->private_data = (void *)ep;
0941 
0942     return 0;
0943 
0944 freebuf:
0945     vfree(buf);
0946 err:
0947     return ret;
0948 
0949 }
0950 
0951 static ssize_t read_file_eeprom(struct file *file, char __user *user_buf,
0952                    size_t count, loff_t *ppos)
0953 {
0954     struct eeprom_private *ep = file->private_data;
0955 
0956     return simple_read_from_buffer(user_buf, count, ppos, ep->buf, ep->len);
0957 }
0958 
0959 static int release_file_eeprom(struct inode *inode, struct file *file)
0960 {
0961     struct eeprom_private *ep = file->private_data;
0962 
0963     vfree(ep->buf);
0964     kfree(ep);
0965 
0966     return 0;
0967 }
0968 
0969 static const struct file_operations fops_eeprom = {
0970     .open = open_file_eeprom,
0971     .read = read_file_eeprom,
0972     .release = release_file_eeprom,
0973     .owner = THIS_MODULE,
0974 };
0975 
0976 
0977 void
0978 ath5k_debug_init_device(struct ath5k_hw *ah)
0979 {
0980     struct dentry *phydir;
0981 
0982     ah->debug.level = ath5k_debug;
0983 
0984     phydir = debugfs_create_dir("ath5k", ah->hw->wiphy->debugfsdir);
0985     if (!phydir)
0986         return;
0987 
0988     debugfs_create_file("debug", 0600, phydir, ah, &fops_debug);
0989     debugfs_create_file("registers", 0400, phydir, ah, &registers_fops);
0990     debugfs_create_file("beacon", 0600, phydir, ah, &fops_beacon);
0991     debugfs_create_file("reset", 0200, phydir, ah, &fops_reset);
0992     debugfs_create_file("antenna", 0600, phydir, ah, &fops_antenna);
0993     debugfs_create_file("misc", 0400, phydir, ah, &fops_misc);
0994     debugfs_create_file("eeprom", 0400, phydir, ah, &fops_eeprom);
0995     debugfs_create_file("frameerrors", 0600, phydir, ah, &fops_frameerrors);
0996     debugfs_create_file("ani", 0600, phydir, ah, &fops_ani);
0997     debugfs_create_file("queue", 0600, phydir, ah, &fops_queue);
0998     debugfs_create_bool("32khz_clock", 0600, phydir,
0999                 &ah->ah_use_32khz_clock);
1000 }
1001 
1002 /* functions used in other places */
1003 
1004 void
1005 ath5k_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 
1047 static inline void
1048 ath5k_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 
1062 void
1063 ath5k_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 
1086 void
1087 ath5k_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 }