ath9k: Move roc completion to the offchannel timer
authorSujith Manoharan <c_manoha@qca.qualcomm.com>
Sun, 16 Nov 2014 00:41:10 +0000 (06:11 +0530)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 17 Nov 2014 20:32:17 +0000 (15:32 -0500)
Currently, when a roc period expires, the offchannel
timer calls ieee80211_remain_on_channel_expired(), but
the roc state is cleared only when the queued work
to switch to the operating channel gets a chance to run.

This race is a problem because mac80211 can issue a
new roc request in this window. To avoid this, handle
roc completion in the offchannel timer itself.

Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/ath9k/channel.c

index 99425fe130555df4f3351cf58381252077ba4436..794d52016437143558891f55b8ce928d6d9b77e7 100644 (file)
@@ -926,8 +926,7 @@ void ath_roc_complete(struct ath_softc *sc, bool abort)
 
        sc->offchannel.roc_vif = NULL;
        sc->offchannel.roc_chan = NULL;
-       if (abort)
-               ieee80211_remain_on_channel_expired(sc->hw);
+       ieee80211_remain_on_channel_expired(sc->hw);
        ath_offchannel_next(sc);
        ath9k_ps_restore(sc);
 }
@@ -1058,10 +1057,8 @@ static void ath_offchannel_timer(unsigned long data)
                break;
        case ATH_OFFCHANNEL_ROC_START:
        case ATH_OFFCHANNEL_ROC_WAIT:
-               ctx = ath_chanctx_get_oper_chan(sc, false);
                sc->offchannel.state = ATH_OFFCHANNEL_ROC_DONE;
-               ieee80211_remain_on_channel_expired(sc->hw);
-               ath_chanctx_switch(sc, ctx, NULL);
+               ath_roc_complete(sc, false);
                break;
        default:
                break;
@@ -1191,7 +1188,6 @@ static void ath_offchannel_channel_change(struct ath_softc *sc)
                ieee80211_ready_on_channel(sc->hw);
                break;
        case ATH_OFFCHANNEL_ROC_DONE:
-               ath_roc_complete(sc, false);
                break;
        default:
                break;