aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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
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')
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c103
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c20
4 files changed, 55 insertions, 75 deletions
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index 1660ef17aaf5..422454fe4ff0 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -480,7 +480,8 @@ void ath_beacon_tasklet(unsigned long data)
480 sc->beacon.updateslot = COMMIT; /* commit next beacon */ 480 sc->beacon.updateslot = COMMIT; /* commit next beacon */
481 sc->beacon.slotupdate = slot; 481 sc->beacon.slotupdate = slot;
482 } else if (sc->beacon.updateslot == COMMIT && sc->beacon.slotupdate == slot) { 482 } else if (sc->beacon.updateslot == COMMIT && sc->beacon.slotupdate == slot) {
483 ath9k_hw_setslottime(sc->sc_ah, sc->beacon.slottime); 483 ah->slottime = sc->beacon.slottime;
484 ath9k_hw_init_global_settings(ah);
484 sc->beacon.updateslot = OK; 485 sc->beacon.updateslot = OK;
485 } 486 }
486 if (bfaddr != 0) { 487 if (bfaddr != 0) {
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;
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 3f0f055ea39b..a7ff07537bc4 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -553,8 +553,6 @@ struct ath_hw {
553 int16_t txpower_indexoffset; 553 int16_t txpower_indexoffset;
554 u32 beacon_interval; 554 u32 beacon_interval;
555 u32 slottime; 555 u32 slottime;
556 u32 acktimeout;
557 u32 ctstimeout;
558 u32 globaltxtimeout; 556 u32 globaltxtimeout;
559 557
560 /* ANI */ 558 /* ANI */
@@ -668,7 +666,7 @@ void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64);
668void ath9k_hw_reset_tsf(struct ath_hw *ah); 666void ath9k_hw_reset_tsf(struct ath_hw *ah);
669void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting); 667void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting);
670u64 ath9k_hw_extend_tsf(struct ath_hw *ah, u32 rstamp); 668u64 ath9k_hw_extend_tsf(struct ath_hw *ah, u32 rstamp);
671bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us); 669void ath9k_hw_init_global_settings(struct ath_hw *ah);
672void ath9k_hw_set11nmac2040(struct ath_hw *ah); 670void ath9k_hw_set11nmac2040(struct ath_hw *ah);
673void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); 671void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period);
674void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, 672void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index b39c7bc41143..580ecca0182c 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1789,6 +1789,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
1789 struct ath_hw *ah = sc->sc_ah; 1789 struct ath_hw *ah = sc->sc_ah;
1790 struct ath_common *common = ath9k_hw_common(ah); 1790 struct ath_common *common = ath9k_hw_common(ah);
1791 struct ath_vif *avp = (void *)vif->drv_priv; 1791 struct ath_vif *avp = (void *)vif->drv_priv;
1792 int slottime;
1792 int error; 1793 int error;
1793 1794
1794 mutex_lock(&sc->mutex); 1795 mutex_lock(&sc->mutex);
@@ -1824,6 +1825,25 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
1824 ath_beacon_config(sc, vif); 1825 ath_beacon_config(sc, vif);
1825 } 1826 }
1826 1827
1828 if (changed & BSS_CHANGED_ERP_SLOT) {
1829 if (bss_conf->use_short_slot)
1830 slottime = 9;
1831 else
1832 slottime = 20;
1833 if (vif->type == NL80211_IFTYPE_AP) {
1834 /*
1835 * Defer update, so that connected stations can adjust
1836 * their settings at the same time.
1837 * See beacon.c for more details
1838 */
1839 sc->beacon.slottime = slottime;
1840 sc->beacon.updateslot = UPDATE;
1841 } else {
1842 ah->slottime = slottime;
1843 ath9k_hw_init_global_settings(ah);
1844 }
1845 }
1846
1827 /* Disable transmission of beacons */ 1847 /* Disable transmission of beacons */
1828 if ((changed & BSS_CHANGED_BEACON_ENABLED) && !bss_conf->enable_beacon) 1848 if ((changed & BSS_CHANGED_BEACON_ENABLED) && !bss_conf->enable_beacon)
1829 ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); 1849 ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);