summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/intel/iwlwifi/mvm
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2024-09-04 17:20:14 -0700
committerJakub Kicinski <kuba@kernel.org>2024-09-04 17:20:14 -0700
commit43b7724487109368363bb5cda034b3f600278d14 (patch)
tree0ca0280d0e240aa38df3eab4b513b7bebfe465c1 /drivers/net/wireless/intel/iwlwifi/mvm
parentd57f7b45945ac0517ff8ea50655f00db6e8d637c (diff)
parent97b766f989bcd06e5a7651b1080001d7327012f5 (diff)
downloadlinux-43b7724487109368363bb5cda034b3f600278d14.tar.gz
linux-43b7724487109368363bb5cda034b3f600278d14.tar.bz2
linux-43b7724487109368363bb5cda034b3f600278d14.zip
Merge tag 'wireless-next-2024-09-04' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next
Kalle Valo says: ==================== pull-request: wireless-next-2024-09-04 here's a pull request to net-next tree, more info below. Please let me know if there are any problems. ==================== Conflicts: drivers/net/wireless/ath/ath12k/hw.c 38055789d151 ("wifi: ath12k: use 128 bytes aligned iova in transmit path for WCN7850") 8be12629b428 ("wifi: ath12k: restore ASPM for supported hardwares only") https://lore.kernel.org/87msldyj97.fsf@kernel.org Link: https://patch.msgid.link/20240904153205.64C11C4CEC2@smtp.kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/coex.c83
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/constants.h5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw.c29
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/link.c25
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c93
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c73
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c24
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h42
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/nvm.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c83
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rx.c17
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/scan.c54
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.c22
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/time-event.c14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tx.c24
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/utils.c64
22 files changed, 482 insertions, 223 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
index ad3e14a0d043..b607961970e9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
@@ -208,7 +208,7 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
}
struct iwl_bt_iterator_data {
- struct iwl_bt_coex_profile_notif *notif;
+ struct iwl_bt_coex_prof_old_notif *notif;
struct iwl_mvm *mvm;
struct ieee80211_chanctx_conf *primary;
struct ieee80211_chanctx_conf *secondary;
@@ -266,10 +266,26 @@ iwl_mvm_bt_coex_calculate_esr_mode(struct iwl_mvm *mvm,
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
bool have_wifi_loss_rate =
iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
- BT_PROFILE_NOTIFICATION, 0) > 4;
+ BT_PROFILE_NOTIFICATION, 0) > 4 ||
+ iwl_fw_lookup_notif_ver(mvm->fw, BT_COEX_GROUP,
+ PROFILE_NOTIF, 0) >= 1;
+ u8 wifi_loss_mid_high_rssi;
+ u8 wifi_loss_low_rssi;
u8 wifi_loss_rate;
- if (mvm->last_bt_notif.wifi_loss_low_rssi == BT_OFF)
+ if (iwl_fw_lookup_notif_ver(mvm->fw, BT_COEX_GROUP,
+ PROFILE_NOTIF, 0) >= 1) {
+ /* For now, we consider 2.4 GHz band / ANT_A only */
+ wifi_loss_mid_high_rssi =
+ mvm->last_bt_wifi_loss.wifi_loss_mid_high_rssi[PHY_BAND_24][0];
+ wifi_loss_low_rssi =
+ mvm->last_bt_wifi_loss.wifi_loss_low_rssi[PHY_BAND_24][0];
+ } else {
+ wifi_loss_mid_high_rssi = mvm->last_bt_notif.wifi_loss_mid_high_rssi;
+ wifi_loss_low_rssi = mvm->last_bt_notif.wifi_loss_low_rssi;
+ }
+
+ if (wifi_loss_low_rssi == BT_OFF)
return true;
if (primary)
@@ -286,20 +302,20 @@ iwl_mvm_bt_coex_calculate_esr_mode(struct iwl_mvm *mvm,
* we will get an update on this and exit eSR.
*/
if (!link_rssi)
- wifi_loss_rate = mvm->last_bt_notif.wifi_loss_mid_high_rssi;
+ wifi_loss_rate = wifi_loss_mid_high_rssi;
else if (mvmvif->esr_active)
/* RSSI needs to get really low to disable eSR... */
wifi_loss_rate =
link_rssi <= -IWL_MVM_BT_COEX_DISABLE_ESR_THRESH ?
- mvm->last_bt_notif.wifi_loss_low_rssi :
- mvm->last_bt_notif.wifi_loss_mid_high_rssi;
+ wifi_loss_low_rssi :
+ wifi_loss_mid_high_rssi;
else
/* ...And really high before we enable it back */
wifi_loss_rate =
link_rssi <= -IWL_MVM_BT_COEX_ENABLE_ESR_THRESH ?
- mvm->last_bt_notif.wifi_loss_low_rssi :
- mvm->last_bt_notif.wifi_loss_mid_high_rssi;
+ wifi_loss_low_rssi :
+ wifi_loss_mid_high_rssi;
return wifi_loss_rate <= IWL_MVM_BT_COEX_WIFI_LOSS_THRESH;
}
@@ -509,6 +525,35 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
iwl_mvm_bt_notif_per_link(mvm, vif, data, link_id);
}
+/* must be called under rcu_read_lock */
+static void iwl_mvm_bt_coex_notif_iterator(void *_data, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mvm *mvm = _data;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ if (vif->type != NL80211_IFTYPE_STATION)
+ return;
+
+ for (int link_id = 0;
+ link_id < IEEE80211_MLD_MAX_NUM_LINKS;
+ link_id++) {
+ struct ieee80211_bss_conf *link_conf =
+ rcu_dereference_check(vif->link_conf[link_id],
+ lockdep_is_held(&mvm->mutex));
+ struct ieee80211_chanctx_conf *chanctx_conf =
+ rcu_dereference_check(link_conf->chanctx_conf,
+ lockdep_is_held(&mvm->mutex));
+
+ if ((!chanctx_conf ||
+ chanctx_conf->def.chan->band != NL80211_BAND_2GHZ))
+ continue;
+
+ iwl_mvm_bt_coex_update_link_esr(mvm, vif, link_id);
+ }
+}
+
static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
{
struct iwl_bt_iterator_data data = {
@@ -591,11 +636,11 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
}
}
-void iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
- struct iwl_rx_cmd_buffer *rxb)
+void iwl_mvm_rx_bt_coex_old_notif(struct iwl_mvm *mvm,
+ struct iwl_rx_cmd_buffer *rxb)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_bt_coex_profile_notif *notif = (void *)pkt->data;
+ struct iwl_bt_coex_prof_old_notif *notif = (void *)pkt->data;
IWL_DEBUG_COEX(mvm, "BT Coex Notification received\n");
IWL_DEBUG_COEX(mvm, "\tBT ci compliance %d\n", notif->bt_ci_compliance);
@@ -612,6 +657,22 @@ void iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
iwl_mvm_bt_coex_notif_handle(mvm);
}
+void iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
+ struct iwl_rx_cmd_buffer *rxb)
+{
+ const struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ const struct iwl_bt_coex_profile_notif *notif = (const void *)pkt->data;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ mvm->last_bt_wifi_loss = *notif;
+
+ ieee80211_iterate_active_interfaces(mvm->hw,
+ IEEE80211_IFACE_ITER_NORMAL,
+ iwl_mvm_bt_coex_notif_iterator,
+ mvm);
+}
+
void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
enum ieee80211_rssi_event_data rssi_event)
{
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
index c4c1e67b9ac7..ddf484027d4f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
@@ -16,6 +16,8 @@
#define IWL_MVM_BT_COEX_WIFI_LOSS_THRESH 0
#define IWL_MVM_TRIGGER_LINK_SEL_TIME_SEC 30
#define IWL_MVM_TPT_COUNT_WINDOW_SEC 5
+#define IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS 5
+#define IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH 11
#define IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT (100 * USEC_PER_MSEC)
#define IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT (100 * USEC_PER_MSEC)
@@ -109,7 +111,7 @@
#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_FTM_NON_TB_MIN_TIME_BETWEEN_MSR 5
+#define IWL_MVM_FTM_NON_TB_MIN_TIME_BETWEEN_MSR 7
#define IWL_MVM_FTM_NON_TB_MAX_TIME_BETWEEN_MSR 1000
#define IWL_MVM_D3_DEBUG false
#define IWL_MVM_USE_TWT true
@@ -125,7 +127,6 @@
#define IWL_MVM_6GHZ_PASSIVE_SCAN_ASSOC_TIMEOUT 60 /* in seconds */
#define IWL_MVM_MIN_BEACON_INTERVAL_TU 16
#define IWL_MVM_AUTO_EML_ENABLE true
-#define IWL_MVM_MISSED_BEACONS_EXIT_ESR_THRESH 7
#define IWL_MVM_HIGH_RSSI_THRESH_20MHZ -67
#define IWL_MVM_LOW_RSSI_THRESH_20MHZ -71
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
index afd90a52d4ec..55245f913286 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
@@ -772,6 +772,7 @@ iwl_mvm_ftm_set_secured_ranging(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct iwl_mvm_ftm_iter_data target;
target.bssid = bssid;
+ target.cipher = cipher;
ieee80211_iter_keys(mvm->hw, vif, iter, &target);
} else {
memcpy(tk, entry->tk, sizeof(entry->tk));
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index 08c4898c8f1a..08546e673cf5 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -863,7 +863,10 @@ static int iwl_mvm_config_ltr(struct iwl_mvm *mvm)
int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
{
u32 cmd_id = REDUCE_TX_POWER_CMD;
- struct iwl_dev_tx_power_cmd cmd = {
+ struct iwl_dev_tx_power_cmd_v3_v8 cmd = {
+ .common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS),
+ };
+ struct iwl_dev_tx_power_cmd cmd_v9_v10 = {
.common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS),
};
__le16 *per_chain;
@@ -871,8 +874,19 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
u16 len = 0;
u32 n_subbands;
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 3);
+ void *cmd_data = &cmd;
- if (cmd_ver >= 7) {
+ if (cmd_ver == 10) {
+ len = sizeof(cmd_v9_v10.v10);
+ n_subbands = IWL_NUM_SUB_BANDS_V2;
+ per_chain = &cmd_v9_v10.v10.per_chain[0][0][0];
+ cmd_v9_v10.v10.flags =
+ cpu_to_le32(mvm->fwrt.reduced_power_flags);
+ } else if (cmd_ver == 9) {
+ 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];
@@ -899,9 +913,14 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
per_chain = cmd.v3.per_chain[0][0];
}
- /* all structs have the same common part, add it */
+ /* all structs have the same common part, add its length */
len += sizeof(cmd.common);
+ if (cmd_ver < 9)
+ len += sizeof(cmd.per_band);
+ else
+ cmd_data = &cmd_v9_v10;
+
ret = iwl_sar_fill_profile(&mvm->fwrt, per_chain,
IWL_NUM_CHAIN_TABLES,
n_subbands, prof_a, prof_b);
@@ -913,7 +932,7 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
iwl_mei_set_power_limit(per_chain);
IWL_DEBUG_RADIO(mvm, "Sending REDUCE_TX_POWER_CMD per chain\n");
- return iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, len, &cmd);
+ return iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, len, cmd_data);
}
int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
@@ -1464,7 +1483,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
RCU_INIT_POINTER(mvm->fw_id_to_link_sta[i], NULL);
}
- for (i = 0; i < IWL_MVM_FW_MAX_LINK_ID + 1; i++)
+ for (i = 0; i < IWL_FW_MAX_LINK_ID + 1; i++)
RCU_INIT_POINTER(mvm->link_id_to_link_conf[i], NULL);
mvm->tdls_cs.peer.sta_id = IWL_MVM_INVALID_STA;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/link.c b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
index a9929aa49913..2b0652168002 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/link.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
@@ -17,7 +17,8 @@
HOW(EXIT_COEX) \
HOW(EXIT_BANDWIDTH) \
HOW(EXIT_CSA) \
- HOW(EXIT_LINK_USAGE)
+ HOW(EXIT_LINK_USAGE) \
+ HOW(EXIT_FAIL_ENTRY)
static const char *const iwl_mvm_esr_states_names[] = {
#define NAME_ENTRY(x) [ilog2(IWL_MVM_ESR_##x)] = #x,
@@ -233,10 +234,15 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
WARN_ON_ONCE(active == link_info->active);
/* When deactivating a link session protection should
- * be stopped
+ * be stopped. Also let the firmware know if we can't Tx.
*/
- if (!active && vif->type == NL80211_IFTYPE_STATION)
+ if (!active && vif->type == NL80211_IFTYPE_STATION) {
iwl_mvm_stop_session_protection(mvm, vif);
+ if (link_info->csa_block_tx) {
+ cmd.block_tx = 1;
+ link_info->csa_block_tx = false;
+ }
+ }
}
cmd.link_id = cpu_to_le32(link_info->fw_link_id);
@@ -258,7 +264,7 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (vif->type == NL80211_IFTYPE_ADHOC && link_conf->bssid)
memcpy(cmd.ibss_bssid_addr, link_conf->bssid, ETH_ALEN);
- iwl_mvm_set_fw_basic_rates(mvm, vif, link_conf,
+ iwl_mvm_set_fw_basic_rates(mvm, vif, link_info,
&cmd.cck_rates, &cmd.ofdm_rates);
cmd.cck_short_preamble = cpu_to_le32(link_conf->use_short_preamble);
@@ -293,6 +299,17 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
(link_conf->uora_ocw_range >> 3) & 0x7;
}
+ /* ap_sta may be NULL if we're disconnecting */
+ if (changes & LINK_CONTEXT_MODIFY_HE_PARAMS && mvmvif->ap_sta) {
+ struct ieee80211_link_sta *link_sta =
+ link_sta_dereference_check(mvmvif->ap_sta, link_id);
+
+ if (!WARN_ON(!link_sta) && link_sta->he_cap.has_he &&
+ link_sta->he_cap.he_cap_elem.mac_cap_info[5] &
+ IEEE80211_HE_MAC_CAP5_OM_CTRL_UL_MU_DATA_DIS_RX)
+ cmd.ul_mu_data_disable = 1;
+ }
+
/* TODO how to set ndp_fdbk_buff_th_exp? */
if (iwl_mvm_set_fw_mu_edca_params(mvm, mvmvif->link[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 dfcc96f18b4f..a7a10e716e65 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -413,19 +413,18 @@ static void iwl_mvm_ack_rates(struct iwl_mvm *mvm,
}
void iwl_mvm_set_fw_basic_rates(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *link_conf,
+ struct iwl_mvm_vif_link_info *link_info,
__le32 *cck_rates, __le32 *ofdm_rates)
{
- struct ieee80211_chanctx_conf *chanctx;
+ struct iwl_mvm_phy_ctxt *phy_ctxt;
u8 cck_ack_rates = 0, ofdm_ack_rates = 0;
+ enum nl80211_band band = NL80211_BAND_2GHZ;
- rcu_read_lock();
- chanctx = rcu_dereference(link_conf->chanctx_conf);
- iwl_mvm_ack_rates(mvm, vif, chanctx ? chanctx->def.chan->band
- : NL80211_BAND_2GHZ,
- &cck_ack_rates, &ofdm_ack_rates);
+ phy_ctxt = link_info->phy_ctxt;
+ if (phy_ctxt && phy_ctxt->channel)
+ band = phy_ctxt->channel->band;
- rcu_read_unlock();
+ iwl_mvm_ack_rates(mvm, vif, band, &cck_ack_rates, &ofdm_ack_rates);
*cck_rates = cpu_to_le32((u32)cck_ack_rates);
*ofdm_rates = cpu_to_le32((u32)ofdm_ack_rates);
@@ -563,7 +562,7 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
else
eth_broadcast_addr(cmd->bssid_addr);
- iwl_mvm_set_fw_basic_rates(mvm, vif, &vif->bss_conf, &cmd->cck_rates,
+ iwl_mvm_set_fw_basic_rates(mvm, vif, &mvmvif->deflink, &cmd->cck_rates,
&cmd->ofdm_rates);
cmd->cck_short_preamble =
@@ -1528,7 +1527,7 @@ void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
mvm->ap_last_beacon_gp2 = le32_to_cpu(beacon->gp2);
if (!iwl_mvm_is_short_beacon_notif_supported(mvm)) {
- struct iwl_mvm_tx_resp *beacon_notify_hdr =
+ struct iwl_tx_resp *beacon_notify_hdr =
&beacon_v5->beacon_notify_hdr;
if (unlikely(pkt_len < sizeof(*beacon_v5)))
@@ -1586,11 +1585,11 @@ void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
}
}
-void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
- struct iwl_rx_cmd_buffer *rxb)
+static void
+iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm,
+ const struct iwl_missed_beacons_notif *mb,
+ struct iwl_rx_packet *pkt)
{
- struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_missed_beacons_notif *mb = (void *)pkt->data;
struct iwl_fw_dbg_trigger_missed_bcon *bcon_trig;
struct iwl_fw_dbg_trigger_tlv *trigger;
u32 stop_trig_missed_bcon, stop_trig_missed_bcon_since_rx;
@@ -1604,6 +1603,16 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
u8 notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
MISSED_BEACONS_NOTIFICATION,
0);
+ u8 new_notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, MAC_CONF_GROUP,
+ MISSED_BEACONS_NOTIF, 0);
+
+ /* If the firmware uses the new notification (from MAC_CONF_GROUP),
+ * refer to that notification's version.
+ * Note that the new notification from MAC_CONF_GROUP starts from
+ * version 5.
+ */
+ 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) {
@@ -1620,13 +1629,11 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
}
IWL_DEBUG_INFO(mvm,
- "missed bcn %s_id=%u, consecutive=%u (%u, %u, %u)\n",
+ "missed bcn %s_id=%u, consecutive=%u (%u)\n",
notif_ver < 4 ? "mac" : "link",
id,
le32_to_cpu(mb->consec_missed_beacons),
- le32_to_cpu(mb->consec_missed_beacons_since_last_rx),
- le32_to_cpu(mb->num_recvd_beacons),
- le32_to_cpu(mb->num_expected_beacons));
+ le32_to_cpu(mb->consec_missed_beacons_since_last_rx));
if (!vif)
return;
@@ -1656,10 +1663,27 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
"missed_beacons:%d, missed_beacons_since_rx:%d\n",
rx_missed_bcon, rx_missed_bcon_since_rx);
}
- } else if (rx_missed_bcon >= IWL_MVM_MISSED_BEACONS_EXIT_ESR_THRESH &&
- link_id >= 0 && hweight16(vif->active_links) > 1) {
- iwl_mvm_exit_esr(mvm, vif, IWL_MVM_ESR_EXIT_MISSED_BEACON,
- iwl_mvm_get_other_link(vif, link_id));
+ } else if (link_id >= 0 && hweight16(vif->active_links) > 1) {
+ u32 scnd_lnk_bcn_lost = 0;
+
+ if (notif_ver >= 5 &&
+ !IWL_FW_CHECK(mvm,
+ le32_to_cpu(mb->other_link_id) == IWL_MVM_FW_LINK_ID_INVALID,
+ "No data for other link id but we are in EMLSR active_links: 0x%x\n",
+ vif->active_links))
+ scnd_lnk_bcn_lost =
+ le32_to_cpu(mb->consec_missed_beacons_other_link);
+
+ /* Exit EMLSR if we lost more than
+ * IWL_MVM_MISSED_BEACONS_EXIT_ESR_THRESH beacons on boths links
+ * OR more than IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH on any link.
+ */
+ if ((rx_missed_bcon >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS &&
+ scnd_lnk_bcn_lost >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS) ||
+ rx_missed_bcon >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH)
+ iwl_mvm_exit_esr(mvm, vif,
+ IWL_MVM_ESR_EXIT_MISSED_BEACON,
+ iwl_mvm_get_primary_link(vif));
} else if (rx_missed_bcon_since_rx > IWL_MVM_MISSED_BEACONS_THRESHOLD) {
if (!iwl_mvm_has_new_tx_api(mvm))
ieee80211_beacon_loss(vif);
@@ -1687,6 +1711,31 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
iwl_fw_dbg_collect_trig(&mvm->fwrt, trigger, NULL);
}
+void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
+ struct iwl_rx_cmd_buffer *rxb)
+{
+ struct iwl_rx_packet *pkt = rxb_addr(rxb);
+
+ iwl_mvm_handle_missed_beacons_notif(mvm, (const void *)pkt->data, pkt);
+}
+
+void iwl_mvm_rx_missed_beacons_notif_legacy(struct iwl_mvm *mvm,
+ struct iwl_rx_cmd_buffer *rxb)
+{
+ struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ const struct iwl_missed_beacons_notif_v4 *mb_v4 =
+ (const void *)pkt->data;
+ struct iwl_missed_beacons_notif mb = {
+ .link_id = mb_v4->link_id,
+ .consec_missed_beacons = mb_v4->consec_missed_beacons,
+ .consec_missed_beacons_since_last_rx =
+ mb_v4->consec_missed_beacons_since_last_rx,
+ .other_link_id = cpu_to_le32(IWL_MVM_FW_LINK_ID_INVALID),
+ };
+
+ iwl_mvm_handle_missed_beacons_notif(mvm, &mb, pkt);
+}
+
void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb)
{
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 625ccf566e1c..6f5b16eb4902 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -165,12 +165,8 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy,
mvm->lar_regdom_set = true;
mvm->mcc_src = src_id;
- /* Some kind of regulatory mess means we need to currently disallow
- * puncturing in the US and Canada. Do that here, at least until we
- * figure out the new chanctx APIs for puncturing.
- */
- if (resp->mcc == cpu_to_le16(IWL_MCC_US) ||
- resp->mcc == cpu_to_le16(IWL_MCC_CANADA))
+ 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);
@@ -639,10 +635,15 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
NL80211_FEATURE_LOW_PRIORITY_SCAN |
NL80211_FEATURE_P2P_GO_OPPPS |
NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE |
- NL80211_FEATURE_DYNAMIC_SMPS |
- NL80211_FEATURE_STATIC_SMPS |
NL80211_FEATURE_SUPPORTS_WMM_ADMISSION;
+ /* when firmware supports RLC/SMPS offload, do not set these
+ * driver features, since it's no longer supported by driver.
+ */
+ if (!iwl_mvm_has_rlc_offload(mvm))
+ hw->wiphy->features |= NL80211_FEATURE_STATIC_SMPS |
+ NL80211_FEATURE_DYNAMIC_SMPS;
+
if (fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT))
hw->wiphy->features |= NL80211_FEATURE_TX_POWER_INSERTION;
@@ -838,20 +839,10 @@ void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
if (ieee80211_is_mgmt(hdr->frame_control))
sta = NULL;
- /* If there is no sta, and it's not offchannel - send through AP */
+ /* this shouldn't even happen: just drop */
if (!sta && info->control.vif->type == NL80211_IFTYPE_STATION &&
- !offchannel) {
- struct iwl_mvm_vif *mvmvif =
- iwl_mvm_vif_from_mac80211(info->control.vif);
- u8 ap_sta_id = READ_ONCE(mvmvif->deflink.ap_sta_id);
-
- if (ap_sta_id < mvm->fw->ucode_capa.num_stations) {
- /* mac80211 holds rcu read lock */
- sta = rcu_dereference(mvm->fw_id_to_mac_id[ap_sta_id]);
- if (IS_ERR_OR_NULL(sta))
- goto drop;
- }
- }
+ !offchannel)
+ goto drop;
if (tmp_sta && !sta && link_id != IEEE80211_LINK_UNSPECIFIED &&
!ieee80211_is_probe_resp(hdr->frame_control)) {
@@ -1480,19 +1471,33 @@ int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
{
u32 cmd_id = REDUCE_TX_POWER_CMD;
int len;
- struct iwl_dev_tx_power_cmd cmd = {
+ struct iwl_dev_tx_power_cmd_v3_v8 cmd = {
.common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_MAC),
.common.mac_context_id =
cpu_to_le32(iwl_mvm_vif_from_mac80211(vif)->id),
- .common.pwr_restriction = cpu_to_le16(8 * tx_power),
};
- u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id,
- IWL_FW_CMD_VER_UNKNOWN);
-
- if (tx_power == IWL_DEFAULT_MAX_TX_POWER)
- cmd.common.pwr_restriction = cpu_to_le16(IWL_DEV_MAX_TX_POWER);
-
- if (cmd_ver == 8)
+ struct iwl_dev_tx_power_cmd cmd_v9_v10;
+ u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 3);
+ u16 u_tx_power = tx_power == IWL_DEFAULT_MAX_TX_POWER ?
+ IWL_DEV_MAX_TX_POWER : 8 * tx_power;
+ void *cmd_data = &cmd;
+
+ cmd.common.pwr_restriction = cpu_to_le16(u_tx_power);
+
+ if (cmd_ver > 8) {
+ /* Those fields sit on the same place for v9 and v10 */
+ cmd_v9_v10.common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_MAC);
+ cmd_v9_v10.common.mac_context_id =
+ cpu_to_le32(iwl_mvm_vif_from_mac80211(vif)->id);
+ cmd_v9_v10.common.pwr_restriction = cpu_to_le16(u_tx_power);
+ cmd_data = &cmd_v9_v10;
+ }
+
+ if (cmd_ver == 10)
+ len = sizeof(cmd_v9_v10.v10);
+ else if (cmd_ver == 9)
+ len = sizeof(cmd_v9_v10.v9);
+ else if (cmd_ver == 8)
len = sizeof(cmd.v8);
else if (cmd_ver == 7)
len = sizeof(cmd.v7);
@@ -1507,10 +1512,14 @@ int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
else
len = sizeof(cmd.v3);
- /* all structs have the same common part, add it */
+ /* all structs have the same common part, add its length */
len += sizeof(cmd.common);
- return iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, len, &cmd);
+ if (cmd_ver < 9)
+ len += sizeof(cmd.per_band);
+
+ return iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, len, cmd_data);
+
}
static void iwl_mvm_post_csa_tx(void *data, struct ieee80211_sta *sta)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
index 8a38fc4b0b0f..455f5f417506 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
@@ -144,7 +144,7 @@ static void iwl_mvm_mld_update_sta_key(struct ieee80211_hw *hw,
if (sta != data->sta || key->link_id >= 0)
return;
- err = iwl_mvm_send_cmd_pdu(mvm, cmd_id, CMD_ASYNC, sizeof(cmd), &cmd);
+ err = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd);
if (err)
data->err = err;
@@ -162,8 +162,8 @@ int iwl_mvm_mld_update_sta_keys(struct iwl_mvm *mvm,
.new_sta_mask = new_sta_mask,
};
- ieee80211_iter_keys_rcu(mvm->hw, vif, iwl_mvm_mld_update_sta_key,
- &data);
+ ieee80211_iter_keys(mvm->hw, vif, iwl_mvm_mld_update_sta_key,
+ &data);
return data.err;
}
@@ -402,7 +402,7 @@ void iwl_mvm_sec_key_remove_ap(struct iwl_mvm *mvm,
if (!sec_key_ver)
return;
- ieee80211_iter_keys_rcu(mvm->hw, vif,
- iwl_mvm_sec_key_remove_ap_iter,
- (void *)(uintptr_t)link_id);
+ ieee80211_iter_keys(mvm->hw, vif,
+ iwl_mvm_sec_key_remove_ap_iter,
+ (void *)(uintptr_t)link_id);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index 3c99396ad369..f2378e0fb2fb 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -223,7 +223,7 @@ static void iwl_mvm_restart_mpdu_count(struct iwl_mvm *mvm,
spin_unlock_bh(&mvmsta->mpdu_counters[q].lock);
}
- IWL_DEBUG_STATS(mvm, "MPDU counters are cleared\n");
+ IWL_DEBUG_INFO(mvm, "MPDU counters are cleared\n");
}
static int iwl_mvm_esr_mode_active(struct iwl_mvm *mvm,
@@ -269,6 +269,9 @@ static int iwl_mvm_esr_mode_active(struct iwl_mvm *mvm,
*/
iwl_mvm_restart_mpdu_count(mvm, mvmvif);
+ iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_ESR_LINK_UP,
+ NULL);
+
return ret;
}
@@ -456,6 +459,9 @@ static int iwl_mvm_esr_mode_inactive(struct iwl_mvm *mvm,
/* Start a new counting window */
iwl_mvm_restart_mpdu_count(mvm, mvmvif);
+ iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_ESR_LINK_DOWN,
+ NULL);
+
return ret;
}
@@ -1335,6 +1341,22 @@ iwl_mvm_mld_mac_pre_channel_switch(struct ieee80211_hw *hw,
else
selected = primary;
+ /*
+ * remembers to tell the firmware that this link can't tx
+ * Note that this logic seems to be unrelated to esr, but it
+ * really is needed only when esr is active. When we have a
+ * single link, the firmware will handle all this on its own.
+ * In multi-link scenarios, we can learn about the CSA from
+ * another link and this logic is too complex for the firmware
+ * to track.
+ * Since we want to de-activate the link that got a CSA, we
+ * need to tell the firmware not to send any frame on that link
+ * as the firmware may not be aware that link is under a CSA
+ * with mode=1 (no Tx allowed).
+ */
+ if (chsw->block_tx && mvmvif->link[chsw->link_id])
+ mvmvif->link[chsw->link_id]->csa_block_tx = true;
+
iwl_mvm_exit_esr(mvm, vif, IWL_MVM_ESR_EXIT_CSA, selected);
mutex_unlock(&mvm->mutex);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
index d5a204e52076..28a9d90ad1cd 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
@@ -46,7 +46,7 @@ u32 iwl_mvm_sta_fw_id_mask(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
}
static int iwl_mvm_mld_send_sta_cmd(struct iwl_mvm *mvm,
- struct iwl_mvm_sta_cfg_cmd *cmd)
+ struct iwl_sta_cfg_cmd *cmd)
{
int ret = iwl_mvm_send_cmd_pdu(mvm,
WIDE_ID(MAC_CONF_GROUP, STA_CONFIG_CMD),
@@ -63,7 +63,7 @@ static int iwl_mvm_mld_add_int_sta_to_fw(struct iwl_mvm *mvm,
struct iwl_mvm_int_sta *sta,
const u8 *addr, int link_id)
{
- struct iwl_mvm_sta_cfg_cmd cmd;
+ struct iwl_sta_cfg_cmd cmd;
lockdep_assert_held(&mvm->mutex);
@@ -94,7 +94,7 @@ static int iwl_mvm_mld_add_int_sta_to_fw(struct iwl_mvm *mvm,
*/
static int iwl_mvm_mld_rm_sta_from_fw(struct iwl_mvm *mvm, u32 sta_id)
{
- struct iwl_mvm_remove_sta_cmd rm_sta_cmd = {
+ struct iwl_remove_sta_cmd rm_sta_cmd = {
.sta_id = cpu_to_le32(sta_id),
};
int ret;
@@ -216,7 +216,7 @@ int iwl_mvm_mld_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
static const u8 _baddr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
const u8 *baddr = _baddr;
unsigned int wdg_timeout =
- iwl_mvm_get_wd_timeout(mvm, vif, false, false);
+ iwl_mvm_get_wd_timeout(mvm, vif);
u16 *queue;
lockdep_assert_held(&mvm->mutex);