diff options
author | Nick Kossifidis <mick@madwifi-project.org> | 2009-04-30 15:55:49 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-05-06 15:14:56 -0400 |
commit | 2bed03ebf62f9d013a455209bf30d7e086120443 (patch) | |
tree | 35592ca12f0e4425213e317895612c3ce15ad3a5 /drivers | |
parent | 6f5f39c95af519c24c0187950147eb79d07d1940 (diff) |
ath5k: Implement antenna control
* Add code to support the various antenna scenarios supported by hw
* For now hardcode the default scenario (single or dual omnis with
tx/rx diversity working and tx antenna handled by session -hw keeps
track on which antenna it got ack from each ap/station and maps each
ap/station to one of the antennas-).
Signed-off-by: Nick Kossifidis <mickflemm@gmail.com>
Signed-off-by: Bob Copeland <me@bobcopeland.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/ath/ath5k/ath5k.h | 25 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/attach.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/base.c | 66 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/eeprom.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/eeprom.h | 11 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/phy.c | 174 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/reg.h | 9 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/reset.c | 28 |
8 files changed, 271 insertions, 51 deletions
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 04b73453f6a5..33da290e4bb5 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h | |||
@@ -209,7 +209,6 @@ | |||
209 | #define AR5K_TUNE_MAX_TXPOWER 63 | 209 | #define AR5K_TUNE_MAX_TXPOWER 63 |
210 | #define AR5K_TUNE_DEFAULT_TXPOWER 25 | 210 | #define AR5K_TUNE_DEFAULT_TXPOWER 25 |
211 | #define AR5K_TUNE_TPC_TXPOWER false | 211 | #define AR5K_TUNE_TPC_TXPOWER false |
212 | #define AR5K_TUNE_ANT_DIVERSITY true | ||
213 | #define AR5K_TUNE_HWTXTRIES 4 | 212 | #define AR5K_TUNE_HWTXTRIES 4 |
214 | 213 | ||
215 | #define AR5K_INIT_CARR_SENSE_EN 1 | 214 | #define AR5K_INIT_CARR_SENSE_EN 1 |
@@ -420,6 +419,17 @@ enum ath5k_driver_mode { | |||
420 | AR5K_MODE_MAX = 5 | 419 | AR5K_MODE_MAX = 5 |
421 | }; | 420 | }; |
422 | 421 | ||
422 | enum ath5k_ant_mode { | ||
423 | AR5K_ANTMODE_DEFAULT = 0, /* default antenna setup */ | ||
424 | AR5K_ANTMODE_FIXED_A = 1, /* only antenna A is present */ | ||
425 | AR5K_ANTMODE_FIXED_B = 2, /* only antenna B is present */ | ||
426 | AR5K_ANTMODE_SINGLE_AP = 3, /* sta locked on a single ap */ | ||
427 | AR5K_ANTMODE_SECTOR_AP = 4, /* AP with tx antenna set on tx desc */ | ||
428 | AR5K_ANTMODE_SECTOR_STA = 5, /* STA with tx antenna set on tx desc */ | ||
429 | AR5K_ANTMODE_DEBUG = 6, /* Debug mode -A -> Rx, B-> Tx- */ | ||
430 | AR5K_ANTMODE_MAX, | ||
431 | }; | ||
432 | |||
423 | 433 | ||
424 | /****************\ | 434 | /****************\ |
425 | TX DEFINITIONS | 435 | TX DEFINITIONS |
@@ -1051,8 +1061,11 @@ struct ath5k_hw { | |||
1051 | bool ah_software_retry; | 1061 | bool ah_software_retry; |
1052 | u32 ah_limit_tx_retries; | 1062 | u32 ah_limit_tx_retries; |
1053 | 1063 | ||
1054 | u32 ah_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; | 1064 | /* Antenna Control */ |
1055 | bool ah_ant_diversity; | 1065 | u32 ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; |
1066 | u8 ah_ant_mode; | ||
1067 | u8 ah_tx_ant; | ||
1068 | u8 ah_def_ant; | ||
1056 | 1069 | ||
1057 | u8 ah_sta_id[ETH_ALEN]; | 1070 | u8 ah_sta_id[ETH_ALEN]; |
1058 | 1071 | ||
@@ -1267,9 +1280,11 @@ extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel | |||
1267 | extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq); | 1280 | extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq); |
1268 | /* Misc PHY functions */ | 1281 | /* Misc PHY functions */ |
1269 | extern u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); | 1282 | extern u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); |
1270 | extern void ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant); | ||
1271 | extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah); | ||
1272 | extern int ath5k_hw_phy_disable(struct ath5k_hw *ah); | 1283 | extern int ath5k_hw_phy_disable(struct ath5k_hw *ah); |
1284 | /* Antenna control */ | ||
1285 | extern void ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode); | ||
1286 | extern void ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant); | ||
1287 | extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah); | ||
1273 | /* TX power setup */ | 1288 | /* TX power setup */ |
1274 | extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, u8 ee_mode, u8 txpower); | 1289 | extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, u8 ee_mode, u8 txpower); |
1275 | extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower); | 1290 | extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower); |
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index 70d376c63aac..c41ef58393e7 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c | |||
@@ -133,7 +133,6 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) | |||
133 | ah->ah_cw_min = AR5K_TUNE_CWMIN; | 133 | ah->ah_cw_min = AR5K_TUNE_CWMIN; |
134 | ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; | 134 | ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; |
135 | ah->ah_software_retry = false; | 135 | ah->ah_software_retry = false; |
136 | ah->ah_ant_diversity = AR5K_TUNE_ANT_DIVERSITY; | ||
137 | 136 | ||
138 | /* | 137 | /* |
139 | * Set the mac version based on the pci id | 138 | * Set the mac version based on the pci id |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 912ffc5c0203..6789c5dfcc76 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -1279,7 +1279,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
1279 | ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL, | 1279 | ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL, |
1280 | (sc->power_level * 2), | 1280 | (sc->power_level * 2), |
1281 | hw_rate, | 1281 | hw_rate, |
1282 | info->control.rates[0].count, keyidx, 0, flags, | 1282 | info->control.rates[0].count, keyidx, ah->ah_tx_ant, flags, |
1283 | cts_rate, duration); | 1283 | cts_rate, duration); |
1284 | if (ret) | 1284 | if (ret) |
1285 | goto err_unmap; | 1285 | goto err_unmap; |
@@ -2009,7 +2009,8 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
2009 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 2009 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
2010 | struct ath5k_hw *ah = sc->ah; | 2010 | struct ath5k_hw *ah = sc->ah; |
2011 | struct ath5k_desc *ds; | 2011 | struct ath5k_desc *ds; |
2012 | int ret, antenna = 0; | 2012 | int ret = 0; |
2013 | u8 antenna; | ||
2013 | u32 flags; | 2014 | u32 flags; |
2014 | 2015 | ||
2015 | bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, | 2016 | bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, |
@@ -2023,23 +2024,35 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
2023 | } | 2024 | } |
2024 | 2025 | ||
2025 | ds = bf->desc; | 2026 | ds = bf->desc; |
2027 | antenna = ah->ah_tx_ant; | ||
2026 | 2028 | ||
2027 | flags = AR5K_TXDESC_NOACK; | 2029 | flags = AR5K_TXDESC_NOACK; |
2028 | if (sc->opmode == NL80211_IFTYPE_ADHOC && ath5k_hw_hasveol(ah)) { | 2030 | if (sc->opmode == NL80211_IFTYPE_ADHOC && ath5k_hw_hasveol(ah)) { |
2029 | ds->ds_link = bf->daddr; /* self-linked */ | 2031 | ds->ds_link = bf->daddr; /* self-linked */ |
2030 | flags |= AR5K_TXDESC_VEOL; | 2032 | flags |= AR5K_TXDESC_VEOL; |
2031 | /* | 2033 | } else |
2032 | * Let hardware handle antenna switching if txantenna is not set | ||
2033 | */ | ||
2034 | } else { | ||
2035 | ds->ds_link = 0; | 2034 | ds->ds_link = 0; |
2036 | /* | 2035 | |
2037 | * Switch antenna every 4 beacons if txantenna is not set | 2036 | /* |
2038 | * XXX assumes two antennas | 2037 | * If we use multiple antennas on AP and use |
2039 | */ | 2038 | * the Sectored AP scenario, switch antenna every |
2040 | if (antenna == 0) | 2039 | * 4 beacons to make sure everybody hears our AP. |
2041 | antenna = sc->bsent & 4 ? 2 : 1; | 2040 | * When a client tries to associate, hw will keep |
2042 | } | 2041 | * track of the tx antenna to be used for this client |
2042 | * automaticaly, based on ACKed packets. | ||
2043 | * | ||
2044 | * Note: AP still listens and transmits RTS on the | ||
2045 | * default antenna which is supposed to be an omni. | ||
2046 | * | ||
2047 | * Note2: On sectored scenarios it's possible to have | ||
2048 | * multiple antennas (1omni -the default- and 14 sectors) | ||
2049 | * so if we choose to actually support this mode we need | ||
2050 | * to allow user to set how many antennas we have and tweak | ||
2051 | * the code below to send beacons on all of them. | ||
2052 | */ | ||
2053 | if (ah->ah_ant_mode == AR5K_ANTMODE_SECTOR_AP) | ||
2054 | antenna = sc->bsent & 4 ? 2 : 1; | ||
2055 | |||
2043 | 2056 | ||
2044 | /* FIXME: If we are in g mode and rate is a CCK rate | 2057 | /* FIXME: If we are in g mode and rate is a CCK rate |
2045 | * subtract ah->ah_txpower.txp_cck_ofdm_pwr_delta | 2058 | * subtract ah->ah_txpower.txp_cck_ofdm_pwr_delta |
@@ -2752,12 +2765,16 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed) | |||
2752 | struct ath5k_softc *sc = hw->priv; | 2765 | struct ath5k_softc *sc = hw->priv; |
2753 | struct ath5k_hw *ah = sc->ah; | 2766 | struct ath5k_hw *ah = sc->ah; |
2754 | struct ieee80211_conf *conf = &hw->conf; | 2767 | struct ieee80211_conf *conf = &hw->conf; |
2755 | int ret; | 2768 | int ret = 0; |
2756 | 2769 | ||
2757 | mutex_lock(&sc->lock); | 2770 | mutex_lock(&sc->lock); |
2758 | 2771 | ||
2759 | sc->bintval = conf->beacon_int; | 2772 | sc->bintval = conf->beacon_int; |
2760 | 2773 | ||
2774 | ret = ath5k_chan_set(sc, conf->channel); | ||
2775 | if (ret < 0) | ||
2776 | return ret; | ||
2777 | |||
2761 | if ((changed & IEEE80211_CONF_CHANGE_POWER) && | 2778 | if ((changed & IEEE80211_CONF_CHANGE_POWER) && |
2762 | (sc->power_level != conf->power_level)) { | 2779 | (sc->power_level != conf->power_level)) { |
2763 | sc->power_level = conf->power_level; | 2780 | sc->power_level = conf->power_level; |
@@ -2766,10 +2783,27 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed) | |||
2766 | ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2)); | 2783 | ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2)); |
2767 | } | 2784 | } |
2768 | 2785 | ||
2769 | ret = ath5k_chan_set(sc, conf->channel); | 2786 | /* TODO: |
2787 | * 1) Move this on config_interface and handle each case | ||
2788 | * separately eg. when we have only one STA vif, use | ||
2789 | * AR5K_ANTMODE_SINGLE_AP | ||
2790 | * | ||
2791 | * 2) Allow the user to change antenna mode eg. when only | ||
2792 | * one antenna is present | ||
2793 | * | ||
2794 | * 3) Allow the user to set default/tx antenna when possible | ||
2795 | * | ||
2796 | * 4) Default mode should handle 90% of the cases, together | ||
2797 | * with fixed a/b and single AP modes we should be able to | ||
2798 | * handle 99%. Sectored modes are extreme cases and i still | ||
2799 | * haven't found a usage for them. If we decide to support them, | ||
2800 | * then we must allow the user to set how many tx antennas we | ||
2801 | * have available | ||
2802 | */ | ||
2803 | ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT); | ||
2770 | 2804 | ||
2771 | mutex_unlock(&sc->lock); | 2805 | mutex_unlock(&sc->lock); |
2772 | return ret; | 2806 | return 0; |
2773 | } | 2807 | } |
2774 | 2808 | ||
2775 | #define SUPPORTED_FIF_FLAGS \ | 2809 | #define SUPPORTED_FIF_FLAGS \ |
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index 8c9dd019d761..c56b494d417a 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c | |||
@@ -208,16 +208,16 @@ static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset, | |||
208 | ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f; | 208 | ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f; |
209 | ee->ee_ant_control[mode][i++] = val & 0x3f; | 209 | ee->ee_ant_control[mode][i++] = val & 0x3f; |
210 | 210 | ||
211 | /* Get antenna modes */ | 211 | /* Get antenna switch tables */ |
212 | ah->ah_antenna[mode][0] = | 212 | ah->ah_ant_ctl[mode][AR5K_ANT_CTL] = |
213 | (ee->ee_ant_control[mode][0] << 4); | 213 | (ee->ee_ant_control[mode][0] << 4); |
214 | ah->ah_antenna[mode][AR5K_ANT_FIXED_A] = | 214 | ah->ah_ant_ctl[mode][AR5K_ANT_SWTABLE_A] = |
215 | ee->ee_ant_control[mode][1] | | 215 | ee->ee_ant_control[mode][1] | |
216 | (ee->ee_ant_control[mode][2] << 6) | | 216 | (ee->ee_ant_control[mode][2] << 6) | |
217 | (ee->ee_ant_control[mode][3] << 12) | | 217 | (ee->ee_ant_control[mode][3] << 12) | |
218 | (ee->ee_ant_control[mode][4] << 18) | | 218 | (ee->ee_ant_control[mode][4] << 18) | |
219 | (ee->ee_ant_control[mode][5] << 24); | 219 | (ee->ee_ant_control[mode][5] << 24); |
220 | ah->ah_antenna[mode][AR5K_ANT_FIXED_B] = | 220 | ah->ah_ant_ctl[mode][AR5K_ANT_SWTABLE_B] = |
221 | ee->ee_ant_control[mode][6] | | 221 | ee->ee_ant_control[mode][6] | |
222 | (ee->ee_ant_control[mode][7] << 6) | | 222 | (ee->ee_ant_control[mode][7] << 6) | |
223 | (ee->ee_ant_control[mode][8] << 12) | | 223 | (ee->ee_ant_control[mode][8] << 12) | |
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h index 46e4d22591f6..64be73a5edae 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.h +++ b/drivers/net/wireless/ath/ath5k/eeprom.h | |||
@@ -240,11 +240,11 @@ enum ath5k_eeprom_freq_bands{ | |||
240 | #define AR5K_EEPROM_READ_HDR(_o, _v) \ | 240 | #define AR5K_EEPROM_READ_HDR(_o, _v) \ |
241 | AR5K_EEPROM_READ(_o, ah->ah_capabilities.cap_eeprom._v); \ | 241 | AR5K_EEPROM_READ(_o, ah->ah_capabilities.cap_eeprom._v); \ |
242 | 242 | ||
243 | enum ath5k_ant_setting { | 243 | enum ath5k_ant_table { |
244 | AR5K_ANT_VARIABLE = 0, /* variable by programming */ | 244 | AR5K_ANT_CTL = 0, /* Idle switch table settings */ |
245 | AR5K_ANT_FIXED_A = 1, /* fixed to 11a frequencies */ | 245 | AR5K_ANT_SWTABLE_A = 1, /* Switch table for antenna A */ |
246 | AR5K_ANT_FIXED_B = 2, /* fixed to 11b frequencies */ | 246 | AR5K_ANT_SWTABLE_B = 2, /* Switch table for antenna B */ |
247 | AR5K_ANT_MAX = 3, | 247 | AR5K_ANT_MAX, |
248 | }; | 248 | }; |
249 | 249 | ||
250 | enum ath5k_ctl_mode { | 250 | enum ath5k_ctl_mode { |
@@ -461,6 +461,7 @@ struct ath5k_eeprom_info { | |||
461 | /* Spur mitigation data (fbin values for spur channels) */ | 461 | /* Spur mitigation data (fbin values for spur channels) */ |
462 | u16 ee_spur_chans[AR5K_EEPROM_N_SPUR_CHANS][AR5K_EEPROM_N_FREQ_BANDS]; | 462 | u16 ee_spur_chans[AR5K_EEPROM_N_SPUR_CHANS][AR5K_EEPROM_N_FREQ_BANDS]; |
463 | 463 | ||
464 | /* Antenna raw switch tables */ | ||
464 | u32 ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; | 465 | u32 ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; |
465 | }; | 466 | }; |
466 | 467 | ||
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index bb61b8e2dce9..fd93c4e20214 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c | |||
@@ -1414,25 +1414,189 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) | |||
1414 | return ret; | 1414 | return ret; |
1415 | } | 1415 | } |
1416 | 1416 | ||
1417 | /*****************\ | ||
1418 | * Antenna control * | ||
1419 | \*****************/ | ||
1420 | |||
1417 | void /*TODO:Boundary check*/ | 1421 | void /*TODO:Boundary check*/ |
1418 | ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant) | 1422 | ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant) |
1419 | { | 1423 | { |
1420 | ATH5K_TRACE(ah->ah_sc); | 1424 | ATH5K_TRACE(ah->ah_sc); |
1421 | /*Just a try M.F.*/ | 1425 | |
1422 | if (ah->ah_version != AR5K_AR5210) | 1426 | if (ah->ah_version != AR5K_AR5210) |
1423 | ath5k_hw_reg_write(ah, ant, AR5K_DEFAULT_ANTENNA); | 1427 | ath5k_hw_reg_write(ah, ant & 0x7, AR5K_DEFAULT_ANTENNA); |
1424 | } | 1428 | } |
1425 | 1429 | ||
1426 | unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah) | 1430 | unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah) |
1427 | { | 1431 | { |
1428 | ATH5K_TRACE(ah->ah_sc); | 1432 | ATH5K_TRACE(ah->ah_sc); |
1429 | /*Just a try M.F.*/ | 1433 | |
1430 | if (ah->ah_version != AR5K_AR5210) | 1434 | if (ah->ah_version != AR5K_AR5210) |
1431 | return ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA); | 1435 | return ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA) & 0x7; |
1432 | 1436 | ||
1433 | return false; /*XXX: What do we return for 5210 ?*/ | 1437 | return false; /*XXX: What do we return for 5210 ?*/ |
1434 | } | 1438 | } |
1435 | 1439 | ||
1440 | /* | ||
1441 | * Enable/disable fast rx antenna diversity | ||
1442 | */ | ||
1443 | static void | ||
1444 | ath5k_hw_set_fast_div(struct ath5k_hw *ah, u8 ee_mode, bool enable) | ||
1445 | { | ||
1446 | switch (ee_mode) { | ||
1447 | case AR5K_EEPROM_MODE_11G: | ||
1448 | /* XXX: This is set to | ||
1449 | * disabled on initvals !!! */ | ||
1450 | case AR5K_EEPROM_MODE_11A: | ||
1451 | if (enable) | ||
1452 | AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGCCTL, | ||
1453 | AR5K_PHY_AGCCTL_OFDM_DIV_DIS); | ||
1454 | else | ||
1455 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | ||
1456 | AR5K_PHY_AGCCTL_OFDM_DIV_DIS); | ||
1457 | break; | ||
1458 | case AR5K_EEPROM_MODE_11B: | ||
1459 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | ||
1460 | AR5K_PHY_AGCCTL_OFDM_DIV_DIS); | ||
1461 | break; | ||
1462 | default: | ||
1463 | return; | ||
1464 | } | ||
1465 | |||
1466 | if (enable) { | ||
1467 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART, | ||
1468 | AR5K_PHY_RESTART_DIV_GC, 0xc); | ||
1469 | |||
1470 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV, | ||
1471 | AR5K_PHY_FAST_ANT_DIV_EN); | ||
1472 | } else { | ||
1473 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART, | ||
1474 | AR5K_PHY_RESTART_DIV_GC, 0x8); | ||
1475 | |||
1476 | AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV, | ||
1477 | AR5K_PHY_FAST_ANT_DIV_EN); | ||
1478 | } | ||
1479 | } | ||
1480 | |||
1481 | /* | ||
1482 | * Set antenna operating mode | ||
1483 | */ | ||
1484 | void | ||
1485 | ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) | ||
1486 | { | ||
1487 | struct ieee80211_channel *channel = &ah->ah_current_channel; | ||
1488 | bool use_def_for_tx, update_def_on_tx, use_def_for_rts, fast_div; | ||
1489 | bool use_def_for_sg; | ||
1490 | u8 def_ant, tx_ant, ee_mode; | ||
1491 | u32 sta_id1 = 0; | ||
1492 | |||
1493 | def_ant = ah->ah_def_ant; | ||
1494 | |||
1495 | ATH5K_TRACE(ah->ah_sc); | ||
1496 | |||
1497 | switch (channel->hw_value & CHANNEL_MODES) { | ||
1498 | case CHANNEL_A: | ||
1499 | case CHANNEL_T: | ||
1500 | case CHANNEL_XR: | ||
1501 | ee_mode = AR5K_EEPROM_MODE_11A; | ||
1502 | break; | ||
1503 | case CHANNEL_G: | ||
1504 | case CHANNEL_TG: | ||
1505 | ee_mode = AR5K_EEPROM_MODE_11G; | ||
1506 | break; | ||
1507 | case CHANNEL_B: | ||
1508 | ee_mode = AR5K_EEPROM_MODE_11B; | ||
1509 | break; | ||
1510 | default: | ||
1511 | ATH5K_ERR(ah->ah_sc, | ||
1512 | "invalid channel: %d\n", channel->center_freq); | ||
1513 | return; | ||
1514 | } | ||
1515 | |||
1516 | switch (ant_mode) { | ||
1517 | case AR5K_ANTMODE_DEFAULT: | ||
1518 | tx_ant = 0; | ||
1519 | use_def_for_tx = false; | ||
1520 | update_def_on_tx = false; | ||
1521 | use_def_for_rts = false; | ||
1522 | use_def_for_sg = false; | ||
1523 | fast_div = true; | ||
1524 | break; | ||
1525 | case AR5K_ANTMODE_FIXED_A: | ||
1526 | def_ant = 1; | ||
1527 | tx_ant = 0; | ||
1528 | use_def_for_tx = true; | ||
1529 | update_def_on_tx = false; | ||
1530 | use_def_for_rts = true; | ||
1531 | use_def_for_sg = true; | ||
1532 | fast_div = false; | ||
1533 | break; | ||
1534 | case AR5K_ANTMODE_FIXED_B: | ||
1535 | def_ant = 2; | ||
1536 | tx_ant = 0; | ||
1537 | use_def_for_tx = true; | ||
1538 | update_def_on_tx = false; | ||
1539 | use_def_for_rts = true; | ||
1540 | use_def_for_sg = true; | ||
1541 | fast_div = false; | ||
1542 | break; | ||
1543 | case AR5K_ANTMODE_SINGLE_AP: | ||
1544 | def_ant = 1; /* updated on tx */ | ||
1545 | tx_ant = 0; | ||
1546 | use_def_for_tx = true; | ||
1547 | update_def_on_tx = true; | ||
1548 | use_def_for_rts = true; | ||
1549 | use_def_for_sg = true; | ||
1550 | fast_div = true; | ||
1551 | break; | ||
1552 | case AR5K_ANTMODE_SECTOR_AP: | ||
1553 | tx_ant = 1; /* variable */ | ||
1554 | use_def_for_tx = false; | ||
1555 | update_def_on_tx = false; | ||
1556 | use_def_for_rts = true; | ||
1557 | use_def_for_sg = false; | ||
1558 | fast_div = false; | ||
1559 | break; | ||
1560 | case AR5K_ANTMODE_SECTOR_STA: | ||
1561 | tx_ant = 1; /* variable */ | ||
1562 | use_def_for_tx = true; | ||
1563 | update_def_on_tx = false; | ||
1564 | use_def_for_rts = true; | ||
1565 | use_def_for_sg = false; | ||
1566 | fast_div = true; | ||
1567 | break; | ||
1568 | case AR5K_ANTMODE_DEBUG: | ||
1569 | def_ant = 1; | ||
1570 | tx_ant = 2; | ||
1571 | use_def_for_tx = false; | ||
1572 | update_def_on_tx = false; | ||
1573 | use_def_for_rts = false; | ||
1574 | use_def_for_sg = false; | ||
1575 | fast_div = false; | ||
1576 | break; | ||
1577 | default: | ||
1578 | return; | ||
1579 | } | ||
1580 | |||
1581 | ah->ah_tx_ant = tx_ant; | ||
1582 | ah->ah_ant_mode = ant_mode; | ||
1583 | |||
1584 | sta_id1 |= use_def_for_tx ? AR5K_STA_ID1_DEFAULT_ANTENNA : 0; | ||
1585 | sta_id1 |= update_def_on_tx ? AR5K_STA_ID1_DESC_ANTENNA : 0; | ||
1586 | sta_id1 |= use_def_for_rts ? AR5K_STA_ID1_RTS_DEF_ANTENNA : 0; | ||
1587 | sta_id1 |= use_def_for_sg ? AR5K_STA_ID1_SELFGEN_DEF_ANT : 0; | ||
1588 | |||
1589 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_ANTENNA_SETTINGS); | ||
1590 | |||
1591 | if (sta_id1) | ||
1592 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, sta_id1); | ||
1593 | |||
1594 | /* Note: set diversity before default antenna | ||
1595 | * because it won't work correctly */ | ||
1596 | ath5k_hw_set_fast_div(ah, ee_mode, fast_div); | ||
1597 | ath5k_hw_set_def_antenna(ah, def_ant); | ||
1598 | } | ||
1599 | |||
1436 | 1600 | ||
1437 | /****************\ | 1601 | /****************\ |
1438 | * TX power setup * | 1602 | * TX power setup * |
diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index 7070d1543cdc..6809b54a2ad7 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h | |||
@@ -1148,6 +1148,11 @@ | |||
1148 | #define AR5K_STA_ID1_CBCIV_ENDIAN 0x40000000 /* ??? */ | 1148 | #define AR5K_STA_ID1_CBCIV_ENDIAN 0x40000000 /* ??? */ |
1149 | #define AR5K_STA_ID1_KEYSRCH_MCAST 0x80000000 /* Do key cache search for mcast frames */ | 1149 | #define AR5K_STA_ID1_KEYSRCH_MCAST 0x80000000 /* Do key cache search for mcast frames */ |
1150 | 1150 | ||
1151 | #define AR5K_STA_ID1_ANTENNA_SETTINGS (AR5K_STA_ID1_DEFAULT_ANTENNA | \ | ||
1152 | AR5K_STA_ID1_DESC_ANTENNA | \ | ||
1153 | AR5K_STA_ID1_RTS_DEF_ANTENNA | \ | ||
1154 | AR5K_STA_ID1_SELFGEN_DEF_ANT) | ||
1155 | |||
1151 | /* | 1156 | /* |
1152 | * First BSSID register (MAC address, lower 32bits) | 1157 | * First BSSID register (MAC address, lower 32bits) |
1153 | */ | 1158 | */ |
@@ -2028,7 +2033,9 @@ | |||
2028 | #define AR5K_PHY_AGCCTL 0x9860 /* Register address */ | 2033 | #define AR5K_PHY_AGCCTL 0x9860 /* Register address */ |
2029 | #define AR5K_PHY_AGCCTL_CAL 0x00000001 /* Enable PHY calibration */ | 2034 | #define AR5K_PHY_AGCCTL_CAL 0x00000001 /* Enable PHY calibration */ |
2030 | #define AR5K_PHY_AGCCTL_NF 0x00000002 /* Enable Noise Floor calibration */ | 2035 | #define AR5K_PHY_AGCCTL_NF 0x00000002 /* Enable Noise Floor calibration */ |
2036 | #define AR5K_PHY_AGCCTL_OFDM_DIV_DIS 0x00000008 /* Disable antenna diversity on OFDM modes */ | ||
2031 | #define AR5K_PHY_AGCCTL_NF_EN 0x00008000 /* Enable nf calibration to happen (?) */ | 2037 | #define AR5K_PHY_AGCCTL_NF_EN 0x00008000 /* Enable nf calibration to happen (?) */ |
2038 | #define AR5K_PHY_AGCTL_FLTR_CAL 0x00010000 /* Allow filter calibration (?) */ | ||
2032 | #define AR5K_PHY_AGCCTL_NF_NOUPDATE 0x00020000 /* Don't update nf automaticaly */ | 2039 | #define AR5K_PHY_AGCCTL_NF_NOUPDATE 0x00020000 /* Don't update nf automaticaly */ |
2033 | 2040 | ||
2034 | /* | 2041 | /* |
@@ -2528,7 +2535,7 @@ | |||
2528 | * PHY CCK Cross-correlator Barker RSSI threshold register [5212+] | 2535 | * PHY CCK Cross-correlator Barker RSSI threshold register [5212+] |
2529 | */ | 2536 | */ |
2530 | #define AR5K_PHY_CCK_CROSSCORR 0xa208 | 2537 | #define AR5K_PHY_CCK_CROSSCORR 0xa208 |
2531 | #define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR 0x0000000f | 2538 | #define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR 0x0000003f |
2532 | #define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR_S 0 | 2539 | #define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR_S 0 |
2533 | 2540 | ||
2534 | /* Same address is used for antenna diversity activation */ | 2541 | /* Same address is used for antenna diversity activation */ |
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index d419c6a3ded7..0e075bca384f 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c | |||
@@ -698,13 +698,13 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, | |||
698 | /* Set antenna idle switch table */ | 698 | /* Set antenna idle switch table */ |
699 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_ANT_CTL, | 699 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_ANT_CTL, |
700 | AR5K_PHY_ANT_CTL_SWTABLE_IDLE, | 700 | AR5K_PHY_ANT_CTL_SWTABLE_IDLE, |
701 | (ah->ah_antenna[ee_mode][0] | | 701 | (ah->ah_ant_ctl[ee_mode][0] | |
702 | AR5K_PHY_ANT_CTL_TXRX_EN)); | 702 | AR5K_PHY_ANT_CTL_TXRX_EN)); |
703 | 703 | ||
704 | /* Set antenna switch table */ | 704 | /* Set antenna switch tables */ |
705 | ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[0]], | 705 | ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant[0]], |
706 | AR5K_PHY_ANT_SWITCH_TABLE_0); | 706 | AR5K_PHY_ANT_SWITCH_TABLE_0); |
707 | ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[1]], | 707 | ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant[1]], |
708 | AR5K_PHY_ANT_SWITCH_TABLE_1); | 708 | AR5K_PHY_ANT_SWITCH_TABLE_1); |
709 | 709 | ||
710 | /* Noise floor threshold */ | 710 | /* Noise floor threshold */ |
@@ -1042,17 +1042,15 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1042 | 1042 | ||
1043 | /* | 1043 | /* |
1044 | * In case a fixed antenna was set as default | 1044 | * In case a fixed antenna was set as default |
1045 | * write the same settings on both AR5K_PHY_ANT_SWITCH_TABLE | 1045 | * use the same switch table twice. |
1046 | * registers. | ||
1047 | */ | 1046 | */ |
1048 | if (s_ant != 0) { | 1047 | if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_A) |
1049 | if (s_ant == AR5K_ANT_FIXED_A) /* 1 - Main */ | 1048 | ant[0] = ant[1] = AR5K_ANT_SWTABLE_A; |
1050 | ant[0] = ant[1] = AR5K_ANT_FIXED_A; | 1049 | else if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_B) |
1051 | else /* 2 - Aux */ | 1050 | ant[0] = ant[1] = AR5K_ANT_SWTABLE_B; |
1052 | ant[0] = ant[1] = AR5K_ANT_FIXED_B; | 1051 | else { |
1053 | } else { | 1052 | ant[0] = AR5K_ANT_SWTABLE_A; |
1054 | ant[0] = AR5K_ANT_FIXED_A; | 1053 | ant[1] = AR5K_ANT_SWTABLE_B; |
1055 | ant[1] = AR5K_ANT_FIXED_B; | ||
1056 | } | 1054 | } |
1057 | 1055 | ||
1058 | /* Commit values from EEPROM */ | 1056 | /* Commit values from EEPROM */ |
@@ -1260,6 +1258,8 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1260 | */ | 1258 | */ |
1261 | ath5k_hw_noise_floor_calibration(ah, channel->center_freq); | 1259 | ath5k_hw_noise_floor_calibration(ah, channel->center_freq); |
1262 | 1260 | ||
1261 | /* Restore antenna mode */ | ||
1262 | ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); | ||
1263 | 1263 | ||
1264 | /* | 1264 | /* |
1265 | * Configure QCUs/DCUs | 1265 | * Configure QCUs/DCUs |