diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index c880bb303db8..41a0ffd56025 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -3740,6 +3740,10 @@ wlan_hdd_cfg80211_get_features(struct wiphy *wiphy, QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST #define PARAM_SCAN_FREQ_LIST_TYPE \ QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST_TYPE +#define PARAM_CAND_SEL_CRITERIA_MAX \ + QCA_ATTR_ROAM_CAND_SEL_CRITERIA_RATE_MAX +#define PARAM_CAND_SEL_SCORE_RSSI \ + QCA_ATTR_ROAM_CAND_SEL_CRITERIA_SCORE_RSSI static const struct nla_policy @@ -4114,6 +4118,7 @@ roam_control_policy[QCA_ATTR_ROAM_CONTROL_MAX + 1] = { [PARAM_FREQ_LIST_SCHEME] = {.type = NLA_NESTED}, [QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD] = {.type = NLA_U32}, [QCA_ATTR_ROAM_CONTROL_TRIGGERS] = {.type = NLA_U32}, + [QCA_ATTR_ROAM_CONTROL_SELECTION_CRITERIA] = {.type = NLA_NESTED}, }; /** @@ -4177,6 +4182,107 @@ hdd_send_roam_triggers_to_sme(struct hdd_context *hdd_ctx, return status; } +/* + * Disable default scoring algorithm. This is intended to set all bits of the + * disable_bitmap in struct scoring_param. + */ +#define DISABLE_SCORING 0 + +/* + * Enable scoring algorithm. This is intended to clear all bits of the + * disable_bitmap in struct scoring_param. + */ +#define ENABLE_SCORING 1 + +/* + * Controlled roam candidate selection is enabled from userspace. + * Driver/firmware should honor the selection criteria + */ +#define CONTROL_ROAM_CAND_SEL_ENABLE 1 + +/* + * Controlled roam candidate selection is disabled from userspace. + * Driver/firmware can use its internal candidate selection criteria + */ +#define CONTROL_ROAM_CAND_SEL_DISABLE 0 + +static const struct nla_policy +roam_scan_cand_sel_policy[PARAM_CAND_SEL_CRITERIA_MAX + 1] = { + [PARAM_CAND_SEL_SCORE_RSSI] = {.type = NLA_U8}, +}; + +/** + * hdd_send_roam_cand_sel_criteria_to_sme() - Send candidate sel criteria to SME + * @hdd_ctx: HDD context + * @vdev_id: vdev id + * @attr: Nested attribute carrying candidate selection criteria + * + * Extract different candidate sel criteria mentioned and convert it to + * driver/firmware understable format. + * + * Return: QDF_STATUS + */ +static QDF_STATUS +hdd_send_roam_cand_sel_criteria_to_sme(struct hdd_context *hdd_ctx, + uint8_t vdev_id, + struct nlattr *attr) +{ + QDF_STATUS status; + struct nlattr *tb2[PARAM_CAND_SEL_CRITERIA_MAX + 1]; + struct nlattr *curr_attr; + uint8_t sel_criteria = 0, rssi_score = 0, scoring; + int rem; + + hdd_debug("Received Command to Set candidate selection criteria "); + nla_for_each_nested(curr_attr, attr, rem) { + sel_criteria++; + break; + } + + if (sel_criteria && + wlan_cfg80211_nla_parse_nested(tb2, PARAM_CAND_SEL_CRITERIA_MAX, + attr, roam_scan_cand_sel_policy)) { + hdd_err("nla_parse failed"); + return QDF_STATUS_E_INVAL; + } + + /* + * Firmware supports the below configurations currently, + * 1. Default selection criteria where all scoring params + * are enabled and different weightages/scores are given to + * different parameters. + * When userspace doesn't specify any candidate selection criteria, + * this will be enabled. + * 2. Legacy candidate selection criteria where scoring + * algorithm is disabled and only RSSI is considered for + * roam candidate selection. + * When userspace specify 100% weightage for RSSI, this will + * be enabled. + * Rest of the combinations are not supported for now. + */ + if (sel_criteria == CONTROL_ROAM_CAND_SEL_ENABLE) { + /* Legacy selection criteria: 100% weightage to RSSI */ + if (tb2[PARAM_CAND_SEL_SCORE_RSSI]) + rssi_score = nla_get_u8(tb2[PARAM_CAND_SEL_SCORE_RSSI]); + + if (rssi_score != 100) { + hdd_debug("Ignore the candidate selection criteria"); + return QDF_STATUS_E_INVAL; + } + scoring = DISABLE_SCORING; + } else { + /* Default selection criteria */ + scoring = ENABLE_SCORING; + } + + status = sme_modify_roam_cand_sel_criteria(hdd_ctx->mac_handle, vdev_id, + !!scoring); + if (QDF_IS_STATUS_ERROR(status)) + hdd_err("Failed to disable scoring"); + + return status; +} + /** * hdd_set_roam_with_control_config() - Set roam control configuration * @hdd_ctx: HDD context @@ -4251,6 +4357,16 @@ hdd_set_roam_with_control_config(struct hdd_context *hdd_ctx, hdd_err("failed to enable/disable roam control config"); } + /* Scoring and roam candidate selection criteria */ + attr = tb2[QCA_ATTR_ROAM_CONTROL_SELECTION_CRITERIA]; + if (attr) { + hdd_debug("Send candidate selection criteria to firmware"); + status = hdd_send_roam_cand_sel_criteria_to_sme(hdd_ctx, + vdev_id, attr); + if (QDF_IS_STATUS_ERROR(status)) + hdd_err("failed to set candidate selection criteria"); + } + return qdf_status_to_os_return(status); } @@ -4259,6 +4375,8 @@ hdd_set_roam_with_control_config(struct hdd_context *hdd_ctx, #undef PARAM_FREQ_LIST_SCHEME #undef PARAM_SCAN_FREQ_LIST #undef PARAM_SCAN_FREQ_LIST_TYPE +#undef PARAM_CAND_SEL_CRITERIA_MAX +#undef PARAM_CAND_SEL_SCORE_RSSI /** * hdd_set_ext_roam_params() - parse ext roam params diff --git a/core/sme/inc/csr_neighbor_roam.h b/core/sme/inc/csr_neighbor_roam.h index d4c9656647a9..61bc0960b749 100644 --- a/core/sme/inc/csr_neighbor_roam.h +++ b/core/sme/inc/csr_neighbor_roam.h @@ -65,6 +65,7 @@ typedef struct sCsrNeighborRoamCfgParams { int32_t hi_rssi_scan_rssi_ub; tCsrChannelInfo pref_chan_info; uint32_t full_roam_scan_period; + bool enable_scoring_for_roam; } tCsrNeighborRoamCfgParams, *tpCsrNeighborRoamCfgParams; #define CSR_NEIGHBOR_ROAM_INVALID_CHANNEL_INDEX 255 @@ -261,6 +262,7 @@ void csr_roam_reset_roam_params(struct mac_context *mac_ptr); #define REASON_SME_ISSUED 42 #define REASON_DRIVER_ENABLED 43 #define REASON_ROAM_FULL_SCAN_PERIOD_CHANGED 44 +#define REASON_SCORING_CRITERIA_CHANGED 45 #if defined(WLAN_FEATURE_HOST_ROAM) || defined(WLAN_FEATURE_ROAM_OFFLOAD) QDF_STATUS csr_roam_offload_scan(struct mac_context *mac, uint8_t sessionId, diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 98ec8c126c61..9d8c0ed00487 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -831,6 +831,25 @@ QDF_STATUS sme_update_empty_scan_refresh_period(mac_handle_t mac_handle, QDF_STATUS sme_update_full_roam_scan_period(mac_handle_t mac_handle, uint8_t vdev_id, uint32_t full_roam_scan_period); + +/** + * sme_modify_roam_cand_sel_criteria() - Modify candidate selection criteria + * @mac_handle: Opaque handle to the global MAC context + * @vdev_id: vdev Identifier + * @enable_scoring_for_roam: Carries enable/disable indication + * + * Enable/disable scoring for roam candidate selection based on the value of + * enable_scoring_for_roam. Below is the description of enable/disable, + * Disable-0: Disable scoring for roam candidate selection. Roaming + * shall fallback to legacy selection criteria, only RSSI. + * Enable-1 : Enable scoring for roam candidate selection. + * + * Return: Success or failure + */ +QDF_STATUS +sme_modify_roam_cand_sel_criteria(mac_handle_t mac_handle, + uint8_t vdev_id, + bool enable_scoring_for_roam); QDF_STATUS sme_set_neighbor_scan_min_chan_time(mac_handle_t mac_handle, const uint16_t nNeighborScanMinChanTime, uint8_t sessionId); diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 09a6c3c06947..327bfe06e5cf 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -6834,6 +6834,41 @@ QDF_STATUS sme_update_full_roam_scan_period(mac_handle_t mac_handle, return status; } +QDF_STATUS +sme_modify_roam_cand_sel_criteria(mac_handle_t mac_handle, + uint8_t vdev_id, + bool enable_scoring_for_roam) +{ + struct mac_context *mac = MAC_CONTEXT(mac_handle); + QDF_STATUS status; + tpCsrNeighborRoamControlInfo neighbor_roam_info; + + if (vdev_id >= WLAN_MAX_VDEVS) { + sme_err("Invalid vdev_id: %d", vdev_id); + return QDF_STATUS_E_INVAL; + } + + status = sme_acquire_global_lock(&mac->sme); + if (QDF_IS_STATUS_ERROR(status)) + return status; + + if (!mac->mlme_cfg->lfr.roam_scan_offload_enabled) { + status = QDF_STATUS_E_INVAL; + goto out; + } + + neighbor_roam_info = &mac->roam.neighborRoamInfo[vdev_id]; + neighbor_roam_info->cfgParams.enable_scoring_for_roam = + enable_scoring_for_roam; + status = csr_roam_offload_scan(mac, vdev_id, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_SCORING_CRITERIA_CHANGED); +out: + sme_release_global_lock(&mac->sme); + + return status; +} + /* * sme_set_neighbor_scan_min_chan_time() - * Update nNeighborScanMinChanTime diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 07f0b8a6fa6d..727a52e7413f 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -19077,7 +19077,8 @@ void csr_update_fils_params_rso(struct mac_context *mac, * Return: None */ static void csr_update_score_params(struct mac_context *mac_ctx, - struct roam_offload_scan_req *req_buffer) + struct roam_offload_scan_req *req_buffer, + tpCsrNeighborRoamControlInfo roam_info) { struct scoring_param *req_score_params; struct rssi_scoring *req_rssi_score; @@ -19092,9 +19093,9 @@ static void csr_update_score_params(struct mac_context *mac_ctx, weight_config = &bss_score_params->weight_cfg; rssi_score = &bss_score_params->rssi_score; - if (!bss_score_params->enable_scoring_for_roam) - req_score_params->disable_bitmap = - WLAN_ROAM_SCORING_DISABLE_ALL; + if (!roam_info->cfgParams.enable_scoring_for_roam) + req_score_params->disable_bitmap = + WLAN_ROAM_SCORING_DISABLE_ALL; req_score_params->rssi_weightage = weight_config->rssi_weightage; req_score_params->ht_weightage = weight_config->ht_caps_weightage; @@ -19524,7 +19525,7 @@ csr_roam_offload_scan(struct mac_context *mac_ctx, uint8_t session_id, session->pAddIEAssoc, session->nAddIEAssocLength); csr_update_driver_assoc_ies(mac_ctx, session, req_buf); - csr_update_score_params(mac_ctx, req_buf); + csr_update_score_params(mac_ctx, req_buf, roam_info); csr_update_fils_params_rso(mac_ctx, session, req_buf); } diff --git a/core/sme/src/csr/csr_neighbor_roam.c b/core/sme/src/csr/csr_neighbor_roam.c index fb62b9757c3b..9e0ca06a4aff 100644 --- a/core/sme/src/csr/csr_neighbor_roam.c +++ b/core/sme/src/csr/csr_neighbor_roam.c @@ -1248,6 +1248,8 @@ QDF_STATUS csr_neighbor_roam_init(struct mac_context *mac, uint8_t sessionId) mac->mlme_cfg->lfr.empty_scan_refresh_period; pNeighborRoamInfo->cfgParams.full_roam_scan_period = mac->mlme_cfg->lfr.roam_full_scan_period; + pNeighborRoamInfo->cfgParams.enable_scoring_for_roam = + mac->mlme_cfg->scoring.enable_scoring_for_roam; specific_chan_info = &pNeighborRoamInfo->cfgParams.specific_chan_info; specific_chan_info->numOfChannels =