Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
debug.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007-2008 Bruno Randolf <[email protected]>
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 <[email protected]>
25  * Copyright (c) 2007 Luis R. Rodriguez <[email protected]>
26  *
27  * All rights reserved.
28  *
29  * Redistribution and use in source and binary forms, with or without
30  * modification, are permitted provided that the following conditions
31  * are met:
32  * 1. Redistributions of source code must retain the above copyright
33  * notice, this list of conditions and the following disclaimer,
34  * without modification.
35  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
36  * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
37  * redistribution must be conditioned upon including a substantially
38  * similar Disclaimer requirement for further binary redistribution.
39  * 3. Neither the names of the above-listed copyright holders nor the names
40  * of any contributors may be used to endorse or promote products derived
41  * from this software without specific prior written permission.
42  *
43  * Alternatively, this software may be distributed under the terms of the
44  * GNU General Public License ("GPL") version 2 as published by the Free
45  * Software Foundation.
46  *
47  * NO WARRANTY
48  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
49  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
50  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
51  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
52  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
53  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
54  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
55  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
56  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
57  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
58  * THE POSSIBILITY OF SUCH DAMAGES.
59  */
60 
61 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
62 
63 #include <linux/export.h>
64 #include <linux/moduleparam.h>
65 
66 #include <linux/seq_file.h>
67 #include <linux/list.h>
68 #include "debug.h"
69 #include "ath5k.h"
70 #include "reg.h"
71 #include "base.h"
72 
73 static unsigned int ath5k_debug;
74 module_param_named(debug, ath5k_debug, uint, 0);
75 
76 
77 /* debugfs: registers */
78 
79 struct reg {
80  const char *name;
81  int addr;
82 };
83 
84 #define REG_STRUCT_INIT(r) { #r, r }
85 
86 /* just a few random registers, might want to add more */
87 static const struct reg regs[] = {
136 };
137 
138 static void *reg_start(struct seq_file *seq, loff_t *pos)
139 {
140  return *pos < ARRAY_SIZE(regs) ? (void *)&regs[*pos] : NULL;
141 }
142 
143 static void reg_stop(struct seq_file *seq, void *p)
144 {
145  /* nothing to do */
146 }
147 
148 static void *reg_next(struct seq_file *seq, void *p, loff_t *pos)
149 {
150  ++*pos;
151  return *pos < ARRAY_SIZE(regs) ? (void *)&regs[*pos] : NULL;
152 }
153 
154 static int reg_show(struct seq_file *seq, void *p)
155 {
156  struct ath5k_hw *ah = seq->private;
157  struct reg *r = p;
158  seq_printf(seq, "%-25s0x%08x\n", r->name,
159  ath5k_hw_reg_read(ah, r->addr));
160  return 0;
161 }
162 
163 static const struct seq_operations register_seq_ops = {
164  .start = reg_start,
165  .next = reg_next,
166  .stop = reg_stop,
167  .show = reg_show
168 };
169 
170 static int open_file_registers(struct inode *inode, struct file *file)
171 {
172  struct seq_file *s;
173  int res;
174  res = seq_open(file, &register_seq_ops);
175  if (res == 0) {
176  s = file->private_data;
177  s->private = inode->i_private;
178  }
179  return res;
180 }
181 
182 static const struct file_operations fops_registers = {
183  .open = open_file_registers,
184  .read = seq_read,
185  .llseek = seq_lseek,
186  .release = seq_release,
187  .owner = THIS_MODULE,
188 };
189 
190 
191 /* debugfs: beacons */
192 
193 static ssize_t read_file_beacon(struct file *file, char __user *user_buf,
194  size_t count, loff_t *ppos)
195 {
196  struct ath5k_hw *ah = file->private_data;
197  char buf[500];
198  unsigned int len = 0;
199  unsigned int v;
200  u64 tsf;
201 
202  v = ath5k_hw_reg_read(ah, AR5K_BEACON);
203  len += snprintf(buf + len, sizeof(buf) - len,
204  "%-24s0x%08x\tintval: %d\tTIM: 0x%x\n",
205  "AR5K_BEACON", v, v & AR5K_BEACON_PERIOD,
207 
208  len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\n",
209  "AR5K_LAST_TSTP", ath5k_hw_reg_read(ah, AR5K_LAST_TSTP));
210 
211  len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\n\n",
212  "AR5K_BEACON_CNT", ath5k_hw_reg_read(ah, AR5K_BEACON_CNT));
213 
214  v = ath5k_hw_reg_read(ah, AR5K_TIMER0);
215  len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
216  "AR5K_TIMER0 (TBTT)", v, v);
217 
218  v = ath5k_hw_reg_read(ah, AR5K_TIMER1);
219  len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
220  "AR5K_TIMER1 (DMA)", v, v >> 3);
221 
222  v = ath5k_hw_reg_read(ah, AR5K_TIMER2);
223  len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
224  "AR5K_TIMER2 (SWBA)", v, v >> 3);
225 
226  v = ath5k_hw_reg_read(ah, AR5K_TIMER3);
227  len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
228  "AR5K_TIMER3 (ATIM)", v, v);
229 
230  tsf = ath5k_hw_get_tsf64(ah);
231  len += snprintf(buf + len, sizeof(buf) - len,
232  "TSF\t\t0x%016llx\tTU: %08x\n",
233  (unsigned long long)tsf, TSF_TO_TU(tsf));
234 
235  if (len > sizeof(buf))
236  len = sizeof(buf);
237 
238  return simple_read_from_buffer(user_buf, count, ppos, buf, len);
239 }
240 
241 static ssize_t write_file_beacon(struct file *file,
242  const char __user *userbuf,
243  size_t count, loff_t *ppos)
244 {
245  struct ath5k_hw *ah = file->private_data;
246  char buf[20];
247 
248  if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
249  return -EFAULT;
250 
251  if (strncmp(buf, "disable", 7) == 0) {
253  pr_info("debugfs disable beacons\n");
254  } else if (strncmp(buf, "enable", 6) == 0) {
256  pr_info("debugfs enable beacons\n");
257  }
258  return count;
259 }
260 
261 static const struct file_operations fops_beacon = {
262  .read = read_file_beacon,
263  .write = write_file_beacon,
264  .open = simple_open,
265  .owner = THIS_MODULE,
266  .llseek = default_llseek,
267 };
268 
269 
270 /* debugfs: reset */
271 
272 static ssize_t write_file_reset(struct file *file,
273  const char __user *userbuf,
274  size_t count, loff_t *ppos)
275 {
276  struct ath5k_hw *ah = file->private_data;
277  ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "debug file triggered reset\n");
279  return count;
280 }
281 
282 static const struct file_operations fops_reset = {
283  .write = write_file_reset,
284  .open = simple_open,
285  .owner = THIS_MODULE,
286  .llseek = noop_llseek,
287 };
288 
289 
290 /* debugfs: debug level */
291 
292 static const struct {
294  const char *name;
295  const char *desc;
296 } dbg_info[] = {
297  { ATH5K_DEBUG_RESET, "reset", "reset and initialization" },
298  { ATH5K_DEBUG_INTR, "intr", "interrupt handling" },
299  { ATH5K_DEBUG_MODE, "mode", "mode init/setup" },
300  { ATH5K_DEBUG_XMIT, "xmit", "basic xmit operation" },
301  { ATH5K_DEBUG_BEACON, "beacon", "beacon handling" },
302  { ATH5K_DEBUG_CALIBRATE, "calib", "periodic calibration" },
303  { ATH5K_DEBUG_TXPOWER, "txpower", "transmit power setting" },
304  { ATH5K_DEBUG_LED, "led", "LED management" },
305  { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" },
306  { ATH5K_DEBUG_DMA, "dma", "dma start/stop" },
307  { ATH5K_DEBUG_ANI, "ani", "adaptive noise immunity" },
308  { ATH5K_DEBUG_DESC, "desc", "descriptor chains" },
309  { ATH5K_DEBUG_ANY, "all", "show all debug levels" },
310 };
311 
312 static ssize_t read_file_debug(struct file *file, char __user *user_buf,
313  size_t count, loff_t *ppos)
314 {
315  struct ath5k_hw *ah = file->private_data;
316  char buf[700];
317  unsigned int len = 0;
318  unsigned int i;
319 
320  len += snprintf(buf + len, sizeof(buf) - len,
321  "DEBUG LEVEL: 0x%08x\n\n", ah->debug.level);
322 
323  for (i = 0; i < ARRAY_SIZE(dbg_info) - 1; i++) {
324  len += snprintf(buf + len, sizeof(buf) - len,
325  "%10s %c 0x%08x - %s\n", dbg_info[i].name,
326  ah->debug.level & dbg_info[i].level ? '+' : ' ',
327  dbg_info[i].level, dbg_info[i].desc);
328  }
329  len += snprintf(buf + len, sizeof(buf) - len,
330  "%10s %c 0x%08x - %s\n", dbg_info[i].name,
331  ah->debug.level == dbg_info[i].level ? '+' : ' ',
332  dbg_info[i].level, dbg_info[i].desc);
333 
334  if (len > sizeof(buf))
335  len = sizeof(buf);
336 
337  return simple_read_from_buffer(user_buf, count, ppos, buf, len);
338 }
339 
340 static ssize_t write_file_debug(struct file *file,
341  const char __user *userbuf,
342  size_t count, loff_t *ppos)
343 {
344  struct ath5k_hw *ah = file->private_data;
345  unsigned int i;
346  char buf[20];
347 
348  if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
349  return -EFAULT;
350 
351  for (i = 0; i < ARRAY_SIZE(dbg_info); i++) {
352  if (strncmp(buf, dbg_info[i].name,
353  strlen(dbg_info[i].name)) == 0) {
354  ah->debug.level ^= dbg_info[i].level; /* toggle bit */
355  break;
356  }
357  }
358  return count;
359 }
360 
361 static const struct file_operations fops_debug = {
362  .read = read_file_debug,
363  .write = write_file_debug,
364  .open = simple_open,
365  .owner = THIS_MODULE,
366  .llseek = default_llseek,
367 };
368 
369 
370 /* debugfs: antenna */
371 
372 static ssize_t read_file_antenna(struct file *file, char __user *user_buf,
373  size_t count, loff_t *ppos)
374 {
375  struct ath5k_hw *ah = file->private_data;
376  char buf[700];
377  unsigned int len = 0;
378  unsigned int i;
379  unsigned int v;
380 
381  len += snprintf(buf + len, sizeof(buf) - len, "antenna mode\t%d\n",
382  ah->ah_ant_mode);
383  len += snprintf(buf + len, sizeof(buf) - len, "default antenna\t%d\n",
384  ah->ah_def_ant);
385  len += snprintf(buf + len, sizeof(buf) - len, "tx antenna\t%d\n",
386  ah->ah_tx_ant);
387 
388  len += snprintf(buf + len, sizeof(buf) - len, "\nANTENNA\t\tRX\tTX\n");
389  for (i = 1; i < ARRAY_SIZE(ah->stats.antenna_rx); i++) {
390  len += snprintf(buf + len, sizeof(buf) - len,
391  "[antenna %d]\t%d\t%d\n",
392  i, ah->stats.antenna_rx[i], ah->stats.antenna_tx[i]);
393  }
394  len += snprintf(buf + len, sizeof(buf) - len, "[invalid]\t%d\t%d\n",
395  ah->stats.antenna_rx[0], ah->stats.antenna_tx[0]);
396 
397  v = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
398  len += snprintf(buf + len, sizeof(buf) - len,
399  "\nAR5K_DEFAULT_ANTENNA\t0x%08x\n", v);
400 
401  v = ath5k_hw_reg_read(ah, AR5K_STA_ID1);
402  len += snprintf(buf + len, sizeof(buf) - len,
403  "AR5K_STA_ID1_DEFAULT_ANTENNA\t%d\n",
404  (v & AR5K_STA_ID1_DEFAULT_ANTENNA) != 0);
405  len += snprintf(buf + len, sizeof(buf) - len,
406  "AR5K_STA_ID1_DESC_ANTENNA\t%d\n",
407  (v & AR5K_STA_ID1_DESC_ANTENNA) != 0);
408  len += snprintf(buf + len, sizeof(buf) - len,
409  "AR5K_STA_ID1_RTS_DEF_ANTENNA\t%d\n",
410  (v & AR5K_STA_ID1_RTS_DEF_ANTENNA) != 0);
411  len += snprintf(buf + len, sizeof(buf) - len,
412  "AR5K_STA_ID1_SELFGEN_DEF_ANT\t%d\n",
413  (v & AR5K_STA_ID1_SELFGEN_DEF_ANT) != 0);
414 
415  v = ath5k_hw_reg_read(ah, AR5K_PHY_AGCCTL);
416  len += snprintf(buf + len, sizeof(buf) - len,
417  "\nAR5K_PHY_AGCCTL_OFDM_DIV_DIS\t%d\n",
418  (v & AR5K_PHY_AGCCTL_OFDM_DIV_DIS) != 0);
419 
420  v = ath5k_hw_reg_read(ah, AR5K_PHY_RESTART);
421  len += snprintf(buf + len, sizeof(buf) - len,
422  "AR5K_PHY_RESTART_DIV_GC\t\t%x\n",
424 
425  v = ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ANT_DIV);
426  len += snprintf(buf + len, sizeof(buf) - len,
427  "AR5K_PHY_FAST_ANT_DIV_EN\t%d\n",
428  (v & AR5K_PHY_FAST_ANT_DIV_EN) != 0);
429 
430  v = ath5k_hw_reg_read(ah, AR5K_PHY_ANT_SWITCH_TABLE_0);
431  len += snprintf(buf + len, sizeof(buf) - len,
432  "\nAR5K_PHY_ANT_SWITCH_TABLE_0\t0x%08x\n", v);
433  v = ath5k_hw_reg_read(ah, AR5K_PHY_ANT_SWITCH_TABLE_1);
434  len += snprintf(buf + len, sizeof(buf) - len,
435  "AR5K_PHY_ANT_SWITCH_TABLE_1\t0x%08x\n", v);
436 
437  if (len > sizeof(buf))
438  len = sizeof(buf);
439 
440  return simple_read_from_buffer(user_buf, count, ppos, buf, len);
441 }
442 
443 static ssize_t write_file_antenna(struct file *file,
444  const char __user *userbuf,
445  size_t count, loff_t *ppos)
446 {
447  struct ath5k_hw *ah = file->private_data;
448  unsigned int i;
449  char buf[20];
450 
451  if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
452  return -EFAULT;
453 
454  if (strncmp(buf, "diversity", 9) == 0) {
456  pr_info("debug: enable diversity\n");
457  } else if (strncmp(buf, "fixed-a", 7) == 0) {
459  pr_info("debug: fixed antenna A\n");
460  } else if (strncmp(buf, "fixed-b", 7) == 0) {
462  pr_info("debug: fixed antenna B\n");
463  } else if (strncmp(buf, "clear", 5) == 0) {
464  for (i = 0; i < ARRAY_SIZE(ah->stats.antenna_rx); i++) {
465  ah->stats.antenna_rx[i] = 0;
466  ah->stats.antenna_tx[i] = 0;
467  }
468  pr_info("debug: cleared antenna stats\n");
469  }
470  return count;
471 }
472 
473 static const struct file_operations fops_antenna = {
474  .read = read_file_antenna,
475  .write = write_file_antenna,
476  .open = simple_open,
477  .owner = THIS_MODULE,
478  .llseek = default_llseek,
479 };
480 
481 /* debugfs: misc */
482 
483 static ssize_t read_file_misc(struct file *file, char __user *user_buf,
484  size_t count, loff_t *ppos)
485 {
486  struct ath5k_hw *ah = file->private_data;
487  char buf[700];
488  unsigned int len = 0;
490 
491  len += snprintf(buf + len, sizeof(buf) - len, "bssid-mask: %pM\n",
492  ah->bssidmask);
493  len += snprintf(buf + len, sizeof(buf) - len, "filter-flags: 0x%x ",
494  filt);
495  if (filt & AR5K_RX_FILTER_UCAST)
496  len += snprintf(buf + len, sizeof(buf) - len, " UCAST");
497  if (filt & AR5K_RX_FILTER_MCAST)
498  len += snprintf(buf + len, sizeof(buf) - len, " MCAST");
499  if (filt & AR5K_RX_FILTER_BCAST)
500  len += snprintf(buf + len, sizeof(buf) - len, " BCAST");
501  if (filt & AR5K_RX_FILTER_CONTROL)
502  len += snprintf(buf + len, sizeof(buf) - len, " CONTROL");
503  if (filt & AR5K_RX_FILTER_BEACON)
504  len += snprintf(buf + len, sizeof(buf) - len, " BEACON");
505  if (filt & AR5K_RX_FILTER_PROM)
506  len += snprintf(buf + len, sizeof(buf) - len, " PROM");
507  if (filt & AR5K_RX_FILTER_XRPOLL)
508  len += snprintf(buf + len, sizeof(buf) - len, " XRPOLL");
509  if (filt & AR5K_RX_FILTER_PROBEREQ)
510  len += snprintf(buf + len, sizeof(buf) - len, " PROBEREQ");
511  if (filt & AR5K_RX_FILTER_PHYERR_5212)
512  len += snprintf(buf + len, sizeof(buf) - len, " PHYERR-5212");
513  if (filt & AR5K_RX_FILTER_RADARERR_5212)
514  len += snprintf(buf + len, sizeof(buf) - len, " RADARERR-5212");
515  if (filt & AR5K_RX_FILTER_PHYERR_5211)
516  snprintf(buf + len, sizeof(buf) - len, " PHYERR-5211");
517  if (filt & AR5K_RX_FILTER_RADARERR_5211)
518  len += snprintf(buf + len, sizeof(buf) - len, " RADARERR-5211");
519 
520  len += snprintf(buf + len, sizeof(buf) - len, "\nopmode: %s (%d)\n",
522 
523  if (len > sizeof(buf))
524  len = sizeof(buf);
525 
526  return simple_read_from_buffer(user_buf, count, ppos, buf, len);
527 }
528 
529 static const struct file_operations fops_misc = {
530  .read = read_file_misc,
531  .open = simple_open,
532  .owner = THIS_MODULE,
533 };
534 
535 
536 /* debugfs: frameerrors */
537 
538 static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf,
539  size_t count, loff_t *ppos)
540 {
541  struct ath5k_hw *ah = file->private_data;
542  struct ath5k_statistics *st = &ah->stats;
543  char buf[700];
544  unsigned int len = 0;
545  int i;
546 
547  len += snprintf(buf + len, sizeof(buf) - len,
548  "RX\n---------------------\n");
549  len += snprintf(buf + len, sizeof(buf) - len, "CRC\t%u\t(%u%%)\n",
550  st->rxerr_crc,
551  st->rx_all_count > 0 ?
552  st->rxerr_crc * 100 / st->rx_all_count : 0);
553  len += snprintf(buf + len, sizeof(buf) - len, "PHY\t%u\t(%u%%)\n",
554  st->rxerr_phy,
555  st->rx_all_count > 0 ?
556  st->rxerr_phy * 100 / st->rx_all_count : 0);
557  for (i = 0; i < 32; i++) {
558  if (st->rxerr_phy_code[i])
559  len += snprintf(buf + len, sizeof(buf) - len,
560  " phy_err[%u]\t%u\n",
561  i, st->rxerr_phy_code[i]);
562  }
563 
564  len += snprintf(buf + len, sizeof(buf) - len, "FIFO\t%u\t(%u%%)\n",
565  st->rxerr_fifo,
566  st->rx_all_count > 0 ?
567  st->rxerr_fifo * 100 / st->rx_all_count : 0);
568  len += snprintf(buf + len, sizeof(buf) - len, "decrypt\t%u\t(%u%%)\n",
569  st->rxerr_decrypt,
570  st->rx_all_count > 0 ?
571  st->rxerr_decrypt * 100 / st->rx_all_count : 0);
572  len += snprintf(buf + len, sizeof(buf) - len, "MIC\t%u\t(%u%%)\n",
573  st->rxerr_mic,
574  st->rx_all_count > 0 ?
575  st->rxerr_mic * 100 / st->rx_all_count : 0);
576  len += snprintf(buf + len, sizeof(buf) - len, "process\t%u\t(%u%%)\n",
577  st->rxerr_proc,
578  st->rx_all_count > 0 ?
579  st->rxerr_proc * 100 / st->rx_all_count : 0);
580  len += snprintf(buf + len, sizeof(buf) - len, "jumbo\t%u\t(%u%%)\n",
581  st->rxerr_jumbo,
582  st->rx_all_count > 0 ?
583  st->rxerr_jumbo * 100 / st->rx_all_count : 0);
584  len += snprintf(buf + len, sizeof(buf) - len, "[RX all\t%u]\n",
585  st->rx_all_count);
586  len += snprintf(buf + len, sizeof(buf) - len, "RX-all-bytes\t%u\n",
587  st->rx_bytes_count);
588 
589  len += snprintf(buf + len, sizeof(buf) - len,
590  "\nTX\n---------------------\n");
591  len += snprintf(buf + len, sizeof(buf) - len, "retry\t%u\t(%u%%)\n",
592  st->txerr_retry,
593  st->tx_all_count > 0 ?
594  st->txerr_retry * 100 / st->tx_all_count : 0);
595  len += snprintf(buf + len, sizeof(buf) - len, "FIFO\t%u\t(%u%%)\n",
596  st->txerr_fifo,
597  st->tx_all_count > 0 ?
598  st->txerr_fifo * 100 / st->tx_all_count : 0);
599  len += snprintf(buf + len, sizeof(buf) - len, "filter\t%u\t(%u%%)\n",
600  st->txerr_filt,
601  st->tx_all_count > 0 ?
602  st->txerr_filt * 100 / st->tx_all_count : 0);
603  len += snprintf(buf + len, sizeof(buf) - len, "[TX all\t%u]\n",
604  st->tx_all_count);
605  len += snprintf(buf + len, sizeof(buf) - len, "TX-all-bytes\t%u\n",
606  st->tx_bytes_count);
607 
608  if (len > sizeof(buf))
609  len = sizeof(buf);
610 
611  return simple_read_from_buffer(user_buf, count, ppos, buf, len);
612 }
613 
614 static ssize_t write_file_frameerrors(struct file *file,
615  const char __user *userbuf,
616  size_t count, loff_t *ppos)
617 {
618  struct ath5k_hw *ah = file->private_data;
619  struct ath5k_statistics *st = &ah->stats;
620  char buf[20];
621 
622  if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
623  return -EFAULT;
624 
625  if (strncmp(buf, "clear", 5) == 0) {
626  st->rxerr_crc = 0;
627  st->rxerr_phy = 0;
628  st->rxerr_fifo = 0;
629  st->rxerr_decrypt = 0;
630  st->rxerr_mic = 0;
631  st->rxerr_proc = 0;
632  st->rxerr_jumbo = 0;
633  st->rx_all_count = 0;
634  st->txerr_retry = 0;
635  st->txerr_fifo = 0;
636  st->txerr_filt = 0;
637  st->tx_all_count = 0;
638  pr_info("debug: cleared frameerrors stats\n");
639  }
640  return count;
641 }
642 
643 static const struct file_operations fops_frameerrors = {
644  .read = read_file_frameerrors,
645  .write = write_file_frameerrors,
646  .open = simple_open,
647  .owner = THIS_MODULE,
648  .llseek = default_llseek,
649 };
650 
651 
652 /* debugfs: ani */
653 
654 static ssize_t read_file_ani(struct file *file, char __user *user_buf,
655  size_t count, loff_t *ppos)
656 {
657  struct ath5k_hw *ah = file->private_data;
658  struct ath5k_statistics *st = &ah->stats;
659  struct ath5k_ani_state *as = &ah->ani_state;
660 
661  char buf[700];
662  unsigned int len = 0;
663 
664  len += snprintf(buf + len, sizeof(buf) - len,
665  "HW has PHY error counters:\t%s\n",
666  ah->ah_capabilities.cap_has_phyerr_counters ?
667  "yes" : "no");
668  len += snprintf(buf + len, sizeof(buf) - len,
669  "HW max spur immunity level:\t%d\n",
670  as->max_spur_level);
671  len += snprintf(buf + len, sizeof(buf) - len,
672  "\nANI state\n--------------------------------------------\n");
673  len += snprintf(buf + len, sizeof(buf) - len, "operating mode:\t\t\t");
674  switch (as->ani_mode) {
675  case ATH5K_ANI_MODE_OFF:
676  len += snprintf(buf + len, sizeof(buf) - len, "OFF\n");
677  break;
679  len += snprintf(buf + len, sizeof(buf) - len,
680  "MANUAL LOW\n");
681  break;
683  len += snprintf(buf + len, sizeof(buf) - len,
684  "MANUAL HIGH\n");
685  break;
686  case ATH5K_ANI_MODE_AUTO:
687  len += snprintf(buf + len, sizeof(buf) - len, "AUTO\n");
688  break;
689  default:
690  len += snprintf(buf + len, sizeof(buf) - len,
691  "??? (not good)\n");
692  break;
693  }
694  len += snprintf(buf + len, sizeof(buf) - len,
695  "noise immunity level:\t\t%d\n",
696  as->noise_imm_level);
697  len += snprintf(buf + len, sizeof(buf) - len,
698  "spur immunity level:\t\t%d\n",
699  as->spur_level);
700  len += snprintf(buf + len, sizeof(buf) - len,
701  "firstep level:\t\t\t%d\n",
702  as->firstep_level);
703  len += snprintf(buf + len, sizeof(buf) - len,
704  "OFDM weak signal detection:\t%s\n",
705  as->ofdm_weak_sig ? "on" : "off");
706  len += snprintf(buf + len, sizeof(buf) - len,
707  "CCK weak signal detection:\t%s\n",
708  as->cck_weak_sig ? "on" : "off");
709 
710  len += snprintf(buf + len, sizeof(buf) - len,
711  "\nMIB INTERRUPTS:\t\t%u\n",
712  st->mib_intr);
713  len += snprintf(buf + len, sizeof(buf) - len,
714  "beacon RSSI average:\t%d\n",
715  (int)ewma_read(&ah->ah_beacon_rssi_avg));
716 
717 #define CC_PRINT(_struct, _field) \
718  _struct._field, \
719  _struct.cycles > 0 ? \
720  _struct._field * 100 / _struct.cycles : 0
721 
722  len += snprintf(buf + len, sizeof(buf) - len,
723  "profcnt tx\t\t%u\t(%d%%)\n",
724  CC_PRINT(as->last_cc, tx_frame));
725  len += snprintf(buf + len, sizeof(buf) - len,
726  "profcnt rx\t\t%u\t(%d%%)\n",
727  CC_PRINT(as->last_cc, rx_frame));
728  len += snprintf(buf + len, sizeof(buf) - len,
729  "profcnt busy\t\t%u\t(%d%%)\n",
730  CC_PRINT(as->last_cc, rx_busy));
731 #undef CC_PRINT
732  len += snprintf(buf + len, sizeof(buf) - len, "profcnt cycles\t\t%u\n",
733  as->last_cc.cycles);
734  len += snprintf(buf + len, sizeof(buf) - len,
735  "listen time\t\t%d\tlast: %d\n",
736  as->listen_time, as->last_listen);
737  len += snprintf(buf + len, sizeof(buf) - len,
738  "OFDM errors\t\t%u\tlast: %u\tsum: %u\n",
739  as->ofdm_errors, as->last_ofdm_errors,
740  as->sum_ofdm_errors);
741  len += snprintf(buf + len, sizeof(buf) - len,
742  "CCK errors\t\t%u\tlast: %u\tsum: %u\n",
743  as->cck_errors, as->last_cck_errors,
744  as->sum_cck_errors);
745  len += snprintf(buf + len, sizeof(buf) - len,
746  "AR5K_PHYERR_CNT1\t%x\t(=%d)\n",
747  ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1),
749  ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1)));
750  len += snprintf(buf + len, sizeof(buf) - len,
751  "AR5K_PHYERR_CNT2\t%x\t(=%d)\n",
752  ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2),
754  ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2)));
755 
756  if (len > sizeof(buf))
757  len = sizeof(buf);
758 
759  return simple_read_from_buffer(user_buf, count, ppos, buf, len);
760 }
761 
762 static ssize_t write_file_ani(struct file *file,
763  const char __user *userbuf,
764  size_t count, loff_t *ppos)
765 {
766  struct ath5k_hw *ah = file->private_data;
767  char buf[20];
768 
769  if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
770  return -EFAULT;
771 
772  if (strncmp(buf, "sens-low", 8) == 0) {
774  } else if (strncmp(buf, "sens-high", 9) == 0) {
776  } else if (strncmp(buf, "ani-off", 7) == 0) {
778  } else if (strncmp(buf, "ani-on", 6) == 0) {
780  } else if (strncmp(buf, "noise-low", 9) == 0) {
782  } else if (strncmp(buf, "noise-high", 10) == 0) {
785  } else if (strncmp(buf, "spur-low", 8) == 0) {
787  } else if (strncmp(buf, "spur-high", 9) == 0) {
789  ah->ani_state.max_spur_level);
790  } else if (strncmp(buf, "fir-low", 7) == 0) {
792  } else if (strncmp(buf, "fir-high", 8) == 0) {
794  } else if (strncmp(buf, "ofdm-off", 8) == 0) {
796  } else if (strncmp(buf, "ofdm-on", 7) == 0) {
798  } else if (strncmp(buf, "cck-off", 7) == 0) {
800  } else if (strncmp(buf, "cck-on", 6) == 0) {
802  }
803  return count;
804 }
805 
806 static const struct file_operations fops_ani = {
807  .read = read_file_ani,
808  .write = write_file_ani,
809  .open = simple_open,
810  .owner = THIS_MODULE,
811  .llseek = default_llseek,
812 };
813 
814 
815 /* debugfs: queues etc */
816 
817 static ssize_t read_file_queue(struct file *file, char __user *user_buf,
818  size_t count, loff_t *ppos)
819 {
820  struct ath5k_hw *ah = file->private_data;
821  char buf[700];
822  unsigned int len = 0;
823 
824  struct ath5k_txq *txq;
825  struct ath5k_buf *bf, *bf0;
826  int i, n;
827 
828  len += snprintf(buf + len, sizeof(buf) - len,
829  "available txbuffers: %d\n", ah->txbuf_len);
830 
831  for (i = 0; i < ARRAY_SIZE(ah->txqs); i++) {
832  txq = &ah->txqs[i];
833 
834  len += snprintf(buf + len, sizeof(buf) - len,
835  "%02d: %ssetup\n", i, txq->setup ? "" : "not ");
836 
837  if (!txq->setup)
838  continue;
839 
840  n = 0;
841  spin_lock_bh(&txq->lock);
842  list_for_each_entry_safe(bf, bf0, &txq->q, list)
843  n++;
844  spin_unlock_bh(&txq->lock);
845 
846  len += snprintf(buf + len, sizeof(buf) - len,
847  " len: %d bufs: %d\n", txq->txq_len, n);
848  len += snprintf(buf + len, sizeof(buf) - len,
849  " stuck: %d\n", txq->txq_stuck);
850  }
851 
852  if (len > sizeof(buf))
853  len = sizeof(buf);
854 
855  return simple_read_from_buffer(user_buf, count, ppos, buf, len);
856 }
857 
858 static ssize_t write_file_queue(struct file *file,
859  const char __user *userbuf,
860  size_t count, loff_t *ppos)
861 {
862  struct ath5k_hw *ah = file->private_data;
863  char buf[20];
864 
865  if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
866  return -EFAULT;
867 
868  if (strncmp(buf, "start", 5) == 0)
870  else if (strncmp(buf, "stop", 4) == 0)
872 
873  return count;
874 }
875 
876 
877 static const struct file_operations fops_queue = {
878  .read = read_file_queue,
879  .write = write_file_queue,
880  .open = simple_open,
881  .owner = THIS_MODULE,
882  .llseek = default_llseek,
883 };
884 
885 
886 void
888 {
889  struct dentry *phydir;
890 
891  ah->debug.level = ath5k_debug;
892 
893  phydir = debugfs_create_dir("ath5k", ah->hw->wiphy->debugfsdir);
894  if (!phydir)
895  return;
896 
897  debugfs_create_file("debug", S_IWUSR | S_IRUSR, phydir, ah,
898  &fops_debug);
899 
900  debugfs_create_file("registers", S_IRUSR, phydir, ah, &fops_registers);
901 
902  debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, ah,
903  &fops_beacon);
904 
905  debugfs_create_file("reset", S_IWUSR, phydir, ah, &fops_reset);
906 
907  debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, ah,
908  &fops_antenna);
909 
910  debugfs_create_file("misc", S_IRUSR, phydir, ah, &fops_misc);
911 
912  debugfs_create_file("frameerrors", S_IWUSR | S_IRUSR, phydir, ah,
913  &fops_frameerrors);
914 
915  debugfs_create_file("ani", S_IWUSR | S_IRUSR, phydir, ah, &fops_ani);
916 
917  debugfs_create_file("queue", S_IWUSR | S_IRUSR, phydir, ah,
918  &fops_queue);
919 
920  debugfs_create_bool("32khz_clock", S_IWUSR | S_IRUSR, phydir,
921  &ah->ah_use_32khz_clock);
922 }
923 
924 /* functions used in other places */
925 
926 void
928 {
929  unsigned int b, i;
930 
931  if (likely(!(ah->debug.level & ATH5K_DEBUG_DUMPBANDS)))
932  return;
933 
934  BUG_ON(!ah->sbands);
935 
936  for (b = 0; b < IEEE80211_NUM_BANDS; b++) {
937  struct ieee80211_supported_band *band = &ah->sbands[b];
938  char bname[6];
939  switch (band->band) {
940  case IEEE80211_BAND_2GHZ:
941  strcpy(bname, "2 GHz");
942  break;
943  case IEEE80211_BAND_5GHZ:
944  strcpy(bname, "5 GHz");
945  break;
946  default:
947  printk(KERN_DEBUG "Band not supported: %d\n",
948  band->band);
949  return;
950  }
951  printk(KERN_DEBUG "Band %s: channels %d, rates %d\n", bname,
952  band->n_channels, band->n_bitrates);
953  printk(KERN_DEBUG " channels:\n");
954  for (i = 0; i < band->n_channels; i++)
955  printk(KERN_DEBUG " %3d %d %.4x %.4x\n",
957  band->channels[i].center_freq),
958  band->channels[i].center_freq,
959  band->channels[i].hw_value,
960  band->channels[i].flags);
961  printk(KERN_DEBUG " rates:\n");
962  for (i = 0; i < band->n_bitrates; i++)
963  printk(KERN_DEBUG " %4d %.4x %.4x %.4x\n",
964  band->bitrates[i].bitrate,
965  band->bitrates[i].hw_value,
966  band->bitrates[i].flags,
967  band->bitrates[i].hw_value_short);
968  }
969 }
970 
971 static inline void
972 ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done,
973  struct ath5k_rx_status *rs)
974 {
975  struct ath5k_desc *ds = bf->desc;
976  struct ath5k_hw_all_rx_desc *rd = &ds->ud.ds_rx;
977 
978  printk(KERN_DEBUG "R (%p %llx) %08x %08x %08x %08x %08x %08x %c\n",
979  ds, (unsigned long long)bf->daddr,
980  ds->ds_link, ds->ds_data,
981  rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1,
982  rd->rx_stat.rx_status_0, rd->rx_stat.rx_status_1,
983  !done ? ' ' : (rs->rs_status == 0) ? '*' : '!');
984 }
985 
986 void
988 {
989  struct ath5k_desc *ds;
990  struct ath5k_buf *bf;
991  struct ath5k_rx_status rs = {};
992  int status;
993 
994  if (likely(!(ah->debug.level & ATH5K_DEBUG_DESC)))
995  return;
996 
997  printk(KERN_DEBUG "rxdp %x, rxlink %p\n",
998  ath5k_hw_get_rxdp(ah), ah->rxlink);
999 
1000  spin_lock_bh(&ah->rxbuflock);
1001  list_for_each_entry(bf, &ah->rxbuf, list) {
1002  ds = bf->desc;
1003  status = ah->ah_proc_rx_desc(ah, ds, &rs);
1004  if (!status)
1005  ath5k_debug_printrxbuf(bf, status == 0, &rs);
1006  }
1007  spin_unlock_bh(&ah->rxbuflock);
1008 }
1009 
1010 void
1012 {
1013  struct ath5k_desc *ds = bf->desc;
1014  struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212;
1015  struct ath5k_tx_status ts = {};
1016  int done;
1017 
1018  if (likely(!(ah->debug.level & ATH5K_DEBUG_DESC)))
1019  return;
1020 
1021  done = ah->ah_proc_tx_desc(ah, bf->desc, &ts);
1022 
1023  printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x "
1024  "%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link,
1025  ds->ds_data, td->tx_ctl.tx_control_0, td->tx_ctl.tx_control_1,
1026  td->tx_ctl.tx_control_2, td->tx_ctl.tx_control_3,
1027  td->tx_stat.tx_status_0, td->tx_stat.tx_status_1,
1028  done ? ' ' : (ts.ts_status == 0) ? '*' : '!');
1029 }