]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/net/wireless/ath/ath5k/debug.c
wireless: Print wiphy name in sysfs.
[net-next-2.6.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 #include "base.h"
62 #include "debug.h"
63 #include "../debug.h"
64
65 static unsigned int ath5k_debug;
66 module_param_named(debug, ath5k_debug, uint, 0);
67
68
69 #ifdef CONFIG_ATH5K_DEBUG
70
71 #include <linux/seq_file.h>
72 #include "reg.h"
73 #include "ani.h"
74
75 static struct dentry *ath5k_global_debugfs;
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_softc *sc = seq->private;
164         struct reg *r = p;
165         seq_printf(seq, "%-25s0x%08x\n", r->name,
166                 ath5k_hw_reg_read(sc->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_softc *sc = file->private_data;
204         struct ath5k_hw *ah = sc->ah;
205         char buf[500];
206         unsigned int len = 0;
207         unsigned int v;
208         u64 tsf;
209
210         v = ath5k_hw_reg_read(sc->ah, AR5K_BEACON);
211         len += snprintf(buf+len, sizeof(buf)-len,
212                 "%-24s0x%08x\tintval: %d\tTIM: 0x%x\n",
213                 "AR5K_BEACON", v, v & AR5K_BEACON_PERIOD,
214                 (v & AR5K_BEACON_TIM) >> AR5K_BEACON_TIM_S);
215
216         len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n",
217                 "AR5K_LAST_TSTP", ath5k_hw_reg_read(sc->ah, AR5K_LAST_TSTP));
218
219         len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n\n",
220                 "AR5K_BEACON_CNT", ath5k_hw_reg_read(sc->ah, AR5K_BEACON_CNT));
221
222         v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER0);
223         len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
224                 "AR5K_TIMER0 (TBTT)", v, v);
225
226         v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER1);
227         len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
228                 "AR5K_TIMER1 (DMA)", v, v >> 3);
229
230         v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER2);
231         len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
232                 "AR5K_TIMER2 (SWBA)", v, v >> 3);
233
234         v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER3);
235         len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
236                 "AR5K_TIMER3 (ATIM)", v, v);
237
238         tsf = ath5k_hw_get_tsf64(sc->ah);
239         len += snprintf(buf+len, sizeof(buf)-len,
240                 "TSF\t\t0x%016llx\tTU: %08x\n",
241                 (unsigned long long)tsf, TSF_TO_TU(tsf));
242
243         if (len > sizeof(buf))
244                 len = sizeof(buf);
245
246         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
247 }
248
249 static ssize_t write_file_beacon(struct file *file,
250                                  const char __user *userbuf,
251                                  size_t count, loff_t *ppos)
252 {
253         struct ath5k_softc *sc = file->private_data;
254         struct ath5k_hw *ah = sc->ah;
255         char buf[20];
256
257         if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
258                 return -EFAULT;
259
260         if (strncmp(buf, "disable", 7) == 0) {
261                 AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
262                 printk(KERN_INFO "debugfs disable beacons\n");
263         } else if (strncmp(buf, "enable", 6) == 0) {
264                 AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
265                 printk(KERN_INFO "debugfs enable beacons\n");
266         }
267         return count;
268 }
269
270 static const struct file_operations fops_beacon = {
271         .read = read_file_beacon,
272         .write = write_file_beacon,
273         .open = ath5k_debugfs_open,
274         .owner = THIS_MODULE,
275 };
276
277
278 /* debugfs: reset */
279
280 static ssize_t write_file_reset(struct file *file,
281                                  const char __user *userbuf,
282                                  size_t count, loff_t *ppos)
283 {
284         struct ath5k_softc *sc = file->private_data;
285         ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "debug file triggered reset\n");
286         ieee80211_queue_work(sc->hw, &sc->reset_work);
287         return count;
288 }
289
290 static const struct file_operations fops_reset = {
291         .write = write_file_reset,
292         .open = ath5k_debugfs_open,
293         .owner = THIS_MODULE,
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_DUMP_RX,  "dumprx",       "print received skb content" },
313         { ATH5K_DEBUG_DUMP_TX,  "dumptx",       "print transmit skb content" },
314         { ATH5K_DEBUG_DUMPBANDS, "dumpbands",   "dump bands" },
315         { ATH5K_DEBUG_ANI,      "ani",          "adaptive noise immunity" },
316         { ATH5K_DEBUG_DESC,     "desc",         "descriptor chains" },
317         { ATH5K_DEBUG_ANY,      "all",          "show all debug levels" },
318 };
319
320 static ssize_t read_file_debug(struct file *file, char __user *user_buf,
321                                    size_t count, loff_t *ppos)
322 {
323         struct ath5k_softc *sc = file->private_data;
324         char buf[700];
325         unsigned int len = 0;
326         unsigned int i;
327
328         len += snprintf(buf+len, sizeof(buf)-len,
329                 "DEBUG LEVEL: 0x%08x\n\n", sc->debug.level);
330
331         for (i = 0; i < ARRAY_SIZE(dbg_info) - 1; i++) {
332                 len += snprintf(buf+len, sizeof(buf)-len,
333                         "%10s %c 0x%08x - %s\n", dbg_info[i].name,
334                         sc->debug.level & dbg_info[i].level ? '+' : ' ',
335                         dbg_info[i].level, dbg_info[i].desc);
336         }
337         len += snprintf(buf+len, sizeof(buf)-len,
338                 "%10s %c 0x%08x - %s\n", dbg_info[i].name,
339                 sc->debug.level == dbg_info[i].level ? '+' : ' ',
340                 dbg_info[i].level, dbg_info[i].desc);
341
342         if (len > sizeof(buf))
343                 len = sizeof(buf);
344
345         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
346 }
347
348 static ssize_t write_file_debug(struct file *file,
349                                  const char __user *userbuf,
350                                  size_t count, loff_t *ppos)
351 {
352         struct ath5k_softc *sc = file->private_data;
353         unsigned int i;
354         char buf[20];
355
356         if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
357                 return -EFAULT;
358
359         for (i = 0; i < ARRAY_SIZE(dbg_info); i++) {
360                 if (strncmp(buf, dbg_info[i].name,
361                                         strlen(dbg_info[i].name)) == 0) {
362                         sc->debug.level ^= dbg_info[i].level; /* toggle bit */
363                         break;
364                 }
365         }
366         return count;
367 }
368
369 static const struct file_operations fops_debug = {
370         .read = read_file_debug,
371         .write = write_file_debug,
372         .open = ath5k_debugfs_open,
373         .owner = THIS_MODULE,
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_softc *sc = 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                 sc->ah->ah_ant_mode);
390         len += snprintf(buf+len, sizeof(buf)-len, "default antenna\t%d\n",
391                 sc->ah->ah_def_ant);
392         len += snprintf(buf+len, sizeof(buf)-len, "tx antenna\t%d\n",
393                 sc->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(sc->stats.antenna_rx); i++) {
397                 len += snprintf(buf+len, sizeof(buf)-len,
398                         "[antenna %d]\t%d\t%d\n",
399                         i, sc->stats.antenna_rx[i], sc->stats.antenna_tx[i]);
400         }
401         len += snprintf(buf+len, sizeof(buf)-len, "[invalid]\t%d\t%d\n",
402                         sc->stats.antenna_rx[0], sc->stats.antenna_tx[0]);
403
404         v = ath5k_hw_reg_read(sc->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(sc->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(sc->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(sc->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(sc->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(sc->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(sc->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_softc *sc = 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(sc->ah, AR5K_ANTMODE_DEFAULT);
463                 printk(KERN_INFO "ath5k debug: enable diversity\n");
464         } else if (strncmp(buf, "fixed-a", 7) == 0) {
465                 ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_A);
466                 printk(KERN_INFO "ath5k debugfs: fixed antenna A\n");
467         } else if (strncmp(buf, "fixed-b", 7) == 0) {
468                 ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_B);
469                 printk(KERN_INFO "ath5k debug: fixed antenna B\n");
470         } else if (strncmp(buf, "clear", 5) == 0) {
471                 for (i = 0; i < ARRAY_SIZE(sc->stats.antenna_rx); i++) {
472                         sc->stats.antenna_rx[i] = 0;
473                         sc->stats.antenna_tx[i] = 0;
474                 }
475                 printk(KERN_INFO "ath5k 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 };
486
487 /* debugfs: misc */
488
489 static ssize_t read_file_misc(struct file *file, char __user *user_buf,
490                                    size_t count, loff_t *ppos)
491 {
492         struct ath5k_softc *sc = file->private_data;
493         char buf[700];
494         unsigned int len = 0;
495         u32 filt = ath5k_hw_get_rx_filter(sc->ah);
496         const char *tmp;
497
498         len += snprintf(buf+len, sizeof(buf)-len, "bssid-mask: %pM\n",
499                         sc->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\n");
526         else
527                 len += snprintf(buf+len, sizeof(buf)-len, "\n");
528
529         tmp = ath_opmode_to_string(sc->opmode);
530         if (tmp)
531                 len += snprintf(buf+len, sizeof(buf)-len, "opmode: %s\n",
532                                 tmp);
533         else
534                 len += snprintf(buf+len, sizeof(buf)-len,
535                                 "opmode: UNKNOWN-%i\n", sc->opmode);
536
537         if (len > sizeof(buf))
538                 len = sizeof(buf);
539
540         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
541 }
542
543 static const struct file_operations fops_misc = {
544         .read = read_file_misc,
545         .open = ath5k_debugfs_open,
546         .owner = THIS_MODULE,
547 };
548
549
550 /* debugfs: frameerrors */
551
552 static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf,
553                                    size_t count, loff_t *ppos)
554 {
555         struct ath5k_softc *sc = file->private_data;
556         struct ath5k_statistics *st = &sc->stats;
557         char buf[700];
558         unsigned int len = 0;
559         int i;
560
561         len += snprintf(buf+len, sizeof(buf)-len,
562                         "RX\n---------------------\n");
563         len += snprintf(buf+len, sizeof(buf)-len, "CRC\t%d\t(%d%%)\n",
564                         st->rxerr_crc,
565                         st->rx_all_count > 0 ?
566                                 st->rxerr_crc*100/st->rx_all_count : 0);
567         len += snprintf(buf+len, sizeof(buf)-len, "PHY\t%d\t(%d%%)\n",
568                         st->rxerr_phy,
569                         st->rx_all_count > 0 ?
570                                 st->rxerr_phy*100/st->rx_all_count : 0);
571         for (i = 0; i < 32; i++) {
572                 if (st->rxerr_phy_code[i])
573                         len += snprintf(buf+len, sizeof(buf)-len,
574                                 " phy_err[%d]\t%d\n",
575                                 i, st->rxerr_phy_code[i]);
576         }
577
578         len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n",
579                         st->rxerr_fifo,
580                         st->rx_all_count > 0 ?
581                                 st->rxerr_fifo*100/st->rx_all_count : 0);
582         len += snprintf(buf+len, sizeof(buf)-len, "decrypt\t%d\t(%d%%)\n",
583                         st->rxerr_decrypt,
584                         st->rx_all_count > 0 ?
585                                 st->rxerr_decrypt*100/st->rx_all_count : 0);
586         len += snprintf(buf+len, sizeof(buf)-len, "MIC\t%d\t(%d%%)\n",
587                         st->rxerr_mic,
588                         st->rx_all_count > 0 ?
589                                 st->rxerr_mic*100/st->rx_all_count : 0);
590         len += snprintf(buf+len, sizeof(buf)-len, "process\t%d\t(%d%%)\n",
591                         st->rxerr_proc,
592                         st->rx_all_count > 0 ?
593                                 st->rxerr_proc*100/st->rx_all_count : 0);
594         len += snprintf(buf+len, sizeof(buf)-len, "jumbo\t%d\t(%d%%)\n",
595                         st->rxerr_jumbo,
596                         st->rx_all_count > 0 ?
597                                 st->rxerr_jumbo*100/st->rx_all_count : 0);
598         len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%d]\n",
599                         st->rx_all_count);
600         len += snprintf(buf+len, sizeof(buf)-len, "RX-all-bytes\t%d\n",
601                         st->rx_bytes_count);
602
603         len += snprintf(buf+len, sizeof(buf)-len,
604                         "\nTX\n---------------------\n");
605         len += snprintf(buf+len, sizeof(buf)-len, "retry\t%d\t(%d%%)\n",
606                         st->txerr_retry,
607                         st->tx_all_count > 0 ?
608                                 st->txerr_retry*100/st->tx_all_count : 0);
609         len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n",
610                         st->txerr_fifo,
611                         st->tx_all_count > 0 ?
612                                 st->txerr_fifo*100/st->tx_all_count : 0);
613         len += snprintf(buf+len, sizeof(buf)-len, "filter\t%d\t(%d%%)\n",
614                         st->txerr_filt,
615                         st->tx_all_count > 0 ?
616                                 st->txerr_filt*100/st->tx_all_count : 0);
617         len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%d]\n",
618                         st->tx_all_count);
619         len += snprintf(buf+len, sizeof(buf)-len, "TX-all-bytes\t%d\n",
620                         st->tx_bytes_count);
621
622         if (len > sizeof(buf))
623                 len = sizeof(buf);
624
625         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
626 }
627
628 static ssize_t write_file_frameerrors(struct file *file,
629                                  const char __user *userbuf,
630                                  size_t count, loff_t *ppos)
631 {
632         struct ath5k_softc *sc = file->private_data;
633         struct ath5k_statistics *st = &sc->stats;
634         char buf[20];
635
636         if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
637                 return -EFAULT;
638
639         if (strncmp(buf, "clear", 5) == 0) {
640                 st->rxerr_crc = 0;
641                 st->rxerr_phy = 0;
642                 st->rxerr_fifo = 0;
643                 st->rxerr_decrypt = 0;
644                 st->rxerr_mic = 0;
645                 st->rxerr_proc = 0;
646                 st->rxerr_jumbo = 0;
647                 st->rx_all_count = 0;
648                 st->txerr_retry = 0;
649                 st->txerr_fifo = 0;
650                 st->txerr_filt = 0;
651                 st->tx_all_count = 0;
652                 printk(KERN_INFO "ath5k debug: cleared frameerrors stats\n");
653         }
654         return count;
655 }
656
657 static const struct file_operations fops_frameerrors = {
658         .read = read_file_frameerrors,
659         .write = write_file_frameerrors,
660         .open = ath5k_debugfs_open,
661         .owner = THIS_MODULE,
662 };
663
664
665 /* debugfs: ani */
666
667 static ssize_t read_file_ani(struct file *file, char __user *user_buf,
668                                    size_t count, loff_t *ppos)
669 {
670         struct ath5k_softc *sc = file->private_data;
671         struct ath5k_statistics *st = &sc->stats;
672         struct ath5k_ani_state *as = &sc->ani_state;
673
674         char buf[700];
675         unsigned int len = 0;
676
677         len += snprintf(buf+len, sizeof(buf)-len,
678                         "HW has PHY error counters:\t%s\n",
679                         sc->ah->ah_capabilities.cap_has_phyerr_counters ?
680                         "yes" : "no");
681         len += snprintf(buf+len, sizeof(buf)-len,
682                         "HW max spur immunity level:\t%d\n",
683                         as->max_spur_level);
684         len += snprintf(buf+len, sizeof(buf)-len,
685                 "\nANI state\n--------------------------------------------\n");
686         len += snprintf(buf+len, sizeof(buf)-len, "operating mode:\t\t\t");
687         switch (as->ani_mode) {
688         case ATH5K_ANI_MODE_OFF:
689                 len += snprintf(buf+len, sizeof(buf)-len, "OFF\n");
690                 break;
691         case ATH5K_ANI_MODE_MANUAL_LOW:
692                 len += snprintf(buf+len, sizeof(buf)-len,
693                         "MANUAL LOW\n");
694                 break;
695         case ATH5K_ANI_MODE_MANUAL_HIGH:
696                 len += snprintf(buf+len, sizeof(buf)-len,
697                         "MANUAL HIGH\n");
698                 break;
699         case ATH5K_ANI_MODE_AUTO:
700                 len += snprintf(buf+len, sizeof(buf)-len, "AUTO\n");
701                 break;
702         default:
703                 len += snprintf(buf+len, sizeof(buf)-len,
704                         "??? (not good)\n");
705                 break;
706         }
707         len += snprintf(buf+len, sizeof(buf)-len,
708                         "noise immunity level:\t\t%d\n",
709                         as->noise_imm_level);
710         len += snprintf(buf+len, sizeof(buf)-len,
711                         "spur immunity level:\t\t%d\n",
712                         as->spur_level);
713         len += snprintf(buf+len, sizeof(buf)-len, "firstep level:\t\t\t%d\n",
714                         as->firstep_level);
715         len += snprintf(buf+len, sizeof(buf)-len,
716                         "OFDM weak signal detection:\t%s\n",
717                         as->ofdm_weak_sig ? "on" : "off");
718         len += snprintf(buf+len, sizeof(buf)-len,
719                         "CCK weak signal detection:\t%s\n",
720                         as->cck_weak_sig ? "on" : "off");
721
722         len += snprintf(buf+len, sizeof(buf)-len,
723                         "\nMIB INTERRUPTS:\t\t%u\n",
724                         st->mib_intr);
725         len += snprintf(buf+len, sizeof(buf)-len,
726                         "beacon RSSI average:\t%d\n",
727                         sc->ah->ah_beacon_rssi_avg.avg);
728
729 #define CC_PRINT(_struct, _field) \
730         _struct._field, \
731         _struct.cycles > 0 ? \
732         _struct._field*100/_struct.cycles : 0
733
734         len += snprintf(buf+len, sizeof(buf)-len, "profcnt tx\t\t%u\t(%d%%)\n",
735                         CC_PRINT(as->last_cc, tx_frame));
736         len += snprintf(buf+len, sizeof(buf)-len, "profcnt rx\t\t%u\t(%d%%)\n",
737                         CC_PRINT(as->last_cc, rx_frame));
738         len += snprintf(buf+len, sizeof(buf)-len, "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(sc->ah, AR5K_PHYERR_CNT1),
757                         ATH5K_ANI_OFDM_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX -
758                         ath5k_hw_reg_read(sc->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(sc->ah, AR5K_PHYERR_CNT2),
762                         ATH5K_ANI_CCK_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX -
763                         ath5k_hw_reg_read(sc->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_softc *sc = file->private_data;
776         char buf[20];
777
778         if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
779                 return -EFAULT;
780
781         if (strncmp(buf, "sens-low", 8) == 0) {
782                 ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_MANUAL_HIGH);
783         } else if (strncmp(buf, "sens-high", 9) == 0) {
784                 ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_MANUAL_LOW);
785         } else if (strncmp(buf, "ani-off", 7) == 0) {
786                 ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_OFF);
787         } else if (strncmp(buf, "ani-on", 6) == 0) {
788                 ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_AUTO);
789         } else if (strncmp(buf, "noise-low", 9) == 0) {
790                 ath5k_ani_set_noise_immunity_level(sc->ah, 0);
791         } else if (strncmp(buf, "noise-high", 10) == 0) {
792                 ath5k_ani_set_noise_immunity_level(sc->ah,
793                                                    ATH5K_ANI_MAX_NOISE_IMM_LVL);
794         } else if (strncmp(buf, "spur-low", 8) == 0) {
795                 ath5k_ani_set_spur_immunity_level(sc->ah, 0);
796         } else if (strncmp(buf, "spur-high", 9) == 0) {
797                 ath5k_ani_set_spur_immunity_level(sc->ah,
798                                                   sc->ani_state.max_spur_level);
799         } else if (strncmp(buf, "fir-low", 7) == 0) {
800                 ath5k_ani_set_firstep_level(sc->ah, 0);
801         } else if (strncmp(buf, "fir-high", 8) == 0) {
802                 ath5k_ani_set_firstep_level(sc->ah, ATH5K_ANI_MAX_FIRSTEP_LVL);
803         } else if (strncmp(buf, "ofdm-off", 8) == 0) {
804                 ath5k_ani_set_ofdm_weak_signal_detection(sc->ah, false);
805         } else if (strncmp(buf, "ofdm-on", 7) == 0) {
806                 ath5k_ani_set_ofdm_weak_signal_detection(sc->ah, true);
807         } else if (strncmp(buf, "cck-off", 7) == 0) {
808                 ath5k_ani_set_cck_weak_signal_detection(sc->ah, false);
809         } else if (strncmp(buf, "cck-on", 6) == 0) {
810                 ath5k_ani_set_cck_weak_signal_detection(sc->ah, true);
811         }
812         return count;
813 }
814
815 static const struct file_operations fops_ani = {
816         .read = read_file_ani,
817         .write = write_file_ani,
818         .open = ath5k_debugfs_open,
819         .owner = THIS_MODULE,
820 };
821
822
823 /* debugfs: queues etc */
824
825 static ssize_t read_file_queue(struct file *file, char __user *user_buf,
826                                    size_t count, loff_t *ppos)
827 {
828         struct ath5k_softc *sc = file->private_data;
829         char buf[700];
830         unsigned int len = 0;
831
832         struct ath5k_txq *txq;
833         struct ath5k_buf *bf, *bf0;
834         int i, n;
835
836         len += snprintf(buf+len, sizeof(buf)-len,
837                         "available txbuffers: %d\n", sc->txbuf_len);
838
839         for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) {
840                 txq = &sc->txqs[i];
841
842                 len += snprintf(buf+len, sizeof(buf)-len,
843                         "%02d: %ssetup\n", i, txq->setup ? "" : "not ");
844
845                 if (!txq->setup)
846                         continue;
847
848                 n = 0;
849                 spin_lock_bh(&txq->lock);
850                 list_for_each_entry_safe(bf, bf0, &txq->q, list)
851                         n++;
852                 spin_unlock_bh(&txq->lock);
853
854                 len += snprintf(buf+len, sizeof(buf)-len,
855                                 "  len: %d bufs: %d\n", txq->txq_len, n);
856                 len += snprintf(buf+len, sizeof(buf)-len,
857                                 "  stuck: %d\n", txq->txq_stuck);
858         }
859
860         if (len > sizeof(buf))
861                 len = sizeof(buf);
862
863         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
864 }
865
866 static ssize_t write_file_queue(struct file *file,
867                                  const char __user *userbuf,
868                                  size_t count, loff_t *ppos)
869 {
870         struct ath5k_softc *sc = file->private_data;
871         char buf[20];
872
873         if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
874                 return -EFAULT;
875
876         if (strncmp(buf, "start", 5) == 0)
877                 ieee80211_wake_queues(sc->hw);
878         else if (strncmp(buf, "stop", 4) == 0)
879                 ieee80211_stop_queues(sc->hw);
880
881         return count;
882 }
883
884
885 static const struct file_operations fops_queue = {
886         .read = read_file_queue,
887         .write = write_file_queue,
888         .open = ath5k_debugfs_open,
889         .owner = THIS_MODULE,
890 };
891
892
893 /* init */
894
895 void
896 ath5k_debug_init(void)
897 {
898         ath5k_global_debugfs = debugfs_create_dir("ath5k", NULL);
899 }
900
901 void
902 ath5k_debug_init_device(struct ath5k_softc *sc)
903 {
904         sc->debug.level = ath5k_debug;
905
906         sc->debug.debugfs_phydir = debugfs_create_dir(wiphy_name(sc->hw->wiphy),
907                                 ath5k_global_debugfs);
908
909         sc->debug.debugfs_debug = debugfs_create_file("debug",
910                                 S_IWUSR | S_IRUSR,
911                                 sc->debug.debugfs_phydir, sc, &fops_debug);
912
913         sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUSR,
914                                 sc->debug.debugfs_phydir, sc, &fops_registers);
915
916         sc->debug.debugfs_beacon = debugfs_create_file("beacon",
917                                 S_IWUSR | S_IRUSR,
918                                 sc->debug.debugfs_phydir, sc, &fops_beacon);
919
920         sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR,
921                                 sc->debug.debugfs_phydir, sc, &fops_reset);
922
923         sc->debug.debugfs_antenna = debugfs_create_file("antenna",
924                                 S_IWUSR | S_IRUSR,
925                                 sc->debug.debugfs_phydir, sc, &fops_antenna);
926
927         sc->debug.debugfs_misc = debugfs_create_file("misc",
928                                 S_IRUSR,
929                                 sc->debug.debugfs_phydir, sc, &fops_misc);
930
931         sc->debug.debugfs_frameerrors = debugfs_create_file("frameerrors",
932                                 S_IWUSR | S_IRUSR,
933                                 sc->debug.debugfs_phydir, sc,
934                                 &fops_frameerrors);
935
936         sc->debug.debugfs_ani = debugfs_create_file("ani",
937                                 S_IWUSR | S_IRUSR,
938                                 sc->debug.debugfs_phydir, sc,
939                                 &fops_ani);
940
941         sc->debug.debugfs_queue = debugfs_create_file("queue",
942                                 S_IWUSR | S_IRUSR,
943                                 sc->debug.debugfs_phydir, sc,
944                                 &fops_queue);
945 }
946
947 void
948 ath5k_debug_finish(void)
949 {
950         debugfs_remove(ath5k_global_debugfs);
951 }
952
953 void
954 ath5k_debug_finish_device(struct ath5k_softc *sc)
955 {
956         debugfs_remove(sc->debug.debugfs_debug);
957         debugfs_remove(sc->debug.debugfs_registers);
958         debugfs_remove(sc->debug.debugfs_beacon);
959         debugfs_remove(sc->debug.debugfs_reset);
960         debugfs_remove(sc->debug.debugfs_antenna);
961         debugfs_remove(sc->debug.debugfs_misc);
962         debugfs_remove(sc->debug.debugfs_frameerrors);
963         debugfs_remove(sc->debug.debugfs_ani);
964         debugfs_remove(sc->debug.debugfs_queue);
965         debugfs_remove(sc->debug.debugfs_phydir);
966 }
967
968
969 /* functions used in other places */
970
971 void
972 ath5k_debug_dump_bands(struct ath5k_softc *sc)
973 {
974         unsigned int b, i;
975
976         if (likely(!(sc->debug.level & ATH5K_DEBUG_DUMPBANDS)))
977                 return;
978
979         BUG_ON(!sc->sbands);
980
981         for (b = 0; b < IEEE80211_NUM_BANDS; b++) {
982                 struct ieee80211_supported_band *band = &sc->sbands[b];
983                 char bname[6];
984                 switch (band->band) {
985                 case IEEE80211_BAND_2GHZ:
986                         strcpy(bname, "2 GHz");
987                         break;
988                 case IEEE80211_BAND_5GHZ:
989                         strcpy(bname, "5 GHz");
990                         break;
991                 default:
992                         printk(KERN_DEBUG "Band not supported: %d\n",
993                                 band->band);
994                         return;
995                 }
996                 printk(KERN_DEBUG "Band %s: channels %d, rates %d\n", bname,
997                                 band->n_channels, band->n_bitrates);
998                 printk(KERN_DEBUG " channels:\n");
999                 for (i = 0; i < band->n_channels; i++)
1000                         printk(KERN_DEBUG "  %3d %d %.4x %.4x\n",
1001                                         ieee80211_frequency_to_channel(
1002                                                 band->channels[i].center_freq),
1003                                         band->channels[i].center_freq,
1004                                         band->channels[i].hw_value,
1005                                         band->channels[i].flags);
1006                 printk(KERN_DEBUG " rates:\n");
1007                 for (i = 0; i < band->n_bitrates; i++)
1008                         printk(KERN_DEBUG "  %4d %.4x %.4x %.4x\n",
1009                                         band->bitrates[i].bitrate,
1010                                         band->bitrates[i].hw_value,
1011                                         band->bitrates[i].flags,
1012                                         band->bitrates[i].hw_value_short);
1013         }
1014 }
1015
1016 static inline void
1017 ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done,
1018                        struct ath5k_rx_status *rs)
1019 {
1020         struct ath5k_desc *ds = bf->desc;
1021         struct ath5k_hw_all_rx_desc *rd = &ds->ud.ds_rx;
1022
1023         printk(KERN_DEBUG "R (%p %llx) %08x %08x %08x %08x %08x %08x %c\n",
1024                 ds, (unsigned long long)bf->daddr,
1025                 ds->ds_link, ds->ds_data,
1026                 rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1,
1027                 rd->rx_stat.rx_status_0, rd->rx_stat.rx_status_1,
1028                 !done ? ' ' : (rs->rs_status == 0) ? '*' : '!');
1029 }
1030
1031 void
1032 ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah)
1033 {
1034         struct ath5k_desc *ds;
1035         struct ath5k_buf *bf;
1036         struct ath5k_rx_status rs = {};
1037         int status;
1038
1039         if (likely(!(sc->debug.level & ATH5K_DEBUG_DESC)))
1040                 return;
1041
1042         printk(KERN_DEBUG "rxdp %x, rxlink %p\n",
1043                 ath5k_hw_get_rxdp(ah), sc->rxlink);
1044
1045         spin_lock_bh(&sc->rxbuflock);
1046         list_for_each_entry(bf, &sc->rxbuf, list) {
1047                 ds = bf->desc;
1048                 status = ah->ah_proc_rx_desc(ah, ds, &rs);
1049                 if (!status)
1050                         ath5k_debug_printrxbuf(bf, status == 0, &rs);
1051         }
1052         spin_unlock_bh(&sc->rxbuflock);
1053 }
1054
1055 void
1056 ath5k_debug_dump_skb(struct ath5k_softc *sc,
1057                         struct sk_buff *skb, const char *prefix, int tx)
1058 {
1059         char buf[16];
1060
1061         if (likely(!((tx && (sc->debug.level & ATH5K_DEBUG_DUMP_TX)) ||
1062                      (!tx && (sc->debug.level & ATH5K_DEBUG_DUMP_RX)))))
1063                 return;
1064
1065         snprintf(buf, sizeof(buf), "%s %s", wiphy_name(sc->hw->wiphy), prefix);
1066
1067         print_hex_dump_bytes(buf, DUMP_PREFIX_NONE, skb->data,
1068                 min(200U, skb->len));
1069
1070         printk(KERN_DEBUG "\n");
1071 }
1072
1073 void
1074 ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf)
1075 {
1076         struct ath5k_desc *ds = bf->desc;
1077         struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212;
1078         struct ath5k_tx_status ts = {};
1079         int done;
1080
1081         if (likely(!(sc->debug.level & ATH5K_DEBUG_DESC)))
1082                 return;
1083
1084         done = sc->ah->ah_proc_tx_desc(sc->ah, bf->desc, &ts);
1085
1086         printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x "
1087                 "%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link,
1088                 ds->ds_data, td->tx_ctl.tx_control_0, td->tx_ctl.tx_control_1,
1089                 td->tx_ctl.tx_control_2, td->tx_ctl.tx_control_3,
1090                 td->tx_stat.tx_status_0, td->tx_stat.tx_status_1,
1091                 done ? ' ' : (ts.ts_status == 0) ? '*' : '!');
1092 }
1093
1094 #endif /* ifdef CONFIG_ATH5K_DEBUG */