Commit fe8b2ad3 authored by Miri Korenblit's avatar Miri Korenblit Committed by Johannes Berg

wifi: iwlwifi: mvm: add cancel/remain_on_channel for MLD mode

Add an MLD version of the remain_on_channel and
cancel_remain_on_channel callbacks.
Signed-off-by: default avatarMiri Korenblit <miriam.rachel.korenblit@intel.com>
Signed-off-by: default avatarGregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230328104948.b51813dbebd4.Ia25bbd63d3138e4759237ce2be0cd0436fe01c0a@changeidSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent feebebae
......@@ -491,11 +491,14 @@ struct iwl_link_config_cmd {
* @STATION_TYPE_MCAST: the station used for BCAST / MCAST in GO. Will be
* suspended / resumed at the right timing depending on the clients'
* power save state and the DTIM timing
* @STATION_TYPE_AUX: aux sta. In the FW there is no need for a special type
* for the aux sta, so this type is only for driver - internal use.
*/
enum iwl_fw_sta_type {
STATION_TYPE_PEER,
STATION_TYPE_BCAST_MGMT,
STATION_TYPE_MCAST,
STATION_TYPE_AUX,
}; /* STATION_TYPE_E_VER_1 */
/**
......
......@@ -4309,6 +4309,20 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
struct ieee80211_channel *channel,
int duration,
enum ieee80211_roc_type type)
{
struct iwl_mvm_roc_ops ops = {
.add_aux_sta_for_hs20 = iwl_mvm_add_aux_sta_for_hs20,
.switch_phy_ctxt = iwl_mvm_roc_switch_binding,
};
return iwl_mvm_roc_common(hw, vif, channel, duration, type, &ops);
}
/* Execute the common part for MLD and non-MLD modes */
int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_channel *channel, int duration,
enum ieee80211_roc_type type,
struct iwl_mvm_roc_ops *ops)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
......@@ -4334,7 +4348,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
lmac_id = iwl_mvm_get_lmac_id(mvm->fw, channel->band);
/* Use aux roc framework (HS20) */
ret = iwl_mvm_add_aux_sta_for_hs20(mvm, lmac_id);
ret = ops->add_aux_sta_for_hs20(mvm, lmac_id);
if (!ret)
ret = iwl_mvm_send_aux_roc_cmd(mvm, channel,
vif, duration);
......@@ -4354,7 +4368,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
continue;
if (phy_ctxt->ref && channel == phy_ctxt->channel) {
ret = iwl_mvm_roc_switch_binding(mvm, vif, phy_ctxt);
ret = ops->switch_phy_ctxt(mvm, vif, phy_ctxt);
if (ret)
goto out_unlock;
......@@ -4408,7 +4422,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
goto out_unlock;
}
ret = iwl_mvm_roc_switch_binding(mvm, vif, phy_ctxt);
ret = ops->switch_phy_ctxt(mvm, vif, phy_ctxt);
if (ret)
goto out_unlock;
......@@ -4425,8 +4439,8 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
return ret;
}
static int iwl_mvm_cancel_roc(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
int iwl_mvm_cancel_roc(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
......
......@@ -592,10 +592,53 @@ iwl_mvm_mld_mac_conf_tx(struct ieee80211_hw *hw,
return 0;
}
static int iwl_mvm_link_switch_phy_ctx(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct iwl_mvm_phy_ctxt *new_phy_ctxt)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ret = 0;
lockdep_assert_held(&mvm->mutex);
/* Inorder to change the phy_ctx of a link, the link needs to be
* inactive. Therefore, first deactivate the link, then change its
* phy_ctx, and then activate it again.
*/
ret = iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ACTIVE, false);
if (WARN(ret, "Failed to deactivate link\n"))
return ret;
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
mvmvif->deflink.phy_ctxt = new_phy_ctxt;
ret = iwl_mvm_link_changed(mvm, vif, 0, false);
if (WARN(ret, "Failed to deactivate link\n"))
return ret;
ret = iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ACTIVE, true);
WARN(ret, "Failed binding P2P_DEVICE\n");
return ret;
}
static int iwl_mvm_mld_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_channel *channel, int duration,
enum ieee80211_roc_type type)
{
struct iwl_mvm_roc_ops ops = {
.add_aux_sta_for_hs20 = iwl_mvm_mld_add_aux_sta,
.switch_phy_ctxt = iwl_mvm_link_switch_phy_ctx,
};
return iwl_mvm_roc_common(hw, vif, channel, duration, type, &ops);
}
const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
.add_interface = iwl_mvm_mld_mac_add_interface,
.remove_interface = iwl_mvm_mld_mac_remove_interface,
.config_iface_filter = iwl_mvm_mld_config_iface_filter,
.remain_on_channel = iwl_mvm_mld_roc,
.cancel_remain_on_channel = iwl_mvm_cancel_roc,
.assign_vif_chanctx = iwl_mvm_mld_assign_vif_chanctx,
.unassign_vif_chanctx = iwl_mvm_mld_unassign_vif_chanctx,
.switch_vif_chanctx = iwl_mvm_mld_switch_vif_chanctx,
......
......@@ -75,6 +75,24 @@ static int iwl_mvm_mld_rm_sta_from_fw(struct iwl_mvm *mvm, u32 sta_id)
return 0;
}
static int iwl_mvm_add_aux_sta_to_fw(struct iwl_mvm *mvm,
struct iwl_mvm_int_sta *sta,
u32 lmac_id)
{
int ret;
struct iwl_mvm_aux_sta_cmd cmd = {
.sta_id = cpu_to_le32(sta->sta_id),
.lmac_id = cpu_to_le32(lmac_id),
};
ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(MAC_CONF_GROUP, AUX_STA_CMD),
0, sizeof(cmd), &cmd);
if (ret)
IWL_ERR(mvm, "Failed to send AUX_STA_CMD\n");
return ret;
}
/*
* Adds an internal sta to the FW table with its queues
*/
......@@ -91,7 +109,10 @@ static int iwl_mvm_mld_add_int_sta_with_queue(struct iwl_mvm *mvm,
if (WARN_ON_ONCE(sta->sta_id == IWL_MVM_INVALID_STA))
return -ENOSPC;
ret = iwl_mvm_mld_add_int_sta_to_fw(mvm, sta, addr, phy_id);
if (sta->type == STATION_TYPE_AUX)
ret = iwl_mvm_add_aux_sta_to_fw(mvm, sta, phy_id);
else
ret = iwl_mvm_mld_add_int_sta_to_fw(mvm, sta, addr, phy_id);
if (ret)
return ret;
......@@ -224,6 +245,19 @@ int iwl_mvm_mld_add_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
IWL_MAX_TID_COUNT, NULL);
}
int iwl_mvm_mld_add_aux_sta(struct iwl_mvm *mvm, u32 lmac_id)
{
lockdep_assert_held(&mvm->mutex);
/* In CDB NICs we need to specify which lmac to use for aux activity
* using the phy_id argument place to send lmac_id to the function
*/
return iwl_mvm_mld_add_int_sta(mvm, &mvm->aux_sta, &mvm->aux_queue,
NL80211_IFTYPE_UNSPECIFIED,
STATION_TYPE_AUX, lmac_id, NULL,
IWL_MAX_TID_COUNT, NULL);
}
static int iwl_mvm_mld_disable_txq(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
u16 *queueptr, u8 tid)
......@@ -332,6 +366,14 @@ int iwl_mvm_mld_rm_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
IWL_MAX_TID_COUNT, &mvm->snif_queue);
}
int iwl_mvm_mld_rm_aux_sta(struct iwl_mvm *mvm)
{
lockdep_assert_held(&mvm->mutex);
return iwl_mvm_mld_rm_int_sta(mvm, &mvm->aux_sta, false,
IWL_MAX_TID_COUNT, &mvm->aux_queue);
}
/* send a cfg sta command to add/update a sta in firmware */
static int iwl_mvm_mld_cfg_sta(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
struct ieee80211_vif *vif, u16 phy_id)
......
......@@ -1827,6 +1827,32 @@ void iwl_mvm_bss_info_changed_station_assoc(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
u64 changes);
/* ROC */
/**
* struct iwl_mvm_roc_ops - callbacks for the remain_on_channel()
*
* Since the only difference between both MLD and
* non-MLD versions of remain_on_channel() is these function calls,
* each version will send its specific function calls to
* %iwl_mvm_roc_common().
*
* @add_aux_sta_for_hs20: pointer to the function that adds an aux sta
* for Hot Spot 2.0
* @switch_phy_ctxt: pointer to the function that switches a vif from one
* phy_ctx to another
*/
struct iwl_mvm_roc_ops {
int (*add_aux_sta_for_hs20)(struct iwl_mvm *mvm, u32 lmac_id);
int (*switch_phy_ctxt)(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct iwl_mvm_phy_ctxt *new_phy_ctxt);
};
int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_channel *channel, int duration,
enum ieee80211_roc_type type,
struct iwl_mvm_roc_ops *ops);
int iwl_mvm_cancel_roc(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
/*Session Protection */
void iwl_mvm_protect_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
u32 duration_override);
......
......@@ -622,9 +622,11 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
int iwl_mvm_mld_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_mld_add_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_mld_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_mld_add_aux_sta(struct iwl_mvm *mvm, u32 lmac_id);
int iwl_mvm_mld_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_mld_rm_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_mld_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_mld_rm_aux_sta(struct iwl_mvm *mvm);
int iwl_mvm_mld_add_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
int iwl_mvm_mld_update_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
......
......@@ -95,6 +95,11 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
/* do the same in case of hot spot 2.0 */
iwl_mvm_flush_sta(mvm, &mvm->aux_sta, true);
if (mvm->mld_api_is_used) {
iwl_mvm_mld_rm_aux_sta(mvm);
goto out_unlock;
}
/* In newer version of this command an aux station is added only
* in cases of dedicated tx queue and need to be removed in end
* of use */
......@@ -102,6 +107,7 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
iwl_mvm_rm_aux_sta(mvm);
}
out_unlock:
mutex_unlock(&mvm->mutex);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment