Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

authored by

Sujith Manoharan and committed by
John W. Linville
367b341e da0162f3

+4 -1
+1
drivers/net/wireless/ath/ath9k/ath9k.h
··· 378 378 struct ath_chanctx_sched { 379 379 bool beacon_pending; 380 380 bool offchannel_pending; 381 + bool wait_switch; 381 382 enum ath_chanctx_state state; 382 383 u8 beacon_miss; 383 384
+3 -1
drivers/net/wireless/ath/ath9k/channel.c
··· 333 333 break; 334 334 } 335 335 336 - if (sc->sched.offchannel_pending) { 336 + if (sc->sched.offchannel_pending && !sc->sched.wait_switch) { 337 337 sc->sched.offchannel_pending = false; 338 338 sc->next_chan = &sc->offchannel.chan; 339 339 sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON; ··· 490 490 "Move chanctx state to WAIT_FOR_TIMER (event SWITCH)\n"); 491 491 492 492 sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_TIMER; 493 + sc->sched.wait_switch = false; 493 494 494 495 tsf_time = TU_TO_USEC(cur_conf->beacon_interval) / 2; 495 496 if (sc->sched.beacon_miss >= 2) { ··· 589 588 if (test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags) && 590 589 (sc->cur_chan != ctx) && (ctx == &sc->offchannel.chan)) { 591 590 sc->sched.offchannel_pending = true; 591 + sc->sched.wait_switch = true; 592 592 if (chandef) 593 593 ctx->chandef = *chandef; 594 594 spin_unlock_bh(&sc->chan_lock);