Commit 38b3998d authored by Ilan Peer's avatar Ilan Peer Committed by Johannes Berg
Browse files

wifi: iwlwifi: mvm: Introduce internal MLO passive scan



Add a new scan type that can be used for internal MLO purposes, i.e.,
in case updated BSS information is required. Currently only passive
scanning is supported.

Signed-off-by: default avatarIlan Peer <ilan.peer@intel.com>
Reviewed-by: default avatarJohannes Berg <johannes.berg@intel.com>
Reviewed-by: default avatarAyala Beker <ayala.beker@intel.com>
Signed-off-by: default avatarMiri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://msgid.link/20240319100755.5ce3e756cf8f.I4a41065f6b3a6ec6c6e44e83bc97c277ff7c599e@changeid


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent a17a58ad
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -1340,6 +1340,11 @@ void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
{
	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);

	/* Stop internal MLO scan, if running */
	mutex_lock(&mvm->mutex);
	iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_INT_MLO, false);
	mutex_unlock(&mvm->mutex);

	flush_work(&mvm->async_handlers_wk);
	flush_work(&mvm->add_stream_wk);

+8 −0
Original line number Diff line number Diff line
@@ -493,10 +493,12 @@ enum iwl_scan_status {
	IWL_MVM_SCAN_REGULAR		= BIT(0),
	IWL_MVM_SCAN_SCHED		= BIT(1),
	IWL_MVM_SCAN_NETDETECT		= BIT(2),
	IWL_MVM_SCAN_INT_MLO		= BIT(3),

	IWL_MVM_SCAN_STOPPING_REGULAR	= BIT(8),
	IWL_MVM_SCAN_STOPPING_SCHED	= BIT(9),
	IWL_MVM_SCAN_STOPPING_NETDETECT	= BIT(10),
	IWL_MVM_SCAN_STOPPING_INT_MLO	= BIT(11),

	IWL_MVM_SCAN_REGULAR_MASK	= IWL_MVM_SCAN_REGULAR |
					  IWL_MVM_SCAN_STOPPING_REGULAR,
@@ -504,6 +506,8 @@ enum iwl_scan_status {
					  IWL_MVM_SCAN_STOPPING_SCHED,
	IWL_MVM_SCAN_NETDETECT_MASK	= IWL_MVM_SCAN_NETDETECT |
					  IWL_MVM_SCAN_STOPPING_NETDETECT,
	IWL_MVM_SCAN_INT_MLO_MASK       = IWL_MVM_SCAN_INT_MLO |
					  IWL_MVM_SCAN_STOPPING_INT_MLO,

	IWL_MVM_SCAN_STOPPING_MASK	= 0xff << IWL_MVM_SCAN_STOPPING_SHIFT,
	IWL_MVM_SCAN_MASK		= 0xff,
@@ -2007,6 +2011,10 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
			   struct ieee80211_scan_ies *ies);
size_t iwl_mvm_scan_size(struct iwl_mvm *mvm);
int iwl_mvm_scan_stop(struct iwl_mvm *mvm, int type, bool notify);
int iwl_mvm_int_mlo_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
			       struct ieee80211_channel **channels,
			       size_t n_channels);

int iwl_mvm_max_scan_ie_len(struct iwl_mvm *mvm);
void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm);
void iwl_mvm_scan_timeout_wk(struct work_struct *work);
+75 −10
Original line number Diff line number Diff line
@@ -1377,11 +1377,14 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm,
		cmd->ooc_priority = cpu_to_le32(IWL_SCAN_PRIORITY_EXT_2);
}

static u32 iwl_mvm_scan_umac_ooc_priority(struct iwl_mvm_scan_params *params)
static u32 iwl_mvm_scan_umac_ooc_priority(int type)
{
	return iwl_mvm_is_regular_scan(params) ?
		IWL_SCAN_PRIORITY_EXT_6 :
		IWL_SCAN_PRIORITY_EXT_2;
	if (type == IWL_MVM_SCAN_REGULAR)
		return IWL_SCAN_PRIORITY_EXT_6;
	if (type == IWL_MVM_SCAN_INT_MLO)
		return IWL_SCAN_PRIORITY_EXT_4;

	return IWL_SCAN_PRIORITY_EXT_2;
}

