Commit 0005baf4 authored by Felix Fietkau's avatar Felix Fietkau Committed by John W. Linville

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: default avatarFelix Fietkau <nbd@openwrt.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 145b6d1a
...@@ -480,7 +480,8 @@ void ath_beacon_tasklet(unsigned long data) ...@@ -480,7 +480,8 @@ void ath_beacon_tasklet(unsigned long data)
sc->beacon.updateslot = COMMIT; /* commit next beacon */ sc->beacon.updateslot = COMMIT; /* commit next beacon */
sc->beacon.slotupdate = slot; sc->beacon.slotupdate = slot;
} else if (sc->beacon.updateslot == COMMIT && sc->beacon.slotupdate == slot) { } else if (sc->beacon.updateslot == COMMIT && sc->beacon.slotupdate == slot) {
ath9k_hw_setslottime(sc->sc_ah, sc->beacon.slottime); ah->slottime = sc->beacon.slottime;
ath9k_hw_init_global_settings(ah);
sc->beacon.updateslot = OK; sc->beacon.updateslot = OK;
} }
if (bfaddr != 0) { if (bfaddr != 0) {
......
...@@ -52,28 +52,6 @@ module_exit(ath9k_exit); ...@@ -52,28 +52,6 @@ module_exit(ath9k_exit);
/* Helper Functions */ /* Helper Functions */
/********************/ /********************/
static u32 ath9k_hw_mac_usec(struct ath_hw *ah, u32 clks)
{
struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
if (!ah->curchan) /* should really check for CCK instead */
return clks / ATH9K_CLOCK_RATE_CCK;
if (conf->channel->band == IEEE80211_BAND_2GHZ)
return clks / ATH9K_CLOCK_RATE_2GHZ_OFDM;
return clks / ATH9K_CLOCK_RATE_5GHZ_OFDM;
}
static u32 ath9k_hw_mac_to_usec(struct ath_hw *ah, u32 clks)
{
struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
if (conf_is_ht40(conf))
return ath9k_hw_mac_usec(ah, clks) / 2;
else
return ath9k_hw_mac_usec(ah, clks);
}
static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs) static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs)
{ {
struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; 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,8 +391,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
ah->beacon_interval = 100; ah->beacon_interval = 100;
ah->enable_32kHz_clock = DONT_USE_32KHZ; ah->enable_32kHz_clock = DONT_USE_32KHZ;
ah->slottime = (u32) -1; ah->slottime = (u32) -1;
ah->acktimeout = (u32) -1;
ah->ctstimeout = (u32) -1;
ah->globaltxtimeout = (u32) -1; ah->globaltxtimeout = (u32) -1;
ah->power_mode = ATH9K_PM_UNDEFINED; ah->power_mode = ATH9K_PM_UNDEFINED;
} }
...@@ -1180,34 +1156,25 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, ...@@ -1180,34 +1156,25 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
} }
} }
static bool ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us) static void ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
{ {
if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { u32 val = ath9k_hw_mac_to_clks(ah, us);
ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, val = min(val, (u32) 0xFFFF);
"bad ack timeout %u\n", us); REG_WRITE(ah, AR_D_GBL_IFS_SLOT, val);
ah->acktimeout = (u32) -1;
return false;
} else {
REG_RMW_FIELD(ah, AR_TIME_OUT,
AR_TIME_OUT_ACK, ath9k_hw_mac_to_clks(ah, us));
ah->acktimeout = us;
return true;
}
} }
static bool ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us) static void ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us)
{ {
if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { u32 val = ath9k_hw_mac_to_clks(ah, us);
ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_ACK));
"bad cts timeout %u\n", us); REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_ACK, val);
ah->ctstimeout = (u32) -1; }
return false;
} else { static void ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us)
REG_RMW_FIELD(ah, AR_TIME_OUT, {
AR_TIME_OUT_CTS, ath9k_hw_mac_to_clks(ah, us)); u32 val = ath9k_hw_mac_to_clks(ah, us);
ah->ctstimeout = us; val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_CTS));
return true; REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_CTS, val);
}
} }
static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu) static 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,23 +1191,32 @@ static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu)
} }
} }
static void ath9k_hw_init_user_settings(struct ath_hw *ah) void ath9k_hw_init_global_settings(struct ath_hw *ah)
{ {
struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
int acktimeout;
int sifstime;
ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n", ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n",
ah->misc_mode); ah->misc_mode);
if (ah->misc_mode != 0) if (ah->misc_mode != 0)
REG_WRITE(ah, AR_PCU_MISC, REG_WRITE(ah, AR_PCU_MISC,
REG_READ(ah, AR_PCU_MISC) | ah->misc_mode); REG_READ(ah, AR_PCU_MISC) | ah->misc_mode);
if (ah->slottime != (u32) -1)
if (conf->channel && conf->channel->band == IEEE80211_BAND_5GHZ)
sifstime = 16;
else
sifstime = 10;
acktimeout = ah->slottime + sifstime;
ath9k_hw_setslottime(ah, ah->slottime); ath9k_hw_setslottime(ah, ah->slottime);
if (ah->acktimeout != (u32) -1) ath9k_hw_set_ack_timeout(ah, acktimeout);
ath9k_hw_set_ack_timeout(ah, ah->acktimeout); ath9k_hw_set_cts_timeout(ah, acktimeout);
if (ah->ctstimeout != (u32) -1)
ath9k_hw_set_cts_timeout(ah, ah->ctstimeout);
if (ah->globaltxtimeout != (u32) -1) if (ah->globaltxtimeout != (u32) -1)
ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout); ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout);
} }
EXPORT_SYMBOL(ath9k_hw_init_global_settings);
void ath9k_hw_deinit(struct ath_hw *ah) void ath9k_hw_deinit(struct ath_hw *ah)
{ {
...@@ -2061,7 +2037,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ...@@ -2061,7 +2037,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
ath9k_enable_rfkill(ah); ath9k_enable_rfkill(ah);
ath9k_hw_init_user_settings(ah); ath9k_hw_init_global_settings(ah);
if (AR_SREV_9287_12_OR_LATER(ah)) { if (AR_SREV_9287_12_OR_LATER(ah)) {
REG_WRITE(ah, AR_D_GBL_IFS_SIFS, REG_WRITE(ah, AR_D_GBL_IFS_SIFS,
...@@ -3658,21 +3634,6 @@ u64 ath9k_hw_extend_tsf(struct ath_hw *ah, u32 rstamp) ...@@ -3658,21 +3634,6 @@ u64 ath9k_hw_extend_tsf(struct ath_hw *ah, u32 rstamp)
} }
EXPORT_SYMBOL(ath9k_hw_extend_tsf); EXPORT_SYMBOL(ath9k_hw_extend_tsf);
bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
{
if (us < ATH9K_SLOT_TIME_9 || us > ath9k_hw_mac_to_usec(ah, 0xffff)) {
ath_print(ath9k_hw_common(ah), ATH_DBG_RESET,
"bad slot time %u\n", us);
ah->slottime = (u32) -1;
return false;
} else {
REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath9k_hw_mac_to_clks(ah, us));
ah->slottime = us;
return true;
}
}
EXPORT_SYMBOL(ath9k_hw_setslottime);
void ath9k_hw_set11nmac2040(struct ath_hw *ah) void ath9k_hw_set11nmac2040(struct ath_hw *ah)
{ {
struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
......
...@@ -553,8 +553,6 @@ struct ath_hw { ...@@ -553,8 +553,6 @@ struct ath_hw {
int16_t txpower_indexoffset; int16_t txpower_indexoffset;
u32 beacon_interval; u32 beacon_interval;
u32 slottime; u32 slottime;
u32 acktimeout;
u32 ctstimeout;
u32 globaltxtimeout; u32 globaltxtimeout;
/* ANI */ /* ANI */
...@@ -668,7 +666,7 @@ void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); ...@@ -668,7 +666,7 @@ void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64);
void ath9k_hw_reset_tsf(struct ath_hw *ah); void ath9k_hw_reset_tsf(struct ath_hw *ah);
void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting); void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting);
u64 ath9k_hw_extend_tsf(struct ath_hw *ah, u32 rstamp); u64 ath9k_hw_extend_tsf(struct ath_hw *ah, u32 rstamp);
bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us); void ath9k_hw_init_global_settings(struct ath_hw *ah);
void ath9k_hw_set11nmac2040(struct ath_hw *ah); void ath9k_hw_set11nmac2040(struct ath_hw *ah);
void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period);
void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
......
...@@ -1789,6 +1789,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, ...@@ -1789,6 +1789,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
struct ath_vif *avp = (void *)vif->drv_priv; struct ath_vif *avp = (void *)vif->drv_priv;
int slottime;
int error; int error;
mutex_lock(&sc->mutex); mutex_lock(&sc->mutex);
...@@ -1824,6 +1825,25 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, ...@@ -1824,6 +1825,25 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
ath_beacon_config(sc, vif); ath_beacon_config(sc, vif);
} }
if (changed & BSS_CHANGED_ERP_SLOT) {
if (bss_conf->use_short_slot)
slottime = 9;
else
slottime = 20;
if (vif->type == NL80211_IFTYPE_AP) {
/*
* Defer update, so that connected stations can adjust
* their settings at the same time.
* See beacon.c for more details
*/
sc->beacon.slottime = slottime;
sc->beacon.updateslot = UPDATE;
} else {
ah->slottime = slottime;
ath9k_hw_init_global_settings(ah);
}
}
/* Disable transmission of beacons */ /* Disable transmission of beacons */
if ((changed & BSS_CHANGED_BEACON_ENABLED) && !bss_conf->enable_beacon) if ((changed & BSS_CHANGED_BEACON_ENABLED) && !bss_conf->enable_beacon)
ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment