aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBruno Randolf <br1@einfach.org>2010-03-09 02:55:17 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-03-10 17:44:30 -0500
commit604eeadd1880bddfb155369491cc13fb8d3f9df6 (patch)
treec9a7357fa34d9751c0dc2b36fb1004281a083cfb /drivers
parent5a7d05830de1ecfdaf0a9fb43e4aa08abbdbfe9f (diff)
ath5k: add antenna statistics and debugfs file for antenna settings
keep statistics about which antenna was used for TX and RX. this is used only for debugging right now, but might have other applications later. add a new file 'antenna' in debugfs (/sys/kernel/debug/ath5k/phy0/antenna) to show antenna use statistics and antenna diversity related register values. it can also be used to set the antenna mode until we have proper support for that in iw: - echo diversity > antenna: use default antenna mode (RX and TX diversity) - echo fixed-a > antenna: use fixed antenna A for RX and TX - echo fixed-b > antenna: use fixed antenna B for RX and TX - echo clear > antenna: reset antenna statistics Signed-off-by: Bruno Randolf <br1@einfach.org> Acked-by: Nick Kossifidis <mickflemm@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c11
-rw-r--r--drivers/net/wireless/ath/ath5k/base.h8
-rw-r--r--drivers/net/wireless/ath/ath5k/debug.c106
-rw-r--r--drivers/net/wireless/ath/ath5k/debug.h1
4 files changed, 126 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 7c08434ebd1a..e7a989c707ac 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -1997,6 +1997,12 @@ accept:
1997 rxs->signal = rxs->noise + rs.rs_rssi; 1997 rxs->signal = rxs->noise + rs.rs_rssi;
1998 1998
1999 rxs->antenna = rs.rs_antenna; 1999 rxs->antenna = rs.rs_antenna;
2000
2001 if (rs.rs_antenna > 0 && rs.rs_antenna < 5)
2002 sc->stats.antenna_rx[rs.rs_antenna]++;
2003 else
2004 sc->stats.antenna_rx[0]++; /* invalid */
2005
2000 rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); 2006 rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate);
2001 rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); 2007 rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs);
2002 2008
@@ -2090,6 +2096,11 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
2090 */ 2096 */
2091 ath5k_remove_padding(skb); 2097 ath5k_remove_padding(skb);
2092 2098
2099 if (ts.ts_antenna > 0 && ts.ts_antenna < 5)
2100 sc->stats.antenna_tx[ts.ts_antenna]++;
2101 else
2102 sc->stats.antenna_tx[0]++; /* invalid */
2103
2093 ieee80211_tx_status(sc->hw, skb); 2104 ieee80211_tx_status(sc->hw, skb);
2094 2105
2095 spin_lock(&sc->txbuflock); 2106 spin_lock(&sc->txbuflock);
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h
index 7e1a88a5abdb..ca525842d827 100644
--- a/drivers/net/wireless/ath/ath5k/base.h
+++ b/drivers/net/wireless/ath/ath5k/base.h
@@ -105,6 +105,12 @@ struct ath5k_rfkill {
105 struct tasklet_struct toggleq; 105 struct tasklet_struct toggleq;
106}; 106};
107 107
108/* statistics (only used for debugging now) */
109struct ath5k_statistics {
110 unsigned int antenna_rx[5]; /* frames count per antenna RX */
111 unsigned int antenna_tx[5]; /* frames count per antenna TX */
112};
113
108#if CHAN_DEBUG 114#if CHAN_DEBUG
109#define ATH_CHAN_MAX (26+26+26+200+200) 115#define ATH_CHAN_MAX (26+26+26+200+200)
110#else 116#else
@@ -191,6 +197,8 @@ struct ath5k_softc {
191 int power_level; /* Requested tx power in dbm */ 197 int power_level; /* Requested tx power in dbm */
192 bool assoc; /* associate state */ 198 bool assoc; /* associate state */
193 bool enable_beacon; /* true if beacons are on */ 199 bool enable_beacon; /* true if beacons are on */
200
201 struct ath5k_statistics stats;
194}; 202};
195 203
196#define ath5k_hw_hasbssidmask(_ah) \ 204#define ath5k_hw_hasbssidmask(_ah) \
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c
index 747508c15d34..236f20f9cd40 100644
--- a/drivers/net/wireless/ath/ath5k/debug.c
+++ b/drivers/net/wireless/ath/ath5k/debug.c
@@ -364,6 +364,107 @@ static const struct file_operations fops_debug = {
364}; 364};
365 365
366 366
367/* debugfs: antenna */
368
369static ssize_t read_file_antenna(struct file *file, char __user *user_buf,
370 size_t count, loff_t *ppos)
371{
372 struct ath5k_softc *sc = file->private_data;
373 char buf[700];
374 unsigned int len = 0;
375 unsigned int i;
376 unsigned int v;
377
378 len += snprintf(buf+len, sizeof(buf)-len, "antenna mode\t%d\n",
379 sc->ah->ah_ant_mode);
380 len += snprintf(buf+len, sizeof(buf)-len, "default antenna\t%d\n",
381 sc->ah->ah_def_ant);
382 len += snprintf(buf+len, sizeof(buf)-len, "tx antenna\t%d\n",
383 sc->ah->ah_tx_ant);
384
385 len += snprintf(buf+len, sizeof(buf)-len, "\nANTENNA\t\tRX\tTX\n");
386 for (i = 1; i < ARRAY_SIZE(sc->stats.antenna_rx); i++) {
387 len += snprintf(buf+len, sizeof(buf)-len,
388 "[antenna %d]\t%d\t%d\n",
389 i, sc->stats.antenna_rx[i], sc->stats.antenna_tx[i]);
390 }
391 len += snprintf(buf+len, sizeof(buf)-len, "[invalid]\t%d\t%d\n",
392 sc->stats.antenna_rx[0], sc->stats.antenna_tx[0]);
393
394 v = ath5k_hw_reg_read(sc->ah, AR5K_DEFAULT_ANTENNA);
395 len += snprintf(buf+len, sizeof(buf)-len,
396 "\nAR5K_DEFAULT_ANTENNA\t0x%08x\n", v);
397
398 v = ath5k_hw_reg_read(sc->ah, AR5K_STA_ID1);
399 len += snprintf(buf+len, sizeof(buf)-len,
400 "AR5K_STA_ID1_DEFAULT_ANTENNA\t%d\n",
401 (v & AR5K_STA_ID1_DEFAULT_ANTENNA) != 0);
402 len += snprintf(buf+len, sizeof(buf)-len,
403 "AR5K_STA_ID1_DESC_ANTENNA\t%d\n",
404 (v & AR5K_STA_ID1_DESC_ANTENNA) != 0);
405 len += snprintf(buf+len, sizeof(buf)-len,
406 "AR5K_STA_ID1_RTS_DEF_ANTENNA\t%d\n",
407 (v & AR5K_STA_ID1_RTS_DEF_ANTENNA) != 0);
408 len += snprintf(buf+len, sizeof(buf)-len,
409 "AR5K_STA_ID1_SELFGEN_DEF_ANT\t%d\n",
410 (v & AR5K_STA_ID1_SELFGEN_DEF_ANT) != 0);
411
412 v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_AGCCTL);
413 len += snprintf(buf+len, sizeof(buf)-len,
414 "\nAR5K_PHY_AGCCTL_OFDM_DIV_DIS\t%d\n",
415 (v & AR5K_PHY_AGCCTL_OFDM_DIV_DIS) != 0);
416
417 v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_RESTART);
418 len += snprintf(buf+len, sizeof(buf)-len,
419 "AR5K_PHY_RESTART_DIV_GC\t\t%x\n",
420 (v & AR5K_PHY_RESTART_DIV_GC) >> AR5K_PHY_RESTART_DIV_GC_S);
421
422 v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_FAST_ANT_DIV);
423 len += snprintf(buf+len, sizeof(buf)-len,
424 "AR5K_PHY_FAST_ANT_DIV_EN\t%d\n",
425 (v & AR5K_PHY_FAST_ANT_DIV_EN) != 0);
426
427 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
428}
429
430static ssize_t write_file_antenna(struct file *file,
431 const char __user *userbuf,
432 size_t count, loff_t *ppos)
433{
434 struct ath5k_softc *sc = file->private_data;
435 unsigned int i;
436 char buf[20];
437
438 if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
439 return -EFAULT;
440
441 if (strncmp(buf, "diversity", 9) == 0) {
442 ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_DEFAULT);
443 printk(KERN_INFO "ath5k debug: enable diversity\n");
444 } else if (strncmp(buf, "fixed-a", 7) == 0) {
445 ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_A);
446 printk(KERN_INFO "ath5k debugfs: fixed antenna A\n");
447 } else if (strncmp(buf, "fixed-b", 7) == 0) {
448 ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_B);
449 printk(KERN_INFO "ath5k debug: fixed antenna B\n");
450 } else if (strncmp(buf, "clear", 5) == 0) {
451 for (i = 0; i < ARRAY_SIZE(sc->stats.antenna_rx); i++) {
452 sc->stats.antenna_rx[i] = 0;
453 sc->stats.antenna_tx[i] = 0;
454 }
455 printk(KERN_INFO "ath5k debug: cleared antenna stats\n");
456 }
457 return count;
458}
459
460static const struct file_operations fops_antenna = {
461 .read = read_file_antenna,
462 .write = write_file_antenna,
463 .open = ath5k_debugfs_open,
464 .owner = THIS_MODULE,
465};
466
467
367/* init */ 468/* init */
368 469
369void 470void
@@ -393,6 +494,10 @@ ath5k_debug_init_device(struct ath5k_softc *sc)
393 494
394 sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR, 495 sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR,
395 sc->debug.debugfs_phydir, sc, &fops_reset); 496 sc->debug.debugfs_phydir, sc, &fops_reset);
497
498 sc->debug.debugfs_antenna = debugfs_create_file("antenna",
499 S_IWUSR | S_IRUSR,
500 sc->debug.debugfs_phydir, sc, &fops_antenna);
396} 501}
397 502
398void 503void
@@ -408,6 +513,7 @@ ath5k_debug_finish_device(struct ath5k_softc *sc)
408 debugfs_remove(sc->debug.debugfs_registers); 513 debugfs_remove(sc->debug.debugfs_registers);
409 debugfs_remove(sc->debug.debugfs_beacon); 514 debugfs_remove(sc->debug.debugfs_beacon);
410 debugfs_remove(sc->debug.debugfs_reset); 515 debugfs_remove(sc->debug.debugfs_reset);
516 debugfs_remove(sc->debug.debugfs_antenna);
411 debugfs_remove(sc->debug.debugfs_phydir); 517 debugfs_remove(sc->debug.debugfs_phydir);
412} 518}
413 519
diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h
index 66f69f04e55e..018612711045 100644
--- a/drivers/net/wireless/ath/ath5k/debug.h
+++ b/drivers/net/wireless/ath/ath5k/debug.h
@@ -74,6 +74,7 @@ struct ath5k_dbg_info {
74 struct dentry *debugfs_registers; 74 struct dentry *debugfs_registers;
75 struct dentry *debugfs_beacon; 75 struct dentry *debugfs_beacon;
76 struct dentry *debugfs_reset; 76 struct dentry *debugfs_reset;
77 struct dentry *debugfs_antenna;
77}; 78};
78 79
79/** 80/**