/* * 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.
*/
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);
}
/* * This function receives the LB link id and checks if eSR should be * enabled or disabled (due to BT coex)
*/ bool
iwl_mvm_bt_coex_calculate_esr_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
s32 link_rssi, bool primary)
{ 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 ||
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 (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) returntrue;
if (primary) returnfalse;
/* The feature is not supported */ if (!have_wifi_loss_rate) returntrue;
/* * 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 = wifi_loss_mid_high_rssi;
elseif (mvmvif->esr_active) /* RSSI needs to get really low to disable eSR... */
wifi_loss_rate =
link_rssi <= -IWL_MVM_BT_COEX_DISABLE_ESR_THRESH ?
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 ?
wifi_loss_low_rssi :
wifi_loss_mid_high_rssi;
if (!ieee80211_vif_is_mld(vif) ||
!iwl_mvm_vif_from_mac80211(vif)->authorized ||
WARN_ON(!link)) return;
if (!iwl_mvm_bt_coex_calculate_esr_mode(mvm, vif,
(s8)link->beacon_stats.avg_signal,
link_id == iwl_mvm_get_primary_link(vif))) /* In case we decided to exit eSR - stay with the primary */
iwl_mvm_exit_esr(mvm, vif, IWL_MVM_ESR_EXIT_COEX,
iwl_mvm_get_primary_link(vif));
}
staticvoid iwl_mvm_bt_notif_per_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct iwl_bt_iterator_data *data, unsignedint link_id)
{ /* 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);
link_info = mvmvif->link[link_id]; if (!link_info) return;
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;
if (vif->type == NL80211_IFTYPE_AP) { if (!mvmvif->ap_ibss_active) return;
if (chanctx_conf == data->primary) return;
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;
}
/* FIXME: TCM load per interface? or need something per link? */ if (data->primary == chanctx_conf)
data->primary_load = mvm->tcm.result.load[mvmvif->id]; elseif (data->secondary == chanctx_conf)
data->secondary_load = mvm->tcm.result.load[mvmvif->id]; return;
}
/* * 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
*/ if (!data->primary || data->primary == chanctx_conf)
data->primary = chanctx_conf; elseif (!data->secondary) /* 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]; elseif (data->secondary == chanctx_conf)
data->secondary_load = mvm->tcm.result.load[mvmvif->id]; /* * don't reduce the Tx power if one of these is true: * we are in LOOSE * BT is inactive * we are not associated
*/ if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT ||
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 = 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, link_info->ap_sta_id, true))
IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
} elseif (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) { 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, link_info, true, ave_rssi);
}
/* must be called under rcu_read_lock */ staticvoid 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; unsignedint 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;
}
/* Don't spam the fw with the same command over and over */ if (memcmp(&cmd, &mvm->last_bt_ci_cmd, sizeof(cmd))) { if (iwl_mvm_send_cmd_pdu(mvm, BT_COEX_CI, 0, sizeof(cmd), &cmd))
IWL_ERR(mvm, "Failed to send BT_CI cmd\n");
memcpy(&mvm->last_bt_ci_cmd, &cmd, sizeof(cmd));
}
}
/* Ignore updates if we are in force mode */ if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS)) return;
/* * Rssi update while not associated - can happen since the statistics * are handled asynchronously
*/ if (mvmvif->deflink.ap_sta_id == IWL_INVALID_STA) return;
/* No BT - reports should be disabled */ if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF) return;
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.
*/ 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->deflink.ap_sta_id, false); else
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");
}
if (mvm->last_bt_notif.ttc_status & BIT(phy_ctxt->id)) returntrue;
if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) <
BT_HIGH_TRAFFIC) returntrue;
/* * 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.
*/
lut_type = iwl_get_coex_type(mvm, mvmsta->vif); return lut_type != BT_COEX_LOOSE_LUT;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.