mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-16 07:24:39 +08:00
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> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
26103b8d1d
commit
c6500ea29a
@ -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;
|
||||
|
@ -421,6 +421,9 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
|
||||
"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, struct ieee80211_vif *vif,
|
||||
}
|
||||
|
||||
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 ath_softc *sc)
|
||||
(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)
|
||||
|
@ -2474,7 +2474,11 @@ static void ath9k_mgd_prepare_tx(struct ieee80211_hw *hw,
|
||||
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 ieee80211_hw *hw,
|
||||
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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user