summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/coex.c')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/coex.c159
1 files changed, 94 insertions, 65 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
index ee3c8a786199..ca63f780140f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2013-2014, 2018-2020, 2022 Intel Corporation
+ * Copyright (C) 2013-2014, 2018-2020, 2022-2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
*/
#include <linux/ieee80211.h>
@@ -116,11 +116,6 @@ iwl_get_coex_type(struct iwl_mvm *mvm, const struct ieee80211_vif *vif)
ret = BT_COEX_TX_DIS_LUT;
- if (mvm->cfg->bt_shared_single_ant) {
- rcu_read_unlock();
- return ret;
- }
-
phy_ctx_id = *((u16 *)chanctx_conf->drv_priv);
primary_ch_phy_id = le32_to_cpu(mvm->last_bt_ci_cmd.primary_ch_phy_id);
secondary_ch_phy_id =
@@ -186,6 +181,9 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
struct iwl_mvm_sta *mvmsta;
u32 value;
+ if (mvm->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
+ return 0;
+
mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
if (!mvmsta)
return 0;
@@ -194,7 +192,7 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
if (mvmsta->bt_reduced_txpower == enable)
return 0;
- value = mvmsta->sta_id;
+ value = mvmsta->deflink.sta_id;
if (enable)
value |= BT_REDUCED_TX_POWER_BIT;
@@ -210,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;
@@ -221,15 +219,13 @@ struct iwl_bt_iterator_data {
static inline
void iwl_mvm_bt_coex_enable_rssi_event(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
+ struct iwl_mvm_vif_link_info *link_info,
bool enable, int rssi)
{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-
- mvmvif->bf_data.last_bt_coex_event = rssi;
- mvmvif->bf_data.bt_coex_max_thold =
+ link_info->bf_data.last_bt_coex_event = rssi;
+ link_info->bf_data.bt_coex_max_thold =
enable ? -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH : 0;
- mvmvif->bf_data.bt_coex_min_thold =
+ link_info->bf_data.bt_coex_min_thold =
enable ? -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH : 0;
}
@@ -257,33 +253,35 @@ static void iwl_mvm_bt_coex_tcm_based_ci(struct iwl_mvm *mvm,
swap(data->primary, data->secondary);
}
-/* must be called under rcu_read_lock */
-static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
- struct ieee80211_vif *vif)
+static void iwl_mvm_bt_notif_per_link(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct iwl_bt_iterator_data *data,
+ unsigned int link_id)
{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_bt_iterator_data *data = _data;
- struct iwl_mvm *mvm = data->mvm;
- struct ieee80211_chanctx_conf *chanctx_conf;
/* default smps_mode is AUTOMATIC - only used for client modes */
enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_AUTOMATIC;
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
u32 bt_activity_grading, min_ag_for_static_smps;
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ struct iwl_mvm_vif_link_info *link_info;
+ struct ieee80211_bss_conf *link_conf;
int ave_rssi;
lockdep_assert_held(&mvm->mutex);
- switch (vif->type) {
- case NL80211_IFTYPE_STATION:
- break;
- case NL80211_IFTYPE_AP:
- if (!mvmvif->ap_ibss_active)
- return;
- break;
- default:
+ link_info = mvmvif->link[link_id];
+ if (!link_info)
return;
- }
- chanctx_conf = rcu_dereference(vif->bss_conf.chanctx_conf);
+ link_conf = rcu_dereference(vif->link_conf[link_id]);
+ /* This can happen due to races: if we receive the notification
+ * and have the mutex held, while mac80211 is stuck on our mutex
+ * in the middle of removing the link.
+ */
+ if (!link_conf)
+ return;
+
+ chanctx_conf = rcu_dereference(link_conf->chanctx_conf);
/* If channel context is invalid or not on 2.4GHz .. */
if ((!chanctx_conf ||
@@ -291,10 +289,11 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
if (vif->type == NL80211_IFTYPE_STATION) {
/* ... relax constraints and disable rssi events */
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
- smps_mode);
- iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
+ smps_mode, link_id);
+ iwl_mvm_bt_coex_reduced_txp(mvm, link_info->ap_sta_id,
false);
- iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
+ iwl_mvm_bt_coex_enable_rssi_event(mvm, link_info, false,
+ 0);
}
return;
}
@@ -314,17 +313,18 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
if (!vif->cfg.assoc)
smps_mode = IEEE80211_SMPS_AUTOMATIC;
- if (mvmvif->phy_ctxt &&
- (mvm->last_bt_notif.rrc_status & BIT(mvmvif->phy_ctxt->id)))
+ if (link_info->phy_ctxt &&
+ (mvm->last_bt_notif.rrc_status & BIT(link_info->phy_ctxt->id)))
smps_mode = IEEE80211_SMPS_AUTOMATIC;
IWL_DEBUG_COEX(data->mvm,
- "mac %d: bt_activity_grading %d smps_req %d\n",
- mvmvif->id, bt_activity_grading, smps_mode);
+ "mac %d link %d: bt_activity_grading %d smps_req %d\n",
+ mvmvif->id, link_info->fw_link_id,
+ bt_activity_grading, smps_mode);
if (vif->type == NL80211_IFTYPE_STATION)
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
- smps_mode);
+ smps_mode, link_id);
/* low latency is always primary */
if (iwl_mvm_vif_low_latency(mvmvif)) {
@@ -353,6 +353,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
data->secondary = chanctx_conf;
}
+ /* FIXME: TCM load per interface? or need something per link? */
if (data->primary == chanctx_conf)
data->primary_load = mvm->tcm.result.load[mvmvif->id];
else if (data->secondary == chanctx_conf)
@@ -370,6 +371,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
/* if secondary is not NULL, it might be a GO */
data->secondary = chanctx_conf;
+ /* FIXME: TCM load per interface? or need something per link? */
if (data->primary == chanctx_conf)
data->primary_load = mvm->tcm.result.load[mvmvif->id];
else if (data->secondary == chanctx_conf)
@@ -377,34 +379,61 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
/*
* don't reduce the Tx power if one of these is true:
* we are in LOOSE
- * single share antenna product
* BT is inactive
* we are not associated
*/
if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT ||
- mvm->cfg->bt_shared_single_ant || !vif->cfg.assoc ||
- le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF) {
- iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false);
- iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
+ le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF ||
+ !vif->cfg.assoc) {
+ iwl_mvm_bt_coex_reduced_txp(mvm, link_info->ap_sta_id, false);
+ iwl_mvm_bt_coex_enable_rssi_event(mvm, link_info, false, 0);
return;
}
/* try to get the avg rssi from fw */
- ave_rssi = mvmvif->bf_data.ave_beacon_signal;
+ ave_rssi = link_info->bf_data.ave_beacon_signal;
/* if the RSSI isn't valid, fake it is very low */
if (!ave_rssi)
ave_rssi = -100;
if (ave_rssi > -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH) {
- if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true))
+ if (iwl_mvm_bt_coex_reduced_txp(mvm, link_info->ap_sta_id,
+ true))
IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
} else if (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) {
- if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false))
+ if (iwl_mvm_bt_coex_reduced_txp(mvm, link_info->ap_sta_id,
+ false))
IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
}
/* Begin to monitor the RSSI: it may influence the reduced Tx power */
- iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, true, ave_rssi);
+ iwl_mvm_bt_coex_enable_rssi_event(mvm, link_info, true, ave_rssi);
+}
+
+/* must be called under rcu_read_lock */
+static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_bt_iterator_data *data = _data;
+ struct iwl_mvm *mvm = data->mvm;
+ unsigned int link_id;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ switch (vif->type) {
+ case NL80211_IFTYPE_STATION:
+ break;
+ case NL80211_IFTYPE_AP:
+ if (!mvmvif->ap_ibss_active)
+ return;
+ break;
+ default:
+ return;
+ }
+
+ for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++)
+ iwl_mvm_bt_notif_per_link(mvm, vif, data, link_id);
}
static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
@@ -425,6 +454,11 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_bt_notif_iterator, &data);
+ if (mvm->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
+ rcu_read_unlock();
+ return;
+ }
+
iwl_mvm_bt_coex_tcm_based_ci(mvm, &data);
if (data.primary) {
@@ -484,11 +518,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);
@@ -521,7 +555,7 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
* Rssi update while not associated - can happen since the statistics
* are handled asynchronously
*/
- if (mvmvif->ap_sta_id == IWL_MVM_INVALID_STA)
+ if (mvmvif->deflink.ap_sta_id == IWL_INVALID_STA)
return;
/* No BT - reports should be disabled */
@@ -535,12 +569,15 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
* Check if rssi is good enough for reduced Tx power, but not in loose
* scheme.
*/
- if (rssi_event == RSSI_EVENT_LOW || mvm->cfg->bt_shared_single_ant ||
+ if (rssi_event == RSSI_EVENT_LOW ||
iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT)
- ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
+ ret = iwl_mvm_bt_coex_reduced_txp(mvm,
+ mvmvif->deflink.ap_sta_id,
false);
else
- ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true);
+ ret = iwl_mvm_bt_coex_reduced_txp(mvm,
+ mvmvif->deflink.ap_sta_id,
+ true);
if (ret)
IWL_ERR(mvm, "couldn't send BT_CONFIG HCMD upon RSSI event\n");
@@ -554,7 +591,7 @@ u16 iwl_mvm_coex_agg_time_limit(struct iwl_mvm *mvm,
{
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
- struct iwl_mvm_phy_ctxt *phy_ctxt = mvmvif->phy_ctxt;
+ struct iwl_mvm_phy_ctxt *phy_ctxt = mvmvif->deflink.phy_ctxt;
enum iwl_bt_coex_lut_type lut_type;
if (mvm->last_bt_notif.ttc_status & BIT(phy_ctxt->id))
@@ -578,7 +615,7 @@ bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm,
{
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
- struct iwl_mvm_phy_ctxt *phy_ctxt = mvmvif->phy_ctxt;
+ struct iwl_mvm_phy_ctxt *phy_ctxt = mvmvif->deflink.phy_ctxt;
enum iwl_bt_coex_lut_type lut_type;
if (mvm->last_bt_notif.ttc_status & BIT(phy_ctxt->id))
@@ -601,10 +638,6 @@ bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm,
bool iwl_mvm_bt_coex_is_ant_avail(struct iwl_mvm *mvm, u8 ant)
{
- /* there is no other antenna, shared antenna is always available */
- if (mvm->cfg->bt_shared_single_ant)
- return true;
-
if (ant & mvm->cfg->non_shared_ant)
return true;
@@ -614,10 +647,6 @@ bool iwl_mvm_bt_coex_is_ant_avail(struct iwl_mvm *mvm, u8 ant)
bool iwl_mvm_bt_coex_is_shared_ant_avail(struct iwl_mvm *mvm)
{
- /* there is no other antenna, shared antenna is always available */
- if (mvm->cfg->bt_shared_single_ant)
- return true;
-
return le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) < BT_HIGH_TRAFFIC;
}