diff mbox series

[iwlwifi-next,13/15] wifi: iwlwifi: mld: add support for ROC on BSS

Message ID 20250509104454.2582160-14-miriam.rachel.korenblit@intel.com
State New
Headers show
Series [iwlwifi-next,01/15] wifi: iwlwifi: cfg: add ucode API min/max to MAC config | expand

Commit Message

Miri Korenblit May 9, 2025, 10:44 a.m. UTC
From: Pagadala Yesu Anjaneyulu <pagadala.yesu.anjaneyulu@intel.com>

add support for remain on channel on BSS vif for iwlmld.

Signed-off-by: Pagadala Yesu Anjaneyulu <pagadala.yesu.anjaneyulu@intel.com>
Message-Id: <20250509134302.0cac670cfbfe.I4318f40866181927da17e6cbfada59107cd3c458@changeid>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
 .../net/wireless/intel/iwlwifi/mld/iface.h    |  4 +-
 drivers/net/wireless/intel/iwlwifi/mld/mld.h  |  2 +
 drivers/net/wireless/intel/iwlwifi/mld/roc.c  | 53 ++++++++++++-------
 drivers/net/wireless/intel/iwlwifi/mld/sta.c  |  4 +-
 drivers/net/wireless/intel/iwlwifi/mld/tx.c   | 22 +++++++-
 5 files changed, 60 insertions(+), 25 deletions(-)
diff mbox series

