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

wifi: iwlwifi: mvm: add start_ap() and join_ibss() callbacks for MLD mode



This is another patch in the series adding all the ops
for the new MLD ieee80211_ops.
The callbacks added here use the new MLD FW API

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.3eb485c359fc.I28be198ea9389083d5a01f68c92763722613ba9b@changeid


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent e8610339
Loading
Loading
Loading
Loading
+46 −30
Original line number Diff line number Diff line
@@ -2669,13 +2669,54 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
		iwl_mvm_apply_fw_smps_request(vif);
}

bool iwl_mvm_start_ap_ibss_common(struct ieee80211_hw *hw,
				  struct ieee80211_vif *vif,
				  int *ret)
{
	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
	int i;

	lockdep_assert_held(&mvm->mutex);

	mvmvif->ap_assoc_sta_count = 0;

	/* must be set before quota calculations */
	mvmvif->ap_ibss_active = true;

	/* send all the early keys to the device now */
	for (i = 0; i < ARRAY_SIZE(mvmvif->ap_early_keys); i++) {
		struct ieee80211_key_conf *key = mvmvif->ap_early_keys[i];

		if (!key)
			continue;

		mvmvif->ap_early_keys[i] = NULL;

		*ret = __iwl_mvm_mac_set_key(hw, SET_KEY, vif, NULL, key);
		if (*ret)
			return true;
	}

	if (vif->type == NL80211_IFTYPE_AP && !vif->p2p) {
		iwl_mvm_vif_set_low_latency(mvmvif, true,
					    LOW_LATENCY_VIF_TYPE);
		iwl_mvm_send_low_latency_cmd(mvm, true, mvmvif->id);
	}

	/* power updated needs to be done before quotas */
	iwl_mvm_power_update_mac(mvm);

	return false;
}

static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
				 struct ieee80211_vif *vif,
				 struct ieee80211_bss_conf *link_conf)
{
	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
	int ret, i;
	int ret;

	mutex_lock(&mvm->mutex);

@@ -2692,8 +2733,6 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
	if (vif->type == NL80211_IFTYPE_AP)
		iwl_mvm_mac_ctxt_recalc_tsf_id(mvm, vif);

	mvmvif->ap_assoc_sta_count = 0;

	/* Add the mac context */
	ret = iwl_mvm_mac_ctxt_add(mvm, vif);
	if (ret)
@@ -2739,35 +2778,12 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
		}
	}

	/* must be set before quota calculations */
	mvmvif->ap_ibss_active = true;

	/* send all the early keys to the device now */
	for (i = 0; i < ARRAY_SIZE(mvmvif->ap_early_keys); i++) {
		struct ieee80211_key_conf *key = mvmvif->ap_early_keys[i];

		if (!key)
			continue;

		mvmvif->ap_early_keys[i] = NULL;

		ret = __iwl_mvm_mac_set_key(hw, SET_KEY, vif, NULL, key);
		if (ret)
			goto out_quota_failed;
	}

	if (vif->type == NL80211_IFTYPE_AP && !vif->p2p) {
		iwl_mvm_vif_set_low_latency(mvmvif, true,
					    LOW_LATENCY_VIF_TYPE);
		iwl_mvm_send_low_latency_cmd(mvm, true, mvmvif->id);
	}

	/* power updated needs to be done before quotas */
	iwl_mvm_power_update_mac(mvm);
	if (iwl_mvm_start_ap_ibss_common(hw, vif, &ret))
		goto out_failed;

	ret = iwl_mvm_update_quotas(mvm, false, NULL);
	if (ret)
		goto out_quota_failed;
		goto out_failed;

	/* Need to update the P2P Device MAC (only GO, IBSS is single vif) */
	if (vif->p2p && mvm->p2p_device_vif)
@@ -2783,7 +2799,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,

	goto out_unlock;

out_quota_failed:
out_failed:
	iwl_mvm_power_update_mac(mvm);
	mvmvif->ap_ibss_active = false;
	iwl_mvm_send_rm_bcast_sta(mvm, vif);
+78 −0
Original line number Diff line number Diff line
@@ -245,9 +245,87 @@ static void iwl_mvm_mld_unassign_vif_chanctx(struct ieee80211_hw *hw,
	__iwl_mvm_mld_unassign_vif_chanctx(mvm, vif, ctx, false);
	mutex_unlock(&mvm->mutex);
}

static int iwl_mvm_mld_start_ap_ibss(struct ieee80211_hw *hw,
				     struct ieee80211_vif *vif)
{
	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
	int ret;

	mutex_lock(&mvm->mutex);

	/* Send the beacon template */
	ret = iwl_mvm_mac_ctxt_beacon_changed(mvm, vif);
	if (ret)
		goto out_unlock;

