qcacmn: Add support for 6GHz scan priority algorithm

Add support for 6Ghz scan channel list priority algorithm.

Change-Id: I63b0ddf384c4bd62a6a25feb7dfe4f80b5f85fbe
CRs-Fixed: 2564949
This commit is contained in:
Sandeep Puligilla
2019-11-08 14:00:10 -08:00
committed by nshrivas
orang tua 76036f10e7
melakukan d763fee333
5 mengubah file dengan 447 tambahan dan 3 penghapusan

Melihat File

@@ -53,6 +53,174 @@
#include <wlan_objmgr_vdev_obj.h>
#include <wlan_dfs_utils_api.h>
/* MAX RNR entries per channel*/
#define WLAN_MAX_RNR_COUNT 15
struct channel_list_db rnr_channel_db;
#ifdef FEATURE_6G_SCAN_CHAN_SORT_ALGO
struct meta_rnr_channel *scm_get_chan_meta(uint32_t chan_freq)
{
int i;
for (i = 0; i <= MAX_6GHZ_CHANNEL; i++)
if (rnr_channel_db.channel[i].chan_freq == chan_freq)
return &rnr_channel_db.channel[i];
return NULL;
}
static void scm_add_rnr_channel_db(struct scan_cache_entry *entry)
{
uint32_t chan_freq;
uint8_t is_6g_bss, i;
struct meta_rnr_channel *channel;
struct rnr_bss_info *rnr_bss;
struct scan_rnr_node *rnr_node;
chan_freq = entry->channel.chan_freq;
is_6g_bss = wlan_reg_is_6ghz_chan_freq(chan_freq);
/* Return if the BSS is not 6G and RNR IE is not present */
if (!(is_6g_bss || entry->ie_list.rnrie))
return;
scm_debug("scan entry channel freq %d", chan_freq);
if (is_6g_bss) {
channel = scm_get_chan_meta(chan_freq);
if (channel) {
scm_debug("Failed to get chan Meta freq %d", chan_freq);
return;
}
channel->bss_beacon_probe_count++;
channel->beacon_probe_last_time_found = entry->scan_entry_time;
}
/*
* If scan entry got RNR IE then loop through all
* entries and increase the BSS count in respective channels
*/
if (!entry->ie_list.rnrie)
return;
for (i = 0; i < MAX_RNR_BSS; i++) {
rnr_bss = &entry->rnr.bss_info[i];
channel->bss_beacon_probe_count++;
/* Don't add RNR entry if list is full */
if (qdf_list_size(&channel->rnr_list) >= WLAN_MAX_RNR_COUNT)
continue;
/* Skip if entry is not valid */
if (!rnr_bss->channel_number)
continue;
rnr_node = qdf_mem_malloc(sizeof(struct scan_rnr_node));
if (!rnr_node)
return;
chan_freq = wlan_reg_chan_opclass_to_freq(rnr_bss->channel_number,
rnr_bss->operating_class,
false);
channel = scm_get_chan_meta(chan_freq);
if (!channel) {
scm_debug("Failed to get chan Meta freq %d", chan_freq);
qdf_mem_free(rnr_node);
return;
}
rnr_node->entry.timestamp = entry->scan_entry_time;
if (!qdf_is_macaddr_zero(&rnr_bss->bssid))
qdf_mem_copy(&rnr_node->entry.bssid,
&rnr_bss->bssid,
QDF_MAC_ADDR_SIZE);
if (rnr_bss->short_ssid)
rnr_node->entry.short_ssid = rnr_bss->short_ssid;
qdf_list_insert_back(&channel->rnr_list,
&rnr_node->node);
}
}
static void scm_del_rnr_channel_db(struct scan_cache_entry *entry)
{
uint32_t chan_freq;
uint8_t is_6g_bss, i;
struct meta_rnr_channel *channel;
struct rnr_bss_info *rnr_bss;
struct scan_rnr_node *rnr_node;
qdf_list_node_t *cur_node, *next_node;
chan_freq = entry->channel.chan_freq;
is_6g_bss = wlan_reg_is_6ghz_chan_freq(chan_freq);
/* Return if the BSS is not 6G and RNR IE is not present*/
if (!(is_6g_bss || entry->ie_list.rnrie))
return;
scm_debug("channel freq of scan entry %d", chan_freq);
if (is_6g_bss) {
channel = scm_get_chan_meta(chan_freq);
if (!channel) {
scm_debug("Failed to get chan Meta freq %d", chan_freq);
return;
}
channel->bss_beacon_probe_count--;
}
/*
* If scan entry got RNR IE then loop through all
* entries and decrease the BSS count in respective channels
*/
if (!entry->ie_list.rnrie)
return;
for (i = 0; i < MAX_RNR_BSS; i++) {
rnr_bss = &entry->rnr.bss_info[i];
/* Skip if entry is not valid */
if (!rnr_bss->channel_number)
continue;
chan_freq = wlan_reg_chan_opclass_to_freq(rnr_bss->channel_number,
rnr_bss->operating_class,
false);
channel = scm_get_chan_meta(chan_freq);
if (!channel) {
scm_debug("Failed to get chan Meta freq %d",
chan_freq);
return;
}
channel->bss_beacon_probe_count--;
qdf_list_peek_front(&channel->rnr_list, &cur_node);
/* Free the Node */
while (cur_node) {
qdf_list_peek_next(&channel->rnr_list, cur_node,
&next_node);
rnr_node = qdf_container_of(cur_node,
struct scan_rnr_node,
node);
if (qdf_is_macaddr_equal(&rnr_node->entry.bssid,
&rnr_bss->bssid)) {
qdf_list_remove_node(&channel->rnr_list,
&rnr_node->node);
qdf_mem_free(rnr_node);
} else if (rnr_node->entry.short_ssid ==
rnr_bss->short_ssid) {
qdf_list_remove_node(&channel->rnr_list,
&rnr_node->node);
qdf_mem_free(rnr_node);
}
cur_node = next_node;
next_node = NULL;
}
}
}
#else
struct meta_rnr_channel *scm_get_chan_meta(uint32_t channel_freq)
{
return NULL;
}
static void scm_add_rnr_channel_db(struct scan_cache_entry *entry)
{
}
static void scm_del_rnr_channel_db(struct scan_cache_entry *entry)
{
}
#endif
/**
* scm_del_scan_node() - API to remove scan node from the list
* @list: hash list
@@ -183,7 +351,7 @@ static void scm_scan_entry_del(struct scan_dbs *scan_db,
return;
}
scan_node->cookie = 0;
scm_del_rnr_channel_db(scan_node->entry);
scm_scan_entry_put_ref(scan_db, scan_node, false);
}
@@ -217,6 +385,7 @@ static void scm_add_scan_node(struct scan_dbs *scan_db,
qdf_list_insert_before(&scan_db->scan_hash_tbl[hash_idx],
&scan_node->node, &dup_node->node);
scm_add_rnr_channel_db(scan_node->entry);
scan_db->num_entries++;
}
@@ -1414,7 +1583,6 @@ QDF_STATUS scm_db_init(struct wlan_objmgr_psoc *psoc)
qdf_list_create(&scan_db->scan_hash_tbl[j],
MAX_SCAN_CACHE_SIZE);
}
return QDF_STATUS_SUCCESS;
}
@@ -1445,6 +1613,65 @@ QDF_STATUS scm_db_deinit(struct wlan_objmgr_psoc *psoc)
return QDF_STATUS_SUCCESS;
}
#ifdef FEATURE_6G_SCAN_CHAN_SORT_ALGO
QDF_STATUS scm_channel_list_db_init(struct wlan_objmgr_psoc *psoc)
{
uint8_t i, j = 0;
uint32_t min_freq, max_freq;
min_freq = wlan_reg_min_6ghz_chan_freq();
max_freq = wlan_reg_max_6ghz_chan_freq();
scm_debug("min_freq %d max_freq %d", min_freq, max_freq);
for (i = min_freq; i <= max_freq; i += 20, j++) {
rnr_channel_db.channel[j].chan_freq = i;
qdf_list_create(&rnr_channel_db.channel[j].rnr_list,
WLAN_MAX_RNR_COUNT);
scm_debug("freq %d", i);
}
return QDF_STATUS_SUCCESS;
}
QDF_STATUS scm_channel_list_db_deinit(struct wlan_objmgr_psoc *psoc)
{
int i;
qdf_list_node_t *cur_node, *next_node;
struct meta_rnr_channel *channel;
struct scan_rnr_node *rnr_node;
for (i = 0; i <= MAX_6GHZ_CHANNEL; i++) {
channel = &rnr_channel_db.channel[i];
channel->chan_freq = 0;
qdf_list_peek_front(&channel->rnr_list, &cur_node);
while (cur_node) {
qdf_list_peek_next(&channel->rnr_list, cur_node,
&next_node);
rnr_node = qdf_container_of(cur_node,
struct scan_rnr_node,
node);
qdf_list_remove_node(&channel->rnr_list,
&rnr_node->node);
qdf_mem_free(rnr_node);
cur_node = next_node;
next_node = NULL;
}
}
return QDF_STATUS_SUCCESS;
}
#else
QDF_STATUS scm_channel_list_db_init(struct wlan_objmgr_psoc *psoc)
{
return QDF_STATUS_SUCCESS;
}
QDF_STATUS scm_channel_list_db_deinit(struct wlan_objmgr_psoc *psoc)
{
return QDF_STATUS_SUCCESS;
}
#endif
QDF_STATUS scm_update_scan_mlme_info(struct wlan_objmgr_pdev *pdev,
struct scan_cache_entry *entry)
{

Melihat File

@@ -199,6 +199,30 @@ QDF_STATUS scm_db_init(struct wlan_objmgr_psoc *psoc);
*/
QDF_STATUS scm_db_deinit(struct wlan_objmgr_psoc *psoc);
/**
* scm_channel_list_db_init() - API to init scan list priority list db
* @psoc: psoc
*
* Return: QDF_STATUS
*/
QDF_STATUS scm_channel_list_db_init(struct wlan_objmgr_psoc *psoc);
/**
* scm_channel_list_db_deinit() - API to deinit scan list priority list db
* @psoc: psoc
*
* Return: QDF_STATUS
*/
QDF_STATUS scm_channel_list_db_deinit(struct wlan_objmgr_psoc *psoc);
/**
* scm_get_chan_meta() - API to return channel meta
* @freq: channel frequency
*
* Return: channel meta information
*/
struct meta_rnr_channel *scm_get_chan_meta(uint32_t freq);
/**
* scm_validate_scoring_config() - validate score config
* @score_cfg: config to be validated

Melihat File

@@ -36,6 +36,18 @@
#include <wlan_dfs_utils_api.h>
#include <wlan_scan_cfg.h>
/* Beacon/probe weightage multiplier */
#define BCN_PROBE_WEIGHTAGE 5
/* Saved profile weightage multiplier */
#define SAVED_PROFILE_WEIGHTAGE 10
/* maximum number of 6ghz hints can be sent per scan request */
#define MAX_HINTS_PER_SCAN_REQ 15
/* maximum number of hints can be sent per 6ghz channel */
#define MAX_HINTS_PER_CHANNEL 4
QDF_STATUS
scm_scan_free_scan_request_mem(struct scan_start_request *req)
{
@@ -899,6 +911,128 @@ scm_update_6ghz_channel_list(struct wlan_objmgr_vdev *vdev,
}
#endif
#ifdef FEATURE_6G_SCAN_CHAN_SORT_ALGO
static void scm_sort_6ghz_channel_list(struct wlan_objmgr_vdev *vdev,
struct chan_list *chan_list)
{
uint8_t i, j = 0, min, tmp_list_count;
struct meta_rnr_channel *channel;
struct chan_info temp_list[MAX_6GHZ_CHANNEL];
struct rnr_chan_weight *rnr_chan_info, *temp;
uint32_t weight;
rnr_chan_info = qdf_mem_malloc(sizeof(rnr_chan_info) * MAX_6GHZ_CHANNEL);
if (!rnr_chan_info)
return;
for (i = 0; i < chan_list->num_chan; i++) {
if (WLAN_REG_IS_6GHZ_CHAN_FREQ(chan_list->chan[i].freq))
temp_list[j++].freq = chan_list->chan[i].freq;
}
tmp_list_count = j;
scm_debug("Total 6ghz channels %d", tmp_list_count);
/* No Need to sort if the 6ghz channels are less than one */
if (tmp_list_count < 1) {
qdf_mem_free(rnr_chan_info);
return;
}
/* compute the weightage */
for (i = 0; i < tmp_list_count; i++) {
channel = scm_get_chan_meta(temp_list[i].freq);
weight = channel->bss_beacon_probe_count * BCN_PROBE_WEIGHTAGE +
channel->saved_profile_count * SAVED_PROFILE_WEIGHTAGE;
rnr_chan_info[i].weight = weight;
rnr_chan_info[i].chan_freq = temp_list[i].freq;
}
/* Sort the channel using selection sort */
for (i = 0; i < tmp_list_count - 1; i++) {
min = i;
for (j = i + 1; j < tmp_list_count; j++) {
if (rnr_chan_info[j].weight <
rnr_chan_info[min].weight) {
min = j;
}
}
if (min != i) {
qdf_mem_copy(&temp, &rnr_chan_info[min],
sizeof(*rnr_chan_info));
qdf_mem_copy(&rnr_chan_info[min], &rnr_chan_info[i],
sizeof(*rnr_chan_info));
qdf_mem_copy(&rnr_chan_info[i], &temp,
sizeof(*rnr_chan_info));
}
}
/* update the 6g list based on the weightage */
for (i = 0, j = 0;
(i < NUM_CHANNELS && j < NUM_6GHZ_CHANNELS); i++) {
if (wlan_reg_is_6ghz_chan_freq(chan_list->chan[i].freq))
chan_list->chan[i].freq = rnr_chan_info[j++].chan_freq;
}
qdf_mem_free(rnr_chan_info);
}
static void scm_update_rnr_info(struct scan_start_request *req)
{
uint8_t i, num_bssid = 0, num_ssid = 0;
uint8_t total_count = MAX_HINTS_PER_SCAN_REQ;
uint32_t freq;
struct meta_rnr_channel *chan;
qdf_list_node_t *cur_node, *next_node;
struct scan_rnr_node *rnr_node;
struct chan_list *chan_list;
if (!req)
return;
chan_list = &req->scan_req.chan_list;
for (i = 0; i < chan_list->num_chan; i++) {
freq = chan_list->chan[i].freq;
if (!wlan_reg_is_6ghz_chan_freq(freq))
continue;
chan = scm_get_chan_meta(freq);
if (qdf_list_empty(&chan->rnr_list))
continue;
qdf_list_peek_front(&chan->rnr_list, &cur_node);
while (cur_node && total_count) {
qdf_list_peek_next(&chan->rnr_list, cur_node,
&next_node);
rnr_node = qdf_container_of(cur_node,
struct scan_rnr_node,
node);
if (!qdf_is_macaddr_zero(&rnr_node->entry.bssid)) {
qdf_mem_copy(&req->scan_req.hint_bssid[num_bssid++].bssid,
&rnr_node->entry.bssid,
QDF_MAC_ADDR_SIZE);
req->scan_req.num_hint_bssid++;
total_count--;
} else if (rnr_node->entry.short_ssid) {
req->scan_req.hint_s_ssid[num_ssid++].short_ssid =
rnr_node->entry.short_ssid;
req->scan_req.num_hint_s_ssid++;
total_count--;
}
cur_node = next_node;
next_node = NULL;
}
}
}
#else
static void scm_sort_6ghz_channel_list(struct wlan_objmgr_vdev *vdev,
struct chan_list *chan_list)
{
}
static void scm_update_rnr_info(struct scan_start_request *req)
{
}
#endif
/**
* scm_update_channel_list() - update scan req params depending on dfs inis
* and initial scan request.
@@ -975,6 +1109,7 @@ scm_update_channel_list(struct scan_start_request *req,
req->scan_req.chan_list.num_chan = num_scan_channels;
scm_update_6ghz_channel_list(req->vdev, &req->scan_req.chan_list,
scan_obj);
scm_sort_6ghz_channel_list(req->vdev, &req->scan_req.chan_list);
scm_scan_chlist_concurrency_modify(req->vdev, req);
}
@@ -1105,6 +1240,7 @@ scm_scan_req_update_params(struct wlan_objmgr_vdev *vdev,
ucfg_scan_init_chanlist_params(req, 0, NULL, NULL);
scm_update_channel_list(req, scan_obj);
scm_update_rnr_info(req);
scm_debug("dwell time: active %d, passive %d, repeat_probe_time %d n_probes %d flags_ext %x, wide_bw_scan: %d priority: %d",
req->scan_req.dwell_time_active,
req->scan_req.dwell_time_passive,

Melihat File

@@ -35,7 +35,7 @@ typedef uint32_t wlan_scan_id;
#define WLAN_SCAN_MAX_HINT_S_SSID 10
#define WLAN_SCAN_MAX_HINT_BSSID 10
#define MAX_RNR_BSS 5
#define MAX_RNR_BSS 5
#define WLAN_SCAN_MAX_NUM_SSID 16
#define WLAN_SCAN_MAX_NUM_BSSID 4
@@ -1470,4 +1470,59 @@ enum ext_cap_bit_field {
OBSS_NARROW_BW_RU_IN_ULOFDMA_TOLERENT_SUPPORT = 79,
};
/**
* scan_rnr_info - RNR information
* @timestamp: time stamp of beacon/probe
* @short_ssid: Short SSID
* @bssid: BSSID
*/
struct scan_rnr_info {
qdf_time_t timestamp;
uint32_t short_ssid;
struct qdf_mac_addr bssid;
};
/**
* struct scan_rnr_node - Scan RNR entry node
* @node: node pointers
* @entry: scan RNR entry pointer
*/
struct scan_rnr_node {
qdf_list_node_t node;
struct scan_rnr_info entry;
};
/**
* meta_rnr_channel - Channel information for scan priority algorithm
* @chan_freq: channel frequency
* @bss_beacon_probe_count: Beacon and probe request count
* @saved_profile_count: Saved profile count
* @beacon_probe_last_time_found: Timestamp of beacon/probe observed
* @rnr_list: RNR list to store RNR IE information
*/
struct meta_rnr_channel {
uint32_t chan_freq;
uint32_t bss_beacon_probe_count;
uint32_t saved_profile_count;
qdf_time_t beacon_probe_last_time_found;
qdf_list_t rnr_list;
};
/**
* channel_list_db - Database for channel information
* @channel: channel meta information
*/
struct channel_list_db {
struct meta_rnr_channel channel[NUM_6GHZ_CHANNELS];
};
/**
* rnr_chan_weight - RNR channel weightage
* @chan_freq: channel frequency
* @weight: weightage of the channel
*/
struct rnr_chan_weight {
uint32_t chan_freq;
uint32_t weight;
};
#endif

Melihat File

@@ -1643,6 +1643,7 @@ ucfg_scan_psoc_open(struct wlan_objmgr_psoc *psoc)
qdf_spinlock_create(&scan_obj->lock);
ucfg_scan_register_pmo_handler();
scm_db_init(psoc);
scm_channel_list_db_init(psoc);
return QDF_STATUS_SUCCESS;
}
@@ -1666,6 +1667,7 @@ ucfg_scan_psoc_close(struct wlan_objmgr_psoc *psoc)
ucfg_scan_unregister_pmo_handler();
qdf_spinlock_destroy(&scan_obj->lock);
wlan_scan_global_deinit(psoc);
scm_channel_list_db_deinit(psoc);
return QDF_STATUS_SUCCESS;
}