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