Commit 043a0405 authored by Sujith's avatar Sujith Committed by John W. Linville

ath9k: Merge queue draining functions

The TX queue draining routines have confusing names,
rename them approprately and merge ath_drain_txdataq()
with ath_drain_all_txq().
Signed-off-by: default avatarSujith <Sujith.Manoharan@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 55f5e4a9
...@@ -220,7 +220,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) ...@@ -220,7 +220,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
* acquires txq lock inside. * acquires txq lock inside.
*/ */
if (sc->sc_nvaps > 1) { if (sc->sc_nvaps > 1) {
ath_tx_draintxq(sc, cabq, false); ath_draintxq(sc, cabq, false);
DPRINTF(sc, ATH_DBG_BEACON, DPRINTF(sc, ATH_DBG_BEACON,
"flush previous cabq traffic\n"); "flush previous cabq traffic\n");
} }
......
...@@ -485,8 +485,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush); ...@@ -485,8 +485,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush);
struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype); struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq); void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
int ath_tx_setup(struct ath_softc *sc, int haltype); int ath_tx_setup(struct ath_softc *sc, int haltype);
void ath_draintxq(struct ath_softc *sc, bool retry_tx); void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx);
void ath_tx_draintxq(struct ath_softc *sc, void ath_draintxq(struct ath_softc *sc,
struct ath_txq *txq, bool retry_tx); struct ath_txq *txq, bool retry_tx);
void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an); void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an);
void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an); void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an);
......
...@@ -247,7 +247,7 @@ static int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan) ...@@ -247,7 +247,7 @@ static int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan)
* the relevant bits of the h/w. * the relevant bits of the h/w.
*/ */
ath9k_hw_set_interrupts(ah, 0); ath9k_hw_set_interrupts(ah, 0);
ath_draintxq(sc, false); ath_drain_all_txq(sc, false);
stopped = ath_stoprecv(sc); stopped = ath_stoprecv(sc);
/* XXX: do not flush receive queue here. We don't want /* XXX: do not flush receive queue here. We don't want
...@@ -1092,7 +1092,7 @@ static void ath_radio_disable(struct ath_softc *sc) ...@@ -1092,7 +1092,7 @@ static void ath_radio_disable(struct ath_softc *sc)
/* Disable interrupts */ /* Disable interrupts */
ath9k_hw_set_interrupts(ah, 0); ath9k_hw_set_interrupts(ah, 0);
ath_draintxq(sc, false); /* clear pending tx frames */ ath_drain_all_txq(sc, false); /* clear pending tx frames */
ath_stoprecv(sc); /* turn off frame recv */ ath_stoprecv(sc); /* turn off frame recv */
ath_flushrecv(sc); /* flush recv queue */ ath_flushrecv(sc); /* flush recv queue */
...@@ -1592,7 +1592,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) ...@@ -1592,7 +1592,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
int r; int r;
ath9k_hw_set_interrupts(ah, 0); ath9k_hw_set_interrupts(ah, 0);
ath_draintxq(sc, retry_tx); ath_drain_all_txq(sc, retry_tx);
ath_stoprecv(sc); ath_stoprecv(sc);
ath_flushrecv(sc); ath_flushrecv(sc);
...@@ -1988,7 +1988,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) ...@@ -1988,7 +1988,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
ath9k_hw_set_interrupts(sc->sc_ah, 0); ath9k_hw_set_interrupts(sc->sc_ah, 0);
if (!(sc->sc_flags & SC_OP_INVALID)) { if (!(sc->sc_flags & SC_OP_INVALID)) {
ath_draintxq(sc, false); ath_drain_all_txq(sc, false);
ath_stoprecv(sc); ath_stoprecv(sc);
ath9k_hw_phy_disable(sc->sc_ah); ath9k_hw_phy_disable(sc->sc_ah);
} else } else
......
...@@ -890,43 +890,6 @@ static void ath_get_beaconconfig(struct ath_softc *sc, int if_id, ...@@ -890,43 +890,6 @@ static void ath_get_beaconconfig(struct ath_softc *sc, int if_id,
conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval; conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval;
} }
static void ath_drain_txdataq(struct ath_softc *sc, bool retry_tx)
{
struct ath_hal *ah = sc->sc_ah;
struct ath_txq *txq;
int i, npend = 0;
if (sc->sc_flags & SC_OP_INVALID)
return;
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
if (ATH_TXQ_SETUP(sc, i)) {
txq = &sc->tx.txq[i];
ath9k_hw_stoptxdma(ah, txq->axq_qnum);
npend += ath9k_hw_numtxpending(ah, txq->axq_qnum);
}
}
if (npend) {
int r;
DPRINTF(sc, ATH_DBG_XMIT, "Unable to stop TxDMA. Reset HAL!\n");
spin_lock_bh(&sc->sc_resetlock);
r = ath9k_hw_reset(ah, sc->sc_ah->ah_curchan, true);
if (r)
DPRINTF(sc, ATH_DBG_FATAL,
"Unable to reset hardware; reset status %u\n",
r);
spin_unlock_bh(&sc->sc_resetlock);
}
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
if (ATH_TXQ_SETUP(sc, i))
ath_tx_draintxq(sc, &sc->tx.txq[i], retry_tx);
}
}
static void ath_txq_drain_pending_buffers(struct ath_softc *sc, static void ath_txq_drain_pending_buffers(struct ath_softc *sc,
struct ath_txq *txq) struct ath_txq *txq)
{ {
...@@ -1120,17 +1083,19 @@ int ath_cabq_update(struct ath_softc *sc) ...@@ -1120,17 +1083,19 @@ int ath_cabq_update(struct ath_softc *sc)
return 0; return 0;
} }
void ath_tx_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) /*
* Drain a given TX queue (could be Beacon or Data)
*
* This assumes output has been stopped and
* we do not need to block ath_tx_tasklet.
*/
void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
{ {
struct ath_buf *bf, *lastbf; struct ath_buf *bf, *lastbf;
struct list_head bf_head; struct list_head bf_head;
INIT_LIST_HEAD(&bf_head); INIT_LIST_HEAD(&bf_head);
/*
* NB: this assumes output has been stopped and
* we do not need to block ath_tx_tasklet
*/
for (;;) { for (;;) {
spin_lock_bh(&txq->axq_lock); spin_lock_bh(&txq->axq_lock);
...@@ -1180,18 +1145,51 @@ void ath_tx_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) ...@@ -1180,18 +1145,51 @@ void ath_tx_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
} }
} }
void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq) void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
{ {
ath9k_hw_releasetxqueue(sc->sc_ah, txq->axq_qnum); struct ath_hal *ah = sc->sc_ah;
sc->tx.txqsetup &= ~(1<<txq->axq_qnum); struct ath_txq *txq;
int i, npend = 0;
if (sc->sc_flags & SC_OP_INVALID)
return;
/* Stop beacon queue */
ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
/* Stop data queues */
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
if (ATH_TXQ_SETUP(sc, i)) {
txq = &sc->tx.txq[i];
ath9k_hw_stoptxdma(ah, txq->axq_qnum);
npend += ath9k_hw_numtxpending(ah, txq->axq_qnum);
}
}
if (npend) {
int r;
DPRINTF(sc, ATH_DBG_XMIT, "Unable to stop TxDMA. Reset HAL!\n");
spin_lock_bh(&sc->sc_resetlock);
r = ath9k_hw_reset(ah, sc->sc_ah->ah_curchan, true);
if (r)
DPRINTF(sc, ATH_DBG_FATAL,
"Unable to reset hardware; reset status %u\n",
r);
spin_unlock_bh(&sc->sc_resetlock);
}
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
if (ATH_TXQ_SETUP(sc, i))
ath_draintxq(sc, &sc->tx.txq[i], retry_tx);
}
} }
void ath_draintxq(struct ath_softc *sc, bool retry_tx) void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)
{ {
if (!(sc->sc_flags & SC_OP_INVALID)) ath9k_hw_releasetxqueue(sc->sc_ah, txq->axq_qnum);
(void) ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); sc->tx.txqsetup &= ~(1<<txq->axq_qnum);
ath_drain_txdataq(sc, retry_tx);
} }
void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment