aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/hw.c
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2010-01-14 20:33:40 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-01-15 17:02:08 -0500
commit0005baf4a31efe6de6f922f73ccbd3762a110062 (patch)
treea5eb0a5e336c17be79c3a3ca1ac823064155ed84 /drivers/net/wireless/ath/ath9k/hw.c
parent145b6d1a56f224d15c61aa7ecfda9a1171b47b6a (diff)
ath9k: cleanup slot time and ack/cts timeout handling
Previously ath9k left the initialization of slot timing and ACK/CTS timeout to the mode specific initvals. This does not handle short vs long slot in 2.4 GHz and uses a rather strange value for the 2.4 GHz ACK timeout (64 usec). This patch uses the proper ath9k_hw functions for setting slot time and timeouts and also implements the switch between short and long slot time in 2.4 GHz Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/hw.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c103
1 files changed, 32 insertions, 71 deletions
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 2311fe7a0bf2..e1fd4cc9fae2 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -52,28 +52,6 @@ module_exit(ath9k_exit);
52/* Helper Functions */ 52/* Helper Functions */
53/********************/ 53/********************/
54 54
55static u32 ath9k_hw_mac_usec(struct ath_hw *ah, u32 clks)
56{
57 struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
58
59 if (!ah->curchan) /* should really check for CCK instead */
60 return clks / ATH9K_CLOCK_RATE_CCK;
61 if (conf->channel->band == IEEE80211_BAND_2GHZ)
62 return clks / ATH9K_CLOCK_RATE_2GHZ_OFDM;
63
64 return clks / ATH9K_CLOCK_RATE_5GHZ_OFDM;
65}
66
67static u32 ath9k_hw_mac_to_usec(struct ath_hw *ah, u32 clks)
68{
69 struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
70
71 if (conf_is_ht40(conf))
72 return ath9k_hw_mac_usec(ah, clks) / 2;
73 else
74 return ath9k_hw_mac_usec(ah, clks);
75}
76
77static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs) 55static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs)
78{ 56{
79 struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; 57 struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
@@ -413,8 +391,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
413 ah->beacon_interval = 100; 391 ah->beacon_interval = 100;
414 ah->enable_32kHz_clock = DONT_USE_32KHZ; 392 ah->enable_32kHz_clock = DONT_USE_32KHZ;
415 ah->slottime = (u32) -1; 393 ah->slottime = (u32) -1;
416 ah->acktimeout = (u32) -1;
417 ah->ctstimeout = (u32) -1;
418 ah->globaltxtimeout = (u32) -1; 394 ah->globaltxtimeout = (u32) -1;
419 ah->power_mode = ATH9K_PM_UNDEFINED; 395 ah->power_mode = ATH9K_PM_UNDEFINED;
420} 396}
@@ -1180,34 +1156,25 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
1180 } 1156 }
1181} 1157}
1182 1158
1183static bool ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us) 1159static void ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
1184{ 1160{
1185 if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { 1161 u32 val = ath9k_hw_mac_to_clks(ah, us);
1186 ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, 1162 val = min(val, (u32) 0xFFFF);
1187 "bad ack timeout %u\n", us); 1163 REG_WRITE(ah, AR_D_GBL_IFS_SLOT, val);
1188 ah->acktimeout = (u32) -1;
1189 return false;
1190 } else {
1191 REG_RMW_FIELD(ah, AR_TIME_OUT,
1192 AR_TIME_OUT_ACK, ath9k_hw_mac_to_clks(ah, us));
1193 ah->acktimeout = us;
1194 return true;
1195 }
1196} 1164}
1197 1165
1198static bool ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us) 1166static void ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us)
1199{ 1167{
1200 if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { 1168 u32 val = ath9k_hw_mac_to_clks(ah, us);
1201 ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, 1169 val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_ACK));
1202 "bad cts timeout %u\n", us); 1170 REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_ACK, val);
1203 ah->ctstimeout = (u32) -1; 1171}
1204 return false; 1172
1205 } else { 1173static void ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us)
1206 REG_RMW_FIELD(ah, AR_TIME_OUT, 1174{
1207 AR_TIME_OUT_CTS, ath9k_hw_mac_to_clks(ah, us)); 1175 u32 val = ath9k_hw_mac_to_clks(ah, us);
1208 ah->ctstimeout = us; 1176 val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_CTS));
1209 return true; 1177 REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_CTS, val);
1210 }
1211} 1178}
1212 1179
1213static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu) 1180static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu)
@@ -1224,23 +1191,32 @@ static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu)
1224 } 1191 }
1225} 1192}
1226 1193
1227static void ath9k_hw_init_user_settings(struct ath_hw *ah) 1194void ath9k_hw_init_global_settings(struct ath_hw *ah)
1228{ 1195{
1196 struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
1197 int acktimeout;
1198 int sifstime;
1199
1229 ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n", 1200 ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n",
1230 ah->misc_mode); 1201 ah->misc_mode);
1231 1202
1232 if (ah->misc_mode != 0) 1203 if (ah->misc_mode != 0)
1233 REG_WRITE(ah, AR_PCU_MISC, 1204 REG_WRITE(ah, AR_PCU_MISC,
1234 REG_READ(ah, AR_PCU_MISC) | ah->misc_mode); 1205 REG_READ(ah, AR_PCU_MISC) | ah->misc_mode);
1235 if (ah->slottime != (u32) -1) 1206
1236 ath9k_hw_setslottime(ah, ah->slottime); 1207 if (conf->channel && conf->channel->band == IEEE80211_BAND_5GHZ)
1237 if (ah->acktimeout != (u32) -1) 1208 sifstime = 16;
1238 ath9k_hw_set_ack_timeout(ah, ah->acktimeout); 1209 else
1239 if (ah->ctstimeout != (u32) -1) 1210 sifstime = 10;
1240 ath9k_hw_set_cts_timeout(ah, ah->ctstimeout); 1211
1212 acktimeout = ah->slottime + sifstime;
1213 ath9k_hw_setslottime(ah, ah->slottime);
1214 ath9k_hw_set_ack_timeout(ah, acktimeout);
1215 ath9k_hw_set_cts_timeout(ah, acktimeout);
1241 if (ah->globaltxtimeout != (u32) -1) 1216 if (ah->globaltxtimeout != (u32) -1)
1242 ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout); 1217 ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout);
1243} 1218}
1219EXPORT_SYMBOL(ath9k_hw_init_global_settings);
1244 1220
1245void ath9k_hw_deinit(struct ath_hw *ah) 1221void ath9k_hw_deinit(struct ath_hw *ah)
1246{ 1222{
@@ -2061,7 +2037,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
2061 if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) 2037 if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
2062 ath9k_enable_rfkill(ah); 2038 ath9k_enable_rfkill(ah);
2063 2039
2064 ath9k_hw_init_user_settings(ah); 2040 ath9k_hw_init_global_settings(ah);
2065 2041
2066 if (AR_SREV_9287_12_OR_LATER(ah)) { 2042 if (AR_SREV_9287_12_OR_LATER(ah)) {
2067 REG_WRITE(ah, AR_D_GBL_IFS_SIFS, 2043 REG_WRITE(ah, AR_D_GBL_IFS_SIFS,
@@ -3658,21 +3634,6 @@ u64 ath9k_hw_extend_tsf(struct ath_hw *ah, u32 rstamp)
3658} 3634}
3659EXPORT_SYMBOL(ath9k_hw_extend_tsf); 3635EXPORT_SYMBOL(ath9k_hw_extend_tsf);
3660 3636
3661bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
3662{
3663 if (us < ATH9K_SLOT_TIME_9 || us > ath9k_hw_mac_to_usec(ah, 0xffff)) {
3664 ath_print(ath9k_hw_common(ah), ATH_DBG_RESET,
3665 "bad slot time %u\n", us);
3666 ah->slottime = (u32) -1;
3667 return false;
3668 } else {
3669 REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath9k_hw_mac_to_clks(ah, us));
3670 ah->slottime = us;
3671 return true;
3672 }
3673}
3674EXPORT_SYMBOL(ath9k_hw_setslottime);
3675
3676void ath9k_hw_set11nmac2040(struct ath_hw *ah) 3637void ath9k_hw_set11nmac2040(struct ath_hw *ah)
3677{ 3638{
3678 struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; 3639 struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;