]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/net/wireless/ath/ath5k/debug.c
ath5k: Add missing vmalloc.h include.
[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 #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
74 static unsigned int ath5k_debug;
75 module_param_named(debug, ath5k_debug, uint, 0);
76
77
78 /* debugfs: registers */
79
80 struct 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 */
88 static 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
139 static void *reg_start(struct seq_file *seq, loff_t *pos)
140 {
141         return *pos < ARRAY_SIZE(regs) ? (void *)&regs[*pos] : NULL;
142 }
143
144 static void reg_stop(struct seq_file *seq, void *p)
145 {
146         /* nothing to do */
147 }
148
149 static 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
155 static 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
164 static const struct seq_operations register_seq_ops = {
165         .start = reg_start,
166         .next  = reg_next,
167         .stop  = reg_stop,
168         .show  = reg_show
169 };
170
171 static int open_file_registers(struct inode *inode, struct file *file)
172 {
173         struct seq_file *s;
174         int res;
175         res = seq_open(file, &register_seq_ops);
176         if (res == 0) {
177                 s = file->private_data;
178                 s->private = inode->i_private;
179         }
180         return res;
181 }
182
183 static const struct file_operations fops_registers = {
184         .open = open_file_registers,
185         .read    = seq_read,
186         .llseek  = seq_lseek,
187         .release = seq_release,
188         .owner = THIS_MODULE,
189 };
190
191
192 /* debugfs: beacons */
193
194 static ssize_t read_file_beacon(struct file *file, char __user *user_buf,
195                                    size_t count, loff_t *ppos)
196 {
197         struct ath5k_hw *ah = file->private_data;
198         char buf[500];
199         unsigned int len = 0;
200         unsigned int v;
201         u64 tsf;
202
203         v = ath5k_hw_reg_read(ah, AR5K_BEACON);
204         len += snprintf(buf + len, sizeof(buf) - len,
205                 "%-24s0x%08x\tintval: %d\tTIM: 0x%x\n",
206                 "AR5K_BEACON", v, v & AR5K_BEACON_PERIOD,
207                 (v & AR5K_BEACON_TIM) >> AR5K_BEACON_TIM_S);
208
209         len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\n",
210                 "AR5K_LAST_TSTP", ath5k_hw_reg_read(ah, AR5K_LAST_TSTP));
211
212         len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\n\n",
213                 "AR5K_BEACON_CNT", ath5k_hw_reg_read(ah, AR5K_BEACON_CNT));
214
215         v = ath5k_hw_reg_read(ah, AR5K_TIMER0);
216         len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
217                 "AR5K_TIMER0 (TBTT)", v, v);
218
219         v = ath5k_hw_reg_read(ah, AR5K_TIMER1);
220         len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
221                 "AR5K_TIMER1 (DMA)", v, v >> 3);
222
223         v = ath5k_hw_reg_read(ah, AR5K_TIMER2);
224         len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
225                 "AR5K_TIMER2 (SWBA)", v, v >> 3);
226
227         v = ath5k_hw_reg_read(ah, AR5K_TIMER3);
228         len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
229                 "AR5K_TIMER3 (ATIM)", v, v);
230
231         tsf = ath5k_hw_get_tsf64(ah);
232         len += snprintf(buf + len, sizeof(buf) - len,
233                 "TSF\t\t0x%016llx\tTU: %08x\n",
234                 (unsigned long long)tsf, TSF_TO_TU(tsf));
235
236         if (len > sizeof(buf))
237                 len = sizeof(buf);
238
239         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
240 }
241
242 static ssize_t write_file_beacon(struct file *file,
243                                  const char __user *userbuf,
244                                  size_t count, loff_t *ppos)
245 {
246         struct ath5k_hw *ah = file->private_data;
247         char buf[20];
248
249         count = min_t(size_t, count, sizeof(buf) - 1);
250         if (copy_from_user(buf, userbuf, count))
251                 return -EFAULT;
252
253         buf[count] = '\0';
254         if (strncmp(buf, "disable", 7) == 0) {
255                 AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
256                 pr_info("debugfs disable beacons\n");
257         } else if (strncmp(buf, "enable", 6) == 0) {
258                 AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
259                 pr_info("debugfs enable beacons\n");
260         }
261         return count;
262 }
263
264 static const struct file_operations fops_beacon = {
265         .read = read_file_beacon,
266         .write = write_file_beacon,
267         .open = simple_open,
268         .owner = THIS_MODULE,
269         .llseek = default_llseek,
270 };
271
272
273 /* debugfs: reset */
274
275 static ssize_t write_file_reset(struct file *file,
276                                  const char __user *userbuf,
277                                  size_t count, loff_t *ppos)
278 {
279         struct ath5k_hw *ah = file->private_data;
280         ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "debug file triggered reset\n");
281         ieee80211_queue_work(ah->hw, &ah->reset_work);
282         return count;
283 }
284
285 static const struct file_operations fops_reset = {
286         .write = write_file_reset,
287         .open = simple_open,
288         .owner = THIS_MODULE,
289         .llseek = noop_llseek,
290 };
291
292
293 /* debugfs: debug level */
294
295 static const struct {
296         enum ath5k_debug_level level;
297         const char *name;
298         const char *desc;
299 } dbg_info[] = {
300         { ATH5K_DEBUG_RESET,    "reset",        "reset and initialization" },
301         { ATH5K_DEBUG_INTR,     "intr",         "interrupt handling" },
302         { ATH5K_DEBUG_MODE,     "mode",         "mode init/setup" },
303         { ATH5K_DEBUG_XMIT,     "xmit",         "basic xmit operation" },
304         { ATH5K_DEBUG_BEACON,   "beacon",       "beacon handling" },
305         { ATH5K_DEBUG_CALIBRATE, "calib",       "periodic calibration" },
306         { ATH5K_DEBUG_TXPOWER,  "txpower",      "transmit power setting" },
307         { ATH5K_DEBUG_LED,      "led",          "LED management" },
308         { ATH5K_DEBUG_DUMPBANDS, "dumpbands",   "dump bands" },
309         { ATH5K_DEBUG_DMA,      "dma",          "dma start/stop" },
310         { ATH5K_DEBUG_ANI,      "ani",          "adaptive noise immunity" },
311         { ATH5K_DEBUG_DESC,     "desc",         "descriptor chains" },
312         { ATH5K_DEBUG_ANY,      "all",          "show all debug levels" },
313 };
314
315 static ssize_t read_file_debug(struct file *file, char __user *user_buf,
316                                    size_t count, loff_t *ppos)
317 {
318         struct ath5k_hw *ah = file->private_data;
319         char buf[700];
320         unsigned int len = 0;
321         unsigned int i;
322
323         len += snprintf(buf + len, sizeof(buf) - len,
324                 "DEBUG LEVEL: 0x%08x\n\n", ah->debug.level);
325
326         for (i = 0; i < ARRAY_SIZE(dbg_info) - 1; i++) {
327                 len += snprintf(buf + len, sizeof(buf) - len,
328                         "%10s %c 0x%08x - %s\n", dbg_info[i].name,
329                         ah->debug.level & dbg_info[i].level ? '+' : ' ',
330                         dbg_info[i].level, dbg_info[i].desc);
331         }
332         len += snprintf(buf + len, sizeof(buf) - len,
333                 "%10s %c 0x%08x - %s\n", dbg_info[i].name,
334                 ah->debug.level == dbg_info[i].level ? '+' : ' ',
335                 dbg_info[i].level, dbg_info[i].desc);
336
337         if (len > sizeof(buf))
338                 len = sizeof(buf);
339
340         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
341 }
342
343 static ssize_t write_file_debug(struct file *file,
344                                  const char __user *userbuf,
345                                  size_t count, loff_t *ppos)
346 {
347         struct ath5k_hw *ah = file->private_data;
348         unsigned int i;
349         char buf[20];
350
351         count = min_t(size_t, count, sizeof(buf) - 1);
352         if (copy_from_user(buf, userbuf, count))
353                 return -EFAULT;
354
355         buf[count] = '\0';
356         for (i = 0; i < ARRAY_SIZE(dbg_info); i++) {
357                 if (strncmp(buf, dbg_info[i].name,
358                                         strlen(dbg_info[i].name)) == 0) {
359                         ah->debug.level ^= dbg_info[i].level; /* toggle bit */
360                         break;
361                 }
362         }
363         return count;
364 }
365
366 static const struct file_operations fops_debug = {
367         .read = read_file_debug,
368         .write = write_file_debug,
369         .open = simple_open,
370         .owner = THIS_MODULE,
371         .llseek = default_llseek,
372 };
373
374
375 /* debugfs: antenna */
376
377 static ssize_t read_file_antenna(struct file *file, char __user *user_buf,
378                                    size_t count, loff_t *ppos)
379 {
380         struct ath5k_hw *ah = file->private_data;
381         char buf[700];
382         unsigned int len = 0;
383         unsigned int i;
384         unsigned int v;
385
386         len += snprintf(buf + len, sizeof(buf) - len, "antenna mode\t%d\n",
387                 ah->ah_ant_mode);
388         len += snprintf(buf + len, sizeof(buf) - len, "default antenna\t%d\n",
389                 ah->ah_def_ant);
390         len += snprintf(buf + len, sizeof(buf) - len, "tx antenna\t%d\n",
391                 ah->ah_tx_ant);
392
393         len += snprintf(buf + len, sizeof(buf) - len, "\nANTENNA\t\tRX\tTX\n");
394         for (i = 1; i < ARRAY_SIZE(ah->stats.antenna_rx); i++) {
395                 len += snprintf(buf + len, sizeof(buf) - len,
396                         "[antenna %d]\t%d\t%d\n",
397                         i, ah->stats.antenna_rx[i], ah->stats.antenna_tx[i]);
398         }
399         len += snprintf(buf + len, sizeof(buf) - len, "[invalid]\t%d\t%d\n",
400                         ah->stats.antenna_rx[0], ah->stats.antenna_tx[0]);
401
402         v = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
403         len += snprintf(buf + len, sizeof(buf) - len,
404                         "\nAR5K_DEFAULT_ANTENNA\t0x%08x\n", v);
405
406         v = ath5k_hw_reg_read(ah, AR5K_STA_ID1);
407         len += snprintf(buf + len, sizeof(buf) - len,
408                 "AR5K_STA_ID1_DEFAULT_ANTENNA\t%d\n",
409                 (v & AR5K_STA_ID1_DEFAULT_ANTENNA) != 0);
410         len += snprintf(buf + len, sizeof(buf) - len,
411                 "AR5K_STA_ID1_DESC_ANTENNA\t%d\n",
412                 (v & AR5K_STA_ID1_DESC_ANTENNA) != 0);
413         len += snprintf(buf + len, sizeof(buf) - len,
414                 "AR5K_STA_ID1_RTS_DEF_ANTENNA\t%d\n",
415                 (v & AR5K_STA_ID1_RTS_DEF_ANTENNA) != 0);
416         len += snprintf(buf + len, sizeof(buf) - len,
417                 "AR5K_STA_ID1_SELFGEN_DEF_ANT\t%d\n",
418                 (v & AR5K_STA_ID1_SELFGEN_DEF_ANT) != 0);
419
420         v = ath5k_hw_reg_read(ah, AR5K_PHY_AGCCTL);
421         len += snprintf(buf + len, sizeof(buf) - len,
422                 "\nAR5K_PHY_AGCCTL_OFDM_DIV_DIS\t%d\n",
423                 (v & AR5K_PHY_AGCCTL_OFDM_DIV_DIS) != 0);
424
425         v = ath5k_hw_reg_read(ah, AR5K_PHY_RESTART);
426         len += snprintf(buf + len, sizeof(buf) - len,
427                 "AR5K_PHY_RESTART_DIV_GC\t\t%x\n",
428                 (v & AR5K_PHY_RESTART_DIV_GC) >> AR5K_PHY_RESTART_DIV_GC_S);
429
430         v = ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ANT_DIV);
431         len += snprintf(buf + len, sizeof(buf) - len,
432                 "AR5K_PHY_FAST_ANT_DIV_EN\t%d\n",
433                 (v & AR5K_PHY_FAST_ANT_DIV_EN) != 0);
434
435         v = ath5k_hw_reg_read(ah, AR5K_PHY_ANT_SWITCH_TABLE_0);
436         len += snprintf(buf + len, sizeof(buf) - len,
437                         "\nAR5K_PHY_ANT_SWITCH_TABLE_0\t0x%08x\n", v);
438         v = ath5k_hw_reg_read(ah, AR5K_PHY_ANT_SWITCH_TABLE_1);
439         len += snprintf(buf + len, sizeof(buf) - len,
440                         "AR5K_PHY_ANT_SWITCH_TABLE_1\t0x%08x\n", v);
441
442         if (len > sizeof(buf))
443                 len = sizeof(buf);
444
445         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
446 }
447
448 static ssize_t write_file_antenna(struct file *file,
449                                  const char __user *userbuf,
450                                  size_t count, loff_t *ppos)
451 {
452         struct ath5k_hw *ah = file->private_data;
453         unsigned int i;
454         char buf[20];
455
456         count = min_t(size_t, count, sizeof(buf) - 1);
457         if (copy_from_user(buf, userbuf, count))
458                 return -EFAULT;
459
460         buf[count] = '\0';
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 = simple_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 = simple_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         count = min_t(size_t, count, sizeof(buf) - 1);
630         if (copy_from_user(buf, userbuf, count))
631                 return -EFAULT;
632
633         buf[count] = '\0';
634         if (strncmp(buf, "clear", 5) == 0) {
635                 st->rxerr_crc = 0;
636                 st->rxerr_phy = 0;
637                 st->rxerr_fifo = 0;
638                 st->rxerr_decrypt = 0;
639                 st->rxerr_mic = 0;
640                 st->rxerr_proc = 0;
641                 st->rxerr_jumbo = 0;
642                 st->rx_all_count = 0;
643                 st->txerr_retry = 0;
644                 st->txerr_fifo = 0;
645                 st->txerr_filt = 0;
646                 st->tx_all_count = 0;
647                 pr_info("debug: cleared frameerrors stats\n");
648         }
649         return count;
650 }
651
652 static const struct file_operations fops_frameerrors = {
653         .read = read_file_frameerrors,
654         .write = write_file_frameerrors,
655         .open = simple_open,
656         .owner = THIS_MODULE,
657         .llseek = default_llseek,
658 };
659
660
661 /* debugfs: ani */
662
663 static ssize_t read_file_ani(struct file *file, char __user *user_buf,
664                                    size_t count, loff_t *ppos)
665 {
666         struct ath5k_hw *ah = file->private_data;
667         struct ath5k_statistics *st = &ah->stats;
668         struct ath5k_ani_state *as = &ah->ani_state;
669
670         char buf[700];
671         unsigned int len = 0;
672
673         len += snprintf(buf + len, sizeof(buf) - len,
674                         "HW has PHY error counters:\t%s\n",
675                         ah->ah_capabilities.cap_has_phyerr_counters ?
676                         "yes" : "no");
677         len += snprintf(buf + len, sizeof(buf) - len,
678                         "HW max spur immunity level:\t%d\n",
679                         as->max_spur_level);
680         len += snprintf(buf + len, sizeof(buf) - len,
681                 "\nANI state\n--------------------------------------------\n");
682         len += snprintf(buf + len, sizeof(buf) - len, "operating mode:\t\t\t");
683         switch (as->ani_mode) {
684         case ATH5K_ANI_MODE_OFF:
685                 len += snprintf(buf + len, sizeof(buf) - len, "OFF\n");
686                 break;
687         case ATH5K_ANI_MODE_MANUAL_LOW:
688                 len += snprintf(buf + len, sizeof(buf) - len,
689                         "MANUAL LOW\n");
690                 break;
691         case ATH5K_ANI_MODE_MANUAL_HIGH:
692                 len += snprintf(buf + len, sizeof(buf) - len,
693                         "MANUAL HIGH\n");
694                 break;
695         case ATH5K_ANI_MODE_AUTO:
696                 len += snprintf(buf + len, sizeof(buf) - len, "AUTO\n");
697                 break;
698         default:
699                 len += snprintf(buf + len, sizeof(buf) - len,
700                         "??? (not good)\n");
701                 break;
702         }
703         len += snprintf(buf + len, sizeof(buf) - len,
704                         "noise immunity level:\t\t%d\n",
705                         as->noise_imm_level);
706         len += snprintf(buf + len, sizeof(buf) - len,
707                         "spur immunity level:\t\t%d\n",
708                         as->spur_level);
709         len += snprintf(buf + len, sizeof(buf) - len,
710                         "firstep level:\t\t\t%d\n",
711                         as->firstep_level);
712         len += snprintf(buf + len, sizeof(buf) - len,
713                         "OFDM weak signal detection:\t%s\n",
714                         as->ofdm_weak_sig ? "on" : "off");
715         len += snprintf(buf + len, sizeof(buf) - len,
716                         "CCK weak signal detection:\t%s\n",
717                         as->cck_weak_sig ? "on" : "off");
718
719         len += snprintf(buf + len, sizeof(buf) - len,
720                         "\nMIB INTERRUPTS:\t\t%u\n",
721                         st->mib_intr);
722         len += snprintf(buf + len, sizeof(buf) - len,
723                         "beacon RSSI average:\t%d\n",
724                         (int)ewma_read(&ah->ah_beacon_rssi_avg));
725
726 #define CC_PRINT(_struct, _field) \
727         _struct._field, \
728         _struct.cycles > 0 ? \
729         _struct._field * 100 / _struct.cycles : 0
730
731         len += snprintf(buf + len, sizeof(buf) - len,
732                         "profcnt tx\t\t%u\t(%d%%)\n",
733                         CC_PRINT(as->last_cc, tx_frame));
734         len += snprintf(buf + len, sizeof(buf) - len,
735                         "profcnt rx\t\t%u\t(%d%%)\n",
736                         CC_PRINT(as->last_cc, rx_frame));
737         len += snprintf(buf + len, sizeof(buf) - len,
738                         "profcnt busy\t\t%u\t(%d%%)\n",
739                         CC_PRINT(as->last_cc, rx_busy));
740 #undef CC_PRINT
741         len += snprintf(buf + len, sizeof(buf) - len, "profcnt cycles\t\t%u\n",
742                         as->last_cc.cycles);
743         len += snprintf(buf + len, sizeof(buf) - len,
744                         "listen time\t\t%d\tlast: %d\n",
745                         as->listen_time, as->last_listen);
746         len += snprintf(buf + len, sizeof(buf) - len,
747                         "OFDM errors\t\t%u\tlast: %u\tsum: %u\n",
748                         as->ofdm_errors, as->last_ofdm_errors,
749                         as->sum_ofdm_errors);
750         len += snprintf(buf + len, sizeof(buf) - len,
751                         "CCK errors\t\t%u\tlast: %u\tsum: %u\n",
752                         as->cck_errors, as->last_cck_errors,
753                         as->sum_cck_errors);
754         len += snprintf(buf + len, sizeof(buf) - len,
755                         "AR5K_PHYERR_CNT1\t%x\t(=%d)\n",
756                         ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1),
757                         ATH5K_ANI_OFDM_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX -
758                         ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1)));
759         len += snprintf(buf + len, sizeof(buf) - len,
760                         "AR5K_PHYERR_CNT2\t%x\t(=%d)\n",
761                         ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2),
762                         ATH5K_ANI_CCK_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX -
763                         ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2)));
764
765         if (len > sizeof(buf))
766                 len = sizeof(buf);
767
768         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
769 }
770
771 static ssize_t write_file_ani(struct file *file,
772                                  const char __user *userbuf,
773                                  size_t count, loff_t *ppos)
774 {
775         struct ath5k_hw *ah = file->private_data;
776         char buf[20];
777
778         count = min_t(size_t, count, sizeof(buf) - 1);
779         if (copy_from_user(buf, userbuf, count))
780                 return -EFAULT;
781
782         buf[count] = '\0';
783         if (strncmp(buf, "sens-low", 8) == 0) {
784                 ath5k_ani_init(ah, ATH5K_ANI_MODE_MANUAL_HIGH);
785         } else if (strncmp(buf, "sens-high", 9) == 0) {
786                 ath5k_ani_init(ah, ATH5K_ANI_MODE_MANUAL_LOW);
787         } else if (strncmp(buf, "ani-off", 7) == 0) {
788                 ath5k_ani_init(ah, ATH5K_ANI_MODE_OFF);
789         } else if (strncmp(buf, "ani-on", 6) == 0) {
790                 ath5k_ani_init(ah, ATH5K_ANI_MODE_AUTO);
791         } else if (strncmp(buf, "noise-low", 9) == 0) {
792                 ath5k_ani_set_noise_immunity_level(ah, 0);
793         } else if (strncmp(buf, "noise-high", 10) == 0) {
794                 ath5k_ani_set_noise_immunity_level(ah,
795                                                    ATH5K_ANI_MAX_NOISE_IMM_LVL);
796         } else if (strncmp(buf, "spur-low", 8) == 0) {
797                 ath5k_ani_set_spur_immunity_level(ah, 0);
798         } else if (strncmp(buf, "spur-high", 9) == 0) {
799                 ath5k_ani_set_spur_immunity_level(ah,
800                                                   ah->ani_state.max_spur_level);
801         } else if (strncmp(buf, "fir-low", 7) == 0) {
802                 ath5k_ani_set_firstep_level(ah, 0);
803         } else if (strncmp(buf, "fir-high", 8) == 0) {
804                 ath5k_ani_set_firstep_level(ah, ATH5K_ANI_MAX_FIRSTEP_LVL);
805         } else if (strncmp(buf, "ofdm-off", 8) == 0) {
806                 ath5k_ani_set_ofdm_weak_signal_detection(ah, false);
807         } else if (strncmp(buf, "ofdm-on", 7) == 0) {
808                 ath5k_ani_set_ofdm_weak_signal_detection(ah, true);
809         } else if (strncmp(buf, "cck-off", 7) == 0) {
810                 ath5k_ani_set_cck_weak_signal_detection(ah, false);
811         } else if (strncmp(buf, "cck-on", 6) == 0) {
812                 ath5k_ani_set_cck_weak_signal_detection(ah, true);
813         }
814         return count;
815 }
816
817 static const struct file_operations fops_ani = {
818         .read = read_file_ani,
819         .write = write_file_ani,
820         .open = simple_open,
821         .owner = THIS_MODULE,
822         .llseek = default_llseek,
823 };
824
825
826 /* debugfs: queues etc */
827
828 static ssize_t read_file_queue(struct file *file, char __user *user_buf,
829                                    size_t count, loff_t *ppos)
830 {
831         struct ath5k_hw *ah = file->private_data;
832         char buf[700];
833         unsigned int len = 0;
834
835         struct ath5k_txq *txq;
836         struct ath5k_buf *bf, *bf0;
837         int i, n;
838
839         len += snprintf(buf + len, sizeof(buf) - len,
840                         "available txbuffers: %d\n", ah->txbuf_len);
841
842         for (i = 0; i < ARRAY_SIZE(ah->txqs); i++) {
843                 txq = &ah->txqs[i];
844
845                 len += snprintf(buf + len, sizeof(buf) - len,
846                         "%02d: %ssetup\n", i, txq->setup ? "" : "not ");
847
848                 if (!txq->setup)
849                         continue;
850
851                 n = 0;
852                 spin_lock_bh(&txq->lock);
853                 list_for_each_entry_safe(bf, bf0, &txq->q, list)
854                         n++;
855                 spin_unlock_bh(&txq->lock);
856
857                 len += snprintf(buf + len, sizeof(buf) - len,
858                                 "  len: %d bufs: %d\n", txq->txq_len, n);
859                 len += snprintf(buf + len, sizeof(buf) - len,
860                                 "  stuck: %d\n", txq->txq_stuck);
861         }
862
863         if (len > sizeof(buf))
864                 len = sizeof(buf);
865
866         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
867 }
868
869 static ssize_t write_file_queue(struct file *file,
870                                  const char __user *userbuf,
871                                  size_t count, loff_t *ppos)
872 {
873         struct ath5k_hw *ah = file->private_data;
874         char buf[20];
875
876         count = min_t(size_t, count, sizeof(buf) - 1);
877         if (copy_from_user(buf, userbuf, count))
878                 return -EFAULT;
879
880         buf[count] = '\0';
881         if (strncmp(buf, "start", 5) == 0)
882                 ieee80211_wake_queues(ah->hw);
883         else if (strncmp(buf, "stop", 4) == 0)
884                 ieee80211_stop_queues(ah->hw);
885
886         return count;
887 }
888
889
890 static const struct file_operations fops_queue = {
891         .read = read_file_queue,
892         .write = write_file_queue,
893         .open = simple_open,
894         .owner = THIS_MODULE,
895         .llseek = default_llseek,
896 };
897
898 /* debugfs: eeprom */
899
900 struct eeprom_private {
901         u16 *buf;
902         int len;
903 };
904
905 static int open_file_eeprom(struct inode *inode, struct file *file)
906 {
907         struct eeprom_private *ep;
908         struct ath5k_hw *ah = inode->i_private;
909         bool res;
910         int i, ret;
911         u32 eesize;
912         u16 val, *buf;
913
914         /* Get eeprom size */
915
916         res = ath5k_hw_nvram_read(ah, AR5K_EEPROM_SIZE_UPPER, &val);
917         if (!res)
918                 return -EACCES;
919
920         if (val == 0) {
921                 eesize = AR5K_EEPROM_INFO_MAX + AR5K_EEPROM_INFO_BASE;
922         } else {
923                 eesize = (val & AR5K_EEPROM_SIZE_UPPER_MASK) <<
924                         AR5K_EEPROM_SIZE_ENDLOC_SHIFT;
925                 ath5k_hw_nvram_read(ah, AR5K_EEPROM_SIZE_LOWER, &val);
926                 eesize = eesize | val;
927         }
928
929         if (eesize > 4096)
930                 return -EINVAL;
931
932         /* Create buffer and read in eeprom */
933
934         buf = vmalloc(eesize);
935         if (!buf) {
936                 ret = -ENOMEM;
937                 goto err;
938         }
939
940         for (i = 0; i < eesize; ++i) {
941                 AR5K_EEPROM_READ(i, val);
942                 buf[i] = val;
943         }
944
945         /* Create private struct and assign to file */
946
947         ep = kmalloc(sizeof(*ep), GFP_KERNEL);
948         if (!ep) {
949                 ret = -ENOMEM;
950                 goto freebuf;
951         }
952
953         ep->buf = buf;
954         ep->len = i;
955
956         file->private_data = (void *)ep;
957
958         return 0;
959
960 freebuf:
961         vfree(buf);
962 err:
963         return ret;
964
965 }
966
967 static ssize_t read_file_eeprom(struct file *file, char __user *user_buf,
968                                    size_t count, loff_t *ppos)
969 {
970         struct eeprom_private *ep = file->private_data;
971
972         return simple_read_from_buffer(user_buf, count, ppos, ep->buf, ep->len);
973 }
974
975 static int release_file_eeprom(struct inode *inode, struct file *file)
976 {
977         struct eeprom_private *ep = file->private_data;
978
979         vfree(ep->buf);
980         kfree(ep);
981
982         return 0;
983 }
984
985 static const struct file_operations fops_eeprom = {
986         .open = open_file_eeprom,
987         .read = read_file_eeprom,
988         .release = release_file_eeprom,
989         .owner = THIS_MODULE,
990 };
991
992
993 void
994 ath5k_debug_init_device(struct ath5k_hw *ah)
995 {
996         struct dentry *phydir;
997
998         ah->debug.level = ath5k_debug;
999
1000         phydir = debugfs_create_dir("ath5k", ah->hw->wiphy->debugfsdir);
1001         if (!phydir)
1002                 return;
1003
1004         debugfs_create_file("debug", S_IWUSR | S_IRUSR, phydir, ah,
1005                             &fops_debug);
1006
1007         debugfs_create_file("registers", S_IRUSR, phydir, ah, &fops_registers);
1008
1009         debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, ah,
1010                             &fops_beacon);
1011
1012         debugfs_create_file("reset", S_IWUSR, phydir, ah, &fops_reset);
1013
1014         debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, ah,
1015                             &fops_antenna);
1016
1017         debugfs_create_file("misc", S_IRUSR, phydir, ah, &fops_misc);
1018
1019         debugfs_create_file("eeprom", S_IRUSR, phydir, ah, &fops_eeprom);
1020
1021         debugfs_create_file("frameerrors", S_IWUSR | S_IRUSR, phydir, ah,
1022                             &fops_frameerrors);
1023
1024         debugfs_create_file("ani", S_IWUSR | S_IRUSR, phydir, ah, &fops_ani);
1025
1026         debugfs_create_file("queue", S_IWUSR | S_IRUSR, phydir, ah,
1027                             &fops_queue);
1028
1029         debugfs_create_bool("32khz_clock", S_IWUSR | S_IRUSR, phydir,
1030                             &ah->ah_use_32khz_clock);
1031 }
1032
1033 /* functions used in other places */
1034
1035 void
1036 ath5k_debug_dump_bands(struct ath5k_hw *ah)
1037 {
1038         unsigned int b, i;
1039
1040         if (likely(!(ah->debug.level & ATH5K_DEBUG_DUMPBANDS)))
1041                 return;
1042
1043         BUG_ON(!ah->sbands);
1044
1045         for (b = 0; b < IEEE80211_NUM_BANDS; b++) {
1046                 struct ieee80211_supported_band *band = &ah->sbands[b];
1047                 char bname[6];
1048                 switch (band->band) {
1049                 case IEEE80211_BAND_2GHZ:
1050                         strcpy(bname, "2 GHz");
1051                         break;
1052                 case IEEE80211_BAND_5GHZ:
1053                         strcpy(bname, "5 GHz");
1054                         break;
1055                 default:
1056                         printk(KERN_DEBUG "Band not supported: %d\n",
1057                                 band->band);
1058                         return;
1059                 }
1060                 printk(KERN_DEBUG "Band %s: channels %d, rates %d\n", bname,
1061                                 band->n_channels, band->n_bitrates);
1062                 printk(KERN_DEBUG " channels:\n");
1063                 for (i = 0; i < band->n_channels; i++)
1064                         printk(KERN_DEBUG "  %3d %d %.4x %.4x\n",
1065                                         ieee80211_frequency_to_channel(
1066                                                 band->channels[i].center_freq),
1067                                         band->channels[i].center_freq,
1068                                         band->channels[i].hw_value,
1069                                         band->channels[i].flags);
1070                 printk(KERN_DEBUG " rates:\n");
1071                 for (i = 0; i < band->n_bitrates; i++)
1072                         printk(KERN_DEBUG "  %4d %.4x %.4x %.4x\n",
1073                                         band->bitrates[i].bitrate,
1074                                         band->bitrates[i].hw_value,
1075                                         band->bitrates[i].flags,
1076                                         band->bitrates[i].hw_value_short);
1077         }
1078 }
1079
1080 static inline void
1081 ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done,
1082                        struct ath5k_rx_status *rs)
1083 {
1084         struct ath5k_desc *ds = bf->desc;
1085         struct ath5k_hw_all_rx_desc *rd = &ds->ud.ds_rx;
1086
1087         printk(KERN_DEBUG "R (%p %llx) %08x %08x %08x %08x %08x %08x %c\n",
1088                 ds, (unsigned long long)bf->daddr,
1089                 ds->ds_link, ds->ds_data,
1090                 rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1,
1091                 rd->rx_stat.rx_status_0, rd->rx_stat.rx_status_1,
1092                 !done ? ' ' : (rs->rs_status == 0) ? '*' : '!');
1093 }
1094
1095 void
1096 ath5k_debug_printrxbuffs(struct ath5k_hw *ah)
1097 {
1098         struct ath5k_desc *ds;
1099         struct ath5k_buf *bf;
1100         struct ath5k_rx_status rs = {};
1101         int status;
1102
1103         if (likely(!(ah->debug.level & ATH5K_DEBUG_DESC)))
1104                 return;
1105
1106         printk(KERN_DEBUG "rxdp %x, rxlink %p\n",
1107                 ath5k_hw_get_rxdp(ah), ah->rxlink);
1108
1109         spin_lock_bh(&ah->rxbuflock);
1110         list_for_each_entry(bf, &ah->rxbuf, list) {
1111                 ds = bf->desc;
1112                 status = ah->ah_proc_rx_desc(ah, ds, &rs);
1113                 if (!status)
1114                         ath5k_debug_printrxbuf(bf, status == 0, &rs);
1115         }
1116         spin_unlock_bh(&ah->rxbuflock);
1117 }
1118
1119 void
1120 ath5k_debug_printtxbuf(struct ath5k_hw *ah, struct ath5k_buf *bf)
1121 {
1122         struct ath5k_desc *ds = bf->desc;
1123         struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212;
1124         struct ath5k_tx_status ts = {};
1125         int done;
1126
1127         if (likely(!(ah->debug.level & ATH5K_DEBUG_DESC)))
1128                 return;
1129
1130         done = ah->ah_proc_tx_desc(ah, bf->desc, &ts);
1131
1132         printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x "
1133                 "%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link,
1134                 ds->ds_data, td->tx_ctl.tx_control_0, td->tx_ctl.tx_control_1,
1135                 td->tx_ctl.tx_control_2, td->tx_ctl.tx_control_3,
1136                 td->tx_stat.tx_status_0, td->tx_stat.tx_status_1,
1137                 done ? ' ' : (ts.ts_status == 0) ? '*' : '!');
1138 }