ath9k: fix short slot vs long slot handling, implement support for setting the coverage class
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@19141 3c298f89-4303-0410-b956-a3cf2f4a3e73master
parent
e5dd7c7635
commit
042ce3d63c
|
@ -0,0 +1,11 @@
|
|||
--- a/net/mac80211/mlme.c
|
||||
+++ b/net/mac80211/mlme.c
|
||||
@@ -670,6 +670,8 @@ static u32 ieee80211_handle_bss_capabili
|
||||
}
|
||||
|
||||
use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME);
|
||||
+ if (sdata->local->hw.conf.channel->band == IEEE80211_BAND_5GHZ)
|
||||
+ use_short_slot = true;
|
||||
|
||||
if (use_protection != bss_conf->use_cts_prot) {
|
||||
bss_conf->use_cts_prot = use_protection;
|
|
@ -0,0 +1,229 @@
|
|||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -1790,6 +1790,7 @@ static void ath9k_bss_info_changed(struc
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath_vif *avp = (void *)vif->drv_priv;
|
||||
+ int slottime;
|
||||
int error;
|
||||
|
||||
mutex_lock(&sc->mutex);
|
||||
@@ -1825,6 +1826,25 @@ static void ath9k_bss_info_changed(struc
|
||||
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 */
|
||||
if ((changed & BSS_CHANGED_BEACON_ENABLED) && !bss_conf->enable_beacon)
|
||||
ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.c
|
||||
@@ -55,28 +55,6 @@ module_exit(ath9k_exit);
|
||||
/* 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)
|
||||
{
|
||||
struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
|
||||
@@ -413,8 +391,6 @@ static void ath9k_hw_init_defaults(struc
|
||||
ah->beacon_interval = 100;
|
||||
ah->enable_32kHz_clock = DONT_USE_32KHZ;
|
||||
ah->slottime = (u32) -1;
|
||||
- ah->acktimeout = (u32) -1;
|
||||
- ah->ctstimeout = (u32) -1;
|
||||
ah->globaltxtimeout = (u32) -1;
|
||||
ah->power_mode = ATH9K_PM_UNDEFINED;
|
||||
}
|
||||
@@ -1196,34 +1172,25 @@ static void ath9k_hw_init_interrupt_mask
|
||||
}
|
||||
}
|
||||
|
||||
-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))) {
|
||||
- ath_print(ath9k_hw_common(ah), ATH_DBG_RESET,
|
||||
- "bad ack timeout %u\n", us);
|
||||
- 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;
|
||||
- }
|
||||
+ u32 val = ath9k_hw_mac_to_clks(ah, us);
|
||||
+ val = min(val, (u32) 0xFFFF);
|
||||
+ REG_WRITE(ah, AR_D_GBL_IFS_SLOT, val);
|
||||
}
|
||||
|
||||
-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))) {
|
||||
- ath_print(ath9k_hw_common(ah), ATH_DBG_RESET,
|
||||
- "bad cts timeout %u\n", us);
|
||||
- ah->ctstimeout = (u32) -1;
|
||||
- return false;
|
||||
- } else {
|
||||
- REG_RMW_FIELD(ah, AR_TIME_OUT,
|
||||
- AR_TIME_OUT_CTS, ath9k_hw_mac_to_clks(ah, us));
|
||||
- ah->ctstimeout = us;
|
||||
- return true;
|
||||
- }
|
||||
+ u32 val = ath9k_hw_mac_to_clks(ah, us);
|
||||
+ val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_ACK));
|
||||
+ REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_ACK, val);
|
||||
+}
|
||||
+
|
||||
+static void ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us)
|
||||
+{
|
||||
+ u32 val = ath9k_hw_mac_to_clks(ah, us);
|
||||
+ val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_CTS));
|
||||
+ 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)
|
||||
@@ -1240,23 +1207,32 @@ static bool ath9k_hw_set_global_txtimeou
|
||||
}
|
||||
}
|
||||
|
||||
-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",
|
||||
ah->misc_mode);
|
||||
|
||||
if (ah->misc_mode != 0)
|
||||
REG_WRITE(ah, AR_PCU_MISC,
|
||||
REG_READ(ah, AR_PCU_MISC) | ah->misc_mode);
|
||||
- if (ah->slottime != (u32) -1)
|
||||
- ath9k_hw_setslottime(ah, ah->slottime);
|
||||
- if (ah->acktimeout != (u32) -1)
|
||||
- ath9k_hw_set_ack_timeout(ah, ah->acktimeout);
|
||||
- if (ah->ctstimeout != (u32) -1)
|
||||
- ath9k_hw_set_cts_timeout(ah, ah->ctstimeout);
|
||||
+
|
||||
+ 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_set_ack_timeout(ah, acktimeout);
|
||||
+ ath9k_hw_set_cts_timeout(ah, acktimeout);
|
||||
if (ah->globaltxtimeout != (u32) -1)
|
||||
ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout);
|
||||
}
|
||||
+EXPORT_SYMBOL(ath9k_hw_init_global_settings);
|
||||
|
||||
void ath9k_hw_deinit(struct ath_hw *ah)
|
||||
{
|
||||
@@ -2077,7 +2053,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
|
||||
if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
|
||||
ath9k_enable_rfkill(ah);
|
||||
|
||||
- ath9k_hw_init_user_settings(ah);
|
||||
+ ath9k_hw_init_global_settings(ah);
|
||||
|
||||
if (AR_SREV_9287_12_OR_LATER(ah)) {
|
||||
REG_WRITE(ah, AR_D_GBL_IFS_SIFS,
|
||||
@@ -3674,21 +3650,6 @@ u64 ath9k_hw_extend_tsf(struct ath_hw *a
|
||||
}
|
||||
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)
|
||||
{
|
||||
struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.h
|
||||
@@ -553,8 +553,6 @@ struct ath_hw {
|
||||
int16_t txpower_indexoffset;
|
||||
u32 beacon_interval;
|
||||
u32 slottime;
|
||||
- u32 acktimeout;
|
||||
- u32 ctstimeout;
|
||||
u32 globaltxtimeout;
|
||||
|
||||
/* ANI */
|
||||
@@ -668,7 +666,7 @@ void ath9k_hw_settsf64(struct ath_hw *ah
|
||||
void ath9k_hw_reset_tsf(struct ath_hw *ah);
|
||||
void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting);
|
||||
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_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period);
|
||||
void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
|
||||
--- 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 da
|
||||
sc->beacon.updateslot = COMMIT; /* commit next beacon */
|
||||
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;
|
||||
}
|
||||
if (bfaddr != 0) {
|
|
@ -0,0 +1,60 @@
|
|||
--- a/drivers/net/wireless/ath/ath9k/hw.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.c
|
||||
@@ -1211,6 +1211,7 @@ void ath9k_hw_init_global_settings(struc
|
||||
{
|
||||
struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
|
||||
int acktimeout;
|
||||
+ int slottime;
|
||||
int sifstime;
|
||||
|
||||
ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n",
|
||||
@@ -1225,8 +1226,10 @@ void ath9k_hw_init_global_settings(struc
|
||||
else
|
||||
sifstime = 10;
|
||||
|
||||
- acktimeout = ah->slottime + sifstime;
|
||||
- ath9k_hw_setslottime(ah, ah->slottime);
|
||||
+ /* As defined by IEEE 802.11-2007 17.3.8.6 */
|
||||
+ slottime = ah->slottime + 3 * ah->coverage_class;
|
||||
+ acktimeout = slottime + sifstime;
|
||||
+ ath9k_hw_setslottime(ah, slottime);
|
||||
ath9k_hw_set_ack_timeout(ah, acktimeout);
|
||||
ath9k_hw_set_cts_timeout(ah, acktimeout);
|
||||
if (ah->globaltxtimeout != (u32) -1)
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.h
|
||||
@@ -551,6 +551,7 @@ struct ath_hw {
|
||||
u32 *bank6Temp;
|
||||
|
||||
int16_t txpower_indexoffset;
|
||||
+ int coverage_class;
|
||||
u32 beacon_interval;
|
||||
u32 slottime;
|
||||
u32 globaltxtimeout;
|
||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -2015,6 +2015,18 @@ static void ath9k_sw_scan_complete(struc
|
||||
mutex_unlock(&sc->mutex);
|
||||
}
|
||||
|
||||
+static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
|
||||
+{
|
||||
+ struct ath_wiphy *aphy = hw->priv;
|
||||
+ struct ath_softc *sc = aphy->sc;
|
||||
+ struct ath_hw *ah = sc->sc_ah;
|
||||
+
|
||||
+ mutex_lock(&sc->mutex);
|
||||
+ ah->coverage_class = coverage_class;
|
||||
+ ath9k_hw_init_global_settings(ah);
|
||||
+ mutex_unlock(&sc->mutex);
|
||||
+}
|
||||
+
|
||||
struct ieee80211_ops ath9k_ops = {
|
||||
.tx = ath9k_tx,
|
||||
.start = ath9k_start,
|
||||
@@ -2034,4 +2046,5 @@ struct ieee80211_ops ath9k_ops = {
|
||||
.sw_scan_start = ath9k_sw_scan_start,
|
||||
.sw_scan_complete = ath9k_sw_scan_complete,
|
||||
.rfkill_poll = ath9k_rfkill_poll_state,
|
||||
+ .set_coverage_class = ath9k_set_coverage_class,
|
||||
};
|
Loading…
Reference in New Issue