]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: iwlwifi: mvm: Add support for prep_add_interface() callback
authorIlan Peer <ilan.peer@intel.com>
Tue, 8 Oct 2024 04:25:15 +0000 (07:25 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 23 Oct 2024 14:43:39 +0000 (16:43 +0200)
Implement the prep_add_interface() callback, so that in case
EMLSR is active and an AP or a P2P interface is do to be added,
EMLSR would be blocked.

Add a delayed work, so that in case that the interface was not
eventually added, EMLSR would be unblocked after 5 seconds.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20241008072037.3baf282d0a01.Ife0a929455cb13a95ab197ca765d8db777ff9d89@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/intel/iwlwifi/mvm/link.c
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h

index 2b06521680020c6f7d31fa5801073a9fabca2f19..19ecd215f1dcc886f0beb4f70c82473e4d400f75 100644 (file)
@@ -12,6 +12,7 @@
        HOW(BLOCKED_FW)                 \
        HOW(BLOCKED_NON_BSS)            \
        HOW(BLOCKED_ROC)                \
+       HOW(BLOCKED_TMP_NON_BSS)        \
        HOW(EXIT_MISSED_BEACON)         \
        HOW(EXIT_LOW_RSSI)              \
        HOW(EXIT_COEX)                  \
index 3721d6349cc5bd9387f89e2302d9ed9de3a131d3..99e017f365e05d330032e104bc95e1204b44dc17 100644 (file)
@@ -1731,6 +1731,21 @@ static void iwl_mvm_unblock_esr_tpt(struct wiphy *wiphy, struct wiphy_work *wk)
        iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_TPT);
 }
 
+static void iwl_mvm_unblock_esr_tmp_non_bss(struct wiphy *wiphy,
+                                           struct wiphy_work *wk)
+{
+       struct iwl_mvm_vif *mvmvif =
+               container_of(wk, struct iwl_mvm_vif,
+                            unblock_esr_tmp_non_bss_wk.work);
+       struct iwl_mvm *mvm = mvmvif->mvm;
+       struct ieee80211_vif *vif =
+               container_of((void *)mvmvif, struct ieee80211_vif, drv_priv);
+
+       mutex_lock(&mvm->mutex);
+       iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_TMP_NON_BSS);
+       mutex_unlock(&mvm->mutex);
+}
+
 void iwl_mvm_mac_init_mvmvif(struct iwl_mvm *mvm, struct iwl_mvm_vif *mvmvif)
 {
        lockdep_assert_held(&mvm->mutex);
@@ -1749,6 +1764,9 @@ void iwl_mvm_mac_init_mvmvif(struct iwl_mvm *mvm, struct iwl_mvm_vif *mvmvif)
 
        wiphy_work_init(&mvmvif->unblock_esr_tpt_wk,
                        iwl_mvm_unblock_esr_tpt);
+
+       wiphy_delayed_work_init(&mvmvif->unblock_esr_tmp_non_bss_wk,
+                               iwl_mvm_unblock_esr_tmp_non_bss);
 }
 
 static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
@@ -1899,6 +1917,8 @@ void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
                                  &mvmvif->mlo_int_scan_wk);
 
        wiphy_work_cancel(mvm->hw->wiphy, &mvmvif->unblock_esr_tpt_wk);
+       wiphy_delayed_work_cancel(mvm->hw->wiphy,
+                                 &mvmvif->unblock_esr_tmp_non_bss_wk);
 
        cancel_delayed_work_sync(&mvmvif->csa_work);
 }
@@ -4075,6 +4095,8 @@ iwl_mvm_sta_state_authorized_to_assoc(struct iwl_mvm *mvm,
                                          &mvmvif->mlo_int_scan_wk);
 
                wiphy_work_cancel(mvm->hw->wiphy, &mvmvif->unblock_esr_tpt_wk);
+               wiphy_delayed_work_cancel(mvm->hw->wiphy,
+                                         &mvmvif->unblock_esr_tmp_non_bss_wk);
 
                /* No need for the periodic statistics anymore */
                if (ieee80211_vif_is_mld(vif) && mvmvif->esr_active)
index 7de6c96646caa90cda0d7621f6ec4261946f6713..3947f6a0e0cfd84549d11c8ea7f6b2bccf753d70 100644 (file)
@@ -1376,6 +1376,36 @@ iwl_mvm_mld_mac_pre_channel_switch(struct ieee80211_hw *hw,
        return ret;
 }
 
