Branch data Line data Source code
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 : 6 : static int ath_set_channel(struct ath_softc *sc)
24 : : {
25 : 6 : struct ath_hw *ah = sc->sc_ah;
26 : 6 : struct ath_common *common = ath9k_hw_common(ah);
27 : 6 : struct ieee80211_hw *hw = sc->hw;
28 : 6 : struct ath9k_channel *hchan;
29 : 6 : struct cfg80211_chan_def *chandef = &sc->cur_chan->chandef;
30 : 6 : struct ieee80211_channel *chan = chandef->chan;
31 : 6 : int pos = chan->hw_value;
32 : 6 : unsigned long flags;
33 : 6 : int old_pos = -1;
34 : 6 : int r;
35 : :
36 [ + - ]: 6 : if (test_bit(ATH_OP_INVALID, &common->op_flags))
37 : : return -EIO;
38 : :
39 [ + - ]: 6 : if (ah->curchan)
40 : 6 : old_pos = ah->curchan - &ah->channels[0];
41 : :
42 [ - + ]: 6 : ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n",
43 : : chan->center_freq, chandef->width);
44 : :
45 : : /* update survey stats for the old channel before switching */
46 : 6 : spin_lock_irqsave(&common->cc_lock, flags);
47 : 6 : ath_update_survey_stats(sc);
48 : 6 : spin_unlock_irqrestore(&common->cc_lock, flags);
49 : :
50 : 6 : ath9k_cmn_get_channel(hw, ah, chandef);
51 : :
52 : : /* If the operating channel changes, change the survey in-use flags
53 : : * along with it.
54 : : * Reset the survey data for the new channel, unless we're switching
55 : : * back to the operating channel from an off-channel operation.
56 : : */
57 [ + - + - ]: 6 : if (!sc->cur_chan->offchannel && sc->cur_survey != &sc->survey[pos]) {
58 [ - + ]: 6 : if (sc->cur_survey)
59 : 0 : sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE;
60 : :
61 : 6 : sc->cur_survey = &sc->survey[pos];
62 : :
63 : 6 : memset(sc->cur_survey, 0, sizeof(struct survey_info));
64 : 6 : sc->cur_survey->filled |= SURVEY_INFO_IN_USE;
65 [ # # ]: 0 : } else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) {
66 : 0 : memset(&sc->survey[pos], 0, sizeof(struct survey_info));
67 : : }
68 : :
69 : 6 : hchan = &sc->sc_ah->channels[pos];
70 : 6 : r = ath_reset(sc, hchan);
71 [ + - ]: 6 : if (r)
72 : : return r;
73 : :
74 : : /* The most recent snapshot of channel->noisefloor for the old
75 : : * channel is only available after the hardware reset. Copy it to
76 : : * the survey stats now.
77 : : */
78 [ + - ]: 6 : if (old_pos >= 0)
79 : 6 : ath_update_survey_nf(sc, old_pos);
80 : :
81 : : /* Enable radar pulse detection if on a DFS channel. Spectral
82 : : * scanning and radar detection can not be used concurrently.
83 : : */
84 [ - + ]: 6 : if (hw->conf.radar_enabled) {
85 : 0 : u32 rxfilter;
86 : :
87 : 0 : rxfilter = ath9k_hw_getrxfilter(ah);
88 : 0 : rxfilter |= ATH9K_RX_FILTER_PHYRADAR |
89 : : ATH9K_RX_FILTER_PHYERR;
90 : 0 : ath9k_hw_setrxfilter(ah, rxfilter);
91 [ # # ]: 0 : ath_dbg(common, DFS, "DFS enabled at freq %d\n",
92 : : chan->center_freq);
93 : : } else {
94 : : /* perform spectral scan if requested. */
95 [ - + ]: 6 : if (test_bit(ATH_OP_SCANNING, &common->op_flags) &&
96 [ # # ]: 0 : sc->spec_priv.spectral_mode == SPECTRAL_CHANSCAN)
97 : 0 : ath9k_cmn_spectral_scan_trigger(common, &sc->spec_priv);
98 : : }
99 : :
100 : : return 0;
101 : : }
102 : :
103 : 6 : void ath_chanctx_init(struct ath_softc *sc)
104 : : {
105 : 6 : struct ath_chanctx *ctx;
106 [ - + ]: 6 : struct ath_common *common = ath9k_hw_common(sc->sc_ah);
107 : 6 : struct ieee80211_supported_band *sband;
108 : 6 : struct ieee80211_channel *chan;
109 : 6 : int i, j;
110 : :
111 : 6 : sband = &common->sbands[NL80211_BAND_2GHZ];
112 [ - + ]: 6 : if (!sband->n_channels)
113 : 0 : sband = &common->sbands[NL80211_BAND_5GHZ];
114 : :
115 : 6 : chan = &sband->channels[0];
116 [ + + ]: 18 : for (i = 0; i < ATH9K_NUM_CHANCTX; i++) {
117 : 12 : ctx = &sc->chanctx[i];
118 : 12 : cfg80211_chandef_create(&ctx->chandef, chan, NL80211_CHAN_HT20);
119 : 12 : INIT_LIST_HEAD(&ctx->vifs);
120 : 12 : ctx->txpower = ATH_TXPOWER_MAX;
121 : 12 : ctx->flush_timeout = HZ / 5; /* 200ms */
122 [ + + ]: 60 : for (j = 0; j < ARRAY_SIZE(ctx->acq); j++) {
123 : 48 : INIT_LIST_HEAD(&ctx->acq[j].acq_new);
124 : 48 : INIT_LIST_HEAD(&ctx->acq[j].acq_old);
125 : 48 : spin_lock_init(&ctx->acq[j].lock);
126 : : }
127 : : }
128 : 6 : }
129 : :
130 : 6 : void ath_chanctx_set_channel(struct ath_softc *sc, struct ath_chanctx *ctx,
131 : : struct cfg80211_chan_def *chandef)
132 : : {
133 : 6 : struct ath_common *common = ath9k_hw_common(sc->sc_ah);
134 : 6 : bool cur_chan;
135 : :
136 : 6 : spin_lock_bh(&sc->chan_lock);
137 [ + - ]: 6 : if (chandef)
138 : 6 : memcpy(&ctx->chandef, chandef, sizeof(*chandef));
139 : 6 : cur_chan = sc->cur_chan == ctx;
140 : 6 : spin_unlock_bh(&sc->chan_lock);
141 : :
142 [ - + ]: 6 : if (!cur_chan) {
143 [ # # ]: 0 : ath_dbg(common, CHAN_CTX,
144 : : "Current context differs from the new context\n");
145 : 0 : return;
146 : : }
147 : :
148 : 6 : ath_set_channel(sc);
149 : : }
150 : :
151 : : #ifdef CONFIG_ATH9K_CHANNEL_CONTEXT
152 : :
153 : : /*************/
154 : : /* Utilities */
155 : : /*************/
156 : :
157 : : struct ath_chanctx* ath_is_go_chanctx_present(struct ath_softc *sc)
158 : : {
159 : : struct ath_chanctx *ctx;
160 : : struct ath_vif *avp;
161 : : struct ieee80211_vif *vif;
162 : :
163 : : spin_lock_bh(&sc->chan_lock);
164 : :
165 : : ath_for_each_chanctx(sc, ctx) {
166 : : if (!ctx->active)
167 : : continue;
168 : :
169 : : list_for_each_entry(avp, &ctx->vifs, list) {
170 : : vif = avp->vif;
171 : :
172 : : if (ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_P2P_GO) {
173 : : spin_unlock_bh(&sc->chan_lock);
174 : : return ctx;
175 : : }
176 : : }
177 : : }
178 : :
179 : : spin_unlock_bh(&sc->chan_lock);
180 : : return NULL;
181 : : }
182 : :
183 : : /**********************************************************/
184 : : /* Functions to handle the channel context state machine. */
185 : : /**********************************************************/
186 : :
187 : : static const char *offchannel_state_string(enum ath_offchannel_state state)
188 : : {
189 : : switch (state) {
190 : : case_rtn_string(ATH_OFFCHANNEL_IDLE);
191 : : case_rtn_string(ATH_OFFCHANNEL_PROBE_SEND);
192 : : case_rtn_string(ATH_OFFCHANNEL_PROBE_WAIT);
193 : : case_rtn_string(ATH_OFFCHANNEL_SUSPEND);
194 : : case_rtn_string(ATH_OFFCHANNEL_ROC_START);
195 : : case_rtn_string(ATH_OFFCHANNEL_ROC_WAIT);
196 : : case_rtn_string(ATH_OFFCHANNEL_ROC_DONE);
197 : : default:
198 : : return "unknown";
199 : : }
200 : : }
201 : :
202 : : static const char *chanctx_event_string(enum ath_chanctx_event ev)
203 : : {
204 : : switch (ev) {
205 : : case_rtn_string(ATH_CHANCTX_EVENT_BEACON_PREPARE);
206 : : case_rtn_string(ATH_CHANCTX_EVENT_BEACON_SENT);
207 : : case_rtn_string(ATH_CHANCTX_EVENT_TSF_TIMER);
208 : : case_rtn_string(ATH_CHANCTX_EVENT_BEACON_RECEIVED);
209 : : case_rtn_string(ATH_CHANCTX_EVENT_AUTHORIZED);
210 : : case_rtn_string(ATH_CHANCTX_EVENT_SWITCH);
211 : : case_rtn_string(ATH_CHANCTX_EVENT_ASSIGN);
212 : : case_rtn_string(ATH_CHANCTX_EVENT_UNASSIGN);
213 : : case_rtn_string(ATH_CHANCTX_EVENT_CHANGE);
214 : : case_rtn_string(ATH_CHANCTX_EVENT_ENABLE_MULTICHANNEL);
215 : : default:
216 : : return "unknown";
217 : : }
218 : : }
219 : :
220 : : static const char *chanctx_state_string(enum ath_chanctx_state state)
221 : : {
222 : : switch (state) {
223 : : case_rtn_string(ATH_CHANCTX_STATE_IDLE);
224 : : case_rtn_string(ATH_CHANCTX_STATE_WAIT_FOR_BEACON);
225 : : case_rtn_string(ATH_CHANCTX_STATE_WAIT_FOR_TIMER);
226 : : case_rtn_string(ATH_CHANCTX_STATE_SWITCH);
227 : : case_rtn_string(ATH_CHANCTX_STATE_FORCE_ACTIVE);
228 : : default:
229 : : return "unknown";
230 : : }
231 : : }
232 : :
233 : : static u32 chanctx_event_delta(struct ath_softc *sc)
234 : : {
235 : : u64 ms;
236 : : struct timespec64 ts, *old;
237 : :
238 : : ktime_get_raw_ts64(&ts);
239 : : old = &sc->last_event_time;
240 : : ms = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
241 : : ms -= old->tv_sec * 1000 + old->tv_nsec / 1000000;
242 : : sc->last_event_time = ts;
243 : :
244 : : return (u32)ms;
245 : : }
246 : :
247 : : void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx)
248 : : {
249 : : struct ath_common *common = ath9k_hw_common(sc->sc_ah);
250 : : struct ath_chanctx *ictx;
251 : : struct ath_vif *avp;
252 : : bool active = false;
253 : : u8 n_active = 0;
254 : :
255 : : if (!ctx)
256 : : return;
257 : :
258 : : if (ctx == &sc->offchannel.chan) {
259 : : spin_lock_bh(&sc->chan_lock);
260 : :
261 : : if (likely(sc->sched.channel_switch_time))
262 : : ctx->flush_timeout =
263 : : usecs_to_jiffies(sc->sched.channel_switch_time);
264 : : else
265 : : ctx->flush_timeout =
266 : : msecs_to_jiffies(10);
267 : :
268 : : spin_unlock_bh(&sc->chan_lock);
269 : :
270 : : /*
271 : : * There is no need to iterate over the
272 : : * active/assigned channel contexts if
273 : : * the current context is offchannel.
274 : : */
275 : : return;
276 : : }
277 : :
278 : : ictx = ctx;
279 : :
280 : : list_for_each_entry(avp, &ctx->vifs, list) {
281 : : struct ieee80211_vif *vif = avp->vif;
282 : :
283 : : switch (vif->type) {
284 : : case NL80211_IFTYPE_P2P_CLIENT:
285 : : case NL80211_IFTYPE_STATION:
286 : : if (avp->assoc)
287 : : active = true;
288 : : break;
289 : : default:
290 : : active = true;
291 : : break;
292 : : }
293 : : }
294 : : ctx->active = active;
295 : :
296 : : ath_for_each_chanctx(sc, ctx) {
297 : : if (!ctx->assigned || list_empty(&ctx->vifs))
298 : : continue;
299 : : n_active++;
300 : : }
301 : :
302 : : spin_lock_bh(&sc->chan_lock);
303 : :
304 : : if (n_active <= 1) {
305 : : ictx->flush_timeout = HZ / 5;
306 : : clear_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags);
307 : : spin_unlock_bh(&sc->chan_lock);
308 : : return;
309 : : }
310 : :
311 : : ictx->flush_timeout = usecs_to_jiffies(sc->sched.channel_switch_time);
312 : :
313 : : if (test_and_set_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags)) {
314 : : spin_unlock_bh(&sc->chan_lock);
315 : : return;
316 : : }
317 : :
318 : : spin_unlock_bh(&sc->chan_lock);
319 : :
320 : : if (ath9k_is_chanctx_enabled()) {
321 : : ath_chanctx_event(sc, NULL,
322 : : ATH_CHANCTX_EVENT_ENABLE_MULTICHANNEL);
323 : : }
324 : : }
325 : :
326 : : static struct ath_chanctx *
327 : : ath_chanctx_get_next(struct ath_softc *sc, struct ath_chanctx *ctx)
328 : : {
329 : : int idx = ctx - &sc->chanctx[0];
330 : :
331 : : return &sc->chanctx[!idx];
332 : : }
333 : :
334 : : static void ath_chanctx_adjust_tbtt_delta(struct ath_softc *sc)
335 : : {
336 : : struct ath_chanctx *prev, *cur;
337 : : struct timespec64 ts;
338 : : u32 cur_tsf, prev_tsf, beacon_int;
339 : : s32 offset;
340 : :
341 : : beacon_int = TU_TO_USEC(sc->cur_chan->beacon.beacon_interval);
342 : :
343 : : cur = sc->cur_chan;
344 : : prev = ath_chanctx_get_next(sc, cur);
345 : :
346 : : if (!prev->switch_after_beacon)
347 : : return;
348 : :
349 : : ktime_get_raw_ts64(&ts);
350 : : cur_tsf = (u32) cur->tsf_val +
351 : : ath9k_hw_get_tsf_offset(&cur->tsf_ts, &ts);
352 : :
353 : : prev_tsf = prev->last_beacon - (u32) prev->tsf_val + cur_tsf;
354 : : prev_tsf -= ath9k_hw_get_tsf_offset(&prev->tsf_ts, &ts);
355 : :
356 : : /* Adjust the TSF time of the AP chanctx to keep its beacons
357 : : * at half beacon interval offset relative to the STA chanctx.
358 : : */
359 : : offset = cur_tsf - prev_tsf;
360 : :
361 : : /* Ignore stale data or spurious timestamps */
362 : : if (offset < 0 || offset > 3 * beacon_int)
363 : : return;
364 : :
365 : : offset = beacon_int / 2 - (offset % beacon_int);
366 : : prev->tsf_val += offset;
367 : : }
368 : :
369 : : /* Configure the TSF based hardware timer for a channel switch.
370 : : * Also set up backup software timer, in case the gen timer fails.
371 : : * This could be caused by a hardware reset.
372 : : */
373 : : static void ath_chanctx_setup_timer(struct ath_softc *sc, u32 tsf_time)
374 : : {
375 : : struct ath_common *common = ath9k_hw_common(sc->sc_ah);
376 : : struct ath_hw *ah = sc->sc_ah;
377 : : unsigned long timeout;
378 : :
379 : : ath9k_hw_gen_timer_start(ah, sc->p2p_ps_timer, tsf_time, 1000000);
380 : : tsf_time -= ath9k_hw_gettsf32(ah);
381 : : timeout = msecs_to_jiffies(tsf_time / 1000) + 1;
382 : : mod_timer(&sc->sched.timer, jiffies + timeout);
383 : :
384 : : ath_dbg(common, CHAN_CTX,
385 : : "Setup chanctx timer with timeout: %d (%d) ms\n",
386 : : tsf_time / 1000, jiffies_to_msecs(timeout));
387 : : }
388 : :
389 : : static void ath_chanctx_handle_bmiss(struct ath_softc *sc,
390 : : struct ath_chanctx *ctx,
391 : : struct ath_vif *avp)
392 : : {
393 : : /*
394 : : * Clear the extend_absence flag if it had been
395 : : * set during the previous beacon transmission,
396 : : * since we need to revert to the normal NoA
397 : : * schedule.
398 : : */
399 : : if (ctx->active && sc->sched.extend_absence) {
400 : : avp->noa_duration = 0;
401 : : sc->sched.extend_absence = false;
402 : : }
403 : :
404 : : /* If at least two consecutive beacons were missed on the STA
405 : : * chanctx, stay on the STA channel for one extra beacon period,
406 : : * to resync the timer properly.
407 : : */
408 : : if (ctx->active && sc->sched.beacon_miss >= 2) {
409 : : avp->noa_duration = 0;
410 : : sc->sched.extend_absence = true;
411 : : }
412 : : }
413 : :
414 : : static void ath_chanctx_offchannel_noa(struct ath_softc *sc,
415 : : struct ath_chanctx *ctx,
416 : : struct ath_vif *avp,
417 : : u32 tsf_time)
418 : : {
419 : : struct ath_common *common = ath9k_hw_common(sc->sc_ah);
420 : :
421 : : avp->noa_index++;
422 : : avp->offchannel_start = tsf_time;
423 : : avp->offchannel_duration = sc->sched.offchannel_duration;
424 : :
425 : : ath_dbg(common, CHAN_CTX,
426 : : "offchannel noa_duration: %d, noa_start: %u, noa_index: %d\n",
427 : : avp->offchannel_duration,
428 : : avp->offchannel_start,
429 : : avp->noa_index);
430 : :
431 : : /*
432 : : * When multiple contexts are active, the NoA
433 : : * has to be recalculated and advertised after
434 : : * an offchannel operation.
435 : : */
436 : : if (ctx->active && avp->noa_duration)
437 : : avp->noa_duration = 0;
438 : : }
439 : :
440 : : static void ath_chanctx_set_periodic_noa(struct ath_softc *sc,
441 : : struct ath_vif *avp,
442 : : struct ath_beacon_config *cur_conf,
443 : : u32 tsf_time,
444 : : u32 beacon_int)
445 : : {
446 : : struct ath_common *common = ath9k_hw_common(sc->sc_ah);
447 : :
448 : : avp->noa_index++;
449 : : avp->noa_start = tsf_time;
450 : :
451 : : if (sc->sched.extend_absence)
452 : : avp->noa_duration = (3 * beacon_int / 2) +
453 : : sc->sched.channel_switch_time;
454 : : else
455 : : avp->noa_duration =
456 : : TU_TO_USEC(cur_conf->beacon_interval) / 2 +
457 : : sc->sched.channel_switch_time;
458 : :
459 : : if (test_bit(ATH_OP_SCANNING, &common->op_flags) ||
460 : : sc->sched.extend_absence)
461 : : avp->periodic_noa = false;
462 : : else
463 : : avp->periodic_noa = true;
464 : :
465 : : ath_dbg(common, CHAN_CTX,
466 : : "noa_duration: %d, noa_start: %u, noa_index: %d, periodic: %d\n",
467 : : avp->noa_duration,
468 : : avp->noa_start,
469 : : avp->noa_index,
470 : : avp->periodic_noa);
471 : : }
472 : :
473 : : static void ath_chanctx_set_oneshot_noa(struct ath_softc *sc,
474 : : struct ath_vif *avp,
475 : : u32 tsf_time,
476 : : u32 duration)
477 : : {
478 : : struct ath_common *common = ath9k_hw_common(sc->sc_ah);
479 : :
480 : : avp->noa_index++;
481 : : avp->noa_start = tsf_time;
482 : : avp->periodic_noa = false;
483 : : avp->oneshot_noa = true;
484 : : avp->noa_duration = duration + sc->sched.channel_switch_time;
485 : :
486 : : ath_dbg(common, CHAN_CTX,
487 : : "oneshot noa_duration: %d, noa_start: %u, noa_index: %d, periodic: %d\n",
488 : : avp->noa_duration,
489 : : avp->noa_start,
490 : : avp->noa_index,
491 : : avp->periodic_noa);
492 : : }
493 : :
494 : : void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
495 : : enum ath_chanctx_event ev)
496 : : {
497 : : struct ath_hw *ah = sc->sc_ah;
498 : : struct ath_common *common = ath9k_hw_common(ah);
499 : : struct ath_beacon_config *cur_conf;
500 : : struct ath_vif *avp = NULL;
501 : : struct ath_chanctx *ctx;
502 : : u32 tsf_time;
503 : : u32 beacon_int;
504 : :
505 : : if (vif)
506 : : avp = (struct ath_vif *) vif->drv_priv;
507 : :
508 : : spin_lock_bh(&sc->chan_lock);
509 : :
510 : : ath_dbg(common, CHAN_CTX, "cur_chan: %d MHz, event: %s, state: %s, delta: %u ms\n",
511 : : sc->cur_chan->chandef.center_freq1,
512 : : chanctx_event_string(ev),
513 : : chanctx_state_string(sc->sched.state),
514 : : chanctx_event_delta(sc));
515 : :
516 : : switch (ev) {
517 : : case ATH_CHANCTX_EVENT_BEACON_PREPARE:
518 : : if (avp->offchannel_duration)
519 : : avp->offchannel_duration = 0;
520 : :
521 : : if (avp->oneshot_noa) {
522 : : avp->noa_duration = 0;
523 : : avp->oneshot_noa = false;
524 : :
525 : : ath_dbg(common, CHAN_CTX,
526 : : "Clearing oneshot NoA\n");
527 : : }
528 : :
529 : : if (avp->chanctx != sc->cur_chan) {
530 : : ath_dbg(common, CHAN_CTX,
531 : : "Contexts differ, not preparing beacon\n");
532 : : break;
533 : : }
534 : :
535 : : if (sc->sched.offchannel_pending && !sc->sched.wait_switch) {
536 : : sc->sched.offchannel_pending = false;
537 : : sc->next_chan = &sc->offchannel.chan;
538 : : sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON;
539 : : ath_dbg(common, CHAN_CTX,
540 : : "Setting offchannel_pending to false\n");
541 : : }
542 : :
543 : : ctx = ath_chanctx_get_next(sc, sc->cur_chan);
544 : : if (ctx->active && sc->sched.state == ATH_CHANCTX_STATE_IDLE) {
545 : : sc->next_chan = ctx;
546 : : sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON;
547 : : ath_dbg(common, CHAN_CTX,
548 : : "Set next context, move chanctx state to WAIT_FOR_BEACON\n");
549 : : }
550 : :
551 : : /* if the timer missed its window, use the next interval */
552 : : if (sc->sched.state == ATH_CHANCTX_STATE_WAIT_FOR_TIMER) {
553 : : sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON;
554 : : ath_dbg(common, CHAN_CTX,
555 : : "Move chanctx state from WAIT_FOR_TIMER to WAIT_FOR_BEACON\n");
556 : : }
557 : :
558 : : if (sc->sched.mgd_prepare_tx)
559 : : sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON;
560 : :
561 : : /*
562 : : * When a context becomes inactive, for example,
563 : : * disassociation of a station context, the NoA
564 : : * attribute needs to be removed from subsequent
565 : : * beacons.
566 : : */
567 : : if (!ctx->active && avp->noa_duration &&
568 : : sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON) {
569 : : avp->noa_duration = 0;
570 : : avp->periodic_noa = false;
571 : :
572 : : ath_dbg(common, CHAN_CTX,
573 : : "Clearing NoA schedule\n");
574 : : }
575 : :
576 : : if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON)
577 : : break;
578 : :
579 : : ath_dbg(common, CHAN_CTX, "Preparing beacon for vif: %pM\n", vif->addr);
580 : :
581 : : sc->sched.beacon_pending = true;
582 : : sc->sched.next_tbtt = REG_READ(ah, AR_NEXT_TBTT_TIMER);
583 : :
584 : : cur_conf = &sc->cur_chan->beacon;
585 : : beacon_int = TU_TO_USEC(cur_conf->beacon_interval);
586 : :
587 : : /* defer channel switch by a quarter beacon interval */
588 : : tsf_time = sc->sched.next_tbtt + beacon_int / 4;
589 : : sc->sched.switch_start_time = tsf_time;
590 : : sc->cur_chan->last_beacon = sc->sched.next_tbtt;
591 : :
592 : : /*
593 : : * If an offchannel switch is scheduled to happen after
594 : : * a beacon transmission, update the NoA with one-shot
595 : : * values and increment the index.
596 : : */
597 : : if (sc->next_chan == &sc->offchannel.chan) {
598 : : ath_chanctx_offchannel_noa(sc, ctx, avp, tsf_time);
599 : : break;
600 : : }
601 : :
602 : : ath_chanctx_handle_bmiss(sc, ctx, avp);
603 : :
604 : : /*
605 : : * If a mgd_prepare_tx() has been called by mac80211,
606 : : * a one-shot NoA needs to be sent. This can happen
607 : : * with one or more active channel contexts - in both
608 : : * cases, a new NoA schedule has to be advertised.
609 : : */
610 : : if (sc->sched.mgd_prepare_tx) {
611 : : ath_chanctx_set_oneshot_noa(sc, avp, tsf_time,
612 : : jiffies_to_usecs(HZ / 5));
613 : : break;
614 : : }
615 : :
616 : : /* Prevent wrap-around issues */
617 : : if (avp->noa_duration && tsf_time - avp->noa_start > BIT(30))
618 : : avp->noa_duration = 0;
619 : :
620 : : /*
621 : : * If multiple contexts are active, start periodic
622 : : * NoA and increment the index for the first
623 : : * announcement.
624 : : */
625 : : if (ctx->active &&
626 : : (!avp->noa_duration || sc->sched.force_noa_update))
627 : : ath_chanctx_set_periodic_noa(sc, avp, cur_conf,
628 : : tsf_time, beacon_int);
629 : :
630 : : if (ctx->active && sc->sched.force_noa_update)
631 : : sc->sched.force_noa_update = false;
632 : :
633 : : break;
634 : : case ATH_CHANCTX_EVENT_BEACON_SENT:
635 : : if (!sc->sched.beacon_pending) {
636 : : ath_dbg(common, CHAN_CTX,
637 : : "No pending beacon\n");
638 : : break;
639 : : }
640 : :
641 : : sc->sched.beacon_pending = false;
642 : :
643 : : if (sc->sched.mgd_prepare_tx) {
644 : : sc->sched.mgd_prepare_tx = false;
645 : : complete(&sc->go_beacon);
646 : : ath_dbg(common, CHAN_CTX,
647 : : "Beacon sent, complete go_beacon\n");
648 : : break;
649 : : }
650 : :
651 : : if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON)
652 : : break;
653 : :
654 : : ath_dbg(common, CHAN_CTX,
655 : : "Move chanctx state to WAIT_FOR_TIMER\n");
656 : :
657 : : sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_TIMER;
658 : : ath_chanctx_setup_timer(sc, sc->sched.switch_start_time);
659 : : break;
660 : : case ATH_CHANCTX_EVENT_TSF_TIMER:
661 : : if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_TIMER)
662 : : break;
663 : :
664 : : if (!sc->cur_chan->switch_after_beacon &&
665 : : sc->sched.beacon_pending)
666 : : sc->sched.beacon_miss++;
667 : :
668 : : ath_dbg(common, CHAN_CTX,
669 : : "Move chanctx state to SWITCH\n");
670 : :
671 : : sc->sched.state = ATH_CHANCTX_STATE_SWITCH;
672 : : ieee80211_queue_work(sc->hw, &sc->chanctx_work);
673 : : break;
674 : : case ATH_CHANCTX_EVENT_BEACON_RECEIVED:
675 : : if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags) ||
676 : : sc->cur_chan == &sc->offchannel.chan)
677 : : break;
678 : :
679 : : sc->sched.beacon_pending = false;
680 : : sc->sched.beacon_miss = 0;
681 : :
682 : : if (sc->sched.state == ATH_CHANCTX_STATE_FORCE_ACTIVE ||
683 : : !sc->sched.beacon_adjust ||
684 : : !sc->cur_chan->tsf_val)
685 : : break;
686 : :
687 : : ath_chanctx_adjust_tbtt_delta(sc);
688 : :
689 : : /* TSF time might have been updated by the incoming beacon,
690 : : * need update the channel switch timer to reflect the change.
691 : : */
692 : : tsf_time = sc->sched.switch_start_time;
693 : : tsf_time -= (u32) sc->cur_chan->tsf_val +
694 : : ath9k_hw_get_tsf_offset(&sc->cur_chan->tsf_ts, NULL);
695 : : tsf_time += ath9k_hw_gettsf32(ah);
696 : :
697 : : sc->sched.beacon_adjust = false;
698 : : ath_chanctx_setup_timer(sc, tsf_time);
699 : : break;
700 : : case ATH_CHANCTX_EVENT_AUTHORIZED:
701 : : if (sc->sched.state != ATH_CHANCTX_STATE_FORCE_ACTIVE ||
702 : : avp->chanctx != sc->cur_chan)
703 : : break;
704 : :
705 : : ath_dbg(common, CHAN_CTX,
706 : : "Move chanctx state from FORCE_ACTIVE to IDLE\n");
707 : :
708 : : sc->sched.state = ATH_CHANCTX_STATE_IDLE;
709 : : /* fall through */
710 : : case ATH_CHANCTX_EVENT_SWITCH:
711 : : if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags) ||
712 : : sc->sched.state == ATH_CHANCTX_STATE_FORCE_ACTIVE ||
713 : : sc->cur_chan->switch_after_beacon ||
714 : : sc->cur_chan == &sc->offchannel.chan)
715 : : break;
716 : :
717 : : /* If this is a station chanctx, stay active for a half
718 : : * beacon period (minus channel switch time)
719 : : */
720 : : sc->next_chan = ath_chanctx_get_next(sc, sc->cur_chan);
721 : : cur_conf = &sc->cur_chan->beacon;
722 : :
723 : : ath_dbg(common, CHAN_CTX,
724 : : "Move chanctx state to WAIT_FOR_TIMER (event SWITCH)\n");
725 : :
726 : : sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_TIMER;
727 : : sc->sched.wait_switch = false;
728 : :
729 : : tsf_time = TU_TO_USEC(cur_conf->beacon_interval) / 2;
730 : :
731 : : if (sc->sched.extend_absence) {
732 : : sc->sched.beacon_miss = 0;
733 : : tsf_time *= 3;
734 : : }
735 : :
736 : : tsf_time -= sc->sched.channel_switch_time;
737 : : tsf_time += ath9k_hw_gettsf32(sc->sc_ah);
738 : : sc->sched.switch_start_time = tsf_time;
739 : :
740 : : ath_chanctx_setup_timer(sc, tsf_time);
741 : : sc->sched.beacon_pending = true;
742 : : sc->sched.beacon_adjust = true;
743 : : break;
744 : : case ATH_CHANCTX_EVENT_ENABLE_MULTICHANNEL:
745 : : if (sc->cur_chan == &sc->offchannel.chan ||
746 : : sc->cur_chan->switch_after_beacon)
747 : : break;
748 : :
749 : : sc->next_chan = ath_chanctx_get_next(sc, sc->cur_chan);
750 : : ieee80211_queue_work(sc->hw, &sc->chanctx_work);
751 : : break;
752 : : case ATH_CHANCTX_EVENT_UNASSIGN:
753 : : if (sc->cur_chan->assigned) {
754 : : if (sc->next_chan && !sc->next_chan->assigned &&
755 : : sc->next_chan != &sc->offchannel.chan)
756 : : sc->sched.state = ATH_CHANCTX_STATE_IDLE;
757 : : break;
758 : : }
759 : :
760 : : ctx = ath_chanctx_get_next(sc, sc->cur_chan);
761 : : sc->sched.state = ATH_CHANCTX_STATE_IDLE;
762 : : if (!ctx->assigned)
763 : : break;
764 : :
765 : : sc->next_chan = ctx;
766 : : ieee80211_queue_work(sc->hw, &sc->chanctx_work);
767 : : break;
768 : : case ATH_CHANCTX_EVENT_ASSIGN:
769 : : break;
770 : : case ATH_CHANCTX_EVENT_CHANGE:
771 : : break;
772 : : }
773 : :
774 : : spin_unlock_bh(&sc->chan_lock);
775 : : }
776 : :
777 : : void ath_chanctx_beacon_sent_ev(struct ath_softc *sc,
778 : : enum ath_chanctx_event ev)
779 : : {
780 : : if (sc->sched.beacon_pending)
781 : : ath_chanctx_event(sc, NULL, ev);
782 : : }
783 : :
784 : : void ath_chanctx_beacon_recv_ev(struct ath_softc *sc,
785 : : enum ath_chanctx_event ev)
786 : : {
787 : : ath_chanctx_event(sc, NULL, ev);
788 : : }
789 : :
790 : : static int ath_scan_channel_duration(struct ath_softc *sc,
791 : : struct ieee80211_channel *chan)
792 : : {
793 : : struct cfg80211_scan_request *req = sc->offchannel.scan_req;
794 : :
795 : : if (!req->n_ssids || (chan->flags & IEEE80211_CHAN_NO_IR))
796 : : return (HZ / 9); /* ~110 ms */
797 : :
798 : : return (HZ / 16); /* ~60 ms */
799 : : }
800 : :
801 : : static void ath_chanctx_switch(struct ath_softc *sc, struct ath_chanctx *ctx,
802 : : struct cfg80211_chan_def *chandef)
803 : : {
804 : : struct ath_common *common = ath9k_hw_common(sc->sc_ah);
805 : :
806 : : spin_lock_bh(&sc->chan_lock);
807 : :
808 : : if (test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags) &&
809 : : (sc->cur_chan != ctx) && (ctx == &sc->offchannel.chan)) {
810 : : if (chandef)
811 : : ctx->chandef = *chandef;
812 : :
813 : : sc->sched.offchannel_pending = true;
814 : : sc->sched.wait_switch = true;
815 : : sc->sched.offchannel_duration =
816 : : jiffies_to_usecs(sc->offchannel.duration) +
817 : : sc->sched.channel_switch_time;
818 : :
819 : : spin_unlock_bh(&sc->chan_lock);
820 : : ath_dbg(common, CHAN_CTX,
821 : : "Set offchannel_pending to true\n");
822 : : return;
823 : : }
824 : :
825 : : sc->next_chan = ctx;
826 : : if (chandef) {
827 : : ctx->chandef = *chandef;
828 : : ath_dbg(common, CHAN_CTX,
829 : : "Assigned next_chan to %d MHz\n", chandef->center_freq1);
830 : : }
831 : :
832 : : if (sc->next_chan == &sc->offchannel.chan) {
833 : : sc->sched.offchannel_duration =
834 : : jiffies_to_usecs(sc->offchannel.duration) +
835 : : sc->sched.channel_switch_time;
836 : :
837 : : if (chandef) {
838 : : ath_dbg(common, CHAN_CTX,
839 : : "Offchannel duration for chan %d MHz : %u\n",
840 : : chandef->center_freq1,
841 : : sc->sched.offchannel_duration);
842 : : }
843 : : }
844 : : spin_unlock_bh(&sc->chan_lock);
845 : : ieee80211_queue_work(sc->hw, &sc->chanctx_work);
846 : : }
847 : :
848 : : static void ath_chanctx_offchan_switch(struct ath_softc *sc,
849 : : struct ieee80211_channel *chan)
850 : : {
851 : : struct ath_common *common = ath9k_hw_common(sc->sc_ah);
852 : : struct cfg80211_chan_def chandef;
853 : :
854 : : cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT);
855 : : ath_dbg(common, CHAN_CTX,
856 : : "Channel definition created: %d MHz\n", chandef.center_freq1);
857 : :
858 : : ath_chanctx_switch(sc, &sc->offchannel.chan, &chandef);
859 : : }
860 : :
861 : : static struct ath_chanctx *ath_chanctx_get_oper_chan(struct ath_softc *sc,
862 : : bool active)
863 : : {
864 : : struct ath_chanctx *ctx;
865 : :
866 : : ath_for_each_chanctx(sc, ctx) {
867 : : if (!ctx->assigned || list_empty(&ctx->vifs))
868 : : continue;
869 : : if (active && !ctx->active)
870 : : continue;
871 : :
872 : : if (ctx->switch_after_beacon)
873 : : return ctx;
874 : : }
875 : :
876 : : return &sc->chanctx[0];
877 : : }
878 : :
879 : : static void
880 : : ath_scan_next_channel(struct ath_softc *sc)
881 : : {
882 : : struct ath_common *common = ath9k_hw_common(sc->sc_ah);
883 : : struct cfg80211_scan_request *req = sc->offchannel.scan_req;
884 : : struct ieee80211_channel *chan;
885 : :
886 : : if (sc->offchannel.scan_idx >= req->n_channels) {
887 : : ath_dbg(common, CHAN_CTX,
888 : : "Moving offchannel state to ATH_OFFCHANNEL_IDLE, "
889 : : "scan_idx: %d, n_channels: %d\n",
890 : : sc->offchannel.scan_idx,
891 : : req->n_channels);
892 : :
893 : : sc->offchannel.state = ATH_OFFCHANNEL_IDLE;
894 : : ath_chanctx_switch(sc, ath_chanctx_get_oper_chan(sc, false),
895 : : NULL);
896 : : return;
897 : : }
898 : :
899 : : ath_dbg(common, CHAN_CTX,
900 : : "Moving offchannel state to ATH_OFFCHANNEL_PROBE_SEND, scan_idx: %d\n",
901 : : sc->offchannel.scan_idx);
902 : :
903 : : chan = req->channels[sc->offchannel.scan_idx++];
904 : : sc->offchannel.duration = ath_scan_channel_duration(sc, chan);
905 : : sc->offchannel.state = ATH_OFFCHANNEL_PROBE_SEND;
906 : :
907 : : ath_chanctx_offchan_switch(sc, chan);
908 : : }
909 : :
910 : : void ath_offchannel_next(struct ath_softc *sc)
911 : : {
912 : : struct ieee80211_vif *vif;
913 : :
914 : : if (sc->offchannel.scan_req) {
915 : : vif = sc->offchannel.scan_vif;
916 : : sc->offchannel.chan.txpower = vif->bss_conf.txpower;
917 : : ath_scan_next_channel(sc);
918 : : } else if (sc->offchannel.roc_vif) {
919 : : vif = sc->offchannel.roc_vif;
920 : : sc->offchannel.chan.txpower = vif->bss_conf.txpower;
921 : : sc->offchannel.duration =
922 : : msecs_to_jiffies(sc->offchannel.roc_duration);
923 : : sc->offchannel.state = ATH_OFFCHANNEL_ROC_START;
924 : : ath_chanctx_offchan_switch(sc, sc->offchannel.roc_chan);
925 : : } else {
926 : : spin_lock_bh(&sc->chan_lock);
927 : : sc->sched.offchannel_pending = false;
928 : : sc->sched.wait_switch = false;
929 : : spin_unlock_bh(&sc->chan_lock);
930 : :
931 : : ath_chanctx_switch(sc, ath_chanctx_get_oper_chan(sc, false),
932 : : NULL);
933 : : sc->offchannel.state = ATH_OFFCHANNEL_IDLE;
934 : : if (sc->ps_idle)
935 : : ath_cancel_work(sc);
936 : : }
937 : : }
938 : :
939 : : void ath_roc_complete(struct ath_softc *sc, enum ath_roc_complete_reason reason)
940 : : {
941 : : struct ath_common *common = ath9k_hw_common(sc->sc_ah);
942 : :
943 : : sc->offchannel.roc_vif = NULL;
944 : : sc->offchannel.roc_chan = NULL;
945 : :
946 : : switch (reason) {
947 : : case ATH_ROC_COMPLETE_ABORT:
948 : : ath_dbg(common, CHAN_CTX, "RoC aborted\n");
949 : : ieee80211_remain_on_channel_expired(sc->hw);
950 : : break;
951 : : case ATH_ROC_COMPLETE_EXPIRE:
952 : : ath_dbg(common, CHAN_CTX, "RoC expired\n");
953 : : ieee80211_remain_on_channel_expired(sc->hw);
954 : : break;
955 : : case ATH_ROC_COMPLETE_CANCEL:
956 : : ath_dbg(common, CHAN_CTX, "RoC canceled\n");
957 : : break;
958 : : }
959 : :
960 : : ath_offchannel_next(sc);
961 : : ath9k_ps_restore(sc);
962 : : }
963 : :
964 : : void ath_scan_complete(struct ath_softc *sc, bool abort)
965 : : {
966 : : struct ath_common *common = ath9k_hw_common(sc->sc_ah);
967 : : struct cfg80211_scan_info info = {
968 : : .aborted = abort,
969 : : };
970 : :
971 : : if (abort)
972 : : ath_dbg(common, CHAN_CTX, "HW scan aborted\n");
973 : : else
974 : : ath_dbg(common, CHAN_CTX, "HW scan complete\n");
975 : :
976 : : sc->offchannel.scan_req = NULL;
977 : : sc->offchannel.scan_vif = NULL;
978 : : sc->offchannel.state = ATH_OFFCHANNEL_IDLE;
979 : : ieee80211_scan_completed(sc->hw, &info);
980 : : clear_bit(ATH_OP_SCANNING, &common->op_flags);
981 : : spin_lock_bh(&sc->chan_lock);
982 : : if (test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags))
983 : : sc->sched.force_noa_update = true;
984 : : spin_unlock_bh(&sc->chan_lock);
985 : : ath_offchannel_next(sc);
986 : : ath9k_ps_restore(sc);
987 : : }
988 : :
989 : : static void ath_scan_send_probe(struct ath_softc *sc,
990 : : struct cfg80211_ssid *ssid)
991 : : {
992 : : struct cfg80211_scan_request *req = sc->offchannel.scan_req;
993 : : struct ieee80211_vif *vif = sc->offchannel.scan_vif;
994 : : struct ath_tx_control txctl = {};
995 : : struct sk_buff *skb;
996 : : struct ieee80211_tx_info *info;
997 : : int band = sc->offchannel.chan.chandef.chan->band;
998 : :
999 : : skb = ieee80211_probereq_get(sc->hw, vif->addr,
1000 : : ssid->ssid, ssid->ssid_len, req->ie_len);
1001 : : if (!skb)
1002 : : return;
1003 : :
1004 : : info = IEEE80211_SKB_CB(skb);
1005 : : if (req->no_cck)
1006 : : info->flags |= IEEE80211_TX_CTL_NO_CCK_RATE;
1007 : :
1008 : : if (req->ie_len)
1009 : : skb_put_data(skb, req->ie, req->ie_len);
1010 : :
1011 : : skb_set_queue_mapping(skb, IEEE80211_AC_VO);
1012 : :
1013 : : if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, NULL))
1014 : : goto error;
1015 : :
1016 : : txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO];
1017 : : if (ath_tx_start(sc->hw, skb, &txctl))
1018 : : goto error;
1019 : :
1020 : : return;
1021 : :
1022 : : error:
1023 : : ieee80211_free_txskb(sc->hw, skb);
1024 : : }
1025 : :
1026 : : static void ath_scan_channel_start(struct ath_softc *sc)
1027 : : {
1028 : : struct ath_common *common = ath9k_hw_common(sc->sc_ah);
1029 : : struct cfg80211_scan_request *req = sc->offchannel.scan_req;
1030 : : int i;
1031 : :
1032 : : if (!(sc->cur_chan->chandef.chan->flags & IEEE80211_CHAN_NO_IR) &&
1033 : : req->n_ssids) {
1034 : : for (i = 0; i < req->n_ssids; i++)
1035 : : ath_scan_send_probe(sc, &req->ssids[i]);
1036 : :
1037 : : }
1038 : :
1039 : : ath_dbg(common, CHAN_CTX,
1040 : : "Moving offchannel state to ATH_OFFCHANNEL_PROBE_WAIT\n");
1041 : :
1042 : : sc->offchannel.state = ATH_OFFCHANNEL_PROBE_WAIT;
1043 : : mod_timer(&sc->offchannel.timer, jiffies + sc->offchannel.duration);
1044 : : }
1045 : :
1046 : : static void ath_chanctx_timer(struct timer_list *t)
1047 : : {
1048 : : struct ath_softc *sc = from_timer(sc, t, sched.timer);
1049 : : struct ath_common *common = ath9k_hw_common(sc->sc_ah);
1050 : :
1051 : : ath_dbg(common, CHAN_CTX,
1052 : : "Channel context timer invoked\n");
1053 : :
1054 : : ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_TSF_TIMER);
1055 : : }
1056 : :
1057 : : static void ath_offchannel_timer(struct timer_list *t)
1058 : : {
1059 : : struct ath_softc *sc = from_timer(sc, t, offchannel.timer);
1060 : : struct ath_chanctx *ctx;
1061 : : struct ath_common *common = ath9k_hw_common(sc->sc_ah);
1062 : :
1063 : : ath_dbg(common, CHAN_CTX, "%s: offchannel state: %s\n",
1064 : : __func__, offchannel_state_string(sc->offchannel.state));
1065 : :
1066 : : switch (sc->offchannel.state) {
1067 : : case ATH_OFFCHANNEL_PROBE_WAIT:
1068 : : if (!sc->offchannel.scan_req)
1069 : : return;
1070 : :
1071 : : /* get first active channel context */
1072 : : ctx = ath_chanctx_get_oper_chan(sc, true);
1073 : : if (ctx->active) {
1074 : : ath_dbg(common, CHAN_CTX,
1075 : : "Switch to oper/active context, "
1076 : : "move offchannel state to ATH_OFFCHANNEL_SUSPEND\n");
1077 : :
1078 : : sc->offchannel.state = ATH_OFFCHANNEL_SUSPEND;
1079 : : ath_chanctx_switch(sc, ctx, NULL);
1080 : : mod_timer(&sc->offchannel.timer, jiffies + HZ / 10);
1081 : : break;
1082 : : }
1083 : : /* fall through */
1084 : : case ATH_OFFCHANNEL_SUSPEND:
1085 : : if (!sc->offchannel.scan_req)
1086 : : return;
1087 : :
1088 : : ath_scan_next_channel(sc);
1089 : : break;
1090 : : case ATH_OFFCHANNEL_ROC_START:
1091 : : case ATH_OFFCHANNEL_ROC_WAIT:
1092 : : sc->offchannel.state = ATH_OFFCHANNEL_ROC_DONE;
1093 : : ath_roc_complete(sc, ATH_ROC_COMPLETE_EXPIRE);
1094 : : break;
1095 : : default:
1096 : : break;
1097 : : }
1098 : : }
1099 : :
1100 : : static bool
1101 : : ath_chanctx_send_vif_ps_frame(struct ath_softc *sc, struct ath_vif *avp,
1102 : : bool powersave)
1103 : : {
1104 : : struct ieee80211_vif *vif = avp->vif;
1105 : : struct ieee80211_sta *sta = NULL;
1106 : : struct ieee80211_hdr_3addr *nullfunc;
1107 : : struct ath_tx_control txctl;
1108 : : struct sk_buff *skb;
1109 : : int band = sc->cur_chan->chandef.chan->band;
1110 : :
1111 : : switch (vif->type) {
1112 : : case NL80211_IFTYPE_STATION:
1113 : : if (!avp->assoc)
1114 : : return false;
1115 : :
1116 : : skb = ieee80211_nullfunc_get(sc->hw, vif, false);
1117 : : if (!skb)
1118 : : return false;
1119 : :
1120 : : nullfunc = (struct ieee80211_hdr_3addr *) skb->data;
1121 : : if (powersave)
1122 : : nullfunc->frame_control |=
1123 : : cpu_to_le16(IEEE80211_FCTL_PM);
1124 : :
1125 : : skb->priority = 7;
1126 : : skb_set_queue_mapping(skb, IEEE80211_AC_VO);
1127 : : if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, &sta)) {
1128 : : dev_kfree_skb_any(skb);
1129 : : return false;
1130 : : }
1131 : : break;
1132 : : default:
1133 : : return false;
1134 : : }
1135 : :
1136 : : memset(&txctl, 0, sizeof(txctl));
1137 : : txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO];
1138 : : txctl.sta = sta;
1139 : : if (ath_tx_start(sc->hw, skb, &txctl)) {
1140 : : ieee80211_free_txskb(sc->hw, skb);
1141 : : return false;
1142 : : }
1143 : :
1144 : : return true;
1145 : : }
1146 : :
1147 : : static bool
1148 : : ath_chanctx_send_ps_frame(struct ath_softc *sc, bool powersave)
1149 : : {
1150 : : struct ath_vif *avp;
1151 : : bool sent = false;
1152 : :
1153 : : rcu_read_lock();
1154 : : list_for_each_entry(avp, &sc->cur_chan->vifs, list) {
1155 : : if (ath_chanctx_send_vif_ps_frame(sc, avp, powersave))
1156 : : sent = true;
1157 : : }
1158 : : rcu_read_unlock();
1159 : :
1160 : : return sent;
1161 : : }
1162 : :
1163 : : static bool ath_chanctx_defer_switch(struct ath_softc *sc)
1164 : : {
1165 : : struct ath_common *common = ath9k_hw_common(sc->sc_ah);
1166 : :
1167 : : if (sc->cur_chan == &sc->offchannel.chan)
1168 : : return false;
1169 : :
1170 : : switch (sc->sched.state) {
1171 : : case ATH_CHANCTX_STATE_SWITCH:
1172 : : return false;
1173 : : case ATH_CHANCTX_STATE_IDLE:
1174 : : if (!sc->cur_chan->switch_after_beacon)
1175 : : return false;
1176 : :
1177 : : ath_dbg(common, CHAN_CTX,
1178 : : "Defer switch, set chanctx state to WAIT_FOR_BEACON\n");
1179 : :
1180 : : sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON;
1181 : : break;
1182 : : default:
1183 : : break;
1184 : : }
1185 : :
1186 : : return true;
1187 : : }
1188 : :
1189 : : static void ath_offchannel_channel_change(struct ath_softc *sc)
1190 : : {
1191 : : struct ath_common *common = ath9k_hw_common(sc->sc_ah);
1192 : :
1193 : : ath_dbg(common, CHAN_CTX, "%s: offchannel state: %s\n",
1194 : : __func__, offchannel_state_string(sc->offchannel.state));
1195 : :
1196 : : switch (sc->offchannel.state) {
1197 : : case ATH_OFFCHANNEL_PROBE_SEND:
1198 : : if (!sc->offchannel.scan_req)
1199 : : return;
1200 : :
1201 : : if (sc->cur_chan->chandef.chan !=
1202 : : sc->offchannel.chan.chandef.chan)
1203 : : return;
1204 : :
1205 : : ath_scan_channel_start(sc);
1206 : : break;
1207 : : case ATH_OFFCHANNEL_IDLE:
1208 : : if (!sc->offchannel.scan_req)
1209 : : return;
1210 : :
1211 : : ath_scan_complete(sc, false);
1212 : : break;
1213 : : case ATH_OFFCHANNEL_ROC_START:
1214 : : if (sc->cur_chan != &sc->offchannel.chan)
1215 : : break;
1216 : :
1217 : : sc->offchannel.state = ATH_OFFCHANNEL_ROC_WAIT;
1218 : : mod_timer(&sc->offchannel.timer,
1219 : : jiffies + sc->offchannel.duration);
1220 : : ieee80211_ready_on_channel(sc->hw);
1221 : : break;
1222 : : case ATH_OFFCHANNEL_ROC_DONE:
1223 : : break;
1224 : : default:
1225 : : break;
1226 : : }
1227 : : }
1228 : :
1229 : : void ath_chanctx_set_next(struct ath_softc *sc, bool force)
1230 : : {
1231 : : struct ath_common *common = ath9k_hw_common(sc->sc_ah);
1232 : : struct ath_chanctx *old_ctx;
1233 : : struct timespec64 ts;
1234 : : bool measure_time = false;
1235 : : bool send_ps = false;
1236 : : bool queues_stopped = false;
1237 : :
1238 : : spin_lock_bh(&sc->chan_lock);
1239 : : if (!sc->next_chan) {
1240 : : spin_unlock_bh(&sc->chan_lock);
1241 : : return;
1242 : : }
1243 : :
1244 : : if (!force && ath_chanctx_defer_switch(sc)) {
1245 : : spin_unlock_bh(&sc->chan_lock);
1246 : : return;
1247 : : }
1248 : :
1249 : : ath_dbg(common, CHAN_CTX,
1250 : : "%s: current: %d MHz, next: %d MHz\n",
1251 : : __func__,
1252 : : sc->cur_chan->chandef.center_freq1,
1253 : : sc->next_chan->chandef.center_freq1);
1254 : :
1255 : : if (sc->cur_chan != sc->next_chan) {
1256 : : ath_dbg(common, CHAN_CTX,
1257 : : "Stopping current chanctx: %d\n",
1258 : : sc->cur_chan->chandef.center_freq1);
1259 : : sc->cur_chan->stopped = true;
1260 : : spin_unlock_bh(&sc->chan_lock);
1261 : :
1262 : : if (sc->next_chan == &sc->offchannel.chan) {
1263 : : ktime_get_raw_ts64(&ts);
1264 : : measure_time = true;
1265 : : }
1266 : :
1267 : : ath9k_chanctx_stop_queues(sc, sc->cur_chan);
1268 : : queues_stopped = true;
1269 : :
1270 : : __ath9k_flush(sc->hw, ~0, true, false, false);
1271 : :
1272 : : if (ath_chanctx_send_ps_frame(sc, true))
1273 : : __ath9k_flush(sc->hw, BIT(IEEE80211_AC_VO),
1274 : : false, false, false);
1275 : :
1276 : : send_ps = true;
1277 : : spin_lock_bh(&sc->chan_lock);
1278 : :
1279 : : if (sc->cur_chan != &sc->offchannel.chan) {
1280 : : ktime_get_raw_ts64(&sc->cur_chan->tsf_ts);
1281 : : sc->cur_chan->tsf_val = ath9k_hw_gettsf64(sc->sc_ah);
1282 : : }
1283 : : }
1284 : : old_ctx = sc->cur_chan;
1285 : : sc->cur_chan = sc->next_chan;
1286 : : sc->cur_chan->stopped = false;
1287 : : sc->next_chan = NULL;
1288 : :
1289 : : if (!sc->sched.offchannel_pending)
1290 : : sc->sched.offchannel_duration = 0;
1291 : :
1292 : : if (sc->sched.state != ATH_CHANCTX_STATE_FORCE_ACTIVE)
1293 : : sc->sched.state = ATH_CHANCTX_STATE_IDLE;
1294 : :
1295 : : spin_unlock_bh(&sc->chan_lock);
1296 : :
1297 : : if (sc->sc_ah->chip_fullsleep ||
1298 : : memcmp(&sc->cur_chandef, &sc->cur_chan->chandef,
1299 : : sizeof(sc->cur_chandef))) {
1300 : : ath_dbg(common, CHAN_CTX,
1301 : : "%s: Set channel %d MHz\n",
1302 : : __func__, sc->cur_chan->chandef.center_freq1);
1303 : : ath_set_channel(sc);
1304 : : if (measure_time)
1305 : : sc->sched.channel_switch_time =
1306 : : ath9k_hw_get_tsf_offset(&ts, NULL);
1307 : : /*
1308 : : * A reset will ensure that all queues are woken up,
1309 : : * so there is no need to awaken them again.
1310 : : */
1311 : : goto out;
1312 : : }
1313 : :
1314 : : if (queues_stopped)
1315 : : ath9k_chanctx_wake_queues(sc, old_ctx);
1316 : : out:
1317 : : if (send_ps)
1318 : : ath_chanctx_send_ps_frame(sc, false);
1319 : :
1320 : : ath_offchannel_channel_change(sc);
1321 : : ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_SWITCH);
1322 : : }
1323 : :
1324 : : static void ath_chanctx_work(struct work_struct *work)
1325 : : {
1326 : : struct ath_softc *sc = container_of(work, struct ath_softc,
1327 : : chanctx_work);
1328 : : mutex_lock(&sc->mutex);
1329 : : ath_chanctx_set_next(sc, false);
1330 : : mutex_unlock(&sc->mutex);
1331 : : }
1332 : :
1333 : : void ath9k_offchannel_init(struct ath_softc *sc)
1334 : : {
1335 : : struct ath_chanctx *ctx;
1336 : : struct ath_common *common = ath9k_hw_common(sc->sc_ah);
1337 : : struct ieee80211_supported_band *sband;
1338 : : struct ieee80211_channel *chan;
1339 : : int i;
1340 : :
1341 : : sband = &common->sbands[NL80211_BAND_2GHZ];
1342 : : if (!sband->n_channels)
1343 : : sband = &common->sbands[NL80211_BAND_5GHZ];
1344 : :
1345 : : chan = &sband->channels[0];
1346 : :
1347 : : ctx = &sc->offchannel.chan;
1348 : : INIT_LIST_HEAD(&ctx->vifs);
1349 : : ctx->txpower = ATH_TXPOWER_MAX;
1350 : : cfg80211_chandef_create(&ctx->chandef, chan, NL80211_CHAN_HT20);
1351 : :
1352 : : for (i = 0; i < ARRAY_SIZE(ctx->acq); i++) {
1353 : : INIT_LIST_HEAD(&ctx->acq[i].acq_new);
1354 : : INIT_LIST_HEAD(&ctx->acq[i].acq_old);
1355 : : spin_lock_init(&ctx->acq[i].lock);
1356 : : }
1357 : :
1358 : : sc->offchannel.chan.offchannel = true;
1359 : : }
1360 : :
1361 : : void ath9k_init_channel_context(struct ath_softc *sc)
1362 : : {
1363 : : INIT_WORK(&sc->chanctx_work, ath_chanctx_work);
1364 : :
1365 : : timer_setup(&sc->offchannel.timer, ath_offchannel_timer, 0);
1366 : : timer_setup(&sc->sched.timer, ath_chanctx_timer, 0);
1367 : :
1368 : : init_completion(&sc->go_beacon);
1369 : : }
1370 : :
1371 : : void ath9k_deinit_channel_context(struct ath_softc *sc)
1372 : : {
1373 : : cancel_work_sync(&sc->chanctx_work);
1374 : : }
1375 : :
1376 : : bool ath9k_is_chanctx_enabled(void)
1377 : : {
1378 : : return (ath9k_use_chanctx == 1);
1379 : : }
1380 : :
1381 : : /********************/
1382 : : /* Queue management */
1383 : : /********************/
1384 : :
1385 : : void ath9k_chanctx_stop_queues(struct ath_softc *sc, struct ath_chanctx *ctx)
1386 : : {
1387 : : struct ath_hw *ah = sc->sc_ah;
1388 : : int i;
1389 : :
1390 : : if (ctx == &sc->offchannel.chan) {
1391 : : ieee80211_stop_queue(sc->hw,
1392 : : sc->hw->offchannel_tx_hw_queue);
1393 : : } else {
1394 : : for (i = 0; i < IEEE80211_NUM_ACS; i++)
1395 : : ieee80211_stop_queue(sc->hw,
1396 : : ctx->hw_queue_base + i);
1397 : : }
1398 : :
1399 : : if (ah->opmode == NL80211_IFTYPE_AP)
1400 : : ieee80211_stop_queue(sc->hw, sc->hw->queues - 2);
1401 : : }
1402 : :
1403 : :
1404 : : void ath9k_chanctx_wake_queues(struct ath_softc *sc, struct ath_chanctx *ctx)
1405 : : {
1406 : : struct ath_hw *ah = sc->sc_ah;
1407 : : int i;
1408 : :
1409 : : if (ctx == &sc->offchannel.chan) {
1410 : : ieee80211_wake_queue(sc->hw,
1411 : : sc->hw->offchannel_tx_hw_queue);
1412 : : } else {
1413 : : for (i = 0; i < IEEE80211_NUM_ACS; i++)
1414 : : ieee80211_wake_queue(sc->hw,
1415 : : ctx->hw_queue_base + i);
1416 : : }
1417 : :
1418 : : if (ah->opmode == NL80211_IFTYPE_AP)
1419 : : ieee80211_wake_queue(sc->hw, sc->hw->queues - 2);
1420 : : }
1421 : :
1422 : : /*****************/
1423 : : /* P2P Powersave */
1424 : : /*****************/
1425 : :
1426 : : static void ath9k_update_p2p_ps_timer(struct ath_softc *sc, struct ath_vif *avp)
1427 : : {
1428 : : struct ath_common *common = ath9k_hw_common(sc->sc_ah);
1429 : : struct ath_hw *ah = sc->sc_ah;
1430 : : u32 tsf, target_tsf;
1431 : :
1432 : : if (!avp || !avp->noa.has_next_tsf)
1433 : : return;
1434 : :
1435 : : ath9k_hw_gen_timer_stop(ah, sc->p2p_ps_timer);
1436 : :
1437 : : tsf = ath9k_hw_gettsf32(sc->sc_ah);
1438 : :
1439 : : target_tsf = avp->noa.next_tsf;
1440 : : if (!avp->noa.absent)
1441 : : target_tsf -= ATH_P2P_PS_STOP_TIME;
1442 : : else
1443 : : target_tsf += ATH_P2P_PS_STOP_TIME;
1444 : :
1445 : : if (target_tsf - tsf < ATH_P2P_PS_STOP_TIME)
1446 : : target_tsf = tsf + ATH_P2P_PS_STOP_TIME;
1447 : :
1448 : : ath_dbg(common, CHAN_CTX, "%s absent %d tsf 0x%08X next_tsf 0x%08X (%dms)\n",
1449 : : __func__, avp->noa.absent, tsf, target_tsf,
1450 : : (target_tsf - tsf) / 1000);
1451 : :
1452 : : ath9k_hw_gen_timer_start(ah, sc->p2p_ps_timer, target_tsf, 1000000);
1453 : : }
1454 : :
1455 : : static void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif)
1456 : : {
1457 : : struct ath_vif *avp = (void *)vif->drv_priv;
1458 : : u32 tsf;
1459 : :
1460 : : if (!sc->p2p_ps_timer)
1461 : : return;
1462 : :
1463 : : if (vif->type != NL80211_IFTYPE_STATION)
1464 : : return;
1465 : :
1466 : : sc->p2p_ps_vif = avp;
1467 : :
1468 : : if (sc->ps_flags & PS_BEACON_SYNC)
1469 : : return;
1470 : :
1471 : : tsf = ath9k_hw_gettsf32(sc->sc_ah);
1472 : : ieee80211_parse_p2p_noa(&vif->bss_conf.p2p_noa_attr, &avp->noa, tsf);
1473 : : ath9k_update_p2p_ps_timer(sc, avp);
1474 : : }
1475 : :
1476 : : static u8 ath9k_get_ctwin(struct ath_softc *sc, struct ath_vif *avp)
1477 : : {
1478 : : struct ath_beacon_config *cur_conf = &sc->cur_chan->beacon;
1479 : : u8 switch_time, ctwin;
1480 : :
1481 : : /*
1482 : : * Channel switch in multi-channel mode is deferred
1483 : : * by a quarter beacon interval when handling
1484 : : * ATH_CHANCTX_EVENT_BEACON_PREPARE, so the P2P-GO
1485 : : * interface is guaranteed to be discoverable
1486 : : * for that duration after a TBTT.
1487 : : */
1488 : : switch_time = cur_conf->beacon_interval / 4;
1489 : :
1490 : : ctwin = avp->vif->bss_conf.p2p_noa_attr.oppps_ctwindow;
1491 : : if (ctwin && (ctwin < switch_time))
1492 : : return ctwin;
1493 : :
1494 : : if (switch_time < P2P_DEFAULT_CTWIN)
1495 : : return 0;
1496 : :
1497 : : return P2P_DEFAULT_CTWIN;
1498 : : }
1499 : :
1500 : : void ath9k_beacon_add_noa(struct ath_softc *sc, struct ath_vif *avp,
1501 : : struct sk_buff *skb)
1502 : : {
1503 : : static const u8 noa_ie_hdr[] = {
1504 : : WLAN_EID_VENDOR_SPECIFIC, /* type */
1505 : : 0, /* length */
1506 : : 0x50, 0x6f, 0x9a, /* WFA OUI */
1507 : : 0x09, /* P2P subtype */
1508 : : 0x0c, /* Notice of Absence */
1509 : : 0x00, /* LSB of little-endian len */
1510 : : 0x00, /* MSB of little-endian len */
1511 : : };
1512 : :
1513 : : struct ieee80211_p2p_noa_attr *noa;
1514 : : int noa_len, noa_desc, i = 0;
1515 : : u8 *hdr;
1516 : :
1517 : : if (!avp->offchannel_duration && !avp->noa_duration)
1518 : : return;
1519 : :
1520 : : noa_desc = !!avp->offchannel_duration + !!avp->noa_duration;
1521 : : noa_len = 2 + sizeof(struct ieee80211_p2p_noa_desc) * noa_desc;
1522 : :
1523 : : hdr = skb_put_data(skb, noa_ie_hdr, sizeof(noa_ie_hdr));
1524 : : hdr[1] = sizeof(noa_ie_hdr) + noa_len - 2;
1525 : : hdr[7] = noa_len;
1526 : :
1527 : : noa = skb_put_zero(skb, noa_len);
1528 : :
1529 : : noa->index = avp->noa_index;
1530 : : noa->oppps_ctwindow = ath9k_get_ctwin(sc, avp);
1531 : : if (noa->oppps_ctwindow)
1532 : : noa->oppps_ctwindow |= BIT(7);
1533 : :
1534 : : if (avp->noa_duration) {
1535 : : if (avp->periodic_noa) {
1536 : : u32 interval = TU_TO_USEC(sc->cur_chan->beacon.beacon_interval);
1537 : : noa->desc[i].count = 255;
1538 : : noa->desc[i].interval = cpu_to_le32(interval);
1539 : : } else {
1540 : : noa->desc[i].count = 1;
1541 : : }
1542 : :
1543 : : noa->desc[i].start_time = cpu_to_le32(avp->noa_start);
1544 : : noa->desc[i].duration = cpu_to_le32(avp->noa_duration);
1545 : : i++;
1546 : : }
1547 : :
1548 : : if (avp->offchannel_duration) {
1549 : : noa->desc[i].count = 1;
1550 : : noa->desc[i].start_time = cpu_to_le32(avp->offchannel_start);
1551 : : noa->desc[i].duration = cpu_to_le32(avp->offchannel_duration);
1552 : : }
1553 : : }
1554 : :
1555 : : void ath9k_p2p_ps_timer(void *priv)
1556 : : {
1557 : : struct ath_softc *sc = priv;
1558 : : struct ath_vif *avp = sc->p2p_ps_vif;
1559 : : struct ieee80211_vif *vif;
1560 : : struct ieee80211_sta *sta;
1561 : : struct ath_node *an;
1562 : : u32 tsf;
1563 : :
1564 : : del_timer_sync(&sc->sched.timer);
1565 : : ath9k_hw_gen_timer_stop(sc->sc_ah, sc->p2p_ps_timer);
1566 : : ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_TSF_TIMER);
1567 : :
1568 : : if (!avp || avp->chanctx != sc->cur_chan)
1569 : : return;
1570 : :
1571 : : tsf = ath9k_hw_gettsf32(sc->sc_ah);
1572 : : if (!avp->noa.absent)
1573 : : tsf += ATH_P2P_PS_STOP_TIME;
1574 : : else
1575 : : tsf -= ATH_P2P_PS_STOP_TIME;
1576 : :
1577 : : if (!avp->noa.has_next_tsf ||
1578 : : avp->noa.next_tsf - tsf > BIT(31))
1579 : : ieee80211_update_p2p_noa(&avp->noa, tsf);
1580 : :
1581 : : ath9k_update_p2p_ps_timer(sc, avp);
1582 : :
1583 : : rcu_read_lock();
1584 : :
1585 : : vif = avp->vif;
1586 : : sta = ieee80211_find_sta(vif, avp->bssid);
1587 : : if (!sta)
1588 : : goto out;
1589 : :
1590 : : an = (void *) sta->drv_priv;
1591 : : if (an->sleeping == !!avp->noa.absent)
1592 : : goto out;
1593 : :
1594 : : an->sleeping = avp->noa.absent;
1595 : : if (an->sleeping)
1596 : : ath_tx_aggr_sleep(sta, sc, an);
1597 : : else
1598 : : ath_tx_aggr_wakeup(sc, an);
1599 : :
1600 : : out:
1601 : : rcu_read_unlock();
1602 : : }
1603 : :
1604 : : void ath9k_p2p_bss_info_changed(struct ath_softc *sc,
1605 : : struct ieee80211_vif *vif)
1606 : : {
1607 : : unsigned long flags;
1608 : :
1609 : : spin_lock_bh(&sc->sc_pcu_lock);
1610 : : spin_lock_irqsave(&sc->sc_pm_lock, flags);
1611 : : ath9k_update_p2p_ps(sc, vif);
1612 : : spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
1613 : : spin_unlock_bh(&sc->sc_pcu_lock);
1614 : : }
1615 : :
1616 : : void ath9k_p2p_beacon_sync(struct ath_softc *sc)
1617 : : {
1618 : : if (sc->p2p_ps_vif)
1619 : : ath9k_update_p2p_ps(sc, sc->p2p_ps_vif->vif);
1620 : : }
1621 : :
1622 : : void ath9k_p2p_remove_vif(struct ath_softc *sc,
1623 : : struct ieee80211_vif *vif)
1624 : : {
1625 : : struct ath_vif *avp = (void *)vif->drv_priv;
1626 : :
1627 : : spin_lock_bh(&sc->sc_pcu_lock);
1628 : : if (avp == sc->p2p_ps_vif) {
1629 : : sc->p2p_ps_vif = NULL;
1630 : : ath9k_update_p2p_ps_timer(sc, NULL);
1631 : : }
1632 : : spin_unlock_bh(&sc->sc_pcu_lock);
1633 : : }
1634 : :
1635 : : int ath9k_init_p2p(struct ath_softc *sc)
1636 : : {
1637 : : sc->p2p_ps_timer = ath_gen_timer_alloc(sc->sc_ah, ath9k_p2p_ps_timer,
1638 : : NULL, sc, AR_FIRST_NDP_TIMER);
1639 : : if (!sc->p2p_ps_timer)
1640 : : return -ENOMEM;
1641 : :
1642 : : return 0;
1643 : : }
1644 : :
1645 : : void ath9k_deinit_p2p(struct ath_softc *sc)
1646 : : {
1647 : : if (sc->p2p_ps_timer)
1648 : : ath_gen_timer_free(sc->sc_ah, sc->p2p_ps_timer);
1649 : : }
1650 : :
1651 : : #endif /* CONFIG_ATH9K_CHANNEL_CONTEXT */
|