wifi: iwlwifi: mvm: Add helper functions to update EMLSR status
authorMiri Korenblit <miriam.rachel.korenblit@intel.com>
Tue, 16 Apr 2024 10:54:04 +0000 (13:54 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 19 Apr 2024 08:16:33 +0000 (10:16 +0200)
There are reasons for which we need to exit EMLSR, but not to block it
completely, and there are reasons for which we need to block EMLSR.

For both reason types we have the enum iwl_mvm_esr_state, when the
blocking reasons are stored in the `mvmvif::esr_disable_reason` bitmap.

This change introduces the APIs to use in the different cases:
- iwl_mvm_exit_esr - will exit from EMLSR mode.
- iwl_mvm_block_esr - will update the bitmap and exit EMLSR, to
  be used for the blocking reasons only.
- iwl_mvm_unblock_esr - will update the bitmap. To be used for the
  blocking reasons only.

Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Link: https://msgid.link/20240416134215.d54142a75876.I552926065521f5f848c37b0bd845494bd7865fb7@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/intel/iwlwifi/mvm/coex.c
drivers/net/wireless/intel/iwlwifi/mvm/link.c
drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h

index 54f086d9457f65be8e608666e43d1445ac93aa4d..c7987676335aea5474fa60f21c08e8be35772aae 100644 (file)
@@ -253,28 +253,6 @@ static void iwl_mvm_bt_coex_tcm_based_ci(struct iwl_mvm *mvm,
        swap(data->primary, data->secondary);
 }
 
-static void iwl_mvm_bt_coex_enable_esr(struct iwl_mvm *mvm,
-                                      struct ieee80211_vif *vif, bool enable)
-{
-       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-
-       lockdep_assert_held(&mvm->mutex);
-
-       if (!vif->cfg.assoc || !ieee80211_vif_is_mld(vif))
-               return;
-
-       /* Done already */
-       if ((mvmvif->esr_disable_reason & IWL_MVM_ESR_DISABLE_COEX) == !enable)
-               return;
-
-       if (enable)
-               mvmvif->esr_disable_reason &= ~IWL_MVM_ESR_DISABLE_COEX;
-       else
-               mvmvif->esr_disable_reason |= IWL_MVM_ESR_DISABLE_COEX;
-
-       iwl_mvm_recalc_esr(mvm, vif);
-}
-
 /*
  * This function receives the LB link id and checks if eSR should be
  * enabled or disabled (due to BT coex)
@@ -320,7 +298,7 @@ iwl_mvm_bt_coex_calculate_esr_mode(struct iwl_mvm *mvm,
        if (!link_rssi)
                wifi_loss_rate = mvm->last_bt_notif.wifi_loss_mid_high_rssi;
 
-       else if (!(mvmvif->esr_disable_reason & IWL_MVM_ESR_DISABLE_COEX))
+       else if (!(mvmvif->esr_disable_reason & IWL_MVM_ESR_BLOCKED_COEX))
                 /* RSSI needs to get really low to disable eSR... */
                wifi_loss_rate =
                        link_rssi <= -IWL_MVM_BT_COEX_DISABLE_ESR_THRESH ?
@@ -348,7 +326,12 @@ void iwl_mvm_bt_coex_update_link_esr(struct iwl_mvm *mvm,
 
        enable = iwl_mvm_bt_coex_calculate_esr_mode(mvm, vif, link_id);
 
-       iwl_mvm_bt_coex_enable_esr(mvm, vif, enable);
+       if (enable)
+               iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_COEX);
+       else
+               /* In case we decided to exit eSR - stay with the primary */
+               iwl_mvm_block_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_COEX,
+                                 iwl_mvm_get_primary_link(vif));
 }
 
 static void iwl_mvm_bt_notif_per_link(struct iwl_mvm *mvm,
@@ -534,7 +517,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
 
        /* When BT is off this will be 0 */
        if (data->notif->wifi_loss_low_rssi == BT_OFF)
-               iwl_mvm_bt_coex_enable_esr(mvm, vif, true);
+               iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_COEX);
 
        for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++)
                iwl_mvm_bt_notif_per_link(mvm, vif, data, link_id);
