Skip to content

Commit

Permalink
ath9k: simplify hw reset locking
Browse files Browse the repository at this point in the history
The new PCU lock is better placed so we can just contend
against that when trying to reset hardware.

This is part of a series of patches which fix stopping
TX DMA completley when requested on the driver.
For more details about this issue refer to this thread:

http://marc.info/?l=linux-wireless&m=128629803703756&w=2

Tested-by:  Ben Greear <greearb@candelatech.com>
Cc: Kyungwan Nam <kyungwan.nam@atheros.com>
Cc: stable@kernel.org
Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Luis R. Rodriguez authored and John W. Linville committed Nov 15, 2010
1 parent 5d4c428 commit 9d94674
Show file tree
Hide file tree
Showing 4 changed files with 8 additions and 20 deletions.
1 change: 0 additions & 1 deletion drivers/net/wireless/ath/ath9k/ath9k.h
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,6 @@ struct ath_softc {
struct ath_hw *sc_ah;
void __iomem *mem;
int irq;
spinlock_t sc_resetlock;
spinlock_t sc_serial_rw;
spinlock_t sc_pm_lock;
struct mutex mutex;
Expand Down
1 change: 0 additions & 1 deletion drivers/net/wireless/ath/ath9k/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
spin_lock_init(&common->cc_lock);

spin_lock_init(&sc->wiphy_lock);
spin_lock_init(&sc->sc_resetlock);
spin_lock_init(&sc->sc_serial_rw);
spin_lock_init(&sc->sc_pm_lock);
mutex_init(&sc->mutex);
Expand Down
22 changes: 6 additions & 16 deletions drivers/net/wireless/ath/ath9k/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,19 +262,15 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
channel->center_freq, conf_is_ht40(conf),
fastcc);

spin_lock_bh(&sc->sc_resetlock);

r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
if (r) {
ath_print(common, ATH_DBG_FATAL,
"Unable to reset channel (%u MHz), "
"reset status %d\n",
channel->center_freq, r);
spin_unlock_bh(&sc->sc_resetlock);
spin_unlock_bh(&sc->rx.pcu_lock);
goto ps_restore;
}
spin_unlock_bh(&sc->sc_resetlock);

if (ath_startrecv(sc) != 0) {
ath_print(common, ATH_DBG_FATAL,
Expand Down Expand Up @@ -886,15 +882,13 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
ah->curchan = ath_get_curchannel(sc, sc->hw);

spin_lock_bh(&sc->rx.pcu_lock);
spin_lock_bh(&sc->sc_resetlock);
r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
if (r) {
ath_print(common, ATH_DBG_FATAL,
"Unable to reset channel (%u MHz), "
"reset status %d\n",
channel->center_freq, r);
}
spin_unlock_bh(&sc->sc_resetlock);

ath_update_txpow(sc);
if (ath_startrecv(sc) != 0) {
Expand Down Expand Up @@ -951,15 +945,13 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
if (!ah->curchan)
ah->curchan = ath_get_curchannel(sc, hw);

spin_lock_bh(&sc->sc_resetlock);
r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
if (r) {
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
"Unable to reset channel (%u MHz), "
"reset status %d\n",
channel->center_freq, r);
}
spin_unlock_bh(&sc->sc_resetlock);

ath9k_hw_phy_disable(ah);

Expand Down Expand Up @@ -990,12 +982,10 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
ath_stoprecv(sc);
ath_flushrecv(sc);

spin_lock_bh(&sc->sc_resetlock);
r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
if (r)
ath_print(common, ATH_DBG_FATAL,
"Unable to reset hardware; reset status %d\n", r);
spin_unlock_bh(&sc->sc_resetlock);

if (ath_startrecv(sc) != 0)
ath_print(common, ATH_DBG_FATAL,
Expand Down Expand Up @@ -1166,18 +1156,15 @@ static int ath9k_start(struct ieee80211_hw *hw)
* and then setup of the interrupt mask.
*/
spin_lock_bh(&sc->rx.pcu_lock);
spin_lock_bh(&sc->sc_resetlock);
r = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
if (r) {
ath_print(common, ATH_DBG_FATAL,
"Unable to reset hardware; reset status %d "
"(freq %u MHz)\n", r,
curchan->center_freq);
spin_unlock_bh(&sc->sc_resetlock);
spin_unlock_bh(&sc->rx.pcu_lock);
goto mutex_unlock;
}
spin_unlock_bh(&sc->sc_resetlock);

/*
* This is needed only to setup initial state
Expand Down Expand Up @@ -1398,14 +1385,17 @@ static void ath9k_stop(struct ieee80211_hw *hw)
* before setting the invalid flag. */
ath9k_hw_disable_interrupts(ah);

spin_lock_bh(&sc->rx.pcu_lock);
if (!(sc->sc_flags & SC_OP_INVALID)) {
ath_drain_all_txq(sc, false);
spin_lock_bh(&sc->rx.pcu_lock);
ath_stoprecv(sc);
ath9k_hw_phy_disable(ah);
} else
spin_unlock_bh(&sc->rx.pcu_lock);
} else {
spin_lock_bh(&sc->rx.pcu_lock);
sc->rx.rxlink = NULL;
spin_unlock_bh(&sc->rx.pcu_lock);
spin_unlock_bh(&sc->rx.pcu_lock);
}

/* disable HAL and put h/w to sleep */
ath9k_hw_disable(ah);
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/ath/ath9k/xmit.c
Original file line number Diff line number Diff line change
Expand Up @@ -1148,13 +1148,13 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
ath_print(common, ATH_DBG_FATAL,
"Failed to stop TX DMA. Resetting hardware!\n");

spin_lock_bh(&sc->sc_resetlock);
spin_lock_bh(&sc->rx.pcu_lock);
r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
if (r)
ath_print(common, ATH_DBG_FATAL,
"Unable to reset hardware; reset status %d\n",
r);
spin_unlock_bh(&sc->sc_resetlock);
spin_unlock_bh(&sc->rx.pcu_lock);
}

for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
Expand Down

0 comments on commit 9d94674

Please sign in to comment.