0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0062
0063 #include <linux/export.h>
0064 #include <linux/moduleparam.h>
0065 #include <linux/vmalloc.h>
0066
0067 #include <linux/seq_file.h>
0068 #include <linux/list.h>
0069 #include "debug.h"
0070 #include "ath5k.h"
0071 #include "reg.h"
0072 #include "base.h"
0073
0074 static unsigned int ath5k_debug;
0075 module_param_named(debug, ath5k_debug, uint, 0);
0076
0077
0078
0079
0080 struct reg {
0081 const char *name;
0082 int addr;
0083 };
0084
0085 #define REG_STRUCT_INIT(r) { #r, r }
0086
0087
0088 static const struct reg regs[] = {
0089 REG_STRUCT_INIT(AR5K_CR),
0090 REG_STRUCT_INIT(AR5K_RXDP),
0091 REG_STRUCT_INIT(AR5K_CFG),
0092 REG_STRUCT_INIT(AR5K_IER),
0093 REG_STRUCT_INIT(AR5K_BCR),
0094 REG_STRUCT_INIT(AR5K_RTSD0),
0095 REG_STRUCT_INIT(AR5K_RTSD1),
0096 REG_STRUCT_INIT(AR5K_TXCFG),
0097 REG_STRUCT_INIT(AR5K_RXCFG),
0098 REG_STRUCT_INIT(AR5K_RXJLA),
0099 REG_STRUCT_INIT(AR5K_MIBC),
0100 REG_STRUCT_INIT(AR5K_TOPS),
0101 REG_STRUCT_INIT(AR5K_RXNOFRM),
0102 REG_STRUCT_INIT(AR5K_TXNOFRM),
0103 REG_STRUCT_INIT(AR5K_RPGTO),
0104 REG_STRUCT_INIT(AR5K_RFCNT),
0105 REG_STRUCT_INIT(AR5K_MISC),
0106 REG_STRUCT_INIT(AR5K_QCUDCU_CLKGT),
0107 REG_STRUCT_INIT(AR5K_ISR),
0108 REG_STRUCT_INIT(AR5K_PISR),
0109 REG_STRUCT_INIT(AR5K_SISR0),
0110 REG_STRUCT_INIT(AR5K_SISR1),
0111 REG_STRUCT_INIT(AR5K_SISR2),
0112 REG_STRUCT_INIT(AR5K_SISR3),
0113 REG_STRUCT_INIT(AR5K_SISR4),
0114 REG_STRUCT_INIT(AR5K_IMR),
0115 REG_STRUCT_INIT(AR5K_PIMR),
0116 REG_STRUCT_INIT(AR5K_SIMR0),
0117 REG_STRUCT_INIT(AR5K_SIMR1),
0118 REG_STRUCT_INIT(AR5K_SIMR2),
0119 REG_STRUCT_INIT(AR5K_SIMR3),
0120 REG_STRUCT_INIT(AR5K_SIMR4),
0121 REG_STRUCT_INIT(AR5K_DCM_ADDR),
0122 REG_STRUCT_INIT(AR5K_DCCFG),
0123 REG_STRUCT_INIT(AR5K_CCFG),
0124 REG_STRUCT_INIT(AR5K_CPC0),
0125 REG_STRUCT_INIT(AR5K_CPC1),
0126 REG_STRUCT_INIT(AR5K_CPC2),
0127 REG_STRUCT_INIT(AR5K_CPC3),
0128 REG_STRUCT_INIT(AR5K_CPCOVF),
0129 REG_STRUCT_INIT(AR5K_RESET_CTL),
0130 REG_STRUCT_INIT(AR5K_SLEEP_CTL),
0131 REG_STRUCT_INIT(AR5K_INTPEND),
0132 REG_STRUCT_INIT(AR5K_SFR),
0133 REG_STRUCT_INIT(AR5K_PCICFG),
0134 REG_STRUCT_INIT(AR5K_GPIOCR),
0135 REG_STRUCT_INIT(AR5K_GPIODO),
0136 REG_STRUCT_INIT(AR5K_SREV),
0137 };
0138
0139 static void *reg_start(struct seq_file *seq, loff_t *pos)
0140 {
0141 return *pos < ARRAY_SIZE(regs) ? (void *)®s[*pos] : NULL;
0142 }
0143
0144 static void reg_stop(struct seq_file *seq, void *p)
0145 {
0146
0147 }
0148
0149 static void *reg_next(struct seq_file *seq, void *p, loff_t *pos)
0150 {
0151 ++*pos;
0152 return *pos < ARRAY_SIZE(regs) ? (void *)®s[*pos] : NULL;
0153 }
0154
0155 static int reg_show(struct seq_file *seq, void *p)
0156 {
0157 struct ath5k_hw *ah = seq->private;
0158 struct reg *r = p;
0159 seq_printf(seq, "%-25s0x%08x\n", r->name,
0160 ath5k_hw_reg_read(ah, r->addr));
0161 return 0;
0162 }
0163
0164 static const struct seq_operations registers_sops = {
0165 .start = reg_start,
0166 .next = reg_next,
0167 .stop = reg_stop,
0168 .show = reg_show
0169 };
0170
0171 DEFINE_SEQ_ATTRIBUTE(registers);
0172
0173
0174
0175 static ssize_t read_file_beacon(struct file *file, char __user *user_buf,
0176 size_t count, loff_t *ppos)
0177 {
0178 struct ath5k_hw *ah = file->private_data;
0179 char buf[500];
0180 unsigned int len = 0;
0181 unsigned int v;
0182 u64 tsf;
0183
0184 v = ath5k_hw_reg_read(ah, AR5K_BEACON);
0185 len += scnprintf(buf + len, sizeof(buf) - len,
0186 "%-24s0x%08x\tintval: %d\tTIM: 0x%x\n",
0187 "AR5K_BEACON", v, v & AR5K_BEACON_PERIOD,
0188 (v & AR5K_BEACON_TIM) >> AR5K_BEACON_TIM_S);
0189
0190 len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\n",
0191 "AR5K_LAST_TSTP", ath5k_hw_reg_read(ah, AR5K_LAST_TSTP));
0192
0193 len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\n\n",
0194 "AR5K_BEACON_CNT", ath5k_hw_reg_read(ah, AR5K_BEACON_CNT));
0195
0196 v = ath5k_hw_reg_read(ah, AR5K_TIMER0);
0197 len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
0198 "AR5K_TIMER0 (TBTT)", v, v);
0199
0200 v = ath5k_hw_reg_read(ah, AR5K_TIMER1);
0201 len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
0202 "AR5K_TIMER1 (DMA)", v, v >> 3);
0203
0204 v = ath5k_hw_reg_read(ah, AR5K_TIMER2);
0205 len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
0206 "AR5K_TIMER2 (SWBA)", v, v >> 3);
0207
0208 v = ath5k_hw_reg_read(ah, AR5K_TIMER3);
0209 len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
0210 "AR5K_TIMER3 (ATIM)", v, v);
0211
0212 tsf = ath5k_hw_get_tsf64(ah);
0213 len += scnprintf(buf + len, sizeof(buf) - len,
0214 "TSF\t\t0x%016llx\tTU: %08x\n",
0215 (unsigned long long)tsf, TSF_TO_TU(tsf));
0216
0217 if (len > sizeof(buf))
0218 len = sizeof(buf);
0219
0220 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0221 }
0222
0223 static ssize_t write_file_beacon(struct file *file,
0224 const char __user *userbuf,
0225 size_t count, loff_t *ppos)
0226 {
0227 struct ath5k_hw *ah = file->private_data;
0228 char buf[20];
0229
0230 count = min_t(size_t, count, sizeof(buf) - 1);
0231 if (copy_from_user(buf, userbuf, count))
0232 return -EFAULT;
0233
0234 buf[count] = '\0';
0235 if (strncmp(buf, "disable", 7) == 0) {
0236 AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
0237 pr_info("debugfs disable beacons\n");
0238 } else if (strncmp(buf, "enable", 6) == 0) {
0239 AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
0240 pr_info("debugfs enable beacons\n");
0241 }
0242 return count;
0243 }
0244
0245 static const struct file_operations fops_beacon = {
0246 .read = read_file_beacon,
0247 .write = write_file_beacon,
0248 .open = simple_open,
0249 .owner = THIS_MODULE,
0250 .llseek = default_llseek,
0251 };
0252
0253
0254
0255
0256 static ssize_t write_file_reset(struct file *file,
0257 const char __user *userbuf,
0258 size_t count, loff_t *ppos)
0259 {
0260 struct ath5k_hw *ah = file->private_data;
0261 ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "debug file triggered reset\n");
0262 ieee80211_queue_work(ah->hw, &ah->reset_work);
0263 return count;
0264 }
0265
0266 static const struct file_operations fops_reset = {
0267 .write = write_file_reset,
0268 .open = simple_open,
0269 .owner = THIS_MODULE,
0270 .llseek = noop_llseek,
0271 };
0272
0273
0274
0275
0276 static const struct {
0277 enum ath5k_debug_level level;
0278 const char *name;
0279 const char *desc;
0280 } dbg_info[] = {
0281 { ATH5K_DEBUG_RESET, "reset", "reset and initialization" },
0282 { ATH5K_DEBUG_INTR, "intr", "interrupt handling" },
0283 { ATH5K_DEBUG_MODE, "mode", "mode init/setup" },
0284 { ATH5K_DEBUG_XMIT, "xmit", "basic xmit operation" },
0285 { ATH5K_DEBUG_BEACON, "beacon", "beacon handling" },
0286 { ATH5K_DEBUG_CALIBRATE, "calib", "periodic calibration" },
0287 { ATH5K_DEBUG_TXPOWER, "txpower", "transmit power setting" },
0288 { ATH5K_DEBUG_LED, "led", "LED management" },
0289 { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" },
0290 { ATH5K_DEBUG_DMA, "dma", "dma start/stop" },
0291 { ATH5K_DEBUG_ANI, "ani", "adaptive noise immunity" },
0292 { ATH5K_DEBUG_DESC, "desc", "descriptor chains" },
0293 { ATH5K_DEBUG_ANY, "all", "show all debug levels" },
0294 };
0295
0296 static ssize_t read_file_debug(struct file *file, char __user *user_buf,
0297 size_t count, loff_t *ppos)
0298 {
0299 struct ath5k_hw *ah = file->private_data;
0300 char buf[700];
0301 unsigned int len = 0;
0302 unsigned int i;
0303
0304 len += scnprintf(buf + len, sizeof(buf) - len,
0305 "DEBUG LEVEL: 0x%08x\n\n", ah->debug.level);
0306
0307 for (i = 0; i < ARRAY_SIZE(dbg_info) - 1; i++) {
0308 len += scnprintf(buf + len, sizeof(buf) - len,
0309 "%10s %c 0x%08x - %s\n", dbg_info[i].name,
0310 ah->debug.level & dbg_info[i].level ? '+' : ' ',
0311 dbg_info[i].level, dbg_info[i].desc);
0312 }
0313 len += scnprintf(buf + len, sizeof(buf) - len,
0314 "%10s %c 0x%08x - %s\n", dbg_info[i].name,
0315 ah->debug.level == dbg_info[i].level ? '+' : ' ',
0316 dbg_info[i].level, dbg_info[i].desc);
0317
0318 if (len > sizeof(buf))
0319 len = sizeof(buf);
0320
0321 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0322 }
0323
0324 static ssize_t write_file_debug(struct file *file,
0325 const char __user *userbuf,
0326 size_t count, loff_t *ppos)
0327 {
0328 struct ath5k_hw *ah = file->private_data;
0329 unsigned int i;
0330 char buf[20];
0331
0332 count = min_t(size_t, count, sizeof(buf) - 1);
0333 if (copy_from_user(buf, userbuf, count))
0334 return -EFAULT;
0335
0336 buf[count] = '\0';
0337 for (i = 0; i < ARRAY_SIZE(dbg_info); i++) {
0338 if (strncmp(buf, dbg_info[i].name,
0339 strlen(dbg_info[i].name)) == 0) {
0340 ah->debug.level ^= dbg_info[i].level;
0341 break;
0342 }
0343 }
0344 return count;
0345 }
0346
0347 static const struct file_operations fops_debug = {
0348 .read = read_file_debug,
0349 .write = write_file_debug,
0350 .open = simple_open,
0351 .owner = THIS_MODULE,
0352 .llseek = default_llseek,
0353 };
0354
0355
0356
0357
0358 static ssize_t read_file_antenna(struct file *file, char __user *user_buf,
0359 size_t count, loff_t *ppos)
0360 {
0361 struct ath5k_hw *ah = file->private_data;
0362 char buf[700];
0363 unsigned int len = 0;
0364 unsigned int i;
0365 unsigned int v;
0366
0367 len += scnprintf(buf + len, sizeof(buf) - len, "antenna mode\t%d\n",
0368 ah->ah_ant_mode);
0369 len += scnprintf(buf + len, sizeof(buf) - len, "default antenna\t%d\n",
0370 ah->ah_def_ant);
0371 len += scnprintf(buf + len, sizeof(buf) - len, "tx antenna\t%d\n",
0372 ah->ah_tx_ant);
0373
0374 len += scnprintf(buf + len, sizeof(buf) - len, "\nANTENNA\t\tRX\tTX\n");
0375 for (i = 1; i < ARRAY_SIZE(ah->stats.antenna_rx); i++) {
0376 len += scnprintf(buf + len, sizeof(buf) - len,
0377 "[antenna %d]\t%d\t%d\n",
0378 i, ah->stats.antenna_rx[i], ah->stats.antenna_tx[i]);
0379 }
0380 len += scnprintf(buf + len, sizeof(buf) - len, "[invalid]\t%d\t%d\n",
0381 ah->stats.antenna_rx[0], ah->stats.antenna_tx[0]);
0382
0383 v = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
0384 len += scnprintf(buf + len, sizeof(buf) - len,
0385 "\nAR5K_DEFAULT_ANTENNA\t0x%08x\n", v);
0386
0387 v = ath5k_hw_reg_read(ah, AR5K_STA_ID1);
0388 len += scnprintf(buf + len, sizeof(buf) - len,
0389 "AR5K_STA_ID1_DEFAULT_ANTENNA\t%d\n",
0390 (v & AR5K_STA_ID1_DEFAULT_ANTENNA) != 0);
0391 len += scnprintf(buf + len, sizeof(buf) - len,
0392 "AR5K_STA_ID1_DESC_ANTENNA\t%d\n",
0393 (v & AR5K_STA_ID1_DESC_ANTENNA) != 0);
0394 len += scnprintf(buf + len, sizeof(buf) - len,
0395 "AR5K_STA_ID1_RTS_DEF_ANTENNA\t%d\n",
0396 (v & AR5K_STA_ID1_RTS_DEF_ANTENNA) != 0);
0397 len += scnprintf(buf + len, sizeof(buf) - len,
0398 "AR5K_STA_ID1_SELFGEN_DEF_ANT\t%d\n",
0399 (v & AR5K_STA_ID1_SELFGEN_DEF_ANT) != 0);
0400
0401 v = ath5k_hw_reg_read(ah, AR5K_PHY_AGCCTL);
0402 len += scnprintf(buf + len, sizeof(buf) - len,
0403 "\nAR5K_PHY_AGCCTL_OFDM_DIV_DIS\t%d\n",
0404 (v & AR5K_PHY_AGCCTL_OFDM_DIV_DIS) != 0);
0405
0406 v = ath5k_hw_reg_read(ah, AR5K_PHY_RESTART);
0407 len += scnprintf(buf + len, sizeof(buf) - len,
0408 "AR5K_PHY_RESTART_DIV_GC\t\t%x\n",
0409 (v & AR5K_PHY_RESTART_DIV_GC) >> AR5K_PHY_RESTART_DIV_GC_S);
0410
0411 v = ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ANT_DIV);
0412 len += scnprintf(buf + len, sizeof(buf) - len,
0413 "AR5K_PHY_FAST_ANT_DIV_EN\t%d\n",
0414 (v & AR5K_PHY_FAST_ANT_DIV_EN) != 0);
0415
0416 v = ath5k_hw_reg_read(ah, AR5K_PHY_ANT_SWITCH_TABLE_0);
0417 len += scnprintf(buf + len, sizeof(buf) - len,
0418 "\nAR5K_PHY_ANT_SWITCH_TABLE_0\t0x%08x\n", v);
0419 v = ath5k_hw_reg_read(ah, AR5K_PHY_ANT_SWITCH_TABLE_1);
0420 len += scnprintf(buf + len, sizeof(buf) - len,
0421 "AR5K_PHY_ANT_SWITCH_TABLE_1\t0x%08x\n", v);
0422
0423 if (len > sizeof(buf))
0424 len = sizeof(buf);
0425
0426 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0427 }
0428
0429 static ssize_t write_file_antenna(struct file *file,
0430 const char __user *userbuf,
0431 size_t count, loff_t *ppos)
0432 {
0433 struct ath5k_hw *ah = file->private_data;
0434 unsigned int i;
0435 char buf[20];
0436
0437 count = min_t(size_t, count, sizeof(buf) - 1);
0438 if (copy_from_user(buf, userbuf, count))
0439 return -EFAULT;
0440
0441 buf[count] = '\0';
0442 if (strncmp(buf, "diversity", 9) == 0) {
0443 ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT);
0444 pr_info("debug: enable diversity\n");
0445 } else if (strncmp(buf, "fixed-a", 7) == 0) {
0446 ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_A);
0447 pr_info("debug: fixed antenna A\n");
0448 } else if (strncmp(buf, "fixed-b", 7) == 0) {
0449 ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_B);
0450 pr_info("debug: fixed antenna B\n");
0451 } else if (strncmp(buf, "clear", 5) == 0) {
0452 for (i = 0; i < ARRAY_SIZE(ah->stats.antenna_rx); i++) {
0453 ah->stats.antenna_rx[i] = 0;
0454 ah->stats.antenna_tx[i] = 0;
0455 }
0456 pr_info("debug: cleared antenna stats\n");
0457 }
0458 return count;
0459 }
0460
0461 static const struct file_operations fops_antenna = {
0462 .read = read_file_antenna,
0463 .write = write_file_antenna,
0464 .open = simple_open,
0465 .owner = THIS_MODULE,
0466 .llseek = default_llseek,
0467 };
0468
0469
0470
0471 static ssize_t read_file_misc(struct file *file, char __user *user_buf,
0472 size_t count, loff_t *ppos)
0473 {
0474 struct ath5k_hw *ah = file->private_data;
0475 char buf[700];
0476 unsigned int len = 0;
0477 u32 filt = ath5k_hw_get_rx_filter(ah);
0478
0479 len += scnprintf(buf + len, sizeof(buf) - len, "bssid-mask: %pM\n",
0480 ah->bssidmask);
0481 len += scnprintf(buf + len, sizeof(buf) - len, "filter-flags: 0x%x ",
0482 filt);
0483 if (filt & AR5K_RX_FILTER_UCAST)
0484 len += scnprintf(buf + len, sizeof(buf) - len, " UCAST");
0485 if (filt & AR5K_RX_FILTER_MCAST)
0486 len += scnprintf(buf + len, sizeof(buf) - len, " MCAST");
0487 if (filt & AR5K_RX_FILTER_BCAST)
0488 len += scnprintf(buf + len, sizeof(buf) - len, " BCAST");
0489 if (filt & AR5K_RX_FILTER_CONTROL)
0490 len += scnprintf(buf + len, sizeof(buf) - len, " CONTROL");
0491 if (filt & AR5K_RX_FILTER_BEACON)
0492 len += scnprintf(buf + len, sizeof(buf) - len, " BEACON");
0493 if (filt & AR5K_RX_FILTER_PROM)
0494 len += scnprintf(buf + len, sizeof(buf) - len, " PROM");
0495 if (filt & AR5K_RX_FILTER_XRPOLL)
0496 len += scnprintf(buf + len, sizeof(buf) - len, " XRPOLL");
0497 if (filt & AR5K_RX_FILTER_PROBEREQ)
0498 len += scnprintf(buf + len, sizeof(buf) - len, " PROBEREQ");
0499 if (filt & AR5K_RX_FILTER_PHYERR_5212)
0500 len += scnprintf(buf + len, sizeof(buf) - len, " PHYERR-5212");
0501 if (filt & AR5K_RX_FILTER_RADARERR_5212)
0502 len += scnprintf(buf + len, sizeof(buf) - len, " RADARERR-5212");
0503 if (filt & AR5K_RX_FILTER_PHYERR_5211)
0504 snprintf(buf + len, sizeof(buf) - len, " PHYERR-5211");
0505 if (filt & AR5K_RX_FILTER_RADARERR_5211)
0506 len += scnprintf(buf + len, sizeof(buf) - len, " RADARERR-5211");
0507
0508 len += scnprintf(buf + len, sizeof(buf) - len, "\nopmode: %s (%d)\n",
0509 ath_opmode_to_string(ah->opmode), ah->opmode);
0510
0511 if (len > sizeof(buf))
0512 len = sizeof(buf);
0513
0514 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0515 }
0516
0517 static const struct file_operations fops_misc = {
0518 .read = read_file_misc,
0519 .open = simple_open,
0520 .owner = THIS_MODULE,
0521 };
0522
0523
0524
0525
0526 static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf,
0527 size_t count, loff_t *ppos)
0528 {
0529 struct ath5k_hw *ah = file->private_data;
0530 struct ath5k_statistics *st = &ah->stats;
0531 char buf[700];
0532 unsigned int len = 0;
0533 int i;
0534
0535 len += scnprintf(buf + len, sizeof(buf) - len,
0536 "RX\n---------------------\n");
0537 len += scnprintf(buf + len, sizeof(buf) - len, "CRC\t%u\t(%u%%)\n",
0538 st->rxerr_crc,
0539 st->rx_all_count > 0 ?
0540 st->rxerr_crc * 100 / st->rx_all_count : 0);
0541 len += scnprintf(buf + len, sizeof(buf) - len, "PHY\t%u\t(%u%%)\n",
0542 st->rxerr_phy,
0543 st->rx_all_count > 0 ?
0544 st->rxerr_phy * 100 / st->rx_all_count : 0);
0545 for (i = 0; i < 32; i++) {
0546 if (st->rxerr_phy_code[i])
0547 len += scnprintf(buf + len, sizeof(buf) - len,
0548 " phy_err[%u]\t%u\n",
0549 i, st->rxerr_phy_code[i]);
0550 }
0551
0552 len += scnprintf(buf + len, sizeof(buf) - len, "FIFO\t%u\t(%u%%)\n",
0553 st->rxerr_fifo,
0554 st->rx_all_count > 0 ?
0555 st->rxerr_fifo * 100 / st->rx_all_count : 0);
0556 len += scnprintf(buf + len, sizeof(buf) - len, "decrypt\t%u\t(%u%%)\n",
0557 st->rxerr_decrypt,
0558 st->rx_all_count > 0 ?
0559 st->rxerr_decrypt * 100 / st->rx_all_count : 0);
0560 len += scnprintf(buf + len, sizeof(buf) - len, "MIC\t%u\t(%u%%)\n",
0561 st->rxerr_mic,
0562 st->rx_all_count > 0 ?
0563 st->rxerr_mic * 100 / st->rx_all_count : 0);
0564 len += scnprintf(buf + len, sizeof(buf) - len, "process\t%u\t(%u%%)\n",
0565 st->rxerr_proc,
0566 st->rx_all_count > 0 ?
0567 st->rxerr_proc * 100 / st->rx_all_count : 0);
0568 len += scnprintf(buf + len, sizeof(buf) - len, "jumbo\t%u\t(%u%%)\n",
0569 st->rxerr_jumbo,
0570 st->rx_all_count > 0 ?
0571 st->rxerr_jumbo * 100 / st->rx_all_count : 0);
0572 len += scnprintf(buf + len, sizeof(buf) - len, "[RX all\t%u]\n",
0573 st->rx_all_count);
0574 len += scnprintf(buf + len, sizeof(buf) - len, "RX-all-bytes\t%u\n",
0575 st->rx_bytes_count);
0576
0577 len += scnprintf(buf + len, sizeof(buf) - len,
0578 "\nTX\n---------------------\n");
0579 len += scnprintf(buf + len, sizeof(buf) - len, "retry\t%u\t(%u%%)\n",
0580 st->txerr_retry,
0581 st->tx_all_count > 0 ?
0582 st->txerr_retry * 100 / st->tx_all_count : 0);
0583 len += scnprintf(buf + len, sizeof(buf) - len, "FIFO\t%u\t(%u%%)\n",
0584 st->txerr_fifo,
0585 st->tx_all_count > 0 ?
0586 st->txerr_fifo * 100 / st->tx_all_count : 0);
0587 len += scnprintf(buf + len, sizeof(buf) - len, "filter\t%u\t(%u%%)\n",
0588 st->txerr_filt,
0589 st->tx_all_count > 0 ?
0590 st->txerr_filt * 100 / st->tx_all_count : 0);
0591 len += scnprintf(buf + len, sizeof(buf) - len, "[TX all\t%u]\n",
0592 st->tx_all_count);
0593 len += scnprintf(buf + len, sizeof(buf) - len, "TX-all-bytes\t%u\n",
0594 st->tx_bytes_count);
0595
0596 if (len > sizeof(buf))
0597 len = sizeof(buf);
0598
0599 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0600 }
0601
0602 static ssize_t write_file_frameerrors(struct file *file,
0603 const char __user *userbuf,
0604 size_t count, loff_t *ppos)
0605 {
0606 struct ath5k_hw *ah = file->private_data;
0607 struct ath5k_statistics *st = &ah->stats;
0608 char buf[20];
0609
0610 count = min_t(size_t, count, sizeof(buf) - 1);
0611 if (copy_from_user(buf, userbuf, count))
0612 return -EFAULT;
0613
0614 buf[count] = '\0';
0615 if (strncmp(buf, "clear", 5) == 0) {
0616 st->rxerr_crc = 0;
0617 st->rxerr_phy = 0;
0618 st->rxerr_fifo = 0;
0619 st->rxerr_decrypt = 0;
0620 st->rxerr_mic = 0;
0621 st->rxerr_proc = 0;
0622 st->rxerr_jumbo = 0;
0623 st->rx_all_count = 0;
0624 st->txerr_retry = 0;
0625 st->txerr_fifo = 0;
0626 st->txerr_filt = 0;
0627 st->tx_all_count = 0;
0628 pr_info("debug: cleared frameerrors stats\n");
0629 }
0630 return count;
0631 }
0632
0633 static const struct file_operations fops_frameerrors = {
0634 .read = read_file_frameerrors,
0635 .write = write_file_frameerrors,
0636 .open = simple_open,
0637 .owner = THIS_MODULE,
0638 .llseek = default_llseek,
0639 };
0640
0641
0642
0643
0644 static ssize_t read_file_ani(struct file *file, char __user *user_buf,
0645 size_t count, loff_t *ppos)
0646 {
0647 struct ath5k_hw *ah = file->private_data;
0648 struct ath5k_statistics *st = &ah->stats;
0649 struct ath5k_ani_state *as = &ah->ani_state;
0650
0651 char buf[700];
0652 unsigned int len = 0;
0653
0654 len += scnprintf(buf + len, sizeof(buf) - len,
0655 "HW has PHY error counters:\t%s\n",
0656 ah->ah_capabilities.cap_has_phyerr_counters ?
0657 "yes" : "no");
0658 len += scnprintf(buf + len, sizeof(buf) - len,
0659 "HW max spur immunity level:\t%d\n",
0660 as->max_spur_level);
0661 len += scnprintf(buf + len, sizeof(buf) - len,
0662 "\nANI state\n--------------------------------------------\n");
0663 len += scnprintf(buf + len, sizeof(buf) - len, "operating mode:\t\t\t");
0664 switch (as->ani_mode) {
0665 case ATH5K_ANI_MODE_OFF:
0666 len += scnprintf(buf + len, sizeof(buf) - len, "OFF\n");
0667 break;
0668 case ATH5K_ANI_MODE_MANUAL_LOW:
0669 len += scnprintf(buf + len, sizeof(buf) - len,
0670 "MANUAL LOW\n");
0671 break;
0672 case ATH5K_ANI_MODE_MANUAL_HIGH:
0673 len += scnprintf(buf + len, sizeof(buf) - len,
0674 "MANUAL HIGH\n");
0675 break;
0676 case ATH5K_ANI_MODE_AUTO:
0677 len += scnprintf(buf + len, sizeof(buf) - len, "AUTO\n");
0678 break;
0679 default:
0680 len += scnprintf(buf + len, sizeof(buf) - len,
0681 "??? (not good)\n");
0682 break;
0683 }
0684 len += scnprintf(buf + len, sizeof(buf) - len,
0685 "noise immunity level:\t\t%d\n",
0686 as->noise_imm_level);
0687 len += scnprintf(buf + len, sizeof(buf) - len,
0688 "spur immunity level:\t\t%d\n",
0689 as->spur_level);
0690 len += scnprintf(buf + len, sizeof(buf) - len,
0691 "firstep level:\t\t\t%d\n",
0692 as->firstep_level);
0693 len += scnprintf(buf + len, sizeof(buf) - len,
0694 "OFDM weak signal detection:\t%s\n",
0695 as->ofdm_weak_sig ? "on" : "off");
0696 len += scnprintf(buf + len, sizeof(buf) - len,
0697 "CCK weak signal detection:\t%s\n",
0698 as->cck_weak_sig ? "on" : "off");
0699
0700 len += scnprintf(buf + len, sizeof(buf) - len,
0701 "\nMIB INTERRUPTS:\t\t%u\n",
0702 st->mib_intr);
0703 len += scnprintf(buf + len, sizeof(buf) - len,
0704 "beacon RSSI average:\t%d\n",
0705 (int)ewma_beacon_rssi_read(&ah->ah_beacon_rssi_avg));
0706
0707 #define CC_PRINT(_struct, _field) \
0708 _struct._field, \
0709 _struct.cycles > 0 ? \
0710 _struct._field * 100 / _struct.cycles : 0
0711
0712 len += scnprintf(buf + len, sizeof(buf) - len,
0713 "profcnt tx\t\t%u\t(%d%%)\n",
0714 CC_PRINT(as->last_cc, tx_frame));
0715 len += scnprintf(buf + len, sizeof(buf) - len,
0716 "profcnt rx\t\t%u\t(%d%%)\n",
0717 CC_PRINT(as->last_cc, rx_frame));
0718 len += scnprintf(buf + len, sizeof(buf) - len,
0719 "profcnt busy\t\t%u\t(%d%%)\n",
0720 CC_PRINT(as->last_cc, rx_busy));
0721 #undef CC_PRINT
0722 len += scnprintf(buf + len, sizeof(buf) - len, "profcnt cycles\t\t%u\n",
0723 as->last_cc.cycles);
0724 len += scnprintf(buf + len, sizeof(buf) - len,
0725 "listen time\t\t%d\tlast: %d\n",
0726 as->listen_time, as->last_listen);
0727 len += scnprintf(buf + len, sizeof(buf) - len,
0728 "OFDM errors\t\t%u\tlast: %u\tsum: %u\n",
0729 as->ofdm_errors, as->last_ofdm_errors,
0730 as->sum_ofdm_errors);
0731 len += scnprintf(buf + len, sizeof(buf) - len,
0732 "CCK errors\t\t%u\tlast: %u\tsum: %u\n",
0733 as->cck_errors, as->last_cck_errors,
0734 as->sum_cck_errors);
0735 len += scnprintf(buf + len, sizeof(buf) - len,
0736 "AR5K_PHYERR_CNT1\t%x\t(=%d)\n",
0737 ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1),
0738 ATH5K_ANI_OFDM_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX -
0739 ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1)));
0740 len += scnprintf(buf + len, sizeof(buf) - len,
0741 "AR5K_PHYERR_CNT2\t%x\t(=%d)\n",
0742 ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2),
0743 ATH5K_ANI_CCK_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX -
0744 ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2)));
0745
0746 if (len > sizeof(buf))
0747 len = sizeof(buf);
0748
0749 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0750 }
0751
0752 static ssize_t write_file_ani(struct file *file,
0753 const char __user *userbuf,
0754 size_t count, loff_t *ppos)
0755 {
0756 struct ath5k_hw *ah = file->private_data;
0757 char buf[20];
0758
0759 count = min_t(size_t, count, sizeof(buf) - 1);
0760 if (copy_from_user(buf, userbuf, count))
0761 return -EFAULT;
0762
0763 buf[count] = '\0';
0764 if (strncmp(buf, "sens-low", 8) == 0) {
0765 ath5k_ani_init(ah, ATH5K_ANI_MODE_MANUAL_HIGH);
0766 } else if (strncmp(buf, "sens-high", 9) == 0) {
0767 ath5k_ani_init(ah, ATH5K_ANI_MODE_MANUAL_LOW);
0768 } else if (strncmp(buf, "ani-off", 7) == 0) {
0769 ath5k_ani_init(ah, ATH5K_ANI_MODE_OFF);
0770 } else if (strncmp(buf, "ani-on", 6) == 0) {
0771 ath5k_ani_init(ah, ATH5K_ANI_MODE_AUTO);
0772 } else if (strncmp(buf, "noise-low", 9) == 0) {
0773 ath5k_ani_set_noise_immunity_level(ah, 0);
0774 } else if (strncmp(buf, "noise-high", 10) == 0) {
0775 ath5k_ani_set_noise_immunity_level(ah,
0776 ATH5K_ANI_MAX_NOISE_IMM_LVL);
0777 } else if (strncmp(buf, "spur-low", 8) == 0) {
0778 ath5k_ani_set_spur_immunity_level(ah, 0);
0779 } else if (strncmp(buf, "spur-high", 9) == 0) {
0780 ath5k_ani_set_spur_immunity_level(ah,
0781 ah->ani_state.max_spur_level);
0782 } else if (strncmp(buf, "fir-low", 7) == 0) {
0783 ath5k_ani_set_firstep_level(ah, 0);
0784 } else if (strncmp(buf, "fir-high", 8) == 0) {
0785 ath5k_ani_set_firstep_level(ah, ATH5K_ANI_MAX_FIRSTEP_LVL);
0786 } else if (strncmp(buf, "ofdm-off", 8) == 0) {
0787 ath5k_ani_set_ofdm_weak_signal_detection(ah, false);
0788 } else if (strncmp(buf, "ofdm-on", 7) == 0) {
0789 ath5k_ani_set_ofdm_weak_signal_detection(ah, true);
0790 } else if (strncmp(buf, "cck-off", 7) == 0) {
0791 ath5k_ani_set_cck_weak_signal_detection(ah, false);
0792 } else if (strncmp(buf, "cck-on", 6) == 0) {
0793 ath5k_ani_set_cck_weak_signal_detection(ah, true);
0794 }
0795 return count;
0796 }
0797
0798 static const struct file_operations fops_ani = {
0799 .read = read_file_ani,
0800 .write = write_file_ani,
0801 .open = simple_open,
0802 .owner = THIS_MODULE,
0803 .llseek = default_llseek,
0804 };
0805
0806
0807
0808
0809 static ssize_t read_file_queue(struct file *file, char __user *user_buf,
0810 size_t count, loff_t *ppos)
0811 {
0812 struct ath5k_hw *ah = file->private_data;
0813 char buf[700];
0814 unsigned int len = 0;
0815
0816 struct ath5k_txq *txq;
0817 struct ath5k_buf *bf, *bf0;
0818 int i, n;
0819
0820 len += scnprintf(buf + len, sizeof(buf) - len,
0821 "available txbuffers: %d\n", ah->txbuf_len);
0822
0823 for (i = 0; i < ARRAY_SIZE(ah->txqs); i++) {
0824 txq = &ah->txqs[i];
0825
0826 len += scnprintf(buf + len, sizeof(buf) - len,
0827 "%02d: %ssetup\n", i, txq->setup ? "" : "not ");
0828
0829 if (!txq->setup)
0830 continue;
0831
0832 n = 0;
0833 spin_lock_bh(&txq->lock);
0834 list_for_each_entry_safe(bf, bf0, &txq->q, list)
0835 n++;
0836 spin_unlock_bh(&txq->lock);
0837
0838 len += scnprintf(buf + len, sizeof(buf) - len,
0839 " len: %d bufs: %d\n", txq->txq_len, n);
0840 len += scnprintf(buf + len, sizeof(buf) - len,
0841 " stuck: %d\n", txq->txq_stuck);
0842 }
0843
0844 if (len > sizeof(buf))
0845 len = sizeof(buf);
0846
0847 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0848 }
0849
0850 static ssize_t write_file_queue(struct file *file,
0851 const char __user *userbuf,
0852 size_t count, loff_t *ppos)
0853 {
0854 struct ath5k_hw *ah = file->private_data;
0855 char buf[20];
0856
0857 count = min_t(size_t, count, sizeof(buf) - 1);
0858 if (copy_from_user(buf, userbuf, count))
0859 return -EFAULT;
0860
0861 buf[count] = '\0';
0862 if (strncmp(buf, "start", 5) == 0)
0863 ieee80211_wake_queues(ah->hw);
0864 else if (strncmp(buf, "stop", 4) == 0)
0865 ieee80211_stop_queues(ah->hw);
0866
0867 return count;
0868 }
0869
0870
0871 static const struct file_operations fops_queue = {
0872 .read = read_file_queue,
0873 .write = write_file_queue,
0874 .open = simple_open,
0875 .owner = THIS_MODULE,
0876 .llseek = default_llseek,
0877 };
0878
0879
0880
0881 struct eeprom_private {
0882 u16 *buf;
0883 int len;
0884 };
0885
0886 static int open_file_eeprom(struct inode *inode, struct file *file)
0887 {
0888 struct eeprom_private *ep;
0889 struct ath5k_hw *ah = inode->i_private;
0890 bool res;
0891 int i, ret;
0892 u32 eesize;
0893 u16 val, *buf;
0894
0895
0896
0897 res = ath5k_hw_nvram_read(ah, AR5K_EEPROM_SIZE_UPPER, &val);
0898 if (!res)
0899 return -EACCES;
0900
0901 if (val == 0) {
0902 eesize = AR5K_EEPROM_INFO_MAX + AR5K_EEPROM_INFO_BASE;
0903 } else {
0904 eesize = (val & AR5K_EEPROM_SIZE_UPPER_MASK) <<
0905 AR5K_EEPROM_SIZE_ENDLOC_SHIFT;
0906 ath5k_hw_nvram_read(ah, AR5K_EEPROM_SIZE_LOWER, &val);
0907 eesize = eesize | val;
0908 }
0909
0910 if (eesize > 4096)
0911 return -EINVAL;
0912
0913
0914
0915 buf = vmalloc(array_size(eesize, 2));
0916 if (!buf) {
0917 ret = -ENOMEM;
0918 goto err;
0919 }
0920
0921 for (i = 0; i < eesize; ++i) {
0922 if (!ath5k_hw_nvram_read(ah, i, &val)) {
0923 ret = -EIO;
0924 goto freebuf;
0925 }
0926 buf[i] = val;
0927 }
0928
0929
0930
0931 ep = kmalloc(sizeof(*ep), GFP_KERNEL);
0932 if (!ep) {
0933 ret = -ENOMEM;
0934 goto freebuf;
0935 }
0936
0937 ep->buf = buf;
0938 ep->len = eesize * 2;
0939
0940 file->private_data = (void *)ep;
0941
0942 return 0;
0943
0944 freebuf:
0945 vfree(buf);
0946 err:
0947 return ret;
0948
0949 }
0950
0951 static ssize_t read_file_eeprom(struct file *file, char __user *user_buf,
0952 size_t count, loff_t *ppos)
0953 {
0954 struct eeprom_private *ep = file->private_data;
0955
0956 return simple_read_from_buffer(user_buf, count, ppos, ep->buf, ep->len);
0957 }
0958
0959 static int release_file_eeprom(struct inode *inode, struct file *file)
0960 {
0961 struct eeprom_private *ep = file->private_data;
0962
0963 vfree(ep->buf);
0964 kfree(ep);
0965
0966 return 0;
0967 }
0968
0969 static const struct file_operations fops_eeprom = {
0970 .open = open_file_eeprom,
0971 .read = read_file_eeprom,
0972 .release = release_file_eeprom,
0973 .owner = THIS_MODULE,
0974 };
0975
0976
0977 void
0978 ath5k_debug_init_device(struct ath5k_hw *ah)
0979 {
0980 struct dentry *phydir;
0981
0982 ah->debug.level = ath5k_debug;
0983
0984 phydir = debugfs_create_dir("ath5k", ah->hw->wiphy->debugfsdir);
0985 if (!phydir)
0986 return;
0987
0988 debugfs_create_file("debug", 0600, phydir, ah, &fops_debug);
0989 debugfs_create_file("registers", 0400, phydir, ah, ®isters_fops);
0990 debugfs_create_file("beacon", 0600, phydir, ah, &fops_beacon);
0991 debugfs_create_file("reset", 0200, phydir, ah, &fops_reset);
0992 debugfs_create_file("antenna", 0600, phydir, ah, &fops_antenna);
0993 debugfs_create_file("misc", 0400, phydir, ah, &fops_misc);
0994 debugfs_create_file("eeprom", 0400, phydir, ah, &fops_eeprom);
0995 debugfs_create_file("frameerrors", 0600, phydir, ah, &fops_frameerrors);
0996 debugfs_create_file("ani", 0600, phydir, ah, &fops_ani);
0997 debugfs_create_file("queue", 0600, phydir, ah, &fops_queue);
0998 debugfs_create_bool("32khz_clock", 0600, phydir,
0999 &ah->ah_use_32khz_clock);
1000 }
1001
1002
1003
1004 void
1005 ath5k_debug_dump_bands(struct ath5k_hw *ah)
1006 {
1007 unsigned int b, i;
1008
1009 if (likely(!(ah->debug.level & ATH5K_DEBUG_DUMPBANDS)))
1010 return;
1011
1012 for (b = 0; b < NUM_NL80211_BANDS; b++) {
1013 struct ieee80211_supported_band *band = &ah->sbands[b];
1014 char bname[6];
1015 switch (band->band) {
1016 case NL80211_BAND_2GHZ:
1017 strcpy(bname, "2 GHz");
1018 break;
1019 case NL80211_BAND_5GHZ:
1020 strcpy(bname, "5 GHz");
1021 break;
1022 default:
1023 printk(KERN_DEBUG "Band not supported: %d\n",
1024 band->band);
1025 return;
1026 }
1027 printk(KERN_DEBUG "Band %s: channels %d, rates %d\n", bname,
1028 band->n_channels, band->n_bitrates);
1029 printk(KERN_DEBUG " channels:\n");
1030 for (i = 0; i < band->n_channels; i++)
1031 printk(KERN_DEBUG " %3d %d %.4x %.4x\n",
1032 ieee80211_frequency_to_channel(
1033 band->channels[i].center_freq),
1034 band->channels[i].center_freq,
1035 band->channels[i].hw_value,
1036 band->channels[i].flags);
1037 printk(KERN_DEBUG " rates:\n");
1038 for (i = 0; i < band->n_bitrates; i++)
1039 printk(KERN_DEBUG " %4d %.4x %.4x %.4x\n",
1040 band->bitrates[i].bitrate,
1041 band->bitrates[i].hw_value,
1042 band->bitrates[i].flags,
1043 band->bitrates[i].hw_value_short);
1044 }
1045 }
1046
1047 static inline void
1048 ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done,
1049 struct ath5k_rx_status *rs)
1050 {
1051 struct ath5k_desc *ds = bf->desc;
1052 struct ath5k_hw_all_rx_desc *rd = &ds->ud.ds_rx;
1053
1054 printk(KERN_DEBUG "R (%p %llx) %08x %08x %08x %08x %08x %08x %c\n",
1055 ds, (unsigned long long)bf->daddr,
1056 ds->ds_link, ds->ds_data,
1057 rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1,
1058 rd->rx_stat.rx_status_0, rd->rx_stat.rx_status_1,
1059 !done ? ' ' : (rs->rs_status == 0) ? '*' : '!');
1060 }
1061
1062 void
1063 ath5k_debug_printrxbuffs(struct ath5k_hw *ah)
1064 {
1065 struct ath5k_desc *ds;
1066 struct ath5k_buf *bf;
1067 struct ath5k_rx_status rs = {};
1068 int status;
1069
1070 if (likely(!(ah->debug.level & ATH5K_DEBUG_DESC)))
1071 return;
1072
1073 printk(KERN_DEBUG "rxdp %x, rxlink %p\n",
1074 ath5k_hw_get_rxdp(ah), ah->rxlink);
1075
1076 spin_lock_bh(&ah->rxbuflock);
1077 list_for_each_entry(bf, &ah->rxbuf, list) {
1078 ds = bf->desc;
1079 status = ah->ah_proc_rx_desc(ah, ds, &rs);
1080 if (!status)
1081 ath5k_debug_printrxbuf(bf, status == 0, &rs);
1082 }
1083 spin_unlock_bh(&ah->rxbuflock);
1084 }
1085
1086 void
1087 ath5k_debug_printtxbuf(struct ath5k_hw *ah, struct ath5k_buf *bf)
1088 {
1089 struct ath5k_desc *ds = bf->desc;
1090 struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212;
1091 struct ath5k_tx_status ts = {};
1092 int done;
1093
1094 if (likely(!(ah->debug.level & ATH5K_DEBUG_DESC)))
1095 return;
1096
1097 done = ah->ah_proc_tx_desc(ah, bf->desc, &ts);
1098
1099 printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x "
1100 "%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link,
1101 ds->ds_data, td->tx_ctl.tx_control_0, td->tx_ctl.tx_control_1,
1102 td->tx_ctl.tx_control_2, td->tx_ctl.tx_control_3,
1103 td->tx_stat.tx_status_0, td->tx_stat.tx_status_1,
1104 done ? ' ' : (ts.ts_status == 0) ? '*' : '!');
1105 }