	/* No need to re-calculate the tsf_is, as it was offloaded */

	/* Add the mac context */
	ret = iwl_mvm_mld_mac_ctxt_add(mvm, vif);
	if (ret)
		goto out_unlock;

	/* Add link and activate it */
	ret = iwl_mvm_add_link(mvm, vif);
	if (ret)
		goto out_remove_mac;

	ret = iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ACTIVE,
				   true);
	if (ret)
		goto out_remove_link;

	ret = iwl_mvm_mld_add_mcast_sta(mvm, vif);
	if (ret)
		goto out_remove_link;

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

	iwl_mvm_ftm_restart_responder(mvm, vif);

	goto out_unlock;

out_failed:
	iwl_mvm_power_update_mac(mvm);
	mvmvif->ap_ibss_active = false;
	iwl_mvm_mld_rm_bcast_sta(mvm, vif);
out_rm_mcast:
	iwl_mvm_mld_rm_mcast_sta(mvm, vif);
out_remove_link:
	/* Link needs to be deactivated before removal */
	iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ACTIVE, false);
	iwl_mvm_remove_link(mvm, vif);
out_remove_mac:
	iwl_mvm_mld_mac_ctxt_remove(mvm, vif);
out_unlock:
	mutex_unlock(&mvm->mutex);
	return ret;
}

const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
	.add_interface = iwl_mvm_mld_mac_add_interface,
	.remove_interface = iwl_mvm_mld_mac_remove_interface,
	.assign_vif_chanctx = iwl_mvm_mld_assign_vif_chanctx,
	.unassign_vif_chanctx = iwl_mvm_mld_unassign_vif_chanctx,
	.join_ibss = iwl_mvm_mld_start_ap_ibss,
};
+45 −0
Original line number Diff line number Diff line
@@ -176,6 +176,38 @@ int iwl_mvm_mld_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
				       IWL_MAX_TID_COUNT, &wdg_timeout);
}

/* Allocate a new station entry for the broadcast station to the given vif,
 * and send it to the FW.
 * Note that each AP/GO mac should have its own multicast station.
 */
int iwl_mvm_mld_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;
	static const u8 _maddr[] = {0x03, 0x00, 0x00, 0x00, 0x00, 0x00};
	const u8 *maddr = _maddr;
	unsigned int timeout = iwl_mvm_get_wd_timeout(mvm, vif, false, false);

	lockdep_assert_held(&mvm->mutex);

	if (WARN_ON(vif->type != NL80211_IFTYPE_AP &&
		    vif->type != NL80211_IFTYPE_ADHOC))
		return -EOPNOTSUPP;

	/* In IBSS, ieee80211_check_queues() sets the cab_queue to be
	 * invalid, so make sure we use the queue we want.
	 * Note that this is done here as we want to avoid making DQA
	 * changes in mac80211 layer.
	 */
	if (vif->type == NL80211_IFTYPE_ADHOC)
		mvmvif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE;

	return iwl_mvm_mld_add_int_sta(mvm, msta, &mvmvif->cab_queue,
				       vif->type, STATION_TYPE_MCAST,
				       mvmvif->phy_ctxt->id, maddr, 0,
				       &timeout);
}

/* Allocate a new station entry for the sniffer station to the given vif,
 * and send it to the FW.
 */
@@ -272,6 +304,19 @@ int iwl_mvm_mld_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
				      IWL_MAX_TID_COUNT, queueptr);
}

/* Send the FW a request to remove the station from it's internal data
 * structures, and in addition remove it from the local data structure.
 */
int iwl_mvm_mld_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);

	lockdep_assert_held(&mvm->mutex);

	return iwl_mvm_mld_rm_int_sta(mvm, &mvmvif->mcast_sta, true, 0,
				      &mvmvif->cab_queue);
}

int iwl_mvm_mld_rm_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
	lockdep_assert_held(&mvm->mutex);
+4 −0
Original line number Diff line number Diff line
@@ -1766,6 +1766,10 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
			 u32 changes, bool active);
int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif);

/* AP and IBSS */
bool iwl_mvm_start_ap_ibss_common(struct ieee80211_hw *hw,
				  struct ieee80211_vif *vif, int *ret);

/* Quota management */
static inline size_t iwl_mvm_quota_cmd_size(struct iwl_mvm *mvm)
{
+2 −0
Original line number Diff line number Diff line
@@ -563,8 +563,10 @@ int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm,
/* STA */
int iwl_mvm_mld_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_mld_add_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_mld_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_mld_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_mld_rm_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_mld_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);

/* Queues */
void iwl_mvm_mld_modify_all_sta_disable_tx(struct iwl_mvm *mvm,