diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/sta.c')
| -rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 742 | 
1 files changed, 461 insertions, 281 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 69634fb82a9b..5469d634e289 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -24,8 +24,7 @@ static inline int iwl_mvm_add_sta_cmd_size(struct iwl_mvm *mvm)  		return sizeof(struct iwl_mvm_add_sta_cmd_v7);  } -static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm, -				    enum nl80211_iftype iftype) +int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm, enum nl80211_iftype iftype)  {  	int sta_id;  	u32 reserved_ids = 0; @@ -51,13 +50,79 @@ static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm,  	return IWL_MVM_INVALID_STA;  } +/* Calculate the ampdu density and max size */ +u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_link_sta *link_sta, +			       struct ieee80211_bss_conf *link_conf, +			       u32 *_agg_size) +{ +	u32 agg_size = 0, mpdu_dens = 0; + +	if (WARN_ON(!link_sta)) +		return 0; + +	if (link_sta->ht_cap.ht_supported) +		mpdu_dens = link_sta->ht_cap.ampdu_density; + +	if (link_conf->chandef.chan->band == +	    NL80211_BAND_6GHZ) { +		mpdu_dens = le16_get_bits(link_sta->he_6ghz_capa.capa, +					  IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START); +		agg_size = le16_get_bits(link_sta->he_6ghz_capa.capa, +					 IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP); +	} else if (link_sta->vht_cap.vht_supported) { +		agg_size = link_sta->vht_cap.cap & +			IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; +		agg_size >>= +			IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; +	} else if (link_sta->ht_cap.ht_supported) { +		agg_size = link_sta->ht_cap.ampdu_factor; +	} + +	/* D6.0 10.12.2 A-MPDU length limit rules +	 * A STA indicates the maximum length of the A-MPDU preEOF padding +	 * that it can receive in an HE PPDU in the Maximum A-MPDU Length +	 * Exponent field in its HT Capabilities, VHT Capabilities, +	 * and HE 6 GHz Band Capabilities elements (if present) and the +	 * Maximum AMPDU Length Exponent Extension field in its HE +	 * Capabilities element +	 */ +	if (link_sta->he_cap.has_he) +		agg_size += +			u8_get_bits(link_sta->he_cap.he_cap_elem.mac_cap_info[3], +				    IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK); + +	/* Limit to max A-MPDU supported by FW */ +	if (agg_size > (STA_FLG_MAX_AGG_SIZE_4M >> STA_FLG_MAX_AGG_SIZE_SHIFT)) +		agg_size = (STA_FLG_MAX_AGG_SIZE_4M >> +			    STA_FLG_MAX_AGG_SIZE_SHIFT); + +	*_agg_size = agg_size; +	return mpdu_dens; +} + +u8 iwl_mvm_get_sta_uapsd_acs(struct ieee80211_sta *sta) +{ +	u8 uapsd_acs = 0; + +	if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK) +		uapsd_acs |= BIT(AC_BK); +	if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE) +		uapsd_acs |= BIT(AC_BE); +	if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI) +		uapsd_acs |= BIT(AC_VI); +	if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) +		uapsd_acs |= BIT(AC_VO); + +	return uapsd_acs | uapsd_acs << 4; +} +  /* send station add/update command to firmware */  int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,  			   bool update, unsigned int flags)  {  	struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);  	struct iwl_mvm_add_sta_cmd add_sta_cmd = { -		.sta_id = mvm_sta->sta_id, +		.sta_id = mvm_sta->deflink.sta_id,  		.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color),  		.add_modify = update ? 1 : 0,  		.station_flags_msk = cpu_to_le32(STA_FLG_FAT_EN_MSK | @@ -134,68 +199,26 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,  		break;  	} -	if (sta->deflink.ht_cap.ht_supported) { -		add_sta_cmd.station_flags_msk |= -			cpu_to_le32(STA_FLG_MAX_AGG_SIZE_MSK | -				    STA_FLG_AGG_MPDU_DENS_MSK); - -		mpdu_dens = sta->deflink.ht_cap.ampdu_density; -	} - -	if (mvm_sta->vif->bss_conf.chandef.chan->band == NL80211_BAND_6GHZ) { +	if (sta->deflink.ht_cap.ht_supported || +	    mvm_sta->vif->bss_conf.chandef.chan->band == NL80211_BAND_6GHZ)  		add_sta_cmd.station_flags_msk |=  			cpu_to_le32(STA_FLG_MAX_AGG_SIZE_MSK |  				    STA_FLG_AGG_MPDU_DENS_MSK); -		mpdu_dens = le16_get_bits(sta->deflink.he_6ghz_capa.capa, -					  IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START); -		agg_size = le16_get_bits(sta->deflink.he_6ghz_capa.capa, -					 IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP); -	} else if (sta->deflink.vht_cap.vht_supported) { -		agg_size = sta->deflink.vht_cap.cap & -			IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; -		agg_size >>= -			IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; -	} else if (sta->deflink.ht_cap.ht_supported) { -		agg_size = sta->deflink.ht_cap.ampdu_factor; -	} - -	/* D6.0 10.12.2 A-MPDU length limit rules -	 * A STA indicates the maximum length of the A-MPDU preEOF padding -	 * that it can receive in an HE PPDU in the Maximum A-MPDU Length -	 * Exponent field in its HT Capabilities, VHT Capabilities, -	 * and HE 6 GHz Band Capabilities elements (if present) and the -	 * Maximum AMPDU Length Exponent Extension field in its HE -	 * Capabilities element -	 */ -	if (sta->deflink.he_cap.has_he) -		agg_size += u8_get_bits(sta->deflink.he_cap.he_cap_elem.mac_cap_info[3], -					IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK); - -	/* Limit to max A-MPDU supported by FW */ -	if (agg_size > (STA_FLG_MAX_AGG_SIZE_4M >> STA_FLG_MAX_AGG_SIZE_SHIFT)) -		agg_size = (STA_FLG_MAX_AGG_SIZE_4M >> -			    STA_FLG_MAX_AGG_SIZE_SHIFT); - +	mpdu_dens = iwl_mvm_get_sta_ampdu_dens(&sta->deflink, +					       &mvm_sta->vif->bss_conf, +					       &agg_size);  	add_sta_cmd.station_flags |=  		cpu_to_le32(agg_size << STA_FLG_MAX_AGG_SIZE_SHIFT);  	add_sta_cmd.station_flags |=  		cpu_to_le32(mpdu_dens << STA_FLG_AGG_MPDU_DENS_SHIFT); +  	if (mvm_sta->sta_state >= IEEE80211_STA_ASSOC)  		add_sta_cmd.assoc_id = cpu_to_le16(sta->aid);  	if (sta->wme) {  		add_sta_cmd.modify_mask |= STA_MODIFY_UAPSD_ACS; - -		if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK) -			add_sta_cmd.uapsd_acs |= BIT(AC_BK); -		if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE) -			add_sta_cmd.uapsd_acs |= BIT(AC_BE); -		if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI) -			add_sta_cmd.uapsd_acs |= BIT(AC_VI); -		if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) -			add_sta_cmd.uapsd_acs |= BIT(AC_VO); -		add_sta_cmd.uapsd_acs |= add_sta_cmd.uapsd_acs << 4; +		add_sta_cmd.uapsd_acs = iwl_mvm_get_sta_uapsd_acs(sta);  		add_sta_cmd.sp_length = sta->max_sp ? sta->max_sp * 2 : 128;  	} @@ -228,6 +251,7 @@ static void iwl_mvm_rx_agg_session_expired(struct timer_list *t)  	struct ieee80211_sta *sta;  	struct iwl_mvm_sta *mvm_sta;  	unsigned long timeout; +	unsigned int sta_id;  	rcu_read_lock(); @@ -246,7 +270,8 @@ static void iwl_mvm_rx_agg_session_expired(struct timer_list *t)  	}  	/* Timer expired */ -	sta = rcu_dereference(ba_data->mvm->fw_id_to_mac_id[ba_data->sta_id]); +	sta_id = ffs(ba_data->sta_mask) - 1; /* don't care which one */ +	sta = rcu_dereference(ba_data->mvm->fw_id_to_mac_id[sta_id]);  	/*  	 * sta should be valid unless the following happens: @@ -296,7 +321,7 @@ static int iwl_mvm_invalidate_sta_queue(struct iwl_mvm *mvm, int queue,  	mvmsta->tid_disable_agg |= disable_agg_tids;  	cmd.mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color); -	cmd.sta_id = mvmsta->sta_id; +	cmd.sta_id = mvmsta->deflink.sta_id;  	cmd.add_modify = STA_MODE_MODIFY;  	cmd.modify_mask = STA_MODIFY_QUEUES;  	if (disable_agg_tids) @@ -333,10 +358,14 @@ static int iwl_mvm_disable_txq(struct iwl_mvm *mvm, struct ieee80211_sta *sta,  					     SCD_QUEUE_CONFIG_CMD);  			struct iwl_scd_queue_cfg_cmd remove_cmd = {  				.operation = cpu_to_le32(IWL_SCD_QUEUE_REMOVE), -				.u.remove.tid = cpu_to_le32(tid),  				.u.remove.sta_mask = cpu_to_le32(BIT(sta_id)),  			}; +			if (tid == IWL_MAX_TID_COUNT) +				tid = IWL_MGMT_TID; + +			remove_cmd.u.remove.tid = cpu_to_le32(tid); +  			ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0,  						   sizeof(remove_cmd),  						   &remove_cmd); @@ -384,8 +413,11 @@ static int iwl_mvm_disable_txq(struct iwl_mvm *mvm, struct ieee80211_sta *sta,  		struct iwl_mvm_txq *mvmtxq =  			iwl_mvm_txq_from_tid(sta, tid); -		mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE; +		spin_lock_bh(&mvm->add_stream_lock);  		list_del_init(&mvmtxq->list); +		clear_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state); +		mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE; +		spin_unlock_bh(&mvm->add_stream_lock);  	}  	/* Regardless if this is a reserved TXQ for a STA - mark it as false */ @@ -479,8 +511,11 @@ static int iwl_mvm_remove_sta_queue_marking(struct iwl_mvm *mvm, int queue)  			disable_agg_tids |= BIT(tid);  		mvmsta->tid_data[tid].txq_id = IWL_MVM_INVALID_QUEUE; -		mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE; +		spin_lock_bh(&mvm->add_stream_lock);  		list_del_init(&mvmtxq->list); +		clear_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state); +		mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE; +		spin_unlock_bh(&mvm->add_stream_lock);  	}  	mvmsta->tfd_queue_msk &= ~BIT(queue); /* Don't use this queue anymore */ @@ -693,7 +728,7 @@ static int iwl_mvm_redirect_queue(struct iwl_mvm *mvm, int queue, int tid,  			    queue, iwl_mvm_ac_to_tx_fifo[ac]);  	/* Stop the queue and wait for it to empty */ -	txq->stopped = true; +	set_bit(IWL_MVM_TXQ_STATE_STOP_REDIRECT, &txq->state);  	ret = iwl_trans_wait_tx_queues_empty(mvm->trans, BIT(queue));  	if (ret) { @@ -736,7 +771,7 @@ static int iwl_mvm_redirect_queue(struct iwl_mvm *mvm, int queue, int tid,  out:  	/* Continue using the queue */ -	txq->stopped = false; +	clear_bit(IWL_MVM_TXQ_STATE_STOP_REDIRECT, &txq->state);  	return ret;  } @@ -766,32 +801,52 @@ static int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 sta_id,  	return -ENOSPC;  } -static int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm, -				   u8 sta_id, u8 tid, unsigned int timeout) +static int iwl_mvm_get_queue_size(struct ieee80211_sta *sta) +{ +	int max_size = IWL_DEFAULT_QUEUE_SIZE; +	unsigned int link_id; + +	/* this queue isn't used for traffic (cab_queue) */ +	if (!sta) +		return IWL_MGMT_QUEUE_SIZE; + +	rcu_read_lock(); + +	for (link_id = 0; link_id < ARRAY_SIZE(sta->link); link_id++) { +		struct ieee80211_link_sta *link = +			rcu_dereference(sta->link[link_id]); + +		if (!link) +			continue; + +		/* support for 1k ba size */ +		if (link->eht_cap.has_eht && +		    max_size < IWL_DEFAULT_QUEUE_SIZE_EHT) +			max_size = IWL_DEFAULT_QUEUE_SIZE_EHT; + +		/* support for 256 ba size */ +		if (link->he_cap.has_he && +		    max_size < IWL_DEFAULT_QUEUE_SIZE_HE) +			max_size = IWL_DEFAULT_QUEUE_SIZE_HE; +	} + +	rcu_read_unlock(); +	return max_size; +} + +int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm, +			    struct ieee80211_sta *sta, +			    u8 sta_id, u8 tid, unsigned int timeout)  {  	int queue, size; +	u32 sta_mask = 0;  	if (tid == IWL_MAX_TID_COUNT) {  		tid = IWL_MGMT_TID;  		size = max_t(u32, IWL_MGMT_QUEUE_SIZE,  			     mvm->trans->cfg->min_txq_size);  	} else { -		struct ieee80211_sta *sta; - -		rcu_read_lock(); -		sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); - -		/* this queue isn't used for traffic (cab_queue) */ -		if (IS_ERR_OR_NULL(sta)) { -			size = IWL_MGMT_QUEUE_SIZE; -		} else if (sta->deflink.he_cap.has_he) { -			/* support for 256 ba size */ -			size = IWL_DEFAULT_QUEUE_SIZE_HE; -		} else { -			size = IWL_DEFAULT_QUEUE_SIZE; -		} - -		rcu_read_unlock(); +		size = iwl_mvm_get_queue_size(sta);  	}  	/* take the min with bc tbl entries allowed */ @@ -800,22 +855,45 @@ static int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm,  	/* size needs to be power of 2 values for calculating read/write pointers */  	size = rounddown_pow_of_two(size); +	if (sta) { +		struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); +		unsigned int link_id; + +		for (link_id = 0; +		     link_id < ARRAY_SIZE(mvmsta->link); +		     link_id++) { +			struct iwl_mvm_link_sta *link = +				rcu_dereference_protected(mvmsta->link[link_id], +							  lockdep_is_held(&mvm->mutex)); + +			if (!link) +				continue; + +			sta_mask |= BIT(link->sta_id); +		} +	} else { +		sta_mask |= BIT(sta_id); +	} + +	if (!sta_mask) +		return -EINVAL; +  	do { -		queue = iwl_trans_txq_alloc(mvm->trans, 0, BIT(sta_id), +		queue = iwl_trans_txq_alloc(mvm->trans, 0, sta_mask,  					    tid, size, timeout);  		if (queue < 0)  			IWL_DEBUG_TX_QUEUES(mvm, -					    "Failed allocating TXQ of size %d for sta %d tid %d, ret: %d\n", -					    size, sta_id, tid, queue); +					    "Failed allocating TXQ of size %d for sta mask %x tid %d, ret: %d\n", +					    size, sta_mask, tid, queue);  		size /= 2;  	} while (queue < 0 && size >= 16);  	if (queue < 0)  		return queue; -	IWL_DEBUG_TX_QUEUES(mvm, "Enabling TXQ #%d for sta %d tid %d\n", -			    queue, sta_id, tid); +	IWL_DEBUG_TX_QUEUES(mvm, "Enabling TXQ #%d for sta mask 0x%x tid %d\n", +			    queue, sta_mask, tid);  	return queue;  } @@ -835,14 +913,15 @@ static int iwl_mvm_sta_alloc_queue_tvqm(struct iwl_mvm *mvm,  	IWL_DEBUG_TX_QUEUES(mvm,  			    "Allocating queue for sta %d on tid %d\n", -			    mvmsta->sta_id, tid); -	queue = iwl_mvm_tvqm_enable_txq(mvm, mvmsta->sta_id, tid, wdg_timeout); +			    mvmsta->deflink.sta_id, tid); +	queue = iwl_mvm_tvqm_enable_txq(mvm, sta, mvmsta->deflink.sta_id, +					tid, wdg_timeout);  	if (queue < 0)  		return queue;  	mvmtxq->txq_id = queue;  	mvm->tvqm_info[queue].txq_tid = tid; -	mvm->tvqm_info[queue].sta_id = mvmsta->sta_id; +	mvm->tvqm_info[queue].sta_id = mvmsta->deflink.sta_id;  	IWL_DEBUG_TX_QUEUES(mvm, "Allocated queue is %d\n", queue); @@ -1027,7 +1106,7 @@ static void iwl_mvm_unshare_queue(struct iwl_mvm *mvm, int queue)  		mvmsta->tid_disable_agg &= ~BIT(tid);  		cmd.mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color); -		cmd.sta_id = mvmsta->sta_id; +		cmd.sta_id = mvmsta->deflink.sta_id;  		cmd.add_modify = STA_MODE_MODIFY;  		cmd.modify_mask = STA_MODIFY_TID_DISABLE_TX;  		cmd.tfd_queue_msk = cpu_to_le32(mvmsta->tfd_queue_msk); @@ -1252,7 +1331,7 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,  	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);  	struct iwl_trans_txq_scd_cfg cfg = {  		.fifo = iwl_mvm_mac_ac_to_tx_fifo(mvm, ac), -		.sta_id = mvmsta->sta_id, +		.sta_id = mvmsta->deflink.sta_id,  		.tid = tid,  		.frame_limit = IWL_FRAME_LIMIT,  	}; @@ -1278,7 +1357,7 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,  	spin_unlock_bh(&mvmsta->lock);  	if (tid == IWL_MAX_TID_COUNT) { -		queue = iwl_mvm_find_free_queue(mvm, mvmsta->sta_id, +		queue = iwl_mvm_find_free_queue(mvm, mvmsta->deflink.sta_id,  						IWL_MVM_DQA_MIN_MGMT_QUEUE,  						IWL_MVM_DQA_MAX_MGMT_QUEUE);  		if (queue >= IWL_MVM_DQA_MIN_MGMT_QUEUE) @@ -1297,12 +1376,12 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,  	}  	if (queue < 0) -		queue = iwl_mvm_find_free_queue(mvm, mvmsta->sta_id, +		queue = iwl_mvm_find_free_queue(mvm, mvmsta->deflink.sta_id,  						IWL_MVM_DQA_MIN_DATA_QUEUE,  						IWL_MVM_DQA_MAX_DATA_QUEUE);  	if (queue < 0) {  		/* try harder - perhaps kill an inactive queue */ -		queue = iwl_mvm_inactivity_check(mvm, mvmsta->sta_id); +		queue = iwl_mvm_inactivity_check(mvm, mvmsta->deflink.sta_id);  	}  	/* No free queue - we'll have to share */ @@ -1342,7 +1421,7 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,  	IWL_DEBUG_TX_QUEUES(mvm,  			    "Allocating %squeue #%d to sta %d on tid %d\n",  			    shared_queue ? "shared " : "", queue, -			    mvmsta->sta_id, tid); +			    mvmsta->deflink.sta_id, tid);  	if (shared_queue) {  		/* Disable any open aggs on this queue */ @@ -1409,7 +1488,7 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,  out_err:  	queue_tmp = queue; -	iwl_mvm_disable_txq(mvm, sta, mvmsta->sta_id, &queue_tmp, tid); +	iwl_mvm_disable_txq(mvm, sta, mvmsta->deflink.sta_id, &queue_tmp, tid);  	return ret;  } @@ -1444,12 +1523,22 @@ void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk)  		 * a queue in the function itself.  		 */  		if (iwl_mvm_sta_alloc_queue(mvm, txq->sta, txq->ac, tid)) { +			spin_lock_bh(&mvm->add_stream_lock);  			list_del_init(&mvmtxq->list); +			spin_unlock_bh(&mvm->add_stream_lock);  			continue;  		} -		list_del_init(&mvmtxq->list); +		/* now we're ready, any remaining races/concurrency will be +		 * handled in iwl_mvm_mac_itxq_xmit() +		 */ +		set_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state); +  		local_bh_disable(); +		spin_lock(&mvm->add_stream_lock); +		list_del_init(&mvmtxq->list); +		spin_unlock(&mvm->add_stream_lock); +  		iwl_mvm_mac_itxq_xmit(mvm->hw, txq);  		local_bh_enable();  	} @@ -1478,12 +1567,12 @@ static int iwl_mvm_reserve_sta_stream(struct iwl_mvm *mvm,  	     IWL_MVM_QUEUE_FREE))  		queue = IWL_MVM_DQA_BSS_CLIENT_QUEUE;  	else -		queue = iwl_mvm_find_free_queue(mvm, mvmsta->sta_id, +		queue = iwl_mvm_find_free_queue(mvm, mvmsta->deflink.sta_id,  						IWL_MVM_DQA_MIN_DATA_QUEUE,  						IWL_MVM_DQA_MAX_DATA_QUEUE);  	if (queue < 0) {  		/* try again - this time kick out a queue if needed */ -		queue = iwl_mvm_inactivity_check(mvm, mvmsta->sta_id); +		queue = iwl_mvm_inactivity_check(mvm, mvmsta->deflink.sta_id);  		if (queue < 0) {  			IWL_ERR(mvm, "No available queues for new station\n");  			return -ENOSPC; @@ -1494,7 +1583,7 @@ static int iwl_mvm_reserve_sta_stream(struct iwl_mvm *mvm,  	mvmsta->reserved_queue = queue;  	IWL_DEBUG_TX_QUEUES(mvm, "Reserving data queue #%d for sta_id %d\n", -			    queue, mvmsta->sta_id); +			    queue, mvmsta->deflink.sta_id);  	return 0;  } @@ -1506,15 +1595,15 @@ static int iwl_mvm_reserve_sta_stream(struct iwl_mvm *mvm,   *   * Note that re-enabling aggregations isn't done in this function.   */ -static void iwl_mvm_realloc_queues_after_restart(struct iwl_mvm *mvm, -						 struct ieee80211_sta *sta) +void iwl_mvm_realloc_queues_after_restart(struct iwl_mvm *mvm, +					  struct ieee80211_sta *sta)  {  	struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);  	unsigned int wdg =  		iwl_mvm_get_wd_timeout(mvm, mvm_sta->vif, false, false);  	int i;  	struct iwl_trans_txq_scd_cfg cfg = { -		.sta_id = mvm_sta->sta_id, +		.sta_id = mvm_sta->deflink.sta_id,  		.frame_limit = IWL_FRAME_LIMIT,  	}; @@ -1536,8 +1625,9 @@ static void iwl_mvm_realloc_queues_after_restart(struct iwl_mvm *mvm,  		if (iwl_mvm_has_new_tx_api(mvm)) {  			IWL_DEBUG_TX_QUEUES(mvm,  					    "Re-mapping sta %d tid %d\n", -					    mvm_sta->sta_id, i); -			txq_id = iwl_mvm_tvqm_enable_txq(mvm, mvm_sta->sta_id, +					    mvm_sta->deflink.sta_id, i); +			txq_id = iwl_mvm_tvqm_enable_txq(mvm, sta, +							 mvm_sta->deflink.sta_id,  							 i, wdg);  			/*  			 * on failures, just set it to IWL_MVM_INVALID_QUEUE @@ -1566,7 +1656,8 @@ static void iwl_mvm_realloc_queues_after_restart(struct iwl_mvm *mvm,  			IWL_DEBUG_TX_QUEUES(mvm,  					    "Re-mapping sta %d tid %d to queue %d\n", -					    mvm_sta->sta_id, i, txq_id); +					    mvm_sta->deflink.sta_id, i, +					    txq_id);  			iwl_mvm_enable_txq(mvm, sta, txq_id, seq, &cfg, wdg);  			mvm->queue_info[txq_id].status = IWL_MVM_QUEUE_READY; @@ -1624,74 +1715,45 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm,  	return ret;  } -int iwl_mvm_add_sta(struct iwl_mvm *mvm, -		    struct ieee80211_vif *vif, -		    struct ieee80211_sta *sta) +/* Initialize driver data of a new sta */ +int iwl_mvm_sta_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif, +		     struct ieee80211_sta *sta, int sta_id, u8 sta_type)  {  	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);  	struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);  	struct iwl_mvm_rxq_dup_data *dup_data; -	int i, ret, sta_id; -	bool sta_update = false; -	unsigned int sta_flags = 0; +	int i, ret = 0;  	lockdep_assert_held(&mvm->mutex); -	if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) -		sta_id = iwl_mvm_find_free_sta_id(mvm, -						  ieee80211_vif_type_p2p(vif)); -	else -		sta_id = mvm_sta->sta_id; - -	if (sta_id == IWL_MVM_INVALID_STA) -		return -ENOSPC; - -	spin_lock_init(&mvm_sta->lock); +	mvm_sta->mac_id_n_color = FW_CMD_ID_AND_COLOR(mvmvif->id, +						      mvmvif->color); +	mvm_sta->vif = vif; -	/* if this is a HW restart re-alloc existing queues */ -	if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { -		struct iwl_mvm_int_sta tmp_sta = { -			.sta_id = sta_id, -			.type = mvm_sta->sta_type, -		}; +	/* for MLD sta_id(s) should be allocated for each link before calling +	 * this function +	 */ +	if (!mvm->mld_api_is_used) { +		if (WARN_ON(sta_id == IWL_MVM_INVALID_STA)) +			return -EINVAL; -		/* -		 * First add an empty station since allocating -		 * a queue requires a valid station -		 */ -		ret = iwl_mvm_add_int_sta_common(mvm, &tmp_sta, sta->addr, -						 mvmvif->id, mvmvif->color); -		if (ret) -			goto err; +		mvm_sta->deflink.sta_id = sta_id; +		rcu_assign_pointer(mvm_sta->link[0], &mvm_sta->deflink); -		iwl_mvm_realloc_queues_after_restart(mvm, sta); -		sta_update = true; -		sta_flags = iwl_mvm_has_new_tx_api(mvm) ? 0 : STA_MODIFY_QUEUES; -		goto update_fw; +		if (!mvm->trans->trans_cfg->gen2) +			mvm_sta->deflink.lq_sta.rs_drv.pers.max_agg_bufsize = +				LINK_QUAL_AGG_FRAME_LIMIT_DEF; +		else +			mvm_sta->deflink.lq_sta.rs_drv.pers.max_agg_bufsize = +				LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF;  	} -	mvm_sta->sta_id = sta_id; -	mvm_sta->mac_id_n_color = FW_CMD_ID_AND_COLOR(mvmvif->id, -						      mvmvif->color); -	mvm_sta->vif = vif; -	if (!mvm->trans->trans_cfg->gen2) -		mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_DEF; -	else -		mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF; -	mvm_sta->tx_protection = 0;  	mvm_sta->tt_tx_protection = false; -	mvm_sta->sta_type = sta->tdls ? IWL_STA_TDLS_LINK : IWL_STA_LINK; +	mvm_sta->sta_type = sta_type; -	/* HW restart, don't assume the memory has been zeroed */  	mvm_sta->tid_disable_agg = 0xffff; /* No aggs at first */ -	mvm_sta->tfd_queue_msk = 0; -	/* for HW restart - reset everything but the sequence number */  	for (i = 0; i <= IWL_MAX_TID_COUNT; i++) { -		u16 seq = mvm_sta->tid_data[i].seq_number; -		memset(&mvm_sta->tid_data[i], 0, sizeof(mvm_sta->tid_data[i])); -		mvm_sta->tid_data[i].seq_number = seq; -  		/*  		 * Mark all queues for this STA as unallocated and defer TX  		 * frames until the queue is allocated @@ -1708,10 +1770,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,  		atomic_set(&mvmtxq->tx_request, 0);  	} -	mvm_sta->agg_tids = 0; - -	if (iwl_mvm_has_new_rx_api(mvm) && -	    !test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { +	if (iwl_mvm_has_new_rx_api(mvm)) {  		int q;  		dup_data = kcalloc(mvm->trans->num_rx_queues, @@ -1737,7 +1796,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,  		ret = iwl_mvm_reserve_sta_stream(mvm, sta,  						 ieee80211_vif_type_p2p(vif));  		if (ret) -			goto err; +			return ret;  	}  	/* @@ -1747,10 +1806,60 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,  	if (iwl_mvm_has_tlc_offload(mvm))  		iwl_mvm_rs_add_sta(mvm, mvm_sta);  	else -		spin_lock_init(&mvm_sta->lq_sta.rs_drv.pers.lock); +		spin_lock_init(&mvm_sta->deflink.lq_sta.rs_drv.pers.lock);  	iwl_mvm_toggle_tx_ant(mvm, &mvm_sta->tx_ant); +	return 0; +} + +int iwl_mvm_add_sta(struct iwl_mvm *mvm, +		    struct ieee80211_vif *vif, +		    struct ieee80211_sta *sta) +{ +	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); +	struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); +	int ret, sta_id; +	bool sta_update = false; +	unsigned int sta_flags = 0; + +	lockdep_assert_held(&mvm->mutex); + +	if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) +		sta_id = iwl_mvm_find_free_sta_id(mvm, +						  ieee80211_vif_type_p2p(vif)); +	else +		sta_id = mvm_sta->deflink.sta_id; + +	if (sta_id == IWL_MVM_INVALID_STA) +		return -ENOSPC; + +	spin_lock_init(&mvm_sta->lock); + +	/* if this is a HW restart re-alloc existing queues */ +	if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { +		struct iwl_mvm_int_sta tmp_sta = { +			.sta_id = sta_id, +			.type = mvm_sta->sta_type, +		}; + +		/* First add an empty station since allocating +		 * a queue requires a valid station +		 */ +		ret = iwl_mvm_add_int_sta_common(mvm, &tmp_sta, sta->addr, +						 mvmvif->id, mvmvif->color); +		if (ret) +			goto err; + +		iwl_mvm_realloc_queues_after_restart(mvm, sta); +		sta_update = true; +		sta_flags = iwl_mvm_has_new_tx_api(mvm) ? 0 : STA_MODIFY_QUEUES; +		goto update_fw; +	} + +	ret = iwl_mvm_sta_init(mvm, vif, sta, sta_id, +			       sta->tdls ? IWL_STA_TDLS_LINK : IWL_STA_LINK); +  update_fw:  	ret = iwl_mvm_sta_send_to_fw(mvm, sta, sta_update, sta_flags);  	if (ret) @@ -1758,10 +1867,10 @@ update_fw:  	if (vif->type == NL80211_IFTYPE_STATION) {  		if (!sta->tdls) { -			WARN_ON(mvmvif->ap_sta_id != IWL_MVM_INVALID_STA); -			mvmvif->ap_sta_id = sta_id; +			WARN_ON(mvmvif->deflink.ap_sta_id != IWL_MVM_INVALID_STA); +			mvmvif->deflink.ap_sta_id = sta_id;  		} else { -			WARN_ON(mvmvif->ap_sta_id == IWL_MVM_INVALID_STA); +			WARN_ON(mvmvif->deflink.ap_sta_id == IWL_MVM_INVALID_STA);  		}  	} @@ -1783,7 +1892,7 @@ int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,  	lockdep_assert_held(&mvm->mutex);  	cmd.mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color); -	cmd.sta_id = mvmsta->sta_id; +	cmd.sta_id = mvmsta->deflink.sta_id;  	cmd.add_modify = STA_MODE_MODIFY;  	cmd.station_flags = drain ? cpu_to_le32(STA_FLG_DRAIN_FLOW) : 0;  	cmd.station_flags_msk = cpu_to_le32(STA_FLG_DRAIN_FLOW); @@ -1798,12 +1907,12 @@ int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,  	switch (status & IWL_ADD_STA_STATUS_MASK) {  	case ADD_STA_SUCCESS:  		IWL_DEBUG_INFO(mvm, "Frames for staid %d will drained in fw\n", -			       mvmsta->sta_id); +			       mvmsta->deflink.sta_id);  		break;  	default:  		ret = -EIO;  		IWL_ERR(mvm, "Couldn't drain frames for staid %d\n", -			mvmsta->sta_id); +			mvmsta->deflink.sta_id);  		break;  	} @@ -1855,7 +1964,7 @@ static void iwl_mvm_disable_sta_queues(struct iwl_mvm *mvm,  		if (mvm_sta->tid_data[i].txq_id == IWL_MVM_INVALID_QUEUE)  			continue; -		iwl_mvm_disable_txq(mvm, sta, mvm_sta->sta_id, +		iwl_mvm_disable_txq(mvm, sta, mvm_sta->deflink.sta_id,  				    &mvm_sta->tid_data[i].txq_id, i);  		mvm_sta->tid_data[i].txq_id = IWL_MVM_INVALID_QUEUE;  	} @@ -1864,8 +1973,11 @@ static void iwl_mvm_disable_sta_queues(struct iwl_mvm *mvm,  		struct iwl_mvm_txq *mvmtxq =  			iwl_mvm_txq_from_mac80211(sta->txq[i]); +		spin_lock_bh(&mvm->add_stream_lock);  		mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;  		list_del_init(&mvmtxq->list); +		clear_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state); +		spin_unlock_bh(&mvm->add_stream_lock);  	}  } @@ -1893,42 +2005,27 @@ int iwl_mvm_wait_sta_queues_empty(struct iwl_mvm *mvm,  	return 0;  } -int iwl_mvm_rm_sta(struct iwl_mvm *mvm, -		   struct ieee80211_vif *vif, -		   struct ieee80211_sta *sta) +/* Execute the common part for both MLD and non-MLD modes. + * Returns if we're done with removing the station, either + * with error or success + */ +bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif, +		     struct ieee80211_sta *sta, +		     struct ieee80211_link_sta *link_sta, int *ret)  {  	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); +	struct iwl_mvm_vif_link_info *mvm_link = +		mvmvif->link[link_sta->link_id];  	struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); -	u8 sta_id = mvm_sta->sta_id; -	int ret; +	struct iwl_mvm_link_sta *mvm_link_sta; +	u8 sta_id;  	lockdep_assert_held(&mvm->mutex); -	if (iwl_mvm_has_new_rx_api(mvm)) -		kfree(mvm_sta->dup_data); - -	ret = iwl_mvm_drain_sta(mvm, mvm_sta, true); -	if (ret) -		return ret; - -	/* flush its queues here since we are freeing mvm_sta */ -	ret = iwl_mvm_flush_sta(mvm, mvm_sta, false); -	if (ret) -		return ret; -	if (iwl_mvm_has_new_tx_api(mvm)) { -		ret = iwl_mvm_wait_sta_queues_empty(mvm, mvm_sta); -	} else { -		u32 q_mask = mvm_sta->tfd_queue_msk; - -		ret = iwl_trans_wait_tx_queues_empty(mvm->trans, -						     q_mask); -	} -	if (ret) -		return ret; - -	ret = iwl_mvm_drain_sta(mvm, mvm_sta, false); - -	iwl_mvm_disable_sta_queues(mvm, vif, sta); +	mvm_link_sta = +		rcu_dereference_protected(mvm_sta->link[link_sta->link_id], +					  lockdep_is_held(&mvm->mutex)); +	sta_id = mvm_link_sta->sta_id;  	/* If there is a TXQ still marked as reserved - free it */  	if (mvm_sta->reserved_queue != IEEE80211_INVAL_HW_QUEUE) { @@ -1944,23 +2041,24 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,  		if (WARN((*status != IWL_MVM_QUEUE_RESERVED) &&  			 (*status != IWL_MVM_QUEUE_FREE),  			 "sta_id %d reserved txq %d status %d", -			 sta_id, reserved_txq, *status)) -			return -EINVAL; +			 sta_id, reserved_txq, *status)) { +			*ret = -EINVAL; +			return true; +		}  		*status = IWL_MVM_QUEUE_FREE;  	} -	if (vif->type == NL80211_IFTYPE_STATION && -	    mvmvif->ap_sta_id == sta_id) { +	if (vif->type == NL80211_IFTYPE_STATION) {  		/* if associated - we can't remove the AP STA now */  		if (vif->cfg.assoc) -			return ret; +			return true;  		/* first remove remaining keys */ -		iwl_mvm_sec_key_remove_ap(mvm, vif); +		iwl_mvm_sec_key_remove_ap(mvm, vif, mvm_link, 0);  		/* unassoc - go ahead - remove the AP STA now */ -		mvmvif->ap_sta_id = IWL_MVM_INVALID_STA; +		mvm_link->ap_sta_id = IWL_MVM_INVALID_STA;  	}  	/* @@ -1979,8 +2077,49 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,  	spin_lock_bh(&mvm_sta->lock);  	spin_unlock_bh(&mvm_sta->lock); -	ret = iwl_mvm_rm_sta_common(mvm, mvm_sta->sta_id); -	RCU_INIT_POINTER(mvm->fw_id_to_mac_id[mvm_sta->sta_id], NULL); +	return false; +} + +int iwl_mvm_rm_sta(struct iwl_mvm *mvm, +		   struct ieee80211_vif *vif, +		   struct ieee80211_sta *sta) +{ +	struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); +	int ret; + +	lockdep_assert_held(&mvm->mutex); + +	if (iwl_mvm_has_new_rx_api(mvm)) +		kfree(mvm_sta->dup_data); + +	ret = iwl_mvm_drain_sta(mvm, mvm_sta, true); +	if (ret) +		return ret; + +	/* flush its queues here since we are freeing mvm_sta */ +	ret = iwl_mvm_flush_sta(mvm, mvm_sta, false); +	if (ret) +		return ret; +	if (iwl_mvm_has_new_tx_api(mvm)) { +		ret = iwl_mvm_wait_sta_queues_empty(mvm, mvm_sta); +	} else { +		u32 q_mask = mvm_sta->tfd_queue_msk; + +		ret = iwl_trans_wait_tx_queues_empty(mvm->trans, +						     q_mask); +	} +	if (ret) +		return ret; + +	ret = iwl_mvm_drain_sta(mvm, mvm_sta, false); + +	iwl_mvm_disable_sta_queues(mvm, vif, sta); + +	if (iwl_mvm_sta_del(mvm, vif, sta, &sta->deflink, &ret)) +		return ret; + +	ret = iwl_mvm_rm_sta_common(mvm, mvm_sta->deflink.sta_id); +	RCU_INIT_POINTER(mvm->fw_id_to_mac_id[mvm_sta->deflink.sta_id], NULL);  	return ret;  } @@ -2000,7 +2139,7 @@ int iwl_mvm_rm_sta_id(struct iwl_mvm *mvm,  int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm,  			     struct iwl_mvm_int_sta *sta,  			     u32 qmask, enum nl80211_iftype iftype, -			     enum iwl_sta_type type) +			     u8 type)  {  	if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) ||  	    sta->sta_id == IWL_MVM_INVALID_STA) { @@ -2013,7 +2152,7 @@ int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm,  	sta->type = type;  	/* put a non-NULL value so iterating over the stations won't stop */ -	rcu_assign_pointer(mvm->fw_id_to_mac_id[sta->sta_id], ERR_PTR(-EINVAL)); +	RCU_INIT_POINTER(mvm->fw_id_to_mac_id[sta->sta_id], ERR_PTR(-EINVAL));  	return 0;  } @@ -2049,7 +2188,7 @@ static int iwl_mvm_enable_aux_snif_queue_tvqm(struct iwl_mvm *mvm, u8 sta_id)  	WARN_ON(!iwl_mvm_has_new_tx_api(mvm)); -	return iwl_mvm_tvqm_enable_txq(mvm, sta_id, IWL_MAX_TID_COUNT, +	return iwl_mvm_tvqm_enable_txq(mvm, NULL, sta_id, IWL_MAX_TID_COUNT,  				       wdg_timeout);  } @@ -2094,11 +2233,13 @@ static int iwl_mvm_add_int_sta_with_queue(struct iwl_mvm *mvm, int macidx,  int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm, u32 lmac_id)  {  	int ret; +	u32 qmask = mvm->aux_queue == IWL_MVM_INVALID_QUEUE ? 0 : +		BIT(mvm->aux_queue);  	lockdep_assert_held(&mvm->mutex);  	/* Allocate aux station and assign to it the aux queue */ -	ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, BIT(mvm->aux_queue), +	ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, qmask,  				       NL80211_IFTYPE_UNSPECIFIED,  				       IWL_STA_AUX_ACTIVITY);  	if (ret) @@ -2184,7 +2325,7 @@ void iwl_mvm_dealloc_snif_sta(struct iwl_mvm *mvm)  int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)  {  	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); -	struct iwl_mvm_int_sta *bsta = &mvmvif->bcast_sta; +	struct iwl_mvm_int_sta *bsta = &mvmvif->deflink.bcast_sta;  	static const u8 _baddr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};  	const u8 *baddr = _baddr;  	int queue; @@ -2193,7 +2334,7 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)  		iwl_mvm_get_wd_timeout(mvm, vif, false, false);  	struct iwl_trans_txq_scd_cfg cfg = {  		.fifo = IWL_MVM_TX_FIFO_VO, -		.sta_id = mvmvif->bcast_sta.sta_id, +		.sta_id = mvmvif->deflink.bcast_sta.sta_id,  		.tid = IWL_MAX_TID_COUNT,  		.aggregate = false,  		.frame_limit = IWL_FRAME_LIMIT, @@ -2233,7 +2374,7 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)  	 * to firmware so enable queue here - after the station was added  	 */  	if (iwl_mvm_has_new_tx_api(mvm)) { -		queue = iwl_mvm_tvqm_enable_txq(mvm, bsta->sta_id, +		queue = iwl_mvm_tvqm_enable_txq(mvm, NULL, bsta->sta_id,  						IWL_MAX_TID_COUNT,  						wdg_timeout);  		if (queue < 0) { @@ -2242,24 +2383,32 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)  		}  		if (vif->type == NL80211_IFTYPE_AP || -		    vif->type == NL80211_IFTYPE_ADHOC) +		    vif->type == NL80211_IFTYPE_ADHOC) { +			/* for queue management */  			mvm->probe_queue = queue; -		else if (vif->type == NL80211_IFTYPE_P2P_DEVICE) +			/* for use in TX */ +			mvmvif->deflink.mgmt_queue = queue; +		} else if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {  			mvm->p2p_dev_queue = queue; +		} +	} else if (vif->type == NL80211_IFTYPE_AP || +		   vif->type == NL80211_IFTYPE_ADHOC) { +		/* set it for use in TX */ +		mvmvif->deflink.mgmt_queue = mvm->probe_queue;  	}  	return 0;  } -static void iwl_mvm_free_bcast_sta_queues(struct iwl_mvm *mvm, -					  struct ieee80211_vif *vif) +void iwl_mvm_free_bcast_sta_queues(struct iwl_mvm *mvm, +				   struct ieee80211_vif *vif)  {  	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);  	u16 *queueptr, queue;  	lockdep_assert_held(&mvm->mutex); -	iwl_mvm_flush_sta(mvm, &mvmvif->bcast_sta, true); +	iwl_mvm_flush_sta(mvm, &mvmvif->deflink.bcast_sta, true);  	switch (vif->type) {  	case NL80211_IFTYPE_AP: @@ -2276,13 +2425,17 @@ static void iwl_mvm_free_bcast_sta_queues(struct iwl_mvm *mvm,  	}  	queue = *queueptr; -	iwl_mvm_disable_txq(mvm, NULL, mvmvif->bcast_sta.sta_id, +	iwl_mvm_disable_txq(mvm, NULL, mvmvif->deflink.bcast_sta.sta_id,  			    queueptr, IWL_MAX_TID_COUNT); + +	if (vif->type == NL80211_IFTYPE_AP || vif->type == NL80211_IFTYPE_ADHOC) +		mvmvif->deflink.mgmt_queue = mvm->probe_queue; +  	if (iwl_mvm_has_new_tx_api(mvm))  		return; -	WARN_ON(!(mvmvif->bcast_sta.tfd_queue_msk & BIT(queue))); -	mvmvif->bcast_sta.tfd_queue_msk &= ~BIT(queue); +	WARN_ON(!(mvmvif->deflink.bcast_sta.tfd_queue_msk & BIT(queue))); +	mvmvif->deflink.bcast_sta.tfd_queue_msk &= ~BIT(queue);  }  /* Send the FW a request to remove the station from it's internal data @@ -2296,7 +2449,7 @@ int iwl_mvm_send_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)  	iwl_mvm_free_bcast_sta_queues(mvm, vif); -	ret = iwl_mvm_rm_sta_common(mvm, mvmvif->bcast_sta.sta_id); +	ret = iwl_mvm_rm_sta_common(mvm, mvmvif->deflink.bcast_sta.sta_id);  	if (ret)  		IWL_WARN(mvm, "Failed sending remove station\n");  	return ret; @@ -2308,7 +2461,7 @@ int iwl_mvm_alloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)  	lockdep_assert_held(&mvm->mutex); -	return iwl_mvm_allocate_int_sta(mvm, &mvmvif->bcast_sta, 0, +	return iwl_mvm_allocate_int_sta(mvm, &mvmvif->deflink.bcast_sta, 0,  					ieee80211_vif_type_p2p(vif),  					IWL_STA_GENERAL_PURPOSE);  } @@ -2323,7 +2476,7 @@ int iwl_mvm_alloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)  int iwl_mvm_add_p2p_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)  {  	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); -	struct iwl_mvm_int_sta *bsta = &mvmvif->bcast_sta; +	struct iwl_mvm_int_sta *bsta = &mvmvif->deflink.bcast_sta;  	int ret;  	lockdep_assert_held(&mvm->mutex); @@ -2344,7 +2497,7 @@ void iwl_mvm_dealloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)  {  	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); -	iwl_mvm_dealloc_int_sta(mvm, &mvmvif->bcast_sta); +	iwl_mvm_dealloc_int_sta(mvm, &mvmvif->deflink.bcast_sta);  }  /* @@ -2375,7 +2528,7 @@ int iwl_mvm_rm_p2p_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)  int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)  {  	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); -	struct iwl_mvm_int_sta *msta = &mvmvif->mcast_sta; +	struct iwl_mvm_int_sta *msta = &mvmvif->deflink.mcast_sta;  	static const u8 _maddr[] = {0x03, 0x00, 0x00, 0x00, 0x00, 0x00};  	const u8 *maddr = _maddr;  	struct iwl_trans_txq_scd_cfg cfg = { @@ -2402,7 +2555,7 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)  	 * changes in mac80211 layer.  	 */  	if (vif->type == NL80211_IFTYPE_ADHOC) -		mvmvif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE; +		mvmvif->deflink.cab_queue = IWL_MVM_DQA_GCAST_QUEUE;  	/*  	 * While in previous FWs we had to exclude cab queue from TFD queue @@ -2410,9 +2563,10 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)  	 */  	if (!iwl_mvm_has_new_tx_api(mvm) &&  	    fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_STA_TYPE)) { -		iwl_mvm_enable_txq(mvm, NULL, mvmvif->cab_queue, 0, &cfg, +		iwl_mvm_enable_txq(mvm, NULL, mvmvif->deflink.cab_queue, 0, +				   &cfg,  				   timeout); -		msta->tfd_queue_msk |= BIT(mvmvif->cab_queue); +		msta->tfd_queue_msk |= BIT(mvmvif->deflink.cab_queue);  	}  	ret = iwl_mvm_add_int_sta_common(mvm, msta, maddr,  					 mvmvif->id, mvmvif->color); @@ -2427,17 +2581,17 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)  	 * tfd_queue_mask.  	 */  	if (iwl_mvm_has_new_tx_api(mvm)) { -		int queue = iwl_mvm_tvqm_enable_txq(mvm, msta->sta_id, -						    0, -						    timeout); +		int queue = iwl_mvm_tvqm_enable_txq(mvm, NULL, msta->sta_id, +						    0, timeout);  		if (queue < 0) {  			ret = queue;  			goto err;  		} -		mvmvif->cab_queue = queue; +		mvmvif->deflink.cab_queue = queue;  	} else if (!fw_has_api(&mvm->fw->ucode_capa,  			       IWL_UCODE_TLV_API_STA_TYPE)) -		iwl_mvm_enable_txq(mvm, NULL, mvmvif->cab_queue, 0, &cfg, +		iwl_mvm_enable_txq(mvm, NULL, mvmvif->deflink.cab_queue, 0, +				   &cfg,  				   timeout);  	return 0; @@ -2510,12 +2664,12 @@ int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)  	lockdep_assert_held(&mvm->mutex); -	iwl_mvm_flush_sta(mvm, &mvmvif->mcast_sta, true); +	iwl_mvm_flush_sta(mvm, &mvmvif->deflink.mcast_sta, true); -	iwl_mvm_disable_txq(mvm, NULL, mvmvif->mcast_sta.sta_id, -			    &mvmvif->cab_queue, 0); +	iwl_mvm_disable_txq(mvm, NULL, mvmvif->deflink.mcast_sta.sta_id, +			    &mvmvif->deflink.cab_queue, 0); -	ret = iwl_mvm_rm_sta_common(mvm, mvmvif->mcast_sta.sta_id); +	ret = iwl_mvm_rm_sta_common(mvm, mvmvif->deflink.mcast_sta.sta_id);  	if (ret)  		IWL_WARN(mvm, "Failed sending remove station\n"); @@ -2604,13 +2758,14 @@ static void iwl_mvm_init_reorder_buffer(struct iwl_mvm *mvm,  }  static int iwl_mvm_fw_baid_op_sta(struct iwl_mvm *mvm, -				  struct iwl_mvm_sta *mvm_sta, +				  struct ieee80211_sta *sta,  				  bool start, int tid, u16 ssn,  				  u16 buf_size)  { +	struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);  	struct iwl_mvm_add_sta_cmd cmd = {  		.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color), -		.sta_id = mvm_sta->sta_id, +		.sta_id = mvm_sta->deflink.sta_id,  		.add_modify = STA_MODE_MODIFY,  	};  	u32 status; @@ -2652,7 +2807,7 @@ static int iwl_mvm_fw_baid_op_sta(struct iwl_mvm *mvm,  }  static int iwl_mvm_fw_baid_op_cmd(struct iwl_mvm *mvm, -				  struct iwl_mvm_sta *mvm_sta, +				  struct ieee80211_sta *sta,  				  bool start, int tid, u16 ssn,  				  u16 buf_size, int baid)  { @@ -2666,7 +2821,8 @@ static int iwl_mvm_fw_baid_op_cmd(struct iwl_mvm *mvm,  	BUILD_BUG_ON(sizeof(struct iwl_rx_baid_cfg_resp) != sizeof(baid));  	if (start) { -		cmd.alloc.sta_id_mask = cpu_to_le32(BIT(mvm_sta->sta_id)); +		cmd.alloc.sta_id_mask = +			cpu_to_le32(iwl_mvm_sta_fw_id_mask(mvm, sta, -1));  		cmd.alloc.tid = tid;  		cmd.alloc.ssn = cpu_to_le16(ssn);  		cmd.alloc.win_size = cpu_to_le16(buf_size); @@ -2675,7 +2831,8 @@ static int iwl_mvm_fw_baid_op_cmd(struct iwl_mvm *mvm,  		cmd.remove_v1.baid = cpu_to_le32(baid);  		BUILD_BUG_ON(sizeof(cmd.remove_v1) > sizeof(cmd.remove));  	} else { -		cmd.remove.sta_id_mask = cpu_to_le32(BIT(mvm_sta->sta_id)); +		cmd.remove.sta_id_mask = +			cpu_to_le32(iwl_mvm_sta_fw_id_mask(mvm, sta, -1));  		cmd.remove.tid = cpu_to_le32(tid);  	} @@ -2698,16 +2855,16 @@ static int iwl_mvm_fw_baid_op_cmd(struct iwl_mvm *mvm,  	return baid;  } -static int iwl_mvm_fw_baid_op(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvm_sta, +static int iwl_mvm_fw_baid_op(struct iwl_mvm *mvm, struct ieee80211_sta *sta,  			      bool start, int tid, u16 ssn, u16 buf_size,  			      int baid)  {  	if (fw_has_capa(&mvm->fw->ucode_capa,  			IWL_UCODE_TLV_CAPA_BAID_ML_SUPPORT)) -		return iwl_mvm_fw_baid_op_cmd(mvm, mvm_sta, start, +		return iwl_mvm_fw_baid_op_cmd(mvm, sta, start,  					      tid, ssn, buf_size, baid); -	return iwl_mvm_fw_baid_op_sta(mvm, mvm_sta, start, +	return iwl_mvm_fw_baid_op_sta(mvm, sta, start,  				      tid, ssn, buf_size);  } @@ -2777,7 +2934,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,  	/* Don't send command to remove (start=0) BAID during restart */  	if (start || !test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) -		baid = iwl_mvm_fw_baid_op(mvm, mvm_sta, start, tid, ssn, buf_size, +		baid = iwl_mvm_fw_baid_op(mvm, sta, start, tid, ssn, buf_size,  					  baid);  	if (baid < 0) { @@ -2799,7 +2956,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,  			    iwl_mvm_rx_agg_session_expired, 0);  		baid_data->mvm = mvm;  		baid_data->tid = tid; -		baid_data->sta_id = mvm_sta->sta_id; +		baid_data->sta_mask = iwl_mvm_sta_fw_id_mask(mvm, sta, -1);  		mvm_sta->tid_to_baid[tid] = baid;  		if (timeout) @@ -2814,7 +2971,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,  		 * RX is being processed in parallel  		 */  		IWL_DEBUG_HT(mvm, "Sta %d(%d) is assigned to BAID %d\n", -			     mvm_sta->sta_id, tid, baid); +			     mvm_sta->deflink.sta_id, tid, baid);  		WARN_ON(rcu_access_pointer(mvm->baid_map[baid]));  		rcu_assign_pointer(mvm->baid_map[baid], baid_data);  	} else  { @@ -2876,7 +3033,7 @@ int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,  	}  	cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color); -	cmd.sta_id = mvm_sta->sta_id; +	cmd.sta_id = mvm_sta->deflink.sta_id;  	cmd.add_modify = STA_MODE_MODIFY;  	if (!iwl_mvm_has_new_tx_api(mvm))  		cmd.modify_mask = STA_MODIFY_QUEUES; @@ -2968,7 +3125,7 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,  	 */  	txq_id = mvmsta->tid_data[tid].txq_id;  	if (txq_id == IWL_MVM_INVALID_QUEUE) { -		ret = iwl_mvm_find_free_queue(mvm, mvmsta->sta_id, +		ret = iwl_mvm_find_free_queue(mvm, mvmsta->deflink.sta_id,  					      IWL_MVM_DQA_MIN_DATA_QUEUE,  					      IWL_MVM_DQA_MAX_DATA_QUEUE);  		if (ret < 0) { @@ -3006,7 +3163,8 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,  	IWL_DEBUG_TX_QUEUES(mvm,  			    "Start AGG: sta %d tid %d queue %d - ssn = %d, next_recl = %d\n", -			    mvmsta->sta_id, tid, txq_id, tid_data->ssn, +			    mvmsta->deflink.sta_id, tid, txq_id, +			    tid_data->ssn,  			    tid_data->next_reclaimed);  	/* @@ -3045,7 +3203,7 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,  	u16 ssn;  	struct iwl_trans_txq_scd_cfg cfg = { -		.sta_id = mvmsta->sta_id, +		.sta_id = mvmsta->deflink.sta_id,  		.tid = tid,  		.frame_limit = buf_size,  		.aggregate = true, @@ -3117,7 +3275,7 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,  		}  		ret = iwl_mvm_reconfig_scd(mvm, queue, cfg.fifo, -					   mvmsta->sta_id, tid, +					   mvmsta->deflink.sta_id, tid,  					   buf_size, ssn);  		if (ret) {  			IWL_ERR(mvm, @@ -3148,14 +3306,16 @@ out:  	 * for each station. Therefore, use the minimum of all the  	 * aggregation sessions and our default value.  	 */ -	mvmsta->max_agg_bufsize = -		min(mvmsta->max_agg_bufsize, buf_size); -	mvmsta->lq_sta.rs_drv.lq.agg_frame_cnt_limit = mvmsta->max_agg_bufsize; +	mvmsta->deflink.lq_sta.rs_drv.pers.max_agg_bufsize = +		min(mvmsta->deflink.lq_sta.rs_drv.pers.max_agg_bufsize, +		    buf_size); +	mvmsta->deflink.lq_sta.rs_drv.lq.agg_frame_cnt_limit = +		mvmsta->deflink.lq_sta.rs_drv.pers.max_agg_bufsize;  	IWL_DEBUG_HT(mvm, "Tx aggregation enabled on ra = %pM tid = %d\n",  		     sta->addr, tid); -	return iwl_mvm_send_lq_cmd(mvm, &mvmsta->lq_sta.rs_drv.lq); +	return iwl_mvm_send_lq_cmd(mvm, &mvmsta->deflink.lq_sta.rs_drv.lq);  }  static void iwl_mvm_unreserve_agg_queue(struct iwl_mvm *mvm, @@ -3204,7 +3364,8 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,  	txq_id = tid_data->txq_id;  	IWL_DEBUG_TX_QUEUES(mvm, "Stop AGG: sta %d tid %d q %d state %d\n", -			    mvmsta->sta_id, tid, txq_id, tid_data->state); +			    mvmsta->deflink.sta_id, tid, txq_id, +			    tid_data->state);  	mvmsta->agg_tids &= ~BIT(tid); @@ -3243,7 +3404,7 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,  	default:  		IWL_ERR(mvm,  			"Stopping AGG while state not ON or starting for %d on %d (%d)\n", -			mvmsta->sta_id, tid, tid_data->state); +			mvmsta->deflink.sta_id, tid, tid_data->state);  		IWL_ERR(mvm,  			"\ttid_data->txq_id = %d\n", tid_data->txq_id);  		err = -EINVAL; @@ -3269,7 +3430,8 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,  	spin_lock_bh(&mvmsta->lock);  	txq_id = tid_data->txq_id;  	IWL_DEBUG_TX_QUEUES(mvm, "Flush AGG: sta %d tid %d q %d state %d\n", -			    mvmsta->sta_id, tid, txq_id, tid_data->state); +			    mvmsta->deflink.sta_id, tid, txq_id, +			    tid_data->state);  	old_state = tid_data->state;  	tid_data->state = IWL_AGG_OFF;  	mvmsta->agg_tids &= ~BIT(tid); @@ -3281,7 +3443,7 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,  		iwl_mvm_drain_sta(mvm, mvmsta, true);  		if (iwl_mvm_has_new_tx_api(mvm)) { -			if (iwl_mvm_flush_sta_tids(mvm, mvmsta->sta_id, +			if (iwl_mvm_flush_sta_tids(mvm, mvmsta->deflink.sta_id,  						   BIT(tid)))  				IWL_ERR(mvm, "Couldn't flush the AGG queue\n");  			iwl_trans_wait_txq_empty(mvm->trans, txq_id); @@ -3341,8 +3503,8 @@ static struct iwl_mvm_sta *iwl_mvm_get_key_sta(struct iwl_mvm *mvm,  	 * station ID, then use AP's station ID.  	 */  	if (vif->type == NL80211_IFTYPE_STATION && -	    mvmvif->ap_sta_id != IWL_MVM_INVALID_STA) { -		u8 sta_id = mvmvif->ap_sta_id; +	    mvmvif->deflink.ap_sta_id != IWL_MVM_INVALID_STA) { +		u8 sta_id = mvmvif->deflink.ap_sta_id;  		sta = rcu_dereference_check(mvm->fw_id_to_mac_id[sta_id],  					    lockdep_is_held(&mvm->mutex)); @@ -3619,8 +3781,8 @@ static inline u8 *iwl_mvm_get_mac_addr(struct iwl_mvm *mvm,  		return sta->addr;  	if (vif->type == NL80211_IFTYPE_STATION && -	    mvmvif->ap_sta_id != IWL_MVM_INVALID_STA) { -		u8 sta_id = mvmvif->ap_sta_id; +	    mvmvif->deflink.ap_sta_id != IWL_MVM_INVALID_STA) { +		u8 sta_id = mvmvif->deflink.ap_sta_id;  		sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],  						lockdep_is_held(&mvm->mutex));  		return sta->addr; @@ -3646,13 +3808,13 @@ static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm,  	if (sta) {  		struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); -		sta_id = mvm_sta->sta_id; +		sta_id = mvm_sta->deflink.sta_id;  		mfp = sta->mfp;  	} else if (vif->type == NL80211_IFTYPE_AP &&  		   !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {  		struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); -		sta_id = mvmvif->mcast_sta.sta_id; +		sta_id = mvmvif->deflink.mcast_sta.sta_id;  	} else {  		IWL_ERR(mvm, "Failed to find station id\n");  		return -EINVAL; @@ -3695,7 +3857,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,  			IWL_ERR(mvm, "Failed to find station\n");  			return -EINVAL;  		} -		sta_id = mvm_sta->sta_id; +		sta_id = mvm_sta->deflink.sta_id;  		/*  		 * It is possible that the 'sta' parameter is NULL, and thus @@ -3717,7 +3879,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,  	} else {  		struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); -		sta_id = mvmvif->mcast_sta.sta_id; +		sta_id = mvmvif->deflink.mcast_sta.sta_id;  	}  	if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC || @@ -3790,9 +3952,9 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,  	/* Get the station from the mvm local station table */  	mvm_sta = iwl_mvm_get_key_sta(mvm, vif, sta);  	if (mvm_sta) -		sta_id = mvm_sta->sta_id; +		sta_id = mvm_sta->deflink.sta_id;  	else if (!sta && vif->type == NL80211_IFTYPE_AP && mcast) -		sta_id = iwl_mvm_vif_from_mac80211(vif)->mcast_sta.sta_id; +		sta_id = iwl_mvm_vif_from_mac80211(vif)->deflink.mcast_sta.sta_id;  	IWL_DEBUG_WEP(mvm, "mvm remove dynamic key: idx=%d sta=%d\n", @@ -3848,7 +4010,7 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,  	mvm_sta = iwl_mvm_get_key_sta(mvm, vif, sta);  	if (WARN_ON_ONCE(!mvm_sta))  		goto unlock; -	iwl_mvm_send_sta_key(mvm, mvm_sta->sta_id, keyconf, mcast, +	iwl_mvm_send_sta_key(mvm, mvm_sta->deflink.sta_id, keyconf, mcast,  			     iv32, phase1key, CMD_ASYNC, keyconf->hw_key_idx,  			     mfp); @@ -3862,7 +4024,7 @@ void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm,  	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);  	struct iwl_mvm_add_sta_cmd cmd = {  		.add_modify = STA_MODE_MODIFY, -		.sta_id = mvmsta->sta_id, +		.sta_id = mvmsta->deflink.sta_id,  		.station_flags_msk = cpu_to_le32(STA_FLG_PS),  		.mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color),  	}; @@ -3883,7 +4045,7 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm,  	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);  	struct iwl_mvm_add_sta_cmd cmd = {  		.add_modify = STA_MODE_MODIFY, -		.sta_id = mvmsta->sta_id, +		.sta_id = mvmsta->deflink.sta_id,  		.modify_mask = STA_MODIFY_SLEEPING_STA_TX_COUNT,  		.sleep_tx_count = cpu_to_le16(cnt),  		.mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color), @@ -3976,17 +4138,23 @@ void iwl_mvm_rx_eosp_notif(struct iwl_mvm *mvm,  }  void iwl_mvm_sta_modify_disable_tx(struct iwl_mvm *mvm, -				   struct iwl_mvm_sta *mvmsta, bool disable) +				   struct iwl_mvm_sta *mvmsta, +				   bool disable)  {  	struct iwl_mvm_add_sta_cmd cmd = {  		.add_modify = STA_MODE_MODIFY, -		.sta_id = mvmsta->sta_id, +		.sta_id = mvmsta->deflink.sta_id,  		.station_flags = disable ? cpu_to_le32(STA_FLG_DISABLE_TX) : 0,  		.station_flags_msk = cpu_to_le32(STA_FLG_DISABLE_TX),  		.mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color),  	};  	int ret; +	if (mvm->mld_api_is_used) { +		iwl_mvm_mld_sta_modify_disable_tx(mvm, mvmsta, disable); +		return; +	} +  	ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC,  				   iwl_mvm_add_sta_cmd_size(mvm), &cmd);  	if (ret) @@ -3999,6 +4167,11 @@ void iwl_mvm_sta_modify_disable_tx_ap(struct iwl_mvm *mvm,  {  	struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); +	if (mvm->mld_api_is_used) { +		iwl_mvm_mld_sta_modify_disable_tx_ap(mvm, sta, disable); +		return; +	} +  	spin_lock_bh(&mvm_sta->lock);  	if (mvm_sta->disable_tx == disable) { @@ -4049,6 +4222,11 @@ void iwl_mvm_modify_all_sta_disable_tx(struct iwl_mvm *mvm,  	struct iwl_mvm_sta *mvm_sta;  	int i; +	if (mvm->mld_api_is_used) { +		iwl_mvm_mld_modify_all_sta_disable_tx(mvm, mvmvif, disable); +		return; +	} +  	rcu_read_lock();  	/* Block/unblock all the stations of the given mvmvif */ @@ -4071,17 +4249,19 @@ void iwl_mvm_modify_all_sta_disable_tx(struct iwl_mvm *mvm,  		return;  	/* Need to block/unblock also multicast station */ -	if (mvmvif->mcast_sta.sta_id != IWL_MVM_INVALID_STA) +	if (mvmvif->deflink.mcast_sta.sta_id != IWL_MVM_INVALID_STA)  		iwl_mvm_int_sta_modify_disable_tx(mvm, mvmvif, -						  &mvmvif->mcast_sta, disable); +						  &mvmvif->deflink.mcast_sta, +						  disable);  	/*  	 * Only unblock the broadcast station (FW blocks it for immediate  	 * quiet, not the driver)  	 */ -	if (!disable && mvmvif->bcast_sta.sta_id != IWL_MVM_INVALID_STA) +	if (!disable && mvmvif->deflink.bcast_sta.sta_id != IWL_MVM_INVALID_STA)  		iwl_mvm_int_sta_modify_disable_tx(mvm, mvmvif, -						  &mvmvif->bcast_sta, disable); +						  &mvmvif->deflink.bcast_sta, +						  disable);  }  void iwl_mvm_csa_client_absent(struct iwl_mvm *mvm, struct ieee80211_vif *vif) @@ -4091,7 +4271,7 @@ void iwl_mvm_csa_client_absent(struct iwl_mvm *mvm, struct ieee80211_vif *vif)  	rcu_read_lock(); -	mvmsta = iwl_mvm_sta_from_staid_rcu(mvm, mvmvif->ap_sta_id); +	mvmsta = iwl_mvm_sta_from_staid_rcu(mvm, mvmvif->deflink.ap_sta_id);  	if (mvmsta)  		iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, true);  |