Commit 7dd74f5f authored by Felix Fietkau's avatar Felix Fietkau Committed by John W. Linville

ath9k: avoid passing buffers to the hardware during flush

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: default avatarFelix Fietkau <nbd@openwrt.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 3f3c09f3
...@@ -34,7 +34,8 @@ static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) ...@@ -34,7 +34,8 @@ static inline bool ath9k_check_auto_sleep(struct ath_softc *sc)
* buffer (or rx fifo). This can incorrectly acknowledge packets * buffer (or rx fifo). This can incorrectly acknowledge packets
* to a sender if last desc is self-linked. * 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_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
...@@ -59,18 +60,19 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf) ...@@ -59,18 +60,19 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf)
common->rx_bufsize, common->rx_bufsize,
0); 0);
if (sc->rx.rxlink == NULL) if (sc->rx.rxlink)
ath9k_hw_putrxbuf(ah, bf->bf_daddr);
else
*sc->rx.rxlink = bf->bf_daddr; *sc->rx.rxlink = bf->bf_daddr;
else if (!flush)
ath9k_hw_putrxbuf(ah, bf->bf_daddr);
sc->rx.rxlink = &ds->ds_link; 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) 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; sc->rx.buf_hold = bf;
} }
...@@ -442,7 +444,7 @@ int ath_startrecv(struct ath_softc *sc) ...@@ -442,7 +444,7 @@ int ath_startrecv(struct ath_softc *sc)
sc->rx.buf_hold = NULL; sc->rx.buf_hold = NULL;
sc->rx.rxlink = NULL; sc->rx.rxlink = NULL;
list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) { 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 */ /* We could have deleted elements so the list may be empty now */
...@@ -1118,12 +1120,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) ...@@ -1118,12 +1120,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
requeue: requeue:
list_add_tail(&bf->list, &sc->rx.rxbuf); list_add_tail(&bf->list, &sc->rx.rxbuf);
if (edma) { if (!edma) {
ath_rx_edma_buf_link(sc, qtype); ath_rx_buf_relink(sc, bf, flush);
} else {
ath_rx_buf_relink(sc, bf);
if (!flush) if (!flush)
ath9k_hw_rxena(ah); ath9k_hw_rxena(ah);
} else if (!flush) {
ath_rx_edma_buf_link(sc, qtype);
} }
if (!budget--) if (!budget--)
......
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