index 710c8802a3c6b1cf3f8aa028d2d2aa314a49b406..8a4b1b89791cd7a1e4a465c56aeafca390faaba1 100644 (file)
@@ -560,7 +560,7 @@ bool iwl_mvm_mld_valid_link_pair(struct ieee80211_vif *vif,
 
        /* BT Coex effects eSR mode only if one of the link is on LB */
        if (a->band == NL80211_BAND_2GHZ || b->band == NL80211_BAND_2GHZ)
-               return !(mvmvif->esr_disable_reason & IWL_MVM_ESR_DISABLE_COEX);
+               return !(mvmvif->esr_disable_reason & IWL_MVM_ESR_BLOCKED_COEX);
 
        return true;
 }
@@ -691,3 +691,72 @@ u8 iwl_mvm_get_primary_link(struct ieee80211_vif *vif)
 
        return __ffs(vif->active_links);
 }
+
+/* API to exit eSR mode */
+void iwl_mvm_exit_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+                     enum iwl_mvm_esr_state reason,
+                     u8 link_to_keep)
+{
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+       u16 new_active_links;
+
+       lockdep_assert_held(&mvm->mutex);
+
+       /* Nothing to do */
+       if (!mvmvif->esr_active)
+               return;
+
+       if (WARN_ON(!ieee80211_vif_is_mld(vif) || !mvmvif->authorized))
+               return;
+
+       if (WARN_ON(!(vif->active_links & BIT(link_to_keep))))
+               link_to_keep = __ffs(vif->active_links);
+
+       new_active_links = BIT(link_to_keep);
+       IWL_DEBUG_INFO(mvm,
+                      "Exiting EMLSR. Reason = 0x%x. Current active links=0x%x, new active links = 0x%x\n",
+                      reason, vif->active_links, new_active_links);
+
+       ieee80211_set_active_links_async(vif, new_active_links);
+}
+
+#define IWL_MVM_BLOCK_ESR_REASONS IWL_MVM_ESR_BLOCKED_COEX
+
+void iwl_mvm_block_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+                      enum iwl_mvm_esr_state reason,
+                      u8 link_to_keep)
+{
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+       lockdep_assert_held(&mvm->mutex);
+
+       /* This should be called only with disable reasons */
+       if (WARN_ON(!(reason & IWL_MVM_BLOCK_ESR_REASONS)))
+               return;
+
+       if (!(mvmvif->esr_disable_reason & reason))
+               IWL_DEBUG_INFO(mvm, "Blocking EMSLR mode. reason = 0x%x\n",
+                              reason);
+
+       mvmvif->esr_disable_reason |= reason;
+
+       iwl_mvm_exit_esr(mvm, vif, reason, link_to_keep);
+}
+
+void iwl_mvm_unblock_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+                        enum iwl_mvm_esr_state reason)
+{
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+       lockdep_assert_held(&mvm->mutex);
+
+       /* This should be called only with disable reasons */
+       if (WARN_ON(!(reason & IWL_MVM_BLOCK_ESR_REASONS)))
+               return;
+
+       if (mvmvif->esr_disable_reason & reason)
+               IWL_DEBUG_INFO(mvm, "Unblocking EMSLR mode. reason = 0x%x\n",
+                              reason);
+
+       mvmvif->esr_disable_reason &= ~reason;
+}
index 105ac43e4cd78d24d5c6addefac6b54731430715..2a7d7d4e06493624d0133324966913863d4805cd 100644 (file)
@@ -1151,28 +1151,6 @@ iwl_mvm_mld_change_sta_links(struct ieee80211_hw *hw,
        return ret;
 }
 
