summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSujith Manoharan <c_manoha@qca.qualcomm.com>2014-10-02 06:33:20 +0530
committerJohn W. Linville <linville@tuxdriver.com>2014-10-02 14:26:32 -0400
commite2cba8d7590e76661e86f1f0987ef9f8c13c9a6d (patch)
treeedc1651fe9e9ea589399ad6bddda48cfabce1c0f
parent5ba8d9d2f018f2c4e23f9e68b90ca5b9d5470457 (diff)
ath9k: Fix flushing in MCC mode
When we are attempting to switch to a new channel context, the TX queues are flushed, but the mac80211 queues are not stopped and traffic can still come down to the driver. This patch fixes it by stopping the queues assigned to the current context/vif before trying to flush. Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/ath9k/channel.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c
index bf5ecd8da2f1..945c89826b14 100644
--- a/drivers/net/wireless/ath/ath9k/channel.c
+++ b/drivers/net/wireless/ath/ath9k/channel.c
@@ -1044,9 +1044,11 @@ static void ath_offchannel_channel_change(struct ath_softc *sc)
void ath_chanctx_set_next(struct ath_softc *sc, bool force)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_chanctx *old_ctx;
struct timespec ts;
bool measure_time = false;
bool send_ps = false;
+ bool queues_stopped = false;
spin_lock_bh(&sc->chan_lock);
if (!sc->next_chan) {
@@ -1076,6 +1078,10 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force)
getrawmonotonic(&ts);
measure_time = true;
}
+
+ ath9k_chanctx_stop_queues(sc, sc->cur_chan);
+ queues_stopped = true;
+
__ath9k_flush(sc->hw, ~0, true);
if (ath_chanctx_send_ps_frame(sc, true))
@@ -1089,6 +1095,7 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force)
sc->cur_chan->tsf_val = ath9k_hw_gettsf64(sc->sc_ah);
}
}
+ old_ctx = sc->cur_chan;
sc->cur_chan = sc->next_chan;
sc->cur_chan->stopped = false;
sc->next_chan = NULL;
@@ -1111,7 +1118,16 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force)
if (measure_time)
sc->sched.channel_switch_time =
ath9k_hw_get_tsf_offset(&ts, NULL);
+ /*
+ * A reset will ensure that all queues are woken up,
+ * so there is no need to awaken them again.
+ */
+ goto out;
}
+
+ if (queues_stopped)
+ ath9k_chanctx_wake_queues(sc, old_ctx);
+out:
if (send_ps)
ath_chanctx_send_ps_frame(sc, false);