2020-12-10 00:06:03 +02:00
|
|
|
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
|
|
|
/*
|
2024-04-16 13:53:56 +03:00
|
|
|
* Copyright (C) 2013-2014, 2018-2020, 2022-2024 Intel Corporation
|
2020-12-10 00:06:03 +02:00
|
|
|
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
|
|
|
*/
|
2014-03-06 10:30:49 +02:00
|
|
|
#include <linux/ieee80211.h>
|
|
|
|
#include <linux/etherdevice.h>
|
2013-01-24 10:35:13 +02:00
|
|
|
#include <net/mac80211.h>
|
|
|
|
|
2017-06-02 15:15:53 +02:00
|
|
|
#include "fw/api/coex.h"
|
2013-01-17 09:42:25 +02:00
|
|
|
#include "iwl-modparams.h"
|
|
|
|
#include "mvm.h"
|
2013-01-17 14:20:29 +02:00
|
|
|
#include "iwl-debug.h"
|
2013-01-17 09:42:25 +02:00
|
|
|
|
2013-06-18 07:35:27 +03:00
|
|
|
/* 20MHz / 40MHz below / 40Mhz above*/
|
|
|
|
static const __le64 iwl_ci_mask[][3] = {
|
|
|
|
/* dummy entry for channel 0 */
|
|
|
|
{cpu_to_le64(0), cpu_to_le64(0), cpu_to_le64(0)},
|
|
|
|
{
|
|
|
|
cpu_to_le64(0x0000001FFFULL),
|
|
|
|
cpu_to_le64(0x0ULL),
|
|
|
|
cpu_to_le64(0x00007FFFFFULL),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
cpu_to_le64(0x000000FFFFULL),
|
|
|
|
cpu_to_le64(0x0ULL),
|
|
|
|
cpu_to_le64(0x0003FFFFFFULL),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
cpu_to_le64(0x000003FFFCULL),
|
|
|
|
cpu_to_le64(0x0ULL),
|
|
|
|
cpu_to_le64(0x000FFFFFFCULL),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
cpu_to_le64(0x00001FFFE0ULL),
|
|
|
|
cpu_to_le64(0x0ULL),
|
|
|
|
cpu_to_le64(0x007FFFFFE0ULL),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
cpu_to_le64(0x00007FFF80ULL),
|
|
|
|
cpu_to_le64(0x00007FFFFFULL),
|
|
|
|
cpu_to_le64(0x01FFFFFF80ULL),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
cpu_to_le64(0x0003FFFC00ULL),
|
|
|
|
cpu_to_le64(0x0003FFFFFFULL),
|
|
|
|
cpu_to_le64(0x0FFFFFFC00ULL),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
cpu_to_le64(0x000FFFF000ULL),
|
|
|
|
cpu_to_le64(0x000FFFFFFCULL),
|
|
|
|
cpu_to_le64(0x3FFFFFF000ULL),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
cpu_to_le64(0x007FFF8000ULL),
|
|
|
|
cpu_to_le64(0x007FFFFFE0ULL),
|
|
|
|
cpu_to_le64(0xFFFFFF8000ULL),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
cpu_to_le64(0x01FFFE0000ULL),
|
|
|
|
cpu_to_le64(0x01FFFFFF80ULL),
|
|
|
|
cpu_to_le64(0xFFFFFE0000ULL),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
cpu_to_le64(0x0FFFF00000ULL),
|
|
|
|
cpu_to_le64(0x0FFFFFFC00ULL),
|
|
|
|
cpu_to_le64(0x0ULL),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
cpu_to_le64(0x3FFFC00000ULL),
|
|
|
|
cpu_to_le64(0x3FFFFFF000ULL),
|
|
|
|
cpu_to_le64(0x0)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
cpu_to_le64(0xFFFE000000ULL),
|
|
|
|
cpu_to_le64(0xFFFFFF8000ULL),
|
|
|
|
cpu_to_le64(0x0)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
cpu_to_le64(0xFFF8000000ULL),
|
|
|
|
cpu_to_le64(0xFFFFFE0000ULL),
|
|
|
|
cpu_to_le64(0x0)
|
|
|
|
},
|
|
|
|
{
|
2016-06-22 10:51:31 +03:00
|
|
|
cpu_to_le64(0xFE00000000ULL),
|
2013-06-18 07:35:27 +03:00
|
|
|
cpu_to_le64(0x0ULL),
|
2013-12-24 10:55:24 +02:00
|
|
|
cpu_to_le64(0x0ULL)
|
2013-06-18 07:35:27 +03:00
|
|
|
},
|
2013-01-17 09:42:25 +02:00
|
|
|
};
|
|
|
|
|
2013-06-30 07:51:54 +03:00
|
|
|
static enum iwl_bt_coex_lut_type
|
|
|
|
iwl_get_coex_type(struct iwl_mvm *mvm, const struct ieee80211_vif *vif)
|
|
|
|
{
|
|
|
|
struct ieee80211_chanctx_conf *chanctx_conf;
|
|
|
|
enum iwl_bt_coex_lut_type ret;
|
|
|
|
u16 phy_ctx_id;
|
2014-04-02 09:55:16 +03:00
|
|
|
u32 primary_ch_phy_id, secondary_ch_phy_id;
|
2013-06-30 07:51:54 +03:00
|
|
|
|
2013-07-18 08:45:41 +03:00
|
|
|
/*
|
|
|
|
* Checking that we hold mvm->mutex is a good idea, but the rate
|
|
|
|
* control can't acquire the mutex since it runs in Tx path.
|
|
|
|
* So this is racy in that case, but in the worst case, the AMPDU
|
|
|
|
* size limit will be wrong for a short time which is not a big
|
|
|
|
* issue.
|
|
|
|
*/
|
2013-06-30 07:51:54 +03:00
|
|
|
|
|
|
|
rcu_read_lock();
|
|
|
|
|
wifi: mac80211: move some future per-link data to bss_conf
To add MLD, reuse the bss_conf structure later for per-link
information, so move some things into it that are per link.
Most transformations were done with the following spatch:
@@
expression sdata;
identifier var = { chanctx_conf, mu_mimo_owner, csa_active, color_change_active, color_change_color };
@@
-sdata->vif.var
+sdata->vif.bss_conf.var
@@
struct ieee80211_vif *vif;
identifier var = { chanctx_conf, mu_mimo_owner, csa_active, color_change_active, color_change_color };
@@
-vif->var
+vif->bss_conf.var
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2022-05-10 13:26:44 +02:00
|
|
|
chanctx_conf = rcu_dereference(vif->bss_conf.chanctx_conf);
|
2013-06-30 07:51:54 +03:00
|
|
|
|
|
|
|
if (!chanctx_conf ||
|
2016-04-12 15:56:15 +02:00
|
|
|
chanctx_conf->def.chan->band != NL80211_BAND_2GHZ) {
|
2013-06-30 07:51:54 +03:00
|
|
|
rcu_read_unlock();
|
2014-05-25 13:58:31 +03:00
|
|
|
return BT_COEX_INVALID_LUT;
|
2013-06-30 07:51:54 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
ret = BT_COEX_TX_DIS_LUT;
|
|
|
|
|
|
|
|
phy_ctx_id = *((u16 *)chanctx_conf->drv_priv);
|
2014-04-02 09:55:16 +03:00
|
|
|
primary_ch_phy_id = le32_to_cpu(mvm->last_bt_ci_cmd.primary_ch_phy_id);
|
|
|
|
secondary_ch_phy_id =
|
|
|
|
le32_to_cpu(mvm->last_bt_ci_cmd.secondary_ch_phy_id);
|
2013-06-30 07:51:54 +03:00
|
|
|
|
2014-04-02 09:55:16 +03:00
|
|
|
if (primary_ch_phy_id == phy_ctx_id)
|
2013-06-30 07:51:54 +03:00
|
|
|
ret = le32_to_cpu(mvm->last_bt_notif.primary_ch_lut);
|
2014-04-02 09:55:16 +03:00
|
|
|
else if (secondary_ch_phy_id == phy_ctx_id)
|
2013-06-30 07:51:54 +03:00
|
|
|
ret = le32_to_cpu(mvm->last_bt_notif.secondary_ch_lut);
|
|
|
|
/* else - default = TX TX disallowed */
|
|
|
|
|
|
|
|
rcu_read_unlock();
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-05-29 14:01:06 +03:00
|
|
|
int iwl_mvm_send_bt_init_conf(struct iwl_mvm *mvm)
|
2013-01-17 09:42:25 +02:00
|
|
|
{
|
2015-05-11 09:05:25 +03:00
|
|
|
struct iwl_bt_coex_cmd bt_cmd = {};
|
2014-04-02 09:55:16 +03:00
|
|
|
u32 mode;
|
2013-06-18 07:35:27 +03:00
|
|
|
|
2014-05-28 12:06:41 +03:00
|
|
|
lockdep_assert_held(&mvm->mutex);
|
|
|
|
|
|
|
|
if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS)) {
|
|
|
|
switch (mvm->bt_force_ant_mode) {
|
|
|
|
case BT_FORCE_ANT_BT:
|
2014-04-02 09:55:16 +03:00
|
|
|
mode = BT_COEX_BT;
|
2014-05-28 12:06:41 +03:00
|
|
|
break;
|
|
|
|
case BT_FORCE_ANT_WIFI:
|
2014-04-02 09:55:16 +03:00
|
|
|
mode = BT_COEX_WIFI;
|
2014-05-28 12:06:41 +03:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
WARN_ON(1);
|
2014-04-02 09:55:16 +03:00
|
|
|
mode = 0;
|
2014-05-28 12:06:41 +03:00
|
|
|
}
|
|
|
|
|
2015-05-11 09:05:25 +03:00
|
|
|
bt_cmd.mode = cpu_to_le32(mode);
|
2014-05-28 12:06:41 +03:00
|
|
|
goto send_cmd;
|
|
|
|
}
|
|
|
|
|
2020-04-24 18:48:13 +03:00
|
|
|
bt_cmd.mode = cpu_to_le32(BT_COEX_NW);
|
2013-06-18 07:35:27 +03:00
|
|
|
|
2014-01-27 12:12:50 +02:00
|
|
|
if (IWL_MVM_BT_COEX_SYNC2SCO)
|
2015-05-11 09:05:25 +03:00
|
|
|
bt_cmd.enabled_modules |=
|
2014-04-02 09:55:16 +03:00
|
|
|
cpu_to_le32(BT_COEX_SYNC2SCO_ENABLED);
|
2014-01-27 12:12:50 +02:00
|
|
|
|
2015-10-29 16:50:57 +02:00
|
|
|
if (iwl_mvm_is_mplut_supported(mvm))
|
2015-05-11 09:05:25 +03:00
|
|
|
bt_cmd.enabled_modules |= cpu_to_le32(BT_COEX_MPLUT_ENABLED);
|
2014-03-16 21:55:43 +02:00
|
|
|
|
2015-05-11 09:05:25 +03:00
|
|
|
bt_cmd.enabled_modules |= cpu_to_le32(BT_COEX_HIGH_BAND_RET);
|
2014-06-11 15:37:25 +03:00
|
|
|
|
2014-05-28 12:06:41 +03:00
|
|
|
send_cmd:
|
2013-01-24 10:35:13 +02:00
|
|
|
memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
|
2013-06-18 07:35:27 +03:00
|
|
|
memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd));
|
2013-01-24 10:35:13 +02:00
|
|
|
|
2015-05-11 09:05:25 +03:00
|
|
|
return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, 0, sizeof(bt_cmd), &bt_cmd);
|
2013-01-17 09:42:25 +02:00
|
|
|
}
|
2013-01-17 14:20:29 +02:00
|
|
|
|
2014-05-20 13:54:27 +03:00
|
|
|
static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
|
|
|
|
bool enable)
|
2013-01-24 10:35:13 +02:00
|
|
|
{
|
2014-05-22 12:48:27 +03:00
|
|
|
struct iwl_bt_coex_reduced_txp_update_cmd cmd = {};
|
2013-01-24 10:35:13 +02:00
|
|
|
struct iwl_mvm_sta *mvmsta;
|
2014-05-22 12:48:27 +03:00
|
|
|
u32 value;
|
2013-01-24 10:35:13 +02:00
|
|
|
|
2024-02-05 00:06:12 +02:00
|
|
|
if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
|
|
|
|
return 0;
|
|
|
|
|
2014-01-14 08:30:32 +02:00
|
|
|
mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
|
|
|
|
if (!mvmsta)
|
2013-01-24 10:35:13 +02:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* nothing to do */
|
2014-05-20 13:54:27 +03:00
|
|
|
if (mvmsta->bt_reduced_txpower == enable)
|
2013-01-24 10:35:13 +02:00
|
|
|
return 0;
|
|
|
|
|
2023-03-28 10:58:42 +03:00
|
|
|
value = mvmsta->deflink.sta_id;
|
2013-06-26 15:54:34 +03:00
|
|
|
|
2013-01-24 10:35:13 +02:00
|
|
|
if (enable)
|
2014-05-22 12:48:27 +03:00
|
|
|
value |= BT_REDUCED_TX_POWER_BIT;
|
2013-01-24 10:35:13 +02:00
|
|
|
|
|
|
|
IWL_DEBUG_COEX(mvm, "%sable reduced Tx Power for sta %d\n",
|
|
|
|
enable ? "en" : "dis", sta_id);
|
|
|
|
|
2014-05-22 12:48:27 +03:00
|
|
|
cmd.reduced_txp = cpu_to_le32(value);
|
2013-01-24 10:35:13 +02:00
|
|
|
mvmsta->bt_reduced_txpower = enable;
|
|
|
|
|
2018-11-16 11:18:26 +02:00
|
|
|
return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_UPDATE_REDUCED_TXP,
|
|
|
|
CMD_ASYNC, sizeof(cmd), &cmd);
|
2013-01-24 10:35:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
struct iwl_bt_iterator_data {
|
2014-04-02 09:55:16 +03:00
|
|
|
struct iwl_bt_coex_profile_notif *notif;
|
2013-01-24 10:35:13 +02:00
|
|
|
struct iwl_mvm *mvm;
|
2013-06-18 07:35:27 +03:00
|
|
|
struct ieee80211_chanctx_conf *primary;
|
|
|
|
struct ieee80211_chanctx_conf *secondary;
|
2014-01-15 16:57:54 +02:00
|
|
|
bool primary_ll;
|
2014-12-09 17:08:41 +02:00
|
|
|
u8 primary_load;
|
|
|
|
u8 secondary_load;
|
2013-02-10 17:06:17 +02:00
|
|
|
};
|
|
|
|
|
2013-09-08 08:57:15 +03:00
|
|
|
static inline
|
|
|
|
void iwl_mvm_bt_coex_enable_rssi_event(struct iwl_mvm *mvm,
|
2024-03-11 08:28:04 +02:00
|
|
|
struct iwl_mvm_vif_link_info *link_info,
|
2013-09-08 08:57:15 +03:00
|
|
|
bool enable, int rssi)
|
|
|
|
{
|
2024-03-11 08:28:04 +02:00
|
|
|
link_info->bf_data.last_bt_coex_event = rssi;
|
|
|
|
link_info->bf_data.bt_coex_max_thold =
|
2014-05-27 22:54:18 +03:00
|
|
|
enable ? -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH : 0;
|
2024-03-11 08:28:04 +02:00
|
|
|
link_info->bf_data.bt_coex_min_thold =
|
2014-05-27 22:54:18 +03:00
|
|
|
enable ? -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH : 0;
|
2013-09-08 08:57:15 +03:00
|
|
|
}
|
|
|
|
|
2014-12-09 17:08:41 +02:00
|
|
|
#define MVM_COEX_TCM_PERIOD (HZ * 10)
|
|
|
|
|
|
|
|
static void iwl_mvm_bt_coex_tcm_based_ci(struct iwl_mvm *mvm,
|
|
|
|
struct iwl_bt_iterator_data *data)
|
|
|
|
{
|
|
|
|
unsigned long now = jiffies;
|
|
|
|
|
|
|
|
if (!time_after(now, mvm->bt_coex_last_tcm_ts + MVM_COEX_TCM_PERIOD))
|
|
|
|
return;
|
|
|
|
|
|
|
|
mvm->bt_coex_last_tcm_ts = now;
|
|
|
|
|
|
|
|
/* We assume here that we don't have more than 2 vifs on 2.4GHz */
|
|
|
|
|
|
|
|
/* if the primary is low latency, it will stay primary */
|
|
|
|
if (data->primary_ll)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (data->primary_load >= data->secondary_load)
|
|
|
|
return;
|
|
|
|
|
|
|
|
swap(data->primary, data->secondary);
|
|
|
|
}
|
|
|
|
|
2024-01-31 22:56:32 +02:00
|
|
|
/*
|
|
|
|
* This function receives the LB link id and checks if eSR should be
|
|
|
|
* enabled or disabled (due to BT coex)
|
|
|
|
*/
|
2024-05-05 09:19:45 +03:00
|
|
|
bool
|
2024-01-31 22:56:32 +02:00
|
|
|
iwl_mvm_bt_coex_calculate_esr_mode(struct iwl_mvm *mvm,
|
|
|
|
struct ieee80211_vif *vif,
|
2024-05-05 09:19:45 +03:00
|
|
|
s32 link_rssi,
|
|
|
|
bool primary)
|
2024-01-31 22:56:32 +02:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
u8 wifi_loss_rate;
|
|
|
|
|
|
|
|
if (mvm->last_bt_notif.wifi_loss_low_rssi == BT_OFF)
|
|
|
|
return true;
|
|
|
|
|
2024-05-05 09:19:45 +03:00
|
|
|
if (primary)
|
2024-01-31 22:56:32 +02:00
|
|
|
return false;
|
|
|
|
|
|
|
|
/* The feature is not supported */
|
|
|
|
if (!have_wifi_loss_rate)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* In case we don't know the RSSI - take the lower wifi loss,
|
|
|
|
* so we will more likely enter eSR, and if RSSI is low -
|
|
|
|
* 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;
|
|
|
|
|
2024-05-05 09:19:45 +03:00
|
|
|
else if (mvmvif->esr_active)
|
2024-01-31 22:56:32 +02:00
|
|
|
/* 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;
|
|
|
|
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;
|
|
|
|
|
|
|
|
return wifi_loss_rate <= IWL_MVM_BT_COEX_WIFI_LOSS_THRESH;
|
|
|
|
}
|
|
|
|
|
2024-04-16 13:53:59 +03:00
|
|
|
void iwl_mvm_bt_coex_update_link_esr(struct iwl_mvm *mvm,
|
|
|
|
struct ieee80211_vif *vif,
|
|
|
|
int link_id)
|
2024-01-31 22:56:32 +02:00
|
|
|
{
|
2024-05-05 09:19:45 +03:00
|
|
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
|
|
|
struct iwl_mvm_vif_link_info *link = mvmvif->link[link_id];
|
2024-01-31 22:56:32 +02:00
|
|
|
|
2024-04-16 13:54:03 +03:00
|
|
|
if (!ieee80211_vif_is_mld(vif) ||
|
2024-05-05 09:19:45 +03:00
|
|
|
!iwl_mvm_vif_from_mac80211(vif)->authorized ||
|
|
|
|
WARN_ON(!link))
|
2024-01-31 22:56:32 +02:00
|
|
|
return;
|
|
|
|
|
2024-05-05 09:19:45 +03:00
|
|
|
if (!iwl_mvm_bt_coex_calculate_esr_mode(mvm, vif,
|
|
|
|
(s8)link->beacon_stats.avg_signal,
|
|
|
|
link_id == iwl_mvm_get_primary_link(vif)))
|
2024-04-16 13:54:04 +03:00
|
|
|
/* In case we decided to exit eSR - stay with the primary */
|
2024-05-05 09:19:45 +03:00
|
|
|
iwl_mvm_exit_esr(mvm, vif, IWL_MVM_ESR_EXIT_COEX,
|
|
|
|
iwl_mvm_get_primary_link(vif));
|
2024-01-31 22:56:32 +02:00
|
|
|
}
|
|
|
|
|
2023-03-29 10:05:12 +03:00
|
|
|
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)
|
2013-02-10 17:06:17 +02:00
|
|
|
{
|
2014-08-21 19:08:44 +02:00
|
|
|
/* default smps_mode is AUTOMATIC - only used for client modes */
|
|
|
|
enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_AUTOMATIC;
|
2023-03-29 10:05:12 +03:00
|
|
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
2018-04-23 11:43:02 +03:00
|
|
|
u32 bt_activity_grading, min_ag_for_static_smps;
|
2023-03-29 10:05:12 +03:00
|
|
|
struct ieee80211_chanctx_conf *chanctx_conf;
|
|
|
|
struct iwl_mvm_vif_link_info *link_info;
|
|
|
|
struct ieee80211_bss_conf *link_conf;
|
2013-01-24 10:35:13 +02:00
|
|
|
int ave_rssi;
|
2013-02-10 17:06:17 +02:00
|
|
|
|
2013-05-19 19:14:41 +03:00
|
|
|
lockdep_assert_held(&mvm->mutex);
|
2013-02-10 17:06:17 +02:00
|
|
|
|
2023-03-29 10:05:12 +03:00
|
|
|
link_info = mvmvif->link[link_id];
|
|
|
|
if (!link_info)
|
2013-12-26 15:32:40 +02:00
|
|
|
return;
|
2013-02-10 17:06:17 +02:00
|
|
|
|
2023-03-29 10:05:12 +03:00
|
|
|
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);
|
2013-06-18 07:35:27 +03:00
|
|
|
|
|
|
|
/* If channel context is invalid or not on 2.4GHz .. */
|
|
|
|
if ((!chanctx_conf ||
|
2016-04-12 15:56:15 +02:00
|
|
|
chanctx_conf->def.chan->band != NL80211_BAND_2GHZ)) {
|
2014-05-20 15:48:18 +03:00
|
|
|
if (vif->type == NL80211_IFTYPE_STATION) {
|
2014-07-07 14:38:39 +03:00
|
|
|
/* ... relax constraints and disable rssi events */
|
|
|
|
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
|
2023-03-29 10:05:12 +03:00
|
|
|
smps_mode, link_id);
|
|
|
|
iwl_mvm_bt_coex_reduced_txp(mvm, link_info->ap_sta_id,
|
2014-05-20 15:48:18 +03:00
|
|
|
false);
|
2024-03-11 08:28:04 +02:00
|
|
|
iwl_mvm_bt_coex_enable_rssi_event(mvm, link_info, false,
|
|
|
|
0);
|
2014-05-20 15:48:18 +03:00
|
|
|
}
|
2013-06-25 21:49:19 +03:00
|
|
|
return;
|
2013-06-18 07:35:27 +03:00
|
|
|
}
|
|
|
|
|
2024-04-16 13:53:59 +03:00
|
|
|
iwl_mvm_bt_coex_update_link_esr(mvm, vif, link_id);
|
2024-01-31 22:56:32 +02:00
|
|
|
|
2018-04-23 11:43:02 +03:00
|
|
|
if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2))
|
|
|
|
min_ag_for_static_smps = BT_VERY_HIGH_TRAFFIC;
|
|
|
|
else
|
|
|
|
min_ag_for_static_smps = BT_HIGH_TRAFFIC;
|
|
|
|
|
2013-12-26 15:32:40 +02:00
|
|
|
bt_activity_grading = le32_to_cpu(data->notif->bt_activity_grading);
|
2018-04-23 11:43:02 +03:00
|
|
|
if (bt_activity_grading >= min_ag_for_static_smps)
|
2013-12-26 15:32:40 +02:00
|
|
|
smps_mode = IEEE80211_SMPS_STATIC;
|
|
|
|
else if (bt_activity_grading >= BT_LOW_TRAFFIC)
|
2014-07-07 14:38:39 +03:00
|
|
|
smps_mode = IEEE80211_SMPS_DYNAMIC;
|
2014-04-30 18:09:59 +03:00
|
|
|
|
2014-08-21 19:08:44 +02:00
|
|
|
/* relax SMPS constraints for next association */
|
wifi: mac80211: move interface config to new struct
We'll use bss_conf for per-link configuration later, so
move out all the non-link-specific data out into a new
struct ieee80211_vif_cfg used in the vif.
Some adjustments were done with the following spatch:
@@
expression sdata;
struct ieee80211_vif *vifp;
identifier var = { assoc, ibss_joined, aid, arp_addr_list, arp_addr_cnt, ssid, ssid_len, s1g, ibss_creator };
@@
(
-sdata->vif.bss_conf.var
+sdata->vif.cfg.var
|
-vifp->bss_conf.var
+vifp->cfg.var
)
@bss_conf@
struct ieee80211_bss_conf *bss_conf;
identifier var = { assoc, ibss_joined, aid, arp_addr_list, arp_addr_cnt, ssid, ssid_len, s1g, ibss_creator };
@@
-bss_conf->var
+vif_cfg->var
(though more manual fixups were needed, e.g. replacing
"vif_cfg->" by "vif->cfg." in many files.)
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2022-05-10 17:05:04 +02:00
|
|
|
if (!vif->cfg.assoc)
|
2014-04-30 18:09:59 +03:00
|
|
|
smps_mode = IEEE80211_SMPS_AUTOMATIC;
|
|
|
|
|
2023-03-29 10:05:12 +03:00
|
|
|
if (link_info->phy_ctxt &&
|
|
|
|
(mvm->last_bt_notif.rrc_status & BIT(link_info->phy_ctxt->id)))
|
2014-06-30 10:26:02 +03:00
|
|
|
smps_mode = IEEE80211_SMPS_AUTOMATIC;
|
|
|
|
|
2013-12-26 15:32:40 +02:00
|
|
|
IWL_DEBUG_COEX(data->mvm,
|
2023-03-29 10:05:12 +03:00
|
|
|
"mac %d link %d: bt_activity_grading %d smps_req %d\n",
|
|
|
|
mvmvif->id, link_info->fw_link_id,
|
|
|
|
bt_activity_grading, smps_mode);
|
2013-12-26 15:32:40 +02:00
|
|
|
|
2014-07-07 14:38:39 +03:00
|
|
|
if (vif->type == NL80211_IFTYPE_STATION)
|
|
|
|
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
|
2023-03-29 10:05:12 +03:00
|
|
|
smps_mode, link_id);
|
2013-12-26 15:32:40 +02:00
|
|
|
|
2014-01-15 16:57:54 +02:00
|
|
|
/* low latency is always primary */
|
|
|
|
if (iwl_mvm_vif_low_latency(mvmvif)) {
|
|
|
|
data->primary_ll = true;
|
|
|
|
|
|
|
|
data->secondary = data->primary;
|
|
|
|
data->primary = chanctx_conf;
|
|
|
|
}
|
|
|
|
|
2013-06-18 07:35:27 +03:00
|
|
|
if (vif->type == NL80211_IFTYPE_AP) {
|
2013-07-31 14:07:43 +02:00
|
|
|
if (!mvmvif->ap_ibss_active)
|
2013-06-18 07:35:27 +03:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (chanctx_conf == data->primary)
|
|
|
|
return;
|
|
|
|
|
2014-01-15 16:57:54 +02:00
|
|
|
if (!data->primary_ll) {
|
|
|
|
/*
|
|
|
|
* downgrade the current primary no matter what its
|
|
|
|
* type is.
|
|
|
|
*/
|
|
|
|
data->secondary = data->primary;
|
|
|
|
data->primary = chanctx_conf;
|
|
|
|
} else {
|
|
|
|
/* there is low latency vif - we will be secondary */
|
|
|
|
data->secondary = chanctx_conf;
|
|
|
|
}
|
2014-12-09 17:08:41 +02:00
|
|
|
|
2023-03-29 10:05:12 +03:00
|
|
|
/* FIXME: TCM load per interface? or need something per link? */
|
2014-12-09 17:08:41 +02:00
|
|
|
if (data->primary == chanctx_conf)
|
|
|
|
data->primary_load = mvm->tcm.result.load[mvmvif->id];
|
|
|
|
else if (data->secondary == chanctx_conf)
|
|
|
|
data->secondary_load = mvm->tcm.result.load[mvmvif->id];
|
2013-03-20 15:28:27 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-01-15 16:57:54 +02:00
|
|
|
/*
|
|
|
|
* STA / P2P Client, try to be primary if first vif. If we are in low
|
|
|
|
* latency mode, we are already in primary and just don't do much
|
|
|
|
*/
|
2013-06-18 07:35:27 +03:00
|
|
|
if (!data->primary || data->primary == chanctx_conf)
|
|
|
|
data->primary = chanctx_conf;
|
|
|
|
else if (!data->secondary)
|
|
|
|
/* if secondary is not NULL, it might be a GO */
|
|
|
|
data->secondary = chanctx_conf;
|
|
|
|
|
2023-03-29 10:05:12 +03:00
|
|
|
/* FIXME: TCM load per interface? or need something per link? */
|
2014-12-09 17:08:41 +02:00
|
|
|
if (data->primary == chanctx_conf)
|
|
|
|
data->primary_load = mvm->tcm.result.load[mvmvif->id];
|
|
|
|
else if (data->secondary == chanctx_conf)
|
|
|
|
data->secondary_load = mvm->tcm.result.load[mvmvif->id];
|
2014-04-30 18:09:59 +03:00
|
|
|
/*
|
|
|
|
* don't reduce the Tx power if one of these is true:
|
|
|
|
* we are in LOOSE
|
2016-06-20 09:40:40 +03:00
|
|
|
* BT is inactive
|
|
|
|
* we are not associated
|
2014-04-30 18:09:59 +03:00
|
|
|
*/
|
2013-07-14 13:40:21 +03:00
|
|
|
if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT ||
|
2023-12-19 21:58:57 +02:00
|
|
|
le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF ||
|
|
|
|
!vif->cfg.assoc) {
|
2023-03-29 10:05:12 +03:00
|
|
|
iwl_mvm_bt_coex_reduced_txp(mvm, link_info->ap_sta_id, false);
|
2024-03-11 08:28:04 +02:00
|
|
|
iwl_mvm_bt_coex_enable_rssi_event(mvm, link_info, false, 0);
|
2013-01-24 10:35:13 +02:00
|
|
|
return;
|
2013-07-14 13:40:21 +03:00
|
|
|
}
|
2013-01-24 10:35:13 +02:00
|
|
|
|
2013-07-21 17:37:19 +03:00
|
|
|
/* try to get the avg rssi from fw */
|
2024-03-11 08:28:04 +02:00
|
|
|
ave_rssi = link_info->bf_data.ave_beacon_signal;
|
2013-01-24 10:35:13 +02:00
|
|
|
|
|
|
|
/* if the RSSI isn't valid, fake it is very low */
|
|
|
|
if (!ave_rssi)
|
|
|
|
ave_rssi = -100;
|
2014-05-27 22:54:18 +03:00
|
|
|
if (ave_rssi > -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH) {
|
2023-03-29 10:05:12 +03:00
|
|
|
if (iwl_mvm_bt_coex_reduced_txp(mvm, link_info->ap_sta_id,
|
wifi: iwlwifi: mvm: vif preparation for MLO
In MLO, some fields of iwl_mvm_vif should be defined in the
context of a link. Define a separate structure for these fields and
add a deflink object to hold it as part of iwl_mvm_vif. Non-MLO legacy
code will use only deflink object while MLO related code will use the
corresponding link from the link array.
It follows the strategy applied in mac80211 for introducing MLO
changes.
The below spatch takes care of updating all driver code to access
fields separated into MLD specific data structure via deflink (need
to convert all references to the fields listed in var to deflink.var
and also to take care of calls like iwl_mvm_vif_from_mac80211(vif)->field).
@iwl_mld_vif@
struct iwl_mvm_vif *v;
struct ieee80211_vif *vv;
identifier fn;
identifier var = {bssid, ap_sta_id, bcast_sta, mcast_sta,
beacon_stats, smps_requests, probe_resp_data,
he_ru_2mhz_block, cab_queue, phy_ctxt,
queue_params};
@@
(
v->
- var
+ deflink.var
|
fn(vv)->
- var
+ deflink.var
)
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230328104948.4896576f0a9f.Ifaf0187c96b9fe52b24bd629331165831a877691@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2023-03-28 10:58:41 +03:00
|
|
|
true))
|
2013-01-24 10:35:13 +02:00
|
|
|
IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
|
2014-05-27 22:54:18 +03:00
|
|
|
} else if (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) {
|
2023-03-29 10:05:12 +03:00
|
|
|
if (iwl_mvm_bt_coex_reduced_txp(mvm, link_info->ap_sta_id,
|
wifi: iwlwifi: mvm: vif preparation for MLO
In MLO, some fields of iwl_mvm_vif should be defined in the
context of a link. Define a separate structure for these fields and
add a deflink object to hold it as part of iwl_mvm_vif. Non-MLO legacy
code will use only deflink object while MLO related code will use the
corresponding link from the link array.
It follows the strategy applied in mac80211 for introducing MLO
changes.
The below spatch takes care of updating all driver code to access
fields separated into MLD specific data structure via deflink (need
to convert all references to the fields listed in var to deflink.var
and also to take care of calls like iwl_mvm_vif_from_mac80211(vif)->field).
@iwl_mld_vif@
struct iwl_mvm_vif *v;
struct ieee80211_vif *vv;
identifier fn;
identifier var = {bssid, ap_sta_id, bcast_sta, mcast_sta,
beacon_stats, smps_requests, probe_resp_data,
he_ru_2mhz_block, cab_queue, phy_ctxt,
queue_params};
@@
(
v->
- var
+ deflink.var
|
fn(vv)->
- var
+ deflink.var
)
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230328104948.4896576f0a9f.Ifaf0187c96b9fe52b24bd629331165831a877691@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2023-03-28 10:58:41 +03:00
|
|
|
false))
|
2013-01-24 10:35:13 +02:00
|
|
|
IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Begin to monitor the RSSI: it may influence the reduced Tx power */
|
2024-03-11 08:28:04 +02:00
|
|
|
iwl_mvm_bt_coex_enable_rssi_event(mvm, link_info, true, ave_rssi);
|
2013-02-10 17:06:17 +02:00
|
|
|
}
|
|
|
|
|
2023-03-29 10:05:12 +03:00
|
|
|
/* 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);
|
|
|
|
}
|
|
|
|
|
2013-03-29 14:56:19 +03:00
|
|
|
static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
|
2013-01-17 14:20:29 +02:00
|
|
|
{
|
2013-01-24 10:35:13 +02:00
|
|
|
struct iwl_bt_iterator_data data = {
|
2013-02-10 17:06:17 +02:00
|
|
|
.mvm = mvm,
|
2013-03-29 14:56:19 +03:00
|
|
|
.notif = &mvm->last_bt_notif,
|
2013-02-10 17:06:17 +02:00
|
|
|
};
|
2014-04-02 09:55:16 +03:00
|
|
|
struct iwl_bt_coex_ci_cmd cmd = {};
|
2013-06-18 07:35:27 +03:00
|
|
|
u8 ci_bw_idx;
|
2013-01-17 14:20:29 +02:00
|
|
|
|
2014-05-28 12:06:41 +03:00
|
|
|
/* Ignore updates if we are in force mode */
|
|
|
|
if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
|
|
|
|
return;
|
|
|
|
|
2013-06-18 07:35:27 +03:00
|
|
|
rcu_read_lock();
|
2013-02-10 17:06:17 +02:00
|
|
|
ieee80211_iterate_active_interfaces_atomic(
|
|
|
|
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
|
|
|
|
iwl_mvm_bt_notif_iterator, &data);
|
|
|
|
|
2024-02-01 16:17:38 +02:00
|
|
|
if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
|
|
|
|
rcu_read_unlock();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-12-09 17:08:41 +02:00
|
|
|
iwl_mvm_bt_coex_tcm_based_ci(mvm, &data);
|
|
|
|
|
2013-06-18 07:35:27 +03:00
|
|
|
if (data.primary) {
|
|
|
|
struct ieee80211_chanctx_conf *chan = data.primary;
|
|
|
|
if (WARN_ON(!chan->def.chan)) {
|
|
|
|
rcu_read_unlock();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (chan->def.width < NL80211_CHAN_WIDTH_40) {
|
|
|
|
ci_bw_idx = 0;
|
|
|
|
} else {
|
|
|
|
if (chan->def.center_freq1 >
|
|
|
|
chan->def.chan->center_freq)
|
|
|
|
ci_bw_idx = 2;
|
|
|
|
else
|
|
|
|
ci_bw_idx = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
cmd.bt_primary_ci =
|
|
|
|
iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx];
|
2014-04-02 09:55:16 +03:00
|
|
|
cmd.primary_ch_phy_id =
|
|
|
|
cpu_to_le32(*((u16 *)data.primary->drv_priv));
|
2013-06-18 07:35:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (data.secondary) {
|
|
|
|
struct ieee80211_chanctx_conf *chan = data.secondary;
|
|
|
|
if (WARN_ON(!data.secondary->def.chan)) {
|
|
|
|
rcu_read_unlock();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (chan->def.width < NL80211_CHAN_WIDTH_40) {
|
|
|
|
ci_bw_idx = 0;
|
|
|
|
} else {
|
|
|
|
if (chan->def.center_freq1 >
|
|
|
|
chan->def.chan->center_freq)
|
|
|
|
ci_bw_idx = 2;
|
|
|
|
else
|
|
|
|
ci_bw_idx = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
cmd.bt_secondary_ci =
|
|
|
|
iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx];
|
2014-04-02 09:55:16 +03:00
|
|
|
cmd.secondary_ch_phy_id =
|
|
|
|
cpu_to_le32(*((u16 *)data.secondary->drv_priv));
|
2013-06-18 07:35:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
rcu_read_unlock();
|
|
|
|
|
|
|
|
/* Don't spam the fw with the same command over and over */
|
|
|
|
if (memcmp(&cmd, &mvm->last_bt_ci_cmd, sizeof(cmd))) {
|
2014-05-12 11:36:41 +03:00
|
|
|
if (iwl_mvm_send_cmd_pdu(mvm, BT_COEX_CI, 0,
|
2013-06-18 07:35:27 +03:00
|
|
|
sizeof(cmd), &cmd))
|
2014-05-07 11:47:53 +02:00
|
|
|
IWL_ERR(mvm, "Failed to send BT_CI cmd\n");
|
2013-06-18 07:35:27 +03:00
|
|
|
memcpy(&mvm->last_bt_ci_cmd, &cmd, sizeof(cmd));
|
|
|
|
}
|
2013-03-20 15:28:27 +02:00
|
|
|
}
|
|
|
|
|
2015-06-23 21:22:09 +02:00
|
|
|
void iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
|
|
|
|
struct iwl_rx_cmd_buffer *rxb)
|
2013-03-20 15:28:27 +02:00
|
|
|
{
|
|
|
|
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
2014-04-02 12:23:09 +03:00
|
|
|
struct iwl_bt_coex_profile_notif *notif = (void *)pkt->data;
|
2013-03-20 15:28:27 +02:00
|
|
|
|
|
|
|
IWL_DEBUG_COEX(mvm, "BT Coex Notification received\n");
|
2017-11-01 13:27:49 +02:00
|
|
|
IWL_DEBUG_COEX(mvm, "\tBT ci compliance %d\n", notif->bt_ci_compliance);
|
2013-06-18 07:35:27 +03:00
|
|
|
IWL_DEBUG_COEX(mvm, "\tBT primary_ch_lut %d\n",
|
2017-11-01 13:27:49 +02:00
|
|
|
le32_to_cpu(notif->primary_ch_lut));
|
2013-06-18 07:35:27 +03:00
|
|
|
IWL_DEBUG_COEX(mvm, "\tBT secondary_ch_lut %d\n",
|
2017-11-01 13:27:49 +02:00
|
|
|
le32_to_cpu(notif->secondary_ch_lut));
|
2013-06-18 07:35:27 +03:00
|
|
|
IWL_DEBUG_COEX(mvm, "\tBT activity grading %d\n",
|
2017-11-01 13:27:49 +02:00
|
|
|
le32_to_cpu(notif->bt_activity_grading));
|
2013-03-20 15:28:27 +02:00
|
|
|
|
2017-11-01 13:27:49 +02:00
|
|
|
/* remember this notification for future use: rssi fluctuations */
|
|
|
|
memcpy(&mvm->last_bt_notif, notif, sizeof(mvm->last_bt_notif));
|
2013-03-29 14:56:19 +03:00
|
|
|
|
|
|
|
iwl_mvm_bt_coex_notif_handle(mvm);
|
2013-01-24 10:35:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
2015-03-16 23:23:34 +02:00
|
|
|
enum ieee80211_rssi_event_data rssi_event)
|
2013-01-24 10:35:13 +02:00
|
|
|
{
|
2014-12-23 16:00:17 +01:00
|
|
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
2013-01-24 10:35:13 +02:00
|
|
|
int ret;
|
|
|
|
|
2013-10-02 12:05:24 +02:00
|
|
|
lockdep_assert_held(&mvm->mutex);
|
2013-01-24 10:35:13 +02:00
|
|
|
|
2014-05-28 12:06:41 +03:00
|
|
|
/* Ignore updates if we are in force mode */
|
|
|
|
if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
|
|
|
|
return;
|
|
|
|
|
2014-03-04 10:28:23 +02:00
|
|
|
/*
|
|
|
|
* Rssi update while not associated - can happen since the statistics
|
|
|
|
* are handled asynchronously
|
|
|
|
*/
|
wifi: iwlwifi: mvm: vif preparation for MLO
In MLO, some fields of iwl_mvm_vif should be defined in the
context of a link. Define a separate structure for these fields and
add a deflink object to hold it as part of iwl_mvm_vif. Non-MLO legacy
code will use only deflink object while MLO related code will use the
corresponding link from the link array.
It follows the strategy applied in mac80211 for introducing MLO
changes.
The below spatch takes care of updating all driver code to access
fields separated into MLD specific data structure via deflink (need
to convert all references to the fields listed in var to deflink.var
and also to take care of calls like iwl_mvm_vif_from_mac80211(vif)->field).
@iwl_mld_vif@
struct iwl_mvm_vif *v;
struct ieee80211_vif *vv;
identifier fn;
identifier var = {bssid, ap_sta_id, bcast_sta, mcast_sta,
beacon_stats, smps_requests, probe_resp_data,
he_ru_2mhz_block, cab_queue, phy_ctxt,
queue_params};
@@
(
v->
- var
+ deflink.var
|
fn(vv)->
- var
+ deflink.var
)
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230328104948.4896576f0a9f.Ifaf0187c96b9fe52b24bd629331165831a877691@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2023-03-28 10:58:41 +03:00
|
|
|
if (mvmvif->deflink.ap_sta_id == IWL_MVM_INVALID_STA)
|
2013-10-02 12:05:24 +02:00
|
|
|
return;
|
2013-01-24 10:35:13 +02:00
|
|
|
|
2013-06-30 07:51:54 +03:00
|
|
|
/* No BT - reports should be disabled */
|
2014-04-02 09:55:16 +03:00
|
|
|
if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF)
|
2013-10-02 12:05:24 +02:00
|
|
|
return;
|
2013-01-24 10:35:13 +02:00
|
|
|
|
|
|
|
IWL_DEBUG_COEX(mvm, "RSSI for %pM is now %s\n", vif->bss_conf.bssid,
|
|
|
|
rssi_event == RSSI_EVENT_HIGH ? "HIGH" : "LOW");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if rssi is good enough for reduced Tx power, but not in loose
|
|
|
|
* scheme.
|
|
|
|
*/
|
2023-12-19 21:58:57 +02:00
|
|
|
if (rssi_event == RSSI_EVENT_LOW ||
|
2013-06-30 07:51:54 +03:00
|
|
|
iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT)
|
wifi: iwlwifi: mvm: vif preparation for MLO
In MLO, some fields of iwl_mvm_vif should be defined in the
context of a link. Define a separate structure for these fields and
add a deflink object to hold it as part of iwl_mvm_vif. Non-MLO legacy
code will use only deflink object while MLO related code will use the
corresponding link from the link array.
It follows the strategy applied in mac80211 for introducing MLO
changes.
The below spatch takes care of updating all driver code to access
fields separated into MLD specific data structure via deflink (need
to convert all references to the fields listed in var to deflink.var
and also to take care of calls like iwl_mvm_vif_from_mac80211(vif)->field).
@iwl_mld_vif@
struct iwl_mvm_vif *v;
struct ieee80211_vif *vv;
identifier fn;
identifier var = {bssid, ap_sta_id, bcast_sta, mcast_sta,
beacon_stats, smps_requests, probe_resp_data,
he_ru_2mhz_block, cab_queue, phy_ctxt,
queue_params};
@@
(
v->
- var
+ deflink.var
|
fn(vv)->
- var
+ deflink.var
)
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230328104948.4896576f0a9f.Ifaf0187c96b9fe52b24bd629331165831a877691@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2023-03-28 10:58:41 +03:00
|
|
|
ret = iwl_mvm_bt_coex_reduced_txp(mvm,
|
|
|
|
mvmvif->deflink.ap_sta_id,
|
2013-01-24 10:35:13 +02:00
|
|
|
false);
|
2013-01-17 14:20:29 +02:00
|
|
|
else
|
wifi: iwlwifi: mvm: vif preparation for MLO
In MLO, some fields of iwl_mvm_vif should be defined in the
context of a link. Define a separate structure for these fields and
add a deflink object to hold it as part of iwl_mvm_vif. Non-MLO legacy
code will use only deflink object while MLO related code will use the
corresponding link from the link array.
It follows the strategy applied in mac80211 for introducing MLO
changes.
The below spatch takes care of updating all driver code to access
fields separated into MLD specific data structure via deflink (need
to convert all references to the fields listed in var to deflink.var
and also to take care of calls like iwl_mvm_vif_from_mac80211(vif)->field).
@iwl_mld_vif@
struct iwl_mvm_vif *v;
struct ieee80211_vif *vv;
identifier fn;
identifier var = {bssid, ap_sta_id, bcast_sta, mcast_sta,
beacon_stats, smps_requests, probe_resp_data,
he_ru_2mhz_block, cab_queue, phy_ctxt,
queue_params};
@@
(
v->
- var
+ deflink.var
|
fn(vv)->
- var
+ deflink.var
)
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230328104948.4896576f0a9f.Ifaf0187c96b9fe52b24bd629331165831a877691@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2023-03-28 10:58:41 +03:00
|
|
|
ret = iwl_mvm_bt_coex_reduced_txp(mvm,
|
|
|
|
mvmvif->deflink.ap_sta_id,
|
|
|
|
true);
|
2013-01-17 14:20:29 +02:00
|
|
|
|
2013-01-24 10:35:13 +02:00
|
|
|
if (ret)
|
|
|
|
IWL_ERR(mvm, "couldn't send BT_CONFIG HCMD upon RSSI event\n");
|
2013-01-17 14:20:29 +02:00
|
|
|
}
|
2013-03-20 15:28:27 +02:00
|
|
|
|
2013-07-18 08:45:41 +03:00
|
|
|
#define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000)
|
|
|
|
#define LINK_QUAL_AGG_TIME_LIMIT_BT_ACT (1200)
|
|
|
|
|
2014-03-11 19:27:45 +02:00
|
|
|
u16 iwl_mvm_coex_agg_time_limit(struct iwl_mvm *mvm,
|
|
|
|
struct ieee80211_sta *sta)
|
2013-07-18 08:45:41 +03:00
|
|
|
{
|
2013-11-14 18:20:04 +01:00
|
|
|
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
2014-06-30 10:26:02 +03:00
|
|
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
|
wifi: iwlwifi: mvm: vif preparation for MLO
In MLO, some fields of iwl_mvm_vif should be defined in the
context of a link. Define a separate structure for these fields and
add a deflink object to hold it as part of iwl_mvm_vif. Non-MLO legacy
code will use only deflink object while MLO related code will use the
corresponding link from the link array.
It follows the strategy applied in mac80211 for introducing MLO
changes.
The below spatch takes care of updating all driver code to access
fields separated into MLD specific data structure via deflink (need
to convert all references to the fields listed in var to deflink.var
and also to take care of calls like iwl_mvm_vif_from_mac80211(vif)->field).
@iwl_mld_vif@
struct iwl_mvm_vif *v;
struct ieee80211_vif *vv;
identifier fn;
identifier var = {bssid, ap_sta_id, bcast_sta, mcast_sta,
beacon_stats, smps_requests, probe_resp_data,
he_ru_2mhz_block, cab_queue, phy_ctxt,
queue_params};
@@
(
v->
- var
+ deflink.var
|
fn(vv)->
- var
+ deflink.var
)
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230328104948.4896576f0a9f.Ifaf0187c96b9fe52b24bd629331165831a877691@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2023-03-28 10:58:41 +03:00
|
|
|
struct iwl_mvm_phy_ctxt *phy_ctxt = mvmvif->deflink.phy_ctxt;
|
2013-07-18 08:45:41 +03:00
|
|
|
enum iwl_bt_coex_lut_type lut_type;
|
|
|
|
|
2017-07-23 12:53:46 +03:00
|
|
|
if (mvm->last_bt_notif.ttc_status & BIT(phy_ctxt->id))
|
2014-06-30 10:26:02 +03:00
|
|
|
return LINK_QUAL_AGG_TIME_LIMIT_DEF;
|
|
|
|
|
2013-07-18 08:45:41 +03:00
|
|
|
if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) <
|
2013-11-13 22:00:30 +02:00
|
|
|
BT_HIGH_TRAFFIC)
|
2013-07-18 08:45:41 +03:00
|
|
|
return LINK_QUAL_AGG_TIME_LIMIT_DEF;
|
2014-06-02 16:18:42 +03:00
|
|
|
|
2013-07-18 08:45:41 +03:00
|
|
|
lut_type = iwl_get_coex_type(mvm, mvmsta->vif);
|
|
|
|
|
2014-05-25 13:58:31 +03:00
|
|
|
if (lut_type == BT_COEX_LOOSE_LUT || lut_type == BT_COEX_INVALID_LUT)
|
2013-07-18 08:45:41 +03:00
|
|
|
return LINK_QUAL_AGG_TIME_LIMIT_DEF;
|
|
|
|
|
|
|
|
/* tight coex, high bt traffic, reduce AGG time limit */
|
|
|
|
return LINK_QUAL_AGG_TIME_LIMIT_BT_ACT;
|
|
|
|
}
|
|
|
|
|
2013-10-06 11:41:20 +03:00
|
|
|
bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm,
|
|
|
|
struct ieee80211_sta *sta)
|
|
|
|
{
|
2013-11-14 18:20:04 +01:00
|
|
|
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
2014-06-30 10:26:02 +03:00
|
|
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
|
wifi: iwlwifi: mvm: vif preparation for MLO
In MLO, some fields of iwl_mvm_vif should be defined in the
context of a link. Define a separate structure for these fields and
add a deflink object to hold it as part of iwl_mvm_vif. Non-MLO legacy
code will use only deflink object while MLO related code will use the
corresponding link from the link array.
It follows the strategy applied in mac80211 for introducing MLO
changes.
The below spatch takes care of updating all driver code to access
fields separated into MLD specific data structure via deflink (need
to convert all references to the fields listed in var to deflink.var
and also to take care of calls like iwl_mvm_vif_from_mac80211(vif)->field).
@iwl_mld_vif@
struct iwl_mvm_vif *v;
struct ieee80211_vif *vv;
identifier fn;
identifier var = {bssid, ap_sta_id, bcast_sta, mcast_sta,
beacon_stats, smps_requests, probe_resp_data,
he_ru_2mhz_block, cab_queue, phy_ctxt,
queue_params};
@@
(
v->
- var
+ deflink.var
|
fn(vv)->
- var
+ deflink.var
)
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230328104948.4896576f0a9f.Ifaf0187c96b9fe52b24bd629331165831a877691@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2023-03-28 10:58:41 +03:00
|
|
|
struct iwl_mvm_phy_ctxt *phy_ctxt = mvmvif->deflink.phy_ctxt;
|
2014-05-25 13:58:31 +03:00
|
|
|
enum iwl_bt_coex_lut_type lut_type;
|
2013-10-06 11:41:20 +03:00
|
|
|
|
2017-07-23 12:53:46 +03:00
|
|
|
if (mvm->last_bt_notif.ttc_status & BIT(phy_ctxt->id))
|
2014-06-02 16:18:42 +03:00
|
|
|
return true;
|
|
|
|
|
2013-10-06 11:41:20 +03:00
|
|
|
if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) <
|
|
|
|
BT_HIGH_TRAFFIC)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
/*
|
2014-05-25 13:58:31 +03:00
|
|
|
* In Tight / TxTxDis, BT can't Rx while we Tx, so use both antennas
|
|
|
|
* since BT is already killed.
|
|
|
|
* In Loose, BT can Rx while we Tx, so forbid MIMO to let BT Rx while
|
|
|
|
* we Tx.
|
|
|
|
* When we are in 5GHz, we'll get BT_COEX_INVALID_LUT allowing MIMO.
|
2013-10-06 11:41:20 +03:00
|
|
|
*/
|
2014-05-25 13:58:31 +03:00
|
|
|
lut_type = iwl_get_coex_type(mvm, mvmsta->vif);
|
|
|
|
return lut_type != BT_COEX_LOOSE_LUT;
|
2013-10-06 11:41:20 +03:00
|
|
|
}
|
|
|
|
|
2014-10-30 11:59:40 +02:00
|
|
|
bool iwl_mvm_bt_coex_is_ant_avail(struct iwl_mvm *mvm, u8 ant)
|
|
|
|
{
|
|
|
|
if (ant & mvm->cfg->non_shared_ant)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) <
|
|
|
|
BT_HIGH_TRAFFIC;
|
|
|
|
}
|
|
|
|
|
2014-05-28 21:53:39 +03:00
|
|
|
bool iwl_mvm_bt_coex_is_shared_ant_avail(struct iwl_mvm *mvm)
|
|
|
|
{
|
2015-05-16 22:47:56 +03:00
|
|
|
return le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) < BT_HIGH_TRAFFIC;
|
2014-05-28 21:53:39 +03:00
|
|
|
}
|
|
|
|
|
2014-03-13 17:21:36 +02:00
|
|
|
bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm,
|
2016-04-12 15:56:15 +02:00
|
|
|
enum nl80211_band band)
|
2014-03-13 17:21:36 +02:00
|
|
|
{
|
|
|
|
u32 bt_activity = le32_to_cpu(mvm->last_bt_notif.bt_activity_grading);
|
|
|
|
|
2016-04-12 15:56:15 +02:00
|
|
|
if (band != NL80211_BAND_2GHZ)
|
2014-03-13 17:21:36 +02:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return bt_activity >= BT_LOW_TRAFFIC;
|
|
|
|
}
|
|
|
|
|
2018-05-28 17:18:47 +03:00
|
|
|
u8 iwl_mvm_bt_coex_get_single_ant_msk(struct iwl_mvm *mvm, u8 enabled_ants)
|
|
|
|
{
|
|
|
|
if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2) &&
|
|
|
|
(mvm->cfg->non_shared_ant & enabled_ants))
|
|
|
|
return mvm->cfg->non_shared_ant;
|
|
|
|
|
|
|
|
return first_antenna(enabled_ants);
|
|
|
|
}
|
|
|
|
|
2014-03-06 10:30:49 +02:00
|
|
|
u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
|
2014-03-06 14:49:36 +02:00
|
|
|
struct ieee80211_tx_info *info, u8 ac)
|
2014-03-06 10:30:49 +02:00
|
|
|
{
|
|
|
|
__le16 fc = hdr->frame_control;
|
2015-11-02 14:16:07 +02:00
|
|
|
bool mplut_enabled = iwl_mvm_is_mplut_supported(mvm);
|
2014-03-06 10:30:49 +02:00
|
|
|
|
2016-04-12 15:56:15 +02:00
|
|
|
if (info->band != NL80211_BAND_2GHZ)
|
2014-03-06 14:49:36 +02:00
|
|
|
return 0;
|
|
|
|
|
2014-03-16 21:55:43 +02:00
|
|
|
if (unlikely(mvm->bt_tx_prio))
|
|
|
|
return mvm->bt_tx_prio - 1;
|
|
|
|
|
2015-11-02 14:16:07 +02:00
|
|
|
if (likely(ieee80211_is_data(fc))) {
|
|
|
|
if (likely(ieee80211_is_data_qos(fc))) {
|
|
|
|
switch (ac) {
|
|
|
|
case IEEE80211_AC_BE:
|
|
|
|
return mplut_enabled ? 1 : 0;
|
|
|
|
case IEEE80211_AC_VI:
|
|
|
|
return mplut_enabled ? 2 : 3;
|
|
|
|
case IEEE80211_AC_VO:
|
|
|
|
return 3;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else if (is_multicast_ether_addr(hdr->addr1)) {
|
|
|
|
return 3;
|
|
|
|
} else
|
|
|
|
return 0;
|
|
|
|
} else if (ieee80211_is_mgmt(fc)) {
|
|
|
|
return ieee80211_is_disassoc(fc) ? 0 : 3;
|
|
|
|
} else if (ieee80211_is_ctl(fc)) {
|
|
|
|
/* ignore cfend and cfendack frames as we never send those */
|
2014-03-06 14:49:36 +02:00
|
|
|
return 3;
|
|
|
|
}
|
2014-03-06 10:30:49 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-10-02 15:02:25 +03:00
|
|
|
void iwl_mvm_bt_coex_vif_change(struct iwl_mvm *mvm)
|
2013-03-20 15:28:27 +02:00
|
|
|
{
|
2013-03-29 14:56:19 +03:00
|
|
|
iwl_mvm_bt_coex_notif_handle(mvm);
|
2013-03-20 15:28:27 +02:00
|
|
|
}
|