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 { ...@@ -491,11 +491,14 @@ struct iwl_link_config_cmd {
* @STATION_TYPE_MCAST: the station used for BCAST / MCAST in GO. Will be * @STATION_TYPE_MCAST: the station used for BCAST / MCAST in GO. Will be
* suspended / resumed at the right timing depending on the clients' * suspended / resumed at the right timing depending on the clients'
* power save state and the DTIM timing * 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 { enum iwl_fw_sta_type {
STATION_TYPE_PEER, STATION_TYPE_PEER,
STATION_TYPE_BCAST_MGMT, STATION_TYPE_BCAST_MGMT,
STATION_TYPE_MCAST, STATION_TYPE_MCAST,
STATION_TYPE_AUX,
}; /* STATION_TYPE_E_VER_1 */ }; /* STATION_TYPE_E_VER_1 */
/** /**
......
...@@ -4309,6 +4309,20 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, ...@@ -4309,6 +4309,20 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
struct ieee80211_channel *channel, struct ieee80211_channel *channel,
int duration, int duration,
enum ieee80211_roc_type type) 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 *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
...@@ -4334,7 +4348,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, ...@@ -4334,7 +4348,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
lmac_id = iwl_mvm_get_lmac_id(mvm->fw, channel->band); lmac_id = iwl_mvm_get_lmac_id(mvm->fw, channel->band);
/* Use aux roc framework (HS20) */ /* 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) if (!ret)
ret = iwl_mvm_send_aux_roc_cmd(mvm, channel, ret = iwl_mvm_send_aux_roc_cmd(mvm, channel,
vif, duration); vif, duration);
...@@ -4354,7 +4368,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, ...@@ -4354,7 +4368,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
continue; continue;
if (phy_ctxt->ref && channel == phy_ctxt->channel) { 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) if (ret)
goto out_unlock; goto out_unlock;
...@@ -4408,7 +4422,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, ...@@ -4408,7 +4422,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
goto out_unlock; goto out_unlock;
} }
ret = iwl_mvm_roc_switch_binding(mvm, vif, phy_ctxt); ret = ops->switch_phy_ctxt(mvm, vif, phy_ctxt);
if (ret) if (ret)
goto out_unlock; goto out_unlock;
...@@ -4425,8 +4439,8 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, ...@@ -4425,8 +4439,8 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
return ret; return ret;
} }
static int iwl_mvm_cancel_roc(struct ieee80211_hw *hw, int iwl_mvm_cancel_roc(struct ieee80211_hw *hw,
struct ieee80211_vif *vif) struct ieee80211_vif *vif)
{ {
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
......
...@@ -592,10 +592,53 @@ iwl_mvm_mld_mac_conf_tx(struct ieee80211_hw *hw, ...@@ -592,10 +592,53 @@ iwl_mvm_mld_mac_conf_tx(struct ieee80211_hw *hw,
return 0; 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 = { const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
.add_interface = iwl_mvm_mld_mac_add_interface, .add_interface = iwl_mvm_mld_mac_add_interface,
.remove_interface = iwl_mvm_mld_mac_remove_interface, .remove_interface = iwl_mvm_mld_mac_remove_interface,
.config_iface_filter = iwl_mvm_mld_config_iface_filter, .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, .assign_vif_chanctx = iwl_mvm_mld_assign_vif_chanctx,
.unassign_vif_chanctx = iwl_mvm_mld_unassign_vif_chanctx, .unassign_vif_chanctx = iwl_mvm_mld_unassign_vif_chanctx,
.switch_vif_chanctx = iwl_mvm_mld_switch_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) ...@@ -75,6 +75,24 @@ static int iwl_mvm_mld_rm_sta_from_fw(struct iwl_mvm *mvm, u32 sta_id)
return 0; 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 * 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, ...@@ -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)) if (WARN_ON_ONCE(sta->sta_id == IWL_MVM_INVALID_STA))
return -ENOSPC; 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) if (ret)
return ret; return ret;
...@@ -224,6 +245,19 @@ int iwl_mvm_mld_add_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) ...@@ -224,6 +245,19 @@ int iwl_mvm_mld_add_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
IWL_MAX_TID_COUNT, NULL); 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, static int iwl_mvm_mld_disable_txq(struct iwl_mvm *mvm,
struct ieee80211_sta *sta, struct ieee80211_sta *sta,
u16 *queueptr, u8 tid) u16 *queueptr, u8 tid)
...@@ -332,6 +366,14 @@ int iwl_mvm_mld_rm_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) ...@@ -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); 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 */ /* 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, static int iwl_mvm_mld_cfg_sta(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
struct ieee80211_vif *vif, u16 phy_id) struct ieee80211_vif *vif, u16 phy_id)
......
...@@ -1827,6 +1827,32 @@ void iwl_mvm_bss_info_changed_station_assoc(struct iwl_mvm *mvm, ...@@ -1827,6 +1827,32 @@ void iwl_mvm_bss_info_changed_station_assoc(struct iwl_mvm *mvm,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
u64 changes); 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 */ /*Session Protection */
void iwl_mvm_protect_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, void iwl_mvm_protect_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
u32 duration_override); u32 duration_override);
......
...@@ -622,9 +622,11 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw, ...@@ -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_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_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_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_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_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_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, int iwl_mvm_mld_add_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_sta *sta); struct ieee80211_sta *sta);
int iwl_mvm_mld_update_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 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) ...@@ -95,6 +95,11 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
/* do the same in case of hot spot 2.0 */ /* do the same in case of hot spot 2.0 */
iwl_mvm_flush_sta(mvm, &mvm->aux_sta, true); 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 newer version of this command an aux station is added only
* in cases of dedicated tx queue and need to be removed in end * in cases of dedicated tx queue and need to be removed in end
* of use */ * of use */
...@@ -102,6 +107,7 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk) ...@@ -102,6 +107,7 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
iwl_mvm_rm_aux_sta(mvm); iwl_mvm_rm_aux_sta(mvm);
} }
out_unlock:
mutex_unlock(&mvm->mutex); 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