Commit 69aef848 authored by Miri Korenblit's avatar Miri Korenblit Committed by Johannes Berg
Browse files

wifi: iwlwifi: mvm: refactor iwl_mvm_add_sta(), iwl_mvm_rm_sta()



As we have a new MLD STA cmd, there will be a different function to
add/remove a station in MLD mode. But both functions will share a
common part. Put this part in a separate function which will be used
later in adding/removing a sta in MLD mode.

Signed-off-by: default avatarMiri Korenblit <miriam.rachel.korenblit@intel.com>
Signed-off-by: default avatarGregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230320122330.d01e0c9ccdc3.I5e9e27c3b363b36209a0ff960d2e59708e7ff0bf@changeid


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 6a8dee13
Loading
Loading
Loading
Loading
+106 −76
Original line number Diff line number Diff line
@@ -1648,52 +1648,17 @@ 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 */
static 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);

	/* 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;
	}

	mvm_sta->sta_id = sta_id;
	mvm_sta->mac_id_n_color = FW_CMD_ID_AND_COLOR(mvmvif->id,
						      mvmvif->color);
@@ -1703,7 +1668,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
	else
		mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF;
	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;

	mvm_sta->tid_disable_agg = 0xffff; /* No aggs at first */

@@ -1724,8 +1689,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
		atomic_set(&mvmtxq->tx_request, 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,
@@ -1751,7 +1715,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;
	}

	/*
@@ -1765,6 +1729,56 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,

	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->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)
@@ -1912,43 +1926,16 @@ 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 */
static bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
			    struct ieee80211_sta *sta, int *ret)
{
	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
	struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
	u8 sta_id = mvm_sta->sta_id;
	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 there is a TXQ still marked as reserved - free it */
	if (mvm_sta->reserved_queue != IEEE80211_INVAL_HW_QUEUE) {
		u8 reserved_txq = mvm_sta->reserved_queue;
@@ -1963,8 +1950,10 @@ 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;
	}
@@ -1973,7 +1962,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
	    mvmvif->ap_sta_id == sta_id) {
		/* 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);
@@ -2000,6 +1989,47 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,

	iwl_mvm_time_sync_sta_rm(mvm, sta);

	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, &ret))
		return ret;

	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);