diff options
author | Felix Fietkau <nbd@openwrt.org> | 2014-10-18 17:38:59 +0000 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2014-10-18 17:38:59 +0000 |
commit | f0d9e712e459332ec527802f7eaca104c47b14c2 (patch) | |
tree | b03de3247dbdd3f785bda5318729be5ab75f5f95 /package/kernel/mac80211/patches/317-ath9k-Check-for-active-GO-in-mgd_prepare_tx.patch | |
parent | 6d3fd947e4aa0430f592e9e3b0eb6b78cbe21f7b (diff) | |
download | mtk-20170518-f0d9e712e459332ec527802f7eaca104c47b14c2.zip mtk-20170518-f0d9e712e459332ec527802f7eaca104c47b14c2.tar.gz mtk-20170518-f0d9e712e459332ec527802f7eaca104c47b14c2.tar.bz2 |
mac80211: update to 2014-10-08
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
SVN-Revision: 42952
Diffstat (limited to 'package/kernel/mac80211/patches/317-ath9k-Check-for-active-GO-in-mgd_prepare_tx.patch')
-rw-r--r-- | package/kernel/mac80211/patches/317-ath9k-Check-for-active-GO-in-mgd_prepare_tx.patch | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/317-ath9k-Check-for-active-GO-in-mgd_prepare_tx.patch b/package/kernel/mac80211/patches/317-ath9k-Check-for-active-GO-in-mgd_prepare_tx.patch new file mode 100644 index 0000000..6e9aa1f --- /dev/null +++ b/package/kernel/mac80211/patches/317-ath9k-Check-for-active-GO-in-mgd_prepare_tx.patch @@ -0,0 +1,134 @@ +From: Sujith Manoharan <c_manoha@qca.qualcomm.com> +Date: Fri, 17 Oct 2014 07:40:22 +0530 +Subject: [PATCH] ath9k: Check for active GO in mgd_prepare_tx() + +If a GO interface is active when we receive a +mgd_prepare_tx() call, then we need to send +out a new NoA before switching to a new context. + +Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com> +--- + +--- a/drivers/net/wireless/ath/ath9k/ath9k.h ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h +@@ -385,6 +385,7 @@ struct ath_chanctx_sched { + bool wait_switch; + bool force_noa_update; + bool extend_absence; ++ bool mgd_prepare_tx; + enum ath_chanctx_state state; + u8 beacon_miss; + +@@ -977,6 +978,7 @@ struct ath_softc { + struct ath_chanctx_sched sched; + struct ath_offchannel offchannel; + struct ath_chanctx *next_chan; ++ struct completion go_beacon; + #endif + + unsigned long driver_data; +--- a/drivers/net/wireless/ath/ath9k/channel.c ++++ b/drivers/net/wireless/ath/ath9k/channel.c +@@ -421,6 +421,9 @@ void ath_chanctx_event(struct ath_softc + "Move chanctx state from WAIT_FOR_TIMER to WAIT_FOR_BEACON\n"); + } + ++ if (sc->sched.mgd_prepare_tx) ++ sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON; ++ + /* + * When a context becomes inactive, for example, + * disassociation of a station context, the NoA +@@ -547,6 +550,15 @@ void ath_chanctx_event(struct ath_softc + } + + sc->sched.beacon_pending = false; ++ ++ if (sc->sched.mgd_prepare_tx) { ++ sc->sched.mgd_prepare_tx = false; ++ complete(&sc->go_beacon); ++ ath_dbg(common, CHAN_CTX, ++ "Beacon sent, complete go_beacon\n"); ++ break; ++ } ++ + if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON) + break; + +@@ -1263,6 +1275,8 @@ void ath9k_init_channel_context(struct a + (unsigned long)sc); + setup_timer(&sc->sched.timer, ath_chanctx_timer, + (unsigned long)sc); ++ ++ init_completion(&sc->go_beacon); + } + + void ath9k_deinit_channel_context(struct ath_softc *sc) +--- a/drivers/net/wireless/ath/ath9k/main.c ++++ b/drivers/net/wireless/ath/ath9k/main.c +@@ -2474,7 +2474,11 @@ static void ath9k_mgd_prepare_tx(struct + struct ath_softc *sc = hw->priv; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_vif *avp = (struct ath_vif *) vif->drv_priv; ++ struct ath_beacon_config *cur_conf; ++ struct ath_chanctx *go_ctx; ++ unsigned long timeout; + bool changed = false; ++ u32 beacon_int; + + if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags)) + return; +@@ -2485,19 +2489,46 @@ static void ath9k_mgd_prepare_tx(struct + mutex_lock(&sc->mutex); + + spin_lock_bh(&sc->chan_lock); +- if (sc->next_chan || (sc->cur_chan != avp->chanctx)) { +- sc->next_chan = avp->chanctx; ++ if (sc->next_chan || (sc->cur_chan != avp->chanctx)) + changed = true; ++ spin_unlock_bh(&sc->chan_lock); ++ ++ if (!changed) ++ goto out; ++ ++ go_ctx = ath_is_go_chanctx_present(sc); ++ ++ if (go_ctx) { ++ /* ++ * Wait till the GO interface gets a chance ++ * to send out an NoA. ++ */ ++ spin_lock_bh(&sc->chan_lock); ++ sc->sched.mgd_prepare_tx = true; ++ cur_conf = &go_ctx->beacon; ++ beacon_int = TU_TO_USEC(cur_conf->beacon_interval); ++ spin_unlock_bh(&sc->chan_lock); ++ ++ timeout = usecs_to_jiffies(beacon_int); ++ init_completion(&sc->go_beacon); ++ ++ if (wait_for_completion_timeout(&sc->go_beacon, ++ timeout) == 0) ++ ath_dbg(common, CHAN_CTX, ++ "Failed to send new NoA\n"); + } ++ + ath_dbg(common, CHAN_CTX, +- "%s: Set chanctx state to FORCE_ACTIVE, changed: %d\n", +- __func__, changed); ++ "%s: Set chanctx state to FORCE_ACTIVE for vif: %pM\n", ++ __func__, vif->addr); ++ ++ spin_lock_bh(&sc->chan_lock); ++ sc->next_chan = avp->chanctx; + sc->sched.state = ATH_CHANCTX_STATE_FORCE_ACTIVE; + spin_unlock_bh(&sc->chan_lock); + +- if (changed) +- ath_chanctx_set_next(sc, true); +- ++ ath_chanctx_set_next(sc, true); ++out: + mutex_unlock(&sc->mutex); + } + |