96 lines
3 KiB
Diff
96 lines
3 KiB
Diff
|
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||
|
Date: Fri, 17 Oct 2014 07:40:29 +0530
|
||
|
Subject: [PATCH] ath9k: Improve flush() in mcc mode
|
||
|
|
||
|
The flush timeout in MCC mode is very small, since
|
||
|
we are constrained by the time slice for each
|
||
|
channel context, but since only the HW queues are
|
||
|
flushed when switching contexts, it is acceptable.
|
||
|
|
||
|
Since the SW queues are also emptied in the mac80211 flush()
|
||
|
callback, a larger duration is needed. Add an override
|
||
|
argument to __ath9k_flush() and set it when flush()
|
||
|
is called in MCC mode. This allows the driver to
|
||
|
drain both the SW and HW queues.
|
||
|
|
||
|
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||
|
---
|
||
|
|
||
|
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||
|
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||
|
@@ -719,7 +719,7 @@ void ath_update_survey_nf(struct ath_sof
|
||
|
void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type);
|
||
|
void ath_ps_full_sleep(unsigned long data);
|
||
|
void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop,
|
||
|
- bool sw_pending);
|
||
|
+ bool sw_pending, bool timeout_override);
|
||
|
|
||
|
/**********/
|
||
|
/* BTCOEX */
|
||
|
--- a/drivers/net/wireless/ath/ath9k/channel.c
|
||
|
+++ b/drivers/net/wireless/ath/ath9k/channel.c
|
||
|
@@ -1232,11 +1232,11 @@ void ath_chanctx_set_next(struct ath_sof
|
||
|
ath9k_chanctx_stop_queues(sc, sc->cur_chan);
|
||
|
queues_stopped = true;
|
||
|
|
||
|
- __ath9k_flush(sc->hw, ~0, true, false);
|
||
|
+ __ath9k_flush(sc->hw, ~0, true, false, false);
|
||
|
|
||
|
if (ath_chanctx_send_ps_frame(sc, true))
|
||
|
__ath9k_flush(sc->hw, BIT(IEEE80211_AC_VO),
|
||
|
- false, false);
|
||
|
+ false, false, false);
|
||
|
|
||
|
send_ps = true;
|
||
|
spin_lock_bh(&sc->chan_lock);
|
||
|
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||
|
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||
|
@@ -2031,14 +2031,33 @@ static void ath9k_flush(struct ieee80211
|
||
|
u32 queues, bool drop)
|
||
|
{
|
||
|
struct ath_softc *sc = hw->priv;
|
||
|
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||
|
+
|
||
|
+ if (ath9k_is_chanctx_enabled()) {
|
||
|
+ if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags))
|
||
|
+ goto flush;
|
||
|
|
||
|
+ /*
|
||
|
+ * If MCC is active, extend the flush timeout
|
||
|
+ * and wait for the HW/SW queues to become
|
||
|
+ * empty. This needs to be done outside the
|
||
|
+ * sc->mutex lock to allow the channel scheduler
|
||
|
+ * to switch channel contexts.
|
||
|
+ *
|
||
|
+ * The vif queues have been stopped in mac80211,
|
||
|
+ * so there won't be any incoming frames.
|
||
|
+ */
|
||
|
+ __ath9k_flush(hw, queues, drop, true, true);
|
||
|
+ return;
|
||
|
+ }
|
||
|
+flush:
|
||
|
mutex_lock(&sc->mutex);
|
||
|
- __ath9k_flush(hw, queues, drop, true);
|
||
|
+ __ath9k_flush(hw, queues, drop, true, false);
|
||
|
mutex_unlock(&sc->mutex);
|
||
|
}
|
||
|
|
||
|
void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop,
|
||
|
- bool sw_pending)
|
||
|
+ bool sw_pending, bool timeout_override)
|
||
|
{
|
||
|
struct ath_softc *sc = hw->priv;
|
||
|
struct ath_hw *ah = sc->sc_ah;
|
||
|
@@ -2059,7 +2078,10 @@ void __ath9k_flush(struct ieee80211_hw *
|
||
|
}
|
||
|
|
||
|
spin_lock_bh(&sc->chan_lock);
|
||
|
- timeout = sc->cur_chan->flush_timeout;
|
||
|
+ if (timeout_override)
|
||
|
+ timeout = HZ / 5;
|
||
|
+ else
|
||
|
+ timeout = sc->cur_chan->flush_timeout;
|
||
|
spin_unlock_bh(&sc->chan_lock);
|
||
|
|
||
|
ath_dbg(common, CHAN_CTX,
|