summaryrefslogtreecommitdiff
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/d3.c501
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw.c69
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/link.c62
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c52
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c59
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c13
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h60
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c68
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/power.c1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ptp.c14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs.h1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rx.c24
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c96
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/scan.c121
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.h3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tests/Makefile2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tests/scan.c110
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/time-event.c25
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/time-event.h8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tx.c93
22 files changed, 425 insertions, 965 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
index 507c03198c92..029c846a236f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
@@ -120,19 +120,17 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
switch (key->cipher) {
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104: { /* hack it for now */
- struct {
- struct iwl_mvm_wep_key_cmd wep_key_cmd;
- struct iwl_mvm_wep_key wep_key;
- } __packed wkc = {
- .wep_key_cmd.mac_id_n_color =
- cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
- mvmvif->color)),
- .wep_key_cmd.num_keys = 1,
- /* firmware sets STA_KEY_FLG_WEP_13BYTES */
- .wep_key_cmd.decryption_type = STA_KEY_FLG_WEP,
- .wep_key.key_index = key->keyidx,
- .wep_key.key_size = key->keylen,
- };
+ DEFINE_RAW_FLEX(struct iwl_mvm_wep_key_cmd, wkc, wep_key, 1);
+ struct iwl_mvm_wep_key *wep_key = wkc->wep_key;
+
+ wkc->mac_id_n_color =
+ cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
+ mvmvif->color));
+ wkc->num_keys = 1;
+ /* firmware sets STA_KEY_FLG_WEP_13BYTES */
+ wkc->decryption_type = STA_KEY_FLG_WEP;
+ wep_key->key_index = key->keyidx;
+ wep_key->key_size = key->keylen;
/*
* This will fail -- the key functions don't set support
@@ -142,18 +140,19 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
break;
- memcpy(&wkc.wep_key.key[3], key->key, key->keylen);
+ memcpy(&wep_key->key[3], key->key, key->keylen);
if (key->keyidx == mvmvif->tx_key_idx) {
/* TX key must be at offset 0 */
- wkc.wep_key.key_offset = 0;
+ wep_key->key_offset = 0;
} else {
/* others start at 1 */
data->wep_key_idx++;
- wkc.wep_key.key_offset = data->wep_key_idx;
+ wep_key->key_offset = data->wep_key_idx;
}
mutex_lock(&mvm->mutex);
- ret = iwl_mvm_send_cmd_pdu(mvm, WEP_KEY, 0, sizeof(wkc), &wkc);
+ ret = iwl_mvm_send_cmd_pdu(mvm, WEP_KEY, 0,
+ __struct_size(wkc), wkc);
data->error = ret != 0;
mvm->ptk_ivlen = key->iv_len;
@@ -212,7 +211,7 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
}
struct wowlan_key_rsc_tsc_data {
- struct iwl_wowlan_rsc_tsc_params_cmd_v4 *rsc_tsc;
+ struct iwl_wowlan_rsc_tsc_params_cmd_ver_2 *rsc_tsc;
bool have_rsc_tsc;
};
@@ -237,21 +236,21 @@ static void iwl_mvm_wowlan_get_rsc_tsc_data(struct ieee80211_hw *hw,
u64 pn64;
tkip_sc =
- data->rsc_tsc->params.all_tsc_rsc.tkip.unicast_rsc;
+ data->rsc_tsc->all_tsc_rsc.tkip.unicast_rsc;
tkip_tx_sc =
- &data->rsc_tsc->params.all_tsc_rsc.tkip.tsc;
+ &data->rsc_tsc->all_tsc_rsc.tkip.tsc;
pn64 = atomic64_read(&key->tx_pn);
tkip_tx_sc->iv16 = cpu_to_le16(TKIP_PN_TO_IV16(pn64));
tkip_tx_sc->iv32 = cpu_to_le32(TKIP_PN_TO_IV32(pn64));
} else {
tkip_sc =
- data->rsc_tsc->params.all_tsc_rsc.tkip.multicast_rsc;
+ data->rsc_tsc->all_tsc_rsc.tkip.multicast_rsc;
}
/*
* For non-QoS this relies on the fact that both the uCode and
- * mac80211 use TID 0 (as they need to to avoid replay attacks)
+ * mac80211 use TID 0 (as they need to avoid replay attacks)
* for checking the IV in the frames.
*/
for (i = 0; i < IWL_NUM_RSC; i++) {
@@ -270,15 +269,15 @@ static void iwl_mvm_wowlan_get_rsc_tsc_data(struct ieee80211_hw *hw,
u64 pn64;
aes_sc =
- data->rsc_tsc->params.all_tsc_rsc.aes.unicast_rsc;
+ data->rsc_tsc->all_tsc_rsc.aes.unicast_rsc;
aes_tx_sc =
- &data->rsc_tsc->params.all_tsc_rsc.aes.tsc;
+ &data->rsc_tsc->all_tsc_rsc.aes.tsc;
pn64 = atomic64_read(&key->tx_pn);
aes_tx_sc->pn = cpu_to_le64(pn64);
} else {
aes_sc =
- data->rsc_tsc->params.all_tsc_rsc.aes.multicast_rsc;
+ data->rsc_tsc->all_tsc_rsc.aes.multicast_rsc;
}
/*
@@ -387,7 +386,7 @@ static void iwl_mvm_wowlan_get_rsc_v5_data(struct ieee80211_hw *hw,
/*
* For non-QoS this relies on the fact that both the uCode and
- * mac80211 use TID 0 (as they need to to avoid replay attacks)
+ * mac80211 use TID 0 (as they need to avoid replay attacks)
* for checking the IV in the frames.
*/
for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
@@ -481,30 +480,21 @@ static int iwl_mvm_wowlan_config_rsc_tsc(struct iwl_mvm *mvm,
else
ret = 0;
kfree(data.rsc);
- } else if (ver == 4 || ver == 2 || ver == IWL_FW_CMD_VER_UNKNOWN) {
+ } else if (ver == 2 || ver == IWL_FW_CMD_VER_UNKNOWN) {
struct wowlan_key_rsc_tsc_data data = {};
- int size;
data.rsc_tsc = kzalloc(sizeof(*data.rsc_tsc), GFP_KERNEL);
if (!data.rsc_tsc)
return -ENOMEM;
- if (ver == 4) {
- size = sizeof(*data.rsc_tsc);
- data.rsc_tsc->sta_id =
- cpu_to_le32(mvm_link->ap_sta_id);
- } else {
- /* ver == 2 || ver == IWL_FW_CMD_VER_UNKNOWN */
- size = sizeof(data.rsc_tsc->params);
- }
-
ieee80211_iter_keys(mvm->hw, vif,
iwl_mvm_wowlan_get_rsc_tsc_data,
&data);
if (data.have_rsc_tsc)
ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_TSC_RSC_PARAM,
- CMD_ASYNC, size,
+ CMD_ASYNC,
+ sizeof(*data.rsc_tsc),
data.rsc_tsc);
else
ret = 0;
@@ -1475,9 +1465,6 @@ struct iwl_wowlan_status_data {
struct iwl_multicast_key_data igtk;
struct iwl_multicast_key_data bigtk[WOWLAN_BIGTK_KEYS_NUM];
- int num_mlo_keys;
- struct iwl_wowlan_mlo_gtk mlo_keys[WOWLAN_MAX_MLO_KEYS];
-
u8 *wake_packet;
};
@@ -1693,7 +1680,7 @@ static void iwl_mvm_set_aes_ptk_rx_seq(struct iwl_mvm *mvm,
}
static void iwl_mvm_convert_key_counters(struct iwl_wowlan_status_data *status,
- union iwl_all_tsc_rsc *sc)
+ union iwl_all_tsc_rsc *sc, u8 key_idx)
{
int i;
@@ -1708,7 +1695,7 @@ static void iwl_mvm_convert_key_counters(struct iwl_wowlan_status_data *status,
&status->gtk_seq[0].aes.seq[i]);
}
status->gtk_seq[0].valid = true;
- status->gtk_seq[0].key_id = -1;
+ status->gtk_seq[0].key_id = key_idx;
/* PTK TX counter */
status->ptk.tkip.tx_pn = (u64)le16_to_cpu(sc->tkip.tsc.iv16) |
@@ -1791,8 +1778,7 @@ static void iwl_mvm_set_key_rx_seq_idx(struct ieee80211_key_conf *key,
}
static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key,
- struct iwl_wowlan_status_data *status,
- bool installed)
+ struct iwl_wowlan_status_data *status)
{
int i;
@@ -1800,23 +1786,7 @@ static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key,
if (!status->gtk_seq[i].valid)
continue;
- /* Handle the case where we know the key ID */
- if (status->gtk_seq[i].key_id == key->keyidx) {
- s8 new_key_id = -1;
-
- if (status->num_of_gtk_rekeys)
- new_key_id = status->gtk[0].flags &
- IWL_WOWLAN_GTK_IDX_MASK;
-
- /* Don't install a new key's value to an old key */
- if (new_key_id != key->keyidx)
- iwl_mvm_set_key_rx_seq_idx(key, status, i);
- continue;
- }
-
- /* handle the case where we didn't, last key only */
- if (status->gtk_seq[i].key_id == -1 &&
- (!status->num_of_gtk_rekeys || installed))
+ if (status->gtk_seq[i].key_id == key->keyidx)
iwl_mvm_set_key_rx_seq_idx(key, status, i);
}
}
@@ -1906,17 +1876,10 @@ iwl_mvm_d3_update_igtk_bigtk(struct iwl_wowlan_status_data *status,
struct ieee80211_key_conf *key,
struct iwl_multicast_key_data *key_data)
{
- if (status->num_of_gtk_rekeys && key_data->len) {
- /* remove rekeyed key */
- ieee80211_remove_key(key);
- } else {
- struct ieee80211_key_seq seq;
+ struct ieee80211_key_seq seq;
- iwl_mvm_d3_set_igtk_bigtk_ipn(key_data,
- &seq,
- key->cipher);
- ieee80211_set_key_rx_seq(key, 0, &seq);
- }
+ iwl_mvm_d3_set_igtk_bigtk_ipn(key_data, &seq, key->cipher);
+ ieee80211_set_key_rx_seq(key, 0, &seq);
}
static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
@@ -1957,18 +1920,13 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
return;
}
keyidx = key->keyidx;
- /* The current key is always sent by the FW, even if it wasn't
- * rekeyed during D3.
- * We remove an existing key if it has the same index as
- * a new key
+ /*
+ * Update the seq even if there was a rekey. If there was a
+ * rekey, we will update again after replacing the key
*/
- if (status->num_of_gtk_rekeys &&
- ((status->gtk[0].len && keyidx == status->gtk[0].id) ||
- (status->gtk[1].len && keyidx == status->gtk[1].id))) {
- ieee80211_remove_key(key);
- } else {
- iwl_mvm_set_key_rx_seq(key, data->status, false);
- }
+ if ((status->gtk[0].len && keyidx == status->gtk[0].id) ||
+ (status->gtk[1].len && keyidx == status->gtk[1].id))
+ iwl_mvm_set_key_rx_seq(key, status);
break;
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
@@ -1987,199 +1945,35 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
}
}
-struct iwl_mvm_d3_mlo_old_keys {
- u32 cipher[IEEE80211_MLD_MAX_NUM_LINKS][WOWLAN_MLO_GTK_KEY_NUM_TYPES];
- struct ieee80211_key_conf *key[IEEE80211_MLD_MAX_NUM_LINKS][8];
-};
-
-static void iwl_mvm_mlo_key_ciphers(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct ieee80211_key_conf *key,
- void *data)
-{
- struct iwl_mvm_d3_mlo_old_keys *old_keys = data;
- enum iwl_wowlan_mlo_gtk_type key_type;
-
- if (key->link_id < 0)
- return;
-
- if (WARN_ON(key->link_id >= IEEE80211_MLD_MAX_NUM_LINKS ||
- key->keyidx >= 8))
- return;
-
- if (WARN_ON(old_keys->key[key->link_id][key->keyidx]))
- return;
-
- switch (key->cipher) {
- case WLAN_CIPHER_SUITE_CCMP:
- case WLAN_CIPHER_SUITE_GCMP:
- case WLAN_CIPHER_SUITE_GCMP_256:
- key_type = WOWLAN_MLO_GTK_KEY_TYPE_GTK;
- break;
- case WLAN_CIPHER_SUITE_BIP_GMAC_128:
- case WLAN_CIPHER_SUITE_BIP_GMAC_256:
- case WLAN_CIPHER_SUITE_BIP_CMAC_256:
- case WLAN_CIPHER_SUITE_AES_CMAC:
- if (key->keyidx == 4 || key->keyidx == 5) {
- key_type = WOWLAN_MLO_GTK_KEY_TYPE_IGTK;
- break;
- } else if (key->keyidx == 6 || key->keyidx == 7) {
- key_type = WOWLAN_MLO_GTK_KEY_TYPE_BIGTK;
- break;
- }
- return;
- default:
- /* ignore WEP/TKIP or unknown ciphers */
- return;
- }
-
- old_keys->cipher[key->link_id][key_type] = key->cipher;
- old_keys->key[key->link_id][key->keyidx] = key;
-}
-
-static bool iwl_mvm_mlo_gtk_rekey(struct iwl_wowlan_status_data *status,
- struct ieee80211_vif *vif,
- struct iwl_mvm *mvm)
-{
- int i;
- struct iwl_mvm_d3_mlo_old_keys *old_keys;
- bool ret = true;
-
- IWL_DEBUG_WOWLAN(mvm, "Num of MLO Keys: %d\n", status->num_mlo_keys);
- if (!status->num_mlo_keys)
- return true;
-
- old_keys = kzalloc(sizeof(*old_keys), GFP_KERNEL);
- if (!old_keys)
- return false;
-
- /* find the cipher for each mlo key */
- ieee80211_iter_keys(mvm->hw, vif, iwl_mvm_mlo_key_ciphers, old_keys);
-
- for (i = 0; i < status->num_mlo_keys; i++) {
- struct iwl_wowlan_mlo_gtk *mlo_key = &status->mlo_keys[i];
- struct ieee80211_key_conf *key, *old_key;
- struct ieee80211_key_seq seq;
- struct {
- struct ieee80211_key_conf conf;
- u8 key[32];
- } conf = {};
- u16 flags = le16_to_cpu(mlo_key->flags);
- int j, link_id, key_id, key_type;
-
- link_id = u16_get_bits(flags, WOWLAN_MLO_GTK_FLAG_LINK_ID_MSK);
- key_id = u16_get_bits(flags, WOWLAN_MLO_GTK_FLAG_KEY_ID_MSK);
- key_type = u16_get_bits(flags,
- WOWLAN_MLO_GTK_FLAG_KEY_TYPE_MSK);
-
- if (!(vif->valid_links & BIT(link_id)))
- continue;
-
- if (WARN_ON(link_id >= IEEE80211_MLD_MAX_NUM_LINKS ||
- key_id >= 8 ||
- key_type >= WOWLAN_MLO_GTK_KEY_NUM_TYPES))
- continue;
-
- conf.conf.cipher = old_keys->cipher[link_id][key_type];
- /* WARN_ON? */
- if (!conf.conf.cipher)
- continue;
-
- conf.conf.keylen = 0;
- switch (conf.conf.cipher) {
- case WLAN_CIPHER_SUITE_CCMP:
- case WLAN_CIPHER_SUITE_GCMP:
- conf.conf.keylen = WLAN_KEY_LEN_CCMP;
- break;
- case WLAN_CIPHER_SUITE_GCMP_256:
- conf.conf.keylen = WLAN_KEY_LEN_GCMP_256;
- break;
- case WLAN_CIPHER_SUITE_BIP_GMAC_128:
- conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_128;
- break;
- case WLAN_CIPHER_SUITE_BIP_GMAC_256:
- conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_256;
- break;
- case WLAN_CIPHER_SUITE_AES_CMAC:
- conf.conf.keylen = WLAN_KEY_LEN_AES_CMAC;
- break;
- case WLAN_CIPHER_SUITE_BIP_CMAC_256:
- conf.conf.keylen = WLAN_KEY_LEN_BIP_CMAC_256;
- break;
- }
-
- if (WARN_ON(!conf.conf.keylen ||
- conf.conf.keylen > sizeof(conf.key)))
- continue;
-
- memcpy(conf.conf.key, mlo_key->key, conf.conf.keylen);
- conf.conf.keyidx = key_id;
-
- old_key = old_keys->key[link_id][key_id];
- if (old_key) {
- IWL_DEBUG_WOWLAN(mvm,
- "Remove MLO key id %d, link id %d\n",
- key_id, link_id);
- ieee80211_remove_key(old_key);
- }
-
- IWL_DEBUG_WOWLAN(mvm, "Add MLO key id %d, link id %d\n",
- key_id, link_id);
- key = ieee80211_gtk_rekey_add(vif, &conf.conf, link_id);
- if (WARN_ON(IS_ERR(key))) {
- ret = false;
- goto out;
- }
-
- /*
- * mac80211 expects the pn in big-endian
- * also note that seq is a union of all cipher types
- * (ccmp, gcmp, cmac, gmac), and they all have the same
- * pn field (of length 6) so just copy it to ccmp.pn.
- */
- for (j = 5; j >= 0; j--)
- seq.ccmp.pn[5 - j] = mlo_key->pn[j];
-
- /* group keys are non-QoS and use TID 0 */
- ieee80211_set_key_rx_seq(key, 0, &seq);
- }
-
-out:
- kfree(old_keys);
- return ret;
-}
-
static bool iwl_mvm_gtk_rekey(struct iwl_wowlan_status_data *status,
struct ieee80211_vif *vif,
struct iwl_mvm *mvm, u32 gtk_cipher)
{
int i, j;
struct ieee80211_key_conf *key;
- struct {
- struct ieee80211_key_conf conf;
- u8 key[32];
- } conf = {
- .conf.cipher = gtk_cipher,
- };
+ DEFINE_RAW_FLEX(struct ieee80211_key_conf, conf, key,
+ WOWLAN_KEY_MAX_SIZE);
int link_id = vif->active_links ? __ffs(vif->active_links) : -1;
+ u8 key_data[WOWLAN_KEY_MAX_SIZE];
+
+ conf->cipher = gtk_cipher;
BUILD_BUG_ON(WLAN_KEY_LEN_CCMP != WLAN_KEY_LEN_GCMP);
- BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_CCMP);
- BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_GCMP_256);
- BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_TKIP);
- BUILD_BUG_ON(sizeof(conf.key) < sizeof(status->gtk[0].key));
+ BUILD_BUG_ON(WOWLAN_KEY_MAX_SIZE < WLAN_KEY_LEN_CCMP);
+ BUILD_BUG_ON(WOWLAN_KEY_MAX_SIZE < WLAN_KEY_LEN_GCMP_256);
+ BUILD_BUG_ON(WOWLAN_KEY_MAX_SIZE < WLAN_KEY_LEN_TKIP);
+ BUILD_BUG_ON(WOWLAN_KEY_MAX_SIZE < sizeof(status->gtk[0].key));
switch (gtk_cipher) {
case WLAN_CIPHER_SUITE_CCMP:
case WLAN_CIPHER_SUITE_GCMP:
- conf.conf.keylen = WLAN_KEY_LEN_CCMP;
+ conf->keylen = WLAN_KEY_LEN_CCMP;
break;
case WLAN_CIPHER_SUITE_GCMP_256:
- conf.conf.keylen = WLAN_KEY_LEN_GCMP_256;
+ conf->keylen = WLAN_KEY_LEN_GCMP_256;
break;
case WLAN_CIPHER_SUITE_TKIP:
- conf.conf.keylen = WLAN_KEY_LEN_TKIP;
+ conf->keylen = WLAN_KEY_LEN_TKIP;
break;
default:
WARN_ON(1);
@@ -2189,16 +1983,22 @@ static bool iwl_mvm_gtk_rekey(struct iwl_wowlan_status_data *status,
if (!status->gtk[i].len)
continue;
- conf.conf.keyidx = status->gtk[i].id;
+ conf->keyidx = status->gtk[i].id;
IWL_DEBUG_WOWLAN(mvm,
"Received from FW GTK cipher %d, key index %d\n",
- conf.conf.cipher, conf.conf.keyidx);
- memcpy(conf.conf.key, status->gtk[i].key,
+ conf->cipher, conf->keyidx);
+ memcpy(conf->key, status->gtk[i].key,
sizeof(status->gtk[i].key));
+ memcpy(key_data, status->gtk[i].key, sizeof(status->gtk[i].key));
- key = ieee80211_gtk_rekey_add(vif, &conf.conf, link_id);
- if (IS_ERR(key))
+ key = ieee80211_gtk_rekey_add(vif, status->gtk[i].id, key_data,
+ sizeof(key_data), link_id);
+ if (IS_ERR(key)) {
+ /* FW may send also the old keys */
+ if (PTR_ERR(key) == -EALREADY)
+ continue;
return false;
+ }
for (j = 0; j < ARRAY_SIZE(status->gtk_seq); j++) {
if (!status->gtk_seq[j].valid ||
@@ -2218,55 +2018,66 @@ iwl_mvm_d3_igtk_bigtk_rekey_add(struct iwl_wowlan_status_data *status,
struct ieee80211_vif *vif, u32 cipher,
struct iwl_multicast_key_data *key_data)
{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ DEFINE_RAW_FLEX(struct ieee80211_key_conf, conf, key,
+ WOWLAN_KEY_MAX_SIZE);
struct ieee80211_key_conf *key_config;
- struct {
- struct ieee80211_key_conf conf;
- u8 key[WOWLAN_KEY_MAX_SIZE];
- } conf = {
- .conf.cipher = cipher,
- .conf.keyidx = key_data->id,
- };
struct ieee80211_key_seq seq;
int link_id = vif->active_links ? __ffs(vif->active_links) : -1;
+ u8 key[WOWLAN_KEY_MAX_SIZE];
+ s8 keyidx = key_data->id;
+
+ conf->cipher = cipher;
+ conf->keyidx = keyidx;
if (!key_data->len)
return true;
- iwl_mvm_d3_set_igtk_bigtk_ipn(key_data, &seq, conf.conf.cipher);
+ iwl_mvm_d3_set_igtk_bigtk_ipn(key_data, &seq, conf->cipher);
switch (cipher) {
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
- conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_128;
+ conf->keylen = WLAN_KEY_LEN_BIP_GMAC_128;
break;
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
- conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_256;
+ conf->keylen = WLAN_KEY_LEN_BIP_GMAC_256;
break;
case WLAN_CIPHER_SUITE_AES_CMAC:
- conf.conf.keylen = WLAN_KEY_LEN_AES_CMAC;
+ conf->keylen = WLAN_KEY_LEN_AES_CMAC;
break;
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
- conf.conf.keylen = WLAN_KEY_LEN_BIP_CMAC_256;
+ conf->keylen = WLAN_KEY_LEN_BIP_CMAC_256;
break;
default:
WARN_ON(1);
}
- BUILD_BUG_ON(sizeof(conf.key) < sizeof(key_data->key));
- memcpy(conf.conf.key, key_data->key, conf.conf.keylen);
+ BUILD_BUG_ON(WOWLAN_KEY_MAX_SIZE < sizeof(key_data->key));
+ memcpy(conf->key, key_data->key, conf->keylen);
- key_config = ieee80211_gtk_rekey_add(vif, &conf.conf, link_id);
- if (IS_ERR(key_config))
- return false;
+ memcpy(key, key_data->key, sizeof(key_data->key));
+
+ key_config = ieee80211_gtk_rekey_add(vif, keyidx, key, sizeof(key),
+ link_id);
+ if (IS_ERR(key_config)) {
+ /* FW may send also the old keys */
+ return PTR_ERR(key_config) == -EALREADY;
+ }
ieee80211_set_key_rx_seq(key_config, 0, &seq);
- if (key_config->keyidx == 4 || key_config->keyidx == 5) {
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ if (keyidx == 4 || keyidx == 5) {
struct iwl_mvm_vif_link_info *mvm_link;
link_id = link_id < 0 ? 0 : link_id;
mvm_link = mvmvif->link[link_id];
+ if (mvm_link->igtk)
+ mvm_link->igtk->hw_key_idx = STA_KEY_IDX_INVALID;
mvm_link->igtk = key_config;
}
+ if (vif->type == NL80211_IFTYPE_STATION && (keyidx == 6 || keyidx == 7))
+ rcu_assign_pointer(mvmvif->bcn_prot.keys[keyidx - 6],
+ key_config);
+
return true;
}
@@ -2353,9 +2164,6 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
return false;
}
- if (!iwl_mvm_mlo_gtk_rekey(status, vif, mvm))
- return false;
-
ieee80211_gtk_rekey_notify(vif, vif->bss_conf.bssid,
(void *)&replay_ctr, GFP_KERNEL);
}
@@ -2385,6 +2193,7 @@ static void iwl_mvm_convert_gtk_v2(struct iwl_wowlan_status_data *status,
status->gtk[0].len = data->key_len;
status->gtk[0].flags = data->key_flags;
+ status->gtk[0].id = status->gtk[0].flags & IWL_WOWLAN_GTK_IDX_MASK;
memcpy(status->gtk[0].key, data->key, sizeof(data->key));
@@ -2486,10 +2295,11 @@ static void iwl_mvm_parse_wowlan_info_notif(struct iwl_mvm *mvm,
struct iwl_wowlan_status_data *status,
u32 len)
{
- u32 expected_len = sizeof(*data) +
- data->num_mlo_link_keys * sizeof(status->mlo_keys[0]);
+ if (IWL_FW_CHECK(mvm, data->num_mlo_link_keys,
+ "MLO is not supported, shouldn't receive MLO keys\n"))
+ return;
- if (len < expected_len) {
+ if (len < sizeof(*data)) {
IWL_ERR(mvm, "Invalid WoWLAN info notification!\n");
status = NULL;
return;
@@ -2518,33 +2328,17 @@ static void iwl_mvm_parse_wowlan_info_notif(struct iwl_mvm *mvm,
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,
+iwl_mvm_parse_wowlan_info_notif_v3(struct iwl_mvm *mvm,
+ struct iwl_wowlan_info_notif_v3 *data,
struct iwl_wowlan_status_data *status,
- u32 len, bool has_mlo_keys)
+ u32 len)
{
u32 i;
- u32 expected_len = sizeof(*data);
-
- if (has_mlo_keys)
- expected_len += (data->num_mlo_link_keys *
- sizeof(status->mlo_keys[0]));
- if (len < expected_len) {
+ if (len < sizeof(*data)) {
IWL_ERR(mvm, "Invalid WoWLAN info notification!\n");
status = NULL;
return;
@@ -2567,22 +2361,11 @@ iwl_mvm_parse_wowlan_info_notif_v4(struct iwl_mvm *mvm,
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 (has_mlo_keys && 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_v2(struct iwl_mvm *mvm,
- struct iwl_wowlan_info_notif_v2 *data,
+iwl_mvm_parse_wowlan_info_notif_v1(struct iwl_mvm *mvm,
+ struct iwl_wowlan_info_notif_v1 *data,
struct iwl_wowlan_status_data *status,
u32 len)
{
@@ -2667,8 +2450,6 @@ iwl_mvm_parse_wowlan_status_common_ ## _ver(struct iwl_mvm *mvm, \
iwl_mvm_parse_wowlan_status_common(v6)
iwl_mvm_parse_wowlan_status_common(v7)
-iwl_mvm_parse_wowlan_status_common(v9)
-iwl_mvm_parse_wowlan_status_common(v12)
static struct iwl_wowlan_status_data *
iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
@@ -2724,7 +2505,8 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
v6->gtk.tkip_mic_key,
sizeof(v6->gtk.tkip_mic_key));
- iwl_mvm_convert_key_counters(status, &v6->gtk.rsc.all_tsc_rsc);
+ iwl_mvm_convert_key_counters(status, &v6->gtk.rsc.all_tsc_rsc,
+ v6->gtk.key_index);
/* hardcode the key length to 16 since v6 only supports 16 */
status->gtk[0].len = 16;
@@ -2735,6 +2517,7 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
* currently used key.
*/
status->gtk[0].flags = v6->gtk.key_index | BIT(7);
+ status->gtk[0].id = v6->gtk.key_index;
} else if (notif_ver == 7) {
struct iwl_wowlan_status_v7 *v7 = (void *)cmd.resp_pkt->data;
@@ -2742,36 +2525,10 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
if (!status)
goto out_free_resp;
- iwl_mvm_convert_key_counters(status, &v7->gtk[0].rsc.all_tsc_rsc);
+ iwl_mvm_convert_key_counters(status, &v7->gtk[0].rsc.all_tsc_rsc,
+ v7->gtk[0].key_flags & IWL_WOWLAN_GTK_IDX_MASK);
iwl_mvm_convert_gtk_v2(status, &v7->gtk[0]);
iwl_mvm_convert_igtk(status, &v7->igtk[0]);
- } else if (notif_ver == 9 || notif_ver == 10 || notif_ver == 11) {
- struct iwl_wowlan_status_v9 *v9 = (void *)cmd.resp_pkt->data;
-
- /* these three command versions have same layout and size, the
- * difference is only in a few not used (reserved) fields.
- */
- status = iwl_mvm_parse_wowlan_status_common_v9(mvm, v9, len);
- if (!status)
- goto out_free_resp;
-
- iwl_mvm_convert_key_counters(status, &v9->gtk[0].rsc.all_tsc_rsc);
- iwl_mvm_convert_gtk_v2(status, &v9->gtk[0]);
- iwl_mvm_convert_igtk(status, &v9->igtk[0]);
-
- status->tid_tear_down = v9->tid_tear_down;
- } else if (notif_ver == 12) {
- struct iwl_wowlan_status_v12 *v12 = (void *)cmd.resp_pkt->data;
-
- status = iwl_mvm_parse_wowlan_status_common_v12(mvm, v12, len);
- if (!status)
- goto out_free_resp;
-
- iwl_mvm_convert_key_counters_v5(status, &v12->gtk[0].sc);
- iwl_mvm_convert_gtk_v3(status, v12->gtk);
- iwl_mvm_convert_igtk(status, &v12->igtk[0]);
-
- status->tid_tear_down = v12->tid_tear_down;
} else {
IWL_ERR(mvm,
"Firmware advertises unknown WoWLAN status response %d!\n",
@@ -3298,44 +3055,30 @@ static bool iwl_mvm_wait_d3_notif(struct iwl_notif_wait_data *notif_wait,
break;
}
- if (wowlan_info_ver < 2) {
+ if (wowlan_info_ver == 1) {
struct iwl_wowlan_info_notif_v1 *notif_v1 =
(void *)pkt->data;
- struct iwl_wowlan_info_notif_v2 *notif_v2;
-
- notif_v2 = kmemdup(notif_v1, sizeof(*notif_v2), GFP_ATOMIC);
-
- if (!notif_v2)
- return false;
-
- notif_v2->tid_tear_down = notif_v1->tid_tear_down;
- notif_v2->station_id = notif_v1->station_id;
- memset_after(notif_v2, 0, station_id);
- iwl_mvm_parse_wowlan_info_notif_v2(mvm, notif_v2,
- d3_data->status,
- len);
- kfree(notif_v2);
-
- } else if (wowlan_info_ver == 2) {
- struct iwl_wowlan_info_notif_v2 *notif_v2 =
- (void *)pkt->data;
- iwl_mvm_parse_wowlan_info_notif_v2(mvm, notif_v2,
+ iwl_mvm_parse_wowlan_info_notif_v1(mvm, notif_v1,
d3_data->status,
len);
- } else if (wowlan_info_ver < 5) {
- struct iwl_wowlan_info_notif_v4 *notif =
+ } else if (wowlan_info_ver == 3) {
+ struct iwl_wowlan_info_notif_v3 *notif =
(void *)pkt->data;
- iwl_mvm_parse_wowlan_info_notif_v4(mvm, notif,
- d3_data->status, len,
- wowlan_info_ver > 3);
- } else {
+ iwl_mvm_parse_wowlan_info_notif_v3(mvm, notif,
+ d3_data->status, len);
+ } else if (wowlan_info_ver == 5) {
struct iwl_wowlan_info_notif *notif =
(void *)pkt->data;
iwl_mvm_parse_wowlan_info_notif(mvm, notif,
d3_data->status, len);
+ } else {
+ IWL_FW_CHECK(mvm, 1,
+ "Firmware advertises unknown WoWLAN info notification %d!\n",
+ wowlan_info_ver);
+ return false;
}
d3_data->notif_received |= IWL_D3_NOTIF_WOWLAN_INFO;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
index 86a87ea89916..f0e184c8a81a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
@@ -1134,7 +1134,7 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
if (count == 6 && !strcmp(buf, "nolog\n")) {
set_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE, &mvm->status);
- set_bit(STATUS_SUPPRESS_CMD_ERROR_ONCE, &mvm->trans->status);
+ iwl_trans_suppress_cmd_error_once(mvm->trans);
}
/* take the return value to make compiler happy - it will fail anyway */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index 819e3228462a..d931c6eaf12f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -121,6 +121,22 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
return false;
palive = (void *)pkt->data;
+
+ umac = &palive->umac_data;
+ lmac1 = &palive->lmac_data[0];
+ lmac2 = &palive->lmac_data[1];
+ status = le16_to_cpu(palive->status);
+
+ BUILD_BUG_ON(sizeof(palive->sku_id.data) !=
+ sizeof(alive_data->sku_id));
+ memcpy(alive_data->sku_id, palive->sku_id.data,
+ sizeof(palive->sku_id.data));
+
+ IWL_DEBUG_FW(mvm, "Got sku_id: 0x0%x 0x0%x 0x0%x\n",
+ le32_to_cpu(alive_data->sku_id[0]),
+ le32_to_cpu(alive_data->sku_id[1]),
+ le32_to_cpu(alive_data->sku_id[2]));
+
mvm->trans->dbg.imr_data.imr_enable =
le32_to_cpu(palive->imr.enabled);
mvm->trans->dbg.imr_data.imr_size =
@@ -168,40 +184,6 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
IWL_DEBUG_FW(mvm, "platform id: 0x%llx\n",
palive_v8->platform_id);
}
- }
-
- if (version >= 5) {
- struct iwl_alive_ntf_v5 *palive;
-
- if (pkt_len < sizeof(*palive))
- return false;
-
- palive = (void *)pkt->data;
- umac = &palive->umac_data;
- lmac1 = &palive->lmac_data[0];
- lmac2 = &palive->lmac_data[1];
- status = le16_to_cpu(palive->status);
-
- BUILD_BUG_ON(sizeof(palive->sku_id.data) !=
- sizeof(alive_data->sku_id));
- memcpy(alive_data->sku_id, palive->sku_id.data,
- sizeof(palive->sku_id.data));
-
- IWL_DEBUG_FW(mvm, "Got sku_id: 0x0%x 0x0%x 0x0%x\n",
- le32_to_cpu(alive_data->sku_id[0]),
- le32_to_cpu(alive_data->sku_id[1]),
- le32_to_cpu(alive_data->sku_id[2]));
- } else if (iwl_rx_packet_payload_len(pkt) == sizeof(struct iwl_alive_ntf_v4)) {
- struct iwl_alive_ntf_v4 *palive;
-
- if (pkt_len < sizeof(*palive))
- return false;
-
- palive = (void *)pkt->data;
- umac = &palive->umac_data;
- lmac1 = &palive->lmac_data[0];
- lmac2 = &palive->lmac_data[1];
- status = le16_to_cpu(palive->status);
} else if (iwl_rx_packet_payload_len(pkt) ==
sizeof(struct iwl_alive_ntf_v3)) {
struct iwl_alive_ntf_v3 *palive3;
@@ -432,7 +414,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
iwl_trans_fw_alive(mvm->trans);
ret = iwl_pnvm_load(mvm->trans, &mvm->notif_wait,
- &mvm->fw->ucode_capa, alive_data.sku_id);
+ mvm->fw, alive_data.sku_id);
if (ret) {
IWL_ERR(mvm, "Timeout waiting for PNVM load!\n");
iwl_fw_set_current_image(&mvm->fwrt, old_type);
@@ -888,17 +870,11 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
len = sizeof(cmd_v9_v10.v9);
n_subbands = IWL_NUM_SUB_BANDS_V1;
per_chain = &cmd_v9_v10.v9.per_chain[0][0];
- } else if (cmd_ver >= 7) {
- len = sizeof(cmd.v7);
- n_subbands = IWL_NUM_SUB_BANDS_V2;
- per_chain = cmd.v7.per_chain[0][0];
- cmd.v7.flags = cpu_to_le32(mvm->fwrt.reduced_power_flags);
- if (cmd_ver == 8)
- len = sizeof(cmd.v8);
- } else if (cmd_ver == 6) {
- len = sizeof(cmd.v6);
+ } else if (cmd_ver == 8) {
+ len = sizeof(cmd.v8);
n_subbands = IWL_NUM_SUB_BANDS_V2;
- per_chain = cmd.v6.per_chain[0][0];
+ per_chain = cmd.v8.per_chain[0][0];
+ cmd.v8.flags = cpu_to_le32(mvm->fwrt.reduced_power_flags);
} else if (fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_REDUCE_TX_POWER)) {
len = sizeof(cmd.v5);
@@ -1462,9 +1438,6 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
RCU_INIT_POINTER(mvm->fw_id_to_link_sta[i], NULL);
}
- 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_INVALID_STA;
/* reset quota debouncing buffer - 0xff will yield invalid data */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/link.c b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
index 851869c0bd50..2269acc55c0e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/link.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
@@ -18,8 +18,7 @@
HOW(EXIT_COEX) \
HOW(EXIT_BANDWIDTH) \
HOW(EXIT_CSA) \
- HOW(EXIT_LINK_USAGE) \
- HOW(EXIT_FAIL_ENTRY)
+ HOW(EXIT_LINK_USAGE)
static const char *const iwl_mvm_esr_states_names[] = {
#define NAME_ENTRY(x) [ilog2(IWL_MVM_ESR_##x)] = #x,
@@ -50,20 +49,6 @@ static void iwl_mvm_print_esr_state(struct iwl_mvm *mvm, u32 mask)
#undef NAME_PR
}
-static u32 iwl_mvm_get_free_fw_link_id(struct iwl_mvm *mvm,
- struct iwl_mvm_vif *mvm_vif)
-{
- u32 i;
-
- lockdep_assert_held(&mvm->mutex);
-
- for (i = 0; i < ARRAY_SIZE(mvm->link_id_to_link_conf); i++)
- if (!rcu_access_pointer(mvm->link_id_to_link_conf[i]))
- return i;
-
- return IWL_MVM_FW_LINK_ID_INVALID;
-}
-
static int iwl_mvm_link_cmd_send(struct iwl_mvm *mvm,
struct iwl_link_config_cmd *cmd,
enum iwl_ctxt_action action)
@@ -80,25 +65,15 @@ static int iwl_mvm_link_cmd_send(struct iwl_mvm *mvm,
return ret;
}
-int iwl_mvm_set_link_mapping(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *link_conf)
+void iwl_mvm_set_link_fw_id(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_vif_link_info *link_info =
mvmvif->link[link_conf->link_id];
- if (link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID) {
- link_info->fw_link_id = iwl_mvm_get_free_fw_link_id(mvm,
- mvmvif);
- if (link_info->fw_link_id >=
- ARRAY_SIZE(mvm->link_id_to_link_conf))
- return -EINVAL;
-
- rcu_assign_pointer(mvm->link_id_to_link_conf[link_info->fw_link_id],
- link_conf);
- }
-
- return 0;
+ if (link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID)
+ link_info->fw_link_id = mvmvif->id;
}
int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
@@ -110,14 +85,11 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct iwl_link_config_cmd cmd = {};
unsigned int cmd_id = WIDE_ID(MAC_CONF_GROUP, LINK_CONFIG_CMD);
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 1);
- int ret;
if (WARN_ON_ONCE(!link_info))
return -EINVAL;
- ret = iwl_mvm_set_link_mapping(mvm, vif, link_conf);
- if (ret)
- return ret;
+ iwl_mvm_set_link_fw_id(mvm, vif, link_conf);
/* Update SF - Disable if needed. if this fails, SF might still be on
* while many macs are bound, which is forbidden - so fail the binding.
@@ -374,24 +346,6 @@ send_cmd:
return ret;
}
-int iwl_mvm_unset_link_mapping(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *link_conf)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm_vif_link_info *link_info =
- mvmvif->link[link_conf->link_id];
-
- /* mac80211 thought we have the link, but it was never configured */
- if (WARN_ON(!link_info ||
- link_info->fw_link_id >=
- ARRAY_SIZE(mvm->link_id_to_link_conf)))
- return -EINVAL;
-
- RCU_INIT_POINTER(mvm->link_id_to_link_conf[link_info->fw_link_id],
- NULL);
- return 0;
-}
-
int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf)
{
@@ -401,10 +355,6 @@ int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct iwl_link_config_cmd cmd = {};
int ret;
- ret = iwl_mvm_unset_link_mapping(mvm, vif, link_conf);
- if (ret)
- return 0;
-
cmd.link_id = cpu_to_le32(link_info->fw_link_id);
link_info->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
cmd.spec_link_id = link_conf->link_id;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index 9098a36530cc..8805ab344895 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -301,7 +301,7 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
iwl_mvm_init_link(&mvmvif->deflink);
- /* No need to allocate data queues to P2P Device MAC and NAN.*/
+ /* No need to allocate data queues to P2P Device MAC */
if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
return 0;
@@ -976,7 +976,7 @@ u8 iwl_mvm_mac_ctxt_get_beacon_rate(struct iwl_mvm *mvm,
static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct sk_buff *beacon,
- struct iwl_tx_cmd_v6 *tx)
+ struct iwl_tx_cmd_v6_params *tx_params)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct ieee80211_tx_info *info;
@@ -986,30 +986,30 @@ static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm,
info = IEEE80211_SKB_CB(beacon);
/* Set up TX command fields */
- tx->len = cpu_to_le16((u16)beacon->len);
- tx->sta_id = mvmvif->deflink.bcast_sta.sta_id;
- tx->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
+ tx_params->len = cpu_to_le16((u16)beacon->len);
+ tx_params->sta_id = mvmvif->deflink.bcast_sta.sta_id;
+ tx_params->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
tx_flags = TX_CMD_FLG_SEQ_CTL | TX_CMD_FLG_TSF;
tx_flags |=
iwl_mvm_bt_coex_tx_prio(mvm, (void *)beacon->data, info, 0) <<
TX_CMD_FLG_BT_PRIO_POS;
- tx->tx_flags = cpu_to_le32(tx_flags);
+ tx_params->tx_flags = cpu_to_le32(tx_flags);
if (!fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION)) {
iwl_mvm_toggle_tx_ant(mvm, &mvm->mgmt_last_antenna_idx);
- tx->rate_n_flags =
+ tx_params->rate_n_flags =
cpu_to_le32(BIT(mvm->mgmt_last_antenna_idx) <<
RATE_MCS_ANT_POS);
}
rate = iwl_mvm_mac_ctxt_get_beacon_rate(mvm, info, vif);
- tx->rate_n_flags |=
+ tx_params->rate_n_flags |=
cpu_to_le32(iwl_mvm_mac80211_idx_to_hwrate(mvm->fw, rate));
if (rate == IWL_FIRST_CCK_RATE)
- tx->rate_n_flags |= cpu_to_le32(RATE_MCS_CCK_MSK_V1);
+ tx_params->rate_n_flags |= cpu_to_le32(RATE_MCS_CCK_MSK_V1);
}
@@ -1586,7 +1586,7 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm,
u32 id = le32_to_cpu(mb->link_id);
union iwl_dbg_tlv_tp_data tp_data = { .fw_pkt = pkt };
u32 mac_type;
- int link_id = -1;
+ int link_id;
u8 notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
MISSED_BEACONS_NOTIFICATION,
0);
@@ -1602,20 +1602,6 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm,
if (new_notif_ver)
notif_ver = new_notif_ver;
- /* 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 {
- bss_conf = iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, id, false);
-
- if (!bss_conf)
- return;
-
- vif = bss_conf->vif;
- link_id = bss_conf->link_id;
- }
-
IWL_DEBUG_INFO(mvm,
"missed bcn %s_id=%u, consecutive=%u (%u)\n",
notif_ver < 4 ? "mac" : "link",
@@ -1623,9 +1609,16 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm,
le32_to_cpu(mb->consec_missed_beacons),
le32_to_cpu(mb->consec_missed_beacons_since_last_rx));
+ /*
+ * starting from version 4 the ID is link ID, but driver
+ * uses link ID == MAC ID, so always treat as MAC ID
+ */
+ vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, false);
if (!vif)
return;
+ bss_conf = &vif->bss_conf;
+ link_id = bss_conf->link_id;
mac_type = iwl_mvm_get_mac_type(vif);
IWL_DEBUG_INFO(mvm, "missed beacon mac_type=%u,\n", mac_type);
@@ -1875,16 +1868,15 @@ void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm,
} else {
struct iwl_channel_switch_start_notif *notif = (void *)pkt->data;
u32 link_id = le32_to_cpu(notif->link_id);
- struct ieee80211_bss_conf *bss_conf =
- iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, link_id, true);
- if (!bss_conf)
+ /* we use link ID == MAC ID */
+ vif = iwl_mvm_rcu_dereference_vif_id(mvm, link_id, true);
+ if (!vif)
goto out_unlock;
id = link_id;
- mac_link_id = bss_conf->link_id;
- vif = bss_conf->vif;
- csa_active = bss_conf->csa_active;
+ mac_link_id = vif->bss_conf.link_id;
+ csa_active = vif->bss_conf.csa_active;
}
mvmvif = iwl_mvm_vif_from_mac80211(vif);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 956b491ae5a4..4ad3d32683d8 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -5,6 +5,7 @@
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#include <linux/kernel.h>
+#include <linux/fips.h>
#include <linux/slab.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
@@ -165,12 +166,6 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy,
mvm->lar_regdom_set = true;
mvm->mcc_src = src_id;
- if (!iwl_puncturing_is_allowed_in_bios(mvm->bios_enable_puncturing,
- le16_to_cpu(resp->mcc)))
- ieee80211_hw_set(mvm->hw, DISALLOW_PUNCTURING);
- else
- __clear_bit(IEEE80211_HW_DISALLOW_PUNCTURING, mvm->hw->flags);
-
iwl_mei_set_country_code(__le16_to_cpu(resp->mcc));
out:
@@ -298,7 +293,8 @@ static const struct wiphy_iftype_ext_capab add_iftypes_ext_capa[] = {
},
};
-int iwl_mvm_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
+int iwl_mvm_op_get_antenna(struct ieee80211_hw *hw, int radio_idx,
+ u32 *tx_ant, u32 *rx_ant)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
*tx_ant = iwl_mvm_get_valid_tx_ant(mvm);
@@ -306,13 +302,15 @@ int iwl_mvm_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
return 0;
}
-int iwl_mvm_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
+int iwl_mvm_op_set_antenna(struct ieee80211_hw *hw, int radio_idx, u32 tx_ant,
+ u32 rx_ant)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
/* This has been tested on those devices only */
if (mvm->trans->mac_cfg->device_family != IWL_DEVICE_FAMILY_9000 &&
- mvm->trans->mac_cfg->device_family != IWL_DEVICE_FAMILY_22000)
+ mvm->trans->mac_cfg->device_family != IWL_DEVICE_FAMILY_22000 &&
+ mvm->trans->mac_cfg->device_family != IWL_DEVICE_FAMILY_AX210)
return -EOPNOTSUPP;
if (!mvm->nvm_data)
@@ -464,7 +462,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
IWL_ERR(mvm,
"iwlmvm doesn't allow to disable BT Coex, check bt_coex_active module parameter\n");
- ieee80211_hw_set(hw, MFP_CAPABLE);
+ if (!fips_enabled)
+ ieee80211_hw_set(hw, MFP_CAPABLE);
+
mvm->ciphers[hw->wiphy->n_cipher_suites] = WLAN_CIPHER_SUITE_AES_CMAC;
hw->wiphy->n_cipher_suites++;
if (iwl_mvm_has_new_rx_api(mvm)) {
@@ -488,12 +488,17 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->wiphy->pmsr_capa = &iwl_mvm_pmsr_capa;
}
- if (sec_key_ver &&
+ /*
+ * beacon protection must be handled by firmware,
+ * so cannot be done with fips_enabled
+ */
+ if (!fips_enabled && sec_key_ver &&
fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_BIGTK_TX_SUPPORT))
wiphy_ext_feature_set(hw->wiphy,
NL80211_EXT_FEATURE_BEACON_PROTECTION);
- else if (fw_has_capa(&mvm->fw->ucode_capa,
+ else if (!fips_enabled &&
+ fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_BIGTK_SUPPORT))
wiphy_ext_feature_set(hw->wiphy,
NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT);
@@ -733,7 +738,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
#ifdef CONFIG_PM_SLEEP
if ((unified || mvm->fw->img[IWL_UCODE_WOWLAN].num_sec) &&
- device_can_wakeup(mvm->trans->dev)) {
+ device_can_wakeup(mvm->trans->dev) && !fips_enabled) {
mvm->wowlan.flags |= WIPHY_WOWLAN_MAGIC_PKT |
WIPHY_WOWLAN_DISCONNECT |
WIPHY_WOWLAN_EAP_IDENTITY_REQ |
@@ -1518,10 +1523,6 @@ int iwl_mvm_set_tx_power(struct iwl_mvm *mvm,
len = sizeof(cmd_v9_v10.v9);
else if (cmd_ver == 8)
len = sizeof(cmd.v8);
- else if (cmd_ver == 7)
- len = sizeof(cmd.v7);
- else if (cmd_ver == 6)
- len = sizeof(cmd.v6);
else if (fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_REDUCE_TX_POWER))
len = sizeof(cmd.v5);
@@ -1772,6 +1773,8 @@ void iwl_mvm_mac_init_mvmvif(struct iwl_mvm *mvm, struct iwl_mvm_vif *mvmvif)
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
return;
+ mvmvif->deflink.average_beacon_energy = 0;
+
INIT_DELAYED_WORK(&mvmvif->csa_work,
iwl_mvm_channel_switch_disconnect_wk);
@@ -1809,9 +1812,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
vif->driver_flags = IEEE80211_VIF_REMOVE_AP_AFTER_DISASSOC;
- ret = iwl_mvm_set_link_mapping(mvm, vif, &vif->bss_conf);
- if (ret)
- goto out;
+ iwl_mvm_set_link_fw_id(mvm, vif, &vif->bss_conf);
/*
* Not much to do here. The stack will not allow interface
@@ -1832,12 +1833,6 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
rcu_assign_pointer(mvm->vif_id_to_mac[mvmvif->id], vif);
- /* Currently not much to do for NAN */
- if (vif->type == NL80211_IFTYPE_NAN) {
- ret = 0;
- goto out;
- }
-
/*
* The AP binding flow can be done only after the beacon
* template is configured (which happens only in the mac80211
@@ -2012,7 +2007,6 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
mvm->monitor_on = false;
out:
- iwl_mvm_unset_link_mapping(mvm, vif, &vif->bss_conf);
if (vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_ADHOC) {
iwl_mvm_dealloc_int_sta(mvm, &mvmvif->deflink.mcast_sta);
@@ -3338,7 +3332,7 @@ void iwl_mvm_mac_cancel_hw_scan(struct ieee80211_hw *hw,
* us to stop a hw_scan when it's already stopped. This can
* happen, for instance, if we stopped the scan ourselves,
* called ieee80211_scan_completed() and the userspace called
- * cancel scan scan before ieee80211_scan_work() could run.
+ * cancel scan before ieee80211_scan_work() could run.
* To handle that, simply return if the scan is not running.
*/
if (mvm->scan_status & IWL_MVM_SCAN_REGULAR)
@@ -4249,7 +4243,8 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
return ret;
}
-int iwl_mvm_mac_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
+int iwl_mvm_mac_set_rts_threshold(struct ieee80211_hw *hw, int radio_idx,
+ u32 value)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
@@ -4350,7 +4345,7 @@ int iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw,
* us to stop a sched_scan when it's already stopped. This
* can happen, for instance, if we stopped the scan ourselves,
* called ieee80211_sched_scan_stopped() and the userspace called
- * stop sched scan scan before ieee80211_sched_scan_stopped_work()
+ * stop sched scan before ieee80211_sched_scan_stopped_work()
* could run. To handle this, simply return if the scan is
* not running.
*/
@@ -4614,6 +4609,10 @@ int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ /* When resuming from wowlan, FW already knows about the newest keys */
+ if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status))
+ return 0;
+
guard(mvm)(mvm);
return __iwl_mvm_mac_set_key(hw, cmd, vif, sta, key);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
index 3c255ae916c8..2d116a41913c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
@@ -32,9 +32,9 @@ static void iwl_mvm_mld_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
unsigned int link_id;
int cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
WIDE_ID(MAC_CONF_GROUP,
- MAC_CONFIG_CMD), 0);
+ MAC_CONFIG_CMD), 1);
- if (WARN_ON(cmd_ver < 1 || cmd_ver > 3))
+ if (WARN_ON(cmd_ver > 3))
return;
cmd->id_and_color = cpu_to_le32(mvmvif->id);
@@ -282,9 +282,6 @@ int iwl_mvm_mld_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ret;
- if (WARN_ON_ONCE(vif->type == NL80211_IFTYPE_NAN))
- return -EOPNOTSUPP;
-
if (WARN_ONCE(mvmvif->uploaded, "Adding active MAC %pM/%d\n",
vif->addr, ieee80211_vif_type_p2p(vif)))
return -EIO;
@@ -307,9 +304,6 @@ int iwl_mvm_mld_mac_ctxt_changed(struct iwl_mvm *mvm,
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- if (WARN_ON_ONCE(vif->type == NL80211_IFTYPE_NAN))
- return -EOPNOTSUPP;
-
if (WARN_ONCE(!mvmvif->uploaded, "Changing inactive MAC %pM/%d\n",
vif->addr, ieee80211_vif_type_p2p(vif)))
return -EIO;
@@ -327,9 +321,6 @@ int iwl_mvm_mld_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
};
int ret;
- if (WARN_ON_ONCE(vif->type == NL80211_IFTYPE_NAN))
- return -EOPNOTSUPP;
-
if (WARN_ONCE(!mvmvif->uploaded, "Removing inactive MAC %pM/%d\n",
vif->addr, ieee80211_vif_type_p2p(vif)))
return -EIO;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index a4f412e750d0..fdaeefa305e1 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -304,6 +304,8 @@ struct iwl_probe_resp_data {
* @mcast_sta: multicast station
* @phy_ctxt: phy context allocated to this link, if any
* @bf_data: beacon filtering data
+ * @average_beacon_energy: average beacon energy for beacons received during
+ * client connections
*/
struct iwl_mvm_vif_link_info {
u8 bssid[ETH_ALEN];
@@ -342,6 +344,7 @@ struct iwl_mvm_vif_link_info {
u16 mgmt_queue;
struct iwl_mvm_link_bf_data bf_data;
+ u32 average_beacon_energy;
};
/**
@@ -374,7 +377,6 @@ struct iwl_mvm_vif_link_info {
* preventing the enablement of EMLSR
* @IWL_MVM_ESR_EXIT_CSA: CSA happened, so exit EMLSR
* @IWL_MVM_ESR_EXIT_LINK_USAGE: Exit EMLSR due to low tpt on secondary link
- * @IWL_MVM_ESR_EXIT_FAIL_ENTRY: Exit EMLSR due to entry failure
*/
enum iwl_mvm_esr_state {
IWL_MVM_ESR_BLOCKED_PREVENTION = 0x1,
@@ -390,7 +392,6 @@ enum iwl_mvm_esr_state {
IWL_MVM_ESR_EXIT_BANDWIDTH = 0x80000,
IWL_MVM_ESR_EXIT_CSA = 0x100000,
IWL_MVM_ESR_EXIT_LINK_USAGE = 0x200000,
- IWL_MVM_ESR_EXIT_FAIL_ENTRY = 0x400000,
};
#define IWL_MVM_BLOCK_ESR_REASONS 0xffff
@@ -1179,8 +1180,6 @@ struct iwl_mvm {
struct ieee80211_vif __rcu *vif_id_to_mac[NUM_MAC_INDEX_DRIVER];
- struct ieee80211_bss_conf __rcu *link_id_to_link_conf[IWL_FW_MAX_LINK_ID + 1];
-
u8 *error_recovery_buf;
#ifdef CONFIG_IWLWIFI_LEDS
@@ -1326,7 +1325,6 @@ struct iwl_mvm {
u8 range_resp;
} cmd_ver;
- struct ieee80211_vif *nan_vif;
struct iwl_mvm_baid_data __rcu *baid_map[IWL_MAX_BAID];
/*
@@ -1372,7 +1370,6 @@ struct iwl_mvm {
struct iwl_mvm_acs_survey *acs_survey;
bool statistics_clear;
- u32 bios_enable_puncturing;
};
/* Extract MVM priv from op_mode and _hw */
@@ -1488,20 +1485,6 @@ iwl_mvm_rcu_dereference_vif_id(struct iwl_mvm *mvm, u8 vif_id, bool rcu)
lockdep_is_held(&mvm->mutex));
}
-static inline struct ieee80211_bss_conf *
-iwl_mvm_rcu_fw_link_id_to_link_conf(struct iwl_mvm *mvm, u8 link_id, bool rcu)
-{
- if (IWL_FW_CHECK(mvm, link_id >= ARRAY_SIZE(mvm->link_id_to_link_conf),
- "erroneous FW link ID: %d\n", link_id))
- return NULL;
-
- if (rcu)
- return rcu_dereference(mvm->link_id_to_link_conf[link_id]);
-
- return rcu_dereference_protected(mvm->link_id_to_link_conf[link_id],
- lockdep_is_held(&mvm->mutex));
-}
-
static inline bool iwl_mvm_is_adaptive_dwell_supported(struct iwl_mvm *mvm)
{
return fw_has_api(&mvm->fw->ucode_capa,
@@ -1837,11 +1820,12 @@ int iwl_mvm_tx_skb_sta(struct iwl_mvm *mvm, struct sk_buff *skb,
struct ieee80211_sta *sta);
int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb);
void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
- struct iwl_tx_cmd_v6 *tx_cmd,
+ struct iwl_tx_cmd_v6_params *tx_cmd_params,
struct ieee80211_tx_info *info, u8 sta_id);
-void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd_v6 *tx_cmd,
- struct ieee80211_tx_info *info,
- struct ieee80211_sta *sta, __le16 fc);
+void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm,
+ struct iwl_tx_cmd_v6_params *tx_cmd_params,
+ struct ieee80211_tx_info *info,
+ struct ieee80211_sta *sta, __le16 fc);
void iwl_mvm_mac_itxq_xmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq);
unsigned int iwl_mvm_max_amsdu_size(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
@@ -1870,12 +1854,12 @@ int iwl_mvm_set_sta_pkt_ext(struct iwl_mvm *mvm,
void iwl_mvm_async_handlers_purge(struct iwl_mvm *mvm);
static inline void iwl_mvm_set_tx_cmd_ccmp(struct ieee80211_tx_info *info,
- struct iwl_tx_cmd_v6 *tx_cmd)
+ struct iwl_tx_cmd_v6_params *tx_cmd_params)
{
struct ieee80211_key_conf *keyconf = info->control.hw_key;
- tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
- memcpy(tx_cmd->key, keyconf->key, keyconf->keylen);
+ tx_cmd_params->sec_ctl = TX_CMD_SEC_CCM;
+ memcpy(tx_cmd_params->key, keyconf->key, keyconf->keylen);
}
static inline void iwl_mvm_wait_for_async_handlers(struct iwl_mvm *mvm)
@@ -2093,6 +2077,9 @@ void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_channel_switch_error_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb);
+void iwl_mvm_rx_beacon_filter_notif(struct iwl_mvm *mvm,
+ struct iwl_rx_cmd_buffer *rxb);
+
/* Bindings */
int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
@@ -2100,15 +2087,13 @@ 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);
+void iwl_mvm_set_link_fw_id(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,
struct ieee80211_bss_conf *link_conf);
int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf,
u32 changes, bool active);
-int iwl_mvm_unset_link_mapping(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *link_conf);
int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf);
int iwl_mvm_disable_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
@@ -2133,7 +2118,6 @@ bool iwl_mvm_mld_valid_link_pair(struct ieee80211_vif *vif,
s8 iwl_mvm_average_dbm_values(const struct iwl_umac_scan_channel_survey_notif *notif);
-
extern const struct iwl_hcmd_arr iwl_mvm_groups[];
extern const unsigned int iwl_mvm_groups_size;
#endif
@@ -2866,13 +2850,16 @@ void iwl_mvm_mac_wake_tx_queue(struct ieee80211_hw *hw,
int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_ampdu_params *params);
-int iwl_mvm_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
-int iwl_mvm_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant);
+int iwl_mvm_op_get_antenna(struct ieee80211_hw *hw, int radio_idx, u32 *tx_ant,
+ u32 *rx_ant);
+int iwl_mvm_op_set_antenna(struct ieee80211_hw *hw, int radio_idx, u32 tx_ant,
+ u32 rx_ant);
int iwl_mvm_mac_start(struct ieee80211_hw *hw);
void iwl_mvm_mac_reconfig_complete(struct ieee80211_hw *hw,
enum ieee80211_reconfig_type reconfig_type);
void iwl_mvm_mac_stop(struct ieee80211_hw *hw, bool suspend);
-static inline int iwl_mvm_mac_config(struct ieee80211_hw *hw, u32 changed)
+static inline int iwl_mvm_mac_config(struct ieee80211_hw *hw, int radio_idx,
+ u32 changed)
{
return 0;
}
@@ -2905,7 +2892,8 @@ iwl_mvm_mac_release_buffered_frames(struct ieee80211_hw *hw,
int num_frames,
enum ieee80211_frame_release_type reason,
bool more_data);
-int iwl_mvm_mac_set_rts_threshold(struct ieee80211_hw *hw, u32 value);
+int iwl_mvm_mac_set_rts_threshold(struct ieee80211_hw *hw, int radio_idx,
+ u32 value);
void iwl_mvm_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_link_sta *link_sta, u32 changed);
void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index a2dc5c3b0596..c7f08cde1f72 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -61,8 +61,10 @@ static int __init iwl_mvm_init(void)
}
ret = iwl_opmode_register("iwlmvm", &iwl_mvm_ops);
- if (ret)
+ if (ret) {
pr_err("Unable to register MVM op_mode: %d\n", ret);
+ iwl_mvm_rate_control_unregister();
+ }
return ret;
}
@@ -159,43 +161,6 @@ static void iwl_mvm_rx_esr_mode_notif(struct iwl_mvm *mvm,
iwl_mvm_get_primary_link(vif));
}
-static void iwl_mvm_rx_esr_trans_fail_notif(struct iwl_mvm *mvm,
- struct iwl_rx_cmd_buffer *rxb)
-{
- struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_esr_trans_fail_notif *notif = (void *)pkt->data;
- struct ieee80211_vif *vif = iwl_mvm_get_bss_vif(mvm);
- u8 fw_link_id = le32_to_cpu(notif->link_id);
- struct ieee80211_bss_conf *bss_conf;
-
- if (IS_ERR_OR_NULL(vif))
- return;
-
- IWL_DEBUG_INFO(mvm, "Failed to %s eSR on link %d, reason %d\n",
- le32_to_cpu(notif->activation) ? "enter" : "exit",
- le32_to_cpu(notif->link_id),
- le32_to_cpu(notif->err_code));
-
- /* we couldn't go back to single link, disconnect */
- if (!le32_to_cpu(notif->activation)) {
- iwl_mvm_connection_loss(mvm, vif, "emlsr exit failed");
- return;
- }
-
- bss_conf = iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, fw_link_id, false);
- if (IWL_FW_CHECK(mvm, !bss_conf,
- "FW reported failure to activate EMLSR on a non-existing link: %d\n",
- fw_link_id))
- return;
-
- /*
- * We failed to activate the second link and enter EMLSR, we need to go
- * back to single link.
- */
- iwl_mvm_exit_esr(mvm, vif, IWL_MVM_ESR_EXIT_FAIL_ENTRY,
- bss_conf->link_id);
-}
-
static void iwl_mvm_rx_monitor_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb)
{
@@ -524,10 +489,11 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
RX_HANDLER_GRP(SCAN_GROUP, CHANNEL_SURVEY_NOTIF,
iwl_mvm_rx_channel_survey_notif, RX_HANDLER_ASYNC_LOCKED,
struct iwl_umac_scan_channel_survey_notif),
- RX_HANDLER_GRP(MAC_CONF_GROUP, EMLSR_TRANS_FAIL_NOTIF,
- iwl_mvm_rx_esr_trans_fail_notif,
- RX_HANDLER_ASYNC_LOCKED_WIPHY,
- struct iwl_esr_trans_fail_notif),
+ RX_HANDLER_GRP(DATA_PATH_GROUP, BEACON_FILTER_IN_NOTIF,
+ iwl_mvm_rx_beacon_filter_notif,
+ RX_HANDLER_ASYNC_LOCKED,
+ /* same size as v1 */
+ struct iwl_beacon_filter_notif),
};
#undef RX_HANDLER
#undef RX_HANDLER_GRP
@@ -658,7 +624,6 @@ static const struct iwl_hcmd_names iwl_mvm_mac_conf_names[] = {
HCMD_NAME(STA_REMOVE_CMD),
HCMD_NAME(STA_DISABLE_TX_CMD),
HCMD_NAME(ROC_CMD),
- HCMD_NAME(EMLSR_TRANS_FAIL_NOTIF),
HCMD_NAME(ROC_NOTIF),
HCMD_NAME(CHANNEL_SWITCH_ERROR_NOTIF),
HCMD_NAME(MISSED_VAP_NOTIF),
@@ -699,6 +664,7 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = {
HCMD_NAME(ESR_MODE_NOTIF),
HCMD_NAME(MONITOR_NOTIF),
HCMD_NAME(THERMAL_DUAL_CHAIN_REQUEST),
+ HCMD_NAME(BEACON_FILTER_IN_NOTIF),
HCMD_NAME(STA_PM_NOTIF),
HCMD_NAME(MU_GROUP_MGMT_NOTIF),
HCMD_NAME(RX_QUEUES_NOTIFICATION),
@@ -1395,8 +1361,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
}
}
- mvm->bios_enable_puncturing = iwl_uefi_get_puncturing(&mvm->fwrt);
-
if (iwl_mvm_has_new_tx_api(mvm)) {
/*
* If we have the new TX/queue allocation API initialize them
@@ -2053,7 +2017,7 @@ static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode,
if (type == IWL_ERR_TYPE_CMD_QUEUE_FULL)
IWL_ERR(mvm, "Command queue full!\n");
- else if (!test_bit(STATUS_TRANS_DEAD, &mvm->trans->status) &&
+ else if (!iwl_trans_is_dead(mvm->trans) &&
!test_and_clear_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE,
&mvm->status))
iwl_mvm_dump_nic_error_log(mvm);
@@ -2155,6 +2119,17 @@ static void iwl_op_mode_mvm_time_point(struct iwl_op_mode *op_mode,
iwl_dbg_tlv_time_point(&mvm->fwrt, tp_id, tp_data);
}
+static void iwl_mvm_dump(struct iwl_op_mode *op_mode)
+{
+ struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
+ struct iwl_fw_runtime *fwrt = &mvm->fwrt;
+
+ if (!iwl_trans_fw_running(fwrt->trans))
+ return;
+
+ iwl_dbg_tlv_time_point(fwrt, IWL_FW_INI_TIME_POINT_USER_TRIGGER, NULL);
+}
+
#ifdef CONFIG_PM_SLEEP
static void iwl_op_mode_mvm_device_powered_off(struct iwl_op_mode *op_mode)
{
@@ -2217,4 +2192,5 @@ static const struct iwl_op_mode_ops iwl_mvm_ops_mq = {
IWL_MVM_COMMON_OPS,
.rx = iwl_mvm_rx_mq,
.rx_rss = iwl_mvm_rx_mq_rss,
+ .dump = iwl_mvm_dump,
};
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/power.c b/drivers/net/wireless/intel/iwlwifi/mvm/power.c
index 0057fddf88f0..610de29b7be0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/power.c
@@ -231,7 +231,6 @@ static void iwl_mvm_allow_uapsd_iterator(void *_data, u8 *mac,
switch (vif->type) {
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_ADHOC:
- case NL80211_IFTYPE_NAN:
data->allow_uapsd = false;
break;
case NL80211_IFTYPE_STATION:
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ptp.c b/drivers/net/wireless/intel/iwlwifi/mvm/ptp.c
index e89259de6f4c..06a4c9f74797 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ptp.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ptp.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2021 - 2023 Intel Corporation
+ * Copyright (C) 2021 - 2023, 2025 Intel Corporation
*/
#include "mvm.h"
@@ -298,9 +298,9 @@ void iwl_mvm_ptp_init(struct iwl_mvm *mvm)
PTR_ERR(mvm->ptp_data.ptp_clock));
mvm->ptp_data.ptp_clock = NULL;
} else if (mvm->ptp_data.ptp_clock) {
- IWL_INFO(mvm, "Registered PHC clock: %s, with index: %d\n",
- mvm->ptp_data.ptp_clock_info.name,
- ptp_clock_index(mvm->ptp_data.ptp_clock));
+ IWL_DEBUG_INFO(mvm, "Registered PHC clock: %s, with index: %d\n",
+ mvm->ptp_data.ptp_clock_info.name,
+ ptp_clock_index(mvm->ptp_data.ptp_clock));
}
}
@@ -312,9 +312,9 @@ void iwl_mvm_ptp_init(struct iwl_mvm *mvm)
void iwl_mvm_ptp_remove(struct iwl_mvm *mvm)
{
if (mvm->ptp_data.ptp_clock) {
- IWL_INFO(mvm, "Unregistering PHC clock: %s, with index: %d\n",
- mvm->ptp_data.ptp_clock_info.name,
- ptp_clock_index(mvm->ptp_data.ptp_clock));
+ IWL_DEBUG_INFO(mvm, "Unregistering PHC clock: %s, with index: %d\n",
+ mvm->ptp_data.ptp_clock_info.name,
+ ptp_clock_index(mvm->ptp_data.ptp_clock));
ptp_clock_unregister(mvm->ptp_data.ptp_clock);
mvm->ptp_data.ptp_clock = NULL;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
index 69259ebb966b..dfb062b7c5c2 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
@@ -411,6 +411,7 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
* with the mac80211 subsystem. This should be performed prior to calling
* ieee80211_register_hw
*
+ * Return: negative error code, or 0 on success
*/
int iwl_mvm_rate_control_register(void);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
index 8eb0aa448c85..8fae0d41b119 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
@@ -877,28 +877,28 @@ iwl_mvm_stat_iterator_all_links(struct iwl_mvm *mvm,
u32 rx_bytes[MAC_INDEX_AUX] = {};
int fw_link_id;
- for (fw_link_id = 0; fw_link_id < ARRAY_SIZE(mvm->link_id_to_link_conf);
+ /* driver uses link ID == MAC ID */
+ for (fw_link_id = 0; fw_link_id < ARRAY_SIZE(mvm->vif_id_to_mac);
fw_link_id++) {
struct iwl_stats_ntfy_per_link *link_stats;
- struct ieee80211_bss_conf *bss_conf;
- struct iwl_mvm_vif *mvmvif;
struct iwl_mvm_vif_link_info *link_info;
+ struct iwl_mvm_vif *mvmvif;
+ struct ieee80211_vif *vif;
int link_id;
int sig;
- bss_conf = iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, fw_link_id,
- false);
- if (!bss_conf)
+ vif = iwl_mvm_rcu_dereference_vif_id(mvm, fw_link_id, false);
+ if (!vif)
continue;
- if (bss_conf->vif->type != NL80211_IFTYPE_STATION)
+ if (vif->type != NL80211_IFTYPE_STATION)
continue;
- link_id = bss_conf->link_id;
+ link_id = vif->bss_conf.link_id;
if (link_id >= ARRAY_SIZE(mvmvif->link))
continue;
- mvmvif = iwl_mvm_vif_from_mac80211(bss_conf->vif);
+ mvmvif = iwl_mvm_vif_from_mac80211(vif);
link_info = mvmvif->link[link_id];
if (!link_info)
continue;
@@ -916,8 +916,7 @@ iwl_mvm_stat_iterator_all_links(struct iwl_mvm *mvm,
if (link_info->phy_ctxt &&
link_info->phy_ctxt->channel->band == NL80211_BAND_2GHZ)
- iwl_mvm_bt_coex_update_link_esr(mvm, bss_conf->vif,
- link_id);
+ iwl_mvm_bt_coex_update_link_esr(mvm, vif, link_id);
/* make sure that beacon statistics don't go backwards with TCM
* request to clear statistics
@@ -927,8 +926,7 @@ iwl_mvm_stat_iterator_all_links(struct iwl_mvm *mvm,
mvmvif->link[link_id]->beacon_stats.num_beacons;
sig = -le32_to_cpu(link_stats->beacon_filter_average_energy);
- iwl_mvm_update_link_sig(bss_conf->vif, sig, link_info,
- bss_conf);
+ iwl_mvm_update_link_sig(vif, sig, link_info, &vif->bss_conf);
if (WARN_ONCE(mvmvif->id >= MAC_INDEX_AUX,
"invalid mvmvif id: %d", mvmvif->id))
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
index 077aadbf95db..62e76a79f621 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
@@ -246,13 +246,62 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
ieee80211_rx_napi(mvm->hw, sta, skb, napi);
}
+static bool iwl_mvm_used_average_energy(struct iwl_mvm *mvm,
+ struct iwl_rx_mpdu_desc *desc,
+ struct ieee80211_hdr *hdr,
+ struct ieee80211_rx_status *rx_status)
+{
+ struct iwl_mvm_vif *mvm_vif;
+ struct ieee80211_vif *vif;
+ u32 id;
+
+ if (unlikely(!hdr || !desc))
+ return false;
+
+ if (likely(!ieee80211_is_beacon(hdr->frame_control)))
+ return false;
+
+ /* for the link conf lookup */
+ guard(rcu)();
+
+ /* MAC or link ID depending on FW, but driver has them equal */
+ id = u8_get_bits(desc->mac_phy_band,
+ IWL_RX_MPDU_MAC_PHY_BAND_MAC_MASK);
+
+ /* >= means AUX MAC/link ID, no energy correction needed then */
+ if (id >= ARRAY_SIZE(mvm->vif_id_to_mac))
+ return false;
+
+ vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true);
+ if (!vif)
+ return false;
+
+ mvm_vif = iwl_mvm_vif_from_mac80211(vif);
+
+ /*
+ * If we know the MAC by MAC or link ID then the frame was
+ * received for the link, so by filtering it means it was
+ * from the AP the link is connected to.
+ */
+
+ /* skip also in case we don't have it (yet) */
+ if (!mvm_vif->deflink.average_beacon_energy)
+ return false;
+
+ IWL_DEBUG_STATS(mvm, "energy override by average %d\n",
+ mvm_vif->deflink.average_beacon_energy);
+ rx_status->signal = -mvm_vif->deflink.average_beacon_energy;
+ return true;
+}
+
static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,
+ struct iwl_rx_mpdu_desc *desc,
+ struct ieee80211_hdr *hdr,
struct ieee80211_rx_status *rx_status,
u32 rate_n_flags, int energy_a,
int energy_b)
{
int max_energy;
- u32 rate_flags = rate_n_flags;
energy_a = energy_a ? -energy_a : S8_MIN;
energy_b = energy_b ? -energy_b : S8_MIN;
@@ -261,9 +310,11 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,
IWL_DEBUG_STATS(mvm, "energy In A %d B %d, and max %d\n",
energy_a, energy_b, max_energy);
+ if (iwl_mvm_used_average_energy(mvm, desc, hdr, rx_status))
+ return;
+
rx_status->signal = max_energy;
- rx_status->chains =
- (rate_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS;
+ rx_status->chains = u32_get_bits(rate_n_flags, RATE_MCS_ANT_AB_MSK);
rx_status->chain_signal[0] = energy_a;
rx_status->chain_signal[1] = energy_b;
}
@@ -854,10 +905,15 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
* already ahead and it will be dropped.
* If the last sub-frame is not on this queue - we will get frame
* release notification with up to date NSSN.
+ * If this is the first frame that is stored in the buffer, the head_sn
+ * may be outdated. Update it based on the last NSSN to make sure it
+ * will be released when the frame release notification arrives.
*/
if (!amsdu || last_subframe)
iwl_mvm_release_frames(mvm, sta, napi, baid_data,
buffer, nssn);
+ else if (buffer->num_stored == 1)
+ buffer->head_sn = nssn;
spin_unlock_bh(&buffer->lock);
return true;
@@ -1906,8 +1962,11 @@ static void iwl_mvm_rx_get_sta_block_tx(void *data, struct ieee80211_sta *sta)
/*
* Note: requires also rx_status->band to be prefilled, as well
* as phy_data (apart from phy_data->info_type)
+ * Note: desc/hdr may be NULL
*/
static void iwl_mvm_rx_fill_status(struct iwl_mvm *mvm,
+ struct iwl_rx_mpdu_desc *desc,
+ struct ieee80211_hdr *hdr,
struct sk_buff *skb,
struct iwl_mvm_rx_phy_data *phy_data,
int queue)
@@ -1962,7 +2021,7 @@ static void iwl_mvm_rx_fill_status(struct iwl_mvm *mvm,
rx_status->freq = ieee80211_channel_to_frequency(phy_data->channel,
rx_status->band);
- iwl_mvm_get_signal_strength(mvm, rx_status, rate_n_flags,
+ iwl_mvm_get_signal_strength(mvm, desc, hdr, rx_status, rate_n_flags,
phy_data->energy_a, phy_data->energy_b);
/* using TLV format and must be after all fixed len fields */
@@ -2215,7 +2274,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
goto out;
}
- iwl_mvm_rx_fill_status(mvm, skb, &phy_data, queue);
+ iwl_mvm_rx_fill_status(mvm, desc, hdr, skb, &phy_data, queue);
if (sta) {
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
@@ -2445,7 +2504,7 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
rx_status->band = phy_data.channel > 14 ? NL80211_BAND_5GHZ :
NL80211_BAND_2GHZ;
- iwl_mvm_rx_fill_status(mvm, skb, &phy_data, queue);
+ iwl_mvm_rx_fill_status(mvm, NULL, NULL, skb, &phy_data, queue);
/* no more radio tap info should be put after this point.
*
@@ -2548,3 +2607,28 @@ void iwl_mvm_rx_bar_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
out:
rcu_read_unlock();
}
+
+void iwl_mvm_rx_beacon_filter_notif(struct iwl_mvm *mvm,
+ struct iwl_rx_cmd_buffer *rxb)
+{
+ struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ /* MAC or link ID in v1/v2, but driver has the IDs equal */
+ struct iwl_beacon_filter_notif *notif = (void *)pkt->data;
+ u32 id = le32_to_cpu(notif->link_id);
+ struct iwl_mvm_vif *mvm_vif;
+ struct ieee80211_vif *vif;
+
+ /* >= means AUX MAC/link ID, no energy correction needed then */
+ if (IWL_FW_CHECK(mvm, id >= ARRAY_SIZE(mvm->vif_id_to_mac),
+ "invalid link ID %d\n", id))
+ return;
+
+ vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, false);
+ if (!vif)
+ return;
+
+ mvm_vif = iwl_mvm_vif_from_mac80211(vif);
+
+ mvm_vif->deflink.average_beacon_energy =
+ le32_to_cpu(notif->average_energy);
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
index 60bd9c7e5f03..9ce1ce0dab34 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2024 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -11,6 +11,7 @@
#include "mvm.h"
#include "fw/api/scan.h"
#include "iwl-io.h"
+#include "iwl-utils.h"
#define IWL_DENSE_EBS_SCAN_RATIO 5
#define IWL_SPARSE_EBS_SCAN_RATIO 1
@@ -835,7 +836,7 @@ static inline bool iwl_mvm_scan_fits(struct iwl_mvm *mvm, int n_ssids,
int n_channels)
{
return ((n_ssids <= PROBE_OPTION_MAX) &&
- (n_channels <= mvm->fw->ucode_capa.n_scan_channels) &
+ (n_channels <= mvm->fw->ucode_capa.n_scan_channels) &&
(ies->common_ie_len +
ies->len[NL80211_BAND_2GHZ] + ies->len[NL80211_BAND_5GHZ] +
ies->len[NL80211_BAND_6GHZ] <=
@@ -3546,7 +3547,7 @@ int iwl_mvm_scan_stop(struct iwl_mvm *mvm, int type, bool notify)
if (!(mvm->scan_status & type))
return 0;
- if (!test_bit(STATUS_DEVICE_ENABLED, &mvm->trans->status)) {
+ if (!iwl_trans_device_enabled(mvm->trans)) {
ret = 0;
goto out;
}
@@ -3685,117 +3686,6 @@ static int iwl_mvm_chanidx_from_phy(struct iwl_mvm *mvm,
return -EINVAL;
}
-static u32 iwl_mvm_div_by_db(u32 value, u8 db)
-{
- /*
- * 2^32 * 10**(i / 10) for i = [1, 10], skipping 0 and simply stopping
- * at 10 dB and looping instead of using a much larger table.
- *
- * Using 64 bit math is overkill, but means the helper does not require
- * a limit on the input range.
- */
- static const u32 db_to_val[] = {
- 0xcb59185e, 0xa1866ba8, 0x804dce7a, 0x65ea59fe, 0x50f44d89,
- 0x404de61f, 0x331426af, 0x2892c18b, 0x203a7e5b, 0x1999999a,
- };
-
- while (value && db > 0) {
- u8 change = min_t(u8, db, ARRAY_SIZE(db_to_val));
-
- value = (((u64)value) * db_to_val[change - 1]) >> 32;
-
- db -= change;
- }
-
- return value;
-}
-
-VISIBLE_IF_IWLWIFI_KUNIT s8
-iwl_mvm_average_dbm_values(const struct iwl_umac_scan_channel_survey_notif *notif)
-{
- s8 average_magnitude;
- u32 average_factor;
- s8 sum_magnitude = -128;
- u32 sum_factor = 0;
- int i, count = 0;
-
- /*
- * To properly average the decibel values (signal values given in dBm)
- * we need to do the math in linear space. Doing a linear average of
- * dB (dBm) values is a bit annoying though due to the large range of
- * at least -10 to -110 dBm that will not fit into a 32 bit integer.
- *
- * A 64 bit integer should be sufficient, but then we still have the
- * problem that there are no directly usable utility functions
- * available.
- *
- * So, lets not deal with that and instead do much of the calculation
- * with a 16.16 fixed point integer along with a base in dBm. 16.16 bit
- * gives us plenty of head-room for adding up a few values and even
- * doing some math on it. And the tail should be accurate enough too
- * (1/2^16 is somewhere around -48 dB, so effectively zero).
- *
- * i.e. the real value of sum is:
- * sum = sum_factor / 2^16 * 10^(sum_magnitude / 10) mW
- *
- * However, that does mean we need to be able to bring two values to
- * a common base, so we need a helper for that.
- *
- * Note that this function takes an input with unsigned negative dBm
- * values but returns a signed dBm (i.e. a negative value).
- */
-
- for (i = 0; i < ARRAY_SIZE(notif->noise); i++) {
- s8 val_magnitude;
- u32 val_factor;
-
- if (notif->noise[i] == 0xff)
- continue;
-
- val_factor = 0x10000;
- val_magnitude = -notif->noise[i];
-
- if (val_magnitude <= sum_magnitude) {
- u8 div_db = sum_magnitude - val_magnitude;
-
- val_factor = iwl_mvm_div_by_db(val_factor, div_db);
- val_magnitude = sum_magnitude;
- } else {
- u8 div_db = val_magnitude - sum_magnitude;
-
- sum_factor = iwl_mvm_div_by_db(sum_factor, div_db);
- sum_magnitude = val_magnitude;
- }
-
- sum_factor += val_factor;
- count++;
- }
-
- /* No valid noise measurement, return a very high noise level */
- if (count == 0)
- return 0;
-
- average_magnitude = sum_magnitude;
- average_factor = sum_factor / count;
-
- /*
- * average_factor will be a number smaller than 1.0 (0x10000) at this
- * point. What we need to do now is to adjust average_magnitude so that
- * average_factor is between -0.5 dB and 0.5 dB.
- *
- * Just do -1 dB steps and find the point where
- * -0.5 dB * -i dB = 0x10000 * 10^(-0.5/10) / i dB
- * = div_by_db(0xe429, i)
- * is smaller than average_factor.
- */
- for (i = 0; average_factor < iwl_mvm_div_by_db(0xe429, i); i++) {
- /* nothing */
- }
-
- return average_magnitude - i;
-}
-EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mvm_average_dbm_values);
-
void iwl_mvm_rx_channel_survey_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb)
{
@@ -3853,5 +3743,6 @@ void iwl_mvm_rx_channel_survey_notif(struct iwl_mvm *mvm,
info->time_busy = le32_to_cpu(notif->busy_time);
info->time_rx = le32_to_cpu(notif->rx_time);
info->time_tx = le32_to_cpu(notif->tx_time);
- info->noise = iwl_mvm_average_dbm_values(notif);
+ info->noise =
+ iwl_average_neg_dbm(notif->noise, ARRAY_SIZE(notif->noise));
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index 5f6797598998..11c6b86db4ec 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -2461,7 +2461,7 @@ void iwl_mvm_free_bcast_sta_queues(struct iwl_mvm *mvm,
mvmvif->deflink.bcast_sta.tfd_queue_msk &= ~BIT(queue);
}
-/* Send the FW a request to remove the station from it's internal data
+/* Send the FW a request to remove the station from its internal data
* structures, but DO NOT remove the entry from the local data structures. */
int iwl_mvm_send_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
@@ -2524,7 +2524,7 @@ void iwl_mvm_dealloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
}
/*
- * Send the FW a request to remove the station from it's internal data
+ * Send the FW a request to remove the station from its internal data
* structures, and in addition remove it from the local data structure.
*/
int iwl_mvm_rm_p2p_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
@@ -2677,7 +2677,7 @@ static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id,
}
/*
- * Send the FW a request to remove the station from it's internal data
+ * Send the FW a request to remove the station from its internal data
* structures, and in addition remove it from the local data structure.
*/
int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index 6b183f5e9bbc..f6906061510b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -214,7 +214,7 @@ struct iwl_mvm_vif;
*/
/**
- * enum iwl_mvm_agg_state
+ * enum iwl_mvm_agg_state - aggregation session state
*
* The state machine of the BA agreement establishment / tear down.
* These states relate to a specific RA / TID.
@@ -483,6 +483,7 @@ struct iwl_mvm_int_sta {
* about. Otherwise (if this is a new STA), this should be false.
* @flags: if update==true, this marks what is being changed via ORs of values
* from enum iwl_sta_modify_flag. Otherwise, this is ignored.
+ * Return: negative error code or 0 on success
*/
int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
bool update, unsigned int flags);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tests/Makefile b/drivers/net/wireless/intel/iwlwifi/mvm/tests/Makefile
index 895d53f223e9..bb33f4a06f1c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tests/Makefile
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tests/Makefile
@@ -1,3 +1,3 @@
-iwlmvm-tests-y += module.o links.o scan.o hcmd.o
+iwlmvm-tests-y += module.o links.o hcmd.o
obj-$(CONFIG_IWLWIFI_KUNIT_TESTS) += iwlmvm-tests.o
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tests/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/tests/scan.c
deleted file mode 100644
index 7a3275199ace..000000000000
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tests/scan.c
+++ /dev/null
@@ -1,110 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * KUnit tests for channel helper functions
- *
- * Copyright (C) 2024 Intel Corporation
- */
-#include <net/mac80211.h>
-#include "../mvm.h"
-#include <kunit/test.h>
-
-MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
-
-static const struct acs_average_db_case {
- const char *desc;
- u8 neg_dbm[22];
- s8 result;
-} acs_average_db_cases[] = {
- {
- .desc = "Smallest possible value, all filled",
- .neg_dbm = {
- 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128
- },
- .result = -128,
- },
- {
- .desc = "Biggest possible value, all filled",
- .neg_dbm = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0,
- },
- .result = 0,
- },
- {
- .desc = "Smallest possible value, partial filled",
- .neg_dbm = {
- 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
- 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff,
- },
- .result = -128,
- },
- {
- .desc = "Biggest possible value, partial filled",
- .neg_dbm = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff,
- },
- .result = 0,
- },
- {
- .desc = "Adding -80dBm to -75dBm until it is still rounded to -79dBm",
- .neg_dbm = {
- 75, 80, 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 0xff, 0xff, 0xff,
- 0xff, 0xff,
- },
- .result = -79,
- },
- {
- .desc = "Adding -80dBm to -75dBm until it is just rounded to -80dBm",
- .neg_dbm = {
- 75, 80, 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80, 0xff, 0xff,
- 0xff, 0xff,
- },
- .result = -80,
- },
-};
-
-KUNIT_ARRAY_PARAM_DESC(acs_average_db, acs_average_db_cases, desc)
-
-static void test_acs_average_db(struct kunit *test)
-{
- const struct acs_average_db_case *params = test->param_value;
- struct iwl_umac_scan_channel_survey_notif notif;
- int i;
-
- /* Test the values in the given order */
- for (i = 0; i < ARRAY_SIZE(params->neg_dbm); i++)
- notif.noise[i] = params->neg_dbm[i];
- KUNIT_ASSERT_EQ(test,
- iwl_mvm_average_dbm_values(&notif),
- params->result);
-
- /* Test in reverse order */
- for (i = 0; i < ARRAY_SIZE(params->neg_dbm); i++)
- notif.noise[ARRAY_SIZE(params->neg_dbm) - i - 1] =
- params->neg_dbm[i];
- KUNIT_ASSERT_EQ(test,
- iwl_mvm_average_dbm_values(&notif),
- params->result);
-}
-
-static struct kunit_case acs_average_db_case[] = {
- KUNIT_CASE_PARAM(test_acs_average_db, acs_average_db_gen_params),
- {}
-};
-
-static struct kunit_suite acs_average_db = {
- .name = "iwlmvm-acs-average-db",
- .test_cases = acs_average_db_case,
-};
-
-kunit_test_suite(acs_average_db);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
index 478408f802d9..aa653782d6d7 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
@@ -958,40 +958,19 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm,
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_session_prot_notif *notif = (void *)pkt->data;
- unsigned int ver =
- iwl_fw_lookup_notif_ver(mvm->fw, MAC_CONF_GROUP,
- SESSION_PROTECTION_NOTIF, 2);
int id = le32_to_cpu(notif->mac_link_id);
struct ieee80211_vif *vif;
struct iwl_mvm_vif *mvmvif;
- unsigned int notif_link_id;
rcu_read_lock();
- if (ver <= 2) {
- vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true);
- } else {
- struct ieee80211_bss_conf *link_conf =
- iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, id, true);
-
- if (!link_conf)
- goto out_unlock;
-
- notif_link_id = link_conf->link_id;
- vif = link_conf->vif;
- }
-
+ /* note we use link ID == MAC ID */
+ vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true);
if (!vif)
goto out_unlock;
mvmvif = iwl_mvm_vif_from_mac80211(vif);
- if (WARN(ver > 2 && mvmvif->time_event_data.link_id >= 0 &&
- mvmvif->time_event_data.link_id != notif_link_id,
- "SESSION_PROTECTION_NOTIF was received for link %u, while the current time event is on link %u\n",
- notif_link_id, mvmvif->time_event_data.link_id))
- goto out_unlock;
-
/* The vif is not a P2P_DEVICE, maintain its time_event_data */
if (vif->type != NL80211_IFTYPE_P2P_DEVICE) {
struct iwl_mvm_time_event_data *te_data =
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.h b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.h
index 49256ba4cf58..1ef8768756db 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2019-2020, 2023 Intel Corporation
+ * Copyright (C) 2012-2014, 2019-2020, 2023, 2025 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
*/
#ifndef __time_event_h__
@@ -124,6 +124,8 @@ void iwl_mvm_rx_roc_notif(struct iwl_mvm *mvm,
* ROC request, it will issue a notification to the driver that it is on the
* requested channel. Once the FW completes the ROC request it will issue
* another notification to the driver.
+ *
+ * Return: negative error code or 0 on success
*/
int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
int duration, enum ieee80211_roc_type type);
@@ -179,6 +181,8 @@ void iwl_mvm_remove_csa_period(struct iwl_mvm *mvm,
*
* This function is used to schedule NoA time event and is used to perform
* the channel switch flow.
+ *
+ * Return: negative error code or 0 on success
*/
int iwl_mvm_schedule_csa_period(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
@@ -188,7 +192,7 @@ int iwl_mvm_schedule_csa_period(struct iwl_mvm *mvm,
* iwl_mvm_te_scheduled - check if the fw received the TE cmd
* @te_data: the time event data that corresponds to that time event
*
- * This function returns true iff this TE is added to the fw.
+ * Return: %true if this TE is added to the fw, %false otherwise
*/
static inline bool
iwl_mvm_te_scheduled(struct iwl_mvm_time_event_data *te_data)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index ac2cf1b8ce23..25d1a882a6a0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -148,12 +148,12 @@ out:
* Sets most of the Tx cmd's fields
*/
void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
- struct iwl_tx_cmd_v6 *tx_cmd,
+ struct iwl_tx_cmd_v6_params *tx_cmd_params,
struct ieee80211_tx_info *info, u8 sta_id)
{
struct ieee80211_hdr *hdr = (void *)skb->data;
__le16 fc = hdr->frame_control;
- u32 tx_flags = le32_to_cpu(tx_cmd->tx_flags);
+ u32 tx_flags = le32_to_cpu(tx_cmd_params->tx_flags);
u32 len = skb->len + FCS_LEN;
bool amsdu = false;
u8 ac;
@@ -173,7 +173,7 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
if (ieee80211_is_data_qos(fc)) {
u8 *qc = ieee80211_get_qos_ctl(hdr);
- tx_cmd->tid_tspec = qc[0] & 0xf;
+ tx_cmd_params->tid_tspec = qc[0] & 0xf;
tx_flags &= ~TX_CMD_FLG_SEQ_CTL;
amsdu = *qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT;
} else if (ieee80211_is_back_req(fc)) {
@@ -182,17 +182,17 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
u16 ssn = le16_to_cpu(bar->start_seq_num);
tx_flags |= TX_CMD_FLG_ACK | TX_CMD_FLG_BAR;
- tx_cmd->tid_tspec = (control &
+ tx_cmd_params->tid_tspec = (control &
IEEE80211_BAR_CTRL_TID_INFO_MASK) >>
IEEE80211_BAR_CTRL_TID_INFO_SHIFT;
- WARN_ON_ONCE(tx_cmd->tid_tspec >= IWL_MAX_TID_COUNT);
- iwl_mvm_bar_check_trigger(mvm, bar->ra, tx_cmd->tid_tspec,
+ WARN_ON_ONCE(tx_cmd_params->tid_tspec >= IWL_MAX_TID_COUNT);
+ iwl_mvm_bar_check_trigger(mvm, bar->ra, tx_cmd_params->tid_tspec,
ssn);
} else {
if (ieee80211_is_data(fc))
- tx_cmd->tid_tspec = IWL_TID_NON_QOS;
+ tx_cmd_params->tid_tspec = IWL_TID_NON_QOS;
else
- tx_cmd->tid_tspec = IWL_MAX_TID_COUNT;
+ tx_cmd_params->tid_tspec = IWL_MAX_TID_COUNT;
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
tx_flags |= TX_CMD_FLG_SEQ_CTL;
@@ -201,8 +201,8 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
}
/* Default to 0 (BE) when tid_spec is set to IWL_MAX_TID_COUNT */
- if (tx_cmd->tid_tspec < IWL_MAX_TID_COUNT)
- ac = tid_to_mac80211_ac[tx_cmd->tid_tspec];
+ if (tx_cmd_params->tid_tspec < IWL_MAX_TID_COUNT)
+ ac = tid_to_mac80211_ac[tx_cmd_params->tid_tspec];
else
ac = tid_to_mac80211_ac[0];
@@ -211,20 +211,20 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
if (ieee80211_is_mgmt(fc)) {
if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc))
- tx_cmd->pm_frame_timeout = cpu_to_le16(PM_FRAME_ASSOC);
+ tx_cmd_params->pm_frame_timeout = cpu_to_le16(PM_FRAME_ASSOC);
else if (ieee80211_is_action(fc))
- tx_cmd->pm_frame_timeout = cpu_to_le16(PM_FRAME_NONE);
+ tx_cmd_params->pm_frame_timeout = cpu_to_le16(PM_FRAME_NONE);
else
- tx_cmd->pm_frame_timeout = cpu_to_le16(PM_FRAME_MGMT);
+ tx_cmd_params->pm_frame_timeout = cpu_to_le16(PM_FRAME_MGMT);
/* The spec allows Action frames in A-MPDU, we don't support
* it
*/
WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_AMPDU);
} else if (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO) {
- tx_cmd->pm_frame_timeout = cpu_to_le16(PM_FRAME_MGMT);
+ tx_cmd_params->pm_frame_timeout = cpu_to_le16(PM_FRAME_MGMT);
} else {
- tx_cmd->pm_frame_timeout = cpu_to_le16(PM_FRAME_NONE);
+ tx_cmd_params->pm_frame_timeout = cpu_to_le16(PM_FRAME_NONE);
}
if (ieee80211_is_data(fc) && len > mvm->rts_threshold &&
@@ -236,13 +236,13 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
ieee80211_action_contains_tpc(skb))
tx_flags |= TX_CMD_FLG_WRITE_TX_POWER;
- tx_cmd->tx_flags = cpu_to_le32(tx_flags);
+ tx_cmd_params->tx_flags = cpu_to_le32(tx_flags);
/* Total # bytes to be transmitted - PCIe code will adjust for A-MSDU */
- tx_cmd->len = cpu_to_le16((u16)skb->len);
- tx_cmd->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
- tx_cmd->sta_id = sta_id;
+ tx_cmd_params->len = cpu_to_le16((u16)skb->len);
+ tx_cmd_params->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
+ tx_cmd_params->sta_id = sta_id;
- tx_cmd->offload_assist =
+ tx_cmd_params->offload_assist =
cpu_to_le16(iwl_mvm_tx_csum(mvm, skb, info, amsdu));
}
@@ -395,22 +395,23 @@ static __le32 iwl_mvm_get_tx_rate_n_flags(struct iwl_mvm *mvm,
/*
* Sets the fields in the Tx cmd that are rate related
*/
-void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd_v6 *tx_cmd,
- struct ieee80211_tx_info *info,
- struct ieee80211_sta *sta, __le16 fc)
+void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm,
+ struct iwl_tx_cmd_v6_params *tx_cmd_params,
+ struct ieee80211_tx_info *info,
+ struct ieee80211_sta *sta, __le16 fc)
{
/* Set retry limit on RTS packets */
- tx_cmd->rts_retry_limit = IWL_RTS_DFAULT_RETRY_LIMIT;
+ tx_cmd_params->rts_retry_limit = IWL_RTS_DFAULT_RETRY_LIMIT;
/* Set retry limit on DATA packets and Probe Responses*/
if (ieee80211_is_probe_resp(fc)) {
- tx_cmd->data_retry_limit = IWL_MGMT_DFAULT_RETRY_LIMIT;
- tx_cmd->rts_retry_limit =
- min(tx_cmd->data_retry_limit, tx_cmd->rts_retry_limit);
+ tx_cmd_params->data_retry_limit = IWL_MGMT_DFAULT_RETRY_LIMIT;
+ tx_cmd_params->rts_retry_limit =
+ min(tx_cmd_params->data_retry_limit, tx_cmd_params->rts_retry_limit);
} else if (ieee80211_is_back_req(fc)) {
- tx_cmd->data_retry_limit = IWL_BAR_DFAULT_RETRY_LIMIT;
+ tx_cmd_params->data_retry_limit = IWL_BAR_DFAULT_RETRY_LIMIT;
} else {
- tx_cmd->data_retry_limit = IWL_DEFAULT_TX_RETRY;
+ tx_cmd_params->data_retry_limit = IWL_DEFAULT_TX_RETRY;
}
/*
@@ -423,17 +424,17 @@ void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd_v6 *tx_cmd,
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
if (mvmsta->sta_state >= IEEE80211_STA_AUTHORIZED) {
- tx_cmd->initial_rate_index = 0;
- tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_STA_RATE);
+ tx_cmd_params->initial_rate_index = 0;
+ tx_cmd_params->tx_flags |= cpu_to_le32(TX_CMD_FLG_STA_RATE);
return;
}
} else if (ieee80211_is_back_req(fc)) {
- tx_cmd->tx_flags |=
+ tx_cmd_params->tx_flags |=
cpu_to_le32(TX_CMD_FLG_ACK | TX_CMD_FLG_BAR);
}
/* Set the rate in the TX cmd */
- tx_cmd->rate_n_flags = iwl_mvm_get_tx_rate_n_flags(mvm, info, sta, fc);
+ tx_cmd_params->rate_n_flags = iwl_mvm_get_tx_rate_n_flags(mvm, info, sta, fc);
}
static inline void iwl_mvm_set_tx_cmd_pn(struct ieee80211_tx_info *info,
@@ -458,7 +459,7 @@ static inline void iwl_mvm_set_tx_cmd_pn(struct ieee80211_tx_info *info,
*/
static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm,
struct ieee80211_tx_info *info,
- struct iwl_tx_cmd_v6 *tx_cmd,
+ struct iwl_tx_cmd_v6_params *tx_cmd_params,
struct sk_buff *skb_frag,
int hdrlen)
{
@@ -469,26 +470,26 @@ static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm,
switch (keyconf->cipher) {
case WLAN_CIPHER_SUITE_CCMP:
- iwl_mvm_set_tx_cmd_ccmp(info, tx_cmd);
+ iwl_mvm_set_tx_cmd_ccmp(info, tx_cmd_params);
iwl_mvm_set_tx_cmd_pn(info, crypto_hdr);
break;
case WLAN_CIPHER_SUITE_TKIP:
- tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
+ tx_cmd_params->sec_ctl = TX_CMD_SEC_TKIP;
pn = atomic64_inc_return(&keyconf->tx_pn);
ieee80211_tkip_add_iv(crypto_hdr, keyconf, pn);
- ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key);
+ ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd_params->key);
break;
case WLAN_CIPHER_SUITE_WEP104:
- tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
+ tx_cmd_params->sec_ctl |= TX_CMD_SEC_KEY128;
fallthrough;
case WLAN_CIPHER_SUITE_WEP40:
- tx_cmd->sec_ctl |= TX_CMD_SEC_WEP |
+ tx_cmd_params->sec_ctl |= TX_CMD_SEC_WEP |
((keyconf->keyidx << TX_CMD_SEC_WEP_KEY_IDX_POS) &
TX_CMD_SEC_WEP_KEY_IDX_MSK);
- memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen);
+ memcpy(&tx_cmd_params->key[3], keyconf->key, keyconf->keylen);
break;
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256:
@@ -501,12 +502,12 @@ static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm,
* one.
* Need to handle this.
*/
- tx_cmd->sec_ctl |= type | TX_CMD_SEC_KEY_FROM_TABLE;
- tx_cmd->key[0] = keyconf->hw_key_idx;
+ tx_cmd_params->sec_ctl |= type | TX_CMD_SEC_KEY_FROM_TABLE;
+ tx_cmd_params->key[0] = keyconf->hw_key_idx;
iwl_mvm_set_tx_cmd_pn(info, crypto_hdr);
break;
default:
- tx_cmd->sec_ctl |= TX_CMD_SEC_EXT;
+ tx_cmd_params->sec_ctl |= TX_CMD_SEC_EXT;
}
}
@@ -636,11 +637,11 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
tx_cmd = (struct iwl_tx_cmd_v6 *)dev_cmd->payload;
if (info->control.hw_key)
- iwl_mvm_set_tx_cmd_crypto(mvm, info, tx_cmd, skb, hdrlen);
+ iwl_mvm_set_tx_cmd_crypto(mvm, info, &tx_cmd->params, skb, hdrlen);
- iwl_mvm_set_tx_cmd(mvm, skb, tx_cmd, info, sta_id);
+ iwl_mvm_set_tx_cmd(mvm, skb, &tx_cmd->params, info, sta_id);
- iwl_mvm_set_tx_cmd_rate(mvm, tx_cmd, info, sta, hdr->frame_control);
+ iwl_mvm_set_tx_cmd_rate(mvm, &tx_cmd->params, info, sta, hdr->frame_control);
/* Copy MAC header from skb into command buffer */
iwl_mvm_copy_hdr(tx_cmd->hdr, hdr, hdrlen, addr3_override);