all my ath5k patches
cover all my ath5k patches
since it must be difficult for john to track all the different revisions of my patches i send them here again as a clean series.
two of them are new:
ath5k: add debugfs file frameerrors
ath5k: Minor EEPROM documentation updates
others may be slightly updated.
greetings,
bruno
---
Bruno Randolf (13):
ath5k: add antenna statistics and debugfs file for antenna settings
ath5k: use fixed antenna for tx descriptors
ath5k: preserve antenna settings
ath5k: fix TSF reset
ath5k: remove double opmode definition
ath5k: remove ah_magic
ath5k: remove ah_mac_revision
ath5k: remove ah_gpio_npins
ath5k: add debugfs file frameerrors
ath5k: fix I/Q calibration (for real)
ath5k: read eeprom IQ calibration values correctly for G mode
ath5k: IQ calibration for AR5211 is slightly different
ath5k: Minor EEPROM documentation updates
drivers/net/wireless/ath/ath5k/ath5k.h | 7 - drivers/net/wireless/ath/ath5k/attach.c | 5 - drivers/net/wireless/ath/ath5k/base.c | 43 +++++- drivers/net/wireless/ath/ath5k/base.h | 20 +++ drivers/net/wireless/ath/ath5k/caps.c | 3 drivers/net/wireless/ath/ath5k/debug.c | 212 +++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath5k/debug.h | 2 drivers/net/wireless/ath/ath5k/desc.c | 6 - drivers/net/wireless/ath/ath5k/eeprom.c | 8 + drivers/net/wireless/ath/ath5k/eeprom.h | 88 +++++++++---- drivers/net/wireless/ath/ath5k/pcu.c | 14 +- drivers/net/wireless/ath/ath5k/phy.c | 51 ++++--- drivers/net/wireless/ath/ath5k/reg.h | 3 drivers/net/wireless/ath/ath5k/reset.c | 31 ++--- 14 files changed, 396 insertions(+), 97 deletions(-)
Signature · 1 line
Signature
PATCH 1/13 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
--- drivers/net/wireless/ath/ath5k/base.c | 11 +++ drivers/net/wireless/ath/ath5k/base.h | 8 ++ drivers/net/wireless/ath/ath5k/debug.c | 106 ++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath5k/debug.h | 1 4 files changed, 126 insertions(+), 0 deletions(-)
drivers/net/wireless/ath/ath5k/base.c +11 -0
@@ -1942,6 +1942,12 @@ accept: 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);
@@ -2029,6 +2035,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->stats.antenna_tx[ts.ts_antenna]++; +else + sc->stats.antenna_tx[0 ]++;/* invalid */ +ieee80211_tx_status (sc->hw, skb);spin_lock (&sc->txbuflock);
drivers/net/wireless/ath/ath5k/base.h +8 -0
@@ -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
@@ -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) \
drivers/net/wireless/ath/ath5k/debug.c +106 -0
124 lines not on this page · raw message
drivers/net/wireless/ath/ath5k/debug.h +1 -0
@@ -74,6 +74,7 @@ struct ath5k_dbg_info {struct dentry *debugfs_registers;struct dentry *debugfs_beacon;struct dentry *debugfs_reset; +struct dentry *debugfs_antenna; };/**
Re: [PATCH 01/13] ath5k: add antenna statistics and debugfs file for antenna settings
2010/3/9 Bruno Randolf <[email protected]>:
Quoted 220 lines
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 statisticsSigned-off-by Bruno Randolf <[email protected]>---
drivers/net/wireless/ath/ath5k/base.c | 11 +++drivers/net/wireless/ath/ath5k/base.h| 8 ++drivers/net/wireless/ath/ath5k/debug.c| 106 ++++++++++++++++++++++++++++++++drivers/net/wireless/ath/ath5k/debug.h| 14 files changed, 126 insertions(+), 0 deletions(-)drivers/net/wireless/ath/ath5k/base.c +11
-0@@ -1942,6 +1942,12 @@ accept: 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);@@ -2029,6 +2035,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->stats.antenna_tx[ts.ts_antenna]++; + else + sc->stats.antenna_tx[0]++; /* invalid */ + ieee80211_tx_status(sc->hw, skb); spin_lock(&sc->txbuflock);drivers/net/wireless/ath/ath5k/base.h +6
-0@@ -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@@ -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 */ +
+ structath5k_statisticsstats;
};#define
ath5k_hw_hasbssidmask(_ah)\drivers/net/wireless/ath/ath5k/debug.c +101
-0@@ -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
drivers/net/wireless/ath/ath5k/debug.c +4
-0@@ -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
drivers/net/wireless/ath/ath5k/debug.c +1
-0@@ -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); }drivers/net/wireless/ath/ath5k/debug.h +1
-1@@ -74,6 +74,7 @@ struct ath5k_dbg_info { struct dentry *debugfs_registers; struct dentry *debugfs_beacon; struct dentry *debugfs_reset; + struct dentry *debugfs_antenna; }; /** --
Quoted 4 lines
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
GPG ID: 0xD21DB2DB As you read this post global entropy rises. Have Fun ;-) Nick
PATCH 2/13 ath5k: use fixed antenna for tx descriptors
In reply to Bruno Randolfwhen using a fixed antenna we should use the antenna number in all tx descriptors, otherwise the hardware will sometimes send the frame out on the other antenna. it seems like the hardware does not always respect the default antenna and diversity settings (esp. AR5K_STA_ID1_DEFAULT_ANTENNA).
also i would like to note that antenna diversity does not always work correctly on 5414 (at least) when only one antenna is connected: for example all frames might be received on antenna A but still the HW tries to send on antenna B some times, causing packet loss.
this is both verified with the antenna statistics output of the previous patch and a spectrum analyzer.
--- drivers/net/wireless/ath/ath5k/phy.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
drivers/net/wireless/ath/ath5k/phy.c +2 -2
@@ -1873,7 +1873,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode)break ;case AR5K_ANTMODE_FIXED_A : def_ant =1 ; - tx_ant =0 ; + tx_ant =1 ; use_def_for_tx = true; update_def_on_tx = false; use_def_for_rts = true;
@@ -1882,7 +1882,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode)break ;case AR5K_ANTMODE_FIXED_B : def_ant =2 ; - tx_ant =0 ; + tx_ant =2 ; use_def_for_tx = true; update_def_on_tx = false; use_def_for_rts = true;
Re: [PATCH 02/13] ath5k: use fixed antenna for tx descriptors
2010/3/9 Bruno Randolf <[email protected]>:
Quoted 41 lines
when using a fixed antenna we should use the antenna number in all tx descriptors, otherwise the hardware will sometimes send the frame out on the other antenna. it seems like the hardware does not always respect the default antenna and diversity settings (esp. AR5K_STA_ID1_DEFAULT_ANTENNA).
also i would like to note that antenna diversity does not always work correctly on 5414 (at least) when only one antenna is connected: for example all frames might be received on antenna A but still the HW tries to send on antenna B some times, causing packet loss.
this is both verified with the antenna statistics output of the previous patch and a spectrum analyzer.
Signed-off-by Bruno Randolf <[email protected]>---
drivers/net/wireless/ath/ath5k/phy.c | 4 ++--1 files changed, 2 insertions(+), 2 deletions(-)drivers/net/wireless/ath/ath5k/phy.c +0
-0@@ -1873,7 +1873,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) break;case
AR5K_ANTMODE_FIXED_A:
def_ant = 1;
-tx_ant= 0;
+tx_ant= 1;
use_def_for_tx = true;
update_def_on_tx = false;
use_def_for_rts = true;drivers/net/wireless/ath/ath5k/phy.c +0
-0@@ -1882,7 +1882,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) break;case
AR5K_ANTMODE_FIXED_B:
def_ant = 2;
-tx_ant= 0;
+tx_ant= 2;
use_def_for_tx = true;
update_def_on_tx = false;
use_def_for_rts = true;
Quoted 5 lines
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
GPG ID: 0xD21DB2DB As you read this post global entropy rises. Have Fun ;-) Nick
PATCH 3/13 ath5k: preserve antenna settings
In reply to Bruno Randolfsave antenna settings and preserve across resets.
--- drivers/net/wireless/ath/ath5k/attach.c | 1 + drivers/net/wireless/ath/ath5k/base.c | 2 +- drivers/net/wireless/ath/ath5k/phy.c | 1 + 3 files changed, 3 insertions(+), 1 deletions(-)
drivers/net/wireless/ath/ath5k/attach.c +1 -0
@@ -123,6 +123,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) ah->ah_cw_min =AR5K_TUNE_CWMIN ; ah->ah_limit_tx_retries =AR5K_INIT_TX_RETRY ; ah->ah_software_retry = false; + ah->ah_ant_mode =AR5K_ANTMODE_DEFAULT ;/* * Find the mac version
drivers/net/wireless/ath/ath5k/base.c +1 -1
@@ -2916,7 +2916,7 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed)* then we must allow the user to set how many tx antennas we * have available */ -ath5k_hw_set_antenna_mode (ah,AR5K_ANTMODE_DEFAULT ); +ath5k_hw_set_antenna_mode (ah, ah->ah_ant_mode); unlock:mutex_unlock (&sc->lock);
drivers/net/wireless/ath/ath5k/phy.c +1 -0
@@ -1929,6 +1929,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) ah->ah_tx_ant = tx_ant; ah->ah_ant_mode = ant_mode; + ah->ah_def_ant = def_ant; sta_id1 |= use_def_for_tx ?AR5K_STA_ID1_DEFAULT_ANTENNA :0 ; sta_id1 |= update_def_on_tx ?AR5K_STA_ID1_DESC_ANTENNA :0 ;
Re: [PATCH 03/13] ath5k: preserve antenna settings
2010/3/9 Bruno Randolf <[email protected]>:
Quoted 48 lines
save antenna settings and preserve across resets.
Signed-off-by Bruno Randolf <[email protected]>---
drivers/net/wireless/ath/ath5k/attach.c | 1 +drivers/net/wireless/ath/ath5k/base.c| 2 +-drivers/net/wireless/ath/ath5k/phy.c| 1 +3 files changed, 3 insertions(+), 1 deletions(-)drivers/net/wireless/ath/ath5k/attach.c +1
-0@@ -123,6 +123,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) ah->ah_cw_min = AR5K_TUNE_CWMIN; ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; ah->ah_software_retry = false; + ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT; /** Find the mac version drivers/net/wireless/ath/ath5k/base.c +1
-1@@ -2916,7 +2916,7 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed)* then we must allow the user to set how many tx antennas we * have available */ - ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT); + ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode);unlock:
mutex_unlock(&sc->lock);drivers/net/wireless/ath/ath5k/phy.c +1
-1@@ -1929,6 +1929,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) ah->ah_tx_ant = tx_ant; ah->ah_ant_mode = ant_mode; + ah->ah_def_ant = def_ant; sta_id1 |= use_def_for_tx ? AR5K_STA_ID1_DEFAULT_ANTENNA : 0; sta_id1 |= update_def_on_tx ? AR5K_STA_ID1_DESC_ANTENNA : 0; --
Quoted 4 lines
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
GPG ID: 0xD21DB2DB As you read this post global entropy rises. Have Fun ;-) Nick
PATCH 4/13 ath5k: fix TSF reset
In reply to Bruno Randolfto reset the TSF, AR5K_BEACON_RESET_TSF has to be 1, not 0. also we have a function for that so use it.
--- drivers/net/wireless/ath/ath5k/reset.c | 7 +++---- 1 files changed, 3 insertions(+), 4 deletions(-)
drivers/net/wireless/ath/ath5k/reset.c +3 -4
@@ -1379,11 +1379,10 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,ath5k_hw_set_sleep_clock (ah, true);/* -* Disable beacons and reset the register +* Disable beacons and reset the TSF */ -AR5K_REG_DISABLE_BITS (ah,AR5K_BEACON ,AR5K_BEACON_ENABLE | -AR5K_BEACON_RESET_TSF ); - +AR5K_REG_DISABLE_BITS (ah,AR5K_BEACON ,AR5K_BEACON_ENABLE ); +ath5k_hw_reset_tsf (ah);return 0 ; }
Re: [PATCH 04/13] ath5k: fix TSF reset
2010/3/9 Bruno Randolf <[email protected]>:
Quoted 29 lines
to reset the TSF,
AR5K_BEACON_RESET_TSFhas to be 1, not 0. also we have a function for that so use it.Signed-off-by Bruno Randolf <[email protected]>---
drivers/net/wireless/ath/ath5k/reset.c | 7 +++----1 files changed, 3 insertions(+), 4 deletions(-)drivers/net/wireless/ath/ath5k/reset.c +3
-5@@ -1379,11 +1379,10 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, ath5k_hw_set_sleep_clock(ah, true); /* - * Disable beacons and reset the register + * Disable beacons and reset the TSF */ - AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE | - AR5K_BEACON_RESET_TSF); - + AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); + ath5k_hw_reset_tsf(ah); return 0; } --
Quoted 4 lines
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
GPG ID: 0xD21DB2DB As you read this post global entropy rises. Have Fun ;-) Nick
PATCH 5/13 ath5k: remove double opmode definition
In reply to Bruno Randolfopmode (operating mode) was defined in struct ath5k_hw and struct ath5k_softc. remove it from ath5k_hw and use only from ath5k_softc (sc->opmode).
(btw: what's the meaning of opmode when we have multiple interfaces?)
--- drivers/net/wireless/ath/ath5k/ath5k.h | 3 +-- drivers/net/wireless/ath/ath5k/attach.c | 3 +-- drivers/net/wireless/ath/ath5k/base.c | 7 ++++--- drivers/net/wireless/ath/ath5k/pcu.c | 14 +++++++------- drivers/net/wireless/ath/ath5k/reset.c | 9 ++------- 5 files changed, 15 insertions(+), 21 deletions(-)
drivers/net/wireless/ath/ath5k/ath5k.h +1 -2
@@ -1036,7 +1036,6 @@ struct ath5k_hw {enum ath5k_int ah_imr; -enum nl80211_iftype ah_op_mode;struct ieee80211_channel *ah_current_channel;bool ah_turbo;bool ah_calibration;
@@ -1199,7 +1198,7 @@ extern int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac);extern bool ath5k_eeprom_is_hb63 (struct ath5k_hw *ah);/* Protocol Control Unit Functions */ -extern int ath5k_hw_set_opmode (struct ath5k_hw *ah); +extern int ath5k_hw_set_opmode (struct ath5k_hw *ah,enum nl80211_iftype opmode);extern void ath5k_hw_set_coverage_class (struct ath5k_hw *ah,u8 coverage_class);/* BSSID Functions */ extern int ath5k_hw_set_lladdr (struct ath5k_hw *ah,const u8 *mac);
drivers/net/wireless/ath/ath5k/attach.c +1 -2
@@ -113,7 +113,6 @@ int ath5k_hw_attach(struct ath5k_softc *sc)/* * HW information */ - ah->ah_op_mode =NL80211_IFTYPE_STATION ; ah->ah_radar.r_enabled =AR5K_TUNE_RADAR_ALERT ; ah->ah_turbo = false; ah->ah_txpower.txp_tpc =AR5K_TUNE_TPC_TXPOWER ;
@@ -328,7 +327,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc)/* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ memcpy (common->curbssid, ath_bcast_mac,ETH_ALEN );ath5k_hw_set_associd (ah); -ath5k_hw_set_opmode (ah); +ath5k_hw_set_opmode (ah, sc->opmode);ath5k_hw_rfgain_opt_init (ah);
drivers/net/wireless/ath/ath5k/base.c +4 -3
@@ -1137,8 +1137,6 @@ ath5k_mode_setup(struct ath5k_softc *sc)struct ath5k_hw *ah = sc->ah;u32 rfilt; - ah->ah_op_mode = sc->opmode; -/* configure rx filter */ rfilt = sc->filter_flags;ath5k_hw_set_rx_filter (ah, rfilt);
@@ -1147,8 +1145,9 @@ ath5k_mode_setup(struct ath5k_softc *sc)ath5k_hw_set_bssid_mask (ah, sc->bssidmask);/* configure operational mode */ -ath5k_hw_set_opmode (ah); +ath5k_hw_set_opmode (ah, sc->opmode); +ATH5K_DBG (sc,ATH5K_DEBUG_MODE ,"mode setup opmode %d\n" , sc->opmode);ATH5K_DBG (sc,ATH5K_DEBUG_MODE ,"RX filter 0x%x\n" , rfilt); }
@@ -2846,6 +2845,8 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, goto end; } +ATH5K_DBG (sc,ATH5K_DEBUG_MODE ,"add interface mode %d\n" , sc->opmode); +ath5k_hw_set_lladdr (sc->ah, vif->addr);ath5k_mode_setup (sc);
drivers/net/wireless/ath/ath5k/pcu.c +7 -7
@@ -39,16 +39,16 @@* ath5k_hw_set_opmode - Set PCU operating mode * * @ah: The &struct ath5k_hw +* @op_mode: &enum nl80211_iftype operating mode * * Initialize PCU for the various operating modes (AP/STA etc) -* -* NOTE: ah->ah_op_mode must be set before calling this. */ -int ath5k_hw_set_opmode (struct ath5k_hw *ah) +int ath5k_hw_set_opmode (struct ath5k_hw *ah,enum nl80211_iftype op_mode) {struct ath_common *common =ath5k_hw_common (ah);u32 pcu_reg, beacon_reg, low_id, high_id; +ATH5K_DBG (ah->ah_sc,ATH5K_DEBUG_MODE ,"mode %d\n" , op_mode);/* Preserve rest settings */ pcu_reg =ath5k_hw_reg_read (ah,AR5K_STA_ID1 ) &0xffff0000 ;
@@ -61,7 +61,7 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah)ATH5K_TRACE (ah->ah_sc); -switch (ah->ah_op_mode) { +switch (op_mode) {case NL80211_IFTYPE_ADHOC : pcu_reg |=AR5K_STA_ID1_ADHOC |AR5K_STA_ID1_KEYSRCH_MODE ; beacon_reg |=AR5K_BCR_ADHOC ;
@@ -651,7 +651,7 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)/* * Set the additional timers by mode */ -switch (ah->ah_op_mode) { +switch (ah->ah_sc->opmode) {case NL80211_IFTYPE_MONITOR :case NL80211_IFTYPE_STATION :/* In STA mode timer1 is used as next wakeup
@@ -688,8 +688,8 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)* Set the beacon register and enable all timers. */ /* When in AP or Mesh Point mode zero timer0 to start TSF */ -if (ah->ah_op_mode ==NL80211_IFTYPE_AP || - ah->ah_op_mode ==NL80211_IFTYPE_MESH_POINT ) +if (ah->ah_sc->opmode ==NL80211_IFTYPE_AP || + ah->ah_sc->opmode ==NL80211_IFTYPE_MESH_POINT )ath5k_hw_reg_write (ah,0 ,AR5K_TIMER0 );ath5k_hw_reg_write (ah, next_beacon,AR5K_TIMER0 );
drivers/net/wireless/ath/ath5k/reset.c +2 -7
@@ -1014,11 +1014,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,if (ret)return ret; -/* -* Initialize operating mode -*/ - ah->ah_op_mode = op_mode; -/* PHY access enable */ if (ah->ah_mac_srev >=AR5K_SREV_AR5211 )ath5k_hw_reg_write (ah,AR5K_PHY_SHIFT_5GHZ ,AR5K_PHY (0 ));
@@ -1189,7 +1184,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,ath5k_hw_set_associd (ah);/* Set PCU config */ -ath5k_hw_set_opmode (ah); +ath5k_hw_set_opmode (ah, op_mode);/* Clear any pending interrupts * PISR/SISR Not available on 5210 */
@@ -1375,7 +1370,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,* external 32KHz crystal when sleeping if one * exists */ if (ah->ah_version ==AR5K_AR5212 && - ah->ah_op_mode !=NL80211_IFTYPE_AP ) + op_mode !=NL80211_IFTYPE_AP )ath5k_hw_set_sleep_clock (ah, true);/*
Re: [PATCH 05/13] ath5k: remove double opmode definition
2010/3/9 Bruno Randolf <[email protected]>:
Quoted 175 lines
opmode (operating mode) was defined in struct
ath5k_hwand structath5k_softc. remove it fromath5k_hwand use only fromath5k_softc(sc->opmode).(btw: what's the meaning of opmode when we have multiple interfaces?)
Signed-off-by Bruno Randolf <[email protected]>---
drivers/net/wireless/ath/ath5k/ath5k.h | 3 +--drivers/net/wireless/ath/ath5k/attach.c| 3 +--drivers/net/wireless/ath/ath5k/base.c| 7 ++++---drivers/net/wireless/ath/ath5k/pcu.c| 14 +++++++-------drivers/net/wireless/ath/ath5k/reset.c| 9 ++-------5 files changed, 15 insertions(+), 21 deletions(-)drivers/net/wireless/ath/ath5k/ath5k.h +1
-2@@ -1036,7 +1036,6 @@ struct ath5k_hw { enum ath5k_int ah_imr; - enum nl80211_iftype ah_op_mode; struct ieee80211_channel *ah_current_channel; bool ah_turbo; bool ah_calibration;@@ -1199,7 +1198,7 @@ extern int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac); extern bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah); /* Protocol Control Unit Functions */ -extern int ath5k_hw_set_opmode (struct ath5k_hw *ah); +extern int ath5k_hw_set_opmode (struct ath5k_hw *ah,enum nl80211_iftype opmode); extern void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class); /* BSSID Functions */ extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac);drivers/net/wireless/ath/ath5k/attach.c +1
-2@@ -113,7 +113,6 @@ int ath5k_hw_attach(struct ath5k_softc *sc) /* * HW information */ - ah->ah_op_mode = NL80211_IFTYPE_STATION; ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT; ah->ah_turbo = false; ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;@@ -328,7 +327,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ memcpy(common->curbssid, ath_bcast_mac, ETH_ALEN); ath5k_hw_set_associd(ah); - ath5k_hw_set_opmode(ah); + ath5k_hw_set_opmode(ah, sc->opmode); ath5k_hw_rfgain_opt_init(ah);drivers/net/wireless/ath/ath5k/base.c +4
-3@@ -1137,8 +1137,6 @@ ath5k_mode_setup(struct ath5k_softc *sc) struct ath5k_hw *ah = sc->ah; u32 rfilt; - ah->ah_op_mode = sc->opmode; - /* configure rx filter */ rfilt = sc->filter_flags; ath5k_hw_set_rx_filter(ah, rfilt);@@ -1147,8 +1145,9 @@ ath5k_mode_setup(struct ath5k_softc *sc) ath5k_hw_set_bssid_mask(ah, sc->bssidmask); /* configure operational mode */ - ath5k_hw_set_opmode(ah); + ath5k_hw_set_opmode(ah, sc->opmode); + ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d\n", sc->opmode); ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt); }@@ -2846,6 +2845,8 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, goto end; } + ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", sc->opmode); + ath5k_hw_set_lladdr(sc->ah, vif->addr); ath5k_mode_setup(sc);drivers/net/wireless/ath/ath5k/pcu.c +4
-4@@ -39,16 +39,16 @@* ath5k_hw_set_opmode - Set PCU operating mode * * @ah: The &struct ath5k_hw +* @op_mode: &enum nl80211_iftype operating mode * * Initialize PCU for the various operating modes (AP/STA etc) -* -* NOTE: ah->ah_op_mode must be set before calling this. */ -int ath5k_hw_set_opmode (struct ath5k_hw *ah) +int ath5k_hw_set_opmode (struct ath5k_hw *ah,enum nl80211_iftype op_mode) { struct ath_common *common = ath5k_hw_common(ah); u32 pcu_reg, beacon_reg, low_id, high_id; + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_MODE, "mode %d\n", op_mode); /* Preserve rest settings */ pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;@@ -61,7 +61,7 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah) ATH5K_TRACE(ah->ah_sc); - switch (ah->ah_op_mode) { + switch (op_mode) {case
NL80211_IFTYPE_ADHOC:
pcu_reg |=AR5K_STA_ID1_ADHOC|AR5K_STA_ID1_KEYSRCH_MODE;beacon_reg|=AR5K_BCR_ADHOC;drivers/net/wireless/ath/ath5k/pcu.c +1
-1@@ -651,7 +651,7 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) /* * Set the additional timers by mode */ - switch (ah->ah_op_mode) { + switch (ah->ah_sc->opmode) {case
NL80211_IFTYPE_MONITOR:
caseNL80211_IFTYPE_STATION:
/* In STA mode timer1 is used as next wakeupdrivers/net/wireless/ath/ath5k/pcu.c +2
-2@@ -688,8 +688,8 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)* Set the beacon register and enable all timers. */ /* When in AP or Mesh Point mode zero timer0 to start TSF */ - if (ah->ah_op_mode == NL80211_IFTYPE_AP || - ah->ah_op_mode == NL80211_IFTYPE_MESH_POINT) + if (ah->ah_sc->opmode == NL80211_IFTYPE_AP || + ah->ah_sc->opmode == NL80211_IFTYPE_MESH_POINT) ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0);drivers/net/wireless/ath/ath5k/reset.c +1
-6@@ -1014,11 +1014,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, if (ret) return ret; - /* - * Initialize operating mode - */ - ah->ah_op_mode = op_mode; - /* PHY access enable */ if (ah->ah_mac_srev >= AR5K_SREV_AR5211) ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));@@ -1189,7 +1184,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, ath5k_hw_set_associd(ah); /* Set PCU config */ - ath5k_hw_set_opmode(ah); + ath5k_hw_set_opmode(ah, op_mode); /* Clear any pending interrupts* PISR/SISR Not available on 5210 */ @@ -1375,7 +1370,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,* external 32KHz crystal when sleeping if one * exists */ if (
ah->ah_version==AR5K_AR5212&&
-ah->ah_op_mode!=NL80211_IFTYPE_AP)
+op_mode!=NL80211_IFTYPE_AP)ath5k_hw_set_sleep_clock(ah, true);
Quoted 7 lines
/*
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
GPG ID: 0xD21DB2DB As you read this post global entropy rises. Have Fun ;-) Nick
PATCH 6/13 ath5k: remove ah_magic
In reply to Bruno Randolfit's never used. probably a leftover from the old OpenHAL days...
--- drivers/net/wireless/ath/ath5k/ath5k.h | 1 - drivers/net/wireless/ath/ath5k/desc.c | 6 ------ drivers/net/wireless/ath/ath5k/eeprom.h | 3 --- 3 files changed, 0 insertions(+), 10 deletions(-)
drivers/net/wireless/ath/ath5k/ath5k.h +0 -1
@@ -1028,7 +1028,6 @@ struct ath5k_nfcal_hist/* TODO: Clean up and merge with ath5k_softc */ struct ath5k_hw { -u32 ah_magic;struct ath_common common;struct ath5k_softc *ah_sc;
drivers/net/wireless/ath/ath5k/desc.c +0 -6
@@ -668,12 +668,6 @@ int ath5k_hw_init_desc_functions(struct ath5k_hw *ah) ah->ah_version != AR5K_AR5212)return -ENOTSUPP ; -/* XXX: What is this magic value and where is it used ? */ -if (ah->ah_version ==AR5K_AR5212 ) - ah->ah_magic =AR5K_EEPROM_MAGIC_5212 ; -else if (ah->ah_version ==AR5K_AR5211 ) - ah->ah_magic =AR5K_EEPROM_MAGIC_5211 ; -if (ah->ah_version ==AR5K_AR5212 ) { ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc; ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc;
drivers/net/wireless/ath/ath5k/eeprom.h +0 -3
@@ -24,9 +24,6 @@* SERDES infos are present */ #define AR5K_EEPROM_MAGIC 0x003d/* EEPROM Magic number */ #define AR5K_EEPROM_MAGIC_VALUE 0x5aa5/* Default - found on EEPROM */ -#define AR5K_EEPROM_MAGIC_5212 0x0000145c/* 5212 */ -#define AR5K_EEPROM_MAGIC_5211 0x0000145b/* 5211 */ -#define AR5K_EEPROM_MAGIC_5210 0x0000145a/* 5210 */ #define AR5K_EEPROM_IS_HB63 0x000b/* Talon detect */
Re: [PATCH 06/13] ath5k: remove ah_magic
2010/3/9 Bruno Randolf <[email protected]>:
Quoted 54 lines
it's never used. probably a leftover from the old OpenHAL days...
Signed-off-by Bruno Randolf <[email protected]>---
drivers/net/wireless/ath/ath5k/ath5k.h | 1 -drivers/net/wireless/ath/ath5k/desc.c| 6 ------drivers/net/wireless/ath/ath5k/eeprom.h| 3 ---3 files changed, 0 insertions(+), 10 deletions(-)drivers/net/wireless/ath/ath5k/ath5k.h +0
-1@@ -1028,7 +1028,6 @@ struct ath5k_nfcal_hist /* TODO: Clean up and merge with ath5k_softc */ struct ath5k_hw { - u32 ah_magic; struct ath_common common; struct ath5k_softc *ah_sc;drivers/net/wireless/ath/ath5k/desc.c +0
-6@@ -668,12 +668,6 @@ int ath5k_hw_init_desc_functions(struct ath5k_hw *ah) ah->ah_version != AR5K_AR5212) return -ENOTSUPP; - /* XXX: What is this magic value and where is it used ? */ - if (ah->ah_version == AR5K_AR5212) - ah->ah_magic = AR5K_EEPROM_MAGIC_5212; - else if (ah->ah_version == AR5K_AR5211) - ah->ah_magic = AR5K_EEPROM_MAGIC_5211; - if (ah->ah_version == AR5K_AR5212) { ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc; ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc;drivers/net/wireless/ath/ath5k/eeprom.h +0
-4@@ -24,9 +24,6 @@* SERDES infos are present */ #define AR5K_EEPROM_MAGIC 0x003d /* EEPROM Magic number */ #define AR5K_EEPROM_MAGIC_VALUE 0x5aa5 /* Default - found on EEPROM */ -#define AR5K_EEPROM_MAGIC_5212 0x0000145c/* 5212 */ -#define AR5K_EEPROM_MAGIC_5211 0x0000145b/* 5211 */ -#define AR5K_EEPROM_MAGIC_5210 0x0000145a/* 5210 */ #define AR5K_EEPROM_IS_HB63 0x000b /* Talon detect */ --
Quoted 4 lines
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
GPG ID: 0xD21DB2DB As you read this post global entropy rises. Have Fun ;-) Nick
PATCH 7/13 ath5k: remove ah_mac_revision
In reply to Bruno Randolfit's not used, and we have ah_mac_srev.
--- drivers/net/wireless/ath/ath5k/ath5k.h | 1 - drivers/net/wireless/ath/ath5k/attach.c | 1 - 2 files changed, 0 insertions(+), 2 deletions(-)
drivers/net/wireless/ath/ath5k/ath5k.h +0 -1
@@ -1047,7 +1047,6 @@ struct ath5k_hw {u32 ah_phy;u32 ah_mac_srev;u16 ah_mac_version; -u16 ah_mac_revision;u16 ah_phy_revision;u16 ah_radio_5ghz_revision;u16 ah_radio_2ghz_revision;
drivers/net/wireless/ath/ath5k/attach.c +0 -1
@@ -148,7 +148,6 @@ int ath5k_hw_attach(struct ath5k_softc *sc)/* Get MAC, PHY and RADIO revisions */ ah->ah_mac_srev = srev; ah->ah_mac_version =AR5K_REG_MS (srev,AR5K_SREV_VER ); - ah->ah_mac_revision =AR5K_REG_MS (srev,AR5K_SREV_REV ); ah->ah_phy_revision =ath5k_hw_reg_read (ah,AR5K_PHY_CHIP_ID ) &0xffffffff ; ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah,
Re: [PATCH 07/13] ath5k: remove ah_mac_revision
2010/3/9 Bruno Randolf <[email protected]>:
Quoted 33 lines
it's not used, and we have
ah_mac_srev.Signed-off-by Bruno Randolf <[email protected]>---
drivers/net/wireless/ath/ath5k/ath5k.h | 1 -
drivers/net/wireless/ath/ath5k/attach.c | 1 -2 files changed, 0 insertions(+), 2 deletions(-)drivers/net/wireless/ath/ath5k/ath5k.h +0
-1@@ -1047,7 +1047,6 @@ struct ath5k_hw { u32 ah_phy; u32 ah_mac_srev; u16 ah_mac_version; - u16 ah_mac_revision; u16 ah_phy_revision; u16 ah_radio_5ghz_revision; u16 ah_radio_2ghz_revision;drivers/net/wireless/ath/ath5k/attach.c +0
-1@@ -148,7 +148,6 @@ int ath5k_hw_attach(struct ath5k_softc *sc) /* Get MAC, PHY and RADIO revisions */ ah->ah_mac_srev = srev; ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER); - ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV);ah->ah_phy_revision =
ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID)&0xffffffff;ah->ah_radio_5ghz_revision= ath5k_hw_radio_revision(ah,
Quoted 5 lines
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
GPG ID: 0xD21DB2DB As you read this post global entropy rises. Have Fun ;-) Nick
PATCH 8/13 ath5k: remove ah_gpio_npins
In reply to Bruno Randolfit's never used and we have a newer implementation in gpio.c.
--- drivers/net/wireless/ath/ath5k/ath5k.h | 2 -- drivers/net/wireless/ath/ath5k/caps.c | 3 --- 2 files changed, 0 insertions(+), 5 deletions(-)
drivers/net/wireless/ath/ath5k/ath5k.h +0 -2
@@ -1068,8 +1068,6 @@ struct ath5k_hw {u8 ah_def_ant;bool ah_software_retry; -int ah_gpio_npins; -struct ath5k_capabilities ah_capabilities;struct ath5k_txq_info ah_txq[AR5K_NUM_TX_QUEUES ];
drivers/net/wireless/ath/ath5k/caps.c +0 -3
@@ -102,9 +102,6 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) } } -/* GPIO */ - ah->ah_gpio_npins =AR5K_NUM_GPIO ; -/* Set number of supported TX queues */ if (ah->ah_version ==AR5K_AR5210 ) ah->ah_capabilities.cap_queues.q_tx_num =
Re: [PATCH 08/13] ath5k: remove ah_gpio_npins
2010/3/9 Bruno Randolf <[email protected]>:
Quoted 36 lines
it's never used and we have a newer implementation in
gpio.c.Signed-off-by Bruno Randolf <[email protected]>---
drivers/net/wireless/ath/ath5k/ath5k.h | 2 --drivers/net/wireless/ath/ath5k/caps.c| 3 ---2 files changed, 0 insertions(+), 5 deletions(-)drivers/net/wireless/ath/ath5k/ath5k.h +0
-2@@ -1068,8 +1068,6 @@ struct ath5k_hw { u8 ah_def_ant; bool ah_software_retry; - int ah_gpio_npins; - struct ath5k_capabilities ah_capabilities; struct ath5k_txq_info ah_txq[AR5K_NUM_TX_QUEUES];drivers/net/wireless/ath/ath5k/caps.c +0
-3@@ -102,9 +102,6 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) } } - /* GPIO */ - ah->ah_gpio_npins = AR5K_NUM_GPIO; - /* Set number of supported TX queues */ if (ah->ah_version == AR5K_AR5210)ah->ah_capabilities.cap_queues.q_tx_num =
Quoted 5 lines
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
GPG ID: 0xD21DB2DB As you read this post global entropy rises. Have Fun ;-) Nick
PATCH 9/13 ath5k: add debugfs file frameerrors
In reply to Bruno Randolfadd a debugfs file to see different RX and TX errors as reported in our status descriptors. this can help to diagnose driver problems.
statistics can be cleared by writing 'clear' into the frameerrors file.
example:
# cat /sys/kernel/debug/ath5k/phy0/frameerrors RX --------------------- CRC 27 (11%) PHY 3 (1%) FIFO 0 (0%) decrypt 0 (0%) MIC 0 (0%) process 0 (0%) jumbo 0 (0%) [RX all 245]
TX
---------------------
retry 2 (9%) FIFO 0 (0%) filter 0 (0%)
[TX all 21]
--- drivers/net/wireless/ath/ath5k/base.c | 23 ++++++- drivers/net/wireless/ath/ath5k/base.h | 12 ++++ drivers/net/wireless/ath/ath5k/debug.c | 106 ++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath5k/debug.h | 1 4 files changed, 140 insertions(+), 2 deletions(-)
drivers/net/wireless/ath/ath5k/base.c +21 -2
@@ -1843,18 +1843,28 @@ ath5k_tasklet_rx(unsigned long data)break ; else if (unlikely(ret)) {ATH5K_ERR (sc,"error in processing rx descriptor\n" ); + sc->stats.rxerr_proc++;spin_unlock (&sc->rxbuflock);return ; } + sc->stats.rx_all_count++; +if (unlikely (rs.rs_more)) {ATH5K_WARN (sc,"unsupported jumbo\n" ); + sc->stats.rxerr_jumbo++; goto next; }if (unlikely (rs.rs_status)) { -if (rs.rs_status &AR5K_RXERR_PHY ) +if (rs.rs_status &AR5K_RXERR_CRC ) + sc->stats.rxerr_crc++; +if (rs.rs_status &AR5K_RXERR_FIFO ) + sc->stats.rxerr_fifo++; +if (rs.rs_status &AR5K_RXERR_PHY ) { + sc->stats.rxerr_phy++; goto next; + }if (rs.rs_status &AR5K_RXERR_DECRYPT ) {/* * Decrypt error. If the error occurred
@@ -1866,12 +1876,14 @@ ath5k_tasklet_rx(unsigned long data)* * XXX do key cache faulting */ + sc->stats.rxerr_decrypt++;if (rs.rs_keyix ==AR5K_RXKEYIX_INVALID && !(rs.rs_status &AR5K_RXERR_CRC )) goto accept; }if (rs.rs_status &AR5K_RXERR_MIC ) { rx_flag |=RX_FLAG_MMIC_ERROR ; + sc->stats.rxerr_mic++; goto accept; }
@@ -2001,6 +2013,7 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)break ; } + sc->stats.tx_all_count++; skb = bf->skb; info =IEEE80211_SKB_CB (skb); bf->skb =NULL ;
@@ -2027,8 +2040,14 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)if (unlikely (ts.ts_status)) { sc->ll_stats.dot11ACKFailureCount++; -if (ts.ts_status &AR5K_TXERR_FILT ) +if (ts.ts_status &AR5K_TXERR_FILT ) { info->flags |=IEEE80211_TX_STAT_TX_FILTERED ; + sc->stats.txerr_filt++; + } +if (ts.ts_status &AR5K_TXERR_XRETRY ) + sc->stats.txerr_retry++; +if (ts.ts_status &AR5K_TXERR_FIFO ) + sc->stats.txerr_fifo++; }else { info->flags |=IEEE80211_TX_STAT_ACK ; info->status.ack_signal = ts.ts_rssi;
drivers/net/wireless/ath/ath5k/base.h +12 -0
@@ -109,6 +109,18 @@ struct ath5k_rfkill {struct ath5k_statistics {unsigned int antenna_rx[5 ];/* frames count per antenna RX */ unsigned int antenna_tx[5 ];/* frames count per antenna TX */ +unsigned int rx_all_count;/* all RX frames, including errors */ +unsigned int tx_all_count;/* all TX frames, including errors */ +unsigned int rxerr_crc; +unsigned int rxerr_phy; +unsigned int rxerr_fifo; +unsigned int rxerr_decrypt; +unsigned int rxerr_mic; +unsigned int rxerr_proc; +unsigned int rxerr_jumbo; +unsigned int txerr_retry; +unsigned int txerr_fifo; +unsigned int txerr_filt; };#if CHAN_DEBUG
drivers/net/wireless/ath/ath5k/debug.c +106 -0
124 lines not on this page · raw message
drivers/net/wireless/ath/ath5k/debug.h +1 -0
@@ -75,6 +75,7 @@ struct ath5k_dbg_info {struct dentry *debugfs_beacon;struct dentry *debugfs_reset;struct dentry *debugfs_antenna; +struct dentry *debugfs_frameerrors; };/**
Nick Kossifidis
maintainerRe: [PATCH 09/13] ath5k: add debugfs file frameerrors
MjAxMC8zLzkgQnJ1bm8gUmFuZG9sZiA8YnIxQGVpbmZhY2gub3JnPjoKPiBhZGQgYSBkZWJ1Z2Zz IGZpbGUgdG8gc2VlIGRpZmZlcmVudCBSWCBhbmQgVFggZXJyb3JzIGFzIHJlcG9ydGVkIGluIG91 ciBzdGF0dXMKPiBkZXNjcmlwdG9ycy4gdGhpcyBjYW4gaGVscCB0byBkaWFnbm9zZSBkcml2ZXIg cHJvYmxlbXMuCj4KPiBzdGF0aXN0aWNzIGNhbiBiZSBjbGVhcmVkIGJ5IHdyaXRpbmcgJ2NsZWFy JyBpbnRvIHRoZSBmcmFtZWVycm9ycyBmaWxlLgo+Cj4gZXhhbXBsZToKPgo+ICMgY2F0IC9zeXMv a2VybmVsL2RlYnVnL2F0aDVrL3BoeTAvZnJhbWVlcnJvcnMKPiBSWAo+IC0tLS0tLS0tLS0tLS0t LS0tLS0tLQo+IENSQyDCoCDCoCAyNyDCoCDCoCDCoCgxMSUpCj4gUEhZIMKgIMKgIDMgwqAgwqAg wqAgKDElKQo+IEZJRk8gwqAgwqAwIMKgIMKgIMKgICgwJSkKPiBkZWNyeXB0IDAgwqAgwqAgwqAg KDAlKQo+IE1JQyDCoCDCoCAwIMKgIMKgIMKgICgwJSkKPiBwcm9jZXNzIDAgwqAgwqAgwqAgKDAl KQo+IGp1bWJvIMKgIDAgwqAgwqAgwqAgKDAlKQo+IFtSWCBhbGwgMjQ1XQo+Cj4gVFgKPiAtLS0t LS0tLS0tLS0tLS0tLS0tLS0KPiByZXRyeSDCoCAyIMKgIMKgIMKgICg5JSkKPiBGSUZPIMKgIMKg MCDCoCDCoCDCoCAoMCUpCj4gZmlsdGVyIMKgMCDCoCDCoCDCoCAoMCUpCj4gW1RYIGFsbCAyMV0K Pgo+IFNpZ25lZC1vZmYtYnk6IEJydW5vIFJhbmRvbGYgPGJyMUBlaW5mYWNoLm9yZz4KPiAtLS0K PiDCoGRyaXZlcnMvbmV0L3dpcmVsZXNzL2F0aC9hdGg1ay9iYXNlLmMgwqB8IMKgIDIzICsrKysr Ky0KPiDCoGRyaXZlcnMvbmV0L3dpcmVsZXNzL2F0aC9hdGg1ay9iYXNlLmggwqB8IMKgIDEyICsr KysKPiDCoGRyaXZlcnMvbmV0L3dpcmVsZXNzL2F0aC9hdGg1ay9kZWJ1Zy5jIHwgwqAxMDYgKysr KysrKysrKysrKysrKysrKysrKysrKysrKysrKysKPiDCoGRyaXZlcnMvbmV0L3dpcmVsZXNzL2F0 aC9hdGg1ay9kZWJ1Zy5oIHwgwqAgwqAxCj4gwqA0IGZpbGVzIGNoYW5nZWQsIDE0MCBpbnNlcnRp b25zKCspLCAyIGRlbGV0aW9ucygtKQo+Cj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvbmV0L3dpcmVs ZXNzL2F0aC9hdGg1ay9iYXNlLmMgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9hdGgvYXRoNWsvYmFz ZS5jCj4gaW5kZXggZTYzY2NhOS4uOWM0MjQ5OCAxMDA2NDQKPiAtLS0gYS9kcml2ZXJzL25ldC93 aXJlbGVzcy9hdGgvYXRoNWsvYmFzZS5jCj4gKysrIGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvYXRo L2F0aDVrL2Jhc2UuYwo+IEBAIC0xODQzLDE4ICsxODQzLDI4IEBAIGF0aDVrX3Rhc2tsZXRfcngo dW5zaWduZWQgbG9uZyBkYXRhKQo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg YnJlYWs7Cj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBlbHNlIGlmICh1bmxpa2VseShyZXQpKSB7 Cj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBBVEg1S19FUlIoc2MsICJlcnJv ciBpbiBwcm9jZXNzaW5nIHJ4IGRlc2NyaXB0b3JcbiIpOwo+ICsgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgc2MtPnN0YXRzLnJ4ZXJyX3Byb2MrKzsKPiDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoHNwaW5fdW5sb2NrKCZzYy0+cnhidWZsb2NrKTsKPiDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybjsKPiDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoH0KPgo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgc2MtPnN0YXRzLnJ4X2FsbF9jb3VudCsr Owo+ICsKPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGlmICh1bmxpa2VseShycy5yc19tb3JlKSkg ewo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgQVRINUtfV0FSTihzYywgInVu c3VwcG9ydGVkIGp1bWJvXG4iKTsKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IHNjLT5zdGF0cy5yeGVycl9qdW1ibysrOwo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgZ290byBuZXh0Owo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgfQo+Cj4gwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqBpZiAodW5saWtlbHkocnMucnNfc3RhdHVzKSkgewo+IC0gwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYgKHJzLnJzX3N0YXR1cyAmIEFSNUtfUlhFUlJfUEhZ KQo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYgKHJzLnJzX3N0YXR1cyAm IEFSNUtfUlhFUlJfQ1JDKQo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgc2MtPnN0YXRzLnJ4ZXJyX2NyYysrOwo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgaWYgKHJzLnJzX3N0YXR1cyAmIEFSNUtfUlhFUlJfRklGTykKPiArIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHNjLT5zdGF0cy5yeGVycl9m aWZvKys7Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBpZiAocnMucnNfc3Rh dHVzICYgQVI1S19SWEVSUl9QSFkpIHsKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIHNjLT5zdGF0cy5yeGVycl9waHkrKzsKPiDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGdvdG8gbmV4dDsKPiArIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIH0KPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoGlmIChycy5yc19zdGF0dXMgJiBBUjVLX1JYRVJSX0RFQ1JZUFQpIHsKPiDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoC8qCj4gwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgKiBEZWNyeXB0IGVycm9yLiDCoElmIHRo ZSBlcnJvciBvY2N1cnJlZAo+IEBAIC0xODY2LDEyICsxODc2LDE0IEBAIGF0aDVrX3Rhc2tsZXRf cngodW5zaWduZWQgbG9uZyBkYXRhKQo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgICoKPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCAqIFhYWCBkbyBrZXkgY2FjaGUgZmF1bHRpbmcKPiDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAqLwo+ICsgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgc2MtPnN0YXRzLnJ4ZXJyX2RlY3J5cHQrKzsKPiDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGlmIChycy5yc19r ZXlpeCA9PSBBUjVLX1JYS0VZSVhfSU5WQUxJRCAmJgo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIShycy5yc19zdGF0dXMgJiBBUjVLX1JYRVJS X0NSQykpCj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqBnb3RvIGFjY2VwdDsKPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoH0KPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGlmIChycy5yc19zdGF0 dXMgJiBBUjVLX1JYRVJSX01JQykgewo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgcnhfZmxhZyB8PSBSWF9GTEFHX01NSUNfRVJST1I7Cj4gKyDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBzYy0+c3RhdHMucnhlcnJfbWlj Kys7Cj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBnb3Rv IGFjY2VwdDsKPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoH0KPgo+IEBAIC0y MDAxLDYgKzIwMTMsNyBAQCBhdGg1a190eF9wcm9jZXNzcShzdHJ1Y3QgYXRoNWtfc29mdGMgKnNj LCBzdHJ1Y3QgYXRoNWtfdHhxICp0eHEpCj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqBicmVhazsKPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoH0KPgo+ICsgwqAgwqAgwqAgwqAg wqAgwqAgwqAgc2MtPnN0YXRzLnR4X2FsbF9jb3VudCsrOwo+IMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgc2tiID0gYmYtPnNrYjsKPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGluZm8gPSBJRUVFODAy MTFfU0tCX0NCKHNrYik7Cj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBiZi0+c2tiID0gTlVMTDsK PiBAQCAtMjAyNyw4ICsyMDQwLDE0IEBAIGF0aDVrX3R4X3Byb2Nlc3NxKHN0cnVjdCBhdGg1a19z b2Z0YyAqc2MsIHN0cnVjdCBhdGg1a190eHEgKnR4cSkKPgo+IMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgaWYgKHVubGlrZWx5KHRzLnRzX3N0YXR1cykpIHsKPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoHNjLT5sbF9zdGF0cy5kb3QxMUFDS0ZhaWx1cmVDb3VudCsrOwo+IC0gwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYgKHRzLnRzX3N0YXR1cyAmIEFSNUtfVFhF UlJfRklMVCkKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGlmICh0cy50c19z dGF0dXMgJiBBUjVLX1RYRVJSX0ZJTFQpIHsKPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoGluZm8tPmZsYWdzIHw9IElFRUU4MDIxMV9UWF9TVEFUX1RYX0ZJ TFRFUkVEOwo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg c2MtPnN0YXRzLnR4ZXJyX2ZpbHQrKzsKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIH0KPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGlmICh0cy50c19zdGF0 dXMgJiBBUjVLX1RYRVJSX1hSRVRSWSkKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIHNjLT5zdGF0cy50eGVycl9yZXRyeSsrOwo+ICsgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYgKHRzLnRzX3N0YXR1cyAmIEFSNUtfVFhFUlJfRklGTykK PiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHNjLT5zdGF0 cy50eGVycl9maWZvKys7Cj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB9IGVsc2Ugewo+IMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaW5mby0+ZmxhZ3MgfD0gSUVFRTgwMjExX1RY X1NUQVRfQUNLOwo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaW5mby0+c3Rh dHVzLmFja19zaWduYWwgPSB0cy50c19yc3NpOwo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL25ldC93 aXJlbGVzcy9hdGgvYXRoNWsvYmFzZS5oIGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvYXRoL2F0aDVr L2Jhc2UuaAo+IGluZGV4IGNhNTI1ODQuLjMzZjFkOGIgMTAwNjQ0Cj4gLS0tIGEvZHJpdmVycy9u ZXQvd2lyZWxlc3MvYXRoL2F0aDVrL2Jhc2UuaAo+ICsrKyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNz L2F0aC9hdGg1ay9iYXNlLmgKPiBAQCAtMTA5LDYgKzEwOSwxOCBAQCBzdHJ1Y3QgYXRoNWtfcmZr aWxsIHsKPiDCoHN0cnVjdCBhdGg1a19zdGF0aXN0aWNzIHsKPiDCoCDCoCDCoCDCoHVuc2lnbmVk IGludCBhbnRlbm5hX3J4WzVdOyDCoCDCoCAvKiBmcmFtZXMgY291bnQgcGVyIGFudGVubmEgUlgg Ki8KPiDCoCDCoCDCoCDCoHVuc2lnbmVkIGludCBhbnRlbm5hX3R4WzVdOyDCoCDCoCAvKiBmcmFt ZXMgY291bnQgcGVyIGFudGVubmEgVFggKi8KPiArIMKgIMKgIMKgIHVuc2lnbmVkIGludCByeF9h bGxfY291bnQ7IMKgIMKgIMKgLyogYWxsIFJYIGZyYW1lcywgaW5jbHVkaW5nIGVycm9ycyAqLwo+ ICsgwqAgwqAgwqAgdW5zaWduZWQgaW50IHR4X2FsbF9jb3VudDsgwqAgwqAgwqAvKiBhbGwgVFgg ZnJhbWVzLCBpbmNsdWRpbmcgZXJyb3JzICovCj4gKyDCoCDCoCDCoCB1bnNpZ25lZCBpbnQgcnhl cnJfY3JjOwo+ICsgwqAgwqAgwqAgdW5zaWduZWQgaW50IHJ4ZXJyX3BoeTsKPiArIMKgIMKgIMKg IHVuc2lnbmVkIGludCByeGVycl9maWZvOwo+ICsgwqAgwqAgwqAgdW5zaWduZWQgaW50IHJ4ZXJy X2RlY3J5cHQ7Cj4gKyDCoCDCoCDCoCB1bnNpZ25lZCBpbnQgcnhlcnJfbWljOwo+ICsgwqAgwqAg wqAgdW5zaWduZWQgaW50IHJ4ZXJyX3Byb2M7Cj4gKyDCoCDCoCDCoCB1bnNpZ25lZCBpbnQgcnhl cnJfanVtYm87Cj4gKyDCoCDCoCDCoCB1bnNpZ25lZCBpbnQgdHhlcnJfcmV0cnk7Cj4gKyDCoCDC oCDCoCB1bnNpZ25lZCBpbnQgdHhlcnJfZmlmbzsKPiArIMKgIMKgIMKgIHVuc2lnbmVkIGludCB0 eGVycl9maWx0Owo+IMKgfTsKPgo+IMKgI2lmIENIQU5fREVCVUcKPiBkaWZmIC0tZ2l0IGEvZHJp dmVycy9uZXQvd2lyZWxlc3MvYXRoL2F0aDVrL2RlYnVnLmMgYi9kcml2ZXJzL25ldC93aXJlbGVz cy9hdGgvYXRoNWsvZGVidWcuYwo+IGluZGV4IDIzNmYyMGYuLmJjY2Q0YTcgMTAwNjQ0Cj4gLS0t IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvYXRoL2F0aDVrL2RlYnVnLmMKPiArKysgYi9kcml2ZXJz L25ldC93aXJlbGVzcy9hdGgvYXRoNWsvZGVidWcuYwo+IEBAIC00NjUsNiArNDY1LDEwNiBAQCBz dGF0aWMgY29uc3Qgc3RydWN0IGZpbGVfb3BlcmF0aW9ucyBmb3BzX2FudGVubmEgPSB7Cj4gwqB9 Owo+Cj4KPiArLyogZGVidWdmczogZnJhbWVlcnJvcnMgKi8KPiArCj4gK3N0YXRpYyBzc2l6ZV90 IHJlYWRfZmlsZV9mcmFtZWVycm9ycyhzdHJ1Y3QgZmlsZSAqZmlsZSwgY2hhciBfX3VzZXIgKnVz ZXJfYnVmLAo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqBzaXplX3QgY291bnQsIGxvZmZfdCAqcHBvcykKPiArewo+ICsgwqAgwqAgwqAgc3RydWN0 IGF0aDVrX3NvZnRjICpzYyA9IGZpbGUtPnByaXZhdGVfZGF0YTsKPiArIMKgIMKgIMKgIHN0cnVj dCBhdGg1a19zdGF0aXN0aWNzICpzdCA9ICZzYy0+c3RhdHM7Cj4gKyDCoCDCoCDCoCBjaGFyIGJ1 Zls3MDBdOwo+ICsgwqAgwqAgwqAgdW5zaWduZWQgaW50IGxlbiA9IDA7Cj4gKwo+ICsgwqAgwqAg wqAgbGVuICs9IHNucHJpbnRmKGJ1ZitsZW4sIHNpemVvZihidWYpLWxlbiwKPiArIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgICJSWFxuLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4iKTsK PiArIMKgIMKgIMKgIGxlbiArPSBzbnByaW50ZihidWYrbGVuLCBzaXplb2YoYnVmKS1sZW4sICJD UkNcdCVkXHQoJWQlJSlcbiIsCj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBz dC0+cnhlcnJfY3JjLAo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgc3QtPnJ4 X2FsbF9jb3VudCA+IDAgPwo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgc3QtPnJ4ZXJyX2NyYyoxMDAvc3QtPnJ4X2FsbF9jb3VudCA6IDApOwo+ICsgwqAg wqAgwqAgbGVuICs9IHNucHJpbnRmKGJ1ZitsZW4sIHNpemVvZihidWYpLWxlbiwgIlBIWVx0JWRc dCglZCUlKVxuIiwKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHN0LT5yeGVy cl9waHksCj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBzdC0+cnhfYWxsX2Nv dW50ID4gMCA/Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCBzdC0+cnhlcnJfcGh5KjEwMC9zdC0+cnhfYWxsX2NvdW50IDogMCk7Cj4gKyDCoCDCoCDCoCBs ZW4gKz0gc25wcmludGYoYnVmK2xlbiwgc2l6ZW9mKGJ1ZiktbGVuLCAiRklGT1x0JWRcdCglZCUl KVxuIiwKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHN0LT5yeGVycl9maWZv LAo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgc3QtPnJ4X2FsbF9jb3VudCA+ IDAgPwo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgc3Qt PnJ4ZXJyX2ZpZm8qMTAwL3N0LT5yeF9hbGxfY291bnQgOiAwKTsKPiArIMKgIMKgIMKgIGxlbiAr PSBzbnByaW50ZihidWYrbGVuLCBzaXplb2YoYnVmKS1sZW4sICJkZWNyeXB0XHQlZFx0KCVkJSUp XG4iLAo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgc3QtPnJ4ZXJyX2RlY3J5 cHQsCj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBzdC0+cnhfYWxsX2NvdW50 ID4gMCA/Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBz dC0+cnhlcnJfZGVjcnlwdCoxMDAvc3QtPnJ4X2FsbF9jb3VudCA6IDApOwo+ICsgwqAgwqAgwqAg bGVuICs9IHNucHJpbnRmKGJ1ZitsZW4sIHNpemVvZihidWYpLWxlbiwgIk1JQ1x0JWRcdCglZCUl KVxuIiwKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHN0LT5yeGVycl9taWMs Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBzdC0+cnhfYWxsX2NvdW50ID4g MCA/Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBzdC0+ cnhlcnJfbWljKjEwMC9zdC0+cnhfYWxsX2NvdW50IDogMCk7Cj4gKyDCoCDCoCDCoCBsZW4gKz0g c25wcmludGYoYnVmK2xlbiwgc2l6ZW9mKGJ1ZiktbGVuLCAicHJvY2Vzc1x0JWRcdCglZCUlKVxu IiwKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHN0LT5yeGVycl9wcm9jLAo+ ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgc3QtPnJ4X2FsbF9jb3VudCA+IDAg Pwo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgc3QtPnJ4 ZXJyX3Byb2MqMTAwL3N0LT5yeF9hbGxfY291bnQgOiAwKTsKPiArIMKgIMKgIMKgIGxlbiArPSBz bnByaW50ZihidWYrbGVuLCBzaXplb2YoYnVmKS1sZW4sICJqdW1ib1x0JWRcdCglZCUlKVxuIiwK PiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHN0LT5yeGVycl9qdW1ibywKPiAr IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHN0LT5yeF9hbGxfY291bnQgPiAwID8K PiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHN0LT5yeGVy cl9qdW1ibyoxMDAvc3QtPnJ4X2FsbF9jb3VudCA6IDApOwo+ICsgwqAgwqAgwqAgbGVuICs9IHNu cHJpbnRmKGJ1ZitsZW4sIHNpemVvZihidWYpLWxlbiwgIltSWCBhbGxcdCVkXVxuIiwKPiArIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHN0LT5yeF9hbGxfY291bnQpOwo+ICsKPiAr IMKgIMKgIMKgIGxlbiArPSBzbnByaW50ZihidWYrbGVuLCBzaXplb2YoYnVmKS1sZW4sCj4gKyDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAiXG5UWFxuLS0tLS0tLS0tLS0tLS0tLS0t LS0tXG4iKTsKPiArIMKgIMKgIMKgIGxlbiArPSBzbnByaW50ZihidWYrbGVuLCBzaXplb2YoYnVm KS1sZW4sICJyZXRyeVx0JWRcdCglZCUlKVxuIiwKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIHN0LT50eGVycl9yZXRyeSwKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIHN0LT50eF9hbGxfY291bnQgPiAwID8KPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIHN0LT50eGVycl9yZXRyeSoxMDAvc3QtPnR4X2FsbF9jb3Vu dCA6IDApOwo+ICsgwqAgwqAgwqAgbGVuICs9IHNucHJpbnRmKGJ1ZitsZW4sIHNpemVvZihidWYp LWxlbiwgIkZJRk9cdCVkXHQoJWQlJSlcbiIsCj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCBzdC0+dHhlcnJfZmlmbywKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIHN0LT50eF9hbGxfY291bnQgPiAwID8KPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIHN0LT50eGVycl9maWZvKjEwMC9zdC0+dHhfYWxsX2NvdW50IDog MCk7Cj4gKyDCoCDCoCDCoCBsZW4gKz0gc25wcmludGYoYnVmK2xlbiwgc2l6ZW9mKGJ1ZiktbGVu LCAiZmlsdGVyXHQlZFx0KCVkJSUpXG4iLAo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgc3QtPnR4ZXJyX2ZpbHQsCj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCBzdC0+dHhfYWxsX2NvdW50ID4gMCA/Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCBzdC0+dHhlcnJfZmlsdCoxMDAvc3QtPnR4X2FsbF9jb3VudCA6IDAp Owo+ICsgwqAgwqAgwqAgbGVuICs9IHNucHJpbnRmKGJ1ZitsZW4sIHNpemVvZihidWYpLWxlbiwg IltUWCBhbGxcdCVkXVxuIiwKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHN0 LT50eF9hbGxfY291bnQpOwo+ICsKPiArIMKgIMKgIMKgIHJldHVybiBzaW1wbGVfcmVhZF9mcm9t X2J1ZmZlcih1c2VyX2J1ZiwgY291bnQsIHBwb3MsIGJ1ZiwgbGVuKTsKPiArfQo+ICsKPiArc3Rh dGljIHNzaXplX3Qgd3JpdGVfZmlsZV9mcmFtZWVycm9ycyhzdHJ1Y3QgZmlsZSAqZmlsZSwKPiAr IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgY29uc3QgY2hh ciBfX3VzZXIgKnVzZXJidWYsCj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoHNpemVfdCBjb3VudCwgbG9mZl90ICpwcG9zKQo+ICt7Cj4gKyDCoCDCoCDC oCBzdHJ1Y3QgYXRoNWtfc29mdGMgKnNjID0gZmlsZS0+cHJpdmF0ZV9kYXRhOwo+ICsgwqAgwqAg wqAgc3RydWN0IGF0aDVrX3N0YXRpc3RpY3MgKnN0ID0gJnNjLT5zdGF0czsKPiArIMKgIMKgIMKg IGNoYXIgYnVmWzIwXTsKPiArCj4gKyDCoCDCoCDCoCBpZiAoY29weV9mcm9tX3VzZXIoYnVmLCB1 c2VyYnVmLCBtaW4oY291bnQsIHNpemVvZihidWYpKSkpCj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDC oCByZXR1cm4gLUVGQVVMVDsKPiArCj4gKyDCoCDCoCDCoCBpZiAoc3RybmNtcChidWYsICJjbGVh ciIsIDUpID09IDApIHsKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHN0LT5yeGVycl9jcmMgPSAw Owo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgc3QtPnJ4ZXJyX3BoeSA9IDA7Cj4gKyDCoCDCoCDC oCDCoCDCoCDCoCDCoCBzdC0+cnhlcnJfZmlmbyA9IDA7Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDC oCBzdC0+cnhlcnJfZGVjcnlwdCA9IDA7Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCBzdC0+cnhl cnJfbWljID0gMDsKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHN0LT5yeGVycl9wcm9jID0gMDsK PiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHN0LT5yeGVycl9qdW1ibyA9IDA7Cj4gKyDCoCDCoCDC oCDCoCDCoCDCoCDCoCBzdC0+cnhfYWxsX2NvdW50ID0gMDsKPiArIMKgIMKgIMKgIMKgIMKgIMKg IMKgIHN0LT50eGVycl9yZXRyeSA9IDA7Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCBzdC0+dHhl cnJfZmlmbyA9IDA7Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCBzdC0+dHhlcnJfZmlsdCA9IDA7 Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCBzdC0+dHhfYWxsX2NvdW50ID0gMDsKPiArIMKgIMKg IMKgIMKgIMKgIMKgIMKgIHByaW50ayhLRVJOX0lORk8gImF0aDVrIGRlYnVnOiBjbGVhcmVkIGZy YW1lZXJyb3JzIHN0YXRzXG4iKTsKPiArIMKgIMKgIMKgIH0KPiArIMKgIMKgIMKgIHJldHVybiBj b3VudDsKPiArfQo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCBmaWxlX29wZXJhdGlvbnMgZm9w c19mcmFtZWVycm9ycyA9IHsKPiArIMKgIMKgIMKgIC5yZWFkID0gcmVhZF9maWxlX2ZyYW1lZXJy b3JzLAo+ICsgwqAgwqAgwqAgLndyaXRlID0gd3JpdGVfZmlsZV9mcmFtZWVycm9ycywKPiArIMKg IMKgIMKgIC5vcGVuID0gYXRoNWtfZGVidWdmc19vcGVuLAo+ICsgwqAgwqAgwqAgLm93bmVyID0g VEhJU19NT0RVTEUsCj4gK307Cj4gKwo+ICsKPiDCoC8qIGluaXQgKi8KPgo+IMKgdm9pZAo+IEBA IC00OTgsNiArNTk4LDExIEBAIGF0aDVrX2RlYnVnX2luaXRfZGV2aWNlKHN0cnVjdCBhdGg1a19z b2Z0YyAqc2MpCj4gwqAgwqAgwqAgwqBzYy0+ZGVidWcuZGVidWdmc19hbnRlbm5hID0gZGVidWdm c19jcmVhdGVfZmlsZSgiYW50ZW5uYSIsCj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqBTX0lXVVNSIHwgU19JUlVTUiwKPiDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHNjLT5kZWJ1Zy5kZWJ1Z2ZzX3BoeWRpciwgc2Ms ICZmb3BzX2FudGVubmEpOwo+ICsKPiArIMKgIMKgIMKgIHNjLT5kZWJ1Zy5kZWJ1Z2ZzX2ZyYW1l ZXJyb3JzID0gZGVidWdmc19jcmVhdGVfZmlsZSgiZnJhbWVlcnJvcnMiLAo+ICsgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgU19JV1VTUiB8IFNfSVJVU1IsCj4g KyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBzYy0+ZGVidWcu ZGVidWdmc19waHlkaXIsIHNjLAo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgJmZvcHNfZnJhbWVlcnJvcnMpOwo+IMKgfQo+Cj4gwqB2b2lkCj4gQEAgLTUx NCw2ICs2MTksNyBAQCBhdGg1a19kZWJ1Z19maW5pc2hfZGV2aWNlKHN0cnVjdCBhdGg1a19zb2Z0 YyAqc2MpCj4gwqAgwqAgwqAgwqBkZWJ1Z2ZzX3JlbW92ZShzYy0+ZGVidWcuZGVidWdmc19iZWFj b24pOwo+IMKgIMKgIMKgIMKgZGVidWdmc19yZW1vdmUoc2MtPmRlYnVnLmRlYnVnZnNfcmVzZXQp Owo+IMKgIMKgIMKgIMKgZGVidWdmc19yZW1vdmUoc2MtPmRlYnVnLmRlYnVnZnNfYW50ZW5uYSk7 Cj4gKyDCoCDCoCDCoCBkZWJ1Z2ZzX3JlbW92ZShzYy0+ZGVidWcuZGVidWdmc19mcmFtZWVycm9y cyk7Cj4gwqAgwqAgwqAgwqBkZWJ1Z2ZzX3JlbW92ZShzYy0+ZGVidWcuZGVidWdmc19waHlkaXIp Owo+IMKgfQo+Cj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2F0aC9hdGg1ay9k ZWJ1Zy5oIGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvYXRoL2F0aDVrL2RlYnVnLmgKPiBpbmRleCAw MTg2MTI3Li5kYTI0ZmY1IDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2F0aC9h dGg1ay9kZWJ1Zy5oCj4gKysrIGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvYXRoL2F0aDVrL2RlYnVn LmgKPiBAQCAtNzUsNiArNzUsNyBAQCBzdHJ1Y3QgYXRoNWtfZGJnX2luZm8gewo+IMKgIMKgIMKg IMKgc3RydWN0IGRlbnRyeSDCoCDCoCDCoCDCoCDCoCAqZGVidWdmc19iZWFjb247Cj4gwqAgwqAg wqAgwqBzdHJ1Y3QgZGVudHJ5IMKgIMKgIMKgIMKgIMKgICpkZWJ1Z2ZzX3Jlc2V0Owo+IMKgIMKg IMKgIMKgc3RydWN0IGRlbnRyeSDCoCDCoCDCoCDCoCDCoCAqZGVidWdmc19hbnRlbm5hOwo+ICsg wqAgwqAgwqAgc3RydWN0IGRlbnRyeSDCoCDCoCDCoCDCoCDCoCAqZGVidWdmc19mcmFtZWVycm9y czsKPiDCoH07Cj4KPiDCoC8qKgo+Cj4gLS0KPiBUbyB1bnN1YnNjcmliZSBmcm9tIHRoaXMgbGlz dDogc2VuZCB0aGUgbGluZSAidW5zdWJzY3JpYmUgbGludXgtd2lyZWxlc3MiIGluCj4gdGhlIGJv ZHkgb2YgYSBtZXNzYWdlIHRvIG1ham9yZG9tb0B2Z2VyLmtlcm5lbC5vcmcKPiBNb3JlIG1ham9y ZG9tbyBpbmZvIGF0IMKgaHR0cDovL3ZnZXIua2VybmVsLm9yZy9tYWpvcmRvbW8taW5mby5odG1s Cj4KCkFja2VkLWJ5OiBOaWNrIEtvc3NpZmlkaXMgPG1pY2tmbGVtbUBnbWFpbC5jb20+CgotLSAK R1BHIElEOiAweEQyMURCMkRCCkFzIHlvdSByZWFkIHRoaXMgcG9zdCBnbG9iYWwgZW50cm9weSBy aXNlcy4gSGF2ZSBGdW4gOy0pCk5pY2sK
PATCH 10/13 ath5k: fix I/Q calibration (for real)
In reply to Bruno RandolfI/Q calibration was completely broken, resulting in a high number of CRC errors on received packets. before i could see around 10% to 20% CRC errors, with this patch they are between 0% and 3%.
1.) the removal of the mask in commit "ath5k: Fix I/Q calibration (f1cf2dbd0f798b71b1590e7aca6647f2caef1649)" resulted in no mask beeing used when writing the I/Q values into the register. additional errors in the calculation of the values (see 2.) resulted too high numbers, exceeding the masks, so wrong values like 0xfffffffe were written. to be safe we should always use the bitmask when writing parts of a register.
2.) using a (s32) cast for q_coff is a wrong conversion to signed, since we convert to a signed value later by substracting 128. this resulted in too low numbers for Q many times, which were limited to -16 by the boundary check later on.
3.) checked everything against the HAL sources and took over comments and minor optimizations from there.
4.) we can't use ENABLE_BITS when we want to write a number (the number can contain zeros). also always write the correction values first and set ENABLE bit last, like the HAL does.
--- drivers/net/wireless/ath/ath5k/phy.c | 37 +++++++++++++++++----------------- drivers/net/wireless/ath/ath5k/reg.h | 1 + 2 files changed, 20 insertions(+), 18 deletions(-)
drivers/net/wireless/ath/ath5k/phy.c +19 -18
@@ -1386,38 +1386,39 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, goto done;/* Calibration has finished, get the results and re-run */ + +/* work around empty results which can apparently happen on 5212 */ for (i =0 ; i <=10 ; i++) { iq_corr =ath5k_hw_reg_read (ah,AR5K_PHY_IQRES_CAL_CORR ); i_pwr =ath5k_hw_reg_read (ah,AR5K_PHY_IQRES_CAL_PWR_I ); q_pwr =ath5k_hw_reg_read (ah,AR5K_PHY_IQRES_CAL_PWR_Q ); +ATH5K_DBG_UNLIMIT (ah->ah_sc,ATH5K_DEBUG_CALIBRATE , +"iq_corr:%x i_pwr:%x q_pwr:%x" , iq_corr, i_pwr, q_pwr); +if (i_pwr && q_pwr) +break ; } i_coffd = ((i_pwr >>1 ) + (q_pwr >>1 )) >>7 ; q_coffd = q_pwr >>7 ; -/* No correction */ -if (i_coffd ==0 || q_coffd ==0 ) +/* protect against divide by 0 and loss of sign bits */ +if (i_coffd ==0 || q_coffd <2 ) goto done; - i_coff = ((-iq_corr) / i_coffd); + i_coff = (-iq_corr) / i_coffd; + i_coff =clamp (i_coff,-32 ,31 );/* signed 6 bit */ -/* Boundary check */ -if (i_coff >31 ) - i_coff =31 ; -if (i_coff <-32 ) - i_coff =-32 ; + q_coff = (i_pwr / q_coffd) -128 ; + q_coff =clamp (q_coff,-16 ,15 );/* signed 5 bit */ - q_coff = (((s32 )i_pwr / q_coffd) -128 ); +ATH5K_DBG_UNLIMIT (ah->ah_sc,ATH5K_DEBUG_CALIBRATE , +"new I:%d Q:%d (i_coffd:%x q_coffd:%x)" , + i_coff, q_coff, i_coffd, q_coffd); -/* Boundary check */ -if (q_coff >15 ) - q_coff =15 ; -if (q_coff <-16 ) - q_coff =-16 ; - -/* Commit new I/Q value */ -AR5K_REG_ENABLE_BITS (ah,AR5K_PHY_IQ ,AR5K_PHY_IQ_CORR_ENABLE | - ((u32 )q_coff) | ((u32 )i_coff <<AR5K_PHY_IQ_CORR_Q_I_COFF_S )); +/* Commit new I/Q values (set enable bit last to match HAL sources) */ +AR5K_REG_WRITE_BITS (ah,AR5K_PHY_IQ ,AR5K_PHY_IQ_CORR_Q_I_COFF , i_coff); +AR5K_REG_WRITE_BITS (ah,AR5K_PHY_IQ ,AR5K_PHY_IQ_CORR_Q_Q_COFF , q_coff); +AR5K_REG_ENABLE_BITS (ah,AR5K_PHY_IQ ,AR5K_PHY_IQ_CORR_ENABLE );/* Re-enable calibration -if we don't we'll commit * the same values again and again */
drivers/net/wireless/ath/ath5k/reg.h +1 -0
@@ -2187,6 +2187,7 @@*/ #define AR5K_PHY_IQ 0x9920/* Register Address */ #define AR5K_PHY_IQ_CORR_Q_Q_COFF 0x0000001f/* Mask for q correction info */ +#define AR5K_PHY_IQ_CORR_Q_Q_COFF_S 0#define AR5K_PHY_IQ_CORR_Q_I_COFF 0x000007e0/* Mask for i correction info */ #define AR5K_PHY_IQ_CORR_Q_I_COFF_S 5#define AR5K_PHY_IQ_CORR_ENABLE 0x00000800/* Enable i/q correction */
Re: [PATCH 10/13] ath5k: fix I/Q calibration (for real)
2010/3/9 Bruno Randolf <[email protected]>:
Quoted 107 lines
I/Q calibration was completely broken, resulting in a high number of CRC errors on received packets. before i could see around 10% to 20% CRC errors, with this patch they are between 0% and 3%.
1.) the removal of the mask in commit "ath5k: Fix I/Q calibration (
f1cf2dbd0f798b71b1590e7aca6647f2caef1649)" resulted in no mask beeing used when writing the I/Q values into the register. additional errors in the calculation of the values (see 2.) resulted too high numbers, exceeding the masks, so wrong values like0xfffffffewere written. to be safe we should always use the bitmask when writing parts of a register.2.) using a (s32) cast for
q_coffis a wrong conversion to signed, since we convert to a signed value later by substracting 128. this resulted in too low numbers for Q many times, which were limited to -16 by the boundary check later on.3.) checked everything against the HAL sources and took over comments and minor optimizations from there.
4.) we can't use
ENABLE_BITSwhen we want to write a number (the number can contain zeros). also always write the correction values first and set ENABLE bit last, like the HAL does.Signed-off-by Bruno Randolf <[email protected]>---
drivers/net/wireless/ath/ath5k/phy.c | 37 +++++++++++++++++-----------------drivers/net/wireless/ath/ath5k/reg.h| 1 +2 files changed, 20 insertions(+), 18 deletions(-)drivers/net/wireless/ath/ath5k/phy.c +19
-18@@ -1386,38 +1386,39 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, goto done; /* Calibration has finished, get the results and re-run */ + + /* work around empty results which can apparently happen on 5212 */ for (i = 0; i <= 10; i++) { iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR); i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I); q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q); + ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, + "iq_corr:%x i_pwr:%x q_pwr:%x", iq_corr, i_pwr, q_pwr); + if (i_pwr && q_pwr) + break; } i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7; q_coffd = q_pwr >> 7; - /* No correction */ - if (i_coffd == 0 || q_coffd == 0) + /* protect against divide by 0 and loss of sign bits */ + if (i_coffd == 0 || q_coffd < 2) goto done; - i_coff = ((-iq_corr) / i_coffd); + i_coff = (-iq_corr) / i_coffd; + i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */ - /* Boundary check */ - if (i_coff > 31) - i_coff = 31; - if (i_coff < -32) - i_coff = -32; + q_coff = (i_pwr / q_coffd) - 128; + q_coff = clamp(q_coff, -16, 15); /* signed 5 bit */ - q_coff = (((s32)i_pwr / q_coffd) - 128); + ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, + "new I:%d Q:%d (i_coffd:%x q_coffd:%x)", + i_coff, q_coff, i_coffd, q_coffd); - /* Boundary check */ - if (q_coff > 15) - q_coff = 15; - if (q_coff < -16) - q_coff = -16; - - /* Commit new I/Q value */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE | - ((u32)q_coff) | ((u32)i_coff << AR5K_PHY_IQ_CORR_Q_I_COFF_S)); + /* Commit new I/Q values (set enable bit last to match HAL sources) */ + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_Q_I_COFF, i_coff); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_Q_Q_COFF, q_coff); + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE); /* Re-enable calibration -if we don't we'll commit* the same values again and again */ drivers/net/wireless/ath/ath5k/reg.h +1
-1@@ -2187,6 +2187,7 @@*/ #define AR5K_PHY_IQ 0x9920 /* Register Address */ #define AR5K_PHY_IQ_CORR_Q_Q_COFF 0x0000001f /* Mask for q correction info */ +#define AR5K_PHY_IQ_CORR_Q_Q_COFF_S 0 #define AR5K_PHY_IQ_CORR_Q_I_COFF 0x000007e0 /* Mask for i correction info */ #define AR5K_PHY_IQ_CORR_Q_I_COFF_S 5 #define AR5K_PHY_IQ_CORR_ENABLE 0x00000800 /* Enable i/q correction */ --
Quoted 4 lines
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
GPG ID: 0xD21DB2DB As you read this post global entropy rises. Have Fun ;-) Nick
PATCH 11/13 ath5k: read eeprom IQ calibration values correctly for G mode
In reply to Bruno Randolfwe read the IQ correction values (i_cal and q_cal) for G mode from a wrong location (the same shifts as for A mode is applied which is incorrect). use correct locations, matching the docs and HAL sources.
also we should write IQ correction only when we have that information in the EEPROM, starting from version 4. also write it in the same way as we do in the periodic recalibration (enable last), just to be sure.
--- drivers/net/wireless/ath/ath5k/eeprom.c | 4 ++-- drivers/net/wireless/ath/ath5k/reset.c | 15 +++++++++------ 2 files changed, 11 insertions(+), 8 deletions(-)
drivers/net/wireless/ath/ath5k/eeprom.c +2 -2
@@ -429,8 +429,8 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, ee->ee_margin_tx_rx[mode] = (val >>8 ) &0x3f ;AR5K_EEPROM_READ (o++, val); - ee->ee_i_cal[mode] = (val >>8 ) &0x3f ; - ee->ee_q_cal[mode] = (val >>3 ) &0x1f ; + ee->ee_i_cal[mode] = (val >>5 ) &0x3f ; + ee->ee_q_cal[mode] = val &0x1f ;if (ah->ah_ee_version >=AR5K_EEPROM_VERSION_4_2 ) {AR5K_EEPROM_READ (o++, val);
drivers/net/wireless/ath/ath5k/reset.c +9 -6
@@ -851,12 +851,15 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1 , AR5K_INIT_CYCRSSI_THR1); -/* I/Q correction -* TODO: Per channel i/q infos ? */ -AR5K_REG_ENABLE_BITS (ah,AR5K_PHY_IQ , -AR5K_PHY_IQ_CORR_ENABLE | - (ee->ee_i_cal[ee_mode] <<AR5K_PHY_IQ_CORR_Q_I_COFF_S ) | - ee->ee_q_cal[ee_mode]); +/* I/Q correction (set enable bit last to match HAL sources) */ +/* TODO: Per channel i/q infos ? */ +if (ah->ah_ee_version >=AR5K_EEPROM_VERSION_4_0 ) { +AR5K_REG_WRITE_BITS (ah,AR5K_PHY_IQ ,AR5K_PHY_IQ_CORR_Q_I_COFF , + ee->ee_i_cal[ee_mode]); +AR5K_REG_WRITE_BITS (ah,AR5K_PHY_IQ ,AR5K_PHY_IQ_CORR_Q_Q_COFF , + ee->ee_q_cal[ee_mode]); +AR5K_REG_ENABLE_BITS (ah,AR5K_PHY_IQ ,AR5K_PHY_IQ_CORR_ENABLE ); + }/* Heavy clipping -disable for now */ if (ah->ah_ee_version >=AR5K_EEPROM_VERSION_5_1 )
Re: [PATCH 11/13] ath5k: read eeprom IQ calibration values correctly for G mode
2010/3/9 Bruno Randolf <[email protected]>:
Quoted 57 lines
we read the IQ correction values (
i_calandq_cal) for G mode from a wrong location (the same shifts as for A mode is applied which is incorrect). use correct locations, matching the docs and HAL sources.also we should write IQ correction only when we have that information in the EEPROM, starting from version 4. also write it in the same way as we do in the periodic recalibration (enable last), just to be sure.
Signed-off-by Bruno Randolf <[email protected]>---
drivers/net/wireless/ath/ath5k/eeprom.c | 4 ++--drivers/net/wireless/ath/ath5k/reset.c| 15 +++++++++------2 files changed, 11 insertions(+), 8 deletions(-)drivers/net/wireless/ath/ath5k/eeprom.c +2
-2@@ -429,8 +429,8 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f; AR5K_EEPROM_READ(o++, val); - ee->ee_i_cal[mode] = (val >> 8) & 0x3f; - ee->ee_q_cal[mode] = (val >> 3) & 0x1f; + ee->ee_i_cal[mode] = (val >> 5) & 0x3f; + ee->ee_q_cal[mode] = val & 0x1f; if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) { AR5K_EEPROM_READ(o++, val);drivers/net/wireless/ath/ath5k/reset.c +9
-7@@ -851,12 +851,15 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1, AR5K_INIT_CYCRSSI_THR1); - /* I/Q correction - * TODO: Per channel i/q infos ? */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, - AR5K_PHY_IQ_CORR_ENABLE | - (ee->ee_i_cal[ee_mode] << AR5K_PHY_IQ_CORR_Q_I_COFF_S) | - ee->ee_q_cal[ee_mode]); + /* I/Q correction (set enable bit last to match HAL sources) */ + /* TODO: Per channel i/q infos ? */ + if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) { + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_Q_I_COFF, + ee->ee_i_cal[ee_mode]); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_Q_Q_COFF, + ee->ee_q_cal[ee_mode]); + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE); + } /* Heavy clipping -disable for now */ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_1) --
Quoted 4 lines
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
GPG ID: 0xD21DB2DB As you read this post global entropy rises. Have Fun ;-) Nick
PATCH 12/13 ath5k: IQ calibration for AR5211 is slightly different
In reply to Bruno Randolfaccording to the HAL sources the calculation of the Q value is slightly different for AR5211 chips.
i couldn't test this since IQ calibration never finishes on older parts. this is a different problem...
--- drivers/net/wireless/ath/ath5k/phy.c | 11 +++++++++-- 1 files changed, 9 insertions(+), 2 deletions(-)
drivers/net/wireless/ath/ath5k/phy.c +9 -2
@@ -1399,7 +1399,11 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, } i_coffd = ((i_pwr >>1 ) + (q_pwr >>1 )) >>7 ; - q_coffd = q_pwr >>7 ; + +if (ah->ah_version ==AR5K_AR5211 ) + q_coffd = q_pwr >>6 ; +else + q_coffd = q_pwr >>7 ;/* protect against divide by 0 and loss of sign bits */ if (i_coffd ==0 || q_coffd <2 )
@@ -1408,7 +1412,10 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, i_coff = (-iq_corr) / i_coffd; i_coff =clamp (i_coff,-32 ,31 );/* signed 6 bit */ - q_coff = (i_pwr / q_coffd) -128 ; +if (ah->ah_version ==AR5K_AR5211 ) + q_coff = (i_pwr / q_coffd) -64 ; +else + q_coff = (i_pwr / q_coffd) -128 ; q_coff =clamp (q_coff,-16 ,15 );/* signed 5 bit */ ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
Re: [PATCH 12/13] ath5k: IQ calibration for AR5211 is slightly different
2010/3/9 Bruno Randolf <[email protected]>:
Quoted 39 lines
according to the HAL sources the calculation of the Q value is slightly different for AR5211 chips.
i couldn't test this since IQ calibration never finishes on older parts. this is a different problem...
Signed-off-by Bruno Randolf <[email protected]>---
drivers/net/wireless/ath/ath5k/phy.c | 11 +++++++++--1 files changed, 9 insertions(+), 2 deletions(-)drivers/net/wireless/ath/ath5k/phy.c +5
-1@@ -1399,7 +1399,11 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, } i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7; - q_coffd = q_pwr >> 7; + + if (ah->ah_version == AR5K_AR5211) + q_coffd = q_pwr >> 6; + else + q_coffd = q_pwr >> 7; /* protect against divide by 0 and loss of sign bits */ if (i_coffd == 0 || q_coffd < 2)@@ -1408,7 +1412,10 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, i_coff = (-iq_corr) / i_coffd;i_coff =
clamp(i_coff, -32, 31); /* signed 6 bit */-
q_coff= (i_pwr/q_coffd) - 128;
+ if (ah->ah_version==AR5K_AR5211)
+q_coff= (i_pwr/q_coffd) - 64;
+ else
+q_coff= (i_pwr/q_coffd) - 128;q_coff=clamp(q_coff, -16, 15); /* signed 5 bit */
Quoted 7 lines
ATH5K_DBG_UNLIMIT(ah->ah_sc,
ATH5K_DEBUG_CALIBRATE,--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
GPG ID: 0xD21DB2DB As you read this post global entropy rises. Have Fun ;-) Nick
PATCH 13/13 ath5k: Minor EEPROM documentation updates
In reply to Bruno RandolfHere are some minor updates for EEPROM, mostly documentation and some small fixes which have no effect at the moment.
- fixed_bias is not available for B mode.
- AR5K_EEPROM_[RT]X_CHAIN_DIS is 3 bit. this is MIMO and will not be used in ath5k, but just to be correct.
- AR5K_EEPROM_JAP_MID_EN added, and shift of following flags adapted.
- added some documentation for EEPROM values and some comments.
--- drivers/net/wireless/ath/ath5k/eeprom.c | 4 + drivers/net/wireless/ath/ath5k/eeprom.h | 85 +++++++++++++++++++++++-------- drivers/net/wireless/ath/ath5k/reg.h | 2 - 3 files changed, 68 insertions(+), 23 deletions(-)
drivers/net/wireless/ath/ath5k/eeprom.c +3 -1
@@ -329,7 +329,8 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, ee->ee_x_gain[mode] = (val >>1 ) &0xf ; ee->ee_xpd[mode] = val &0x1 ; -if (ah->ah_ee_version >=AR5K_EEPROM_VERSION_4_0 ) +if (ah->ah_ee_version >=AR5K_EEPROM_VERSION_4_0 && + mode !=AR5K_EEPROM_MODE_11B ) ee->ee_fixed_bias[mode] = (val >>13 ) &0x1 ;if (ah->ah_ee_version >=AR5K_EEPROM_VERSION_3_3 ) {
@@ -339,6 +340,7 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,if (mode ==AR5K_EEPROM_MODE_11A ) ee->ee_xr_power[mode] = val &0x3f ;else { +/* b_DB_11[bg] and b_OB_11[bg] */ ee->ee_ob[mode][0 ] = val &0x7 ; ee->ee_db[mode][0 ] = (val >>3 ) &0x7 ; }
drivers/net/wireless/ath/ath5k/eeprom.h +64 -21
113 lines not on this page · raw message
drivers/net/wireless/ath/ath5k/reg.h +1 -1
@@ -1974,7 +1974,7 @@#define AR5K_PHY_SETTLING 0x9844/* Register Address */ #define AR5K_PHY_SETTLING_AGC 0x0000007f/* AGC settling time */ #define AR5K_PHY_SETTLING_AGC_S 0 -#define AR5K_PHY_SETTLING_SWITCH 0x00003f80/* Switch settlig time */ +#define AR5K_PHY_SETTLING_SWITCH 0x00003f80/* Switch settling time */ #define AR5K_PHY_SETTLING_SWITCH_S 7/*
Quoted 8 lines · Bruno Randolf
since it must be difficult for john to track all the different revisions of my patches i send them here again as a clean series.
two of them are new:
ath5k: add debugfs file frameerrors
ath5k: Minor EEPROM documentation updatesothers may be slightly updated.
Thank you for posting the clean series! I'll try to get to them soon...
John
Signature · 2 lines
John W. Linville Someday the world will need a hero, and you [email protected] might be all we have. Be ready.