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>
This commit is contained in:
Sujith Manoharan 2014-10-17 07:40:18 +05:30 committed by John W. Linville
parent 290c8a77e8
commit e2d389b5aa
3 changed files with 19 additions and 10 deletions

View File

@ -715,7 +715,8 @@ int ath_update_survey_stats(struct ath_softc *sc);
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 */

View File

@ -1137,10 +1137,11 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force)
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);

View File

@ -54,7 +54,8 @@ u8 ath9k_parse_mpdudensity(u8 mpdudensity)
}
}
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(struct ath_softc *sc, struct ath_txq *txq)
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(struct ieee80211_hw *hw,
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 ath_softc *sc)
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_hw *hw, struct ieee80211_vif *vif,
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 *hw, u32 queues, bool drop)
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(struct ieee80211_hw *hw)
{
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)