Path: blob/main/sys/contrib/dev/iwlwifi/mvm/mld-mac.c
48287 views
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause1/*2* Copyright (C) 2022 - 2025 Intel Corporation3*/4#include "mvm.h"56static void iwl_mvm_mld_set_he_support(struct iwl_mvm *mvm,7struct ieee80211_vif *vif,8struct iwl_mac_config_cmd *cmd,9int cmd_ver)10{11if (vif->type == NL80211_IFTYPE_AP) {12if (cmd_ver == 2)13cmd->wifi_gen_v2.he_ap_support = cpu_to_le16(1);14else15cmd->wifi_gen.he_ap_support = 1;16} else {17if (cmd_ver == 2)18cmd->wifi_gen_v2.he_support = cpu_to_le16(1);19else20cmd->wifi_gen.he_support = 1;21}22}2324static void iwl_mvm_mld_mac_ctxt_cmd_common(struct iwl_mvm *mvm,25struct ieee80211_vif *vif,26struct iwl_mac_config_cmd *cmd,27u32 action)28{29struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);30struct ieee80211_bss_conf *link_conf;31unsigned int link_id;32int cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,33WIDE_ID(MAC_CONF_GROUP,34MAC_CONFIG_CMD), 1);3536if (WARN_ON(cmd_ver > 3))37return;3839cmd->id_and_color = cpu_to_le32(mvmvif->id);40cmd->action = cpu_to_le32(action);4142cmd->mac_type = cpu_to_le32(iwl_mvm_get_mac_type(vif));4344memcpy(cmd->local_mld_addr, vif->addr, ETH_ALEN);4546cmd->wifi_gen_v2.he_support = 0;47cmd->wifi_gen_v2.eht_support = 0;4849/* should be set by specific context type handler */50cmd->filter_flags = 0;5152cmd->nic_not_ack_enabled =53cpu_to_le32(!iwl_mvm_is_nic_ack_enabled(mvm, vif));5455if (iwlwifi_mod_params.disable_11ax)56return;5758/* If we have MLO enabled, then the firmware needs to enable59* address translation for the station(s) we add. That depends60* on having EHT enabled in firmware, which in turn depends on61* mac80211 in the code below.62* However, mac80211 doesn't enable HE/EHT until it has parsed63* the association response successfully, so just skip all that64* and enable both when we have MLO.65*/66if (ieee80211_vif_is_mld(vif)) {67iwl_mvm_mld_set_he_support(mvm, vif, cmd, cmd_ver);68if (cmd_ver == 2)69cmd->wifi_gen_v2.eht_support = cpu_to_le32(1);70else71cmd->wifi_gen.eht_support = 1;72return;73}7475rcu_read_lock();76for (link_id = 0; link_id < ARRAY_SIZE((vif)->link_conf); link_id++) {77link_conf = rcu_dereference(vif->link_conf[link_id]);78if (!link_conf)79continue;8081if (link_conf->he_support)82iwl_mvm_mld_set_he_support(mvm, vif, cmd, cmd_ver);8384/* It's not reasonable to have EHT without HE and FW API doesn't85* support it. Ignore EHT in this case.86*/87if (!link_conf->he_support && link_conf->eht_support)88continue;8990if (link_conf->eht_support) {91if (cmd_ver == 2)92cmd->wifi_gen_v2.eht_support = cpu_to_le32(1);93else94cmd->wifi_gen.eht_support = 1;95break;96}97}98rcu_read_unlock();99}100101static int iwl_mvm_mld_mac_ctxt_send_cmd(struct iwl_mvm *mvm,102struct iwl_mac_config_cmd *cmd)103{104int ret = iwl_mvm_send_cmd_pdu(mvm,105WIDE_ID(MAC_CONF_GROUP, MAC_CONFIG_CMD),1060, sizeof(*cmd), cmd);107if (ret)108IWL_ERR(mvm, "Failed to send MAC_CONFIG_CMD (action:%d): %d\n",109le32_to_cpu(cmd->action), ret);110return ret;111}112113static int iwl_mvm_mld_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,114struct ieee80211_vif *vif,115u32 action, bool force_assoc_off)116{117struct iwl_mac_config_cmd cmd = {};118u16 esr_transition_timeout;119120WARN_ON(vif->type != NL80211_IFTYPE_STATION);121122/* Fill the common data for all mac context types */123iwl_mvm_mld_mac_ctxt_cmd_common(mvm, vif, &cmd, action);124125/*126* We always want to hear MCAST frames, if we're not authorized yet,127* we'll drop them.128*/129cmd.filter_flags |= cpu_to_le32(MAC_CFG_FILTER_ACCEPT_GRP);130131if (vif->p2p)132cmd.client.ctwin =133iwl_mvm_mac_ctxt_cmd_p2p_sta_get_oppps_ctwin(mvm, vif);134135if (vif->cfg.assoc && !force_assoc_off) {136struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);137138cmd.client.is_assoc = 1;139140if (!mvmvif->authorized &&141fw_has_capa(&mvm->fw->ucode_capa,142IWL_UCODE_TLV_CAPA_COEX_HIGH_PRIO))143cmd.client.data_policy |=144cpu_to_le16(COEX_HIGH_PRIORITY_ENABLE);145146} else {147cmd.client.is_assoc = 0;148149/* Allow beacons to pass through as long as we are not150* associated, or we do not have dtim period information.151*/152cmd.filter_flags |= cpu_to_le32(MAC_CFG_FILTER_ACCEPT_BEACON);153}154155cmd.client.assoc_id = cpu_to_le16(vif->cfg.aid);156if (ieee80211_vif_is_mld(vif)) {157esr_transition_timeout =158u16_get_bits(vif->cfg.eml_cap,159IEEE80211_EML_CAP_TRANSITION_TIMEOUT);160161cmd.client.esr_transition_timeout =162min_t(u16, IEEE80211_EML_CAP_TRANSITION_TIMEOUT_128TU,163esr_transition_timeout);164cmd.client.medium_sync_delay =165cpu_to_le16(vif->cfg.eml_med_sync_delay);166}167168if (vif->probe_req_reg && vif->cfg.assoc && vif->p2p)169cmd.filter_flags |= cpu_to_le32(MAC_CFG_FILTER_ACCEPT_PROBE_REQ);170171if (vif->bss_conf.he_support && !iwlwifi_mod_params.disable_11ax)172cmd.client.data_policy |=173cpu_to_le16(iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(mvm, vif));174175return iwl_mvm_mld_mac_ctxt_send_cmd(mvm, &cmd);176}177178static int iwl_mvm_mld_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,179struct ieee80211_vif *vif,180u32 action)181{182struct iwl_mac_config_cmd cmd = {};183184WARN_ON(vif->type != NL80211_IFTYPE_MONITOR);185186iwl_mvm_mld_mac_ctxt_cmd_common(mvm, vif, &cmd, action);187188cmd.filter_flags = cpu_to_le32(MAC_CFG_FILTER_PROMISC |189MAC_CFG_FILTER_ACCEPT_CONTROL_AND_MGMT |190MAC_CFG_FILTER_ACCEPT_BEACON |191MAC_CFG_FILTER_ACCEPT_PROBE_REQ |192MAC_CFG_FILTER_ACCEPT_GRP);193194return iwl_mvm_mld_mac_ctxt_send_cmd(mvm, &cmd);195}196197static int iwl_mvm_mld_mac_ctxt_cmd_ibss(struct iwl_mvm *mvm,198struct ieee80211_vif *vif,199u32 action)200{201struct iwl_mac_config_cmd cmd = {};202203WARN_ON(vif->type != NL80211_IFTYPE_ADHOC);204205iwl_mvm_mld_mac_ctxt_cmd_common(mvm, vif, &cmd, action);206207cmd.filter_flags = cpu_to_le32(MAC_CFG_FILTER_ACCEPT_BEACON |208MAC_CFG_FILTER_ACCEPT_PROBE_REQ |209MAC_CFG_FILTER_ACCEPT_GRP);210211return iwl_mvm_mld_mac_ctxt_send_cmd(mvm, &cmd);212}213214static int iwl_mvm_mld_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm,215struct ieee80211_vif *vif,216u32 action)217{218struct iwl_mac_config_cmd cmd = {};219220WARN_ON(vif->type != NL80211_IFTYPE_P2P_DEVICE);221222iwl_mvm_mld_mac_ctxt_cmd_common(mvm, vif, &cmd, action);223224cmd.p2p_dev.is_disc_extended =225iwl_mac_ctxt_p2p_dev_has_extended_disc(mvm, vif);226227/* Override the filter flags to accept all management frames. This is228* needed to support both P2P device discovery using probe requests and229* P2P service discovery using action frames230*/231cmd.filter_flags = cpu_to_le32(MAC_CFG_FILTER_ACCEPT_CONTROL_AND_MGMT);232233return iwl_mvm_mld_mac_ctxt_send_cmd(mvm, &cmd);234}235236static int iwl_mvm_mld_mac_ctxt_cmd_ap_go(struct iwl_mvm *mvm,237struct ieee80211_vif *vif,238u32 action)239{240struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);241struct iwl_mac_config_cmd cmd = {};242243WARN_ON(vif->type != NL80211_IFTYPE_AP);244245/* Fill the common data for all mac context types */246iwl_mvm_mld_mac_ctxt_cmd_common(mvm, vif, &cmd, action);247248iwl_mvm_mac_ctxt_cmd_ap_set_filter_flags(mvm, mvmvif,249&cmd.filter_flags,250MAC_CFG_FILTER_ACCEPT_PROBE_REQ,251MAC_CFG_FILTER_ACCEPT_BEACON);252253return iwl_mvm_mld_mac_ctxt_send_cmd(mvm, &cmd);254}255256static int iwl_mvm_mld_mac_ctx_send(struct iwl_mvm *mvm,257struct ieee80211_vif *vif,258u32 action, bool force_assoc_off)259{260switch (vif->type) {261case NL80211_IFTYPE_STATION:262return iwl_mvm_mld_mac_ctxt_cmd_sta(mvm, vif, action,263force_assoc_off);264case NL80211_IFTYPE_AP:265return iwl_mvm_mld_mac_ctxt_cmd_ap_go(mvm, vif, action);266case NL80211_IFTYPE_MONITOR:267return iwl_mvm_mld_mac_ctxt_cmd_listener(mvm, vif, action);268case NL80211_IFTYPE_P2P_DEVICE:269return iwl_mvm_mld_mac_ctxt_cmd_p2p_device(mvm, vif, action);270case NL80211_IFTYPE_ADHOC:271return iwl_mvm_mld_mac_ctxt_cmd_ibss(mvm, vif, action);272default:273break;274}275276return -EOPNOTSUPP;277}278279int iwl_mvm_mld_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif)280{281struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);282int ret;283284if (WARN_ONCE(mvmvif->uploaded, "Adding active MAC %pM/%d\n",285vif->addr, ieee80211_vif_type_p2p(vif)))286return -EIO;287288ret = iwl_mvm_mld_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_ADD,289true);290if (ret)291return ret;292293/* will only do anything at resume from D3 time */294iwl_mvm_set_last_nonqos_seq(mvm, vif);295296mvmvif->uploaded = true;297return 0;298}299300int iwl_mvm_mld_mac_ctxt_changed(struct iwl_mvm *mvm,301struct ieee80211_vif *vif,302bool force_assoc_off)303{304struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);305306if (WARN_ONCE(!mvmvif->uploaded, "Changing inactive MAC %pM/%d\n",307vif->addr, ieee80211_vif_type_p2p(vif)))308return -EIO;309310return iwl_mvm_mld_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_MODIFY,311force_assoc_off);312}313314int iwl_mvm_mld_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)315{316struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);317struct iwl_mac_config_cmd cmd = {318.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),319.id_and_color = cpu_to_le32(mvmvif->id),320};321int ret;322323if (WARN_ONCE(!mvmvif->uploaded, "Removing inactive MAC %pM/%d\n",324vif->addr, ieee80211_vif_type_p2p(vif)))325return -EIO;326327ret = iwl_mvm_mld_mac_ctxt_send_cmd(mvm, &cmd);328if (ret)329return ret;330331mvmvif->uploaded = false;332333return 0;334}335336337