Skip to content

Commit 7dd74f5

Browse files
Felix Fietkaulinvjw
authored andcommitted
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: Felix Fietkau <[email protected]> Signed-off-by: John W. Linville <[email protected]>
1 parent 3f3c09f commit 7dd74f5

File tree

1 file changed

+13
-11
lines changed
  • drivers/net/wireless/ath/ath9k

1 file changed

+13
-11
lines changed

drivers/net/wireless/ath/ath9k/recv.c

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ static inline bool ath9k_check_auto_sleep(struct ath_softc *sc)
3434
* buffer (or rx fifo). This can incorrectly acknowledge packets
3535
* to a sender if last desc is self-linked.
3636
*/
37-
static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf)
37+
static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf,
38+
bool flush)
3839
{
3940
struct ath_hw *ah = sc->sc_ah;
4041
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)
5960
common->rx_bufsize,
6061
0);
6162

62-
if (sc->rx.rxlink == NULL)
63-
ath9k_hw_putrxbuf(ah, bf->bf_daddr);
64-
else
63+
if (sc->rx.rxlink)
6564
*sc->rx.rxlink = bf->bf_daddr;
65+
else if (!flush)
66+
ath9k_hw_putrxbuf(ah, bf->bf_daddr);
6667

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

70-
static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf)
71+
static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf,
72+
bool flush)
7173
{
7274
if (sc->rx.buf_hold)
73-
ath_rx_buf_link(sc, sc->rx.buf_hold);
75+
ath_rx_buf_link(sc, sc->rx.buf_hold, flush);
7476

7577
sc->rx.buf_hold = bf;
7678
}
@@ -442,7 +444,7 @@ int ath_startrecv(struct ath_softc *sc)
442444
sc->rx.buf_hold = NULL;
443445
sc->rx.rxlink = NULL;
444446
list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
445-
ath_rx_buf_link(sc, bf);
447+
ath_rx_buf_link(sc, bf, false);
446448
}
447449

448450
/* 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)
11181120
requeue:
11191121
list_add_tail(&bf->list, &sc->rx.rxbuf);
11201122

1121-
if (edma) {
1122-
ath_rx_edma_buf_link(sc, qtype);
1123-
} else {
1124-
ath_rx_buf_relink(sc, bf);
1123+
if (!edma) {
1124+
ath_rx_buf_relink(sc, bf, flush);
11251125
if (!flush)
11261126
ath9k_hw_rxena(ah);
1127+
} else if (!flush) {
1128+
ath_rx_edma_buf_link(sc, qtype);
11271129
}
11281130

11291131
if (!budget--)

0 commit comments

Comments
 (0)