From 7b59903d414f0e2fab3b385545624e9dee07ed11 Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Fri, 10 Nov 2017 14:42:31 +0530 Subject: [PATCH] qcacmn: Update new scoring logic with configurable user value Adds new scoring logic with configurable user value Change-Id: Ie8c051a3f380930d8a7951617b27aa8f8187619b CRs-Fixed: 2144588 --- .../cmn_defs/inc/wlan_cmn_ieee80211.h | 78 ++ umac/scan/core/src/wlan_scan_cache_db.h | 40 +- umac/scan/core/src/wlan_scan_cache_db_i.h | 28 +- umac/scan/core/src/wlan_scan_cache_db_ops.c | 895 ++++++++++++++---- umac/scan/core/src/wlan_scan_main.h | 1 + .../dispatcher/inc/wlan_scan_public_structs.h | 181 +++- .../scan/dispatcher/inc/wlan_scan_utils_api.h | 15 + umac/scan/dispatcher/src/wlan_scan_ucfg_api.c | 8 +- .../scan/dispatcher/src/wlan_scan_utils_api.c | 7 + 9 files changed, 981 insertions(+), 272 deletions(-) diff --git a/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h b/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h index 527f866dcb..c5491a8980 100644 --- a/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h +++ b/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h @@ -31,6 +31,10 @@ #define P2P_WFA_VER 0x09 #define WSC_OUI 0x0050f204 +#define MBO_OCE_OUI 0x506f9a16 +#define MBO_OCE_OUI_SIZE 4 +#define REDUCED_WAN_METRICS_ATTR 103 + /* WCN IE */ /* Microsoft OUI */ #define WCN_OUI 0xf25000 @@ -997,6 +1001,17 @@ struct wlan_esp_ie { struct wlan_esp_info esp_info_AC_VI; struct wlan_esp_info esp_info_AC_VO; } qdf_packed; + +/** + * struct oce_reduced_wan_metrics: struct for oce wan metrics + * @downlink_av_cap: Download available capacity + * @uplink_av_cap: Upload available capacity + */ +struct oce_reduced_wan_metrics { + uint8_t downlink_av_cap:4; + uint8_t uplink_av_cap:4; +}; + /** * is_wpa_oui() - If vendor IE is WPA type * @frm: vendor IE pointer @@ -1026,6 +1041,20 @@ is_wps_oui(const uint8_t *frm) return frm[1] > 3 && BE_READ_4(frm + 2) == WSC_OUI; } +/** + * is_mbo_oce_oui() - If vendor IE is MBO/OCE type + * @frm: vendor IE pointer + * + * API to check if vendor IE is MBO/OCE + * + * Return: true if its MBO/OCE IE + */ +static inline bool +is_mbo_oce_oui(const uint8_t *frm) +{ + return frm[1] > 3 && BE_READ_4(frm + 2) == MBO_OCE_OUI; +} + /** * is_wcn_oui() - If vendor IE is WCN type * @frm: vendor IE pointer @@ -1474,4 +1503,53 @@ static inline void wlan_parse_wapi_ie(uint8_t *wapi_ie, wapi->mc_cipher_suite = LE_READ_4(ie); } +/** + * wlan_parse_oce_reduced_wan_metrics_ie() - parse oce wan metrics + * @mbo_oce_ie: MBO/OCE ie ptr + * @wan_metrics: out structure for the reduced wan metric + * + * API, function to parse reduced wan metric + * + * Return: true if oce wan metrics is present + */ +static inline bool +wlan_parse_oce_reduced_wan_metrics_ie(uint8_t *mbo_oce_ie, + struct oce_reduced_wan_metrics *wan_metrics) +{ + uint8_t len, attribute_len, attribute_id; + uint8_t *ie; + + if (!mbo_oce_ie) + return false; + + ie = mbo_oce_ie; + len = ie[1]; + ie += 2; + + if (len <= MBO_OCE_OUI_SIZE) + return false; + + ie += MBO_OCE_OUI_SIZE; + len -= MBO_OCE_OUI_SIZE; + + while (len > 2) { + attribute_id = ie[0]; + attribute_len = ie[1]; + len -= 2; + if (attribute_len > len) + return false; + + if (attribute_id == REDUCED_WAN_METRICS_ATTR) { + wan_metrics->downlink_av_cap = ie[2] & 0xff; + wan_metrics->uplink_av_cap = ie[2] >> 4; + return true; + } + + ie += (attribute_len + 2); + len -= attribute_len; + } + + return false; +} + #endif /* _WLAN_CMN_IEEE80211_DEFS_H_ */ diff --git a/umac/scan/core/src/wlan_scan_cache_db.h b/umac/scan/core/src/wlan_scan_cache_db.h index a250313d19..931bd25182 100644 --- a/umac/scan/core/src/wlan_scan_cache_db.h +++ b/umac/scan/core/src/wlan_scan_cache_db.h @@ -33,36 +33,7 @@ #define SCAN_GET_HASH(addr) \ (((const uint8_t *)(addr))[QDF_MAC_ADDR_SIZE - 1] % SCAN_HASH_SIZE) -#define RSSI_THRESHOLD_5GHZ -70 -#define BEST_CANDIDATE_RSSI_WEIGHT 50 -#define MIN_RSSI (-100) -#define MAX_RSSI 0 -#define ROAM_MAX_CHANNEL_WEIGHT 100 -#define MAX_CHANNEL_UTILIZATION 100 -#define NSS_1X1_WEIGHTAGE 3 -#define MAX_ESTIMATED_AIR_TIME_FRACTION 255 -#define MAX_AP_LOAD 255 - -#define LOW_CHANNEL_CONGESTION_WEIGHT 500 -#define MODERATE_CHANNEL_CONGESTION_WEIGHT 370 -#define CONSIDERABLE_CHANNEL_CONGESTION_WEIGHT 250 -#define HIGH_CHANNEL_CONGESTION_WEIGHT 120 - -#define LOW_CHANNEL_CONGESTION 0 -#define MODERATE_CHANNEL_CONGESTION 25 -#define CONSIDERABLE_CHANNEL_CONGESTION 50 -#define HIGH_CHANNEL_CONGESTION 75 -#define EXTREME_CHANNEL_CONGESTION 100 - -#define EXCELLENT_RSSI -55 -#define BAD_RSSI -80 -#define EXCELLENT_RSSI_WEIGHT 100 -#define RSSI_BUCKET 5 -#define RSSI_WEIGHT_BUCKET 250 - -#define BEST_CANDIDATE_80MHZ 100 -#define BEST_CANDIDATE_40MHZ 70 -#define BEST_CANDIDATE_20MHZ 30 +#define SCM_PCL_RSSI_THRESHOLD -75 #define BEST_CANDIDATE_MAX_BSS_SCORE 10000 /** @@ -213,4 +184,13 @@ QDF_STATUS scm_db_init(struct wlan_objmgr_psoc *psoc); * Return: QDF_STATUS */ QDF_STATUS scm_db_deinit(struct wlan_objmgr_psoc *psoc); + +/** + * scm_validate_scoring_config() - validate score config + * @score_cfg: config to be validated + * + * Return: void + */ +void scm_validate_scoring_config( + struct scoring_config *score_cfg); #endif diff --git a/umac/scan/core/src/wlan_scan_cache_db_i.h b/umac/scan/core/src/wlan_scan_cache_db_i.h index a2a4a51b0f..b234257936 100644 --- a/umac/scan/core/src/wlan_scan_cache_db_i.h +++ b/umac/scan/core/src/wlan_scan_cache_db_i.h @@ -53,37 +53,11 @@ bool scm_filter_match(struct wlan_objmgr_psoc *psoc, bool scm_is_better_bss(struct scan_default_params *params, struct scan_cache_entry *bss1, struct scan_cache_entry *bss2); -/** - * scm_derive_prefer_value_from_rssi() - to derive prefer value - * @params: scan params - * @filter: filter - * @rssi: RSSI of the BSS - * - * This routine will derive preferred value from given rssi - * - * Return: value between 0 to 14 - */ -static inline int -scm_derive_prefer_value_from_rssi(struct scan_default_params *params, - int rssi) -{ - int i = SCM_NUM_RSSI_CAT - 1, pref_val = 0; - - while (i >= 0) { - if (rssi >= params->rssi_cat[i]) { - pref_val = params->bss_prefer_val[i]; - break; - } - i--; - }; - - return pref_val; -} /** * scm_calculate_bss_score() - calculate BSS score used to get * the preference - * psoc: psoc ptr; + * @psoc: psoc ptr; * @params: scan params * @entry: scan entry for which score needs to be calculated * @pcl_chan_weight: weight for pcl channel diff --git a/umac/scan/core/src/wlan_scan_cache_db_ops.c b/umac/scan/core/src/wlan_scan_cache_db_ops.c index 72f90dce2b..4d1b630e77 100644 --- a/umac/scan/core/src/wlan_scan_cache_db_ops.c +++ b/umac/scan/core/src/wlan_scan_cache_db_ops.c @@ -25,205 +25,766 @@ #include "wlan_scan_cache_db.h" #include "wlan_scan_main.h" #include "wlan_scan_cache_db_i.h" +#ifdef WLAN_POLICY_MGR_ENABLE +#include "wlan_policy_mgr_api.h" +#endif + +#define SCM_20MHZ_BW_INDEX 0 +#define SCM_40MHZ_BW_INDEX 1 +#define SCM_80MHZ_BW_INDEX 2 +#define SCM_160MHZ_BW_INDEX 3 +#define SCM_MAX_BW_INDEX 4 + +#define SCM_NSS_1x1_INDEX 0 +#define SCM_NSS_2x2_INDEX 1 +#define SCM_NSS_3x3_INDEX 2 +#define SCM_NSS_4x4_INDEX 3 +#define SCM_MAX_NSS_INDEX 4 + +#define SCM_BAND_2G_INDEX 0 +#define SCM_BAND_5G_INDEX 1 +/* 2 and 3 are reserved */ +#define SCM_MAX_BAND_INDEX 4 + +#define SCM_SCORE_INDEX_0 0 +#define SCM_SCORE_INDEX_3 3 +#define SCM_SCORE_INDEX_7 7 +#define SCM_SCORE_OFFSET_INDEX_7_4 4 +#define SCM_SCORE_INDEX_11 11 +#define SCM_SCORE_OFFSET_INDEX_11_8 8 +#define SCM_SCORE_MAX_INDEX 15 +#define SCM_SCORE_OFFSET_INDEX_15_12 12 + +#define SCM_MAX_OCE_WAN_DL_CAP 16 + +#define SCM_MAX_CHANNEL_WEIGHT 100 +#define SCM_MAX_CHANNEL_UTILIZATION 100 +#define SCM_MAX_ESTIMATED_AIR_TIME_FRACTION 255 +#define MAX_AP_LOAD 255 + +#define SCM_MAX_OCE_WAN_DL_CAP 16 + +#define SCM_MAX_WEIGHT_OF_PCL_CHANNELS 255 +#define SCM_PCL_GROUPS_WEIGHT_DIFFERENCE 20 bool scm_is_better_bss(struct scan_default_params *params, struct scan_cache_entry *bss1, struct scan_cache_entry *bss2) { - bool ret; if (bss1->bss_score > bss2->bss_score) - ret = true; - else - ret = false; - return ret; + return true; + else if (bss1->bss_score == bss2->bss_score) + if (bss1->rssi_raw > bss2->rssi_raw) + return true; + + return false; +} + +/** + * scm_limit_max_per_index_score() -check if per index score does not exceed + * 100% (0x64). If it exceed make it 100% + * + * @per_index_score: per_index_score as input + * + * Return: per_index_score within the max limit + */ +static uint32_t scm_limit_max_per_index_score(uint32_t per_index_score) +{ + uint8_t i, score; + + for (i = 0; i < MAX_INDEX_PER_INI; i++) { + score = WLAN_GET_SCORE_PERCENTAGE(per_index_score, i); + if (score > MAX_INDEX_SCORE) + WLAN_SET_SCORE_PERCENTAGE(per_index_score, + MAX_INDEX_SCORE, i); + } + + return per_index_score; +} + +void scm_validate_scoring_config(struct scoring_config *score_cfg) +{ + int total_weight; + + total_weight = score_cfg->weight_cfg.rssi_weightage + + score_cfg->weight_cfg.ht_caps_weightage + + score_cfg->weight_cfg.vht_caps_weightage + + score_cfg->weight_cfg.chan_width_weightage + + score_cfg->weight_cfg.chan_band_weightage + + score_cfg->weight_cfg.nss_weightage + + score_cfg->weight_cfg.beamforming_cap_weightage + + score_cfg->weight_cfg.pcl_weightage + + score_cfg->weight_cfg.channel_congestion_weightage + + score_cfg->weight_cfg.oce_wan_weightage; + + if (total_weight > BEST_CANDIDATE_MAX_WEIGHT) { + + scm_err("total weight is greater than %d fallback to default values", + BEST_CANDIDATE_MAX_WEIGHT); + + score_cfg->weight_cfg.rssi_weightage = RSSI_WEIGHTAGE; + score_cfg->weight_cfg.ht_caps_weightage = + HT_CAPABILITY_WEIGHTAGE; + score_cfg->weight_cfg.vht_caps_weightage = VHT_CAP_WEIGHTAGE; + score_cfg->weight_cfg.chan_width_weightage = + CHAN_WIDTH_WEIGHTAGE; + score_cfg->weight_cfg.chan_band_weightage = + CHAN_BAND_WEIGHTAGE; + score_cfg->weight_cfg.nss_weightage = NSS_WEIGHTAGE; + score_cfg->weight_cfg.beamforming_cap_weightage = + BEAMFORMING_CAP_WEIGHTAGE; + score_cfg->weight_cfg.pcl_weightage = PCL_WEIGHT; + score_cfg->weight_cfg.channel_congestion_weightage = + CHANNEL_CONGESTION_WEIGHTAGE; + score_cfg->weight_cfg.oce_wan_weightage = OCE_WAN_WEIGHTAGE; + } + + score_cfg->bandwidth_weight_per_index = + scm_limit_max_per_index_score( + score_cfg->bandwidth_weight_per_index); + score_cfg->nss_weight_per_index = + scm_limit_max_per_index_score(score_cfg->nss_weight_per_index); + score_cfg->band_weight_per_index = + scm_limit_max_per_index_score(score_cfg->band_weight_per_index); + + + score_cfg->esp_qbss_scoring.score_pcnt3_to_0 = + scm_limit_max_per_index_score( + score_cfg->esp_qbss_scoring.score_pcnt3_to_0); + score_cfg->esp_qbss_scoring.score_pcnt7_to_4 = + scm_limit_max_per_index_score( + score_cfg->esp_qbss_scoring.score_pcnt7_to_4); + score_cfg->esp_qbss_scoring.score_pcnt11_to_8 = + scm_limit_max_per_index_score( + score_cfg->esp_qbss_scoring.score_pcnt11_to_8); + score_cfg->esp_qbss_scoring.score_pcnt15_to_12 = + scm_limit_max_per_index_score( + score_cfg->esp_qbss_scoring.score_pcnt15_to_12); + + score_cfg->oce_wan_scoring.score_pcnt3_to_0 = + scm_limit_max_per_index_score( + score_cfg->oce_wan_scoring.score_pcnt3_to_0); + score_cfg->oce_wan_scoring.score_pcnt7_to_4 = + scm_limit_max_per_index_score( + score_cfg->oce_wan_scoring.score_pcnt7_to_4); + score_cfg->oce_wan_scoring.score_pcnt11_to_8 = + scm_limit_max_per_index_score( + score_cfg->oce_wan_scoring.score_pcnt11_to_8); + score_cfg->oce_wan_scoring.score_pcnt15_to_12 = + scm_limit_max_per_index_score( + score_cfg->oce_wan_scoring.score_pcnt15_to_12); } + +/** + * scm_get_rssi_pcnt_for_slot () - calculate rssi % score based on the slot + * index between the high rssi and low rssi threshold + * @high_rssi_threshold: High rssi of the window + * @low_rssi_threshold: low rssi of the window + * @high_rssi_pcnt: % score for the high rssi + * @low_rssi_pcnt: %score for the low rssi + * @bucket_size: bucket size of the window + * @bss_rssi: Input rssi for which value need to be calculated + * + * Return : rssi pct to use for the given rssi + */ +static inline +int8_t scm_get_rssi_pcnt_for_slot(int32_t high_rssi_threshold, + int32_t low_rssi_threshold, uint32_t high_rssi_pcnt, + uint32_t low_rssi_pcnt, uint32_t bucket_size, int8_t bss_rssi) +{ + int8_t slot_index, slot_size, rssi_diff, num_slot, rssi_pcnt; + + num_slot = ((high_rssi_threshold - + low_rssi_threshold) / bucket_size) + 1; + slot_size = ((high_rssi_pcnt - low_rssi_pcnt) + + (num_slot / 2)) / (num_slot); + rssi_diff = high_rssi_threshold - bss_rssi; + slot_index = (rssi_diff / bucket_size) + 1; + rssi_pcnt = high_rssi_pcnt - (slot_size * slot_index); + if (rssi_pcnt < low_rssi_pcnt) + rssi_pcnt = low_rssi_pcnt; + + scm_debug("Window %d -> %d pcnt range %d -> %d bucket_size %d bss_rssi %d num_slot %d slot_size %d rssi_diff %d slot_index %d rssi_pcnt %d", + high_rssi_threshold, low_rssi_threshold, high_rssi_pcnt, + low_rssi_pcnt, bucket_size, bss_rssi, num_slot, slot_size, + rssi_diff, slot_index, rssi_pcnt); + + return rssi_pcnt; +} + +/** + * scm_calculate_rssi_score () - Calculate RSSI score based on AP RSSI + * @score_param: rssi score params + * @rssi: rssi of the AP + * @rssi_weightage: rssi_weightage out of total weightage + * + * Return : rssi score + */ +static int32_t scm_calculate_rssi_score( + struct rssi_cfg_score *score_param, + int32_t rssi, uint8_t rssi_weightage) +{ + int8_t rssi_pcnt; + int32_t total_rssi_score; + int32_t best_rssi_threshold; + int32_t good_rssi_threshold; + int32_t bad_rssi_threshold; + uint32_t good_rssi_pcnt; + uint32_t bad_rssi_pcnt; + uint32_t good_bucket_size; + uint32_t bad_bucket_size; + + best_rssi_threshold = score_param->best_rssi_threshold*(-1); + good_rssi_threshold = score_param->good_rssi_threshold*(-1); + bad_rssi_threshold = score_param->bad_rssi_threshold*(-1); + good_rssi_pcnt = score_param->good_rssi_pcnt; + bad_rssi_pcnt = score_param->bad_rssi_pcnt; + good_bucket_size = score_param->good_rssi_bucket_size; + bad_bucket_size = score_param->bad_rssi_bucket_size; + + total_rssi_score = (BEST_CANDIDATE_MAX_WEIGHT * rssi_weightage); + + /* + * If RSSI is better than the best rssi threshold then it return full + * score. + */ + if (rssi > best_rssi_threshold) + return total_rssi_score; + /* + * If RSSI is less or equal to bad rssi threshold then it return + * least score. + */ + if (rssi <= bad_rssi_threshold) + return (total_rssi_score * bad_rssi_pcnt) / 100; + + /* RSSI lies between best to good rssi threshold */ + if (rssi > good_rssi_threshold) + rssi_pcnt = scm_get_rssi_pcnt_for_slot(best_rssi_threshold, + good_rssi_threshold, 100, good_rssi_pcnt, + good_bucket_size, rssi); + else + rssi_pcnt = scm_get_rssi_pcnt_for_slot(good_rssi_threshold, + bad_rssi_threshold, good_rssi_pcnt, + bad_rssi_pcnt, bad_bucket_size, + rssi); + + return (total_rssi_score * rssi_pcnt) / 100; + +} + +/** + * scm_calculate_pcl_score () - Calculate PCL score based on PCL weightage + * @pcl_chan_weight: pcl weight of BSS channel + * @pcl_weightage: PCL _weightage out of total weightage + * + * Return : pcl score + */ +static int32_t scm_calculate_pcl_score(int pcl_chan_weight, + uint8_t pcl_weightage) +{ + int32_t pcl_score = 0; + int32_t temp_pcl_chan_weight = 0; + + if (pcl_chan_weight) { + temp_pcl_chan_weight = + (SCM_MAX_WEIGHT_OF_PCL_CHANNELS - pcl_chan_weight); + temp_pcl_chan_weight = qdf_do_div(temp_pcl_chan_weight, + SCM_PCL_GROUPS_WEIGHT_DIFFERENCE); + pcl_score = pcl_weightage - temp_pcl_chan_weight; + if (pcl_score < 0) + pcl_score = 0; + } + return pcl_score * BEST_CANDIDATE_MAX_WEIGHT; + +} + +/** + * scm_rssi_is_same_bucket () - check if both rssi fall in same bucket + * @rssi_top_thresh: high rssi threshold of the the window + * @low_rssi_threshold: low rssi of the window + * @rssi_ref1: rssi ref one + * @rssi_ref2: rssi ref two + * @bucket_size: bucket size of the window + * + * Return : true if both fall in same window + */ +static inline bool scm_rssi_is_same_bucket(int8_t rssi_top_thresh, + int8_t rssi_ref1, int8_t rssi_ref2, int8_t bucket_size) +{ + int8_t rssi_diff1 = 0; + int8_t rssi_diff2 = 0; + + rssi_diff1 = rssi_top_thresh - rssi_ref1; + rssi_diff2 = rssi_top_thresh - rssi_ref2; + + return (rssi_diff1 / bucket_size) == (rssi_diff2 / bucket_size); +} + +/** + * scm_roam_calculate_prorated_pcnt_by_rssi () - Calculate prorated RSSI score + * based on AP RSSI. This will be used to determine HT VHT score + * @score_param: rssi score params + * @rssi: bss rssi + * @rssi_weightage: rssi_weightage out of total weightage + * + * If rssi is greater than good threshold return 100, if less than bad return 0, + * if between good and bad, return prorated rssi score for the index. + * + * Return : rssi prorated score + */ +static int8_t scm_roam_calculate_prorated_pcnt_by_rssi( + struct rssi_cfg_score *score_param, + int32_t rssi, uint8_t rssi_weightage) +{ + int32_t good_rssi_threshold; + int32_t bad_rssi_threshold; + int8_t rssi_pref_5g_rssi_thresh; + bool same_bucket; + + good_rssi_threshold = score_param->good_rssi_threshold * (-1); + bad_rssi_threshold = score_param->bad_rssi_threshold * (-1); + rssi_pref_5g_rssi_thresh = score_param->rssi_pref_5g_rssi_thresh * (-1); + + /* If RSSI is greater than good rssi return full weight */ + if (rssi > good_rssi_threshold) + return BEST_CANDIDATE_MAX_WEIGHT; + + same_bucket = scm_rssi_is_same_bucket(good_rssi_threshold, + rssi, rssi_pref_5g_rssi_thresh, + score_param->bad_rssi_bucket_size); + if (same_bucket || (rssi < rssi_pref_5g_rssi_thresh)) + return 0; + /* If RSSI is less or equal to bad rssi threshold then it return 0 */ + if (rssi <= bad_rssi_threshold) + return 0; + + /* If RSSI is between good and bad threshold */ + return scm_get_rssi_pcnt_for_slot(good_rssi_threshold, + bad_rssi_threshold, + score_param->good_rssi_pcnt, + score_param->bad_rssi_pcnt, + score_param->bad_rssi_bucket_size, + rssi); +} + +/** + * scm_calculate_bandwidth_score () - Calculate BW score + * @entry: scan entry + * @score_config: scoring config + * @prorated_pct: prorated % to return dependent on RSSI + * + * Return : bw score + */ +static int32_t scm_calculate_bandwidth_score( + struct scan_cache_entry *entry, + struct scoring_config *score_config, uint8_t prorated_pct) +{ + uint32_t score; + int32_t bw_weight_per_idx; + uint8_t cbmode = 0; + uint8_t ch_width_index; + bool is_vht; + + bw_weight_per_idx = score_config->bandwidth_weight_per_index; + + if (WLAN_CHAN_IS_2GHZ(entry->channel.chan_idx)) { + cbmode = score_config->cb_mode_24G; + if (score_config->vht_24G_cap) + is_vht = true; + } else if (score_config->vht_cap) { + is_vht = true; + cbmode = score_config->cb_mode_5G; + } + + if (entry->phy_mode == WLAN_PHYMODE_11AC_VHT80_80 || + entry->phy_mode == WLAN_PHYMODE_11AC_VHT160) + ch_width_index = SCM_160MHZ_BW_INDEX; + else if (entry->phy_mode == WLAN_PHYMODE_11AC_VHT80) + ch_width_index = SCM_80MHZ_BW_INDEX; + else if (entry->phy_mode == WLAN_PHYMODE_11NA_HT40PLUS || + entry->phy_mode == WLAN_PHYMODE_11NA_HT40MINUS || + entry->phy_mode == WLAN_PHYMODE_11NG_HT40PLUS || + entry->phy_mode == WLAN_PHYMODE_11NG_HT40MINUS || + entry->phy_mode == WLAN_PHYMODE_11NG_HT40 || + entry->phy_mode == WLAN_PHYMODE_11NA_HT40 || + entry->phy_mode == WLAN_PHYMODE_11AC_VHT40PLUS || + entry->phy_mode == WLAN_PHYMODE_11AC_VHT40MINUS || + entry->phy_mode == WLAN_PHYMODE_11AC_VHT40) + ch_width_index = SCM_40MHZ_BW_INDEX; + else + ch_width_index = SCM_20MHZ_BW_INDEX; + + + if (!score_config->ht_cap && ch_width_index > SCM_20MHZ_BW_INDEX) + ch_width_index = SCM_20MHZ_BW_INDEX; + + if (!is_vht && ch_width_index > SCM_40MHZ_BW_INDEX) + ch_width_index = SCM_40MHZ_BW_INDEX; + + if (cbmode && ch_width_index > SCM_20MHZ_BW_INDEX) + score = WLAN_GET_SCORE_PERCENTAGE(bw_weight_per_idx, + ch_width_index); + else + score = WLAN_GET_SCORE_PERCENTAGE(bw_weight_per_idx, + SCM_20MHZ_BW_INDEX); + + return (prorated_pct * score * + score_config->weight_cfg.chan_width_weightage) / + BEST_CANDIDATE_MAX_WEIGHT; +} + +/** + * scm_get_score_for_index () - get score for the given index + * @index: index for which we need the score + * @weightage: weigtage for the param + * @score: per slot score + * + * Return : score for the index + */ +static int32_t scm_get_score_for_index(uint8_t index, + uint8_t weightage, struct per_slot_scoring *score) +{ + if (index <= SCM_SCORE_INDEX_3) + return weightage * WLAN_GET_SCORE_PERCENTAGE( + score->score_pcnt3_to_0, + index); + else if (index <= SCM_SCORE_INDEX_7) + return weightage * WLAN_GET_SCORE_PERCENTAGE( + score->score_pcnt7_to_4, + index - SCM_SCORE_OFFSET_INDEX_7_4); + else if (index <= SCM_SCORE_INDEX_11) + return weightage * WLAN_GET_SCORE_PERCENTAGE( + score->score_pcnt11_to_8, + index - SCM_SCORE_OFFSET_INDEX_11_8); + else + return weightage * WLAN_GET_SCORE_PERCENTAGE( + score->score_pcnt15_to_12, + index - SCM_SCORE_OFFSET_INDEX_15_12); +} + +/** + * scm_calculate_congestion_score () - Calculate congestion score + * @entry: bss information + * @score_params: bss score params + * + * Return : congestion score + */ +static int32_t scm_calculate_congestion_score( + struct scan_cache_entry *entry, + struct scoring_config *score_params) +{ + uint32_t ap_load = 0; + uint32_t est_air_time_percentage = 0; + uint32_t congestion = 0; + uint32_t window_size; + uint8_t index; + int32_t good_rssi_threshold; + + if (!score_params->esp_qbss_scoring.num_slot) + return 0; + + if (score_params->esp_qbss_scoring.num_slot > + SCM_SCORE_MAX_INDEX) + score_params->esp_qbss_scoring.num_slot = + SCM_SCORE_MAX_INDEX; + + good_rssi_threshold = + score_params->rssi_score.good_rssi_threshold * (-1); + + /* For bad zone rssi get score from last index */ + if (entry->rssi_raw < good_rssi_threshold) + return scm_get_score_for_index( + score_params->esp_qbss_scoring.num_slot, + score_params->weight_cfg. + channel_congestion_weightage, + &score_params->esp_qbss_scoring); + + if (entry->air_time_fraction) { + /* Convert 0-255 range to percentage */ + est_air_time_percentage = + entry->air_time_fraction * + SCM_MAX_CHANNEL_WEIGHT; + est_air_time_percentage = + qdf_do_div(est_air_time_percentage, + SCM_MAX_ESTIMATED_AIR_TIME_FRACTION); + /* + * Calculate channel congestion from estimated air time + * fraction. + */ + congestion = SCM_MAX_CHANNEL_UTILIZATION - + est_air_time_percentage; + } else if (entry->qbss_chan_load) { + ap_load = (entry->qbss_chan_load * + BEST_CANDIDATE_MAX_WEIGHT); + /* + * Calculate ap_load in % from qbss channel load from + * 0-255 range + */ + congestion = qdf_do_div(ap_load, MAX_AP_LOAD); + } else { + return score_params->weight_cfg.channel_congestion_weightage * + WLAN_GET_SCORE_PERCENTAGE( + score_params->esp_qbss_scoring.score_pcnt3_to_0, + SCM_SCORE_INDEX_0); + } + + window_size = BEST_CANDIDATE_MAX_WEIGHT / + score_params->esp_qbss_scoring.num_slot; + + /* Desired values are from 1 to 15, as 0 is for not present. so do +1 */ + index = qdf_do_div(congestion, window_size) + 1; + + if (index > score_params->esp_qbss_scoring.num_slot) + index = score_params->esp_qbss_scoring.num_slot; + + return scm_get_score_for_index(index, score_params->weight_cfg. + channel_congestion_weightage, + &score_params->esp_qbss_scoring); +} + +/** + * scm_calculate_nss_score () - Calculate congestion score + * @psoc: psoc ptr + * @score_config: scoring config + * @ap_nss: ap nss + * @prorated_pct: prorated % to return dependent on RSSI + * + * Return : nss score + */ +static int32_t scm_calculate_nss_score(struct wlan_objmgr_psoc *psoc, + struct scoring_config *score_config, uint8_t ap_nss, + uint8_t prorated_pct) +{ + uint8_t nss; + uint8_t score_pct; + uint8_t sta_nss; + + sta_nss = score_config->nss; + +#ifdef WLAN_POLICY_MGR_ENABLE + if (policy_mgr_is_current_hwmode_dbs(psoc)) + sta_nss--; +#endif + nss = ap_nss; + if (sta_nss < nss) + nss = sta_nss; + + if (nss == 4) + score_pct = WLAN_GET_SCORE_PERCENTAGE( + score_config->nss_weight_per_index, + SCM_NSS_4x4_INDEX); + else if (nss == 3) + score_pct = WLAN_GET_SCORE_PERCENTAGE( + score_config->nss_weight_per_index, + SCM_NSS_3x3_INDEX); + else if (nss == 2) + score_pct = WLAN_GET_SCORE_PERCENTAGE( + score_config->nss_weight_per_index, + SCM_NSS_2x2_INDEX); + else + score_pct = WLAN_GET_SCORE_PERCENTAGE( + score_config->nss_weight_per_index, + SCM_NSS_1x1_INDEX); + + return (score_config->weight_cfg.nss_weightage * score_pct * + prorated_pct) / BEST_CANDIDATE_MAX_WEIGHT; +} + +/** + * scm_calculate_oce_wan_score () - Calculate oce wan score + * @entry: bss information + * @score_params: bss score params + * + * Return : oce wan score + */ +static int32_t scm_calculate_oce_wan_score( + struct scan_cache_entry *entry, + struct scoring_config *score_params) +{ + uint32_t window_size; + uint8_t index; + struct oce_reduced_wan_metrics wan_metrics; + uint8_t *mbo_oce_ie; + + if (!score_params->oce_wan_scoring.num_slot) + return 0; + + if (score_params->oce_wan_scoring.num_slot > + SCM_SCORE_MAX_INDEX) + score_params->oce_wan_scoring.num_slot = + SCM_SCORE_MAX_INDEX; + + window_size = SCM_MAX_OCE_WAN_DL_CAP/ + score_params->oce_wan_scoring.num_slot; + mbo_oce_ie = util_scan_entry_mbo_oce(entry); + if (wlan_parse_oce_reduced_wan_metrics_ie(mbo_oce_ie, + &wan_metrics)) { + scm_err("downlink_av_cap %d", wan_metrics.downlink_av_cap); + /* Desired values are from 1 to 15, as 0 is for not present.*/ + index = qdf_do_div(wan_metrics.downlink_av_cap, + window_size) + 1; + } else { + index = SCM_SCORE_INDEX_0; + } + + if (index > score_params->oce_wan_scoring.num_slot) + index = score_params->oce_wan_scoring.num_slot; + + return scm_get_score_for_index(index, + score_params->weight_cfg.oce_wan_weightage, + &score_params->oce_wan_scoring); +} + int scm_calculate_bss_score(struct wlan_objmgr_psoc *psoc, struct scan_default_params *params, struct scan_cache_entry *entry, int pcl_chan_weight) { int32_t score = 0; - int32_t ap_load = 0; - int32_t normalised_width = BEST_CANDIDATE_20MHZ; + int32_t rssi_score = 0; int32_t pcl_score = 0; - uint64_t temp_pcl_chan_weight = 0; - int32_t est_air_time_percentage = 0; - int32_t congestion = 0; - int32_t rssi_diff = 0; - int32_t rssi_weight = 0; - struct qbss_load_ie *qbss_load; + int32_t ht_score = 0; + int32_t vht_score = 0; + int32_t he_score = 0; + int32_t bandwidth_score = 0; + int32_t beamformee_score = 0; + int32_t band_score = 0; + int32_t nss_score = 0; + int32_t congestion_score = 0; + int32_t oce_wan_score = 0; + uint8_t prorated_pcnt; + bool is_vht = false; + int8_t good_rssi_threshold; + int8_t rssi_pref_5g_rssi_thresh; + bool same_bucket = false; + bool ap_su_beam_former = false; + struct wlan_ie_vhtcaps *vht_cap; + struct scoring_config *score_config; + struct weight_config *weight_config; struct wlan_scan_obj *scan_obj; - int32_t ht_score, vht_score, qbss_score = 0; - scan_obj = wlan_psoc_get_scan_obj(psoc); if (!scan_obj) { scm_err("scan_obj is NULL"); return 0; } + + score_config = &scan_obj->scan_def.score_config; + weight_config = &score_config->weight_cfg; + + rssi_score = scm_calculate_rssi_score(&score_config->rssi_score, + entry->rssi_raw, weight_config->rssi_weightage); + score += rssi_score; + + pcl_score = scm_calculate_pcl_score(pcl_chan_weight, + weight_config->pcl_weightage); + score += pcl_score; + + prorated_pcnt = scm_roam_calculate_prorated_pcnt_by_rssi( + &score_config->rssi_score, entry->rssi_raw, + weight_config->rssi_weightage); + /* If device and AP supports HT caps, extra 10% score will be added */ + if (score_config->ht_cap && entry->ie_list.htcap) + ht_score = prorated_pcnt * + weight_config->ht_caps_weightage; + score += ht_score; + + if (WLAN_CHAN_IS_2GHZ(entry->channel.chan_idx)) { + if (score_config->vht_24G_cap) + is_vht = true; + } else if (score_config->vht_cap) { + is_vht = true; + } /* - * Total weight of a BSSID is calculated on basis of 100 in which - * contribution of every factor is considered like this. - * RSSI: RSSI_WEIGHTAGE : 25 - * HT_CAPABILITY_WEIGHTAGE: 7 - * VHT_CAP_WEIGHTAGE: 5 - * BEAMFORMING_CAP_WEIGHTAGE: 2 - * CHAN_WIDTH_WEIGHTAGE:10 - * CHAN_BAND_WEIGHTAGE: 5 - * NSS: 5 - * PCL: 10 - * CHANNEL_CONGESTION: 5 - * Reserved: 31 + * If device and AP supports VHT caps, Extra 6% score will + * be added to score */ - /* - * Further bucketization of rssi is also done out of 25 score. - * RSSI > -55=> weight = 2500 - * RSSI > -60=> weight = 2250 - * RSSI >-65 =>weight = 2000 - * RSSI > -70=> weight = 1750 - * RSSI > -75=> weight = 1500 - * RSSI > -80=> weight = 1250 - */ - if (entry->rssi_raw) { - /* - * if RSSI of AP is less then -80, driver should ignore that - * candidate. - */ - if (entry->rssi_raw < BAD_RSSI) { - scm_err("Drop this BSS %pM due to low rssi %d", - entry->bssid.bytes, entry->rssi_raw); - score = 0; - return score; - } - if (entry->rssi_raw >= EXCELLENT_RSSI) { - rssi_weight = EXCELLENT_RSSI_WEIGHT * - RSSI_WEIGHTAGE; - } else { - rssi_diff = EXCELLENT_RSSI - entry->rssi_raw; - rssi_diff = rssi_diff/5; - rssi_weight = (rssi_diff + 1) * RSSI_WEIGHT_BUCKET; - rssi_weight = (EXCELLENT_RSSI_WEIGHT * - RSSI_WEIGHTAGE) - rssi_weight; + if (is_vht && entry->ie_list.vhtcap) + vht_score = prorated_pcnt * + weight_config->vht_caps_weightage; + score += vht_score; - } - score += rssi_weight; - } - if (pcl_chan_weight) { - temp_pcl_chan_weight = - (SCM_MAX_WEIGHT_OF_PCL_CHANNELS - pcl_chan_weight); - do_div(temp_pcl_chan_weight, - 20); - pcl_score = PCL_WEIGHT - temp_pcl_chan_weight; + if (score_config->he_cap && entry->ie_list.hecap) + he_score = prorated_pcnt * + weight_config->he_caps_weightage; + score += he_score; - if (pcl_score < 0) - pcl_score = 0; + bandwidth_score = scm_calculate_bandwidth_score(entry, score_config, + prorated_pcnt); + score += bandwidth_score; - score += pcl_score * BEST_CANDIDATE_MAX_WEIGHT; - } - /* If AP supports HT caps, extra 10% score will be added */ - if (entry->ie_list.htcap) { - ht_score = BEST_CANDIDATE_MAX_WEIGHT * HT_CAPABILITY_WEIGHTAGE; - score += BEST_CANDIDATE_MAX_WEIGHT * HT_CAPABILITY_WEIGHTAGE; - } + good_rssi_threshold = + score_config->rssi_score.good_rssi_threshold * (-1); + rssi_pref_5g_rssi_thresh = + score_config->rssi_score.rssi_pref_5g_rssi_thresh * (-1); + if (entry->rssi_raw < good_rssi_threshold) + same_bucket = scm_rssi_is_same_bucket(good_rssi_threshold, + entry->rssi_raw, rssi_pref_5g_rssi_thresh, + score_config->rssi_score.bad_rssi_bucket_size); - /* If AP supports VHT caps, Extra 6% score will be added to score */ - if (entry->ie_list.vhtcap) { - vht_score = BEST_CANDIDATE_MAX_WEIGHT * VHT_CAP_WEIGHTAGE; - score += BEST_CANDIDATE_MAX_WEIGHT * VHT_CAP_WEIGHTAGE; - } + vht_cap = (struct wlan_ie_vhtcaps *) util_scan_entry_vhtcap(entry); + if (vht_cap && vht_cap->su_beam_former) + ap_su_beam_former = true; + if (is_vht && ap_su_beam_former && + (entry->rssi_raw > rssi_pref_5g_rssi_thresh) && !same_bucket) + beamformee_score = BEST_CANDIDATE_MAX_WEIGHT * + weight_config->beamforming_cap_weightage; + score += beamformee_score; /* - * Channel width is again calculated on basis of 100. - * Where if AP is - * 80MHZ = 100 - * 40MHZ = 70 - * 20MHZ = 30 weightage is given out of 100. - * Channel width weightage is given as CHAN_WIDTH_WEIGHTAGE (10%). + * If AP is on 5Ghz channel , extra weigtage is added to BSS score. + * if RSSI is greater tha 5g rssi threshold or fall in same bucket. + * else give weigtage to 2.4 GH. */ - if (entry->phy_mode == WLAN_PHYMODE_11AC_VHT20 || - entry->phy_mode == WLAN_PHYMODE_11AC_VHT40PLUS || - entry->phy_mode == WLAN_PHYMODE_11AC_VHT40MINUS || - entry->phy_mode == WLAN_PHYMODE_11AC_VHT40 || - entry->phy_mode == WLAN_PHYMODE_11AC_VHT80 || - entry->phy_mode == WLAN_PHYMODE_11AC_VHT80_80 || - entry->phy_mode == WLAN_PHYMODE_11AC_VHT160) - normalised_width = BEST_CANDIDATE_80MHZ; - else if (entry->phy_mode == WLAN_PHYMODE_11NA_HT40PLUS || - entry->phy_mode == WLAN_PHYMODE_11NA_HT40MINUS || - entry->phy_mode == WLAN_PHYMODE_11NG_HT40PLUS || - entry->phy_mode == WLAN_PHYMODE_11NG_HT40MINUS || - entry->phy_mode == WLAN_PHYMODE_11NG_HT40 || - entry->phy_mode == WLAN_PHYMODE_11NA_HT40) - normalised_width = BEST_CANDIDATE_40MHZ; - else - normalised_width = BEST_CANDIDATE_20MHZ; - score += normalised_width * CHAN_WIDTH_WEIGHTAGE; - - if (util_scan_scm_chan_to_band( - entry->channel.chan_idx) == WLAN_BAND_5_GHZ && - entry->rssi_raw > RSSI_THRESHOLD_5GHZ) - score += BEST_CANDIDATE_MAX_WEIGHT * CHAN_BAND_WEIGHTAGE; - /* - * If ESP is being transmitted by the AP, use the estimated airtime for - * AC_BE from that, Estimated airtime 0-25% = 120, 25-50% = 250, 50-75% - * = 370, 75-100% = 500. - * Else if QBSSLoad is being transmitted and QBSSLoad < 25% = 500 - * else assing default weight of 370 - */ - if (entry->air_time_fraction) { - est_air_time_percentage = - entry->air_time_fraction * ROAM_MAX_CHANNEL_WEIGHT; - est_air_time_percentage = - est_air_time_percentage/MAX_ESTIMATED_AIR_TIME_FRACTION; - /* - * Calculate channel congestion from estimated air time - * fraction. - */ - congestion = MAX_CHANNEL_UTILIZATION - est_air_time_percentage; - if (congestion >= LOW_CHANNEL_CONGESTION && - congestion < MODERATE_CHANNEL_CONGESTION) - score += LOW_CHANNEL_CONGESTION_WEIGHT; - else if (congestion >= MODERATE_CHANNEL_CONGESTION && - congestion < CONSIDERABLE_CHANNEL_CONGESTION) - score += MODERATE_CHANNEL_CONGESTION_WEIGHT; - else if (congestion >= CONSIDERABLE_CHANNEL_CONGESTION && - congestion < HIGH_CHANNEL_CONGESTION) - score += CONSIDERABLE_CHANNEL_CONGESTION_WEIGHT; - else - score += HIGH_CHANNEL_CONGESTION_WEIGHT; - } else if (entry->ie_list.qbssload) { - qbss_load = (struct qbss_load_ie *) - util_scan_entry_qbssload(entry); - scm_debug("qbss_load is %d", qbss_load->qbss_chan_load); - /* - * Calculate ap_load in % from qbss channel load from 0-255 - * range - */ - ap_load = (qbss_load->qbss_chan_load * - BEST_CANDIDATE_MAX_WEIGHT); - ap_load = ap_load/MAX_AP_LOAD; - congestion = ap_load; - if (congestion < MODERATE_CHANNEL_CONGESTION) { - qbss_score = LOW_CHANNEL_CONGESTION_WEIGHT; - score += LOW_CHANNEL_CONGESTION_WEIGHT; - } else { - qbss_score = HIGH_CHANNEL_CONGESTION_WEIGHT; - score += HIGH_CHANNEL_CONGESTION_WEIGHT; - } - } else { - qbss_score = MODERATE_CHANNEL_CONGESTION_WEIGHT; - scm_debug("qbss load is not present so qbss_Score is %d", - qbss_score); - score += MODERATE_CHANNEL_CONGESTION_WEIGHT; + if ((entry->rssi_raw > rssi_pref_5g_rssi_thresh) && !same_bucket) { + if (WLAN_CHAN_IS_2GHZ(entry->channel.chan_idx)) + band_score = weight_config->chan_band_weightage * + WLAN_GET_SCORE_PERCENTAGE( + score_config->band_weight_per_index, + SCM_BAND_5G_INDEX); + } else if (WLAN_CHAN_IS_2GHZ(entry->channel.chan_idx)) { + band_score = weight_config->chan_band_weightage * + WLAN_GET_SCORE_PERCENTAGE( + score_config->band_weight_per_index, + SCM_BAND_2G_INDEX); } - scm_debug(" ht_score %d vht_score %d and qbss_score %d", - ht_score, vht_score, qbss_score); - scm_debug(" BSS %pM rssi %d channel %d final score %d", - entry->bssid.bytes, - entry->rssi_raw, entry->channel.chan_idx, - score); - scm_info("nss %d", entry->nss); + score += band_score; + + congestion_score = scm_calculate_congestion_score(entry, score_config); + score += congestion_score; + + /* + * If station support nss as 2*2 but AP support NSS as 1*1, + * this AP will be given half weight compare to AP which are having + * NSS as 2*2. + */ + nss_score = scm_calculate_nss_score(psoc, score_config, entry->nss, + prorated_pcnt); + score += nss_score; + + oce_wan_score = scm_calculate_oce_wan_score(entry, score_config); + score += oce_wan_score; + + scm_debug("Self Cap: HT %d VHT %d HE %d VHT_24Ghz %d BF cap %d cb_mode_24g %d cb_mode_5G %d NSS %d", + score_config->ht_cap, score_config->vht_cap, + score_config->he_cap, score_config->vht_24G_cap, + score_config->beamformee_cap, score_config->cb_mode_24G, + score_config->cb_mode_5G, score_config->nss); + + scm_debug("Candidate (BSSID: %pM Chan %d) Cap:: rssi=%d HT=%d VHT=%d HE %d su beamformer %d phymode=%d air time fraction %d qbss load %d NSS %d", + entry->bssid.bytes, entry->channel.chan_idx, + entry->rssi_raw, util_scan_entry_htcap(entry) ? 1 : 0, + util_scan_entry_vhtcap(entry) ? 1 : 0, + util_scan_entry_hecap(entry) ? 1 : 0, ap_su_beam_former, + entry->phy_mode, entry->air_time_fraction, + entry->qbss_chan_load, entry->nss); + + scm_debug("Candidate Scores : prorated_pcnt %d rssi %d pcl %d ht %d vht %d he %d beamformee %d bw %d band %d congestion %d nss %d oce wan %d TOTAL score %d", + prorated_pcnt, rssi_score, pcl_score, ht_score, vht_score, + he_score, beamformee_score, bandwidth_score, band_score, + congestion_score, nss_score, oce_wan_score, score); + entry->bss_score = score; return score; } diff --git a/umac/scan/core/src/wlan_scan_main.h b/umac/scan/core/src/wlan_scan_main.h index e12ee4c5cb..12a7a5988c 100644 --- a/umac/scan/core/src/wlan_scan_main.h +++ b/umac/scan/core/src/wlan_scan_main.h @@ -365,6 +365,7 @@ struct scan_default_params { uint32_t scan_events; }; struct roam_filter_params roam_params; + struct scoring_config score_config; }; /** diff --git a/umac/scan/dispatcher/inc/wlan_scan_public_structs.h b/umac/scan/dispatcher/inc/wlan_scan_public_structs.h index 079c233c2c..50d689e8bb 100644 --- a/umac/scan/dispatcher/inc/wlan_scan_public_structs.h +++ b/umac/scan/dispatcher/inc/wlan_scan_public_structs.h @@ -35,18 +35,6 @@ typedef uint32_t wlan_scan_id; #define WLAN_SCAN_MAX_NUM_BSSID 10 #define WLAN_SCAN_MAX_NUM_CHANNELS 40 -#define SCM_PCL_ADVANTAGE 30 -#define SCM_PCL_RSSI_THRESHOLD -75 -#define SCM_MAX_WEIGHT_OF_PCL_CHANNELS 255 - -#define SCM_BSS_CAP_VALUE_NONE 0/* not much value */ -#define SCM_BSS_CAP_VALUE_HT 1 -#define SCM_BSS_CAP_VALUE_VHT 2 -#define SCM_BSS_CAP_VALUE_HE 3 -#define SCM_BSS_CAP_VALUE_WMM 1 -#define SCM_BSS_CAP_VALUE_UAPSD 1 -#define SCM_BSS_CAP_VALUE_5GHZ 2 - #define SCM_CANCEL_SCAN_WAIT_TIME 50 #define SCM_CANCEL_SCAN_WAIT_ITERATION 600 @@ -77,13 +65,13 @@ typedef uint32_t wlan_scan_id; #define MAX_INDEX_SCORE 100 #define MAX_INDEX_PER_INI 4 -#define WLAN_GET_BITS(_val, _index, _num_bits) \ - (((_val) >> (_index)) & ((1 << (_num_bits)) - 1)) +#define WLAN_GET_BITS(_val, _index, _num_bits) \ + (((_val) >> (_index)) & ((1 << (_num_bits)) - 1)) -#define WLAN_SET_BITS(_var, _index, _num_bits, _val) do { \ - (_var) &= ~(((1 << (_num_bits)) - 1) << (_index)); \ - (_var) |= (((_val) & ((1 << (_num_bits)) - 1)) << (_index)); \ - } while (0) +#define WLAN_SET_BITS(_var, _index, _num_bits, _val) do { \ + (_var) &= ~(((1 << (_num_bits)) - 1) << (_index)); \ + (_var) |= (((_val) & ((1 << (_num_bits)) - 1)) << (_index)); \ + } while (0) #define WLAN_GET_SCORE_PERCENTAGE(value32, bw_index) \ WLAN_GET_BITS(value32, (8 * (bw_index)), 8) @@ -157,6 +145,7 @@ struct element_info { * @srp: pointer to spatial reuse parameter sub extended ie * @fils_indication: pointer to FILS indication ie * @esp: pointer to ESP indication ie + * @mbo_oce: pointer to mbo/oce indication ie */ struct ie_list { uint8_t *tim; @@ -200,6 +189,7 @@ struct ie_list { uint8_t *srp; uint8_t *fils_indication; uint8_t *esp; + uint8_t *mbo_oce; }; /** @@ -268,6 +258,7 @@ struct security_info { * @erp: erp info * @dtim_period: dtime period * @air_time_fraction: Air time fraction from ESP param + * @qbss_chan_load: Qbss channel load * @nss: supported NSS information * @is_p2p_ssid: is P2P entry * @scan_entry_time: boottime in microsec when last beacon/probe is received @@ -278,8 +269,6 @@ struct security_info { * @channel_mismatch: if channel received in metadata * doesnot match the one in beacon * @tsf_delta: TSF delta - * @prefer_value: Preffer value calulated for the AP - * @cap_value: Capability value calculated for the AP * @bss_score: bss score calculated on basis of RSSI/caps etc. * @neg_sec_info: negotiated security info * @rrm_parent_tsf: RRM parent tsf @@ -306,6 +295,7 @@ struct scan_cache_entry { uint8_t erp; uint8_t dtim_period; uint8_t air_time_fraction; + uint8_t qbss_chan_load; uint8_t nss; bool is_p2p; qdf_time_t scan_entry_time; @@ -315,8 +305,6 @@ struct scan_cache_entry { bool channel_mismatch; struct mlme_info mlme_info; uint32_t tsf_delta; - uint32_t prefer_value; - uint32_t cap_val; uint32_t bss_score; struct security_info neg_sec_info; uint32_t rrm_parent_tsf; @@ -335,40 +323,137 @@ struct scan_cache_entry { * avoid connecting to. It is like a * blacklist of BSSID's. * also for roaming apart from the connected one's - * @num_bssid_favored: Number of BSSID's which have a preference over - * others - * @raise_rssi_thresh_5g: The RSSI threshold below which the - * raise_factor_5g (boost factor) should be - * applied. - * @drop_rssi_thresh_5g: The RSSI threshold beyond which the - * drop_factor_5g (penalty factor) should be - * applied - * @raise_factor_5g: Boost factor - * @drop_factor_5g: Penalty factor - * @max_raise_rssi_5g: Maximum amount of Boost that can added - * @max_drop_rssi_5g: Maximum amount of penalty that can be subtracted - * @is_5g_pref_enabled: 5GHz BSSID preference feature enable/disable. * @bssid_avoid_list: Blacklist SSID's - * @bssid_favored: Favorable BSSID's - * @bssid_favored_factor: RSSI to be added to this BSSID to prefer it * * This structure holds all the key parameters related to * initial connection and also roaming connections. */ struct roam_filter_params { uint32_t num_bssid_avoid_list; - uint32_t num_bssid_favored; - int raise_rssi_thresh_5g; - int drop_rssi_thresh_5g; - uint32_t raise_factor_5g; - uint32_t drop_factor_5g; - int max_raise_rssi_5g; - int max_drop_rssi_5g; - uint32_t is_5g_pref_enabled; /* Variable params list */ struct qdf_mac_addr bssid_avoid_list[MAX_AVOID_LIST_BSSID]; - struct qdf_mac_addr bssid_favored[MAX_FAVORED_BSSID]; - uint8_t bssid_favored_factor[MAX_FAVORED_BSSID]; +}; + +/** + * struct weight_config - weight params to calculate best candidate + * @rssi_weightage: RSSI weightage + * @ht_caps_weightage: HT caps weightage + * @vht_caps_weightage: VHT caps weightage + * @he_caps_weightage: HE caps weightage + * @chan_width_weightage: Channel width weightage + * @chan_band_weightage: Channel band weightage + * @nss_weightage: NSS weightage + * @beamforming_cap_weightage: Beamforming caps weightage + * @pcl_weightage: PCL weightage + * @channel_congestion_weightage: channel congestion weightage + * @oce_wan_weightage: OCE WAN metrics weightage + */ +struct weight_config { + uint8_t rssi_weightage; + uint8_t ht_caps_weightage; + uint8_t vht_caps_weightage; + uint8_t he_caps_weightage; + uint8_t chan_width_weightage; + uint8_t chan_band_weightage; + uint8_t nss_weightage; + uint8_t beamforming_cap_weightage; + uint8_t pcl_weightage; + uint8_t channel_congestion_weightage; + uint8_t oce_wan_weightage; +}; + +/** + * struct rssi_cfg_score - rssi related params for scoring logic + * @best_rssi_threshold: RSSI weightage + * @good_rssi_threshold: HT caps weightage + * @bad_rssi_threshold: VHT caps weightage + * @good_rssi_pcnt: HE caps weightage + * @bad_rssi_pcnt: Channel width weightage + * @good_rssi_bucket_size: Channel band weightage + * @bad_rssi_bucket_size: NSS weightage + * @rssi_pref_5g_rssi_thresh: Beamforming caps weightage + */ +struct rssi_cfg_score { + uint32_t best_rssi_threshold; + uint32_t good_rssi_threshold; + uint32_t bad_rssi_threshold; + uint32_t good_rssi_pcnt; + uint32_t bad_rssi_pcnt; + uint32_t good_rssi_bucket_size; + uint32_t bad_rssi_bucket_size; + uint32_t rssi_pref_5g_rssi_thresh; +}; + +/** + * struct per_slot_scoring - define % score for differents slots for a + * scoring param. + * num_slot: number of slots in which the param will be divided. + * Max 15. index 0 is used for 'not_present. Num_slot will + * equally divide 100. e.g, if num_slot = 4 slot 0 = 0-25%, slot + * 1 = 26-50% slot 2 = 51-75%, slot 3 = 76-100% + * score_pcnt3_to_0: Conatins score percentage for slot 0-3 + * BITS 0-7 :- the scoring pcnt when not present + * BITS 8-15 :- SLOT_1 + * BITS 16-23 :- SLOT_2 + * BITS 24-31 :- SLOT_3 + * score_pcnt7_to_4: Conatins score percentage for slot 4-7 + * BITS 0-7 :- SLOT_4 + * BITS 8-15 :- SLOT_5 + * BITS 16-23 :- SLOT_6 + * BITS 24-31 :- SLOT_7 + * score_pcnt11_to_8: Conatins score percentage for slot 8-11 + * BITS 0-7 :- SLOT_8 + * BITS 8-15 :- SLOT_9 + * BITS 16-23 :- SLOT_10 + * BITS 24-31 :- SLOT_11 + * score_pcnt15_to_12: Conatins score percentage for slot 12-15 + * BITS 0-7 :- SLOT_12 + * BITS 8-15 :- SLOT_13 + * BITS 16-23 :- SLOT_14 + * BITS 24-31 :- SLOT_15 + */ +struct per_slot_scoring { + uint32_t num_slot; + uint32_t score_pcnt3_to_0; + uint32_t score_pcnt7_to_4; + uint32_t score_pcnt11_to_8; + uint32_t score_pcnt15_to_12; +}; + +/** + * struct scoring_config - Scoring related configuration + * @weight_cfg: weigtage config for config + * @rssi_score: Rssi related config for scoring config + * @esp_qbss_scoring: esp and qbss related scoring config + * @oce_wan_scoring: oce related scoring config + * @bandwidth_weight_per_index: BW wight per index + * @nss_weight_per_index: nss weight per index + * @band_weight_per_index: band weight per index + * @cb_mode_24G: cb mode supprted for 2.4Ghz + * @cb_mode_5G: cb mode supprted for 5Ghz + * @nss: Number of NSS the device support + * @ht_cap: If dev is configured as HT capable + * @vht_cap:If dev is configured as VHT capable + * @he_cap: If dev is configured as HE capable + * @vht_24G_cap:If dev is configured as VHT capable for 2.4Ghz + * @beamformee_cap:If dev is configured as BF capable + */ +struct scoring_config { + struct weight_config weight_cfg; + struct rssi_cfg_score rssi_score; + struct per_slot_scoring esp_qbss_scoring; + struct per_slot_scoring oce_wan_scoring; + uint32_t bandwidth_weight_per_index; + uint32_t nss_weight_per_index; + uint32_t band_weight_per_index; + uint8_t cb_mode_24G; + uint8_t cb_mode_5G; + uint8_t nss; + uint8_t ht_cap:1, + vht_cap:1, + he_cap:1, + vht_24G_cap:1, + beamformee_cap:1; }; #define WLAN_SCAN_FILTER_NUM_SSID 5 @@ -1112,6 +1197,7 @@ struct pno_user_cfg { * @ie_whitelist: probe req IE whitelist attrs * @is_bssid_hint_priority: True if bssid_hint is priority * @enable_mac_spoofing: enable mac address spoof in scan + * @score_config: scoring logic configuration */ struct scan_user_cfg { uint32_t active_dwell; @@ -1134,6 +1220,7 @@ struct scan_user_cfg { uint32_t usr_cfg_num_probes; bool is_bssid_hint_priority; bool enable_mac_spoofing; + struct scoring_config score_config; }; /** diff --git a/umac/scan/dispatcher/inc/wlan_scan_utils_api.h b/umac/scan/dispatcher/inc/wlan_scan_utils_api.h index 0f9b3e1a8b..c093cbd7b9 100644 --- a/umac/scan/dispatcher/inc/wlan_scan_utils_api.h +++ b/umac/scan/dispatcher/inc/wlan_scan_utils_api.h @@ -652,6 +652,7 @@ util_scan_copy_beacon_data(struct scan_cache_entry *new_entry, ie_lst->fils_indication = conv_ptr(ie_lst->fils_indication, old_ptr, new_ptr); ie_lst->esp = conv_ptr(ie_lst->esp, old_ptr, new_ptr); + ie_lst->mbo_oce = conv_ptr(ie_lst->mbo_oce, old_ptr, new_ptr); return QDF_STATUS_SUCCESS; } @@ -1369,6 +1370,20 @@ util_scan_entry_esp_info(struct scan_cache_entry *scan_entry) return scan_entry->ie_list.esp; } +/** + * util_scan_entry_mbo_oce() - function to read MBO/OCE ie + * @scan_entry: scan entry + * + * API, function to read MBO/OCE ie + * + * Return: MBO/OCE ie + */ +static inline uint8_t * +util_scan_entry_mbo_oce(struct scan_cache_entry *scan_entry) +{ + return scan_entry->ie_list.mbo_oce; +} + /** * util_scan_scm_chan_to_band() - function to tell band for channel number * @chan: Channel number diff --git a/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c b/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c index c5ef8db845..7f45ac9b49 100644 --- a/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c @@ -1313,8 +1313,14 @@ QDF_STATUS ucfg_scan_update_user_config(struct wlan_objmgr_psoc *psoc, scan_cfg->scan_bucket_threshold, scan_cfg->rssi_cat_gap); - return ucfg_scan_update_pno_config(&scan_obj->pno_cfg, + ucfg_scan_update_pno_config(&scan_obj->pno_cfg, &scan_cfg->pno_cfg); + + qdf_mem_copy(&scan_def->score_config, &scan_cfg->score_config, + sizeof(struct scoring_config)); + scm_validate_scoring_config(&scan_def->score_config); + + return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_scan_update_roam_params(struct wlan_objmgr_psoc *psoc, diff --git a/umac/scan/dispatcher/src/wlan_scan_utils_api.c b/umac/scan/dispatcher/src/wlan_scan_utils_api.c index 8fec73d724..2943b90382 100644 --- a/umac/scan/dispatcher/src/wlan_scan_utils_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_utils_api.c @@ -417,6 +417,8 @@ util_scan_parse_vendor_ie(struct scan_cache_entry *scan_params, * hence copy data just after version byte */ scan_params->ie_list.bwnss_map = (((uint8_t *)ie) + 8); + } else if (is_mbo_oce_oui((uint8_t *)ie)) { + scan_params->ie_list.mbo_oce = (uint8_t *)ie; } } @@ -727,6 +729,7 @@ util_scan_unpack_beacon_frame(uint8_t *frame, QDF_STATUS status; struct ie_ssid *ssid; struct scan_cache_entry *scan_entry = NULL; + struct qbss_load_ie *qbss_load; scan_entry = qdf_mem_malloc(sizeof(*scan_entry)); if (!scan_entry) { @@ -832,6 +835,10 @@ util_scan_unpack_beacon_frame(uint8_t *frame, scan_entry->nss = util_scan_scm_calc_nss_supported_by_ap(scan_entry); util_scan_scm_update_bss_with_esp_data(scan_entry); + qbss_load = (struct qbss_load_ie *) + util_scan_entry_qbssload(scan_entry); + if (qbss_load) + scan_entry->qbss_chan_load = qbss_load->qbss_chan_load; /* TODO calculate channel struct */ return scan_entry;