qcacmn: Implement primary UMAC selection based on RSSI
This implements RSSI Primary UMAC selection algorithm for MLO Change-Id: Ia1901e91e2b6184a5895c4d784425f387cd9474d CRs-Fixed: 3105927
此提交包含在:
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -23,14 +23,202 @@
|
||||
#include <wlan_utility.h>
|
||||
#include <wlan_reg_services_api.h>
|
||||
|
||||
/**
|
||||
* struct mlpeer_data: PSOC peers MLO data
|
||||
* @total_rssi: sum of RSSI of all ML peers
|
||||
* @num_ml_peers: Number of ML peer's with this PSOC as TQM
|
||||
* @max_ml_peers: Max ML peers can have this PSOC as TQM
|
||||
* (it is to distribute peers across all PSOCs)
|
||||
* @num_non_ml_peers: Non MLO peers of this PSOC
|
||||
*/
|
||||
struct mlpeer_data {
|
||||
int32_t total_rssi;
|
||||
uint16_t num_ml_peers;
|
||||
uint16_t max_ml_peers;
|
||||
uint16_t num_non_ml_peers;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mlo_all_link_rssi: structure to collect TQM params for all PSOCs
|
||||
* @psoc_tqm_parms: It collects peer data for all PSOCs
|
||||
* @num_psocs: Number of PSOCs in the system
|
||||
* @current_psoc_id: current psoc id, it is for iterator
|
||||
*/
|
||||
struct mlo_all_link_rssi {
|
||||
struct mlpeer_data psoc_tqm_parms[WLAN_OBJMGR_MAX_DEVICES];
|
||||
uint8_t num_psocs;
|
||||
uint8_t current_psoc_id;
|
||||
};
|
||||
|
||||
/* Invalid TQM/PSOC ID */
|
||||
#define ML_INVALID_PRIMARY_TQM 0xff
|
||||
|
||||
static void wlan_mlo_peer_get_rssi(struct wlan_objmgr_psoc *psoc,
|
||||
void *obj, void *args)
|
||||
{
|
||||
struct wlan_mlo_peer_context *mlo_peer_ctx;
|
||||
struct wlan_objmgr_peer *peer = (struct wlan_objmgr_peer *)obj;
|
||||
struct mlo_all_link_rssi *rssi_data = (struct mlo_all_link_rssi *)args;
|
||||
struct mlpeer_data *tqm_params = NULL;
|
||||
uint8_t index;
|
||||
|
||||
mlo_peer_ctx = peer->mlo_peer_ctx;
|
||||
index = rssi_data->current_psoc_id;
|
||||
tqm_params = &rssi_data->psoc_tqm_parms[index];
|
||||
|
||||
if (!wlan_peer_is_mlo(peer) || !mlo_peer_ctx) {
|
||||
if (wlan_peer_get_peer_type(peer) == WLAN_PEER_STA)
|
||||
tqm_params->num_non_ml_peers += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If this psoc is not primary UMAC, don't account RSSI */
|
||||
if (mlo_peer_ctx->primary_umac_psoc_id != rssi_data->current_psoc_id)
|
||||
return;
|
||||
|
||||
tqm_params->total_rssi += mlo_peer_ctx->avg_link_rssi;
|
||||
tqm_params->num_ml_peers += 1;
|
||||
}
|
||||
|
||||
static void wlan_get_rssi_data_each_psoc(struct wlan_objmgr_psoc *psoc,
|
||||
void *arg, uint8_t index)
|
||||
{
|
||||
struct mlo_all_link_rssi *rssi_data = (struct mlo_all_link_rssi *)arg;
|
||||
struct mlpeer_data *tqm_params = NULL;
|
||||
|
||||
tqm_params = &rssi_data->psoc_tqm_parms[index];
|
||||
|
||||
tqm_params->total_rssi = 0;
|
||||
tqm_params->num_ml_peers = 0;
|
||||
tqm_params->num_non_ml_peers = 0;
|
||||
tqm_params->max_ml_peers = MAX_MLO_PEER;
|
||||
|
||||
rssi_data->current_psoc_id = index;
|
||||
|
||||
wlan_objmgr_iterate_obj_list(psoc, WLAN_PEER_OP,
|
||||
wlan_mlo_peer_get_rssi, rssi_data, 0,
|
||||
WLAN_MLO_MGR_ID);
|
||||
}
|
||||
|
||||
static QDF_STATUS mld_get_link_rssi(struct mlo_all_link_rssi *rssi_data)
|
||||
{
|
||||
rssi_data->num_psocs = 0;
|
||||
|
||||
wlan_objmgr_iterate_psoc_list(wlan_get_rssi_data_each_psoc,
|
||||
rssi_data, WLAN_MLO_MGR_ID);
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
mld_get_best_primary_umac_w_rssi(struct wlan_mlo_peer_context *ml_peer,
|
||||
struct wlan_objmgr_vdev *link_vdevs[])
|
||||
{
|
||||
struct wlan_objmgr_peer *assoc_peer;
|
||||
struct mlo_all_link_rssi rssi_data;
|
||||
uint8_t i;
|
||||
int32_t avg_rssi[WLAN_OBJMGR_MAX_DEVICES] = {0};
|
||||
int32_t diff_rssi[WLAN_OBJMGR_MAX_DEVICES] = {0};
|
||||
int32_t diff_low;
|
||||
bool mld_sta_links[WLAN_OBJMGR_MAX_DEVICES] = {0};
|
||||
uint8_t num_psocs_w_no_sta = 0;
|
||||
struct wlan_objmgr_peer *assoc_peer = NULL;
|
||||
uint8_t prim_link, id;
|
||||
uint8_t num_psocs;
|
||||
struct mlpeer_data *tqm_params = NULL;
|
||||
|
||||
mld_get_link_rssi(&rssi_data);
|
||||
|
||||
for (i = 0; i < rssi_data.num_psocs; i++) {
|
||||
tqm_params = &rssi_data.psoc_tqm_parms[i];
|
||||
|
||||
if (tqm_params->num_ml_peers)
|
||||
avg_rssi[i] = (tqm_params->total_rssi /
|
||||
tqm_params->num_ml_peers);
|
||||
else
|
||||
num_psocs_w_no_sta++;
|
||||
}
|
||||
|
||||
assoc_peer = wlan_mlo_peer_get_assoc_peer(ml_peer);
|
||||
ml_peer->primary_umac_psoc_id = wlan_peer_get_psoc_id(assoc_peer);
|
||||
if (!assoc_peer) {
|
||||
mlo_err("Assoc peer of ML Peer " QDF_MAC_ADDR_FMT " is invalid",
|
||||
QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
|
||||
QDF_BUG(0);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this is first station, then assign primary umac to
|
||||
* assoc peer's psoc
|
||||
*/
|
||||
if (num_psocs_w_no_sta == rssi_data.num_psocs) {
|
||||
ml_peer->primary_umac_psoc_id =
|
||||
wlan_peer_get_psoc_id(assoc_peer);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* If MLD STA associated to a set of links, choose primary UMAC
|
||||
* from those links only
|
||||
*/
|
||||
num_psocs = 0;
|
||||
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
|
||||
if (!link_vdevs[i])
|
||||
continue;
|
||||
|
||||
id = wlan_vdev_get_psoc_id(link_vdevs[i]);
|
||||
if (id >= WLAN_OBJMGR_MAX_DEVICES)
|
||||
continue;
|
||||
|
||||
tqm_params = &rssi_data.psoc_tqm_parms[id];
|
||||
mld_sta_links[id] = true;
|
||||
|
||||
/* If this PSOC has exceeded limit, skip it */
|
||||
if ((tqm_params->num_ml_peers +
|
||||
tqm_params->num_non_ml_peers) >=
|
||||
tqm_params->max_ml_peers) {
|
||||
mld_sta_links[id] = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
num_psocs++;
|
||||
|
||||
/* If no stations are associated, derive diff rssi
|
||||
* based on psoc id {0-20, 20-40, 40 } so that
|
||||
* stations are distributed across TQMs
|
||||
*/
|
||||
if (!avg_rssi[id]) {
|
||||
diff_rssi[id] = (id * 20);
|
||||
continue;
|
||||
}
|
||||
diff_rssi[id] = (ml_peer->avg_link_rssi >= avg_rssi[id]) ?
|
||||
(ml_peer->avg_link_rssi - avg_rssi[id]) :
|
||||
(avg_rssi[id] - ml_peer->avg_link_rssi);
|
||||
}
|
||||
|
||||
prim_link = ML_INVALID_PRIMARY_TQM;
|
||||
diff_low = 0;
|
||||
|
||||
/* find min diff, based on it, allocate primary umac */
|
||||
for (i = 0; i < WLAN_OBJMGR_MAX_DEVICES; i++) {
|
||||
if (!mld_sta_links[i])
|
||||
continue;
|
||||
|
||||
/* First iteration */
|
||||
if (diff_low == 0) {
|
||||
diff_low = diff_rssi[i];
|
||||
prim_link = i;
|
||||
} else if (diff_low > diff_rssi[i]) {
|
||||
diff_low = diff_rssi[i];
|
||||
prim_link = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (prim_link != 0xff)
|
||||
ml_peer->primary_umac_psoc_id =
|
||||
wlan_vdev_get_psoc_id(link_vdevs[prim_link]);
|
||||
else
|
||||
ml_peer->primary_umac_psoc_id =
|
||||
wlan_peer_get_psoc_id(assoc_peer);
|
||||
}
|
||||
|
||||
void mlo_peer_assign_primary_umac(
|
||||
@@ -57,6 +245,92 @@ void mlo_peer_assign_primary_umac(
|
||||
}
|
||||
}
|
||||
|
||||
static int8_t wlan_vdev_derive_link_rssi(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_objmgr_vdev *assoc_vdev,
|
||||
int8_t rssi)
|
||||
{
|
||||
struct wlan_channel *channel, *assoc_channel;
|
||||
uint16_t ch_freq, assoc_freq;
|
||||
uint8_t tx_pow, assoc_tx_pow;
|
||||
int8_t diff_txpow;
|
||||
struct wlan_objmgr_pdev *pdev, *assoc_pdev;
|
||||
uint8_t log10_freq;
|
||||
uint8_t derived_rssi;
|
||||
int16_t ten_derived_rssi;
|
||||
int8_t ten_diff_pl = 0;
|
||||
|
||||
pdev = wlan_vdev_get_pdev(vdev);
|
||||
assoc_pdev = wlan_vdev_get_pdev(assoc_vdev);
|
||||
|
||||
channel = wlan_vdev_get_active_channel(vdev);
|
||||
if (channel)
|
||||
ch_freq = channel->ch_freq;
|
||||
else
|
||||
ch_freq = 1;
|
||||
|
||||
assoc_channel = wlan_vdev_get_active_channel(assoc_vdev);
|
||||
if (assoc_channel)
|
||||
assoc_freq = assoc_channel->ch_freq;
|
||||
else
|
||||
assoc_freq = 1;
|
||||
|
||||
/*
|
||||
* diff of path loss (of two links) = log10(freq1) - log10(freq2)
|
||||
* (since distance is constant)
|
||||
* since log10 is not available, we cameup with approximate ranges
|
||||
*/
|
||||
log10_freq = (ch_freq * 10) / assoc_freq;
|
||||
if ((log10_freq >= 20) && (log10_freq < 30))
|
||||
ten_diff_pl = 4; /* 0.4 *10 */
|
||||
else if ((log10_freq >= 11) && (log10_freq < 20))
|
||||
ten_diff_pl = 1; /* 0.1 *10 */
|
||||
else if ((log10_freq >= 8) && (log10_freq < 11))
|
||||
ten_diff_pl = 0; /* 0 *10 */
|
||||
else if ((log10_freq >= 4) && (log10_freq < 8))
|
||||
ten_diff_pl = -1; /* -0.1 * 10 */
|
||||
else if ((log10_freq >= 1) && (log10_freq < 4))
|
||||
ten_diff_pl = -4; /* -0.4 * 10 */
|
||||
|
||||
assoc_tx_pow = wlan_reg_get_channel_reg_power_for_freq(assoc_pdev,
|
||||
assoc_freq);
|
||||
tx_pow = wlan_reg_get_channel_reg_power_for_freq(pdev, ch_freq);
|
||||
|
||||
diff_txpow = tx_pow - assoc_tx_pow;
|
||||
|
||||
ten_derived_rssi = (diff_txpow * 10) - ten_diff_pl + (rssi * 10);
|
||||
derived_rssi = ten_derived_rssi / 10;
|
||||
|
||||
return derived_rssi;
|
||||
}
|
||||
|
||||
static void mlo_peer_calculate_avg_rssi(
|
||||
struct wlan_mlo_dev_context *ml_dev,
|
||||
struct wlan_mlo_peer_context *ml_peer,
|
||||
int8_t rssi,
|
||||
struct wlan_objmgr_vdev *assoc_vdev)
|
||||
{
|
||||
int32_t total_rssi = 0;
|
||||
uint8_t num_psocs = 0;
|
||||
uint8_t i;
|
||||
struct wlan_objmgr_vdev *vdev;
|
||||
|
||||
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
|
||||
vdev = ml_dev->wlan_vdev_list[i];
|
||||
if (!vdev)
|
||||
continue;
|
||||
|
||||
num_psocs++;
|
||||
if (vdev == assoc_vdev)
|
||||
total_rssi += rssi;
|
||||
else
|
||||
total_rssi += wlan_vdev_derive_link_rssi(vdev,
|
||||
assoc_vdev,
|
||||
rssi);
|
||||
}
|
||||
|
||||
ml_peer->avg_link_rssi = total_rssi / num_psocs;
|
||||
}
|
||||
|
||||
QDF_STATUS mlo_peer_allocate_primary_umac(
|
||||
struct wlan_mlo_dev_context *ml_dev,
|
||||
struct wlan_mlo_peer_context *ml_peer,
|
||||
@@ -122,6 +396,8 @@ QDF_STATUS mlo_peer_allocate_primary_umac(
|
||||
}
|
||||
|
||||
rssi = wlan_peer_get_rssi(assoc_peer);
|
||||
mlo_peer_calculate_avg_rssi(ml_dev, ml_peer, rssi,
|
||||
wlan_peer_get_vdev(assoc_peer));
|
||||
|
||||
mld_get_best_primary_umac_w_rssi(ml_peer, link_vdevs);
|
||||
|
||||
|
新增問題並參考
封鎖使用者