Merge tag 'microblaze-3.17-rc1' of git://git.monstr.eu/linux-2.6-microblaze
[cascardo/linux.git] / drivers / net / wireless / ath / ath9k / channel.c
1 /*
2  * Copyright (c) 2014 Qualcomm Atheros, Inc.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include "ath9k.h"
18
19 /* Set/change channels.  If the channel is really being changed, it's done
20  * by reseting the chip.  To accomplish this we must first cleanup any pending
21  * DMA, then restart stuff.
22  */
23 static int ath_set_channel(struct ath_softc *sc)
24 {
25         struct ath_hw *ah = sc->sc_ah;
26         struct ath_common *common = ath9k_hw_common(ah);
27         struct ieee80211_hw *hw = sc->hw;
28         struct ath9k_channel *hchan;
29         struct cfg80211_chan_def *chandef = &sc->cur_chan->chandef;
30         struct ieee80211_channel *chan = chandef->chan;
31         int pos = chan->hw_value;
32         int old_pos = -1;
33         int r;
34
35         if (test_bit(ATH_OP_INVALID, &common->op_flags))
36                 return -EIO;
37
38         if (ah->curchan)
39                 old_pos = ah->curchan - &ah->channels[0];
40
41         ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n",
42                 chan->center_freq, chandef->width);
43
44         /* update survey stats for the old channel before switching */
45         spin_lock_bh(&common->cc_lock);
46         ath_update_survey_stats(sc);
47         spin_unlock_bh(&common->cc_lock);
48
49         ath9k_cmn_get_channel(hw, ah, chandef);
50
51         /* If the operating channel changes, change the survey in-use flags
52          * along with it.
53          * Reset the survey data for the new channel, unless we're switching
54          * back to the operating channel from an off-channel operation.
55          */
56         if (!sc->cur_chan->offchannel && sc->cur_survey != &sc->survey[pos]) {
57                 if (sc->cur_survey)
58                         sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE;
59
60                 sc->cur_survey = &sc->survey[pos];
61
62                 memset(sc->cur_survey, 0, sizeof(struct survey_info));
63                 sc->cur_survey->filled |= SURVEY_INFO_IN_USE;
64         } else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) {
65                 memset(&sc->survey[pos], 0, sizeof(struct survey_info));
66         }
67
68         hchan = &sc->sc_ah->channels[pos];
69         r = ath_reset_internal(sc, hchan);
70         if (r)
71                 return r;
72
73         /* The most recent snapshot of channel->noisefloor for the old
74          * channel is only available after the hardware reset. Copy it to
75          * the survey stats now.
76          */
77         if (old_pos >= 0)
78                 ath_update_survey_nf(sc, old_pos);
79
80         /* Enable radar pulse detection if on a DFS channel. Spectral
81          * scanning and radar detection can not be used concurrently.
82          */
83         if (hw->conf.radar_enabled) {
84                 u32 rxfilter;
85
86                 /* set HW specific DFS configuration */
87                 ath9k_hw_set_radar_params(ah);
88                 rxfilter = ath9k_hw_getrxfilter(ah);
89                 rxfilter |= ATH9K_RX_FILTER_PHYRADAR |
90                                 ATH9K_RX_FILTER_PHYERR;
91                 ath9k_hw_setrxfilter(ah, rxfilter);
92                 ath_dbg(common, DFS, "DFS enabled at freq %d\n",
93                         chan->center_freq);
94         } else {
95                 /* perform spectral scan if requested. */
96                 if (test_bit(ATH_OP_SCANNING, &common->op_flags) &&
97                         sc->spectral_mode == SPECTRAL_CHANSCAN)
98                         ath9k_spectral_scan_trigger(hw);
99         }
100
101         return 0;
102 }
103
104 static bool
105 ath_chanctx_send_vif_ps_frame(struct ath_softc *sc, struct ath_vif *avp,
106                               bool powersave)
107 {
108         struct ieee80211_vif *vif = avp->vif;
109         struct ieee80211_sta *sta = NULL;
110         struct ieee80211_hdr_3addr *nullfunc;
111         struct ath_tx_control txctl;
112         struct sk_buff *skb;
113         int band = sc->cur_chan->chandef.chan->band;
114
115         switch (vif->type) {
116         case NL80211_IFTYPE_STATION:
117                 if (!vif->bss_conf.assoc)
118                         return false;
119
120                 skb = ieee80211_nullfunc_get(sc->hw, vif);
121                 if (!skb)
122                         return false;
123
124                 nullfunc = (struct ieee80211_hdr_3addr *) skb->data;
125                 if (powersave)
126                         nullfunc->frame_control |=
127                                 cpu_to_le16(IEEE80211_FCTL_PM);
128
129                 skb_set_queue_mapping(skb, IEEE80211_AC_VO);
130                 if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, &sta)) {
131                         dev_kfree_skb_any(skb);
132                         return false;
133                 }
134                 break;
135         default:
136                 return false;
137         }
138
139         memset(&txctl, 0, sizeof(txctl));
140         txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO];
141         txctl.sta = sta;
142         txctl.force_channel = true;
143         if (ath_tx_start(sc->hw, skb, &txctl)) {
144                 ieee80211_free_txskb(sc->hw, skb);
145                 return false;
146         }
147
148         return true;
149 }
150
151 void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx)
152 {
153         struct ath_common *common = ath9k_hw_common(sc->sc_ah);
154         struct ath_vif *avp;
155         bool active = false;
156         u8 n_active = 0;
157
158         if (!ctx)
159                 return;
160
161         list_for_each_entry(avp, &ctx->vifs, list) {
162                 struct ieee80211_vif *vif = avp->vif;
163
164                 switch (vif->type) {
165                 case NL80211_IFTYPE_P2P_CLIENT:
166                 case NL80211_IFTYPE_STATION:
167                         if (vif->bss_conf.assoc)
168                                 active = true;
169                         break;
170                 default:
171                         active = true;
172                         break;
173                 }
174         }
175         ctx->active = active;
176
177         ath_for_each_chanctx(sc, ctx) {
178                 if (!ctx->assigned || list_empty(&ctx->vifs))
179                         continue;
180                 n_active++;
181         }
182
183         if (n_active <= 1) {
184                 clear_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags);
185                 return;
186         }
187         if (test_and_set_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags))
188                 return;
189         ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_ENABLE_MULTICHANNEL);
190 }
191
192 static bool
193 ath_chanctx_send_ps_frame(struct ath_softc *sc, bool powersave)
194 {
195         struct ath_vif *avp;
196         bool sent = false;
197
198         rcu_read_lock();
199         list_for_each_entry(avp, &sc->cur_chan->vifs, list) {
200                 if (ath_chanctx_send_vif_ps_frame(sc, avp, powersave))
201                         sent = true;
202         }
203         rcu_read_unlock();
204
205         return sent;
206 }
207
208 static bool ath_chanctx_defer_switch(struct ath_softc *sc)
209 {
210         if (sc->cur_chan == &sc->offchannel.chan)
211                 return false;
212
213         switch (sc->sched.state) {
214         case ATH_CHANCTX_STATE_SWITCH:
215                 return false;
216         case ATH_CHANCTX_STATE_IDLE:
217                 if (!sc->cur_chan->switch_after_beacon)
218                         return false;
219
220                 sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON;
221                 break;
222         default:
223                 break;
224         }
225
226         return true;
227 }
228
229 static void ath_chanctx_set_next(struct ath_softc *sc, bool force)
230 {
231         struct timespec ts;
232         bool measure_time = false;
233         bool send_ps = false;
234
235         spin_lock_bh(&sc->chan_lock);
236         if (!sc->next_chan) {
237                 spin_unlock_bh(&sc->chan_lock);
238                 return;
239         }
240
241         if (!force && ath_chanctx_defer_switch(sc)) {
242                 spin_unlock_bh(&sc->chan_lock);
243                 return;
244         }
245
246         if (sc->cur_chan != sc->next_chan) {
247                 sc->cur_chan->stopped = true;
248                 spin_unlock_bh(&sc->chan_lock);
249
250                 if (sc->next_chan == &sc->offchannel.chan) {
251                         getrawmonotonic(&ts);
252                         measure_time = true;
253                 }
254                 __ath9k_flush(sc->hw, ~0, true);
255
256                 if (ath_chanctx_send_ps_frame(sc, true))
257                         __ath9k_flush(sc->hw, BIT(IEEE80211_AC_VO), false);
258
259                 send_ps = true;
260                 spin_lock_bh(&sc->chan_lock);
261
262                 if (sc->cur_chan != &sc->offchannel.chan) {
263                         getrawmonotonic(&sc->cur_chan->tsf_ts);
264                         sc->cur_chan->tsf_val = ath9k_hw_gettsf64(sc->sc_ah);
265                 }
266         }
267         sc->cur_chan = sc->next_chan;
268         sc->cur_chan->stopped = false;
269         sc->next_chan = NULL;
270         sc->sched.offchannel_duration = 0;
271         if (sc->sched.state != ATH_CHANCTX_STATE_FORCE_ACTIVE)
272                 sc->sched.state = ATH_CHANCTX_STATE_IDLE;
273
274         spin_unlock_bh(&sc->chan_lock);
275
276         if (sc->sc_ah->chip_fullsleep ||
277             memcmp(&sc->cur_chandef, &sc->cur_chan->chandef,
278                    sizeof(sc->cur_chandef))) {
279                 ath_set_channel(sc);
280                 if (measure_time)
281                         sc->sched.channel_switch_time =
282                                 ath9k_hw_get_tsf_offset(&ts, NULL);
283         }
284         if (send_ps)
285                 ath_chanctx_send_ps_frame(sc, false);
286
287         ath_offchannel_channel_change(sc);
288         ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_SWITCH);
289 }
290
291 void ath_chanctx_work(struct work_struct *work)
292 {
293         struct ath_softc *sc = container_of(work, struct ath_softc,
294                                             chanctx_work);
295         mutex_lock(&sc->mutex);
296         ath_chanctx_set_next(sc, false);
297         mutex_unlock(&sc->mutex);
298 }
299
300 void ath_chanctx_init(struct ath_softc *sc)
301 {
302         struct ath_chanctx *ctx;
303         struct ath_common *common = ath9k_hw_common(sc->sc_ah);
304         struct ieee80211_supported_band *sband;
305         struct ieee80211_channel *chan;
306         int i, j;
307
308         sband = &common->sbands[IEEE80211_BAND_2GHZ];
309         if (!sband->n_channels)
310                 sband = &common->sbands[IEEE80211_BAND_5GHZ];
311
312         chan = &sband->channels[0];
313         for (i = 0; i < ATH9K_NUM_CHANCTX; i++) {
314                 ctx = &sc->chanctx[i];
315                 cfg80211_chandef_create(&ctx->chandef, chan, NL80211_CHAN_HT20);
316                 INIT_LIST_HEAD(&ctx->vifs);
317                 ctx->txpower = ATH_TXPOWER_MAX;
318                 for (j = 0; j < ARRAY_SIZE(ctx->acq); j++)
319                         INIT_LIST_HEAD(&ctx->acq[j]);
320         }
321         ctx = &sc->offchannel.chan;
322         cfg80211_chandef_create(&ctx->chandef, chan, NL80211_CHAN_HT20);
323         INIT_LIST_HEAD(&ctx->vifs);
324         ctx->txpower = ATH_TXPOWER_MAX;
325         for (j = 0; j < ARRAY_SIZE(ctx->acq); j++)
326                 INIT_LIST_HEAD(&ctx->acq[j]);
327         sc->offchannel.chan.offchannel = true;
328
329 }
330
331 void ath9k_chanctx_force_active(struct ieee80211_hw *hw,
332                                 struct ieee80211_vif *vif)
333 {
334         struct ath_softc *sc = hw->priv;
335         struct ath_common *common = ath9k_hw_common(sc->sc_ah);
336         struct ath_vif *avp = (struct ath_vif *) vif->drv_priv;
337         bool changed = false;
338
339         if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags))
340                 return;
341
342         if (!avp->chanctx)
343                 return;
344
345         mutex_lock(&sc->mutex);
346
347         spin_lock_bh(&sc->chan_lock);
348         if (sc->next_chan || (sc->cur_chan != avp->chanctx)) {
349                 sc->next_chan = avp->chanctx;
350                 changed = true;
351         }
352         sc->sched.state = ATH_CHANCTX_STATE_FORCE_ACTIVE;
353         spin_unlock_bh(&sc->chan_lock);
354
355         if (changed)
356                 ath_chanctx_set_next(sc, true);
357
358         mutex_unlock(&sc->mutex);
359 }
360
361 void ath_chanctx_switch(struct ath_softc *sc, struct ath_chanctx *ctx,
362                         struct cfg80211_chan_def *chandef)
363 {
364         struct ath_common *common = ath9k_hw_common(sc->sc_ah);
365
366         spin_lock_bh(&sc->chan_lock);
367
368         if (test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags) &&
369             (sc->cur_chan != ctx) && (ctx == &sc->offchannel.chan)) {
370                 sc->sched.offchannel_pending = true;
371                 spin_unlock_bh(&sc->chan_lock);
372                 return;
373         }
374
375         sc->next_chan = ctx;
376         if (chandef)
377                 ctx->chandef = *chandef;
378
379         if (sc->next_chan == &sc->offchannel.chan) {
380                 sc->sched.offchannel_duration =
381                         TU_TO_USEC(sc->offchannel.duration) +
382                         sc->sched.channel_switch_time;
383         }
384         spin_unlock_bh(&sc->chan_lock);
385         ieee80211_queue_work(sc->hw, &sc->chanctx_work);
386 }
387
388 void ath_chanctx_set_channel(struct ath_softc *sc, struct ath_chanctx *ctx,
389                              struct cfg80211_chan_def *chandef)
390 {
391         bool cur_chan;
392
393         spin_lock_bh(&sc->chan_lock);
394         if (chandef)
395                 memcpy(&ctx->chandef, chandef, sizeof(*chandef));
396         cur_chan = sc->cur_chan == ctx;
397         spin_unlock_bh(&sc->chan_lock);
398
399         if (!cur_chan)
400                 return;
401
402         ath_set_channel(sc);
403 }
404
405 struct ath_chanctx *ath_chanctx_get_oper_chan(struct ath_softc *sc, bool active)
406 {
407         struct ath_chanctx *ctx;
408
409         ath_for_each_chanctx(sc, ctx) {
410                 if (!ctx->assigned || list_empty(&ctx->vifs))
411                         continue;
412                 if (active && !ctx->active)
413                         continue;
414
415                 if (ctx->switch_after_beacon)
416                         return ctx;
417         }
418
419         return &sc->chanctx[0];
420 }
421
422 void ath_chanctx_offchan_switch(struct ath_softc *sc,
423                                 struct ieee80211_channel *chan)
424 {
425         struct cfg80211_chan_def chandef;
426
427         cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT);
428
429         ath_chanctx_switch(sc, &sc->offchannel.chan, &chandef);
430 }
431
432 static struct ath_chanctx *
433 ath_chanctx_get_next(struct ath_softc *sc, struct ath_chanctx *ctx)
434 {
435         int idx = ctx - &sc->chanctx[0];
436
437         return &sc->chanctx[!idx];
438 }
439
440 static void ath_chanctx_adjust_tbtt_delta(struct ath_softc *sc)
441 {
442         struct ath_chanctx *prev, *cur;
443         struct timespec ts;
444         u32 cur_tsf, prev_tsf, beacon_int;
445         s32 offset;
446
447         beacon_int = TU_TO_USEC(sc->cur_chan->beacon.beacon_interval);
448
449         cur = sc->cur_chan;
450         prev = ath_chanctx_get_next(sc, cur);
451
452         getrawmonotonic(&ts);
453         cur_tsf = (u32) cur->tsf_val +
454                   ath9k_hw_get_tsf_offset(&cur->tsf_ts, &ts);
455
456         prev_tsf = prev->last_beacon - (u32) prev->tsf_val + cur_tsf;
457         prev_tsf -= ath9k_hw_get_tsf_offset(&prev->tsf_ts, &ts);
458
459         /* Adjust the TSF time of the AP chanctx to keep its beacons
460          * at half beacon interval offset relative to the STA chanctx.
461          */
462         offset = cur_tsf - prev_tsf;
463
464         /* Ignore stale data or spurious timestamps */
465         if (offset < 0 || offset > 3 * beacon_int)
466                 return;
467
468         offset = beacon_int / 2 - (offset % beacon_int);
469         prev->tsf_val += offset;
470 }
471
472 void ath_chanctx_timer(unsigned long data)
473 {
474         struct ath_softc *sc = (struct ath_softc *) data;
475
476         ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_TSF_TIMER);
477 }
478
479 /* Configure the TSF based hardware timer for a channel switch.
480  * Also set up backup software timer, in case the gen timer fails.
481  * This could be caused by a hardware reset.
482  */
483 static void ath_chanctx_setup_timer(struct ath_softc *sc, u32 tsf_time)
484 {
485         struct ath_hw *ah = sc->sc_ah;
486
487         ath9k_hw_gen_timer_start(ah, sc->p2p_ps_timer, tsf_time, 1000000);
488         tsf_time -= ath9k_hw_gettsf32(ah);
489         tsf_time = msecs_to_jiffies(tsf_time / 1000) + 1;
490         mod_timer(&sc->sched.timer, tsf_time);
491 }
492
493 void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
494                        enum ath_chanctx_event ev)
495 {
496         struct ath_hw *ah = sc->sc_ah;
497         struct ath_common *common = ath9k_hw_common(ah);
498         struct ath_beacon_config *cur_conf;
499         struct ath_vif *avp = NULL;
500         struct ath_chanctx *ctx;
501         u32 tsf_time;
502         u32 beacon_int;
503         bool noa_changed = false;
504
505         if (vif)
506                 avp = (struct ath_vif *) vif->drv_priv;
507
508         spin_lock_bh(&sc->chan_lock);
509
510         switch (ev) {
511         case ATH_CHANCTX_EVENT_BEACON_PREPARE:
512                 if (avp->offchannel_duration)
513                         avp->offchannel_duration = 0;
514
515                 if (avp->chanctx != sc->cur_chan)
516                         break;
517
518                 if (sc->sched.offchannel_pending) {
519                         sc->sched.offchannel_pending = false;
520                         sc->next_chan = &sc->offchannel.chan;
521                         sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON;
522                 }
523
524                 ctx = ath_chanctx_get_next(sc, sc->cur_chan);
525                 if (ctx->active && sc->sched.state == ATH_CHANCTX_STATE_IDLE) {
526                         sc->next_chan = ctx;
527                         sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON;
528                 }
529
530                 /* if the timer missed its window, use the next interval */
531                 if (sc->sched.state == ATH_CHANCTX_STATE_WAIT_FOR_TIMER)
532                         sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON;
533
534                 if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON)
535                         break;
536
537                 sc->sched.beacon_pending = true;
538                 sc->sched.next_tbtt = REG_READ(ah, AR_NEXT_TBTT_TIMER);
539
540                 cur_conf = &sc->cur_chan->beacon;
541                 beacon_int = TU_TO_USEC(cur_conf->beacon_interval);
542
543                 /* defer channel switch by a quarter beacon interval */
544                 tsf_time = sc->sched.next_tbtt + beacon_int / 4;
545                 sc->sched.switch_start_time = tsf_time;
546                 sc->cur_chan->last_beacon = sc->sched.next_tbtt;
547
548                 /* Prevent wrap-around issues */
549                 if (avp->periodic_noa_duration &&
550                     tsf_time - avp->periodic_noa_start > BIT(30))
551                         avp->periodic_noa_duration = 0;
552
553                 if (ctx->active && !avp->periodic_noa_duration) {
554                         avp->periodic_noa_start = tsf_time;
555                         avp->periodic_noa_duration =
556                                 TU_TO_USEC(cur_conf->beacon_interval) / 2 -
557                                 sc->sched.channel_switch_time;
558                         noa_changed = true;
559                 } else if (!ctx->active && avp->periodic_noa_duration) {
560                         avp->periodic_noa_duration = 0;
561                         noa_changed = true;
562                 }
563
564                 /* If at least two consecutive beacons were missed on the STA
565                  * chanctx, stay on the STA channel for one extra beacon period,
566                  * to resync the timer properly.
567                  */
568                 if (ctx->active && sc->sched.beacon_miss >= 2)
569                         sc->sched.offchannel_duration = 3 * beacon_int / 2;
570
571                 if (sc->sched.offchannel_duration) {
572                         noa_changed = true;
573                         avp->offchannel_start = tsf_time;
574                         avp->offchannel_duration =
575                                 sc->sched.offchannel_duration;
576                 }
577
578                 if (noa_changed)
579                         avp->noa_index++;
580                 break;
581         case ATH_CHANCTX_EVENT_BEACON_SENT:
582                 if (!sc->sched.beacon_pending)
583                         break;
584
585                 sc->sched.beacon_pending = false;
586                 if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON)
587                         break;
588
589                 sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_TIMER;
590                 ath_chanctx_setup_timer(sc, sc->sched.switch_start_time);
591                 break;
592         case ATH_CHANCTX_EVENT_TSF_TIMER:
593                 if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_TIMER)
594                         break;
595
596                 if (!sc->cur_chan->switch_after_beacon &&
597                     sc->sched.beacon_pending)
598                         sc->sched.beacon_miss++;
599
600                 sc->sched.state = ATH_CHANCTX_STATE_SWITCH;
601                 ieee80211_queue_work(sc->hw, &sc->chanctx_work);
602                 break;
603         case ATH_CHANCTX_EVENT_BEACON_RECEIVED:
604                 if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags) ||
605                     sc->cur_chan == &sc->offchannel.chan)
606                         break;
607
608                 ath_chanctx_adjust_tbtt_delta(sc);
609                 sc->sched.beacon_pending = false;
610                 sc->sched.beacon_miss = 0;
611
612                 /* TSF time might have been updated by the incoming beacon,
613                  * need update the channel switch timer to reflect the change.
614                  */
615                 tsf_time = sc->sched.switch_start_time;
616                 tsf_time -= (u32) sc->cur_chan->tsf_val +
617                         ath9k_hw_get_tsf_offset(&sc->cur_chan->tsf_ts, NULL);
618                 tsf_time += ath9k_hw_gettsf32(ah);
619
620
621                 ath_chanctx_setup_timer(sc, tsf_time);
622                 break;
623         case ATH_CHANCTX_EVENT_ASSOC:
624                 if (sc->sched.state != ATH_CHANCTX_STATE_FORCE_ACTIVE ||
625                     avp->chanctx != sc->cur_chan)
626                         break;
627
628                 sc->sched.state = ATH_CHANCTX_STATE_IDLE;
629                 /* fall through */
630         case ATH_CHANCTX_EVENT_SWITCH:
631                 if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags) ||
632                     sc->sched.state == ATH_CHANCTX_STATE_FORCE_ACTIVE ||
633                     sc->cur_chan->switch_after_beacon ||
634                     sc->cur_chan == &sc->offchannel.chan)
635                         break;
636
637                 /* If this is a station chanctx, stay active for a half
638                  * beacon period (minus channel switch time)
639                  */
640                 sc->next_chan = ath_chanctx_get_next(sc, sc->cur_chan);
641                 cur_conf = &sc->cur_chan->beacon;
642
643                 sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_TIMER;
644
645                 tsf_time = TU_TO_USEC(cur_conf->beacon_interval) / 2;
646                 if (sc->sched.beacon_miss >= 2) {
647                         sc->sched.beacon_miss = 0;
648                         tsf_time *= 3;
649                 }
650
651                 tsf_time -= sc->sched.channel_switch_time;
652                 tsf_time += ath9k_hw_gettsf32(sc->sc_ah);
653                 sc->sched.switch_start_time = tsf_time;
654
655                 ath_chanctx_setup_timer(sc, tsf_time);
656                 sc->sched.beacon_pending = true;
657                 break;
658         case ATH_CHANCTX_EVENT_ENABLE_MULTICHANNEL:
659                 if (sc->cur_chan == &sc->offchannel.chan ||
660                     sc->cur_chan->switch_after_beacon)
661                         break;
662
663                 sc->next_chan = ath_chanctx_get_next(sc, sc->cur_chan);
664                 ieee80211_queue_work(sc->hw, &sc->chanctx_work);
665                 break;
666         case ATH_CHANCTX_EVENT_UNASSIGN:
667                 if (sc->cur_chan->assigned) {
668                         if (sc->next_chan && !sc->next_chan->assigned &&
669                             sc->next_chan != &sc->offchannel.chan)
670                                 sc->sched.state = ATH_CHANCTX_STATE_IDLE;
671                         break;
672                 }
673
674                 ctx = ath_chanctx_get_next(sc, sc->cur_chan);
675                 sc->sched.state = ATH_CHANCTX_STATE_IDLE;
676                 if (!ctx->assigned)
677                         break;
678
679                 sc->next_chan = ctx;
680                 ieee80211_queue_work(sc->hw, &sc->chanctx_work);
681                 break;
682         }
683
684         spin_unlock_bh(&sc->chan_lock);
685 }