Commit 660eba5a authored by Miri Korenblit's avatar Miri Korenblit Committed by Johannes Berg

wifi: iwlwifi: mvm: add some new MLD ops

Add MLD version of bss_info_changed/switch_vif_chanctx/
config_iface_filter and conf_tx() 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.9c83c253d610.Ibf2006be9ece87896c17cb43dfe3654ac73d81ff@changeidSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 87f7e243
...@@ -2433,9 +2433,8 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm, ...@@ -2433,9 +2433,8 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,
IWL_ERR(mvm, "Failed to config FW to work HE!\n"); IWL_ERR(mvm, "Failed to config FW to work HE!\n");
} }
static void iwl_mvm_protect_assoc(struct iwl_mvm *mvm, void iwl_mvm_protect_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_vif *vif, u32 duration_override)
u32 duration_override)
{ {
u32 duration = IWL_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS; u32 duration = IWL_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS;
u32 min_duration = IWL_MVM_TE_SESSION_PROTECTION_MIN_TIME_MS; u32 min_duration = IWL_MVM_TE_SESSION_PROTECTION_MIN_TIME_MS;
...@@ -2461,6 +2460,82 @@ static void iwl_mvm_protect_assoc(struct iwl_mvm *mvm, ...@@ -2461,6 +2460,82 @@ static void iwl_mvm_protect_assoc(struct iwl_mvm *mvm,
min_duration, 500, false); min_duration, 500, false);
} }
/* Handle association common part to MLD and non-MLD modes */
void iwl_mvm_bss_info_changed_station_assoc(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
u64 changes)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ret;
/* The firmware tracks the MU-MIMO group on its own.
* However, on HW restart we should restore this data.
*/
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
(changes & BSS_CHANGED_MU_GROUPS) && vif->bss_conf.mu_mimo_owner) {
ret = iwl_mvm_update_mu_groups(mvm, vif);
if (ret)
IWL_ERR(mvm,
"failed to update VHT MU_MIMO groups\n");
}
iwl_mvm_recalc_multicast(mvm);
/* reset rssi values */
mvmvif->bf_data.ave_beacon_signal = 0;
iwl_mvm_bt_coex_vif_change(mvm);
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_TT,
IEEE80211_SMPS_AUTOMATIC);
if (fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_UMAC_SCAN))
iwl_mvm_config_scan(mvm);
}
/* Execute the common part for MLD and non-MLD modes */
void iwl_mvm_bss_info_changed_station_common(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
u64 changes)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ret;
if (changes & BSS_CHANGED_BEACON_INFO) {
/* We received a beacon from the associated AP so
* remove the session protection.
*/
iwl_mvm_stop_session_protection(mvm, vif);
iwl_mvm_sf_update(mvm, vif, false);
WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
}
if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | BSS_CHANGED_QOS |
/* Send power command on every beacon change,
* because we may have not enabled beacon abort yet.
*/
BSS_CHANGED_BEACON_INFO)) {
ret = iwl_mvm_power_update_mac(mvm);
if (ret)
IWL_ERR(mvm, "failed to update power mode\n");
}
if (changes & BSS_CHANGED_CQM) {
IWL_DEBUG_MAC80211(mvm, "cqm info_changed\n");
/* reset cqm events tracking */
mvmvif->bf_data.last_cqm_event = 0;
if (mvmvif->bf_data.bf_enabled) {
ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
if (ret)
IWL_ERR(mvm,
"failed to update CQM thresholds\n");
}
}
if (changes & BSS_CHANGED_BANDWIDTH)
iwl_mvm_apply_fw_smps_request(vif);
}
static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf, struct ieee80211_bss_conf *bss_conf,
...@@ -2623,67 +2698,10 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, ...@@ -2623,67 +2698,10 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
vif->addr); vif->addr);
} }
/* iwl_mvm_bss_info_changed_station_assoc(mvm, vif, changes);
* The firmware tracks the MU-MIMO group on its own.
* However, on HW restart we should restore this data.
*/
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
(changes & BSS_CHANGED_MU_GROUPS) && vif->bss_conf.mu_mimo_owner) {
ret = iwl_mvm_update_mu_groups(mvm, vif);
if (ret)
IWL_ERR(mvm,
"failed to update VHT MU_MIMO groups\n");
}
iwl_mvm_recalc_multicast(mvm);
/* reset rssi values */
mvmvif->bf_data.ave_beacon_signal = 0;
iwl_mvm_bt_coex_vif_change(mvm);
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_TT,
IEEE80211_SMPS_AUTOMATIC);
if (fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_UMAC_SCAN))
iwl_mvm_config_scan(mvm);
}
if (changes & BSS_CHANGED_BEACON_INFO) {
/*
* We received a beacon from the associated AP so
* remove the session protection.
*/
iwl_mvm_stop_session_protection(mvm, vif);
iwl_mvm_sf_update(mvm, vif, false);
WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
} }
if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | BSS_CHANGED_QOS | iwl_mvm_bss_info_changed_station_common(mvm, vif, changes);
/*
* Send power command on every beacon change,
* because we may have not enabled beacon abort yet.
*/
BSS_CHANGED_BEACON_INFO)) {
ret = iwl_mvm_power_update_mac(mvm);
if (ret)
IWL_ERR(mvm, "failed to update power mode\n");
}
if (changes & BSS_CHANGED_CQM) {
IWL_DEBUG_MAC80211(mvm, "cqm info_changed\n");
/* reset cqm events tracking */
mvmvif->bf_data.last_cqm_event = 0;
if (mvmvif->bf_data.bf_enabled) {
ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
if (ret)
IWL_ERR(mvm,
"failed to update CQM thresholds\n");
}
}
if (changes & BSS_CHANGED_BANDWIDTH)
iwl_mvm_apply_fw_smps_request(vif);
} }
bool iwl_mvm_start_ap_ibss_common(struct ieee80211_hw *hw, bool iwl_mvm_start_ap_ibss_common(struct ieee80211_hw *hw,
...@@ -2967,6 +2985,22 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw, ...@@ -2967,6 +2985,22 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf, struct ieee80211_bss_conf *bss_conf,
u64 changes) u64 changes)
{
struct iwl_mvm_bss_info_changed_ops callbacks = {
.bss_info_changed_sta = iwl_mvm_bss_info_changed_station,
.bss_info_changed_ap_ibss = iwl_mvm_bss_info_changed_ap_ibss,
};
iwl_mvm_bss_info_changed_common(hw, vif, bss_conf, &callbacks,
changes);
}
void
iwl_mvm_bss_info_changed_common(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
struct iwl_mvm_bss_info_changed_ops *callbacks,
u64 changes)
{ {
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
...@@ -2977,11 +3011,12 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw, ...@@ -2977,11 +3011,12 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
switch (vif->type) { switch (vif->type) {
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
iwl_mvm_bss_info_changed_station(mvm, vif, bss_conf, changes); callbacks->bss_info_changed_sta(mvm, vif, bss_conf, changes);
break; break;
case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_ADHOC:
iwl_mvm_bss_info_changed_ap_ibss(mvm, vif, bss_conf, changes); callbacks->bss_info_changed_ap_ibss(mvm, vif, bss_conf,
changes);
break; break;
case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_MONITOR:
if (changes & BSS_CHANGED_MU_GROUPS) if (changes & BSS_CHANGED_MU_GROUPS)
...@@ -4762,12 +4797,13 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw, ...@@ -4762,12 +4797,13 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw,
static int static int
iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm, iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm,
struct ieee80211_vif_chanctx_switch *vifs) struct ieee80211_vif_chanctx_switch *vifs,
struct iwl_mvm_switch_vif_chanctx_ops *ops)
{ {
int ret; int ret;
mutex_lock(&mvm->mutex); mutex_lock(&mvm->mutex);
__iwl_mvm_unassign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx, true); ops->__unassign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx, true);
__iwl_mvm_remove_chanctx(mvm, vifs[0].old_ctx); __iwl_mvm_remove_chanctx(mvm, vifs[0].old_ctx);
ret = __iwl_mvm_add_chanctx(mvm, vifs[0].new_ctx); ret = __iwl_mvm_add_chanctx(mvm, vifs[0].new_ctx);
...@@ -4776,7 +4812,7 @@ iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm, ...@@ -4776,7 +4812,7 @@ iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm,
goto out_reassign; goto out_reassign;
} }
ret = __iwl_mvm_assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].new_ctx, ret = ops->__assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].new_ctx,
true); true);
if (ret) { if (ret) {
IWL_ERR(mvm, IWL_ERR(mvm,
...@@ -4799,8 +4835,8 @@ iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm, ...@@ -4799,8 +4835,8 @@ iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm,
goto out_restart; goto out_restart;
} }
if (__iwl_mvm_assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx, if (ops->__assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx,
true)) { true)) {
IWL_ERR(mvm, "failed to reassign old_ctx after failure.\n"); IWL_ERR(mvm, "failed to reassign old_ctx after failure.\n");
goto out_restart; goto out_restart;
} }
...@@ -4819,14 +4855,15 @@ iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm, ...@@ -4819,14 +4855,15 @@ iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm,
static int static int
iwl_mvm_switch_vif_chanctx_reassign(struct iwl_mvm *mvm, iwl_mvm_switch_vif_chanctx_reassign(struct iwl_mvm *mvm,
struct ieee80211_vif_chanctx_switch *vifs) struct ieee80211_vif_chanctx_switch *vifs,
struct iwl_mvm_switch_vif_chanctx_ops *ops)
{ {
int ret; int ret;
mutex_lock(&mvm->mutex); mutex_lock(&mvm->mutex);
__iwl_mvm_unassign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx, true); ops->__unassign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx, true);
ret = __iwl_mvm_assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].new_ctx, ret = ops->__assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].new_ctx,
true); true);
if (ret) { if (ret) {
IWL_ERR(mvm, IWL_ERR(mvm,
...@@ -4837,8 +4874,8 @@ iwl_mvm_switch_vif_chanctx_reassign(struct iwl_mvm *mvm, ...@@ -4837,8 +4874,8 @@ iwl_mvm_switch_vif_chanctx_reassign(struct iwl_mvm *mvm,
goto out; goto out;
out_reassign: out_reassign:
if (__iwl_mvm_assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx, if (ops->__assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx,
true)) { true)) {
IWL_ERR(mvm, "failed to reassign old_ctx after failure.\n"); IWL_ERR(mvm, "failed to reassign old_ctx after failure.\n");
goto out_restart; goto out_restart;
} }
...@@ -4855,10 +4892,13 @@ iwl_mvm_switch_vif_chanctx_reassign(struct iwl_mvm *mvm, ...@@ -4855,10 +4892,13 @@ iwl_mvm_switch_vif_chanctx_reassign(struct iwl_mvm *mvm,
return ret; return ret;
} }
static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw, /* Execute the common part for both MLD and non-MLD modes */
struct ieee80211_vif_chanctx_switch *vifs, int
int n_vifs, iwl_mvm_switch_vif_chanctx_common(struct ieee80211_hw *hw,
enum ieee80211_chanctx_switch_mode mode) struct ieee80211_vif_chanctx_switch *vifs,
int n_vifs,
enum ieee80211_chanctx_switch_mode mode,
struct iwl_mvm_switch_vif_chanctx_ops *ops)
{ {
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret; int ret;
...@@ -4869,10 +4909,10 @@ static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw, ...@@ -4869,10 +4909,10 @@ static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw,
switch (mode) { switch (mode) {
case CHANCTX_SWMODE_SWAP_CONTEXTS: case CHANCTX_SWMODE_SWAP_CONTEXTS:
ret = iwl_mvm_switch_vif_chanctx_swap(mvm, vifs); ret = iwl_mvm_switch_vif_chanctx_swap(mvm, vifs, ops);
break; break;
case CHANCTX_SWMODE_REASSIGN_VIF: case CHANCTX_SWMODE_REASSIGN_VIF:
ret = iwl_mvm_switch_vif_chanctx_reassign(mvm, vifs); ret = iwl_mvm_switch_vif_chanctx_reassign(mvm, vifs, ops);
break; break;
default: default:
ret = -EOPNOTSUPP; ret = -EOPNOTSUPP;
...@@ -4882,6 +4922,19 @@ static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw, ...@@ -4882,6 +4922,19 @@ static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw,
return ret; return ret;
} }
static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw,
struct ieee80211_vif_chanctx_switch *vifs,
int n_vifs,
enum ieee80211_chanctx_switch_mode mode)
{
struct iwl_mvm_switch_vif_chanctx_ops ops = {
.__assign_vif_chanctx = __iwl_mvm_assign_vif_chanctx,
.__unassign_vif_chanctx = __iwl_mvm_unassign_vif_chanctx,
};
return iwl_mvm_switch_vif_chanctx_common(hw, vifs, n_vifs, mode, &ops);
}
static int iwl_mvm_tx_last_beacon(struct ieee80211_hw *hw) static int iwl_mvm_tx_last_beacon(struct ieee80211_hw *hw)
{ {
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
......
...@@ -369,12 +369,239 @@ static int iwl_mvm_mld_mac_sta_state(struct ieee80211_hw *hw, ...@@ -369,12 +369,239 @@ static int iwl_mvm_mld_mac_sta_state(struct ieee80211_hw *hw,
&callbacks); &callbacks);
} }
static void
iwl_mvm_mld_bss_info_changed_station(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
u64 changes)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ret;
u32 link_changes = 0;
bool has_he = vif->bss_conf.he_support &&
!iwlwifi_mod_params.disable_11ax;
bool has_eht = vif->bss_conf.eht_support &&
!iwlwifi_mod_params.disable_11be;
if (changes & BSS_CHANGED_ASSOC && vif->cfg.assoc &&
(has_he || has_eht)) {
IWL_DEBUG_MAC80211(mvm, "Associated in HE mode\n");
link_changes |= LINK_CONTEXT_MODIFY_HE_PARAMS;
}
/* Update MU EDCA params */
if (changes & BSS_CHANGED_QOS && vif->cfg.assoc &&
(has_he || has_eht))
link_changes |= LINK_CONTEXT_MODIFY_QOS_PARAMS;
/* Update EHT Puncturing info */
if (changes & BSS_CHANGED_EHT_PUNCTURING && vif->cfg.assoc && has_eht)
link_changes |= LINK_CONTEXT_MODIFY_EHT_PARAMS;
if (link_changes) {
ret = iwl_mvm_link_changed(mvm, vif, link_changes, true);
if (ret)
IWL_ERR(mvm, "failed to update link\n");
}
ret = iwl_mvm_mld_mac_ctxt_changed(mvm, vif, false);
if (ret)
IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
memcpy(mvmvif->deflink.bssid, bss_conf->bssid, ETH_ALEN);
mvmvif->associated = vif->cfg.assoc;
if (changes & BSS_CHANGED_ASSOC) {
if (vif->cfg.assoc) {
/* clear statistics to get clean beacon counter */
iwl_mvm_request_statistics(mvm, true);
memset(&mvmvif->deflink.beacon_stats, 0,
sizeof(mvmvif->deflink.beacon_stats));
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART,
&mvm->status) &&
!vif->bss_conf.dtim_period) {
/* If we're not restarting and still haven't
* heard a beacon (dtim period unknown) then
* make sure we still have enough minimum time
* remaining in the time event, since the auth
* might actually have taken quite a while
* (especially for SAE) and so the remaining
* time could be small without us having heard
* a beacon yet.
*/
iwl_mvm_protect_assoc(mvm, vif, 0);
}
iwl_mvm_sf_update(mvm, vif, false);
iwl_mvm_power_vif_assoc(mvm, vif);
if (vif->p2p) {
iwl_mvm_update_smps(mvm, vif,
IWL_MVM_SMPS_REQ_PROT,
IEEE80211_SMPS_DYNAMIC);
}
} else if (mvmvif->deflink.ap_sta_id != IWL_MVM_INVALID_STA) {
iwl_mvm_mei_host_disassociated(mvm);
/* If update fails - SF might be running in associated
* mode while disassociated - which is forbidden.
*/
ret = iwl_mvm_sf_update(mvm, vif, false);
WARN_ONCE(ret &&
!test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
&mvm->status),
"Failed to update SF upon disassociation\n");
/* If we get an assert during the connection (after the
* station has been added, but before the vif is set
* to associated), mac80211 will re-add the station and
* then configure the vif. Since the vif is not
* associated, we would remove the station here and
* this would fail the recovery.
*/
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART,
&mvm->status)) {
/* first remove remaining keys */
iwl_mvm_sec_key_remove_ap(mvm, vif);
/* Remove AP station now that
* the MAC is unassoc
*/
ret = iwl_mvm_mld_rm_sta_id(mvm, vif,
mvmvif->deflink.ap_sta_id);
if (ret)
IWL_ERR(mvm,
"failed to remove AP station\n");
mvmvif->deflink.ap_sta_id = IWL_MVM_INVALID_STA;
}
}
iwl_mvm_bss_info_changed_station_assoc(mvm, vif, changes);
}
iwl_mvm_bss_info_changed_station_common(mvm, vif, changes);
}
static void
iwl_mvm_mld_bss_info_changed_ap_ibss(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
u64 changes)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
u32 link_changes = LINK_CONTEXT_MODIFY_PROTECT_FLAGS |
LINK_CONTEXT_MODIFY_QOS_PARAMS;
/* Changes will be applied when the AP/IBSS is started */
if (!mvmvif->ap_ibss_active)
return;
if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_HT |
BSS_CHANGED_BANDWIDTH | BSS_CHANGED_QOS) &&
iwl_mvm_link_changed(mvm, vif, link_changes, true))
IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
/* Need to send a new beacon template to the FW */
if (changes & BSS_CHANGED_BEACON &&
iwl_mvm_mac_ctxt_beacon_changed(mvm, vif))
IWL_WARN(mvm, "Failed updating beacon data\n");
if (changes & BSS_CHANGED_FTM_RESPONDER) {
int ret = iwl_mvm_ftm_start_responder(mvm, vif);
if (ret)
IWL_WARN(mvm, "Failed to enable FTM responder (%d)\n",
ret);
}
}
static void iwl_mvm_mld_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
u64 changes)
{
struct iwl_mvm_bss_info_changed_ops callbacks = {
.bss_info_changed_sta = iwl_mvm_mld_bss_info_changed_station,
.bss_info_changed_ap_ibss =
iwl_mvm_mld_bss_info_changed_ap_ibss,
};
iwl_mvm_bss_info_changed_common(hw, vif, bss_conf, &callbacks,
changes);
}
static int
iwl_mvm_mld_switch_vif_chanctx(struct ieee80211_hw *hw,
struct ieee80211_vif_chanctx_switch *vifs,
int n_vifs,
enum ieee80211_chanctx_switch_mode mode)
{
struct iwl_mvm_switch_vif_chanctx_ops ops = {
.__assign_vif_chanctx = __iwl_mvm_mld_assign_vif_chanctx,
.__unassign_vif_chanctx = __iwl_mvm_mld_unassign_vif_chanctx,
};
return iwl_mvm_switch_vif_chanctx_common(hw, vifs, n_vifs, mode, &ops);
}
static void iwl_mvm_mld_config_iface_filter(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
unsigned int filter_flags,
unsigned int changed_flags)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
/* We support only filter for probe requests */
if (!(changed_flags & FIF_PROBE_REQ))
return;
/* Supported only for p2p client interfaces */
if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc ||
!vif->p2p)
return;
mutex_lock(&mvm->mutex);
iwl_mvm_mld_mac_ctxt_changed(mvm, vif, false);
mutex_unlock(&mvm->mutex);
}
static int
iwl_mvm_mld_mac_conf_tx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
unsigned int link_id, u16 ac,
const struct ieee80211_tx_queue_params *params)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
mvmvif->deflink.queue_params[ac] = *params;
/* No need to update right away, we'll get BSS_CHANGED_QOS
* The exception is P2P_DEVICE interface which needs immediate update.
*/
if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
int ret;
mutex_lock(&mvm->mutex);
ret = iwl_mvm_link_changed(mvm, vif,
LINK_CONTEXT_MODIFY_QOS_PARAMS,
true);
mutex_unlock(&mvm->mutex);
return ret;
}
return 0;
}
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,
.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,
.join_ibss = iwl_mvm_mld_start_ap_ibss, .join_ibss = iwl_mvm_mld_start_ap_ibss,
.leave_ibss = iwl_mvm_mld_stop_ap_ibss, .leave_ibss = iwl_mvm_mld_stop_ap_ibss,
.sta_state = iwl_mvm_mld_mac_sta_state, .sta_state = iwl_mvm_mld_mac_sta_state,
.conf_tx = iwl_mvm_mld_mac_conf_tx,
.bss_info_changed = iwl_mvm_mld_bss_info_changed,
}; };
...@@ -536,6 +536,17 @@ int iwl_mvm_mld_rm_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ...@@ -536,6 +536,17 @@ int iwl_mvm_mld_rm_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return ret; return ret;
} }
int iwl_mvm_mld_rm_sta_id(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
u8 sta_id)
{
int ret = iwl_mvm_mld_rm_sta_from_fw(mvm, sta_id);
lockdep_assert_held(&mvm->mutex);
RCU_INIT_POINTER(mvm->fw_id_to_mac_id[sta_id], NULL);
return ret;
}
static void iwl_mvm_mld_sta_modify_disable_tx(struct iwl_mvm *mvm, static void iwl_mvm_mld_sta_modify_disable_tx(struct iwl_mvm *mvm,
struct ieee80211_sta *sta, struct ieee80211_sta *sta,
bool disable) bool disable)
......
...@@ -1789,6 +1789,48 @@ bool iwl_mvm_start_ap_ibss_common(struct ieee80211_hw *hw, ...@@ -1789,6 +1789,48 @@ bool iwl_mvm_start_ap_ibss_common(struct ieee80211_hw *hw,
void iwl_mvm_stop_ap_ibss_common(struct iwl_mvm *mvm, void iwl_mvm_stop_ap_ibss_common(struct iwl_mvm *mvm,
struct ieee80211_vif *vif); struct ieee80211_vif *vif);
/* BSS Info */
/**
* struct iwl_mvm_bss_info_changed_ops - callbacks for the bss_info_changed()
*
* Since the only difference between both MLD and
* non-MLD versions of bss_info_changed() is these function calls,
* each version will send its specific function calls to
* %iwl_mvm_bss_info_changed_common().
*
* @bss_info_changed_sta: pointer to the function that handles changes
* in bss_info in sta mode
* @bss_info_changed_ap_ibss: pointer to the function that handles changes
* in bss_info in ap and ibss modes
*/
struct iwl_mvm_bss_info_changed_ops {
void (*bss_info_changed_sta)(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
u64 changes);
void (*bss_info_changed_ap_ibss)(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
u64 changes);
};
void
iwl_mvm_bss_info_changed_common(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
struct iwl_mvm_bss_info_changed_ops *callbacks,
u64 changes);
void iwl_mvm_bss_info_changed_station_common(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
u64 changes);
void iwl_mvm_bss_info_changed_station_assoc(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
u64 changes);
/*Session Protection */
void iwl_mvm_protect_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
u32 duration_override);
/* Quota management */ /* Quota management */
static inline size_t iwl_mvm_quota_cmd_size(struct iwl_mvm *mvm) static inline size_t iwl_mvm_quota_cmd_size(struct iwl_mvm *mvm)
{ {
...@@ -2232,6 +2274,37 @@ static inline u8 iwl_mvm_phy_band_from_nl80211(enum nl80211_band band) ...@@ -2232,6 +2274,37 @@ static inline u8 iwl_mvm_phy_band_from_nl80211(enum nl80211_band band)
void iwl_mvm_channel_switch_disconnect_wk(struct work_struct *wk); void iwl_mvm_channel_switch_disconnect_wk(struct work_struct *wk);
/* Channel Context */ /* Channel Context */
/**
* struct iwl_mvm_switch_vif_chanctx_ops - callbacks for switch_vif_chanctx()
*
* Since the only difference between both MLD and
* non-MLD versions of switch_vif_chanctx() is these function calls,
* each version will send its specific function calls to
* %iwl_mvm_switch_vif_chanctx_common().
*
* @__assign_vif_chanctx: pointer to the function that assigns a chanctx to
* a given vif
* @__unassign_vif_chanctx: pointer to the function that unassigns a chanctx to
* a given vif
*/
struct iwl_mvm_switch_vif_chanctx_ops {
int (*__assign_vif_chanctx)(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_chanctx_conf *ctx,
bool switching_chanctx);
void (*__unassign_vif_chanctx)(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_chanctx_conf *ctx,
bool switching_chanctx);
};
int
iwl_mvm_switch_vif_chanctx_common(struct ieee80211_hw *hw,
struct ieee80211_vif_chanctx_switch *vifs,
int n_vifs,
enum ieee80211_chanctx_switch_mode mode,
struct iwl_mvm_switch_vif_chanctx_ops *ops);
bool __iwl_mvm_assign_vif_chanctx_common(struct iwl_mvm *mvm, bool __iwl_mvm_assign_vif_chanctx_common(struct iwl_mvm *mvm,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct ieee80211_chanctx_conf *ctx, struct ieee80211_chanctx_conf *ctx,
......
...@@ -631,6 +631,8 @@ int iwl_mvm_mld_update_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ...@@ -631,6 +631,8 @@ int iwl_mvm_mld_update_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_sta *sta); struct ieee80211_sta *sta);
int iwl_mvm_mld_rm_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, int iwl_mvm_mld_rm_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_sta *sta); struct ieee80211_sta *sta);
int iwl_mvm_mld_rm_sta_id(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
u8 sta_id);
/* Queues */ /* Queues */
void iwl_mvm_mld_modify_all_sta_disable_tx(struct iwl_mvm *mvm, void iwl_mvm_mld_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
......
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