xref: /freebsd/sys/contrib/dev/iwlwifi/mvm/mld-mac.c (revision a4128aad8503277614f2d214011ef60a19447b83)
19af1bba4SBjoern A. Zeeb // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
29af1bba4SBjoern A. Zeeb /*
3*a4128aadSBjoern A. Zeeb  * Copyright (C) 2022 - 2024 Intel Corporation
49af1bba4SBjoern A. Zeeb  */
59af1bba4SBjoern A. Zeeb #include "mvm.h"
69af1bba4SBjoern A. Zeeb 
79af1bba4SBjoern A. Zeeb static void iwl_mvm_mld_set_he_support(struct iwl_mvm *mvm,
89af1bba4SBjoern A. Zeeb 				       struct ieee80211_vif *vif,
99af1bba4SBjoern A. Zeeb 				       struct iwl_mac_config_cmd *cmd)
109af1bba4SBjoern A. Zeeb {
119af1bba4SBjoern A. Zeeb 	if (vif->type == NL80211_IFTYPE_AP)
129af1bba4SBjoern A. Zeeb 		cmd->he_ap_support = cpu_to_le16(1);
139af1bba4SBjoern A. Zeeb 	else
149af1bba4SBjoern A. Zeeb 		cmd->he_support = cpu_to_le16(1);
159af1bba4SBjoern A. Zeeb }
169af1bba4SBjoern A. Zeeb 
179af1bba4SBjoern A. Zeeb static void iwl_mvm_mld_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
189af1bba4SBjoern A. Zeeb 					    struct ieee80211_vif *vif,
199af1bba4SBjoern A. Zeeb 					    struct iwl_mac_config_cmd *cmd,
209af1bba4SBjoern A. Zeeb 					    u32 action)
219af1bba4SBjoern A. Zeeb {
229af1bba4SBjoern A. Zeeb 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
239af1bba4SBjoern A. Zeeb 	struct ieee80211_bss_conf *link_conf;
249af1bba4SBjoern A. Zeeb 	unsigned int link_id;
259af1bba4SBjoern A. Zeeb 
269af1bba4SBjoern A. Zeeb 	cmd->id_and_color = cpu_to_le32(mvmvif->id);
279af1bba4SBjoern A. Zeeb 	cmd->action = cpu_to_le32(action);
289af1bba4SBjoern A. Zeeb 
299af1bba4SBjoern A. Zeeb 	cmd->mac_type = cpu_to_le32(iwl_mvm_get_mac_type(vif));
309af1bba4SBjoern A. Zeeb 
319af1bba4SBjoern A. Zeeb 	memcpy(cmd->local_mld_addr, vif->addr, ETH_ALEN);
329af1bba4SBjoern A. Zeeb 
339af1bba4SBjoern A. Zeeb 	cmd->he_support = 0;
349af1bba4SBjoern A. Zeeb 	cmd->eht_support = 0;
359af1bba4SBjoern A. Zeeb 
369af1bba4SBjoern A. Zeeb 	/* should be set by specific context type handler */
379af1bba4SBjoern A. Zeeb 	cmd->filter_flags = 0;
389af1bba4SBjoern A. Zeeb 
399af1bba4SBjoern A. Zeeb 	cmd->nic_not_ack_enabled =
409af1bba4SBjoern A. Zeeb 		cpu_to_le32(!iwl_mvm_is_nic_ack_enabled(mvm, vif));
419af1bba4SBjoern A. Zeeb 
429af1bba4SBjoern A. Zeeb 	if (iwlwifi_mod_params.disable_11ax)
439af1bba4SBjoern A. Zeeb 		return;
449af1bba4SBjoern A. Zeeb 
459af1bba4SBjoern A. Zeeb 	/* If we have MLO enabled, then the firmware needs to enable
469af1bba4SBjoern A. Zeeb 	 * address translation for the station(s) we add. That depends
479af1bba4SBjoern A. Zeeb 	 * on having EHT enabled in firmware, which in turn depends on
489af1bba4SBjoern A. Zeeb 	 * mac80211 in the code below.
499af1bba4SBjoern A. Zeeb 	 * However, mac80211 doesn't enable HE/EHT until it has parsed
509af1bba4SBjoern A. Zeeb 	 * the association response successfully, so just skip all that
519af1bba4SBjoern A. Zeeb 	 * and enable both when we have MLO.
529af1bba4SBjoern A. Zeeb 	 */
539af1bba4SBjoern A. Zeeb 	if (ieee80211_vif_is_mld(vif)) {
549af1bba4SBjoern A. Zeeb 		iwl_mvm_mld_set_he_support(mvm, vif, cmd);
559af1bba4SBjoern A. Zeeb 		cmd->eht_support = cpu_to_le32(1);
569af1bba4SBjoern A. Zeeb 		return;
579af1bba4SBjoern A. Zeeb 	}
589af1bba4SBjoern A. Zeeb 
599af1bba4SBjoern A. Zeeb 	rcu_read_lock();
609af1bba4SBjoern A. Zeeb 	for (link_id = 0; link_id < ARRAY_SIZE((vif)->link_conf); link_id++) {
619af1bba4SBjoern A. Zeeb 		link_conf = rcu_dereference(vif->link_conf[link_id]);
629af1bba4SBjoern A. Zeeb 		if (!link_conf)
639af1bba4SBjoern A. Zeeb 			continue;
649af1bba4SBjoern A. Zeeb 
659af1bba4SBjoern A. Zeeb 		if (link_conf->he_support)
669af1bba4SBjoern A. Zeeb 			iwl_mvm_mld_set_he_support(mvm, vif, cmd);
679af1bba4SBjoern A. Zeeb 
689af1bba4SBjoern A. Zeeb 		/* it's not reasonable to have EHT without HE and FW API doesn't
699af1bba4SBjoern A. Zeeb 		 * support it. Ignore EHT in this case.
709af1bba4SBjoern A. Zeeb 		 */
719af1bba4SBjoern A. Zeeb 		if (!link_conf->he_support && link_conf->eht_support)
729af1bba4SBjoern A. Zeeb 			continue;
739af1bba4SBjoern A. Zeeb 
749af1bba4SBjoern A. Zeeb 		if (link_conf->eht_support) {
759af1bba4SBjoern A. Zeeb 			cmd->eht_support = cpu_to_le32(1);
769af1bba4SBjoern A. Zeeb 			break;
779af1bba4SBjoern A. Zeeb 		}
789af1bba4SBjoern A. Zeeb 	}
799af1bba4SBjoern A. Zeeb 	rcu_read_unlock();
809af1bba4SBjoern A. Zeeb }
819af1bba4SBjoern A. Zeeb 
829af1bba4SBjoern A. Zeeb static int iwl_mvm_mld_mac_ctxt_send_cmd(struct iwl_mvm *mvm,
839af1bba4SBjoern A. Zeeb 					 struct iwl_mac_config_cmd *cmd)
849af1bba4SBjoern A. Zeeb {
859af1bba4SBjoern A. Zeeb 	int ret = iwl_mvm_send_cmd_pdu(mvm,
869af1bba4SBjoern A. Zeeb 				       WIDE_ID(MAC_CONF_GROUP, MAC_CONFIG_CMD),
879af1bba4SBjoern A. Zeeb 				       0, sizeof(*cmd), cmd);
889af1bba4SBjoern A. Zeeb 	if (ret)
899af1bba4SBjoern A. Zeeb 		IWL_ERR(mvm, "Failed to send MAC_CONFIG_CMD (action:%d): %d\n",
909af1bba4SBjoern A. Zeeb 			le32_to_cpu(cmd->action), ret);
919af1bba4SBjoern A. Zeeb 	return ret;
929af1bba4SBjoern A. Zeeb }
939af1bba4SBjoern A. Zeeb 
949af1bba4SBjoern A. Zeeb static int iwl_mvm_mld_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
959af1bba4SBjoern A. Zeeb 					struct ieee80211_vif *vif,
969af1bba4SBjoern A. Zeeb 					u32 action, bool force_assoc_off)
979af1bba4SBjoern A. Zeeb {
989af1bba4SBjoern A. Zeeb 	struct iwl_mac_config_cmd cmd = {};
999af1bba4SBjoern A. Zeeb 	u16 esr_transition_timeout;
1009af1bba4SBjoern A. Zeeb 
1019af1bba4SBjoern A. Zeeb 	WARN_ON(vif->type != NL80211_IFTYPE_STATION);
1029af1bba4SBjoern A. Zeeb 
1039af1bba4SBjoern A. Zeeb 	/* Fill the common data for all mac context types */
1049af1bba4SBjoern A. Zeeb 	iwl_mvm_mld_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
1059af1bba4SBjoern A. Zeeb 
1069af1bba4SBjoern A. Zeeb 	/*
1079af1bba4SBjoern A. Zeeb 	 * We always want to hear MCAST frames, if we're not authorized yet,
1089af1bba4SBjoern A. Zeeb 	 * we'll drop them.
1099af1bba4SBjoern A. Zeeb 	 */
1109af1bba4SBjoern A. Zeeb 	cmd.filter_flags |= cpu_to_le32(MAC_CFG_FILTER_ACCEPT_GRP);
1119af1bba4SBjoern A. Zeeb 
1129af1bba4SBjoern A. Zeeb 	if (vif->p2p)
1139af1bba4SBjoern A. Zeeb 		cmd.client.ctwin =
1149af1bba4SBjoern A. Zeeb 			iwl_mvm_mac_ctxt_cmd_p2p_sta_get_oppps_ctwin(mvm, vif);
1159af1bba4SBjoern A. Zeeb 
1169af1bba4SBjoern A. Zeeb 	if (vif->cfg.assoc && !force_assoc_off) {
1179af1bba4SBjoern A. Zeeb 		struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1189af1bba4SBjoern A. Zeeb 
1199af1bba4SBjoern A. Zeeb 		cmd.client.is_assoc = 1;
1209af1bba4SBjoern A. Zeeb 
1219af1bba4SBjoern A. Zeeb 		if (!mvmvif->authorized &&
1229af1bba4SBjoern A. Zeeb 		    fw_has_capa(&mvm->fw->ucode_capa,
1239af1bba4SBjoern A. Zeeb 				IWL_UCODE_TLV_CAPA_COEX_HIGH_PRIO))
1249af1bba4SBjoern A. Zeeb 			cmd.client.data_policy |=
1259af1bba4SBjoern A. Zeeb 				cpu_to_le16(COEX_HIGH_PRIORITY_ENABLE);
1269af1bba4SBjoern A. Zeeb 
1279af1bba4SBjoern A. Zeeb 	} else {
1289af1bba4SBjoern A. Zeeb 		cmd.client.is_assoc = 0;
1299af1bba4SBjoern A. Zeeb 
1309af1bba4SBjoern A. Zeeb 		/* Allow beacons to pass through as long as we are not
1319af1bba4SBjoern A. Zeeb 		 * associated, or we do not have dtim period information.
1329af1bba4SBjoern A. Zeeb 		 */
1339af1bba4SBjoern A. Zeeb 		cmd.filter_flags |= cpu_to_le32(MAC_CFG_FILTER_ACCEPT_BEACON);
1349af1bba4SBjoern A. Zeeb 	}
1359af1bba4SBjoern A. Zeeb 
1369af1bba4SBjoern A. Zeeb 	cmd.client.assoc_id = cpu_to_le16(vif->cfg.aid);
1379af1bba4SBjoern A. Zeeb 	if (ieee80211_vif_is_mld(vif)) {
1389af1bba4SBjoern A. Zeeb 		esr_transition_timeout =
1399af1bba4SBjoern A. Zeeb 			u16_get_bits(vif->cfg.eml_cap,
1409af1bba4SBjoern A. Zeeb 				     IEEE80211_EML_CAP_TRANSITION_TIMEOUT);
1419af1bba4SBjoern A. Zeeb 
1429af1bba4SBjoern A. Zeeb 		cmd.client.esr_transition_timeout =
1439af1bba4SBjoern A. Zeeb 			min_t(u16, IEEE80211_EML_CAP_TRANSITION_TIMEOUT_128TU,
1449af1bba4SBjoern A. Zeeb 			      esr_transition_timeout);
1459af1bba4SBjoern A. Zeeb 		cmd.client.medium_sync_delay =
1469af1bba4SBjoern A. Zeeb 			cpu_to_le16(vif->cfg.eml_med_sync_delay);
1479af1bba4SBjoern A. Zeeb 	}
1489af1bba4SBjoern A. Zeeb 
1499af1bba4SBjoern A. Zeeb 	if (vif->probe_req_reg && vif->cfg.assoc && vif->p2p)
1509af1bba4SBjoern A. Zeeb 		cmd.filter_flags |= cpu_to_le32(MAC_CFG_FILTER_ACCEPT_PROBE_REQ);
1519af1bba4SBjoern A. Zeeb 
1529af1bba4SBjoern A. Zeeb 	if (vif->bss_conf.he_support && !iwlwifi_mod_params.disable_11ax)
1539af1bba4SBjoern A. Zeeb 		cmd.client.data_policy |=
1549af1bba4SBjoern A. Zeeb 			cpu_to_le16(iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(mvm, vif));
1559af1bba4SBjoern A. Zeeb 
1569af1bba4SBjoern A. Zeeb 	return iwl_mvm_mld_mac_ctxt_send_cmd(mvm, &cmd);
1579af1bba4SBjoern A. Zeeb }
1589af1bba4SBjoern A. Zeeb 
1599af1bba4SBjoern A. Zeeb static int iwl_mvm_mld_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,
1609af1bba4SBjoern A. Zeeb 					     struct ieee80211_vif *vif,
1619af1bba4SBjoern A. Zeeb 					     u32 action)
1629af1bba4SBjoern A. Zeeb {
1639af1bba4SBjoern A. Zeeb 	struct iwl_mac_config_cmd cmd = {};
1649af1bba4SBjoern A. Zeeb 
1659af1bba4SBjoern A. Zeeb 	WARN_ON(vif->type != NL80211_IFTYPE_MONITOR);
1669af1bba4SBjoern A. Zeeb 
1679af1bba4SBjoern A. Zeeb 	iwl_mvm_mld_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
1689af1bba4SBjoern A. Zeeb 
1699af1bba4SBjoern A. Zeeb 	cmd.filter_flags = cpu_to_le32(MAC_CFG_FILTER_PROMISC |
170*a4128aadSBjoern A. Zeeb 				       MAC_CFG_FILTER_ACCEPT_CONTROL_AND_MGMT |
1719af1bba4SBjoern A. Zeeb 				       MAC_CFG_FILTER_ACCEPT_BEACON |
1729af1bba4SBjoern A. Zeeb 				       MAC_CFG_FILTER_ACCEPT_PROBE_REQ |
1739af1bba4SBjoern A. Zeeb 				       MAC_CFG_FILTER_ACCEPT_GRP);
1749af1bba4SBjoern A. Zeeb 
1759af1bba4SBjoern A. Zeeb 	return iwl_mvm_mld_mac_ctxt_send_cmd(mvm, &cmd);
1769af1bba4SBjoern A. Zeeb }
1779af1bba4SBjoern A. Zeeb 
1789af1bba4SBjoern A. Zeeb static int iwl_mvm_mld_mac_ctxt_cmd_ibss(struct iwl_mvm *mvm,
1799af1bba4SBjoern A. Zeeb 					 struct ieee80211_vif *vif,
1809af1bba4SBjoern A. Zeeb 					 u32 action)
1819af1bba4SBjoern A. Zeeb {
1829af1bba4SBjoern A. Zeeb 	struct iwl_mac_config_cmd cmd = {};
1839af1bba4SBjoern A. Zeeb 
1849af1bba4SBjoern A. Zeeb 	WARN_ON(vif->type != NL80211_IFTYPE_ADHOC);
1859af1bba4SBjoern A. Zeeb 
1869af1bba4SBjoern A. Zeeb 	iwl_mvm_mld_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
1879af1bba4SBjoern A. Zeeb 
1889af1bba4SBjoern A. Zeeb 	cmd.filter_flags = cpu_to_le32(MAC_CFG_FILTER_ACCEPT_BEACON |
1899af1bba4SBjoern A. Zeeb 				       MAC_CFG_FILTER_ACCEPT_PROBE_REQ |
1909af1bba4SBjoern A. Zeeb 				       MAC_CFG_FILTER_ACCEPT_GRP);
1919af1bba4SBjoern A. Zeeb 
1929af1bba4SBjoern A. Zeeb 	return iwl_mvm_mld_mac_ctxt_send_cmd(mvm, &cmd);
1939af1bba4SBjoern A. Zeeb }
1949af1bba4SBjoern A. Zeeb 
1959af1bba4SBjoern A. Zeeb static int iwl_mvm_mld_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm,
1969af1bba4SBjoern A. Zeeb 					       struct ieee80211_vif *vif,
1979af1bba4SBjoern A. Zeeb 					       u32 action)
1989af1bba4SBjoern A. Zeeb {
1999af1bba4SBjoern A. Zeeb 	struct iwl_mac_config_cmd cmd = {};
2009af1bba4SBjoern A. Zeeb 
2019af1bba4SBjoern A. Zeeb 	WARN_ON(vif->type != NL80211_IFTYPE_P2P_DEVICE);
2029af1bba4SBjoern A. Zeeb 
2039af1bba4SBjoern A. Zeeb 	iwl_mvm_mld_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
2049af1bba4SBjoern A. Zeeb 
2059af1bba4SBjoern A. Zeeb 	cmd.p2p_dev.is_disc_extended =
2069af1bba4SBjoern A. Zeeb 		iwl_mac_ctxt_p2p_dev_has_extended_disc(mvm, vif);
2079af1bba4SBjoern A. Zeeb 
208*a4128aadSBjoern A. Zeeb 	/* Override the filter flags to accept all management frames. This is
209*a4128aadSBjoern A. Zeeb 	 * needed to support both P2P device discovery using probe requests and
210*a4128aadSBjoern A. Zeeb 	 * P2P service discovery using action frames
211*a4128aadSBjoern A. Zeeb 	 */
212*a4128aadSBjoern A. Zeeb 	cmd.filter_flags = cpu_to_le32(MAC_CFG_FILTER_ACCEPT_CONTROL_AND_MGMT);
2139af1bba4SBjoern A. Zeeb 
2149af1bba4SBjoern A. Zeeb 	return iwl_mvm_mld_mac_ctxt_send_cmd(mvm, &cmd);
2159af1bba4SBjoern A. Zeeb }
2169af1bba4SBjoern A. Zeeb 
2179af1bba4SBjoern A. Zeeb static int iwl_mvm_mld_mac_ctxt_cmd_ap_go(struct iwl_mvm *mvm,
2189af1bba4SBjoern A. Zeeb 					  struct ieee80211_vif *vif,
2199af1bba4SBjoern A. Zeeb 					  u32 action)
2209af1bba4SBjoern A. Zeeb {
2219af1bba4SBjoern A. Zeeb 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
2229af1bba4SBjoern A. Zeeb 	struct iwl_mac_config_cmd cmd = {};
2239af1bba4SBjoern A. Zeeb 
2249af1bba4SBjoern A. Zeeb 	WARN_ON(vif->type != NL80211_IFTYPE_AP);
2259af1bba4SBjoern A. Zeeb 
2269af1bba4SBjoern A. Zeeb 	/* Fill the common data for all mac context types */
2279af1bba4SBjoern A. Zeeb 	iwl_mvm_mld_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
2289af1bba4SBjoern A. Zeeb 
2299af1bba4SBjoern A. Zeeb 	iwl_mvm_mac_ctxt_cmd_ap_set_filter_flags(mvm, mvmvif,
2309af1bba4SBjoern A. Zeeb 						 &cmd.filter_flags,
2319af1bba4SBjoern A. Zeeb 						 MAC_CFG_FILTER_ACCEPT_PROBE_REQ,
2329af1bba4SBjoern A. Zeeb 						 MAC_CFG_FILTER_ACCEPT_BEACON);
2339af1bba4SBjoern A. Zeeb 
2349af1bba4SBjoern A. Zeeb 	return iwl_mvm_mld_mac_ctxt_send_cmd(mvm, &cmd);
2359af1bba4SBjoern A. Zeeb }
2369af1bba4SBjoern A. Zeeb 
2379af1bba4SBjoern A. Zeeb static int iwl_mvm_mld_mac_ctx_send(struct iwl_mvm *mvm,
2389af1bba4SBjoern A. Zeeb 				    struct ieee80211_vif *vif,
2399af1bba4SBjoern A. Zeeb 				    u32 action, bool force_assoc_off)
2409af1bba4SBjoern A. Zeeb {
2419af1bba4SBjoern A. Zeeb 	switch (vif->type) {
2429af1bba4SBjoern A. Zeeb 	case NL80211_IFTYPE_STATION:
2439af1bba4SBjoern A. Zeeb 		return iwl_mvm_mld_mac_ctxt_cmd_sta(mvm, vif, action,
2449af1bba4SBjoern A. Zeeb 						    force_assoc_off);
2459af1bba4SBjoern A. Zeeb 	case NL80211_IFTYPE_AP:
2469af1bba4SBjoern A. Zeeb 		return iwl_mvm_mld_mac_ctxt_cmd_ap_go(mvm, vif, action);
2479af1bba4SBjoern A. Zeeb 	case NL80211_IFTYPE_MONITOR:
2489af1bba4SBjoern A. Zeeb 		return iwl_mvm_mld_mac_ctxt_cmd_listener(mvm, vif, action);
2499af1bba4SBjoern A. Zeeb 	case NL80211_IFTYPE_P2P_DEVICE:
2509af1bba4SBjoern A. Zeeb 		return iwl_mvm_mld_mac_ctxt_cmd_p2p_device(mvm, vif, action);
2519af1bba4SBjoern A. Zeeb 	case NL80211_IFTYPE_ADHOC:
2529af1bba4SBjoern A. Zeeb 		return iwl_mvm_mld_mac_ctxt_cmd_ibss(mvm, vif, action);
2539af1bba4SBjoern A. Zeeb 	default:
2549af1bba4SBjoern A. Zeeb 		break;
2559af1bba4SBjoern A. Zeeb 	}
2569af1bba4SBjoern A. Zeeb 
2579af1bba4SBjoern A. Zeeb 	return -EOPNOTSUPP;
2589af1bba4SBjoern A. Zeeb }
2599af1bba4SBjoern A. Zeeb 
2609af1bba4SBjoern A. Zeeb int iwl_mvm_mld_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
2619af1bba4SBjoern A. Zeeb {
2629af1bba4SBjoern A. Zeeb 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
2639af1bba4SBjoern A. Zeeb 	int ret;
2649af1bba4SBjoern A. Zeeb 
2659af1bba4SBjoern A. Zeeb 	if (WARN_ON_ONCE(vif->type == NL80211_IFTYPE_NAN))
2669af1bba4SBjoern A. Zeeb 		return -EOPNOTSUPP;
2679af1bba4SBjoern A. Zeeb 
2689af1bba4SBjoern A. Zeeb 	if (WARN_ONCE(mvmvif->uploaded, "Adding active MAC %pM/%d\n",
2699af1bba4SBjoern A. Zeeb 		      vif->addr, ieee80211_vif_type_p2p(vif)))
2709af1bba4SBjoern A. Zeeb 		return -EIO;
2719af1bba4SBjoern A. Zeeb 
2729af1bba4SBjoern A. Zeeb 	ret = iwl_mvm_mld_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_ADD,
2739af1bba4SBjoern A. Zeeb 				       true);
2749af1bba4SBjoern A. Zeeb 	if (ret)
2759af1bba4SBjoern A. Zeeb 		return ret;
2769af1bba4SBjoern A. Zeeb 
2779af1bba4SBjoern A. Zeeb 	/* will only do anything at resume from D3 time */
2789af1bba4SBjoern A. Zeeb 	iwl_mvm_set_last_nonqos_seq(mvm, vif);
2799af1bba4SBjoern A. Zeeb 
2809af1bba4SBjoern A. Zeeb 	mvmvif->uploaded = true;
2819af1bba4SBjoern A. Zeeb 	return 0;
2829af1bba4SBjoern A. Zeeb }
2839af1bba4SBjoern A. Zeeb 
2849af1bba4SBjoern A. Zeeb int iwl_mvm_mld_mac_ctxt_changed(struct iwl_mvm *mvm,
2859af1bba4SBjoern A. Zeeb 				 struct ieee80211_vif *vif,
2869af1bba4SBjoern A. Zeeb 				 bool force_assoc_off)
2879af1bba4SBjoern A. Zeeb {
2889af1bba4SBjoern A. Zeeb 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
2899af1bba4SBjoern A. Zeeb 
2909af1bba4SBjoern A. Zeeb 	if (WARN_ON_ONCE(vif->type == NL80211_IFTYPE_NAN))
2919af1bba4SBjoern A. Zeeb 		return -EOPNOTSUPP;
2929af1bba4SBjoern A. Zeeb 
2939af1bba4SBjoern A. Zeeb 	if (WARN_ONCE(!mvmvif->uploaded, "Changing inactive MAC %pM/%d\n",
2949af1bba4SBjoern A. Zeeb 		      vif->addr, ieee80211_vif_type_p2p(vif)))
2959af1bba4SBjoern A. Zeeb 		return -EIO;
2969af1bba4SBjoern A. Zeeb 
2979af1bba4SBjoern A. Zeeb 	return iwl_mvm_mld_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_MODIFY,
2989af1bba4SBjoern A. Zeeb 					force_assoc_off);
2999af1bba4SBjoern A. Zeeb }
3009af1bba4SBjoern A. Zeeb 
3019af1bba4SBjoern A. Zeeb int iwl_mvm_mld_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
3029af1bba4SBjoern A. Zeeb {
3039af1bba4SBjoern A. Zeeb 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
3049af1bba4SBjoern A. Zeeb 	struct iwl_mac_config_cmd cmd = {
3059af1bba4SBjoern A. Zeeb 		.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),
3069af1bba4SBjoern A. Zeeb 		.id_and_color = cpu_to_le32(mvmvif->id),
3079af1bba4SBjoern A. Zeeb 	};
3089af1bba4SBjoern A. Zeeb 	int ret;
3099af1bba4SBjoern A. Zeeb 
3109af1bba4SBjoern A. Zeeb 	if (WARN_ON_ONCE(vif->type == NL80211_IFTYPE_NAN))
3119af1bba4SBjoern A. Zeeb 		return -EOPNOTSUPP;
3129af1bba4SBjoern A. Zeeb 
3139af1bba4SBjoern A. Zeeb 	if (WARN_ONCE(!mvmvif->uploaded, "Removing inactive MAC %pM/%d\n",
3149af1bba4SBjoern A. Zeeb 		      vif->addr, ieee80211_vif_type_p2p(vif)))
3159af1bba4SBjoern A. Zeeb 		return -EIO;
3169af1bba4SBjoern A. Zeeb 
3179af1bba4SBjoern A. Zeeb 	ret = iwl_mvm_mld_mac_ctxt_send_cmd(mvm, &cmd);
3189af1bba4SBjoern A. Zeeb 	if (ret)
3199af1bba4SBjoern A. Zeeb 		return ret;
3209af1bba4SBjoern A. Zeeb 
3219af1bba4SBjoern A. Zeeb 	mvmvif->uploaded = false;
3229af1bba4SBjoern A. Zeeb 
3239af1bba4SBjoern A. Zeeb 	return 0;
3249af1bba4SBjoern A. Zeeb }
325