diff --git a/umac/mlme/connection_mgr/core/src/wlan_cm_bss_scoring.c b/umac/mlme/connection_mgr/core/src/wlan_cm_bss_scoring.c index 7d72ad0196..9dba36da2e 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_bss_scoring.c +++ b/umac/mlme/connection_mgr/core/src/wlan_cm_bss_scoring.c @@ -1974,6 +1974,7 @@ static int cm_calculate_mlo_bss_score(struct wlan_objmgr_psoc *psoc, return best_total_score; } + #else static inline int cm_calculate_emlsr_score(struct weight_cfg *weight_config) { @@ -1998,6 +1999,101 @@ static int cm_calculate_mlo_bss_score(struct wlan_objmgr_psoc *psoc, } #endif +#if defined(WLAN_FEATURE_11BE_MLO) && defined(CONN_MGR_ADV_FEATURE) +static void +cm_sort_vendor_algo_mlo_bss_entry(struct wlan_objmgr_psoc *psoc, + struct scan_cache_entry *entry, + struct psoc_phy_config *phy_config, + qdf_list_t *scan_list, + enum MLO_TYPE bss_mlo_type) +{ + struct scan_cache_entry *entry_partner[MLD_MAX_LINKS - 1]; + uint32_t freq[MLD_MAX_LINKS - 1]; + uint32_t etp_score[MLD_MAX_LINKS - 1] = {0}; + uint32_t total_score[MLD_MAX_LINKS - 1] = {0}; + uint8_t i, j; + uint32_t best_total_score = 0; + uint8_t best_partner_index = 0; + uint32_t freq_entry; + struct partner_link_info *link; + bool eht_capab; + struct partner_link_info tmp_link_info; + uint32_t tmp_total_score = 0; + + wlan_psoc_mlme_get_11be_capab(psoc, &eht_capab); + if (!eht_capab) + return; + + link = &entry->ml_info.link_info[0]; + freq_entry = entry->channel.chan_freq; + for (i = 0; i < entry->ml_info.num_links; i++) { + mlme_debug("freq: %d, link id: %d is valid %d "QDF_MAC_ADDR_FMT, + link[i].freq, link[i].link_id, + link[i].is_valid_link, + QDF_MAC_ADDR_REF(link[i].link_addr.bytes)); + if (!link[i].is_valid_link) + continue; + + entry_partner[i] = cm_get_entry(scan_list, &link[i].link_addr); + if (entry_partner[i]) + freq[i] = entry_partner[i]->channel.chan_freq; + else + freq[i] = link[i].freq; + + if (policy_mgr_are_2_freq_on_same_mac(psoc, freq[i], + freq_entry)) { + link[i].is_valid_link = false; + total_score[i] = 0; + mlme_nofl_debug("freq %d and %d can't be MLMR", + freq[i], freq_entry); + continue; + } + + if (!entry_partner[i]) + continue; + + etp_score[i] = cm_calculate_etp_score(psoc, entry_partner[i], + phy_config, bss_mlo_type); + + total_score[i] = etp_score[i]; + if (total_score[i] > best_total_score) { + best_total_score = total_score[i]; + best_partner_index = i; + } + } + + /* reorder the link idx per score */ + for (j = 0; j < entry->ml_info.num_links; j++) { + tmp_total_score = total_score[j]; + best_partner_index = j; + for (i = j + 1; i < entry->ml_info.num_links; i++) { + if (tmp_total_score < total_score[i]) { + tmp_total_score = total_score[i]; + best_partner_index = i; + } + } + + if (best_partner_index != j) { + tmp_link_info = entry->ml_info.link_info[j]; + entry->ml_info.link_info[j] = + entry->ml_info.link_info[best_partner_index]; + entry->ml_info.link_info[best_partner_index] = + tmp_link_info; + total_score[best_partner_index] = total_score[j]; + } + total_score[j] = 0; + } +} +#else +static void +cm_sort_vendor_algo_mlo_bss_entry(struct wlan_objmgr_psoc *psoc, + struct scan_cache_entry *entry, + struct psoc_phy_config *phy_config, + qdf_list_t *scan_list, + enum MLO_TYPE bss_mlo_type) +{} +#endif + static int cm_calculate_bss_score(struct wlan_objmgr_psoc *psoc, struct scan_cache_entry *entry, int pcl_chan_weight, @@ -2063,6 +2159,15 @@ static int cm_calculate_bss_score(struct wlan_objmgr_psoc *psoc, score = cm_calculate_etp_score(psoc, entry, phy_config, bss_mlo_type); entry->bss_score = score; + if (bss_mlo_type == MLMR) { + cm_sort_vendor_algo_mlo_bss_entry(psoc, entry, + phy_config, scan_list, + bss_mlo_type); + } + mlme_nofl_debug("Candidate("QDF_MAC_ADDR_FMT" freq %d): rssi %d score %d", + QDF_MAC_ADDR_REF(entry->bssid.bytes), + entry->channel.chan_freq, + entry->rssi_raw, entry->bss_score); return score; } diff --git a/umac/mlme/connection_mgr/core/src/wlan_cm_connect.c b/umac/mlme/connection_mgr/core/src/wlan_cm_connect.c index 4719ae3868..4551676c7a 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_connect.c +++ b/umac/mlme/connection_mgr/core/src/wlan_cm_connect.c @@ -42,6 +42,7 @@ #include "wlan_mlo_mgr_op.h" #include #include "wlan_psoc_mlme_api.h" +#include "wlan_scan_public_structs.h" void cm_fill_failure_resp_from_cm_id(struct cnx_mgr *cm_ctx, @@ -886,6 +887,54 @@ cm_inform_dlm_connect_complete(struct wlan_objmgr_vdev *vdev, return QDF_STATUS_SUCCESS; } +#ifdef WLAN_FEATURE_11BE_MLO +static bool +cm_update_mlo_links_for_retry_with_same_candidate(struct wlan_objmgr_psoc *psoc, + struct cm_connect_req *cm_req) +{ + uint8_t mlo_link_num; + struct scan_cache_entry *entry; + + if (!cm_req->req.ml_parnter_info.num_partner_links) + return false; + + entry = cm_req->cur_candidate->entry; + + mlo_link_num = wlan_mlme_get_sta_mlo_conn_max_num(psoc); + if (cm_req->req.ml_parnter_info.num_partner_links > mlo_link_num) + cm_req->req.ml_parnter_info.num_partner_links = mlo_link_num; + + /* + * Try next candidate for non-ML AP + */ + if (!entry->ie_list.multi_link_bv || !entry->ml_info.num_links) { + cm_req->req.ml_parnter_info.num_partner_links = NO_LINK; + return false; + } + + if (cm_req->req.ml_parnter_info.num_partner_links > NO_LINK) { + /* + * Try to same AP exhaustively till single link ML connection + * is tried with the AP + */ + cm_req->req.ml_parnter_info.num_partner_links--; + } + + mlme_debug(CM_PREFIX_FMT "try ML connection with %d partner links", + CM_PREFIX_REF(cm_req->req.vdev_id, cm_req->cm_id), + cm_req->req.ml_parnter_info.num_partner_links); + + return true; +} +#else +static inline bool +cm_update_mlo_links_for_retry_with_same_candidate(struct wlan_objmgr_psoc *psoc, + struct cm_connect_req *cm_req) +{ + return false; +} +#endif + /** * cm_is_retry_with_same_candidate() - This API check if reconnect attempt is * required with the same candidate again @@ -907,14 +956,25 @@ static bool cm_is_retry_with_same_candidate(struct cnx_mgr *cm_ctx, bool sae_connection; QDF_STATUS status; qdf_freq_t freq; + struct scoring_cfg *score_config; + struct psoc_mlme_obj *mlme_psoc_obj; psoc = wlan_pdev_get_psoc(wlan_vdev_get_pdev(cm_ctx->vdev)); + mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc); + if (!mlme_psoc_obj) + return false; + + score_config = &mlme_psoc_obj->psoc_cfg.score_config; key_mgmt = req->cur_candidate->entry->neg_sec_info.key_mgmt; freq = req->cur_candidate->entry->channel.chan_freq; /* Try once again for the invalid PMKID case without PMKID */ - if (resp->status_code == STATUS_INVALID_PMKID) + if (resp->status_code == STATUS_INVALID_PMKID) { + if (score_config->vendor_roam_score_algorithm) + cm_update_mlo_links_for_retry_with_same_candidate(psoc, + req); goto use_same_candidate; + } /* Try again for the JOIN timeout if only one candidate */ if (resp->reason == CM_JOIN_TIMEOUT && @@ -929,6 +989,9 @@ static bool cm_is_retry_with_same_candidate(struct cnx_mgr *cm_ctx, return false; wlan_mlme_get_sae_assoc_retry_count(psoc, &max_retry_count); + if (score_config->vendor_roam_score_algorithm) + cm_update_mlo_links_for_retry_with_same_candidate(psoc, + req); goto use_same_candidate; } @@ -946,9 +1009,29 @@ static bool cm_is_retry_with_same_candidate(struct cnx_mgr *cm_ctx, if (sae_connection) wlan_mlme_get_sae_assoc_retry_count(psoc, &max_retry_count); + + if (score_config->vendor_roam_score_algorithm) + cm_update_mlo_links_for_retry_with_same_candidate(psoc, + req); goto use_same_candidate; } + /* + * When vendor roam score algorithm is enabled and association failure + * happens while trying MLO connection with multiple link, then + * retry with same candidate with same primary link and other band as + * secondary link. If still failure happens, then try standlone single + * link MLO mode with the same candidate AP. Ex: + * Priority 1(candidate AP’s 6 GHz case) – 6 GHz (Associating link) + + * 5 GHz + 2.4 GHz + * Priority 2(candidate AP’s 6 GHz case) – 6 GHz (Associating link) + + * 2.4 GHz + * Priority 3(AP’s 6 GHz case) – 6 GHz (single Link) + */ + if (resp->status_code && score_config->vendor_roam_score_algorithm && + cm_update_mlo_links_for_retry_with_same_candidate(psoc, req)) + goto use_same_candidate; + return false; use_same_candidate: @@ -1707,6 +1790,30 @@ connect_err: return cm_send_connect_start_fail(cm_ctx, cm_req, reason); } +#if defined(CONN_MGR_ADV_FEATURE) && defined(WLAN_FEATURE_11BE_MLO) +static void +cm_connect_req_update_ml_partner_info(struct cnx_mgr *cm_ctx, + struct cm_req *cm_req, + bool same_candidate_used) +{ + bool eht_capable = false; + struct cm_connect_req *conn_req = &cm_req->connect_req; + + wlan_psoc_mlme_get_11be_capab(wlan_vdev_get_psoc(cm_ctx->vdev), + &eht_capable); + if (!same_candidate_used && eht_capable && + cm_bss_peer_is_assoc_peer(conn_req)) + cm_get_ml_partner_info(conn_req->cur_candidate->entry, + &conn_req->req.ml_parnter_info); +} +#else +static void +cm_connect_req_update_ml_partner_info(struct cnx_mgr *cm_ctx, + struct cm_req *cm_req, + bool same_candidate_used) +{} +#endif + /** * cm_get_valid_candidate() - This API will be called to get the next valid * candidate @@ -1850,6 +1957,9 @@ try_same_candidate: cm_req->connect_req.connect_attempts++; cm_req->connect_req.cur_candidate = new_candidate; + cm_connect_req_update_ml_partner_info(cm_ctx, cm_req, + use_same_candidate); + flush_single_pmk: akm = wlan_crypto_get_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_KEY_MGMT); /* @@ -2106,17 +2216,21 @@ static inline void cm_set_fils_connection(struct cnx_mgr *cm_ctx, #ifdef WLAN_FEATURE_11BE_MLO static inline -void cm_update_ml_partner_info(struct wlan_cm_connect_req *req, +void cm_update_ml_partner_info(struct wlan_objmgr_vdev *vdev, + struct wlan_cm_connect_req *req, struct wlan_cm_vdev_connect_req *connect_req) { - if (req->ml_parnter_info.num_partner_links) - qdf_mem_copy(&connect_req->ml_parnter_info, - &req->ml_parnter_info, - sizeof(struct mlo_partner_info)); + if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) + return; + + qdf_mem_copy(&connect_req->ml_parnter_info, + &req->ml_parnter_info, + sizeof(struct mlo_partner_info)); } #else static inline -void cm_update_ml_partner_info(struct wlan_cm_connect_req *req, +void cm_update_ml_partner_info(struct wlan_objmgr_vdev *vdev, + struct wlan_cm_connect_req *req, struct wlan_cm_vdev_connect_req *connect_req) { } @@ -2310,7 +2424,7 @@ cm_resume_connect_after_peer_create(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id) req.vht_caps = cm_req->connect_req.req.vht_caps; req.vht_caps_mask = cm_req->connect_req.req.vht_caps_mask; req.is_non_assoc_link = cm_req->connect_req.req.is_non_assoc_link; - cm_update_ml_partner_info(&cm_req->connect_req.req, &req); + cm_update_ml_partner_info(cm_ctx->vdev, &cm_req->connect_req.req, &req); neg_sec_info = &cm_req->connect_req.cur_candidate->entry->neg_sec_info; if (util_scan_entry_is_hidden_ap(req.bss->entry) && diff --git a/umac/scan/dispatcher/inc/wlan_scan_public_structs.h b/umac/scan/dispatcher/inc/wlan_scan_public_structs.h index ef1e1beb73..ac75673632 100644 --- a/umac/scan/dispatcher/inc/wlan_scan_public_structs.h +++ b/umac/scan/dispatcher/inc/wlan_scan_public_structs.h @@ -548,6 +548,20 @@ struct ml_info { struct partner_link_info link_info[MLD_MAX_LINKS - 1]; uint16_t ml_bss_score; }; + +/** + * enum number_of_partner_link: Enumeration for number of partner links + * @NO_LINK: Default value + * @ONE_LINK: Single Link + * @TWO_LINK: 2 Links + * @THREE_LINK: 3 Links + */ +enum number_of_partner_link { + NO_LINK, + ONE_LINK, + TWO_LINK, + THREE_LINK, +}; #endif /**