ff491a4a9c0c8749a7a8d089850db4d6ece95c47
[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,95 @@ 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 +       sc->sc_flags &= ~SC_OP_HW_RESET;
158  
159 +       if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) {
160 +               fastcc = false;
161 +               caldata = &sc->caldata;
162 +       }
163 +
164 +       if (!hchan) {
165 +               fastcc = false;
166 +               flush = true;
167 +               hchan = ah->curchan;
168 +       }
169 +
170 +       if (fastcc && !ath9k_hw_check_alive(ah))
171 +               fastcc = false;
172 +
173 +       if (!ath_prepare_reset(sc, retry_tx, flush))
174 +               fastcc = false;
175 +
176 +       ath_dbg(common, ATH_DBG_CONFIG,
177 +               "Reset to %u MHz, HT40: %d fastcc: %d\n",
178 +               hchan->channel, !!(hchan->channelFlags & (CHANNEL_HT40MINUS |
179 +                                                         CHANNEL_HT40PLUS)),
180 +               fastcc);
181 +
182 +       r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
183 +       if (r) {
184 +               ath_err(common,
185 +                       "Unable to reset channel, reset status %d\n", r);
186 +               goto out;
187 +       }
188 +
189 +       if (!ath_complete_reset(sc, true))
190 +               r = -EIO;
191 +
192 +out:
193         spin_unlock_bh(&sc->sc_pcu_lock);
194 +       return r;
195 +}
196 +
197 +
198 +/*
199 + * Set/change channels.  If the channel is really being changed, it's done
200 + * by reseting the chip.  To accomplish this we must first cleanup any pending
201 + * DMA, then restart stuff.
202 +*/
203 +static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
204 +                   struct ath9k_channel *hchan)
205 +{
206 +       int r;
207 +
208 +       if (sc->sc_flags & SC_OP_INVALID)
209 +               return -EIO;
210 +
211 +       ath9k_ps_wakeup(sc);
212 +
213 +       r = ath_reset_internal(sc, hchan, false);
214  
215         ath9k_ps_restore(sc);
216 +
217         return r;
218  }
219  
220 @@ -824,28 +871,13 @@ static void ath_radio_enable(struct ath_
221                         channel->center_freq, r);
222         }
223  
224 -       ath9k_cmn_update_txpow(ah, sc->curtxpow,
225 -                              sc->config.txpowlimit, &sc->curtxpow);
226 -       if (ath_startrecv(sc) != 0) {
227 -               ath_err(common, "Unable to restart recv logic\n");
228 -               goto out;
229 -       }
230 -       if (sc->sc_flags & SC_OP_BEACONS)
231 -               ath_set_beacon(sc);     /* restart beacons */
232 -
233 -       /* Re-Enable  interrupts */
234 -       ath9k_hw_set_interrupts(ah, ah->imask);
235 -       ath9k_hw_enable_interrupts(ah);
236 +       ath_complete_reset(sc, true);
237  
238         /* Enable LED */
239         ath9k_hw_cfg_output(ah, ah->led_pin,
240                             AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
241         ath9k_hw_set_gpio(ah, ah->led_pin, 0);
242  
243 -       ieee80211_wake_queues(hw);
244 -       ieee80211_queue_delayed_work(hw, &sc->hw_pll_work, HZ/2);
245 -
246 -out:
247         spin_unlock_bh(&sc->sc_pcu_lock);
248  
249         ath9k_ps_restore(sc);
250 @@ -858,11 +890,10 @@ void ath_radio_disable(struct ath_softc 
251         int r;
252  
253         ath9k_ps_wakeup(sc);
254 -       cancel_delayed_work_sync(&sc->hw_pll_work);
255  
256 -       spin_lock_bh(&sc->sc_pcu_lock);
257 +       ath_cancel_work(sc);
258  
259 -       ieee80211_stop_queues(hw);
260 +       spin_lock_bh(&sc->sc_pcu_lock);
261  
262         /*
263          * Keep the LED on when the radio is disabled
264 @@ -873,13 +904,7 @@ void ath_radio_disable(struct ath_softc 
265                 ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
266         }
267  
268 -       /* Disable interrupts */
269 -       ath9k_hw_disable_interrupts(ah);
270 -
271 -       ath_drain_all_txq(sc, false);   /* clear pending tx frames */
272 -
273 -       ath_stoprecv(sc);               /* turn off frame recv */
274 -       ath_flushrecv(sc);              /* flush recv queue */
275 +       ath_prepare_reset(sc, false, true);
276  
277         if (!ah->curchan)
278                 ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
279 @@ -901,49 +926,11 @@ void ath_radio_disable(struct ath_softc 
280  
281  static int ath_reset(struct ath_softc *sc, bool retry_tx)
282  {
283 -       struct ath_hw *ah = sc->sc_ah;
284 -       struct ath_common *common = ath9k_hw_common(ah);
285 -       struct ieee80211_hw *hw = sc->hw;
286         int r;
287  
288 -       sc->sc_flags &= ~SC_OP_HW_RESET;
289 -       sc->hw_busy_count = 0;
290 -
291 -       /* Stop ANI */
292 -
293 -       del_timer_sync(&common->ani.timer);
294 -
295         ath9k_ps_wakeup(sc);
296  
297 -       ieee80211_stop_queues(hw);
298 -
299 -       ath9k_hw_disable_interrupts(ah);
300 -       ath_drain_all_txq(sc, retry_tx);
301 -
302 -       ath_stoprecv(sc);
303 -       ath_flushrecv(sc);
304 -
305 -       r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
306 -       if (r)
307 -               ath_err(common,
308 -                       "Unable to reset hardware; reset status %d\n", r);
309 -
310 -       if (ath_startrecv(sc) != 0)
311 -               ath_err(common, "Unable to start recv logic\n");
312 -
313 -       /*
314 -        * We may be doing a reset in response to a request
315 -        * that changes the channel so update any state that
316 -        * might change as a result.
317 -        */
318 -       ath9k_cmn_update_txpow(ah, sc->curtxpow,
319 -                              sc->config.txpowlimit, &sc->curtxpow);
320 -
321 -       if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL)))
322 -               ath_set_beacon(sc);     /* restart beacons */
323 -
324 -       ath9k_hw_set_interrupts(ah, ah->imask);
325 -       ath9k_hw_enable_interrupts(ah);
326 +       r = ath_reset_internal(sc, NULL, retry_tx);
327  
328         if (retry_tx) {
329                 int i;
330 @@ -956,12 +943,6 @@ static int ath_reset(struct ath_softc *s
331                 }
332         }
333  
334 -       ieee80211_wake_queues(hw);
335 -
336 -       /* Start ANI */
337 -       if (!common->disable_ani)
338 -               ath_start_ani(common);
339 -
340         ath9k_ps_restore(sc);
341  
342         return r;
343 @@ -971,9 +952,7 @@ void ath_reset_work(struct work_struct *
344  {
345         struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
346  
347 -       spin_lock_bh(&sc->sc_pcu_lock);
348         ath_reset(sc, true);
349 -       spin_unlock_bh(&sc->sc_pcu_lock);
350  }
351  
352  void ath_hw_check(struct work_struct *work)
353 @@ -994,11 +973,8 @@ void ath_hw_check(struct work_struct *wo
354         ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
355                 "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
356         if (busy >= 99) {
357 -               if (++sc->hw_busy_count >= 3) {
358 -                       spin_lock_bh(&sc->sc_pcu_lock);
359 -                       ath_reset(sc, true);
360 -                       spin_unlock_bh(&sc->sc_pcu_lock);
361 -               }
362 +               if (++sc->hw_busy_count >= 3)
363 +                       ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
364  
365         } else if (busy >= 0)
366                 sc->hw_busy_count = 0;
367 @@ -1018,9 +994,7 @@ static void ath_hw_pll_rx_hang_check(str
368                         /* Rx is hung for more than 500ms. Reset it */
369                         ath_dbg(common, ATH_DBG_RESET,
370                                 "Possible RX hang, resetting");
371 -                       spin_lock_bh(&sc->sc_pcu_lock);
372 -                       ath_reset(sc, true);
373 -                       spin_unlock_bh(&sc->sc_pcu_lock);
374 +                       ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
375                         count = 0;
376                 }
377         } else
378 @@ -1091,28 +1065,6 @@ static int ath9k_start(struct ieee80211_
379                 goto mutex_unlock;
380         }
381  
382 -       /*
383 -        * This is needed only to setup initial state
384 -        * but it's best done after a reset.
385 -        */
386 -       ath9k_cmn_update_txpow(ah, sc->curtxpow,
387 -                       sc->config.txpowlimit, &sc->curtxpow);
388 -
389 -       /*
390 -        * Setup the hardware after reset:
391 -        * The receive engine is set going.
392 -        * Frame transmit is handled entirely
393 -        * in the frame output path; there's nothing to do
394 -        * here except setup the interrupt mask.
395 -        */
396 -       if (ath_startrecv(sc) != 0) {
397 -               ath_err(common, "Unable to start recv logic\n");
398 -               r = -EIO;
399 -               spin_unlock_bh(&sc->sc_pcu_lock);
400 -               goto mutex_unlock;
401 -       }
402 -       spin_unlock_bh(&sc->sc_pcu_lock);
403 -
404         /* Setup our intr mask. */
405         ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
406                     ATH9K_INT_RXORN | ATH9K_INT_FATAL |
407 @@ -1135,12 +1087,14 @@ static int ath9k_start(struct ieee80211_
408  
409         /* Disable BMISS interrupt when we're not associated */
410         ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
411 -       ath9k_hw_set_interrupts(ah, ah->imask);
412 -       ath9k_hw_enable_interrupts(ah);
413  
414 -       ieee80211_wake_queues(hw);
415 +       if (!ath_complete_reset(sc, false)) {
416 +               r = -EIO;
417 +               spin_unlock_bh(&sc->sc_pcu_lock);
418 +               goto mutex_unlock;
419 +       }
420  
421 -       ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
422 +       spin_unlock_bh(&sc->sc_pcu_lock);
423  
424         if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) &&
425             !ah->btcoex_hw.enabled) {
426 @@ -1233,11 +1187,7 @@ static void ath9k_stop(struct ieee80211_
427  
428         mutex_lock(&sc->mutex);
429  
430 -       cancel_delayed_work_sync(&sc->tx_complete_work);
431 -       cancel_delayed_work_sync(&sc->hw_pll_work);
432 -       cancel_work_sync(&sc->paprd_work);
433 -       cancel_work_sync(&sc->hw_check_work);
434 -       cancel_work_sync(&sc->hw_reset_work);
435 +       ath_cancel_work(sc);
436  
437         if (sc->sc_flags & SC_OP_INVALID) {
438                 ath_dbg(common, ATH_DBG_ANY, "Device not present\n");
439 @@ -2354,9 +2304,11 @@ static void ath9k_flush(struct ieee80211
440         ath9k_ps_wakeup(sc);
441         spin_lock_bh(&sc->sc_pcu_lock);
442         drain_txq = ath_drain_all_txq(sc, false);
443 +       spin_unlock_bh(&sc->sc_pcu_lock);
444 +
445         if (!drain_txq)
446                 ath_reset(sc, false);
447 -       spin_unlock_bh(&sc->sc_pcu_lock);
448 +
449         ath9k_ps_restore(sc);
450         ieee80211_wake_queues(hw);
451