diff options
author | Bob Copeland <me@bobcopeland.com> | 2009-04-15 07:57:36 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-04-22 16:57:15 -0400 |
commit | 26925042b6b105995ee54c6015e95f0caf9632d6 (patch) | |
tree | 9305c7204ac3aa0bc081b67d36d6ad8a66303c0e /drivers/net/wireless/ath/ath5k/base.c | |
parent | c57ca81576e7ca0369ea52c9ac5f35d0f6ca1270 (diff) |
ath5k: manipulate rxlink and descriptor address under rxbuf lock
Grabbing an ath5k_buf then dropping the lock is racy because the
referenced descriptor can be obtained in another thread and released
before the buffer is handed to the hardware. Likewise, manipulating
sc->rxlink without the lock can lead to having multiple self-linked
hardware descriptors.
Changes-licensed-under: 3-Clause-BSD
Signed-off-by: Bob Copeland <me@bobcopeland.com>
Acked-by: Nick Kossifidis <mickflemm@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath5k/base.c')
-rw-r--r-- | drivers/net/wireless/ath/ath5k/base.c | 5 |
1 files changed, 2 insertions, 3 deletions
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 1a6e72fe7be9..c8c658bfcf9d 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -1618,9 +1618,8 @@ ath5k_rx_start(struct ath5k_softc *sc) | |||
1618 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n", | 1618 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n", |
1619 | sc->cachelsz, sc->rxbufsize); | 1619 | sc->cachelsz, sc->rxbufsize); |
1620 | 1620 | ||
1621 | sc->rxlink = NULL; | ||
1622 | |||
1623 | spin_lock_bh(&sc->rxbuflock); | 1621 | spin_lock_bh(&sc->rxbuflock); |
1622 | sc->rxlink = NULL; | ||
1624 | list_for_each_entry(bf, &sc->rxbuf, list) { | 1623 | list_for_each_entry(bf, &sc->rxbuf, list) { |
1625 | ret = ath5k_rxbuf_setup(sc, bf); | 1624 | ret = ath5k_rxbuf_setup(sc, bf); |
1626 | if (ret != 0) { | 1625 | if (ret != 0) { |
@@ -1629,9 +1628,9 @@ ath5k_rx_start(struct ath5k_softc *sc) | |||
1629 | } | 1628 | } |
1630 | } | 1629 | } |
1631 | bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); | 1630 | bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); |
1631 | ath5k_hw_set_rxdp(ah, bf->daddr); | ||
1632 | spin_unlock_bh(&sc->rxbuflock); | 1632 | spin_unlock_bh(&sc->rxbuflock); |
1633 | 1633 | ||
1634 | ath5k_hw_set_rxdp(ah, bf->daddr); | ||
1635 | ath5k_hw_start_rx_dma(ah); /* enable recv descriptors */ | 1634 | ath5k_hw_start_rx_dma(ah); /* enable recv descriptors */ |
1636 | ath5k_mode_setup(sc); /* set filters, etc. */ | 1635 | ath5k_mode_setup(sc); /* set filters, etc. */ |
1637 | ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */ | 1636 | ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */ |