1 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
2 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
3 @@ -429,6 +429,7 @@ void ath9k_set_beaconing_status(struct a
5 #define ATH_PAPRD_TIMEOUT 100 /* msecs */
7 +void ath_reset_work(struct work_struct *work);
8 void ath_hw_check(struct work_struct *work);
9 void ath_hw_pll_work(struct work_struct *work);
10 void ath_paprd_calibrate(struct work_struct *work);
11 @@ -559,6 +560,7 @@ struct ath_ant_comb {
12 #define SC_OP_RXFLUSH BIT(7)
13 #define SC_OP_LED_ASSOCIATED BIT(8)
14 #define SC_OP_LED_ON BIT(9)
15 +#define SC_OP_HW_RESET BIT(10)
16 #define SC_OP_TSF_RESET BIT(11)
17 #define SC_OP_BT_PRIORITY_DETECTED BIT(12)
18 #define SC_OP_BT_SCAN BIT(13)
19 @@ -609,6 +611,7 @@ struct ath_softc {
21 struct work_struct paprd_work;
22 struct work_struct hw_check_work;
23 + struct work_struct hw_reset_work;
24 struct completion paprd_complete;
26 unsigned int hw_busy_count;
27 @@ -655,7 +658,6 @@ struct ath_softc {
30 void ath9k_tasklet(unsigned long data);
31 -int ath_reset(struct ath_softc *sc, bool retry_tx);
32 int ath_cabq_update(struct ath_softc *);
34 static inline void ath_read_cachesize(struct ath_common *common, int *csz)
35 --- a/drivers/net/wireless/ath/ath9k/beacon.c
36 +++ b/drivers/net/wireless/ath/ath9k/beacon.c
37 @@ -386,9 +386,7 @@ void ath_beacon_tasklet(unsigned long da
38 ath_dbg(common, ATH_DBG_BSTUCK,
39 "beacon is officially stuck\n");
40 sc->sc_flags |= SC_OP_TSF_RESET;
41 - spin_lock(&sc->sc_pcu_lock);
42 - ath_reset(sc, true);
43 - spin_unlock(&sc->sc_pcu_lock);
44 + ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
48 --- a/drivers/net/wireless/ath/ath9k/init.c
49 +++ b/drivers/net/wireless/ath/ath9k/init.c
50 @@ -776,6 +776,7 @@ int ath9k_init_device(u16 devid, struct
54 + INIT_WORK(&sc->hw_reset_work, ath_reset_work);
55 INIT_WORK(&sc->hw_check_work, ath_hw_check);
56 INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
57 INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
58 --- a/drivers/net/wireless/ath/ath9k/main.c
59 +++ b/drivers/net/wireless/ath/ath9k/main.c
60 @@ -236,6 +236,7 @@ static int ath_set_channel(struct ath_so
61 del_timer_sync(&common->ani.timer);
62 cancel_work_sync(&sc->paprd_work);
63 cancel_work_sync(&sc->hw_check_work);
64 + cancel_work_sync(&sc->hw_reset_work);
65 cancel_delayed_work_sync(&sc->tx_complete_work);
66 cancel_delayed_work_sync(&sc->hw_pll_work);
68 @@ -595,74 +596,6 @@ static void ath_node_detach(struct ath_s
69 ath_tx_node_cleanup(sc, an);
72 -void ath_hw_check(struct work_struct *work)
74 - struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
75 - struct ath_common *common = ath9k_hw_common(sc->sc_ah);
76 - unsigned long flags;
79 - ath9k_ps_wakeup(sc);
80 - if (ath9k_hw_check_alive(sc->sc_ah))
83 - spin_lock_irqsave(&common->cc_lock, flags);
84 - busy = ath_update_survey_stats(sc);
85 - spin_unlock_irqrestore(&common->cc_lock, flags);
87 - ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
88 - "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
90 - if (++sc->hw_busy_count >= 3) {
91 - spin_lock_bh(&sc->sc_pcu_lock);
92 - ath_reset(sc, true);
93 - spin_unlock_bh(&sc->sc_pcu_lock);
95 - } else if (busy >= 0)
96 - sc->hw_busy_count = 0;
99 - ath9k_ps_restore(sc);
102 -static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
105 - struct ath_common *common = ath9k_hw_common(sc->sc_ah);
107 - if (pll_sqsum >= 0x40000) {
110 - /* Rx is hung for more than 500ms. Reset it */
111 - ath_dbg(common, ATH_DBG_RESET,
112 - "Possible RX hang, resetting");
113 - spin_lock_bh(&sc->sc_pcu_lock);
114 - ath_reset(sc, true);
115 - spin_unlock_bh(&sc->sc_pcu_lock);
122 -void ath_hw_pll_work(struct work_struct *work)
124 - struct ath_softc *sc = container_of(work, struct ath_softc,
128 - if (AR_SREV_9485(sc->sc_ah)) {
130 - ath9k_ps_wakeup(sc);
131 - pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
132 - ath9k_ps_restore(sc);
134 - ath_hw_pll_rx_hang_check(sc, pll_sqsum);
136 - ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5);
141 void ath9k_tasklet(unsigned long data)
143 @@ -675,9 +608,7 @@ void ath9k_tasklet(unsigned long data)
145 if ((status & ATH9K_INT_FATAL) ||
146 (status & ATH9K_INT_BB_WATCHDOG)) {
147 - spin_lock(&sc->sc_pcu_lock);
148 - ath_reset(sc, true);
149 - spin_unlock(&sc->sc_pcu_lock);
150 + ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
154 @@ -968,13 +899,14 @@ void ath_radio_disable(struct ath_softc
155 ath9k_ps_restore(sc);
158 -int ath_reset(struct ath_softc *sc, bool retry_tx)
159 +static int ath_reset(struct ath_softc *sc, bool retry_tx)
161 struct ath_hw *ah = sc->sc_ah;
162 struct ath_common *common = ath9k_hw_common(ah);
163 struct ieee80211_hw *hw = sc->hw;
166 + sc->sc_flags &= ~SC_OP_HW_RESET;
167 sc->hw_busy_count = 0;
170 @@ -1035,6 +967,84 @@ int ath_reset(struct ath_softc *sc, bool
174 +void ath_reset_work(struct work_struct *work)
176 + struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work);
178 + spin_lock_bh(&sc->sc_pcu_lock);
179 + ath_reset(sc, true);
180 + spin_unlock_bh(&sc->sc_pcu_lock);
183 +void ath_hw_check(struct work_struct *work)
185 + struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
186 + struct ath_common *common = ath9k_hw_common(sc->sc_ah);
187 + unsigned long flags;
190 + ath9k_ps_wakeup(sc);
191 + if (ath9k_hw_check_alive(sc->sc_ah))
194 + spin_lock_irqsave(&common->cc_lock, flags);
195 + busy = ath_update_survey_stats(sc);
196 + spin_unlock_irqrestore(&common->cc_lock, flags);
198 + ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
199 + "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
201 + if (++sc->hw_busy_count >= 3) {
202 + spin_lock_bh(&sc->sc_pcu_lock);
203 + ath_reset(sc, true);
204 + spin_unlock_bh(&sc->sc_pcu_lock);
207 + } else if (busy >= 0)
208 + sc->hw_busy_count = 0;
211 + ath9k_ps_restore(sc);
214 +static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
217 + struct ath_common *common = ath9k_hw_common(sc->sc_ah);
219 + if (pll_sqsum >= 0x40000) {
222 + /* Rx is hung for more than 500ms. Reset it */
223 + ath_dbg(common, ATH_DBG_RESET,
224 + "Possible RX hang, resetting");
225 + spin_lock_bh(&sc->sc_pcu_lock);
226 + ath_reset(sc, true);
227 + spin_unlock_bh(&sc->sc_pcu_lock);
234 +void ath_hw_pll_work(struct work_struct *work)
236 + struct ath_softc *sc = container_of(work, struct ath_softc,
240 + if (AR_SREV_9485(sc->sc_ah)) {
242 + ath9k_ps_wakeup(sc);
243 + pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
244 + ath9k_ps_restore(sc);
246 + ath_hw_pll_rx_hang_check(sc, pll_sqsum);
248 + ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5);
252 /**********************/
253 /* mac80211 callbacks */
254 /**********************/
255 @@ -1227,6 +1237,7 @@ static void ath9k_stop(struct ieee80211_
256 cancel_delayed_work_sync(&sc->hw_pll_work);
257 cancel_work_sync(&sc->paprd_work);
258 cancel_work_sync(&sc->hw_check_work);
259 + cancel_work_sync(&sc->hw_reset_work);
261 if (sc->sc_flags & SC_OP_INVALID) {
262 ath_dbg(common, ATH_DBG_ANY, "Device not present\n");
263 --- a/drivers/net/wireless/ath/ath9k/xmit.c
264 +++ b/drivers/net/wireless/ath/ath9k/xmit.c
265 @@ -603,8 +603,10 @@ static void ath_tx_complete_aggr(struct
270 - ath_reset(sc, false);
272 + sc->sc_flags |= SC_OP_HW_RESET;
273 + ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
277 static bool ath_lookup_legacy(struct ath_buf *bf)
278 @@ -1357,7 +1359,7 @@ void ath_txq_schedule(struct ath_softc *
279 struct ath_atx_ac *ac, *ac_tmp, *last_ac;
280 struct ath_atx_tid *tid, *last_tid;
282 - if (list_empty(&txq->axq_acq) ||
283 + if ((sc->sc_flags & SC_OP_HW_RESET) || list_empty(&txq->axq_acq) ||
284 txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
287 @@ -2184,6 +2186,9 @@ static void ath_tx_processq(struct ath_s
289 spin_lock_bh(&txq->axq_lock);
291 + if (sc->sc_flags & SC_OP_HW_RESET)
294 if (list_empty(&txq->axq_q)) {
295 txq->axq_link = NULL;
296 if (sc->sc_flags & SC_OP_TXAGGR)
297 @@ -2271,9 +2276,7 @@ static void ath_tx_complete_poll_work(st
299 ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
300 "tx hung, resetting the chip\n");
301 - spin_lock_bh(&sc->sc_pcu_lock);
302 - ath_reset(sc, true);
303 - spin_unlock_bh(&sc->sc_pcu_lock);
304 + ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
307 ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
308 @@ -2306,6 +2309,9 @@ void ath_tx_edma_tasklet(struct ath_soft
312 + if (sc->sc_flags & SC_OP_HW_RESET)
315 status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts);
316 if (status == -EINPROGRESS)