ath9k: add some more minor hw reset related fixes
[oweals/openwrt.git] / package / mac80211 / patches / 582-ath9k_merge_reset_functions.patch
1 --- a/drivers/net/wireless/ath/ath9k/main.c
2 +++ b/drivers/net/wireless/ath/ath9k/main.c
3 @@ -212,83 +212,57 @@ static int ath_update_survey_stats(struc
4         return ret;
5  }
6  
7 -/*
8 - * Set/change channels.  If the channel is really being changed, it's done
9 - * by reseting the chip.  To accomplish this we must first cleanup any pending
10 - * DMA, then restart stuff.
11 -*/
12 -static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
13 -                   struct ath9k_channel *hchan)
14 +static void __ath_cancel_work(struct ath_softc *sc)
15  {
16 -       struct ath_hw *ah = sc->sc_ah;
17 -       struct ath_common *common = ath9k_hw_common(ah);
18 -       struct ieee80211_conf *conf = &common->hw->conf;
19 -       bool fastcc = true, stopped;
20 -       struct ieee80211_channel *channel = hw->conf.channel;
21 -       struct ath9k_hw_cal_data *caldata = NULL;
22 -       int r;
23 -
24 -       if (sc->sc_flags & SC_OP_INVALID)
25 -               return -EIO;
26 -
27 -       sc->hw_busy_count = 0;
28 -
29 -       del_timer_sync(&common->ani.timer);
30         cancel_work_sync(&sc->paprd_work);
31         cancel_work_sync(&sc->hw_check_work);
32         cancel_delayed_work_sync(&sc->tx_complete_work);
33         cancel_delayed_work_sync(&sc->hw_pll_work);
34 +}
35  
36 -       ath9k_ps_wakeup(sc);
37 +static void ath_cancel_work(struct ath_softc *sc)
38 +{
39 +       __ath_cancel_work(sc);
40 +       cancel_work_sync(&sc->hw_reset_work);
41 +}
42  
43 -       spin_lock_bh(&sc->sc_pcu_lock);
44 +static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush)
45 +{
46 +       struct ath_hw *ah = sc->sc_ah;
47 +       struct ath_common *common = ath9k_hw_common(ah);
48 +       bool ret;
49  
50 -       /*
51 -        * This is only performed if the channel settings have
52 -        * actually changed.
53 -        *
54 -        * To switch channels clear any pending DMA operations;
55 -        * wait long enough for the RX fifo to drain, reset the
56 -        * hardware at the new frequency, and then re-enable
57 -        * the relevant bits of the h/w.
58 -        */
59 -       ath9k_hw_disable_interrupts(ah);
60 -       stopped = ath_drain_all_txq(sc, false);
61 +       ieee80211_stop_queues(sc->hw);
62  
63 -       if (!ath_stoprecv(sc))
64 -               stopped = false;
65 +       sc->hw_busy_count = 0;
66 +       del_timer_sync(&common->ani.timer);
67  
68 -       if (!ath9k_hw_check_alive(ah))
69 -               stopped = false;
70 +       ath9k_hw_disable_interrupts(ah);
71  
72 -       /* XXX: do not flush receive queue here. We don't want
73 -        * to flush data frames already in queue because of
74 -        * changing channel. */
75 +       ret = ath_drain_all_txq(sc, retry_tx);
76  
77 -       if (!stopped || !(sc->sc_flags & SC_OP_OFFCHANNEL))
78 -               fastcc = false;
79 +       if (!ath_stoprecv(sc))
80 +               ret = false;
81  
82 -       if (!(sc->sc_flags & SC_OP_OFFCHANNEL))
83 -               caldata = &sc->caldata;
84 +       if (!flush) {
85 +               if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
86 +                       ath_rx_tasklet(sc, 0, true);
87 +               ath_rx_tasklet(sc, 0, false);
88 +       } else {
89 +               ath_flushrecv(sc);
90 +       }
91  
92 -       ath_dbg(common, ATH_DBG_CONFIG,
93 -               "(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n",
94 -               sc->sc_ah->curchan->channel,
95 -               channel->center_freq, conf_is_ht40(conf),
96 -               fastcc);
97 +       return ret;
98 +}
99  
100 -       r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
101 -       if (r) {
102 -               ath_err(common,
103 -                       "Unable to reset channel (%u MHz), reset status %d\n",
104 -                       channel->center_freq, r);
105 -               goto ps_restore;
106 -       }
107 +static bool ath_complete_reset(struct ath_softc *sc, bool start)
108 +{
109 +       struct ath_hw *ah = sc->sc_ah;
110 +       struct ath_common *common = ath9k_hw_common(ah);
111  
112         if (ath_startrecv(sc) != 0) {
113                 ath_err(common, "Unable to restart recv logic\n");
114 -               r = -EIO;
115 -               goto ps_restore;
116 +               return false;
117         }
118  
119         ath9k_cmn_update_txpow(ah, sc->curtxpow,
120 @@ -296,21 +270,95 @@ static int ath_set_channel(struct ath_so
121         ath9k_hw_set_interrupts(ah, ah->imask);
122         ath9k_hw_enable_interrupts(ah);
123  
124 -       if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) {
125 +       if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) && start) {
126                 if (sc->sc_flags & SC_OP_BEACONS)
127                         ath_set_beacon(sc);
128 +
129                 ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
130                 ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2);
131                 if (!common->disable_ani)
132                         ath_start_ani(common);
133         }
134  
135 - ps_restore:
136 -       ieee80211_wake_queues(hw);
137 +       ieee80211_wake_queues(sc->hw);
138 +
139 +       return true;
140 +}
141 +
142 +static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan,
143 +                             bool retry_tx)
144 +{
145 +       struct ath_hw *ah = sc->sc_ah;
146 +       struct ath_common *common = ath9k_hw_common(ah);
147 +       struct ath9k_hw_cal_data *caldata = NULL;
148 +       bool fastcc = true;
149 +       bool flush = false;
150 +       int r;
151 +
152 +       __ath_cancel_work(sc);
153 +
154 +       spin_lock_bh(&sc->sc_pcu_lock);
155 +
156 +       sc->sc_flags &= ~SC_OP_HW_RESET;
157  
158 +       if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) {
159 +               fastcc = false;
160 +               caldata = &sc->caldata;
161 +       }
162 +
163 +       if (!hchan) {
164 +               fastcc = false;
165 +               flush = true;
166 +               hchan = ah->curchan;
167 +       }
168 +
169 +       if (fastcc && !ath9k_hw_check_alive(ah))
170 +               fastcc = false;
171 +
172 +       if (!ath_prepare_reset(sc, retry_tx, flush))
173 +               fastcc = false;
174 +
175 +       ath_dbg(common, ATH_DBG_CONFIG,
176 +               "Reset to %u MHz, HT40: %d fastcc: %d\n",
177 +               hchan->channel, !!(hchan->channelFlags & (CHANNEL_HT40MINUS |
178 +                                                         CHANNEL_HT40PLUS)),
179 +               fastcc);
180 +
181 +       r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
182 +       if (r) {
183 +               ath_err(common,
184 +                       "Unable to reset channel, reset status %d\n", r);
185 +               goto out;
186 +       }
187 +
188 +       if (!ath_complete_reset(sc, true))
189 +               r = -EIO;
190 +
191 +out:
192         spin_unlock_bh(&sc->sc_pcu_lock);
193 +       return r;
194 +}
195 +
196 +
197 +/*
198 + * Set/change channels.  If the channel is really being changed, it's done
199 + * by reseting the chip.  To accomplish this we must first cleanup any pending
200 + * DMA, then restart stuff.
201 +*/
202 +static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
203 +                   struct ath9k_channel *hchan)
204 +{
205 +       int r;
206 +
207 +       if (sc->sc_flags & SC_OP_INVALID)
208 +               return -EIO;
209 +
210 +       ath9k_ps_wakeup(sc);
211 +
212 +       r = ath_reset_internal(sc, hchan, false);
213  
214         ath9k_ps_restore(sc);
215 +
216         return r;
217  }
218  
219 @@ -823,28 +871,13 @@ static void ath_radio_enable(struct ath_
220                         channel->center_freq, r);
221         }
222  
223 -       ath9k_cmn_update_txpow(ah, sc->curtxpow,
224 -                              sc->config.txpowlimit, &sc->curtxpow);
225 -       if (ath_startrecv(sc) != 0) {
226 -               ath_err(common, "Unable to restart recv logic\n");
227 -               goto out;
228 -       }
229 -       if (sc->sc_flags & SC_OP_BEACONS)
230 -               ath_set_beacon(sc);     /* restart beacons */
231 -
232 -       /* Re-Enable  interrupts */
233 -       ath9k_hw_set_interrupts(ah, ah->imask);
234 -       ath9k_hw_enable_interrupts(ah);
235 +       ath_complete_reset(sc, true);
236  
237         /* Enable LED */
238         ath9k_hw_cfg_output(ah, ah->led_pin,
239                             AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
240         ath9k_hw_set_gpio(ah, ah->led_pin, 0);
241  
242 -       ieee80211_wake_queues(hw);
243 -       ieee80211_queue_delayed_work(hw, &sc->hw_pll_work, HZ/2);
244 -
245 -out:
246         spin_unlock_bh(&sc->sc_pcu_lock);
247  
248         ath9k_ps_restore(sc);
249 @@ -857,11 +890,10 @@ void ath_radio_disable(struct ath_softc 
250         int r;
251  
252         ath9k_ps_wakeup(sc);
253 -       cancel_delayed_work_sync(&sc->hw_pll_work);
254  
255 -       spin_lock_bh(&sc->sc_pcu_lock);
256 +       ath_cancel_work(sc);
257  
258 -       ieee80211_stop_queues(hw);
259 +       spin_lock_bh(&sc->sc_pcu_lock);
260  
261         /*
262          * Keep the LED on when the radio is disabled
263 @@ -872,13 +904,7 @@ void ath_radio_disable(struct ath_softc 
264                 ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
265         }
266  
267 -       /* Disable interrupts */
268 -       ath9k_hw_disable_interrupts(ah);
269 -
270 -       ath_drain_all_txq(sc, false);   /* clear pending tx frames */
271 -
272 -       ath_stoprecv(sc);               /* turn off frame recv */
273 -       ath_flushrecv(sc);              /* flush recv queue */
274 +       ath_prepare_reset(sc, false, true);
275  
276         if (!ah->curchan)
277                 ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
278 @@ -900,49 +926,11 @@ void ath_radio_disable(struct ath_softc 
279  
280  static int ath_reset(struct ath_softc *sc, bool retry_tx)
281  {
282 -       struct ath_hw *ah = sc->sc_ah;
283 -       struct ath_common *common = ath9k_hw_common(ah);
284 -       struct ieee80211_hw *hw = sc->hw;
285         int r;
286  
287 -       sc->sc_flags &= ~SC_OP_HW_RESET;
288 -       sc->hw_busy_count = 0;
289 -
290 -       /* Stop ANI */
291 -
292 -       del_timer_sync(&common->ani.timer);
293 -
294         ath9k_ps_wakeup(sc);
295  
296 -       ieee80211_stop_queues(hw);
297 -
298 -       ath9k_hw_disable_interrupts(ah);
299 -       ath_drain_all_txq(sc, retry_tx);
300 -
301 -       ath_stoprecv(sc);
302 -       ath_flushrecv(sc);
303 -
304 -       r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
305 -       if (r)
306 -               ath_err(common,
307 -                       "Unable to reset hardware; reset status %d\n", r);
308 -
309 -       if (ath_startrecv(sc) != 0)
310 -               ath_err(common, "Unable to start recv logic\n");
311 -
312 -       /*
313 -        * We may be doing a reset in response to a request
314 -        * that changes the channel so update any state that
315 -        * might change as a result.
316 -        */
317 -       ath9k_cmn_update_txpow(ah, sc->curtxpow,
318 -                              sc->config.txpowlimit, &sc->curtxpow);
319 -
320 -       if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL)))
321 -               ath_set_beacon(sc);     /* restart beacons */
322 -
323 -       ath9k_hw_set_interrupts(ah, ah->imask);
324 -       ath9k_hw_enable_interrupts(ah);
325 +       r = ath_reset_internal(sc, NULL, retry_tx);
326  
327         if (retry_tx) {
328                 int i;
329 @@ -955,12 +943,6 @@ static int ath_reset(struct ath_softc *s
330                 }
331         }
332  
333 -       ieee80211_wake_queues(hw);
334 -
335 -       /* Start ANI */
336 -       if (!common->disable_ani)
337 -               ath_start_ani(common);
338 -
339         ath9k_ps_restore(sc);
340  
341         return r;
342 @@ -970,9 +952,7 @@ void ath_reset_work(struct work_struct *
343  {
344         struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
345  
346 -       spin_lock_bh(&sc->sc_pcu_lock);
347         ath_reset(sc, true);
348 -       spin_unlock_bh(&sc->sc_pcu_lock);
349  }
350  
351  void ath_hw_check(struct work_struct *work)
352 @@ -993,11 +973,8 @@ void ath_hw_check(struct work_struct *wo
353         ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
354                 "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
355         if (busy >= 99) {
356 -               if (++sc->hw_busy_count >= 3) {
357 -                       spin_lock_bh(&sc->sc_pcu_lock);
358 -                       ath_reset(sc, true);
359 -                       spin_unlock_bh(&sc->sc_pcu_lock);
360 -               }
361 +               if (++sc->hw_busy_count >= 3)
362 +                       ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
363  
364         } else if (busy >= 0)
365                 sc->hw_busy_count = 0;
366 @@ -1017,9 +994,7 @@ static void ath_hw_pll_rx_hang_check(str
367                         /* Rx is hung for more than 500ms. Reset it */
368                         ath_dbg(common, ATH_DBG_RESET,
369                                 "Possible RX hang, resetting");
370 -                       spin_lock_bh(&sc->sc_pcu_lock);
371 -                       ath_reset(sc, true);
372 -                       spin_unlock_bh(&sc->sc_pcu_lock);
373 +                       ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
374                         count = 0;
375                 }
376         } else
377 @@ -1090,28 +1065,6 @@ static int ath9k_start(struct ieee80211_
378                 goto mutex_unlock;
379         }
380  
381 -       /*
382 -        * This is needed only to setup initial state
383 -        * but it's best done after a reset.
384 -        */
385 -       ath9k_cmn_update_txpow(ah, sc->curtxpow,
386 -                       sc->config.txpowlimit, &sc->curtxpow);
387 -
388 -       /*
389 -        * Setup the hardware after reset:
390 -        * The receive engine is set going.
391 -        * Frame transmit is handled entirely
392 -        * in the frame output path; there's nothing to do
393 -        * here except setup the interrupt mask.
394 -        */
395 -       if (ath_startrecv(sc) != 0) {
396 -               ath_err(common, "Unable to start recv logic\n");
397 -               r = -EIO;
398 -               spin_unlock_bh(&sc->sc_pcu_lock);
399 -               goto mutex_unlock;
400 -       }
401 -       spin_unlock_bh(&sc->sc_pcu_lock);
402 -
403         /* Setup our intr mask. */
404         ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
405                     ATH9K_INT_RXORN | ATH9K_INT_FATAL |
406 @@ -1134,12 +1087,14 @@ static int ath9k_start(struct ieee80211_
407  
408         /* Disable BMISS interrupt when we're not associated */
409         ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
410 -       ath9k_hw_set_interrupts(ah, ah->imask);
411 -       ath9k_hw_enable_interrupts(ah);
412  
413 -       ieee80211_wake_queues(hw);
414 +       if (!ath_complete_reset(sc, false)) {
415 +               r = -EIO;
416 +               spin_unlock_bh(&sc->sc_pcu_lock);
417 +               goto mutex_unlock;
418 +       }
419  
420 -       ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
421 +       spin_unlock_bh(&sc->sc_pcu_lock);
422  
423         if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) &&
424             !ah->btcoex_hw.enabled) {
425 @@ -1232,10 +1187,7 @@ static void ath9k_stop(struct ieee80211_
426  
427         mutex_lock(&sc->mutex);
428  
429 -       cancel_delayed_work_sync(&sc->tx_complete_work);
430 -       cancel_delayed_work_sync(&sc->hw_pll_work);
431 -       cancel_work_sync(&sc->paprd_work);
432 -       cancel_work_sync(&sc->hw_check_work);
433 +       ath_cancel_work(sc);
434  
435         if (sc->sc_flags & SC_OP_INVALID) {
436                 ath_dbg(common, ATH_DBG_ANY, "Device not present\n");
437 @@ -2352,9 +2304,11 @@ static void ath9k_flush(struct ieee80211
438         ath9k_ps_wakeup(sc);
439         spin_lock_bh(&sc->sc_pcu_lock);
440         drain_txq = ath_drain_all_txq(sc, false);
441 +       spin_unlock_bh(&sc->sc_pcu_lock);
442 +
443         if (!drain_txq)
444                 ath_reset(sc, false);
445 -       spin_unlock_bh(&sc->sc_pcu_lock);
446 +
447         ath9k_ps_restore(sc);
448         ieee80211_wake_queues(hw);
449