Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
0002 /*
0003  * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
0004  * Copyright (C) 2013-2014 Intel Mobile Communications GmbH
0005  * Copyright (C) 2015-2017 Intel Deutschland GmbH
0006  */
0007 #include <linux/etherdevice.h>
0008 #include <linux/crc32.h>
0009 #include <net/mac80211.h>
0010 #include "iwl-io.h"
0011 #include "iwl-prph.h"
0012 #include "fw-api.h"
0013 #include "mvm.h"
0014 #include "time-event.h"
0015 
0016 const u8 iwl_mvm_ac_to_tx_fifo[] = {
0017     IWL_MVM_TX_FIFO_VO,
0018     IWL_MVM_TX_FIFO_VI,
0019     IWL_MVM_TX_FIFO_BE,
0020     IWL_MVM_TX_FIFO_BK,
0021 };
0022 
0023 const u8 iwl_mvm_ac_to_gen2_tx_fifo[] = {
0024     IWL_GEN2_EDCA_TX_FIFO_VO,
0025     IWL_GEN2_EDCA_TX_FIFO_VI,
0026     IWL_GEN2_EDCA_TX_FIFO_BE,
0027     IWL_GEN2_EDCA_TX_FIFO_BK,
0028     IWL_GEN2_TRIG_TX_FIFO_VO,
0029     IWL_GEN2_TRIG_TX_FIFO_VI,
0030     IWL_GEN2_TRIG_TX_FIFO_BE,
0031     IWL_GEN2_TRIG_TX_FIFO_BK,
0032 };
0033 
0034 struct iwl_mvm_mac_iface_iterator_data {
0035     struct iwl_mvm *mvm;
0036     struct ieee80211_vif *vif;
0037     unsigned long available_mac_ids[BITS_TO_LONGS(NUM_MAC_INDEX_DRIVER)];
0038     unsigned long available_tsf_ids[BITS_TO_LONGS(NUM_TSF_IDS)];
0039     enum iwl_tsf_id preferred_tsf;
0040     bool found_vif;
0041 };
0042 
0043 static void iwl_mvm_mac_tsf_id_iter(void *_data, u8 *mac,
0044                     struct ieee80211_vif *vif)
0045 {
0046     struct iwl_mvm_mac_iface_iterator_data *data = _data;
0047     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
0048     u16 min_bi;
0049 
0050     /* Skip the interface for which we are trying to assign a tsf_id  */
0051     if (vif == data->vif)
0052         return;
0053 
0054     /*
0055      * The TSF is a hardware/firmware resource, there are 4 and
0056      * the driver should assign and free them as needed. However,
0057      * there are cases where 2 MACs should share the same TSF ID
0058      * for the purpose of clock sync, an optimization to avoid
0059      * clock drift causing overlapping TBTTs/DTIMs for a GO and
0060      * client in the system.
0061      *
0062      * The firmware will decide according to the MAC type which
0063      * will be the leader and follower. Clients that need to sync
0064      * with a remote station will be the leader, and an AP or GO
0065      * will be the follower.
0066      *
0067      * Depending on the new interface type it can be following
0068      * or become the leader of an existing interface.
0069      */
0070     switch (data->vif->type) {
0071     case NL80211_IFTYPE_STATION:
0072         /*
0073          * The new interface is a client, so if the one we're iterating
0074          * is an AP, and the beacon interval of the AP is a multiple or
0075          * divisor of the beacon interval of the client, the same TSF
0076          * should be used to avoid drift between the new client and
0077          * existing AP. The existing AP will get drift updates from the
0078          * new client context in this case.
0079          */
0080         if (vif->type != NL80211_IFTYPE_AP ||
0081             data->preferred_tsf != NUM_TSF_IDS ||
0082             !test_bit(mvmvif->tsf_id, data->available_tsf_ids))
0083             break;
0084 
0085         min_bi = min(data->vif->bss_conf.beacon_int,
0086                  vif->bss_conf.beacon_int);
0087 
0088         if (!min_bi)
0089             break;
0090 
0091         if ((data->vif->bss_conf.beacon_int -
0092              vif->bss_conf.beacon_int) % min_bi == 0) {
0093             data->preferred_tsf = mvmvif->tsf_id;
0094             return;
0095         }
0096         break;
0097 
0098     case NL80211_IFTYPE_AP:
0099         /*
0100          * The new interface is AP/GO, so if its beacon interval is a
0101          * multiple or a divisor of the beacon interval of an existing
0102          * interface, it should get drift updates from an existing
0103          * client or use the same TSF as an existing GO. There's no
0104          * drift between TSFs internally but if they used different
0105          * TSFs then a new client MAC could update one of them and
0106          * cause drift that way.
0107          */
0108         if ((vif->type != NL80211_IFTYPE_AP &&
0109              vif->type != NL80211_IFTYPE_STATION) ||
0110             data->preferred_tsf != NUM_TSF_IDS ||
0111             !test_bit(mvmvif->tsf_id, data->available_tsf_ids))
0112             break;
0113 
0114         min_bi = min(data->vif->bss_conf.beacon_int,
0115                  vif->bss_conf.beacon_int);
0116 
0117         if (!min_bi)
0118             break;
0119 
0120         if ((data->vif->bss_conf.beacon_int -
0121              vif->bss_conf.beacon_int) % min_bi == 0) {
0122             data->preferred_tsf = mvmvif->tsf_id;
0123             return;
0124         }
0125         break;
0126     default:
0127         /*
0128          * For all other interface types there's no need to
0129          * take drift into account. Either they're exclusive
0130          * like IBSS and monitor, or we don't care much about
0131          * their TSF (like P2P Device), but we won't be able
0132          * to share the TSF resource.
0133          */
0134         break;
0135     }
0136 
0137     /*
0138      * Unless we exited above, we can't share the TSF resource
0139      * that the virtual interface we're iterating over is using
0140      * with the new one, so clear the available bit and if this
0141      * was the preferred one, reset that as well.
0142      */
0143     __clear_bit(mvmvif->tsf_id, data->available_tsf_ids);
0144 
0145     if (data->preferred_tsf == mvmvif->tsf_id)
0146         data->preferred_tsf = NUM_TSF_IDS;
0147 }
0148 
0149 static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac,
0150                        struct ieee80211_vif *vif)
0151 {
0152     struct iwl_mvm_mac_iface_iterator_data *data = _data;
0153     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
0154 
0155     /* Iterator may already find the interface being added -- skip it */
0156     if (vif == data->vif) {
0157         data->found_vif = true;
0158         return;
0159     }
0160 
0161     /* Mark MAC IDs as used by clearing the available bit, and
0162      * (below) mark TSFs as used if their existing use is not
0163      * compatible with the new interface type.
0164      * No locking or atomic bit operations are needed since the
0165      * data is on the stack of the caller function.
0166      */
0167     __clear_bit(mvmvif->id, data->available_mac_ids);
0168 
0169     /* find a suitable tsf_id */
0170     iwl_mvm_mac_tsf_id_iter(_data, mac, vif);
0171 }
0172 
0173 void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm,
0174                     struct ieee80211_vif *vif)
0175 {
0176     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
0177     struct iwl_mvm_mac_iface_iterator_data data = {
0178         .mvm = mvm,
0179         .vif = vif,
0180         .available_tsf_ids = { (1 << NUM_TSF_IDS) - 1 },
0181         /* no preference yet */
0182         .preferred_tsf = NUM_TSF_IDS,
0183     };
0184 
0185     ieee80211_iterate_active_interfaces_atomic(
0186         mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
0187         iwl_mvm_mac_tsf_id_iter, &data);
0188 
0189     if (data.preferred_tsf != NUM_TSF_IDS)
0190         mvmvif->tsf_id = data.preferred_tsf;
0191     else if (!test_bit(mvmvif->tsf_id, data.available_tsf_ids))
0192         mvmvif->tsf_id = find_first_bit(data.available_tsf_ids,
0193                         NUM_TSF_IDS);
0194 }
0195 
0196 int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
0197 {
0198     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
0199     struct iwl_mvm_mac_iface_iterator_data data = {
0200         .mvm = mvm,
0201         .vif = vif,
0202         .available_mac_ids = { (1 << NUM_MAC_INDEX_DRIVER) - 1 },
0203         .available_tsf_ids = { (1 << NUM_TSF_IDS) - 1 },
0204         /* no preference yet */
0205         .preferred_tsf = NUM_TSF_IDS,
0206         .found_vif = false,
0207     };
0208     int ret, i;
0209 
0210     lockdep_assert_held(&mvm->mutex);
0211 
0212     /*
0213      * Allocate a MAC ID and a TSF for this MAC, along with the queues
0214      * and other resources.
0215      */
0216 
0217     /*
0218      * Before the iterator, we start with all MAC IDs and TSFs available.
0219      *
0220      * During iteration, all MAC IDs are cleared that are in use by other
0221      * virtual interfaces, and all TSF IDs are cleared that can't be used
0222      * by this new virtual interface because they're used by an interface
0223      * that can't share it with the new one.
0224      * At the same time, we check if there's a preferred TSF in the case
0225      * that we should share it with another interface.
0226      */
0227 
0228     /* Currently, MAC ID 0 should be used only for the managed/IBSS vif */
0229     switch (vif->type) {
0230     case NL80211_IFTYPE_ADHOC:
0231         break;
0232     case NL80211_IFTYPE_STATION:
0233         if (!vif->p2p)
0234             break;
0235         fallthrough;
0236     default:
0237         __clear_bit(0, data.available_mac_ids);
0238     }
0239 
0240     ieee80211_iterate_active_interfaces_atomic(
0241         mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
0242         iwl_mvm_mac_iface_iterator, &data);
0243 
0244     /*
0245      * In the case we're getting here during resume, it's similar to
0246      * firmware restart, and with RESUME_ALL the iterator will find
0247      * the vif being added already.
0248      * We don't want to reassign any IDs in either case since doing
0249      * so would probably assign different IDs (as interfaces aren't
0250      * necessarily added in the same order), but the old IDs were
0251      * preserved anyway, so skip ID assignment for both resume and
0252      * recovery.
0253      */
0254     if (data.found_vif)
0255         return 0;
0256 
0257     /* Therefore, in recovery, we can't get here */
0258     if (WARN_ON_ONCE(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
0259         return -EBUSY;
0260 
0261     mvmvif->id = find_first_bit(data.available_mac_ids,
0262                     NUM_MAC_INDEX_DRIVER);
0263     if (mvmvif->id == NUM_MAC_INDEX_DRIVER) {
0264         IWL_ERR(mvm, "Failed to init MAC context - no free ID!\n");
0265         ret = -EIO;
0266         goto exit_fail;
0267     }
0268 
0269     if (data.preferred_tsf != NUM_TSF_IDS)
0270         mvmvif->tsf_id = data.preferred_tsf;
0271     else
0272         mvmvif->tsf_id = find_first_bit(data.available_tsf_ids,
0273                         NUM_TSF_IDS);
0274     if (mvmvif->tsf_id == NUM_TSF_IDS) {
0275         IWL_ERR(mvm, "Failed to init MAC context - no free TSF!\n");
0276         ret = -EIO;
0277         goto exit_fail;
0278     }
0279 
0280     mvmvif->color = 0;
0281 
0282     INIT_LIST_HEAD(&mvmvif->time_event_data.list);
0283     mvmvif->time_event_data.id = TE_MAX;
0284 
0285     /* No need to allocate data queues to P2P Device MAC and NAN.*/
0286     if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
0287         return 0;
0288 
0289     /* Allocate the CAB queue for softAP and GO interfaces */
0290     if (vif->type == NL80211_IFTYPE_AP ||
0291         vif->type == NL80211_IFTYPE_ADHOC) {
0292         /*
0293          * For TVQM this will be overwritten later with the FW assigned
0294          * queue value (when queue is enabled).
0295          */
0296         mvmvif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE;
0297     }
0298 
0299     mvmvif->bcast_sta.sta_id = IWL_MVM_INVALID_STA;
0300     mvmvif->mcast_sta.sta_id = IWL_MVM_INVALID_STA;
0301     mvmvif->ap_sta_id = IWL_MVM_INVALID_STA;
0302 
0303     for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++)
0304         mvmvif->smps_requests[i] = IEEE80211_SMPS_AUTOMATIC;
0305 
0306     return 0;
0307 
0308 exit_fail:
0309     memset(mvmvif, 0, sizeof(struct iwl_mvm_vif));
0310     return ret;
0311 }
0312 
0313 static void iwl_mvm_ack_rates(struct iwl_mvm *mvm,
0314                   struct ieee80211_vif *vif,
0315                   enum nl80211_band band,
0316                   u8 *cck_rates, u8 *ofdm_rates)
0317 {
0318     struct ieee80211_supported_band *sband;
0319     unsigned long basic = vif->bss_conf.basic_rates;
0320     int lowest_present_ofdm = 100;
0321     int lowest_present_cck = 100;
0322     u8 cck = 0;
0323     u8 ofdm = 0;
0324     int i;
0325 
0326     sband = mvm->hw->wiphy->bands[band];
0327 
0328     for_each_set_bit(i, &basic, BITS_PER_LONG) {
0329         int hw = sband->bitrates[i].hw_value;
0330         if (hw >= IWL_FIRST_OFDM_RATE) {
0331             ofdm |= BIT(hw - IWL_FIRST_OFDM_RATE);
0332             if (lowest_present_ofdm > hw)
0333                 lowest_present_ofdm = hw;
0334         } else {
0335             BUILD_BUG_ON(IWL_FIRST_CCK_RATE != 0);
0336 
0337             cck |= BIT(hw);
0338             if (lowest_present_cck > hw)
0339                 lowest_present_cck = hw;
0340         }
0341     }
0342 
0343     /*
0344      * Now we've got the basic rates as bitmaps in the ofdm and cck
0345      * variables. This isn't sufficient though, as there might not
0346      * be all the right rates in the bitmap. E.g. if the only basic
0347      * rates are 5.5 Mbps and 11 Mbps, we still need to add 1 Mbps
0348      * and 6 Mbps because the 802.11-2007 standard says in 9.6:
0349      *
0350      *    [...] a STA responding to a received frame shall transmit
0351      *    its Control Response frame [...] at the highest rate in the
0352      *    BSSBasicRateSet parameter that is less than or equal to the
0353      *    rate of the immediately previous frame in the frame exchange
0354      *    sequence ([...]) and that is of the same modulation class
0355      *    ([...]) as the received frame. If no rate contained in the
0356      *    BSSBasicRateSet parameter meets these conditions, then the
0357      *    control frame sent in response to a received frame shall be
0358      *    transmitted at the highest mandatory rate of the PHY that is
0359      *    less than or equal to the rate of the received frame, and
0360      *    that is of the same modulation class as the received frame.
0361      *
0362      * As a consequence, we need to add all mandatory rates that are
0363      * lower than all of the basic rates to these bitmaps.
0364      */
0365 
0366     if (IWL_RATE_24M_INDEX < lowest_present_ofdm)
0367         ofdm |= IWL_RATE_BIT_MSK(24) >> IWL_FIRST_OFDM_RATE;
0368     if (IWL_RATE_12M_INDEX < lowest_present_ofdm)
0369         ofdm |= IWL_RATE_BIT_MSK(12) >> IWL_FIRST_OFDM_RATE;
0370     /* 6M already there or needed so always add */
0371     ofdm |= IWL_RATE_BIT_MSK(6) >> IWL_FIRST_OFDM_RATE;
0372 
0373     /*
0374      * CCK is a bit more complex with DSSS vs. HR/DSSS vs. ERP.
0375      * Note, however:
0376      *  - if no CCK rates are basic, it must be ERP since there must
0377      *    be some basic rates at all, so they're OFDM => ERP PHY
0378      *    (or we're in 5 GHz, and the cck bitmap will never be used)
0379      *  - if 11M is a basic rate, it must be ERP as well, so add 5.5M
0380      *  - if 5.5M is basic, 1M and 2M are mandatory
0381      *  - if 2M is basic, 1M is mandatory
0382      *  - if 1M is basic, that's the only valid ACK rate.
0383      * As a consequence, it's not as complicated as it sounds, just add
0384      * any lower rates to the ACK rate bitmap.
0385      */
0386     if (IWL_RATE_11M_INDEX < lowest_present_cck)
0387         cck |= IWL_RATE_BIT_MSK(11) >> IWL_FIRST_CCK_RATE;
0388     if (IWL_RATE_5M_INDEX < lowest_present_cck)
0389         cck |= IWL_RATE_BIT_MSK(5) >> IWL_FIRST_CCK_RATE;
0390     if (IWL_RATE_2M_INDEX < lowest_present_cck)
0391         cck |= IWL_RATE_BIT_MSK(2) >> IWL_FIRST_CCK_RATE;
0392     /* 1M already there or needed so always add */
0393     cck |= IWL_RATE_BIT_MSK(1) >> IWL_FIRST_CCK_RATE;
0394 
0395     *cck_rates = cck;
0396     *ofdm_rates = ofdm;
0397 }
0398 
0399 static void iwl_mvm_mac_ctxt_set_ht_flags(struct iwl_mvm *mvm,
0400                      struct ieee80211_vif *vif,
0401                      struct iwl_mac_ctx_cmd *cmd)
0402 {
0403     /* for both sta and ap, ht_operation_mode hold the protection_mode */
0404     u8 protection_mode = vif->bss_conf.ht_operation_mode &
0405                  IEEE80211_HT_OP_MODE_PROTECTION;
0406     /* The fw does not distinguish between ht and fat */
0407     u32 ht_flag = MAC_PROT_FLG_HT_PROT | MAC_PROT_FLG_FAT_PROT;
0408 
0409     IWL_DEBUG_RATE(mvm, "protection mode set to %d\n", protection_mode);
0410     /*
0411      * See section 9.23.3.1 of IEEE 80211-2012.
0412      * Nongreenfield HT STAs Present is not supported.
0413      */
0414     switch (protection_mode) {
0415     case IEEE80211_HT_OP_MODE_PROTECTION_NONE:
0416         break;
0417     case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
0418     case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
0419         cmd->protection_flags |= cpu_to_le32(ht_flag);
0420         break;
0421     case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
0422         /* Protect when channel wider than 20MHz */
0423         if (vif->bss_conf.chandef.width > NL80211_CHAN_WIDTH_20)
0424             cmd->protection_flags |= cpu_to_le32(ht_flag);
0425         break;
0426     default:
0427         IWL_ERR(mvm, "Illegal protection mode %d\n",
0428             protection_mode);
0429         break;
0430     }
0431 }
0432 
0433 static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
0434                     struct ieee80211_vif *vif,
0435                     struct iwl_mac_ctx_cmd *cmd,
0436                     const u8 *bssid_override,
0437                     u32 action)
0438 {
0439     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
0440     struct ieee80211_chanctx_conf *chanctx;
0441     bool ht_enabled = !!(vif->bss_conf.ht_operation_mode &
0442                  IEEE80211_HT_OP_MODE_PROTECTION);
0443     u8 cck_ack_rates, ofdm_ack_rates;
0444     const u8 *bssid = bssid_override ?: vif->bss_conf.bssid;
0445     int i;
0446 
0447     cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
0448                                 mvmvif->color));
0449     cmd->action = cpu_to_le32(action);
0450 
0451     switch (vif->type) {
0452     case NL80211_IFTYPE_STATION:
0453         if (vif->p2p)
0454             cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_P2P_STA);
0455         else
0456             cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_BSS_STA);
0457         break;
0458     case NL80211_IFTYPE_AP:
0459         cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_GO);
0460         break;
0461     case NL80211_IFTYPE_MONITOR:
0462         cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_LISTENER);
0463         break;
0464     case NL80211_IFTYPE_P2P_DEVICE:
0465         cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_P2P_DEVICE);
0466         break;
0467     case NL80211_IFTYPE_ADHOC:
0468         cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_IBSS);
0469         break;
0470     default:
0471         WARN_ON_ONCE(1);
0472     }
0473 
0474     cmd->tsf_id = cpu_to_le32(mvmvif->tsf_id);
0475 
0476     memcpy(cmd->node_addr, vif->addr, ETH_ALEN);
0477 
0478     if (bssid)
0479         memcpy(cmd->bssid_addr, bssid, ETH_ALEN);
0480     else
0481         eth_broadcast_addr(cmd->bssid_addr);
0482 
0483     rcu_read_lock();
0484     chanctx = rcu_dereference(vif->bss_conf.chanctx_conf);
0485     iwl_mvm_ack_rates(mvm, vif, chanctx ? chanctx->def.chan->band
0486                         : NL80211_BAND_2GHZ,
0487               &cck_ack_rates, &ofdm_ack_rates);
0488     rcu_read_unlock();
0489 
0490     cmd->cck_rates = cpu_to_le32((u32)cck_ack_rates);
0491     cmd->ofdm_rates = cpu_to_le32((u32)ofdm_ack_rates);
0492 
0493     cmd->cck_short_preamble =
0494         cpu_to_le32(vif->bss_conf.use_short_preamble ?
0495                 MAC_FLG_SHORT_PREAMBLE : 0);
0496     cmd->short_slot =
0497         cpu_to_le32(vif->bss_conf.use_short_slot ?
0498                 MAC_FLG_SHORT_SLOT : 0);
0499 
0500     cmd->filter_flags = 0;
0501 
0502     for (i = 0; i < IEEE80211_NUM_ACS; i++) {
0503         u8 txf = iwl_mvm_mac_ac_to_tx_fifo(mvm, i);
0504         u8 ucode_ac = iwl_mvm_mac80211_ac_to_ucode_ac(i);
0505 
0506         cmd->ac[ucode_ac].cw_min =
0507             cpu_to_le16(mvmvif->queue_params[i].cw_min);
0508         cmd->ac[ucode_ac].cw_max =
0509             cpu_to_le16(mvmvif->queue_params[i].cw_max);
0510         cmd->ac[ucode_ac].edca_txop =
0511             cpu_to_le16(mvmvif->queue_params[i].txop * 32);
0512         cmd->ac[ucode_ac].aifsn = mvmvif->queue_params[i].aifs;
0513         cmd->ac[ucode_ac].fifos_mask = BIT(txf);
0514     }
0515 
0516     if (vif->bss_conf.qos)
0517         cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA);
0518 
0519     if (vif->bss_conf.use_cts_prot)
0520         cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT);
0521 
0522     IWL_DEBUG_RATE(mvm, "use_cts_prot %d, ht_operation_mode %d\n",
0523                vif->bss_conf.use_cts_prot,
0524                vif->bss_conf.ht_operation_mode);
0525     if (vif->bss_conf.chandef.width != NL80211_CHAN_WIDTH_20_NOHT)
0526         cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_TGN);
0527     if (ht_enabled)
0528         iwl_mvm_mac_ctxt_set_ht_flags(mvm, vif, cmd);
0529 }
0530 
0531 static int iwl_mvm_mac_ctxt_send_cmd(struct iwl_mvm *mvm,
0532                      struct iwl_mac_ctx_cmd *cmd)
0533 {
0534     int ret = iwl_mvm_send_cmd_pdu(mvm, MAC_CONTEXT_CMD, 0,
0535                        sizeof(*cmd), cmd);
0536     if (ret)
0537         IWL_ERR(mvm, "Failed to send MAC context (action:%d): %d\n",
0538             le32_to_cpu(cmd->action), ret);
0539     return ret;
0540 }
0541 
0542 static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
0543                     struct ieee80211_vif *vif,
0544                     u32 action, bool force_assoc_off,
0545                     const u8 *bssid_override)
0546 {
0547     struct iwl_mac_ctx_cmd cmd = {};
0548     struct iwl_mac_data_sta *ctxt_sta;
0549 
0550     WARN_ON(vif->type != NL80211_IFTYPE_STATION);
0551 
0552     /* Fill the common data for all mac context types */
0553     iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, bssid_override, action);
0554 
0555     /*
0556      * We always want to hear MCAST frames, if we're not authorized yet,
0557      * we'll drop them.
0558      */
0559     cmd.filter_flags |= cpu_to_le32(MAC_FILTER_ACCEPT_GRP);
0560 
0561     if (vif->p2p) {
0562         struct ieee80211_p2p_noa_attr *noa =
0563             &vif->bss_conf.p2p_noa_attr;
0564 
0565         cmd.p2p_sta.ctwin = cpu_to_le32(noa->oppps_ctwindow &
0566                     IEEE80211_P2P_OPPPS_CTWINDOW_MASK);
0567         ctxt_sta = &cmd.p2p_sta.sta;
0568     } else {
0569         ctxt_sta = &cmd.sta;
0570     }
0571 
0572     /* We need the dtim_period to set the MAC as associated */
0573     if (vif->cfg.assoc && vif->bss_conf.dtim_period &&
0574         !force_assoc_off) {
0575         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
0576         u32 dtim_offs;
0577 
0578         /*
0579          * The DTIM count counts down, so when it is N that means N
0580          * more beacon intervals happen until the DTIM TBTT. Therefore
0581          * add this to the current time. If that ends up being in the
0582          * future, the firmware will handle it.
0583          *
0584          * Also note that the system_timestamp (which we get here as
0585          * "sync_device_ts") and TSF timestamp aren't at exactly the
0586          * same offset in the frame -- the TSF is at the first symbol
0587          * of the TSF, the system timestamp is at signal acquisition
0588          * time. This means there's an offset between them of at most
0589          * a few hundred microseconds (24 * 8 bits + PLCP time gives
0590          * 384us in the longest case), this is currently not relevant
0591          * as the firmware wakes up around 2ms before the TBTT.
0592          */
0593         dtim_offs = vif->bss_conf.sync_dtim_count *
0594                 vif->bss_conf.beacon_int;
0595         /* convert TU to usecs */
0596         dtim_offs *= 1024;
0597 
0598         ctxt_sta->dtim_tsf =
0599             cpu_to_le64(vif->bss_conf.sync_tsf + dtim_offs);
0600         ctxt_sta->dtim_time =
0601             cpu_to_le32(vif->bss_conf.sync_device_ts + dtim_offs);
0602         ctxt_sta->assoc_beacon_arrive_time =
0603             cpu_to_le32(vif->bss_conf.sync_device_ts);
0604 
0605         IWL_DEBUG_INFO(mvm, "DTIM TBTT is 0x%llx/0x%x, offset %d\n",
0606                    le64_to_cpu(ctxt_sta->dtim_tsf),
0607                    le32_to_cpu(ctxt_sta->dtim_time),
0608                    dtim_offs);
0609 
0610         ctxt_sta->is_assoc = cpu_to_le32(1);
0611 
0612         if (!mvmvif->authorized &&
0613             fw_has_capa(&mvm->fw->ucode_capa,
0614                 IWL_UCODE_TLV_CAPA_COEX_HIGH_PRIO))
0615             ctxt_sta->data_policy |=
0616                 cpu_to_le32(COEX_HIGH_PRIORITY_ENABLE);
0617     } else {
0618         ctxt_sta->is_assoc = cpu_to_le32(0);
0619 
0620         /* Allow beacons to pass through as long as we are not
0621          * associated, or we do not have dtim period information.
0622          */
0623         cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON);
0624     }
0625 
0626     ctxt_sta->bi = cpu_to_le32(vif->bss_conf.beacon_int);
0627     ctxt_sta->dtim_interval = cpu_to_le32(vif->bss_conf.beacon_int *
0628                           vif->bss_conf.dtim_period);
0629 
0630     ctxt_sta->listen_interval = cpu_to_le32(mvm->hw->conf.listen_interval);
0631     ctxt_sta->assoc_id = cpu_to_le32(vif->cfg.aid);
0632 
0633     if (vif->probe_req_reg && vif->cfg.assoc && vif->p2p)
0634         cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
0635 
0636     if (vif->bss_conf.he_support && !iwlwifi_mod_params.disable_11ax) {
0637         cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_11AX);
0638         if (vif->bss_conf.twt_requester && IWL_MVM_USE_TWT)
0639             ctxt_sta->data_policy |= cpu_to_le32(TWT_SUPPORTED);
0640         if (vif->bss_conf.twt_protected)
0641             ctxt_sta->data_policy |=
0642                 cpu_to_le32(PROTECTED_TWT_SUPPORTED);
0643         if (vif->bss_conf.twt_broadcast)
0644             ctxt_sta->data_policy |=
0645                 cpu_to_le32(BROADCAST_TWT_SUPPORTED);
0646     }
0647 
0648 
0649     return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
0650 }
0651 
0652 static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,
0653                      struct ieee80211_vif *vif,
0654                      u32 action)
0655 {
0656     struct iwl_mac_ctx_cmd cmd = {};
0657     u32 tfd_queue_msk = BIT(mvm->snif_queue);
0658     int ret;
0659 
0660     WARN_ON(vif->type != NL80211_IFTYPE_MONITOR);
0661 
0662     iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
0663 
0664     cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROMISC |
0665                        MAC_FILTER_IN_CONTROL_AND_MGMT |
0666                        MAC_FILTER_IN_BEACON |
0667                        MAC_FILTER_IN_PROBE_REQUEST |
0668                        MAC_FILTER_IN_CRC32 |
0669                        MAC_FILTER_ACCEPT_GRP);
0670     ieee80211_hw_set(mvm->hw, RX_INCLUDES_FCS);
0671 
0672     /* Allocate sniffer station */
0673     ret = iwl_mvm_allocate_int_sta(mvm, &mvm->snif_sta, tfd_queue_msk,
0674                        vif->type, IWL_STA_GENERAL_PURPOSE);
0675     if (ret)
0676         return ret;
0677 
0678     return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
0679 }
0680 
0681 static int iwl_mvm_mac_ctxt_cmd_ibss(struct iwl_mvm *mvm,
0682                      struct ieee80211_vif *vif,
0683                      u32 action)
0684 {
0685     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
0686     struct iwl_mac_ctx_cmd cmd = {};
0687 
0688     WARN_ON(vif->type != NL80211_IFTYPE_ADHOC);
0689 
0690     iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
0691 
0692     cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_BEACON |
0693                        MAC_FILTER_IN_PROBE_REQUEST |
0694                        MAC_FILTER_ACCEPT_GRP);
0695 
0696     /* cmd.ibss.beacon_time/cmd.ibss.beacon_tsf are curently ignored */
0697     cmd.ibss.bi = cpu_to_le32(vif->bss_conf.beacon_int);
0698 
0699     /* TODO: Assumes that the beacon id == mac context id */
0700     cmd.ibss.beacon_template = cpu_to_le32(mvmvif->id);
0701 
0702     return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
0703 }
0704 
0705 struct iwl_mvm_go_iterator_data {
0706     bool go_active;
0707 };
0708 
0709 static void iwl_mvm_go_iterator(void *_data, u8 *mac, struct ieee80211_vif *vif)
0710 {
0711     struct iwl_mvm_go_iterator_data *data = _data;
0712     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
0713 
0714     if (vif->type == NL80211_IFTYPE_AP && vif->p2p &&
0715         mvmvif->ap_ibss_active)
0716         data->go_active = true;
0717 }
0718 
0719 static int iwl_mvm_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm,
0720                        struct ieee80211_vif *vif,
0721                        u32 action)
0722 {
0723     struct iwl_mac_ctx_cmd cmd = {};
0724     struct iwl_mvm_go_iterator_data data = {};
0725 
0726     WARN_ON(vif->type != NL80211_IFTYPE_P2P_DEVICE);
0727 
0728     iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
0729 
0730     /* Override the filter flags to accept only probe requests */
0731     cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
0732 
0733     /*
0734      * This flag should be set to true when the P2P Device is
0735      * discoverable and there is at least another active P2P GO. Settings
0736      * this flag will allow the P2P Device to be discoverable on other
0737      * channels in addition to its listen channel.
0738      * Note that this flag should not be set in other cases as it opens the
0739      * Rx filters on all MAC and increases the number of interrupts.
0740      */
0741     ieee80211_iterate_active_interfaces_atomic(
0742         mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
0743         iwl_mvm_go_iterator, &data);
0744 
0745     cmd.p2p_dev.is_disc_extended = cpu_to_le32(data.go_active ? 1 : 0);
0746     return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
0747 }
0748 
0749 void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm,
0750                   __le32 *tim_index, __le32 *tim_size,
0751                   u8 *beacon, u32 frame_size)
0752 {
0753     u32 tim_idx;
0754     struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon;
0755 
0756     /* The index is relative to frame start but we start looking at the
0757      * variable-length part of the beacon. */
0758     tim_idx = mgmt->u.beacon.variable - beacon;
0759 
0760     /* Parse variable-length elements of beacon to find WLAN_EID_TIM */
0761     while ((tim_idx < (frame_size - 2)) &&
0762             (beacon[tim_idx] != WLAN_EID_TIM))
0763         tim_idx += beacon[tim_idx+1] + 2;
0764 
0765     /* If TIM field was found, set variables */
0766     if ((tim_idx < (frame_size - 1)) && (beacon[tim_idx] == WLAN_EID_TIM)) {
0767         *tim_index = cpu_to_le32(tim_idx);
0768         *tim_size = cpu_to_le32((u32)beacon[tim_idx + 1]);
0769     } else {
0770         IWL_WARN(mvm, "Unable to find TIM Element in beacon\n");
0771     }
0772 }
0773 
0774 static u32 iwl_mvm_find_ie_offset(u8 *beacon, u8 eid, u32 frame_size)
0775 {
0776     struct ieee80211_mgmt *mgmt = (void *)beacon;
0777     const u8 *ie;
0778 
0779     if (WARN_ON_ONCE(frame_size <= (mgmt->u.beacon.variable - beacon)))
0780         return 0;
0781 
0782     frame_size -= mgmt->u.beacon.variable - beacon;
0783 
0784     ie = cfg80211_find_ie(eid, mgmt->u.beacon.variable, frame_size);
0785     if (!ie)
0786         return 0;
0787 
0788     return ie - beacon;
0789 }
0790 
0791 u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info,
0792                     struct ieee80211_vif *vif)
0793 {
0794     u8 rate;
0795     if (info->band == NL80211_BAND_2GHZ && !vif->p2p)
0796         rate = IWL_FIRST_CCK_RATE;
0797     else
0798         rate = IWL_FIRST_OFDM_RATE;
0799 
0800     return rate;
0801 }
0802 
0803 u16 iwl_mvm_mac_ctxt_get_beacon_flags(const struct iwl_fw *fw, u8 rate_idx)
0804 {
0805     u16 flags = iwl_mvm_mac80211_idx_to_hwrate(fw, rate_idx);
0806     bool is_new_rate = iwl_fw_lookup_cmd_ver(fw, BEACON_TEMPLATE_CMD, 0) > 10;
0807 
0808     if (rate_idx <= IWL_FIRST_CCK_RATE)
0809         flags |= is_new_rate ? IWL_MAC_BEACON_CCK
0810               : IWL_MAC_BEACON_CCK_V1;
0811 
0812     return flags;
0813 }
0814 
0815 static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm,
0816                     struct ieee80211_vif *vif,
0817                     struct sk_buff *beacon,
0818                     struct iwl_tx_cmd *tx)
0819 {
0820     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
0821     struct ieee80211_tx_info *info;
0822     u8 rate;
0823     u32 tx_flags;
0824 
0825     info = IEEE80211_SKB_CB(beacon);
0826 
0827     /* Set up TX command fields */
0828     tx->len = cpu_to_le16((u16)beacon->len);
0829     tx->sta_id = mvmvif->bcast_sta.sta_id;
0830     tx->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
0831     tx_flags = TX_CMD_FLG_SEQ_CTL | TX_CMD_FLG_TSF;
0832     tx_flags |=
0833         iwl_mvm_bt_coex_tx_prio(mvm, (void *)beacon->data, info, 0) <<
0834                         TX_CMD_FLG_BT_PRIO_POS;
0835     tx->tx_flags = cpu_to_le32(tx_flags);
0836 
0837     if (!fw_has_capa(&mvm->fw->ucode_capa,
0838              IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION))
0839         iwl_mvm_toggle_tx_ant(mvm, &mvm->mgmt_last_antenna_idx);
0840 
0841     tx->rate_n_flags =
0842         cpu_to_le32(BIT(mvm->mgmt_last_antenna_idx) <<
0843                 RATE_MCS_ANT_POS);
0844 
0845     rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif);
0846 
0847     tx->rate_n_flags |=
0848         cpu_to_le32(iwl_mvm_mac80211_idx_to_hwrate(mvm->fw, rate));
0849     if (rate == IWL_FIRST_CCK_RATE)
0850         tx->rate_n_flags |= cpu_to_le32(RATE_MCS_CCK_MSK_V1);
0851 
0852 }
0853 
0854 int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm,
0855                      struct sk_buff *beacon,
0856                      void *data, int len)
0857 {
0858     struct iwl_host_cmd cmd = {
0859         .id = BEACON_TEMPLATE_CMD,
0860         .flags = CMD_ASYNC,
0861     };
0862 
0863     cmd.len[0] = len;
0864     cmd.data[0] = data;
0865     cmd.dataflags[0] = 0;
0866     cmd.len[1] = beacon->len;
0867     cmd.data[1] = beacon->data;
0868     cmd.dataflags[1] = IWL_HCMD_DFL_DUP;
0869 
0870     return iwl_mvm_send_cmd(mvm, &cmd);
0871 }
0872 
0873 static int iwl_mvm_mac_ctxt_send_beacon_v6(struct iwl_mvm *mvm,
0874                        struct ieee80211_vif *vif,
0875                        struct sk_buff *beacon)
0876 {
0877     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
0878     struct iwl_mac_beacon_cmd_v6 beacon_cmd = {};
0879 
0880     iwl_mvm_mac_ctxt_set_tx(mvm, vif, beacon, &beacon_cmd.tx);
0881 
0882     beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id);
0883 
0884     if (vif->type == NL80211_IFTYPE_AP)
0885         iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx,
0886                      &beacon_cmd.tim_size,
0887                      beacon->data, beacon->len);
0888 
0889     return iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd,
0890                         sizeof(beacon_cmd));
0891 }
0892 
0893 static int iwl_mvm_mac_ctxt_send_beacon_v7(struct iwl_mvm *mvm,
0894                        struct ieee80211_vif *vif,
0895                        struct sk_buff *beacon)
0896 {
0897     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
0898     struct iwl_mac_beacon_cmd_v7 beacon_cmd = {};
0899 
0900     iwl_mvm_mac_ctxt_set_tx(mvm, vif, beacon, &beacon_cmd.tx);
0901 
0902     beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id);
0903 
0904     if (vif->type == NL80211_IFTYPE_AP)
0905         iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx,
0906                      &beacon_cmd.tim_size,
0907                      beacon->data, beacon->len);
0908 
0909     beacon_cmd.csa_offset =
0910         cpu_to_le32(iwl_mvm_find_ie_offset(beacon->data,
0911                            WLAN_EID_CHANNEL_SWITCH,
0912                            beacon->len));
0913     beacon_cmd.ecsa_offset =
0914         cpu_to_le32(iwl_mvm_find_ie_offset(beacon->data,
0915                            WLAN_EID_EXT_CHANSWITCH_ANN,
0916                            beacon->len));
0917 
0918     return iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd,
0919                         sizeof(beacon_cmd));
0920 }
0921 
0922 static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,
0923                        struct ieee80211_vif *vif,
0924                        struct sk_buff *beacon)
0925 {
0926     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
0927     struct ieee80211_tx_info *info = IEEE80211_SKB_CB(beacon);
0928     struct iwl_mac_beacon_cmd beacon_cmd = {};
0929     u8 rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif);
0930     u16 flags;
0931     struct ieee80211_chanctx_conf *ctx;
0932     int channel;
0933     flags = iwl_mvm_mac_ctxt_get_beacon_flags(mvm->fw, rate);
0934 
0935     /* Enable FILS on PSC channels only */
0936     rcu_read_lock();
0937     ctx = rcu_dereference(vif->bss_conf.chanctx_conf);
0938     channel = ieee80211_frequency_to_channel(ctx->def.chan->center_freq);
0939     WARN_ON(channel == 0);
0940     if (cfg80211_channel_is_psc(ctx->def.chan) &&
0941         !IWL_MVM_DISABLE_AP_FILS) {
0942         flags |= iwl_fw_lookup_cmd_ver(mvm->fw, BEACON_TEMPLATE_CMD,
0943                            0) > 10 ?
0944             IWL_MAC_BEACON_FILS :
0945             IWL_MAC_BEACON_FILS_V1;
0946         beacon_cmd.short_ssid =
0947             cpu_to_le32(~crc32_le(~0, vif->cfg.ssid,
0948                           vif->cfg.ssid_len));
0949     }
0950     rcu_read_unlock();
0951 
0952     beacon_cmd.flags = cpu_to_le16(flags);
0953     beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len);
0954     beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id);
0955 
0956     if (vif->type == NL80211_IFTYPE_AP)
0957         iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx,
0958                      &beacon_cmd.tim_size,
0959                      beacon->data, beacon->len);
0960 
0961     beacon_cmd.csa_offset =
0962         cpu_to_le32(iwl_mvm_find_ie_offset(beacon->data,
0963                            WLAN_EID_CHANNEL_SWITCH,
0964                            beacon->len));
0965     beacon_cmd.ecsa_offset =
0966         cpu_to_le32(iwl_mvm_find_ie_offset(beacon->data,
0967                            WLAN_EID_EXT_CHANSWITCH_ANN,
0968                            beacon->len));
0969 
0970     return iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd,
0971                         sizeof(beacon_cmd));
0972 }
0973 
0974 int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
0975                  struct ieee80211_vif *vif,
0976                  struct sk_buff *beacon)
0977 {
0978     if (WARN_ON(!beacon))
0979         return -EINVAL;
0980 
0981     if (IWL_MVM_NON_TRANSMITTING_AP)
0982         return 0;
0983 
0984     if (!fw_has_capa(&mvm->fw->ucode_capa,
0985              IWL_UCODE_TLV_CAPA_CSA_AND_TBTT_OFFLOAD))
0986         return iwl_mvm_mac_ctxt_send_beacon_v6(mvm, vif, beacon);
0987 
0988     if (fw_has_api(&mvm->fw->ucode_capa,
0989                IWL_UCODE_TLV_API_NEW_BEACON_TEMPLATE))
0990         return iwl_mvm_mac_ctxt_send_beacon_v9(mvm, vif, beacon);
0991 
0992     return iwl_mvm_mac_ctxt_send_beacon_v7(mvm, vif, beacon);
0993 }
0994 
0995 /* The beacon template for the AP/GO/IBSS has changed and needs update */
0996 int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
0997                     struct ieee80211_vif *vif)
0998 {
0999     struct sk_buff *beacon;
1000     int ret;
1001 
1002     WARN_ON(vif->type != NL80211_IFTYPE_AP &&
1003         vif->type != NL80211_IFTYPE_ADHOC);
1004 
1005     beacon = ieee80211_beacon_get_template(mvm->hw, vif, NULL, 0);
1006     if (!beacon)
1007         return -ENOMEM;
1008 
1009 #ifdef CONFIG_IWLWIFI_DEBUGFS
1010     if (mvm->beacon_inject_active) {
1011         dev_kfree_skb(beacon);
1012         return -EBUSY;
1013     }
1014 #endif
1015 
1016     ret = iwl_mvm_mac_ctxt_send_beacon(mvm, vif, beacon);
1017     dev_kfree_skb(beacon);
1018     return ret;
1019 }
1020 
1021 struct iwl_mvm_mac_ap_iterator_data {
1022     struct iwl_mvm *mvm;
1023     struct ieee80211_vif *vif;
1024     u32 beacon_device_ts;
1025     u16 beacon_int;
1026 };
1027 
1028 /* Find the beacon_device_ts and beacon_int for a managed interface */
1029 static void iwl_mvm_mac_ap_iterator(void *_data, u8 *mac,
1030                     struct ieee80211_vif *vif)
1031 {
1032     struct iwl_mvm_mac_ap_iterator_data *data = _data;
1033 
1034     if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc)
1035         return;
1036 
1037     /* Station client has higher priority over P2P client*/
1038     if (vif->p2p && data->beacon_device_ts)
1039         return;
1040 
1041     data->beacon_device_ts = vif->bss_conf.sync_device_ts;
1042     data->beacon_int = vif->bss_conf.beacon_int;
1043 }
1044 
1045 /*
1046  * Fill the specific data for mac context of type AP of P2P GO
1047  */
1048 static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm,
1049                      struct ieee80211_vif *vif,
1050                      struct iwl_mac_ctx_cmd *cmd,
1051                      struct iwl_mac_data_ap *ctxt_ap,
1052                      bool add)
1053 {
1054     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1055     struct iwl_mvm_mac_ap_iterator_data data = {
1056         .mvm = mvm,
1057         .vif = vif,
1058         .beacon_device_ts = 0
1059     };
1060 
1061     /* in AP mode, the MCAST FIFO takes the EDCA params from VO */
1062     cmd->ac[IWL_MVM_TX_FIFO_VO].fifos_mask |= BIT(IWL_MVM_TX_FIFO_MCAST);
1063 
1064     /*
1065      * in AP mode, pass probe requests and beacons from other APs
1066      * (needed for ht protection); when there're no any associated
1067      * station don't ask FW to pass beacons to prevent unnecessary
1068      * wake-ups.
1069      */
1070     cmd->filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
1071     if (mvmvif->ap_assoc_sta_count || !mvm->drop_bcn_ap_mode) {
1072         cmd->filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON);
1073         IWL_DEBUG_HC(mvm, "Asking FW to pass beacons\n");
1074     } else {
1075         IWL_DEBUG_HC(mvm, "No need to receive beacons\n");
1076     }
1077 
1078     ctxt_ap->bi = cpu_to_le32(vif->bss_conf.beacon_int);
1079     ctxt_ap->dtim_interval = cpu_to_le32(vif->bss_conf.beacon_int *
1080                          vif->bss_conf.dtim_period);
1081 
1082     if (!fw_has_api(&mvm->fw->ucode_capa,
1083             IWL_UCODE_TLV_API_STA_TYPE))
1084         ctxt_ap->mcast_qid = cpu_to_le32(mvmvif->cab_queue);
1085 
1086     /*
1087      * Only set the beacon time when the MAC is being added, when we
1088      * just modify the MAC then we should keep the time -- the firmware
1089      * can otherwise have a "jumping" TBTT.
1090      */
1091     if (add) {
1092         /*
1093          * If there is a station/P2P client interface which is
1094          * associated, set the AP's TBTT far enough from the station's
1095          * TBTT. Otherwise, set it to the current system time
1096          */
1097         ieee80211_iterate_active_interfaces_atomic(
1098             mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
1099             iwl_mvm_mac_ap_iterator, &data);
1100 
1101         if (data.beacon_device_ts) {
1102             u32 rand = (prandom_u32() % (64 - 36)) + 36;
1103             mvmvif->ap_beacon_time = data.beacon_device_ts +
1104                 ieee80211_tu_to_usec(data.beacon_int * rand /
1105                              100);
1106         } else {
1107             mvmvif->ap_beacon_time = iwl_mvm_get_systime(mvm);
1108         }
1109     }
1110 
1111     ctxt_ap->beacon_time = cpu_to_le32(mvmvif->ap_beacon_time);
1112     ctxt_ap->beacon_tsf = 0; /* unused */
1113 
1114     /* TODO: Assume that the beacon id == mac context id */
1115     ctxt_ap->beacon_template = cpu_to_le32(mvmvif->id);
1116 }
1117 
1118 static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm,
1119                    struct ieee80211_vif *vif,
1120                    u32 action)
1121 {
1122     struct iwl_mac_ctx_cmd cmd = {};
1123 
1124     WARN_ON(vif->type != NL80211_IFTYPE_AP || vif->p2p);
1125 
1126     /* Fill the common data for all mac context types */
1127     iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
1128 
1129     /* Fill the data specific for ap mode */
1130     iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd, &cmd.ap,
1131                      action == FW_CTXT_ACTION_ADD);
1132 
1133     return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
1134 }
1135 
1136 static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm,
1137                    struct ieee80211_vif *vif,
1138                    u32 action)
1139 {
1140     struct iwl_mac_ctx_cmd cmd = {};
1141     struct ieee80211_p2p_noa_attr *noa = &vif->bss_conf.p2p_noa_attr;
1142 
1143     WARN_ON(vif->type != NL80211_IFTYPE_AP || !vif->p2p);
1144 
1145     /* Fill the common data for all mac context types */
1146     iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
1147 
1148     /* Fill the data specific for GO mode */
1149     iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd, &cmd.go.ap,
1150                      action == FW_CTXT_ACTION_ADD);
1151 
1152     cmd.go.ctwin = cpu_to_le32(noa->oppps_ctwindow &
1153                     IEEE80211_P2P_OPPPS_CTWINDOW_MASK);
1154     cmd.go.opp_ps_enabled =
1155             cpu_to_le32(!!(noa->oppps_ctwindow &
1156                     IEEE80211_P2P_OPPPS_ENABLE_BIT));
1157 
1158     return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
1159 }
1160 
1161 static int iwl_mvm_mac_ctx_send(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
1162                 u32 action, bool force_assoc_off,
1163                 const u8 *bssid_override)
1164 {
1165     switch (vif->type) {
1166     case NL80211_IFTYPE_STATION:
1167         return iwl_mvm_mac_ctxt_cmd_sta(mvm, vif, action,
1168                         force_assoc_off,
1169                         bssid_override);
1170     case NL80211_IFTYPE_AP:
1171         if (!vif->p2p)
1172             return iwl_mvm_mac_ctxt_cmd_ap(mvm, vif, action);
1173         else
1174             return iwl_mvm_mac_ctxt_cmd_go(mvm, vif, action);
1175     case NL80211_IFTYPE_MONITOR:
1176         return iwl_mvm_mac_ctxt_cmd_listener(mvm, vif, action);
1177     case NL80211_IFTYPE_P2P_DEVICE:
1178         return iwl_mvm_mac_ctxt_cmd_p2p_device(mvm, vif, action);
1179     case NL80211_IFTYPE_ADHOC:
1180         return iwl_mvm_mac_ctxt_cmd_ibss(mvm, vif, action);
1181     default:
1182         break;
1183     }
1184 
1185     return -EOPNOTSUPP;
1186 }
1187 
1188 int iwl_mvm_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
1189 {
1190     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1191     int ret;
1192 
1193     if (WARN_ONCE(mvmvif->uploaded, "Adding active MAC %pM/%d\n",
1194               vif->addr, ieee80211_vif_type_p2p(vif)))
1195         return -EIO;
1196 
1197     ret = iwl_mvm_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_ADD,
1198                    true, NULL);
1199     if (ret)
1200         return ret;
1201 
1202     /* will only do anything at resume from D3 time */
1203     iwl_mvm_set_last_nonqos_seq(mvm, vif);
1204 
1205     mvmvif->uploaded = true;
1206     return 0;
1207 }
1208 
1209 int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
1210                  bool force_assoc_off, const u8 *bssid_override)
1211 {
1212     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1213 
1214     if (WARN_ONCE(!mvmvif->uploaded, "Changing inactive MAC %pM/%d\n",
1215               vif->addr, ieee80211_vif_type_p2p(vif)))
1216         return -EIO;
1217 
1218     return iwl_mvm_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_MODIFY,
1219                     force_assoc_off, bssid_override);
1220 }
1221 
1222 int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
1223 {
1224     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1225     struct iwl_mac_ctx_cmd cmd;
1226     int ret;
1227 
1228     if (WARN_ONCE(!mvmvif->uploaded, "Removing inactive MAC %pM/%d\n",
1229               vif->addr, ieee80211_vif_type_p2p(vif)))
1230         return -EIO;
1231 
1232     memset(&cmd, 0, sizeof(cmd));
1233 
1234     cmd.id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
1235                                mvmvif->color));
1236     cmd.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE);
1237 
1238     ret = iwl_mvm_send_cmd_pdu(mvm, MAC_CONTEXT_CMD, 0,
1239                    sizeof(cmd), &cmd);
1240     if (ret) {
1241         IWL_ERR(mvm, "Failed to remove MAC context: %d\n", ret);
1242         return ret;
1243     }
1244 
1245     mvmvif->uploaded = false;
1246 
1247     if (vif->type == NL80211_IFTYPE_MONITOR) {
1248         __clear_bit(IEEE80211_HW_RX_INCLUDES_FCS, mvm->hw->flags);
1249         iwl_mvm_dealloc_snif_sta(mvm);
1250     }
1251 
1252     return 0;
1253 }
1254 
1255 static void iwl_mvm_csa_count_down(struct iwl_mvm *mvm,
1256                    struct ieee80211_vif *csa_vif, u32 gp2,
1257                    bool tx_success)
1258 {
1259     struct iwl_mvm_vif *mvmvif =
1260             iwl_mvm_vif_from_mac80211(csa_vif);
1261 
1262     /* Don't start to countdown from a failed beacon */
1263     if (!tx_success && !mvmvif->csa_countdown)
1264         return;
1265 
1266     mvmvif->csa_countdown = true;
1267 
1268     if (!ieee80211_beacon_cntdwn_is_complete(csa_vif)) {
1269         int c = ieee80211_beacon_update_cntdwn(csa_vif);
1270 
1271         iwl_mvm_mac_ctxt_beacon_changed(mvm, csa_vif);
1272         if (csa_vif->p2p &&
1273             !iwl_mvm_te_scheduled(&mvmvif->time_event_data) && gp2 &&
1274             tx_success) {
1275             u32 rel_time = (c + 1) *
1276                        csa_vif->bss_conf.beacon_int -
1277                        IWL_MVM_CHANNEL_SWITCH_TIME_GO;
1278             u32 apply_time = gp2 + rel_time * 1024;
1279 
1280             iwl_mvm_schedule_csa_period(mvm, csa_vif,
1281                      IWL_MVM_CHANNEL_SWITCH_TIME_GO -
1282                      IWL_MVM_CHANNEL_SWITCH_MARGIN,
1283                      apply_time);
1284         }
1285     } else if (!iwl_mvm_te_scheduled(&mvmvif->time_event_data)) {
1286         /* we don't have CSA NoA scheduled yet, switch now */
1287         ieee80211_csa_finish(csa_vif);
1288         RCU_INIT_POINTER(mvm->csa_vif, NULL);
1289     }
1290 }
1291 
1292 void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
1293                  struct iwl_rx_cmd_buffer *rxb)
1294 {
1295     struct iwl_rx_packet *pkt = rxb_addr(rxb);
1296     unsigned int pkt_len = iwl_rx_packet_payload_len(pkt);
1297     struct iwl_extended_beacon_notif *beacon = (void *)pkt->data;
1298     struct iwl_extended_beacon_notif_v5 *beacon_v5 = (void *)pkt->data;
1299     struct ieee80211_vif *csa_vif;
1300     struct ieee80211_vif *tx_blocked_vif;
1301     struct agg_tx_status *agg_status;
1302     u16 status;
1303 
1304     lockdep_assert_held(&mvm->mutex);
1305 
1306     mvm->ap_last_beacon_gp2 = le32_to_cpu(beacon->gp2);
1307 
1308     if (!iwl_mvm_is_short_beacon_notif_supported(mvm)) {
1309         struct iwl_mvm_tx_resp *beacon_notify_hdr =
1310             &beacon_v5->beacon_notify_hdr;
1311 
1312         if (unlikely(pkt_len < sizeof(*beacon_v5)))
1313             return;
1314 
1315         mvm->ibss_manager = beacon_v5->ibss_mgr_status != 0;
1316         agg_status = iwl_mvm_get_agg_status(mvm, beacon_notify_hdr);
1317         status = le16_to_cpu(agg_status->status) & TX_STATUS_MSK;
1318         IWL_DEBUG_RX(mvm,
1319                  "beacon status %#x retries:%d tsf:0x%016llX gp2:0x%X rate:%d\n",
1320                  status, beacon_notify_hdr->failure_frame,
1321                  le64_to_cpu(beacon->tsf),
1322                  mvm->ap_last_beacon_gp2,
1323                  le32_to_cpu(beacon_notify_hdr->initial_rate));
1324     } else {
1325         if (unlikely(pkt_len < sizeof(*beacon)))
1326             return;
1327 
1328         mvm->ibss_manager = beacon->ibss_mgr_status != 0;
1329         status = le32_to_cpu(beacon->status) & TX_STATUS_MSK;
1330         IWL_DEBUG_RX(mvm,
1331                  "beacon status %#x tsf:0x%016llX gp2:0x%X\n",
1332                  status, le64_to_cpu(beacon->tsf),
1333                  mvm->ap_last_beacon_gp2);
1334     }
1335 
1336     csa_vif = rcu_dereference_protected(mvm->csa_vif,
1337                         lockdep_is_held(&mvm->mutex));
1338     if (unlikely(csa_vif && csa_vif->bss_conf.csa_active))
1339         iwl_mvm_csa_count_down(mvm, csa_vif, mvm->ap_last_beacon_gp2,
1340                        (status == TX_STATUS_SUCCESS));
1341 
1342     tx_blocked_vif = rcu_dereference_protected(mvm->csa_tx_blocked_vif,
1343                         lockdep_is_held(&mvm->mutex));
1344     if (unlikely(tx_blocked_vif)) {
1345         struct iwl_mvm_vif *mvmvif =
1346             iwl_mvm_vif_from_mac80211(tx_blocked_vif);
1347 
1348         /*
1349          * The channel switch is started and we have blocked the
1350          * stations. If this is the first beacon (the timeout wasn't
1351          * set), set the unblock timeout, otherwise countdown
1352          */
1353         if (!mvm->csa_tx_block_bcn_timeout)
1354             mvm->csa_tx_block_bcn_timeout =
1355                 IWL_MVM_CS_UNBLOCK_TX_TIMEOUT;
1356         else
1357             mvm->csa_tx_block_bcn_timeout--;
1358 
1359         /* Check if the timeout is expired, and unblock tx */
1360         if (mvm->csa_tx_block_bcn_timeout == 0) {
1361             iwl_mvm_modify_all_sta_disable_tx(mvm, mvmvif, false);
1362             RCU_INIT_POINTER(mvm->csa_tx_blocked_vif, NULL);
1363         }
1364     }
1365 }
1366 
1367 void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
1368                      struct iwl_rx_cmd_buffer *rxb)
1369 {
1370     struct iwl_rx_packet *pkt = rxb_addr(rxb);
1371     struct iwl_missed_beacons_notif *mb = (void *)pkt->data;
1372     struct iwl_fw_dbg_trigger_missed_bcon *bcon_trig;
1373     struct iwl_fw_dbg_trigger_tlv *trigger;
1374     u32 stop_trig_missed_bcon, stop_trig_missed_bcon_since_rx;
1375     u32 rx_missed_bcon, rx_missed_bcon_since_rx;
1376     struct ieee80211_vif *vif;
1377     u32 id = le32_to_cpu(mb->mac_id);
1378     union iwl_dbg_tlv_tp_data tp_data = { .fw_pkt = pkt };
1379 
1380     IWL_DEBUG_INFO(mvm,
1381                "missed bcn mac_id=%u, consecutive=%u (%u, %u, %u)\n",
1382                le32_to_cpu(mb->mac_id),
1383                le32_to_cpu(mb->consec_missed_beacons),
1384                le32_to_cpu(mb->consec_missed_beacons_since_last_rx),
1385                le32_to_cpu(mb->num_recvd_beacons),
1386                le32_to_cpu(mb->num_expected_beacons));
1387 
1388     rcu_read_lock();
1389 
1390     vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true);
1391     if (!vif)
1392         goto out;
1393 
1394     rx_missed_bcon = le32_to_cpu(mb->consec_missed_beacons);
1395     rx_missed_bcon_since_rx =
1396         le32_to_cpu(mb->consec_missed_beacons_since_last_rx);
1397     /*
1398      * TODO: the threshold should be adjusted based on latency conditions,
1399      * and/or in case of a CS flow on one of the other AP vifs.
1400      */
1401     if (rx_missed_bcon > IWL_MVM_MISSED_BEACONS_THRESHOLD_LONG)
1402         iwl_mvm_connection_loss(mvm, vif, "missed beacons");
1403     else if (rx_missed_bcon_since_rx > IWL_MVM_MISSED_BEACONS_THRESHOLD)
1404         ieee80211_beacon_loss(vif);
1405 
1406     iwl_dbg_tlv_time_point(&mvm->fwrt,
1407                    IWL_FW_INI_TIME_POINT_MISSED_BEACONS, &tp_data);
1408 
1409     trigger = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif),
1410                     FW_DBG_TRIGGER_MISSED_BEACONS);
1411     if (!trigger)
1412         goto out;
1413 
1414     bcon_trig = (void *)trigger->data;
1415     stop_trig_missed_bcon = le32_to_cpu(bcon_trig->stop_consec_missed_bcon);
1416     stop_trig_missed_bcon_since_rx =
1417         le32_to_cpu(bcon_trig->stop_consec_missed_bcon_since_rx);
1418 
1419     /* TODO: implement start trigger */
1420 
1421     if (rx_missed_bcon_since_rx >= stop_trig_missed_bcon_since_rx ||
1422         rx_missed_bcon >= stop_trig_missed_bcon)
1423         iwl_fw_dbg_collect_trig(&mvm->fwrt, trigger, NULL);
1424 
1425 out:
1426     rcu_read_unlock();
1427 }
1428 
1429 void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm,
1430                     struct iwl_rx_cmd_buffer *rxb)
1431 {
1432     struct iwl_rx_packet *pkt = rxb_addr(rxb);
1433     unsigned int pkt_len = iwl_rx_packet_payload_len(pkt);
1434     struct iwl_stored_beacon_notif_common *sb = (void *)pkt->data;
1435     struct ieee80211_rx_status rx_status;
1436     struct sk_buff *skb;
1437     u8 *data;
1438     u32 size = le32_to_cpu(sb->byte_count);
1439     int ver = iwl_fw_lookup_cmd_ver(mvm->fw,
1440                     WIDE_ID(PROT_OFFLOAD_GROUP, STORED_BEACON_NTF),
1441                     0);
1442 
1443     if (size == 0)
1444         return;
1445 
1446     /* handle per-version differences */
1447     if (ver <= 2) {
1448         struct iwl_stored_beacon_notif_v2 *sb_v2 = (void *)pkt->data;
1449 
1450         if (pkt_len < struct_size(sb_v2, data, size))
1451             return;
1452 
1453         data = sb_v2->data;
1454     } else {
1455         struct iwl_stored_beacon_notif_v3 *sb_v3 = (void *)pkt->data;
1456 
1457         if (pkt_len < struct_size(sb_v3, data, size))
1458             return;
1459 
1460         data = sb_v3->data;
1461     }
1462 
1463     skb = alloc_skb(size, GFP_ATOMIC);
1464     if (!skb) {
1465         IWL_ERR(mvm, "alloc_skb failed\n");
1466         return;
1467     }
1468 
1469     /* update rx_status according to the notification's metadata */
1470     memset(&rx_status, 0, sizeof(rx_status));
1471     rx_status.mactime = le64_to_cpu(sb->tsf);
1472     /* TSF as indicated by the firmware  is at INA time */
1473     rx_status.flag |= RX_FLAG_MACTIME_PLCP_START;
1474     rx_status.device_timestamp = le32_to_cpu(sb->system_time);
1475     rx_status.band =
1476         (sb->band & cpu_to_le16(RX_RES_PHY_FLAGS_BAND_24)) ?
1477                 NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
1478     rx_status.freq =
1479         ieee80211_channel_to_frequency(le16_to_cpu(sb->channel),
1480                            rx_status.band);
1481 
1482     /* copy the data */
1483     skb_put_data(skb, data, size);
1484     memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
1485 
1486     /* pass it as regular rx to mac80211 */
1487     ieee80211_rx_napi(mvm->hw, NULL, skb, NULL);
1488 }
1489 
1490 void iwl_mvm_probe_resp_data_notif(struct iwl_mvm *mvm,
1491                    struct iwl_rx_cmd_buffer *rxb)
1492 {
1493     struct iwl_rx_packet *pkt = rxb_addr(rxb);
1494     struct iwl_probe_resp_data_notif *notif = (void *)pkt->data;
1495     struct iwl_probe_resp_data *old_data, *new_data;
1496     u32 id = le32_to_cpu(notif->mac_id);
1497     struct ieee80211_vif *vif;
1498     struct iwl_mvm_vif *mvmvif;
1499 
1500     IWL_DEBUG_INFO(mvm, "Probe response data notif: noa %d, csa %d\n",
1501                notif->noa_active, notif->csa_counter);
1502 
1503     vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, false);
1504     if (!vif)
1505         return;
1506 
1507     mvmvif = iwl_mvm_vif_from_mac80211(vif);
1508 
1509     new_data = kzalloc(sizeof(*new_data), GFP_KERNEL);
1510     if (!new_data)
1511         return;
1512 
1513     memcpy(&new_data->notif, notif, sizeof(new_data->notif));
1514 
1515     /* noa_attr contains 1 reserved byte, need to substruct it */
1516     new_data->noa_len = sizeof(struct ieee80211_vendor_ie) +
1517                 sizeof(new_data->notif.noa_attr) - 1;
1518 
1519     /*
1520      * If it's a one time NoA, only one descriptor is needed,
1521      * adjust the length according to len_low.
1522      */
1523     if (new_data->notif.noa_attr.len_low ==
1524         sizeof(struct ieee80211_p2p_noa_desc) + 2)
1525         new_data->noa_len -= sizeof(struct ieee80211_p2p_noa_desc);
1526 
1527     old_data = rcu_dereference_protected(mvmvif->probe_resp_data,
1528                     lockdep_is_held(&mvmvif->mvm->mutex));
1529     rcu_assign_pointer(mvmvif->probe_resp_data, new_data);
1530 
1531     if (old_data)
1532         kfree_rcu(old_data, rcu_head);
1533 
1534     if (notif->csa_counter != IWL_PROBE_RESP_DATA_NO_CSA &&
1535         notif->csa_counter >= 1)
1536         ieee80211_beacon_set_cntdwn(vif, notif->csa_counter);
1537 }
1538 
1539 void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm,
1540                     struct iwl_rx_cmd_buffer *rxb)
1541 {
1542     struct iwl_rx_packet *pkt = rxb_addr(rxb);
1543     struct iwl_channel_switch_start_notif *notif = (void *)pkt->data;
1544     struct ieee80211_vif *csa_vif, *vif;
1545     struct iwl_mvm_vif *mvmvif;
1546     u32 id_n_color, csa_id, mac_id;
1547 
1548     id_n_color = le32_to_cpu(notif->id_and_color);
1549     mac_id = id_n_color & FW_CTXT_ID_MSK;
1550 
1551     if (WARN_ON_ONCE(mac_id >= NUM_MAC_INDEX_DRIVER))
1552         return;
1553 
1554     rcu_read_lock();
1555     vif = rcu_dereference(mvm->vif_id_to_mac[mac_id]);
1556     mvmvif = iwl_mvm_vif_from_mac80211(vif);
1557 
1558     switch (vif->type) {
1559     case NL80211_IFTYPE_AP:
1560         csa_vif = rcu_dereference(mvm->csa_vif);
1561         if (WARN_ON(!csa_vif || !csa_vif->bss_conf.csa_active ||
1562                 csa_vif != vif))
1563             goto out_unlock;
1564 
1565         csa_id = FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color);
1566         if (WARN(csa_id != id_n_color,
1567              "channel switch noa notification on unexpected vif (csa_vif=%d, notif=%d)",
1568              csa_id, id_n_color))
1569             goto out_unlock;
1570 
1571         IWL_DEBUG_INFO(mvm, "Channel Switch Started Notification\n");
1572 
1573         schedule_delayed_work(&mvm->cs_tx_unblock_dwork,
1574                       msecs_to_jiffies(IWL_MVM_CS_UNBLOCK_TX_TIMEOUT *
1575                                csa_vif->bss_conf.beacon_int));
1576 
1577         ieee80211_csa_finish(csa_vif);
1578 
1579         rcu_read_unlock();
1580 
1581         RCU_INIT_POINTER(mvm->csa_vif, NULL);
1582         return;
1583     case NL80211_IFTYPE_STATION:
1584         /*
1585          * if we don't know about an ongoing channel switch,
1586          * make sure FW cancels it
1587          */
1588         if (iwl_fw_lookup_notif_ver(mvm->fw, MAC_CONF_GROUP,
1589                         CHANNEL_SWITCH_ERROR_NOTIF,
1590                         0) && !vif->bss_conf.csa_active) {
1591             IWL_DEBUG_INFO(mvm, "Channel Switch was canceled\n");
1592             iwl_mvm_cancel_channel_switch(mvm, vif, mac_id);
1593             break;
1594         }
1595 
1596         iwl_mvm_csa_client_absent(mvm, vif);
1597         cancel_delayed_work(&mvmvif->csa_work);
1598         ieee80211_chswitch_done(vif, true);
1599         break;
1600     default:
1601         /* should never happen */
1602         WARN_ON_ONCE(1);
1603         break;
1604     }
1605 out_unlock:
1606     rcu_read_unlock();
1607 }
1608 
1609 void iwl_mvm_channel_switch_error_notif(struct iwl_mvm *mvm,
1610                     struct iwl_rx_cmd_buffer *rxb)
1611 {
1612     struct iwl_rx_packet *pkt = rxb_addr(rxb);
1613     struct iwl_channel_switch_error_notif *notif = (void *)pkt->data;
1614     struct ieee80211_vif *vif;
1615     u32 id = le32_to_cpu(notif->mac_id);
1616     u32 csa_err_mask = le32_to_cpu(notif->csa_err_mask);
1617 
1618     rcu_read_lock();
1619     vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true);
1620     if (!vif) {
1621         rcu_read_unlock();
1622         return;
1623     }
1624 
1625     IWL_DEBUG_INFO(mvm, "FW reports CSA error: mac_id=%u, csa_err_mask=%u\n",
1626                id, csa_err_mask);
1627     if (csa_err_mask & (CS_ERR_COUNT_ERROR |
1628                 CS_ERR_LONG_DELAY_AFTER_CS |
1629                 CS_ERR_TX_BLOCK_TIMER_EXPIRED))
1630         ieee80211_channel_switch_disconnect(vif, true);
1631     rcu_read_unlock();
1632 }
1633 
1634 void iwl_mvm_rx_missed_vap_notif(struct iwl_mvm *mvm,
1635                  struct iwl_rx_cmd_buffer *rxb)
1636 {
1637     struct iwl_rx_packet *pkt = rxb_addr(rxb);
1638     struct iwl_missed_vap_notif *mb = (void *)pkt->data;
1639     struct ieee80211_vif *vif;
1640     u32 id = le32_to_cpu(mb->mac_id);
1641 
1642     IWL_DEBUG_INFO(mvm,
1643                "missed_vap notify mac_id=%u, num_beacon_intervals_elapsed=%u, profile_periodicity=%u\n",
1644                le32_to_cpu(mb->mac_id),
1645                mb->num_beacon_intervals_elapsed,
1646                mb->profile_periodicity);
1647 
1648     rcu_read_lock();
1649 
1650     vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true);
1651     if (vif)
1652         iwl_mvm_connection_loss(mvm, vif, "missed vap beacon");
1653 
1654     rcu_read_unlock();
1655 }