Commit 367b341e authored by Sujith Manoharan's avatar Sujith Manoharan Committed by John W. Linville

ath9k: Fix MCC scanning

Scanning is curently broken when two channel contexts
are active. For example in a P2P-GO/STA setup, the
offchannel timer allows HZ / 10 to elapse before initiating
a switch to the next scan channel from the current operating
channel, which in this case would be the P2P-GO context.

But, the channel context timer might decide to switch
to the STA context when an SWBA comes early and a beacon
is sent out. Since pending offchannel requests are processed
in EVENT_BEACON_PREPARE, this causes inconsistent scanning.

Fix this by making sure that a context switch happens
before processing the pending offchannel request. This
also makes sure that active channel contexts will always
have higher priority than offchannel operations and the
scan sequence looks like this:

p2p-go, sta, p2p-go, offchannel, p2p-go, sta, p2p-go, offchannel,.....

The oper-channel is p2p-go, so the STA context has to
switch to p2p-go again before switching offchannel.
Signed-off-by: default avatarSujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent da0162f3
...@@ -378,6 +378,7 @@ enum ath_chanctx_state { ...@@ -378,6 +378,7 @@ enum ath_chanctx_state {
struct ath_chanctx_sched { struct ath_chanctx_sched {
bool beacon_pending; bool beacon_pending;
bool offchannel_pending; bool offchannel_pending;
bool wait_switch;
enum ath_chanctx_state state; enum ath_chanctx_state state;
u8 beacon_miss; u8 beacon_miss;
......
...@@ -333,7 +333,7 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, ...@@ -333,7 +333,7 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
break; break;
} }
if (sc->sched.offchannel_pending) { if (sc->sched.offchannel_pending && !sc->sched.wait_switch) {
sc->sched.offchannel_pending = false; sc->sched.offchannel_pending = false;
sc->next_chan = &sc->offchannel.chan; sc->next_chan = &sc->offchannel.chan;
sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON; sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON;
...@@ -490,6 +490,7 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, ...@@ -490,6 +490,7 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
"Move chanctx state to WAIT_FOR_TIMER (event SWITCH)\n"); "Move chanctx state to WAIT_FOR_TIMER (event SWITCH)\n");
sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_TIMER; sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_TIMER;
sc->sched.wait_switch = false;
tsf_time = TU_TO_USEC(cur_conf->beacon_interval) / 2; tsf_time = TU_TO_USEC(cur_conf->beacon_interval) / 2;
if (sc->sched.beacon_miss >= 2) { if (sc->sched.beacon_miss >= 2) {
...@@ -588,6 +589,7 @@ static void ath_chanctx_switch(struct ath_softc *sc, struct ath_chanctx *ctx, ...@@ -588,6 +589,7 @@ static void ath_chanctx_switch(struct ath_softc *sc, struct ath_chanctx *ctx,
if (test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags) && if (test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags) &&
(sc->cur_chan != ctx) && (ctx == &sc->offchannel.chan)) { (sc->cur_chan != ctx) && (ctx == &sc->offchannel.chan)) {
sc->sched.offchannel_pending = true; sc->sched.offchannel_pending = true;
sc->sched.wait_switch = true;
if (chandef) if (chandef)
ctx->chandef = *chandef; ctx->chandef = *chandef;
spin_unlock_bh(&sc->chan_lock); spin_unlock_bh(&sc->chan_lock);
......
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