2023-03-28 08:05:00

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 00/31] wifi: iwlwifi: updates intended for v6.4 2023-03-28

From: Gregory Greenman <[email protected]>

Hi,

Here's a new set of iwlwifi patches.

All the changes are related to adding MLO support.
This patch set will be followed by a few more that focus specifically on
adding MLO support.

Thanks,
Gregory

Avraham Stern (1):
wifi: iwlwifi: mvm: add set_hw_timestamp to mld ops

Gregory Greenman (14):
wifi: iwlwifi: mvm: vif preparation for MLO
wifi: iwlwifi: mvm: sta preparation for MLO
wifi: iwlwifi: mvm: adjust smart fifo configuration to MLO
wifi: iwlwifi: mvm: adjust mld_mac_ctxt_/beacon_changed() for MLO
wifi: iwlwifi: mvm: adjust some PS and PM methods to MLD
wifi: iwlwifi: mvm: adjust SMPS for MLO
wifi: iwlwifi: mvm: add link_conf parameter for add/remove/change link
wifi: iwlwifi: mvm: replace bss_info_changed() with vif_cfg/link_info_changed()
wifi: iwlwifi: mvm: adjust internal stations to MLO
wifi: iwlwifi: mvm: add fw link id allocation
wifi: iwlwifi: mvm: adjust to MLO assign/unassign/switch_vif_chanctx()
wifi: iwlwifi: mvm: update iwl_mvm_tx_reclaim() for MLO
wifi: iwlwifi: mvm: refactor iwl_mvm_mac_sta_state_common()
wifi: iwlwifi: mvm: adjust some cleanup functions to MLO

Johannes Berg (3):
wifi: iwlwifi: mvm: add link to firmware earlier
wifi: iwlwifi: mvm: don't check dtim_period in new API
wifi: iwlwifi: mvm: implement link change ops

Miri Korenblit (13):
wifi: iwlwifi: mvm: add an indication that the new MLD API is used
wifi: iwlwifi: mvm: add sta handling flows for MLD mode
wifi: iwlwifi: mvm: add some new MLD ops
wifi: iwlwifi: mvm: refactor iwl_mvm_roc()
wifi: iwlwifi: mvm: add cancel/remain_on_channel for MLD mode
wifi: iwlwifi: mvm: unite sta_modify_disable_tx flows
wifi: iwlwifi: mvm: add support for post_channel_switch in MLD mode
wifi: iwlwifi: mvm: add all missing ops to iwl_mvm_mld_ops
wifi: iwlwifi: mvm: fix "modify_mask" value in the link cmd.
wifi: iwlwifi: mvm: fix crash on queue removal for MLD API too
wifi: iwlwifi: mvm: modify link instead of removing it during csa
wifi: iwlwifi: mvm: always use the sta->addr as the peers addr
wifi: iwlwifi: mvm: align to the LINK cmd update in the FW

.../wireless/intel/iwlwifi/fw/api/mac-cfg.h | 26 +-
.../net/wireless/intel/iwlwifi/fw/api/tx.h | 10 +-
.../net/wireless/intel/iwlwifi/mvm/binding.c | 13 +-
drivers/net/wireless/intel/iwlwifi/mvm/coex.c | 35 +-
drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 39 +-
.../wireless/intel/iwlwifi/mvm/debugfs-vif.c | 14 +-
.../net/wireless/intel/iwlwifi/mvm/debugfs.c | 28 +-
.../intel/iwlwifi/mvm/ftm-initiator.c | 6 +-
.../intel/iwlwifi/mvm/ftm-responder.c | 2 +-
drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 2 +
drivers/net/wireless/intel/iwlwifi/mvm/link.c | 214 ++-
.../net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 102 +-
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 1263 +++++++++++------
.../net/wireless/intel/iwlwifi/mvm/mld-key.c | 14 +-
.../net/wireless/intel/iwlwifi/mvm/mld-mac.c | 51 +-
.../wireless/intel/iwlwifi/mvm/mld-mac80211.c | 895 ++++++++++--
.../net/wireless/intel/iwlwifi/mvm/mld-sta.c | 562 +++++++-
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 438 +++++-
drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 26 +-
.../net/wireless/intel/iwlwifi/mvm/phy-ctxt.c | 4 +-
.../net/wireless/intel/iwlwifi/mvm/power.c | 24 +-
.../net/wireless/intel/iwlwifi/mvm/quota.c | 11 +-
.../net/wireless/intel/iwlwifi/mvm/rs-fw.c | 34 +-
drivers/net/wireless/intel/iwlwifi/mvm/rs.c | 42 +-
drivers/net/wireless/intel/iwlwifi/mvm/rx.c | 30 +-
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 5 +-
drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 15 +-
drivers/net/wireless/intel/iwlwifi/mvm/sf.c | 38 +-
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 357 +++--
drivers/net/wireless/intel/iwlwifi/mvm/sta.h | 108 +-
drivers/net/wireless/intel/iwlwifi/mvm/tdls.c | 8 +-
.../wireless/intel/iwlwifi/mvm/time-event.c | 12 +-
drivers/net/wireless/intel/iwlwifi/mvm/tt.c | 4 +-
drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 53 +-
.../net/wireless/intel/iwlwifi/mvm/utils.c | 87 +-
35 files changed, 3417 insertions(+), 1155 deletions(-)

--
2.38.1


2023-03-28 08:05:01

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 01/31] wifi: iwlwifi: mvm: vif preparation for MLO

From: Gregory Greenman <[email protected]>

In MLO, some fields of iwl_mvm_vif should be defined in the
context of a link. Define a separate structure for these fields and
add a deflink object to hold it as part of iwl_mvm_vif. Non-MLO legacy
code will use only deflink object while MLO related code will use the
corresponding link from the link array.

It follows the strategy applied in mac80211 for introducing MLO
changes.

The below spatch takes care of updating all driver code to access
fields separated into MLD specific data structure via deflink (need
to convert all references to the fields listed in var to deflink.var
and also to take care of calls like iwl_mvm_vif_from_mac80211(vif)->field).

@iwl_mld_vif@
struct iwl_mvm_vif *v;
struct ieee80211_vif *vv;
identifier fn;
identifier var = {bssid, ap_sta_id, bcast_sta, mcast_sta,
beacon_stats, smps_requests, probe_resp_data,
he_ru_2mhz_block, cab_queue, phy_ctxt,
queue_params};
@@

(
v->
- var
+ deflink.var
|
fn(vv)->
- var
+ deflink.var
)

Signed-off-by: Gregory Greenman <[email protected]>
---
.../net/wireless/intel/iwlwifi/mvm/binding.c | 13 +-
drivers/net/wireless/intel/iwlwifi/mvm/coex.c | 29 ++--
drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 39 ++---
.../wireless/intel/iwlwifi/mvm/debugfs-vif.c | 14 +-
.../intel/iwlwifi/mvm/ftm-initiator.c | 6 +-
.../intel/iwlwifi/mvm/ftm-responder.c | 2 +-
drivers/net/wireless/intel/iwlwifi/mvm/link.c | 14 +-
.../net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 28 ++--
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 138 ++++++++++--------
.../net/wireless/intel/iwlwifi/mvm/mld-key.c | 12 +-
.../wireless/intel/iwlwifi/mvm/mld-mac80211.c | 19 +--
.../net/wireless/intel/iwlwifi/mvm/mld-sta.c | 21 +--
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 121 ++++++++-------
.../net/wireless/intel/iwlwifi/mvm/phy-ctxt.c | 4 +-
.../net/wireless/intel/iwlwifi/mvm/power.c | 22 +--
.../net/wireless/intel/iwlwifi/mvm/quota.c | 11 +-
drivers/net/wireless/intel/iwlwifi/mvm/rx.c | 26 ++--
drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 15 +-
drivers/net/wireless/intel/iwlwifi/mvm/sf.c | 6 +-
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 78 +++++-----
.../wireless/intel/iwlwifi/mvm/time-event.c | 6 +-
drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 8 +-
.../net/wireless/intel/iwlwifi/mvm/utils.c | 31 ++--
23 files changed, 355 insertions(+), 308 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/binding.c b/drivers/net/wireless/intel/iwlwifi/mvm/binding.c
index 0aac306304cb..ef50ccabcc73 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/binding.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/binding.c
@@ -2,6 +2,7 @@
/*
* Copyright (C) 2012-2014, 2020 Intel Corporation
* Copyright (C) 2016 Intel Deutschland GmbH
+ * Copyright (C) 2022 Intel Corporation
*/
#include <net/mac80211.h>
#include "fw-api.h"
@@ -75,7 +76,7 @@ static void iwl_mvm_iface_iterator(void *_data, u8 *mac,
if (vif == data->ignore_vif)
return;

- if (mvmvif->phy_ctxt != data->phyctxt)
+ if (mvmvif->deflink.phy_ctxt != data->phyctxt)
return;

if (WARN_ON_ONCE(data->idx >= MAX_MACS_IN_BINDING))
@@ -132,7 +133,7 @@ int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);

- if (WARN_ON_ONCE(!mvmvif->phy_ctxt))
+ if (WARN_ON_ONCE(!mvmvif->deflink.phy_ctxt))
return -EINVAL;

/*
@@ -142,7 +143,8 @@ int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
if (iwl_mvm_sf_update(mvm, vif, false))
return -EINVAL;

- return iwl_mvm_binding_update(mvm, vif, mvmvif->phy_ctxt, true);
+ return iwl_mvm_binding_update(mvm, vif, mvmvif->deflink.phy_ctxt,
+ true);
}

int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
@@ -150,10 +152,11 @@ int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ret;

- if (WARN_ON_ONCE(!mvmvif->phy_ctxt))
+ if (WARN_ON_ONCE(!mvmvif->deflink.phy_ctxt))
return -EINVAL;

- ret = iwl_mvm_binding_update(mvm, vif, mvmvif->phy_ctxt, false);
+ ret = iwl_mvm_binding_update(mvm, vif, mvmvif->deflink.phy_ctxt,
+ false);

if (!ret)
if (iwl_mvm_sf_update(mvm, vif, true))
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
index ee3c8a786199..73ef1da3ccac 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
@@ -292,7 +292,8 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
/* ... relax constraints and disable rssi events */
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
smps_mode);
- iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
+ iwl_mvm_bt_coex_reduced_txp(mvm,
+ mvmvif->deflink.ap_sta_id,
false);
iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
}
@@ -314,8 +315,8 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
if (!vif->cfg.assoc)
smps_mode = IEEE80211_SMPS_AUTOMATIC;

- if (mvmvif->phy_ctxt &&
- (mvm->last_bt_notif.rrc_status & BIT(mvmvif->phy_ctxt->id)))
+ if (mvmvif->deflink.phy_ctxt &&
+ (mvm->last_bt_notif.rrc_status & BIT(mvmvif->deflink.phy_ctxt->id)))
smps_mode = IEEE80211_SMPS_AUTOMATIC;

IWL_DEBUG_COEX(data->mvm,
@@ -384,7 +385,8 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT ||
mvm->cfg->bt_shared_single_ant || !vif->cfg.assoc ||
le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF) {
- iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false);
+ iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->deflink.ap_sta_id,
+ false);
iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
return;
}
@@ -396,10 +398,12 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
if (!ave_rssi)
ave_rssi = -100;
if (ave_rssi > -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH) {
- if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true))
+ if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->deflink.ap_sta_id,
+ true))
IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
} else if (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) {
- if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false))
+ if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->deflink.ap_sta_id,
+ false))
IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
}

@@ -521,7 +525,7 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
* Rssi update while not associated - can happen since the statistics
* are handled asynchronously
*/
- if (mvmvif->ap_sta_id == IWL_MVM_INVALID_STA)
+ if (mvmvif->deflink.ap_sta_id == IWL_MVM_INVALID_STA)
return;

/* No BT - reports should be disabled */
@@ -537,10 +541,13 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
*/
if (rssi_event == RSSI_EVENT_LOW || mvm->cfg->bt_shared_single_ant ||
iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT)
- ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
+ ret = iwl_mvm_bt_coex_reduced_txp(mvm,
+ mvmvif->deflink.ap_sta_id,
false);
else
- ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true);
+ ret = iwl_mvm_bt_coex_reduced_txp(mvm,
+ mvmvif->deflink.ap_sta_id,
+ true);

if (ret)
IWL_ERR(mvm, "couldn't send BT_CONFIG HCMD upon RSSI event\n");
@@ -554,7 +561,7 @@ u16 iwl_mvm_coex_agg_time_limit(struct iwl_mvm *mvm,
{
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
- struct iwl_mvm_phy_ctxt *phy_ctxt = mvmvif->phy_ctxt;
+ struct iwl_mvm_phy_ctxt *phy_ctxt = mvmvif->deflink.phy_ctxt;
enum iwl_bt_coex_lut_type lut_type;

if (mvm->last_bt_notif.ttc_status & BIT(phy_ctxt->id))
@@ -578,7 +585,7 @@ bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm,
{
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
- struct iwl_mvm_phy_ctxt *phy_ctxt = mvmvif->phy_ctxt;
+ struct iwl_mvm_phy_ctxt *phy_ctxt = mvmvif->deflink.phy_ctxt;
enum iwl_bt_coex_lut_type lut_type;

if (mvm->last_bt_notif.ttc_status & BIT(phy_ctxt->id))
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
index c5ad34b063df..40adf789c8fc 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
@@ -470,7 +470,7 @@ static int iwl_mvm_wowlan_config_rsc_tsc(struct iwl_mvm *mvm,
for (i = 0; i < ARRAY_SIZE(data.rsc->mcast_key_id_map); i++)
data.rsc->mcast_key_id_map[i] =
IWL_MCAST_KEY_MAP_INVALID;
- data.rsc->sta_id = cpu_to_le32(mvmvif->ap_sta_id);
+ data.rsc->sta_id = cpu_to_le32(mvmvif->deflink.ap_sta_id);

ieee80211_iter_keys(mvm->hw, vif,
iwl_mvm_wowlan_get_rsc_v5_data,
@@ -493,7 +493,8 @@ static int iwl_mvm_wowlan_config_rsc_tsc(struct iwl_mvm *mvm,

if (ver == 4) {
size = sizeof(*data.rsc_tsc);
- data.rsc_tsc->sta_id = cpu_to_le32(mvmvif->ap_sta_id);
+ data.rsc_tsc->sta_id =
+ cpu_to_le32(mvmvif->deflink.ap_sta_id);
} else {
/* ver == 2 || ver == IWL_FW_CMD_VER_UNKNOWN */
size = sizeof(data.rsc_tsc->params);
@@ -691,7 +692,7 @@ static int iwl_mvm_send_patterns(struct iwl_mvm *mvm,

pattern_cmd->n_patterns = wowlan->n_patterns;
if (ver >= 3)
- pattern_cmd->sta_id = mvmvif->ap_sta_id;
+ pattern_cmd->sta_id = mvmvif->deflink.ap_sta_id;

for (i = 0; i < wowlan->n_patterns; i++) {
int mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8);
@@ -732,7 +733,7 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return -EINVAL;

/* add back the PHY */
- if (WARN_ON(!mvmvif->phy_ctxt))
+ if (WARN_ON(!mvmvif->deflink.phy_ctxt))
return -EINVAL;

rcu_read_lock();
@@ -746,7 +747,7 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
chains_dynamic = ctx->rx_chains_dynamic;
rcu_read_unlock();

- ret = iwl_mvm_phy_ctxt_add(mvm, mvmvif->phy_ctxt, &chandef,
+ ret = iwl_mvm_phy_ctxt_add(mvm, mvmvif->deflink.phy_ctxt, &chandef,
chains_static, chains_dynamic);
if (ret)
return ret;
@@ -763,12 +764,12 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,

/* add back binding - XXX refactor? */
binding_cmd.id_and_color =
- cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->phy_ctxt->id,
- mvmvif->phy_ctxt->color));
+ cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->deflink.phy_ctxt->id,
+ mvmvif->deflink.phy_ctxt->color));
binding_cmd.action = cpu_to_le32(FW_CTXT_ACTION_ADD);
binding_cmd.phy =
- cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->phy_ctxt->id,
- mvmvif->phy_ctxt->color));
+ cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->deflink.phy_ctxt->id,
+ mvmvif->deflink.phy_ctxt->color));
binding_cmd.macs[0] = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
mvmvif->color));
for (i = 1; i < MAX_MACS_IN_BINDING; i++)
@@ -791,7 +792,8 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
ret = iwl_mvm_sta_send_to_fw(mvm, ap_sta, false, 0);
if (ret)
return ret;
- rcu_assign_pointer(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id], ap_sta);
+ rcu_assign_pointer(mvm->fw_id_to_mac_id[mvmvif->deflink.ap_sta_id],
+ ap_sta);

ret = iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
if (ret)
@@ -800,8 +802,8 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
/* and some quota */
quota = iwl_mvm_quota_cmd_get_quota(mvm, &quota_cmd, 0);
quota->id_and_color =
- cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->phy_ctxt->id,
- mvmvif->phy_ctxt->color));
+ cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->deflink.phy_ctxt->id,
+ mvmvif->deflink.phy_ctxt->color));
quota->quota = cpu_to_le32(IWL_MVM_MAX_QUOTA);
quota->max_duration = cpu_to_le32(IWL_MVM_MAX_QUOTA);

@@ -1027,7 +1029,7 @@ static int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
if (ver == 2) {
size = sizeof(tkip_data.tkip);
tkip_data.tkip.sta_id =
- cpu_to_le32(mvmvif->ap_sta_id);
+ cpu_to_le32(mvmvif->deflink.ap_sta_id);
} else if (ver == 1 || ver == IWL_FW_CMD_VER_UNKNOWN) {
size = sizeof(struct iwl_wowlan_tkip_params_cmd_ver_1);
} else {
@@ -1076,7 +1078,7 @@ static int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
kek_kck_cmd.kek_len = cpu_to_le16(mvmvif->rekey_data.kek_len);
kek_kck_cmd.replay_ctr = mvmvif->rekey_data.replay_ctr;
kek_kck_cmd.akm = cpu_to_le32(mvmvif->rekey_data.akm);
- kek_kck_cmd.sta_id = cpu_to_le32(mvmvif->ap_sta_id);
+ kek_kck_cmd.sta_id = cpu_to_le32(mvmvif->deflink.ap_sta_id);

if (cmd_ver == 4) {
cmd_size = sizeof(struct iwl_wowlan_kek_kck_material_cmd_v4);
@@ -1269,7 +1271,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,

mvmvif = iwl_mvm_vif_from_mac80211(vif);

- if (mvmvif->ap_sta_id == IWL_MVM_INVALID_STA) {
+ if (mvmvif->deflink.ap_sta_id == IWL_MVM_INVALID_STA) {
/* if we're not associated, this must be netdetect */
if (!wowlan->nd_config) {
ret = 1;
@@ -1285,10 +1287,10 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
} else {
struct iwl_wowlan_config_cmd wowlan_config_cmd = {};

- wowlan_config_cmd.sta_id = mvmvif->ap_sta_id;
+ wowlan_config_cmd.sta_id = mvmvif->deflink.ap_sta_id;

ap_sta = rcu_dereference_protected(
- mvm->fw_id_to_mac_id[mvmvif->ap_sta_id],
+ mvm->fw_id_to_mac_id[mvmvif->deflink.ap_sta_id],
lockdep_is_held(&mvm->mutex));
if (IS_ERR_OR_NULL(ap_sta)) {
ret = -EINVAL;
@@ -2575,7 +2577,8 @@ iwl_mvm_choose_query_wakeup_reasons(struct iwl_mvm *mvm,
/* if FW uses status notification, status shouldn't be NULL here */
if (!d3_data->status) {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- u8 sta_id = mvm->net_detect ? IWL_MVM_INVALID_STA : mvmvif->ap_sta_id;
+ u8 sta_id = mvm->net_detect ? IWL_MVM_INVALID_STA :
+ mvmvif->deflink.ap_sta_id;

d3_data->status = iwl_mvm_send_wowlan_get_status(mvm, sta_id);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
index 3779ac040ba0..3613b1fdc5d9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
@@ -179,7 +179,7 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file,

mutex_lock(&mvm->mutex);

- ap_sta_id = mvmvif->ap_sta_id;
+ ap_sta_id = mvmvif->deflink.ap_sta_id;

switch (ieee80211_vif_type_p2p(vif)) {
case NL80211_IFTYPE_ADHOC:
@@ -211,14 +211,14 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
pos += scnprintf(buf+pos, bufsz-pos, "Load: %d\n",
mvm->tcm.result.load[mvmvif->id]);
pos += scnprintf(buf+pos, bufsz-pos, "QoS:\n");
- for (i = 0; i < ARRAY_SIZE(mvmvif->queue_params); i++)
+ for (i = 0; i < ARRAY_SIZE(mvmvif->deflink.queue_params); i++)
pos += scnprintf(buf+pos, bufsz-pos,
"\t%d: txop:%d - cw_min:%d - cw_max = %d - aifs = %d upasd = %d\n",
- i, mvmvif->queue_params[i].txop,
- mvmvif->queue_params[i].cw_min,
- mvmvif->queue_params[i].cw_max,
- mvmvif->queue_params[i].aifs,
- mvmvif->queue_params[i].uapsd);
+ i, mvmvif->deflink.queue_params[i].txop,
+ mvmvif->deflink.queue_params[i].cw_min,
+ mvmvif->deflink.queue_params[i].cw_max,
+ mvmvif->deflink.queue_params[i].aifs,
+ mvmvif->deflink.queue_params[i].uapsd);

if (vif->type == NL80211_IFTYPE_STATION &&
ap_sta_id != IWL_MVM_INVALID_STA) {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
index 05f3136b1c43..379da4bec5dd 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
@@ -73,7 +73,7 @@ int iwl_mvm_ftm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_sta *sta;

rcu_read_lock();
- sta = rcu_dereference(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id]);
+ sta = rcu_dereference(mvm->fw_id_to_mac_id[mvmvif->deflink.ap_sta_id]);
if (!IS_ERR_OR_NULL(sta) && sta->mfp)
expected_tk_len = 0;
rcu_read_unlock();
@@ -510,13 +510,13 @@ iwl_mvm_ftm_put_target(struct iwl_mvm *mvm, struct ieee80211_vif *vif,

rcu_read_lock();

- sta = rcu_dereference(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id]);
+ sta = rcu_dereference(mvm->fw_id_to_mac_id[mvmvif->deflink.ap_sta_id]);
if (sta->mfp && (peer->ftm.trigger_based || peer->ftm.non_trigger_based))
FTM_PUT_FLAG(PMF);

rcu_read_unlock();

- target->sta_id = mvmvif->ap_sta_id;
+ target->sta_id = mvmvif->deflink.ap_sta_id;
} else {
target->sta_id = IWL_MVM_INVALID_STA;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
index e862d1b43f21..c37d793d6a4a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
@@ -119,7 +119,7 @@ iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm,
cpu_to_le32(IWL_TOF_RESPONDER_CMD_VALID_CHAN_INFO |
IWL_TOF_RESPONDER_CMD_VALID_BSSID |
IWL_TOF_RESPONDER_CMD_VALID_STA_ID),
- .sta_id = mvmvif->bcast_sta.sta_id,
+ .sta_id = mvmvif->deflink.bcast_sta.sta_id,
};
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 6);
int err;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/link.c b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
index 2688cb49c951..21e45f89c5f9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/link.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
@@ -25,7 +25,7 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_link_config_cmd cmd = {};

- if (WARN_ON_ONCE(!mvmvif->phy_ctxt))
+ if (WARN_ON_ONCE(!mvmvif->deflink.phy_ctxt))
return -EINVAL;

/* Update SF - Disable if needed. if this fails, SF might still be on
@@ -34,9 +34,9 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
if (iwl_mvm_sf_update(mvm, vif, false))
return -EINVAL;

- cmd.link_id = cpu_to_le32(mvmvif->phy_ctxt->id);
+ cmd.link_id = cpu_to_le32(mvmvif->deflink.phy_ctxt->id);
cmd.mac_id = cpu_to_le32(mvmvif->id);
- cmd.phy_id = cpu_to_le32(mvmvif->phy_ctxt->id);
+ cmd.phy_id = cpu_to_le32(mvmvif->deflink.phy_ctxt->id);

memcpy(cmd.local_link_addr, vif->addr, ETH_ALEN);

@@ -47,7 +47,7 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
u32 changes, bool active)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm_phy_ctxt *phyctxt = mvmvif->phy_ctxt;
+ struct iwl_mvm_phy_ctxt *phyctxt = mvmvif->deflink.phy_ctxt;
struct iwl_link_config_cmd cmd = {};
u32 ht_flag, flags = 0, flags_mask = 0;

@@ -136,7 +136,7 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
cmd.frame_time_rts_th = cpu_to_le16(vif->bss_conf.frame_time_rts_th);

/* Block 26-tone RU OFDMA transmissions */
- if (mvmvif->he_ru_2mhz_block) {
+ if (mvmvif->deflink.he_ru_2mhz_block) {
flags |= LINK_FLG_RU_2MHZ_BLOCK;
flags_mask |= LINK_FLG_RU_2MHZ_BLOCK;
}
@@ -161,10 +161,10 @@ int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
struct iwl_link_config_cmd cmd = {};
int ret;

- if (WARN_ON_ONCE(!mvmvif->phy_ctxt))
+ if (WARN_ON_ONCE(!mvmvif->deflink.phy_ctxt))
return -EINVAL;

- cmd.link_id = cpu_to_le32(mvmvif->phy_ctxt->id);
+ cmd.link_id = cpu_to_le32(mvmvif->deflink.phy_ctxt->id);
ret = iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_REMOVE);

if (!ret)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index 4d7ad91c53d4..10dc1fdbdeb3 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -293,15 +293,15 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
* For TVQM this will be overwritten later with the FW assigned
* queue value (when queue is enabled).
*/
- mvmvif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE;
+ mvmvif->deflink.cab_queue = IWL_MVM_DQA_GCAST_QUEUE;
}

- mvmvif->bcast_sta.sta_id = IWL_MVM_INVALID_STA;
- mvmvif->mcast_sta.sta_id = IWL_MVM_INVALID_STA;
- mvmvif->ap_sta_id = IWL_MVM_INVALID_STA;
+ mvmvif->deflink.bcast_sta.sta_id = IWL_MVM_INVALID_STA;
+ mvmvif->deflink.mcast_sta.sta_id = IWL_MVM_INVALID_STA;
+ mvmvif->deflink.ap_sta_id = IWL_MVM_INVALID_STA;

for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++)
- mvmvif->smps_requests[i] = IEEE80211_SMPS_AUTOMATIC;
+ mvmvif->deflink.smps_requests[i] = IEEE80211_SMPS_AUTOMATIC;

return 0;

@@ -469,12 +469,12 @@ void iwl_mvm_set_fw_qos_params(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
u8 ucode_ac = iwl_mvm_mac80211_ac_to_ucode_ac(i);

ac[ucode_ac].cw_min =
- cpu_to_le16(mvmvif->queue_params[i].cw_min);
+ cpu_to_le16(mvmvif->deflink.queue_params[i].cw_min);
ac[ucode_ac].cw_max =
- cpu_to_le16(mvmvif->queue_params[i].cw_max);
+ cpu_to_le16(mvmvif->deflink.queue_params[i].cw_max);
ac[ucode_ac].edca_txop =
- cpu_to_le16(mvmvif->queue_params[i].txop * 32);
- ac[ucode_ac].aifsn = mvmvif->queue_params[i].aifs;
+ cpu_to_le16(mvmvif->deflink.queue_params[i].txop * 32);
+ ac[ucode_ac].aifsn = mvmvif->deflink.queue_params[i].aifs;
ac[ucode_ac].fifos_mask = BIT(txf);
}

@@ -944,7 +944,7 @@ static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm,

/* Set up TX command fields */
tx->len = cpu_to_le16((u16)beacon->len);
- tx->sta_id = mvmvif->bcast_sta.sta_id;
+ tx->sta_id = mvmvif->deflink.bcast_sta.sta_id;
tx->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
tx_flags = TX_CMD_FLG_SEQ_CTL | TX_CMD_FLG_TSF;
tx_flags |=
@@ -1214,7 +1214,7 @@ static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm,

if (!fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_STA_TYPE))
- ctxt_ap->mcast_qid = cpu_to_le32(mvmvif->cab_queue);
+ ctxt_ap->mcast_qid = cpu_to_le32(mvmvif->deflink.cab_queue);

/*
* Only set the beacon time when the MAC is being added, when we
@@ -1663,9 +1663,9 @@ void iwl_mvm_probe_resp_data_notif(struct iwl_mvm *mvm,
sizeof(struct ieee80211_p2p_noa_desc) + 2)
new_data->noa_len -= sizeof(struct ieee80211_p2p_noa_desc);

- old_data = rcu_dereference_protected(mvmvif->probe_resp_data,
- lockdep_is_held(&mvmvif->mvm->mutex));
- rcu_assign_pointer(mvmvif->probe_resp_data, new_data);
+ old_data = rcu_dereference_protected(mvmvif->deflink.probe_resp_data,
+ lockdep_is_held(&mvmvif->mvm->mutex));
+ rcu_assign_pointer(mvmvif->deflink.probe_resp_data, new_data);

if (old_data)
kfree_rcu(old_data, rcu_head);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 33582f4eea91..163515db6828 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -736,7 +736,7 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
!offchannel) {
struct iwl_mvm_vif *mvmvif =
iwl_mvm_vif_from_mac80211(info->control.vif);
- u8 ap_sta_id = READ_ONCE(mvmvif->ap_sta_id);
+ u8 ap_sta_id = READ_ONCE(mvmvif->deflink.ap_sta_id);

if (ap_sta_id < mvm->fw->ucode_capa.num_stations) {
/* mac80211 holds rcu read lock */
@@ -921,7 +921,7 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,

switch (action) {
case IEEE80211_AMPDU_RX_START:
- if (iwl_mvm_vif_from_mac80211(vif)->ap_sta_id ==
+ if (iwl_mvm_vif_from_mac80211(vif)->deflink.ap_sta_id ==
iwl_mvm_sta_from_mac80211(sta)->sta_id) {
struct iwl_mvm_vif *mvmvif;
u16 macid = iwl_mvm_vif_from_mac80211(vif)->id;
@@ -987,15 +987,16 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);

mvmvif->uploaded = false;
- mvmvif->ap_sta_id = IWL_MVM_INVALID_STA;
+ mvmvif->deflink.ap_sta_id = IWL_MVM_INVALID_STA;

spin_lock_bh(&mvm->time_event_lock);
iwl_mvm_te_clear_data(mvm, &mvmvif->time_event_data);
spin_unlock_bh(&mvm->time_event_lock);

- mvmvif->phy_ctxt = NULL;
+ mvmvif->deflink.phy_ctxt = NULL;
memset(&mvmvif->bf_data, 0, sizeof(mvmvif->bf_data));
- memset(&mvmvif->probe_resp_data, 0, sizeof(mvmvif->probe_resp_data));
+ memset(&mvmvif->deflink.probe_resp_data, 0,
+ sizeof(mvmvif->deflink.probe_resp_data));
}

static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
@@ -1330,7 +1331,7 @@ static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,

mvmvif->csa_bcn_pending = false;
mvmsta = iwl_mvm_sta_from_staid_protected(mvm,
- mvmvif->ap_sta_id);
+ mvmvif->deflink.ap_sta_id);

if (WARN_ON(!mvmsta)) {
ret = -EIO;
@@ -1447,7 +1448,10 @@ bool iwl_mvm_mac_add_interface_common(struct iwl_mvm *mvm,
lockdep_assert_held(&mvm->mutex);

mvmvif->mvm = mvm;
- RCU_INIT_POINTER(mvmvif->probe_resp_data, NULL);
+ RCU_INIT_POINTER(mvmvif->deflink.probe_resp_data, NULL);
+
+ /* the first link always points to the default one */
+ mvmvif->link[0] = &mvmvif->deflink;

/*
* Not much to do here. The stack will not allow interface
@@ -1457,8 +1461,8 @@ bool iwl_mvm_mac_add_interface_common(struct iwl_mvm *mvm,

/* make sure that beacon statistics don't go backwards with FW reset */
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
- mvmvif->beacon_stats.accu_num_beacons +=
- mvmvif->beacon_stats.num_beacons;
+ mvmvif->deflink.beacon_stats.accu_num_beacons +=
+ mvmvif->deflink.beacon_stats.num_beacons;

/* Allocate resources for the MAC context, and add it to the fw */
*ret = iwl_mvm_mac_ctxt_init(mvm, vif);
@@ -1485,6 +1489,7 @@ bool iwl_mvm_mac_add_interface_common(struct iwl_mvm *mvm,
}

mvmvif->features |= hw->netdev_features;
+
return false;
}

@@ -1506,7 +1511,8 @@ static int iwl_mvm_alloc_bcast_mcast_sta(struct iwl_mvm *mvm,
* Only queue for this station is the mcast queue,
* which shouldn't be in TFD mask anyway
*/
- return iwl_mvm_allocate_int_sta(mvm, &mvmvif->mcast_sta, 0, vif->type,
+ return iwl_mvm_allocate_int_sta(mvm, &mvmvif->deflink.mcast_sta, 0,
+ vif->type,
IWL_STA_MULTICAST);
}

@@ -1550,13 +1556,13 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
*/
if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {

- mvmvif->phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm);
- if (!mvmvif->phy_ctxt) {
+ mvmvif->deflink.phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm);
+ if (!mvmvif->deflink.phy_ctxt) {
ret = -ENOSPC;
goto out_free_bf;
}

- iwl_mvm_phy_ctxt_ref(mvm, mvmvif->phy_ctxt);
+ iwl_mvm_phy_ctxt_ref(mvm, mvmvif->deflink.phy_ctxt);
ret = iwl_mvm_binding_add_vif(mvm, vif);
if (ret)
goto out_unref_phy;
@@ -1600,7 +1606,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
out_unbind:
iwl_mvm_binding_remove_vif(mvm, vif);
out_unref_phy:
- iwl_mvm_phy_ctxt_unref(mvm, mvmvif->phy_ctxt);
+ iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
out_free_bf:
if (mvm->bf_allowed_vif == mvmvif) {
mvm->bf_allowed_vif = NULL;
@@ -1608,7 +1614,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
IEEE80211_VIF_SUPPORTS_CQM_RSSI);
}
out_remove_mac:
- mvmvif->phy_ctxt = NULL;
+ mvmvif->deflink.phy_ctxt = NULL;
iwl_mvm_mac_ctxt_remove(mvm, vif);
out_unlock:
mutex_unlock(&mvm->mutex);
@@ -1653,9 +1659,9 @@ bool iwl_mvm_mac_remove_interface_common(struct ieee80211_hw *hw,
mvm->csme_vif = NULL;
}

- probe_data = rcu_dereference_protected(mvmvif->probe_resp_data,
+ probe_data = rcu_dereference_protected(mvmvif->deflink.probe_resp_data,
lockdep_is_held(&mvm->mutex));
- RCU_INIT_POINTER(mvmvif->probe_resp_data, NULL);
+ RCU_INIT_POINTER(mvmvif->deflink.probe_resp_data, NULL);
if (probe_data)
kfree_rcu(probe_data, rcu_head);

@@ -1702,8 +1708,8 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
mvm->p2p_device_vif = NULL;
iwl_mvm_rm_p2p_bcast_sta(mvm, vif);
iwl_mvm_binding_remove_vif(mvm, vif);
- iwl_mvm_phy_ctxt_unref(mvm, mvmvif->phy_ctxt);
- mvmvif->phy_ctxt = NULL;
+ iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
+ mvmvif->deflink.phy_ctxt = NULL;
}

iwl_mvm_mac_ctxt_remove(mvm, vif);
@@ -1716,7 +1722,7 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
out:
if (vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_ADHOC) {
- iwl_mvm_dealloc_int_sta(mvm, &mvmvif->mcast_sta);
+ iwl_mvm_dealloc_int_sta(mvm, &mvmvif->deflink.mcast_sta);
iwl_mvm_dealloc_bcast_sta(mvm, vif);
}

@@ -2207,10 +2213,10 @@ bool iwl_mvm_set_fw_mu_edca_params(struct iwl_mvm *mvm,

for (i = 0; i < IEEE80211_NUM_ACS; i++) {
struct ieee80211_he_mu_edca_param_ac_rec *mu_edca =
- &mvmvif->queue_params[i].mu_edca_param_rec;
+ &mvmvif->deflink.queue_params[i].mu_edca_param_rec;
u8 ac = iwl_mvm_mac80211_ac_to_ucode_ac(i);

- if (!mvmvif->queue_params[i].mu_edca) {
+ if (!mvmvif->deflink.queue_params[i].mu_edca) {
mu_edca_enabled = false;
break;
}
@@ -2335,7 +2341,7 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,
flags = 0;

/* Block 26-tone RU OFDMA transmissions */
- if (mvmvif->he_ru_2mhz_block)
+ if (mvmvif->deflink.he_ru_2mhz_block)
flags |= STA_CTXT_HE_RU_2MHZ_BLOCK;

/* HTC flags */
@@ -2474,7 +2480,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
!iwlwifi_mod_params.disable_11ax) ||
(vif->bss_conf.eht_support &&
!iwlwifi_mod_params.disable_11be))
- iwl_mvm_cfg_he_sta(mvm, vif, mvmvif->ap_sta_id);
+ iwl_mvm_cfg_he_sta(mvm, vif, mvmvif->deflink.ap_sta_id);

iwl_mvm_mac_ctxt_recalc_tsf_id(mvm, vif);
}
@@ -2486,7 +2492,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
!iwlwifi_mod_params.disable_11ax) ||
(vif->bss_conf.eht_support &&
!iwlwifi_mod_params.disable_11be)))
- iwl_mvm_cfg_he_sta(mvm, vif, mvmvif->ap_sta_id);
+ iwl_mvm_cfg_he_sta(mvm, vif, mvmvif->deflink.ap_sta_id);

/*
* If we're not associated yet, take the (new) BSSID before associating
@@ -2495,22 +2501,22 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
* branch for disassociation below.
*/
if (changes & BSS_CHANGED_BSSID && !mvmvif->associated)
- memcpy(mvmvif->bssid, bss_conf->bssid, ETH_ALEN);
+ memcpy(mvmvif->deflink.bssid, bss_conf->bssid, ETH_ALEN);

- ret = iwl_mvm_mac_ctxt_changed(mvm, vif, false, mvmvif->bssid);
+ ret = iwl_mvm_mac_ctxt_changed(mvm, vif, false, mvmvif->deflink.bssid);
if (ret)
IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);

/* after sending it once, adopt mac80211 data */
- memcpy(mvmvif->bssid, bss_conf->bssid, ETH_ALEN);
+ 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->beacon_stats, 0,
- sizeof(mvmvif->beacon_stats));
+ memset(&mvmvif->deflink.beacon_stats, 0,
+ sizeof(mvmvif->deflink.beacon_stats));

/* add quota for this interface */
ret = iwl_mvm_update_quotas(mvm, true, NULL);
@@ -2567,7 +2573,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
IWL_MVM_SMPS_REQ_PROT,
IEEE80211_SMPS_DYNAMIC);
}
- } else if (mvmvif->ap_sta_id != IWL_MVM_INVALID_STA) {
+ } 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
@@ -2597,12 +2603,12 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
* the MAC is unassoc
*/
ret = iwl_mvm_rm_sta_id(mvm, vif,
- mvmvif->ap_sta_id);
+ mvmvif->deflink.ap_sta_id);
if (ret)
IWL_ERR(mvm,
"failed to remove AP station\n");

- mvmvif->ap_sta_id = IWL_MVM_INVALID_STA;
+ mvmvif->deflink.ap_sta_id = IWL_MVM_INVALID_STA;
}

/* remove quota for this interface */
@@ -3305,7 +3311,7 @@ static void iwl_mvm_check_he_obss_narrow_bw_ru(struct ieee80211_hw *hw,
};

if (!(vif->bss_conf.chandef.chan->flags & IEEE80211_CHAN_RADAR)) {
- mvmvif->he_ru_2mhz_block = false;
+ mvmvif->deflink.he_ru_2mhz_block = false;
return;
}

@@ -3317,7 +3323,7 @@ static void iwl_mvm_check_he_obss_narrow_bw_ru(struct ieee80211_hw *hw,
* If there is at least one AP on radar channel that cannot
* tolerate 26-tone RU UL OFDMA transmissions using HE TB PPDU.
*/
- mvmvif->he_ru_2mhz_block = !iter_data.tolerated;
+ mvmvif->deflink.he_ru_2mhz_block = !iter_data.tolerated;
}

static void iwl_mvm_reset_cca_40mhz_workaround(struct iwl_mvm *mvm,
@@ -3434,7 +3440,7 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
sta->addr, old_state, new_state);

/* this would be a mac80211 bug ... but don't crash */
- if (WARN_ON_ONCE(!mvmvif->phy_ctxt))
+ if (WARN_ON_ONCE(!mvmvif->deflink.phy_ctxt))
return test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status) ? 0 : -EINVAL;

/*
@@ -3532,14 +3538,15 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
} else if (vif->type == NL80211_IFTYPE_STATION) {
vif->bss_conf.he_support = sta->deflink.he_cap.has_he;

- mvmvif->he_ru_2mhz_block = false;
+ mvmvif->deflink.he_ru_2mhz_block = false;
if (sta->deflink.he_cap.has_he)
iwl_mvm_check_he_obss_narrow_bw_ru(hw, vif);

iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
}

- iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band,
+ iwl_mvm_rs_rate_init(mvm, sta,
+ mvmvif->deflink.phy_ctxt->channel->band,
false);
ret = iwl_mvm_update_sta(mvm, vif, sta);
} else if (old_state == IEEE80211_STA_ASSOC &&
@@ -3563,14 +3570,16 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
iwl_mvm_mei_host_associated(mvm, vif, mvm_sta);
}

- iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band,
+ iwl_mvm_rs_rate_init(mvm, sta,
+ mvmvif->deflink.phy_ctxt->channel->band,
true);
} else if (old_state == IEEE80211_STA_AUTHORIZED &&
new_state == IEEE80211_STA_ASSOC) {
/* once we move into assoc state, need to update rate scale to
* disable using wide bandwidth
*/
- iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band,
+ iwl_mvm_rs_rate_init(mvm, sta,
+ mvmvif->deflink.phy_ctxt->channel->band,
false);
if (!sta->tdls) {
/*
@@ -3650,7 +3659,8 @@ static void iwl_mvm_sta_rc_update(struct ieee80211_hw *hw,
if (changed & (IEEE80211_RC_BW_CHANGED |
IEEE80211_RC_SUPP_RATES_CHANGED |
IEEE80211_RC_NSS_CHANGED))
- iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band,
+ iwl_mvm_rs_rate_init(mvm, sta,
+ mvmvif->deflink.phy_ctxt->channel->band,
true);

if (vif->type == NL80211_IFTYPE_STATION &&
@@ -3666,7 +3676,7 @@ static int iwl_mvm_mac_conf_tx(struct ieee80211_hw *hw,
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);

- mvmvif->queue_params[ac] = *params;
+ mvmvif->deflink.queue_params[ac] = *params;

/*
* No need to update right away, we'll get BSS_CHANGED_QOS
@@ -4237,7 +4247,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,

for (i = 0; i < NUM_PHY_CTX; i++) {
phy_ctxt = &mvm->phy_ctxts[i];
- if (phy_ctxt->ref == 0 || mvmvif->phy_ctxt == phy_ctxt)
+ if (phy_ctxt->ref == 0 || mvmvif->deflink.phy_ctxt == phy_ctxt)
continue;

if (phy_ctxt->ref && channel == phy_ctxt->channel) {
@@ -4249,22 +4259,22 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
if (WARN(ret, "Failed unbinding P2P_DEVICE\n"))
goto out_unlock;

- iwl_mvm_phy_ctxt_unref(mvm, mvmvif->phy_ctxt);
+ iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);

/* Bind the P2P_DEVICE to the current PHY Context */
- mvmvif->phy_ctxt = phy_ctxt;
+ mvmvif->deflink.phy_ctxt = phy_ctxt;

ret = iwl_mvm_binding_add_vif(mvm, vif);
if (WARN(ret, "Failed binding P2P_DEVICE\n"))
goto out_unlock;

- iwl_mvm_phy_ctxt_ref(mvm, mvmvif->phy_ctxt);
+ iwl_mvm_phy_ctxt_ref(mvm, mvmvif->deflink.phy_ctxt);
goto schedule_time_event;
}
}

/* Need to update the PHY context only if the ROC channel changed */
- if (channel == mvmvif->phy_ctxt->channel)
+ if (channel == mvmvif->deflink.phy_ctxt->channel)
goto schedule_time_event;

cfg80211_chandef_create(&chandef, channel, NL80211_CHAN_NO_HT);
@@ -4278,14 +4288,14 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
band_change_removal =
fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT) &&
- mvmvif->phy_ctxt->channel->band != chandef.chan->band;
+ mvmvif->deflink.phy_ctxt->channel->band != chandef.chan->band;

- if (mvmvif->phy_ctxt->ref == 1 && !band_change_removal) {
+ if (mvmvif->deflink.phy_ctxt->ref == 1 && !band_change_removal) {
/*
* Change the PHY context configuration as it is currently
* referenced only by the P2P Device MAC (and we can modify it)
*/
- ret = iwl_mvm_phy_ctxt_changed(mvm, mvmvif->phy_ctxt,
+ ret = iwl_mvm_phy_ctxt_changed(mvm, mvmvif->deflink.phy_ctxt,
&chandef, 1, 1);
if (ret)
goto out_unlock;
@@ -4313,16 +4323,16 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
if (WARN(ret, "Failed unbinding P2P_DEVICE\n"))
goto out_unlock;

- iwl_mvm_phy_ctxt_unref(mvm, mvmvif->phy_ctxt);
+ iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);

/* Bind the P2P_DEVICE to the new allocated PHY context */
- mvmvif->phy_ctxt = phy_ctxt;
+ mvmvif->deflink.phy_ctxt = phy_ctxt;

ret = iwl_mvm_binding_add_vif(mvm, vif);
if (WARN(ret, "Failed binding P2P_DEVICE\n"))
goto out_unlock;

- iwl_mvm_phy_ctxt_ref(mvm, mvmvif->phy_ctxt);
+ iwl_mvm_phy_ctxt_ref(mvm, mvmvif->deflink.phy_ctxt);
}

schedule_time_event:
@@ -4505,7 +4515,7 @@ bool __iwl_mvm_assign_vif_chanctx_common(struct iwl_mvm *mvm,

lockdep_assert_held(&mvm->mutex);

- mvmvif->phy_ctxt = phy_ctxt;
+ mvmvif->deflink.phy_ctxt = phy_ctxt;

switch (vif->type) {
case NL80211_IFTYPE_AP:
@@ -4609,7 +4619,7 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm,
iwl_mvm_power_update_mac(mvm);
out:
if (ret)
- mvmvif->phy_ctxt = NULL;
+ mvmvif->deflink.phy_ctxt = NULL;
return ret;
}

@@ -4641,7 +4651,8 @@ bool __iwl_mvm_unassign_vif_chanctx_common(struct iwl_mvm *mvm,
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);

lockdep_assert_held(&mvm->mutex);
- iwl_mvm_remove_time_event(mvm, mvmvif, &mvmvif->time_event_data);
+ iwl_mvm_remove_time_event(mvm, mvmvif,
+ &mvmvif->time_event_data);

switch (vif->type) {
case NL80211_IFTYPE_ADHOC:
@@ -4700,7 +4711,7 @@ static void __iwl_mvm_unassign_vif_chanctx(struct iwl_mvm *mvm,
if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD) &&
switching_chanctx)
return;
- mvmvif->phy_ctxt = NULL;
+ mvmvif->deflink.phy_ctxt = NULL;
iwl_mvm_power_update_mac(mvm);
}

@@ -5243,7 +5254,7 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,
continue;

/* make sure only TDLS peers or the AP are flushed */
- WARN_ON(i != mvmvif->ap_sta_id && !sta->tdls);
+ WARN_ON(i != mvmvif->deflink.ap_sta_id && !sta->tdls);

if (drop) {
if (iwl_mvm_flush_sta(mvm, mvmsta, false))
@@ -5480,18 +5491,19 @@ static void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw,

mutex_lock(&mvm->mutex);

- if (mvmvif->ap_sta_id != mvmsta->sta_id)
+ if (mvmvif->deflink.ap_sta_id != mvmsta->sta_id)
goto unlock;

if (iwl_mvm_request_statistics(mvm, false))
goto unlock;

- sinfo->rx_beacon = mvmvif->beacon_stats.num_beacons +
- mvmvif->beacon_stats.accu_num_beacons;
+ sinfo->rx_beacon = mvmvif->deflink.beacon_stats.num_beacons +
+ mvmvif->deflink.beacon_stats.accu_num_beacons;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_BEACON_RX);
- if (mvmvif->beacon_stats.avg_signal) {
+ if (mvmvif->deflink.beacon_stats.avg_signal) {
/* firmware only reports a value after RXing a few beacons */
- sinfo->rx_beacon_signal_avg = mvmvif->beacon_stats.avg_signal;
+ sinfo->rx_beacon_signal_avg =
+ mvmvif->deflink.beacon_stats.avg_signal;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG);
}
unlock:
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
index e27c893502f7..4eaba89ba0c5 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
@@ -17,7 +17,7 @@ static u32 iwl_mvm_get_sec_sta_mask(struct iwl_mvm *mvm,

if (vif->type == NL80211_IFTYPE_AP &&
!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
- return BIT(mvmvif->mcast_sta.sta_id);
+ return BIT(mvmvif->deflink.mcast_sta.sta_id);

if (sta) {
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
@@ -26,8 +26,8 @@ static u32 iwl_mvm_get_sec_sta_mask(struct iwl_mvm *mvm,
}

if (vif->type == NL80211_IFTYPE_STATION &&
- mvmvif->ap_sta_id != IWL_MVM_INVALID_STA)
- return BIT(mvmvif->ap_sta_id);
+ mvmvif->deflink.ap_sta_id != IWL_MVM_INVALID_STA)
+ return BIT(mvmvif->deflink.ap_sta_id);

/* invalid */
return 0;
@@ -70,8 +70,8 @@ static u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm,

rcu_read_lock();
if (!sta && vif->type == NL80211_IFTYPE_STATION &&
- mvmvif->ap_sta_id != IWL_MVM_INVALID_STA) {
- u8 sta_id = mvmvif->ap_sta_id;
+ mvmvif->deflink.ap_sta_id != IWL_MVM_INVALID_STA) {
+ u8 sta_id = mvmvif->deflink.ap_sta_id;

sta = rcu_dereference_check(mvm->fw_id_to_mac_id[sta_id],
lockdep_is_held(&mvm->mutex));
@@ -214,7 +214,7 @@ void iwl_mvm_sec_key_remove_ap(struct iwl_mvm *mvm,
u8 sec_key_ver = iwl_fw_lookup_cmd_ver(mvm->fw, sec_key_id, 0);

if (WARN_ON(vif->type != NL80211_IFTYPE_STATION ||
- mvmvif->ap_sta_id == IWL_MVM_INVALID_STA))
+ mvmvif->deflink.ap_sta_id == IWL_MVM_INVALID_STA))
return;

if (!sec_key_ver)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index f800bf0b6d90..fe55efce8dd5 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -43,13 +43,13 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
* MAC context is bound to it at this stage.
*/
if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
- mvmvif->phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm);
- if (!mvmvif->phy_ctxt) {
+ mvmvif->deflink.phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm);
+ if (!mvmvif->deflink.phy_ctxt) {
ret = -ENOSPC;
goto out_free_bf;
}

- iwl_mvm_phy_ctxt_ref(mvm, mvmvif->phy_ctxt);
+ iwl_mvm_phy_ctxt_ref(mvm, mvmvif->deflink.phy_ctxt);
ret = iwl_mvm_add_link(mvm, vif);
if (ret)
goto out_unref_phy;
@@ -97,7 +97,7 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ACTIVE, false);
iwl_mvm_remove_link(mvm, vif);
out_unref_phy:
- iwl_mvm_phy_ctxt_unref(mvm, mvmvif->phy_ctxt);
+ iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
out_free_bf:
if (mvm->bf_allowed_vif == mvmvif) {
mvm->bf_allowed_vif = NULL;
@@ -105,7 +105,8 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
IEEE80211_VIF_SUPPORTS_CQM_RSSI);
}
out_remove_mac:
- mvmvif->phy_ctxt = NULL;
+ mvmvif->deflink.phy_ctxt = NULL;
+ mvmvif->link[0] = NULL;
iwl_mvm_mld_mac_ctxt_remove(mvm, vif);
out_unlock:
mutex_unlock(&mvm->mutex);
@@ -129,8 +130,8 @@ static void iwl_mvm_mld_mac_remove_interface(struct ieee80211_hw *hw,
iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ACTIVE,
false);
iwl_mvm_remove_link(mvm, vif);
- iwl_mvm_phy_ctxt_unref(mvm, mvmvif->phy_ctxt);
- mvmvif->phy_ctxt = NULL;
+ iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
+ mvmvif->deflink.phy_ctxt = NULL;
}

iwl_mvm_mld_mac_ctxt_remove(mvm, vif);
@@ -187,7 +188,7 @@ static int __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
iwl_mvm_power_update_mac(mvm);
out:
if (ret)
- mvmvif->phy_ctxt = NULL;
+ mvmvif->deflink.phy_ctxt = NULL;
return ret;
}

@@ -230,7 +231,7 @@ static void __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm,
out:
if (switching_chanctx)
return;
- mvmvif->phy_ctxt = NULL;
+ mvmvif->deflink.phy_ctxt = NULL;
iwl_mvm_power_update_mac(mvm);
}

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
index 51532b6379e2..b2a7fa09f900 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
@@ -147,7 +147,7 @@ static int iwl_mvm_mld_add_int_sta(struct iwl_mvm *mvm,
int iwl_mvm_mld_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm_int_sta *bsta = &mvmvif->bcast_sta;
+ struct iwl_mvm_int_sta *bsta = &mvmvif->deflink.bcast_sta;
static const u8 _baddr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
const u8 *baddr = _baddr;
unsigned int wdg_timeout =
@@ -172,7 +172,7 @@ int iwl_mvm_mld_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
return iwl_mvm_mld_add_int_sta(mvm, bsta, queue,
ieee80211_vif_type_p2p(vif),
STATION_TYPE_BCAST_MGMT,
- mvmvif->phy_ctxt->id, baddr,
+ mvmvif->deflink.phy_ctxt->id, baddr,
IWL_MAX_TID_COUNT, &wdg_timeout);
}

@@ -183,7 +183,7 @@ int iwl_mvm_mld_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
int iwl_mvm_mld_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm_int_sta *msta = &mvmvif->mcast_sta;
+ struct iwl_mvm_int_sta *msta = &mvmvif->deflink.mcast_sta;
static const u8 _maddr[] = {0x03, 0x00, 0x00, 0x00, 0x00, 0x00};
const u8 *maddr = _maddr;
unsigned int timeout = iwl_mvm_get_wd_timeout(mvm, vif, false, false);
@@ -200,11 +200,11 @@ int iwl_mvm_mld_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
* changes in mac80211 layer.
*/
if (vif->type == NL80211_IFTYPE_ADHOC)
- mvmvif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE;
+ mvmvif->deflink.cab_queue = IWL_MVM_DQA_GCAST_QUEUE;

- return iwl_mvm_mld_add_int_sta(mvm, msta, &mvmvif->cab_queue,
+ return iwl_mvm_mld_add_int_sta(mvm, msta, &mvmvif->deflink.cab_queue,
vif->type, STATION_TYPE_MCAST,
- mvmvif->phy_ctxt->id, maddr, 0,
+ mvmvif->deflink.phy_ctxt->id, maddr, 0,
&timeout);
}

@@ -219,7 +219,7 @@ int iwl_mvm_mld_add_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)

return iwl_mvm_mld_add_int_sta(mvm, &mvm->snif_sta, &mvm->snif_queue,
vif->type, STATION_TYPE_BCAST_MGMT,
- mvmvif->phy_ctxt->id, NULL,
+ mvmvif->deflink.phy_ctxt->id, NULL,
IWL_MAX_TID_COUNT, NULL);
}

@@ -305,7 +305,7 @@ int iwl_mvm_mld_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
return -EINVAL;
}

- return iwl_mvm_mld_rm_int_sta(mvm, &mvmvif->bcast_sta, true,
+ return iwl_mvm_mld_rm_int_sta(mvm, &mvmvif->deflink.bcast_sta, true,
IWL_MAX_TID_COUNT, queueptr);
}

@@ -318,8 +318,9 @@ int iwl_mvm_mld_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)

lockdep_assert_held(&mvm->mutex);

- return iwl_mvm_mld_rm_int_sta(mvm, &mvmvif->mcast_sta, true, 0,
- &mvmvif->cab_queue);
+ return iwl_mvm_mld_rm_int_sta(mvm, &mvmvif->deflink.mcast_sta, true,
+ 0,
+ &mvmvif->deflink.cab_queue);
}

int iwl_mvm_mld_rm_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index cea94250d197..72056cccc77e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -280,12 +280,55 @@ struct iwl_probe_resp_data {
int noa_len;
};

+/**
+ * struct iwl_mvm_vif_link_info - per link data in Virtual Interface
+ * @ap_sta_id: the sta_id of the AP - valid only if VIF type is STA
+ * @bssid: BSSID for this (client) interface
+ * @bcast_sta: station used for broadcast packets. Used by the following
+ * vifs: P2P_DEVICE, GO and AP.
+ * @beacon_stats: beacon statistics, containing the # of received beacons,
+ * # of received beacons accumulated over FW restart, and the current
+ * average signal of beacons retrieved from the firmware
+ * @smps_requests: the SMPS requests of different parts of the driver,
+ * combined on update to yield the overall request to mac80211.
+ * @probe_resp_data: data from FW notification to store NOA and CSA related
+ * data to be inserted into probe response.
+ * @he_ru_2mhz_block: 26-tone RU OFDMA transmissions should be blocked
+ * @queue_params: QoS params for this MAC
+ */
+struct iwl_mvm_vif_link_info {
+ u8 bssid[ETH_ALEN];
+ u8 ap_sta_id;
+
+ struct iwl_mvm_int_sta bcast_sta;
+ struct iwl_mvm_int_sta mcast_sta;
+
+ struct {
+ u32 num_beacons, accu_num_beacons;
+ u8 avg_signal;
+ } beacon_stats;
+
+ enum ieee80211_smps_mode smps_requests[NUM_IWL_MVM_SMPS_REQ];
+ struct iwl_probe_resp_data __rcu *probe_resp_data;
+
+ bool he_ru_2mhz_block;
+
+ u16 cab_queue;
+ /* Assigned while mac80211 has the link in a channel context,
+ * or, for P2P Device, while it exists.
+ */
+ struct iwl_mvm_phy_ctxt *phy_ctxt;
+ /* QoS data from mac80211, need to store this here
+ * as mac80211 has a separate callback but we need
+ * to have the data for the MAC context
+ */
+ struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
+};
+
/**
* struct iwl_mvm_vif - data per Virtual Interface, it is a MAC context
* @id: between 0 and 3
* @color: to solve races upon MAC addition and removal
- * @ap_sta_id: the sta_id of the AP - valid only if VIF type is STA
- * @bssid: BSSID for this (client) interface
* @associated: indicates that we're currently associated, used only for
* managing the firmware state in iwl_mvm_bss_info_changed_station()
* @ap_assoc_sta_count: count of stations associated to us - valid only
@@ -293,7 +336,7 @@ struct iwl_probe_resp_data {
* @uploaded: indicates the MAC context has been added to the device
* @ap_ibss_active: indicates that AP/IBSS is configured and that the interface
* should get quota etc.
- * @pm_enabled - Indicate if MAC power management is allowed
+ * @pm_enabled - indicate if MAC power management is allowed
* @monitor_active: indicates that monitor context is configured, and that the
* interface should get quota etc.
* @low_latency: bit flags for low latency
@@ -302,68 +345,31 @@ struct iwl_probe_resp_data {
* as a result from low_latency bit flags and takes force into account.
* @authorized: indicates the AP station was set to authorized
* @ps_disabled: indicates that this interface requires PS to be disabled
- * @queue_params: QoS params for this MAC
- * @bcast_sta: station used for broadcast packets. Used by the following
- * vifs: P2P_DEVICE, GO and AP.
- * @beacon_skb: the skb used to hold the AP/GO beacon template
- * @smps_requests: the SMPS requests of different parts of the driver,
- * combined on update to yield the overall request to mac80211.
- * @beacon_stats: beacon statistics, containing the # of received beacons,
- * # of received beacons accumulated over FW restart, and the current
- * average signal of beacons retrieved from the firmware
+ * @csa_countdown: indicates that CSA countdown may be started
* @csa_failed: CSA failed to schedule time event, report an error later
+ * @csa_bcn_pending: indicates that we are waiting for a beacon on a new channel
* @features: hw features active for this vif
- * @probe_resp_data: data from FW notification to store NOA and CSA related
- * data to be inserted into probe response.
*/
struct iwl_mvm_vif {
struct iwl_mvm *mvm;
u16 id;
u16 color;
- u8 ap_sta_id;

- u8 bssid[ETH_ALEN];
bool associated;
u8 ap_assoc_sta_count;
-
- u16 cab_queue;
-
bool uploaded;
bool ap_ibss_active;
bool pm_enabled;
bool monitor_active;
+
u8 low_latency: 6;
u8 low_latency_actual: 1;
+
u8 authorized:1;
bool ps_disabled;
- struct iwl_mvm_vif_bf_data bf_data;
-
- struct {
- u32 num_beacons, accu_num_beacons;
- u8 avg_signal;
- } beacon_stats;

u32 ap_beacon_time;
-
- enum iwl_tsf_id tsf_id;
-
- /*
- * QoS data from mac80211, need to store this here
- * as mac80211 has a separate callback but we need
- * to have the data for the MAC context
- */
- struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
- struct iwl_mvm_time_event_data time_event_data;
- struct iwl_mvm_time_event_data hs_time_event_data;
-
- struct iwl_mvm_int_sta bcast_sta;
- struct iwl_mvm_int_sta mcast_sta;
-
- /*
- * Assigned while mac80211 has the interface in a channel context,
- * or, for P2P Device, while it exists.
- */
- struct iwl_mvm_phy_ctxt *phy_ctxt;
+ struct iwl_mvm_vif_bf_data bf_data;

#ifdef CONFIG_PM
/* WoWLAN GTK rekey data */
@@ -399,40 +405,43 @@ struct iwl_mvm_vif {
int dbgfs_quota_min;
#endif

- enum ieee80211_smps_mode smps_requests[NUM_IWL_MVM_SMPS_REQ];
-
/* FW identified misbehaving AP */
u8 uapsd_misbehaving_bssid[ETH_ALEN];
-
struct delayed_work uapsd_nonagg_detected_wk;

- /* Indicates that CSA countdown may be started */
bool csa_countdown;
bool csa_failed;
+ bool csa_bcn_pending;
u16 csa_target_freq;
u16 csa_count;
u16 csa_misbehave;
struct delayed_work csa_work;

- /* Indicates that we are waiting for a beacon on a new channel */
- bool csa_bcn_pending;
+ enum iwl_tsf_id tsf_id;
+
+ struct iwl_mvm_time_event_data time_event_data;
+ struct iwl_mvm_time_event_data hs_time_event_data;

/* TCP Checksum Offload */
netdev_features_t features;

- struct iwl_probe_resp_data __rcu *probe_resp_data;
-
/* we can only have 2 GTK + 2 IGTK active at a time */
struct ieee80211_key_conf *ap_early_keys[4];

- /* 26-tone RU OFDMA transmissions should be blocked */
- bool he_ru_2mhz_block;
-
struct {
struct ieee80211_key_conf __rcu *keys[2];
} bcn_prot;
+
+ struct iwl_mvm_vif_link_info deflink;
+ struct iwl_mvm_vif_link_info *link[IEEE80211_MLD_MAX_NUM_LINKS];
};

+#define for_each_mvm_vif_valid_link(mvm_vif, link_id) \
+ for (link_id = 0; \
+ link_id < ARRAY_SIZE((mvm_vif)->link); \
+ link_id++) \
+ if ((mvm_vif)->link[link_id])
+
static inline struct iwl_mvm_vif *
iwl_mvm_vif_from_mac80211(struct ieee80211_vif *vif)
{
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c
index 06f4203fb989..3ab6fb83a175 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c
@@ -382,12 +382,12 @@ static void iwl_mvm_binding_iterator(void *_data, u8 *mac,
unsigned long *data = _data;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);

- if (!mvmvif->phy_ctxt)
+ if (!mvmvif->deflink.phy_ctxt)
return;

if (vif->type == NL80211_IFTYPE_STATION ||
vif->type == NL80211_IFTYPE_AP)
- __set_bit(mvmvif->phy_ctxt->id, data);
+ __set_bit(mvmvif->deflink.phy_ctxt->id, data);
}

int iwl_mvm_phy_ctx_count(struct iwl_mvm *mvm)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/power.c b/drivers/net/wireless/intel/iwlwifi/mvm/power.c
index f5744162d0d8..6e2e3127843f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/power.c
@@ -150,7 +150,7 @@ static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm,
#endif

for (ac = IEEE80211_AC_VO; ac <= IEEE80211_AC_BK; ac++) {
- if (!mvmvif->queue_params[ac].uapsd)
+ if (!mvmvif->deflink.queue_params[ac].uapsd)
continue;

if (!test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status))
@@ -160,7 +160,7 @@ static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm,
cmd->uapsd_ac_flags |= BIT(ac);

/* QNDP TID - the highest TID with no admission control */
- if (!tid_found && !mvmvif->queue_params[ac].acm) {
+ if (!tid_found && !mvmvif->deflink.queue_params[ac].acm) {
tid_found = true;
switch (ac) {
case IEEE80211_AC_VO:
@@ -509,8 +509,9 @@ static void iwl_mvm_power_uapsd_misbehav_ap_iterator(void *_data, u8 *mac,
/* The ap_sta_id is not expected to change during current association
* so no explicit protection is needed
*/
- if (mvmvif->ap_sta_id == *ap_sta_id)
- memcpy(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid,
+ if (mvmvif->deflink.ap_sta_id == *ap_sta_id)
+ memcpy(mvmvif->uapsd_misbehaving_bssid,
+ vif->bss_conf.bssid,
ETH_ALEN);
}

@@ -552,7 +553,8 @@ static void iwl_mvm_power_ps_disabled_iterator(void *_data, u8* mac,
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
bool *disable_ps = _data;

- if (mvmvif->phy_ctxt && mvmvif->phy_ctxt->id < NUM_PHY_CTX)
+ if (mvmvif->deflink.phy_ctxt &&
+ mvmvif->deflink.phy_ctxt->id < NUM_PHY_CTX)
*disable_ps |= mvmvif->ps_disabled;
}

@@ -561,7 +563,7 @@ static void iwl_mvm_power_get_vifs_iterator(void *_data, u8 *mac,
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_power_vifs *power_iterator = _data;
- bool active = mvmvif->phy_ctxt && mvmvif->phy_ctxt->id < NUM_PHY_CTX;
+ bool active = mvmvif->deflink.phy_ctxt && mvmvif->deflink.phy_ctxt->id < NUM_PHY_CTX;

if (!mvmvif->uploaded)
return;
@@ -649,11 +651,11 @@ static void iwl_mvm_power_set_pm(struct iwl_mvm *mvm,
}

if (vifs->bss_active && vifs->p2p_active)
- client_same_channel = (bss_mvmvif->phy_ctxt->id ==
- p2p_mvmvif->phy_ctxt->id);
+ client_same_channel = (bss_mvmvif->deflink.phy_ctxt->id ==
+ p2p_mvmvif->deflink.phy_ctxt->id);
if (vifs->bss_active && vifs->ap_active)
- ap_same_channel = (bss_mvmvif->phy_ctxt->id ==
- ap_mvmvif->phy_ctxt->id);
+ ap_same_channel = (bss_mvmvif->deflink.phy_ctxt->id ==
+ ap_mvmvif->deflink.phy_ctxt->id);

/* clients are not stand alone: enable PM if DCM */
if (!(client_same_channel || ap_same_channel)) {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/quota.c b/drivers/net/wireless/intel/iwlwifi/mvm/quota.c
index cea1a34f9130..aad2614af9ad 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/quota.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/quota.c
@@ -33,11 +33,11 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac,
if (vif == data->disabled_vif)
return;

- if (!mvmvif->phy_ctxt)
+ if (!mvmvif->deflink.phy_ctxt)
return;

/* currently, PHY ID == binding ID */
- id = mvmvif->phy_ctxt->id;
+ id = mvmvif->deflink.phy_ctxt->id;

/* need at least one binding per PHY */
BUILD_BUG_ON(NUM_PHY_CTX > MAX_BINDINGS);
@@ -67,9 +67,10 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac,
}

if (data->colors[id] < 0)
- data->colors[id] = mvmvif->phy_ctxt->color;
+ data->colors[id] = mvmvif->deflink.phy_ctxt->color;
else
- WARN_ON_ONCE(data->colors[id] != mvmvif->phy_ctxt->color);
+ WARN_ON_ONCE(data->colors[id] !=
+ mvmvif->deflink.phy_ctxt->color);

data->n_interfaces[id]++;

@@ -99,7 +100,7 @@ static void iwl_mvm_adjust_quota_for_noa(struct iwl_mvm *mvm,
if (!mvmvif->ap_ibss_active)
return;

- phy_id = mvmvif->phy_ctxt->id;
+ phy_id = mvmvif->deflink.phy_ctxt->id;
beacon_int = mvm->noa_vif->bss_conf.beacon_int;

for (i = 0; i < MAX_BINDINGS; i++) {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
index d2ce414879aa..4105b79db467 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
@@ -237,11 +237,11 @@ static void iwl_mvm_rx_handle_tcm(struct iwl_mvm *mvm,

if (mdata->opened_rx_ba_sessions ||
mdata->uapsd_nonagg_detect.detected ||
- (!mvmvif->queue_params[IEEE80211_AC_VO].uapsd &&
- !mvmvif->queue_params[IEEE80211_AC_VI].uapsd &&
- !mvmvif->queue_params[IEEE80211_AC_BE].uapsd &&
- !mvmvif->queue_params[IEEE80211_AC_BK].uapsd) ||
- mvmsta->sta_id != mvmvif->ap_sta_id)
+ (!mvmvif->deflink.queue_params[IEEE80211_AC_VO].uapsd &&
+ !mvmvif->deflink.queue_params[IEEE80211_AC_VI].uapsd &&
+ !mvmvif->deflink.queue_params[IEEE80211_AC_BE].uapsd &&
+ !mvmvif->deflink.queue_params[IEEE80211_AC_BK].uapsd) ||
+ mvmsta->sta_id != mvmvif->deflink.ap_sta_id)
return;

if (rate_n_flags & RATE_MCS_HT_MSK_V1) {
@@ -628,9 +628,9 @@ static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
* data copied into the "data" struct, but rather the data from
* the notification directly.
*/
- mvmvif->beacon_stats.num_beacons =
+ mvmvif->deflink.beacon_stats.num_beacons =
le32_to_cpu(data->beacon_counter[vif_id]);
- mvmvif->beacon_stats.avg_signal =
+ mvmvif->deflink.beacon_stats.avg_signal =
-data->beacon_average_energy[vif_id];

if (mvmvif->id != id)
@@ -643,8 +643,8 @@ static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
* request to clear statistics
*/
if (le32_to_cpu(data->flags) & IWL_STATISTICS_REPLY_FLG_CLEAR)
- mvmvif->beacon_stats.accu_num_beacons +=
- mvmvif->beacon_stats.num_beacons;
+ mvmvif->deflink.beacon_stats.accu_num_beacons +=
+ mvmvif->deflink.beacon_stats.num_beacons;

iwl_mvm_update_vif_sig(vif, sig);
}
@@ -666,17 +666,17 @@ static void iwl_mvm_stat_iterator_all_macs(void *_data, u8 *mac,

mac_stats = &data->per_mac_stats[vif_id];

- mvmvif->beacon_stats.num_beacons =
+ mvmvif->deflink.beacon_stats.num_beacons =
le32_to_cpu(mac_stats->beacon_counter);
- mvmvif->beacon_stats.avg_signal =
+ mvmvif->deflink.beacon_stats.avg_signal =
-le32_to_cpu(mac_stats->beacon_average_energy);

/* make sure that beacon statistics don't go backwards with TCM
* request to clear statistics
*/
if (le32_to_cpu(data->flags) & IWL_STATISTICS_REPLY_FLG_CLEAR)
- mvmvif->beacon_stats.accu_num_beacons +=
- mvmvif->beacon_stats.num_beacons;
+ mvmvif->deflink.beacon_stats.accu_num_beacons +=
+ mvmvif->deflink.beacon_stats.num_beacons;

sig = -le32_to_cpu(mac_stats->beacon_filter_average_energy);
iwl_mvm_update_vif_sig(vif, sig);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
index acd8803dbcdd..975edc02e637 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -193,8 +193,9 @@ static void iwl_mvm_scan_iterator(void *_data, u8 *mac,
struct iwl_mvm_scan_iter_data *data = _data;
struct iwl_mvm_vif *curr_mvmvif;

- if (vif->type != NL80211_IFTYPE_P2P_DEVICE && mvmvif->phy_ctxt &&
- mvmvif->phy_ctxt->id < NUM_PHY_CTX)
+ if (vif->type != NL80211_IFTYPE_P2P_DEVICE &&
+ mvmvif->deflink.phy_ctxt &&
+ mvmvif->deflink.phy_ctxt->id < NUM_PHY_CTX)
data->global_cnt += 1;

if (!data->current_vif || vif == data->current_vif)
@@ -203,8 +204,8 @@ static void iwl_mvm_scan_iterator(void *_data, u8 *mac,
curr_mvmvif = iwl_mvm_vif_from_mac80211(data->current_vif);

if (vif->type == NL80211_IFTYPE_AP && vif->p2p &&
- mvmvif->phy_ctxt && curr_mvmvif->phy_ctxt &&
- mvmvif->phy_ctxt->id != curr_mvmvif->phy_ctxt->id)
+ mvmvif->deflink.phy_ctxt && curr_mvmvif->deflink.phy_ctxt &&
+ mvmvif->deflink.phy_ctxt->id != curr_mvmvif->deflink.phy_ctxt->id)
data->is_dcm_with_p2p_go = true;
}

@@ -2677,9 +2678,9 @@ static void iwl_mvm_scan_respect_p2p_go_iter(void *_data, u8 *mac,
return;

if (vif->type == NL80211_IFTYPE_AP && vif->p2p &&
- mvmvif->phy_ctxt->id < NUM_PHY_CTX &&
+ mvmvif->deflink.phy_ctxt->id < NUM_PHY_CTX &&
(data->band == NUM_NL80211_BANDS ||
- mvmvif->phy_ctxt->channel->band == data->band))
+ mvmvif->deflink.phy_ctxt->channel->band == data->band))
data->p2p_go = true;
}

@@ -2980,7 +2981,7 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
.scan_start_tsf = mvm->scan_start,
};

- memcpy(info.tsf_bssid, mvm->scan_vif->bssid, ETH_ALEN);
+ memcpy(info.tsf_bssid, mvm->scan_vif->deflink.bssid, ETH_ALEN);
ieee80211_scan_completed(mvm->hw, &info);
mvm->scan_vif = NULL;
cancel_delayed_work(&mvm->scan_timeout_dwork);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sf.c b/drivers/net/wireless/intel/iwlwifi/mvm/sf.c
index 1f4ac1e93cee..84b750d02848 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sf.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sf.c
@@ -23,14 +23,14 @@ static void iwl_mvm_bound_iface_iterator(void *_data, u8 *mac,
struct iwl_mvm_active_iface_iterator_data *data = _data;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);

- if (vif == data->ignore_vif || !mvmvif->phy_ctxt ||
+ if (vif == data->ignore_vif || !mvmvif->deflink.phy_ctxt ||
vif->type == NL80211_IFTYPE_P2P_DEVICE)
return;

data->num_active_macs++;

if (vif->type == NL80211_IFTYPE_STATION) {
- data->sta_vif_ap_sta_id = mvmvif->ap_sta_id;
+ data->sta_vif_ap_sta_id = mvmvif->deflink.ap_sta_id;
if (vif->cfg.assoc)
data->sta_vif_state = SF_FULL_ON;
else
@@ -264,7 +264,7 @@ int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *changed_vif,
} else if (changed_vif->cfg.assoc &&
changed_vif->bss_conf.dtim_period) {
mvmvif = iwl_mvm_vif_from_mac80211(changed_vif);
- sta_id = mvmvif->ap_sta_id;
+ sta_id = mvmvif->deflink.ap_sta_id;
new_state = SF_FULL_ON;
} else {
new_state = SF_INIT_OFF;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index ec843f1b0165..c3b81021898b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -1785,10 +1785,10 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,

if (vif->type == NL80211_IFTYPE_STATION) {
if (!sta->tdls) {
- WARN_ON(mvmvif->ap_sta_id != IWL_MVM_INVALID_STA);
- mvmvif->ap_sta_id = sta_id;
+ WARN_ON(mvmvif->deflink.ap_sta_id != IWL_MVM_INVALID_STA);
+ mvmvif->deflink.ap_sta_id = sta_id;
} else {
- WARN_ON(mvmvif->ap_sta_id == IWL_MVM_INVALID_STA);
+ WARN_ON(mvmvif->deflink.ap_sta_id == IWL_MVM_INVALID_STA);
}
}

@@ -1953,7 +1953,7 @@ static bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
}

if (vif->type == NL80211_IFTYPE_STATION &&
- mvmvif->ap_sta_id == sta_id) {
+ mvmvif->deflink.ap_sta_id == sta_id) {
/* if associated - we can't remove the AP STA now */
if (vif->cfg.assoc)
return true;
@@ -1962,7 +1962,7 @@ static bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
iwl_mvm_sec_key_remove_ap(mvm, vif);

/* unassoc - go ahead - remove the AP STA now */
- mvmvif->ap_sta_id = IWL_MVM_INVALID_STA;
+ mvmvif->deflink.ap_sta_id = IWL_MVM_INVALID_STA;
}

/*
@@ -2227,7 +2227,7 @@ void iwl_mvm_dealloc_snif_sta(struct iwl_mvm *mvm)
int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm_int_sta *bsta = &mvmvif->bcast_sta;
+ struct iwl_mvm_int_sta *bsta = &mvmvif->deflink.bcast_sta;
static const u8 _baddr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
const u8 *baddr = _baddr;
int queue;
@@ -2236,7 +2236,7 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
iwl_mvm_get_wd_timeout(mvm, vif, false, false);
struct iwl_trans_txq_scd_cfg cfg = {
.fifo = IWL_MVM_TX_FIFO_VO,
- .sta_id = mvmvif->bcast_sta.sta_id,
+ .sta_id = mvmvif->deflink.bcast_sta.sta_id,
.tid = IWL_MAX_TID_COUNT,
.aggregate = false,
.frame_limit = IWL_FRAME_LIMIT,
@@ -2302,7 +2302,7 @@ void iwl_mvm_free_bcast_sta_queues(struct iwl_mvm *mvm,

lockdep_assert_held(&mvm->mutex);

- iwl_mvm_flush_sta(mvm, &mvmvif->bcast_sta, true);
+ iwl_mvm_flush_sta(mvm, &mvmvif->deflink.bcast_sta, true);

switch (vif->type) {
case NL80211_IFTYPE_AP:
@@ -2319,13 +2319,13 @@ void iwl_mvm_free_bcast_sta_queues(struct iwl_mvm *mvm,
}

queue = *queueptr;
- iwl_mvm_disable_txq(mvm, NULL, mvmvif->bcast_sta.sta_id,
+ iwl_mvm_disable_txq(mvm, NULL, mvmvif->deflink.bcast_sta.sta_id,
queueptr, IWL_MAX_TID_COUNT);
if (iwl_mvm_has_new_tx_api(mvm))
return;

- WARN_ON(!(mvmvif->bcast_sta.tfd_queue_msk & BIT(queue)));
- mvmvif->bcast_sta.tfd_queue_msk &= ~BIT(queue);
+ WARN_ON(!(mvmvif->deflink.bcast_sta.tfd_queue_msk & BIT(queue)));
+ mvmvif->deflink.bcast_sta.tfd_queue_msk &= ~BIT(queue);
}

/* Send the FW a request to remove the station from it's internal data
@@ -2339,7 +2339,7 @@ int iwl_mvm_send_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)

iwl_mvm_free_bcast_sta_queues(mvm, vif);

- ret = iwl_mvm_rm_sta_common(mvm, mvmvif->bcast_sta.sta_id);
+ ret = iwl_mvm_rm_sta_common(mvm, mvmvif->deflink.bcast_sta.sta_id);
if (ret)
IWL_WARN(mvm, "Failed sending remove station\n");
return ret;
@@ -2351,7 +2351,7 @@ int iwl_mvm_alloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)

lockdep_assert_held(&mvm->mutex);

- return iwl_mvm_allocate_int_sta(mvm, &mvmvif->bcast_sta, 0,
+ return iwl_mvm_allocate_int_sta(mvm, &mvmvif->deflink.bcast_sta, 0,
ieee80211_vif_type_p2p(vif),
IWL_STA_GENERAL_PURPOSE);
}
@@ -2366,7 +2366,7 @@ int iwl_mvm_alloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
int iwl_mvm_add_p2p_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm_int_sta *bsta = &mvmvif->bcast_sta;
+ struct iwl_mvm_int_sta *bsta = &mvmvif->deflink.bcast_sta;
int ret;

lockdep_assert_held(&mvm->mutex);
@@ -2387,7 +2387,7 @@ void iwl_mvm_dealloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);

- iwl_mvm_dealloc_int_sta(mvm, &mvmvif->bcast_sta);
+ iwl_mvm_dealloc_int_sta(mvm, &mvmvif->deflink.bcast_sta);
}

/*
@@ -2418,7 +2418,7 @@ int iwl_mvm_rm_p2p_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm_int_sta *msta = &mvmvif->mcast_sta;
+ struct iwl_mvm_int_sta *msta = &mvmvif->deflink.mcast_sta;
static const u8 _maddr[] = {0x03, 0x00, 0x00, 0x00, 0x00, 0x00};
const u8 *maddr = _maddr;
struct iwl_trans_txq_scd_cfg cfg = {
@@ -2445,7 +2445,7 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
* changes in mac80211 layer.
*/
if (vif->type == NL80211_IFTYPE_ADHOC)
- mvmvif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE;
+ mvmvif->deflink.cab_queue = IWL_MVM_DQA_GCAST_QUEUE;

/*
* While in previous FWs we had to exclude cab queue from TFD queue
@@ -2453,9 +2453,10 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
*/
if (!iwl_mvm_has_new_tx_api(mvm) &&
fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_STA_TYPE)) {
- iwl_mvm_enable_txq(mvm, NULL, mvmvif->cab_queue, 0, &cfg,
+ iwl_mvm_enable_txq(mvm, NULL, mvmvif->deflink.cab_queue, 0,
+ &cfg,
timeout);
- msta->tfd_queue_msk |= BIT(mvmvif->cab_queue);
+ msta->tfd_queue_msk |= BIT(mvmvif->deflink.cab_queue);
}
ret = iwl_mvm_add_int_sta_common(mvm, msta, maddr,
mvmvif->id, mvmvif->color);
@@ -2476,10 +2477,11 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
ret = queue;
goto err;
}
- mvmvif->cab_queue = queue;
+ mvmvif->deflink.cab_queue = queue;
} else if (!fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_STA_TYPE))
- iwl_mvm_enable_txq(mvm, NULL, mvmvif->cab_queue, 0, &cfg,
+ iwl_mvm_enable_txq(mvm, NULL, mvmvif->deflink.cab_queue, 0,
+ &cfg,
timeout);

return 0;
@@ -2552,12 +2554,12 @@ int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)

lockdep_assert_held(&mvm->mutex);

- iwl_mvm_flush_sta(mvm, &mvmvif->mcast_sta, true);
+ iwl_mvm_flush_sta(mvm, &mvmvif->deflink.mcast_sta, true);

- iwl_mvm_disable_txq(mvm, NULL, mvmvif->mcast_sta.sta_id,
- &mvmvif->cab_queue, 0);
+ iwl_mvm_disable_txq(mvm, NULL, mvmvif->deflink.mcast_sta.sta_id,
+ &mvmvif->deflink.cab_queue, 0);

- ret = iwl_mvm_rm_sta_common(mvm, mvmvif->mcast_sta.sta_id);
+ ret = iwl_mvm_rm_sta_common(mvm, mvmvif->deflink.mcast_sta.sta_id);
if (ret)
IWL_WARN(mvm, "Failed sending remove station\n");

@@ -3383,8 +3385,8 @@ static struct iwl_mvm_sta *iwl_mvm_get_key_sta(struct iwl_mvm *mvm,
* station ID, then use AP's station ID.
*/
if (vif->type == NL80211_IFTYPE_STATION &&
- mvmvif->ap_sta_id != IWL_MVM_INVALID_STA) {
- u8 sta_id = mvmvif->ap_sta_id;
+ mvmvif->deflink.ap_sta_id != IWL_MVM_INVALID_STA) {
+ u8 sta_id = mvmvif->deflink.ap_sta_id;

sta = rcu_dereference_check(mvm->fw_id_to_mac_id[sta_id],
lockdep_is_held(&mvm->mutex));
@@ -3661,8 +3663,8 @@ static inline u8 *iwl_mvm_get_mac_addr(struct iwl_mvm *mvm,
return sta->addr;

if (vif->type == NL80211_IFTYPE_STATION &&
- mvmvif->ap_sta_id != IWL_MVM_INVALID_STA) {
- u8 sta_id = mvmvif->ap_sta_id;
+ mvmvif->deflink.ap_sta_id != IWL_MVM_INVALID_STA) {
+ u8 sta_id = mvmvif->deflink.ap_sta_id;
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
lockdep_is_held(&mvm->mutex));
return sta->addr;
@@ -3694,7 +3696,7 @@ static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);

- sta_id = mvmvif->mcast_sta.sta_id;
+ sta_id = mvmvif->deflink.mcast_sta.sta_id;
} else {
IWL_ERR(mvm, "Failed to find station id\n");
return -EINVAL;
@@ -3759,7 +3761,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
} else {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);

- sta_id = mvmvif->mcast_sta.sta_id;
+ sta_id = mvmvif->deflink.mcast_sta.sta_id;
}

if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
@@ -3834,7 +3836,7 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
if (mvm_sta)
sta_id = mvm_sta->sta_id;
else if (!sta && vif->type == NL80211_IFTYPE_AP && mcast)
- sta_id = iwl_mvm_vif_from_mac80211(vif)->mcast_sta.sta_id;
+ sta_id = iwl_mvm_vif_from_mac80211(vif)->deflink.mcast_sta.sta_id;


IWL_DEBUG_WEP(mvm, "mvm remove dynamic key: idx=%d sta=%d\n",
@@ -4113,17 +4115,19 @@ void iwl_mvm_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
return;

/* Need to block/unblock also multicast station */
- if (mvmvif->mcast_sta.sta_id != IWL_MVM_INVALID_STA)
+ if (mvmvif->deflink.mcast_sta.sta_id != IWL_MVM_INVALID_STA)
iwl_mvm_int_sta_modify_disable_tx(mvm, mvmvif,
- &mvmvif->mcast_sta, disable);
+ &mvmvif->deflink.mcast_sta,
+ disable);

/*
* Only unblock the broadcast station (FW blocks it for immediate
* quiet, not the driver)
*/
- if (!disable && mvmvif->bcast_sta.sta_id != IWL_MVM_INVALID_STA)
+ if (!disable && mvmvif->deflink.bcast_sta.sta_id != IWL_MVM_INVALID_STA)
iwl_mvm_int_sta_modify_disable_tx(mvm, mvmvif,
- &mvmvif->bcast_sta, disable);
+ &mvmvif->deflink.bcast_sta,
+ disable);
}

void iwl_mvm_csa_client_absent(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
@@ -4133,7 +4137,7 @@ void iwl_mvm_csa_client_absent(struct iwl_mvm *mvm, struct ieee80211_vif *vif)

rcu_read_lock();

- mvmsta = iwl_mvm_sta_from_staid_rcu(mvm, mvmvif->ap_sta_id);
+ mvmsta = iwl_mvm_sta_from_staid_rcu(mvm, mvmvif->deflink.ap_sta_id);

if (mvmsta)
iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, true);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
index e403a240a82f..3b17dd998d19 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
@@ -79,7 +79,8 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)

if (!WARN_ON(!mvm->p2p_device_vif)) {
mvmvif = iwl_mvm_vif_from_mac80211(mvm->p2p_device_vif);
- iwl_mvm_flush_sta(mvm, &mvmvif->bcast_sta, true);
+ iwl_mvm_flush_sta(mvm, &mvmvif->deflink.bcast_sta,
+ true);
}
}

@@ -170,7 +171,8 @@ static bool iwl_mvm_te_check_disconnect(struct iwl_mvm *mvm,
struct iwl_mvm_sta *mvmsta;

rcu_read_lock();
- mvmsta = iwl_mvm_sta_from_staid_rcu(mvm, mvmvif->ap_sta_id);
+ mvmsta = iwl_mvm_sta_from_staid_rcu(mvm,
+ mvmvif->deflink.ap_sta_id);
if (!WARN_ON(!mvmsta))
iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, false);
rcu_read_unlock();
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index 6e2e0791d848..890fe93896ba 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -631,7 +631,7 @@ static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm,

if (!ieee80211_has_order(fc) && !ieee80211_is_probe_req(fc) &&
is_multicast_ether_addr(hdr->addr1))
- return mvmvif->cab_queue;
+ return mvmvif->deflink.cab_queue;

WARN_ONCE(info->control.vif->type != NL80211_IFTYPE_ADHOC,
"fc=0x%02x", le16_to_cpu(fc));
@@ -668,7 +668,7 @@ static void iwl_mvm_probe_resp_set_noa(struct iwl_mvm *mvm,

rcu_read_lock();

- resp_data = rcu_dereference(mvmvif->probe_resp_data);
+ resp_data = rcu_dereference(mvmvif->deflink.probe_resp_data);
if (!resp_data)
goto out;

@@ -740,9 +740,9 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
info.control.vif->type == NL80211_IFTYPE_AP ||
info.control.vif->type == NL80211_IFTYPE_ADHOC) {
if (!ieee80211_is_data(hdr->frame_control))
- sta_id = mvmvif->bcast_sta.sta_id;
+ sta_id = mvmvif->deflink.bcast_sta.sta_id;
else
- sta_id = mvmvif->mcast_sta.sta_id;
+ sta_id = mvmvif->deflink.mcast_sta.sta_id;

queue = iwl_mvm_get_ctrl_vif_queue(mvm, &info, hdr);
} else if (info.control.vif->type == NL80211_IFTYPE_MONITOR) {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
index 14b2de65bd84..c1f6dd8f7d10 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
@@ -294,13 +294,13 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return;

mvmvif = iwl_mvm_vif_from_mac80211(vif);
- mvmvif->smps_requests[req_type] = smps_request;
+ mvmvif->deflink.smps_requests[req_type] = smps_request;
for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) {
- if (mvmvif->smps_requests[i] == IEEE80211_SMPS_STATIC) {
+ if (mvmvif->deflink.smps_requests[i] == IEEE80211_SMPS_STATIC) {
smps_mode = IEEE80211_SMPS_STATIC;
break;
}
- if (mvmvif->smps_requests[i] == IEEE80211_SMPS_DYNAMIC)
+ if (mvmvif->deflink.smps_requests[i] == IEEE80211_SMPS_DYNAMIC)
smps_mode = IEEE80211_SMPS_DYNAMIC;
}

@@ -392,12 +392,12 @@ static void iwl_mvm_diversity_iter(void *_data, u8 *mac,
struct iwl_mvm_diversity_iter_data *data = _data;
int i;

- if (mvmvif->phy_ctxt != data->ctxt)
+ if (mvmvif->deflink.phy_ctxt != data->ctxt)
return;

for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) {
- if (mvmvif->smps_requests[i] == IEEE80211_SMPS_STATIC ||
- mvmvif->smps_requests[i] == IEEE80211_SMPS_DYNAMIC) {
+ if (mvmvif->deflink.smps_requests[i] == IEEE80211_SMPS_STATIC ||
+ mvmvif->deflink.smps_requests[i] == IEEE80211_SMPS_DYNAMIC) {
data->result = false;
break;
}
@@ -495,10 +495,10 @@ static void iwl_mvm_ll_iter(void *_data, u8 *mac, struct ieee80211_vif *vif)
if (iwl_mvm_vif_low_latency(mvmvif)) {
result->result = true;

- if (!mvmvif->phy_ctxt)
+ if (!mvmvif->deflink.phy_ctxt)
return;

- band = mvmvif->phy_ctxt->channel->band;
+ band = mvmvif->deflink.phy_ctxt->channel->band;
result->result_per_band[band] = true;
}
}
@@ -819,10 +819,10 @@ static void iwl_mvm_uapsd_agg_disconnect(struct iwl_mvm *mvm,
if (!vif->cfg.assoc)
return;

- if (!mvmvif->queue_params[IEEE80211_AC_VO].uapsd &&
- !mvmvif->queue_params[IEEE80211_AC_VI].uapsd &&
- !mvmvif->queue_params[IEEE80211_AC_BE].uapsd &&
- !mvmvif->queue_params[IEEE80211_AC_BK].uapsd)
+ if (!mvmvif->deflink.queue_params[IEEE80211_AC_VO].uapsd &&
+ !mvmvif->deflink.queue_params[IEEE80211_AC_VI].uapsd &&
+ !mvmvif->deflink.queue_params[IEEE80211_AC_BE].uapsd &&
+ !mvmvif->deflink.queue_params[IEEE80211_AC_BK].uapsd)
return;

if (mvm->tcm.data[mvmvif->id].uapsd_nonagg_detect.detected)
@@ -831,7 +831,8 @@ static void iwl_mvm_uapsd_agg_disconnect(struct iwl_mvm *mvm,
mvm->tcm.data[mvmvif->id].uapsd_nonagg_detect.detected = true;
IWL_INFO(mvm,
"detected AP should do aggregation but isn't, likely due to U-APSD\n");
- schedule_delayed_work(&mvmvif->uapsd_nonagg_detected_wk, 15 * HZ);
+ schedule_delayed_work(&mvmvif->uapsd_nonagg_detected_wk,
+ 15 * HZ);
}

static void iwl_mvm_check_uapsd_agg_expected_tpt(struct iwl_mvm *mvm,
@@ -883,10 +884,10 @@ static void iwl_mvm_tcm_iterator(void *_data, u8 *mac,
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
u32 *band = _data;

- if (!mvmvif->phy_ctxt)
+ if (!mvmvif->deflink.phy_ctxt)
return;

- band[mvmvif->id] = mvmvif->phy_ctxt->channel->band;
+ band[mvmvif->id] = mvmvif->deflink.phy_ctxt->channel->band;
}

static unsigned long iwl_mvm_calc_tcm_stats(struct iwl_mvm *mvm,
--
2.38.1

2023-03-28 08:05:04

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 03/31] wifi: iwlwifi: mvm: add an indication that the new MLD API is used

From: Miri Korenblit <[email protected]>

WE can't mix between the new MLD API and the old API.
I.e. - we can't send one of the new cmds and then one of the old ones.
This will cause a FW assert. So we need an indication what API should be
used. We use the new API if:
1. FW supports it
2. We are registered to mac80211 with the new MLD ops
Add an indication which will only be true if both conditions are true.

Signed-off-by: Miri Korenblit <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 1 +
drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 3 +++
2 files changed, 4 insertions(+)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 72056cccc77e..443f0b80b63e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -1155,6 +1155,7 @@ struct iwl_mvm {
unsigned long last_reset_or_resume_time_jiffies;

bool sta_remove_requires_queue_remove;
+ bool mld_api_is_used;

bool pldr_sync;

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index 70926bb1df6c..5c8784ddfa66 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -1295,6 +1295,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
mvm->sta_remove_requires_queue_remove =
trans_cfg.queue_alloc_cmd_ver > 0;

+ /* Until we register with the MLD ops - we don't use the MLD API */
+ mvm->mld_api_is_used = false;
+
/* Configure transport layer */
iwl_trans_configure(mvm->trans, &trans_cfg);

--
2.38.1

2023-03-28 08:05:07

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 02/31] wifi: iwlwifi: mvm: sta preparation for MLO

From: Gregory Greenman <[email protected]>

Split iwl_mvm_sta into general and link specific parts. As a first
step, all link dependent parameters reside in deflink.

The change was done mostly using the spatch below with some manual
adjustments.

@iwl_mvm_sta@
struct iwl_mvm_sta *s;
identifier var = {sta_id, lq_sta, avg_energy};
@@

(
s->
- var
+ deflink.var
)

Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/coex.c | 2 +-
.../net/wireless/intel/iwlwifi/mvm/debugfs.c | 2 +-
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 19 +--
.../net/wireless/intel/iwlwifi/mvm/mld-key.c | 2 +-
.../net/wireless/intel/iwlwifi/mvm/mld-sta.c | 4 +-
.../net/wireless/intel/iwlwifi/mvm/rs-fw.c | 10 +-
drivers/net/wireless/intel/iwlwifi/mvm/rs.c | 42 +++----
drivers/net/wireless/intel/iwlwifi/mvm/rx.c | 6 +-
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 5 +-
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 113 ++++++++++--------
drivers/net/wireless/intel/iwlwifi/mvm/sta.h | 37 ++++--
drivers/net/wireless/intel/iwlwifi/mvm/tdls.c | 8 +-
drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 34 +++---
13 files changed, 161 insertions(+), 123 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
index 73ef1da3ccac..21ba3c7dd9b4 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
@@ -194,7 +194,7 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
if (mvmsta->bt_reduced_txpower == enable)
return 0;

- value = mvmsta->sta_id;
+ value = mvmsta->deflink.sta_id;

if (enable)
value |= BT_REDUCED_TX_POWER_BIT;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
index 2a6f42f07c9e..b5eb0ee298ad 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
@@ -376,7 +376,7 @@ static ssize_t iwl_dbgfs_rs_data_read(struct file *file, char __user *user_buf,
{
struct ieee80211_sta *sta = file->private_data;
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
- struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->lq_sta.rs_fw;
+ struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->deflink.lq_sta.rs_fw;
struct iwl_mvm *mvm = lq_sta->pers.drv;
static const size_t bufsz = 2048;
char *buff;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 163515db6828..282c15e74f08 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -922,7 +922,7 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
switch (action) {
case IEEE80211_AMPDU_RX_START:
if (iwl_mvm_vif_from_mac80211(vif)->deflink.ap_sta_id ==
- iwl_mvm_sta_from_mac80211(sta)->sta_id) {
+ iwl_mvm_sta_from_mac80211(sta)->deflink.sta_id) {
struct iwl_mvm_vif *mvmvif;
u16 macid = iwl_mvm_vif_from_mac80211(vif)->id;
struct iwl_mvm_tcm_mac *mdata = &mvm->tcm.data[macid];
@@ -3116,7 +3116,7 @@ static void __iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
*/
break;
case STA_NOTIFY_AWAKE:
- if (WARN_ON(mvmsta->sta_id == IWL_MVM_INVALID_STA))
+ if (WARN_ON(mvmsta->deflink.sta_id == IWL_MVM_INVALID_STA))
break;

if (txqs)
@@ -3206,8 +3206,8 @@ static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
* callback deleted the station.
*/
mutex_lock(&mvm->mutex);
- if (sta == rcu_access_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id]))
- rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id],
+ if (sta == rcu_access_pointer(mvm->fw_id_to_mac_id[mvm_sta->deflink.sta_id]))
+ rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->deflink.sta_id],
ERR_PTR(-ENOENT));

mutex_unlock(&mvm->mutex);
@@ -3534,7 +3534,8 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
!iwlwifi_mod_params.disable_11ax) ||
(vif->bss_conf.eht_support &&
!iwlwifi_mod_params.disable_11be))
- iwl_mvm_cfg_he_sta(mvm, vif, mvm_sta->sta_id);
+ iwl_mvm_cfg_he_sta(mvm, vif,
+ mvm_sta->deflink.sta_id);
} else if (vif->type == NL80211_IFTYPE_STATION) {
vif->bss_conf.he_support = sta->deflink.he_cap.has_he;

@@ -5470,13 +5471,13 @@ static void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw,
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);

- if (mvmsta->avg_energy) {
- sinfo->signal_avg = -(s8)mvmsta->avg_energy;
+ if (mvmsta->deflink.avg_energy) {
+ sinfo->signal_avg = -(s8)mvmsta->deflink.avg_energy;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);
}

if (iwl_mvm_has_tlc_offload(mvm)) {
- struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->lq_sta.rs_fw;
+ struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->deflink.lq_sta.rs_fw;

iwl_mvm_set_sta_rate(lq_sta->last_rate_n_flags, &sinfo->txrate);
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
@@ -5491,7 +5492,7 @@ static void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw,

mutex_lock(&mvm->mutex);

- if (mvmvif->deflink.ap_sta_id != mvmsta->sta_id)
+ if (mvmvif->deflink.ap_sta_id != mvmsta->deflink.sta_id)
goto unlock;

if (iwl_mvm_request_statistics(mvm, false))
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
index 4eaba89ba0c5..154f145396ce 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
@@ -22,7 +22,7 @@ static u32 iwl_mvm_get_sec_sta_mask(struct iwl_mvm *mvm,
if (sta) {
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);

- return BIT(mvmsta->sta_id);
+ return BIT(mvmsta->deflink.sta_id);
}

if (vif->type == NL80211_IFTYPE_STATION &&
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
index b2a7fa09f900..c063383247f9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
@@ -243,7 +243,7 @@ static int iwl_mvm_mld_disable_txq(struct iwl_mvm *mvm,
.operation = cpu_to_le32(IWL_SCD_QUEUE_REMOVE),
.u.remove.tid = cpu_to_le32(tid),
.u.remove.sta_mask =
- cpu_to_le32(BIT(mvmsta->sta_id)),
+ cpu_to_le32(BIT(mvmsta->deflink.sta_id)),
};

ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0,
@@ -348,7 +348,7 @@ static void iwl_mvm_mld_sta_modify_disable_tx(struct iwl_mvm *mvm,

mvm_sta->disable_tx = disable;

- cmd.sta_id = cpu_to_le32(mvm_sta->sta_id);
+ cmd.sta_id = cpu_to_le32(mvm_sta->deflink.sta_id);
cmd.disable = cpu_to_le32(disable);

ret = iwl_mvm_send_cmd_pdu(mvm,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
index e3fb1b2cea6d..a33673c6ae7d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
@@ -438,7 +438,7 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,

flags = le32_to_cpu(notif->flags);

- lq_sta = &mvmsta->lq_sta.rs_fw;
+ lq_sta = &mvmsta->deflink.lq_sta.rs_fw;

if (flags & IWL_TLC_NOTIF_FLAG_RATE) {
char pretty_rate[100];
@@ -547,12 +547,12 @@ void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
{
struct ieee80211_hw *hw = mvm->hw;
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
- struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->lq_sta.rs_fw;
+ struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->deflink.lq_sta.rs_fw;
u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, TLC_MNG_CONFIG_CMD);
struct ieee80211_supported_band *sband = hw->wiphy->bands[band];
u16 max_amsdu_len = rs_fw_get_max_amsdu_len(sta);
struct iwl_tlc_config_cmd_v4 cfg_cmd = {
- .sta_id = mvmsta->sta_id,
+ .sta_id = mvmsta->deflink.sta_id,
.max_ch_width = update ?
rs_fw_bw_from_sta_bw(sta) : IWL_TLC_MNG_CH_WIDTH_20MHZ,
.flags = cpu_to_le16(rs_fw_get_config_flags(mvm, sta, sband)),
@@ -641,12 +641,12 @@ int rs_fw_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,

void iwl_mvm_rs_add_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta)
{
- struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->lq_sta.rs_fw;
+ struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->deflink.lq_sta.rs_fw;

IWL_DEBUG_RATE(mvm, "create station rate scale window\n");

lq_sta->pers.drv = mvm;
- lq_sta->pers.sta_id = mvmsta->sta_id;
+ lq_sta->pers.sta_id = mvmsta->deflink.sta_id;
lq_sta->pers.chains = 0;
memset(lq_sta->pers.chain_signal, 0, sizeof(lq_sta->pers.chain_signal));
lq_sta->pers.last_rssi = S8_MIN;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
index bd135b7168cb..1b0e99377156 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
@@ -754,7 +754,7 @@ static int rs_collect_tlc_data(struct iwl_mvm *mvm,
return -EINVAL;

if (tbl->column != RS_COLUMN_INVALID) {
- struct lq_sta_pers *pers = &mvmsta->lq_sta.rs_drv.pers;
+ struct lq_sta_pers *pers = &mvmsta->deflink.lq_sta.rs_drv.pers;

pers->tx_stats[tbl->column][scale_index].total += attempts;
pers->tx_stats[tbl->column][scale_index].success += successes;
@@ -2599,7 +2599,7 @@ void rs_update_last_rssi(struct iwl_mvm *mvm,
struct iwl_mvm_sta *mvmsta,
struct ieee80211_rx_status *rx_status)
{
- struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta.rs_drv;
+ struct iwl_lq_sta *lq_sta = &mvmsta->deflink.lq_sta.rs_drv;
int i;

lq_sta->pers.chains = rx_status->chains;
@@ -2711,7 +2711,7 @@ static void *rs_drv_alloc_sta(void *mvm_rate, struct ieee80211_sta *sta,
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_op_mode *op_mode = (struct iwl_op_mode *)mvm_rate;
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
- struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta.rs_drv;
+ struct iwl_lq_sta *lq_sta = &mvmsta->deflink.lq_sta.rs_drv;

IWL_DEBUG_RATE(mvm, "create station rate scale window\n");

@@ -2917,18 +2917,18 @@ static void rs_drv_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
- struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta.rs_drv;
+ struct iwl_lq_sta *lq_sta = &mvmsta->deflink.lq_sta.rs_drv;
struct ieee80211_supported_band *sband;
unsigned long supp; /* must be unsigned long for for_each_set_bit */

- lockdep_assert_held(&mvmsta->lq_sta.rs_drv.pers.lock);
+ lockdep_assert_held(&mvmsta->deflink.lq_sta.rs_drv.pers.lock);

/* clear all non-persistent lq data */
memset(lq_sta, 0, offsetof(typeof(*lq_sta), pers));

sband = hw->wiphy->bands[band];

- lq_sta->lq.sta_id = mvmsta->sta_id;
+ lq_sta->lq.sta_id = mvmsta->deflink.sta_id;
mvmsta->amsdu_enabled = 0;
mvmsta->max_amsdu_len = sta->cur->max_amsdu_len;

@@ -2940,7 +2940,7 @@ static void rs_drv_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,

IWL_DEBUG_RATE(mvm,
"LQ: *** rate scale station global init for station %d ***\n",
- mvmsta->sta_id);
+ mvmsta->deflink.sta_id);
/* TODO: what is a good starting rate for STA? About middle? Maybe not
* the lowest or the highest rate.. Could consider using RSSI from
* previous packets? Need to have IEEE 802.1X auth succeed immediately
@@ -3032,7 +3032,7 @@ static void __iwl_mvm_rs_tx_status(struct iwl_mvm *mvm,
u8 lq_color = RS_DRV_DATA_LQ_COLOR_GET(tlc_info);
u32 tx_resp_hwrate = (uintptr_t)info->status.status_driver_data[1];
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
- struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta.rs_drv;
+ struct iwl_lq_sta *lq_sta = &mvmsta->deflink.lq_sta.rs_drv;

if (!lq_sta->pers.drv) {
IWL_DEBUG_RATE(mvm, "Rate scaling not initialized yet.\n");
@@ -3256,11 +3256,11 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
/* If it's locked we are in middle of init flow
* just wait for next tx status to update the lq_sta data
*/
- if (!spin_trylock(&mvmsta->lq_sta.rs_drv.pers.lock))
+ if (!spin_trylock(&mvmsta->deflink.lq_sta.rs_drv.pers.lock))
return;

__iwl_mvm_rs_tx_status(mvm, sta, tid, info, ndp);
- spin_unlock(&mvmsta->lq_sta.rs_drv.pers.lock);
+ spin_unlock(&mvmsta->deflink.lq_sta.rs_drv.pers.lock);
}

#ifdef CONFIG_MAC80211_DEBUGFS
@@ -3436,7 +3436,7 @@ static void rs_bfer_active_iter(void *_data,
{
struct rs_bfer_active_iter_data *data = _data;
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
- struct iwl_lq_cmd *lq_cmd = &mvmsta->lq_sta.rs_drv.lq;
+ struct iwl_lq_cmd *lq_cmd = &mvmsta->deflink.lq_sta.rs_drv.lq;
u32 ss_params = le32_to_cpu(lq_cmd->ss_params);

if (sta == data->exclude_sta)
@@ -3467,7 +3467,8 @@ static int rs_bfer_priority(struct iwl_mvm_sta *sta)
prio = 1;
break;
default:
- WARN_ONCE(true, "viftype %d sta_id %d", viftype, sta->sta_id);
+ WARN_ONCE(true, "viftype %d sta_id %d", viftype,
+ sta->deflink.sta_id);
prio = -1;
}

@@ -3544,12 +3545,12 @@ static void rs_set_lq_ss_params(struct iwl_mvm *mvm,
}

IWL_DEBUG_RATE(mvm, "Found existing sta %d with BFER activated\n",
- bfer_mvmsta->sta_id);
+ bfer_mvmsta->deflink.sta_id);

/* Disallow BFER on another STA if active and we're a higher priority */
if (rs_bfer_priority_cmp(mvmsta, bfer_mvmsta) > 0) {
struct iwl_lq_cmd *bfersta_lq_cmd =
- &bfer_mvmsta->lq_sta.rs_drv.lq;
+ &bfer_mvmsta->deflink.lq_sta.rs_drv.lq;
u32 bfersta_ss_params = le32_to_cpu(bfersta_lq_cmd->ss_params);

bfersta_ss_params &= ~LQ_SS_BFER_ALLOWED;
@@ -3559,7 +3560,7 @@ static void rs_set_lq_ss_params(struct iwl_mvm *mvm,
ss_params |= LQ_SS_BFER_ALLOWED;
IWL_DEBUG_RATE(mvm,
"Lower priority BFER sta found (%d). Switch BFER\n",
- bfer_mvmsta->sta_id);
+ bfer_mvmsta->deflink.sta_id);
}
out:
lq_cmd->ss_params = cpu_to_le32(ss_params);
@@ -3744,7 +3745,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,

struct iwl_lq_sta *lq_sta = file->private_data;
struct iwl_mvm_sta *mvmsta =
- container_of(lq_sta, struct iwl_mvm_sta, lq_sta.rs_drv);
+ container_of(lq_sta, struct iwl_mvm_sta, deflink.lq_sta.rs_drv);
struct iwl_mvm *mvm;
struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
struct rs_rate *rate = &tbl->rate;
@@ -4045,7 +4046,8 @@ static void rs_drv_add_sta_debugfs(void *mvm, void *priv_sta,
struct iwl_lq_sta *lq_sta = priv_sta;
struct iwl_mvm_sta *mvmsta;

- mvmsta = container_of(lq_sta, struct iwl_mvm_sta, lq_sta.rs_drv);
+ mvmsta = container_of(lq_sta, struct iwl_mvm_sta,
+ deflink.lq_sta.rs_drv);

if (!mvmsta->vif)
return;
@@ -4102,9 +4104,9 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
} else {
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);

- spin_lock(&mvmsta->lq_sta.rs_drv.pers.lock);
+ spin_lock(&mvmsta->deflink.lq_sta.rs_drv.pers.lock);
rs_drv_rate_init(mvm, sta, band);
- spin_unlock(&mvmsta->lq_sta.rs_drv.pers.lock);
+ spin_unlock(&mvmsta->deflink.lq_sta.rs_drv.pers.lock);
}
}

@@ -4121,7 +4123,7 @@ void iwl_mvm_rate_control_unregister(void)
static int rs_drv_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
bool enable)
{
- struct iwl_lq_cmd *lq = &mvmsta->lq_sta.rs_drv.lq;
+ struct iwl_lq_cmd *lq = &mvmsta->deflink.lq_sta.rs_drv.lq;

lockdep_assert_held(&mvm->mutex);

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
index 4105b79db467..e08dca8d2baa 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
@@ -241,7 +241,7 @@ static void iwl_mvm_rx_handle_tcm(struct iwl_mvm *mvm,
!mvmvif->deflink.queue_params[IEEE80211_AC_VI].uapsd &&
!mvmvif->deflink.queue_params[IEEE80211_AC_BE].uapsd &&
!mvmvif->deflink.queue_params[IEEE80211_AC_BK].uapsd) ||
- mvmsta->sta_id != mvmvif->deflink.ap_sta_id)
+ mvmsta->deflink.sta_id != mvmvif->deflink.ap_sta_id)
return;

if (rate_n_flags & RATE_MCS_HT_MSK_V1) {
@@ -712,14 +712,14 @@ static void iwl_mvm_stats_energy_iter(void *_data,
{
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
u8 *energy = _data;
- u32 sta_id = mvmsta->sta_id;
+ u32 sta_id = mvmsta->deflink.sta_id;

if (WARN_ONCE(sta_id >= IWL_MVM_STATION_COUNT_MAX, "sta_id %d >= %d",
sta_id, IWL_MVM_STATION_COUNT_MAX))
return;

if (energy[sta_id])
- mvmsta->avg_energy = energy[sta_id];
+ mvmsta->deflink.avg_energy = energy[sta_id];

}

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
index 6286132f165a..b160ae137c4a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
@@ -979,9 +979,10 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
return false;
}

- if (WARN(tid != baid_data->tid || mvm_sta->sta_id != baid_data->sta_id,
+ if (WARN(tid != baid_data->tid ||
+ mvm_sta->deflink.sta_id != baid_data->sta_id,
"baid 0x%x is mapped to sta:%d tid:%d, but was received for sta:%d tid:%d\n",
- baid, baid_data->sta_id, baid_data->tid, mvm_sta->sta_id,
+ baid, baid_data->sta_id, baid_data->tid, mvm_sta->deflink.sta_id,
tid))
return false;

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index c3b81021898b..d01c67e1ce2a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -119,7 +119,7 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
{
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_mvm_add_sta_cmd add_sta_cmd = {
- .sta_id = mvm_sta->sta_id,
+ .sta_id = mvm_sta->deflink.sta_id,
.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color),
.add_modify = update ? 1 : 0,
.station_flags_msk = cpu_to_le32(STA_FLG_FAT_EN_MSK |
@@ -314,7 +314,7 @@ static int iwl_mvm_invalidate_sta_queue(struct iwl_mvm *mvm, int queue,
mvmsta->tid_disable_agg |= disable_agg_tids;

cmd.mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color);
- cmd.sta_id = mvmsta->sta_id;
+ cmd.sta_id = mvmsta->deflink.sta_id;
cmd.add_modify = STA_MODE_MODIFY;
cmd.modify_mask = STA_MODIFY_QUEUES;
if (disable_agg_tids)
@@ -856,15 +856,15 @@ static int iwl_mvm_sta_alloc_queue_tvqm(struct iwl_mvm *mvm,

IWL_DEBUG_TX_QUEUES(mvm,
"Allocating queue for sta %d on tid %d\n",
- mvmsta->sta_id, tid);
- queue = iwl_mvm_tvqm_enable_txq(mvm, sta, mvmsta->sta_id,
+ mvmsta->deflink.sta_id, tid);
+ queue = iwl_mvm_tvqm_enable_txq(mvm, sta, mvmsta->deflink.sta_id,
tid, wdg_timeout);
if (queue < 0)
return queue;

mvmtxq->txq_id = queue;
mvm->tvqm_info[queue].txq_tid = tid;
- mvm->tvqm_info[queue].sta_id = mvmsta->sta_id;
+ mvm->tvqm_info[queue].sta_id = mvmsta->deflink.sta_id;

IWL_DEBUG_TX_QUEUES(mvm, "Allocated queue is %d\n", queue);

@@ -1049,7 +1049,7 @@ static void iwl_mvm_unshare_queue(struct iwl_mvm *mvm, int queue)
mvmsta->tid_disable_agg &= ~BIT(tid);

cmd.mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color);
- cmd.sta_id = mvmsta->sta_id;
+ cmd.sta_id = mvmsta->deflink.sta_id;
cmd.add_modify = STA_MODE_MODIFY;
cmd.modify_mask = STA_MODIFY_TID_DISABLE_TX;
cmd.tfd_queue_msk = cpu_to_le32(mvmsta->tfd_queue_msk);
@@ -1274,7 +1274,7 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_trans_txq_scd_cfg cfg = {
.fifo = iwl_mvm_mac_ac_to_tx_fifo(mvm, ac),
- .sta_id = mvmsta->sta_id,
+ .sta_id = mvmsta->deflink.sta_id,
.tid = tid,
.frame_limit = IWL_FRAME_LIMIT,
};
@@ -1300,7 +1300,7 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
spin_unlock_bh(&mvmsta->lock);

if (tid == IWL_MAX_TID_COUNT) {
- queue = iwl_mvm_find_free_queue(mvm, mvmsta->sta_id,
+ queue = iwl_mvm_find_free_queue(mvm, mvmsta->deflink.sta_id,
IWL_MVM_DQA_MIN_MGMT_QUEUE,
IWL_MVM_DQA_MAX_MGMT_QUEUE);
if (queue >= IWL_MVM_DQA_MIN_MGMT_QUEUE)
@@ -1319,12 +1319,12 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
}

if (queue < 0)
- queue = iwl_mvm_find_free_queue(mvm, mvmsta->sta_id,
+ queue = iwl_mvm_find_free_queue(mvm, mvmsta->deflink.sta_id,
IWL_MVM_DQA_MIN_DATA_QUEUE,
IWL_MVM_DQA_MAX_DATA_QUEUE);
if (queue < 0) {
/* try harder - perhaps kill an inactive queue */
- queue = iwl_mvm_inactivity_check(mvm, mvmsta->sta_id);
+ queue = iwl_mvm_inactivity_check(mvm, mvmsta->deflink.sta_id);
}

/* No free queue - we'll have to share */
@@ -1364,7 +1364,7 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
IWL_DEBUG_TX_QUEUES(mvm,
"Allocating %squeue #%d to sta %d on tid %d\n",
shared_queue ? "shared " : "", queue,
- mvmsta->sta_id, tid);
+ mvmsta->deflink.sta_id, tid);

if (shared_queue) {
/* Disable any open aggs on this queue */
@@ -1431,7 +1431,7 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,

out_err:
queue_tmp = queue;
- iwl_mvm_disable_txq(mvm, sta, mvmsta->sta_id, &queue_tmp, tid);
+ iwl_mvm_disable_txq(mvm, sta, mvmsta->deflink.sta_id, &queue_tmp, tid);

return ret;
}
@@ -1500,12 +1500,12 @@ static int iwl_mvm_reserve_sta_stream(struct iwl_mvm *mvm,
IWL_MVM_QUEUE_FREE))
queue = IWL_MVM_DQA_BSS_CLIENT_QUEUE;
else
- queue = iwl_mvm_find_free_queue(mvm, mvmsta->sta_id,
+ queue = iwl_mvm_find_free_queue(mvm, mvmsta->deflink.sta_id,
IWL_MVM_DQA_MIN_DATA_QUEUE,
IWL_MVM_DQA_MAX_DATA_QUEUE);
if (queue < 0) {
/* try again - this time kick out a queue if needed */
- queue = iwl_mvm_inactivity_check(mvm, mvmsta->sta_id);
+ queue = iwl_mvm_inactivity_check(mvm, mvmsta->deflink.sta_id);
if (queue < 0) {
IWL_ERR(mvm, "No available queues for new station\n");
return -ENOSPC;
@@ -1516,7 +1516,7 @@ static int iwl_mvm_reserve_sta_stream(struct iwl_mvm *mvm,
mvmsta->reserved_queue = queue;

IWL_DEBUG_TX_QUEUES(mvm, "Reserving data queue #%d for sta_id %d\n",
- queue, mvmsta->sta_id);
+ queue, mvmsta->deflink.sta_id);

return 0;
}
@@ -1536,7 +1536,7 @@ static void iwl_mvm_realloc_queues_after_restart(struct iwl_mvm *mvm,
iwl_mvm_get_wd_timeout(mvm, mvm_sta->vif, false, false);
int i;
struct iwl_trans_txq_scd_cfg cfg = {
- .sta_id = mvm_sta->sta_id,
+ .sta_id = mvm_sta->deflink.sta_id,
.frame_limit = IWL_FRAME_LIMIT,
};

@@ -1558,9 +1558,9 @@ static void iwl_mvm_realloc_queues_after_restart(struct iwl_mvm *mvm,
if (iwl_mvm_has_new_tx_api(mvm)) {
IWL_DEBUG_TX_QUEUES(mvm,
"Re-mapping sta %d tid %d\n",
- mvm_sta->sta_id, i);
+ mvm_sta->deflink.sta_id, i);
txq_id = iwl_mvm_tvqm_enable_txq(mvm, sta,
- mvm_sta->sta_id,
+ mvm_sta->deflink.sta_id,
i, wdg);
/*
* on failures, just set it to IWL_MVM_INVALID_QUEUE
@@ -1589,7 +1589,8 @@ static void iwl_mvm_realloc_queues_after_restart(struct iwl_mvm *mvm,

IWL_DEBUG_TX_QUEUES(mvm,
"Re-mapping sta %d tid %d to queue %d\n",
- mvm_sta->sta_id, i, txq_id);
+ mvm_sta->deflink.sta_id, i,
+ txq_id);

iwl_mvm_enable_txq(mvm, sta, txq_id, seq, &cfg, wdg);
mvm->queue_info[txq_id].status = IWL_MVM_QUEUE_READY;
@@ -1658,7 +1659,9 @@ static int iwl_mvm_sta_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif,

lockdep_assert_held(&mvm->mutex);

- mvm_sta->sta_id = sta_id;
+ mvm_sta->deflink.sta_id = sta_id;
+ rcu_assign_pointer(mvm_sta->link[0], &mvm_sta->deflink);
+
mvm_sta->mac_id_n_color = FW_CMD_ID_AND_COLOR(mvmvif->id,
mvmvif->color);
mvm_sta->vif = vif;
@@ -1724,7 +1727,7 @@ static int iwl_mvm_sta_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (iwl_mvm_has_tlc_offload(mvm))
iwl_mvm_rs_add_sta(mvm, mvm_sta);
else
- spin_lock_init(&mvm_sta->lq_sta.rs_drv.pers.lock);
+ spin_lock_init(&mvm_sta->deflink.lq_sta.rs_drv.pers.lock);

iwl_mvm_toggle_tx_ant(mvm, &mvm_sta->tx_ant);

@@ -1747,7 +1750,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
sta_id = iwl_mvm_find_free_sta_id(mvm,
ieee80211_vif_type_p2p(vif));
else
- sta_id = mvm_sta->sta_id;
+ sta_id = mvm_sta->deflink.sta_id;

if (sta_id == IWL_MVM_INVALID_STA)
return -ENOSPC;
@@ -1810,7 +1813,7 @@ int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
lockdep_assert_held(&mvm->mutex);

cmd.mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color);
- cmd.sta_id = mvmsta->sta_id;
+ cmd.sta_id = mvmsta->deflink.sta_id;
cmd.add_modify = STA_MODE_MODIFY;
cmd.station_flags = drain ? cpu_to_le32(STA_FLG_DRAIN_FLOW) : 0;
cmd.station_flags_msk = cpu_to_le32(STA_FLG_DRAIN_FLOW);
@@ -1825,12 +1828,12 @@ int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
switch (status & IWL_ADD_STA_STATUS_MASK) {
case ADD_STA_SUCCESS:
IWL_DEBUG_INFO(mvm, "Frames for staid %d will drained in fw\n",
- mvmsta->sta_id);
+ mvmsta->deflink.sta_id);
break;
default:
ret = -EIO;
IWL_ERR(mvm, "Couldn't drain frames for staid %d\n",
- mvmsta->sta_id);
+ mvmsta->deflink.sta_id);
break;
}

@@ -1882,7 +1885,7 @@ static void iwl_mvm_disable_sta_queues(struct iwl_mvm *mvm,
if (mvm_sta->tid_data[i].txq_id == IWL_MVM_INVALID_QUEUE)
continue;

- iwl_mvm_disable_txq(mvm, sta, mvm_sta->sta_id,
+ iwl_mvm_disable_txq(mvm, sta, mvm_sta->deflink.sta_id,
&mvm_sta->tid_data[i].txq_id, i);
mvm_sta->tid_data[i].txq_id = IWL_MVM_INVALID_QUEUE;
}
@@ -1926,7 +1929,7 @@ static bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
- u8 sta_id = mvm_sta->sta_id;
+ u8 sta_id = mvm_sta->deflink.sta_id;

lockdep_assert_held(&mvm->mutex);

@@ -2022,8 +2025,8 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
if (iwl_mvm_sta_del(mvm, vif, sta, &ret))
return ret;

- ret = iwl_mvm_rm_sta_common(mvm, mvm_sta->sta_id);
- RCU_INIT_POINTER(mvm->fw_id_to_mac_id[mvm_sta->sta_id], NULL);
+ ret = iwl_mvm_rm_sta_common(mvm, mvm_sta->deflink.sta_id);
+ RCU_INIT_POINTER(mvm->fw_id_to_mac_id[mvm_sta->deflink.sta_id], NULL);

return ret;
}
@@ -2654,7 +2657,7 @@ static int iwl_mvm_fw_baid_op_sta(struct iwl_mvm *mvm,
{
struct iwl_mvm_add_sta_cmd cmd = {
.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color),
- .sta_id = mvm_sta->sta_id,
+ .sta_id = mvm_sta->deflink.sta_id,
.add_modify = STA_MODE_MODIFY,
};
u32 status;
@@ -2710,7 +2713,8 @@ static int iwl_mvm_fw_baid_op_cmd(struct iwl_mvm *mvm,
BUILD_BUG_ON(sizeof(struct iwl_rx_baid_cfg_resp) != sizeof(baid));

if (start) {
- cmd.alloc.sta_id_mask = cpu_to_le32(BIT(mvm_sta->sta_id));
+ cmd.alloc.sta_id_mask =
+ cpu_to_le32(BIT(mvm_sta->deflink.sta_id));
cmd.alloc.tid = tid;
cmd.alloc.ssn = cpu_to_le16(ssn);
cmd.alloc.win_size = cpu_to_le16(buf_size);
@@ -2719,7 +2723,8 @@ static int iwl_mvm_fw_baid_op_cmd(struct iwl_mvm *mvm,
cmd.remove_v1.baid = cpu_to_le32(baid);
BUILD_BUG_ON(sizeof(cmd.remove_v1) > sizeof(cmd.remove));
} else {
- cmd.remove.sta_id_mask = cpu_to_le32(BIT(mvm_sta->sta_id));
+ cmd.remove.sta_id_mask =
+ cpu_to_le32(BIT(mvm_sta->deflink.sta_id));
cmd.remove.tid = cpu_to_le32(tid);
}

@@ -2843,7 +2848,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
iwl_mvm_rx_agg_session_expired, 0);
baid_data->mvm = mvm;
baid_data->tid = tid;
- baid_data->sta_id = mvm_sta->sta_id;
+ baid_data->sta_id = mvm_sta->deflink.sta_id;

mvm_sta->tid_to_baid[tid] = baid;
if (timeout)
@@ -2858,7 +2863,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
* RX is being processed in parallel
*/
IWL_DEBUG_HT(mvm, "Sta %d(%d) is assigned to BAID %d\n",
- mvm_sta->sta_id, tid, baid);
+ mvm_sta->deflink.sta_id, tid, baid);
WARN_ON(rcu_access_pointer(mvm->baid_map[baid]));
rcu_assign_pointer(mvm->baid_map[baid], baid_data);
} else {
@@ -2920,7 +2925,7 @@ int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
}

cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color);
- cmd.sta_id = mvm_sta->sta_id;
+ cmd.sta_id = mvm_sta->deflink.sta_id;
cmd.add_modify = STA_MODE_MODIFY;
if (!iwl_mvm_has_new_tx_api(mvm))
cmd.modify_mask = STA_MODIFY_QUEUES;
@@ -3012,7 +3017,7 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
*/
txq_id = mvmsta->tid_data[tid].txq_id;
if (txq_id == IWL_MVM_INVALID_QUEUE) {
- ret = iwl_mvm_find_free_queue(mvm, mvmsta->sta_id,
+ ret = iwl_mvm_find_free_queue(mvm, mvmsta->deflink.sta_id,
IWL_MVM_DQA_MIN_DATA_QUEUE,
IWL_MVM_DQA_MAX_DATA_QUEUE);
if (ret < 0) {
@@ -3050,7 +3055,8 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,

IWL_DEBUG_TX_QUEUES(mvm,
"Start AGG: sta %d tid %d queue %d - ssn = %d, next_recl = %d\n",
- mvmsta->sta_id, tid, txq_id, tid_data->ssn,
+ mvmsta->deflink.sta_id, tid, txq_id,
+ tid_data->ssn,
tid_data->next_reclaimed);

/*
@@ -3089,7 +3095,7 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
u16 ssn;

struct iwl_trans_txq_scd_cfg cfg = {
- .sta_id = mvmsta->sta_id,
+ .sta_id = mvmsta->deflink.sta_id,
.tid = tid,
.frame_limit = buf_size,
.aggregate = true,
@@ -3161,7 +3167,7 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
}

ret = iwl_mvm_reconfig_scd(mvm, queue, cfg.fifo,
- mvmsta->sta_id, tid,
+ mvmsta->deflink.sta_id, tid,
buf_size, ssn);
if (ret) {
IWL_ERR(mvm,
@@ -3194,12 +3200,13 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
*/
mvmsta->max_agg_bufsize =
min(mvmsta->max_agg_bufsize, buf_size);
- mvmsta->lq_sta.rs_drv.lq.agg_frame_cnt_limit = mvmsta->max_agg_bufsize;
+ mvmsta->deflink.lq_sta.rs_drv.lq.agg_frame_cnt_limit =
+ mvmsta->max_agg_bufsize;

IWL_DEBUG_HT(mvm, "Tx aggregation enabled on ra = %pM tid = %d\n",
sta->addr, tid);

- return iwl_mvm_send_lq_cmd(mvm, &mvmsta->lq_sta.rs_drv.lq);
+ return iwl_mvm_send_lq_cmd(mvm, &mvmsta->deflink.lq_sta.rs_drv.lq);
}

static void iwl_mvm_unreserve_agg_queue(struct iwl_mvm *mvm,
@@ -3248,7 +3255,8 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
txq_id = tid_data->txq_id;

IWL_DEBUG_TX_QUEUES(mvm, "Stop AGG: sta %d tid %d q %d state %d\n",
- mvmsta->sta_id, tid, txq_id, tid_data->state);
+ mvmsta->deflink.sta_id, tid, txq_id,
+ tid_data->state);

mvmsta->agg_tids &= ~BIT(tid);

@@ -3287,7 +3295,7 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
default:
IWL_ERR(mvm,
"Stopping AGG while state not ON or starting for %d on %d (%d)\n",
- mvmsta->sta_id, tid, tid_data->state);
+ mvmsta->deflink.sta_id, tid, tid_data->state);
IWL_ERR(mvm,
"\ttid_data->txq_id = %d\n", tid_data->txq_id);
err = -EINVAL;
@@ -3313,7 +3321,8 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
spin_lock_bh(&mvmsta->lock);
txq_id = tid_data->txq_id;
IWL_DEBUG_TX_QUEUES(mvm, "Flush AGG: sta %d tid %d q %d state %d\n",
- mvmsta->sta_id, tid, txq_id, tid_data->state);
+ mvmsta->deflink.sta_id, tid, txq_id,
+ tid_data->state);
old_state = tid_data->state;
tid_data->state = IWL_AGG_OFF;
mvmsta->agg_tids &= ~BIT(tid);
@@ -3325,7 +3334,7 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
iwl_mvm_drain_sta(mvm, mvmsta, true);

if (iwl_mvm_has_new_tx_api(mvm)) {
- if (iwl_mvm_flush_sta_tids(mvm, mvmsta->sta_id,
+ if (iwl_mvm_flush_sta_tids(mvm, mvmsta->deflink.sta_id,
BIT(tid)))
IWL_ERR(mvm, "Couldn't flush the AGG queue\n");
iwl_trans_wait_txq_empty(mvm->trans, txq_id);
@@ -3690,7 +3699,7 @@ static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
if (sta) {
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);

- sta_id = mvm_sta->sta_id;
+ sta_id = mvm_sta->deflink.sta_id;
mfp = sta->mfp;
} else if (vif->type == NL80211_IFTYPE_AP &&
!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
@@ -3739,7 +3748,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
IWL_ERR(mvm, "Failed to find station\n");
return -EINVAL;
}
- sta_id = mvm_sta->sta_id;
+ sta_id = mvm_sta->deflink.sta_id;

/*
* It is possible that the 'sta' parameter is NULL, and thus
@@ -3834,7 +3843,7 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
/* Get the station from the mvm local station table */
mvm_sta = iwl_mvm_get_key_sta(mvm, vif, sta);
if (mvm_sta)
- sta_id = mvm_sta->sta_id;
+ sta_id = mvm_sta->deflink.sta_id;
else if (!sta && vif->type == NL80211_IFTYPE_AP && mcast)
sta_id = iwl_mvm_vif_from_mac80211(vif)->deflink.mcast_sta.sta_id;

@@ -3892,7 +3901,7 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,
mvm_sta = iwl_mvm_get_key_sta(mvm, vif, sta);
if (WARN_ON_ONCE(!mvm_sta))
goto unlock;
- iwl_mvm_send_sta_key(mvm, mvm_sta->sta_id, keyconf, mcast,
+ iwl_mvm_send_sta_key(mvm, mvm_sta->deflink.sta_id, keyconf, mcast,
iv32, phase1key, CMD_ASYNC, keyconf->hw_key_idx,
mfp);

@@ -3906,7 +3915,7 @@ void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm,
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_mvm_add_sta_cmd cmd = {
.add_modify = STA_MODE_MODIFY,
- .sta_id = mvmsta->sta_id,
+ .sta_id = mvmsta->deflink.sta_id,
.station_flags_msk = cpu_to_le32(STA_FLG_PS),
.mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color),
};
@@ -3927,7 +3936,7 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm,
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_mvm_add_sta_cmd cmd = {
.add_modify = STA_MODE_MODIFY,
- .sta_id = mvmsta->sta_id,
+ .sta_id = mvmsta->deflink.sta_id,
.modify_mask = STA_MODIFY_SLEEPING_STA_TX_COUNT,
.sleep_tx_count = cpu_to_le16(cnt),
.mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color),
@@ -4024,7 +4033,7 @@ void iwl_mvm_sta_modify_disable_tx(struct iwl_mvm *mvm,
{
struct iwl_mvm_add_sta_cmd cmd = {
.add_modify = STA_MODE_MODIFY,
- .sta_id = mvmsta->sta_id,
+ .sta_id = mvmsta->deflink.sta_id,
.station_flags = disable ? cpu_to_le32(STA_FLG_DISABLE_TX) : 0,
.station_flags_msk = cpu_to_le32(STA_FLG_DISABLE_TX),
.mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color),
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index a0c13c409ccd..bfd44c489286 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -330,9 +330,27 @@ struct iwl_mvm_rxq_dup_data {
u8 last_sub_frame[IWL_MAX_TID_COUNT + 1];
} ____cacheline_aligned_in_smp;

+/**
+ * struct iwl_mvm_link_sta - link specific parameters of a station
+ * @rcu_head: used for freeing the data
+ * @sta_id: the index of the station in the fw
+ * @lq_sta: holds rate scaling data, either for the case when RS is done in
+ * the driver - %rs_drv or in the FW - %rs_fw.
+ * @avg_energy: energy as reported by FW statistics notification
+ */
+struct iwl_mvm_link_sta {
+ struct rcu_head rcu_head;
+ u32 sta_id;
+ union {
+ struct iwl_lq_sta_rs_fw rs_fw;
+ struct iwl_lq_sta rs_drv;
+ } lq_sta;
+
+ u8 avg_energy;
+};
+
/**
* struct iwl_mvm_sta - representation of a station in the driver
- * @sta_id: the index of the station in the fw (will be replaced by id_n_color)
* @tfd_queue_msk: the tfd queues used by the station
* @mac_id_n_color: the MAC context this station is linked to
* @tid_disable_agg: bitmap: if bit(tid) is set, the fw won't send ampdus for
@@ -347,8 +365,6 @@ struct iwl_mvm_rxq_dup_data {
* and from Tx response flow, it needs a spinlock.
* @tid_data: per tid data + mgmt. Look at %iwl_mvm_tid_data.
* @tid_to_baid: a simple map of TID to baid
- * @lq_sta: holds rate scaling data, either for the case when RS is done in
- * the driver - %rs_drv or in the FW - %rs_fw.
* @reserved_queue: the queue reserved for this STA for DQA purposes
* Every STA has is given one reserved queue to allow it to operate. If no
* such queue can be guaranteed, the STA addition will fail.
@@ -374,6 +390,12 @@ struct iwl_mvm_rxq_dup_data {
* used during connection establishment (e.g. for the 4 way handshake
* exchange).
* @pairwise_cipher: used to feed iwlmei upon authorization
+ * @deflink: the default link station, for non-MLO STA, all link specific data
+ * is accessed via deflink (or link[0]). For MLO, it will hold data of the
+ * first added link STA.
+ * @link: per link sta entries. For non-MLO only link[0] holds data. For MLO,
+ * link[0] points to deflink and link[link_id] is allocated when new link
+ * sta is added.
*
* When mac80211 creates a station it reserves some space (hw->sta_data_size)
* in the structure for use by driver. This structure is placed in that
@@ -381,7 +403,6 @@ struct iwl_mvm_rxq_dup_data {
*
*/
struct iwl_mvm_sta {
- u32 sta_id;
u32 tfd_queue_msk;
u32 mac_id_n_color;
u16 tid_disable_agg;
@@ -393,10 +414,6 @@ struct iwl_mvm_sta {
spinlock_t lock;
struct iwl_mvm_tid_data tid_data[IWL_MAX_TID_COUNT + 1];
u8 tid_to_baid[IWL_MAX_TID_COUNT];
- union {
- struct iwl_lq_sta_rs_fw rs_fw;
- struct iwl_lq_sta rs_drv;
- } lq_sta;
struct ieee80211_vif *vif;
struct iwl_mvm_key_pn __rcu *ptk_pn[4];
struct iwl_mvm_rxq_dup_data *dup_data;
@@ -414,9 +431,11 @@ struct iwl_mvm_sta {
bool sleeping;
u8 agg_tids;
u8 sleep_tx_count;
- u8 avg_energy;
u8 tx_ant;
u32 pairwise_cipher;
+
+ struct iwl_mvm_link_sta deflink;
+ struct iwl_mvm_link_sta __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
};

u16 iwl_mvm_tid_queued(struct iwl_mvm *mvm, struct iwl_mvm_tid_data *tid_data);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c b/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
index 674dd137fb9f..dae6f2a1aad9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
@@ -369,7 +369,7 @@ iwl_mvm_tdls_config_channel_switch(struct iwl_mvm *mvm,
goto out;
}
mvmsta = iwl_mvm_sta_from_mac80211(sta);
- cmd.peer_sta_id = cpu_to_le32(mvmsta->sta_id);
+ cmd.peer_sta_id = cpu_to_le32(mvmsta->deflink.sta_id);

if (!chandef) {
if (mvm->tdls_cs.state == IWL_MVM_TDLS_SW_REQ_SENT &&
@@ -414,7 +414,7 @@ iwl_mvm_tdls_config_channel_switch(struct iwl_mvm *mvm,
}

iwl_mvm_set_tx_cmd(mvm, skb, &tail->frame.tx_cmd, info,
- mvmsta->sta_id);
+ mvmsta->deflink.sta_id);

iwl_mvm_set_tx_cmd_rate(mvm, &tail->frame.tx_cmd, info, sta,
hdr->frame_control);
@@ -431,7 +431,7 @@ iwl_mvm_tdls_config_channel_switch(struct iwl_mvm *mvm,

/* channel switch has started, update state */
if (type != TDLS_MOVE_CH) {
- mvm->tdls_cs.cur_sta_id = mvmsta->sta_id;
+ mvm->tdls_cs.cur_sta_id = mvmsta->deflink.sta_id;
iwl_mvm_tdls_update_cs_state(mvm,
type == TDLS_SEND_CHAN_SW_REQ ?
IWL_MVM_TDLS_SW_REQ_SENT :
@@ -541,7 +541,7 @@ iwl_mvm_tdls_channel_switch(struct ieee80211_hw *hw,
}

mvmsta = iwl_mvm_sta_from_mac80211(sta);
- mvm->tdls_cs.peer.sta_id = mvmsta->sta_id;
+ mvm->tdls_cs.peer.sta_id = mvmsta->deflink.sta_id;
mvm->tdls_cs.peer.chandef = *chandef;
mvm->tdls_cs.peer.initiator = sta->tdls_initiator;
mvm->tdls_cs.peer.op_class = oper_class;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index 890fe93896ba..1737f2ad21ad 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -1084,7 +1084,7 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
if (WARN_ON_ONCE(!mvmsta))
return -1;

- if (WARN_ON_ONCE(mvmsta->sta_id == IWL_MVM_INVALID_STA))
+ if (WARN_ON_ONCE(mvmsta->deflink.sta_id == IWL_MVM_INVALID_STA))
return -1;

if (unlikely(ieee80211_is_any_nullfunc(fc)) && sta->deflink.he_cap.has_he)
@@ -1094,7 +1094,7 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
iwl_mvm_probe_resp_set_noa(mvm, skb);

dev_cmd = iwl_mvm_set_tx_params(mvm, skb, info, hdrlen,
- sta, mvmsta->sta_id);
+ sta, mvmsta->deflink.sta_id);
if (!dev_cmd)
goto drop;

@@ -1170,7 +1170,7 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
}

IWL_DEBUG_TX(mvm, "TX to [%d|%d] Q:%d - seq: 0x%x len %d\n",
- mvmsta->sta_id, tid, txq_id,
+ mvmsta->deflink.sta_id, tid, txq_id,
IEEE80211_SEQ_TO_SN(seq_number), skb->len);

/* From now on, we cannot access info->control */
@@ -1205,7 +1205,8 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
iwl_trans_free_tx_cmd(mvm->trans, dev_cmd);
spin_unlock(&mvmsta->lock);
drop:
- IWL_DEBUG_TX(mvm, "TX to [%d|%d] dropped\n", mvmsta->sta_id, tid);
+ IWL_DEBUG_TX(mvm, "TX to [%d|%d] dropped\n", mvmsta->deflink.sta_id,
+ tid);
return -1;
}

@@ -1222,7 +1223,7 @@ int iwl_mvm_tx_skb_sta(struct iwl_mvm *mvm, struct sk_buff *skb,
if (WARN_ON_ONCE(!mvmsta))
return -1;

- if (WARN_ON_ONCE(mvmsta->sta_id == IWL_MVM_INVALID_STA))
+ if (WARN_ON_ONCE(mvmsta->deflink.sta_id == IWL_MVM_INVALID_STA))
return -1;

memcpy(&info, skb->cb, sizeof(info));
@@ -2230,17 +2231,22 @@ int iwl_mvm_flush_sta_tids(struct iwl_mvm *mvm, u32 sta_id, u16 tids)

int iwl_mvm_flush_sta(struct iwl_mvm *mvm, void *sta, bool internal)
{
- struct iwl_mvm_int_sta *int_sta = sta;
- struct iwl_mvm_sta *mvm_sta = sta;
+ u32 sta_id, tfd_queue_msk;

- BUILD_BUG_ON(offsetof(struct iwl_mvm_int_sta, sta_id) !=
- offsetof(struct iwl_mvm_sta, sta_id));
+ if (internal) {
+ struct iwl_mvm_int_sta *int_sta = sta;

- if (iwl_mvm_has_new_tx_api(mvm))
- return iwl_mvm_flush_sta_tids(mvm, mvm_sta->sta_id, 0xffff);
+ sta_id = int_sta->sta_id;
+ tfd_queue_msk = int_sta->tfd_queue_msk;
+ } else {
+ struct iwl_mvm_sta *mvm_sta = sta;

- if (internal)
- return iwl_mvm_flush_tx_path(mvm, int_sta->tfd_queue_msk);
+ sta_id = mvm_sta->deflink.sta_id;
+ tfd_queue_msk = mvm_sta->tfd_queue_msk;
+ }
+
+ if (iwl_mvm_has_new_tx_api(mvm))
+ return iwl_mvm_flush_sta_tids(mvm, sta_id, 0xffff);

- return iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk);
+ return iwl_mvm_flush_tx_path(mvm, tfd_queue_msk);
}
--
2.38.1

2023-03-28 08:05:15

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 06/31] wifi: iwlwifi: mvm: refactor iwl_mvm_roc()

From: Miri Korenblit <[email protected]>

This flow is almost the same for both MLD and non-MLD modes,
except for some function calls. Therefore there is no reason to
add an MLD version of this flow. Instead - put the parts that are unique
for each mode in helper functions, and in the next patch each version of
this flow will call the common part with pointers to its specific
helper functions.

Signed-off-by: Miri Korenblit <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 100 ++++++++++--------
1 file changed, 56 insertions(+), 44 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index dae5e1b7d1cc..bb7e4e26d99f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -4258,6 +4258,52 @@ static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm,
return res;
}

+static int iwl_mvm_add_aux_sta_for_hs20(struct iwl_mvm *mvm, u32 lmac_id)
+{
+ int ret = 0;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ if (!fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT)) {
+ IWL_ERR(mvm, "hotspot not supported\n");
+ return -EINVAL;
+ }
+
+ if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) >= 12) {
+ ret = iwl_mvm_add_aux_sta(mvm, lmac_id);
+ WARN(ret, "Failed to allocate aux station");
+ }
+
+ return ret;
+}
+
+static int iwl_mvm_roc_switch_binding(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);
+
+ /* Unbind the P2P_DEVICE from the current PHY context,
+ * and if the PHY context is not used remove it.
+ */
+ ret = iwl_mvm_binding_remove_vif(mvm, vif);
+ if (WARN(ret, "Failed unbinding P2P_DEVICE\n"))
+ return ret;
+
+ iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
+
+ /* Bind the P2P_DEVICE to the current PHY Context */
+ mvmvif->deflink.phy_ctxt = new_phy_ctxt;
+
+ ret = iwl_mvm_binding_add_vif(mvm, vif);
+ WARN(ret, "Failed binding P2P_DEVICE\n");
+ return ret;
+}
+
static int iwl_mvm_roc(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_channel *channel,
@@ -4270,6 +4316,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
struct iwl_mvm_phy_ctxt *phy_ctxt;
bool band_change_removal;
int ret, i;
+ u32 lmac_id;

IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value,
duration, type);
@@ -4284,25 +4331,13 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,

switch (vif->type) {
case NL80211_IFTYPE_STATION:
- if (fw_has_capa(&mvm->fw->ucode_capa,
- IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT)) {
- /* Use aux roc framework (HS20) */
- if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) >= 12) {
- u32 lmac_id;
-
- lmac_id = iwl_mvm_get_lmac_id(mvm->fw,
- channel->band);
- ret = iwl_mvm_add_aux_sta(mvm, lmac_id);
- if (WARN(ret,
- "Failed to allocate aux station"))
- goto out_unlock;
- }
+ 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);
+ if (!ret)
ret = iwl_mvm_send_aux_roc_cmd(mvm, channel,
vif, duration);
- goto out_unlock;
- }
- IWL_ERR(mvm, "hotspot not supported\n");
- ret = -EINVAL;
goto out_unlock;
case NL80211_IFTYPE_P2P_DEVICE:
/* handle below */
@@ -4319,21 +4354,8 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
continue;

if (phy_ctxt->ref && channel == phy_ctxt->channel) {
- /*
- * Unbind the P2P_DEVICE from the current PHY context,
- * and if the PHY context is not used remove it.
- */
- ret = iwl_mvm_binding_remove_vif(mvm, vif);
- if (WARN(ret, "Failed unbinding P2P_DEVICE\n"))
- goto out_unlock;
-
- iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
-
- /* Bind the P2P_DEVICE to the current PHY Context */
- mvmvif->deflink.phy_ctxt = phy_ctxt;
-
- ret = iwl_mvm_binding_add_vif(mvm, vif);
- if (WARN(ret, "Failed binding P2P_DEVICE\n"))
+ ret = iwl_mvm_roc_switch_binding(mvm, vif, phy_ctxt);
+ if (ret)
goto out_unlock;

iwl_mvm_phy_ctxt_ref(mvm, mvmvif->deflink.phy_ctxt);
@@ -4386,18 +4408,8 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
goto out_unlock;
}

- /* Unbind the P2P_DEVICE from the current PHY context */
- ret = iwl_mvm_binding_remove_vif(mvm, vif);
- if (WARN(ret, "Failed unbinding P2P_DEVICE\n"))
- goto out_unlock;
-
- iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
-
- /* Bind the P2P_DEVICE to the new allocated PHY context */
- mvmvif->deflink.phy_ctxt = phy_ctxt;
-
- ret = iwl_mvm_binding_add_vif(mvm, vif);
- if (WARN(ret, "Failed binding P2P_DEVICE\n"))
+ ret = iwl_mvm_roc_switch_binding(mvm, vif, phy_ctxt);
+ if (ret)
goto out_unlock;

iwl_mvm_phy_ctxt_ref(mvm, mvmvif->deflink.phy_ctxt);
--
2.38.1

2023-03-28 08:05:15

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 04/31] wifi: iwlwifi: mvm: add sta handling flows for MLD mode

From: Miri Korenblit <[email protected]>

In MLD mode we have a new STA cmd. As a result, it is also changes
the flows of adding/updating/removing and handling state of
a station. Add these flows.

Signed-off-by: Miri Korenblit <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 58 +++--
.../wireless/intel/iwlwifi/mvm/mld-mac80211.c | 18 ++
.../net/wireless/intel/iwlwifi/mvm/mld-sta.c | 205 ++++++++++++++++++
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 7 +
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 25 ++-
drivers/net/wireless/intel/iwlwifi/mvm/sta.h | 45 ++++
6 files changed, 333 insertions(+), 25 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 282c15e74f08..b730b605da74 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -2103,9 +2103,8 @@ static void iwl_mvm_get_optimal_ppe_info(struct iwl_he_pkt_ext_v2 *pkt_ext,
}

/* Set the pkt_ext field according to PPE Thresholds element */
-static int iwl_mvm_set_sta_pkt_ext(struct iwl_mvm *mvm,
- struct ieee80211_sta *sta,
- struct iwl_he_pkt_ext_v2 *pkt_ext)
+int iwl_mvm_set_sta_pkt_ext(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
+ struct iwl_he_pkt_ext_v2 *pkt_ext)
{
u8 nominal_padding;
int i, ret = 0;
@@ -2250,7 +2249,7 @@ bool iwl_mvm_is_nic_ack_enabled(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
IEEE80211_HE_MAC_CAP2_ACK_EN));
}

-static __le32 iwl_mvm_get_sta_htc_flags(struct ieee80211_sta *sta)
+__le32 iwl_mvm_get_sta_htc_flags(struct ieee80211_sta *sta)
{
u8 *mac_cap_info = &sta->deflink.he_cap.he_cap_elem.mac_cap_info[0];
__le32 htc_flags = 0;
@@ -3425,11 +3424,37 @@ static void iwl_mvm_mei_host_associated(struct iwl_mvm *mvm,
#endif
}

+static int iwl_mvm_mac_ctxt_changed_wrapper(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ bool force_assoc_off)
+{
+ return iwl_mvm_mac_ctxt_changed(mvm, vif, force_assoc_off, NULL);
+}
+
static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
enum ieee80211_sta_state old_state,
enum ieee80211_sta_state new_state)
+{
+ struct iwl_mvm_sta_state_ops callbacks = {
+ .add_sta = iwl_mvm_add_sta,
+ .update_sta = iwl_mvm_update_sta,
+ .rm_sta = iwl_mvm_rm_sta,
+ .mac_ctxt_changed = iwl_mvm_mac_ctxt_changed_wrapper,
+ };
+
+ return iwl_mvm_mac_sta_state_common(hw, vif, sta, old_state, new_state,
+ &callbacks);
+}
+
+/* Common part for MLD and non-MLD modes */
+int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ enum ieee80211_sta_state old_state,
+ enum ieee80211_sta_state new_state,
+ struct iwl_mvm_sta_state_ops *callbacks)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
@@ -3507,7 +3532,7 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
goto out_unlock;
}

- ret = iwl_mvm_add_sta(mvm, vif, sta);
+ ret = callbacks->add_sta(mvm, vif, sta);
if (sta->tdls && ret == 0) {
iwl_mvm_recalc_tdls_state(mvm, vif, true);
iwl_mvm_tdls_check_trigger(mvm, vif, sta->addr,
@@ -3529,11 +3554,12 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
if (vif->type == NL80211_IFTYPE_AP) {
vif->bss_conf.he_support = sta->deflink.he_cap.has_he;
mvmvif->ap_assoc_sta_count++;
- iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
- if ((vif->bss_conf.he_support &&
+ callbacks->mac_ctxt_changed(mvm, vif, false);
+ if (!mvm->mld_api_is_used &&
+ ((vif->bss_conf.he_support &&
!iwlwifi_mod_params.disable_11ax) ||
(vif->bss_conf.eht_support &&
- !iwlwifi_mod_params.disable_11be))
+ !iwlwifi_mod_params.disable_11be)))
iwl_mvm_cfg_he_sta(mvm, vif,
mvm_sta->deflink.sta_id);
} else if (vif->type == NL80211_IFTYPE_STATION) {
@@ -3543,13 +3569,19 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
if (sta->deflink.he_cap.has_he)
iwl_mvm_check_he_obss_narrow_bw_ru(hw, vif);

- iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
+ callbacks->mac_ctxt_changed(mvm, vif, false);
+
+ if (mvm->mld_api_is_used)
+ iwl_mvm_link_changed(mvm, vif,
+ LINK_CONTEXT_MODIFY_ALL &
+ ~LINK_CONTEXT_MODIFY_ACTIVE,
+ true);
}

iwl_mvm_rs_rate_init(mvm, sta,
mvmvif->deflink.phy_ctxt->channel->band,
false);
- ret = iwl_mvm_update_sta(mvm, vif, sta);
+ ret = callbacks->update_sta(mvm, vif, sta);
} else if (old_state == IEEE80211_STA_ASSOC &&
new_state == IEEE80211_STA_AUTHORIZED) {
ret = 0;
@@ -3567,7 +3599,7 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,

mvmvif->authorized = 1;

- iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
+ callbacks->mac_ctxt_changed(mvm, vif, false);
iwl_mvm_mei_host_associated(mvm, vif, mvm_sta);
}

@@ -3601,7 +3633,7 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
new_state == IEEE80211_STA_AUTH) {
if (vif->type == NL80211_IFTYPE_AP) {
mvmvif->ap_assoc_sta_count--;
- iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
+ callbacks->mac_ctxt_changed(mvm, vif, false);
} else if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
iwl_mvm_stop_session_protection(mvm, vif);
ret = 0;
@@ -3612,7 +3644,7 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
new_state == IEEE80211_STA_NOTEXIST) {
if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
iwl_mvm_stop_session_protection(mvm, vif);
- ret = iwl_mvm_rm_sta(mvm, vif, sta);
+ ret = callbacks->rm_sta(mvm, vif, sta);
if (sta->tdls) {
iwl_mvm_recalc_tdls_state(mvm, vif, false);
iwl_mvm_tdls_check_trigger(mvm, vif, sta->addr,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index fe55efce8dd5..36c87d755d5c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -352,6 +352,23 @@ static void iwl_mvm_mld_stop_ap_ibss(struct ieee80211_hw *hw,
mutex_unlock(&mvm->mutex);
}

+static int iwl_mvm_mld_mac_sta_state(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ enum ieee80211_sta_state old_state,
+ enum ieee80211_sta_state new_state)
+{
+ struct iwl_mvm_sta_state_ops callbacks = {
+ .add_sta = iwl_mvm_mld_add_sta,
+ .update_sta = iwl_mvm_mld_update_sta,
+ .rm_sta = iwl_mvm_mld_rm_sta,
+ .mac_ctxt_changed = iwl_mvm_mld_mac_ctxt_changed,
+ };
+
+ return iwl_mvm_mac_sta_state_common(hw, vif, sta, old_state, new_state,
+ &callbacks);
+}
+
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,
@@ -359,4 +376,5 @@ const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
.unassign_vif_chanctx = iwl_mvm_mld_unassign_vif_chanctx,
.join_ibss = iwl_mvm_mld_start_ap_ibss,
.leave_ibss = iwl_mvm_mld_stop_ap_ibss,
+ .sta_state = iwl_mvm_mld_mac_sta_state,
};
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
index c063383247f9..0e9c87bc224c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
@@ -3,6 +3,7 @@
* Copyright (C) 2022 Intel Corporation
*/
#include "mvm.h"
+#include "time-sync.h"

static int iwl_mvm_mld_send_sta_cmd(struct iwl_mvm *mvm,
struct iwl_mvm_sta_cfg_cmd *cmd)
@@ -331,6 +332,210 @@ int iwl_mvm_mld_rm_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
IWL_MAX_TID_COUNT, &mvm->snif_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)
+{
+ struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
+ struct iwl_mvm_sta_cfg_cmd cmd = {
+ .sta_id = cpu_to_le32(mvm_sta->deflink.sta_id),
+ .link_id = cpu_to_le32(phy_id),
+ .station_type = cpu_to_le32(mvm_sta->sta_type),
+ .mfp = cpu_to_le32(sta->mfp),
+ };
+ u32 agg_size = 0, mpdu_dens = 0;
+
+ /* For now the link addr is the same as the mld addr */
+ if (vif->type == NL80211_IFTYPE_AP) {
+ memcpy(&cmd.peer_mld_address, sta->addr, ETH_ALEN);
+ memcpy(&cmd.peer_link_address, sta->addr, ETH_ALEN);
+ } else if (vif->bss_conf.bssid) {
+ memcpy(&cmd.peer_mld_address, vif->bss_conf.bssid, ETH_ALEN);
+ memcpy(&cmd.peer_link_address, vif->bss_conf.bssid, ETH_ALEN);
+ }
+
+ if (mvm_sta->sta_state >= IEEE80211_STA_ASSOC)
+ cmd.assoc_id = cpu_to_le32(sta->aid);
+
+ switch (sta->deflink.rx_nss) {
+ case 1:
+ cmd.mimo = cpu_to_le32(0);
+ break;
+ case 2 ... 8:
+ cmd.mimo = cpu_to_le32(1);
+ break;
+ }
+
+ switch (sta->deflink.smps_mode) {
+ case IEEE80211_SMPS_AUTOMATIC:
+ case IEEE80211_SMPS_NUM_MODES:
+ WARN_ON(1);
+ break;
+ case IEEE80211_SMPS_STATIC:
+ /* override NSS */
+ cmd.mimo = cpu_to_le32(0);
+ break;
+ case IEEE80211_SMPS_DYNAMIC:
+ cmd.mimo_protection = cpu_to_le32(1);
+ break;
+ case IEEE80211_SMPS_OFF:
+ /* nothing */
+ break;
+ }
+
+ mpdu_dens = iwl_mvm_get_sta_ampdu_dens(sta, &agg_size);
+ cmd.tx_ampdu_spacing = cpu_to_le32(mpdu_dens);
+ cmd.tx_ampdu_max_size = cpu_to_le32(agg_size);
+
+ if (sta->wme) {
+ cmd.sp_length =
+ cpu_to_le32(sta->max_sp ? sta->max_sp * 2 : 128);
+ cmd.uapsd_acs = cpu_to_le32(iwl_mvm_get_sta_uapsd_acs(sta));
+ }
+
+ if (sta->deflink.he_cap.has_he) {
+ cmd.trig_rnd_alloc =
+ cpu_to_le32(vif->bss_conf.uora_exists ? 1 : 0);
+
+ /* PPE Thresholds */
+ iwl_mvm_set_sta_pkt_ext(mvm, sta, &cmd.pkt_ext);
+
+ /* HTC flags */
+ cmd.htc_flags = iwl_mvm_get_sta_htc_flags(sta);
+
+ if (sta->deflink.he_cap.he_cap_elem.mac_cap_info[2] &
+ IEEE80211_HE_MAC_CAP2_ACK_EN)
+ cmd.ack_enabled = cpu_to_le32(1);
+ }
+
+ return iwl_mvm_mld_send_sta_cmd(mvm, &cmd);
+}
+
+int iwl_mvm_mld_add_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
+ int sta_id, ret = 0;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
+ sta_id = iwl_mvm_find_free_sta_id(mvm,
+ ieee80211_vif_type_p2p(vif));
+ else
+ sta_id = mvm_sta->deflink.sta_id;
+
+ if (sta_id == IWL_MVM_INVALID_STA)
+ return -ENOSPC;
+
+ spin_lock_init(&mvm_sta->lock);
+
+ /* if this is a HW restart re-alloc existing queues */
+ if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
+ struct iwl_mvm_int_sta tmp_sta = {
+ .sta_id = sta_id,
+ .type = mvm_sta->sta_type,
+ };
+
+ /* First add an empty station since allocating
+ * a queue requires a valid station
+ */
+ ret = iwl_mvm_mld_add_int_sta_to_fw(mvm, &tmp_sta,
+ vif->bss_conf.bssid,
+ mvmvif->deflink.phy_ctxt->id);
+ if (ret)
+ return ret;
+
+ iwl_mvm_realloc_queues_after_restart(mvm, sta);
+ } else {
+ ret = iwl_mvm_sta_init(mvm, vif, sta, sta_id,
+ STATION_TYPE_PEER);
+ }
+
+ ret = iwl_mvm_mld_cfg_sta(mvm, sta, vif, mvmvif->deflink.phy_ctxt->id);
+ if (ret)
+ return ret;
+
+ if (vif->type == NL80211_IFTYPE_STATION) {
+ if (!sta->tdls) {
+ WARN_ON(mvmvif->deflink.ap_sta_id != IWL_MVM_INVALID_STA);
+ mvmvif->deflink.ap_sta_id = sta_id;
+ } else {
+ WARN_ON(mvmvif->deflink.ap_sta_id == IWL_MVM_INVALID_STA);
+ }
+ }
+
+ rcu_assign_pointer(mvm->fw_id_to_mac_id[sta_id], sta);
+
+ return 0;
+}
+
+int iwl_mvm_mld_update_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+ lockdep_assert_held(&mvm->mutex);
+
+ return iwl_mvm_mld_cfg_sta(mvm, sta, vif, mvmvif->deflink.phy_ctxt->id);
+}
+
+static void iwl_mvm_mld_disable_sta_queues(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
+ int i;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ for (i = 0; i < ARRAY_SIZE(mvm_sta->tid_data); i++) {
+ if (mvm_sta->tid_data[i].txq_id == IWL_MVM_INVALID_QUEUE)
+ continue;
+
+ iwl_mvm_mld_disable_txq(mvm, sta, &mvm_sta->tid_data[i].txq_id,
+ i);
+ mvm_sta->tid_data[i].txq_id = IWL_MVM_INVALID_QUEUE;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(sta->txq); i++) {
+ struct iwl_mvm_txq *mvmtxq =
+ iwl_mvm_txq_from_mac80211(sta->txq[i]);
+
+ mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
+ }
+}
+
+int iwl_mvm_mld_rm_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
+ int ret;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ kfree(mvm_sta->dup_data);
+
+ /* flush its queues here since we are freeing mvm_sta */
+ ret = iwl_mvm_flush_sta(mvm, mvm_sta, false);
+ if (ret)
+ return ret;
+ ret = iwl_mvm_wait_sta_queues_empty(mvm, mvm_sta);
+ if (ret)
+ return ret;
+
+ iwl_mvm_mld_disable_sta_queues(mvm, vif, sta);
+
+ if (iwl_mvm_sta_del(mvm, vif, sta, &ret))
+ return ret;
+
+ ret = iwl_mvm_mld_rm_sta_from_fw(mvm, mvm_sta->deflink.sta_id);
+ RCU_INIT_POINTER(mvm->fw_id_to_mac_id[mvm_sta->deflink.sta_id], NULL);
+
+ return ret;
+}
+
static void iwl_mvm_mld_sta_modify_disable_tx(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
bool disable)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 443f0b80b63e..24884e102673 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -1573,6 +1573,13 @@ int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk);
int iwl_mvm_flush_sta(struct iwl_mvm *mvm, void *sta, bool internal);
int iwl_mvm_flush_sta_tids(struct iwl_mvm *mvm, u32 sta_id, u16 tids);

+/* Utils to extract sta related data */
+__le32 iwl_mvm_get_sta_htc_flags(struct ieee80211_sta *sta);
+u8 iwl_mvm_get_sta_uapsd_acs(struct ieee80211_sta *sta);
+u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_sta *sta, u32 *_agg_size);
+int iwl_mvm_set_sta_pkt_ext(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
+ struct iwl_he_pkt_ext_v2 *pkt_ext);
+
void iwl_mvm_async_handlers_purge(struct iwl_mvm *mvm);

static inline void iwl_mvm_set_tx_cmd_ccmp(struct ieee80211_tx_info *info,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index d01c67e1ce2a..0ff66ffc5bee 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -24,8 +24,7 @@ static inline int iwl_mvm_add_sta_cmd_size(struct iwl_mvm *mvm)
return sizeof(struct iwl_mvm_add_sta_cmd_v7);
}

-static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm,
- enum nl80211_iftype iftype)
+int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm, enum nl80211_iftype iftype)
{
int sta_id;
u32 reserved_ids = 0;
@@ -52,8 +51,7 @@ static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm,
}

/* Calculate the ampdu density and max size */
-static u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_sta *sta,
- u32 *_agg_size)
+u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_sta *sta, u32 *_agg_size)
{
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
u32 agg_size = 0, mpdu_dens = 0;
@@ -97,7 +95,7 @@ static u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_sta *sta,
return mpdu_dens;
}

-static u8 iwl_mvm_get_sta_uapsd_acs(struct ieee80211_sta *sta)
+u8 iwl_mvm_get_sta_uapsd_acs(struct ieee80211_sta *sta)
{
u8 uapsd_acs = 0;

@@ -1528,8 +1526,8 @@ static int iwl_mvm_reserve_sta_stream(struct iwl_mvm *mvm,
*
* Note that re-enabling aggregations isn't done in this function.
*/
-static void iwl_mvm_realloc_queues_after_restart(struct iwl_mvm *mvm,
- struct ieee80211_sta *sta)
+void iwl_mvm_realloc_queues_after_restart(struct iwl_mvm *mvm,
+ struct ieee80211_sta *sta)
{
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
unsigned int wdg =
@@ -1649,8 +1647,8 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm,
}

/* Initialize driver data of a new sta */
-static int iwl_mvm_sta_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta, int sta_id, u8 sta_type)
+int iwl_mvm_sta_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta, int sta_id, u8 sta_type)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
@@ -1923,9 +1921,12 @@ int iwl_mvm_wait_sta_queues_empty(struct iwl_mvm *mvm,
return 0;
}

-/* Execute the common part for both MLD and non-MLD modes */
-static bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta, int *ret)
+/* Execute the common part for both MLD and non-MLD modes.
+ * Returns if we're done with removing the station, either
+ * with error or success
+ */
+bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta, int *ret)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index bfd44c489286..fa644928746a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -471,6 +471,9 @@ struct iwl_mvm_int_sta {
*/
int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
bool update, unsigned int flags);
+int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm, enum nl80211_iftype iftype);
+int iwl_mvm_sta_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta, int sta_id, u8 sta_type);
int iwl_mvm_add_sta(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
@@ -482,8 +485,12 @@ static inline int iwl_mvm_update_sta(struct iwl_mvm *mvm,
return iwl_mvm_sta_send_to_fw(mvm, sta, true, 0);
}

+void iwl_mvm_realloc_queues_after_restart(struct iwl_mvm *mvm,
+ struct ieee80211_sta *sta);
int iwl_mvm_wait_sta_queues_empty(struct iwl_mvm *mvm,
struct iwl_mvm_sta *mvm_sta);
+bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta, int *ret);
int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
@@ -578,6 +585,38 @@ int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
u8 sta_id, u8 tid, unsigned int timeout);

+/* Sta state */
+/**
+ * struct iwl_mvm_sta_state_ops - callbacks for the sta_state() ops
+ *
+ * Since the only difference between both MLD and
+ * non-MLD versions of sta_state() is these function calls,
+ * each version will send its specific function calls to
+ * %iwl_mvm_mac_sta_state_common().
+ *
+ * @add_sta: pointer to the function that adds a new sta
+ * @update_sta: pointer to the function that updates a sta
+ * @rm_sta: pointer to the functions that removes a sta
+ * @mac_ctxt_changed: pointer to the function that handles a change in mac ctxt
+ */
+struct iwl_mvm_sta_state_ops {
+ int (*add_sta)(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
+ int (*update_sta)(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
+ int (*rm_sta)(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
+ int (*mac_ctxt_changed)(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ bool force_assoc_off);
+};
+
+int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ enum ieee80211_sta_state old_state,
+ enum ieee80211_sta_state new_state,
+ struct iwl_mvm_sta_state_ops *callbacks);
+
/* New MLD STA related APIs */
/* STA */
int iwl_mvm_mld_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
@@ -586,6 +625,12 @@ int iwl_mvm_mld_add_mcast_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_mcast_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);
+int iwl_mvm_mld_update_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
+int iwl_mvm_mld_rm_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);

/* Queues */
void iwl_mvm_mld_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
--
2.38.1

2023-03-28 08:05:18

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 07/31] wifi: iwlwifi: mvm: add cancel/remain_on_channel for MLD mode

From: Miri Korenblit <[email protected]>

Add an MLD version of the remain_on_channel and
cancel_remain_on_channel callbacks.

Signed-off-by: Miri Korenblit <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
.../wireless/intel/iwlwifi/fw/api/mac-cfg.h | 3 ++
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 24 +++++++---
.../wireless/intel/iwlwifi/mvm/mld-mac80211.c | 43 ++++++++++++++++++
.../net/wireless/intel/iwlwifi/mvm/mld-sta.c | 44 ++++++++++++++++++-
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 26 +++++++++++
drivers/net/wireless/intel/iwlwifi/mvm/sta.h | 2 +
.../wireless/intel/iwlwifi/mvm/time-event.c | 6 +++
7 files changed, 142 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
index a111e7366d49..3c540aa9c0c8 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
@@ -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 */

/**
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index bb7e4e26d99f..d36319bd9247 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -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);

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index 9d97098ab57c..871da586ebb4 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -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,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
index 16723d581a3d..643eb58317f0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
@@ -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)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 2ea224acdea1..ba59a6c30529 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -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);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index 770516b20303..5436e52ca639 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -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,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
index 3b17dd998d19..6b7b6250f1bb 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
@@ -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);
}

--
2.38.1

2023-03-28 08:05:31

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 05/31] wifi: iwlwifi: mvm: add some new MLD ops

From: Miri Korenblit <[email protected]>

Add MLD version of bss_info_changed/switch_vif_chanctx/
config_iface_filter and conf_tx() callbacks.

Signed-off-by: Miri Korenblit <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 213 ++++++++++------
.../wireless/intel/iwlwifi/mvm/mld-mac80211.c | 227 ++++++++++++++++++
.../net/wireless/intel/iwlwifi/mvm/mld-sta.c | 11 +
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 73 ++++++
drivers/net/wireless/intel/iwlwifi/mvm/sta.h | 2 +
5 files changed, 446 insertions(+), 80 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index b730b605da74..dae5e1b7d1cc 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -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");
}

-static void iwl_mvm_protect_assoc(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- u32 duration_override)
+void iwl_mvm_protect_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ u32 duration_override)
{
u32 duration = IWL_MVM_TE_SESSION_PROTECTION_MAX_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,
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,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
@@ -2623,67 +2698,10 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
vif->addr);
}

- /*
- * 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));
+ iwl_mvm_bss_info_changed_station_assoc(mvm, vif, changes);
}

- 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);
+ iwl_mvm_bss_info_changed_station_common(mvm, vif, changes);
}

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,
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_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);

@@ -2977,11 +3011,12 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,

switch (vif->type) {
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;
case NL80211_IFTYPE_AP:
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;
case NL80211_IFTYPE_MONITOR:
if (changes & BSS_CHANGED_MU_GROUPS)
@@ -4762,12 +4797,13 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw,

static int
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;

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

ret = __iwl_mvm_add_chanctx(mvm, vifs[0].new_ctx);
@@ -4776,7 +4812,7 @@ iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm,
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);
if (ret) {
IWL_ERR(mvm,
@@ -4799,8 +4835,8 @@ iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm,
goto out_restart;
}

- if (__iwl_mvm_assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx,
- true)) {
+ if (ops->__assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx,
+ true)) {
IWL_ERR(mvm, "failed to reassign old_ctx after failure.\n");
goto out_restart;
}
@@ -4819,14 +4855,15 @@ iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm,

static int
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;

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);
if (ret) {
IWL_ERR(mvm,
@@ -4837,8 +4874,8 @@ iwl_mvm_switch_vif_chanctx_reassign(struct iwl_mvm *mvm,
goto out;

out_reassign:
- if (__iwl_mvm_assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx,
- true)) {
+ if (ops->__assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx,
+ true)) {
IWL_ERR(mvm, "failed to reassign old_ctx after failure.\n");
goto out_restart;
}
@@ -4855,10 +4892,13 @@ iwl_mvm_switch_vif_chanctx_reassign(struct iwl_mvm *mvm,
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)
+/* Execute the common part for both MLD and non-MLD modes */
+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)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
@@ -4869,10 +4909,10 @@ static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw,

switch (mode) {
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;
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;
default:
ret = -EOPNOTSUPP;
@@ -4882,6 +4922,19 @@ static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw,
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)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index 36c87d755d5c..9d97098ab57c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -369,12 +369,239 @@ static int iwl_mvm_mld_mac_sta_state(struct ieee80211_hw *hw,
&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 = {
.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,
.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,
.join_ibss = iwl_mvm_mld_start_ap_ibss,
.leave_ibss = iwl_mvm_mld_stop_ap_ibss,
.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,
};
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
index 0e9c87bc224c..16723d581a3d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
@@ -536,6 +536,17 @@ int iwl_mvm_mld_rm_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
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,
struct ieee80211_sta *sta,
bool disable)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 24884e102673..2ea224acdea1 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -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,
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 */
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)
void iwl_mvm_channel_switch_disconnect_wk(struct work_struct *wk);

/* 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,
struct ieee80211_vif *vif,
struct ieee80211_chanctx_conf *ctx,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index fa644928746a..770516b20303 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -631,6 +631,8 @@ int iwl_mvm_mld_update_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
int iwl_mvm_mld_rm_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
+int iwl_mvm_mld_rm_sta_id(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ u8 sta_id);

/* Queues */
void iwl_mvm_mld_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
--
2.38.1

2023-03-28 08:05:46

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 08/31] wifi: iwlwifi: mvm: unite sta_modify_disable_tx flows

From: Miri Korenblit <[email protected]>

These flows are the same in both MLD API and the current API,
except for the commands that are being sent during this flows.
Instead of checking each time before calling these floews
what API we use and then call the correct function, call always the old
one, which in turn will call the new one in case we're using the MLD
API.

Signed-off-by: Miri Korenblit <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 6 ++--
.../wireless/intel/iwlwifi/mvm/mld-mac80211.c | 4 ---
.../net/wireless/intel/iwlwifi/mvm/mld-sta.c | 36 +++++++++++--------
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 18 +++++++++-
drivers/net/wireless/intel/iwlwifi/mvm/sta.h | 6 ++++
5 files changed, 47 insertions(+), 23 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index d36319bd9247..ce2f502bfff8 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -4762,6 +4762,9 @@ bool __iwl_mvm_unassign_vif_chanctx_common(struct iwl_mvm *mvm,

mvmvif->csa_countdown = false;

+ /* Set CS bit on all the stations */
+ iwl_mvm_modify_all_sta_disable_tx(mvm, mvmvif, true);
+
/* Save blocked iface, the timeout is set on the next beacon */
rcu_assign_pointer(mvm->csa_tx_blocked_vif, vif);

@@ -4787,9 +4790,6 @@ static void __iwl_mvm_unassign_vif_chanctx(struct iwl_mvm *mvm,
if (vif->type == NL80211_IFTYPE_MONITOR)
iwl_mvm_rm_snif_sta(mvm, vif);

- if (vif->type == NL80211_IFTYPE_AP)
- /* Set CS bit on all the stations */
- iwl_mvm_modify_all_sta_disable_tx(mvm, mvmvif, true);

if (vif->type == NL80211_IFTYPE_STATION && switching_chanctx) {
disabled_vif = vif;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index 871da586ebb4..92f174231f60 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -220,10 +220,6 @@ static void __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm,
if (vif->type == NL80211_IFTYPE_MONITOR)
iwl_mvm_mld_rm_snif_sta(mvm, vif);

- if (vif->type == NL80211_IFTYPE_AP)
- /* Set CS bit on all the stations */
- iwl_mvm_mld_modify_all_sta_disable_tx(mvm, mvmvif, true);
-
/* Link needs to be deactivated before removal */
iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ACTIVE, false);
iwl_mvm_remove_link(mvm, vif);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
index 643eb58317f0..a6eb18830cd9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
@@ -589,24 +589,14 @@ int iwl_mvm_mld_rm_sta_id(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return ret;
}

-static void iwl_mvm_mld_sta_modify_disable_tx(struct iwl_mvm *mvm,
- struct ieee80211_sta *sta,
- bool disable)
+void iwl_mvm_mld_sta_modify_disable_tx(struct iwl_mvm *mvm,
+ struct iwl_mvm_sta *mvmsta,
+ bool disable)
{
- struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_mvm_sta_disable_tx_cmd cmd;
int ret;

- spin_lock_bh(&mvm_sta->lock);
-
- if (mvm_sta->disable_tx == disable) {
- spin_unlock_bh(&mvm_sta->lock);
- return;
- }
-
- mvm_sta->disable_tx = disable;
-
- cmd.sta_id = cpu_to_le32(mvm_sta->deflink.sta_id);
+ cmd.sta_id = cpu_to_le32(mvmsta->deflink.sta_id);
cmd.disable = cpu_to_le32(disable);

ret = iwl_mvm_send_cmd_pdu(mvm,
@@ -616,6 +606,22 @@ static void iwl_mvm_mld_sta_modify_disable_tx(struct iwl_mvm *mvm,
IWL_ERR(mvm,
"Failed to send STA_DISABLE_TX_CMD command (%d)\n",
ret);
+}
+
+void iwl_mvm_mld_sta_modify_disable_tx_ap(struct iwl_mvm *mvm,
+ struct ieee80211_sta *sta,
+ bool disable)
+{
+ struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
+
+ spin_lock_bh(&mvm_sta->lock);
+
+ if (mvm_sta->disable_tx == disable) {
+ spin_unlock_bh(&mvm_sta->lock);
+ return;
+ }
+
+ iwl_mvm_mld_sta_modify_disable_tx(mvm, mvm_sta, disable);

spin_unlock_bh(&mvm_sta->lock);
}
@@ -641,7 +647,7 @@ void iwl_mvm_mld_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color))
continue;

- iwl_mvm_mld_sta_modify_disable_tx(mvm, sta, disable);
+ iwl_mvm_mld_sta_modify_disable_tx(mvm, mvm_sta, disable);
}

rcu_read_unlock();
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index 0ff66ffc5bee..54ef749be488 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -4030,7 +4030,8 @@ void iwl_mvm_rx_eosp_notif(struct iwl_mvm *mvm,
}

void iwl_mvm_sta_modify_disable_tx(struct iwl_mvm *mvm,
- struct iwl_mvm_sta *mvmsta, bool disable)
+ struct iwl_mvm_sta *mvmsta,
+ bool disable)
{
struct iwl_mvm_add_sta_cmd cmd = {
.add_modify = STA_MODE_MODIFY,
@@ -4041,6 +4042,11 @@ void iwl_mvm_sta_modify_disable_tx(struct iwl_mvm *mvm,
};
int ret;

+ if (mvm->mld_api_is_used) {
+ iwl_mvm_mld_sta_modify_disable_tx(mvm, mvmsta, disable);
+ return;
+ }
+
ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC,
iwl_mvm_add_sta_cmd_size(mvm), &cmd);
if (ret)
@@ -4053,6 +4059,11 @@ void iwl_mvm_sta_modify_disable_tx_ap(struct iwl_mvm *mvm,
{
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);

+ if (mvm->mld_api_is_used) {
+ iwl_mvm_mld_sta_modify_disable_tx_ap(mvm, sta, disable);
+ return;
+ }
+
spin_lock_bh(&mvm_sta->lock);

if (mvm_sta->disable_tx == disable) {
@@ -4103,6 +4114,11 @@ void iwl_mvm_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
struct iwl_mvm_sta *mvm_sta;
int i;

+ if (mvm->mld_api_is_used) {
+ iwl_mvm_mld_modify_all_sta_disable_tx(mvm, mvmvif, disable);
+ return;
+ }
+
rcu_read_lock();

/* Block/unblock all the stations of the given mvmvif */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index 5436e52ca639..3a9002eeb5fb 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -640,4 +640,10 @@ int iwl_mvm_mld_rm_sta_id(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
void iwl_mvm_mld_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
struct iwl_mvm_vif *mvmvif,
bool disable);
+void iwl_mvm_mld_sta_modify_disable_tx(struct iwl_mvm *mvm,
+ struct iwl_mvm_sta *mvm_sta,
+ bool disable);
+void iwl_mvm_mld_sta_modify_disable_tx_ap(struct iwl_mvm *mvm,
+ struct ieee80211_sta *sta,
+ bool disable);
#endif /* __sta_h__ */
--
2.38.1

2023-03-28 08:05:47

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 09/31] wifi: iwlwifi: mvm: add support for post_channel_switch in MLD mode

From: Miri Korenblit <[email protected]>

Adjust the existing iwl_mvm_post_channel_switch()
to the new MLD API and use it in the new MLD ieee80211_ops

Signed-off-by: Miri Korenblit <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 10 ++++++----
drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c | 1 +
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 2 ++
3 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index ce2f502bfff8..631d1becc6ab 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -1317,8 +1317,8 @@ static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, len, &cmd);
}

-static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
@@ -1339,8 +1339,10 @@ static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
}

iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, false);
-
- iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
+ if (mvm->mld_api_is_used)
+ iwl_mvm_mld_mac_ctxt_changed(mvm, vif, false);
+ else
+ iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);

if (!fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD)) {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index 92f174231f60..818aed050b73 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -640,6 +640,7 @@ const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
.switch_vif_chanctx = iwl_mvm_mld_switch_vif_chanctx,
.join_ibss = iwl_mvm_mld_start_ap_ibss,
.leave_ibss = iwl_mvm_mld_stop_ap_ibss,
+ .post_channel_switch = iwl_mvm_post_channel_switch,
.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,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index ba59a6c30529..bf1de6405cd6 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -2298,6 +2298,8 @@ static inline u8 iwl_mvm_phy_band_from_nl80211(enum nl80211_band band)

/* Channel Switch */
void iwl_mvm_channel_switch_disconnect_wk(struct work_struct *wk);
+int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);

/* Channel Context */
/**
--
2.38.1

2023-03-28 08:05:50

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 10/31] wifi: iwlwifi: mvm: add all missing ops to iwl_mvm_mld_ops

From: Miri Korenblit <[email protected]>

Add all the callbacks that are not changing with the
new MLD API and register to mac80211 with the new ops.

Signed-off-by: Miri Korenblit <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 200 ++++++++----------
.../wireless/intel/iwlwifi/mvm/mld-mac80211.c | 114 +++++++++-
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 135 ++++++++++++
drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 4 +-
4 files changed, 334 insertions(+), 119 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 631d1becc6ab..e922cc45c390 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -258,8 +258,7 @@ static const struct wiphy_iftype_ext_capab add_iftypes_ext_capa[] = {
},
};

-static int
-iwl_mvm_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
+int iwl_mvm_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
*tx_ant = iwl_mvm_get_valid_tx_ant(mvm);
@@ -703,9 +702,8 @@ static void iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
ieee80211_free_txskb(mvm->hw, skb);
}

-static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
- struct ieee80211_tx_control *control,
- struct sk_buff *skb)
+void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
+ struct ieee80211_tx_control *control, struct sk_buff *skb)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct ieee80211_sta *sta = control->sta;
@@ -801,8 +799,8 @@ void iwl_mvm_mac_itxq_xmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
rcu_read_unlock();
}

-static void iwl_mvm_mac_wake_tx_queue(struct ieee80211_hw *hw,
- struct ieee80211_txq *txq)
+void iwl_mvm_mac_wake_tx_queue(struct ieee80211_hw *hw,
+ struct ieee80211_txq *txq)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_txq *mvmtxq = iwl_mvm_txq_from_mac80211(txq);
@@ -897,9 +895,9 @@ iwl_mvm_ampdu_check_trigger(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
}
}

-static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_ampdu_params *params)
+int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_ampdu_params *params)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
@@ -1095,7 +1093,7 @@ int __iwl_mvm_mac_start(struct iwl_mvm *mvm)
return ret;
}

-static int iwl_mvm_mac_start(struct ieee80211_hw *hw)
+int iwl_mvm_mac_start(struct ieee80211_hw *hw)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
@@ -1164,9 +1162,8 @@ static void iwl_mvm_restart_complete(struct iwl_mvm *mvm)
mutex_unlock(&mvm->mutex);
}

-static void
-iwl_mvm_mac_reconfig_complete(struct ieee80211_hw *hw,
- enum ieee80211_reconfig_type reconfig_type)
+void iwl_mvm_mac_reconfig_complete(struct ieee80211_hw *hw,
+ enum ieee80211_reconfig_type reconfig_type)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);

@@ -1228,7 +1225,7 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm)
}
}

-static void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
+void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);

@@ -1366,8 +1363,8 @@ int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
return ret;
}

-static void iwl_mvm_abort_channel_switch(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+void iwl_mvm_abort_channel_switch(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
@@ -1731,11 +1728,6 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
mutex_unlock(&mvm->mutex);
}

-static int iwl_mvm_mac_config(struct ieee80211_hw *hw, u32 changed)
-{
- return 0;
-}
-
struct iwl_mvm_mc_iter_data {
struct iwl_mvm *mvm;
int port_id;
@@ -1807,8 +1799,8 @@ static void iwl_mvm_recalc_multicast(struct iwl_mvm *mvm)
IWL_ERR(mvm, "Failed to synchronize multicast groups update\n");
}

-static u64 iwl_mvm_prepare_multicast(struct ieee80211_hw *hw,
- struct netdev_hw_addr_list *mc_list)
+u64 iwl_mvm_prepare_multicast(struct ieee80211_hw *hw,
+ struct netdev_hw_addr_list *mc_list)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mcast_filter_cmd *cmd;
@@ -1844,10 +1836,9 @@ static u64 iwl_mvm_prepare_multicast(struct ieee80211_hw *hw,
return (u64)(unsigned long)cmd;
}

-static void iwl_mvm_configure_filter(struct ieee80211_hw *hw,
- unsigned int changed_flags,
- unsigned int *total_flags,
- u64 multicast)
+void iwl_mvm_configure_filter(struct ieee80211_hw *hw,
+ unsigned int changed_flags,
+ unsigned int *total_flags, u64 multicast)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mcast_filter_cmd *cmd = (void *)(unsigned long)multicast;
@@ -3038,9 +3029,8 @@ iwl_mvm_bss_info_changed_common(struct ieee80211_hw *hw,
mutex_unlock(&mvm->mutex);
}

-static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_scan_request *hw_req)
+int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_scan_request *hw_req)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
@@ -3056,8 +3046,8 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
return ret;
}

-static void iwl_mvm_mac_cancel_hw_scan(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+void iwl_mvm_mac_cancel_hw_scan(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);

@@ -3076,7 +3066,7 @@ static void iwl_mvm_mac_cancel_hw_scan(struct ieee80211_hw *hw,
mutex_unlock(&mvm->mutex);
}

-static void
+void
iwl_mvm_mac_allow_buffered_frames(struct ieee80211_hw *hw,
struct ieee80211_sta *sta, u16 tids,
int num_frames,
@@ -3091,7 +3081,7 @@ iwl_mvm_mac_allow_buffered_frames(struct ieee80211_hw *hw,
tids, more_data, false);
}

-static void
+void
iwl_mvm_mac_release_buffered_frames(struct ieee80211_hw *hw,
struct ieee80211_sta *sta, u16 tids,
int num_frames,
@@ -3165,10 +3155,8 @@ static void __iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
spin_unlock_bh(&mvmsta->lock);
}

-static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- enum sta_notify_cmd cmd,
- struct ieee80211_sta *sta)
+void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ enum sta_notify_cmd cmd, struct ieee80211_sta *sta)
{
__iwl_mvm_mac_sta_notify(hw, cmd, sta);
}
@@ -3226,9 +3214,9 @@ void iwl_mvm_sta_pm_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
rcu_read_unlock();
}

-static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
@@ -3710,7 +3698,7 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
return ret;
}

-static int iwl_mvm_mac_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
+int iwl_mvm_mac_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);

@@ -3719,9 +3707,8 @@ static int iwl_mvm_mac_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
return 0;
}

-static void iwl_mvm_sta_rc_update(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta, u32 changed)
+void iwl_mvm_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta, u32 changed)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
@@ -3763,9 +3750,9 @@ static int iwl_mvm_mac_conf_tx(struct ieee80211_hw *hw,
return 0;
}

-static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_prep_tx_info *info)
+void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_prep_tx_info *info)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);

@@ -3774,9 +3761,9 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
mutex_unlock(&mvm->mutex);
}

-static void iwl_mvm_mac_mgd_complete_tx(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_prep_tx_info *info)
+void iwl_mvm_mac_mgd_complete_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_prep_tx_info *info)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);

@@ -3789,10 +3776,10 @@ static void iwl_mvm_mac_mgd_complete_tx(struct ieee80211_hw *hw,
mutex_unlock(&mvm->mutex);
}

-static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct cfg80211_sched_scan_request *req,
- struct ieee80211_scan_ies *ies)
+int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct cfg80211_sched_scan_request *req,
+ struct ieee80211_scan_ies *ies)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);

@@ -3812,8 +3799,8 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
return ret;
}

-static int iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+int iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
@@ -4069,11 +4056,9 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
return ret;
}

-static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
- enum set_key_cmd cmd,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct ieee80211_key_conf *key)
+int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
@@ -4085,11 +4070,11 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
return ret;
}

-static void iwl_mvm_mac_update_tkip_key(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_key_conf *keyconf,
- struct ieee80211_sta *sta,
- u32 iv32, u16 *phase1key)
+void iwl_mvm_mac_update_tkip_key(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_key_conf *keyconf,
+ struct ieee80211_sta *sta,
+ u32 iv32, u16 *phase1key)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);

@@ -4519,8 +4504,8 @@ static int __iwl_mvm_add_chanctx(struct iwl_mvm *mvm,
return ret;
}

-static int iwl_mvm_add_chanctx(struct ieee80211_hw *hw,
- struct ieee80211_chanctx_conf *ctx)
+int iwl_mvm_add_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *ctx)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
@@ -4543,8 +4528,8 @@ static void __iwl_mvm_remove_chanctx(struct iwl_mvm *mvm,
iwl_mvm_phy_ctxt_unref(mvm, phy_ctxt);
}

-static void iwl_mvm_remove_chanctx(struct ieee80211_hw *hw,
- struct ieee80211_chanctx_conf *ctx)
+void iwl_mvm_remove_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *ctx)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);

@@ -4553,9 +4538,8 @@ static void iwl_mvm_remove_chanctx(struct ieee80211_hw *hw,
mutex_unlock(&mvm->mutex);
}

-static void iwl_mvm_change_chanctx(struct ieee80211_hw *hw,
- struct ieee80211_chanctx_conf *ctx,
- u32 changed)
+void iwl_mvm_change_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *ctx, u32 changed)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
@@ -4963,16 +4947,15 @@ static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw,
return iwl_mvm_switch_vif_chanctx_common(hw, vifs, n_vifs, mode, &ops);
}

-static int iwl_mvm_tx_last_beacon(struct ieee80211_hw *hw)
+int iwl_mvm_tx_last_beacon(struct ieee80211_hw *hw)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);

return mvm->ibss_manager;
}

-static int iwl_mvm_set_tim(struct ieee80211_hw *hw,
- struct ieee80211_sta *sta,
- bool set)
+int iwl_mvm_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
+ bool set)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
@@ -5038,9 +5021,9 @@ static int __iwl_mvm_mac_testmode_cmd(struct iwl_mvm *mvm,
return -EOPNOTSUPP;
}

-static int iwl_mvm_mac_testmode_cmd(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- void *data, int len)
+int iwl_mvm_mac_testmode_cmd(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ void *data, int len)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int err;
@@ -5053,9 +5036,8 @@ static int iwl_mvm_mac_testmode_cmd(struct ieee80211_hw *hw,
}
#endif

-static void iwl_mvm_channel_switch(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_channel_switch *chsw)
+void iwl_mvm_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_channel_switch *chsw)
{
/* By implementing this operation, we prevent mac80211 from
* starting its own channel switch timer, so that we can call
@@ -5130,9 +5112,9 @@ static int iwl_mvm_old_pre_chan_sw_sta(struct iwl_mvm *mvm,
}

#define IWL_MAX_CSA_BLOCK_TX 1500
-static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_channel_switch *chsw)
+int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_channel_switch *chsw)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct ieee80211_vif *csa_vif;
@@ -5245,9 +5227,9 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
return ret;
}

-static void iwl_mvm_channel_switch_rx_beacon(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_channel_switch *chsw)
+void iwl_mvm_channel_switch_rx_beacon(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_channel_switch *chsw)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
@@ -5332,8 +5314,8 @@ static void iwl_mvm_flush_no_vif(struct iwl_mvm *mvm, u32 queues, bool drop)
mutex_unlock(&mvm->mutex);
}

-static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif, u32 queues, bool drop)
+void iwl_mvm_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ u32 queues, bool drop)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif;
@@ -5390,8 +5372,8 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,
iwl_trans_wait_tx_queues_empty(mvm->trans, msk);
}

-static int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx,
- struct survey_info *survey)
+int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx,
+ struct survey_info *survey)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
@@ -5575,10 +5557,10 @@ static void iwl_mvm_set_sta_rate(u32 rate_n_flags, struct rate_info *rinfo)
}
}

-static void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct station_info *sinfo)
+void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct station_info *sinfo)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
@@ -5719,9 +5701,9 @@ static void iwl_mvm_event_bar_rx_callback(struct iwl_mvm *mvm,
event->u.ba.ssn);
}

-static void iwl_mvm_mac_event_callback(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- const struct ieee80211_event *event)
+void iwl_mvm_mac_event_callback(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ const struct ieee80211_event *event)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);

@@ -5803,7 +5785,7 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
}
}

-static void iwl_mvm_sync_rx_queues(struct ieee80211_hw *hw)
+void iwl_mvm_sync_rx_queues(struct ieee80211_hw *hw)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);

@@ -5812,7 +5794,7 @@ static void iwl_mvm_sync_rx_queues(struct ieee80211_hw *hw)
mutex_unlock(&mvm->mutex);
}

-static int
+int
iwl_mvm_mac_get_ftm_responder_stats(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_ftm_responder_stats *stats)
@@ -5841,9 +5823,8 @@ iwl_mvm_mac_get_ftm_responder_stats(struct ieee80211_hw *hw,
return 0;
}

-static int iwl_mvm_start_pmsr(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct cfg80211_pmsr_request *request)
+int iwl_mvm_start_pmsr(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct cfg80211_pmsr_request *request)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
@@ -5855,9 +5836,8 @@ static int iwl_mvm_start_pmsr(struct ieee80211_hw *hw,
return ret;
}

-static void iwl_mvm_abort_pmsr(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct cfg80211_pmsr_request *request)
+void iwl_mvm_abort_pmsr(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct cfg80211_pmsr_request *request)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index 818aed050b73..5f54e57de8e6 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -244,7 +244,8 @@ static void iwl_mvm_mld_unassign_vif_chanctx(struct ieee80211_hw *hw,
}

static int iwl_mvm_mld_start_ap_ibss(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
@@ -319,8 +320,22 @@ static int iwl_mvm_mld_start_ap_ibss(struct ieee80211_hw *hw,
return ret;
}

+static int iwl_mvm_mld_start_ap(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf)
+{
+ return iwl_mvm_mld_start_ap_ibss(hw, vif, link_conf);
+}
+
+static int iwl_mvm_mld_start_ibss(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ return iwl_mvm_mld_start_ap_ibss(hw, vif, &vif->bss_conf);
+}
+
static void iwl_mvm_mld_stop_ap_ibss(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);

@@ -348,6 +363,19 @@ static void iwl_mvm_mld_stop_ap_ibss(struct ieee80211_hw *hw,
mutex_unlock(&mvm->mutex);
}

+static void iwl_mvm_mld_stop_ap(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf)
+{
+ iwl_mvm_mld_stop_ap_ibss(hw, vif, link_conf);
+}
+
+static void iwl_mvm_mld_stop_ibss(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ iwl_mvm_mld_stop_ap_ibss(hw, vif, &vif->bss_conf);
+}
+
static int iwl_mvm_mld_mac_sta_state(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -630,18 +658,90 @@ static int iwl_mvm_mld_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
return iwl_mvm_roc_common(hw, vif, channel, duration, type, &ops);
}
const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
+ .tx = iwl_mvm_mac_tx,
+ .wake_tx_queue = iwl_mvm_mac_wake_tx_queue,
+ .ampdu_action = iwl_mvm_mac_ampdu_action,
+ .get_antenna = iwl_mvm_op_get_antenna,
+ .start = iwl_mvm_mac_start,
+ .reconfig_complete = iwl_mvm_mac_reconfig_complete,
+ .stop = iwl_mvm_mac_stop,
.add_interface = iwl_mvm_mld_mac_add_interface,
.remove_interface = iwl_mvm_mld_mac_remove_interface,
+ .config = iwl_mvm_mac_config,
+ .prepare_multicast = iwl_mvm_prepare_multicast,
+ .configure_filter = iwl_mvm_configure_filter,
.config_iface_filter = iwl_mvm_mld_config_iface_filter,
+ .bss_info_changed = iwl_mvm_mld_bss_info_changed,
+ .hw_scan = iwl_mvm_mac_hw_scan,
+ .cancel_hw_scan = iwl_mvm_mac_cancel_hw_scan,
+ .sta_pre_rcu_remove = iwl_mvm_sta_pre_rcu_remove,
+ .sta_state = iwl_mvm_mld_mac_sta_state,
+ .sta_notify = iwl_mvm_mac_sta_notify,
+ .allow_buffered_frames = iwl_mvm_mac_allow_buffered_frames,
+ .release_buffered_frames = iwl_mvm_mac_release_buffered_frames,
+ .set_rts_threshold = iwl_mvm_mac_set_rts_threshold,
+ .sta_rc_update = iwl_mvm_sta_rc_update,
+ .conf_tx = iwl_mvm_mld_mac_conf_tx,
+ .mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx,
+ .mgd_complete_tx = iwl_mvm_mac_mgd_complete_tx,
+ .mgd_protect_tdls_discover = iwl_mvm_mac_mgd_protect_tdls_discover,
+ .flush = iwl_mvm_mac_flush,
+ .sched_scan_start = iwl_mvm_mac_sched_scan_start,
+ .sched_scan_stop = iwl_mvm_mac_sched_scan_stop,
+ .set_key = iwl_mvm_mac_set_key,
+ .update_tkip_key = iwl_mvm_mac_update_tkip_key,
.remain_on_channel = iwl_mvm_mld_roc,
.cancel_remain_on_channel = iwl_mvm_cancel_roc,
+ .add_chanctx = iwl_mvm_add_chanctx,
+ .remove_chanctx = iwl_mvm_remove_chanctx,
+ .change_chanctx = iwl_mvm_change_chanctx,
.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,
- .join_ibss = iwl_mvm_mld_start_ap_ibss,
- .leave_ibss = iwl_mvm_mld_stop_ap_ibss,
+
+ .start_ap = iwl_mvm_mld_start_ap,
+ .stop_ap = iwl_mvm_mld_stop_ap,
+ .join_ibss = iwl_mvm_mld_start_ibss,
+ .leave_ibss = iwl_mvm_mld_stop_ibss,
+
+ .tx_last_beacon = iwl_mvm_tx_last_beacon,
+
+ .set_tim = iwl_mvm_set_tim,
+
+ .channel_switch = iwl_mvm_channel_switch,
+ .pre_channel_switch = iwl_mvm_pre_channel_switch,
.post_channel_switch = iwl_mvm_post_channel_switch,
- .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,
+ .abort_channel_switch = iwl_mvm_abort_channel_switch,
+ .channel_switch_rx_beacon = iwl_mvm_channel_switch_rx_beacon,
+
+ .tdls_channel_switch = iwl_mvm_tdls_channel_switch,
+ .tdls_cancel_channel_switch = iwl_mvm_tdls_cancel_channel_switch,
+ .tdls_recv_channel_switch = iwl_mvm_tdls_recv_channel_switch,
+
+ .event_callback = iwl_mvm_mac_event_callback,
+
+ .sync_rx_queues = iwl_mvm_sync_rx_queues,
+
+ CFG80211_TESTMODE_CMD(iwl_mvm_mac_testmode_cmd)
+
+#ifdef CONFIG_PM_SLEEP
+ /* look at d3.c */
+ .suspend = iwl_mvm_suspend,
+ .resume = iwl_mvm_resume,
+ .set_wakeup = iwl_mvm_set_wakeup,
+ .set_rekey_data = iwl_mvm_set_rekey_data,
+#if IS_ENABLED(CONFIG_IPV6)
+ .ipv6_addr_change = iwl_mvm_ipv6_addr_change,
+#endif
+ .set_default_unicast_key = iwl_mvm_set_default_unicast_key,
+#endif
+ .get_survey = iwl_mvm_mac_get_survey,
+ .sta_statistics = iwl_mvm_mac_sta_statistics,
+ .get_ftm_responder_stats = iwl_mvm_mac_get_ftm_responder_stats,
+ .start_pmsr = iwl_mvm_start_pmsr,
+ .abort_pmsr = iwl_mvm_abort_pmsr,
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+ .sta_add_debugfs = iwl_mvm_sta_add_debugfs,
+#endif
};
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index bf1de6405cd6..6f4ed5d1efb9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -1384,6 +1384,28 @@ static inline bool iwl_mvm_has_new_rx_api(struct iwl_mvm *mvm)
IWL_UCODE_TLV_CAPA_MULTI_QUEUE_RX_SUPPORT);
}

+static inline bool iwl_mvm_has_mld_api(const struct iwl_fw *fw)
+{
+ return (iwl_fw_lookup_cmd_ver(fw, LINK_CONFIG_CMD,
+ IWL_FW_CMD_VER_UNKNOWN) !=
+ IWL_FW_CMD_VER_UNKNOWN) &&
+ (iwl_fw_lookup_cmd_ver(fw, MAC_CONFIG_CMD,
+ IWL_FW_CMD_VER_UNKNOWN) !=
+ IWL_FW_CMD_VER_UNKNOWN) &&
+ (iwl_fw_lookup_cmd_ver(fw, STA_CONFIG_CMD,
+ IWL_FW_CMD_VER_UNKNOWN) !=
+ IWL_FW_CMD_VER_UNKNOWN) &&
+ (iwl_fw_lookup_cmd_ver(fw, AUX_STA_CMD,
+ IWL_FW_CMD_VER_UNKNOWN) !=
+ IWL_FW_CMD_VER_UNKNOWN) &&
+ (iwl_fw_lookup_cmd_ver(fw, STA_REMOVE_CMD,
+ IWL_FW_CMD_VER_UNKNOWN) !=
+ IWL_FW_CMD_VER_UNKNOWN) &&
+ (iwl_fw_lookup_cmd_ver(fw, STA_DISABLE_TX_CMD,
+ IWL_FW_CMD_VER_UNKNOWN) !=
+ IWL_FW_CMD_VER_UNKNOWN);
+}
+
static inline bool iwl_mvm_has_new_tx_api(struct iwl_mvm *mvm)
{
/* TODO - replace with TLV once defined */
@@ -2462,4 +2484,117 @@ void iwl_mvm_send_roaming_forbidden_event(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
bool forbidden);
bool iwl_mvm_is_vendor_in_approved_list(void);
+
+/* Callbacks for ieee80211_ops */
+void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
+ struct ieee80211_tx_control *control, struct sk_buff *skb);
+void iwl_mvm_mac_wake_tx_queue(struct ieee80211_hw *hw,
+ struct ieee80211_txq *txq);
+
+int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_ampdu_params *params);
+int iwl_mvm_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
+int iwl_mvm_mac_start(struct ieee80211_hw *hw);
+void iwl_mvm_mac_reconfig_complete(struct ieee80211_hw *hw,
+ enum ieee80211_reconfig_type reconfig_type);
+void iwl_mvm_mac_stop(struct ieee80211_hw *hw);
+static inline int iwl_mvm_mac_config(struct ieee80211_hw *hw, u32 changed)
+{
+ return 0;
+}
+
+u64 iwl_mvm_prepare_multicast(struct ieee80211_hw *hw,
+ struct netdev_hw_addr_list *mc_list);
+
+void iwl_mvm_configure_filter(struct ieee80211_hw *hw,
+ unsigned int changed_flags,
+ unsigned int *total_flags, u64 multicast);
+int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_scan_request *hw_req);
+void iwl_mvm_mac_cancel_hw_scan(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
+void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
+void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ enum sta_notify_cmd cmd,
+ struct ieee80211_sta *sta);
+void
+iwl_mvm_mac_allow_buffered_frames(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta, u16 tids,
+ int num_frames,
+ enum ieee80211_frame_release_type reason,
+ bool more_data);
+void
+iwl_mvm_mac_release_buffered_frames(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta, u16 tids,
+ int num_frames,
+ enum ieee80211_frame_release_type reason,
+ bool more_data);
+int iwl_mvm_mac_set_rts_threshold(struct ieee80211_hw *hw, u32 value);
+void iwl_mvm_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta, u32 changed);
+void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_prep_tx_info *info);
+void iwl_mvm_mac_mgd_complete_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_prep_tx_info *info);
+void iwl_mvm_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ u32 queues, bool drop);
+int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct cfg80211_sched_scan_request *req,
+ struct ieee80211_scan_ies *ies);
+int iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
+int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key);
+void iwl_mvm_mac_update_tkip_key(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_key_conf *keyconf,
+ struct ieee80211_sta *sta,
+ u32 iv32, u16 *phase1key);
+int iwl_mvm_add_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *ctx);
+void iwl_mvm_remove_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *ctx);
+void iwl_mvm_change_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *ctx, u32 changed);
+int iwl_mvm_tx_last_beacon(struct ieee80211_hw *hw);
+int iwl_mvm_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
+ bool set);
+void iwl_mvm_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_channel_switch *chsw);
+int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_channel_switch *chsw);
+void iwl_mvm_abort_channel_switch(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
+void iwl_mvm_channel_switch_rx_beacon(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_channel_switch *chsw);
+void iwl_mvm_mac_event_callback(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ const struct ieee80211_event *event);
+void iwl_mvm_sync_rx_queues(struct ieee80211_hw *hw);
+int iwl_mvm_mac_testmode_cmd(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ void *data, int len);
+int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx,
+ struct survey_info *survey);
+void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct station_info *sinfo);
+int
+iwl_mvm_mac_get_ftm_responder_stats(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct cfg80211_ftm_responder_stats *stats);
+int iwl_mvm_start_pmsr(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct cfg80211_pmsr_request *request);
+void iwl_mvm_abort_pmsr(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct cfg80211_pmsr_request *request);
#endif /* __IWL_MVM_H__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index 5c8784ddfa66..b355b9ebad0a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -1116,6 +1116,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
********************************/
hw = ieee80211_alloc_hw(sizeof(struct iwl_op_mode) +
sizeof(struct iwl_mvm),
+ iwl_mvm_has_mld_api(fw) ? &iwl_mvm_mld_hw_ops :
&iwl_mvm_hw_ops);
if (!hw)
return NULL;
@@ -1295,8 +1296,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
mvm->sta_remove_requires_queue_remove =
trans_cfg.queue_alloc_cmd_ver > 0;

- /* Until we register with the MLD ops - we don't use the MLD API */
- mvm->mld_api_is_used = false;
+ mvm->mld_api_is_used = iwl_mvm_has_mld_api(mvm->fw);

/* Configure transport layer */
iwl_trans_configure(mvm->trans, &trans_cfg);
--
2.38.1

2023-03-28 08:05:56

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 12/31] wifi: iwlwifi: mvm: fix crash on queue removal for MLD API too

From: Miri Korenblit <[email protected]>

The patch linked below fixes the crash on queue removal bug only
for the non-MLD API. Do the same for the MLD API.

Fixes: c5a976cf6a75 ("wifi: iwlwifi: modify new queue allocation command")
Signed-off-by: Miri Korenblit <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
.../net/wireless/intel/iwlwifi/mvm/mld-sta.c | 18 +++++-------------
1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
index a6eb18830cd9..fc380e59c740 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
@@ -258,27 +258,19 @@ int iwl_mvm_mld_add_aux_sta(struct iwl_mvm *mvm, u32 lmac_id)
IWL_MAX_TID_COUNT, NULL);
}

-static int iwl_mvm_mld_disable_txq(struct iwl_mvm *mvm,
- struct ieee80211_sta *sta,
+static int iwl_mvm_mld_disable_txq(struct iwl_mvm *mvm, int sta_id,
u16 *queueptr, u8 tid)
{
- struct iwl_mvm_sta *mvmsta;
int queue = *queueptr;
int ret = 0;

- if (!sta)
- return -EINVAL;
-
- mvmsta = iwl_mvm_sta_from_mac80211(sta);
-
if (mvm->sta_remove_requires_queue_remove) {
u32 cmd_id = WIDE_ID(DATA_PATH_GROUP,
SCD_QUEUE_CONFIG_CMD);
struct iwl_scd_queue_cfg_cmd remove_cmd = {
.operation = cpu_to_le32(IWL_SCD_QUEUE_REMOVE),
.u.remove.tid = cpu_to_le32(tid),
- .u.remove.sta_mask =
- cpu_to_le32(BIT(mvmsta->deflink.sta_id)),
+ .u.remove.sta_mask = cpu_to_le32(BIT(sta_id)),
};

ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0,
@@ -308,7 +300,7 @@ static int iwl_mvm_mld_rm_int_sta(struct iwl_mvm *mvm,
if (flush)
iwl_mvm_flush_sta(mvm, int_sta, true);

- iwl_mvm_mld_disable_txq(mvm, NULL, queuptr, tid);
+ iwl_mvm_mld_disable_txq(mvm, int_sta->sta_id, queuptr, tid);

ret = iwl_mvm_mld_rm_sta_from_fw(mvm, int_sta->sta_id);
if (ret)
@@ -536,8 +528,8 @@ static void iwl_mvm_mld_disable_sta_queues(struct iwl_mvm *mvm,
if (mvm_sta->tid_data[i].txq_id == IWL_MVM_INVALID_QUEUE)
continue;

- iwl_mvm_mld_disable_txq(mvm, sta, &mvm_sta->tid_data[i].txq_id,
- i);
+ iwl_mvm_mld_disable_txq(mvm, mvm_sta->deflink.sta_id,
+ &mvm_sta->tid_data[i].txq_id, i);
mvm_sta->tid_data[i].txq_id = IWL_MVM_INVALID_QUEUE;
}

--
2.38.1

2023-03-28 08:06:03

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 11/31] wifi: iwlwifi: mvm: fix "modify_mask" value in the link cmd.

From: Miri Korenblit <[email protected]>

This bitmap indicates what fields of the cmd got changed.
A field will be ignored by the FW if the corresponding flag wasn't set.
There are a few cases in which we currently set the wrong bits when
sending this cmd, which caused FW asserts. Fix this by setting the
correct bits in each case.

Fixes: 1ab26632332e ("wifi: iwlwifi: mvm: Add an add_interface() callback for mld mode")
Signed-off-by: Miri Korenblit <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index 5f54e57de8e6..33368e5945f4 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -54,9 +54,7 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
if (ret)
goto out_unref_phy;

- ret = iwl_mvm_link_changed(mvm, vif,
- LINK_CONTEXT_MODIFY_ACTIVE |
- LINK_CONTEXT_MODIFY_RATES_INFO,
+ ret = iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ACTIVE,
true);
if (ret)
goto out_remove_link;
@@ -162,7 +160,8 @@ static int __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
ret = iwl_mvm_add_link(mvm, vif);
if (ret)
goto out;
- ret = iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ACTIVE,
+ ret = iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ACTIVE |
+ LINK_CONTEXT_MODIFY_RATES_INFO,
true);
if (ret)
goto out_remove_link;
@@ -270,7 +269,7 @@ static int iwl_mvm_mld_start_ap_ibss(struct ieee80211_hw *hw,
if (ret)
goto out_remove_mac;

- ret = iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ACTIVE,
+ ret = iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ALL,
true);
if (ret)
goto out_remove_link;
--
2.38.1

2023-03-28 08:06:07

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 14/31] wifi: iwlwifi: mvm: always use the sta->addr as the peers addr

From: Miri Korenblit <[email protected]>

Currently we're setting the sta->addr as the peers address only if
the iftype is NL80211_IFTYPE_AP, otherwise we are setting the bssid to
be the addr. This causes bugs in TDLS. Fix this by always using the
sta->addr.

Signed-off-by: Miri Korenblit <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
index fc380e59c740..41f6be7fe75e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
@@ -380,13 +380,8 @@ static int iwl_mvm_mld_cfg_sta(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
u32 agg_size = 0, mpdu_dens = 0;

/* For now the link addr is the same as the mld addr */
- if (vif->type == NL80211_IFTYPE_AP) {
- memcpy(&cmd.peer_mld_address, sta->addr, ETH_ALEN);
- memcpy(&cmd.peer_link_address, sta->addr, ETH_ALEN);
- } else if (vif->bss_conf.bssid) {
- memcpy(&cmd.peer_mld_address, vif->bss_conf.bssid, ETH_ALEN);
- memcpy(&cmd.peer_link_address, vif->bss_conf.bssid, ETH_ALEN);
- }
+ memcpy(&cmd.peer_mld_address, sta->addr, ETH_ALEN);
+ memcpy(&cmd.peer_link_address, sta->addr, ETH_ALEN);

if (mvm_sta->sta_state >= IEEE80211_STA_ASSOC)
cmd.assoc_id = cpu_to_le32(sta->aid);
--
2.38.1

2023-03-28 08:06:11

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 13/31] wifi: iwlwifi: mvm: modify link instead of removing it during csa

From: Miri Korenblit <[email protected]>

During CSA the PHY used by the link is changing, So the driver
needs to modify the links phy to the FW. Currently the driver is doing
it by removing the link and adding a new one with the new phy_id, but the
FW expects the link only to be modified. Fix this by modifying the links
phy_id instead of removing it and adding a new one

Signed-off-by: Miri Korenblit <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
.../wireless/intel/iwlwifi/mvm/mld-mac80211.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index 33368e5945f4..5be8058ca669 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -157,9 +157,16 @@ static int __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
switching_chanctx, &ret))
goto out;

- ret = iwl_mvm_add_link(mvm, vif);
- if (ret)
- goto out;
+ if (!switching_chanctx) {
+ ret = iwl_mvm_add_link(mvm, vif);
+ if (ret)
+ goto out;
+ } else {
+ ret = iwl_mvm_link_changed(mvm, vif, 0, false);
+ if (ret)
+ goto out_remove_link;
+ }
+
ret = iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ACTIVE |
LINK_CONTEXT_MODIFY_RATES_INFO,
true);
@@ -219,10 +226,9 @@ static void __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm,
if (vif->type == NL80211_IFTYPE_MONITOR)
iwl_mvm_mld_rm_snif_sta(mvm, vif);

- /* Link needs to be deactivated before removal */
iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ACTIVE, false);
- iwl_mvm_remove_link(mvm, vif);
-
+ if (!switching_chanctx)
+ iwl_mvm_remove_link(mvm, vif);
out:
if (switching_chanctx)
return;
--
2.38.1

2023-03-28 08:06:22

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 16/31] wifi: iwlwifi: mvm: adjust smart fifo configuration to MLO

From: Gregory Greenman <[email protected]>

Consider properties of all available links for smart FIFO
configuration.

Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/sf.c | 32 +++++++++++++++++----
1 file changed, 27 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sf.c b/drivers/net/wireless/intel/iwlwifi/mvm/sf.c
index 84b750d02848..7c5f41e40e7a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sf.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sf.c
@@ -98,6 +98,10 @@ static void iwl_mvm_fill_sf_command(struct iwl_mvm *mvm,
struct ieee80211_sta *sta)
{
int i, j, watermark;
+ u8 max_rx_nss = 0;
+ bool is_legacy = true;
+ struct ieee80211_link_sta *link_sta;
+ unsigned int link_id;

sf_cmd->watermark[SF_LONG_DELAY_ON] = cpu_to_le32(SF_W_MARK_SCAN);

@@ -106,10 +110,25 @@ static void iwl_mvm_fill_sf_command(struct iwl_mvm *mvm,
* capabilities of the AP station, and choose the watermark accordingly.
*/
if (sta) {
- if (sta->deflink.ht_cap.ht_supported ||
- sta->deflink.vht_cap.vht_supported ||
- sta->deflink.he_cap.has_he) {
- switch (sta->deflink.rx_nss) {
+ /* find the maximal NSS number among all links (if relevant) */
+ rcu_read_lock();
+ for (link_id = 0; link_id < ARRAY_SIZE(sta->link); link_id++) {
+ link_sta = rcu_dereference(sta->link[link_id]);
+ if (!link_sta)
+ continue;
+
+ if (link_sta->ht_cap.ht_supported ||
+ link_sta->vht_cap.vht_supported ||
+ link_sta->eht_cap.has_eht ||
+ link_sta->he_cap.has_he) {
+ is_legacy = false;
+ max_rx_nss = max(max_rx_nss, link_sta->rx_nss);
+ }
+ }
+ rcu_read_unlock();
+
+ if (!is_legacy) {
+ switch (max_rx_nss) {
case 1:
watermark = SF_W_MARK_SISO;
break;
@@ -151,7 +170,6 @@ static void iwl_mvm_fill_sf_command(struct iwl_mvm *mvm,
memcpy(sf_cmd->full_on_timeouts, sf_full_timeout_def,
sizeof(sf_full_timeout_def));
}
-
}

static int iwl_mvm_sf_config(struct iwl_mvm *mvm, u8 sta_id,
@@ -275,5 +293,9 @@ int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *changed_vif,
/* If there are multiple active macs - change to SF_UNINIT */
new_state = SF_UNINIT;
}
+
+ /* For MLO it's ok to use deflink->sta_id as it's needed only to get
+ * a pointer to mac80211 sta
+ */
return iwl_mvm_sf_config(mvm, sta_id, new_state);
}
--
2.38.1

2023-03-28 08:06:24

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 17/31] wifi: iwlwifi: mvm: adjust mld_mac_ctxt_/beacon_changed() for MLO

From: Gregory Greenman <[email protected]>

HE/EHT support is reported to FW if there's at least one link
that supports it. Configure beacon separately for each link.
Don't send the beacon template before adding the MAC.

Co-developed-by: Johannes Berg <[email protected]>
Co-developed-by: Emmanuel Grumbach <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
.../net/wireless/intel/iwlwifi/fw/api/tx.h | 10 ++--
.../net/wireless/intel/iwlwifi/mvm/debugfs.c | 22 +++++----
.../net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 24 +++++----
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 39 ++++++++++-----
.../net/wireless/intel/iwlwifi/mvm/mld-mac.c | 49 ++++++++++++++++---
.../wireless/intel/iwlwifi/mvm/mld-mac80211.c | 12 ++---
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 6 ++-
7 files changed, 115 insertions(+), 47 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h
index ecc6706f66ed..97edf5477ba7 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h
@@ -800,7 +800,7 @@ enum iwl_mac_beacon_flags {
* is &enum iwl_mac_beacon_flags.
* @short_ssid: Short SSID
* @reserved: reserved
- * @template_id: currently equal to the mac context id of the coresponding mac.
+ * @link_id: the firmware id of the link that will use this beacon
* @tim_idx: the offset of the tim IE in the beacon
* @tim_size: the length of the tim IE
* @ecsa_offset: offset to the ECSA IE if present
@@ -812,15 +812,17 @@ struct iwl_mac_beacon_cmd {
__le16 flags;
__le32 short_ssid;
__le32 reserved;
- __le32 template_id;
+ __le32 link_id;
__le32 tim_idx;
__le32 tim_size;
__le32 ecsa_offset;
__le32 csa_offset;
struct ieee80211_hdr frame[];
} __packed; /* BEACON_TEMPLATE_CMD_API_S_VER_10,
- BEACON_TEMPLATE_CMD_API_S_VER_11,
- BEACON_TEMPLATE_CMD_API_S_VER_12 */
+ * BEACON_TEMPLATE_CMD_API_S_VER_11,
+ * BEACON_TEMPLATE_CMD_API_S_VER_12,
+ * BEACON_TEMPLATE_CMD_API_S_VER_13
+ */

struct iwl_beacon_notif {
struct iwl_mvm_tx_resp beacon_notify_hdr;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
index b5eb0ee298ad..2c72f5cb19f1 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
@@ -1388,6 +1388,7 @@ static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len)
struct sk_buff *beacon;
struct ieee80211_tx_info *info;
struct iwl_mac_beacon_cmd beacon_cmd = {};
+ unsigned int link_id;
u8 rate;
int i;

@@ -1436,17 +1437,20 @@ static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len)
info = IEEE80211_SKB_CB(beacon);
rate = iwl_mvm_mac_ctxt_get_beacon_rate(mvm, info, vif);

- beacon_cmd.flags =
- cpu_to_le16(iwl_mvm_mac_ctxt_get_beacon_flags(mvm->fw, rate));
- beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len);
- beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id);
+ for_each_mvm_vif_valid_link(mvmvif, link_id) {
+ beacon_cmd.flags =
+ cpu_to_le16(iwl_mvm_mac_ctxt_get_beacon_flags(mvm->fw,
+ rate));
+ beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len);
+ beacon_cmd.link_id = cpu_to_le32((u32)mvmvif->id);

- iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx,
- &beacon_cmd.tim_size,
- beacon->data, beacon->len);
+ iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx,
+ &beacon_cmd.tim_size,
+ beacon->data, beacon->len);

- iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd,
- sizeof(beacon_cmd));
+ iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd,
+ sizeof(beacon_cmd));
+ }
mutex_unlock(&mvm->mutex);

dev_kfree_skb(beacon);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index 10dc1fdbdeb3..a06513989469 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -1039,7 +1039,8 @@ static int iwl_mvm_mac_ctxt_send_beacon_v7(struct iwl_mvm *mvm,

static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
- struct sk_buff *beacon)
+ struct sk_buff *beacon,
+ struct ieee80211_bss_conf *link_conf)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(beacon);
@@ -1052,7 +1053,7 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,

/* Enable FILS on PSC channels only */
rcu_read_lock();
- ctx = rcu_dereference(vif->bss_conf.chanctx_conf);
+ ctx = rcu_dereference(link_conf->chanctx_conf);
channel = ieee80211_frequency_to_channel(ctx->def.chan->center_freq);
WARN_ON(channel == 0);
if (cfg80211_channel_is_psc(ctx->def.chan) &&
@@ -1069,7 +1070,7 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,

beacon_cmd.flags = cpu_to_le16(flags);
beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len);
- beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id);
+ beacon_cmd.link_id = cpu_to_le32((u32)mvmvif->id);

if (vif->type == NL80211_IFTYPE_AP)
iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx,
@@ -1091,7 +1092,8 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,

int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
- struct sk_buff *beacon)
+ struct sk_buff *beacon,
+ struct ieee80211_bss_conf *link_conf)
{
if (WARN_ON(!beacon))
return -EINVAL;
@@ -1105,14 +1107,16 @@ int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,

if (fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_NEW_BEACON_TEMPLATE))
- return iwl_mvm_mac_ctxt_send_beacon_v9(mvm, vif, beacon);
+ return iwl_mvm_mac_ctxt_send_beacon_v9(mvm, vif, beacon,
+ link_conf);

return iwl_mvm_mac_ctxt_send_beacon_v7(mvm, vif, beacon);
}

/* The beacon template for the AP/GO/IBSS has changed and needs update */
int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif)
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf)
{
struct sk_buff *beacon;
int ret;
@@ -1120,7 +1124,8 @@ int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
WARN_ON(vif->type != NL80211_IFTYPE_AP &&
vif->type != NL80211_IFTYPE_ADHOC);

- beacon = ieee80211_beacon_get_template(mvm->hw, vif, NULL, 0);
+ beacon = ieee80211_beacon_get_template(mvm->hw, vif, NULL,
+ link_conf->link_id);
if (!beacon)
return -ENOMEM;

@@ -1131,7 +1136,7 @@ int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
}
#endif

- ret = iwl_mvm_mac_ctxt_send_beacon(mvm, vif, beacon);
+ ret = iwl_mvm_mac_ctxt_send_beacon(mvm, vif, beacon, link_conf);
dev_kfree_skb(beacon);
return ret;
}
@@ -1398,7 +1403,8 @@ static void iwl_mvm_csa_count_down(struct iwl_mvm *mvm,
if (!ieee80211_beacon_cntdwn_is_complete(csa_vif)) {
int c = ieee80211_beacon_update_cntdwn(csa_vif);

- iwl_mvm_mac_ctxt_beacon_changed(mvm, csa_vif);
+ iwl_mvm_mac_ctxt_beacon_changed(mvm, csa_vif,
+ &csa_vif->bss_conf);
if (csa_vif->p2p &&
!iwl_mvm_te_scheduled(&mvmvif->time_event_data) && gp2 &&
tx_success) {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index e922cc45c390..d9caf326535f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -2748,11 +2748,6 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,

mutex_lock(&mvm->mutex);

- /* Send the beacon template */
- ret = iwl_mvm_mac_ctxt_beacon_changed(mvm, vif);
- if (ret)
- goto out_unlock;
-
/*
* Re-calculate the tsf id, as the leader-follower relations depend on
* the beacon interval, which was not known when the AP interface
@@ -2761,10 +2756,31 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
if (vif->type == NL80211_IFTYPE_AP)
iwl_mvm_mac_ctxt_recalc_tsf_id(mvm, vif);

- /* Add the mac context */
- ret = iwl_mvm_mac_ctxt_add(mvm, vif);
- if (ret)
- goto out_unlock;
+ /* For older devices need to send beacon template before adding mac
+ * context. For the newer, the beacon is a resource that belongs to a
+ * MAC, so need to send beacon template after adding the mac.
+ */
+ if (mvm->trans->trans_cfg->device_family > IWL_DEVICE_FAMILY_22000) {
+ /* Add the mac context */
+ ret = iwl_mvm_mac_ctxt_add(mvm, vif);
+ if (ret)
+ goto out_unlock;
+
+ /* Send the beacon template */
+ ret = iwl_mvm_mac_ctxt_beacon_changed(mvm, vif, link_conf);
+ if (ret)
+ goto out_unlock;
+ } else {
+ /* Send the beacon template */
+ ret = iwl_mvm_mac_ctxt_beacon_changed(mvm, vif, link_conf);
+ if (ret)
+ goto out_unlock;
+
+ /* Add the mac context */
+ ret = iwl_mvm_mac_ctxt_add(mvm, vif);
+ if (ret)
+ goto out_unlock;
+ }

/* Perform the binding */
ret = iwl_mvm_binding_add_vif(mvm, vif);
@@ -2961,7 +2977,7 @@ iwl_mvm_bss_info_changed_ap_ibss(struct iwl_mvm *mvm,

/* Need to send a new beacon template to the FW */
if (changes & BSS_CHANGED_BEACON &&
- iwl_mvm_mac_ctxt_beacon_changed(mvm, vif))
+ iwl_mvm_mac_ctxt_beacon_changed(mvm, vif, &vif->bss_conf))
IWL_WARN(mvm, "Failed updating beacon data\n");

if (changes & BSS_CHANGED_FTM_RESPONDER) {
@@ -4965,7 +4981,8 @@ int iwl_mvm_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
return -EINVAL;
}

- return iwl_mvm_mac_ctxt_beacon_changed(mvm, mvm_sta->vif);
+ return iwl_mvm_mac_ctxt_beacon_changed(mvm, mvm_sta->vif,
+ &mvm_sta->vif->bss_conf);
}

#ifdef CONFIG_NL80211_TESTMODE
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
index 240f51d2fd53..c9a0f68c5d48 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
@@ -10,6 +10,8 @@ static void iwl_mvm_mld_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
u32 action)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct ieee80211_bss_conf *link_conf;
+ unsigned int link_id;

cmd->id_and_color = cpu_to_le32(mvmvif->id);
cmd->action = cpu_to_le32(action);
@@ -18,19 +20,53 @@ static void iwl_mvm_mld_mac_ctxt_cmd_common(struct iwl_mvm *mvm,

memcpy(cmd->local_mld_addr, vif->addr, ETH_ALEN);

- cmd->filter_flags = cpu_to_le32(0);
- cmd->he_support = cpu_to_le32(0);
- cmd->eht_support = cpu_to_le32(0);
+ cmd->he_support = 0;
+ cmd->eht_support = 0;
+
+ /* should be set by specific context type handler */
+ cmd->filter_flags = 0;

cmd->nic_not_ack_enabled =
cpu_to_le32(!iwl_mvm_is_nic_ack_enabled(mvm, vif));

if (iwlwifi_mod_params.disable_11ax)
return;
- cmd->he_support = cpu_to_le32(vif->bss_conf.he_support);

- if (!iwlwifi_mod_params.disable_11be && cmd->he_support)
- cmd->eht_support = cpu_to_le32(vif->bss_conf.eht_support);
+ /* If we have MLO enabled, then the firmware needs to enable
+ * address translation for the station(s) we add. That depends
+ * on having EHT enabled in firmware, which in turn depends on
+ * mac80211 in the code below.
+ * However, mac80211 doesn't enable HE/EHT until it has parsed
+ * the association response successfully, so just skip all that
+ * and enable both when we have MLO.
+ */
+ if (vif->valid_links) {
+ cmd->he_support = cpu_to_le32(1);
+ cmd->eht_support = cpu_to_le32(1);
+ return;
+ }
+
+ rcu_read_lock();
+ for (link_id = 0; link_id < ARRAY_SIZE((vif)->link_conf); link_id++) {
+ link_conf = rcu_dereference(vif->link_conf[link_id]);
+ if (!link_conf)
+ continue;
+
+ if (link_conf->he_support)
+ cmd->he_support = cpu_to_le32(1);
+
+ /* it's not reasonable to have EHT without HE and FW API doesn't
+ * support it. Ignore EHT in this case.
+ */
+ if (!link_conf->he_support && link_conf->eht_support)
+ continue;
+
+ if (link_conf->eht_support) {
+ cmd->eht_support = cpu_to_le32(1);
+ break;
+ }
+ }
+ rcu_read_unlock();
}

static int iwl_mvm_mld_mac_ctxt_send_cmd(struct iwl_mvm *mvm,
@@ -66,6 +102,7 @@ static int iwl_mvm_mld_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
cmd.client.ctwin =
iwl_mvm_mac_ctxt_cmd_p2p_sta_get_oppps_ctwin(mvm, vif);

+ /* FIXME: assume for now that DTIM period is the same for all links */
if (vif->cfg.assoc && vif->bss_conf.dtim_period &&
!force_assoc_off) {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index 5be8058ca669..ec0789484d8b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -258,11 +258,6 @@ static int iwl_mvm_mld_start_ap_ibss(struct ieee80211_hw *hw,

mutex_lock(&mvm->mutex);

- /* Send the beacon template */
- ret = iwl_mvm_mac_ctxt_beacon_changed(mvm, vif);
- if (ret)
- goto out_unlock;
-
/* No need to re-calculate the tsf_is, as it was offloaded */

/* Add the mac context */
@@ -270,6 +265,11 @@ static int iwl_mvm_mld_start_ap_ibss(struct ieee80211_hw *hw,
if (ret)
goto out_unlock;

+ /* Send the beacon template */
+ ret = iwl_mvm_mac_ctxt_beacon_changed(mvm, vif, link_conf);
+ if (ret)
+ goto out_unlock;
+
/* Add link and activate it */
ret = iwl_mvm_add_link(mvm, vif);
if (ret)
@@ -532,7 +532,7 @@ iwl_mvm_mld_bss_info_changed_ap_ibss(struct iwl_mvm *mvm,

/* Need to send a new beacon template to the FW */
if (changes & BSS_CHANGED_BEACON &&
- iwl_mvm_mac_ctxt_beacon_changed(mvm, vif))
+ iwl_mvm_mac_ctxt_beacon_changed(mvm, vif, &vif->bss_conf))
IWL_WARN(mvm, "Failed updating beacon data\n");

if (changes & BSS_CHANGED_FTM_RESPONDER) {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 6f4ed5d1efb9..9c5e772d619e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -1759,10 +1759,12 @@ int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
bool force_assoc_off, const u8 *bssid_override);
int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif);
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf);
int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
- struct sk_buff *beacon);
+ struct sk_buff *beacon,
+ struct ieee80211_bss_conf *link_conf);
int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm,
struct sk_buff *beacon,
void *data, int len);
--
2.38.1

2023-03-28 08:06:27

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 15/31] wifi: iwlwifi: mvm: align to the LINK cmd update in the FW

From: Miri Korenblit <[email protected]>

The LINK cmd host api has been updated. Align the driver to the
new changes. Also, temporary use mac_id for link_id.
Using the phy_id as the link_id is wrong since we might have 2 macs
operating on the same phy - in this case we will have 2 different
links (one for each mac) with the same link_id. On the other hand,
since we don't have MLO implemented yet, we won't have 2 different
links of the same mac. Therefore, we can use the mac_id as the
link_id.

Signed-off-by: Miri Korenblit <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
.../wireless/intel/iwlwifi/fw/api/mac-cfg.h | 17 ++++----
drivers/net/wireless/intel/iwlwifi/mvm/link.c | 22 +++++-----
.../net/wireless/intel/iwlwifi/mvm/mld-sta.c | 40 +++++++++----------
3 files changed, 37 insertions(+), 42 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
index 3c540aa9c0c8..b644274e4a31 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
@@ -383,11 +383,14 @@ enum iwl_link_ctx_protection_flags {
* @LINK_FLG_RU_2MHZ_BLOCK: indicates that 26-tone RU OFDMA transmission are
* not allowed (as there are OBSS that might classify such transmissions as
* radar pulses).
+ * @LINK_FLG_NDP_FEEDBACK_ENABLED: mark support for NDP feedback and change
+ * of threshold
*/
enum iwl_link_ctx_flags {
LINK_FLG_BSS_COLOR_DIS = BIT(0),
LINK_FLG_MU_EDCA_CW = BIT(1),
LINK_FLG_RU_2MHZ_BLOCK = BIT(2),
+ LINK_FLG_NDP_FEEDBACK_ENABLED = BIT(3),
}; /* LINK_CONTEXT_FLAG_E_VER_1 */

/**
@@ -423,13 +426,9 @@ enum iwl_link_ctx_flags {
* @rand_alloc_ecwmax: random CWmax = 2**ECWmax-1
* @ndp_fdbk_buff_th_exp: set exponent for the NDP feedback buffered threshold
* @trig_based_txf: MU EDCA Parameter set for the trigger based traffic queues
- * @dtim_time: DTIM arrival time in system time
- * @dtim_tsf: DTIM arrival time in TSF
- * @assoc_beacon_arrive_time: TSF of first beacon after association
* @bi: beacon interval in TU, applicable only when associated
* @dtim_interval: DTIM interval in TU.
* Relevant only for GO, otherwise this is offloaded.
- * @beacon_template: beacon template ID. For GO only
* @puncture_mask: puncture mask for EHT
* @frame_time_rts_th: HE duration RTS threshold, in units of 32us
* @flags: a combination from &enum iwl_link_ctx_flags
@@ -440,6 +439,9 @@ enum iwl_link_ctx_flags {
* @bssid_index: index of the associated VAP
* @bss_color: 11ax AP ID that is used in the HE SIG-A to mark inter BSS frame
* @reserved: alignment
+ * @ibss_bssid_addr: bssid for ibss
+ * @reserved_for_ibss_bssid_addr: reserved
+ * @reserved1: reserved for future use
*/
struct iwl_link_config_cmd {
__le32 action;
@@ -464,12 +466,8 @@ struct iwl_link_config_cmd {
u8 rand_alloc_ecwmax;
u8 ndp_fdbk_buff_th_exp;
struct iwl_he_backoff_conf trig_based_txf[AC_NUM];
- __le32 dtim_time;
- __le64 dtim_tsf;
- __le32 assoc_beacon_arrive_time;
__le32 bi;
__le32 dtim_interval;
- __le32 beacon_template;
__le16 puncture_mask;
__le16 frame_time_rts_th;
__le32 flags;
@@ -480,6 +478,9 @@ struct iwl_link_config_cmd {
u8 bssid_index;
u8 bss_color;
u8 reserved[2];
+ u8 ibss_bssid_addr[6];
+ __le16 reserved_for_ibss_bssid_addr;
+ __le32 reserved1[8];
} __packed; /* LINK_CONTEXT_CONFIG_CMD_API_S_VER_1 */

/**
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/link.c b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
index 21e45f89c5f9..4905dac3a048 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/link.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
@@ -34,12 +34,15 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
if (iwl_mvm_sf_update(mvm, vif, false))
return -EINVAL;

- cmd.link_id = cpu_to_le32(mvmvif->deflink.phy_ctxt->id);
+ cmd.link_id = cpu_to_le32(mvmvif->id);
cmd.mac_id = cpu_to_le32(mvmvif->id);
cmd.phy_id = cpu_to_le32(mvmvif->deflink.phy_ctxt->id);

memcpy(cmd.local_link_addr, vif->addr, ETH_ALEN);

+ if (vif->type == NL80211_IFTYPE_ADHOC && vif->bss_conf.bssid)
+ memcpy(cmd.ibss_bssid_addr, vif->bss_conf.bssid, ETH_ALEN);
+
return iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_ADD);
}

@@ -54,7 +57,7 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (!phyctxt)
return -EINVAL;

- cmd.link_id = cpu_to_le32(phyctxt->id);
+ cmd.link_id = cpu_to_le32(mvmvif->id);

/* The phy_id, link address and listen_lmac can be modified only until
* the link becomes active, otherwise they will be ignored.
@@ -66,6 +69,9 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,

cmd.active = cpu_to_le32(active);

+ if (vif->type == NL80211_IFTYPE_ADHOC && vif->bss_conf.bssid)
+ memcpy(cmd.ibss_bssid_addr, vif->bss_conf.bssid, ETH_ALEN);
+
/* TODO: set a value to cmd.listen_lmac when system requiremens
* will define it
*/
@@ -82,21 +88,11 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,

iwl_mvm_set_fw_qos_params(mvm, vif, &cmd.ac[0], &cmd.qos_flags);

- /* We need the dtim_period to set the MAC as associated */
- if (vif->cfg.assoc && vif->bss_conf.dtim_period)
- iwl_mvm_set_fw_dtim_tbtt(mvm, vif, &cmd.dtim_tsf,
- &cmd.dtim_time,
- &cmd.assoc_beacon_arrive_time);
- else
- changes &= ~LINK_CONTEXT_MODIFY_BEACON_TIMING;

cmd.bi = cpu_to_le32(vif->bss_conf.beacon_int);
cmd.dtim_interval = cpu_to_le32(vif->bss_conf.beacon_int *
vif->bss_conf.dtim_period);

- /* TODO: Assumes that the beacon id == mac context id */
- cmd.beacon_template = cpu_to_le32(mvmvif->id);
-
if (!vif->bss_conf.he_support || iwlwifi_mod_params.disable_11ax ||
!vif->cfg.assoc) {
changes &= ~LINK_CONTEXT_MODIFY_HE_PARAMS;
@@ -164,7 +160,7 @@ int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
if (WARN_ON_ONCE(!mvmvif->deflink.phy_ctxt))
return -EINVAL;

- cmd.link_id = cpu_to_le32(mvmvif->deflink.phy_ctxt->id);
+ cmd.link_id = cpu_to_le32(mvmvif->id);
ret = iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_REMOVE);

if (!ret)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
index 41f6be7fe75e..1608ac371bb0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
@@ -22,7 +22,7 @@ static int iwl_mvm_mld_send_sta_cmd(struct iwl_mvm *mvm,
static int iwl_mvm_mld_add_int_sta_to_fw(struct iwl_mvm *mvm,
struct iwl_mvm_int_sta *sta,
const u8 *addr,
- u16 phy_id)
+ u16 mac_id)
{
struct iwl_mvm_sta_cfg_cmd cmd;

@@ -31,7 +31,7 @@ static int iwl_mvm_mld_add_int_sta_to_fw(struct iwl_mvm *mvm,
memset(&cmd, 0, sizeof(cmd));
cmd.sta_id = cpu_to_le32((u8)sta->sta_id);

- cmd.link_id = cpu_to_le32(phy_id);
+ cmd.link_id = cpu_to_le32(mac_id);

cmd.station_type = cpu_to_le32(sta->type);

@@ -98,7 +98,7 @@ static int iwl_mvm_add_aux_sta_to_fw(struct iwl_mvm *mvm,
*/
static int iwl_mvm_mld_add_int_sta_with_queue(struct iwl_mvm *mvm,
struct iwl_mvm_int_sta *sta,
- const u8 *addr, int phy_id,
+ const u8 *addr, int mac_id,
u16 *queue, u8 tid,
unsigned int *_wdg_timeout)
{
@@ -110,9 +110,9 @@ static int iwl_mvm_mld_add_int_sta_with_queue(struct iwl_mvm *mvm,
return -ENOSPC;

if (sta->type == STATION_TYPE_AUX)
- ret = iwl_mvm_add_aux_sta_to_fw(mvm, sta, phy_id);
+ ret = iwl_mvm_add_aux_sta_to_fw(mvm, sta, mac_id);
else
- ret = iwl_mvm_mld_add_int_sta_to_fw(mvm, sta, addr, phy_id);
+ ret = iwl_mvm_mld_add_int_sta_to_fw(mvm, sta, addr, mac_id);
if (ret)
return ret;

@@ -139,7 +139,7 @@ static int iwl_mvm_mld_add_int_sta(struct iwl_mvm *mvm,
struct iwl_mvm_int_sta *int_sta, u16 *queue,
enum nl80211_iftype iftype,
enum iwl_fw_sta_type sta_type,
- int phy_id, const u8 *addr, u8 tid,
+ int mac_id, const u8 *addr, u8 tid,
unsigned int *wdg_timeout)
{
int ret;
@@ -152,7 +152,7 @@ static int iwl_mvm_mld_add_int_sta(struct iwl_mvm *mvm,
if (ret)
return ret;

- ret = iwl_mvm_mld_add_int_sta_with_queue(mvm, int_sta, addr, phy_id,
+ ret = iwl_mvm_mld_add_int_sta_with_queue(mvm, int_sta, addr, mac_id,
queue, tid, wdg_timeout);
if (ret) {
iwl_mvm_dealloc_int_sta(mvm, int_sta);
@@ -194,8 +194,8 @@ int iwl_mvm_mld_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
return iwl_mvm_mld_add_int_sta(mvm, bsta, queue,
ieee80211_vif_type_p2p(vif),
STATION_TYPE_BCAST_MGMT,
- mvmvif->deflink.phy_ctxt->id, baddr,
- IWL_MAX_TID_COUNT, &wdg_timeout);
+ mvmvif->id, baddr, IWL_MAX_TID_COUNT,
+ &wdg_timeout);
}

/* Allocate a new station entry for the broadcast station to the given vif,
@@ -226,8 +226,7 @@ int iwl_mvm_mld_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)

return iwl_mvm_mld_add_int_sta(mvm, msta, &mvmvif->deflink.cab_queue,
vif->type, STATION_TYPE_MCAST,
- mvmvif->deflink.phy_ctxt->id, maddr, 0,
- &timeout);
+ mvmvif->id, maddr, 0, &timeout);
}

/* Allocate a new station entry for the sniffer station to the given vif,
@@ -241,8 +240,8 @@ int iwl_mvm_mld_add_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)

return iwl_mvm_mld_add_int_sta(mvm, &mvm->snif_sta, &mvm->snif_queue,
vif->type, STATION_TYPE_BCAST_MGMT,
- mvmvif->deflink.phy_ctxt->id, NULL,
- IWL_MAX_TID_COUNT, NULL);
+ mvmvif->id, NULL, IWL_MAX_TID_COUNT,
+ NULL);
}

int iwl_mvm_mld_add_aux_sta(struct iwl_mvm *mvm, u32 lmac_id)
@@ -250,7 +249,7 @@ 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
+ * using the mac_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,
@@ -368,12 +367,13 @@ int iwl_mvm_mld_rm_aux_sta(struct iwl_mvm *mvm)

/* 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)
+ struct ieee80211_vif *vif)
{
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_sta_cfg_cmd cmd = {
.sta_id = cpu_to_le32(mvm_sta->deflink.sta_id),
- .link_id = cpu_to_le32(phy_id),
+ .link_id = cpu_to_le32(mvmvif->id),
.station_type = cpu_to_le32(mvm_sta->sta_type),
.mfp = cpu_to_le32(sta->mfp),
};
@@ -472,7 +472,7 @@ int iwl_mvm_mld_add_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
*/
ret = iwl_mvm_mld_add_int_sta_to_fw(mvm, &tmp_sta,
vif->bss_conf.bssid,
- mvmvif->deflink.phy_ctxt->id);
+ mvmvif->id);
if (ret)
return ret;

@@ -482,7 +482,7 @@ int iwl_mvm_mld_add_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
STATION_TYPE_PEER);
}

- ret = iwl_mvm_mld_cfg_sta(mvm, sta, vif, mvmvif->deflink.phy_ctxt->id);
+ ret = iwl_mvm_mld_cfg_sta(mvm, sta, vif);
if (ret)
return ret;

@@ -503,11 +503,9 @@ int iwl_mvm_mld_add_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
int iwl_mvm_mld_update_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-
lockdep_assert_held(&mvm->mutex);

- return iwl_mvm_mld_cfg_sta(mvm, sta, vif, mvmvif->deflink.phy_ctxt->id);
+ return iwl_mvm_mld_cfg_sta(mvm, sta, vif);
}

static void iwl_mvm_mld_disable_sta_queues(struct iwl_mvm *mvm,
--
2.38.1

2023-03-28 08:06:30

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 18/31] wifi: iwlwifi: mvm: adjust some PS and PM methods to MLD

From: Gregory Greenman <[email protected]>

When using mvm vif PS/PM related properties, consider all links.

Signed-off-by: Gregory Greenman <[email protected]>
---
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 4 +--
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 6 ++++
.../net/wireless/intel/iwlwifi/mvm/power.c | 16 +++++----
.../net/wireless/intel/iwlwifi/mvm/utils.c | 33 +++++++++++++++++++
4 files changed, 50 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index d9caf326535f..2989285d451a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -1278,8 +1278,8 @@ struct iwl_mvm_phy_ctxt *iwl_mvm_get_free_phy_ctxt(struct iwl_mvm *mvm)
return NULL;
}

-static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- s16 tx_power)
+int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ s16 tx_power)
{
u32 cmd_id = REDUCE_TX_POWER_CMD;
int len;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 9c5e772d619e..ae9c165197e8 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -2599,4 +2599,10 @@ int iwl_mvm_start_pmsr(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct cfg80211_pmsr_request *request);
void iwl_mvm_abort_pmsr(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct cfg80211_pmsr_request *request);
+
+bool iwl_mvm_have_links_same_channel(struct iwl_mvm_vif *vif1,
+ struct iwl_mvm_vif *vif2);
+bool iwl_mvm_vif_is_active(struct iwl_mvm_vif *mvmvif);
+int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ s16 tx_power);
#endif /* __IWL_MVM_H__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/power.c b/drivers/net/wireless/intel/iwlwifi/mvm/power.c
index 6e2e3127843f..45a652cce491 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/power.c
@@ -553,8 +553,7 @@ static void iwl_mvm_power_ps_disabled_iterator(void *_data, u8* mac,
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
bool *disable_ps = _data;

- if (mvmvif->deflink.phy_ctxt &&
- mvmvif->deflink.phy_ctxt->id < NUM_PHY_CTX)
+ if (iwl_mvm_vif_is_active(mvmvif))
*disable_ps |= mvmvif->ps_disabled;
}

@@ -563,11 +562,13 @@ static void iwl_mvm_power_get_vifs_iterator(void *_data, u8 *mac,
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_power_vifs *power_iterator = _data;
- bool active = mvmvif->deflink.phy_ctxt && mvmvif->deflink.phy_ctxt->id < NUM_PHY_CTX;
+ bool active;

if (!mvmvif->uploaded)
return;

+ active = iwl_mvm_vif_is_active(mvmvif);
+
switch (ieee80211_vif_type_p2p(vif)) {
case NL80211_IFTYPE_P2P_DEVICE:
break;
@@ -651,11 +652,12 @@ static void iwl_mvm_power_set_pm(struct iwl_mvm *mvm,
}

if (vifs->bss_active && vifs->p2p_active)
- client_same_channel = (bss_mvmvif->deflink.phy_ctxt->id ==
- p2p_mvmvif->deflink.phy_ctxt->id);
+ client_same_channel =
+ iwl_mvm_have_links_same_channel(bss_mvmvif, p2p_mvmvif);
+
if (vifs->bss_active && vifs->ap_active)
- ap_same_channel = (bss_mvmvif->deflink.phy_ctxt->id ==
- ap_mvmvif->deflink.phy_ctxt->id);
+ ap_same_channel =
+ iwl_mvm_have_links_same_channel(bss_mvmvif, ap_mvmvif);

/* clients are not stand alone: enable PM if DCM */
if (!(client_same_channel || ap_same_channel)) {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
index c1f6dd8f7d10..026856c8f5f2 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
@@ -1138,3 +1138,36 @@ void iwl_mvm_get_sync_time(struct iwl_mvm *mvm, int clock_type,
iwl_mvm_power_update_device(mvm);
}
}
+
+/* Find if at least two links from different vifs use same channel
+ * FIXME: consider having a refcount array in struct iwl_mvm_vif for
+ * used phy_ctxt ids.
+ */
+bool iwl_mvm_have_links_same_channel(struct iwl_mvm_vif *vif1,
+ struct iwl_mvm_vif *vif2)
+{
+ unsigned int i, j;
+
+ for_each_mvm_vif_valid_link(vif1, i) {
+ for_each_mvm_vif_valid_link(vif2, j) {
+ if (vif1->link[i]->phy_ctxt == vif2->link[j]->phy_ctxt)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool iwl_mvm_vif_is_active(struct iwl_mvm_vif *mvmvif)
+{
+ unsigned int i;
+
+ /* FIXME: can it fail when phy_ctxt is assigned? */
+ for_each_mvm_vif_valid_link(mvmvif, i) {
+ if (mvmvif->link[i]->phy_ctxt &&
+ mvmvif->link[i]->phy_ctxt->id < NUM_PHY_CTX)
+ return true;
+ }
+
+ return false;
+}
--
2.38.1

2023-03-28 08:06:31

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 21/31] wifi: iwlwifi: mvm: adjust SMPS for MLO

From: Gregory Greenman <[email protected]>

Configure SMPS per-link. Add link_id parameter to
iwl_mvm_update_smps() and refactor iwl_mvm_intf_dual_chain_req()
since it has to handle all active links.

Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/coex.c | 4 +--
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 19 +++++++-----
.../wireless/intel/iwlwifi/mvm/mld-mac80211.c | 4 +--
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 19 ++++++++----
drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 23 +++++++++++----
drivers/net/wireless/intel/iwlwifi/mvm/tt.c | 4 +--
.../net/wireless/intel/iwlwifi/mvm/utils.c | 29 +++++++++++++++----
7 files changed, 73 insertions(+), 29 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
index 21ba3c7dd9b4..daaa173aaed6 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
@@ -291,7 +291,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
if (vif->type == NL80211_IFTYPE_STATION) {
/* ... relax constraints and disable rssi events */
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
- smps_mode);
+ smps_mode, 0);
iwl_mvm_bt_coex_reduced_txp(mvm,
mvmvif->deflink.ap_sta_id,
false);
@@ -325,7 +325,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,

if (vif->type == NL80211_IFTYPE_STATION)
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
- smps_mode);
+ smps_mode, 0);

/* low latency is always primary */
if (iwl_mvm_vif_low_latency(mvmvif)) {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 4dbc9a57746b..ef3eb57b806a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -2481,17 +2481,19 @@ void iwl_mvm_bss_info_changed_station_assoc(struct iwl_mvm *mvm,
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);
+ iwl_mvm_update_smps_on_active_links(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)
+void
+iwl_mvm_bss_info_changed_station_common(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf,
+ u64 changes)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ret;
@@ -2529,7 +2531,7 @@ void iwl_mvm_bss_info_changed_station_common(struct iwl_mvm *mvm,
}

if (changes & BSS_CHANGED_BANDWIDTH)
- iwl_mvm_apply_fw_smps_request(vif);
+ iwl_mvm_update_link_smps(vif, link_conf);
}

static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
@@ -2641,7 +2643,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
if (vif->p2p) {
iwl_mvm_update_smps(mvm, vif,
IWL_MVM_SMPS_REQ_PROT,
- IEEE80211_SMPS_DYNAMIC);
+ IEEE80211_SMPS_DYNAMIC, 0);
}
} else if (mvmvif->deflink.ap_sta_id != IWL_MVM_INVALID_STA) {
iwl_mvm_mei_host_disassociated(mvm);
@@ -2697,7 +2699,8 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
iwl_mvm_bss_info_changed_station_assoc(mvm, vif, changes);
}

- iwl_mvm_bss_info_changed_station_common(mvm, vif, changes);
+ iwl_mvm_bss_info_changed_station_common(mvm, vif, &vif->bss_conf,
+ changes);
}

bool iwl_mvm_start_ap_ibss_common(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index 15beed41b305..80f1a1ccf16d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -516,7 +516,7 @@ iwl_mvm_mld_bss_info_changed_station(struct iwl_mvm *mvm,
if (vif->p2p) {
iwl_mvm_update_smps(mvm, vif,
IWL_MVM_SMPS_REQ_PROT,
- IEEE80211_SMPS_DYNAMIC);
+ IEEE80211_SMPS_DYNAMIC, 0);
}
} else if (mvmvif->deflink.ap_sta_id != IWL_MVM_INVALID_STA) {
iwl_mvm_mei_host_disassociated(mvm);
@@ -557,7 +557,7 @@ iwl_mvm_mld_bss_info_changed_station(struct iwl_mvm *mvm,
iwl_mvm_bss_info_changed_station_assoc(mvm, vif, changes);
}

- iwl_mvm_bss_info_changed_station_common(mvm, vif, changes);
+ iwl_mvm_bss_info_changed_station_common(mvm, vif, &vif->bss_conf, changes);
}

static void
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 9b04ae9c41ff..d62341269744 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -1841,9 +1841,11 @@ iwl_mvm_bss_info_changed_common(struct ieee80211_hw *hw,
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_common(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf,
+ u64 changes);
void iwl_mvm_bss_info_changed_station_assoc(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
u64 changes);
@@ -2057,10 +2059,17 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
/* SMPS */
void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
enum iwl_mvm_smps_type_request req_type,
- enum ieee80211_smps_mode smps_request);
+ enum ieee80211_smps_mode smps_request,
+ unsigned int link_id);
+void
+iwl_mvm_update_smps_on_active_links(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ enum iwl_mvm_smps_type_request req_type,
+ enum ieee80211_smps_mode smps_request);
bool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm,
struct iwl_mvm_phy_ctxt *ctxt);
-void iwl_mvm_apply_fw_smps_request(struct ieee80211_vif *vif);
+void iwl_mvm_update_link_smps(struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf);

/* Low latency */
int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index b355b9ebad0a..4a679ac132c5 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -209,24 +209,37 @@ static void iwl_mvm_rx_monitor_notif(struct iwl_mvm *mvm,
ieee80211_disconnect(vif, true);
}

-void iwl_mvm_apply_fw_smps_request(struct ieee80211_vif *vif)
+void iwl_mvm_update_link_smps(struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm *mvm = mvmvif->mvm;
enum ieee80211_smps_mode mode = IEEE80211_SMPS_AUTOMATIC;

+ if (!link_conf)
+ return;
+
if (mvm->fw_static_smps_request &&
- vif->bss_conf.chandef.width == NL80211_CHAN_WIDTH_160 &&
- vif->bss_conf.he_support)
+ link_conf->chandef.width == NL80211_CHAN_WIDTH_160 &&
+ link_conf->he_support)
mode = IEEE80211_SMPS_STATIC;

- iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_FW, mode);
+ iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_FW, mode,
+ link_conf->link_id);
}

static void iwl_mvm_intf_dual_chain_req(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
- iwl_mvm_apply_fw_smps_request(vif);
+ struct ieee80211_bss_conf *link_conf;
+ unsigned int link_id;
+
+ rcu_read_lock();
+
+ for_each_vif_active_link(vif, link_conf, link_id)
+ iwl_mvm_update_link_smps(vif, link_conf);
+
+ rcu_read_unlock();
}

static void iwl_mvm_rx_thermal_dual_chain_req(struct iwl_mvm *mvm,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
index 232c200af38f..4d0e161a92e0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2019-2021 Intel Corporation
+ * Copyright (C) 2012-2014, 2019-2022 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2016 Intel Deutschland GmbH
*/
@@ -334,7 +334,7 @@ static void iwl_mvm_tt_smps_iterator(void *_data, u8 *mac,
if (vif->type != NL80211_IFTYPE_STATION)
return;

- iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_TT, smps_mode);
+ iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_TT, smps_mode, 0);
}

static void iwl_mvm_tt_tx_protection(struct iwl_mvm *mvm, bool enable)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
index 026856c8f5f2..cf72b9377411 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
@@ -272,13 +272,15 @@ int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq)
* @vif: Pointer to the ieee80211_vif structure
* @req_type: The part of the driver who call for a change.
* @smps_request: The request to change the SMPS mode.
+ * @link_id: for MLO link_id, otherwise 0 (deflink)
*
* Get a requst to change the SMPS mode,
* and change it according to all other requests in the driver.
*/
void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
enum iwl_mvm_smps_type_request req_type,
- enum ieee80211_smps_mode smps_request)
+ enum ieee80211_smps_mode smps_request,
+ unsigned int link_id)
{
struct iwl_mvm_vif *mvmvif;
enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_AUTOMATIC;
@@ -294,17 +296,34 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return;

mvmvif = iwl_mvm_vif_from_mac80211(vif);
- mvmvif->deflink.smps_requests[req_type] = smps_request;
+ mvmvif->link[link_id]->smps_requests[req_type] = smps_request;
for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) {
- if (mvmvif->deflink.smps_requests[i] == IEEE80211_SMPS_STATIC) {
+ if (mvmvif->link[link_id]->smps_requests[i] ==
+ IEEE80211_SMPS_STATIC) {
smps_mode = IEEE80211_SMPS_STATIC;
break;
}
- if (mvmvif->deflink.smps_requests[i] == IEEE80211_SMPS_DYNAMIC)
+ if (mvmvif->link[link_id]->smps_requests[i] ==
+ IEEE80211_SMPS_DYNAMIC)
smps_mode = IEEE80211_SMPS_DYNAMIC;
}

- ieee80211_request_smps(vif, 0, smps_mode);
+ ieee80211_request_smps(vif, link_id, smps_mode);
+}
+
+void iwl_mvm_update_smps_on_active_links(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ enum iwl_mvm_smps_type_request req_type,
+ enum ieee80211_smps_mode smps_request)
+{
+ struct ieee80211_bss_conf *link_conf;
+ unsigned int link_id;
+
+ rcu_read_lock();
+ for_each_vif_active_link(vif, link_conf, link_id)
+ iwl_mvm_update_smps(mvm, vif, req_type, smps_request,
+ link_id);
+ rcu_read_unlock();
}

static bool iwl_wait_stats_complete(struct iwl_notif_wait_data *notif_wait,
--
2.38.1

2023-03-28 08:06:36

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 19/31] wifi: iwlwifi: mvm: add link to firmware earlier

From: Johannes Berg <[email protected]>

The firmware now allows adding a link that's not yet bound
to a PHY context. Make use of that to align the driver with
mac80211's API expectations. For now, just add the link at
the same time as the MAC since we don't yet have real MLD
support, but that'll obviously change later. This fixes an
issue with apStaId tracking in the firmware.

Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/link.c | 21 +--
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 17 +-
.../wireless/intel/iwlwifi/mvm/mld-mac80211.c | 173 +++++++++++-------
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 7 +-
4 files changed, 133 insertions(+), 85 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/link.c b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
index 4905dac3a048..d8902e0ed2ae 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/link.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
@@ -23,11 +23,9 @@ static int iwl_mvm_link_cmd_send(struct iwl_mvm *mvm,
int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm_phy_ctxt *phyctxt = mvmvif->deflink.phy_ctxt;
struct iwl_link_config_cmd cmd = {};

- if (WARN_ON_ONCE(!mvmvif->deflink.phy_ctxt))
- return -EINVAL;
-
/* Update SF - Disable if needed. if this fails, SF might still be on
* while many macs are bound, which is forbidden - so fail the binding.
*/
@@ -36,7 +34,11 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)

cmd.link_id = cpu_to_le32(mvmvif->id);
cmd.mac_id = cpu_to_le32(mvmvif->id);
- cmd.phy_id = cpu_to_le32(mvmvif->deflink.phy_ctxt->id);
+ /* P2P-Device already has a valid PHY context during add */
+ if (phyctxt)
+ cmd.phy_id = cpu_to_le32(phyctxt->id);
+ else
+ cmd.phy_id = cpu_to_le32(FW_CTXT_INVALID);

memcpy(cmd.local_link_addr, vif->addr, ETH_ALEN);

@@ -54,15 +56,15 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct iwl_link_config_cmd cmd = {};
u32 ht_flag, flags = 0, flags_mask = 0;

- if (!phyctxt)
- return -EINVAL;
-
cmd.link_id = cpu_to_le32(mvmvif->id);

/* The phy_id, link address and listen_lmac can be modified only until
* the link becomes active, otherwise they will be ignored.
*/
- cmd.phy_id = cpu_to_le32(phyctxt->id);
+ if (phyctxt)
+ cmd.phy_id = cpu_to_le32(phyctxt->id);
+ else
+ cmd.phy_id = cpu_to_le32(FW_CTXT_INVALID);
cmd.mac_id = cpu_to_le32(mvmvif->id);

memcpy(cmd.local_link_addr, vif->addr, ETH_ALEN);
@@ -157,9 +159,6 @@ int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
struct iwl_link_config_cmd cmd = {};
int ret;

- if (WARN_ON_ONCE(!mvmvif->deflink.phy_ctxt))
- return -EINVAL;
-
cmd.link_id = cpu_to_le32(mvmvif->id);
ret = iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_REMOVE);

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 2989285d451a..18e7ba98daa0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -1437,10 +1437,13 @@ iwl_mvm_chandef_get_primary_80(struct cfg80211_chan_def *chandef)
/*
* Returns true if addding the interface is done
* (either with success or failure)
+ *
+ * FIXME: remove this again and merge it in
*/
-bool iwl_mvm_mac_add_interface_common(struct iwl_mvm *mvm,
- struct ieee80211_hw *hw,
- struct ieee80211_vif *vif, int *ret)
+static bool iwl_mvm_mac_add_interface_common(struct iwl_mvm *mvm,
+ struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ int *ret)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);

@@ -1621,8 +1624,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
return ret;
}

-static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif)
+void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif)
{
if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
/*
@@ -1638,8 +1641,8 @@ static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
* both - MLD and non-MLD modes. Returns true if removing the interface
* is done
*/
-bool iwl_mvm_mac_remove_interface_common(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+static bool iwl_mvm_mac_remove_interface_common(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index ec0789484d8b..1d2da26408e6 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -13,17 +13,34 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,

mutex_lock(&mvm->mutex);

- /* Common for MLD and non-MLD API */
- if (iwl_mvm_mac_add_interface_common(mvm, hw, vif, &ret))
- goto out_unlock;
+ mvmvif->mvm = mvm;
+ RCU_INIT_POINTER(mvmvif->deflink.probe_resp_data, NULL);

- ret = iwl_mvm_mld_mac_ctxt_add(mvm, vif);
+ /* Not much to do here. The stack will not allow interface
+ * types or combinations that we didn't advertise, so we
+ * don't really have to check the types.
+ */
+
+ /* make sure that beacon statistics don't go backwards with FW reset */
+ if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
+ mvmvif->deflink.beacon_stats.accu_num_beacons +=
+ mvmvif->deflink.beacon_stats.num_beacons;
+
+ /* Allocate resources for the MAC context, and add it to the fw */
+ ret = iwl_mvm_mac_ctxt_init(mvm, vif);
if (ret)
goto out_unlock;

- ret = iwl_mvm_power_update_mac(mvm);
+ rcu_assign_pointer(mvm->vif_id_to_mac[mvmvif->id], vif);
+
+ mvmvif->features |= hw->netdev_features;
+
+ /* the first link always points to the default one */
+ mvmvif->link[0] = &mvmvif->deflink;
+
+ ret = iwl_mvm_mld_mac_ctxt_add(mvm, vif);
if (ret)
- goto out_remove_mac;
+ goto out_unlock;

/* beacon filtering */
ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
@@ -67,8 +84,16 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
* update the p2p device MAC when a GO is started/stopped
*/
mvm->p2p_device_vif = vif;
+ } else {
+ ret = iwl_mvm_add_link(mvm, vif);
+ if (ret)
+ goto out_free_bf;
}

+ ret = iwl_mvm_power_update_mac(mvm);
+ if (ret)
+ goto out_free_bf;
+
iwl_mvm_tcm_add_vif(mvm, vif);
INIT_DELAYED_WORK(&mvmvif->csa_work,
iwl_mvm_channel_switch_disconnect_wk);
@@ -117,9 +142,52 @@ static void iwl_mvm_mld_mac_remove_interface(struct ieee80211_hw *hw,
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_probe_resp_data *probe_data;

- if (iwl_mvm_mac_remove_interface_common(hw, vif))
- goto out;
+ iwl_mvm_prepare_mac_removal(mvm, vif);
+
+ if (!(vif->type == NL80211_IFTYPE_AP ||
+ vif->type == NL80211_IFTYPE_ADHOC))
+ iwl_mvm_tcm_rm_vif(mvm, vif);
+
+ mutex_lock(&mvm->mutex);
+
+ if (vif == mvm->csme_vif) {
+ iwl_mei_set_netdev(NULL);
+ mvm->csme_vif = NULL;
+ }
+
+ probe_data = rcu_dereference_protected(mvmvif->deflink.probe_resp_data,
+ lockdep_is_held(&mvm->mutex));
+ RCU_INIT_POINTER(mvmvif->deflink.probe_resp_data, NULL);
+ if (probe_data)
+ kfree_rcu(probe_data, rcu_head);
+
+ if (mvm->bf_allowed_vif == mvmvif) {
+ mvm->bf_allowed_vif = NULL;
+ vif->driver_flags &= ~(IEEE80211_VIF_BEACON_FILTER |
+ IEEE80211_VIF_SUPPORTS_CQM_RSSI);
+ }
+
+ if (vif->bss_conf.ftm_responder)
+ memset(&mvm->ftm_resp_stats, 0, sizeof(mvm->ftm_resp_stats));
+
+ iwl_mvm_vif_dbgfs_clean(mvm, vif);
+
+ /* For AP/GO interface, the tear down of the resources allocated to the
+ * interface is be handled as part of the stop_ap flow.
+ */
+ if (vif->type == NL80211_IFTYPE_AP ||
+ vif->type == NL80211_IFTYPE_ADHOC) {
+#ifdef CONFIG_NL80211_TESTMODE
+ if (vif == mvm->noa_vif) {
+ mvm->noa_vif = NULL;
+ mvm->noa_duration = 0;
+ }
+#endif
+ }
+
+ iwl_mvm_power_update_mac(mvm);

if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
mvm->p2p_device_vif = NULL;
@@ -130,6 +198,8 @@ static void iwl_mvm_mld_mac_remove_interface(struct ieee80211_hw *hw,
iwl_mvm_remove_link(mvm, vif);
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
mvmvif->deflink.phy_ctxt = NULL;
+ } else {
+ iwl_mvm_remove_link(mvm, vif);
}

iwl_mvm_mld_mac_ctxt_remove(mvm, vif);
@@ -141,7 +211,6 @@ static void iwl_mvm_mld_mac_remove_interface(struct ieee80211_hw *hw,
__clear_bit(IEEE80211_HW_RX_INCLUDES_FCS, mvm->hw->flags);
}

-out:
mutex_unlock(&mvm->mutex);
}

@@ -150,28 +219,30 @@ static int __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
struct ieee80211_chanctx_conf *ctx,
bool switching_chanctx)
{
+ u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
+ struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ret;

- if (__iwl_mvm_assign_vif_chanctx_common(mvm, vif, ctx,
- switching_chanctx, &ret))
- goto out;
+ mvmvif->deflink.phy_ctxt = phy_ctxt;

- if (!switching_chanctx) {
- ret = iwl_mvm_add_link(mvm, vif);
- if (ret)
- goto out;
- } else {
- ret = iwl_mvm_link_changed(mvm, vif, 0, false);
- if (ret)
- goto out_remove_link;
+ if (switching_chanctx) {
+ /* reactivate if we turned this off during channel switch */
+ if (vif->type == NL80211_IFTYPE_AP)
+ mvmvif->ap_ibss_active = true;
}

+ /* send it first with phy context ID */
+ ret = iwl_mvm_link_changed(mvm, vif, 0, false);
+ if (ret)
+ goto out;
+
+ /* then activate */
ret = iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ACTIVE |
LINK_CONTEXT_MODIFY_RATES_INFO,
true);
if (ret)
- goto out_remove_link;
+ goto out;

/*
* Power state must be updated before quotas,
@@ -182,19 +253,16 @@ static int __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
if (vif->type == NL80211_IFTYPE_MONITOR) {
ret = iwl_mvm_mld_add_snif_sta(mvm, vif);
if (ret)
- goto out_remove_link;
+ goto deactivate;
}

- goto out;
+ return 0;

-out_remove_link:
- /* Link needs to be deactivated before removal */
+deactivate:
iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ACTIVE, false);
- iwl_mvm_remove_link(mvm, vif);
- iwl_mvm_power_update_mac(mvm);
out:
- if (ret)
- mvmvif->deflink.phy_ctxt = NULL;
+ mvmvif->deflink.phy_ctxt = NULL;
+ iwl_mvm_power_update_mac(mvm);
return ret;
}

@@ -220,16 +288,23 @@ static void __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm,
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);

- if (__iwl_mvm_unassign_vif_chanctx_common(mvm, vif, switching_chanctx))
- goto out;
+ if (vif->type == NL80211_IFTYPE_AP && switching_chanctx) {
+ mvmvif->csa_countdown = false;
+
+ /* Set CS bit on all the stations */
+ iwl_mvm_modify_all_sta_disable_tx(mvm, mvmvif, true);
+
+ /* Save blocked iface, the timeout is set on the next beacon */
+ rcu_assign_pointer(mvm->csa_tx_blocked_vif, vif);
+
+ mvmvif->ap_ibss_active = false;
+ }

if (vif->type == NL80211_IFTYPE_MONITOR)
iwl_mvm_mld_rm_snif_sta(mvm, vif);

iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ACTIVE, false);
- if (!switching_chanctx)
- iwl_mvm_remove_link(mvm, vif);
-out:
+
if (switching_chanctx)
return;
mvmvif->deflink.phy_ctxt = NULL;
@@ -257,32 +332,19 @@ static int iwl_mvm_mld_start_ap_ibss(struct ieee80211_hw *hw,
int ret;

mutex_lock(&mvm->mutex);
-
- /* No need to re-calculate the tsf_is, as it was offloaded */
-
- /* Add the mac context */
- ret = iwl_mvm_mld_mac_ctxt_add(mvm, vif);
- if (ret)
- goto out_unlock;
-
/* Send the beacon template */
ret = iwl_mvm_mac_ctxt_beacon_changed(mvm, vif, link_conf);
if (ret)
goto out_unlock;

- /* Add link and activate it */
- ret = iwl_mvm_add_link(mvm, vif);
- if (ret)
- goto out_remove_mac;
-
ret = iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ALL,
true);
if (ret)
- goto out_remove_link;
+ goto out_unlock;

ret = iwl_mvm_mld_add_mcast_sta(mvm, vif);
if (ret)
- goto out_remove_link;
+ goto out_unlock;

/* Send the bcast station. At this stage the TBTT and DTIM time
* events are added and applied to the scheduler
@@ -314,12 +376,6 @@ static int iwl_mvm_mld_start_ap_ibss(struct ieee80211_hw *hw,
iwl_mvm_mld_rm_bcast_sta(mvm, vif);
out_rm_mcast:
iwl_mvm_mld_rm_mcast_sta(mvm, vif);
-out_remove_link:
- /* Link needs to be deactivated before removal */
- iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ACTIVE, false);
- iwl_mvm_remove_link(mvm, vif);
-out_remove_mac:
- iwl_mvm_mld_mac_ctxt_remove(mvm, vif);
out_unlock:
mutex_unlock(&mvm->mutex);
return ret;
@@ -357,14 +413,7 @@ static void iwl_mvm_mld_stop_ap_ibss(struct ieee80211_hw *hw,
iwl_mvm_mld_rm_bcast_sta(mvm, vif);
iwl_mvm_mld_rm_mcast_sta(mvm, vif);

- /* Link needs to be deactivated before removal */
- iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ACTIVE, false);
- iwl_mvm_remove_link(mvm, vif);
-
iwl_mvm_power_update_mac(mvm);
-
- iwl_mvm_mld_mac_ctxt_remove(mvm, vif);
-
mutex_unlock(&mvm->mutex);
}

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index ae9c165197e8..af2059155794 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -1718,11 +1718,8 @@ u8 iwl_mvm_get_ctrl_pos(struct cfg80211_chan_def *chandef);

/* MAC (virtual interface) programming */

-bool iwl_mvm_mac_add_interface_common(struct iwl_mvm *mvm,
- struct ieee80211_hw *hw,
- struct ieee80211_vif *vif, int *ret);
-bool iwl_mvm_mac_remove_interface_common(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif);
+void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif);
void iwl_mvm_set_fw_basic_rates(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
__le32 *cck_rates, __le32 *ofdm_rates);
void iwl_mvm_set_fw_protection_flags(struct iwl_mvm *mvm,
--
2.38.1

2023-03-28 08:06:38

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 22/31] wifi: iwlwifi: mvm: don't check dtim_period in new API

From: Johannes Berg <[email protected]>

In newer firmware APIs the firmware is responsible for tracking
the DTIM period and other beacon timing, so we don't need to
wait with setting associated. In real MLO operation, mac80211
isn't tracking this anyway, and connections wouldn't work.

Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
index c9a0f68c5d48..ab0ba85936b4 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
@@ -102,9 +102,7 @@ static int iwl_mvm_mld_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
cmd.client.ctwin =
iwl_mvm_mac_ctxt_cmd_p2p_sta_get_oppps_ctwin(mvm, vif);

- /* FIXME: assume for now that DTIM period is the same for all links */
- if (vif->cfg.assoc && vif->bss_conf.dtim_period &&
- !force_assoc_off) {
+ if (vif->cfg.assoc && !force_assoc_off) {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);

cmd.client.is_assoc = cpu_to_le32(1);
--
2.38.1

2023-03-28 08:06:59

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 20/31] wifi: iwlwifi: mvm: add set_hw_timestamp to mld ops

From: Avraham Stern <[email protected]>

In mld ops, set_hw_timestamp was not set. Fix it.

Signed-off-by: Avraham Stern <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 6 +++---
drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c | 1 +
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 3 +++
3 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 18e7ba98daa0..4dbc9a57746b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -5896,9 +5896,9 @@ static bool iwl_mvm_mac_can_aggregate(struct ieee80211_hw *hw,
return iwl_mvm_can_hw_csum(skb) == iwl_mvm_can_hw_csum(head);
}

-static int iwl_mvm_set_hw_timestamp(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct cfg80211_set_hw_timestamp *hwts)
+int iwl_mvm_set_hw_timestamp(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct cfg80211_set_hw_timestamp *hwts)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
u32 protocols = 0;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index 1d2da26408e6..15beed41b305 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -798,4 +798,5 @@ const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
#ifdef CONFIG_IWLWIFI_DEBUGFS
.sta_add_debugfs = iwl_mvm_sta_add_debugfs,
#endif
+ .set_hw_timestamp = iwl_mvm_set_hw_timestamp,
};
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index af2059155794..9b04ae9c41ff 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -2602,4 +2602,7 @@ bool iwl_mvm_have_links_same_channel(struct iwl_mvm_vif *vif1,
bool iwl_mvm_vif_is_active(struct iwl_mvm_vif *mvmvif);
int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
s16 tx_power);
+int iwl_mvm_set_hw_timestamp(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct cfg80211_set_hw_timestamp *hwts);
#endif /* __IWL_MVM_H__ */
--
2.38.1

2023-03-28 08:07:08

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 25/31] wifi: iwlwifi: mvm: adjust internal stations to MLO

From: Gregory Greenman <[email protected]>

Internal stations are mcast/bcast and sniffer. They need some link
specific data like bss id/phy id. Add link_conf as a parameter.

Signed-off-by: Gregory Greenman <[email protected]>
---
.../wireless/intel/iwlwifi/mvm/mld-mac80211.c | 21 +++++-----
.../net/wireless/intel/iwlwifi/mvm/mld-sta.c | 40 ++++++++++++-------
drivers/net/wireless/intel/iwlwifi/mvm/sta.h | 15 ++++---
3 files changed, 47 insertions(+), 29 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index 950f252c1a5a..c81b92d2e8f7 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -78,7 +78,7 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
if (ret)
goto out_remove_link;

- ret = iwl_mvm_mld_add_bcast_sta(mvm, vif);
+ ret = iwl_mvm_mld_add_bcast_sta(mvm, vif, &vif->bss_conf);
if (ret)
goto out_remove_link;

@@ -194,7 +194,9 @@ static void iwl_mvm_mld_mac_remove_interface(struct ieee80211_hw *hw,

if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
mvm->p2p_device_vif = NULL;
- iwl_mvm_mld_rm_bcast_sta(mvm, vif);
+
+ /* P2P device uses only one link */
+ iwl_mvm_mld_rm_bcast_sta(mvm, vif, &vif->bss_conf);
/* Link needs to be deactivated before removal */
iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
LINK_CONTEXT_MODIFY_ACTIVE, false);
@@ -255,7 +257,8 @@ static int __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
iwl_mvm_power_update_mac(mvm);

if (vif->type == NL80211_IFTYPE_MONITOR) {
- ret = iwl_mvm_mld_add_snif_sta(mvm, vif);
+ ret = iwl_mvm_mld_add_snif_sta(mvm, vif,
+ &vif->bss_conf);
if (ret)
goto deactivate;
}
@@ -348,14 +351,14 @@ static int iwl_mvm_mld_start_ap_ibss(struct ieee80211_hw *hw,
if (ret)
goto out_unlock;

- ret = iwl_mvm_mld_add_mcast_sta(mvm, vif);
+ ret = iwl_mvm_mld_add_mcast_sta(mvm, vif, link_conf);
if (ret)
goto out_unlock;

/* Send the bcast station. At this stage the TBTT and DTIM time
* events are added and applied to the scheduler
*/
- ret = iwl_mvm_mld_add_bcast_sta(mvm, vif);
+ ret = iwl_mvm_mld_add_bcast_sta(mvm, vif, link_conf);
if (ret)
goto out_rm_mcast;

@@ -379,9 +382,9 @@ static int iwl_mvm_mld_start_ap_ibss(struct ieee80211_hw *hw,
out_failed:
iwl_mvm_power_update_mac(mvm);
mvmvif->ap_ibss_active = false;
- iwl_mvm_mld_rm_bcast_sta(mvm, vif);
+ iwl_mvm_mld_rm_bcast_sta(mvm, vif, link_conf);
out_rm_mcast:
- iwl_mvm_mld_rm_mcast_sta(mvm, vif);
+ iwl_mvm_mld_rm_mcast_sta(mvm, vif, link_conf);
out_unlock:
mutex_unlock(&mvm->mutex);
return ret;
@@ -416,8 +419,8 @@ static void iwl_mvm_mld_stop_ap_ibss(struct ieee80211_hw *hw,

iwl_mvm_ftm_responder_clear(mvm, vif);

- iwl_mvm_mld_rm_bcast_sta(mvm, vif);
- iwl_mvm_mld_rm_mcast_sta(mvm, vif);
+ iwl_mvm_mld_rm_bcast_sta(mvm, vif, link_conf);
+ iwl_mvm_mld_rm_mcast_sta(mvm, vif, link_conf);

iwl_mvm_power_update_mac(mvm);
mutex_unlock(&mvm->mutex);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
index 1608ac371bb0..75d4585c0b21 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
@@ -166,10 +166,13 @@ static int iwl_mvm_mld_add_int_sta(struct iwl_mvm *mvm,
* and send it to the FW.
* Note that each P2P mac should have its own broadcast station.
*/
-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,
+ struct ieee80211_bss_conf *link_conf)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm_int_sta *bsta = &mvmvif->deflink.bcast_sta;
+ struct iwl_mvm_vif_link_info *mvm_link =
+ mvmvif->link[link_conf->link_id];
+ struct iwl_mvm_int_sta *bsta = &mvm_link->bcast_sta;
static const u8 _baddr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
const u8 *baddr = _baddr;
unsigned int wdg_timeout =
@@ -179,7 +182,7 @@ int iwl_mvm_mld_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
lockdep_assert_held(&mvm->mutex);

if (vif->type == NL80211_IFTYPE_ADHOC)
- baddr = vif->bss_conf.bssid;
+ baddr = link_conf->bssid;

if (vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_ADHOC) {
@@ -202,10 +205,13 @@ int iwl_mvm_mld_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
* and send it to the FW.
* Note that each AP/GO mac should have its own multicast station.
*/
-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,
+ struct ieee80211_bss_conf *link_conf)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm_int_sta *msta = &mvmvif->deflink.mcast_sta;
+ struct iwl_mvm_vif_link_info *mvm_link =
+ mvmvif->link[link_conf->link_id];
+ struct iwl_mvm_int_sta *msta = &mvm_link->mcast_sta;
static const u8 _maddr[] = {0x03, 0x00, 0x00, 0x00, 0x00, 0x00};
const u8 *maddr = _maddr;
unsigned int timeout = iwl_mvm_get_wd_timeout(mvm, vif, false, false);
@@ -222,9 +228,9 @@ int iwl_mvm_mld_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
* changes in mac80211 layer.
*/
if (vif->type == NL80211_IFTYPE_ADHOC)
- mvmvif->deflink.cab_queue = IWL_MVM_DQA_GCAST_QUEUE;
+ mvm_link->cab_queue = IWL_MVM_DQA_GCAST_QUEUE;

- return iwl_mvm_mld_add_int_sta(mvm, msta, &mvmvif->deflink.cab_queue,
+ return iwl_mvm_mld_add_int_sta(mvm, msta, &mvm_link->cab_queue,
vif->type, STATION_TYPE_MCAST,
mvmvif->id, maddr, 0, &timeout);
}
@@ -232,7 +238,8 @@ int iwl_mvm_mld_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
/* Allocate a new station entry for the sniffer station to the given vif,
* and send it to the FW.
*/
-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,
+ struct ieee80211_bss_conf *link_conf)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);

@@ -310,9 +317,11 @@ static int iwl_mvm_mld_rm_int_sta(struct iwl_mvm *mvm,
return ret;
}

-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,
+ struct ieee80211_bss_conf *link_conf)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm_vif_link_info *link = mvmvif->link[link_conf->link_id];
u16 *queueptr;

lockdep_assert_held(&mvm->mutex);
@@ -331,22 +340,23 @@ int iwl_mvm_mld_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
return -EINVAL;
}

- return iwl_mvm_mld_rm_int_sta(mvm, &mvmvif->deflink.bcast_sta, true,
- IWL_MAX_TID_COUNT, queueptr);
+ return iwl_mvm_mld_rm_int_sta(mvm, &link->bcast_sta,
+ true, IWL_MAX_TID_COUNT, queueptr);
}

/* Send the FW a request to remove the station from it's internal data
* structures, and in addition remove it from the local data structure.
*/
-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,
+ struct ieee80211_bss_conf *link_conf)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm_vif_link_info *link = mvmvif->link[link_conf->link_id];

lockdep_assert_held(&mvm->mutex);

- return iwl_mvm_mld_rm_int_sta(mvm, &mvmvif->deflink.mcast_sta, true,
- 0,
- &mvmvif->deflink.cab_queue);
+ return iwl_mvm_mld_rm_int_sta(mvm, &link->mcast_sta, true, 0,
+ &link->cab_queue);
}

int iwl_mvm_mld_rm_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index 3a9002eeb5fb..7148263dddf8 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -619,13 +619,18 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,

/* New MLD STA related APIs */
/* STA */
-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_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf);
+int iwl_mvm_mld_add_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf);
+int iwl_mvm_mld_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf);
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,
+ struct ieee80211_bss_conf *link_conf);
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,
+ struct ieee80211_bss_conf *link_conf);
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);
--
2.38.1

2023-03-28 08:07:22

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 28/31] wifi: iwlwifi: mvm: update iwl_mvm_tx_reclaim() for MLO

From: Gregory Greenman <[email protected]>

vif->bss_conf is used in this function only when TLC is not offloaded,
so not in MLO flow. Simplify the related "if" condition and call
iwl_mvm_hwrate_to_tx_status() only for driver rate scale.

Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index 1737f2ad21ad..61a95ee3ef2d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -1976,9 +1976,11 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid,
* possible (i.e. first MPDU in the aggregation wasn't acked)
* Still it's important to update RS about sent vs. acked.
*/
- if (!is_flush && skb_queue_empty(&reclaimed_skbs)) {
+ if (!is_flush && skb_queue_empty(&reclaimed_skbs) &&
+ !iwl_mvm_has_tlc_offload(mvm)) {
struct ieee80211_chanctx_conf *chanctx_conf = NULL;

+ /* no TLC offload, so non-MLD mode */
if (mvmsta->vif)
chanctx_conf =
rcu_dereference(mvmsta->vif->bss_conf.chanctx_conf);
@@ -1989,11 +1991,8 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid,
tx_info->band = chanctx_conf->def.chan->band;
iwl_mvm_hwrate_to_tx_status(mvm->fw, rate, tx_info);

- if (!iwl_mvm_has_tlc_offload(mvm)) {
- IWL_DEBUG_TX_REPLY(mvm,
- "No reclaim. Update rs directly\n");
- iwl_mvm_rs_tx_status(mvm, sta, tid, tx_info, false);
- }
+ IWL_DEBUG_TX_REPLY(mvm, "No reclaim. Update rs directly\n");
+ iwl_mvm_rs_tx_status(mvm, sta, tid, tx_info, false);
}

out:
--
2.38.1

2023-03-28 08:07:27

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 30/31] wifi: iwlwifi: mvm: adjust some cleanup functions to MLO

From: Gregory Greenman <[email protected]>

Clean up data for all allocated links of a vif.
Invalidate all link sta pointers.

Signed-off-by: Gregory Greenman <[email protected]>
---
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 32 +++++++++++++++----
1 file changed, 25 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index f778ac69c671..9e825e3cf630 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -983,18 +983,23 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
{
struct iwl_mvm *mvm = data;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ unsigned int link_id;

mvmvif->uploaded = false;
- mvmvif->deflink.ap_sta_id = IWL_MVM_INVALID_STA;

spin_lock_bh(&mvm->time_event_lock);
iwl_mvm_te_clear_data(mvm, &mvmvif->time_event_data);
spin_unlock_bh(&mvm->time_event_lock);

- mvmvif->deflink.phy_ctxt = NULL;
memset(&mvmvif->bf_data, 0, sizeof(mvmvif->bf_data));
- memset(&mvmvif->deflink.probe_resp_data, 0,
- sizeof(mvmvif->deflink.probe_resp_data));
+
+ for_each_mvm_vif_valid_link(mvmvif, link_id) {
+ mvmvif->link[link_id]->ap_sta_id = IWL_MVM_INVALID_STA;
+ mvmvif->link[link_id]->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
+ mvmvif->link[link_id]->phy_ctxt = NULL;
+ memset(&mvmvif->link[link_id]->probe_resp_data, 0,
+ sizeof(mvmvif->link[link_id]->probe_resp_data));
+ }
}

static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
@@ -3251,6 +3256,7 @@ void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
+ unsigned int link_id;

/*
* This is called before mac80211 does RCU synchronisation,
@@ -3259,12 +3265,24 @@ void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
* be able to find the station this way, and we don't rely
* on further RCU synchronisation after the sta_state()
* callback deleted the station.
+ * Since there's mvm->mutex here, no need to have RCU lock for
+ * mvm_sta->link access.
*/
mutex_lock(&mvm->mutex);
- if (sta == rcu_access_pointer(mvm->fw_id_to_mac_id[mvm_sta->deflink.sta_id]))
- rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->deflink.sta_id],
- ERR_PTR(-ENOENT));
+ for (link_id = 0; link_id < ARRAY_SIZE(mvm_sta->link); link_id++) {
+ struct iwl_mvm_link_sta *link_sta;
+ u32 sta_id;
+
+ if (!mvm_sta->link[link_id])
+ continue;

+ link_sta = rcu_dereference_protected(mvm_sta->link[link_id],
+ lockdep_is_held(&mvm->mutex));
+ sta_id = link_sta->sta_id;
+ if (sta == rcu_access_pointer(mvm->fw_id_to_mac_id[sta_id]))
+ rcu_assign_pointer(mvm->fw_id_to_mac_id[sta_id],
+ ERR_PTR(-ENOENT));
+ }
mutex_unlock(&mvm->mutex);
}

--
2.38.1

2023-03-28 08:08:58

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 24/31] wifi: iwlwifi: mvm: replace bss_info_changed() with vif_cfg/link_info_changed()

From: Gregory Greenman <[email protected]>

These are two new handlers for MLO. As the configurations done in
bss_info_changed() are now split into two separate flows, use MLO
specific implementation instead of common functions with the non-MLO
code.

Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/link.c | 2 +-
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 6 +-
.../wireless/intel/iwlwifi/mvm/mld-mac80211.c | 297 ++++++++++++------
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 1 +
4 files changed, 206 insertions(+), 100 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/link.c b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
index bbaac2ba9079..320a3bc4e9c0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/link.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
@@ -113,7 +113,7 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
link_conf->dtim_period);

if (!link_conf->he_support || iwlwifi_mod_params.disable_11ax ||
- !vif->cfg.assoc) {
+ (vif->type == NL80211_IFTYPE_STATION && !vif->cfg.assoc)) {
changes &= ~LINK_CONTEXT_MODIFY_HE_PARAMS;
goto send_cmd;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index cff24bf7e799..b90b0a973cec 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -1888,8 +1888,7 @@ static void iwl_mvm_config_iface_filter(struct ieee80211_hw *hw,
mutex_unlock(&mvm->mutex);
}

-static int iwl_mvm_update_mu_groups(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif)
+int iwl_mvm_update_mu_groups(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
struct iwl_mu_group_mgmt_cmd cmd = {};

@@ -2523,6 +2522,9 @@ iwl_mvm_bss_info_changed_station_common(struct iwl_mvm *mvm,
/* reset cqm events tracking */
mvmvif->bf_data.last_cqm_event = 0;
if (mvmvif->bf_data.bf_enabled) {
+ /* FIXME: need to update per link when FW API will
+ * support it
+ */
ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
if (ret)
IWL_ERR(mvm,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index d02b3165f1d5..950f252c1a5a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -454,37 +454,41 @@ static int iwl_mvm_mld_mac_sta_state(struct ieee80211_hw *hw,
}

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)
+iwl_mvm_mld_link_info_changed_station(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf,
+ u64 changes)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- int ret;
+ bool has_he, has_eht;
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;
+ int ret;
+
+ if (WARN_ON_ONCE(!mvmvif->link[link_conf->link_id]))
+ return;
+
+ has_he = link_conf->he_support && !iwlwifi_mod_params.disable_11ax;
+ has_eht = link_conf->eht_support && !iwlwifi_mod_params.disable_11be;

- if (changes & BSS_CHANGED_ASSOC && vif->cfg.assoc &&
- (has_he || has_eht)) {
+ /* Update EDCA params */
+ if (changes & BSS_CHANGED_QOS && vif->cfg.assoc && link_conf->qos)
+ link_changes |= LINK_CONTEXT_MODIFY_QOS_PARAMS;
+
+ if (changes & BSS_CHANGED_ERP_SLOT)
+ link_changes |= LINK_CONTEXT_MODIFY_RATES_INFO;
+
+ if (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, &vif->bss_conf,
- link_changes, true);
+ ret = iwl_mvm_link_changed(mvm, vif, link_conf, link_changes,
+ true);
if (ret)
IWL_ERR(mvm, "failed to update link\n");
}
@@ -493,85 +497,139 @@ iwl_mvm_mld_bss_info_changed_station(struct iwl_mvm *mvm,
if (ret)
IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);

- memcpy(mvmvif->deflink.bssid, bss_conf->bssid, ETH_ALEN);
+ memcpy(mvmvif->link[link_conf->link_id]->bssid, link_conf->bssid,
+ ETH_ALEN);
+
+ iwl_mvm_bss_info_changed_station_common(mvm, vif, link_conf, changes);
+}
+
+static bool iwl_mvm_mld_vif_have_valid_ap_sta(struct iwl_mvm_vif *mvmvif)
+{
+ int i;
+
+ for_each_mvm_vif_valid_link(mvmvif, i) {
+ if (mvmvif->link[i]->ap_sta_id != IWL_MVM_INVALID_STA)
+ return true;
+ }
+
+ return false;
+}
+
+static void iwl_mvm_mld_vif_delete_all_stas(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ int i, ret;
+
+ if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
+ return;
+
+ iwl_mvm_sec_key_remove_ap(mvm, vif);
+
+ for_each_mvm_vif_valid_link(mvmvif, i) {
+ struct iwl_mvm_vif_link_info *link = mvmvif->link[i];
+
+ if (!link)
+ continue;
+
+ ret = iwl_mvm_mld_rm_sta_id(mvm, vif, link->ap_sta_id);
+ if (ret)
+ IWL_ERR(mvm, "failed to remove AP station\n");
+
+ link->ap_sta_id = IWL_MVM_INVALID_STA;
+ }
+}
+
+static void iwl_mvm_mld_vif_cfg_changed_station(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ u64 changes)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct ieee80211_bss_conf *link_conf;
+ bool protect = false;
+ unsigned int i;
+ int ret;
+
+ ret = iwl_mvm_mld_mac_ctxt_changed(mvm, vif, false);
+ if (ret)
+ IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
+
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);
- }
+ if (!(changes & BSS_CHANGED_ASSOC))
+ return;
+
+ if (vif->cfg.assoc) {
+ /* clear statistics to get clean beacon counter */
+ iwl_mvm_request_statistics(mvm, true);
+ iwl_mvm_sf_update(mvm, vif, false);
+ iwl_mvm_power_vif_assoc(mvm, vif);
+
+ for_each_mvm_vif_valid_link(mvmvif, i) {
+ memset(&mvmvif->link[i]->beacon_stats, 0,
+ sizeof(mvmvif->link[i]->beacon_stats));

- 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, 0);
+ IEEE80211_SMPS_DYNAMIC, i);
}
- } 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.
+
+ rcu_read_lock();
+ link_conf = rcu_dereference(vif->link_conf[i]);
+ if (link_conf && !link_conf->dtim_period)
+ protect = true;
+ rcu_read_unlock();
+ }
+
+ if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
+ protect) {
+ /* 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.
*/
- 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_protect_assoc(mvm, vif, 0);
}

- iwl_mvm_bss_info_changed_station_assoc(mvm, vif, changes);
+ iwl_mvm_sf_update(mvm, vif, false);
+
+ /* FIXME: need to decide about misbehaving AP handling */
+ iwl_mvm_power_vif_assoc(mvm, vif);
+ } else if (iwl_mvm_mld_vif_have_valid_ap_sta(mvmvif)) {
+ 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.
+ */
+ iwl_mvm_mld_vif_delete_all_stas(mvm, vif);
}

- iwl_mvm_bss_info_changed_station_common(mvm, vif, &vif->bss_conf, changes);
+ iwl_mvm_bss_info_changed_station_assoc(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)
+iwl_mvm_mld_link_info_changed_ap_ibss(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf,
+ u64 changes)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
u32 link_changes = LINK_CONTEXT_MODIFY_PROTECT_FLAGS |
@@ -581,17 +639,22 @@ iwl_mvm_mld_bss_info_changed_ap_ibss(struct iwl_mvm *mvm,
if (!mvmvif->ap_ibss_active)
return;

+ if (link_conf->he_support)
+ link_changes |= LINK_CONTEXT_MODIFY_HE_PARAMS;
+
if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_HT |
- BSS_CHANGED_BANDWIDTH | BSS_CHANGED_QOS) &&
- iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
+ BSS_CHANGED_BANDWIDTH | BSS_CHANGED_QOS |
+ BSS_CHANGED_HE_BSS_COLOR) &&
+ iwl_mvm_link_changed(mvm, vif, link_conf,
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, &vif->bss_conf))
+ iwl_mvm_mac_ctxt_beacon_changed(mvm, vif, link_conf))
IWL_WARN(mvm, "Failed updating beacon data\n");

+ /* FIXME: need to decide if we need FTM responder per link */
if (changes & BSS_CHANGED_FTM_RESPONDER) {
int ret = iwl_mvm_ftm_start_responder(mvm, vif);

@@ -601,19 +664,58 @@ iwl_mvm_mld_bss_info_changed_ap_ibss(struct iwl_mvm *mvm,
}
}

-static void iwl_mvm_mld_bss_info_changed(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *bss_conf,
- u64 changes)
+static void iwl_mvm_mld_link_info_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf,
+ u64 changes)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+
+ mutex_lock(&mvm->mutex);
+
+ switch (vif->type) {
+ case NL80211_IFTYPE_STATION:
+ iwl_mvm_mld_link_info_changed_station(mvm, vif, link_conf,
+ changes);
+ break;
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_ADHOC:
+ iwl_mvm_mld_link_info_changed_ap_ibss(mvm, vif, link_conf,
+ changes);
+ break;
+ case NL80211_IFTYPE_MONITOR:
+ if (changes & BSS_CHANGED_MU_GROUPS)
+ iwl_mvm_update_mu_groups(mvm, vif);
+ break;
+ default:
+ /* shouldn't happen */
+ WARN_ON_ONCE(1);
+ }
+
+ if (changes & BSS_CHANGED_TXPOWER) {
+ IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d dBm\n",
+ link_conf->txpower);
+ iwl_mvm_set_tx_power(mvm, vif, link_conf->txpower);
+ }
+
+ mutex_unlock(&mvm->mutex);
+}
+
+static void iwl_mvm_mld_vif_cfg_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ 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,
- };
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);

- iwl_mvm_bss_info_changed_common(hw, vif, bss_conf, &callbacks,
- changes);
+ mutex_lock(&mvm->mutex);
+
+ if (changes & BSS_CHANGED_IDLE && !vif->cfg.idle)
+ iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_SCHED, true);
+
+ if (vif->type == NL80211_IFTYPE_STATION)
+ iwl_mvm_mld_vif_cfg_changed_station(mvm, vif, changes);
+
+ mutex_unlock(&mvm->mutex);
}

static int
@@ -735,7 +837,8 @@ const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
.prepare_multicast = iwl_mvm_prepare_multicast,
.configure_filter = iwl_mvm_configure_filter,
.config_iface_filter = iwl_mvm_mld_config_iface_filter,
- .bss_info_changed = iwl_mvm_mld_bss_info_changed,
+ .link_info_changed = iwl_mvm_mld_link_info_changed,
+ .vif_cfg_changed = iwl_mvm_mld_vif_cfg_changed,
.hw_scan = iwl_mvm_mac_hw_scan,
.cancel_hw_scan = iwl_mvm_mac_cancel_hw_scan,
.sta_pre_rcu_remove = iwl_mvm_sta_pre_rcu_remove,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 03710c0cb57d..03e035b12783 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -2621,4 +2621,5 @@ int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
int iwl_mvm_set_hw_timestamp(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_set_hw_timestamp *hwts);
+int iwl_mvm_update_mu_groups(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
#endif /* __IWL_MVM_H__ */
--
2.38.1

2023-03-28 08:09:01

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 23/31] wifi: iwlwifi: mvm: add link_conf parameter for add/remove/change link

From: Gregory Greenman <[email protected]>

Add link_conf parameter and change all the relevant calls accordingly.

Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/link.c | 81 ++++++++++++-------
.../net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 46 ++++++-----
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 2 +-
.../wireless/intel/iwlwifi/mvm/mld-mac80211.c | 50 +++++++-----
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 13 ++-
5 files changed, 118 insertions(+), 74 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/link.c b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
index d8902e0ed2ae..bbaac2ba9079 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/link.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
@@ -20,11 +20,16 @@ static int iwl_mvm_link_cmd_send(struct iwl_mvm *mvm,
return ret;
}

-int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm_phy_ctxt *phyctxt = mvmvif->deflink.phy_ctxt;
+ unsigned int link_id = link_conf->link_id;
struct iwl_link_config_cmd cmd = {};
+ struct iwl_mvm_phy_ctxt *phyctxt;
+
+ if (WARN_ON_ONCE(!mvmvif->link[link_id]))
+ return -EINVAL;

/* Update SF - Disable if needed. if this fails, SF might still be on
* while many macs are bound, which is forbidden - so fail the binding.
@@ -32,82 +37,94 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
if (iwl_mvm_sf_update(mvm, vif, false))
return -EINVAL;

+ /* FIXME: add proper link id allocation */
cmd.link_id = cpu_to_le32(mvmvif->id);
cmd.mac_id = cpu_to_le32(mvmvif->id);
/* P2P-Device already has a valid PHY context during add */
+ phyctxt = mvmvif->link[link_id]->phy_ctxt;
if (phyctxt)
cmd.phy_id = cpu_to_le32(phyctxt->id);
else
cmd.phy_id = cpu_to_le32(FW_CTXT_INVALID);

- memcpy(cmd.local_link_addr, vif->addr, ETH_ALEN);
+ memcpy(cmd.local_link_addr, link_conf->addr, ETH_ALEN);

- if (vif->type == NL80211_IFTYPE_ADHOC && vif->bss_conf.bssid)
- memcpy(cmd.ibss_bssid_addr, vif->bss_conf.bssid, ETH_ALEN);
+ if (vif->type == NL80211_IFTYPE_ADHOC && link_conf->bssid)
+ memcpy(cmd.ibss_bssid_addr, link_conf->bssid, ETH_ALEN);

return iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_ADD);
}

int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf,
u32 changes, bool active)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm_phy_ctxt *phyctxt = mvmvif->deflink.phy_ctxt;
+ unsigned int link_id = link_conf->link_id;
+ struct iwl_mvm_phy_ctxt *phyctxt;
struct iwl_link_config_cmd cmd = {};
u32 ht_flag, flags = 0, flags_mask = 0;

+ if (WARN_ON_ONCE(!mvmvif->link[link_id]))
+ return -EINVAL;
+
+ /* FIXME: add proper link id allocation */
cmd.link_id = cpu_to_le32(mvmvif->id);

/* The phy_id, link address and listen_lmac can be modified only until
* the link becomes active, otherwise they will be ignored.
*/
+ phyctxt = mvmvif->link[link_id]->phy_ctxt;
if (phyctxt)
cmd.phy_id = cpu_to_le32(phyctxt->id);
else
cmd.phy_id = cpu_to_le32(FW_CTXT_INVALID);
cmd.mac_id = cpu_to_le32(mvmvif->id);

- memcpy(cmd.local_link_addr, vif->addr, ETH_ALEN);
+ memcpy(cmd.local_link_addr, link_conf->addr, ETH_ALEN);

cmd.active = cpu_to_le32(active);

- if (vif->type == NL80211_IFTYPE_ADHOC && vif->bss_conf.bssid)
- memcpy(cmd.ibss_bssid_addr, vif->bss_conf.bssid, ETH_ALEN);
+ if (vif->type == NL80211_IFTYPE_ADHOC && link_conf->bssid)
+ memcpy(cmd.ibss_bssid_addr, link_conf->bssid, ETH_ALEN);

/* TODO: set a value to cmd.listen_lmac when system requiremens
* will define it
*/

- iwl_mvm_set_fw_basic_rates(mvm, vif, &cmd.cck_rates, &cmd.ofdm_rates);
+ iwl_mvm_set_fw_basic_rates(mvm, vif, link_conf,
+ &cmd.cck_rates, &cmd.ofdm_rates);

- cmd.cck_short_preamble = cpu_to_le32(vif->bss_conf.use_short_preamble);
- cmd.short_slot = cpu_to_le32(vif->bss_conf.use_short_slot);
+ cmd.cck_short_preamble = cpu_to_le32(link_conf->use_short_preamble);
+ cmd.short_slot = cpu_to_le32(link_conf->use_short_slot);

/* The fw does not distinguish between ht and fat */
ht_flag = LINK_PROT_FLG_HT_PROT | LINK_PROT_FLG_FAT_PROT;
- iwl_mvm_set_fw_protection_flags(mvm, vif, &cmd.protection_flags,
+ iwl_mvm_set_fw_protection_flags(mvm, vif, link_conf,
+ &cmd.protection_flags,
ht_flag, LINK_PROT_FLG_TGG_PROTECT);

- iwl_mvm_set_fw_qos_params(mvm, vif, &cmd.ac[0], &cmd.qos_flags);
+ iwl_mvm_set_fw_qos_params(mvm, vif, link_conf, &cmd.ac[0],
+ &cmd.qos_flags);


- cmd.bi = cpu_to_le32(vif->bss_conf.beacon_int);
- cmd.dtim_interval = cpu_to_le32(vif->bss_conf.beacon_int *
- vif->bss_conf.dtim_period);
+ cmd.bi = cpu_to_le32(link_conf->beacon_int);
+ cmd.dtim_interval = cpu_to_le32(link_conf->beacon_int *
+ link_conf->dtim_period);

- if (!vif->bss_conf.he_support || iwlwifi_mod_params.disable_11ax ||
+ if (!link_conf->he_support || iwlwifi_mod_params.disable_11ax ||
!vif->cfg.assoc) {
changes &= ~LINK_CONTEXT_MODIFY_HE_PARAMS;
goto send_cmd;
}

- cmd.htc_trig_based_pkt_ext = vif->bss_conf.htc_trig_based_pkt_ext;
+ cmd.htc_trig_based_pkt_ext = link_conf->htc_trig_based_pkt_ext;

- if (vif->bss_conf.uora_exists) {
+ if (link_conf->uora_exists) {
cmd.rand_alloc_ecwmin =
- vif->bss_conf.uora_ocw_range & 0x7;
+ link_conf->uora_ocw_range & 0x7;
cmd.rand_alloc_ecwmax =
- (vif->bss_conf.uora_ocw_range >> 3) & 0x7;
+ (link_conf->uora_ocw_range >> 3) & 0x7;
}

/* TODO how to set ndp_fdbk_buff_th_exp? */
@@ -118,20 +135,20 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
flags_mask |= LINK_FLG_MU_EDCA_CW;
}

- if (vif->bss_conf.eht_puncturing && !iwlwifi_mod_params.disable_11be)
- cmd.puncture_mask = cpu_to_le16(vif->bss_conf.eht_puncturing);
+ if (link_conf->eht_puncturing && !iwlwifi_mod_params.disable_11be)
+ cmd.puncture_mask = cpu_to_le16(link_conf->eht_puncturing);
else
/* This flag can be set only if the MAC has eht support */
changes &= ~LINK_CONTEXT_MODIFY_EHT_PARAMS;

- cmd.bss_color = vif->bss_conf.he_bss_color.color;
+ cmd.bss_color = link_conf->he_bss_color.color;

- if (!vif->bss_conf.he_bss_color.enabled) {
+ if (!link_conf->he_bss_color.enabled) {
flags |= LINK_FLG_BSS_COLOR_DIS;
flags_mask |= LINK_FLG_BSS_COLOR_DIS;
}

- cmd.frame_time_rts_th = cpu_to_le16(vif->bss_conf.frame_time_rts_th);
+ cmd.frame_time_rts_th = cpu_to_le16(link_conf->frame_time_rts_th);

/* Block 26-tone RU OFDMA transmissions */
if (mvmvif->deflink.he_ru_2mhz_block) {
@@ -139,10 +156,10 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
flags_mask |= LINK_FLG_RU_2MHZ_BLOCK;
}

- if (vif->bss_conf.nontransmitted) {
+ if (link_conf->nontransmitted) {
ether_addr_copy(cmd.ref_bssid_addr,
- vif->bss_conf.transmitter_bssid);
- cmd.bssid_index = vif->bss_conf.bssid_index;
+ link_conf->transmitter_bssid);
+ cmd.bssid_index = link_conf->bssid_index;
}

send_cmd:
@@ -153,12 +170,14 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_MODIFY);
}

-int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_link_config_cmd cmd = {};
int ret;

+ /* FIXME: add proper link id allocation */
cmd.link_id = cpu_to_le32(mvmvif->id);
ret = iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_REMOVE);

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index a06513989469..432b9cbcd8a4 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -397,16 +397,18 @@ static void iwl_mvm_ack_rates(struct iwl_mvm *mvm,
}

void iwl_mvm_set_fw_basic_rates(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf,
__le32 *cck_rates, __le32 *ofdm_rates)
{
struct ieee80211_chanctx_conf *chanctx;
- u8 cck_ack_rates, ofdm_ack_rates;
+ u8 cck_ack_rates = 0, ofdm_ack_rates = 0;

rcu_read_lock();
- chanctx = rcu_dereference(vif->bss_conf.chanctx_conf);
+ chanctx = rcu_dereference(link_conf->chanctx_conf);
iwl_mvm_ack_rates(mvm, vif, chanctx ? chanctx->def.chan->band
: NL80211_BAND_2GHZ,
&cck_ack_rates, &ofdm_ack_rates);
+
rcu_read_unlock();

*cck_rates = cpu_to_le32((u32)cck_ack_rates);
@@ -415,21 +417,22 @@ void iwl_mvm_set_fw_basic_rates(struct iwl_mvm *mvm, struct ieee80211_vif *vif,

void iwl_mvm_set_fw_protection_flags(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf,
__le32 *protection_flags, u32 ht_flag,
u32 tgg_flag)
{
/* for both sta and ap, ht_operation_mode hold the protection_mode */
- u8 protection_mode = vif->bss_conf.ht_operation_mode &
+ u8 protection_mode = link_conf->ht_operation_mode &
IEEE80211_HT_OP_MODE_PROTECTION;
- bool ht_enabled = !!(vif->bss_conf.ht_operation_mode &
+ bool ht_enabled = !!(link_conf->ht_operation_mode &
IEEE80211_HT_OP_MODE_PROTECTION);

- if (vif->bss_conf.use_cts_prot)
+ if (link_conf->use_cts_prot)
*protection_flags |= cpu_to_le32(tgg_flag);

IWL_DEBUG_RATE(mvm, "use_cts_prot %d, ht_operation_mode %d\n",
- vif->bss_conf.use_cts_prot,
- vif->bss_conf.ht_operation_mode);
+ link_conf->use_cts_prot,
+ link_conf->ht_operation_mode);

if (!ht_enabled)
return;
@@ -448,7 +451,7 @@ void iwl_mvm_set_fw_protection_flags(struct iwl_mvm *mvm,
break;
case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
/* Protect when channel wider than 20MHz */
- if (vif->bss_conf.chandef.width > NL80211_CHAN_WIDTH_20)
+ if (link_conf->chandef.width > NL80211_CHAN_WIDTH_20)
*protection_flags |= cpu_to_le32(ht_flag);
break;
default:
@@ -459,6 +462,7 @@ void iwl_mvm_set_fw_protection_flags(struct iwl_mvm *mvm,
}

void iwl_mvm_set_fw_qos_params(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf,
struct iwl_ac_qos *ac, __le32 *qos_flags)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
@@ -478,10 +482,10 @@ void iwl_mvm_set_fw_qos_params(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
ac[ucode_ac].fifos_mask = BIT(txf);
}

- if (vif->bss_conf.qos)
+ if (link_conf->qos)
*qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA);

- if (vif->bss_conf.chandef.width != NL80211_CHAN_WIDTH_20_NOHT)
+ if (link_conf->chandef.width != NL80211_CHAN_WIDTH_20_NOHT)
*qos_flags |= cpu_to_le32(MAC_QOS_FLG_TGN);
}

@@ -538,7 +542,7 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
else
eth_broadcast_addr(cmd->bssid_addr);

- iwl_mvm_set_fw_basic_rates(mvm, vif, &cmd->cck_rates,
+ iwl_mvm_set_fw_basic_rates(mvm, vif, &vif->bss_conf, &cmd->cck_rates,
&cmd->ofdm_rates);

cmd->cck_short_preamble =
@@ -550,11 +554,13 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,

cmd->filter_flags = 0;

- iwl_mvm_set_fw_qos_params(mvm, vif, &cmd->ac[0], &cmd->qos_flags);
+ iwl_mvm_set_fw_qos_params(mvm, vif, &vif->bss_conf, &cmd->ac[0],
+ &cmd->qos_flags);

/* The fw does not distinguish between ht and fat */
ht_flag = MAC_PROT_FLG_HT_PROT | MAC_PROT_FLG_FAT_PROT;
- iwl_mvm_set_fw_protection_flags(mvm, vif, &cmd->protection_flags,
+ iwl_mvm_set_fw_protection_flags(mvm, vif, &vif->bss_conf,
+ &cmd->protection_flags,
ht_flag, MAC_PROT_FLG_TGG_PROTECT);
}

@@ -570,6 +576,7 @@ static int iwl_mvm_mac_ctxt_send_cmd(struct iwl_mvm *mvm,
}

void iwl_mvm_set_fw_dtim_tbtt(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf,
__le64 *dtim_tsf, __le32 *dtim_time,
__le32 *assoc_beacon_arrive_time)
{
@@ -590,17 +597,17 @@ void iwl_mvm_set_fw_dtim_tbtt(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
* 384us in the longest case), this is currently not relevant
* as the firmware wakes up around 2ms before the TBTT.
*/
- dtim_offs = vif->bss_conf.sync_dtim_count *
- vif->bss_conf.beacon_int;
+ dtim_offs = link_conf->sync_dtim_count *
+ link_conf->beacon_int;
/* convert TU to usecs */
dtim_offs *= 1024;

*dtim_tsf =
- cpu_to_le64(vif->bss_conf.sync_tsf + dtim_offs);
+ cpu_to_le64(link_conf->sync_tsf + dtim_offs);
*dtim_time =
- cpu_to_le32(vif->bss_conf.sync_device_ts + dtim_offs);
+ cpu_to_le32(link_conf->sync_device_ts + dtim_offs);
*assoc_beacon_arrive_time =
- cpu_to_le32(vif->bss_conf.sync_device_ts);
+ cpu_to_le32(link_conf->sync_device_ts);

IWL_DEBUG_INFO(mvm, "DTIM TBTT is 0x%llx/0x%x, offset %d\n",
le64_to_cpu(*dtim_tsf),
@@ -666,7 +673,8 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
!force_assoc_off) {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);

- iwl_mvm_set_fw_dtim_tbtt(mvm, vif, &ctxt_sta->dtim_tsf,
+ iwl_mvm_set_fw_dtim_tbtt(mvm, vif, &vif->bss_conf,
+ &ctxt_sta->dtim_tsf,
&ctxt_sta->dtim_time,
&ctxt_sta->assoc_beacon_arrive_time);

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index ef3eb57b806a..cff24bf7e799 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -3619,7 +3619,7 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
callbacks->mac_ctxt_changed(mvm, vif, false);

if (mvm->mld_api_is_used)
- iwl_mvm_link_changed(mvm, vif,
+ iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
LINK_CONTEXT_MODIFY_ALL &
~LINK_CONTEXT_MODIFY_ACTIVE,
true);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index 80f1a1ccf16d..d02b3165f1d5 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -67,11 +67,13 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
}

iwl_mvm_phy_ctxt_ref(mvm, mvmvif->deflink.phy_ctxt);
- ret = iwl_mvm_add_link(mvm, vif);
+ ret = iwl_mvm_add_link(mvm, vif, &vif->bss_conf);
if (ret)
goto out_unref_phy;

- ret = iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ACTIVE,
+ ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
+ LINK_CONTEXT_MODIFY_ACTIVE |
+ LINK_CONTEXT_MODIFY_RATES_INFO,
true);
if (ret)
goto out_remove_link;
@@ -85,7 +87,7 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
*/
mvm->p2p_device_vif = vif;
} else {
- ret = iwl_mvm_add_link(mvm, vif);
+ ret = iwl_mvm_add_link(mvm, vif, &vif->bss_conf);
if (ret)
goto out_free_bf;
}
@@ -117,8 +119,9 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,

out_remove_link:
/* Link needs to be deactivated before removal */
- iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ACTIVE, false);
- iwl_mvm_remove_link(mvm, vif);
+ iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
+ LINK_CONTEXT_MODIFY_ACTIVE, false);
+ iwl_mvm_remove_link(mvm, vif, &vif->bss_conf);
out_unref_phy:
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
out_free_bf:
@@ -193,13 +196,13 @@ static void iwl_mvm_mld_mac_remove_interface(struct ieee80211_hw *hw,
mvm->p2p_device_vif = NULL;
iwl_mvm_mld_rm_bcast_sta(mvm, vif);
/* Link needs to be deactivated before removal */
- iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ACTIVE,
- false);
- iwl_mvm_remove_link(mvm, vif);
+ iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
+ LINK_CONTEXT_MODIFY_ACTIVE, false);
+ iwl_mvm_remove_link(mvm, vif, &vif->bss_conf);
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
mvmvif->deflink.phy_ctxt = NULL;
} else {
- iwl_mvm_remove_link(mvm, vif);
+ iwl_mvm_remove_link(mvm, vif, &vif->bss_conf);
}

iwl_mvm_mld_mac_ctxt_remove(mvm, vif);
@@ -233,12 +236,13 @@ static int __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
}

/* send it first with phy context ID */
- ret = iwl_mvm_link_changed(mvm, vif, 0, false);
+ ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf, 0, false);
if (ret)
goto out;

/* then activate */
- ret = iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ACTIVE |
+ ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
+ LINK_CONTEXT_MODIFY_ACTIVE |
LINK_CONTEXT_MODIFY_RATES_INFO,
true);
if (ret)
@@ -259,7 +263,8 @@ static int __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
return 0;

deactivate:
- iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ACTIVE, false);
+ iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
+ LINK_CONTEXT_MODIFY_ACTIVE, false);
out:
mvmvif->deflink.phy_ctxt = NULL;
iwl_mvm_power_update_mac(mvm);
@@ -303,7 +308,8 @@ static void __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm,
if (vif->type == NL80211_IFTYPE_MONITOR)
iwl_mvm_mld_rm_snif_sta(mvm, vif);

- iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ACTIVE, false);
+ iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
+ LINK_CONTEXT_MODIFY_ACTIVE, false);

if (switching_chanctx)
return;
@@ -337,7 +343,7 @@ static int iwl_mvm_mld_start_ap_ibss(struct ieee80211_hw *hw,
if (ret)
goto out_unlock;

- ret = iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ALL,
+ ret = iwl_mvm_link_changed(mvm, vif, link_conf, LINK_CONTEXT_MODIFY_ALL,
true);
if (ret)
goto out_unlock;
@@ -477,7 +483,8 @@ iwl_mvm_mld_bss_info_changed_station(struct iwl_mvm *mvm,
link_changes |= LINK_CONTEXT_MODIFY_EHT_PARAMS;

if (link_changes) {
- ret = iwl_mvm_link_changed(mvm, vif, link_changes, true);
+ ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
+ link_changes, true);
if (ret)
IWL_ERR(mvm, "failed to update link\n");
}
@@ -576,7 +583,8 @@ iwl_mvm_mld_bss_info_changed_ap_ibss(struct iwl_mvm *mvm,

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_mvm_link_changed(mvm, vif, &vif->bss_conf,
+ link_changes, true))
IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);

/* Need to send a new beacon template to the FW */
@@ -661,7 +669,7 @@ iwl_mvm_mld_mac_conf_tx(struct ieee80211_hw *hw,
int ret;

mutex_lock(&mvm->mutex);
- ret = iwl_mvm_link_changed(mvm, vif,
+ ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
LINK_CONTEXT_MODIFY_QOS_PARAMS,
true);
mutex_unlock(&mvm->mutex);
@@ -683,7 +691,8 @@ static int iwl_mvm_link_switch_phy_ctx(struct iwl_mvm *mvm,
* 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);
+ ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
+ LINK_CONTEXT_MODIFY_ACTIVE, false);
if (WARN(ret, "Failed to deactivate link\n"))
return ret;

@@ -691,11 +700,12 @@ static int iwl_mvm_link_switch_phy_ctx(struct iwl_mvm *mvm,

mvmvif->deflink.phy_ctxt = new_phy_ctxt;

- ret = iwl_mvm_link_changed(mvm, vif, 0, false);
+ ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf, 0, false);
if (WARN(ret, "Failed to deactivate link\n"))
return ret;

- ret = iwl_mvm_link_changed(mvm, vif, LINK_CONTEXT_MODIFY_ACTIVE, true);
+ ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
+ LINK_CONTEXT_MODIFY_ACTIVE, true);
WARN(ret, "Failed binding P2P_DEVICE\n");
return ret;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index d62341269744..03710c0cb57d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -1721,17 +1721,21 @@ u8 iwl_mvm_get_ctrl_pos(struct cfg80211_chan_def *chandef);
void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
struct ieee80211_vif *vif);
void iwl_mvm_set_fw_basic_rates(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf,
__le32 *cck_rates, __le32 *ofdm_rates);
void iwl_mvm_set_fw_protection_flags(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf,
__le32 *protection_flags, u32 ht_flag,
- u32 tgg_flag);
+ u32 tgg_flag);
void iwl_mvm_set_fw_qos_params(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf,
struct iwl_ac_qos *ac, __le32 *qos_flags);
bool iwl_mvm_set_fw_mu_edca_params(struct iwl_mvm *mvm,
struct iwl_mvm_vif *mvmvif,
struct iwl_he_backoff_conf *trig_based_txf);
void iwl_mvm_set_fw_dtim_tbtt(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf,
__le64 *dtim_tsf, __le32 *dtim_time,
__le32 *assoc_beacon_arrive_time);
__le32 iwl_mac_ctxt_p2p_dev_has_extended_disc(struct iwl_mvm *mvm,
@@ -1799,10 +1803,13 @@ int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);

/* Links */
-int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
+int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf);
int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf,
u32 changes, bool active);
-int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
+int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf);

/* AP and IBSS */
bool iwl_mvm_start_ap_ibss_common(struct ieee80211_hw *hw,
--
2.38.1

2023-03-28 08:09:03

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 26/31] wifi: iwlwifi: mvm: add fw link id allocation

From: Gregory Greenman <[email protected]>

Driver uses link_id as an index in the array. FW currently can
support only 2 concurrently active links per vif with the ids in the
range 0-3. Add a mapping of dirver link ids to fw link id and track the
number of active link ids.

Signed-off-by: Gregory Greenman <[email protected]>
---
.../wireless/intel/iwlwifi/fw/api/mac-cfg.h | 6 ++
.../net/wireless/intel/iwlwifi/mvm/debugfs.c | 6 +-
drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 2 +
drivers/net/wireless/intel/iwlwifi/mvm/link.c | 87 ++++++++++++++++---
.../net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 6 +-
.../wireless/intel/iwlwifi/mvm/mld-mac80211.c | 1 +
.../net/wireless/intel/iwlwifi/mvm/mld-sta.c | 25 ++++--
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 10 +++
8 files changed, 121 insertions(+), 22 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
index b644274e4a31..e236d1b0aae2 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
@@ -483,6 +483,12 @@ struct iwl_link_config_cmd {
__le32 reserved1[8];
} __packed; /* LINK_CONTEXT_CONFIG_CMD_API_S_VER_1 */

+/* Currently FW supports link ids in the range 0-3 and can have
+ * at most two active links for each vif.
+ */
+#define IWL_MVM_FW_MAX_ACTIVE_LINKS_NUM 2
+#define IWL_MVM_FW_MAX_LINK_ID 3
+
/**
* enum iwl_fw_sta_type - FW station types
* @STATION_TYPE_PEER: represents a peer - AP in BSS, a TDLS sta, a client in
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
index 2c72f5cb19f1..527daaf46f96 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
@@ -1442,7 +1442,11 @@ static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len)
cpu_to_le16(iwl_mvm_mac_ctxt_get_beacon_flags(mvm->fw,
rate));
beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len);
- beacon_cmd.link_id = cpu_to_le32((u32)mvmvif->id);
+ if (iwl_fw_lookup_cmd_ver(mvm->fw, BEACON_TEMPLATE_CMD, 0) > 12)
+ beacon_cmd.link_id =
+ cpu_to_le32(mvmvif->link[link_id]->fw_link_id);
+ else
+ beacon_cmd.link_id = cpu_to_le32((u32)mvmvif->id);

iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx,
&beacon_cmd.tim_size,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index 6d6fa35c2b21..d302d98b7631 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -1573,6 +1573,8 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++)
RCU_INIT_POINTER(mvm->fw_id_to_mac_id[i], NULL);

+ memset(&mvm->fw_link_ids_map, 0, sizeof(mvm->fw_link_ids_map));
+
mvm->tdls_cs.peer.sta_id = IWL_MVM_INVALID_STA;

/* reset quota debouncing buffer - 0xff will yield invalid data */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/link.c b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
index 320a3bc4e9c0..7a70b6ee65ac 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/link.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
@@ -1,9 +1,34 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2022 Intel Corporation
+ * Copyright (C) 2022 - 2023 Intel Corporation
*/
#include "mvm.h"

+static u32 iwl_mvm_get_free_fw_link_id(struct iwl_mvm *mvm,
+ struct iwl_mvm_vif *mvm_vif)
+{
+ u32 link_id;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ link_id = ffz(mvm->fw_link_ids_map);
+
+ /* this case can happen if there're deactivated but not removed links */
+ if (link_id > IWL_MVM_FW_MAX_LINK_ID)
+ return IWL_MVM_FW_LINK_ID_INVALID;
+
+ mvm->fw_link_ids_map |= BIT(link_id);
+ return link_id;
+}
+
+static void iwl_mvm_release_fw_link_id(struct iwl_mvm *mvm, u32 link_id)
+{
+ lockdep_assert_held(&mvm->mutex);
+
+ if (!WARN_ON(link_id > IWL_MVM_FW_MAX_LINK_ID))
+ mvm->fw_link_ids_map &= ~BIT(link_id);
+}
+
static int iwl_mvm_link_cmd_send(struct iwl_mvm *mvm,
struct iwl_link_config_cmd *cmd,
enum iwl_ctxt_action action)
@@ -25,23 +50,30 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
unsigned int link_id = link_conf->link_id;
+ struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id];
struct iwl_link_config_cmd cmd = {};
struct iwl_mvm_phy_ctxt *phyctxt;

- if (WARN_ON_ONCE(!mvmvif->link[link_id]))
+ if (WARN_ON_ONCE(!link_info))
return -EINVAL;

+ if (link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID) {
+ link_info->fw_link_id = iwl_mvm_get_free_fw_link_id(mvm,
+ mvmvif);
+ if (link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID)
+ return -EINVAL;
+ }
+
/* Update SF - Disable if needed. if this fails, SF might still be on
* while many macs are bound, which is forbidden - so fail the binding.
*/
if (iwl_mvm_sf_update(mvm, vif, false))
return -EINVAL;

- /* FIXME: add proper link id allocation */
- cmd.link_id = cpu_to_le32(mvmvif->id);
+ cmd.link_id = cpu_to_le32(link_info->fw_link_id);
cmd.mac_id = cpu_to_le32(mvmvif->id);
/* P2P-Device already has a valid PHY context during add */
- phyctxt = mvmvif->link[link_id]->phy_ctxt;
+ phyctxt = link_info->phy_ctxt;
if (phyctxt)
cmd.phy_id = cpu_to_le32(phyctxt->id);
else
@@ -61,20 +93,27 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
unsigned int link_id = link_conf->link_id;
+ struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id];
struct iwl_mvm_phy_ctxt *phyctxt;
struct iwl_link_config_cmd cmd = {};
u32 ht_flag, flags = 0, flags_mask = 0;
+ int ret;
+
+ if (WARN_ON_ONCE(!link_info ||
+ link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID))
+ return -EINVAL;

- if (WARN_ON_ONCE(!mvmvif->link[link_id]))
+ /* cannot activate third link */
+ if (!link_info->active && active &&
+ mvmvif->fw_active_links_num >= IWL_MVM_FW_MAX_ACTIVE_LINKS_NUM)
return -EINVAL;

- /* FIXME: add proper link id allocation */
- cmd.link_id = cpu_to_le32(mvmvif->id);
+ cmd.link_id = cpu_to_le32(link_info->fw_link_id);

/* The phy_id, link address and listen_lmac can be modified only until
* the link becomes active, otherwise they will be ignored.
*/
- phyctxt = mvmvif->link[link_id]->phy_ctxt;
+ phyctxt = link_info->phy_ctxt;
if (phyctxt)
cmd.phy_id = cpu_to_le32(phyctxt->id);
else
@@ -151,7 +190,7 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
cmd.frame_time_rts_th = cpu_to_le16(link_conf->frame_time_rts_th);

/* Block 26-tone RU OFDMA transmissions */
- if (mvmvif->deflink.he_ru_2mhz_block) {
+ if (link_info->he_ru_2mhz_block) {
flags |= LINK_FLG_RU_2MHZ_BLOCK;
flags_mask |= LINK_FLG_RU_2MHZ_BLOCK;
}
@@ -167,18 +206,40 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
cmd.flags = cpu_to_le32(flags);
cmd.flags_mask = cpu_to_le32(flags_mask);

- return iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_MODIFY);
+ ret = iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_MODIFY);
+ if (!ret) {
+ /* the FW is updated, so now it's possible to update the
+ * activation status. If activating a link, it was already
+ * checked above that we didn't reach the FW limit.
+ */
+ if (link_info->active && !active)
+ mvmvif->fw_active_links_num--;
+ else if (!link_info->active && active)
+ mvmvif->fw_active_links_num++;
+
+ link_info->active = active;
+ }
+
+ return ret;
}

int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ unsigned int link_id = link_conf->link_id;
+ struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id];
struct iwl_link_config_cmd cmd = {};
int ret;

- /* FIXME: add proper link id allocation */
- cmd.link_id = cpu_to_le32(mvmvif->id);
+ if (WARN_ON(!link_info ||
+ link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID))
+ return -EINVAL;
+
+ cmd.link_id = cpu_to_le32(link_info->fw_link_id);
+ iwl_mvm_release_fw_link_id(mvm, link_info->fw_link_id);
+ link_info->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
+
ret = iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_REMOVE);

if (!ret)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index 432b9cbcd8a4..82fad042a281 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -1078,7 +1078,11 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,

beacon_cmd.flags = cpu_to_le16(flags);
beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len);
- beacon_cmd.link_id = cpu_to_le32((u32)mvmvif->id);
+ if (iwl_fw_lookup_cmd_ver(mvm->fw, BEACON_TEMPLATE_CMD, 0) > 12)
+ beacon_cmd.link_id =
+ cpu_to_le32(mvmvif->link[link_conf->link_id]->fw_link_id);
+ else
+ beacon_cmd.link_id = cpu_to_le32((u32)mvmvif->id);

if (vif->type == NL80211_IFTYPE_AP)
iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index c81b92d2e8f7..b861b5478e08 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -36,6 +36,7 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
mvmvif->features |= hw->netdev_features;

/* the first link always points to the default one */
+ mvmvif->deflink.fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
mvmvif->link[0] = &mvmvif->deflink;

ret = iwl_mvm_mld_mac_ctxt_add(mvm, vif);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
index 75d4585c0b21..3791f37afa78 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
@@ -197,8 +197,8 @@ int iwl_mvm_mld_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return iwl_mvm_mld_add_int_sta(mvm, bsta, queue,
ieee80211_vif_type_p2p(vif),
STATION_TYPE_BCAST_MGMT,
- mvmvif->id, baddr, IWL_MAX_TID_COUNT,
- &wdg_timeout);
+ mvm_link->fw_link_id, baddr,
+ IWL_MAX_TID_COUNT, &wdg_timeout);
}

/* Allocate a new station entry for the broadcast station to the given vif,
@@ -232,7 +232,8 @@ int iwl_mvm_mld_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,

return iwl_mvm_mld_add_int_sta(mvm, msta, &mvm_link->cab_queue,
vif->type, STATION_TYPE_MCAST,
- mvmvif->id, maddr, 0, &timeout);
+ mvm_link->fw_link_id, maddr, 0,
+ &timeout);
}

/* Allocate a new station entry for the sniffer station to the given vif,
@@ -242,13 +243,15 @@ int iwl_mvm_mld_add_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm_vif_link_info *mvm_link =
+ mvmvif->link[link_conf->link_id];

lockdep_assert_held(&mvm->mutex);

return iwl_mvm_mld_add_int_sta(mvm, &mvm->snif_sta, &mvm->snif_queue,
vif->type, STATION_TYPE_BCAST_MGMT,
- mvmvif->id, NULL, IWL_MAX_TID_COUNT,
- NULL);
+ mvm_link->fw_link_id, NULL,
+ IWL_MAX_TID_COUNT, NULL);
}

int iwl_mvm_mld_add_aux_sta(struct iwl_mvm *mvm, u32 lmac_id)
@@ -380,15 +383,23 @@ static int iwl_mvm_mld_cfg_sta(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
struct ieee80211_vif *vif)
{
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm_vif *mvm_vif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_sta_cfg_cmd cmd = {
.sta_id = cpu_to_le32(mvm_sta->deflink.sta_id),
- .link_id = cpu_to_le32(mvmvif->id),
.station_type = cpu_to_le32(mvm_sta->sta_type),
.mfp = cpu_to_le32(sta->mfp),
};
+ /* FIXME: use proper link_id */
+ unsigned int link_id = 0;
+ struct iwl_mvm_vif_link_info *link_info = mvm_vif->link[link_id];
u32 agg_size = 0, mpdu_dens = 0;

+ /* when adding sta, link should exist in FW */
+ if (WARN_ON(link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID))
+ return -EINVAL;
+
+ cmd.link_id = cpu_to_le32(link_info->fw_link_id);
+
/* For now the link addr is the same as the mld addr */
memcpy(&cmd.peer_mld_address, sta->addr, ETH_ALEN);
memcpy(&cmd.peer_link_address, sta->addr, ETH_ALEN);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 03e035b12783..ad67a9b71807 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -73,6 +73,9 @@
/* offchannel queue towards mac80211 */
#define IWL_MVM_OFFCHANNEL_QUEUE 0

+/* invalid value for FW link id */
+#define IWL_MVM_FW_LINK_ID_INVALID 0xff
+
extern const struct ieee80211_ops iwl_mvm_hw_ops;
extern const struct ieee80211_ops iwl_mvm_mld_hw_ops;

@@ -283,6 +286,7 @@ struct iwl_probe_resp_data {
/**
* struct iwl_mvm_vif_link_info - per link data in Virtual Interface
* @ap_sta_id: the sta_id of the AP - valid only if VIF type is STA
+ * @fw_link_id: the id of the link according to the FW API
* @bssid: BSSID for this (client) interface
* @bcast_sta: station used for broadcast packets. Used by the following
* vifs: P2P_DEVICE, GO and AP.
@@ -299,6 +303,7 @@ struct iwl_probe_resp_data {
struct iwl_mvm_vif_link_info {
u8 bssid[ETH_ALEN];
u8 ap_sta_id;
+ u8 fw_link_id;

struct iwl_mvm_int_sta bcast_sta;
struct iwl_mvm_int_sta mcast_sta;
@@ -312,6 +317,7 @@ struct iwl_mvm_vif_link_info {
struct iwl_probe_resp_data __rcu *probe_resp_data;

bool he_ru_2mhz_block;
+ bool active;

u16 cab_queue;
/* Assigned while mac80211 has the link in a channel context,
@@ -349,6 +355,7 @@ struct iwl_mvm_vif_link_info {
* @csa_failed: CSA failed to schedule time event, report an error later
* @csa_bcn_pending: indicates that we are waiting for a beacon on a new channel
* @features: hw features active for this vif
+ * @fw_active_links_num: the number of activated links
*/
struct iwl_mvm_vif {
struct iwl_mvm *mvm;
@@ -432,6 +439,8 @@ struct iwl_mvm_vif {
struct ieee80211_key_conf __rcu *keys[2];
} bcn_prot;

+ u32 fw_active_links_num;
+
struct iwl_mvm_vif_link_info deflink;
struct iwl_mvm_vif_link_info *link[IEEE80211_MLD_MAX_NUM_LINKS];
};
@@ -896,6 +905,7 @@ struct iwl_mvm {
/* data related to data path */
struct iwl_rx_phy_info last_phy_info;
struct ieee80211_sta __rcu *fw_id_to_mac_id[IWL_MVM_STATION_COUNT_MAX];
+ unsigned long fw_link_ids_map;
u8 rx_ba_sessions;

/* configured by mac80211 */
--
2.38.1

2023-03-28 08:09:06

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 27/31] wifi: iwlwifi: mvm: adjust to MLO assign/unassign/switch_vif_chanctx()

From: Gregory Greenman <[email protected]>

Pass link_conf when it's necessary and change the code accordingly.

Signed-off-by: Gregory Greenman <[email protected]>
---
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 46 +++++++++-------
.../wireless/intel/iwlwifi/mvm/mld-mac80211.c | 52 ++++++++++++-------
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 10 +---
3 files changed, 61 insertions(+), 47 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index b90b0a973cec..82e7a66c5828 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -4608,10 +4608,11 @@ void iwl_mvm_change_chanctx(struct ieee80211_hw *hw,
* Returns true if we're done assigning the chanctx
* (either on failure or success)
*/
-bool __iwl_mvm_assign_vif_chanctx_common(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- struct ieee80211_chanctx_conf *ctx,
- bool switching_chanctx, int *ret)
+static bool
+__iwl_mvm_assign_vif_chanctx_common(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_chanctx_conf *ctx,
+ bool switching_chanctx, int *ret)
{
u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
@@ -4651,12 +4652,16 @@ bool __iwl_mvm_assign_vif_chanctx_common(struct iwl_mvm *mvm,

static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf,
struct ieee80211_chanctx_conf *ctx,
bool switching_chanctx)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ret;

+ if (WARN_ON(!link_conf))
+ return -EINVAL;
+
if (__iwl_mvm_assign_vif_chanctx_common(mvm, vif, ctx,
switching_chanctx, &ret))
goto out;
@@ -4736,7 +4741,7 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
int ret;

mutex_lock(&mvm->mutex);
- ret = __iwl_mvm_assign_vif_chanctx(mvm, vif, ctx, false);
+ ret = __iwl_mvm_assign_vif_chanctx(mvm, vif, link_conf, ctx, false);
mutex_unlock(&mvm->mutex);

return ret;
@@ -4748,9 +4753,9 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
* Returns if chanctx unassign chanctx is done
* (either on failure or success)
*/
-bool __iwl_mvm_unassign_vif_chanctx_common(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- bool switching_chanctx)
+static bool __iwl_mvm_unassign_vif_chanctx_common(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ bool switching_chanctx)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);

@@ -4788,6 +4793,7 @@ bool __iwl_mvm_unassign_vif_chanctx_common(struct iwl_mvm *mvm,

static void __iwl_mvm_unassign_vif_chanctx(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf,
struct ieee80211_chanctx_conf *ctx,
bool switching_chanctx)
{
@@ -4827,7 +4833,7 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw,
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);

mutex_lock(&mvm->mutex);
- __iwl_mvm_unassign_vif_chanctx(mvm, vif, ctx, false);
+ __iwl_mvm_unassign_vif_chanctx(mvm, vif, link_conf, ctx, false);
mutex_unlock(&mvm->mutex);
}

@@ -4839,7 +4845,8 @@ iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm,
int ret;

mutex_lock(&mvm->mutex);
- ops->__unassign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx, true);
+ ops->__unassign_vif_chanctx(mvm, vifs[0].vif, vifs[0].link_conf,
+ vifs[0].old_ctx, true);
__iwl_mvm_remove_chanctx(mvm, vifs[0].old_ctx);

ret = __iwl_mvm_add_chanctx(mvm, vifs[0].new_ctx);
@@ -4848,8 +4855,8 @@ iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm,
goto out_reassign;
}

- ret = ops->__assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].new_ctx,
- true);
+ ret = ops->__assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].link_conf,
+ vifs[0].new_ctx, true);
if (ret) {
IWL_ERR(mvm,
"failed to assign new_ctx during channel switch\n");
@@ -4871,8 +4878,8 @@ iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm,
goto out_restart;
}

- if (ops->__assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx,
- true)) {
+ if (ops->__assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].link_conf,
+ vifs[0].old_ctx, true)) {
IWL_ERR(mvm, "failed to reassign old_ctx after failure.\n");
goto out_restart;
}
@@ -4897,10 +4904,11 @@ iwl_mvm_switch_vif_chanctx_reassign(struct iwl_mvm *mvm,
int ret;

mutex_lock(&mvm->mutex);
- ops->__unassign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx, true);
+ ops->__unassign_vif_chanctx(mvm, vifs[0].vif, vifs[0].link_conf,
+ vifs[0].old_ctx, true);

- ret = ops->__assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].new_ctx,
- true);
+ ret = ops->__assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].link_conf,
+ vifs[0].new_ctx, true);
if (ret) {
IWL_ERR(mvm,
"failed to assign new_ctx during channel switch\n");
@@ -4910,8 +4918,8 @@ iwl_mvm_switch_vif_chanctx_reassign(struct iwl_mvm *mvm,
goto out;

out_reassign:
- if (ops->__assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx,
- true)) {
+ if (ops->__assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].link_conf,
+ vifs[0].old_ctx, true)) {
IWL_ERR(mvm, "failed to reassign old_ctx after failure.\n");
goto out_restart;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index b861b5478e08..0c233d151231 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -220,17 +220,23 @@ static void iwl_mvm_mld_mac_remove_interface(struct ieee80211_hw *hw,
mutex_unlock(&mvm->mutex);
}

-static int __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- struct ieee80211_chanctx_conf *ctx,
- bool switching_chanctx)
+static int
+__iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf,
+ struct ieee80211_chanctx_conf *ctx,
+ bool switching_chanctx)
{
u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ unsigned int link_id = link_conf->link_id;
int ret;

- mvmvif->deflink.phy_ctxt = phy_ctxt;
+ if (WARN_ON_ONCE(!mvmvif->link[link_id]))
+ return -EINVAL;
+
+ mvmvif->link[link_id]->phy_ctxt = phy_ctxt;

if (switching_chanctx) {
/* reactivate if we turned this off during channel switch */
@@ -239,12 +245,12 @@ static int __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
}

/* send it first with phy context ID */
- ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf, 0, false);
+ ret = iwl_mvm_link_changed(mvm, vif, link_conf, 0, false);
if (ret)
goto out;

/* then activate */
- ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
+ ret = iwl_mvm_link_changed(mvm, vif, link_conf,
LINK_CONTEXT_MODIFY_ACTIVE |
LINK_CONTEXT_MODIFY_RATES_INFO,
true);
@@ -258,8 +264,7 @@ static int __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
iwl_mvm_power_update_mac(mvm);

if (vif->type == NL80211_IFTYPE_MONITOR) {
- ret = iwl_mvm_mld_add_snif_sta(mvm, vif,
- &vif->bss_conf);
+ ret = iwl_mvm_mld_add_snif_sta(mvm, vif, link_conf);
if (ret)
goto deactivate;
}
@@ -267,10 +272,10 @@ static int __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
return 0;

deactivate:
- iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
- LINK_CONTEXT_MODIFY_ACTIVE, false);
+ iwl_mvm_link_changed(mvm, vif, link_conf, LINK_CONTEXT_MODIFY_ACTIVE,
+ false);
out:
- mvmvif->deflink.phy_ctxt = NULL;
+ mvmvif->link[link_id]->phy_ctxt = NULL;
iwl_mvm_power_update_mac(mvm);
return ret;
}
@@ -284,18 +289,25 @@ static int iwl_mvm_mld_assign_vif_chanctx(struct ieee80211_hw *hw,
int ret;

mutex_lock(&mvm->mutex);
- ret = __iwl_mvm_mld_assign_vif_chanctx(mvm, vif, ctx, false);
+ ret = __iwl_mvm_mld_assign_vif_chanctx(mvm, vif, link_conf, ctx, false);
mutex_unlock(&mvm->mutex);

return ret;
}

-static void __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- struct ieee80211_chanctx_conf *ctx,
- bool switching_chanctx)
+static void
+__iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf,
+ struct ieee80211_chanctx_conf *ctx,
+ bool switching_chanctx)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ unsigned int link_id = link_conf->link_id;
+
+ /* shouldn't happen, but verify link_id is valid before accessing */
+ if (WARN_ON_ONCE(!mvmvif->link[link_id]))
+ return;

if (vif->type == NL80211_IFTYPE_AP && switching_chanctx) {
mvmvif->csa_countdown = false;
@@ -312,12 +324,12 @@ static void __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm,
if (vif->type == NL80211_IFTYPE_MONITOR)
iwl_mvm_mld_rm_snif_sta(mvm, vif);

- iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
+ iwl_mvm_link_changed(mvm, vif, link_conf,
LINK_CONTEXT_MODIFY_ACTIVE, false);

if (switching_chanctx)
return;
- mvmvif->deflink.phy_ctxt = NULL;
+ mvmvif->link[link_id]->phy_ctxt = NULL;
iwl_mvm_power_update_mac(mvm);
}

@@ -329,7 +341,7 @@ static void iwl_mvm_mld_unassign_vif_chanctx(struct ieee80211_hw *hw,
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);

mutex_lock(&mvm->mutex);
- __iwl_mvm_mld_unassign_vif_chanctx(mvm, vif, ctx, false);
+ __iwl_mvm_mld_unassign_vif_chanctx(mvm, vif, link_conf, ctx, false);
mutex_unlock(&mvm->mutex);
}

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index ad67a9b71807..811647c8aa71 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -2365,10 +2365,12 @@ int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
struct iwl_mvm_switch_vif_chanctx_ops {
int (*__assign_vif_chanctx)(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf,
struct ieee80211_chanctx_conf *ctx,
bool switching_chanctx);
void (*__unassign_vif_chanctx)(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf,
struct ieee80211_chanctx_conf *ctx,
bool switching_chanctx);
};
@@ -2380,14 +2382,6 @@ iwl_mvm_switch_vif_chanctx_common(struct ieee80211_hw *hw,
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,
- struct ieee80211_vif *vif,
- struct ieee80211_chanctx_conf *ctx,
- bool switching_chanctx, int *ret);
-bool __iwl_mvm_unassign_vif_chanctx_common(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- bool switching_chanctx);
-
/* Channel info utils */
static inline bool iwl_mvm_has_ultra_hb_channel(struct iwl_mvm *mvm)
{
--
2.38.1

2023-03-28 08:09:14

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 29/31] wifi: iwlwifi: mvm: refactor iwl_mvm_mac_sta_state_common()

From: Gregory Greenman <[email protected]>

Move code handling specific state transitions into separate handlers
and adjust them for MLO. Adjust relevant callbacks as well.

Signed-off-by: Gregory Greenman <[email protected]>
---
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 430 ++++++++++++------
.../net/wireless/intel/iwlwifi/mvm/mld-sta.c | 309 ++++++++++---
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 10 +-
.../net/wireless/intel/iwlwifi/mvm/rs-fw.c | 28 +-
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 137 ++++--
drivers/net/wireless/intel/iwlwifi/mvm/sta.h | 3 +-
6 files changed, 671 insertions(+), 246 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 82e7a66c5828..f778ac69c671 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -2013,12 +2013,13 @@ static void iwl_mvm_parse_ppe(struct iwl_mvm *mvm,
}

static void iwl_mvm_set_pkt_ext_from_he_ppe(struct iwl_mvm *mvm,
- struct ieee80211_sta *sta,
+ struct ieee80211_link_sta *link_sta,
struct iwl_he_pkt_ext_v2 *pkt_ext,
bool inheritance)
{
- u8 nss = (sta->deflink.he_cap.ppe_thres[0] & IEEE80211_PPE_THRES_NSS_MASK) + 1;
- u8 *ppe = &sta->deflink.he_cap.ppe_thres[0];
+ u8 nss = (link_sta->he_cap.ppe_thres[0] &
+ IEEE80211_PPE_THRES_NSS_MASK) + 1;
+ u8 *ppe = &link_sta->he_cap.ppe_thres[0];
u8 ru_index_bitmap =
u8_get_bits(*ppe,
IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK);
@@ -2098,31 +2099,35 @@ static void iwl_mvm_get_optimal_ppe_info(struct iwl_he_pkt_ext_v2 *pkt_ext,
}

/* Set the pkt_ext field according to PPE Thresholds element */
-int iwl_mvm_set_sta_pkt_ext(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
+int iwl_mvm_set_sta_pkt_ext(struct iwl_mvm *mvm,
+ struct ieee80211_link_sta *link_sta,
struct iwl_he_pkt_ext_v2 *pkt_ext)
{
u8 nominal_padding;
int i, ret = 0;

+ if (WARN_ON(!link_sta))
+ return -EINVAL;
+
/* Initialize the PPE thresholds to "None" (7), as described in Table
* 9-262ac of 80211.ax/D3.0.
*/
memset(pkt_ext, IWL_HE_PKT_EXT_NONE,
sizeof(struct iwl_he_pkt_ext_v2));

- if (sta->deflink.eht_cap.has_eht) {
+ if (link_sta->eht_cap.has_eht) {
nominal_padding =
- u8_get_bits(sta->deflink.eht_cap.eht_cap_elem.phy_cap_info[5],
+ u8_get_bits(link_sta->eht_cap.eht_cap_elem.phy_cap_info[5],
IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK);

/* If PPE Thresholds exists, parse them into a FW-familiar
* format.
*/
- if (sta->deflink.eht_cap.eht_cap_elem.phy_cap_info[5] &
+ if (link_sta->eht_cap.eht_cap_elem.phy_cap_info[5] &
IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT) {
- u8 nss = (sta->deflink.eht_cap.eht_ppe_thres[0] &
+ u8 nss = (link_sta->eht_cap.eht_ppe_thres[0] &
IEEE80211_EHT_PPE_THRES_NSS_MASK) + 1;
- u8 *ppe = &sta->deflink.eht_cap.eht_ppe_thres[0];
+ u8 *ppe = &link_sta->eht_cap.eht_ppe_thres[0];
u8 ru_index_bitmap =
u16_get_bits(*ppe,
IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK);
@@ -2131,17 +2136,17 @@ int iwl_mvm_set_sta_pkt_ext(struct iwl_mvm *mvm, struct ieee80211_sta *sta,

iwl_mvm_parse_ppe(mvm, pkt_ext, nss, ru_index_bitmap,
ppe, ppe_pos_bit, true);
- /* EHT PPE Thresholds doesn't exist - set the API according
- * to HE PPE Tresholds
+ /* EHT PPE Thresholds doesn't exist - set the API according to
+ * HE PPE Tresholds
*/
- } else if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[6] &
+ } else if (link_sta->he_cap.he_cap_elem.phy_cap_info[6] &
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
/* Even though HE Capabilities IE doesn't contain PPE
* Thresholds for BW 320Mhz, thresholds for this BW will
* be filled in with the same values as 160Mhz, due to
* the inheritance, as required.
*/
- iwl_mvm_set_pkt_ext_from_he_ppe(mvm, sta, pkt_ext,
+ iwl_mvm_set_pkt_ext_from_he_ppe(mvm, link_sta, pkt_ext,
true);

/* According to the requirements, for MCSs 12-13 the
@@ -2157,18 +2162,18 @@ int iwl_mvm_set_sta_pkt_ext(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
ret = iwl_mvm_set_pkt_ext_from_nominal_padding(pkt_ext,
nominal_padding);
}
- } else if (sta->deflink.he_cap.has_he) {
+ } else if (link_sta->he_cap.has_he) {
/* If PPE Thresholds exist, parse them into a FW-familiar format. */
- if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[6] &
+ if (link_sta->he_cap.he_cap_elem.phy_cap_info[6] &
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
- iwl_mvm_set_pkt_ext_from_he_ppe(mvm, sta, pkt_ext,
+ iwl_mvm_set_pkt_ext_from_he_ppe(mvm, link_sta, pkt_ext,
false);
/* PPE Thresholds doesn't exist - set the API PPE values
* according to Common Nominal Packet Padding field.
*/
} else {
nominal_padding =
- u8_get_bits(sta->deflink.he_cap.he_cap_elem.phy_cap_info[9],
+ u8_get_bits(link_sta->he_cap.he_cap_elem.phy_cap_info[9],
IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK);
if (nominal_padding != IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_RESERVED)
ret = iwl_mvm_set_pkt_ext_from_nominal_padding(pkt_ext,
@@ -2244,9 +2249,11 @@ bool iwl_mvm_is_nic_ack_enabled(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
IEEE80211_HE_MAC_CAP2_ACK_EN));
}

-__le32 iwl_mvm_get_sta_htc_flags(struct ieee80211_sta *sta)
+__le32 iwl_mvm_get_sta_htc_flags(struct ieee80211_sta *sta,
+ struct ieee80211_link_sta *link_sta)
{
- u8 *mac_cap_info = &sta->deflink.he_cap.he_cap_elem.mac_cap_info[0];
+ u8 *mac_cap_info =
+ &link_sta->he_cap.he_cap_elem.mac_cap_info[0];
__le32 htc_flags = 0;

if (mac_cap_info[0] & IEEE80211_HE_MAC_CAP0_HTC_HE)
@@ -2339,10 +2346,10 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,
flags |= STA_CTXT_HE_RU_2MHZ_BLOCK;

/* HTC flags */
- sta_ctxt_cmd.htc_flags = iwl_mvm_get_sta_htc_flags(sta);
+ sta_ctxt_cmd.htc_flags = iwl_mvm_get_sta_htc_flags(sta, &sta->deflink);

/* PPE Thresholds */
- if (!iwl_mvm_set_sta_pkt_ext(mvm, sta, &sta_ctxt_cmd.pkt_ext))
+ if (!iwl_mvm_set_sta_pkt_ext(mvm, &sta->deflink, &sta_ctxt_cmd.pkt_ext))
flags |= STA_CTXT_HE_PACKET_EXT;

if (sta->deflink.he_cap.he_cap_elem.mac_cap_info[2] &
@@ -3497,6 +3504,253 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
&callbacks);
}

+/* FIXME: temporary making two assumptions in all sta handling functions:
+ * (1) when setting sta state, the link exists and protected
+ * (2) if a link is valid in sta then it's valid in vif (can
+ * use same index in the link array)
+ */
+
+#define iwl_mvm_rs_rate_init_all_links(mvm, mvmvif, sta, update) do { \
+ typeof(mvmvif) _mvmvif = mvmvif; \
+ unsigned int _i; \
+ for_each_mvm_vif_valid_link(_mvmvif, _i) \
+ iwl_mvm_rs_rate_init((mvm), (sta), \
+ _mvmvif->link[_i]->phy_ctxt->channel->band,\
+ (update)); \
+} while (0)
+
+#define IWL_MVM_MIN_BEACON_INTERVAL_TU 16
+
+static bool iwl_mvm_vif_conf_from_sta(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ unsigned int i;
+
+ /* Beacon interval check - firmware will crash if the beacon
+ * interval is less than 16. We can't avoid connecting at all,
+ * so refuse the station state change, this will cause mac80211
+ * to abandon attempts to connect to this AP, and eventually
+ * wpa_s will blocklist the AP...
+ */
+
+ for_each_set_bit(i, (unsigned long *)&sta->valid_links,
+ IEEE80211_MLD_MAX_NUM_LINKS) {
+ struct ieee80211_link_sta *link_sta =
+ rcu_dereference_protected(sta->link[i], 1);
+ struct ieee80211_bss_conf *link_conf =
+ rcu_dereference_protected(vif->link_conf[i], 1);
+
+ if (!link_conf || !link_sta)
+ continue;
+
+ if (link_conf->beacon_int < IWL_MVM_MIN_BEACON_INTERVAL_TU) {
+ IWL_ERR(mvm,
+ "Beacon interval %d for AP %pM is too small\n",
+ link_conf->beacon_int, link_sta->addr);
+ return false;
+ }
+
+ link_conf->he_support = link_sta->he_cap.has_he;
+ }
+
+ return true;
+}
+
+static void iwl_mvm_vif_set_he_support(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ bool is_sta)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ unsigned int i;
+
+ for_each_set_bit(i, (unsigned long *)&sta->valid_links,
+ IEEE80211_MLD_MAX_NUM_LINKS) {
+ struct ieee80211_link_sta *link_sta =
+ rcu_dereference_protected(sta->link[i], 1);
+ struct ieee80211_bss_conf *link_conf =
+ rcu_dereference_protected(vif->link_conf[i], 1);
+
+ if (!link_conf || !link_sta)
+ continue;
+
+ link_conf->he_support = link_sta->he_cap.has_he;
+
+ if (is_sta) {
+ mvmvif->link[i]->he_ru_2mhz_block = false;
+ if (link_sta->he_cap.has_he)
+ iwl_mvm_check_he_obss_narrow_bw_ru(hw, vif);
+ }
+ }
+}
+
+static int
+iwl_mvm_sta_state_notexist_to_none(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct iwl_mvm_sta_state_ops *callbacks)
+{
+ unsigned int i;
+ int ret;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ if (vif->type == NL80211_IFTYPE_STATION &&
+ !iwl_mvm_vif_conf_from_sta(mvm, vif, sta))
+ return -EINVAL;
+
+ if (sta->tdls &&
+ (vif->p2p ||
+ iwl_mvm_tdls_sta_count(mvm, NULL) == IWL_MVM_TDLS_STA_COUNT ||
+ iwl_mvm_phy_ctx_count(mvm) > 1)) {
+ IWL_DEBUG_MAC80211(mvm, "refusing TDLS sta\n");
+ return -EBUSY;
+ }
+
+ ret = callbacks->add_sta(mvm, vif, sta);
+ if (sta->tdls && ret == 0) {
+ iwl_mvm_recalc_tdls_state(mvm, vif, true);
+ iwl_mvm_tdls_check_trigger(mvm, vif, sta->addr,
+ NL80211_TDLS_SETUP);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(sta->link); i++) {
+ struct ieee80211_link_sta *link_sta;
+
+ link_sta = link_sta_dereference_protected(sta, i);
+ if (!link_sta)
+ continue;
+
+ link_sta->agg.max_rc_amsdu_len = 1;
+ }
+ ieee80211_sta_recalc_aggregates(sta);
+
+ return 0;
+}
+
+static int
+iwl_mvm_sta_state_auth_to_assoc(struct ieee80211_hw *hw,
+ struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct iwl_mvm_sta_state_ops *callbacks)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
+ unsigned int i;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ if (vif->type == NL80211_IFTYPE_AP) {
+ iwl_mvm_vif_set_he_support(hw, vif, sta, false);
+ mvmvif->ap_assoc_sta_count++;
+ callbacks->mac_ctxt_changed(mvm, vif, false);
+
+ /* since the below is not for MLD API, it's ok to use
+ * the default bss_conf
+ */
+ if (!mvm->mld_api_is_used &&
+ ((vif->bss_conf.he_support &&
+ !iwlwifi_mod_params.disable_11ax) ||
+ (vif->bss_conf.eht_support &&
+ !iwlwifi_mod_params.disable_11be)))
+ iwl_mvm_cfg_he_sta(mvm, vif, mvm_sta->deflink.sta_id);
+ } else if (vif->type == NL80211_IFTYPE_STATION) {
+ iwl_mvm_vif_set_he_support(hw, vif, sta, true);
+
+ callbacks->mac_ctxt_changed(mvm, vif, false);
+
+ if (!mvm->mld_api_is_used)
+ goto out;
+
+ for_each_set_bit(i, (unsigned long *)&sta->valid_links,
+ IEEE80211_MLD_MAX_NUM_LINKS) {
+ struct ieee80211_bss_conf *link_conf =
+ rcu_dereference_protected(vif->link_conf[i], 1);
+
+ if (WARN_ON(!link_conf))
+ return -EINVAL;
+
+ iwl_mvm_link_changed(mvm, vif, link_conf,
+ LINK_CONTEXT_MODIFY_ALL &
+ ~LINK_CONTEXT_MODIFY_ACTIVE,
+ true);
+ }
+ }
+
+out:
+ iwl_mvm_rs_rate_init_all_links(mvm, mvmvif, sta, false);
+
+ return callbacks->update_sta(mvm, vif, sta);
+}
+
+static int
+iwl_mvm_sta_state_assoc_to_authorized(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct iwl_mvm_sta_state_ops *callbacks)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
+
+ lockdep_assert_held(&mvm->mutex);
+
+ /* we don't support TDLS during DCM */
+ if (iwl_mvm_phy_ctx_count(mvm) > 1)
+ iwl_mvm_teardown_tdls_peers(mvm);
+
+ if (sta->tdls) {
+ iwl_mvm_tdls_check_trigger(mvm, vif, sta->addr,
+ NL80211_TDLS_ENABLE_LINK);
+ } else {
+ /* enable beacon filtering */
+ WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
+
+ mvmvif->authorized = 1;
+
+ callbacks->mac_ctxt_changed(mvm, vif, false);
+ iwl_mvm_mei_host_associated(mvm, vif, mvm_sta);
+ }
+
+ iwl_mvm_rs_rate_init_all_links(mvm, mvmvif, sta, true);
+
+ return 0;
+}
+
+static int
+iwl_mvm_sta_state_authorized_to_assoc(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct iwl_mvm_sta_state_ops *callbacks)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ int ret;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ /* once we move into assoc state, need to update rate scale to
+ * disable using wide bandwidth
+ */
+ iwl_mvm_rs_rate_init_all_links(mvm, mvmvif, sta, false);
+
+ if (!sta->tdls) {
+ /* Set this but don't call iwl_mvm_mac_ctxt_changed()
+ * yet to avoid sending high prio again for a little
+ * time.
+ */
+ mvmvif->authorized = 0;
+
+ /* disable beacon filtering */
+ ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
+ WARN_ON(ret &&
+ !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
+ &mvm->status));
+ }
+
+ return 0;
+}
+
/* Common part for MLD and non-MLD modes */
int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@@ -3508,15 +3762,12 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
+ unsigned int link_id;
int ret;

IWL_DEBUG_MAC80211(mvm, "station %pM state change %d->%d\n",
sta->addr, old_state, new_state);

- /* this would be a mac80211 bug ... but don't crash */
- if (WARN_ON_ONCE(!mvmvif->deflink.phy_ctxt))
- return test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status) ? 0 : -EINVAL;
-
/*
* If we are in a STA removal flow and in DQA mode:
*
@@ -3547,48 +3798,25 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
}

mutex_lock(&mvm->mutex);
+
+ /* this would be a mac80211 bug ... but don't crash */
+ for_each_mvm_vif_valid_link(mvmvif, link_id) {
+ if (WARN_ON_ONCE(!mvmvif->link[link_id]->phy_ctxt)) {
+ mutex_unlock(&mvm->mutex);
+ return test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
+ &mvm->status) ? 0 : -EINVAL;
+ }
+ }
+
/* track whether or not the station is associated */
mvm_sta->sta_state = new_state;

if (old_state == IEEE80211_STA_NOTEXIST &&
new_state == IEEE80211_STA_NONE) {
- /*
- * Firmware bug - it'll crash if the beacon interval is less
- * than 16. We can't avoid connecting at all, so refuse the
- * station state change, this will cause mac80211 to abandon
- * attempts to connect to this AP, and eventually wpa_s will
- * blocklist the AP...
- */
- if (vif->type == NL80211_IFTYPE_STATION &&
- vif->bss_conf.beacon_int < 16) {
- IWL_ERR(mvm,
- "AP %pM beacon interval is %d, refusing due to firmware bug!\n",
- sta->addr, vif->bss_conf.beacon_int);
- ret = -EINVAL;
+ ret = iwl_mvm_sta_state_notexist_to_none(mvm, vif, sta,
+ callbacks);
+ if (ret < 0)
goto out_unlock;
- }
-
- if (vif->type == NL80211_IFTYPE_STATION)
- vif->bss_conf.he_support = sta->deflink.he_cap.has_he;
-
- if (sta->tdls &&
- (vif->p2p ||
- iwl_mvm_tdls_sta_count(mvm, NULL) ==
- IWL_MVM_TDLS_STA_COUNT ||
- iwl_mvm_phy_ctx_count(mvm) > 1)) {
- IWL_DEBUG_MAC80211(mvm, "refusing TDLS sta\n");
- ret = -EBUSY;
- goto out_unlock;
- }
-
- ret = callbacks->add_sta(mvm, vif, sta);
- if (sta->tdls && ret == 0) {
- iwl_mvm_recalc_tdls_state(mvm, vif, true);
- iwl_mvm_tdls_check_trigger(mvm, vif, sta->addr,
- NL80211_TDLS_SETUP);
- }
-
- sta->deflink.agg.max_rc_amsdu_len = 1;
} else if (old_state == IEEE80211_STA_NONE &&
new_state == IEEE80211_STA_AUTH) {
/*
@@ -3600,84 +3828,16 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
ret = 0;
} else if (old_state == IEEE80211_STA_AUTH &&
new_state == IEEE80211_STA_ASSOC) {
- if (vif->type == NL80211_IFTYPE_AP) {
- vif->bss_conf.he_support = sta->deflink.he_cap.has_he;
- mvmvif->ap_assoc_sta_count++;
- callbacks->mac_ctxt_changed(mvm, vif, false);
- if (!mvm->mld_api_is_used &&
- ((vif->bss_conf.he_support &&
- !iwlwifi_mod_params.disable_11ax) ||
- (vif->bss_conf.eht_support &&
- !iwlwifi_mod_params.disable_11be)))
- iwl_mvm_cfg_he_sta(mvm, vif,
- mvm_sta->deflink.sta_id);
- } else if (vif->type == NL80211_IFTYPE_STATION) {
- vif->bss_conf.he_support = sta->deflink.he_cap.has_he;
-
- mvmvif->deflink.he_ru_2mhz_block = false;
- if (sta->deflink.he_cap.has_he)
- iwl_mvm_check_he_obss_narrow_bw_ru(hw, vif);
-
- callbacks->mac_ctxt_changed(mvm, vif, false);
-
- if (mvm->mld_api_is_used)
- iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
- LINK_CONTEXT_MODIFY_ALL &
- ~LINK_CONTEXT_MODIFY_ACTIVE,
- true);
- }
-
- iwl_mvm_rs_rate_init(mvm, sta,
- mvmvif->deflink.phy_ctxt->channel->band,
- false);
- ret = callbacks->update_sta(mvm, vif, sta);
+ ret = iwl_mvm_sta_state_auth_to_assoc(hw, mvm, vif, sta,
+ callbacks);
} else if (old_state == IEEE80211_STA_ASSOC &&
new_state == IEEE80211_STA_AUTHORIZED) {
- ret = 0;
-
- /* we don't support TDLS during DCM */
- if (iwl_mvm_phy_ctx_count(mvm) > 1)
- iwl_mvm_teardown_tdls_peers(mvm);
-
- if (sta->tdls) {
- iwl_mvm_tdls_check_trigger(mvm, vif, sta->addr,
- NL80211_TDLS_ENABLE_LINK);
- } else {
- /* enable beacon filtering */
- WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
-
- mvmvif->authorized = 1;
-
- callbacks->mac_ctxt_changed(mvm, vif, false);
- iwl_mvm_mei_host_associated(mvm, vif, mvm_sta);
- }
-
- iwl_mvm_rs_rate_init(mvm, sta,
- mvmvif->deflink.phy_ctxt->channel->band,
- true);
+ ret = iwl_mvm_sta_state_assoc_to_authorized(mvm, vif, sta,
+ callbacks);
} else if (old_state == IEEE80211_STA_AUTHORIZED &&
new_state == IEEE80211_STA_ASSOC) {
- /* once we move into assoc state, need to update rate scale to
- * disable using wide bandwidth
- */
- iwl_mvm_rs_rate_init(mvm, sta,
- mvmvif->deflink.phy_ctxt->channel->band,
- false);
- if (!sta->tdls) {
- /*
- * Set this but don't call iwl_mvm_mac_ctxt_changed()
- * yet to avoid sending high prio again for a little
- * time.
- */
- mvmvif->authorized = 0;
-
- /* disable beacon filtering */
- ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
- WARN_ON(ret &&
- !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
- &mvm->status));
- }
- ret = 0;
+ ret = iwl_mvm_sta_state_authorized_to_assoc(mvm, vif, sta,
+ callbacks);
} else if (old_state == IEEE80211_STA_ASSOC &&
new_state == IEEE80211_STA_AUTH) {
if (vif->type == NL80211_IFTYPE_AP) {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
index 3791f37afa78..7a01295949fa 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
@@ -50,18 +50,14 @@ static int iwl_mvm_mld_add_int_sta_to_fw(struct iwl_mvm *mvm,
*/
static int iwl_mvm_mld_rm_sta_from_fw(struct iwl_mvm *mvm, u32 sta_id)
{
- struct ieee80211_sta *sta;
struct iwl_mvm_remove_sta_cmd rm_sta_cmd = {
.sta_id = cpu_to_le32(sta_id),
};
int ret;

- sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
- lockdep_is_held(&mvm->mutex));
-
/* Note: internal stations are marked as error values */
- if (!sta) {
- IWL_ERR(mvm, "Invalid station id\n");
+ if (!rcu_access_pointer(mvm->fw_id_to_mac_id[sta_id])) {
+ IWL_ERR(mvm, "Invalid station id %d\n", sta_id);
return -EINVAL;
}

@@ -380,18 +376,20 @@ int iwl_mvm_mld_rm_aux_sta(struct iwl_mvm *mvm)

/* 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)
+ struct ieee80211_vif *vif,
+ struct ieee80211_link_sta *link_sta,
+ struct ieee80211_bss_conf *link_conf,
+ struct iwl_mvm_link_sta *mvm_link_sta)
{
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_mvm_vif *mvm_vif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm_vif_link_info *link_info =
+ mvm_vif->link[link_conf->link_id];
struct iwl_mvm_sta_cfg_cmd cmd = {
- .sta_id = cpu_to_le32(mvm_sta->deflink.sta_id),
+ .sta_id = cpu_to_le32(mvm_link_sta->sta_id),
.station_type = cpu_to_le32(mvm_sta->sta_type),
.mfp = cpu_to_le32(sta->mfp),
};
- /* FIXME: use proper link_id */
- unsigned int link_id = 0;
- struct iwl_mvm_vif_link_info *link_info = mvm_vif->link[link_id];
u32 agg_size = 0, mpdu_dens = 0;

/* when adding sta, link should exist in FW */
@@ -407,7 +405,7 @@ static int iwl_mvm_mld_cfg_sta(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
if (mvm_sta->sta_state >= IEEE80211_STA_ASSOC)
cmd.assoc_id = cpu_to_le32(sta->aid);

- switch (sta->deflink.rx_nss) {
+ switch (link_sta->rx_nss) {
case 1:
cmd.mimo = cpu_to_le32(0);
break;
@@ -433,7 +431,7 @@ static int iwl_mvm_mld_cfg_sta(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
break;
}

- mpdu_dens = iwl_mvm_get_sta_ampdu_dens(sta, &agg_size);
+ mpdu_dens = iwl_mvm_get_sta_ampdu_dens(link_sta, link_conf, &agg_size);
cmd.tx_ampdu_spacing = cpu_to_le32(mpdu_dens);
cmd.tx_ampdu_max_size = cpu_to_le32(agg_size);

@@ -443,17 +441,17 @@ static int iwl_mvm_mld_cfg_sta(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
cmd.uapsd_acs = cpu_to_le32(iwl_mvm_get_sta_uapsd_acs(sta));
}

- if (sta->deflink.he_cap.has_he) {
+ if (link_sta->he_cap.has_he) {
cmd.trig_rnd_alloc =
- cpu_to_le32(vif->bss_conf.uora_exists ? 1 : 0);
+ cpu_to_le32(link_conf->uora_exists ? 1 : 0);

/* PPE Thresholds */
- iwl_mvm_set_sta_pkt_ext(mvm, sta, &cmd.pkt_ext);
+ iwl_mvm_set_sta_pkt_ext(mvm, link_sta, &cmd.pkt_ext);

/* HTC flags */
- cmd.htc_flags = iwl_mvm_get_sta_htc_flags(sta);
+ cmd.htc_flags = iwl_mvm_get_sta_htc_flags(sta, link_sta);

- if (sta->deflink.he_cap.he_cap_elem.mac_cap_info[2] &
+ if (link_sta->he_cap.he_cap_elem.mac_cap_info[2] &
IEEE80211_HE_MAC_CAP2_ACK_EN)
cmd.ack_enabled = cpu_to_le32(1);
}
@@ -461,72 +459,243 @@ static int iwl_mvm_mld_cfg_sta(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
return iwl_mvm_mld_send_sta_cmd(mvm, &cmd);
}

-int iwl_mvm_mld_add_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+static void iwl_mvm_mld_sta_rm_all_sta_links(struct iwl_mvm *mvm,
+ struct iwl_mvm_sta *mvm_sta)
+{
+ unsigned int link_id;
+
+ for (link_id = 0; link_id < ARRAY_SIZE(mvm_sta->link); link_id++) {
+ struct iwl_mvm_link_sta *link =
+ rcu_dereference_protected(mvm_sta->link[link_id],
+ lockdep_is_held(&mvm->mutex));
+
+ if (!link)
+ continue;
+
+ RCU_INIT_POINTER(mvm->fw_id_to_mac_id[link->sta_id], NULL);
+ RCU_INIT_POINTER(mvm_sta->link[link_id], NULL);
+
+ if (link != &mvm_sta->deflink)
+ kfree_rcu(link, rcu_head);
+ }
+}
+
+/* allocate all the links of a sta, called when the station is first added */
+static int iwl_mvm_mld_alloc_sta_links(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
- int sta_id, ret = 0;
+ struct iwl_mvm_link_sta *link;
+ unsigned int link_id;
+ u32 sta_id;
+ int ret;

lockdep_assert_held(&mvm->mutex);

- if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
+ for (link_id = 0; link_id < ARRAY_SIZE(sta->link); link_id++) {
+ if (!rcu_access_pointer(sta->link[link_id]) ||
+ mvm_sta->link[link_id])
+ continue;
+
sta_id = iwl_mvm_find_free_sta_id(mvm,
ieee80211_vif_type_p2p(vif));
- else
- sta_id = mvm_sta->deflink.sta_id;

- if (sta_id == IWL_MVM_INVALID_STA)
- return -ENOSPC;
+ if (sta_id == IWL_MVM_INVALID_STA) {
+ ret = -ENOSPC;
+ goto err;
+ }

- spin_lock_init(&mvm_sta->lock);
+ if (rcu_access_pointer(sta->link[link_id]) == &sta->deflink) {
+ link = &mvm_sta->deflink;
+ } else {
+ link = kzalloc(sizeof(*link), GFP_KERNEL);
+ if (!link) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ }

- /* if this is a HW restart re-alloc existing queues */
- if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
- struct iwl_mvm_int_sta tmp_sta = {
- .sta_id = sta_id,
- .type = mvm_sta->sta_type,
- };
+ link->sta_id = sta_id;
+ rcu_assign_pointer(mvm_sta->link[link_id], link);
+ rcu_assign_pointer(mvm->fw_id_to_mac_id[link->sta_id], sta);
+ }

- /* First add an empty station since allocating
- * a queue requires a valid station
- */
+ return 0;
+
+err:
+ iwl_mvm_mld_sta_rm_all_sta_links(mvm, mvm_sta);
+ return ret;
+}
+
+static void iwl_mvm_mld_set_ap_sta_id(struct ieee80211_sta *sta,
+ struct iwl_mvm_vif_link_info *vif_link,
+ struct iwl_mvm_link_sta *sta_link)
+{
+ if (!sta->tdls) {
+ WARN_ON(vif_link->ap_sta_id != IWL_MVM_INVALID_STA);
+ vif_link->ap_sta_id = sta_link->sta_id;
+ } else {
+ WARN_ON(vif_link->ap_sta_id == IWL_MVM_INVALID_STA);
+ }
+}
+
+/* FIXME: consider waiting for mac80211 to add the STA instead of allocating
+ * queues here
+ */
+static int iwl_mvm_alloc_sta_after_restart(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct ieee80211_link_sta *link_sta;
+ unsigned int link_id;
+ struct iwl_mvm_int_sta tmp_sta = {
+ .type = mvm_sta->sta_type,
+ };
+ int sta_id, ret;
+
+ /* First add an empty station since allocating a queue requires
+ * a valid station. Since we need a link_id to allocate a station,
+ * pick up the first valid one.
+ */
+ for_each_sta_active_link(vif, sta, link_sta, link_id) {
+ struct iwl_mvm_vif_link_info *mvm_link;
+ struct ieee80211_bss_conf *link_conf =
+ link_conf_dereference_protected(vif, link_id);
+ struct iwl_mvm_link_sta *mvm_link_sta =
+ rcu_dereference_protected(mvm_sta->link[link_id],
+ lockdep_is_held(&mvm->mutex));
+
+ if (!link_conf)
+ continue;
+
+ mvm_link = mvmvif->link[link_conf->link_id];
+
+ if (!mvm_link || !mvm_link_sta)
+ continue;
+
+ sta_id = mvm_link_sta->sta_id;
+ tmp_sta.sta_id = sta_id;
ret = iwl_mvm_mld_add_int_sta_to_fw(mvm, &tmp_sta,
vif->bss_conf.bssid,
- mvmvif->id);
+ mvm_link->fw_link_id);
if (ret)
return ret;

+ rcu_assign_pointer(mvm->fw_id_to_mac_id[sta_id], sta);
iwl_mvm_realloc_queues_after_restart(mvm, sta);
- } else {
- ret = iwl_mvm_sta_init(mvm, vif, sta, sta_id,
- STATION_TYPE_PEER);
+
+ /* since we need only one station, no need to continue */
+ return 0;
}

- ret = iwl_mvm_mld_cfg_sta(mvm, sta, vif);
- if (ret)
- return ret;
+ /* no active link found */
+ return -EINVAL;
+}

- if (vif->type == NL80211_IFTYPE_STATION) {
- if (!sta->tdls) {
- WARN_ON(mvmvif->deflink.ap_sta_id != IWL_MVM_INVALID_STA);
- mvmvif->deflink.ap_sta_id = sta_id;
- } else {
- WARN_ON(mvmvif->deflink.ap_sta_id == IWL_MVM_INVALID_STA);
- }
+int iwl_mvm_mld_add_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct iwl_mvm_vif *mvm_vif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
+ unsigned long link_sta_added_to_fw = 0;
+ struct ieee80211_link_sta *link_sta;
+ int ret = 0;
+ unsigned int link_id;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
+ ret = iwl_mvm_mld_alloc_sta_links(mvm, vif, sta);
+ if (ret)
+ return ret;
}

- rcu_assign_pointer(mvm->fw_id_to_mac_id[sta_id], sta);
+ spin_lock_init(&mvm_sta->lock);
+
+ if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
+ ret = iwl_mvm_alloc_sta_after_restart(mvm, vif, sta);
+ else
+ ret = iwl_mvm_sta_init(mvm, vif, sta, IWL_MVM_INVALID_STA,
+ STATION_TYPE_PEER);
+ if (ret)
+ goto err;
+
+ /* at this stage sta link pointers are already allocated */
+ ret = iwl_mvm_mld_update_sta(mvm, vif, sta);
+
+ for_each_sta_active_link(vif, sta, link_sta, link_id) {
+ struct ieee80211_bss_conf *link_conf =
+ rcu_dereference_protected(vif->link_conf[link_id], 1);
+ struct iwl_mvm_link_sta *mvm_link_sta =
+ rcu_dereference_protected(mvm_sta->link[link_id],
+ lockdep_is_held(&mvm->mutex));
+
+ if (WARN_ON(!link_conf || !mvm_link_sta))
+ goto err;
+
+ ret = iwl_mvm_mld_cfg_sta(mvm, sta, vif, link_sta, link_conf,
+ mvm_link_sta);
+ if (ret)
+ goto err;
+
+ link_sta_added_to_fw |= BIT(link_id);
+
+ if (vif->type == NL80211_IFTYPE_STATION)
+ iwl_mvm_mld_set_ap_sta_id(sta, mvm_vif->link[link_id],
+ mvm_link_sta);
+ }

return 0;
+
+err:
+ /* remove all already allocated stations in FW */
+ for_each_set_bit(link_id, &link_sta_added_to_fw,
+ IEEE80211_MLD_MAX_NUM_LINKS) {
+ struct iwl_mvm_link_sta *mvm_link_sta =
+ rcu_dereference_protected(mvm_sta->link[link_id],
+ lockdep_is_held(&mvm->mutex));
+
+ iwl_mvm_mld_rm_sta_from_fw(mvm, mvm_link_sta->sta_id);
+ }
+
+ /* free all sta resources in the driver */
+ iwl_mvm_mld_sta_rm_all_sta_links(mvm, mvm_sta);
+ return ret;
}

int iwl_mvm_mld_update_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
+ struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
+ struct ieee80211_link_sta *link_sta;
+ unsigned int link_id;
+ int ret = 0;
+
lockdep_assert_held(&mvm->mutex);

- return iwl_mvm_mld_cfg_sta(mvm, sta, vif);
+ for_each_sta_active_link(vif, sta, link_sta, link_id) {
+ struct ieee80211_bss_conf *link_conf =
+ rcu_dereference_protected(vif->link_conf[link_id], 1);
+ struct iwl_mvm_link_sta *mvm_link_sta =
+ rcu_dereference_protected(mvm_sta->link[link_id],
+ lockdep_is_held(&mvm->mutex));
+
+ if (WARN_ON(!link_conf || !mvm_link_sta))
+ return -EINVAL;
+
+ ret = iwl_mvm_mld_cfg_sta(mvm, sta, vif, link_sta, link_conf,
+ mvm_link_sta);
+
+ if (ret) {
+ IWL_ERR(mvm, "Failed to update sta link %d\n", link_id);
+ break;
+ }
+ }
+
+ return ret;
}

static void iwl_mvm_mld_disable_sta_queues(struct iwl_mvm *mvm,
@@ -559,6 +728,8 @@ int iwl_mvm_mld_rm_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
+ struct ieee80211_link_sta *link_sta;
+ unsigned int link_id;
int ret;

lockdep_assert_held(&mvm->mutex);
@@ -566,20 +737,38 @@ int iwl_mvm_mld_rm_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
kfree(mvm_sta->dup_data);

/* flush its queues here since we are freeing mvm_sta */
- ret = iwl_mvm_flush_sta(mvm, mvm_sta, false);
- if (ret)
- return ret;
+ for_each_sta_active_link(vif, sta, link_sta, link_id) {
+ struct iwl_mvm_link_sta *mvm_link_sta =
+ rcu_dereference_protected(mvm_sta->link[link_id],
+ lockdep_is_held(&mvm->mutex));
+
+ if (WARN_ON(!mvm_link_sta))
+ return -EINVAL;
+
+ ret = iwl_mvm_flush_sta_tids(mvm, mvm_link_sta->sta_id,
+ 0xffff);
+ if (ret)
+ return ret;
+ }
+
ret = iwl_mvm_wait_sta_queues_empty(mvm, mvm_sta);
if (ret)
return ret;

iwl_mvm_mld_disable_sta_queues(mvm, vif, sta);

- if (iwl_mvm_sta_del(mvm, vif, sta, &ret))
- return ret;
+ for_each_sta_active_link(vif, sta, link_sta, link_id) {
+ struct iwl_mvm_link_sta *mvm_link_sta =
+ rcu_dereference_protected(mvm_sta->link[link_id],
+ lockdep_is_held(&mvm->mutex));
+
+ if (iwl_mvm_sta_del(mvm, vif, sta, mvm_link_sta, &ret))
+ return ret;
+
+ ret = iwl_mvm_mld_rm_sta_from_fw(mvm, mvm_link_sta->sta_id);
+ }

- ret = iwl_mvm_mld_rm_sta_from_fw(mvm, mvm_sta->deflink.sta_id);
- RCU_INIT_POINTER(mvm->fw_id_to_mac_id[mvm_sta->deflink.sta_id], NULL);
+ iwl_mvm_mld_sta_rm_all_sta_links(mvm, mvm_sta);

return ret;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 811647c8aa71..3a9ece67aff7 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -1606,10 +1606,14 @@ int iwl_mvm_flush_sta(struct iwl_mvm *mvm, void *sta, bool internal);
int iwl_mvm_flush_sta_tids(struct iwl_mvm *mvm, u32 sta_id, u16 tids);

/* Utils to extract sta related data */
-__le32 iwl_mvm_get_sta_htc_flags(struct ieee80211_sta *sta);
+__le32 iwl_mvm_get_sta_htc_flags(struct ieee80211_sta *sta,
+ struct ieee80211_link_sta *link_sta);
u8 iwl_mvm_get_sta_uapsd_acs(struct ieee80211_sta *sta);
-u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_sta *sta, u32 *_agg_size);
-int iwl_mvm_set_sta_pkt_ext(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
+u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_link_sta *link_sta,
+ struct ieee80211_bss_conf *link_conf,
+ u32 *_agg_size);
+int iwl_mvm_set_sta_pkt_ext(struct iwl_mvm *mvm,
+ struct ieee80211_link_sta *link_sta,
struct iwl_he_pkt_ext_v2 *pkt_ext);

void iwl_mvm_async_handlers_purge(struct iwl_mvm *mvm);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
index a33673c6ae7d..778c9237fe87 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
@@ -641,18 +641,30 @@ int rs_fw_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,

void iwl_mvm_rs_add_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta)
{
- struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->deflink.lq_sta.rs_fw;
+ unsigned int link_id;

IWL_DEBUG_RATE(mvm, "create station rate scale window\n");

- lq_sta->pers.drv = mvm;
- lq_sta->pers.sta_id = mvmsta->deflink.sta_id;
- lq_sta->pers.chains = 0;
- memset(lq_sta->pers.chain_signal, 0, sizeof(lq_sta->pers.chain_signal));
- lq_sta->pers.last_rssi = S8_MIN;
- lq_sta->last_rate_n_flags = 0;
+ for (link_id = 0; link_id < ARRAY_SIZE(mvmsta->link); link_id++) {
+ struct iwl_lq_sta_rs_fw *lq_sta;
+ struct iwl_mvm_link_sta *link =
+ rcu_dereference_protected(mvmsta->link[link_id],
+ lockdep_is_held(&mvm->mutex));
+ if (!link)
+ continue;
+
+ lq_sta = &link->lq_sta.rs_fw;
+
+ lq_sta->pers.drv = mvm;
+ lq_sta->pers.sta_id = link->sta_id;
+ lq_sta->pers.chains = 0;
+ memset(lq_sta->pers.chain_signal, 0,
+ sizeof(lq_sta->pers.chain_signal));
+ lq_sta->pers.last_rssi = S8_MIN;
+ lq_sta->last_rate_n_flags = 0;

#ifdef CONFIG_MAC80211_DEBUGFS
- lq_sta->pers.dbg_fixed_rate = 0;
+ lq_sta->pers.dbg_fixed_rate = 0;
#endif
+ }
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index 54ef749be488..eb57acaef96a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -51,26 +51,31 @@ int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm, enum nl80211_iftype iftype)
}

/* Calculate the ampdu density and max size */
-u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_sta *sta, u32 *_agg_size)
+u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_link_sta *link_sta,
+ struct ieee80211_bss_conf *link_conf,
+ u32 *_agg_size)
{
- struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
u32 agg_size = 0, mpdu_dens = 0;

- if (sta->deflink.ht_cap.ht_supported)
- mpdu_dens = sta->deflink.ht_cap.ampdu_density;
+ if (WARN_ON(!link_sta))
+ return 0;
+
+ if (link_sta->ht_cap.ht_supported)
+ mpdu_dens = link_sta->ht_cap.ampdu_density;

- if (mvm_sta->vif->bss_conf.chandef.chan->band == NL80211_BAND_6GHZ) {
- mpdu_dens = le16_get_bits(sta->deflink.he_6ghz_capa.capa,
+ if (link_conf->chandef.chan->band ==
+ NL80211_BAND_6GHZ) {
+ mpdu_dens = le16_get_bits(link_sta->he_6ghz_capa.capa,
IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START);
- agg_size = le16_get_bits(sta->deflink.he_6ghz_capa.capa,
+ agg_size = le16_get_bits(link_sta->he_6ghz_capa.capa,
IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP);
- } else if (sta->deflink.vht_cap.vht_supported) {
- agg_size = sta->deflink.vht_cap.cap &
+ } else if (link_sta->vht_cap.vht_supported) {
+ agg_size = link_sta->vht_cap.cap &
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
agg_size >>=
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
- } else if (sta->deflink.ht_cap.ht_supported) {
- agg_size = sta->deflink.ht_cap.ampdu_factor;
+ } else if (link_sta->ht_cap.ht_supported) {
+ agg_size = link_sta->ht_cap.ampdu_factor;
}

/* D6.0 10.12.2 A-MPDU length limit rules
@@ -81,10 +86,10 @@ u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_sta *sta, u32 *_agg_size)
* Maximum AMPDU Length Exponent Extension field in its HE
* Capabilities element
*/
- if (sta->deflink.he_cap.has_he)
+ if (link_sta->he_cap.has_he)
agg_size +=
- u8_get_bits(sta->deflink.he_cap.he_cap_elem.mac_cap_info[3],
- IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK);
+ u8_get_bits(link_sta->he_cap.he_cap_elem.mac_cap_info[3],
+ IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK);

/* Limit to max A-MPDU supported by FW */
if (agg_size > (STA_FLG_MAX_AGG_SIZE_4M >> STA_FLG_MAX_AGG_SIZE_SHIFT))
@@ -200,7 +205,9 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
cpu_to_le32(STA_FLG_MAX_AGG_SIZE_MSK |
STA_FLG_AGG_MPDU_DENS_MSK);

- mpdu_dens = iwl_mvm_get_sta_ampdu_dens(sta, &agg_size);
+ mpdu_dens = iwl_mvm_get_sta_ampdu_dens(&sta->deflink,
+ &mvm_sta->vif->bss_conf,
+ &agg_size);
add_sta_cmd.station_flags |=
cpu_to_le32(agg_size << STA_FLG_MAX_AGG_SIZE_SHIFT);
add_sta_cmd.station_flags |=
@@ -784,19 +791,35 @@ static int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 sta_id,

static int iwl_mvm_get_queue_size(struct ieee80211_sta *sta)
{
+ int max_size = IWL_DEFAULT_QUEUE_SIZE;
+ unsigned int link_id;
+
/* this queue isn't used for traffic (cab_queue) */
if (!sta)
return IWL_MGMT_QUEUE_SIZE;

- /* support for 1k ba size */
- if (sta->deflink.eht_cap.has_eht)
- return IWL_DEFAULT_QUEUE_SIZE_EHT;
+ rcu_read_lock();

- /* support for 256 ba size */
- if (sta->deflink.he_cap.has_he)
- return IWL_DEFAULT_QUEUE_SIZE_HE;
+ for (link_id = 0; link_id < ARRAY_SIZE(sta->link); link_id++) {
+ struct ieee80211_link_sta *link =
+ rcu_dereference(sta->link[link_id]);

- return IWL_DEFAULT_QUEUE_SIZE;
+ if (!link)
+ continue;
+
+ /* support for 1k ba size */
+ if (link->eht_cap.has_eht &&
+ max_size < IWL_DEFAULT_QUEUE_SIZE_EHT)
+ max_size = IWL_DEFAULT_QUEUE_SIZE_EHT;
+
+ /* support for 256 ba size */
+ if (link->he_cap.has_he &&
+ max_size < IWL_DEFAULT_QUEUE_SIZE_HE)
+ max_size = IWL_DEFAULT_QUEUE_SIZE_HE;
+ }
+
+ rcu_read_unlock();
+ return max_size;
}

int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm,
@@ -804,6 +827,7 @@ int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm,
u8 sta_id, u8 tid, unsigned int timeout)
{
int queue, size;
+ u32 sta_mask = 0;

if (tid == IWL_MAX_TID_COUNT) {
tid = IWL_MGMT_TID;
@@ -819,22 +843,45 @@ int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm,
/* size needs to be power of 2 values for calculating read/write pointers */
size = rounddown_pow_of_two(size);

+ if (sta) {
+ struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+ unsigned int link_id;
+
+ for (link_id = 0;
+ link_id < ARRAY_SIZE(mvmsta->link);
+ link_id++) {
+ struct iwl_mvm_link_sta *link =
+ rcu_dereference_protected(mvmsta->link[link_id],
+ lockdep_is_held(&mvm->mutex));
+
+ if (!link)
+ continue;
+
+ sta_mask |= BIT(link->sta_id);
+ }
+ } else {
+ sta_mask |= BIT(sta_id);
+ }
+
+ if (!sta_mask)
+ return -EINVAL;
+
do {
- queue = iwl_trans_txq_alloc(mvm->trans, 0, BIT(sta_id),
+ queue = iwl_trans_txq_alloc(mvm->trans, 0, sta_mask,
tid, size, timeout);

if (queue < 0)
IWL_DEBUG_TX_QUEUES(mvm,
- "Failed allocating TXQ of size %d for sta %d tid %d, ret: %d\n",
- size, sta_id, tid, queue);
+ "Failed allocating TXQ of size %d for sta mask %x tid %d, ret: %d\n",
+ size, sta_mask, tid, queue);
size /= 2;
} while (queue < 0 && size >= 16);

if (queue < 0)
return queue;

- IWL_DEBUG_TX_QUEUES(mvm, "Enabling TXQ #%d for sta %d tid %d\n",
- queue, sta_id, tid);
+ IWL_DEBUG_TX_QUEUES(mvm, "Enabling TXQ #%d for sta mask 0x%x tid %d\n",
+ queue, sta_mask, tid);

return queue;
}
@@ -1657,16 +1704,28 @@ int iwl_mvm_sta_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif,

lockdep_assert_held(&mvm->mutex);

- mvm_sta->deflink.sta_id = sta_id;
- rcu_assign_pointer(mvm_sta->link[0], &mvm_sta->deflink);
-
mvm_sta->mac_id_n_color = FW_CMD_ID_AND_COLOR(mvmvif->id,
mvmvif->color);
mvm_sta->vif = vif;
- if (!mvm->trans->trans_cfg->gen2)
- mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
- else
- mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF;
+
+ /* for MLD sta_id(s) should be allocated for each link before calling
+ * this function
+ */
+ if (!mvm->mld_api_is_used) {
+ if (WARN_ON(sta_id == IWL_MVM_INVALID_STA))
+ return -EINVAL;
+
+ mvm_sta->deflink.sta_id = sta_id;
+ rcu_assign_pointer(mvm_sta->link[0], &mvm_sta->deflink);
+
+ if (!mvm->trans->trans_cfg->gen2)
+ mvm_sta->max_agg_bufsize =
+ LINK_QUAL_AGG_FRAME_LIMIT_DEF;
+ else
+ mvm_sta->max_agg_bufsize =
+ LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF;
+ }
+
mvm_sta->tt_tx_protection = false;
mvm_sta->sta_type = sta_type;

@@ -1926,11 +1985,12 @@ int iwl_mvm_wait_sta_queues_empty(struct iwl_mvm *mvm,
* with error or success
*/
bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta, int *ret)
+ struct ieee80211_sta *sta,
+ struct iwl_mvm_link_sta *mvm_link_sta, int *ret)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
- u8 sta_id = mvm_sta->deflink.sta_id;
+ u8 sta_id = mvm_link_sta->sta_id;

lockdep_assert_held(&mvm->mutex);

@@ -1956,8 +2016,7 @@ bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
*status = IWL_MVM_QUEUE_FREE;
}

- if (vif->type == NL80211_IFTYPE_STATION &&
- mvmvif->deflink.ap_sta_id == sta_id) {
+ if (vif->type == NL80211_IFTYPE_STATION) {
/* if associated - we can't remove the AP STA now */
if (vif->cfg.assoc)
return true;
@@ -2023,7 +2082,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,

iwl_mvm_disable_sta_queues(mvm, vif, sta);

- if (iwl_mvm_sta_del(mvm, vif, sta, &ret))
+ if (iwl_mvm_sta_del(mvm, vif, sta, &mvm_sta->deflink, &ret))
return ret;

ret = iwl_mvm_rm_sta_common(mvm, mvm_sta->deflink.sta_id);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index 7148263dddf8..6d4db666368b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -490,7 +490,8 @@ void iwl_mvm_realloc_queues_after_restart(struct iwl_mvm *mvm,
int iwl_mvm_wait_sta_queues_empty(struct iwl_mvm *mvm,
struct iwl_mvm_sta *mvm_sta);
bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta, int *ret);
+ struct ieee80211_sta *sta,
+ struct iwl_mvm_link_sta *mvm_link_sta, int *ret);
int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
--
2.38.1

2023-03-28 08:09:21

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 31/31] wifi: iwlwifi: mvm: implement link change ops

From: Johannes Berg <[email protected]>

Implement the link change ops for links and stations.
Note that the stations one is empty for now as we only
have support for a single link so far, and then the
stations are created with the first link as deflink by
mac80211, so right now we don't really need anything.

Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/link.c | 43 ++++++
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 12 +-
.../wireless/intel/iwlwifi/mvm/mld-mac80211.c | 145 ++++++++++++++++--
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 2 +
4 files changed, 187 insertions(+), 15 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/link.c b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
index 7a70b6ee65ac..0cd40672fade 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/link.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
@@ -3,6 +3,7 @@
* Copyright (C) 2022 - 2023 Intel Corporation
*/
#include "mvm.h"
+#include "time-event.h"

static u32 iwl_mvm_get_free_fw_link_id(struct iwl_mvm *mvm,
struct iwl_mvm_vif *mvm_vif)
@@ -108,6 +109,28 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
mvmvif->fw_active_links_num >= IWL_MVM_FW_MAX_ACTIVE_LINKS_NUM)
return -EINVAL;

+ if (changes & LINK_CONTEXT_MODIFY_ACTIVE) {
+ /* When activating a link, phy context should be valid;
+ * when deactivating a link, it also should be valid since
+ * the link was active before. So, do nothing in this case.
+ * Since a link is added first with FW_CTXT_INVALID, then we
+ * can get here in case it's removed before it was activated.
+ */
+ if (!link_info->phy_ctxt)
+ return 0;
+
+ /* Catch early if driver tries to activate or deactivate a link
+ * twice.
+ */
+ WARN_ON_ONCE(active == link_info->active);
+
+ /* When deactivating a link session protection should
+ * be stopped
+ */
+ if (!active && vif->type == NL80211_IFTYPE_STATION)
+ iwl_mvm_stop_session_protection(mvm, vif);
+ }
+
cmd.link_id = cpu_to_le32(link_info->fw_link_id);

/* The phy_id, link address and listen_lmac can be modified only until
@@ -248,3 +271,23 @@ int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,

return ret;
}
+
+/* link should be deactivated before removal, so in most cases we need to
+ * perform these two operations together
+ */
+int iwl_mvm_disable_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf)
+{
+ int ret;
+
+ ret = iwl_mvm_link_changed(mvm, vif, link_conf,
+ LINK_CONTEXT_MODIFY_ACTIVE, false);
+ if (ret)
+ return ret;
+
+ ret = iwl_mvm_remove_link(mvm, vif, link_conf);
+ if (ret)
+ return ret;
+
+ return ret;
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 9e825e3cf630..c60aff0df801 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -983,6 +983,7 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
{
struct iwl_mvm *mvm = data;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_probe_resp_data *probe_data;
unsigned int link_id;

mvmvif->uploaded = false;
@@ -993,13 +994,19 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,

memset(&mvmvif->bf_data, 0, sizeof(mvmvif->bf_data));

+ mvmvif->fw_active_links_num = 0;
for_each_mvm_vif_valid_link(mvmvif, link_id) {
mvmvif->link[link_id]->ap_sta_id = IWL_MVM_INVALID_STA;
mvmvif->link[link_id]->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
mvmvif->link[link_id]->phy_ctxt = NULL;
- memset(&mvmvif->link[link_id]->probe_resp_data, 0,
- sizeof(mvmvif->link[link_id]->probe_resp_data));
+ mvmvif->link[link_id]->active = 0;
}
+
+ probe_data = rcu_dereference_protected(mvmvif->deflink.probe_resp_data,
+ lockdep_is_held(&mvm->mutex));
+ if (probe_data)
+ kfree_rcu(probe_data, rcu_head);
+ RCU_INIT_POINTER(mvmvif->deflink.probe_resp_data, NULL);
}

static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
@@ -1455,7 +1462,6 @@ static bool iwl_mvm_mac_add_interface_common(struct iwl_mvm *mvm,
lockdep_assert_held(&mvm->mutex);

mvmvif->mvm = mvm;
- RCU_INIT_POINTER(mvmvif->deflink.probe_resp_data, NULL);

/* the first link always points to the default one */
mvmvif->link[0] = &mvmvif->deflink;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index 0c233d151231..7463cb8a271a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -14,7 +14,6 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
mutex_lock(&mvm->mutex);

mvmvif->mvm = mvm;
- RCU_INIT_POINTER(mvmvif->deflink.probe_resp_data, NULL);

/* Not much to do here. The stack will not allow interface
* types or combinations that we didn't advertise, so we
@@ -35,8 +34,10 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,

mvmvif->features |= hw->netdev_features;

- /* the first link always points to the default one */
+ /* reset deflink MLO parameters */
mvmvif->deflink.fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
+ mvmvif->deflink.active = 0;
+ /* the first link always points to the default one */
mvmvif->link[0] = &mvmvif->deflink;

ret = iwl_mvm_mld_mac_ctxt_add(mvm, vif);
@@ -119,10 +120,7 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
goto out_unlock;

out_remove_link:
- /* Link needs to be deactivated before removal */
- iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
- LINK_CONTEXT_MODIFY_ACTIVE, false);
- iwl_mvm_remove_link(mvm, vif, &vif->bss_conf);
+ iwl_mvm_disable_link(mvm, vif, &vif->bss_conf);
out_unref_phy:
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
out_free_bf:
@@ -198,14 +196,11 @@ static void iwl_mvm_mld_mac_remove_interface(struct ieee80211_hw *hw,

/* P2P device uses only one link */
iwl_mvm_mld_rm_bcast_sta(mvm, vif, &vif->bss_conf);
- /* Link needs to be deactivated before removal */
- iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
- LINK_CONTEXT_MODIFY_ACTIVE, false);
- iwl_mvm_remove_link(mvm, vif, &vif->bss_conf);
+ iwl_mvm_disable_link(mvm, vif, &vif->bss_conf);
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
mvmvif->deflink.phy_ctxt = NULL;
} else {
- iwl_mvm_remove_link(mvm, vif, &vif->bss_conf);
+ iwl_mvm_disable_link(mvm, vif, &vif->bss_conf);
}

iwl_mvm_mld_mac_ctxt_remove(mvm, vif);
@@ -359,7 +354,10 @@ static int iwl_mvm_mld_start_ap_ibss(struct ieee80211_hw *hw,
if (ret)
goto out_unlock;

- ret = iwl_mvm_link_changed(mvm, vif, link_conf, LINK_CONTEXT_MODIFY_ALL,
+ /* the link should be already activated when assigning chan context */
+ ret = iwl_mvm_link_changed(mvm, vif, link_conf,
+ LINK_CONTEXT_MODIFY_ALL &
+ ~LINK_CONTEXT_MODIFY_ACTIVE,
true);
if (ret)
goto out_unlock;
@@ -839,6 +837,126 @@ static int iwl_mvm_mld_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,

return iwl_mvm_roc_common(hw, vif, channel, duration, type, &ops);
}
+
+static int
+iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ u16 old_links, u16 new_links,
+ struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS])
+{
+ struct iwl_mvm_vif_link_info *new_link[IEEE80211_MLD_MAX_NUM_LINKS] = {};
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ u16 removed = old_links & ~new_links;
+ u16 added = new_links & ~old_links;
+ int err, i;
+
+ if (hweight16(new_links) > 2) {
+ return -EOPNOTSUPP;
+ } else if (hweight16(new_links) > 1) {
+ unsigned int n_active = 0;
+
+ for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
+ struct ieee80211_bss_conf *link_conf;
+
+ link_conf = link_conf_dereference_protected(vif, i);
+ if (link_conf &&
+ rcu_access_pointer(link_conf->chanctx_conf))
+ n_active++;
+ }
+
+ if (n_active > 1)
+ return -EOPNOTSUPP;
+ }
+
+ for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
+ int r;
+
+ if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
+ break;
+
+ if (!(added & BIT(i)))
+ continue;
+ new_link[i] = kzalloc(sizeof(*new_link[i]), GFP_KERNEL);
+ if (!new_link[i]) {
+ err = -ENOMEM;
+ goto free;
+ }
+
+ new_link[i]->bcast_sta.sta_id = IWL_MVM_INVALID_STA;
+ new_link[i]->mcast_sta.sta_id = IWL_MVM_INVALID_STA;
+ new_link[i]->ap_sta_id = IWL_MVM_INVALID_STA;
+ new_link[i]->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
+
+ for (r = 0; r < NUM_IWL_MVM_SMPS_REQ; r++)
+ new_link[i]->smps_requests[r] =
+ IEEE80211_SMPS_AUTOMATIC;
+ }
+
+ mutex_lock(&mvm->mutex);
+
+ if (old_links == 0) {
+ err = iwl_mvm_disable_link(mvm, vif, &vif->bss_conf);
+ if (err)
+ goto out_err;
+ mvmvif->link[0] = NULL;
+ }
+
+ for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
+ if (removed & BIT(i)) {
+ struct ieee80211_bss_conf *link_conf = old[i];
+
+ err = iwl_mvm_disable_link(mvm, vif, link_conf);
+ if (err)
+ goto out_err;
+ kfree(mvmvif->link[i]);
+ mvmvif->link[i] = NULL;
+ }
+
+ if (added & BIT(i)) {
+ struct ieee80211_bss_conf *link_conf;
+
+ /* FIXME: allow use of sdata_dereference()? */
+ link_conf = rcu_dereference_protected(vif->link_conf[i],
+ 1);
+ if (WARN_ON(!link_conf))
+ continue;
+
+ if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART,
+ &mvm->status))
+ mvmvif->link[i] = new_link[i];
+ new_link[i] = NULL;
+ err = iwl_mvm_add_link(mvm, vif, link_conf);
+ if (err)
+ goto out_err;
+ }
+ }
+
+ err = 0;
+ if (new_links == 0) {
+ mvmvif->link[0] = &mvmvif->deflink;
+ err = iwl_mvm_add_link(mvm, vif, &vif->bss_conf);
+ }
+
+out_err:
+ /* we really don't have a good way to roll back here ... */
+ mutex_unlock(&mvm->mutex);
+
+free:
+ for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++)
+ kfree(new_link[i]);
+ return err;
+}
+
+static int
+iwl_mvm_mld_change_sta_links(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ u16 old_links, u16 new_links)
+{
+ return 0;
+}
+
const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
.tx = iwl_mvm_mac_tx,
.wake_tx_queue = iwl_mvm_mac_wake_tx_queue,
@@ -928,4 +1046,7 @@ const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
.sta_add_debugfs = iwl_mvm_sta_add_debugfs,
#endif
.set_hw_timestamp = iwl_mvm_set_hw_timestamp,
+
+ .change_vif_links = iwl_mvm_mld_change_vif_links,
+ .change_sta_links = iwl_mvm_mld_change_sta_links,
};
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 3a9ece67aff7..dfe1aff10548 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -1824,6 +1824,8 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
u32 changes, bool active);
int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf);
+int iwl_mvm_disable_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf);

/* AP and IBSS */
bool iwl_mvm_start_ap_ibss_common(struct ieee80211_hw *hw,
--
2.38.1