diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/coex.c')
| -rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/coex.c | 163 |
1 files changed, 96 insertions, 67 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c index 9b194cb8d65e..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 Intel Corporation + * Copyright (C) 2013-2014, 2018-2020, 2022-2025 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH */ #include <linux/ieee80211.h> @@ -106,7 +106,7 @@ iwl_get_coex_type(struct iwl_mvm *mvm, const struct ieee80211_vif *vif) rcu_read_lock(); - chanctx_conf = rcu_dereference(vif->chanctx_conf); + chanctx_conf = rcu_dereference(vif->bss_conf.chanctx_conf); if (!chanctx_conf || chanctx_conf->def.chan->band != NL80211_BAND_2GHZ) { @@ -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->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; } @@ -311,20 +310,21 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, smps_mode = IEEE80211_SMPS_DYNAMIC; /* relax SMPS constraints for next association */ - if (!vif->bss_conf.assoc) + 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->bss_conf.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; } |
