]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: iwlwifi: mld: allow 2 ROCs on the same vif
authorMiri Korenblit <miriam.rachel.korenblit@intel.com>
Sun, 11 May 2025 16:53:21 +0000 (19:53 +0300)
committerMiri Korenblit <miriam.rachel.korenblit@intel.com>
Thu, 15 May 2025 06:53:37 +0000 (09:53 +0300)
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: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20250511195137.1f8c55198578.I17cb191596ed4e97a4854108f8ca5ca197662a62@changeid
drivers/net/wireless/intel/iwlwifi/mld/mld.h
drivers/net/wireless/intel/iwlwifi/mld/roc.c

index 74fcaad85a32743ce175bebdf5b345c75f16a705..1a2c44f44eff324468ef1037c6b2b926b1c4e04a 100644 (file)
  *     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];
index 944d70901de5554e77ef29a69566ff7176ae7da7..e85f45bce79a7464ad03ad3ced57a3243029f4a2 100644 (file)
@@ -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;