aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSujith Manoharan <c_manoha@qca.qualcomm.com>2012-06-04 10:53:43 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-06-06 15:20:30 -0400
commitaf68abadac378f7a4a44fe766383e7b88c7f9c3b (patch)
treebad7c43d612dfc187dda5be0bf2c4be4c252d1de
parentef1b6cd9a1ba06a3daf9a03aa8f25d52d1f2c31a (diff)
ath9k: Fix work handling
* Currently, there is no synchronization between the reset work and the tx-poll work. Fix this and make sure that we bail out properly if a reset work is in progress. * Cleanup the PLL WAR and enable it for AR9340 too and use a helper for restarting work/timers after a reset. Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/link.c33
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c22
3 files changed, 37 insertions, 19 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index d804416092ce..2faa181d8fcf 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -431,6 +431,7 @@ void ath9k_set_beaconing_status(struct ath_softc *sc, bool status);
431#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ 431#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */
432 432
433#define ATH_PAPRD_TIMEOUT 100 /* msecs */ 433#define ATH_PAPRD_TIMEOUT 100 /* msecs */
434#define ATH_PLL_WORK_INTERVAL 100
434 435
435void ath_tx_complete_poll_work(struct work_struct *work); 436void ath_tx_complete_poll_work(struct work_struct *work);
436void ath_reset_work(struct work_struct *work); 437void ath_reset_work(struct work_struct *work);
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c
index 7368b9630b99..89b38a9ab7c5 100644
--- a/drivers/net/wireless/ath/ath9k/link.c
+++ b/drivers/net/wireless/ath/ath9k/link.c
@@ -52,6 +52,7 @@ void ath_tx_complete_poll_work(struct work_struct *work)
52 "tx hung, resetting the chip\n"); 52 "tx hung, resetting the chip\n");
53 RESET_STAT_INC(sc, RESET_TYPE_TX_HANG); 53 RESET_STAT_INC(sc, RESET_TYPE_TX_HANG);
54 ieee80211_queue_work(sc->hw, &sc->hw_reset_work); 54 ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
55 return;
55 } 56 }
56 57
57 ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 58 ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
@@ -107,9 +108,9 @@ out:
107} 108}
108 109
109/* 110/*
110 * PLL-WAR for AR9485. 111 * PLL-WAR for AR9485/AR9340
111 */ 112 */
112static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum) 113static bool ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
113{ 114{
114 static int count; 115 static int count;
115 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 116 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
@@ -117,29 +118,33 @@ static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
117 if (pll_sqsum >= 0x40000) { 118 if (pll_sqsum >= 0x40000) {
118 count++; 119 count++;
119 if (count == 3) { 120 if (count == 3) {
120 /* Rx is hung for more than 500ms. Reset it */ 121 ath_dbg(common, RESET, "PLL WAR, resetting the chip\n");
121 ath_dbg(common, RESET, "Possible RX hang, resetting\n");
122 RESET_STAT_INC(sc, RESET_TYPE_PLL_HANG); 122 RESET_STAT_INC(sc, RESET_TYPE_PLL_HANG);
123 ieee80211_queue_work(sc->hw, &sc->hw_reset_work); 123 ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
124 count = 0; 124 count = 0;
125 return true;
125 } 126 }
126 } else 127 } else {
127 count = 0; 128 count = 0;
129 }
130
131 return false;
128} 132}
129 133
130void ath_hw_pll_work(struct work_struct *work) 134void ath_hw_pll_work(struct work_struct *work)
131{ 135{
136 u32 pll_sqsum;
132 struct ath_softc *sc = container_of(work, struct ath_softc, 137 struct ath_softc *sc = container_of(work, struct ath_softc,
133 hw_pll_work.work); 138 hw_pll_work.work);
134 u32 pll_sqsum;
135 139
136 if (AR_SREV_9485(sc->sc_ah)) { 140 ath9k_ps_wakeup(sc);
137 ath9k_ps_wakeup(sc); 141 pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
138 pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah); 142 ath9k_ps_restore(sc);
139 ath9k_ps_restore(sc); 143 if (ath_hw_pll_rx_hang_check(sc, pll_sqsum))
140 ath_hw_pll_rx_hang_check(sc, pll_sqsum); 144 return;
141 ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5); 145
142 } 146 ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work,
147 msecs_to_jiffies(ATH_PLL_WORK_INTERVAL));
143} 148}
144 149
145/* 150/*
@@ -293,7 +298,7 @@ void ath_paprd_calibrate(struct work_struct *work)
293 if (ar9003_paprd_create_curve(ah, caldata, chain)) { 298 if (ar9003_paprd_create_curve(ah, caldata, chain)) {
294 ath_dbg(common, CALIBRATE, 299 ath_dbg(common, CALIBRATE,
295 "PAPRD create curve failed on chain %d\n", 300 "PAPRD create curve failed on chain %d\n",
296 chain); 301 chain);
297 break; 302 break;
298 } 303 }
299 304
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 304769a3e179..b228aff481e1 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -158,6 +158,22 @@ static void ath_cancel_work(struct ath_softc *sc)
158 cancel_work_sync(&sc->hw_reset_work); 158 cancel_work_sync(&sc->hw_reset_work);
159} 159}
160 160
161static void ath_restart_work(struct ath_softc *sc)
162{
163 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
164
165 ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
166
167 if (AR_SREV_9485(sc->sc_ah) || AR_SREV_9340(sc->sc_ah))
168 ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work,
169 msecs_to_jiffies(ATH_PLL_WORK_INTERVAL));
170
171 ath_start_rx_poll(sc, 3);
172
173 if (!common->disable_ani)
174 ath_start_ani(common);
175}
176
161static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush) 177static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush)
162{ 178{
163 struct ath_hw *ah = sc->sc_ah; 179 struct ath_hw *ah = sc->sc_ah;
@@ -209,11 +225,7 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start)
209 if (sc->sc_flags & SC_OP_BEACONS) 225 if (sc->sc_flags & SC_OP_BEACONS)
210 ath_set_beacon(sc); 226 ath_set_beacon(sc);
211 227
212 ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); 228 ath_restart_work(sc);
213 ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2);
214 ath_start_rx_poll(sc, 3);
215 if (!common->disable_ani)
216 ath_start_ani(common);
217 } 229 }
218 230
219 if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx != 3) { 231 if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx != 3) {