1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* 3 * Copyright (C) 2022 - 2024 Intel Corporation 4 */ 5 #include "mvm.h" 6 #include "time-event.h" 7 8 static int iwl_mvm_link_cmd_send(struct iwl_mvm *mvm, 9 struct iwl_link_config_cmd *cmd, 10 enum iwl_ctxt_action action) 11 { 12 int ret; 13 14 cmd->action = cpu_to_le32(action); 15 ret = iwl_mvm_send_cmd_pdu(mvm, 16 WIDE_ID(MAC_CONF_GROUP, LINK_CONFIG_CMD), 0, 17 sizeof(*cmd), cmd); 18 if (ret) 19 IWL_ERR(mvm, "Failed to send LINK_CONFIG_CMD (action:%d): %d\n", 20 action, ret); 21 return ret; 22 } 23 24 void iwl_mvm_set_link_fw_id(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 25 struct ieee80211_bss_conf *link_conf) 26 { 27 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 28 struct iwl_mvm_vif_link_info *link_info = 29 mvmvif->link[link_conf->link_id]; 30 31 if (link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID) 32 link_info->fw_link_id = mvmvif->id; 33 } 34 35 int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 36 struct ieee80211_bss_conf *link_conf) 37 { 38 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 39 unsigned int link_id = link_conf->link_id; 40 struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id]; 41 struct iwl_link_config_cmd cmd = {}; 42 unsigned int cmd_id = WIDE_ID(MAC_CONF_GROUP, LINK_CONFIG_CMD); 43 u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 1); 44 45 if (WARN_ON_ONCE(!link_info)) 46 return -EINVAL; 47 48 iwl_mvm_set_link_fw_id(mvm, vif, link_conf); 49 50 /* Update SF - Disable if needed. if this fails, SF might still be on 51 * while many macs are bound, which is forbidden - so fail the binding. 52 */ 53 if (iwl_mvm_sf_update(mvm, vif, false)) 54 return -EINVAL; 55 56 cmd.link_id = cpu_to_le32(link_info->fw_link_id); 57 cmd.mac_id = cpu_to_le32(mvmvif->id); 58 cmd.spec_link_id = link_conf->link_id; 59 WARN_ON_ONCE(link_info->phy_ctxt); 60 cmd.phy_id = cpu_to_le32(FW_CTXT_INVALID); 61 62 memcpy(cmd.local_link_addr, link_conf->addr, ETH_ALEN); 63 64 if (vif->type == NL80211_IFTYPE_ADHOC && link_conf->bssid) 65 memcpy(cmd.ibss_bssid_addr, link_conf->bssid, ETH_ALEN); 66 67 if (cmd_ver < 2) 68 cmd.listen_lmac = cpu_to_le32(link_info->listen_lmac); 69 70 return iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_ADD); 71 } 72 73 int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 74 struct ieee80211_bss_conf *link_conf, 75 u32 changes, bool active) 76 { 77 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 78 unsigned int link_id = link_conf->link_id; 79 struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id]; 80 struct iwl_mvm_phy_ctxt *phyctxt; 81 struct iwl_link_config_cmd cmd = {}; 82 u32 ht_flag, flags = 0, flags_mask = 0; 83 int ret; 84 unsigned int cmd_id = WIDE_ID(MAC_CONF_GROUP, LINK_CONFIG_CMD); 85 u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 1); 86 87 if (WARN_ON_ONCE(!link_info || 88 link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID)) 89 return -EINVAL; 90 91 if (changes & LINK_CONTEXT_MODIFY_ACTIVE) { 92 /* When activating a link, phy context should be valid; 93 * when deactivating a link, it also should be valid since 94 * the link was active before. So, do nothing in this case. 95 * Since a link is added first with FW_CTXT_INVALID, then we 96 * can get here in case it's removed before it was activated. 97 */ 98 if (!link_info->phy_ctxt) 99 return 0; 100 101 /* Catch early if driver tries to activate or deactivate a link 102 * twice. 103 */ 104 WARN_ON_ONCE(active == link_info->active); 105 106 /* When deactivating a link session protection should 107 * be stopped. Also let the firmware know if we can't Tx. 108 */ 109 if (!active && vif->type == NL80211_IFTYPE_STATION) { 110 iwl_mvm_stop_session_protection(mvm, vif); 111 if (link_info->csa_block_tx) { 112 cmd.block_tx = 1; 113 link_info->csa_block_tx = false; 114 } 115 } 116 } 117 118 cmd.link_id = cpu_to_le32(link_info->fw_link_id); 119 120 /* The phy_id, link address and listen_lmac can be modified only until 121 * the link becomes active, otherwise they will be ignored. 122 */ 123 phyctxt = link_info->phy_ctxt; 124 if (phyctxt) 125 cmd.phy_id = cpu_to_le32(phyctxt->id); 126 else 127 cmd.phy_id = cpu_to_le32(FW_CTXT_INVALID); 128 cmd.mac_id = cpu_to_le32(mvmvif->id); 129 130 memcpy(cmd.local_link_addr, link_conf->addr, ETH_ALEN); 131 132 cmd.active = cpu_to_le32(active); 133 134 if (vif->type == NL80211_IFTYPE_ADHOC && link_conf->bssid) 135 memcpy(cmd.ibss_bssid_addr, link_conf->bssid, ETH_ALEN); 136 137 iwl_mvm_set_fw_basic_rates(mvm, vif, link_info, 138 &cmd.cck_rates, &cmd.ofdm_rates); 139 140 cmd.cck_short_preamble = cpu_to_le32(link_conf->use_short_preamble); 141 cmd.short_slot = cpu_to_le32(link_conf->use_short_slot); 142 143 /* The fw does not distinguish between ht and fat */ 144 ht_flag = LINK_PROT_FLG_HT_PROT | LINK_PROT_FLG_FAT_PROT; 145 iwl_mvm_set_fw_protection_flags(mvm, vif, link_conf, 146 &cmd.protection_flags, 147 ht_flag, LINK_PROT_FLG_TGG_PROTECT); 148 149 iwl_mvm_set_fw_qos_params(mvm, vif, link_conf, cmd.ac, 150 &cmd.qos_flags); 151 152 153 cmd.bi = cpu_to_le32(link_conf->beacon_int); 154 cmd.dtim_interval = cpu_to_le32(link_conf->beacon_int * 155 link_conf->dtim_period); 156 157 if (!link_conf->he_support || iwlwifi_mod_params.disable_11ax || 158 (vif->type == NL80211_IFTYPE_STATION && !vif->cfg.assoc)) { 159 changes &= ~LINK_CONTEXT_MODIFY_HE_PARAMS; 160 goto send_cmd; 161 } 162 163 cmd.htc_trig_based_pkt_ext = link_conf->htc_trig_based_pkt_ext; 164 165 if (link_conf->uora_exists) { 166 cmd.rand_alloc_ecwmin = 167 link_conf->uora_ocw_range & 0x7; 168 cmd.rand_alloc_ecwmax = 169 (link_conf->uora_ocw_range >> 3) & 0x7; 170 } 171 172 /* ap_sta may be NULL if we're disconnecting */ 173 if (changes & LINK_CONTEXT_MODIFY_HE_PARAMS && mvmvif->ap_sta) { 174 struct ieee80211_link_sta *link_sta = 175 link_sta_dereference_check(mvmvif->ap_sta, link_id); 176 177 if (!WARN_ON(!link_sta) && link_sta->he_cap.has_he && 178 link_sta->he_cap.he_cap_elem.mac_cap_info[5] & 179 IEEE80211_HE_MAC_CAP5_OM_CTRL_UL_MU_DATA_DIS_RX) 180 cmd.ul_mu_data_disable = 1; 181 } 182 183 /* TODO how to set ndp_fdbk_buff_th_exp? */ 184 185 if (iwl_mvm_set_fw_mu_edca_params(mvm, mvmvif->link[link_id], 186 &cmd.trig_based_txf[0])) { 187 flags |= LINK_FLG_MU_EDCA_CW; 188 flags_mask |= LINK_FLG_MU_EDCA_CW; 189 } 190 191 if (changes & LINK_CONTEXT_MODIFY_EHT_PARAMS) { 192 struct ieee80211_chanctx_conf *ctx; 193 struct cfg80211_chan_def *def = NULL; 194 195 rcu_read_lock(); 196 ctx = rcu_dereference(link_conf->chanctx_conf); 197 if (ctx) 198 def = iwl_mvm_chanctx_def(mvm, ctx); 199 200 if (iwlwifi_mod_params.disable_11be || 201 !link_conf->eht_support || !def || 202 iwl_fw_lookup_cmd_ver(mvm->fw, PHY_CONTEXT_CMD, 1) >= 6) 203 changes &= ~LINK_CONTEXT_MODIFY_EHT_PARAMS; 204 else 205 cmd.puncture_mask = cpu_to_le16(def->punctured); 206 rcu_read_unlock(); 207 } 208 209 cmd.bss_color = link_conf->he_bss_color.color; 210 211 if (!link_conf->he_bss_color.enabled) { 212 flags |= LINK_FLG_BSS_COLOR_DIS; 213 flags_mask |= LINK_FLG_BSS_COLOR_DIS; 214 } 215 216 cmd.frame_time_rts_th = cpu_to_le16(link_conf->frame_time_rts_th); 217 218 /* Block 26-tone RU OFDMA transmissions */ 219 if (link_info->he_ru_2mhz_block) { 220 flags |= LINK_FLG_RU_2MHZ_BLOCK; 221 flags_mask |= LINK_FLG_RU_2MHZ_BLOCK; 222 } 223 224 if (link_conf->nontransmitted) { 225 ether_addr_copy(cmd.ref_bssid_addr, 226 link_conf->transmitter_bssid); 227 cmd.bssid_index = link_conf->bssid_index; 228 } 229 230 send_cmd: 231 cmd.modify_mask = cpu_to_le32(changes); 232 cmd.flags = cpu_to_le32(flags); 233 if (cmd_ver < 6) 234 cmd.flags_mask = cpu_to_le32(flags_mask); 235 cmd.spec_link_id = link_conf->link_id; 236 if (cmd_ver < 2) 237 cmd.listen_lmac = cpu_to_le32(link_info->listen_lmac); 238 239 ret = iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_MODIFY); 240 if (!ret && (changes & LINK_CONTEXT_MODIFY_ACTIVE)) 241 link_info->active = active; 242 243 return ret; 244 } 245 246 int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 247 struct ieee80211_bss_conf *link_conf) 248 { 249 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 250 unsigned int link_id = link_conf->link_id; 251 struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id]; 252 struct iwl_link_config_cmd cmd = {}; 253 int ret; 254 255 cmd.link_id = cpu_to_le32(link_info->fw_link_id); 256 link_info->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID; 257 cmd.spec_link_id = link_conf->link_id; 258 cmd.phy_id = cpu_to_le32(FW_CTXT_INVALID); 259 260 ret = iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_REMOVE); 261 262 if (!ret && iwl_mvm_sf_update(mvm, vif, true)) 263 IWL_ERR(mvm, "Failed to update SF state\n"); 264 265 return ret; 266 } 267 268 /* link should be deactivated before removal, so in most cases we need to 269 * perform these two operations together 270 */ 271 int iwl_mvm_disable_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 272 struct ieee80211_bss_conf *link_conf) 273 { 274 int ret; 275 276 ret = iwl_mvm_link_changed(mvm, vif, link_conf, 277 LINK_CONTEXT_MODIFY_ACTIVE, false); 278 if (ret) 279 return ret; 280 281 ret = iwl_mvm_remove_link(mvm, vif, link_conf); 282 if (ret) 283 return ret; 284 285 return ret; 286 } 287 288 u8 iwl_mvm_get_primary_link(struct ieee80211_vif *vif) 289 { 290 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 291 292 /* relevant data is written with both locks held, so read with either */ 293 lockdep_assert(lockdep_is_held(&mvmvif->mvm->mutex) || 294 lockdep_is_held(&mvmvif->mvm->hw->wiphy->mtx)); 295 296 if (!ieee80211_vif_is_mld(vif)) 297 return 0; 298 299 /* In AP mode, there is no primary link */ 300 if (vif->type == NL80211_IFTYPE_AP) 301 return __ffs(vif->active_links); 302 303 if (mvmvif->esr_active && 304 !WARN_ON(!(BIT(mvmvif->primary_link) & vif->active_links))) 305 return mvmvif->primary_link; 306 307 return __ffs(vif->active_links); 308 } 309 310 void iwl_mvm_init_link(struct iwl_mvm_vif_link_info *link) 311 { 312 link->bcast_sta.sta_id = IWL_INVALID_STA; 313 link->mcast_sta.sta_id = IWL_INVALID_STA; 314 link->ap_sta_id = IWL_INVALID_STA; 315 316 for (int r = 0; r < NUM_IWL_MVM_SMPS_REQ; r++) 317 link->smps_requests[r] = 318 IEEE80211_SMPS_AUTOMATIC; 319 } 320