1652 lines · c
1/*2 * Copyright (c) 2014 Qualcomm Atheros, Inc.3 *4 * Permission to use, copy, modify, and/or distribute this software for any5 * purpose with or without fee is hereby granted, provided that the above6 * copyright notice and this permission notice appear in all copies.7 *8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF14 * 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 done20 * by reseting the chip. To accomplish this we must first cleanup any pending21 * DMA, then restart stuff.22 */23static 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 unsigned long flags;33 int old_pos = -1;34 int r;35 36 if (test_bit(ATH_OP_INVALID, &common->op_flags))37 return -EIO;38 39 if (ah->curchan)40 old_pos = ah->curchan - &ah->channels[0];41 42 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 spin_lock_irqsave(&common->cc_lock, flags);47 ath_update_survey_stats(sc);48 spin_unlock_irqrestore(&common->cc_lock, flags);49 50 ath9k_cmn_get_channel(hw, ah, chandef);51 52 /* If the operating channel changes, change the survey in-use flags53 * along with it.54 * Reset the survey data for the new channel, unless we're switching55 * back to the operating channel from an off-channel operation.56 */57 if (!sc->cur_chan->offchannel && sc->cur_survey != &sc->survey[pos]) {58 if (sc->cur_survey)59 sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE;60 61 sc->cur_survey = &sc->survey[pos];62 63 memset(sc->cur_survey, 0, sizeof(struct survey_info));64 sc->cur_survey->filled |= SURVEY_INFO_IN_USE;65 } else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) {66 memset(&sc->survey[pos], 0, sizeof(struct survey_info));67 }68 69 hchan = &sc->sc_ah->channels[pos];70 r = ath_reset(sc, hchan);71 if (r)72 return r;73 74 /* The most recent snapshot of channel->noisefloor for the old75 * channel is only available after the hardware reset. Copy it to76 * the survey stats now.77 */78 if (old_pos >= 0)79 ath_update_survey_nf(sc, old_pos);80 81 /* Enable radar pulse detection if on a DFS channel. Spectral82 * scanning and radar detection can not be used concurrently.83 */84 if (hw->conf.radar_enabled) {85 u32 rxfilter;86 87 rxfilter = ath9k_hw_getrxfilter(ah);88 rxfilter |= ATH9K_RX_FILTER_PHYRADAR |89 ATH9K_RX_FILTER_PHYERR;90 ath9k_hw_setrxfilter(ah, rxfilter);91 ath_dbg(common, DFS, "DFS enabled at freq %d\n",92 chan->center_freq);93 } else {94 /* perform spectral scan if requested. */95 if (test_bit(ATH_OP_SCANNING, &common->op_flags) &&96 sc->spec_priv.spectral_mode == SPECTRAL_CHANSCAN)97 ath9k_cmn_spectral_scan_trigger(common, &sc->spec_priv);98 }99 100 return 0;101}102 103void ath_chanctx_init(struct ath_softc *sc)104{105 struct ath_chanctx *ctx;106 struct ath_common *common = ath9k_hw_common(sc->sc_ah);107 struct ieee80211_supported_band *sband;108 struct ieee80211_channel *chan;109 int i, j;110 111 sband = &common->sbands[NL80211_BAND_2GHZ];112 if (!sband->n_channels)113 sband = &common->sbands[NL80211_BAND_5GHZ];114 115 chan = &sband->channels[0];116 for (i = 0; i < ATH9K_NUM_CHANCTX; i++) {117 ctx = &sc->chanctx[i];118 cfg80211_chandef_create(&ctx->chandef, chan, NL80211_CHAN_HT20);119 INIT_LIST_HEAD(&ctx->vifs);120 ctx->txpower = ATH_TXPOWER_MAX;121 ctx->flush_timeout = HZ / 5; /* 200ms */122 for (j = 0; j < ARRAY_SIZE(ctx->acq); j++) {123 INIT_LIST_HEAD(&ctx->acq[j].acq_new);124 INIT_LIST_HEAD(&ctx->acq[j].acq_old);125 spin_lock_init(&ctx->acq[j].lock);126 }127 }128}129 130void ath_chanctx_set_channel(struct ath_softc *sc, struct ath_chanctx *ctx,131 struct cfg80211_chan_def *chandef)132{133 struct ath_common *common = ath9k_hw_common(sc->sc_ah);134 bool cur_chan;135 136 spin_lock_bh(&sc->chan_lock);137 if (chandef)138 memcpy(&ctx->chandef, chandef, sizeof(*chandef));139 cur_chan = sc->cur_chan == ctx;140 spin_unlock_bh(&sc->chan_lock);141 142 if (!cur_chan) {143 ath_dbg(common, CHAN_CTX,144 "Current context differs from the new context\n");145 return;146 }147 148 ath_set_channel(sc);149}150 151#ifdef CONFIG_ATH9K_CHANNEL_CONTEXT152 153/*************/154/* Utilities */155/*************/156 157struct 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 187static 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 202static 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 220static 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 233static 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 247void 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 else265 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 the272 * active/assigned channel contexts if273 * 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 326static struct ath_chanctx *327ath_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 334static 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 beacons357 * 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 */373static 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 389static 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 been395 * set during the previous beacon transmission,396 * since we need to revert to the normal NoA397 * 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 STA405 * 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 414static 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 NoA433 * has to be recalculated and advertised after434 * an offchannel operation.435 */436 if (ctx->active && avp->noa_duration)437 avp->noa_duration = 0;438}439 440static 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 else455 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 else463 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 473static 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 494void 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 NoA564 * attribute needs to be removed from subsequent565 * 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 after594 * a beacon transmission, update the NoA with one-shot595 * 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 happen607 * with one or more active channel contexts - in both608 * 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 periodic622 * NoA and increment the index for the first623 * 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 fallthrough;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 half718 * 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 777void 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 784void 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 790static 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 801static 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 848static 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 861static 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 879static void880ath_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 910void 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 939void 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 964void 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 else974 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 989static 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 1022error:1023 ieee80211_free_txskb(sc->hw, skb);1024}1025 1026static 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 1046static 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 1057static 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 fallthrough;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 1100static bool1101ath_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, -1, 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 1147static bool1148ath_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 1163static 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 1189static 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 1229void 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);1316out: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 1324static 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 1333void 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 1361void 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 1371void ath9k_deinit_channel_context(struct ath_softc *sc)1372{1373 cancel_work_sync(&sc->chanctx_work);1374}1375 1376bool ath9k_is_chanctx_enabled(void)1377{1378 return (ath9k_use_chanctx == 1);1379}1380 1381/********************/1382/* Queue management */1383/********************/1384 1385void 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 1404void 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 1426static 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 else1443 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 1455static 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 1476static 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 deferred1483 * by a quarter beacon interval when handling1484 * ATH_CHANCTX_EVENT_BEACON_PREPARE, so the P2P-GO1485 * interface is guaranteed to be discoverable1486 * 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 1500void 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 1555void 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 else1575 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 else1598 ath_tx_aggr_wakeup(sc, an);1599 1600out:1601 rcu_read_unlock();1602}1603 1604void 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 1616void 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 1622void 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 1635int 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 1645void 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 */1652