Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -317,7 +317,6 @@ struct ath_rx {
	u32 *rxlink;
	u32 num_pkts;
	unsigned int rxfilter;
	spinlock_t rxbuflock;
	struct list_head rxbuf;
	struct ath_descdma rxdma;
	struct ath_buf *rx_bufptr;
+0 −13
Original line number Diff line number Diff line
@@ -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)
{
	spin_lock_bh(&sc->rx.rxbuflock);

	ath9k_hw_rxena(sc->sc_ah);

	ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP,
@@ -267,8 +265,6 @@ static void ath_edma_start_recv(struct ath_softc *sc)
	ath_opmode_init(sc);

	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)
@@ -285,7 +281,6 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
	int error = 0;

	spin_lock_init(&sc->sc_pcu_lock);
	spin_lock_init(&sc->rx.rxbuflock);

	common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 +
			     sc->sc_ah->caps.rx_status_len;
@@ -446,7 +441,6 @@ int ath_startrecv(struct ath_softc *sc)
		return 0;
	}

	spin_lock_bh(&sc->rx.rxbuflock);
	if (list_empty(&sc->rx.rxbuf))
		goto start_recv;

@@ -467,8 +461,6 @@ int ath_startrecv(struct ath_softc *sc)
	ath_opmode_init(sc);
	ath9k_hw_startpcureceive(ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL));

	spin_unlock_bh(&sc->rx.rxbuflock);

	return 0;
}

@@ -484,7 +476,6 @@ bool ath_stoprecv(struct ath_softc *sc)
	struct ath_hw *ah = sc->sc_ah;
	bool stopped, reset = false;

	spin_lock_bh(&sc->rx.rxbuflock);
	ath9k_hw_abortpcurecv(ah);
	ath9k_hw_setrxfilter(ah, 0);
	stopped = ath9k_hw_stopdmarecv(ah, &reset);
@@ -495,7 +486,6 @@ bool ath_stoprecv(struct ath_softc *sc)
		ath_edma_stop_recv(sc);
	else
		sc->rx.rxlink = NULL;
	spin_unlock_bh(&sc->rx.rxbuflock);

	if (!(ah->ah_flags & AH_UNPLUGGED) &&
	    unlikely(!stopped)) {
@@ -1059,7 +1049,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
		dma_type = DMA_FROM_DEVICE;

	qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP;
	spin_lock_bh(&sc->rx.rxbuflock);

	tsf = ath9k_hw_gettsf64(ah);
	tsf_lower = tsf & 0xffffffff;
@@ -1254,8 +1243,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
		}
	} while (1);

	spin_unlock_bh(&sc->rx.rxbuflock);

	if (!(ah->imask & ATH9K_INT_RXEOL)) {
		ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
		ath9k_hw_set_interrupts(ah);