ath9k: fix calibration on 5 ghz
[openwrt.git] / package / mac80211 / patches / 581-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,39 @@ 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 bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx)
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 +       bool ret;
24  
25 -       if (sc->sc_flags & SC_OP_INVALID)
26 -               return -EIO;
27 +       ieee80211_stop_queues(sc->hw);
28  
29         sc->hw_busy_count = 0;
30 -
31 -       del_timer_sync(&common->ani.timer);
32         cancel_work_sync(&sc->paprd_work);
33         cancel_work_sync(&sc->hw_check_work);
34         cancel_delayed_work_sync(&sc->tx_complete_work);
35         cancel_delayed_work_sync(&sc->hw_pll_work);
36  
37 -       ath9k_ps_wakeup(sc);
38 -
39 -       spin_lock_bh(&sc->sc_pcu_lock);
40 -
41 -       /*
42 -        * This is only performed if the channel settings have
43 -        * actually changed.
44 -        *
45 -        * To switch channels clear any pending DMA operations;
46 -        * wait long enough for the RX fifo to drain, reset the
47 -        * hardware at the new frequency, and then re-enable
48 -        * the relevant bits of the h/w.
49 -        */
50         ath9k_hw_disable_interrupts(ah);
51 -       stopped = ath_drain_all_txq(sc, false);
52  
53 -       if (!ath_stoprecv(sc))
54 -               stopped = false;
55 -
56 -       if (!ath9k_hw_check_alive(ah))
57 -               stopped = false;
58 -
59 -       /* XXX: do not flush receive queue here. We don't want
60 -        * to flush data frames already in queue because of
61 -        * changing channel. */
62 +       ret = ath_drain_all_txq(sc, retry_tx);
63  
64 -       if (!stopped || !(sc->sc_flags & SC_OP_OFFCHANNEL))
65 -               fastcc = false;
66 +       if (!ath_stoprecv(sc))
67 +               ret = false;
68  
69 -       if (!(sc->sc_flags & SC_OP_OFFCHANNEL))
70 -               caldata = &sc->caldata;
71 +       ath_flushrecv(sc);
72  
73 -       ath_dbg(common, ATH_DBG_CONFIG,
74 -               "(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n",
75 -               sc->sc_ah->curchan->channel,
76 -               channel->center_freq, conf_is_ht40(conf),
77 -               fastcc);
78 +       return ret;
79 +}
80  
81 -       r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
82 -       if (r) {
83 -               ath_err(common,
84 -                       "Unable to reset channel (%u MHz), reset status %d\n",
85 -                       channel->center_freq, r);
86 -               goto ps_restore;
87 -       }
88 +static bool ath_complete_reset(struct ath_softc *sc, bool start)
89 +{
90 +       struct ath_hw *ah = sc->sc_ah;
91 +       struct ath_common *common = ath9k_hw_common(ah);
92  
93         if (ath_startrecv(sc) != 0) {
94                 ath_err(common, "Unable to restart recv logic\n");
95 -               r = -EIO;
96 -               goto ps_restore;
97 +               return false;
98         }
99  
100         ath9k_cmn_update_txpow(ah, sc->curtxpow,
101 @@ -296,21 +252,87 @@ static int ath_set_channel(struct ath_so
102         ath9k_hw_set_interrupts(ah, ah->imask);
103         ath9k_hw_enable_interrupts(ah);
104  
105 -       if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) {
106 +       if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) && start) {
107                 if (sc->sc_flags & SC_OP_BEACONS)
108                         ath_set_beacon(sc);
109 +
110                 ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
111                 ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2);
112                 if (!common->disable_ani)
113                         ath_start_ani(common);
114         }
115  
116 - ps_restore:
117 -       ieee80211_wake_queues(hw);
118 +       ieee80211_wake_queues(sc->hw);
119 +
120 +       return true;
121 +}
122 +
123 +static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan,
124 +                             bool retry_tx)
125 +{
126 +       struct ath_hw *ah = sc->sc_ah;
127 +       struct ath_common *common = ath9k_hw_common(ah);
128 +       struct ath9k_hw_cal_data *caldata = NULL;
129 +       bool fastcc = true;
130 +       int r;
131 +
132 +       if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) {
133 +               fastcc = false;
134 +               caldata = &sc->caldata;
135 +       }
136  
137 +       if (!hchan) {
138 +               fastcc = false;
139 +               hchan = ah->curchan;
140 +       }
141 +
142 +       if (fastcc && !ath9k_hw_check_alive(ah))
143 +               fastcc = false;
144 +
145 +       if (!ath_prepare_reset(sc, retry_tx))
146 +               fastcc = false;
147 +
148 +       ath_dbg(common, ATH_DBG_CONFIG,
149 +               "Reset to %u MHz, HT40: %d fastcc: %d\n",
150 +               hchan->channel, !!(hchan->channelFlags & (CHANNEL_HT40MINUS |
151 +                                                         CHANNEL_HT40PLUS)),
152 +               fastcc);
153 +
154 +       r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
155 +       if (r) {
156 +               ath_err(common,
157 +                       "Unable to reset channel, reset status %d\n", r);
158 +               return r;
159 +       }
160 +
161 +       if (!ath_complete_reset(sc, true))
162 +               return -EIO;
163 +
164 +       return 0;
165 +}
166 +
167 +
168 +/*
169 + * Set/change channels.  If the channel is really being changed, it's done
170 + * by reseting the chip.  To accomplish this we must first cleanup any pending
171 + * DMA, then restart stuff.
172 +*/
173 +static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
174 +                   struct ath9k_channel *hchan)
175 +{
176 +       int r;
177 +
178 +       if (sc->sc_flags & SC_OP_INVALID)
179 +               return -EIO;
180 +
181 +       ath9k_ps_wakeup(sc);
182 +
183 +       spin_lock_bh(&sc->sc_pcu_lock);
184 +       r = ath_reset_internal(sc, hchan, false);
185         spin_unlock_bh(&sc->sc_pcu_lock);
186  
187         ath9k_ps_restore(sc);
188 +
189         return r;
190  }
191  
192 @@ -893,28 +915,13 @@ static void ath_radio_enable(struct ath_
193                         channel->center_freq, r);
194         }
195  
196 -       ath9k_cmn_update_txpow(ah, sc->curtxpow,
197 -                              sc->config.txpowlimit, &sc->curtxpow);
198 -       if (ath_startrecv(sc) != 0) {
199 -               ath_err(common, "Unable to restart recv logic\n");
200 -               goto out;
201 -       }
202 -       if (sc->sc_flags & SC_OP_BEACONS)
203 -               ath_set_beacon(sc);     /* restart beacons */
204 -
205 -       /* Re-Enable  interrupts */
206 -       ath9k_hw_set_interrupts(ah, ah->imask);
207 -       ath9k_hw_enable_interrupts(ah);
208 +       ath_complete_reset(sc, true);
209  
210         /* Enable LED */
211         ath9k_hw_cfg_output(ah, ah->led_pin,
212                             AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
213         ath9k_hw_set_gpio(ah, ah->led_pin, 0);
214  
215 -       ieee80211_wake_queues(hw);
216 -       ieee80211_queue_delayed_work(hw, &sc->hw_pll_work, HZ/2);
217 -
218 -out:
219         spin_unlock_bh(&sc->sc_pcu_lock);
220  
221         ath9k_ps_restore(sc);
222 @@ -942,13 +949,7 @@ void ath_radio_disable(struct ath_softc 
223                 ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
224         }
225  
226 -       /* Disable interrupts */
227 -       ath9k_hw_disable_interrupts(ah);
228 -
229 -       ath_drain_all_txq(sc, false);   /* clear pending tx frames */
230 -
231 -       ath_stoprecv(sc);               /* turn off frame recv */
232 -       ath_flushrecv(sc);              /* flush recv queue */
233 +       ath_prepare_reset(sc, false);
234  
235         if (!ah->curchan)
236                 ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
237 @@ -970,48 +971,11 @@ void ath_radio_disable(struct ath_softc 
238  
239  int ath_reset(struct ath_softc *sc, bool retry_tx)
240  {
241 -       struct ath_hw *ah = sc->sc_ah;
242 -       struct ath_common *common = ath9k_hw_common(ah);
243 -       struct ieee80211_hw *hw = sc->hw;
244         int r;
245  
246 -       sc->hw_busy_count = 0;
247 -
248 -       /* Stop ANI */
249 -
250 -       del_timer_sync(&common->ani.timer);
251 -
252         ath9k_ps_wakeup(sc);
253  
254 -       ieee80211_stop_queues(hw);
255 -
256 -       ath9k_hw_disable_interrupts(ah);
257 -       ath_drain_all_txq(sc, retry_tx);
258 -
259 -       ath_stoprecv(sc);
260 -       ath_flushrecv(sc);
261 -
262 -       r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
263 -       if (r)
264 -               ath_err(common,
265 -                       "Unable to reset hardware; reset status %d\n", r);
266 -
267 -       if (ath_startrecv(sc) != 0)
268 -               ath_err(common, "Unable to start recv logic\n");
269 -
270 -       /*
271 -        * We may be doing a reset in response to a request
272 -        * that changes the channel so update any state that
273 -        * might change as a result.
274 -        */
275 -       ath9k_cmn_update_txpow(ah, sc->curtxpow,
276 -                              sc->config.txpowlimit, &sc->curtxpow);
277 -
278 -       if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL)))
279 -               ath_set_beacon(sc);     /* restart beacons */
280 -
281 -       ath9k_hw_set_interrupts(ah, ah->imask);
282 -       ath9k_hw_enable_interrupts(ah);
283 +       r = ath_reset_internal(sc, NULL, retry_tx);
284  
285         if (retry_tx) {
286                 int i;
287 @@ -1024,12 +988,6 @@ int ath_reset(struct ath_softc *sc, bool
288                 }
289         }
290  
291 -       ieee80211_wake_queues(hw);
292 -
293 -       /* Start ANI */
294 -       if (!common->disable_ani)
295 -               ath_start_ani(common);
296 -
297         ath9k_ps_restore(sc);
298  
299         return r;
300 @@ -1081,28 +1039,6 @@ static int ath9k_start(struct ieee80211_
301                 goto mutex_unlock;
302         }
303  
304 -       /*
305 -        * This is needed only to setup initial state
306 -        * but it's best done after a reset.
307 -        */
308 -       ath9k_cmn_update_txpow(ah, sc->curtxpow,
309 -                       sc->config.txpowlimit, &sc->curtxpow);
310 -
311 -       /*
312 -        * Setup the hardware after reset:
313 -        * The receive engine is set going.
314 -        * Frame transmit is handled entirely
315 -        * in the frame output path; there's nothing to do
316 -        * here except setup the interrupt mask.
317 -        */
318 -       if (ath_startrecv(sc) != 0) {
319 -               ath_err(common, "Unable to start recv logic\n");
320 -               r = -EIO;
321 -               spin_unlock_bh(&sc->sc_pcu_lock);
322 -               goto mutex_unlock;
323 -       }
324 -       spin_unlock_bh(&sc->sc_pcu_lock);
325 -
326         /* Setup our intr mask. */
327         ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
328                     ATH9K_INT_RXORN | ATH9K_INT_FATAL |
329 @@ -1125,12 +1061,14 @@ static int ath9k_start(struct ieee80211_
330  
331         /* Disable BMISS interrupt when we're not associated */
332         ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
333 -       ath9k_hw_set_interrupts(ah, ah->imask);
334 -       ath9k_hw_enable_interrupts(ah);
335  
336 -       ieee80211_wake_queues(hw);
337 +       if (!ath_complete_reset(sc, false)) {
338 +               r = -EIO;
339 +               spin_unlock_bh(&sc->sc_pcu_lock);
340 +               goto mutex_unlock;
341 +       }
342  
343 -       ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
344 +       spin_unlock_bh(&sc->sc_pcu_lock);
345  
346         if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) &&
347             !ah->btcoex_hw.enabled) {