Commit 463e3ed3 authored by Felix Fietkau's avatar Felix Fietkau Committed by John W. Linville

ath9k: remove sc->rx.rxbuflock to fix a deadlock

The commit "ath9k: fix rx flush handling" added a deadlock that happens
because ath_rx_tasklet is called in a section that has already taken the
rx buffer lock.

It seems that the only purpose of the rxbuflock was a band-aid fix to the
reset vs rx tasklet race, which has been properly fixed in the commit
"ath9k: add a better fix for the rx tasklet vs rx flush race".

Now that the fix is in, we can safely remove the lock to avoid such issues.

Cc: stable@vger.kernel.org
Reported-by: default avatarSujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: default avatarFelix Fietkau <nbd@openwrt.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent a1fe5280
...@@ -317,7 +317,6 @@ struct ath_rx { ...@@ -317,7 +317,6 @@ struct ath_rx {
u32 *rxlink; u32 *rxlink;
u32 num_pkts; u32 num_pkts;
unsigned int rxfilter; unsigned int rxfilter;
spinlock_t rxbuflock;
struct list_head rxbuf; struct list_head rxbuf;
struct ath_descdma rxdma; struct ath_descdma rxdma;
struct ath_buf *rx_bufptr; struct ath_buf *rx_bufptr;
......
...@@ -254,8 +254,6 @@ static int ath_rx_edma_init(struct ath_softc *sc, int nbufs) ...@@ -254,8 +254,6 @@ static int ath_rx_edma_init(struct ath_softc *sc, int nbufs)
static void ath_edma_start_recv(struct ath_softc *sc) static void ath_edma_start_recv(struct ath_softc *sc)
{ {
spin_lock_bh(&sc->rx.rxbuflock);
ath9k_hw_rxena(sc->sc_ah); ath9k_hw_rxena(sc->sc_ah);
ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP, ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP,
...@@ -267,8 +265,6 @@ static void ath_edma_start_recv(struct ath_softc *sc) ...@@ -267,8 +265,6 @@ static void ath_edma_start_recv(struct ath_softc *sc)
ath_opmode_init(sc); ath_opmode_init(sc);
ath9k_hw_startpcureceive(sc->sc_ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)); ath9k_hw_startpcureceive(sc->sc_ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL));
spin_unlock_bh(&sc->rx.rxbuflock);
} }
static void ath_edma_stop_recv(struct ath_softc *sc) static void ath_edma_stop_recv(struct ath_softc *sc)
...@@ -285,7 +281,6 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) ...@@ -285,7 +281,6 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
int error = 0; int error = 0;
spin_lock_init(&sc->sc_pcu_lock); spin_lock_init(&sc->sc_pcu_lock);
spin_lock_init(&sc->rx.rxbuflock);
common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 + common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 +
sc->sc_ah->caps.rx_status_len; sc->sc_ah->caps.rx_status_len;
...@@ -446,7 +441,6 @@ int ath_startrecv(struct ath_softc *sc) ...@@ -446,7 +441,6 @@ int ath_startrecv(struct ath_softc *sc)
return 0; return 0;
} }
spin_lock_bh(&sc->rx.rxbuflock);
if (list_empty(&sc->rx.rxbuf)) if (list_empty(&sc->rx.rxbuf))
goto start_recv; goto start_recv;
...@@ -467,8 +461,6 @@ int ath_startrecv(struct ath_softc *sc) ...@@ -467,8 +461,6 @@ int ath_startrecv(struct ath_softc *sc)
ath_opmode_init(sc); ath_opmode_init(sc);
ath9k_hw_startpcureceive(ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)); ath9k_hw_startpcureceive(ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL));
spin_unlock_bh(&sc->rx.rxbuflock);
return 0; return 0;
} }
...@@ -484,7 +476,6 @@ bool ath_stoprecv(struct ath_softc *sc) ...@@ -484,7 +476,6 @@ bool ath_stoprecv(struct ath_softc *sc)
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
bool stopped, reset = false; bool stopped, reset = false;
spin_lock_bh(&sc->rx.rxbuflock);
ath9k_hw_abortpcurecv(ah); ath9k_hw_abortpcurecv(ah);
ath9k_hw_setrxfilter(ah, 0); ath9k_hw_setrxfilter(ah, 0);
stopped = ath9k_hw_stopdmarecv(ah, &reset); stopped = ath9k_hw_stopdmarecv(ah, &reset);
...@@ -495,7 +486,6 @@ bool ath_stoprecv(struct ath_softc *sc) ...@@ -495,7 +486,6 @@ bool ath_stoprecv(struct ath_softc *sc)
ath_edma_stop_recv(sc); ath_edma_stop_recv(sc);
else else
sc->rx.rxlink = NULL; sc->rx.rxlink = NULL;
spin_unlock_bh(&sc->rx.rxbuflock);
if (!(ah->ah_flags & AH_UNPLUGGED) && if (!(ah->ah_flags & AH_UNPLUGGED) &&
unlikely(!stopped)) { unlikely(!stopped)) {
...@@ -1059,7 +1049,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) ...@@ -1059,7 +1049,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
dma_type = DMA_FROM_DEVICE; dma_type = DMA_FROM_DEVICE;
qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP; qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP;
spin_lock_bh(&sc->rx.rxbuflock);
tsf = ath9k_hw_gettsf64(ah); tsf = ath9k_hw_gettsf64(ah);
tsf_lower = tsf & 0xffffffff; tsf_lower = tsf & 0xffffffff;
...@@ -1254,8 +1243,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) ...@@ -1254,8 +1243,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
} }
} while (1); } while (1);
spin_unlock_bh(&sc->rx.rxbuflock);
if (!(ah->imask & ATH9K_INT_RXEOL)) { if (!(ah->imask & ATH9K_INT_RXEOL)) {
ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN); ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
ath9k_hw_set_interrupts(ah); ath9k_hw_set_interrupts(ah);
......
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