/* Not much to do here. The stack will not allow interface * types or combinations that we didn't advertise, so we * don't really have to check the types.
*/
/* make sure that beacon statistics don't go backwards with FW reset */ if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
for_each_mvm_vif_valid_link(mvmvif, i)
mvmvif->link[i]->beacon_stats.accu_num_beacons +=
mvmvif->link[i]->beacon_stats.num_beacons;
/* Allocate resources for the MAC context, and add it to the fw */
ret = iwl_mvm_mac_ctxt_init(mvm, vif); if (ret) return ret;
/* We want link[0] to point to the default link, unless we have MLO and * in this case this will be modified later by .change_vif_links() * If we are in the restart flow with an MLD connection, we will wait * to .change_vif_links() to setup the links.
*/ if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) ||
!ieee80211_vif_is_mld(vif)) {
mvmvif->link[0] = &mvmvif->deflink;
ret = iwl_mvm_add_link(mvm, vif, &vif->bss_conf); if (ret) goto out_free_bf;
}
/* Save a pointer to p2p device vif, so it can later be used to * update the p2p device MAC when a GO is started/stopped
*/ if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
mvm->p2p_device_vif = vif;
ret = iwl_mvm_power_update_mac(mvm); if (ret) goto out_free_bf;
if (vif->bss_conf.ftm_responder)
memset(&mvm->ftm_resp_stats, 0, sizeof(mvm->ftm_resp_stats));
iwl_mvm_vif_dbgfs_rm_link(mvm, vif);
iwl_mvm_power_update_mac(mvm);
/* Before the interface removal, mac80211 would cancel the ROC, and the * ROC worker would be scheduled if needed. The worker would be flushed * in iwl_mvm_prepare_mac_removal() and thus at this point the link is * not active. So need only to remove the link.
*/ if (vif->type == NL80211_IFTYPE_P2P_DEVICE) { if (mvmvif->deflink.phy_ctxt) {
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
mvmvif->deflink.phy_ctxt = NULL;
}
mvm->p2p_device_vif = NULL;
iwl_mvm_remove_link(mvm, vif, &vif->bss_conf);
} else {
iwl_mvm_disable_link(mvm, vif, &vif->bss_conf);
}
if (WARN_ON_ONCE(!mvmvif->link[link_id])) return -EINVAL;
/* if the assigned one was not counted yet, count it now */ if (!mvmvif->link[link_id]->phy_ctxt)
n_active++;
/* mac parameters such as HE support can change at this stage * For sta, need first to configure correct state from drv_sta_state * and only after that update mac config.
*/ if (vif->type == NL80211_IFTYPE_AP) {
ret = iwl_mvm_mld_mac_ctxt_changed(mvm, vif, false); if (ret) {
IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr); return -EINVAL;
}
}
mvmvif->link[link_id]->phy_ctxt = phy_ctxt;
if (iwl_mvm_is_esr_supported(mvm->fwrt.trans) && n_active > 1) {
mvmvif->link[link_id]->listen_lmac = true;
ret = iwl_mvm_esr_mode_active(mvm, vif); if (ret) {
IWL_ERR(mvm, "failed to activate ESR mode (%d)\n", ret); goto out;
}
}
if (switching_chanctx) { /* reactivate if we turned this off during channel switch */ if (vif->type == NL80211_IFTYPE_AP)
mvmvif->ap_ibss_active = true;
}
/* send it first with phy context ID */
ret = iwl_mvm_link_changed(mvm, vif, link_conf, 0, false); if (ret) goto out;
/* * if link switching (link not active yet) we'll activate it in * firmware later on link-info change, which mac80211 guarantees * for link switch after the stations are set up
*/ if (ieee80211_vif_link_active(vif, link_conf->link_id)) {
ret = iwl_mvm_link_changed(mvm, vif, link_conf,
LINK_CONTEXT_MODIFY_ACTIVE |
LINK_CONTEXT_MODIFY_RATES_INFO, true); if (ret) goto out;
}
if (vif->type == NL80211_IFTYPE_STATION)
iwl_mvm_send_ap_tx_power_constraint_cmd(mvm, vif,
link_conf, false);
/* * Power state must be updated before quotas, * otherwise fw will complain.
*/
iwl_mvm_power_update_mac(mvm);
if (vif->type == NL80211_IFTYPE_MONITOR) {
ret = iwl_mvm_mld_add_snif_sta(mvm, vif, link_conf); if (ret) goto deactivate;
}
/* update EMLSR mode */ if (ieee80211_vif_type_p2p(vif) != NL80211_IFTYPE_STATION) { int ret;
ret = iwl_mvm_esr_non_bss_link(mvm, vif, link_conf->link_id, true); /* * Don't activate this link if failed to exit EMLSR in * the BSS interface
*/ if (ret) return ret;
}
mutex_lock(&mvm->mutex);
__iwl_mvm_mld_unassign_vif_chanctx(mvm, vif, link_conf, ctx, false); /* in the non-MLD case, remove/re-add the link to clean up FW state */ if (!ieee80211_vif_is_mld(vif) && !mvmvif->ap_sta &&
!WARN_ON_ONCE(vif->cfg.assoc)) {
iwl_mvm_remove_link(mvm, vif, link_conf);
iwl_mvm_add_link(mvm, vif, link_conf);
}
mutex_unlock(&mvm->mutex);
/* if not valid, mac80211 puts default (max value) */ for (i = 0; i < ARRAY_SIZE(cmd->psd_pwr); i++)
cmd->psd_pwr[i] = min(bss_info->tpe.psd_local[0].power[i],
bss_info->tpe.psd_reg_client[0].power[i]);
for (i = 0; i < ARRAY_SIZE(cmd->eirp_pwr); i++)
cmd->eirp_pwr[i] = min(bss_info->tpe.max_local[0].power[i],
bss_info->tpe.max_reg_client[0].power[i]);
}
if (vif->type == NL80211_IFTYPE_AP)
iwl_mvm_send_ap_tx_power_constraint_cmd(mvm, vif,
link_conf, true);
/* Send the beacon template */
ret = iwl_mvm_mac_ctxt_beacon_changed(mvm, vif, link_conf); if (ret) return ret;
/* the link should be already activated when assigning chan context */
ret = iwl_mvm_link_changed(mvm, vif, link_conf,
LINK_CONTEXT_MODIFY_ALL &
~LINK_CONTEXT_MODIFY_ACTIVE, true); if (ret) return ret;
ret = iwl_mvm_mld_add_mcast_sta(mvm, vif, link_conf); if (ret) return ret;
/* Send the bcast station. At this stage the TBTT and DTIM time * events are added and applied to the scheduler
*/
ret = iwl_mvm_mld_add_bcast_sta(mvm, vif, link_conf); if (ret) goto out_rm_mcast;
if (iwl_mvm_start_ap_ibss_common(hw, vif, &ret)) goto out_failed;
/* Need to update the P2P Device MAC (only GO, IBSS is single vif) */ if (vif->p2p && mvm->p2p_device_vif)
iwl_mvm_mld_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false);
iwl_mvm_bt_coex_vif_change(mvm);
/* we don't support TDLS during DCM */ if (iwl_mvm_phy_ctx_count(mvm) > 1)
iwl_mvm_teardown_tdls_peers(mvm);
/* Need to update the P2P Device MAC (only GO, IBSS is single vif) */ if (vif->p2p && mvm->p2p_device_vif)
iwl_mvm_mld_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false);
if (WARN_ON_ONCE(!mvmvif->link[link_conf->link_id])) return;
/* not yet marked active in vif means during link switch */ if (!ieee80211_vif_link_active(vif, link_conf->link_id) &&
vif->cfg.assoc && mvmvif->link[link_conf->link_id]->phy_ctxt)
link_changes |= LINK_CONTEXT_MODIFY_ACTIVE;
/* This might get called without active links during the * chanctx switch, but we don't care about it anyway.
*/ if (changes == BSS_CHANGED_IDLE) return;
ret = iwl_mvm_mld_mac_ctxt_changed(mvm, vif, false); if (ret)
IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
mvmvif->associated = vif->cfg.assoc;
if (changes & BSS_CHANGED_ASSOC) { if (vif->cfg.assoc) {
mvmvif->session_prot_connection_loss = false;
/* * Clear statistics to get clean beacon counter, and ask for * periodic statistics, as they are needed for link * selection and RX OMI decisions.
*/
iwl_mvm_request_statistics(mvm, true);
iwl_mvm_request_periodic_system_statistics(mvm, true);
iwl_mvm_sf_update(mvm, vif, false);
iwl_mvm_power_vif_assoc(mvm, vif);
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
protect) { /* We are in assoc so only one link is active- * The association link
*/ unsignedint link_id =
ffs(vif->active_links) - 1;
/* If we're not restarting and still haven't * heard a beacon (dtim period unknown) then * make sure we still have enough minimum time * remaining in the time event, since the auth * might actually have taken quite a while * (especially for SAE) and so the remaining * time could be small without us having heard * a beacon yet.
*/
iwl_mvm_protect_assoc(mvm, vif, 0, link_id);
}
iwl_mvm_sf_update(mvm, vif, false);
/* FIXME: need to decide about misbehaving AP handling */
iwl_mvm_power_vif_assoc(mvm, vif);
} elseif (iwl_mvm_mld_vif_have_valid_ap_sta(mvmvif)) {
iwl_mvm_mei_host_disassociated(mvm);
/* If update fails - SF might be running in associated * mode while disassociated - which is forbidden.
*/
ret = iwl_mvm_sf_update(mvm, vif, false);
WARN_ONCE(ret &&
!test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
&mvm->status), "Failed to update SF upon disassociation\n");
}
if (changes & BSS_CHANGED_PS) {
iwl_mvm_smps_workaround(mvm, vif, false);
ret = iwl_mvm_power_update_mac(mvm); if (ret)
IWL_ERR(mvm, "failed to update power mode\n");
}
/* Changes will be applied when the AP/IBSS is started */ if (!mvmvif->ap_ibss_active) return;
if (link_conf->he_support)
link_changes |= LINK_CONTEXT_MODIFY_HE_PARAMS;
if (changes & BSS_CHANGED_ERP_SLOT)
link_changes |= LINK_CONTEXT_MODIFY_RATES_INFO;
if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_SLOT |
BSS_CHANGED_HT |
BSS_CHANGED_BANDWIDTH | BSS_CHANGED_QOS |
BSS_CHANGED_HE_BSS_COLOR) &&
iwl_mvm_link_changed(mvm, vif, link_conf,
link_changes, true))
IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
/* Need to send a new beacon template to the FW */ if (changes & BSS_CHANGED_BEACON &&
iwl_mvm_mac_ctxt_beacon_changed(mvm, vif, link_conf))
IWL_WARN(mvm, "Failed updating beacon data\n");
/* FIXME: need to decide if we need FTM responder per link */ if (changes & BSS_CHANGED_FTM_RESPONDER) { int ret = iwl_mvm_ftm_start_responder(mvm, vif, link_conf);
if (ret)
IWL_WARN(mvm, "Failed to enable FTM responder (%d)\n",
ret);
}
}
/* No need to update right away, we'll get BSS_CHANGED_QOS * The exception is P2P_DEVICE interface which needs immediate update.
*/ if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
guard(mvm)(mvm); return iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
LINK_CONTEXT_MODIFY_QOS_PARAMS, true);
} return 0;
}
staticint iwl_mvm_mld_roc_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{ int ret;
lockdep_assert_held(&mvm->mutex);
/* The PHY context ID might have changed so need to set it */
ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf, 0, false); if (WARN(ret, "Failed to set PHY context ID\n")) return ret;
ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
LINK_CONTEXT_MODIFY_ACTIVE |
LINK_CONTEXT_MODIFY_RATES_INFO, true);
if (WARN(ret, "Failed linking P2P_DEVICE\n")) return ret;
/* The station and queue allocation must be done only after the linking * is done, as otherwise the FW might incorrectly configure its state.
*/ return iwl_mvm_mld_add_bcast_sta(mvm, vif, &vif->bss_conf);
}
/* If we're in RESTART flow, the default link wasn't added in * drv_add_interface(), and link[0] doesn't point to it.
*/ if (old_links == 0 && !test_bit(IWL_MVM_STATUS_IN_HW_RESTART,
&mvm->status)) {
err = iwl_mvm_disable_link(mvm, vif, &vif->bss_conf); if (err) goto out_err;
mvmvif->link[0] = NULL;
}
for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) { if (removed & BIT(i)) { struct ieee80211_bss_conf *link_conf = old[i];
/* Verify all TIDs are mapped to the same links set */
map = neg_ttlm->downlink[0]; for (i = 0; i < IEEE80211_TTLM_NUM_TIDS; i++) { if (neg_ttlm->downlink[i] != neg_ttlm->uplink[i] ||
neg_ttlm->uplink[i] != map) return NEG_TTLM_RES_REJECT;
}
mutex_lock(&mvm->mutex); if (mvmvif->esr_active) {
u8 primary = iwl_mvm_get_primary_link(vif); int selected;
/* prefer primary unless quiet CSA on it */ if (chsw->link_id == primary && chsw->block_tx)
selected = iwl_mvm_get_other_link(vif, primary); else
selected = primary;
/* * remembers to tell the firmware that this link can't tx * Note that this logic seems to be unrelated to esr, but it * really is needed only when esr is active. When we have a * single link, the firmware will handle all this on its own. * In multi-link scenarios, we can learn about the CSA from * another link and this logic is too complex for the firmware * to track. * Since we want to de-activate the link that got a CSA, we * need to tell the firmware not to send any frame on that link * as the firmware may not be aware that link is under a CSA * with mode=1 (no Tx allowed).
*/ if (chsw->block_tx && mvmvif->link[chsw->link_id])
mvmvif->link[chsw->link_id]->csa_block_tx = true;
/* * If we've not kept the link active that's doing the CSA * then we don't need to do anything else, just return.
*/ if (selected != chsw->link_id) return 0;
mutex_lock(&mvm->mutex);
}
ret = iwl_mvm_pre_channel_switch(mvm, vif, chsw);
mutex_unlock(&mvm->mutex);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.