Skip to content

Commit

Permalink
ath9k: Fix a PLL hang issue observed with AR9485.
Browse files Browse the repository at this point in the history
When this PLL hang issue is seen, both Rx and Tx fail to work.
The sqsum_dvc needs to be below 2000 for a good chip. During
this issue the sqsum_dvc value is beyond 80000 and only a
full reset can solve this problem.

Signed-off-by: Vivek Natarajan <vnatarajan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Vivek Natarajan authored and John W. Linville committed Jan 28, 2011
1 parent b141581 commit 181fb18
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/net/wireless/ath/ath9k/ath9k.h
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,7 @@ struct ath_softc {
#endif
struct ath_beacon_config cur_beacon_conf;
struct delayed_work tx_complete_work;
struct delayed_work hw_pll_work;
struct ath_btcoex btcoex;

struct ath_descdma txsdma;
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/wireless/ath/ath9k/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
cancel_work_sync(&sc->paprd_work);
cancel_work_sync(&sc->hw_check_work);
cancel_delayed_work_sync(&sc->tx_complete_work);
cancel_delayed_work_sync(&sc->hw_pll_work);

ath9k_ps_wakeup(sc);

Expand Down Expand Up @@ -290,6 +291,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
if (sc->sc_flags & SC_OP_BEACONS)
ath_beacon_config(sc, NULL);
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2);
ath_start_ani(common);
}

Expand Down Expand Up @@ -1263,6 +1265,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
cancel_delayed_work_sync(&sc->ath_led_blink_work);

cancel_delayed_work_sync(&sc->tx_complete_work);
cancel_delayed_work_sync(&sc->hw_pll_work);
cancel_work_sync(&sc->paprd_work);
cancel_work_sync(&sc->hw_check_work);

Expand Down
23 changes: 23 additions & 0 deletions drivers/net/wireless/ath/ath9k/xmit.c
Original file line number Diff line number Diff line change
Expand Up @@ -2091,6 +2091,28 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
}
}

static void ath_hw_pll_work(struct work_struct *work)
{
struct ath_softc *sc = container_of(work, struct ath_softc,
hw_pll_work.work);
static int count;

if (AR_SREV_9485(sc->sc_ah)) {
if (ar9003_get_pll_sqsum_dvc(sc->sc_ah) >= 0x40000) {
count++;

if (count == 3) {
/* Rx is hung for more than 500ms. Reset it */
ath_reset(sc, true);
count = 0;
}
} else
count = 0;

ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5);
}
}

static void ath_tx_complete_poll_work(struct work_struct *work)
{
struct ath_softc *sc = container_of(work, struct ath_softc,
Expand Down Expand Up @@ -2312,6 +2334,7 @@ int ath_tx_init(struct ath_softc *sc, int nbufs)
}

INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work);
INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);

if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
error = ath_tx_edma_init(sc);
Expand Down

0 comments on commit 181fb18

Please sign in to comment.