Skip to content

Commit

Permalink
ath5k: add antenna statistics and debugfs file for antenna settings
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Bruno Randolf authored and John W. Linville committed Mar 10, 2010
1 parent 5a7d058 commit 604eead
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 0 deletions.
11 changes: 11 additions & 0 deletions drivers/net/wireless/ath/ath5k/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -1997,6 +1997,12 @@ ath5k_tasklet_rx(unsigned long data)
rxs->signal = rxs->noise + rs.rs_rssi;

rxs->antenna = rs.rs_antenna;

if (rs.rs_antenna > 0 && rs.rs_antenna < 5)
sc->stats.antenna_rx[rs.rs_antenna]++;
else
sc->stats.antenna_rx[0]++; /* invalid */

rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate);
rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs);

Expand Down Expand Up @@ -2090,6 +2096,11 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
*/
ath5k_remove_padding(skb);

if (ts.ts_antenna > 0 && ts.ts_antenna < 5)
sc->stats.antenna_tx[ts.ts_antenna]++;
else
sc->stats.antenna_tx[0]++; /* invalid */

ieee80211_tx_status(sc->hw, skb);

spin_lock(&sc->txbuflock);
Expand Down
8 changes: 8 additions & 0 deletions drivers/net/wireless/ath/ath5k/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,12 @@ struct ath5k_rfkill {
struct tasklet_struct toggleq;
};

/* statistics (only used for debugging now) */
struct ath5k_statistics {
unsigned int antenna_rx[5]; /* frames count per antenna RX */
unsigned int antenna_tx[5]; /* frames count per antenna TX */
};

#if CHAN_DEBUG
#define ATH_CHAN_MAX (26+26+26+200+200)
#else
Expand Down Expand Up @@ -191,6 +197,8 @@ struct ath5k_softc {
int power_level; /* Requested tx power in dbm */
bool assoc; /* associate state */
bool enable_beacon; /* true if beacons are on */

struct ath5k_statistics stats;
};

#define ath5k_hw_hasbssidmask(_ah) \
Expand Down
106 changes: 106 additions & 0 deletions drivers/net/wireless/ath/ath5k/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,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->stats.antenna_rx); i++) {
len += snprintf(buf+len, sizeof(buf)-len,
"[antenna %d]\t%d\t%d\n",
i, sc->stats.antenna_rx[i], sc->stats.antenna_tx[i]);
}
len += snprintf(buf+len, sizeof(buf)-len, "[invalid]\t%d\t%d\n",
sc->stats.antenna_rx[0], sc->stats.antenna_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->stats.antenna_rx); i++) {
sc->stats.antenna_rx[i] = 0;
sc->stats.antenna_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
Expand Down Expand Up @@ -393,6 +494,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
Expand All @@ -408,6 +513,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);
}

Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/ath/ath5k/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ struct ath5k_dbg_info {
struct dentry *debugfs_registers;
struct dentry *debugfs_beacon;
struct dentry *debugfs_reset;
struct dentry *debugfs_antenna;
};

/**
Expand Down

0 comments on commit 604eead

Please sign in to comment.