aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLuis R. Rodriguez <lrodriguez@atheros.com>2010-10-20 19:07:03 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-10-27 15:41:14 -0400
commit1e450285281bdf766272c181ecd43d4f2f0711ce (patch)
treec7c8cd58d3f08af970e93f3489450886e4489bec /drivers
parent822395b591db32ad3cf8a5b57b0fe30fb8d12c37 (diff)
ath9k: add locking for stopping RX
ath9k locks for starting RX but not for stopping RX. We could potentially run into a situation where tried to stop RX but immediately started RX. This allows for races on the the RX engine deciding what buffer we last left off on and could potentially cause ath9k to DMA into already free'd memory or in the worst case at a later time to already given memory to other drivers. Fix this by locking stopping RX. This is part of a series that will help resolve the bug: https://bugzilla.kernel.org/show_bug.cgi?id=14624 For more details about this issue refer to: http://marc.info/?l=linux-wireless&m=128629803703756&w=2 Cc: stable@kernel.org Cc: Ben Greear <greearb@candelatech.com> Cc: Kyungwan Nam <kyungwan.nam@atheros.com> Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> Tested-by: Ben Greear <greearb@candelatech.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index fe73fc50082a..e581b1f6c40c 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -306,10 +306,8 @@ static void ath_edma_start_recv(struct ath_softc *sc)
306 306
307static void ath_edma_stop_recv(struct ath_softc *sc) 307static void ath_edma_stop_recv(struct ath_softc *sc)
308{ 308{
309 spin_lock_bh(&sc->rx.rxbuflock);
310 ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP); 309 ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP);
311 ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP); 310 ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP);
312 spin_unlock_bh(&sc->rx.rxbuflock);
313} 311}
314 312
315int ath_rx_init(struct ath_softc *sc, int nbufs) 313int ath_rx_init(struct ath_softc *sc, int nbufs)
@@ -518,6 +516,7 @@ bool ath_stoprecv(struct ath_softc *sc)
518 struct ath_hw *ah = sc->sc_ah; 516 struct ath_hw *ah = sc->sc_ah;
519 bool stopped; 517 bool stopped;
520 518
519 spin_lock_bh(&sc->rx.rxbuflock);
521 ath9k_hw_stoppcurecv(ah); 520 ath9k_hw_stoppcurecv(ah);
522 ath9k_hw_setrxfilter(ah, 0); 521 ath9k_hw_setrxfilter(ah, 0);
523 stopped = ath9k_hw_stopdmarecv(ah); 522 stopped = ath9k_hw_stopdmarecv(ah);
@@ -526,6 +525,7 @@ bool ath_stoprecv(struct ath_softc *sc)
526 ath_edma_stop_recv(sc); 525 ath_edma_stop_recv(sc);
527 else 526 else
528 sc->rx.rxlink = NULL; 527 sc->rx.rxlink = NULL;
528 spin_unlock_bh(&sc->rx.rxbuflock);
529 529
530 return stopped; 530 return stopped;
531} 531}