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/constants.h11
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/d3.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c85
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c27
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw.c232
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c59
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c20
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c58
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/scan.c128
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.h38
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/time-event.c27
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/utils.c18
16 files changed, 451 insertions, 292 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
index 617b41ee5801..1343f25f1090 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
@@ -93,6 +93,15 @@
#define IWL_MVM_ENABLE_EBS 1
#define IWL_MVM_FTM_INITIATOR_ALGO IWL_TOF_ALGO_TYPE_MAX_LIKE
#define IWL_MVM_FTM_INITIATOR_DYNACK true
+#define IWL_MVM_FTM_R2I_MAX_REP 7
+#define IWL_MVM_FTM_I2R_MAX_REP 7
+#define IWL_MVM_FTM_R2I_MAX_STS 1
+#define IWL_MVM_FTM_I2R_MAX_STS 1
+#define IWL_MVM_FTM_R2I_MAX_TOTAL_LTF 3
+#define IWL_MVM_FTM_I2R_MAX_TOTAL_LTF 3
+#define IWL_MVM_FTM_INITIATOR_SECURE_LTF false
+#define IWL_MVM_FTM_RESP_NDP_SUPPORT true
+#define IWL_MVM_FTM_RESP_LMR_FEEDBACK_SUPPORT true
#define IWL_MVM_D3_DEBUG false
#define IWL_MVM_USE_TWT true
#define IWL_MVM_AMPDU_CONSEC_DROPS_DELBA 10
@@ -108,5 +117,7 @@
#define IWL_MVM_FTM_INITIATOR_SMOOTH_OVERSHOOT 20016
#define IWL_MVM_FTM_INITIATOR_SMOOTH_AGE_SEC 2
#define IWL_MVM_DISABLE_AP_FILS false
+#define IWL_MVM_6GHZ_PASSIVE_SCAN_TIMEOUT 3000 /* in seconds */
+#define IWL_MVM_6GHZ_PASSIVE_SCAN_ASSOC_TIMEOUT 60 /* in seconds */
#endif /* __MVM_CONSTANTS_H */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
index a7dc85c704a9..2e28cf299ef4 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
@@ -2028,6 +2028,8 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
mutex_lock(&mvm->mutex);
+ mvm->last_reset_or_resume_time_jiffies = jiffies;
+
/* get the BSS vif pointer again */
vif = iwl_mvm_get_bss_vif(mvm);
if (IS_ERR_OR_NULL(vif))
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
index 34ddef97b099..63d65018d098 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2020 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2021 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -1210,10 +1210,10 @@ static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len)
IWL_UCODE_TLV_API_NEW_BEACON_TEMPLATE))
return -EINVAL;
- rcu_read_lock();
+ mutex_lock(&mvm->mutex);
for (i = 0; i < NUM_MAC_INDEX_DRIVER; i++) {
- vif = iwl_mvm_rcu_dereference_vif_id(mvm, i, true);
+ vif = iwl_mvm_rcu_dereference_vif_id(mvm, i, false);
if (!vif)
continue;
@@ -1253,18 +1253,16 @@ static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len)
&beacon_cmd.tim_size,
beacon->data, beacon->len);
- mutex_lock(&mvm->mutex);
iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd,
sizeof(beacon_cmd));
mutex_unlock(&mvm->mutex);
dev_kfree_skb(beacon);
- rcu_read_unlock();
return 0;
out_err:
- rcu_read_unlock();
+ mutex_unlock(&mvm->mutex);
return -EINVAL;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
index a4fd0bf9ba19..a456b8a0ae58 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
@@ -490,6 +490,15 @@ iwl_mvm_ftm_put_target(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (vif->bss_conf.assoc &&
!memcmp(peer->addr, vif->bss_conf.bssid, ETH_ALEN)) {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct ieee80211_sta *sta;
+
+ rcu_read_lock();
+
+ sta = rcu_dereference(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id]);
+ if (sta->mfp)
+ FTM_PUT_FLAG(PMF);
+
+ rcu_read_unlock();
target->sta_id = mvmvif->ap_sta_id;
} else {
@@ -684,6 +693,19 @@ iwl_mvm_ftm_set_secured_ranging(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
}
}
+static int
+iwl_mvm_ftm_put_target_v7(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct cfg80211_pmsr_request_peer *peer,
+ struct iwl_tof_range_req_ap_entry_v7 *target)
+{
+ int err = iwl_mvm_ftm_put_target(mvm, vif, peer, (void *)target);
+ if (err)
+ return err;
+
+ iwl_mvm_ftm_set_secured_ranging(mvm, vif, target);
+ return err;
+}
+
static int iwl_mvm_ftm_start_v11(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct cfg80211_pmsr_request *req)
@@ -704,11 +726,67 @@ static int iwl_mvm_ftm_start_v11(struct iwl_mvm *mvm,
struct cfg80211_pmsr_request_peer *peer = &req->peers[i];
struct iwl_tof_range_req_ap_entry_v7 *target = &cmd.ap[i];
- err = iwl_mvm_ftm_put_target(mvm, vif, peer, (void *)target);
+ err = iwl_mvm_ftm_put_target_v7(mvm, vif, peer, target);
+ if (err)
+ return err;
+ }
+
+ return iwl_mvm_ftm_send_cmd(mvm, &hcmd);
+}
+
+static void
+iwl_mvm_ftm_set_ndp_params(struct iwl_mvm *mvm,
+ struct iwl_tof_range_req_ap_entry_v8 *target)
+{
+ /* Only 2 STS are supported on Tx */
+ u32 i2r_max_sts = IWL_MVM_FTM_I2R_MAX_STS > 1 ? 1 :
+ IWL_MVM_FTM_I2R_MAX_STS;
+
+ target->r2i_ndp_params = IWL_MVM_FTM_R2I_MAX_REP |
+ (IWL_MVM_FTM_R2I_MAX_STS << IWL_LOCATION_MAX_STS_POS);
+ target->i2r_ndp_params = IWL_MVM_FTM_I2R_MAX_REP |
+ (i2r_max_sts << IWL_LOCATION_MAX_STS_POS);
+ target->r2i_max_total_ltf = IWL_MVM_FTM_R2I_MAX_TOTAL_LTF;
+ target->i2r_max_total_ltf = IWL_MVM_FTM_I2R_MAX_TOTAL_LTF;
+}
+
+static int iwl_mvm_ftm_start_v12(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct cfg80211_pmsr_request *req)
+{
+ struct iwl_tof_range_req_cmd_v12 cmd;
+ struct iwl_host_cmd hcmd = {
+ .id = iwl_cmd_id(TOF_RANGE_REQ_CMD, LOCATION_GROUP, 0),
+ .dataflags[0] = IWL_HCMD_DFL_DUP,
+ .data[0] = &cmd,
+ .len[0] = sizeof(cmd),
+ };
+ u8 i;
+ int err;
+
+ iwl_mvm_ftm_cmd_common(mvm, vif, (void *)&cmd, req);
+
+ for (i = 0; i < cmd.num_of_ap; i++) {
+ struct cfg80211_pmsr_request_peer *peer = &req->peers[i];
+ struct iwl_tof_range_req_ap_entry_v8 *target = &cmd.ap[i];
+ u32 flags;
+
+ err = iwl_mvm_ftm_put_target_v7(mvm, vif, peer, (void *)target);
if (err)
return err;
- iwl_mvm_ftm_set_secured_ranging(mvm, vif, target);
+ iwl_mvm_ftm_set_ndp_params(mvm, target);
+
+ /*
+ * If secure LTF is turned off, replace the flag with PMF only
+ */
+ flags = le32_to_cpu(target->initiator_ap_flags);
+ if ((flags & IWL_INITIATOR_AP_FLAGS_SECURED) &&
+ !IWL_MVM_FTM_INITIATOR_SECURE_LTF) {
+ flags &= ~IWL_INITIATOR_AP_FLAGS_SECURED;
+ flags |= IWL_INITIATOR_AP_FLAGS_PMF;
+ target->initiator_ap_flags = cpu_to_le32(flags);
+ }
}
return iwl_mvm_ftm_send_cmd(mvm, &hcmd);
@@ -732,6 +810,9 @@ int iwl_mvm_ftm_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
IWL_FW_CMD_VER_UNKNOWN);
switch (cmd_ver) {
+ case 12:
+ err = iwl_mvm_ftm_start_v12(mvm, vif, req);
+ break;
case 11:
err = iwl_mvm_ftm_start_v11(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 996f45c19f10..5a249ea97eb2 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
@@ -75,6 +75,24 @@ static int iwl_mvm_ftm_responder_set_bw_v2(struct cfg80211_chan_def *chandef,
return 0;
}
+static void
+iwl_mvm_ftm_responder_set_ndp(struct iwl_mvm *mvm,
+ struct iwl_tof_responder_config_cmd_v8 *cmd)
+{
+ /* Up to 2 R2I STS are allowed on the responder */
+ u32 r2i_max_sts = IWL_MVM_FTM_R2I_MAX_STS < 2 ?
+ IWL_MVM_FTM_R2I_MAX_STS : 1;
+
+ cmd->r2i_ndp_params = IWL_MVM_FTM_R2I_MAX_REP |
+ (r2i_max_sts << IWL_RESPONDER_STS_POS) |
+ (IWL_MVM_FTM_R2I_MAX_TOTAL_LTF << IWL_RESPONDER_TOTAL_LTF_POS);
+ cmd->i2r_ndp_params = IWL_MVM_FTM_I2R_MAX_REP |
+ (IWL_MVM_FTM_I2R_MAX_STS << IWL_RESPONDER_STS_POS) |
+ (IWL_MVM_FTM_I2R_MAX_TOTAL_LTF << IWL_RESPONDER_TOTAL_LTF_POS);
+ cmd->cmd_valid_fields |=
+ cpu_to_le32(IWL_TOF_RESPONDER_CMD_VALID_NDP_PARAMS);
+}
+
static int
iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
@@ -82,11 +100,11 @@ iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm,
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
/*
- * The command structure is the same for versions 6 and 7, (only the
+ * The command structure is the same for versions 6, 7 and 8 (only the
* field interpretation is different), so the same struct can be use
* for all cases.
*/
- struct iwl_tof_responder_config_cmd cmd = {
+ struct iwl_tof_responder_config_cmd_v8 cmd = {
.channel_num = chandef->chan->hw_value,
.cmd_valid_fields =
cpu_to_le32(IWL_TOF_RESPONDER_CMD_VALID_CHAN_INFO |
@@ -100,7 +118,10 @@ iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm,
lockdep_assert_held(&mvm->mutex);
- if (cmd_ver == 7)
+if (cmd_ver == 8)
+ iwl_mvm_ftm_responder_set_ndp(mvm, &cmd);
+
+ if (cmd_ver >= 7)
err = iwl_mvm_ftm_responder_set_bw_v2(chandef, &cmd.format_bw,
&cmd.ctrl_ch_position);
else
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index 5ee64f7f3c85..8aa5f1a2c58c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2020 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2021 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -29,6 +29,9 @@
#define UCODE_VALID_OK cpu_to_le32(0x1)
+#define IWL_PPAG_MASK 3
+#define IWL_PPAG_ETSI_MASK BIT(0)
+
struct iwl_mvm_alive_data {
bool valid;
u32 scd_base_addr;
@@ -70,56 +73,6 @@ static int iwl_send_rss_cfg_cmd(struct iwl_mvm *mvm)
return iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0, sizeof(cmd), &cmd);
}
-static int iwl_configure_rxq(struct iwl_mvm *mvm)
-{
- int i, num_queues, size, ret;
- struct iwl_rfh_queue_config *cmd;
- struct iwl_host_cmd hcmd = {
- .id = WIDE_ID(DATA_PATH_GROUP, RFH_QUEUE_CONFIG_CMD),
- .dataflags[0] = IWL_HCMD_DFL_NOCOPY,
- };
-
- /*
- * The default queue is configured via context info, so if we
- * have a single queue, there's nothing to do here.
- */
- if (mvm->trans->num_rx_queues == 1)
- return 0;
-
- /* skip the default queue */
- num_queues = mvm->trans->num_rx_queues - 1;
-
- size = struct_size(cmd, data, num_queues);
-
- cmd = kzalloc(size, GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
-
- cmd->num_queues = num_queues;
-
- for (i = 0; i < num_queues; i++) {
- struct iwl_trans_rxq_dma_data data;
-
- cmd->data[i].q_num = i + 1;
- iwl_trans_get_rxq_dma_data(mvm->trans, i + 1, &data);
-
- cmd->data[i].fr_bd_cb = cpu_to_le64(data.fr_bd_cb);
- cmd->data[i].urbd_stts_wrptr =
- cpu_to_le64(data.urbd_stts_wrptr);
- cmd->data[i].ur_bd_cb = cpu_to_le64(data.ur_bd_cb);
- cmd->data[i].fr_bd_wid = cpu_to_le32(data.fr_bd_wid);
- }
-
- hcmd.data[0] = cmd;
- hcmd.len[0] = size;
-
- ret = iwl_mvm_send_cmd(mvm, &hcmd);
-
- kfree(cmd);
-
- return ret;
-}
-
static int iwl_mvm_send_dqa_cmd(struct iwl_mvm *mvm)
{
struct iwl_dqa_enable_cmd dqa_cmd = {
@@ -233,7 +186,8 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
mvm->trans->dbg.lmac_error_event_table[1] =
le32_to_cpu(lmac2->dbg_ptrs.error_event_table_ptr);
- umac_error_table = le32_to_cpu(umac->dbg_ptrs.error_info_addr);
+ umac_error_table = le32_to_cpu(umac->dbg_ptrs.error_info_addr) &
+ ~FW_ADDR_CACHE_CONTROL;
if (umac_error_table) {
if (umac_error_table >=
@@ -773,16 +727,16 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
} else if (fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_REDUCE_TX_POWER)) {
len = sizeof(cmd.v5);
- n_subbands = IWL_NUM_SUB_BANDS;
+ n_subbands = IWL_NUM_SUB_BANDS_V1;
per_chain = cmd.v5.per_chain[0][0];
} else if (fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_TX_POWER_ACK)) {
len = sizeof(cmd.v4);
- n_subbands = IWL_NUM_SUB_BANDS;
+ n_subbands = IWL_NUM_SUB_BANDS_V1;
per_chain = cmd.v4.per_chain[0][0];
} else {
len = sizeof(cmd.v3);
- n_subbands = IWL_NUM_SUB_BANDS;
+ n_subbands = IWL_NUM_SUB_BANDS_V1;
per_chain = cmd.v3.per_chain[0][0];
}
@@ -909,46 +863,50 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm)
{
- union acpi_object *wifi_pkg, *data, *enabled;
+ union acpi_object *wifi_pkg, *data, *flags;
int i, j, ret, tbl_rev, num_sub_bands;
int idx = 2;
s8 *gain;
/*
- * The 'enabled' field is the same in v1 and v2 so we can just
+ * The 'flags' field is the same in v1 and in v2 so we can just
* use v1 to access it.
*/
- mvm->fwrt.ppag_table.v1.enabled = cpu_to_le32(0);
+ mvm->fwrt.ppag_table.v1.flags = cpu_to_le32(0);
+
data = iwl_acpi_get_object(mvm->dev, ACPI_PPAG_METHOD);
if (IS_ERR(data))
return PTR_ERR(data);
- /* try to read ppag table revision 1 */
+ /* try to read ppag table rev 2 or 1 (both have the same data size) */
wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
ACPI_PPAG_WIFI_DATA_SIZE_V2, &tbl_rev);
if (!IS_ERR(wifi_pkg)) {
- if (tbl_rev != 1) {
+ if (tbl_rev == 1 || tbl_rev == 2) {
+ num_sub_bands = IWL_NUM_SUB_BANDS_V2;
+ gain = mvm->fwrt.ppag_table.v2.gain[0];
+ mvm->fwrt.ppag_ver = tbl_rev;
+ IWL_DEBUG_RADIO(mvm,
+ "Reading PPAG table v2 (tbl_rev=%d)\n",
+ tbl_rev);
+ goto read_table;
+ } else {
ret = -EINVAL;
goto out_free;
}
- num_sub_bands = IWL_NUM_SUB_BANDS_V2;
- gain = mvm->fwrt.ppag_table.v2.gain[0];
- mvm->fwrt.ppag_ver = 2;
- IWL_DEBUG_RADIO(mvm, "Reading PPAG table v2 (tbl_rev=1)\n");
- goto read_table;
}
/* try to read ppag table revision 0 */
wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
- ACPI_PPAG_WIFI_DATA_SIZE, &tbl_rev);
+ ACPI_PPAG_WIFI_DATA_SIZE_V1, &tbl_rev);
if (!IS_ERR(wifi_pkg)) {
if (tbl_rev != 0) {
ret = -EINVAL;
goto out_free;
}
- num_sub_bands = IWL_NUM_SUB_BANDS;
+ num_sub_bands = IWL_NUM_SUB_BANDS_V1;
gain = mvm->fwrt.ppag_table.v1.gain[0];
- mvm->fwrt.ppag_ver = 1;
+ mvm->fwrt.ppag_ver = 0;
IWL_DEBUG_RADIO(mvm, "Reading PPAG table v1 (tbl_rev=0)\n");
goto read_table;
}
@@ -956,15 +914,17 @@ static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm)
goto out_free;
read_table:
- enabled = &wifi_pkg->package.elements[1];
- if (enabled->type != ACPI_TYPE_INTEGER ||
- (enabled->integer.value != 0 && enabled->integer.value != 1)) {
+ flags = &wifi_pkg->package.elements[1];
+
+ if (flags->type != ACPI_TYPE_INTEGER) {
ret = -EINVAL;
goto out_free;
}
- mvm->fwrt.ppag_table.v1.enabled = cpu_to_le32(enabled->integer.value);
- if (!mvm->fwrt.ppag_table.v1.enabled) {
+ mvm->fwrt.ppag_table.v1.flags = cpu_to_le32(flags->integer.value &
+ IWL_PPAG_MASK);
+
+ if (!mvm->fwrt.ppag_table.v1.flags) {
ret = 0;
goto out_free;
}
@@ -992,12 +952,13 @@ read_table:
(j != 0 &&
(gain[i * num_sub_bands + j] > ACPI_PPAG_MAX_HB ||
gain[i * num_sub_bands + j] < ACPI_PPAG_MIN_HB))) {
- mvm->fwrt.ppag_table.v1.enabled = cpu_to_le32(0);
+ mvm->fwrt.ppag_table.v1.flags = cpu_to_le32(0);
ret = -EINVAL;
goto out_free;
}
}
}
+
ret = 0;
out_free:
kfree(data);
@@ -1015,7 +976,7 @@ int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
"PPAG capability not supported by FW, command not sent.\n");
return 0;
}
- if (!mvm->fwrt.ppag_table.v1.enabled) {
+ if (!mvm->fwrt.ppag_table.v1.flags) {
IWL_DEBUG_RADIO(mvm, "PPAG not enabled, command not sent.\n");
return 0;
}
@@ -1024,20 +985,28 @@ int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
PER_PLATFORM_ANT_GAIN_CMD,
IWL_FW_CMD_VER_UNKNOWN);
if (cmd_ver == 1) {
- num_sub_bands = IWL_NUM_SUB_BANDS;
+ num_sub_bands = IWL_NUM_SUB_BANDS_V1;
gain = mvm->fwrt.ppag_table.v1.gain[0];
cmd_size = sizeof(mvm->fwrt.ppag_table.v1);
- if (mvm->fwrt.ppag_ver == 2) {
+ if (mvm->fwrt.ppag_ver == 1 || mvm->fwrt.ppag_ver == 2) {
IWL_DEBUG_RADIO(mvm,
- "PPAG table is v2 but FW supports v1, sending truncated table\n");
+ "PPAG table rev is %d but FW supports v1, sending truncated table\n",
+ mvm->fwrt.ppag_ver);
+ mvm->fwrt.ppag_table.v1.flags &=
+ cpu_to_le32(IWL_PPAG_ETSI_MASK);
}
- } else if (cmd_ver == 2) {
+ } else if (cmd_ver == 2 || cmd_ver == 3) {
num_sub_bands = IWL_NUM_SUB_BANDS_V2;
gain = mvm->fwrt.ppag_table.v2.gain[0];
cmd_size = sizeof(mvm->fwrt.ppag_table.v2);
- if (mvm->fwrt.ppag_ver == 1) {
+ if (mvm->fwrt.ppag_ver == 0) {
IWL_DEBUG_RADIO(mvm,
"PPAG table is v1 but FW supports v2, sending padded table\n");
+ } else if (cmd_ver == 2 && mvm->fwrt.ppag_ver == 2) {
+ IWL_DEBUG_RADIO(mvm,
+ "PPAG table is v3 but FW supports v2, sending partial bitmap.\n");
+ mvm->fwrt.ppag_table.v1.flags &=
+ cpu_to_le32(IWL_PPAG_ETSI_MASK);
}
} else {
IWL_DEBUG_RADIO(mvm, "Unsupported PPAG command version\n");
@@ -1102,7 +1071,7 @@ static int iwl_mvm_ppag_init(struct iwl_mvm *mvm)
IWL_DEBUG_RADIO(mvm,
"System vendor '%s' is not in the approved list, disabling PPAG.\n",
dmi_get_system_info(DMI_SYS_VENDOR));
- mvm->fwrt.ppag_table.v1.enabled = cpu_to_le32(0);
+ mvm->fwrt.ppag_table.v1.flags = cpu_to_le32(0);
return 0;
}
@@ -1144,33 +1113,6 @@ static void iwl_mvm_tas_init(struct iwl_mvm *mvm)
IWL_DEBUG_RADIO(mvm, "failed to send TAS_CONFIG (%d)\n", ret);
}
-static u8 iwl_mvm_eval_dsm_indonesia_5g2(struct iwl_mvm *mvm)
-{
- u8 value;
-
- int ret = iwl_acpi_get_dsm_u8((&mvm->fwrt)->dev, 0,
- DSM_FUNC_ENABLE_INDONESIA_5G2,
- &iwl_guid, &value);
-
- if (ret < 0)
- IWL_DEBUG_RADIO(mvm,
- "Failed to evaluate DSM function ENABLE_INDONESIA_5G2, ret=%d\n",
- ret);
-
- else if (value >= DSM_VALUE_INDONESIA_MAX)
- IWL_DEBUG_RADIO(mvm,
- "DSM function ENABLE_INDONESIA_5G2 return invalid value, value=%d\n",
- value);
-
- else if (value == DSM_VALUE_INDONESIA_ENABLE) {
- IWL_DEBUG_RADIO(mvm,
- "Evaluated DSM function ENABLE_INDONESIA_5G2: Enabling 5g2\n");
- return DSM_VALUE_INDONESIA_ENABLE;
- }
- /* default behaviour is disabled */
- return DSM_VALUE_INDONESIA_DISABLE;
-}
-
static u8 iwl_mvm_eval_dsm_rfi(struct iwl_mvm *mvm)
{
u8 value;
@@ -1195,64 +1137,27 @@ static u8 iwl_mvm_eval_dsm_rfi(struct iwl_mvm *mvm)
return DSM_VALUE_RFI_DISABLE;
}
-static u8 iwl_mvm_eval_dsm_disable_srd(struct iwl_mvm *mvm)
-{
- u8 value;
- int ret = iwl_acpi_get_dsm_u8((&mvm->fwrt)->dev, 0,
- DSM_FUNC_DISABLE_SRD,
- &iwl_guid, &value);
-
- if (ret < 0)
- IWL_DEBUG_RADIO(mvm,
- "Failed to evaluate DSM function DISABLE_SRD, ret=%d\n",
- ret);
-
- else if (value >= DSM_VALUE_SRD_MAX)
- IWL_DEBUG_RADIO(mvm,
- "DSM function DISABLE_SRD return invalid value, value=%d\n",
- value);
-
- else if (value == DSM_VALUE_SRD_PASSIVE) {
- IWL_DEBUG_RADIO(mvm,
- "Evaluated DSM function DISABLE_SRD: setting SRD to passive\n");
- return DSM_VALUE_SRD_PASSIVE;
-
- } else if (value == DSM_VALUE_SRD_DISABLE) {
- IWL_DEBUG_RADIO(mvm,
- "Evaluated DSM function DISABLE_SRD: disabling SRD\n");
- return DSM_VALUE_SRD_DISABLE;
- }
- /* default behaviour is active */
- return DSM_VALUE_SRD_ACTIVE;
-}
-
static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm)
{
- u8 ret;
int cmd_ret;
- struct iwl_lari_config_change_cmd_v2 cmd = {};
-
- if (iwl_mvm_eval_dsm_indonesia_5g2(mvm) == DSM_VALUE_INDONESIA_ENABLE)
- cmd.config_bitmap |=
- cpu_to_le32(LARI_CONFIG_ENABLE_5G2_IN_INDONESIA_MSK);
+ struct iwl_lari_config_change_cmd_v3 cmd = {};
- ret = iwl_mvm_eval_dsm_disable_srd(mvm);
- if (ret == DSM_VALUE_SRD_PASSIVE)
- cmd.config_bitmap |=
- cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_PASSIVE_MSK);
-
- else if (ret == DSM_VALUE_SRD_DISABLE)
- cmd.config_bitmap |=
- cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_DISABLED_MSK);
+ cmd.config_bitmap = iwl_acpi_get_lari_config_bitmap(&mvm->fwrt);
/* apply more config masks here */
if (cmd.config_bitmap) {
- size_t cmd_size = iwl_fw_lookup_cmd_ver(mvm->fw,
- REGULATORY_AND_NVM_GROUP,
- LARI_CONFIG_CHANGE, 1) == 2 ?
- sizeof(struct iwl_lari_config_change_cmd_v2) :
- sizeof(struct iwl_lari_config_change_cmd_v1);
+ size_t cmd_size;
+ u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
+ REGULATORY_AND_NVM_GROUP,
+ LARI_CONFIG_CHANGE, 1);
+ if (cmd_ver == 3)
+ cmd_size = sizeof(struct iwl_lari_config_change_cmd_v3);
+ else if (cmd_ver == 2)
+ cmd_size = sizeof(struct iwl_lari_config_change_cmd_v2);
+ else
+ cmd_size = sizeof(struct iwl_lari_config_change_cmd_v1);
+
IWL_DEBUG_RADIO(mvm,
"sending LARI_CONFIG_CHANGE, config_bitmap=0x%x\n",
le32_to_cpu(cmd.config_bitmap));
@@ -1485,14 +1390,9 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
}
/* Init RSS configuration */
- if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
- ret = iwl_configure_rxq(mvm);
- if (ret) {
- IWL_ERR(mvm, "Failed to configure RX queues: %d\n",
- ret);
- goto error;
- }
- }
+ ret = iwl_configure_rxq(&mvm->fwrt);
+ if (ret)
+ goto error;
if (iwl_mvm_has_new_rx_api(mvm)) {
ret = iwl_send_rss_cfg_cmd(mvm);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index baf7404c137d..607d5d564928 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -1099,6 +1099,8 @@ int __iwl_mvm_mac_start(struct iwl_mvm *mvm)
iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_PERIODIC,
NULL);
+ mvm->last_reset_or_resume_time_jiffies = jiffies;
+
if (ret && test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
/* Something went wrong - we need to finish some cleanup
* that normally iwl_mvm_mac_restart_complete() below
@@ -4610,6 +4612,16 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
break;
case NL80211_IFTYPE_STATION:
+ /*
+ * We haven't configured the firmware to be associated yet since
+ * we don't know the dtim period. In this case, the firmware can't
+ * track the beacons.
+ */
+ if (!vif->bss_conf.assoc || !vif->bss_conf.dtim_period) {
+ ret = -EBUSY;
+ goto out_unlock;
+ }
+
if (chsw->delay > IWL_MAX_CSA_BLOCK_TX)
schedule_delayed_work(&mvmvif->csa_work, 0);
@@ -5134,28 +5146,50 @@ static void iwl_mvm_mac_event_callback(struct ieee80211_hw *hw,
}
void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
- struct iwl_mvm_internal_rxq_notif *notif,
- u32 size)
+ enum iwl_mvm_rxq_notif_type type,
+ bool sync,
+ const void *data, u32 size)
{
- u32 qmask = BIT(mvm->trans->num_rx_queues) - 1;
+ struct {
+ struct iwl_rxq_sync_cmd cmd;
+ struct iwl_mvm_internal_rxq_notif notif;
+ } __packed cmd = {
+ .cmd.rxq_mask = cpu_to_le32(BIT(mvm->trans->num_rx_queues) - 1),
+ .cmd.count =
+ cpu_to_le32(sizeof(struct iwl_mvm_internal_rxq_notif) +
+ size),
+ .notif.type = type,
+ .notif.sync = sync,
+ };
+ struct iwl_host_cmd hcmd = {
+ .id = WIDE_ID(DATA_PATH_GROUP, TRIGGER_RX_QUEUES_NOTIF_CMD),
+ .data[0] = &cmd,
+ .len[0] = sizeof(cmd),
+ .data[1] = data,
+ .len[1] = size,
+ .flags = sync ? 0 : CMD_ASYNC,
+ };
int ret;
+ /* size must be a multiple of DWORD */
+ if (WARN_ON(cmd.cmd.count & cpu_to_le32(3)))
+ return;
if (!iwl_mvm_has_new_rx_api(mvm))
return;
- if (notif->sync) {
- notif->cookie = mvm->queue_sync_cookie;
+ if (sync) {
+ cmd.notif.cookie = mvm->queue_sync_cookie;
mvm->queue_sync_state = (1 << mvm->trans->num_rx_queues) - 1;
}
- ret = iwl_mvm_notify_rx_queue(mvm, qmask, notif, size, !notif->sync);
+ ret = iwl_mvm_send_cmd(mvm, &hcmd);
if (ret) {
IWL_ERR(mvm, "Failed to trigger RX queues sync (%d)\n", ret);
goto out;
}
- if (notif->sync) {
+ if (sync) {
lockdep_assert_held(&mvm->mutex);
ret = wait_event_timeout(mvm->rx_sync_waitq,
READ_ONCE(mvm->queue_sync_state) == 0 ||
@@ -5167,21 +5201,18 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
}
out:
- mvm->queue_sync_state = 0;
- if (notif->sync)
+ if (sync) {
+ mvm->queue_sync_state = 0;
mvm->queue_sync_cookie++;
+ }
}
static void iwl_mvm_sync_rx_queues(struct ieee80211_hw *hw)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- struct iwl_mvm_internal_rxq_notif data = {
- .type = IWL_MVM_RXQ_EMPTY,
- .sync = 1,
- };
mutex_lock(&mvm->mutex);
- iwl_mvm_sync_rx_queues_internal(mvm, &data, sizeof(data));
+ iwl_mvm_sync_rx_queues_internal(mvm, IWL_MVM_RXQ_EMPTY, true, NULL, 0);
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 0a963d01b825..4d9d4d6892fc 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -591,7 +591,6 @@ struct iwl_mvm_tcm {
enum iwl_mvm_traffic_load global_load;
bool low_latency[NUM_MAC_INDEX_DRIVER];
bool change[NUM_MAC_INDEX_DRIVER];
- bool global_change;
} result;
};
@@ -1096,6 +1095,9 @@ struct iwl_mvm {
/* sniffer data to include in radiotap */
__le16 cur_aid;
u8 cur_bssid[ETH_ALEN];
+
+ unsigned long last_6ghz_passive_scan_jiffies;
+ unsigned long last_reset_or_resume_time_jiffies;
};
/* Extract MVM priv from op_mode and _hw */
@@ -1570,9 +1572,6 @@ void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb, int queue);
void iwl_mvm_rx_bar_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb, int queue);
-int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask,
- const struct iwl_mvm_internal_rxq_notif *notif,
- u32 notif_size, bool async);
void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb, int queue);
void iwl_mvm_rx_tx_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
@@ -2001,8 +2000,9 @@ void iwl_mvm_rx_tdls_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_tdls_ch_switch_work(struct work_struct *work);
void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
- struct iwl_mvm_internal_rxq_notif *notif,
- u32 size);
+ enum iwl_mvm_rxq_notif_type type,
+ bool sync,
+ const void *data, u32 size);
void iwl_mvm_reorder_timer_expired(struct timer_list *t);
struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm);
struct ieee80211_vif *iwl_mvm_get_vif_by_macid(struct iwl_mvm *mvm, u32 macid);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
index 8772b65c9dab..2d58cb969918 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2020 Intel Corporation
+ * Copyright (C) 2018-2021 Intel Corporation
*/
#include "rs.h"
#include "fw-api.h"
@@ -72,19 +72,15 @@ static u16 rs_fw_get_config_flags(struct iwl_mvm *mvm,
bool vht_ena = vht_cap->vht_supported;
u16 flags = 0;
+ /* get STBC flags */
if (mvm->cfg->ht_params->stbc &&
(num_of_ant(iwl_mvm_get_valid_tx_ant(mvm)) > 1)) {
- if (he_cap->has_he) {
- if (he_cap->he_cap_elem.phy_cap_info[2] &
- IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ)
- flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK;
-
- if (he_cap->he_cap_elem.phy_cap_info[7] &
- IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ)
- flags |= IWL_TLC_MNG_CFG_FLAGS_HE_STBC_160MHZ_MSK;
- } else if ((ht_cap->cap & IEEE80211_HT_CAP_RX_STBC) ||
- (vht_ena &&
- (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK)))
+ if (he_cap->has_he && he_cap->he_cap_elem.phy_cap_info[2] &
+ IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ)
+ flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK;
+ else if (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK)
+ flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK;
+ else if (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC)
flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
index 91b6541d579f..b97708cb869d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/******************************************************************************
*
- * Copyright(c) 2005 - 2014, 2018 - 2020 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014, 2018 - 2021 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
*
@@ -1926,9 +1926,7 @@ static bool rs_tpc_allowed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (is_ht(rate))
return index == IWL_RATE_MCS_7_INDEX;
if (is_vht(rate))
- return index == IWL_RATE_MCS_7_INDEX ||
- index == IWL_RATE_MCS_8_INDEX ||
- index == IWL_RATE_MCS_9_INDEX;
+ return index == IWL_RATE_MCS_9_INDEX;
WARN_ON_ONCE(1);
return false;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
index af5a6dd81c41..8e26422ca326 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
@@ -527,37 +527,6 @@ static bool iwl_mvm_is_dup(struct ieee80211_sta *sta, int queue,
return false;
}
-int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask,
- const struct iwl_mvm_internal_rxq_notif *notif,
- u32 notif_size, bool async)
-{
- u8 buf[sizeof(struct iwl_rxq_sync_cmd) +
- sizeof(struct iwl_mvm_rss_sync_notif)];
- struct iwl_rxq_sync_cmd *cmd = (void *)buf;
- u32 data_size = sizeof(*cmd) + notif_size;
- int ret;
-
- /*
- * size must be a multiple of DWORD
- * Ensure we don't overflow buf
- */
- if (WARN_ON(notif_size & 3 ||
- notif_size > sizeof(struct iwl_mvm_rss_sync_notif)))
- return -EINVAL;
-
- cmd->rxq_mask = cpu_to_le32(rxq_mask);
- cmd->count = cpu_to_le32(notif_size);
- cmd->flags = 0;
- memcpy(cmd->payload, notif, notif_size);
-
- ret = iwl_mvm_send_cmd_pdu(mvm,
- WIDE_ID(DATA_PATH_GROUP,
- TRIGGER_RX_QUEUES_NOTIF_CMD),
- async ? CMD_ASYNC : 0, data_size, cmd);
-
- return ret;
-}
-
/*
* Returns true if sn2 - buffer_size < sn1 < sn2.
* To be used only in order to compare reorder buffer head with NSSN.
@@ -573,15 +542,13 @@ static bool iwl_mvm_is_sn_less(u16 sn1, u16 sn2, u16 buffer_size)
static void iwl_mvm_sync_nssn(struct iwl_mvm *mvm, u8 baid, u16 nssn)
{
if (IWL_MVM_USE_NSSN_SYNC) {
- struct iwl_mvm_rss_sync_notif notif = {
- .metadata.type = IWL_MVM_RXQ_NSSN_SYNC,
- .metadata.sync = 0,
- .nssn_sync.baid = baid,
- .nssn_sync.nssn = nssn,
+ struct iwl_mvm_nssn_sync_data notif = {
+ .baid = baid,
+ .nssn = nssn,
};
- iwl_mvm_sync_rx_queues_internal(mvm, (void *)&notif,
- sizeof(notif));
+ iwl_mvm_sync_rx_queues_internal(mvm, IWL_MVM_RXQ_NSSN_SYNC, false,
+ &notif, sizeof(notif));
}
}
@@ -830,8 +797,7 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
"invalid notification size %d (%d)",
len, (int)(sizeof(*notif) + sizeof(*internal_notif))))
return;
- /* remove only the firmware header, we want all of our payload below */
- len -= sizeof(*notif);
+ len -= sizeof(*notif) + sizeof(*internal_notif);
if (internal_notif->sync &&
mvm->queue_sync_cookie != internal_notif->cookie) {
@@ -841,21 +807,19 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
switch (internal_notif->type) {
case IWL_MVM_RXQ_EMPTY:
- WARN_ONCE(len != sizeof(*internal_notif),
- "invalid empty notification size %d (%d)",
- len, (int)sizeof(*internal_notif));
+ WARN_ONCE(len, "invalid empty notification size %d", len);
break;
case IWL_MVM_RXQ_NOTIF_DEL_BA:
- if (WARN_ONCE(len != sizeof(struct iwl_mvm_rss_sync_notif),
+ if (WARN_ONCE(len != sizeof(struct iwl_mvm_delba_data),
"invalid delba notification size %d (%d)",
- len, (int)sizeof(struct iwl_mvm_rss_sync_notif)))
+ len, (int)sizeof(struct iwl_mvm_delba_data)))
break;
iwl_mvm_del_ba(mvm, queue, (void *)internal_notif->data);
break;
case IWL_MVM_RXQ_NSSN_SYNC:
- if (WARN_ONCE(len != sizeof(struct iwl_mvm_rss_sync_notif),
+ if (WARN_ONCE(len != sizeof(struct iwl_mvm_nssn_sync_data),
"invalid nssn sync notification size %d (%d)",
- len, (int)sizeof(struct iwl_mvm_rss_sync_notif)))
+ len, (int)sizeof(struct iwl_mvm_nssn_sync_data)))
break;
iwl_mvm_nssn_sync(mvm, napi, queue,
(void *)internal_notif->data);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
index caf87f320094..5a0696c44f6d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -43,6 +43,9 @@
/* adaptive dwell number of APs override for social channels */
#define IWL_SCAN_ADWELL_N_APS_SOCIAL_CHS 2
+/* minimal number of 2GHz and 5GHz channels in the regular scan request */
+#define IWL_MVM_6GHZ_PASSIVE_SCAN_MIN_CHANS 4
+
struct iwl_mvm_scan_timing_params {
u32 suspend_time;
u32 max_out_time;
@@ -94,6 +97,7 @@ struct iwl_mvm_scan_params {
struct cfg80211_scan_6ghz_params *scan_6ghz_params;
u32 n_6ghz_params;
bool scan_6ghz;
+ bool enable_6ghz_passive;
};
static inline void *iwl_mvm_get_scan_req_umac_data(struct iwl_mvm *mvm)
@@ -1873,6 +1877,98 @@ static u8 iwl_mvm_scan_umac_chan_flags_v2(struct iwl_mvm *mvm,
return flags;
}
+static void iwl_mvm_scan_6ghz_passive_scan(struct iwl_mvm *mvm,
+ struct iwl_mvm_scan_params *params,
+ struct ieee80211_vif *vif)
+{
+ struct ieee80211_supported_band *sband =
+ &mvm->nvm_data->bands[NL80211_BAND_6GHZ];
+ u32 n_disabled, i;
+
+ params->enable_6ghz_passive = false;
+
+ if (params->scan_6ghz)
+ return;
+
+ if (!fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_PASSIVE_6GHZ_SCAN)) {
+ IWL_DEBUG_SCAN(mvm,
+ "6GHz passive scan: Not supported by FW\n");
+ return;
+ }
+
+ /* 6GHz passive scan allowed only on station interface */
+ if (vif->type != NL80211_IFTYPE_STATION) {
+ IWL_DEBUG_SCAN(mvm,
+ "6GHz passive scan: not station interface\n");
+ return;
+ }
+
+ /*
+ * 6GHz passive scan is allowed while associated in a defined time
+ * interval following HW reset or resume flow
+ */
+ if (vif->bss_conf.assoc &&
+ (time_before(mvm->last_reset_or_resume_time_jiffies +
+ (IWL_MVM_6GHZ_PASSIVE_SCAN_ASSOC_TIMEOUT * HZ),
+ jiffies))) {
+ IWL_DEBUG_SCAN(mvm, "6GHz passive scan: associated\n");
+ return;
+ }
+
+ /* No need for 6GHz passive scan if not enough time elapsed */
+ if (time_after(mvm->last_6ghz_passive_scan_jiffies +
+ (IWL_MVM_6GHZ_PASSIVE_SCAN_TIMEOUT * HZ), jiffies)) {
+ IWL_DEBUG_SCAN(mvm,
+ "6GHz passive scan: timeout did not expire\n");
+ return;
+ }
+
+ /* not enough channels in the regular scan request */
+ if (params->n_channels < IWL_MVM_6GHZ_PASSIVE_SCAN_MIN_CHANS) {
+ IWL_DEBUG_SCAN(mvm,
+ "6GHz passive scan: not enough channels\n");
+ return;
+ }
+
+ for (i = 0; i < params->n_ssids; i++) {
+ if (!params->ssids[i].ssid_len)
+ break;
+ }
+
+ /* not a wildcard scan, so cannot enable passive 6GHz scan */
+ if (i == params->n_ssids) {
+ IWL_DEBUG_SCAN(mvm,
+ "6GHz passive scan: no wildcard SSID\n");
+ return;
+ }
+
+ if (!sband || !sband->n_channels) {
+ IWL_DEBUG_SCAN(mvm,
+ "6GHz passive scan: no 6GHz channels\n");
+ return;
+ }
+
+ for (i = 0, n_disabled = 0; i < sband->n_channels; i++) {
+ if (sband->channels[i].flags & (IEEE80211_CHAN_DISABLED))
+ n_disabled++;
+ }
+
+ /*
+ * Not all the 6GHz channels are disabled, so no need for 6GHz passive
+ * scan
+ */
+ if (n_disabled != sband->n_channels) {
+ IWL_DEBUG_SCAN(mvm,
+ "6GHz passive scan: 6GHz channels enabled\n");
+ return;
+ }
+
+ /* all conditions to enable 6ghz passive scan are satisfied */
+ IWL_DEBUG_SCAN(mvm, "6GHz passive scan: can be enabled\n");
+ params->enable_6ghz_passive = true;
+}
+
static u16 iwl_mvm_scan_umac_flags_v2(struct iwl_mvm *mvm,
struct iwl_mvm_scan_params *params,
struct ieee80211_vif *vif,
@@ -1911,6 +2007,9 @@ static u16 iwl_mvm_scan_umac_flags_v2(struct iwl_mvm *mvm,
params->flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ)
flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_TRIGGER_UHB_SCAN;
+ if (params->enable_6ghz_passive)
+ flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_6GHZ_PASSIVE_SCAN;
+
return flags;
}
@@ -2183,6 +2282,30 @@ iwl_mvm_scan_umac_fill_ch_p_v6(struct iwl_mvm *mvm,
params->n_channels,
channel_cfg_flags,
vif->type);
+
+ if (params->enable_6ghz_passive) {
+ struct ieee80211_supported_band *sband =
+ &mvm->nvm_data->bands[NL80211_BAND_6GHZ];
+ u32 i;
+
+ for (i = 0; i < sband->n_channels; i++) {
+ struct ieee80211_channel *channel =
+ &sband->channels[i];
+
+ struct iwl_scan_channel_cfg_umac *cfg =
+ &cp->channel_config[cp->count];
+
+ if (!cfg80211_channel_is_psc(channel))
+ continue;
+
+ cfg->flags = 0;
+ cfg->v2.channel_num = channel->hw_value;
+ cfg->v2.band = PHY_BAND_6;
+ cfg->v2.iter_count = 1;
+ cfg->v2.iter_interval = 0;
+ cp->count++;
+ }
+ }
}
static int iwl_mvm_scan_umac_v12(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
@@ -2500,6 +2623,8 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
iwl_mvm_build_scan_probe(mvm, vif, ies, &params);
+ iwl_mvm_scan_6ghz_passive_scan(mvm, &params, vif);
+
uid = iwl_mvm_build_scan_cmd(mvm, vif, &hcmd, &params,
IWL_MVM_SCAN_REGULAR);
@@ -2524,6 +2649,9 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
mvm->scan_status |= IWL_MVM_SCAN_REGULAR;
mvm->scan_vif = iwl_mvm_vif_from_mac80211(vif);
+ if (params.enable_6ghz_passive)
+ mvm->last_6ghz_passive_scan_jiffies = jiffies;
+
schedule_delayed_work(&mvm->scan_timeout_dwork,
msecs_to_jiffies(SCAN_TIMEOUT));
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index 3a411bbda5fd..f618368eda83 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -2441,12 +2441,12 @@ int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
static void iwl_mvm_sync_rxq_del_ba(struct iwl_mvm *mvm, u8 baid)
{
- struct iwl_mvm_rss_sync_notif notif = {
- .metadata.type = IWL_MVM_RXQ_NOTIF_DEL_BA,
- .metadata.sync = 1,
- .delba.baid = baid,
+ struct iwl_mvm_delba_data notif = {
+ .baid = baid,
};
- iwl_mvm_sync_rx_queues_internal(mvm, (void *)&notif, sizeof(notif));
+
+ iwl_mvm_sync_rx_queues_internal(mvm, IWL_MVM_RXQ_NOTIF_DEL_BA, true,
+ &notif, sizeof(notif));
};
static void iwl_mvm_free_reorder(struct iwl_mvm *mvm,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index 35a18b96aac5..32b4d1935788 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -281,6 +281,36 @@ struct iwl_mvm_key_pn {
} ____cacheline_aligned_in_smp q[];
};
+/**
+ * enum iwl_mvm_rxq_notif_type - Internal message identifier
+ *
+ * @IWL_MVM_RXQ_EMPTY: empty sync notification
+ * @IWL_MVM_RXQ_NOTIF_DEL_BA: notify RSS queues of delBA
+ * @IWL_MVM_RXQ_NSSN_SYNC: notify all the RSS queues with the new NSSN
+ */
+enum iwl_mvm_rxq_notif_type {
+ IWL_MVM_RXQ_EMPTY,
+ IWL_MVM_RXQ_NOTIF_DEL_BA,
+ IWL_MVM_RXQ_NSSN_SYNC,
+};
+
+/**
+ * struct iwl_mvm_internal_rxq_notif - Internal representation of the data sent
+ * in &iwl_rxq_sync_cmd. Should be DWORD aligned.
+ * FW is agnostic to the payload, so there are no endianity requirements.
+ *
+ * @type: value from &iwl_mvm_rxq_notif_type
+ * @sync: ctrl path is waiting for all notifications to be received
+ * @cookie: internal cookie to identify old notifications
+ * @data: payload
+ */
+struct iwl_mvm_internal_rxq_notif {
+ u16 type;
+ u16 sync;
+ u32 cookie;
+ u8 data[];
+} __packed;
+
struct iwl_mvm_delba_data {
u32 baid;
} __packed;
@@ -290,14 +320,6 @@ struct iwl_mvm_nssn_sync_data {
u32 nssn;
} __packed;
-struct iwl_mvm_rss_sync_notif {
- struct iwl_mvm_internal_rxq_notif metadata;
- union {
- struct iwl_mvm_delba_data delba;
- struct iwl_mvm_nssn_sync_data nssn_sync;
- };
-} __packed;
-
/**
* struct iwl_mvm_rxq_dup_data - per station per rx queue data
* @last_seq: last sequence per tid for duplicate packet detection
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
index 0b012f8c9eb2..83342a6a6d5b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2020 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2021 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2017 Intel Deutschland GmbH
*/
@@ -151,6 +151,16 @@ static bool iwl_mvm_te_check_disconnect(struct iwl_mvm *mvm,
if (errmsg)
IWL_ERR(mvm, "%s\n", errmsg);
+ if (mvmvif->csa_bcn_pending) {
+ struct iwl_mvm_sta *mvmsta;
+
+ rcu_read_lock();
+ mvmsta = iwl_mvm_sta_from_staid_rcu(mvm, mvmvif->ap_sta_id);
+ if (!WARN_ON(!mvmsta))
+ iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, false);
+ rcu_read_unlock();
+ }
+
iwl_mvm_connection_loss(mvm, vif, errmsg);
return true;
}
@@ -285,6 +295,17 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
break;
case NL80211_IFTYPE_STATION:
/*
+ * If we are switching channel, don't disconnect
+ * if the time event is already done. Beacons can
+ * be delayed a bit after the switch.
+ */
+ if (te_data->id == TE_CHANNEL_SWITCH_PERIOD) {
+ IWL_DEBUG_TE(mvm,
+ "No beacon heard and the CS time event is over, don't disconnect\n");
+ break;
+ }
+
+ /*
* By now, we should have finished association
* and know the dtim period.
*/
@@ -713,8 +734,8 @@ void iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
IWL_DEBUG_TE(mvm, "Removing TE 0x%x\n", le32_to_cpu(time_cmd.id));
ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, 0,
sizeof(time_cmd), &time_cmd);
- if (WARN_ON(ret))
- return;
+ if (ret)
+ IWL_ERR(mvm, "Couldn't remove the time event\n");
}
/*
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
index b6b481ff1518..c566be99a4c7 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
@@ -1030,15 +1030,9 @@ iwl_mvm_tcm_load(struct iwl_mvm *mvm, u32 airtime, unsigned long elapsed)
return IWL_MVM_TRAFFIC_LOW;
}
-struct iwl_mvm_tcm_iter_data {
- struct iwl_mvm *mvm;
- bool any_sent;
-};
-
static void iwl_mvm_tcm_iter(void *_data, u8 *mac, struct ieee80211_vif *vif)
{
- struct iwl_mvm_tcm_iter_data *data = _data;
- struct iwl_mvm *mvm = data->mvm;
+ struct iwl_mvm *mvm = _data;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
bool low_latency, prev = mvmvif->low_latency & LOW_LATENCY_TRAFFIC;
@@ -1060,22 +1054,15 @@ static void iwl_mvm_tcm_iter(void *_data, u8 *mac, struct ieee80211_vif *vif)
} else {
iwl_mvm_update_quotas(mvm, false, NULL);
}
-
- data->any_sent = true;
}
static void iwl_mvm_tcm_results(struct iwl_mvm *mvm)
{
- struct iwl_mvm_tcm_iter_data data = {
- .mvm = mvm,
- .any_sent = false,
- };
-
mutex_lock(&mvm->mutex);
ieee80211_iterate_active_interfaces(
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
- iwl_mvm_tcm_iter, &data);
+ iwl_mvm_tcm_iter, mvm);
if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN))
iwl_mvm_config_scan(mvm);
@@ -1257,7 +1244,6 @@ static unsigned long iwl_mvm_calc_tcm_stats(struct iwl_mvm *mvm,
}
load = iwl_mvm_tcm_load(mvm, total_airtime, elapsed);
- mvm->tcm.result.global_change = load != mvm->tcm.result.global_load;
mvm->tcm.result.global_load = load;
for (i = 0; i < NUM_NL80211_BANDS; i++) {