Skip to content

Commit

Permalink
ath9k: move the PCU lock to the sc structure
Browse files Browse the repository at this point in the history
The PCU lock should be used to contend TX DMA as well,
this will be done next.

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 9d94674 commit 4bdd1e9
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 25 deletions.
2 changes: 1 addition & 1 deletion drivers/net/wireless/ath/ath9k/ath9k.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,6 @@ struct ath_rx {
u8 rxotherant;
u32 *rxlink;
unsigned int rxfilter;
spinlock_t pcu_lock;
spinlock_t rxbuflock;
struct list_head rxbuf;
struct ath_descdma rxdma;
Expand Down Expand Up @@ -601,6 +600,7 @@ struct ath_softc {
int irq;
spinlock_t sc_serial_rw;
spinlock_t sc_pm_lock;
spinlock_t sc_pcu_lock;
struct mutex mutex;
struct work_struct paprd_work;
struct work_struct hw_check_work;
Expand Down
42 changes: 21 additions & 21 deletions drivers/net/wireless/ath/ath9k/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
ath9k_hw_disable_interrupts(ah);
ath_drain_all_txq(sc, false);

spin_lock_bh(&sc->rx.pcu_lock);
spin_lock_bh(&sc->sc_pcu_lock);

stopped = ath_stoprecv(sc);

Expand All @@ -268,19 +268,19 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
"Unable to reset channel (%u MHz), "
"reset status %d\n",
channel->center_freq, r);
spin_unlock_bh(&sc->rx.pcu_lock);
spin_unlock_bh(&sc->sc_pcu_lock);
goto ps_restore;
}

if (ath_startrecv(sc) != 0) {
ath_print(common, ATH_DBG_FATAL,
"Unable to restart recv logic\n");
r = -EIO;
spin_unlock_bh(&sc->rx.pcu_lock);
spin_unlock_bh(&sc->sc_pcu_lock);
goto ps_restore;
}

spin_unlock_bh(&sc->rx.pcu_lock);
spin_unlock_bh(&sc->sc_pcu_lock);

ath_update_txpow(sc);
ath9k_hw_set_interrupts(ah, ah->imask);
Expand Down Expand Up @@ -615,15 +615,15 @@ void ath9k_tasklet(unsigned long data)
rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN);

if (status & rxmask) {
spin_lock_bh(&sc->rx.pcu_lock);
spin_lock_bh(&sc->sc_pcu_lock);

/* Check for high priority Rx first */
if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
(status & ATH9K_INT_RXHP))
ath_rx_tasklet(sc, 0, true);

ath_rx_tasklet(sc, 0, false);
spin_unlock_bh(&sc->rx.pcu_lock);
spin_unlock_bh(&sc->sc_pcu_lock);
}

if (status & ATH9K_INT_TX) {
Expand Down Expand Up @@ -881,7 +881,7 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
if (!ah->curchan)
ah->curchan = ath_get_curchannel(sc, sc->hw);

spin_lock_bh(&sc->rx.pcu_lock);
spin_lock_bh(&sc->sc_pcu_lock);
r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
if (r) {
ath_print(common, ATH_DBG_FATAL,
Expand All @@ -894,10 +894,10 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
if (ath_startrecv(sc) != 0) {
ath_print(common, ATH_DBG_FATAL,
"Unable to restart recv logic\n");
spin_unlock_bh(&sc->rx.pcu_lock);
spin_unlock_bh(&sc->sc_pcu_lock);
return;
}
spin_unlock_bh(&sc->rx.pcu_lock);
spin_unlock_bh(&sc->sc_pcu_lock);

if (sc->sc_flags & SC_OP_BEACONS)
ath_beacon_config(sc, NULL); /* restart beacons */
Expand Down Expand Up @@ -937,7 +937,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)

ath_drain_all_txq(sc, false); /* clear pending tx frames */

spin_lock_bh(&sc->rx.pcu_lock);
spin_lock_bh(&sc->sc_pcu_lock);

ath_stoprecv(sc); /* turn off frame recv */
ath_flushrecv(sc); /* flush recv queue */
Expand All @@ -955,7 +955,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)

ath9k_hw_phy_disable(ah);

spin_unlock_bh(&sc->rx.pcu_lock);
spin_unlock_bh(&sc->sc_pcu_lock);

ath9k_hw_configpcipowersave(ah, 1, 1);
ath9k_ps_restore(sc);
Expand All @@ -977,7 +977,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
ath9k_hw_disable_interrupts(ah);
ath_drain_all_txq(sc, retry_tx);

spin_lock_bh(&sc->rx.pcu_lock);
spin_lock_bh(&sc->sc_pcu_lock);

ath_stoprecv(sc);
ath_flushrecv(sc);
Expand All @@ -991,7 +991,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
ath_print(common, ATH_DBG_FATAL,
"Unable to start recv logic\n");

spin_unlock_bh(&sc->rx.pcu_lock);
spin_unlock_bh(&sc->sc_pcu_lock);

/*
* We may be doing a reset in response to a request
Expand Down Expand Up @@ -1155,14 +1155,14 @@ static int ath9k_start(struct ieee80211_hw *hw)
* be followed by initialization of the appropriate bits
* and then setup of the interrupt mask.
*/
spin_lock_bh(&sc->rx.pcu_lock);
spin_lock_bh(&sc->sc_pcu_lock);
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->rx.pcu_lock);
spin_unlock_bh(&sc->sc_pcu_lock);
goto mutex_unlock;
}

Expand All @@ -1183,10 +1183,10 @@ static int ath9k_start(struct ieee80211_hw *hw)
ath_print(common, ATH_DBG_FATAL,
"Unable to start recv logic\n");
r = -EIO;
spin_unlock_bh(&sc->rx.pcu_lock);
spin_unlock_bh(&sc->sc_pcu_lock);
goto mutex_unlock;
}
spin_unlock_bh(&sc->rx.pcu_lock);
spin_unlock_bh(&sc->sc_pcu_lock);

/* Setup our intr mask. */
ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
Expand Down Expand Up @@ -1387,14 +1387,14 @@ static void ath9k_stop(struct ieee80211_hw *hw)

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

/* disable HAL and put h/w to sleep */
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/ath/ath9k/recv.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
struct ath_buf *bf;
int error = 0;

spin_lock_init(&sc->rx.pcu_lock);
spin_lock_init(&sc->sc_pcu_lock);
sc->sc_flags &= ~SC_OP_RXFLUSH;
spin_lock_init(&sc->rx.rxbuflock);

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->rx.pcu_lock);
spin_lock_bh(&sc->sc_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->rx.pcu_lock);
spin_unlock_bh(&sc->sc_pcu_lock);
}

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

0 comments on commit 4bdd1e9

Please sign in to comment.