diff mbox

[2/5] ath5k: add antenna statistics and debugfs file for antenna settings

Message ID 20100301115908.13996.83859.stgit@void (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Bruno Randolf March 1, 2010, 11:59 a.m. UTC
None
diff mbox

Patch

diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 904d7f0..79b548c 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -1951,6 +1951,12 @@  accept:
 		rxs->signal = rxs->noise + rs.rs_rssi;
 
 		rxs->antenna = rs.rs_antenna;
+
+		if (rs.rs_antenna > 0 && rs.rs_antenna < 5)
+			sc->ant_stats_rx[rs.rs_antenna]++;
+		else
+			sc->ant_stats_rx[0]++; /* invalid */
+
 		rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate);
 		rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs);
 
@@ -2038,6 +2044,11 @@  ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
 			info->status.ack_signal = ts.ts_rssi;
 		}
 
+		if (ts.ts_antenna > 0 && ts.ts_antenna < 5)
+			sc->ant_stats_tx[ts.ts_antenna]++;
+		else
+			sc->ant_stats_tx[0]++; /* invalid */
+
 		ieee80211_tx_status(sc->hw, skb);
 
 		spin_lock(&sc->txbuflock);
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h
index 7e1a88a..2318fa6 100644
--- a/drivers/net/wireless/ath/ath5k/base.h
+++ b/drivers/net/wireless/ath/ath5k/base.h
@@ -191,6 +191,9 @@  struct ath5k_softc {
 	int 			power_level;	/* Requested tx power in dbm */
 	bool			assoc;		/* associate state */
 	bool			enable_beacon;	/* true if beacons are on */
+
+	int			ant_stats_rx[5];/* antenna use statistics RX */
+	int			ant_stats_tx[5];/* antenna use statistics TX */
 };
 
 #define ath5k_hw_hasbssidmask(_ah) \
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c
index 747508c..148963b 100644
--- a/drivers/net/wireless/ath/ath5k/debug.c
+++ b/drivers/net/wireless/ath/ath5k/debug.c
@@ -138,6 +138,11 @@  static const struct reg regs[] = {
 	REG_STRUCT_INIT(AR5K_GPIOCR),
 	REG_STRUCT_INIT(AR5K_GPIODO),
 	REG_STRUCT_INIT(AR5K_SREV),
+	REG_STRUCT_INIT(AR5K_DEFAULT_ANTENNA),
+	REG_STRUCT_INIT(AR5K_STA_ID1),
+	REG_STRUCT_INIT(AR5K_PHY_AGCCTL),
+	REG_STRUCT_INIT(AR5K_PHY_RESTART),
+	REG_STRUCT_INIT(AR5K_PHY_FAST_ANT_DIV)
 };
 
 static void *reg_start(struct seq_file *seq, loff_t *pos)
@@ -364,6 +369,107 @@  static const struct file_operations fops_debug = {
 };
 
 
