Commit 379f7682 authored by Miri Korenblit's avatar Miri Korenblit
Browse files

wifi: iwlwifi: mld: allow 2 ROCs on the same vif



In the current code, if an ROC is started on a vif that already has an
active ROC we reject it and warn.

But really there is no such limitation. The actual limitation is to not
have 2 ROCs of the same type simultaneously.

Add a helper function to find a vif that has an active ROC of a given
type, and only if one exist - reject the ROC.

This allows also to remove bss_roc_vif.

Reviewed-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarMiri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20250511195137.1f8c55198578.I17cb191596ed4e97a4854108f8ca5ca197662a62@changeid
parent 11e9f426
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -127,7 +127,6 @@
 *	cleanup using iwl_mld_free_internal_sta
 * @netdetect: indicates the FW is in suspend mode with netdetect configured
 * @p2p_device_vif: points to the p2p device vif if exists
 * @bss_roc_vif: points to the BSS vif that has an active ROC.
 * @dev: pointer to device struct. For printing purposes
 * @trans: pointer to the transport layer
 * @cfg: pointer to the device configuration
@@ -213,7 +212,6 @@ struct iwl_mld {
		bool netdetect;
#endif /* CONFIG_PM_SLEEP */
		struct ieee80211_vif *p2p_device_vif;
		struct ieee80211_vif *bss_roc_vif;
		struct iwl_bt_coex_profile_notif last_bt_notif;
	);
	struct ieee80211_link_sta __rcu *fw_id_to_link_sta[IWL_STATION_COUNT_MAX];
+44 −15
Original line number Diff line number Diff line
@@ -31,6 +31,47 @@ iwl_mld_vif_iter_emlsr_block_roc(void *data, u8 *mac, struct ieee80211_vif *vif)
		*result = ret;
}

struct iwl_mld_roc_iter_data {
	enum iwl_roc_activity activity;
	struct ieee80211_vif *vif;
	bool found;
};

static void iwl_mld_find_roc_vif_iter(void *data, u8 *mac,
				      struct ieee80211_vif *vif)
{
	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
	struct iwl_mld_roc_iter_data *roc_data = data;

	if (mld_vif->roc_activity != roc_data->activity)
		return;

	/* The FW supports one ROC of each type simultaneously */
	if (WARN_ON(roc_data->found)) {
		roc_data->vif = NULL;
		return;
	}

	roc_data->found = true;
	roc_data->vif = vif;
}

static struct ieee80211_vif *
iwl_mld_find_roc_vif(struct iwl_mld *mld, enum iwl_roc_activity activity)
{
	struct iwl_mld_roc_iter_data roc_data = {
		.activity = activity,
		.found = false,
	};

	ieee80211_iterate_active_interfaces_mtx(mld->hw,
						IEEE80211_IFACE_ITER_NORMAL,
						iwl_mld_find_roc_vif_iter,
						&roc_data);

	return roc_data.vif;
}

int iwl_mld_start_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
		      struct ieee80211_channel *channel, int duration,
		      enum ieee80211_roc_type type)
@@ -73,10 +114,8 @@ int iwl_mld_start_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
		activity = ROC_ACTIVITY_HOTSPOT;
	}

	if (WARN_ON(mld_vif->roc_activity != ROC_NUM_ACTIVITIES))
		return -EBUSY;

	if (vif->type == NL80211_IFTYPE_STATION && mld->bss_roc_vif)
	/* The FW supports one ROC of each type simultaneously */
	if (WARN_ON(iwl_mld_find_roc_vif(mld, activity)))
		return -EBUSY;

	ieee80211_iterate_active_interfaces_mtx(mld->hw,
@@ -109,9 +148,6 @@ int iwl_mld_start_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,

	mld_vif->roc_activity = activity;

	if (vif->type == NL80211_IFTYPE_STATION)
		mld->bss_roc_vif = vif;

	return 0;
}

@@ -130,9 +166,6 @@ static void iwl_mld_destroy_roc(struct iwl_mld *mld,
{
	mld_vif->roc_activity = ROC_NUM_ACTIVITIES;

	if (vif->type == NL80211_IFTYPE_STATION)
		mld->bss_roc_vif = NULL;

	ieee80211_iterate_active_interfaces_mtx(mld->hw,
						IEEE80211_IFACE_ITER_NORMAL,
						iwl_mld_vif_iter_emlsr_unblock_roc,
@@ -203,11 +236,7 @@ void iwl_mld_handle_roc_notif(struct iwl_mld *mld,
	struct iwl_mld_vif *mld_vif;
	struct ieee80211_vif *vif;

	if (activity == ROC_ACTIVITY_HOTSPOT)
		vif = mld->bss_roc_vif;
	else
		vif = mld->p2p_device_vif;

	vif = iwl_mld_find_roc_vif(mld, activity);
	if (WARN_ON(!vif))
		return;