wifi: iwlwifi: mvm: Introduce internal MLO passive scan
authorIlan Peer <ilan.peer@intel.com>
Tue, 19 Mar 2024 08:10:13 +0000 (10:10 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 25 Mar 2024 14:39:09 +0000 (15:39 +0100)
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: Ilan Peer <ilan.peer@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Reviewed-by: Ayala Beker <ayala.beker@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://msgid.link/20240319100755.5ce3e756cf8f.I4a41065f6b3a6ec6c6e44e83bc97c277ff7c599e@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
drivers/net/wireless/intel/iwlwifi/mvm/scan.c

index 9856db384de049e62a64bdfdf9e72e688723a2a9..fbadc8479f2136b57086891376279272f1bc7141 100644 (file)
@@ -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);
 
index d1392c4077c134401c294c94700b69d441e3f11d..4c441d2bbce3da6ccceb64876fcae6d66b60aa5a 100644 (file)
@@ -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);
index a6f42d55bd9834e1d9b686ba66d6966b77726d00..ea05957fbcec88ff64a8f417c57243f93567cb54 100644 (file)
@@ -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;
-       mvm->scan_vif = iwl_mvm_vif_from_mac80211(vif);
+
+       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 @@ out:
 
        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;
+}