+/* debugfs: antenna */
+
+static ssize_t read_file_antenna(struct file *file, char __user *user_buf,
+				   size_t count, loff_t *ppos)
+{
+	struct ath5k_softc *sc = file->private_data;
+	char buf[700];
+	unsigned int len = 0;
+	unsigned int i;
+	unsigned int v;
+
+	len += snprintf(buf+len, sizeof(buf)-len, "antenna mode\t%d\n",
+		sc->ah->ah_ant_mode);
+	len += snprintf(buf+len, sizeof(buf)-len, "default antenna\t%d\n",
+		sc->ah->ah_def_ant);
+	len += snprintf(buf+len, sizeof(buf)-len, "tx antenna\t%d\n",
+		sc->ah->ah_tx_ant);
+
+	len += snprintf(buf+len, sizeof(buf)-len, "\nANTENNA\t\tRX\tTX\n");
+	for (i = 1; i < ARRAY_SIZE(sc->ant_stats_rx); i++) {
+		len += snprintf(buf+len, sizeof(buf)-len,
+			"[antenna %d]\t%d\t%d\n",
+			i, sc->ant_stats_rx[i], sc->ant_stats_tx[i]);
+	}
+	len += snprintf(buf+len, sizeof(buf)-len, "[invalid]\t%d\t%d\n",
+			sc->ant_stats_rx[0], sc->ant_stats_tx[0]);
+
+	v = ath5k_hw_reg_read(sc->ah, AR5K_DEFAULT_ANTENNA);
+	len += snprintf(buf+len, sizeof(buf)-len,
+			"\nAR5K_DEFAULT_ANTENNA\t0x%08x\n", v);
+
+	v = ath5k_hw_reg_read(sc->ah, AR5K_STA_ID1);
+	len += snprintf(buf+len, sizeof(buf)-len,
+		"AR5K_STA_ID1_DEFAULT_ANTENNA\t%d\n",
+		(v & AR5K_STA_ID1_DEFAULT_ANTENNA) != 0);
+	len += snprintf(buf+len, sizeof(buf)-len,
+		"AR5K_STA_ID1_DESC_ANTENNA\t%d\n",
+		(v & AR5K_STA_ID1_DESC_ANTENNA) != 0);
+	len += snprintf(buf+len, sizeof(buf)-len,
+		"AR5K_STA_ID1_RTS_DEF_ANTENNA\t%d\n",
+		(v & AR5K_STA_ID1_RTS_DEF_ANTENNA) != 0);
+	len += snprintf(buf+len, sizeof(buf)-len,
+		"AR5K_STA_ID1_SELFGEN_DEF_ANT\t%d\n",
+		(v & AR5K_STA_ID1_SELFGEN_DEF_ANT) != 0);
+
+	v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_AGCCTL);
+	len += snprintf(buf+len, sizeof(buf)-len,
+		"\nAR5K_PHY_AGCCTL_OFDM_DIV_DIS\t%d\n",
+		(v & AR5K_PHY_AGCCTL_OFDM_DIV_DIS) != 0);
+
+	v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_RESTART);
+	len += snprintf(buf+len, sizeof(buf)-len,
+		"AR5K_PHY_RESTART_DIV_GC\t\t%x\n",
+		(v & AR5K_PHY_RESTART_DIV_GC) >> AR5K_PHY_RESTART_DIV_GC_S);
+
+	v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_FAST_ANT_DIV);
+	len += snprintf(buf+len, sizeof(buf)-len,
+		"AR5K_PHY_FAST_ANT_DIV_EN\t%d\n",
+		(v & AR5K_PHY_FAST_ANT_DIV_EN) != 0);
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_antenna(struct file *file,
+				 const char __user *userbuf,
+				 size_t count, loff_t *ppos)
+{
+	struct ath5k_softc *sc = file->private_data;
+	unsigned int i;
+	char buf[20];
+
+	if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
+		return -EFAULT;
+
+	if (strncmp(buf, "diversity", 9) == 0) {
+		ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_DEFAULT);
+		printk(KERN_INFO "ath5k debug: enable diversity\n");
+	} else if (strncmp(buf, "fixed-a", 7) == 0) {
+		ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_A);
+		printk(KERN_INFO "ath5k debugfs: fixed antenna A\n");
+	} else if (strncmp(buf, "fixed-b", 7) == 0) {
+		ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_B);
+		printk(KERN_INFO "ath5k debug: fixed antenna B\n");
+	} else if (strncmp(buf, "clear", 5) == 0) {
+		for (i = 0; i < ARRAY_SIZE(sc->ant_stats_rx); i++) {
+			sc->ant_stats_rx[i] = 0;
+			sc->ant_stats_tx[i] = 0;
+		}
+		printk(KERN_INFO "ath5k debug: cleared antenna stats\n");
+	}
+	return count;
+}
+
+static const struct file_operations fops_antenna = {
+	.read = read_file_antenna,
+	.write = write_file_antenna,
+	.open = ath5k_debugfs_open,
+	.owner = THIS_MODULE,
+};
+
+
 /* init */
 
 void
@@ -393,6 +499,10 @@  ath5k_debug_init_device(struct ath5k_softc *sc)
 
 	sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR,
 				sc->debug.debugfs_phydir, sc, &fops_reset);
+
+	sc->debug.debugfs_antenna = debugfs_create_file("antenna",
+				S_IWUSR | S_IRUSR,
+				sc->debug.debugfs_phydir, sc, &fops_antenna);
 }
 
 void
@@ -408,6 +518,7 @@  ath5k_debug_finish_device(struct ath5k_softc *sc)
 	debugfs_remove(sc->debug.debugfs_registers);
 	debugfs_remove(sc->debug.debugfs_beacon);
 	debugfs_remove(sc->debug.debugfs_reset);
+	debugfs_remove(sc->debug.debugfs_antenna);
 	debugfs_remove(sc->debug.debugfs_phydir);
 }
 
diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h
index 66f69f0..0186127 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 {
 	struct dentry		*debugfs_registers;
 	struct dentry		*debugfs_beacon;
 	struct dentry		*debugfs_reset;
+	struct dentry		*debugfs_antenna;
 };
 
 /**