Patch

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/iface.h b/drivers/net/wireless/intel/iwlwifi/mld/iface.h
index 15b437110351..49e2ce65557d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/iface.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/iface.h
@@ -141,8 +141,8 @@  struct iwl_mld_emlsr {
  * @use_ps_poll: use ps_poll frames
  * @disable_bf: disable beacon filter
  * @dbgfs_slink: debugfs symlink for this interface
- * @roc_activity: the id of the roc_activity running. Relevant for p2p device
- *	only. Set to %ROC_NUM_ACTIVITIES when not in use.
+ * @roc_activity: the id of the roc_activity running. Relevant for STA and
+ *	p2p device only. Set to %ROC_NUM_ACTIVITIES when not in use.
  * @aux_sta: station used for remain on channel. Used in P2P device.
  */
 struct iwl_mld_vif {
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mld.h b/drivers/net/wireless/intel/iwlwifi/mld/mld.h
index 1a2c44f44eff..74fcaad85a32 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mld.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mld.h
@@ -127,6 +127,7 @@ 
  *	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
@@ -212,6 +213,7 @@  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];
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/roc.c b/drivers/net/wireless/intel/iwlwifi/mld/roc.c
index cfd010c1ca80..944d70901de5 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/roc.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/roc.c
@@ -49,29 +49,36 @@  int iwl_mld_start_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 
 	lockdep_assert_wiphy(mld->wiphy);
 
-	/* TODO: task=Hotspot 2.0 */
-	if (vif->type != NL80211_IFTYPE_P2P_DEVICE) {
+	if (vif->type != NL80211_IFTYPE_P2P_DEVICE &&
+	    vif->type != NL80211_IFTYPE_STATION) {
 		IWL_ERR(mld, "NOT SUPPORTED: ROC on vif->type %d\n",
 			vif->type);
 
 		return -EOPNOTSUPP;
 	}
 
-	switch (type) {
-	case IEEE80211_ROC_TYPE_NORMAL:
-		activity = ROC_ACTIVITY_P2P_DISC;
-		break;
-	case IEEE80211_ROC_TYPE_MGMT_TX:
-		activity = ROC_ACTIVITY_P2P_NEG;
-		break;
-	default:
-		WARN_ONCE(1, "Got an invalid P2P ROC type\n");
-		return -EINVAL;
+	if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
+		switch (type) {
+		case IEEE80211_ROC_TYPE_NORMAL:
+			activity = ROC_ACTIVITY_P2P_DISC;
+			break;
+		case IEEE80211_ROC_TYPE_MGMT_TX:
+			activity = ROC_ACTIVITY_P2P_NEG;
+			break;
+		default:
+			WARN_ONCE(1, "Got an invalid P2P ROC type\n");
+			return -EINVAL;
+		}
+	} else {
+		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)
+		return -EBUSY;
+
 	ieee80211_iterate_active_interfaces_mtx(mld->hw,
 						IEEE80211_IFACE_ITER_NORMAL,
 						iwl_mld_vif_iter_emlsr_block_roc,
@@ -88,9 +95,6 @@  int iwl_mld_start_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	cmd.channel_info.channel = cpu_to_le32(channel->hw_value);
 	cmd.channel_info.band = iwl_mld_nl80211_band_to_fw(channel->band);
 	cmd.channel_info.width = IWL_PHY_CHANNEL_MODE20;
-	/* TODO: task=Hotspot 2.0, revisit those parameters when we add an ROC
-	 * on the BSS vif
-	 */
 	cmd.max_delay = cpu_to_le32(AUX_ROC_MAX_DELAY);
 	cmd.duration = cpu_to_le32(MSEC_TO_TU(duration));
 
@@ -102,8 +106,12 @@  int iwl_mld_start_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		IWL_ERR(mld, "Couldn't send the ROC_CMD\n");
 		return ret;
 	}
+
 	mld_vif->roc_activity = activity;
 
+	if (vif->type == NL80211_IFTYPE_STATION)
+		mld->bss_roc_vif = vif;
+
 	return 0;
 }
 
@@ -122,6 +130,9 @@  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,
@@ -153,8 +164,8 @@  int iwl_mld_cancel_roc(struct ieee80211_hw *hw,
 
 	lockdep_assert_wiphy(mld->wiphy);
 
-	/* TODO: task=Hotspot 2.0 */
-	if (WARN_ON(vif->type != NL80211_IFTYPE_P2P_DEVICE))
+	if (WARN_ON(vif->type != NL80211_IFTYPE_P2P_DEVICE &&
+		    vif->type != NL80211_IFTYPE_STATION))
 		return -EOPNOTSUPP;
 
 	/* No roc activity running it's probably already done */
@@ -189,9 +200,13 @@  void iwl_mld_handle_roc_notif(struct iwl_mld *mld,
 {
 	const struct iwl_roc_notif *notif = (void *)pkt->data;
 	u32 activity = le32_to_cpu(notif->activity);
-	/* TODO: task=Hotspot 2.0 - roc can run on BSS */
-	struct ieee80211_vif *vif = mld->p2p_device_vif;
 	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;
 
 	if (WARN_ON(!vif))
 		return;
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/sta.c b/drivers/net/wireless/intel/iwlwifi/mld/sta.c
index bc5313f44fde..8fb51209b4a6 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/sta.c
@@ -1164,8 +1164,8 @@  void iwl_mld_remove_aux_sta(struct iwl_mld *mld,
 {
 	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
 
-	/* TODO: Hotspot 2.0 */
-	if (WARN_ON(vif->type != NL80211_IFTYPE_P2P_DEVICE))
+	if (WARN_ON(vif->type != NL80211_IFTYPE_P2P_DEVICE &&
+		    vif->type != NL80211_IFTYPE_STATION))
 		return;
 
 	iwl_mld_remove_internal_sta(mld, &mld_vif->aux_sta, false,
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tx.c b/drivers/net/wireless/intel/iwlwifi/mld/tx.c
index 96ea6320c084..4d4d3308a90d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/tx.c
@@ -638,8 +638,11 @@  iwl_mld_get_tx_queue_id(struct iwl_mld *mld, struct ieee80211_txq *txq,
 	case NL80211_IFTYPE_P2P_DEVICE:
 		mld_vif = iwl_mld_vif_from_mac80211(info->control.vif);
 
-		if (mld_vif->roc_activity == ROC_NUM_ACTIVITIES) {
-			IWL_DEBUG_DROP(mld, "Drop tx outside ROC\n");
+		if (mld_vif->roc_activity != ROC_ACTIVITY_P2P_DISC &&
+		    mld_vif->roc_activity != ROC_ACTIVITY_P2P_NEG) {
+			IWL_DEBUG_DROP(mld,
+				       "Drop tx outside ROC with activity %d\n",
+				       mld_vif->roc_activity);
 			return IWL_MLD_INVALID_DROP_TX;
 		}
 
@@ -649,6 +652,21 @@  iwl_mld_get_tx_queue_id(struct iwl_mld *mld, struct ieee80211_txq *txq,
 	case NL80211_IFTYPE_MONITOR:
 		mld_vif = iwl_mld_vif_from_mac80211(info->control.vif);
 		return mld_vif->deflink.mon_sta.queue_id;
+	case NL80211_IFTYPE_STATION:
+		mld_vif = iwl_mld_vif_from_mac80211(info->control.vif);
+
+		if (!(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)) {
+			IWL_DEBUG_DROP(mld, "Drop tx not off-channel\n");
+			return IWL_MLD_INVALID_DROP_TX;
+		}
+
+		if (mld_vif->roc_activity != ROC_ACTIVITY_HOTSPOT) {
+			IWL_DEBUG_DROP(mld, "Drop tx outside ROC\n");
+			return IWL_MLD_INVALID_DROP_TX;
+		}
+
+		WARN_ON(!ieee80211_is_mgmt(fc));
+		return mld_vif->aux_sta.queue_id;
 	default:
 		WARN_ONCE(1, "Unsupported vif type\n");
 		break;