static void
@@ -2452,7 +2455,7 @@ static int iwl_mvm_scan_umac_v12(struct iwl_mvm *mvm, struct ieee80211_vif *vif,

	mvm->scan_uid_status[uid] = type;

	cmd->ooc_priority = cpu_to_le32(iwl_mvm_scan_umac_ooc_priority(params));
	cmd->ooc_priority = cpu_to_le32(iwl_mvm_scan_umac_ooc_priority(type));
	cmd->uid = cpu_to_le32(uid);

	gen_flags = iwl_mvm_scan_umac_flags_v2(mvm, params, vif, type);
@@ -2489,7 +2492,7 @@ static int iwl_mvm_scan_umac_v14_and_above(struct iwl_mvm *mvm,

	mvm->scan_uid_status[uid] = type;

	cmd->ooc_priority = cpu_to_le32(iwl_mvm_scan_umac_ooc_priority(params));
	cmd->ooc_priority = cpu_to_le32(iwl_mvm_scan_umac_ooc_priority(type));
	cmd->uid = cpu_to_le32(uid);

	gen_flags = iwl_mvm_scan_umac_flags_v2(mvm, params, vif, type);
@@ -3006,14 +3009,16 @@ static int _iwl_mvm_single_scan_start(struct iwl_mvm *mvm,

	IWL_DEBUG_SCAN(mvm, "Scan request was sent successfully\n");
	mvm->scan_status |= type;

	if (type == IWL_MVM_SCAN_REGULAR) {
		mvm->scan_vif = iwl_mvm_vif_from_mac80211(vif);
		schedule_delayed_work(&mvm->scan_timeout_dwork,
				      msecs_to_jiffies(SCAN_TIMEOUT));
	}

	if (params.enable_6ghz_passive)
		mvm->last_6ghz_passive_scan_jiffies = jiffies;

	schedule_delayed_work(&mvm->scan_timeout_dwork,
			      msecs_to_jiffies(SCAN_TIMEOUT));

	return 0;
}

@@ -3189,6 +3194,8 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
	} else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) {
		ieee80211_sched_scan_stopped(mvm->hw);
		mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;
	} else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_INT_MLO) {
		IWL_DEBUG_SCAN(mvm, "Internal MLO scan completed\n");
	}

	mvm->scan_status &= ~mvm->scan_uid_status[uid];
@@ -3375,6 +3382,12 @@ void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm)
			mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;
			mvm->scan_uid_status[uid] = 0;
		}
		uid = iwl_mvm_scan_uid_by_status(mvm, IWL_MVM_SCAN_INT_MLO);
		if (uid >= 0) {
			IWL_DEBUG_SCAN(mvm, "Internal MLO scan aborted\n");
			mvm->scan_uid_status[uid] = 0;
		}

		uid = iwl_mvm_scan_uid_by_status(mvm,
						 IWL_MVM_SCAN_STOPPING_REGULAR);
		if (uid >= 0)
@@ -3385,6 +3398,11 @@ void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm)
		if (uid >= 0)
			mvm->scan_uid_status[uid] = 0;

		uid = iwl_mvm_scan_uid_by_status(mvm,
						 IWL_MVM_SCAN_STOPPING_INT_MLO);
		if (uid >= 0)
			mvm->scan_uid_status[uid] = 0;

		/* We shouldn't have any UIDs still set.  Loop over all the
		 * UIDs to make sure there's nothing left there and warn if
		 * any is found.
@@ -3456,3 +3474,50 @@ int iwl_mvm_scan_stop(struct iwl_mvm *mvm, int type, bool notify)

	return ret;
}

int iwl_mvm_int_mlo_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
			       struct ieee80211_channel **channels,
			       size_t n_channels)
{
	struct cfg80211_scan_request *req = NULL;
	struct ieee80211_scan_ies ies = {};
	size_t size, i;
	int ret;

	lockdep_assert_held(&mvm->mutex);

	IWL_DEBUG_SCAN(mvm, "Starting Internal MLO scan: n_channels=%zu\n",
		       n_channels);

	if (!vif->cfg.assoc || !ieee80211_vif_is_mld(vif))
		return -EINVAL;

	size = struct_size(req, channels, n_channels);
	req = kzalloc(size, GFP_KERNEL);
	if (!req)
		return -ENOMEM;

	/* set the requested channels */
	for (i = 0; i < n_channels; i++)
		req->channels[i] = channels[i];

	req->n_channels = n_channels;

	/* set the rates */
	for (i = 0; i < NUM_NL80211_BANDS; i++)
		if (mvm->hw->wiphy->bands[i])
			req->rates[i] =
				(1 << mvm->hw->wiphy->bands[i]->n_bitrates) - 1;

	req->wdev = ieee80211_vif_to_wdev(vif);
	req->wiphy = mvm->hw->wiphy;
	req->scan_start = jiffies;
	req->tsf_report_link_id = -1;

	ret = _iwl_mvm_single_scan_start(mvm, vif, req, &ies,
					 IWL_MVM_SCAN_INT_MLO);
	kfree(req);

	IWL_DEBUG_SCAN(mvm, "Internal MLO scan: ret=%d\n", ret);
	return ret;
}