]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/net/wireless/ath/ath5k/debug.c
9be885707e2039cc75b6a44c5198e61a40086bc0
[karo-tx-linux.git] / drivers / net / wireless / ath / ath5k / debug.c
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
66 #include <linux/seq_file.h>
67 #include <linux/list.h>
68 #include "debug.h"
69 #include "ath5k.h"
70 #include "reg.h"
71 #include "base.h"
72
73 static unsigned int ath5k_debug;
74 module_param_named(debug, ath5k_debug, uint, 0);
75
76
77 static int ath5k_debugfs_open(struct inode *inode, struct file *file)
78 {
79         file->private_data = inode->i_private;
80         return 0;
81 }
82
83
84 /* debugfs: registers */
85
86 struct reg {
87         const char *name;
88         int addr;
89 };
90
91 #define REG_STRUCT_INIT(r) { #r, r }
92
93 /* just a few random registers, might want to add more */
94 static const struct reg regs[] = {
95         REG_STRUCT_INIT(AR5K_CR),
96         REG_STRUCT_INIT(AR5K_RXDP),
97         REG_STRUCT_INIT(AR5K_CFG),
98         REG_STRUCT_INIT(AR5K_IER),
99         REG_STRUCT_INIT(AR5K_BCR),
100         REG_STRUCT_INIT(AR5K_RTSD0),
101         REG_STRUCT_INIT(AR5K_RTSD1),
102         REG_STRUCT_INIT(AR5K_TXCFG),
103         REG_STRUCT_INIT(AR5K_RXCFG),
104         REG_STRUCT_INIT(AR5K_RXJLA),
105         REG_STRUCT_INIT(AR5K_MIBC),
106         REG_STRUCT_INIT(AR5K_TOPS),
107         REG_STRUCT_INIT(AR5K_RXNOFRM),
108         REG_STRUCT_INIT(AR5K_TXNOFRM),
109         REG_STRUCT_INIT(AR5K_RPGTO),
110         REG_STRUCT_INIT(AR5K_RFCNT),
111         REG_STRUCT_INIT(AR5K_MISC),
112         REG_STRUCT_INIT(AR5K_QCUDCU_CLKGT),
113         REG_STRUCT_INIT(AR5K_ISR),
114         REG_STRUCT_INIT(AR5K_PISR),
115         REG_STRUCT_INIT(AR5K_SISR0),
116         REG_STRUCT_INIT(AR5K_SISR1),
117         REG_STRUCT_INIT(AR5K_SISR2),
118         REG_STRUCT_INIT(AR5K_SISR3),
119         REG_STRUCT_INIT(AR5K_SISR4),
120         REG_STRUCT_INIT(AR5K_IMR),
121         REG_STRUCT_INIT(AR5K_PIMR),
122         REG_STRUCT_INIT(AR5K_SIMR0),
123         REG_STRUCT_INIT(AR5K_SIMR1),
124         REG_STRUCT_INIT(AR5K_SIMR2),
125         REG_STRUCT_INIT(AR5K_SIMR3),
126         REG_STRUCT_INIT(AR5K_SIMR4),
127         REG_STRUCT_INIT(AR5K_DCM_ADDR),
128         REG_STRUCT_INIT(AR5K_DCCFG),
129         REG_STRUCT_INIT(AR5K_CCFG),
130         REG_STRUCT_INIT(AR5K_CPC0),
131         REG_STRUCT_INIT(AR5K_CPC1),
132         REG_STRUCT_INIT(AR5K_CPC2),
133         REG_STRUCT_INIT(AR5K_CPC3),
134         REG_STRUCT_INIT(AR5K_CPCOVF),
135         REG_STRUCT_INIT(AR5K_RESET_CTL),
136         REG_STRUCT_INIT(AR5K_SLEEP_CTL),
137         REG_STRUCT_INIT(AR5K_INTPEND),
138         REG_STRUCT_INIT(AR5K_SFR),
139         REG_STRUCT_INIT(AR5K_PCICFG),
140         REG_STRUCT_INIT(AR5K_GPIOCR),
141         REG_STRUCT_INIT(AR5K_GPIODO),
142         REG_STRUCT_INIT(AR5K_SREV),
143 };
144
145 static void *reg_start(struct seq_file *seq, loff_t *pos)
146 {
147         return *pos < ARRAY_SIZE(regs) ? (void *)&regs[*pos] : NULL;
148 }
149
150 static void reg_stop(struct seq_file *seq, void *p)
151 {
152         /* nothing to do */
153 }
154
155 static void *reg_next(struct seq_file *seq, void *p, loff_t *pos)
156 {
157         ++*pos;
158         return *pos < ARRAY_SIZE(regs) ? (void *)&regs[*pos] : NULL;
159 }
160
161 static int reg_show(struct seq_file *seq, void *p)
162 {
163         struct ath5k_hw *ah = seq->private;
164         struct reg *r = p;
165         seq_printf(seq, "%-25s0x%08x\n", r->name,
166                 ath5k_hw_reg_read(ah, r->addr));
167         return 0;
168 }
169
170 static const struct seq_operations register_seq_ops = {
171         .start = reg_start,
172         .next  = reg_next,
173         .stop  = reg_stop,
174         .show  = reg_show
175 };
176
177 static int open_file_registers(struct inode *inode, struct file *file)
178 {
179         struct seq_file *s;
180         int res;
181         res = seq_open(file, &register_seq_ops);
182         if (res == 0) {
183                 s = file->private_data;
184                 s->private = inode->i_private;
185         }
186         return res;
187 }
188
189 static const struct file_operations fops_registers = {
190         .open = open_file_registers,
191         .read    = seq_read,
192         .llseek  = seq_lseek,
193         .release = seq_release,
194         .owner = THIS_MODULE,
195 };
196
197
198 /* debugfs: beacons */
199
200 static ssize_t read_file_beacon(struct file *file, char __user *user_buf,
201                                    size_t count, loff_t *ppos)
202 {
203         struct ath5k_hw *ah = file->private_data;
204         char buf[500];
205         unsigned int len = 0;
206         unsigned int v;
207         u64 tsf;
208
209         v = ath5k_hw_reg_read(ah, AR5K_BEACON);
210         len += snprintf(buf + len, sizeof(buf) - len,
211                 "%-24s0x%08x\tintval: %d\tTIM: 0x%x\n",
212                 "AR5K_BEACON", v, v & AR5K_BEACON_PERIOD,
213                 (v & AR5K_BEACON_TIM) >> AR5K_BEACON_TIM_S);
214
215         len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\n",
216                 "AR5K_LAST_TSTP", ath5k_hw_reg_read(ah, AR5K_LAST_TSTP));
217
218         len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\n\n",
219                 "AR5K_BEACON_CNT", ath5k_hw_reg_read(ah, AR5K_BEACON_CNT));
220
221         v = ath5k_hw_reg_read(ah, AR5K_TIMER0);
222         len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
223                 "AR5K_TIMER0 (TBTT)", v, v);
224
225         v = ath5k_hw_reg_read(ah, AR5K_TIMER1);
226         len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
227                 "AR5K_TIMER1 (DMA)", v, v >> 3);
228
229         v = ath5k_hw_reg_read(ah, AR5K_TIMER2);
230         len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
231                 "AR5K_TIMER2 (SWBA)", v, v >> 3);
232
233         v = ath5k_hw_reg_read(ah, AR5K_TIMER3);
234         len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
235                 "AR5K_TIMER3 (ATIM)", v, v);
236
237         tsf = ath5k_hw_get_tsf64(ah);
238         len += snprintf(buf + len, sizeof(buf) - len,
239                 "TSF\t\t0x%016llx\tTU: %08x\n",
240                 (unsigned long long)tsf, TSF_TO_TU(tsf));
241
242         if (len > sizeof(buf))
243                 len = sizeof(buf);
244
245         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
246 }
247
248 static ssize_t write_file_beacon(struct file *file,
249                                  const char __user *userbuf,
250                                  size_t count, loff_t *ppos)
251 {
252         struct ath5k_hw *ah = file->private_data;
253         char buf[20];
254
255         if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
256                 return -EFAULT;
257
258         if (strncmp(buf, "disable", 7) == 0) {
259                 AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
260                 pr_info("debugfs disable beacons\n");
261         } else if (strncmp(buf, "enable", 6) == 0) {
262                 AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
263                 pr_info("debugfs enable beacons\n");
264         }
265         return count;
266 }
267
268 static const struct file_operations fops_beacon = {
269         .read = read_file_beacon,
270         .write = write_file_beacon,
271         .open = ath5k_debugfs_open,
272         .owner = THIS_MODULE,
273         .llseek = default_llseek,
274 };
275
276
277 /* debugfs: reset */
278
279 static ssize_t write_file_reset(struct file *file,
280                                  const char __user *userbuf,
281                                  size_t count, loff_t *ppos)
282 {
283         struct ath5k_hw *ah = file->private_data;
284         ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "debug file triggered reset\n");
285         ieee80211_queue_work(ah->hw, &ah->reset_work);
286         return count;
287 }
288
289 static const struct file_operations fops_reset = {
290         .write = write_file_reset,
291         .open = ath5k_debugfs_open,
292         .owner = THIS_MODULE,
293         .llseek = noop_llseek,
294 };
295
296
297 /* debugfs: debug level */
298
299 static const struct {
300         enum ath5k_debug_level level;
301         const char *name;
302         const char *desc;
303 } dbg_info[] = {
304         { ATH5K_DEBUG_RESET,    "reset",        "reset and initialization" },
305         { ATH5K_DEBUG_INTR,     "intr",         "interrupt handling" },
306         { ATH5K_DEBUG_MODE,     "mode",         "mode init/setup" },
307         { ATH5K_DEBUG_XMIT,     "xmit",         "basic xmit operation" },
308         { ATH5K_DEBUG_BEACON,   "beacon",       "beacon handling" },
309         { ATH5K_DEBUG_CALIBRATE, "calib",       "periodic calibration" },
310         { ATH5K_DEBUG_TXPOWER,  "txpower",      "transmit power setting" },
311         { ATH5K_DEBUG_LED,      "led",          "LED management" },
312         { ATH5K_DEBUG_DUMPBANDS, "dumpbands",   "dump bands" },
313         { ATH5K_DEBUG_DMA,      "dma",          "dma start/stop" },
314         { ATH5K_DEBUG_ANI,      "ani",          "adaptive noise immunity" },
315         { ATH5K_DEBUG_DESC,     "desc",         "descriptor chains" },
316         { ATH5K_DEBUG_ANY,      "all",          "show all debug levels" },
317 };
318
319 static ssize_t read_file_debug(struct file *file, char __user *user_buf,
320                                    size_t count, loff_t *ppos)
321 {
322         struct ath5k_hw *ah = file->private_data;
323         char buf[700];
324         unsigned int len = 0;
325         unsigned int i;
326
327         len += snprintf(buf + len, sizeof(buf) - len,
328                 "DEBUG LEVEL: 0x%08x\n\n", ah->debug.level);
329
330         for (i = 0; i < ARRAY_SIZE(dbg_info) - 1; i++) {
331                 len += snprintf(buf + len, sizeof(buf) - len,
332                         "%10s %c 0x%08x - %s\n", dbg_info[i].name,
333                         ah->debug.level & dbg_info[i].level ? '+' : ' ',
334                         dbg_info[i].level, dbg_info[i].desc);
335         }
336         len += snprintf(buf + len, sizeof(buf) - len,
337                 "%10s %c 0x%08x - %s\n", dbg_info[i].name,
338                 ah->debug.level == dbg_info[i].level ? '+' : ' ',
339                 dbg_info[i].level, dbg_info[i].desc);
340
341         if (len > sizeof(buf))
342                 len = sizeof(buf);
343
344         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
345 }
346
347 static ssize_t write_file_debug(struct file *file,
348                                  const char __user *userbuf,
349                                  size_t count, loff_t *ppos)
350 {
351         struct ath5k_hw *ah = file->private_data;
352         unsigned int i;
353         char buf[20];
354
355         if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
356                 return -EFAULT;
357
358         for (i = 0; i < ARRAY_SIZE(dbg_info); i++) {
359                 if (strncmp(buf, dbg_info[i].name,
360                                         strlen(dbg_info[i].name)) == 0) {
361                         ah->debug.level ^= dbg_info[i].level; /* toggle bit */
362                         break;
363                 }
364         }
365         return count;
366 }
367
368 static const struct file_operations fops_debug = {
369         .read = read_file_debug,
370         .write = write_file_debug,
371         .open = ath5k_debugfs_open,
372         .owner = THIS_MODULE,
373         .llseek = default_llseek,
374 };
375
376
377 /* debugfs: antenna */
378
379 static ssize_t read_file_antenna(struct file *file, char __user *user_buf,
380                                    size_t count, loff_t *ppos)
381 {
382         struct ath5k_hw *ah = file->private_data;
383         char buf[700];
384         unsigned int len = 0;
385         unsigned int i;
386         unsigned int v;
387
388         len += snprintf(buf + len, sizeof(buf) - len, "antenna mode\t%d\n",
389                 ah->ah_ant_mode);
390         len += snprintf(buf + len, sizeof(buf) - len, "default antenna\t%d\n",
391                 ah->ah_def_ant);
392         len += snprintf(buf + len, sizeof(buf) - len, "tx antenna\t%d\n",
393                 ah->ah_tx_ant);
394
395         len += snprintf(buf + len, sizeof(buf) - len, "\nANTENNA\t\tRX\tTX\n");
396         for (i = 1; i < ARRAY_SIZE(ah->stats.antenna_rx); i++) {
397                 len += snprintf(buf + len, sizeof(buf) - len,
398                         "[antenna %d]\t%d\t%d\n",
399                         i, ah->stats.antenna_rx[i], ah->stats.antenna_tx[i]);
400         }
401         len += snprintf(buf + len, sizeof(buf) - len, "[invalid]\t%d\t%d\n",
402                         ah->stats.antenna_rx[0], ah->stats.antenna_tx[0]);
403
404         v = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
405         len += snprintf(buf + len, sizeof(buf) - len,
406                         "\nAR5K_DEFAULT_ANTENNA\t0x%08x\n", v);
407
408         v = ath5k_hw_reg_read(ah, AR5K_STA_ID1);
409         len += snprintf(buf + len, sizeof(buf) - len,
410                 "AR5K_STA_ID1_DEFAULT_ANTENNA\t%d\n",
411                 (v & AR5K_STA_ID1_DEFAULT_ANTENNA) != 0);
412         len += snprintf(buf + len, sizeof(buf) - len,
413                 "AR5K_STA_ID1_DESC_ANTENNA\t%d\n",
414                 (v & AR5K_STA_ID1_DESC_ANTENNA) != 0);
415         len += snprintf(buf + len, sizeof(buf) - len,
416                 "AR5K_STA_ID1_RTS_DEF_ANTENNA\t%d\n",
417                 (v & AR5K_STA_ID1_RTS_DEF_ANTENNA) != 0);
418         len += snprintf(buf + len, sizeof(buf) - len,
419                 "AR5K_STA_ID1_SELFGEN_DEF_ANT\t%d\n",
420                 (v & AR5K_STA_ID1_SELFGEN_DEF_ANT) != 0);
421
422         v = ath5k_hw_reg_read(ah, AR5K_PHY_AGCCTL);
423         len += snprintf(buf + len, sizeof(buf) - len,
424                 "\nAR5K_PHY_AGCCTL_OFDM_DIV_DIS\t%d\n",
425                 (v & AR5K_PHY_AGCCTL_OFDM_DIV_DIS) != 0);
426
427         v = ath5k_hw_reg_read(ah, AR5K_PHY_RESTART);
428         len += snprintf(buf + len, sizeof(buf) - len,
429                 "AR5K_PHY_RESTART_DIV_GC\t\t%x\n",
430                 (v & AR5K_PHY_RESTART_DIV_GC) >> AR5K_PHY_RESTART_DIV_GC_S);
431
432         v = ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ANT_DIV);
433         len += snprintf(buf + len, sizeof(buf) - len,
434                 "AR5K_PHY_FAST_ANT_DIV_EN\t%d\n",
435                 (v & AR5K_PHY_FAST_ANT_DIV_EN) != 0);
436
437         v = ath5k_hw_reg_read(ah, AR5K_PHY_ANT_SWITCH_TABLE_0);
438         len += snprintf(buf + len, sizeof(buf) - len,
439                         "\nAR5K_PHY_ANT_SWITCH_TABLE_0\t0x%08x\n", v);
440         v = ath5k_hw_reg_read(ah, AR5K_PHY_ANT_SWITCH_TABLE_1);
441         len += snprintf(buf + len, sizeof(buf) - len,
442                         "AR5K_PHY_ANT_SWITCH_TABLE_1\t0x%08x\n", v);
443
444         if (len > sizeof(buf))
445                 len = sizeof(buf);
446
447         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
448 }
449
450 static ssize_t write_file_antenna(struct file *file,
451                                  const char __user *userbuf,
452                                  size_t count, loff_t *ppos)
453 {
454         struct ath5k_hw *ah = file->private_data;
455         unsigned int i;
456         char buf[20];
457
458         if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
459                 return -EFAULT;
460
461         if (strncmp(buf, "diversity", 9) == 0) {
462                 ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT);
463                 pr_info("debug: enable diversity\n");
464         } else if (strncmp(buf, "fixed-a", 7) == 0) {
465                 ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_A);
466                 pr_info("debug: fixed antenna A\n");
467         } else if (strncmp(buf, "fixed-b", 7) == 0) {
468                 ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_B);
469                 pr_info("debug: fixed antenna B\n");
470         } else if (strncmp(buf, "clear", 5) == 0) {
471                 for (i = 0; i < ARRAY_SIZE(ah->stats.antenna_rx); i++) {
472                         ah->stats.antenna_rx[i] = 0;
473                         ah->stats.antenna_tx[i] = 0;
474                 }
475                 pr_info("debug: cleared antenna stats\n");
476         }
477         return count;
478 }
479
480 static const struct file_operations fops_antenna = {
481         .read = read_file_antenna,
482         .write = write_file_antenna,
483         .open = ath5k_debugfs_open,
484         .owner = THIS_MODULE,
485         .llseek = default_llseek,
486 };
487
488 /* debugfs: misc */
489
490 static ssize_t read_file_misc(struct file *file, char __user *user_buf,
491                                    size_t count, loff_t *ppos)
492 {
493         struct ath5k_hw *ah = file->private_data;
494         char buf[700];
495         unsigned int len = 0;
496         u32 filt = ath5k_hw_get_rx_filter(ah);
497
498         len += snprintf(buf + len, sizeof(buf) - len, "bssid-mask: %pM\n",
499                         ah->bssidmask);
500         len += snprintf(buf + len, sizeof(buf) - len, "filter-flags: 0x%x ",
501                         filt);
502         if (filt & AR5K_RX_FILTER_UCAST)
503                 len += snprintf(buf + len, sizeof(buf) - len, " UCAST");
504         if (filt & AR5K_RX_FILTER_MCAST)
505                 len += snprintf(buf + len, sizeof(buf) - len, " MCAST");
506         if (filt & AR5K_RX_FILTER_BCAST)
507                 len += snprintf(buf + len, sizeof(buf) - len, " BCAST");
508         if (filt & AR5K_RX_FILTER_CONTROL)
509                 len += snprintf(buf + len, sizeof(buf) - len, " CONTROL");
510         if (filt & AR5K_RX_FILTER_BEACON)
511                 len += snprintf(buf + len, sizeof(buf) - len, " BEACON");
512         if (filt & AR5K_RX_FILTER_PROM)
513                 len += snprintf(buf + len, sizeof(buf) - len, " PROM");
514         if (filt & AR5K_RX_FILTER_XRPOLL)
515                 len += snprintf(buf + len, sizeof(buf) - len, " XRPOLL");
516         if (filt & AR5K_RX_FILTER_PROBEREQ)
517                 len += snprintf(buf + len, sizeof(buf) - len, " PROBEREQ");
518         if (filt & AR5K_RX_FILTER_PHYERR_5212)
519                 len += snprintf(buf + len, sizeof(buf) - len, " PHYERR-5212");
520         if (filt & AR5K_RX_FILTER_RADARERR_5212)
521                 len += snprintf(buf + len, sizeof(buf) - len, " RADARERR-5212");
522         if (filt & AR5K_RX_FILTER_PHYERR_5211)
523                 snprintf(buf + len, sizeof(buf) - len, " PHYERR-5211");
524         if (filt & AR5K_RX_FILTER_RADARERR_5211)
525                 len += snprintf(buf + len, sizeof(buf) - len, " RADARERR-5211");
526
527         len += snprintf(buf + len, sizeof(buf) - len, "\nopmode: %s (%d)\n",
528                         ath_opmode_to_string(ah->opmode), ah->opmode);
529
530         if (len > sizeof(buf))
531                 len = sizeof(buf);
532
533         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
534 }
535
536 static const struct file_operations fops_misc = {
537         .read = read_file_misc,
538         .open = ath5k_debugfs_open,
539         .owner = THIS_MODULE,
540 };
541
542
543 /* debugfs: frameerrors */
544
545 static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf,
546                                    size_t count, loff_t *ppos)
547 {
548         struct ath5k_hw *ah = file->private_data;
549         struct ath5k_statistics *st = &ah->stats;
550         char buf[700];
551         unsigned int len = 0;
552         int i;
553
554         len += snprintf(buf + len, sizeof(buf) - len,
555                         "RX\n---------------------\n");
556         len += snprintf(buf + len, sizeof(buf) - len, "CRC\t%u\t(%u%%)\n",
557                         st->rxerr_crc,
558                         st->rx_all_count > 0 ?
559                                 st->rxerr_crc * 100 / st->rx_all_count : 0);
560         len += snprintf(buf + len, sizeof(buf) - len, "PHY\t%u\t(%u%%)\n",
561                         st->rxerr_phy,
562                         st->rx_all_count > 0 ?
563                                 st->rxerr_phy * 100 / st->rx_all_count : 0);
564         for (i = 0; i < 32; i++) {
565                 if (st->rxerr_phy_code[i])
566                         len += snprintf(buf + len, sizeof(buf) - len,
567                                 " phy_err[%u]\t%u\n",
568                                 i, st->rxerr_phy_code[i]);
569         }
570
571         len += snprintf(buf + len, sizeof(buf) - len, "FIFO\t%u\t(%u%%)\n",
572                         st->rxerr_fifo,
573                         st->rx_all_count > 0 ?
574                                 st->rxerr_fifo * 100 / st->rx_all_count : 0);
575         len += snprintf(buf + len, sizeof(buf) - len, "decrypt\t%u\t(%u%%)\n",
576                         st->rxerr_decrypt,
577                         st->rx_all_count > 0 ?
578                                 st->rxerr_decrypt * 100 / st->rx_all_count : 0);
579         len += snprintf(buf + len, sizeof(buf) - len, "MIC\t%u\t(%u%%)\n",
580                         st->rxerr_mic,
581                         st->rx_all_count > 0 ?
582                                 st->rxerr_mic * 100 / st->rx_all_count : 0);
583         len += snprintf(buf + len, sizeof(buf) - len, "process\t%u\t(%u%%)\n",
584                         st->rxerr_proc,
585                         st->rx_all_count > 0 ?
586                                 st->rxerr_proc * 100 / st->rx_all_count : 0);
587         len += snprintf(buf + len, sizeof(buf) - len, "jumbo\t%u\t(%u%%)\n",
588                         st->rxerr_jumbo,
589                         st->rx_all_count > 0 ?
590                                 st->rxerr_jumbo * 100 / st->rx_all_count : 0);
591         len += snprintf(buf + len, sizeof(buf) - len, "[RX all\t%u]\n",
592                         st->rx_all_count);
593         len += snprintf(buf + len, sizeof(buf) - len, "RX-all-bytes\t%u\n",
594                         st->rx_bytes_count);
595
596         len += snprintf(buf + len, sizeof(buf) - len,
597                         "\nTX\n---------------------\n");
598         len += snprintf(buf + len, sizeof(buf) - len, "retry\t%u\t(%u%%)\n",
599                         st->txerr_retry,
600                         st->tx_all_count > 0 ?
601                                 st->txerr_retry * 100 / st->tx_all_count : 0);
602         len += snprintf(buf + len, sizeof(buf) - len, "FIFO\t%u\t(%u%%)\n",
603                         st->txerr_fifo,
604                         st->tx_all_count > 0 ?
605                                 st->txerr_fifo * 100 / st->tx_all_count : 0);
606         len += snprintf(buf + len, sizeof(buf) - len, "filter\t%u\t(%u%%)\n",
607                         st->txerr_filt,
608                         st->tx_all_count > 0 ?
609                                 st->txerr_filt * 100 / st->tx_all_count : 0);
610         len += snprintf(buf + len, sizeof(buf) - len, "[TX all\t%u]\n",
611                         st->tx_all_count);
612         len += snprintf(buf + len, sizeof(buf) - len, "TX-all-bytes\t%u\n",
613                         st->tx_bytes_count);
614
615         if (len > sizeof(buf))
616                 len = sizeof(buf);
617
618         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
619 }
620
621 static ssize_t write_file_frameerrors(struct file *file,
622                                  const char __user *userbuf,
623                                  size_t count, loff_t *ppos)
624 {
625         struct ath5k_hw *ah = file->private_data;
626         struct ath5k_statistics *st = &ah->stats;
627         char buf[20];
628
629         if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
630                 return -EFAULT;
631
632         if (strncmp(buf, "clear", 5) == 0) {
633                 st->rxerr_crc = 0;
634                 st->rxerr_phy = 0;
635                 st->rxerr_fifo = 0;
636                 st->rxerr_decrypt = 0;
637                 st->rxerr_mic = 0;
638                 st->rxerr_proc = 0;
639                 st->rxerr_jumbo = 0;
640                 st->rx_all_count = 0;
641                 st->txerr_retry = 0;
642                 st->txerr_fifo = 0;
643                 st->txerr_filt = 0;
644                 st->tx_all_count = 0;
645                 pr_info("debug: cleared frameerrors stats\n");
646         }
647         return count;
648 }
649
650 static const struct file_operations fops_frameerrors = {
651         .read = read_file_frameerrors,
652         .write = write_file_frameerrors,
653         .open = ath5k_debugfs_open,
654         .owner = THIS_MODULE,
655         .llseek = default_llseek,
656 };
657
658
659 /* debugfs: ani */
660
661 static ssize_t read_file_ani(struct file *file, char __user *user_buf,
662                                    size_t count, loff_t *ppos)
663 {
664         struct ath5k_hw *ah = file->private_data;
665         struct ath5k_statistics *st = &ah->stats;
666         struct ath5k_ani_state *as = &ah->ani_state;
667
668         char buf[700];
669         unsigned int len = 0;
670
671         len += snprintf(buf + len, sizeof(buf) - len,
672                         "HW has PHY error counters:\t%s\n",
673                         ah->ah_capabilities.cap_has_phyerr_counters ?
674                         "yes" : "no");
675         len += snprintf(buf + len, sizeof(buf) - len,
676                         "HW max spur immunity level:\t%d\n",
677                         as->max_spur_level);
678         len += snprintf(buf + len, sizeof(buf) - len,
679                 "\nANI state\n--------------------------------------------\n");
680         len += snprintf(buf + len, sizeof(buf) - len, "operating mode:\t\t\t");
681         switch (as->ani_mode) {
682         case ATH5K_ANI_MODE_OFF:
683                 len += snprintf(buf + len, sizeof(buf) - len, "OFF\n");
684                 break;
685         case ATH5K_ANI_MODE_MANUAL_LOW:
686                 len += snprintf(buf + len, sizeof(buf) - len,
687                         "MANUAL LOW\n");
688                 break;
689         case ATH5K_ANI_MODE_MANUAL_HIGH:
690                 len += snprintf(buf + len, sizeof(buf) - len,
691                         "MANUAL HIGH\n");
692                 break;
693         case ATH5K_ANI_MODE_AUTO:
694                 len += snprintf(buf + len, sizeof(buf) - len, "AUTO\n");
695                 break;
696         default:
697                 len += snprintf(buf + len, sizeof(buf) - len,
698                         "??? (not good)\n");
699                 break;
700         }
701         len += snprintf(buf + len, sizeof(buf) - len,
702                         "noise immunity level:\t\t%d\n",
703                         as->noise_imm_level);
704         len += snprintf(buf + len, sizeof(buf) - len,
705                         "spur immunity level:\t\t%d\n",
706                         as->spur_level);
707         len += snprintf(buf + len, sizeof(buf) - len,
708                         "firstep level:\t\t\t%d\n",
709                         as->firstep_level);
710         len += snprintf(buf + len, sizeof(buf) - len,
711                         "OFDM weak signal detection:\t%s\n",
712                         as->ofdm_weak_sig ? "on" : "off");
713         len += snprintf(buf + len, sizeof(buf) - len,
714                         "CCK weak signal detection:\t%s\n",
715                         as->cck_weak_sig ? "on" : "off");
716
717         len += snprintf(buf + len, sizeof(buf) - len,
718                         "\nMIB INTERRUPTS:\t\t%u\n",
719                         st->mib_intr);
720         len += snprintf(buf + len, sizeof(buf) - len,
721                         "beacon RSSI average:\t%d\n",
722                         (int)ewma_read(&ah->ah_beacon_rssi_avg));
723
724 #define CC_PRINT(_struct, _field) \
725         _struct._field, \
726         _struct.cycles > 0 ? \
727         _struct._field * 100 / _struct.cycles : 0
728
729         len += snprintf(buf + len, sizeof(buf) - len,
730                         "profcnt tx\t\t%u\t(%d%%)\n",
731                         CC_PRINT(as->last_cc, tx_frame));
732         len += snprintf(buf + len, sizeof(buf) - len,
733                         "profcnt rx\t\t%u\t(%d%%)\n",
734                         CC_PRINT(as->last_cc, rx_frame));
735         len += snprintf(buf + len, sizeof(buf) - len,
736                         "profcnt busy\t\t%u\t(%d%%)\n",
737                         CC_PRINT(as->last_cc, rx_busy));
738 #undef CC_PRINT
739         len += snprintf(buf + len, sizeof(buf) - len, "profcnt cycles\t\t%u\n",
740                         as->last_cc.cycles);
741         len += snprintf(buf + len, sizeof(buf) - len,
742                         "listen time\t\t%d\tlast: %d\n",
743                         as->listen_time, as->last_listen);
744         len += snprintf(buf + len, sizeof(buf) - len,
745                         "OFDM errors\t\t%u\tlast: %u\tsum: %u\n",
746                         as->ofdm_errors, as->last_ofdm_errors,
747                         as->sum_ofdm_errors);
748         len += snprintf(buf + len, sizeof(buf) - len,
749                         "CCK errors\t\t%u\tlast: %u\tsum: %u\n",
750                         as->cck_errors, as->last_cck_errors,
751                         as->sum_cck_errors);
752         len += snprintf(buf + len, sizeof(buf) - len,
753                         "AR5K_PHYERR_CNT1\t%x\t(=%d)\n",
754                         ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1),
755                         ATH5K_ANI_OFDM_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX -
756                         ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1)));
757         len += snprintf(buf + len, sizeof(buf) - len,
758                         "AR5K_PHYERR_CNT2\t%x\t(=%d)\n",
759                         ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2),
760                         ATH5K_ANI_CCK_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX -
761                         ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2)));
762
763         if (len > sizeof(buf))
764                 len = sizeof(buf);
765
766         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
767 }
768
769 static ssize_t write_file_ani(struct file *file,
770                                  const char __user *userbuf,
771                                  size_t count, loff_t *ppos)
772 {
773         struct ath5k_hw *ah = file->private_data;
774         char buf[20];
775
776         if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
777                 return -EFAULT;
778
779         if (strncmp(buf, "sens-low", 8) == 0) {
780                 ath5k_ani_init(ah, ATH5K_ANI_MODE_MANUAL_HIGH);
781         } else if (strncmp(buf, "sens-high", 9) == 0) {
782                 ath5k_ani_init(ah, ATH5K_ANI_MODE_MANUAL_LOW);
783         } else if (strncmp(buf, "ani-off", 7) == 0) {
784                 ath5k_ani_init(ah, ATH5K_ANI_MODE_OFF);
785         } else if (strncmp(buf, "ani-on", 6) == 0) {
786                 ath5k_ani_init(ah, ATH5K_ANI_MODE_AUTO);
787         } else if (strncmp(buf, "noise-low", 9) == 0) {
788                 ath5k_ani_set_noise_immunity_level(ah, 0);
789         } else if (strncmp(buf, "noise-high", 10) == 0) {
790                 ath5k_ani_set_noise_immunity_level(ah,
791                                                    ATH5K_ANI_MAX_NOISE_IMM_LVL);
792         } else if (strncmp(buf, "spur-low", 8) == 0) {
793                 ath5k_ani_set_spur_immunity_level(ah, 0);
794         } else if (strncmp(buf, "spur-high", 9) == 0) {
795                 ath5k_ani_set_spur_immunity_level(ah,
796                                                   ah->ani_state.max_spur_level);
797         } else if (strncmp(buf, "fir-low", 7) == 0) {
798                 ath5k_ani_set_firstep_level(ah, 0);
799         } else if (strncmp(buf, "fir-high", 8) == 0) {
800                 ath5k_ani_set_firstep_level(ah, ATH5K_ANI_MAX_FIRSTEP_LVL);
801         } else if (strncmp(buf, "ofdm-off", 8) == 0) {
802                 ath5k_ani_set_ofdm_weak_signal_detection(ah, false);
803         } else if (strncmp(buf, "ofdm-on", 7) == 0) {
804                 ath5k_ani_set_ofdm_weak_signal_detection(ah, true);
805         } else if (strncmp(buf, "cck-off", 7) == 0) {
806                 ath5k_ani_set_cck_weak_signal_detection(ah, false);
807         } else if (strncmp(buf, "cck-on", 6) == 0) {
808                 ath5k_ani_set_cck_weak_signal_detection(ah, true);
809         }
810         return count;
811 }
812
813 static const struct file_operations fops_ani = {
814         .read = read_file_ani,
815         .write = write_file_ani,
816         .open = ath5k_debugfs_open,
817         .owner = THIS_MODULE,
818         .llseek = default_llseek,
819 };
820
821
822 /* debugfs: queues etc */
823
824 static ssize_t read_file_queue(struct file *file, char __user *user_buf,
825                                    size_t count, loff_t *ppos)
826 {
827         struct ath5k_hw *ah = file->private_data;
828         char buf[700];
829         unsigned int len = 0;
830
831         struct ath5k_txq *txq;
832         struct ath5k_buf *bf, *bf0;
833         int i, n;
834
835         len += snprintf(buf + len, sizeof(buf) - len,
836                         "available txbuffers: %d\n", ah->txbuf_len);
837
838         for (i = 0; i < ARRAY_SIZE(ah->txqs); i++) {
839                 txq = &ah->txqs[i];
840
841                 len += snprintf(buf + len, sizeof(buf) - len,
842                         "%02d: %ssetup\n", i, txq->setup ? "" : "not ");
843
844                 if (!txq->setup)
845                         continue;
846
847                 n = 0;
848                 spin_lock_bh(&txq->lock);
849                 list_for_each_entry_safe(bf, bf0, &txq->q, list)
850                         n++;
851                 spin_unlock_bh(&txq->lock);
852
853                 len += snprintf(buf + len, sizeof(buf) - len,
854                                 "  len: %d bufs: %d\n", txq->txq_len, n);
855                 len += snprintf(buf + len, sizeof(buf) - len,
856                                 "  stuck: %d\n", txq->txq_stuck);
857         }
858
859         if (len > sizeof(buf))
860                 len = sizeof(buf);
861
862         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
863 }
864
865 static ssize_t write_file_queue(struct file *file,
866                                  const char __user *userbuf,
867                                  size_t count, loff_t *ppos)
868 {
869         struct ath5k_hw *ah = file->private_data;
870         char buf[20];
871
872         if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
873                 return -EFAULT;
874
875         if (strncmp(buf, "start", 5) == 0)
876                 ieee80211_wake_queues(ah->hw);
877         else if (strncmp(buf, "stop", 4) == 0)
878                 ieee80211_stop_queues(ah->hw);
879
880         return count;
881 }
882
883
884 static const struct file_operations fops_queue = {
885         .read = read_file_queue,
886         .write = write_file_queue,
887         .open = ath5k_debugfs_open,
888         .owner = THIS_MODULE,
889         .llseek = default_llseek,
890 };
891
892
893 void
894 ath5k_debug_init_device(struct ath5k_hw *ah)
895 {
896         struct dentry *phydir;
897
898         ah->debug.level = ath5k_debug;
899
900         phydir = debugfs_create_dir("ath5k", ah->hw->wiphy->debugfsdir);
901         if (!phydir)
902                 return;
903
904         debugfs_create_file("debug", S_IWUSR | S_IRUSR, phydir, ah,
905                             &fops_debug);
906
907         debugfs_create_file("registers", S_IRUSR, phydir, ah, &fops_registers);
908
909         debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, ah,
910                             &fops_beacon);
911
912         debugfs_create_file("reset", S_IWUSR, phydir, ah, &fops_reset);
913
914         debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, ah,
915                             &fops_antenna);
916
917         debugfs_create_file("misc", S_IRUSR, phydir, ah, &fops_misc);
918
919         debugfs_create_file("frameerrors", S_IWUSR | S_IRUSR, phydir, ah,
920                             &fops_frameerrors);
921
922         debugfs_create_file("ani", S_IWUSR | S_IRUSR, phydir, ah, &fops_ani);
923
924         debugfs_create_file("queue", S_IWUSR | S_IRUSR, phydir, ah,
925                             &fops_queue);
926
927         debugfs_create_bool("32khz_clock", S_IWUSR | S_IRUSR, phydir,
928                             &ah->ah_use_32khz_clock);
929 }
930
931 /* functions used in other places */
932
933 void
934 ath5k_debug_dump_bands(struct ath5k_hw *ah)
935 {
936         unsigned int b, i;
937
938         if (likely(!(ah->debug.level & ATH5K_DEBUG_DUMPBANDS)))
939                 return;
940
941         BUG_ON(!ah->sbands);
942
943         for (b = 0; b < IEEE80211_NUM_BANDS; b++) {
944                 struct ieee80211_supported_band *band = &ah->sbands[b];
945                 char bname[6];
946                 switch (band->band) {
947                 case IEEE80211_BAND_2GHZ:
948                         strcpy(bname, "2 GHz");
949                         break;
950                 case IEEE80211_BAND_5GHZ:
951                         strcpy(bname, "5 GHz");
952                         break;
953                 default:
954                         printk(KERN_DEBUG "Band not supported: %d\n",
955                                 band->band);
956                         return;
957                 }
958                 printk(KERN_DEBUG "Band %s: channels %d, rates %d\n", bname,
959                                 band->n_channels, band->n_bitrates);
960                 printk(KERN_DEBUG " channels:\n");
961                 for (i = 0; i < band->n_channels; i++)
962                         printk(KERN_DEBUG "  %3d %d %.4x %.4x\n",
963                                         ieee80211_frequency_to_channel(
964                                                 band->channels[i].center_freq),
965                                         band->channels[i].center_freq,
966                                         band->channels[i].hw_value,
967                                         band->channels[i].flags);
968                 printk(KERN_DEBUG " rates:\n");
969                 for (i = 0; i < band->n_bitrates; i++)
970                         printk(KERN_DEBUG "  %4d %.4x %.4x %.4x\n",
971                                         band->bitrates[i].bitrate,
972                                         band->bitrates[i].hw_value,
973                                         band->bitrates[i].flags,
974                                         band->bitrates[i].hw_value_short);
975         }
976 }
977
978 static inline void
979 ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done,
980                        struct ath5k_rx_status *rs)
981 {
982         struct ath5k_desc *ds = bf->desc;
983         struct ath5k_hw_all_rx_desc *rd = &ds->ud.ds_rx;
984
985         printk(KERN_DEBUG "R (%p %llx) %08x %08x %08x %08x %08x %08x %c\n",
986                 ds, (unsigned long long)bf->daddr,
987                 ds->ds_link, ds->ds_data,
988                 rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1,
989                 rd->rx_stat.rx_status_0, rd->rx_stat.rx_status_1,
990                 !done ? ' ' : (rs->rs_status == 0) ? '*' : '!');
991 }
992
993 void
994 ath5k_debug_printrxbuffs(struct ath5k_hw *ah)
995 {
996         struct ath5k_desc *ds;
997         struct ath5k_buf *bf;
998         struct ath5k_rx_status rs = {};
999         int status;
1000
1001         if (likely(!(ah->debug.level & ATH5K_DEBUG_DESC)))
1002                 return;
1003
1004         printk(KERN_DEBUG "rxdp %x, rxlink %p\n",
1005                 ath5k_hw_get_rxdp(ah), ah->rxlink);
1006
1007         spin_lock_bh(&ah->rxbuflock);
1008         list_for_each_entry(bf, &ah->rxbuf, list) {
1009                 ds = bf->desc;
1010                 status = ah->ah_proc_rx_desc(ah, ds, &rs);
1011                 if (!status)
1012                         ath5k_debug_printrxbuf(bf, status == 0, &rs);
1013         }
1014         spin_unlock_bh(&ah->rxbuflock);
1015 }
1016
1017 void
1018 ath5k_debug_printtxbuf(struct ath5k_hw *ah, struct ath5k_buf *bf)
1019 {
1020         struct ath5k_desc *ds = bf->desc;
1021         struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212;
1022         struct ath5k_tx_status ts = {};
1023         int done;
1024
1025         if (likely(!(ah->debug.level & ATH5K_DEBUG_DESC)))
1026                 return;
1027
1028         done = ah->ah_proc_tx_desc(ah, bf->desc, &ts);
1029
1030         printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x "
1031                 "%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link,
1032                 ds->ds_data, td->tx_ctl.tx_control_0, td->tx_ctl.tx_control_1,
1033                 td->tx_ctl.tx_control_2, td->tx_ctl.tx_control_3,
1034                 td->tx_stat.tx_status_0, td->tx_stat.tx_status_1,
1035                 done ? ' ' : (ts.ts_status == 0) ? '*' : '!');
1036 }