diff options
Diffstat (limited to 'package/kernel/mac80211/patches/313-ath9k-Check-for-pending-frames-properly.patch')
-rw-r--r-- | package/kernel/mac80211/patches/313-ath9k-Check-for-pending-frames-properly.patch | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/313-ath9k-Check-for-pending-frames-properly.patch b/package/kernel/mac80211/patches/313-ath9k-Check-for-pending-frames-properly.patch new file mode 100644 index 0000000000..c1d8791b9d --- /dev/null +++ b/package/kernel/mac80211/patches/313-ath9k-Check-for-pending-frames-properly.patch @@ -0,0 +1,125 @@ +From: Sujith Manoharan <c_manoha@qca.qualcomm.com> +Date: Fri, 17 Oct 2014 07:40:18 +0530 +Subject: [PATCH] ath9k: Check for pending frames properly + +Pending frames in the driver can be present +either in the HW queues or SW. ath9k_has_pending_frames() +currently checks for the HW queues first and then +checks if any ACs are queued in the driver. + +In MCC mode, we need to check the HW queues alone, since +the SW queues are just marked as 'stopped' - they will +be processed in the next context switch. But since we +don't differentiate this now, mention whether we want +to check if there are frames in the SW queues. + +* The flush() callback checks both HW and SW queues. +* The tx_frames_pending() callback does the same. +* The call to __ath9k_flush() in MCC mode checks HW queues alone. + +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 +@@ -715,7 +715,8 @@ int ath_update_survey_stats(struct ath_s + void ath_update_survey_nf(struct ath_softc *sc, int channel); + 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); ++void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop, ++ bool sw_pending); + + /**********/ + /* BTCOEX */ +--- a/drivers/net/wireless/ath/ath9k/channel.c ++++ b/drivers/net/wireless/ath/ath9k/channel.c +@@ -1137,10 +1137,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); ++ __ath9k_flush(sc->hw, ~0, true, false); + + if (ath_chanctx_send_ps_frame(sc, true)) +- __ath9k_flush(sc->hw, BIT(IEEE80211_AC_VO), false); ++ __ath9k_flush(sc->hw, BIT(IEEE80211_AC_VO), ++ 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 +@@ -54,7 +54,8 @@ u8 ath9k_parse_mpdudensity(u8 mpdudensit + } + } + +-static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq) ++static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq, ++ bool sw_pending) + { + bool pending = false; + +@@ -65,6 +66,9 @@ static bool ath9k_has_pending_frames(str + goto out; + } + ++ if (!sw_pending) ++ goto out; ++ + if (txq->mac80211_qnum >= 0) { + struct list_head *list; + +@@ -2003,7 +2007,8 @@ static void ath9k_set_coverage_class(str + mutex_unlock(&sc->mutex); + } + +-static bool ath9k_has_tx_pending(struct ath_softc *sc) ++static bool ath9k_has_tx_pending(struct ath_softc *sc, ++ bool sw_pending) + { + int i, npend = 0; + +@@ -2011,7 +2016,8 @@ static bool ath9k_has_tx_pending(struct + if (!ATH_TXQ_SETUP(sc, i)) + continue; + +- npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i]); ++ npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i], ++ sw_pending); + if (npend) + break; + } +@@ -2025,11 +2031,12 @@ static void ath9k_flush(struct ieee80211 + struct ath_softc *sc = hw->priv; + + mutex_lock(&sc->mutex); +- __ath9k_flush(hw, queues, drop); ++ __ath9k_flush(hw, queues, drop, true); + mutex_unlock(&sc->mutex); + } + +-void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) ++void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop, ++ bool sw_pending) + { + struct ath_softc *sc = hw->priv; + struct ath_hw *ah = sc->sc_ah; +@@ -2056,7 +2063,7 @@ void __ath9k_flush(struct ieee80211_hw * + ath_dbg(common, CHAN_CTX, + "Flush timeout: %d\n", jiffies_to_msecs(timeout)); + +- if (wait_event_timeout(sc->tx_wait, !ath9k_has_tx_pending(sc), ++ if (wait_event_timeout(sc->tx_wait, !ath9k_has_tx_pending(sc, sw_pending), + timeout) > 0) + drop = false; + +@@ -2079,7 +2086,7 @@ static bool ath9k_tx_frames_pending(stru + { + struct ath_softc *sc = hw->priv; + +- return ath9k_has_tx_pending(sc); ++ return ath9k_has_tx_pending(sc, true); + } + + static int ath9k_tx_last_beacon(struct ieee80211_hw *hw) |