Commit 447c55e2 authored by Ilan Peer's avatar Ilan Peer Committed by Johannes Berg
Browse files

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: default avatarIlan Peer <ilan.peer@intel.com>
Signed-off-by: default avatarMiri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20241008072037.3baf282d0a01.Ife0a929455cb13a95ab197ca765d8db777ff9d89@changeid


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 751e7489
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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)			\
+22 −0
Original line number Diff line number Diff line
@@ -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)
+31 −0
Original line number Diff line number Diff line
@@ -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,
};
+7 −0
Original line number Diff line number Diff line
@@ -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];