+#define IWL_MVM_MLD_UNBLOCK_ESR_NON_BSS_TIMEOUT (5 * HZ)
+
+static void iwl_mvm_mld_prep_add_interface(struct ieee80211_hw *hw,
+                                          enum nl80211_iftype type)
+{
+       struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+       struct ieee80211_vif *bss_vif = iwl_mvm_get_bss_vif(mvm);
+       struct iwl_mvm_vif *mvmvif;
+       int ret;
+
+       IWL_DEBUG_MAC80211(mvm, "prep_add_interface: type=%u\n",
+                          type);
+
+       if (IS_ERR_OR_NULL(bss_vif) ||
+           !(type == NL80211_IFTYPE_AP ||
+             type == NL80211_IFTYPE_P2P_GO ||
+             type == NL80211_IFTYPE_P2P_CLIENT))
+               return;
+
+       mvmvif = iwl_mvm_vif_from_mac80211(bss_vif);
+       ret = iwl_mvm_block_esr_sync(mvm, bss_vif,
+                                    IWL_MVM_ESR_BLOCKED_TMP_NON_BSS);
+       if (ret)
+               return;
+
+       wiphy_delayed_work_queue(mvmvif->mvm->hw->wiphy,
+                                &mvmvif->unblock_esr_tmp_non_bss_wk,
+                                IWL_MVM_MLD_UNBLOCK_ESR_NON_BSS_TIMEOUT);
+}
+
 const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
        .tx = iwl_mvm_mac_tx,
        .wake_tx_queue = iwl_mvm_mac_wake_tx_queue,
@@ -1472,4 +1502,5 @@ const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
        .change_sta_links = iwl_mvm_mld_change_sta_links,
        .can_activate_links = iwl_mvm_mld_can_activate_links,
        .can_neg_ttlm = iwl_mvm_mld_can_neg_ttlm,
+       .prep_add_interface = iwl_mvm_mld_prep_add_interface,
 };
index 6246ffce7cf84b25cc9fdf027d3acaa6bcfec3c8..3f7b6465130a8234a9353d661a3946bb1b163085 100644 (file)
@@ -361,6 +361,9 @@ struct iwl_mvm_vif_link_info {
  * @IWL_MVM_ESR_BLOCKED_NON_BSS: An active non-BSS interface's link is
  *     preventing EMLSR
  * @IWL_MVM_ESR_BLOCKED_ROC: remain-on-channel is preventing EMLSR
+ * @IWL_MVM_ESR_BLOCKED_TMP_NON_BSS: An expected active non-BSS interface's link
+ *      is preventing EMLSR. This is a temporary blocking that is set when there
+ *      is an indication that a non-BSS interface is to be added.
  * @IWL_MVM_ESR_EXIT_MISSED_BEACON: exited EMLSR due to missed beacons
  * @IWL_MVM_ESR_EXIT_LOW_RSSI: link is deactivated/not allowed for EMLSR
  *     due to low RSSI.
@@ -379,6 +382,7 @@ enum iwl_mvm_esr_state {
        IWL_MVM_ESR_BLOCKED_FW          = 0x8,
        IWL_MVM_ESR_BLOCKED_NON_BSS     = 0x10,
        IWL_MVM_ESR_BLOCKED_ROC         = 0x20,
+       IWL_MVM_ESR_BLOCKED_TMP_NON_BSS = 0x40,
        IWL_MVM_ESR_EXIT_MISSED_BEACON  = 0x10000,
        IWL_MVM_ESR_EXIT_LOW_RSSI       = 0x20000,
        IWL_MVM_ESR_EXIT_COEX           = 0x40000,
@@ -452,6 +456,8 @@ struct iwl_mvm_esr_exit {
  * @prevent_esr_done_wk: work that should be done when esr prevention ends.
  * @mlo_int_scan_wk: work for the internal MLO scan.
  * @unblock_esr_tpt_wk: work for unblocking EMLSR when tpt is high enough.
+ * @unblock_esr_tmp_non_bss_wk: work for removing the
+ *      IWL_MVM_ESR_BLOCKED_TMP_NON_BSS blocking for EMLSR.
  * @roc_activity: currently running ROC activity for this vif (or
  *     ROC_NUM_ACTIVITIES if no activity is running).
  * @session_prot_connection_loss: the connection was lost due to session
@@ -588,6 +594,7 @@ struct iwl_mvm_vif {
        struct wiphy_delayed_work prevent_esr_done_wk;
        struct wiphy_delayed_work mlo_int_scan_wk;
        struct wiphy_work unblock_esr_tpt_wk;
+       struct wiphy_delayed_work unblock_esr_tmp_non_bss_wk;
 
        struct iwl_mvm_vif_link_info deflink;
        struct iwl_mvm_vif_link_info *link[IEEE80211_MLD_MAX_NUM_LINKS];