ath9k: handle RoC cancel correctly
authorJanusz.Dziedzic@tieto.com <Janusz.Dziedzic@tieto.com>
Tue, 21 Jul 2015 09:11:41 +0000 (11:11 +0200)
committerKalle Valo <kvalo@codeaurora.org>
Thu, 6 Aug 2015 07:11:06 +0000 (10:11 +0300)
In case we will get ROC cancel from mac80211 we
should not call ieee80211_remain_on_channel_expired().

In other case I hit such warning on MIPS and
p2p negotiation failed (tested with use_chanctx=1).

ath: phy0: Starting RoC period
ath: phy0: Channel definition created: 2412 MHz
ath: phy0: Assigned next_chan to 2412 MHz
ath: phy0: Offchannel duration for chan 2412 MHz : 506632
ath: phy0: ath_chanctx_set_next: current: 2412 MHz, next: 2412 MHz
ath: phy0: Stopping current chanctx: 2412
ath: phy0: Flush timeout: 200
ath: phy0: ath_chanctx_set_next: Set channel 2412 MHz
ath: phy0: Set channel: 2412 MHz width: 0
ath: phy0: Reset to 2412 MHz, HT40: 0 fastcc: 0
ath: phy0: cur_chan: 2412 MHz, event: ATH_CHANCTX_EVENT_TSF_TIMER, state: ATH_CHANCTX_STATE_IDLE
ath: phy0: ath_offchannel_channel_change: offchannel state: ATH_OFFCHANNEL_ROC_START
ath: phy0: cur_chan: 2412 MHz, event: ATH_CHANCTX_EVENT_SWITCH, state: ATH_CHANCTX_STATE_IDLE
ath: phy0: Cancel RoC
ath: phy0: RoC aborted
ath: phy0: RoC request on vif: 00:03:7f:4e:a0:cd, type: 1 duration: 500
ath: phy0: Starting RoC period
ath: phy0: Channel definition created: 2412 MHz
ath: phy0: Assigned next_chan to 2412 MHz
ath: phy0: Offchannel duration for chan 2412 MHz : 506705
ath: phy0: ath_chanctx_set_next: current: 2412 MHz, next: 2412 MHz
ath: phy0: ath_offchannel_channel_change: offchannel state: ATH_OFFCHANNEL_ROC_START
ath: phy0: cur_chan: 2412 MHz, event: ATH_CHANCTX_EVENT_SWITCH, state: ATH_CHANCTX_STATE_IDLE
------------[ cut here ]------------
WARNING: CPU: 0 PID: 3312 at drivers/net/wireless/ath/ath9k/main.c:2319
Modules linked in: ath9k ath9k_common ath9k_hw ath mac80211 cfg80211

Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/channel.c
drivers/net/wireless/ath/ath9k/main.c

index a7a81b3969cec7e79b2cb73959c4d8ff1fb7489e..db7a7b64bcdf48277de4008caaed1fea42a45def 100644 (file)
@@ -410,6 +410,12 @@ enum ath_offchannel_state {
        ATH_OFFCHANNEL_ROC_DONE,
 };
 
+enum ath_roc_complete_reason {
+       ATH_ROC_COMPLETE_EXPIRE,
+       ATH_ROC_COMPLETE_ABORT,
+       ATH_ROC_COMPLETE_CANCEL,
+};
+
 struct ath_offchannel {
        struct ath_chanctx chan;
        struct timer_list timer;
@@ -471,7 +477,8 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
 void ath_chanctx_set_next(struct ath_softc *sc, bool force);
 void ath_offchannel_next(struct ath_softc *sc);
 void ath_scan_complete(struct ath_softc *sc, bool abort);
-void ath_roc_complete(struct ath_softc *sc, bool abort);
+void ath_roc_complete(struct ath_softc *sc,
+                     enum ath_roc_complete_reason reason);
 struct ath_chanctx* ath_is_go_chanctx_present(struct ath_softc *sc);
 
 #else
index 206665059d66a67b0bbd2a816ba4c2c4d187ee48..90f5773a1a614e34bceac511ba5d415d8614596b 100644 (file)
@@ -915,18 +915,27 @@ void ath_offchannel_next(struct ath_softc *sc)
        }
 }
 
-void ath_roc_complete(struct ath_softc *sc, bool abort)
+void ath_roc_complete(struct ath_softc *sc, enum ath_roc_complete_reason reason)
 {
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 
-       if (abort)
+       sc->offchannel.roc_vif = NULL;
+       sc->offchannel.roc_chan = NULL;
+
+       switch (reason) {
+       case ATH_ROC_COMPLETE_ABORT:
                ath_dbg(common, CHAN_CTX, "RoC aborted\n");
-       else
+               ieee80211_remain_on_channel_expired(sc->hw);
+               break;
+       case ATH_ROC_COMPLETE_EXPIRE:
                ath_dbg(common, CHAN_CTX, "RoC expired\n");
+               ieee80211_remain_on_channel_expired(sc->hw);
+               break;
+       case ATH_ROC_COMPLETE_CANCEL:
+               ath_dbg(common, CHAN_CTX, "RoC canceled\n");
+               break;
+       }
 
-       sc->offchannel.roc_vif = NULL;
-       sc->offchannel.roc_chan = NULL;
-       ieee80211_remain_on_channel_expired(sc->hw);
        ath_offchannel_next(sc);
        ath9k_ps_restore(sc);
 }
@@ -1058,7 +1067,7 @@ static void ath_offchannel_timer(unsigned long data)
        case ATH_OFFCHANNEL_ROC_START:
        case ATH_OFFCHANNEL_ROC_WAIT:
                sc->offchannel.state = ATH_OFFCHANNEL_ROC_DONE;
-               ath_roc_complete(sc, false);
+               ath_roc_complete(sc, ATH_ROC_COMPLETE_EXPIRE);
                break;
        default:
                break;
index cfd45cb8ccfc13df856bb4bbe07d8e2bef21228f..b7b77e000507dc03b89b1560770d2c70c3993928 100644 (file)
@@ -2246,7 +2246,7 @@ static void ath9k_cancel_pending_offchannel(struct ath_softc *sc)
 
                del_timer_sync(&sc->offchannel.timer);
                if (sc->offchannel.state >= ATH_OFFCHANNEL_ROC_START)
-                       ath_roc_complete(sc, true);
+                       ath_roc_complete(sc, ATH_ROC_COMPLETE_ABORT);
        }
 
        if (test_bit(ATH_OP_SCANNING, &common->op_flags)) {
@@ -2355,7 +2355,7 @@ static int ath9k_cancel_remain_on_channel(struct ieee80211_hw *hw)
 
        if (sc->offchannel.roc_vif) {
                if (sc->offchannel.state >= ATH_OFFCHANNEL_ROC_START)
-                       ath_roc_complete(sc, true);
+                       ath_roc_complete(sc, ATH_ROC_COMPLETE_CANCEL);
        }
 
        mutex_unlock(&sc->mutex);