summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/intel/iwlwifi/mvm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/coex.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/constants.h5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/d3.c179
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c66
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/link.c15
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c25
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c63
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c89
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c30
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h21
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/offloading.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c13
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rx.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/scan.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.c57
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tdls.c14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tx.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/utils.c6
24 files changed, 420 insertions, 210 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
index b607961970e9..36726ea4b822 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
@@ -689,7 +689,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->deflink.ap_sta_id == IWL_MVM_INVALID_STA)
+ if (mvmvif->deflink.ap_sta_id == IWL_INVALID_STA)
return;
/* No BT - reports should be disabled */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
index ddf484027d4f..776600ddaea6 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
@@ -17,7 +17,9 @@
#define IWL_MVM_TRIGGER_LINK_SEL_TIME_SEC 30
#define IWL_MVM_TPT_COUNT_WINDOW_SEC 5
#define IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS 5
-#define IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH 11
+#define IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH 15
+#define IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_BSS_PARAM_CHANGED 11
+#define IWL_MVM_LOW_RSSI_MLO_SCAN_THRESH -72
#define IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT (100 * USEC_PER_MSEC)
#define IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT (100 * USEC_PER_MSEC)
@@ -57,7 +59,6 @@
#define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0
#define IWL_MVM_RS_80_20_FAR_RANGE_TWEAK 1
#define IWL_MVM_TOF_IS_RESPONDER 0
-#define IWL_MVM_HW_CSUM_DISABLE 0
#define IWL_MVM_ADWELL_ENABLE 1
#define IWL_MVM_ADWELL_MAX_BUDGET 0
#define IWL_MVM_TCM_LOAD_MEDIUM_THRESH 10 /* percentage */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
index 244ca8cab9d1..f85c01e04ebf 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
@@ -922,7 +922,7 @@ static int iwl_mvm_switch_to_d3(struct iwl_mvm *mvm)
static int
iwl_mvm_get_wowlan_config(struct iwl_mvm *mvm,
struct cfg80211_wowlan *wowlan,
- struct iwl_wowlan_config_cmd *wowlan_config_cmd,
+ struct iwl_wowlan_config_cmd_v6 *wowlan_config_cmd,
struct ieee80211_vif *vif, struct iwl_mvm_vif *mvmvif,
struct ieee80211_sta *ap_sta)
{
@@ -948,7 +948,8 @@ iwl_mvm_get_wowlan_config(struct iwl_mvm *mvm,
wowlan_config_cmd->non_qos_seq = cpu_to_le16(ret);
}
- iwl_mvm_set_wowlan_qos_seq(mvm_ap_sta, wowlan_config_cmd);
+ if (iwl_fw_lookup_cmd_ver(mvm->fw, WOWLAN_CONFIGURATION, 0) < 7)
+ iwl_mvm_set_wowlan_qos_seq(mvm_ap_sta, wowlan_config_cmd);
if (wowlan->disconnect)
wowlan_config_cmd->wakeup_filter |=
@@ -1122,7 +1123,7 @@ static int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
static int
iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
struct cfg80211_wowlan *wowlan,
- struct iwl_wowlan_config_cmd *wowlan_config_cmd,
+ struct iwl_wowlan_config_cmd_v6 *wowlan_config_cmd_v6,
struct ieee80211_vif *vif, struct iwl_mvm_vif *mvmvif,
struct iwl_mvm_vif_link_info *mvm_link,
struct ieee80211_sta *ap_sta)
@@ -1131,7 +1132,7 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
bool unified_image = fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);
- mvm->offload_tid = wowlan_config_cmd->offloading_tid;
+ mvm->offload_tid = wowlan_config_cmd_v6->offloading_tid;
if (!unified_image) {
ret = iwl_mvm_switch_to_d3(mvm);
@@ -1147,9 +1148,26 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
if (ret)
return ret;
- ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, 0,
- sizeof(*wowlan_config_cmd),
- wowlan_config_cmd);
+ if (iwl_fw_lookup_cmd_ver(mvm->fw, WOWLAN_CONFIGURATION, 0) > 6) {
+ struct iwl_wowlan_config_cmd wowlan_config_cmd = {
+ .wakeup_filter = wowlan_config_cmd_v6->wakeup_filter,
+ .wowlan_ba_teardown_tids =
+ wowlan_config_cmd_v6->wowlan_ba_teardown_tids,
+ .is_11n_connection =
+ wowlan_config_cmd_v6->is_11n_connection,
+ .offloading_tid = wowlan_config_cmd_v6->offloading_tid,
+ .flags = wowlan_config_cmd_v6->flags,
+ .sta_id = wowlan_config_cmd_v6->sta_id,
+ };
+
+ ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, 0,
+ sizeof(wowlan_config_cmd),
+ &wowlan_config_cmd);
+ } else {
+ ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, 0,
+ sizeof(*wowlan_config_cmd_v6),
+ wowlan_config_cmd_v6);
+ }
if (ret)
return ret;
@@ -1288,7 +1306,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
goto out_noreset;
}
- if (mvm_link->ap_sta_id == IWL_MVM_INVALID_STA) {
+ if (mvm_link->ap_sta_id == IWL_INVALID_STA) {
/* if we're not associated, this must be netdetect */
if (!wowlan->nd_config) {
ret = 1;
@@ -1302,7 +1320,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
mvm->net_detect = true;
} else {
- struct iwl_wowlan_config_cmd wowlan_config_cmd = {
+ struct iwl_wowlan_config_cmd_v6 wowlan_config_cmd = {
.offloading_tid = 0,
};
@@ -1425,6 +1443,7 @@ struct iwl_wowlan_status_data {
u16 non_qos_seq_ctr;
u16 qos_seq_ctr[8];
u8 tid_tear_down;
+ u8 tid_offloaded_tx;
struct {
/* including RX MIC key for TKIP */
@@ -2474,7 +2493,64 @@ static void iwl_mvm_convert_bigtk(struct iwl_wowlan_status_data *status,
static void iwl_mvm_parse_wowlan_info_notif(struct iwl_mvm *mvm,
struct iwl_wowlan_info_notif *data,
struct iwl_wowlan_status_data *status,
- u32 len, bool has_mlo_keys)
+ u32 len)
+{
+ u32 expected_len = sizeof(*data) +
+ data->num_mlo_link_keys * sizeof(status->mlo_keys[0]);
+
+ if (!data) {
+ IWL_ERR(mvm, "iwl_wowlan_info_notif data is NULL\n");
+ status = NULL;
+ return;
+ }
+
+ if (len < expected_len) {
+ IWL_ERR(mvm, "Invalid WoWLAN info notification!\n");
+ status = NULL;
+ return;
+ }
+
+ if (mvm->fast_resume)
+ return;
+
+ iwl_mvm_convert_key_counters_v5(status, &data->gtk[0].sc);
+ iwl_mvm_convert_gtk_v3(status, data->gtk);
+ iwl_mvm_convert_igtk(status, &data->igtk[0]);
+ iwl_mvm_convert_bigtk(status, data->bigtk);
+ status->replay_ctr = le64_to_cpu(data->replay_ctr);
+ status->pattern_number = le16_to_cpu(data->pattern_number);
+ status->tid_offloaded_tx = data->tid_offloaded_tx;
+ if (IWL_FW_CHECK(mvm,
+ data->tid_offloaded_tx >=
+ ARRAY_SIZE(status->qos_seq_ctr),
+ "tid_offloaded_tx is out of bound %d\n",
+ data->tid_offloaded_tx))
+ data->tid_offloaded_tx = 0;
+ status->qos_seq_ctr[data->tid_offloaded_tx] =
+ le16_to_cpu(data->qos_seq_ctr);
+ status->wakeup_reasons = le32_to_cpu(data->wakeup_reasons);
+ status->num_of_gtk_rekeys =
+ le32_to_cpu(data->num_of_gtk_rekeys);
+ status->received_beacons = le32_to_cpu(data->received_beacons);
+ status->tid_tear_down = data->tid_tear_down;
+
+ if (data->num_mlo_link_keys) {
+ status->num_mlo_keys = data->num_mlo_link_keys;
+ if (IWL_FW_CHECK(mvm,
+ status->num_mlo_keys > WOWLAN_MAX_MLO_KEYS,
+ "Too many mlo keys: %d, max %d\n",
+ status->num_mlo_keys, WOWLAN_MAX_MLO_KEYS))
+ status->num_mlo_keys = WOWLAN_MAX_MLO_KEYS;
+ memcpy(status->mlo_keys, data->mlo_gtks,
+ status->num_mlo_keys * sizeof(status->mlo_keys[0]));
+ }
+}
+
+static void
+iwl_mvm_parse_wowlan_info_notif_v4(struct iwl_mvm *mvm,
+ struct iwl_wowlan_info_notif_v4 *data,
+ struct iwl_wowlan_status_data *status,
+ u32 len, bool has_mlo_keys)
{
u32 i;
u32 expected_len = sizeof(*data);
@@ -2746,6 +2822,10 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int link_id = vif->active_links ? __ffs(vif->active_links) : 0;
struct iwl_mvm_vif_link_info *mvm_link = mvmvif->link[link_id];
+ int wowlan_info_ver = iwl_fw_lookup_notif_ver(mvm->fw,
+ PROT_OFFLOAD_GROUP,
+ WOWLAN_INFO_NOTIFICATION,
+ IWL_FW_CMD_VER_UNKNOWN);
if (WARN_ON(!mvm_link))
goto out_unlock;
@@ -2760,11 +2840,14 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
if (!mvm_ap_sta)
goto out_unlock;
- for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
- u16 seq = status->qos_seq_ctr[i];
- /* firmware stores last-used value, we store next value */
- seq += 0x10;
- mvm_ap_sta->tid_data[i].seq_number = seq;
+ /* firmware stores last-used value, we store next value */
+ if (wowlan_info_ver >= 5) {
+ mvm_ap_sta->tid_data[status->tid_offloaded_tx].seq_number =
+ status->qos_seq_ctr[status->tid_offloaded_tx] + 0x10;
+ } else {
+ for (i = 0; i < IWL_MAX_TID_COUNT; i++)
+ mvm_ap_sta->tid_data[i].seq_number =
+ status->qos_seq_ctr[i] + 0x10;
}
if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
@@ -3026,34 +3109,15 @@ static void iwl_mvm_d3_disconnect_iter(void *data, u8 *mac,
ieee80211_resume_disconnect(vif);
}
-static bool iwl_mvm_rt_status(struct iwl_trans *trans, u32 base, u32 *err_id)
-{
- struct error_table_start {
- /* cf. struct iwl_error_event_table */
- u32 valid;
- __le32 err_id;
- } err_info;
-
- if (!base)
- return false;
-
- iwl_trans_read_mem_bytes(trans, base,
- &err_info, sizeof(err_info));
- if (err_info.valid && err_id)
- *err_id = le32_to_cpu(err_info.err_id);
-
- return !!err_info.valid;
-}
-
static bool iwl_mvm_check_rt_status(struct iwl_mvm *mvm,
struct ieee80211_vif *vif)
{
u32 err_id;
/* check for lmac1 error */
- if (iwl_mvm_rt_status(mvm->trans,
- mvm->trans->dbg.lmac_error_event_table[0],
- &err_id)) {
+ if (iwl_fwrt_read_err_table(mvm->trans,
+ mvm->trans->dbg.lmac_error_event_table[0],
+ &err_id)) {
if (err_id == RF_KILL_INDICATOR_FOR_WOWLAN && vif) {
struct cfg80211_wowlan_wakeup wakeup = {
.rfkill_release = true,
@@ -3065,13 +3129,15 @@ static bool iwl_mvm_check_rt_status(struct iwl_mvm *mvm,
}
/* check if we have lmac2 set and check for error */
- if (iwl_mvm_rt_status(mvm->trans,
- mvm->trans->dbg.lmac_error_event_table[1], NULL))
+ if (iwl_fwrt_read_err_table(mvm->trans,
+ mvm->trans->dbg.lmac_error_event_table[1],
+ NULL))
return true;
/* check for umac error */
- if (iwl_mvm_rt_status(mvm->trans,
- mvm->trans->dbg.umac_error_event_table, NULL))
+ if (iwl_fwrt_read_err_table(mvm->trans,
+ mvm->trans->dbg.umac_error_event_table,
+ NULL))
return true;
return false;
@@ -3092,7 +3158,7 @@ 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 :
+ u8 sta_id = mvm->net_detect ? IWL_INVALID_STA :
mvmvif->deflink.ap_sta_id;
/* bug - FW with MLO has status notification */
@@ -3264,13 +3330,19 @@ static bool iwl_mvm_wait_d3_notif(struct iwl_notif_wait_data *notif_wait,
iwl_mvm_parse_wowlan_info_notif_v2(mvm, notif_v2,
d3_data->status,
len);
+ } else if (wowlan_info_ver < 5) {
+ struct iwl_wowlan_info_notif_v4 *notif =
+ (void *)pkt->data;
+
+ iwl_mvm_parse_wowlan_info_notif_v4(mvm, notif,
+ d3_data->status, len,
+ wowlan_info_ver > 3);
} else {
struct iwl_wowlan_info_notif *notif =
(void *)pkt->data;
iwl_mvm_parse_wowlan_info_notif(mvm, notif,
- d3_data->status, len,
- wowlan_info_ver > 3);
+ d3_data->status, len);
}
d3_data->notif_received |= IWL_D3_NOTIF_WOWLAN_INFO;
@@ -3612,8 +3684,6 @@ void iwl_mvm_fast_suspend(struct iwl_mvm *mvm)
IWL_ERR(mvm,
"fast suspend: couldn't send D3_CONFIG_CMD %d\n", ret);
- WARN_ON(iwl_mvm_power_update_mac(mvm));
-
ret = iwl_trans_d3_suspend(mvm->trans, false, false);
if (ret)
IWL_ERR(mvm, "fast suspend: trans_d3_suspend failed %d\n", ret);
@@ -3635,22 +3705,31 @@ int iwl_mvm_fast_resume(struct iwl_mvm *mvm)
iwl_fw_dbg_read_d3_debug_data(&mvm->fwrt);
if (iwl_mvm_check_rt_status(mvm, NULL)) {
+ IWL_ERR(mvm,
+ "iwl_mvm_check_rt_status failed, device is gone during suspend\n");
set_bit(STATUS_FW_ERROR, &mvm->trans->status);
iwl_mvm_dump_nic_error_log(mvm);
iwl_dbg_tlv_time_point(&mvm->fwrt,
IWL_FW_INI_TIME_POINT_FW_ASSERT, NULL);
iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert,
false, 0);
- return -ENODEV;
+ mvm->trans->state = IWL_TRANS_NO_FW;
+ ret = -ENODEV;
+
+ goto out;
}
ret = iwl_mvm_d3_notif_wait(mvm, &d3_data);
+
+ if (ret) {
+ IWL_ERR(mvm, "Couldn't get the d3 notif %d\n", ret);
+ mvm->trans->state = IWL_TRANS_NO_FW;
+ }
+
+out:
clear_bit(IWL_MVM_STATUS_IN_D3, &mvm->status);
mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;
mvm->fast_resume = false;
- if (ret)
- IWL_ERR(mvm, "Couldn't get the d3 notif %d\n", ret);
-
return ret;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
index 25f07e00db42..fbe4e4a50852 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
@@ -221,7 +221,7 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
mvmvif->deflink.queue_params[i].uapsd);
if (vif->type == NL80211_IFTYPE_STATION &&
- ap_sta_id != IWL_MVM_INVALID_STA) {
+ ap_sta_id != IWL_INVALID_STA) {
struct iwl_mvm_sta *mvm_sta;
mvm_sta = iwl_mvm_sta_from_staid_protected(mvm, ap_sta_id);
@@ -463,11 +463,13 @@ static ssize_t iwl_dbgfs_os_device_timediff_read(struct file *file,
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
-static ssize_t iwl_dbgfs_low_latency_write(struct ieee80211_vif *vif, char *buf,
- size_t count, loff_t *ppos)
+static ssize_t
+iwl_dbgfs_low_latency_write_handle(struct wiphy *wiphy, struct file *file,
+ char *buf, size_t count, void *data)
{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm *mvm = mvmvif->mvm;
+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ struct ieee80211_vif *vif = data;
u8 value;
int ret;
@@ -484,12 +486,28 @@ static ssize_t iwl_dbgfs_low_latency_write(struct ieee80211_vif *vif, char *buf,
return count;
}
-static ssize_t
-iwl_dbgfs_low_latency_force_write(struct ieee80211_vif *vif, char *buf,
- size_t count, loff_t *ppos)
+static ssize_t iwl_dbgfs_low_latency_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
{
+ struct ieee80211_vif *vif = file->private_data;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm *mvm = mvmvif->mvm;
+ char buf[10] = {};
+
+ return wiphy_locked_debugfs_write(mvm->hw->wiphy, file,
+ buf, sizeof(buf), user_buf, count,
+ iwl_dbgfs_low_latency_write_handle,
+ vif);
+}
+
+static ssize_t
+iwl_dbgfs_low_latency_force_write_handle(struct wiphy *wiphy, struct file *file,
+ char *buf, size_t count, void *data)
+{
+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ struct ieee80211_vif *vif = data;
u8 value;
int ret;
@@ -517,6 +535,22 @@ iwl_dbgfs_low_latency_force_write(struct ieee80211_vif *vif, char *buf,
return count;
}
+static ssize_t
+iwl_dbgfs_low_latency_force_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ieee80211_vif *vif = file->private_data;
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm *mvm = mvmvif->mvm;
+ char buf[10] = {};
+
+ return wiphy_locked_debugfs_write(mvm->hw->wiphy, file,
+ buf, sizeof(buf), user_buf, count,
+ iwl_dbgfs_low_latency_force_write_handle,
+ vif);
+}
+
static ssize_t iwl_dbgfs_low_latency_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
@@ -831,8 +865,20 @@ MVM_DEBUGFS_READ_FILE_OPS(mac_params);
MVM_DEBUGFS_READ_FILE_OPS(tx_pwr_lmt);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params, 32);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params, 256);
-MVM_DEBUGFS_READ_WRITE_FILE_OPS(low_latency, 10);
-MVM_DEBUGFS_WRITE_FILE_OPS(low_latency_force, 10);
+
+static const struct file_operations iwl_dbgfs_low_latency_ops = {
+ .write = iwl_dbgfs_low_latency_write,
+ .read = iwl_dbgfs_low_latency_read,
+ .open = simple_open,
+ .llseek = generic_file_llseek,
+};
+
+static const struct file_operations iwl_dbgfs_low_latency_force_ops = {
+ .write = iwl_dbgfs_low_latency_force_write,
+ .open = simple_open,
+ .llseek = generic_file_llseek,
+};
+
MVM_DEBUGFS_READ_WRITE_FILE_OPS(uapsd_misbehaving, 20);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(rx_phyinfo, 10);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(quota_min, 32);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
index 55245f913286..b26141c30c61 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
@@ -559,12 +559,12 @@ static int iwl_mvm_ftm_set_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
#ifdef CONFIG_IWLWIFI_DEBUGFS
if (mvmvif->ftm_unprotected) {
- *sta_id = IWL_MVM_INVALID_STA;
+ *sta_id = IWL_INVALID_STA;
*flags &= ~cpu_to_le32(IWL_INITIATOR_AP_FLAGS_PMF);
}
#endif
} else {
- *sta_id = IWL_MVM_INVALID_STA;
+ *sta_id = IWL_INVALID_STA;
}
return 0;
@@ -1063,6 +1063,8 @@ int iwl_mvm_ftm_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
IWL_FW_CMD_VER_UNKNOWN);
switch (cmd_ver) {
+ case 15:
+ /* Version 15 has the same struct as 14 */
case 14:
err = iwl_mvm_ftm_start_v14(mvm, vif, req);
break;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
index e4caa362f597..e6e468e81ab3 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
@@ -131,7 +131,7 @@ iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm,
lockdep_assert_held(&mvm->mutex);
- if (cmd_ver == 10) {
+ if (cmd_ver >= 10) {
cmd.band =
iwl_mvm_phy_band_from_nl80211(chandef->chan->band);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index f30b0fc8eca9..5ea684802ad1 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -1401,6 +1401,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
int ret, i;
struct ieee80211_supported_band *sband = NULL;
+ lockdep_assert_wiphy(mvm->hw->wiphy);
lockdep_assert_held(&mvm->mutex);
ret = iwl_trans_start_hw(mvm->trans);
@@ -1484,7 +1485,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
for (i = 0; i < IWL_FW_MAX_LINK_ID + 1; i++)
RCU_INIT_POINTER(mvm->link_id_to_link_conf[i], NULL);
- mvm->tdls_cs.peer.sta_id = IWL_MVM_INVALID_STA;
+ mvm->tdls_cs.peer.sta_id = IWL_INVALID_STA;
/* reset quota debouncing buffer - 0xff will yield invalid data */
memset(&mvm->last_quota_cmd, 0xff, sizeof(mvm->last_quota_cmd));
@@ -1620,6 +1621,7 @@ int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm)
{
int ret, i;
+ lockdep_assert_wiphy(mvm->hw->wiphy);
lockdep_assert_held(&mvm->mutex);
ret = iwl_trans_start_hw(mvm->trans);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/link.c b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
index 2b0652168002..272da41567ef 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/link.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
@@ -12,6 +12,7 @@
HOW(BLOCKED_FW) \
HOW(BLOCKED_NON_BSS) \
HOW(BLOCKED_ROC) \
+ HOW(BLOCKED_TMP_NON_BSS) \
HOW(EXIT_MISSED_BEACON) \
HOW(EXIT_LOW_RSSI) \
HOW(EXIT_COEX) \
@@ -360,7 +361,8 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
send_cmd:
cmd.modify_mask = cpu_to_le32(changes);
cmd.flags = cpu_to_le32(flags);
- cmd.flags_mask = cpu_to_le32(flags_mask);
+ if (cmd_ver < 6)
+ cmd.flags_mask = cpu_to_le32(flags_mask);
cmd.spec_link_id = link_conf->link_id;
if (cmd_ver < 2)
cmd.listen_lmac = cpu_to_le32(link_info->listen_lmac);
@@ -1165,3 +1167,14 @@ void iwl_mvm_unblock_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (!mvmvif->esr_disable_reason)
iwl_mvm_esr_unblocked(mvm, vif);
}
+
+void iwl_mvm_init_link(struct iwl_mvm_vif_link_info *link)
+{
+ link->bcast_sta.sta_id = IWL_INVALID_STA;
+ link->mcast_sta.sta_id = IWL_INVALID_STA;
+ link->ap_sta_id = IWL_INVALID_STA;
+
+ for (int r = 0; r < NUM_IWL_MVM_SMPS_REQ; r++)
+ link->smps_requests[r] =
+ IEEE80211_SMPS_AUTOMATIC;
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index a7a10e716e65..2a13d70da46c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -216,7 +216,7 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
.preferred_tsf = NUM_TSF_IDS,
.found_vif = false,
};
- int ret, i;
+ int ret;
lockdep_assert_held(&mvm->mutex);
@@ -298,9 +298,7 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
mvmvif->time_event_data.id = TE_MAX;
mvmvif->roc_activity = ROC_NUM_ACTIVITIES;
- 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;
+ iwl_mvm_init_link(&mvmvif->deflink);
/* No need to allocate data queues to P2P Device MAC and NAN.*/
if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
@@ -316,9 +314,6 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
mvmvif->deflink.cab_queue = IWL_MVM_DQA_GCAST_QUEUE;
}
- for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++)
- mvmvif->deflink.smps_requests[i] = IEEE80211_SMPS_AUTOMATIC;
-
return 0;
exit_fail:
@@ -1605,6 +1600,7 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm,
0);
u8 new_notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, MAC_CONF_GROUP,
MISSED_BEACONS_NOTIF, 0);
+ struct ieee80211_bss_conf *bss_conf;
/* If the firmware uses the new notification (from MAC_CONF_GROUP),
* refer to that notification's version.
@@ -1617,9 +1613,9 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm,
/* before version four the ID in the notification refers to mac ID */
if (notif_ver < 4) {
vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, false);
+ bss_conf = &vif->bss_conf;
} else {
- struct ieee80211_bss_conf *bss_conf =
- iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, id, false);
+ bss_conf = iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, id, false);
if (!bss_conf)
return;
@@ -1664,6 +1660,8 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm,
rx_missed_bcon, rx_missed_bcon_since_rx);
}
} else if (link_id >= 0 && hweight16(vif->active_links) > 1) {
+ u32 bss_param_ch_cnt_link_id =
+ bss_conf->bss_param_ch_cnt_link_id;
u32 scnd_lnk_bcn_lost = 0;
if (notif_ver >= 5 &&
@@ -1677,10 +1675,14 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm,
/* Exit EMLSR if we lost more than
* IWL_MVM_MISSED_BEACONS_EXIT_ESR_THRESH beacons on boths links
* OR more than IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH on any link.
+ * OR more than IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_BSS_PARAM_CHANGED
+ * and the link's bss_param_ch_count has changed.
*/
if ((rx_missed_bcon >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS &&
scnd_lnk_bcn_lost >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS) ||
- rx_missed_bcon >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH)
+ rx_missed_bcon >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH ||
+ (bss_param_ch_cnt_link_id != link_id &&
+ rx_missed_bcon >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_BSS_PARAM_CHANGED))
iwl_mvm_exit_esr(mvm, vif,
IWL_MVM_ESR_EXIT_MISSED_BEACON,
iwl_mvm_get_primary_link(vif));
@@ -1689,6 +1691,9 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm,
ieee80211_beacon_loss(vif);
else
ieee80211_cqm_beacon_loss_notify(vif, GFP_ATOMIC);
+
+ /* try to switch links, no-op if we don't have MLO */
+ iwl_mvm_int_mlo_scan(mvm, vif);
}
iwl_dbg_tlv_time_point(&mvm->fwrt,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 80b9a115245f..07778d55878b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -1109,7 +1109,7 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
vif->driver_flags &= ~IEEE80211_VIF_EML_ACTIVE;
for_each_mvm_vif_valid_link(mvmvif, link_id) {
- mvmvif->link[link_id]->ap_sta_id = IWL_MVM_INVALID_STA;
+ mvmvif->link[link_id]->ap_sta_id = IWL_INVALID_STA;
mvmvif->link[link_id]->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
mvmvif->link[link_id]->phy_ctxt = NULL;
mvmvif->link[link_id]->active = 0;
@@ -1237,6 +1237,7 @@ int __iwl_mvm_mac_start(struct iwl_mvm *mvm)
fast_resume = mvm->fast_resume;
if (fast_resume) {
+ iwl_mvm_mei_device_state(mvm, true);
ret = iwl_mvm_fast_resume(mvm);
if (ret) {
iwl_mvm_stop_device(mvm);
@@ -1344,6 +1345,8 @@ static void iwl_mvm_restart_complete(struct iwl_mvm *mvm)
* of packets the FW sent out, so we must reconnect.
*/
iwl_mvm_teardown_tdls_peers(mvm);
+
+ IWL_INFO(mvm, "restart completed\n");
}
void iwl_mvm_mac_reconfig_complete(struct ieee80211_hw *hw,
@@ -1377,10 +1380,13 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm, bool suspend)
iwl_mvm_rm_aux_sta(mvm);
if (suspend &&
- mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
+ mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
iwl_mvm_fast_suspend(mvm);
- else
+ /* From this point on, we won't touch the device */
+ iwl_mvm_mei_device_state(mvm, false);
+ } else {
iwl_mvm_stop_device(mvm);
+ }
iwl_mvm_async_handlers_purge(mvm);
/* async_handlers_list is empty and will stay empty: HW is stopped */
@@ -1474,15 +1480,16 @@ struct iwl_mvm_phy_ctxt *iwl_mvm_get_free_phy_ctxt(struct iwl_mvm *mvm)
return NULL;
}
-int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+int iwl_mvm_set_tx_power(struct iwl_mvm *mvm,
+ struct ieee80211_bss_conf *link_conf,
s16 tx_power)
{
u32 cmd_id = REDUCE_TX_POWER_CMD;
+ u32 mac_id = iwl_mvm_vif_from_mac80211(link_conf->vif)->id;
int len;
struct iwl_dev_tx_power_cmd_v3_v8 cmd = {
.common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_MAC),
- .common.mac_context_id =
- cpu_to_le32(iwl_mvm_vif_from_mac80211(vif)->id),
+ .common.mac_context_id = cpu_to_le32(mac_id),
};
struct iwl_dev_tx_power_cmd cmd_v9_v10;
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 3);
@@ -1495,8 +1502,7 @@ int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (cmd_ver > 8) {
/* Those fields sit on the same place for v9 and v10 */
cmd_v9_v10.common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_MAC);
- cmd_v9_v10.common.mac_context_id =
- cpu_to_le32(iwl_mvm_vif_from_mac80211(vif)->id);
+ cmd_v9_v10.common.mac_context_id = cpu_to_le32(mac_id);
cmd_v9_v10.common.pwr_restriction = cpu_to_le16(u_tx_power);
cmd_data = &cmd_v9_v10;
}
@@ -1739,6 +1745,21 @@ static void iwl_mvm_unblock_esr_tpt(struct wiphy *wiphy, struct wiphy_work *wk)
iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_TPT);
}
+static void iwl_mvm_unblock_esr_tmp_non_bss(struct wiphy *wiphy,
+ struct wiphy_work *wk)
+{
+ struct iwl_mvm_vif *mvmvif =
+ container_of(wk, struct iwl_mvm_vif,
+ unblock_esr_tmp_non_bss_wk.work);
+ struct iwl_mvm *mvm = mvmvif->mvm;
+ struct ieee80211_vif *vif =
+ container_of((void *)mvmvif, struct ieee80211_vif, drv_priv);
+
+ mutex_lock(&mvm->mutex);
+ iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_TMP_NON_BSS);
+ mutex_unlock(&mvm->mutex);
+}
+
void iwl_mvm_mac_init_mvmvif(struct iwl_mvm *mvm, struct iwl_mvm_vif *mvmvif)
{
lockdep_assert_held(&mvm->mutex);
@@ -1757,6 +1778,9 @@ void iwl_mvm_mac_init_mvmvif(struct iwl_mvm *mvm, struct iwl_mvm_vif *mvmvif)
wiphy_work_init(&mvmvif->unblock_esr_tpt_wk,
iwl_mvm_unblock_esr_tpt);
+
+ wiphy_delayed_work_init(&mvmvif->unblock_esr_tmp_non_bss_wk,
+ iwl_mvm_unblock_esr_tmp_non_bss);
}
static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
@@ -1907,6 +1931,8 @@ void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
&mvmvif->mlo_int_scan_wk);
wiphy_work_cancel(mvm->hw->wiphy, &mvmvif->unblock_esr_tpt_wk);
+ wiphy_delayed_work_cancel(mvm->hw->wiphy,
+ &mvmvif->unblock_esr_tmp_non_bss_wk);
cancel_delayed_work_sync(&mvmvif->csa_work);
}
@@ -2929,7 +2955,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
IWL_MVM_SMPS_REQ_PROT,
IEEE80211_SMPS_DYNAMIC, 0);
}
- } else if (mvmvif->deflink.ap_sta_id != IWL_MVM_INVALID_STA) {
+ } else if (mvmvif->deflink.ap_sta_id != IWL_INVALID_STA) {
iwl_mvm_mei_host_disassociated(mvm);
/*
* If update fails - SF might be running in associated
@@ -2965,7 +2991,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
IWL_ERR(mvm,
"failed to remove AP station\n");
- mvmvif->deflink.ap_sta_id = IWL_MVM_INVALID_STA;
+ mvmvif->deflink.ap_sta_id = IWL_INVALID_STA;
}
/* remove quota for this interface */
@@ -3311,7 +3337,7 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
if (changes & BSS_CHANGED_TXPOWER) {
IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d dBm\n",
bss_conf->txpower);
- iwl_mvm_set_tx_power(mvm, vif, bss_conf->txpower);
+ iwl_mvm_set_tx_power(mvm, bss_conf, bss_conf->txpower);
}
}
@@ -3422,7 +3448,7 @@ static void __iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
*/
break;
case STA_NOTIFY_AWAKE:
- if (WARN_ON(mvmsta->deflink.sta_id == IWL_MVM_INVALID_STA))
+ if (WARN_ON(mvmsta->deflink.sta_id == IWL_INVALID_STA))
break;
if (txqs)
@@ -3502,6 +3528,8 @@ void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
unsigned int link_id;
+ lockdep_assert_wiphy(mvm->hw->wiphy);
+
/*
* This is called before mac80211 does RCU synchronisation,
* so here we already invalidate our internal RCU-protected
@@ -4083,6 +4111,8 @@ iwl_mvm_sta_state_authorized_to_assoc(struct iwl_mvm *mvm,
&mvmvif->mlo_int_scan_wk);
wiphy_work_cancel(mvm->hw->wiphy, &mvmvif->unblock_esr_tpt_wk);
+ wiphy_delayed_work_cancel(mvm->hw->wiphy,
+ &mvmvif->unblock_esr_tmp_non_bss_wk);
/* No need for the periodic statistics anymore */
if (ieee80211_vif_is_mld(vif) && mvmvif->esr_active)
@@ -4244,8 +4274,9 @@ 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)
+ struct ieee80211_link_sta *link_sta, u32 changed)
{
+ struct ieee80211_sta *sta = link_sta->sta;
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
if (changed & (IEEE80211_RC_BW_CHANGED |
@@ -5075,7 +5106,7 @@ void iwl_mvm_change_chanctx(struct ieee80211_hw *hw,
(changed & ~(IEEE80211_CHANCTX_CHANGE_WIDTH |
IEEE80211_CHANCTX_CHANGE_RX_CHAINS |
IEEE80211_CHANCTX_CHANGE_RADAR |
- IEEE80211_CHANCTX_CHANGE_MIN_WIDTH)),
+ IEEE80211_CHANCTX_CHANGE_MIN_DEF)),
"Cannot change PHY. Ref=%d, changed=0x%X\n",
phy_ctxt->ref, changed))
return;
@@ -5083,7 +5114,7 @@ void iwl_mvm_change_chanctx(struct ieee80211_hw *hw,
guard(mvm)(mvm);
/* we are only changing the min_width, may be a noop */
- if (changed == IEEE80211_CHANCTX_CHANGE_MIN_WIDTH) {
+ if (changed == IEEE80211_CHANCTX_CHANGE_MIN_DEF) {
if (phy_ctxt->width == def->width)
return;
@@ -6570,7 +6601,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
.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,
+ .link_sta_rc_update = iwl_mvm_sta_rc_update,
.conf_tx = iwl_mvm_mac_conf_tx,
.mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx,
.mgd_complete_tx = iwl_mvm_mac_mgd_complete_tx,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
index 455f5f417506..ef0be44207e1 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
@@ -396,7 +396,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_ONCE(vif->type != NL80211_IFTYPE_STATION ||
- link->ap_sta_id == IWL_MVM_INVALID_STA))
+ link->ap_sta_id == IWL_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 e252f0dcea20..b807046144c0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -339,33 +339,20 @@ __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
if (ret)
goto out;
- /* Initialize rate control for the AP station, since we might be
- * doing a link switch here - we cannot initialize it before since
- * this needs the phy context assigned (and in FW?), and we cannot
- * do it later because it needs to be initialized as soon as we're
- * able to TX on the link, i.e. when active.
+ /*
+ * if link switching (link not active yet) we'll activate it in
+ * firmware later on link-info change, which mac80211 guarantees
+ * for link switch after the stations are set up
*/
- if (mvmvif->ap_sta) {
- struct ieee80211_link_sta *link_sta;
-
- rcu_read_lock();
- link_sta = rcu_dereference(mvmvif->ap_sta->link[link_id]);
-
- if (!WARN_ON_ONCE(!link_sta))
- iwl_mvm_rs_rate_init(mvm, vif, mvmvif->ap_sta,
- link_conf, link_sta,
- phy_ctxt->channel->band);
- rcu_read_unlock();
+ if (ieee80211_vif_link_active(vif, link_conf->link_id)) {
+ ret = iwl_mvm_link_changed(mvm, vif, link_conf,
+ LINK_CONTEXT_MODIFY_ACTIVE |
+ LINK_CONTEXT_MODIFY_RATES_INFO,
+ true);
+ if (ret)
+ goto out;
}
- /* then activate */
- ret = iwl_mvm_link_changed(mvm, vif, link_conf,
- LINK_CONTEXT_MODIFY_ACTIVE |
- LINK_CONTEXT_MODIFY_RATES_INFO,
- true);
- if (ret)
- goto out;
-
if (vif->type == NL80211_IFTYPE_STATION)
iwl_mvm_send_ap_tx_power_constraint_cmd(mvm, vif,
link_conf,
@@ -783,6 +770,11 @@ iwl_mvm_mld_link_info_changed_station(struct iwl_mvm *mvm,
if (WARN_ON_ONCE(!mvmvif->link[link_conf->link_id]))
return;
+ /* not yet marked active in vif means during link switch */
+ if (!ieee80211_vif_link_active(vif, link_conf->link_id) &&
+ vif->cfg.assoc && mvmvif->link[link_conf->link_id]->phy_ctxt)
+ link_changes |= LINK_CONTEXT_MODIFY_ACTIVE;
+
has_he = link_conf->he_support && !iwlwifi_mod_params.disable_11ax;
has_eht = link_conf->eht_support && !iwlwifi_mod_params.disable_11be;
@@ -832,7 +824,7 @@ 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)
+ if (mvmvif->link[i]->ap_sta_id != IWL_INVALID_STA)
return true;
}
@@ -859,7 +851,7 @@ static void iwl_mvm_mld_vif_delete_all_stas(struct iwl_mvm *mvm,
if (ret)
IWL_ERR(mvm, "failed to remove AP station\n");
- link->ap_sta_id = IWL_MVM_INVALID_STA;
+ link->ap_sta_id = IWL_INVALID_STA;
}
}
@@ -1046,7 +1038,7 @@ static void iwl_mvm_mld_link_info_changed(struct ieee80211_hw *hw,
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);
+ iwl_mvm_set_tx_power(mvm, link_conf, link_conf->txpower);
}
}
@@ -1177,8 +1169,6 @@ iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw,
int err, i;
for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
- int r;
-
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
break;
@@ -1190,14 +1180,8 @@ iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw,
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;
+ iwl_mvm_init_link(new_link[i]);
}
mutex_lock(&mvm->mutex);
@@ -1388,6 +1372,36 @@ iwl_mvm_mld_mac_pre_channel_switch(struct ieee80211_hw *hw,
return ret;
}
+#define IWL_MVM_MLD_UNBLOCK_ESR_NON_BSS_TIMEOUT (5 * HZ)
+
+static void iwl_mvm_mld_prep_add_interface(struct ieee80211_hw *hw,
+ enum nl80211_iftype type)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ struct ieee80211_vif *bss_vif = iwl_mvm_get_bss_vif(mvm);
+ struct iwl_mvm_vif *mvmvif;
+ int ret;
+
+ IWL_DEBUG_MAC80211(mvm, "prep_add_interface: type=%u\n",
+ type);
+
+ if (IS_ERR_OR_NULL(bss_vif) ||
+ !(type == NL80211_IFTYPE_AP ||
+ type == NL80211_IFTYPE_P2P_GO ||
+ type == NL80211_IFTYPE_P2P_CLIENT))
+ return;
+
+ mvmvif = iwl_mvm_vif_from_mac80211(bss_vif);
+ ret = iwl_mvm_block_esr_sync(mvm, bss_vif,
+ IWL_MVM_ESR_BLOCKED_TMP_NON_BSS);
+ if (ret)
+ return;
+
+ wiphy_delayed_work_queue(mvmvif->mvm->hw->wiphy,
+ &mvmvif->unblock_esr_tmp_non_bss_wk,
+ IWL_MVM_MLD_UNBLOCK_ESR_NON_BSS_TIMEOUT);
+}
+
const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
.tx = iwl_mvm_mac_tx,
.wake_tx_queue = iwl_mvm_mac_wake_tx_queue,
@@ -1413,7 +1427,7 @@ const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
.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,
+ .link_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,
@@ -1484,4 +1498,5 @@ const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
.change_sta_links = iwl_mvm_mld_change_sta_links,
.can_activate_links = iwl_mvm_mld_can_activate_links,
.can_neg_ttlm = iwl_mvm_mld_can_neg_ttlm,
+ .prep_add_interface = iwl_mvm_mld_prep_add_interface,
};
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
index 28a9d90ad1cd..019839604011 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
@@ -146,7 +146,7 @@ int iwl_mvm_mld_add_int_sta_with_queue(struct iwl_mvm *mvm,
unsigned int wdg_timeout = _wdg_timeout ? *_wdg_timeout :
mvm->trans->trans_cfg->base_params->wd_timeout;
- if (WARN_ON_ONCE(sta->sta_id == IWL_MVM_INVALID_STA))
+ if (WARN_ON_ONCE(sta->sta_id == IWL_INVALID_STA))
return -ENOSPC;
if (sta->type == STATION_TYPE_AUX)
@@ -346,7 +346,7 @@ static int iwl_mvm_mld_rm_int_sta(struct iwl_mvm *mvm,
lockdep_assert_held(&mvm->mutex);
- if (WARN_ON_ONCE(int_sta->sta_id == IWL_MVM_INVALID_STA))
+ if (WARN_ON_ONCE(int_sta->sta_id == IWL_INVALID_STA))
return -EINVAL;
if (flush)
@@ -521,6 +521,9 @@ void iwl_mvm_mld_free_sta_link(struct iwl_mvm *mvm,
unsigned int link_id,
bool is_in_fw)
{
+ lockdep_assert_wiphy(mvm->hw->wiphy);
+ lockdep_assert_held(&mvm->mutex);
+
RCU_INIT_POINTER(mvm->fw_id_to_mac_id[mvm_sta_link->sta_id],
is_in_fw ? ERR_PTR(-EINVAL) : NULL);
RCU_INIT_POINTER(mvm->fw_id_to_link_sta[mvm_sta_link->sta_id], NULL);
@@ -559,7 +562,10 @@ static int iwl_mvm_mld_alloc_sta_link(struct iwl_mvm *mvm,
u32 sta_id = iwl_mvm_find_free_sta_id(mvm,
ieee80211_vif_type_p2p(vif));
- if (sta_id == IWL_MVM_INVALID_STA)
+ lockdep_assert_wiphy(mvm->hw->wiphy);
+ lockdep_assert_held(&mvm->mutex);
+
+ if (sta_id == IWL_INVALID_STA)
return -ENOSPC;
if (rcu_access_pointer(sta->link[link_id]) == &sta->deflink) {
@@ -612,10 +618,10 @@ static void iwl_mvm_mld_set_ap_sta_id(struct ieee80211_sta *sta,
struct iwl_mvm_link_sta *sta_link)
{
if (!sta->tdls) {
- WARN_ON(vif_link->ap_sta_id != IWL_MVM_INVALID_STA);
+ WARN_ON(vif_link->ap_sta_id != IWL_INVALID_STA);
vif_link->ap_sta_id = sta_link->sta_id;
} else {
- WARN_ON(vif_link->ap_sta_id == IWL_MVM_INVALID_STA);
+ WARN_ON(vif_link->ap_sta_id == IWL_INVALID_STA);
}
}
@@ -631,6 +637,9 @@ static int iwl_mvm_alloc_sta_after_restart(struct iwl_mvm *mvm,
int ret = -EINVAL;
int sta_id;
+ lockdep_assert_wiphy(mvm->hw->wiphy);
+ lockdep_assert_held(&mvm->mutex);
+
/* 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.
@@ -686,7 +695,7 @@ int iwl_mvm_mld_add_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
spin_lock_init(&mvm_sta->lock);
- ret = iwl_mvm_sta_init(mvm, vif, sta, IWL_MVM_INVALID_STA,
+ ret = iwl_mvm_sta_init(mvm, vif, sta, IWL_INVALID_STA,
STATION_TYPE_PEER);
} else {
ret = iwl_mvm_alloc_sta_after_restart(mvm, vif, sta);
@@ -858,9 +867,10 @@ int iwl_mvm_mld_rm_sta_id(struct iwl_mvm *mvm, u8 sta_id)
{
int ret;
+ lockdep_assert_wiphy(mvm->hw->wiphy);
lockdep_assert_held(&mvm->mutex);
- if (WARN_ON(sta_id == IWL_MVM_INVALID_STA))
+ if (WARN_ON(sta_id == IWL_INVALID_STA))
return 0;
ret = iwl_mvm_mld_rm_sta_from_fw(mvm, sta_id);
@@ -1064,6 +1074,7 @@ int iwl_mvm_mld_update_sta_links(struct iwl_mvm *mvm,
unsigned int link_id;
int ret;
+ lockdep_assert_wiphy(mvm->hw->wiphy);
lockdep_assert_held(&mvm->mutex);
for_each_set_bit(link_id, &old_links_long,
@@ -1109,7 +1120,7 @@ int iwl_mvm_mld_update_sta_links(struct iwl_mvm *mvm,
goto err;
if (vif->type == NL80211_IFTYPE_STATION)
- mvm_vif_link->ap_sta_id = IWL_MVM_INVALID_STA;
+ mvm_vif_link->ap_sta_id = IWL_INVALID_STA;
iwl_mvm_mld_free_sta_link(mvm, mvm_sta, mvm_sta_link, link_id,
false);
@@ -1182,6 +1193,9 @@ int iwl_mvm_mld_update_sta_links(struct iwl_mvm *mvm,
link_sta_added_to_fw |= BIT(link_id);
iwl_mvm_rs_add_sta_link(mvm, mvm_sta_link);
+
+ iwl_mvm_rs_rate_init(mvm, vif, sta, link_conf, link_sta,
+ link_conf->chanreq.oper.chan->band);
}
if (sta_mask_added) {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index ef07cff203b0..2ad615293c75 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -361,6 +361,9 @@ struct iwl_mvm_vif_link_info {
* @IWL_MVM_ESR_BLOCKED_NON_BSS: An active non-BSS interface's link is
* preventing EMLSR
* @IWL_MVM_ESR_BLOCKED_ROC: remain-on-channel is preventing EMLSR
+ * @IWL_MVM_ESR_BLOCKED_TMP_NON_BSS: An expected active non-BSS interface's link
+ * is preventing EMLSR. This is a temporary blocking that is set when there
+ * is an indication that a non-BSS interface is to be added.
* @IWL_MVM_ESR_EXIT_MISSED_BEACON: exited EMLSR due to missed beacons
* @IWL_MVM_ESR_EXIT_LOW_RSSI: link is deactivated/not allowed for EMLSR
* due to low RSSI.
@@ -379,6 +382,7 @@ enum iwl_mvm_esr_state {
IWL_MVM_ESR_BLOCKED_FW = 0x8,
IWL_MVM_ESR_BLOCKED_NON_BSS = 0x10,
IWL_MVM_ESR_BLOCKED_ROC = 0x20,
+ IWL_MVM_ESR_BLOCKED_TMP_NON_BSS = 0x40,
IWL_MVM_ESR_EXIT_MISSED_BEACON = 0x10000,
IWL_MVM_ESR_EXIT_LOW_RSSI = 0x20000,
IWL_MVM_ESR_EXIT_COEX = 0x40000,
@@ -452,6 +456,8 @@ struct iwl_mvm_esr_exit {
* @prevent_esr_done_wk: work that should be done when esr prevention ends.
* @mlo_int_scan_wk: work for the internal MLO scan.
* @unblock_esr_tpt_wk: work for unblocking EMLSR when tpt is high enough.
+ * @unblock_esr_tmp_non_bss_wk: work for removing the
+ * IWL_MVM_ESR_BLOCKED_TMP_NON_BSS blocking for EMLSR.
* @roc_activity: currently running ROC activity for this vif (or
* ROC_NUM_ACTIVITIES if no activity is running).
* @session_prot_connection_loss: the connection was lost due to session
@@ -588,6 +594,7 @@ struct iwl_mvm_vif {
struct wiphy_delayed_work prevent_esr_done_wk;
struct wiphy_delayed_work mlo_int_scan_wk;
struct wiphy_work unblock_esr_tpt_wk;
+ struct wiphy_delayed_work unblock_esr_tmp_non_bss_wk;
struct iwl_mvm_vif_link_info deflink;
struct iwl_mvm_vif_link_info *link[IEEE80211_MLD_MAX_NUM_LINKS];
@@ -773,7 +780,6 @@ struct iwl_mvm_tcm {
* @head_sn: reorder window head sn
* @num_stored: number of mpdus stored in the buffer
* @queue: queue of this reorder buffer
- * @last_amsdu: track last ASMDU SN for duplication detection
* @valid: reordering is valid for this queue
* @lock: protect reorder buffer internal state
*/
@@ -781,7 +787,6 @@ struct iwl_mvm_reorder_buffer {
u16 head_sn;
u16 num_stored;
int queue;
- u16 last_amsdu;
bool valid;
spinlock_t lock;
} ____cacheline_aligned_in_smp;
@@ -1077,6 +1082,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_STATION_COUNT_MAX];
+ /* note: fw_id_to_link_sta must be protected by wiphy and mvm mutexes */
struct ieee80211_link_sta __rcu *fw_id_to_link_sta[IWL_STATION_COUNT_MAX];
u8 rx_ba_sessions;
@@ -1584,8 +1590,7 @@ static inline bool iwl_mvm_bt_is_rrc_supported(struct iwl_mvm *mvm)
static inline bool iwl_mvm_is_csum_supported(struct iwl_mvm *mvm)
{
return fw_has_capa(&mvm->fw->ucode_capa,
- IWL_UCODE_TLV_CAPA_CSUM_SUPPORT) &&
- !IWL_MVM_HW_CSUM_DISABLE;
+ IWL_UCODE_TLV_CAPA_CSUM_SUPPORT);
}
static inline bool iwl_mvm_is_mplut_supported(struct iwl_mvm *mvm)
@@ -2100,6 +2105,7 @@ int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
u32 iwl_mvm_get_lmac_id(struct iwl_mvm *mvm, enum nl80211_band band);
/* Links */
+void iwl_mvm_init_link(struct iwl_mvm_vif_link_info *link);
int iwl_mvm_set_link_mapping(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf);
int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
@@ -2327,7 +2333,7 @@ static inline int iwl_mvm_fast_resume(struct iwl_mvm *mvm)
}
#endif
void iwl_mvm_set_wowlan_qos_seq(struct iwl_mvm_sta *mvm_ap_sta,
- struct iwl_wowlan_config_cmd *cmd);
+ struct iwl_wowlan_config_cmd_v6 *cmd);
int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
bool disable_offloading,
@@ -2914,7 +2920,7 @@ iwl_mvm_mac_release_buffered_frames(struct ieee80211_hw *hw,
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);
+ struct ieee80211_link_sta *link_sta, u32 changed);
void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_prep_tx_info *info);
@@ -2982,7 +2988,8 @@ void iwl_mvm_abort_pmsr(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
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,
+int iwl_mvm_set_tx_power(struct iwl_mvm *mvm,
+ struct ieee80211_bss_conf *bss_conf,
s16 tx_power);
int iwl_mvm_set_hw_timestamp(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/offloading.c b/drivers/net/wireless/intel/iwlwifi/mvm/offloading.c
index 1eb21fe861e5..15d4369678a2 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/offloading.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/offloading.c
@@ -10,7 +10,7 @@
#include "mvm.h"
void iwl_mvm_set_wowlan_qos_seq(struct iwl_mvm_sta *mvm_ap_sta,
- struct iwl_wowlan_config_cmd *cmd)
+ struct iwl_wowlan_config_cmd_v6 *cmd)
{
int i;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index 4dd4a9d5c71f..e25d7570ffab 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -1505,8 +1505,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
mvm->scan_cmd_size = scan_size;
/* invalidate ids to prevent accidental removal of sta_id 0 */
- mvm->aux_sta.sta_id = IWL_MVM_INVALID_STA;
- mvm->snif_sta.sta_id = IWL_MVM_INVALID_STA;
+ mvm->aux_sta.sta_id = IWL_INVALID_STA;
+ mvm->snif_sta.sta_id = IWL_INVALID_STA;
/* Set EBS as successful as long as not stated otherwise by the FW. */
mvm->last_ebs_successful = true;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
index 05715e5af6ab..de5ac000272e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
@@ -440,12 +440,6 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
mvmsta = iwl_mvm_sta_from_mac80211(sta);
- if (!mvmsta) {
- IWL_ERR(mvm, "Invalid sta id (%d) in FW TLC notification\n",
- notif->sta_id);
- goto out;
- }
-
flags = le32_to_cpu(notif->flags);
mvm_link_sta = rcu_dereference(mvmsta->link[link_sta->link_id]);
@@ -615,11 +609,8 @@ void iwl_mvm_rs_fw_rate_init(struct iwl_mvm *mvm,
int cmd_ver;
int ret;
- /* Enable external EHT LTF only for GL device and if there's
- * mutual support by AP and client
- */
- if (CSR_HW_REV_TYPE(mvm->trans->hw_rev) == IWL_CFG_MAC_TYPE_GL &&
- sband_eht_cap &&
+ /* Enable extra EHT LTF if there's mutual support by AP and client */
+ if (sband_eht_cap &&
sband_eht_cap->eht_cap_elem.phy_cap_info[5] &
IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF &&
link_sta->eht_cap.has_eht &&
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
index 1a0b5f8d4339..9e72db9bab40 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
@@ -560,7 +560,8 @@ static void iwl_mvm_update_link_sig(struct ieee80211_vif *vif, int sig,
struct iwl_mvm_vif_link_info *link_info,
struct ieee80211_bss_conf *bss_conf)
{
- struct iwl_mvm *mvm = iwl_mvm_vif_from_mac80211(vif)->mvm;
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm *mvm = mvmvif->mvm;
int thold = bss_conf->cqm_rssi_thold;
int hyst = bss_conf->cqm_rssi_hyst;
int last_event;
@@ -625,6 +626,13 @@ static void iwl_mvm_update_link_sig(struct ieee80211_vif *vif, int sig,
if (!vif->cfg.assoc || !ieee80211_vif_is_mld(vif))
return;
+ /* We're not in EMLSR and our signal is bad, try to switch link maybe */
+ if (sig < IWL_MVM_LOW_RSSI_MLO_SCAN_THRESH && !mvmvif->esr_active) {
+ iwl_mvm_int_mlo_scan(mvm, vif);
+ return;
+ }
+
+ /* We are in EMLSR, check if we need to exit */
exit_esr_thresh =
iwl_mvm_get_esr_rssi_thresh(mvm,
&bss_conf->chanreq.oper,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
index 65f8933c34b4..a2f16bfaec44 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
@@ -773,9 +773,7 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
return false;
}
- rcu_read_lock();
sta_mask = iwl_mvm_sta_fw_id_mask(mvm, sta, -1);
- rcu_read_unlock();
if (IWL_FW_CHECK(mvm,
tid != baid_data->tid ||
@@ -814,7 +812,7 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
if (!buffer->num_stored && ieee80211_sn_less(sn, nssn)) {
if (!amsdu || last_subframe)
buffer->head_sn = nssn;
- /* No need to update AMSDU last SN - we are moving the head */
+
spin_unlock_bh(&buffer->lock);
return false;
}
@@ -831,7 +829,6 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
if (!amsdu || last_subframe)
buffer->head_sn = ieee80211_sn_inc(buffer->head_sn);
- /* No need to update AMSDU last SN - we are moving the head */
spin_unlock_bh(&buffer->lock);
return false;
}
@@ -841,9 +838,6 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
__skb_queue_tail(&entries[index].frames, skb);
buffer->num_stored++;
- if (amsdu)
- buffer->last_amsdu = sn;
-
/*
* We cannot trust NSSN for AMSDU sub-frames that are not the last.
* The reason is that NSSN advances on the first sub-frame, and may
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
index ddcbd80a49fb..376b9b12fa62 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -3597,7 +3597,8 @@ static int iwl_mvm_int_mlo_scan_start(struct iwl_mvm *mvm,
IWL_DEBUG_SCAN(mvm, "Starting Internal MLO scan: n_channels=%zu\n",
n_channels);
- if (!vif->cfg.assoc || !ieee80211_vif_is_mld(vif))
+ if (!vif->cfg.assoc || !ieee80211_vif_is_mld(vif) ||
+ hweight16(vif->valid_links) == 1)
return -EINVAL;
size = struct_size(req, channels, n_channels);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index b6c99cd6d9e5..cd74c181c260 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -47,7 +47,7 @@ int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm, enum nl80211_iftype iftype)
lockdep_is_held(&mvm->mutex)))
return sta_id;
}
- return IWL_MVM_INVALID_STA;
+ return IWL_INVALID_STA;
}
/* Calculate the ampdu density and max size */
@@ -1216,7 +1216,7 @@ static bool iwl_mvm_remove_inactive_tids(struct iwl_mvm *mvm,
* can be unshared and finding one (and only one) that can be
* reused.
* This function is also invoked as a sort of clean-up task,
- * in which case @alloc_for_sta is IWL_MVM_INVALID_STA.
+ * in which case @alloc_for_sta is IWL_INVALID_STA.
*
* Returns the queue number, or -ENOSPC.
*/
@@ -1309,7 +1309,7 @@ static int iwl_mvm_inactivity_check(struct iwl_mvm *mvm, u8 alloc_for_sta)
rcu_read_unlock();
- if (free_queue >= 0 && alloc_for_sta != IWL_MVM_INVALID_STA) {
+ if (free_queue >= 0 && alloc_for_sta != IWL_INVALID_STA) {
ret = iwl_mvm_free_inactive_queue(mvm, free_queue, queue_owner,
alloc_for_sta);
if (ret)
@@ -1522,7 +1522,7 @@ void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk)
mutex_lock(&mvm->mutex);
- iwl_mvm_inactivity_check(mvm, IWL_MVM_INVALID_STA);
+ iwl_mvm_inactivity_check(mvm, IWL_INVALID_STA);
while (!list_empty(&mvm->add_stream_txqs)) {
struct iwl_mvm_txq *mvmtxq;
@@ -1580,7 +1580,7 @@ static int iwl_mvm_reserve_sta_stream(struct iwl_mvm *mvm,
return 0;
/* run the general cleanup/unsharing of queues */
- iwl_mvm_inactivity_check(mvm, IWL_MVM_INVALID_STA);
+ iwl_mvm_inactivity_check(mvm, IWL_INVALID_STA);
/* Make sure we have free resources for this STA */
if (vif_type == NL80211_IFTYPE_STATION && !sta->tdls &&
@@ -1756,7 +1756,7 @@ int iwl_mvm_sta_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
* this function
*/
if (!mvm->mld_api_is_used) {
- if (WARN_ON(sta_id == IWL_MVM_INVALID_STA))
+ if (WARN_ON(sta_id == IWL_INVALID_STA))
return -EINVAL;
mvm_sta->deflink.sta_id = sta_id;
@@ -1865,7 +1865,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
else
sta_id = mvm_sta->deflink.sta_id;
- if (sta_id == IWL_MVM_INVALID_STA)
+ if (sta_id == IWL_INVALID_STA)
return -ENOSPC;
spin_lock_init(&mvm_sta->lock);
@@ -1903,10 +1903,10 @@ update_fw:
if (vif->type == NL80211_IFTYPE_STATION) {
if (!sta->tdls) {
- WARN_ON(mvmvif->deflink.ap_sta_id != IWL_MVM_INVALID_STA);
+ WARN_ON(mvmvif->deflink.ap_sta_id != IWL_INVALID_STA);
mvmvif->deflink.ap_sta_id = sta_id;
} else {
- WARN_ON(mvmvif->deflink.ap_sta_id == IWL_MVM_INVALID_STA);
+ WARN_ON(mvmvif->deflink.ap_sta_id == IWL_INVALID_STA);
}
}
@@ -2095,7 +2095,7 @@ bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
iwl_mvm_sec_key_remove_ap(mvm, vif, mvm_link, 0);
/* unassoc - go ahead - remove the AP STA now */
- mvm_link->ap_sta_id = IWL_MVM_INVALID_STA;
+ mvm_link->ap_sta_id = IWL_INVALID_STA;
}
/*
@@ -2103,7 +2103,7 @@ bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
* before the STA is removed.
*/
if (WARN_ON_ONCE(mvm->tdls_cs.peer.sta_id == sta_id)) {
- mvm->tdls_cs.peer.sta_id = IWL_MVM_INVALID_STA;
+ mvm->tdls_cs.peer.sta_id = IWL_INVALID_STA;
cancel_delayed_work(&mvm->tdls_cs.dwork);
}
@@ -2170,9 +2170,9 @@ int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm,
u8 type)
{
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) ||
- sta->sta_id == IWL_MVM_INVALID_STA) {
+ sta->sta_id == IWL_INVALID_STA) {
sta->sta_id = iwl_mvm_find_free_sta_id(mvm, iftype);
- if (WARN_ON_ONCE(sta->sta_id == IWL_MVM_INVALID_STA))
+ if (WARN_ON_ONCE(sta->sta_id == IWL_INVALID_STA))
return -ENOSPC;
}
@@ -2188,7 +2188,7 @@ void iwl_mvm_dealloc_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta)
{
RCU_INIT_POINTER(mvm->fw_id_to_mac_id[sta->sta_id], NULL);
memset(sta, 0, sizeof(struct iwl_mvm_int_sta));
- sta->sta_id = IWL_MVM_INVALID_STA;
+ sta->sta_id = IWL_INVALID_STA;
}
static void iwl_mvm_enable_aux_snif_queue(struct iwl_mvm *mvm, u16 queue,
@@ -2306,7 +2306,7 @@ int iwl_mvm_rm_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
lockdep_assert_held(&mvm->mutex);
- if (WARN_ON_ONCE(mvm->snif_sta.sta_id == IWL_MVM_INVALID_STA))
+ if (WARN_ON_ONCE(mvm->snif_sta.sta_id == IWL_INVALID_STA))
return -EINVAL;
iwl_mvm_disable_txq(mvm, NULL, mvm->snif_sta.sta_id,
@@ -2324,7 +2324,7 @@ int iwl_mvm_rm_aux_sta(struct iwl_mvm *mvm)
lockdep_assert_held(&mvm->mutex);
- if (WARN_ON_ONCE(mvm->aux_sta.sta_id == IWL_MVM_INVALID_STA))
+ if (WARN_ON_ONCE(mvm->aux_sta.sta_id == IWL_INVALID_STA))
return -EINVAL;
iwl_mvm_disable_txq(mvm, NULL, mvm->aux_sta.sta_id,
@@ -2389,7 +2389,7 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
if (vif->type == NL80211_IFTYPE_ADHOC)
baddr = vif->bss_conf.bssid;
- if (WARN_ON_ONCE(bsta->sta_id == IWL_MVM_INVALID_STA))
+ if (WARN_ON_ONCE(bsta->sta_id == IWL_INVALID_STA))
return -ENOSPC;
ret = iwl_mvm_add_int_sta_common(mvm, bsta, baddr,
@@ -2644,7 +2644,7 @@ static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id,
u32 status;
/* This is a valid situation for GTK removal */
- if (sta_id == IWL_MVM_INVALID_STA)
+ if (sta_id == IWL_INVALID_STA)
return 0;
key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
@@ -3514,7 +3514,7 @@ 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->deflink.ap_sta_id != IWL_MVM_INVALID_STA) {
+ mvmvif->deflink.ap_sta_id != IWL_INVALID_STA) {
u8 sta_id = mvmvif->deflink.ap_sta_id;
sta = rcu_dereference_check(mvm->fw_id_to_mac_id[sta_id],
@@ -3569,7 +3569,7 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
int api_ver = iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA_KEY,
new_api ? 2 : 1);
- if (sta_id == IWL_MVM_INVALID_STA)
+ if (sta_id == IWL_INVALID_STA)
return -EINVAL;
keyidx = (key->keyidx << STA_KEY_FLG_KEYID_POS) &
@@ -3728,7 +3728,7 @@ static int iwl_mvm_send_sta_igtk(struct iwl_mvm *mvm,
if (remove_key) {
/* This is a valid situation for IGTK */
- if (sta_id == IWL_MVM_INVALID_STA)
+ if (sta_id == IWL_INVALID_STA)
return 0;
igtk_cmd.ctrl_flags |= cpu_to_le32(STA_KEY_NOT_VALID);
@@ -3795,7 +3795,7 @@ static inline u8 *iwl_mvm_get_mac_addr(struct iwl_mvm *mvm,
return sta->addr;
if (vif->type == NL80211_IFTYPE_STATION &&
- mvmvif->deflink.ap_sta_id != IWL_MVM_INVALID_STA) {
+ mvmvif->deflink.ap_sta_id != IWL_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));
@@ -3865,7 +3865,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
{
bool mcast = !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE);
struct iwl_mvm_sta *mvm_sta;
- u8 sta_id = IWL_MVM_INVALID_STA;
+ u8 sta_id = IWL_INVALID_STA;
int ret;
static const u8 __maybe_unused zero_addr[ETH_ALEN] = {0};
@@ -3966,7 +3966,7 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
{
bool mcast = !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE);
struct iwl_mvm_sta *mvm_sta;
- u8 sta_id = IWL_MVM_INVALID_STA;
+ u8 sta_id = IWL_INVALID_STA;
int ret, i;
lockdep_assert_held(&mvm->mutex);
@@ -4273,7 +4273,7 @@ void iwl_mvm_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
return;
/* Need to block/unblock also multicast station */
- if (mvmvif->deflink.mcast_sta.sta_id != IWL_MVM_INVALID_STA)
+ if (mvmvif->deflink.mcast_sta.sta_id != IWL_INVALID_STA)
iwl_mvm_int_sta_modify_disable_tx(mvm, mvmvif,
&mvmvif->deflink.mcast_sta,
disable);
@@ -4282,7 +4282,7 @@ void iwl_mvm_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
* Only unblock the broadcast station (FW blocks it for immediate
* quiet, not the driver)
*/
- if (!disable && mvmvif->deflink.bcast_sta.sta_id != IWL_MVM_INVALID_STA)
+ if (!disable && mvmvif->deflink.bcast_sta.sta_id != IWL_INVALID_STA)
iwl_mvm_int_sta_modify_disable_tx(mvm, mvmvif,
&mvmvif->deflink.bcast_sta,
disable);
@@ -4328,7 +4328,10 @@ int iwl_mvm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
unsigned int wdg_timeout =
iwl_mvm_get_wd_timeout(mvm, vif);
bool mld = iwl_mvm_has_mld_api(mvm->fw);
- u32 type = mld ? STATION_TYPE_PEER : IWL_STA_LINK;
+ u32 type = IWL_STA_LINK;
+
+ if (mld)
+ type = STATION_TYPE_PEER;
ret = iwl_mvm_allocate_int_sta(mvm, sta, 0,
NL80211_IFTYPE_UNSPECIFIED, type);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c b/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
index 3d25ff5cd7e8..65927ebbabb7 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
@@ -196,7 +196,7 @@ static void iwl_mvm_tdls_update_cs_state(struct iwl_mvm *mvm,
mvm->tdls_cs.peer.sent_timestamp = iwl_mvm_get_systime(mvm);
if (state == IWL_MVM_TDLS_SW_IDLE)
- mvm->tdls_cs.cur_sta_id = IWL_MVM_INVALID_STA;
+ mvm->tdls_cs.cur_sta_id = IWL_INVALID_STA;
}
void iwl_mvm_rx_tdls_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
@@ -250,7 +250,7 @@ iwl_mvm_tdls_check_action(struct iwl_mvm *mvm,
/* get the existing peer if it's there */
if (mvm->tdls_cs.state != IWL_MVM_TDLS_SW_IDLE &&
- mvm->tdls_cs.cur_sta_id != IWL_MVM_INVALID_STA) {
+ mvm->tdls_cs.cur_sta_id != IWL_INVALID_STA) {
struct ieee80211_sta *sta = rcu_dereference_protected(
mvm->fw_id_to_mac_id[mvm->tdls_cs.cur_sta_id],
lockdep_is_held(&mvm->mutex));
@@ -465,7 +465,7 @@ void iwl_mvm_tdls_ch_switch_work(struct work_struct *work)
iwl_mvm_tdls_update_cs_state(mvm, IWL_MVM_TDLS_SW_IDLE);
/* station might be gone, in that case do nothing */
- if (mvm->tdls_cs.peer.sta_id == IWL_MVM_INVALID_STA)
+ if (mvm->tdls_cs.peer.sta_id == IWL_INVALID_STA)
return;
sta = rcu_dereference_protected(
@@ -512,7 +512,7 @@ iwl_mvm_tdls_channel_switch(struct ieee80211_hw *hw,
sta->addr, chandef->chan->center_freq, chandef->width);
/* we only support a single peer for channel switching */
- if (mvm->tdls_cs.peer.sta_id != IWL_MVM_INVALID_STA) {
+ if (mvm->tdls_cs.peer.sta_id != IWL_INVALID_STA) {
IWL_DEBUG_TDLS(mvm,
"Existing peer. Can't start switch with %pM\n",
sta->addr);
@@ -566,7 +566,7 @@ void iwl_mvm_tdls_cancel_channel_switch(struct ieee80211_hw *hw,
IWL_DEBUG_TDLS(mvm, "TDLS cancel channel switch with %pM\n", sta->addr);
/* we only support a single peer for channel switching */
- if (mvm->tdls_cs.peer.sta_id == IWL_MVM_INVALID_STA) {
+ if (mvm->tdls_cs.peer.sta_id == IWL_INVALID_STA) {
IWL_DEBUG_TDLS(mvm, "No ch switch peer - %pM\n", sta->addr);
goto out;
}
@@ -587,7 +587,7 @@ void iwl_mvm_tdls_cancel_channel_switch(struct ieee80211_hw *hw,
mvm->tdls_cs.state != IWL_MVM_TDLS_SW_IDLE)
wait_for_phy = true;
- mvm->tdls_cs.peer.sta_id = IWL_MVM_INVALID_STA;
+ mvm->tdls_cs.peer.sta_id = IWL_INVALID_STA;
dev_kfree_skb(mvm->tdls_cs.peer.skb);
mvm->tdls_cs.peer.skb = NULL;
@@ -630,7 +630,7 @@ iwl_mvm_tdls_recv_channel_switch(struct ieee80211_hw *hw,
if (params->action_code == WLAN_TDLS_CHANNEL_SWITCH_RESPONSE &&
params->status != 0 &&
mvm->tdls_cs.state == IWL_MVM_TDLS_SW_REQ_SENT &&
- mvm->tdls_cs.cur_sta_id != IWL_MVM_INVALID_STA) {
+ mvm->tdls_cs.cur_sta_id != IWL_INVALID_STA) {
struct ieee80211_sta *cur_sta;
/* make sure it's the same peer */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index ca026b5256ce..c9867d26361b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -1213,7 +1213,7 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
if (IWL_MVM_NON_TRANSMITTING_AP && ieee80211_is_probe_resp(fc))
return -1;
- if (WARN_ON_ONCE(mvmsta->deflink.sta_id == IWL_MVM_INVALID_STA))
+ if (WARN_ON_ONCE(mvmsta->deflink.sta_id == IWL_INVALID_STA))
return -1;
if (unlikely(ieee80211_is_any_nullfunc(fc)) && sta->deflink.he_cap.has_he)
@@ -1357,7 +1357,7 @@ int iwl_mvm_tx_skb_sta(struct iwl_mvm *mvm, struct sk_buff *skb,
mvmsta = iwl_mvm_sta_from_mac80211(sta);
- if (WARN_ON_ONCE(mvmsta->deflink.sta_id == IWL_MVM_INVALID_STA))
+ if (WARN_ON_ONCE(mvmsta->deflink.sta_id == IWL_INVALID_STA))
return -1;
memcpy(&info, skb->cb, sizeof(info));
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
index 1d1364d03f02..dd890dcd1505 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
@@ -261,7 +261,7 @@ int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq)
.data = { lq, },
};
- if (WARN_ON(lq->sta_id == IWL_MVM_INVALID_STA ||
+ if (WARN_ON(lq->sta_id == IWL_INVALID_STA ||
iwl_mvm_has_tlc_offload(mvm)))
return -EINVAL;
@@ -679,10 +679,8 @@ struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm)
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_bss_iface_iterator, &bss_iter_data);
- if (bss_iter_data.error) {
- IWL_ERR(mvm, "More than one managed interface active!\n");
+ if (bss_iter_data.error)
return ERR_PTR(-EINVAL);
- }
return bss_iter_data.vif;
}