aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSujith Manoharan <c_manoha@qca.qualcomm.com>2014-10-16 22:10:18 -0400
committerJohn W. Linville <linville@tuxdriver.com>2014-10-27 14:16:15 -0400
commite2d389b5aa3741431fc89fca993b7818545dc0f1 (patch)
tree692b89647236101d9d4a172a836ffaf9abda6f68
parent290c8a77e8a9c719bbb11862138e76c9c1dfda61 (diff)
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> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/channel.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c21
3 files changed, 19 insertions, 10 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 43c1987978a8..d4b71ed90236 100644
--- 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_softc *sc);
715void ath_update_survey_nf(struct ath_softc *sc, int channel); 715void ath_update_survey_nf(struct ath_softc *sc, int channel);
716void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type); 716void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type);
717void ath_ps_full_sleep(unsigned long data); 717void ath_ps_full_sleep(unsigned long data);
718void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop); 718void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop,
719 bool sw_pending);
719 720
720/**********/ 721/**********/
721/* BTCOEX */ 722/* BTCOEX */
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c
index abc3e2e77ba6..9c4f872c6e27 100644
--- 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_softc *sc, bool force)
1137 ath9k_chanctx_stop_queues(sc, sc->cur_chan); 1137 ath9k_chanctx_stop_queues(sc, sc->cur_chan);
1138 queues_stopped = true; 1138 queues_stopped = true;
1139 1139
1140 __ath9k_flush(sc->hw, ~0, true); 1140 __ath9k_flush(sc->hw, ~0, true, false);
1141 1141
1142 if (ath_chanctx_send_ps_frame(sc, true)) 1142 if (ath_chanctx_send_ps_frame(sc, true))
1143 __ath9k_flush(sc->hw, BIT(IEEE80211_AC_VO), false); 1143 __ath9k_flush(sc->hw, BIT(IEEE80211_AC_VO),
1144 false, false);
1144 1145
1145 send_ps = true; 1146 send_ps = true;
1146 spin_lock_bh(&sc->chan_lock); 1147 spin_lock_bh(&sc->chan_lock);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 81a20de771c5..2048ef1d8369 100644
--- 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 mpdudensity)
54 } 54 }
55} 55}
56 56
57static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq) 57static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq,
58 bool sw_pending)
58{ 59{
59 bool pending = false; 60 bool pending = false;
60 61
@@ -65,6 +66,9 @@ static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq)
65 goto out; 66 goto out;
66 } 67 }
67 68
69 if (!sw_pending)
70 goto out;
71
68 if (txq->mac80211_qnum >= 0) { 72 if (txq->mac80211_qnum >= 0) {
69 struct list_head *list; 73 struct list_head *list;
70 74
@@ -2003,7 +2007,8 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw,
2003 mutex_unlock(&sc->mutex); 2007 mutex_unlock(&sc->mutex);
2004} 2008}
2005 2009
2006static bool ath9k_has_tx_pending(struct ath_softc *sc) 2010static bool ath9k_has_tx_pending(struct ath_softc *sc,
2011 bool sw_pending)
2007{ 2012{
2008 int i, npend = 0; 2013 int i, npend = 0;
2009 2014
@@ -2011,7 +2016,8 @@ static bool ath9k_has_tx_pending(struct ath_softc *sc)
2011 if (!ATH_TXQ_SETUP(sc, i)) 2016 if (!ATH_TXQ_SETUP(sc, i))
2012 continue; 2017 continue;
2013 2018
2014 npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i]); 2019 npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i],
2020 sw_pending);
2015 if (npend) 2021 if (npend)
2016 break; 2022 break;
2017 } 2023 }
@@ -2025,11 +2031,12 @@ static void ath9k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
2025 struct ath_softc *sc = hw->priv; 2031 struct ath_softc *sc = hw->priv;
2026 2032
2027 mutex_lock(&sc->mutex); 2033 mutex_lock(&sc->mutex);
2028 __ath9k_flush(hw, queues, drop); 2034 __ath9k_flush(hw, queues, drop, true);
2029 mutex_unlock(&sc->mutex); 2035 mutex_unlock(&sc->mutex);
2030} 2036}
2031 2037
2032void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) 2038void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop,
2039 bool sw_pending)
2033{ 2040{
2034 struct ath_softc *sc = hw->priv; 2041 struct ath_softc *sc = hw->priv;
2035 struct ath_hw *ah = sc->sc_ah; 2042 struct ath_hw *ah = sc->sc_ah;
@@ -2056,7 +2063,7 @@ void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
2056 ath_dbg(common, CHAN_CTX, 2063 ath_dbg(common, CHAN_CTX,
2057 "Flush timeout: %d\n", jiffies_to_msecs(timeout)); 2064 "Flush timeout: %d\n", jiffies_to_msecs(timeout));
2058 2065
2059 if (wait_event_timeout(sc->tx_wait, !ath9k_has_tx_pending(sc), 2066 if (wait_event_timeout(sc->tx_wait, !ath9k_has_tx_pending(sc, sw_pending),
2060 timeout) > 0) 2067 timeout) > 0)
2061 drop = false; 2068 drop = false;
2062 2069
@@ -2079,7 +2086,7 @@ static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw)
2079{ 2086{
2080 struct ath_softc *sc = hw->priv; 2087 struct ath_softc *sc = hw->priv;
2081 2088
2082 return ath9k_has_tx_pending(sc); 2089 return ath9k_has_tx_pending(sc, true);
2083} 2090}
2084 2091
2085static int ath9k_tx_last_beacon(struct ieee80211_hw *hw) 2092static int ath9k_tx_last_beacon(struct ieee80211_hw *hw)