-void iwl_mvm_recalc_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
-{
-       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-       bool enable = !mvmvif->esr_disable_reason;
-       u16 new_active_links;
-
-       /* Nothing to do */
-       if (mvmvif->esr_active == enable)
-               return;
-
-       /* The next link selection will enter eSR if possible */
-       if (enable)
-               return;
-
-       /*
-        * Find the primary link, as we want to switch to it and drop the
-        * secondary one.
-        */
-       new_active_links = BIT(iwl_mvm_get_primary_link(vif));
-       ieee80211_set_active_links_async(vif, new_active_links);
-}
-
 bool iwl_mvm_esr_allowed_on_vif(struct iwl_mvm *mvm,
                                struct ieee80211_vif *vif)
 {
@@ -1194,7 +1172,7 @@ bool iwl_mvm_esr_allowed_on_vif(struct iwl_mvm *mvm,
            !(ext_capa->eml_capabilities & IEEE80211_EML_CAP_EMLSR_SUPP))
                return false;
 
-       return !(mvmvif->esr_disable_reason & ~IWL_MVM_ESR_DISABLE_COEX);
+       return !(mvmvif->esr_disable_reason & ~IWL_MVM_ESR_BLOCKED_COEX);
 }
 
 /*
index 4755747822b6a003e16067cd38c994eff693215a..3b726c8b9261ecf50947c1270c520c5f5c619eec 100644 (file)
@@ -346,11 +346,17 @@ struct iwl_mvm_vif_link_info {
 };
 
 /**
- * enum iwl_mvm_esr_disable_reason - reasons for which we can't enable EMLSR
- * @IWL_MVM_ESR_DISABLE_COEX: COEX is preventing the enablement of EMLSR
+ * enum iwl_mvm_esr_state - defines reasons for which the EMLSR is exited or
+ * blocked.
+ * The low 16 bits are used for blocking reasons, and the 16 higher bits
+ * are used for exit reasons.
+ * For the blocking reasons - use iwl_mvm_(un)block_esr(), and for the exit
+ * reasons - use iwl_mvm_exit_esr().
+ *
+ * @IWL_MVM_ESR_BLOCKED_COEX: COEX is preventing the enablement of EMLSR
  */
-enum iwl_mvm_esr_disable_reason {
-       IWL_MVM_ESR_DISABLE_COEX        = BIT(0),
+enum iwl_mvm_esr_state {
+       IWL_MVM_ESR_BLOCKED_COEX        = 0x1,
 };
 
 /**
@@ -386,7 +392,7 @@ enum iwl_mvm_esr_disable_reason {
  * @deflink: default link data for use in non-MLO
  * @link: link data for each link in MLO
  * @esr_active: indicates eSR mode is active
- * @esr_disable_reason: a bitmap of enum iwl_mvm_esr_disable_reason
+ * @esr_disable_reason: a bitmap of &enum iwl_mvm_esr_state
  * @pm_enabled: indicates powersave is enabled
  * @link_selection_res: bitmap of active links as it was decided in the last
  *     link selection. Valid only for a MLO vif after assoc. 0 if there wasn't
@@ -2836,8 +2842,15 @@ int iwl_mvm_roc_add_cmd(struct iwl_mvm *mvm,
                        int duration, u32 activity);
 
 /* EMLSR */
-void iwl_mvm_recalc_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
 bool iwl_mvm_esr_allowed_on_vif(struct iwl_mvm *mvm,
                                struct ieee80211_vif *vif);
+void iwl_mvm_block_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+                      enum iwl_mvm_esr_state reason,
+                      u8 link_to_keep);
+void iwl_mvm_unblock_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+                        enum iwl_mvm_esr_state reason);
+void iwl_mvm_exit_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+                     enum iwl_mvm_esr_state reason,
+                     u8 link_to_keep);
 
 #endif /* __IWL_MVM_H__ */