Skip to content

Commit

Permalink
ath9k: avoid passing buffers to the hardware during flush
Browse files Browse the repository at this point in the history
The commit "ath9k: fix possible hang on flush" changed the receive code
to always link rx descriptors of processed frames, even when flushing.
In some cases, this leads to flushed rx buffers being passed to the
hardware while rx is already stopped.

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Felix Fietkau authored and John W. Linville committed May 29, 2014
1 parent 3f3c09f commit 7dd74f5
Showing 1 changed file with 13 additions and 11 deletions.
24 changes: 13 additions & 11 deletions drivers/net/wireless/ath/ath9k/recv.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ static inline bool ath9k_check_auto_sleep(struct ath_softc *sc)
* buffer (or rx fifo). This can incorrectly acknowledge packets
* to a sender if last desc is self-linked.
*/
static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf)
static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf,
bool flush)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
Expand All @@ -59,18 +60,19 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf)
common->rx_bufsize,
0);

if (sc->rx.rxlink == NULL)
ath9k_hw_putrxbuf(ah, bf->bf_daddr);
else
if (sc->rx.rxlink)
*sc->rx.rxlink = bf->bf_daddr;
else if (!flush)
ath9k_hw_putrxbuf(ah, bf->bf_daddr);

sc->rx.rxlink = &ds->ds_link;
}

static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf)
static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf,
bool flush)
{
if (sc->rx.buf_hold)
ath_rx_buf_link(sc, sc->rx.buf_hold);
ath_rx_buf_link(sc, sc->rx.buf_hold, flush);

sc->rx.buf_hold = bf;
}
Expand Down Expand Up @@ -442,7 +444,7 @@ int ath_startrecv(struct ath_softc *sc)
sc->rx.buf_hold = NULL;
sc->rx.rxlink = NULL;
list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
ath_rx_buf_link(sc, bf);
ath_rx_buf_link(sc, bf, false);
}

/* We could have deleted elements so the list may be empty now */
Expand Down Expand Up @@ -1118,12 +1120,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
requeue:
list_add_tail(&bf->list, &sc->rx.rxbuf);

if (edma) {
ath_rx_edma_buf_link(sc, qtype);
} else {
ath_rx_buf_relink(sc, bf);
if (!edma) {
ath_rx_buf_relink(sc, bf, flush);
if (!flush)
ath9k_hw_rxena(ah);
} else if (!flush) {
ath_rx_edma_buf_link(sc, qtype);
}

if (!budget--)
Expand Down

0 comments on commit 7dd74f5

Please sign in to comment.