wifi: iwlwifi: mvm: Add support for prep_add_interface() callback

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>
This commit is contained in:
Ilan Peer 2024-10-08 07:25:15 +03:00 committed by Johannes Berg
parent 751e7489c1
commit 447c55e235
4 changed files with 61 additions and 0 deletions

View 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) \

View 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)

View 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,
};

View 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];