diff --git a/components/cmn_services/interface_mgr/inc/wlan_if_mgr_roam.h b/components/cmn_services/interface_mgr/inc/wlan_if_mgr_roam.h index 71920261d890..08ab0018df88 100644 --- a/components/cmn_services/interface_mgr/inc/wlan_if_mgr_roam.h +++ b/components/cmn_services/interface_mgr/inc/wlan_if_mgr_roam.h @@ -25,6 +25,7 @@ #include "wlan_objmgr_pdev_obj.h" #include "wlan_objmgr_vdev_obj.h" #include "wlan_policy_mgr_api.h" +#include "wlan_if_mgr_public_struct.h" #include "wlan_if_mgr_roam.h" /** @@ -40,6 +41,19 @@ struct change_roam_state_arg { uint8_t curr_vdev_id; }; +/** + * struct bssid_search_arg - Contains candidate validation arguments + * @peer_addr: MAC address of the BSS + * @vdev_id: virtual device ID + * + * This structure is used to pass the candidate validation information to the + * callback + */ +struct bssid_search_arg { + struct qdf_mac_addr peer_addr; + uint8_t vdev_id; +}; + /** * if_mgr_enable_roaming() - interface manager enable roaming * @vdev: vdev object @@ -106,4 +120,19 @@ QDF_STATUS if_mgr_enable_roaming_after_p2p_disconnect( struct wlan_objmgr_pdev *pdev, enum wlan_cm_rso_control_requestor requestor); +/** + * if_mgr_validate_candidate() - validate candidate event handler + * @vdev: vdev object + * @event_data: Interface mgr event data + * + * This function will validate the candidate to see if it is a suitable option + * for roaming to. + * + * Context: It should run in thread context + * + * Return: QDF_STATUS + */ +QDF_STATUS if_mgr_validate_candidate(struct wlan_objmgr_vdev *vdev, + struct if_mgr_event_data *event_data); + #endif diff --git a/components/cmn_services/interface_mgr/src/wlan_if_mgr_roam.c b/components/cmn_services/interface_mgr/src/wlan_if_mgr_roam.c index f97064967680..ce229126f304 100644 --- a/components/cmn_services/interface_mgr/src/wlan_if_mgr_roam.c +++ b/components/cmn_services/interface_mgr/src/wlan_if_mgr_roam.c @@ -21,7 +21,9 @@ #include "wlan_objmgr_pdev_obj.h" #include "wlan_objmgr_vdev_obj.h" #include "wlan_policy_mgr_api.h" +#include "wlan_policy_mgr_i.h" #include "wlan_if_mgr_roam.h" +#include "wlan_if_mgr_public_struct.h" #include "wlan_cm_roam_api.h" #include "wlan_if_mgr_main.h" #include "wlan_p2p_ucfg_api.h" @@ -164,3 +166,82 @@ QDF_STATUS if_mgr_enable_roaming_after_p2p_disconnect( return status; } + +static void if_mgr_get_vdev_id_from_bssid(struct wlan_objmgr_pdev *pdev, + void *object, void *arg) +{ + struct bssid_search_arg *bssid_arg = arg; + struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object; + struct wlan_objmgr_vdev_objmgr *objmgr = &vdev->vdev_objmgr; + struct wlan_objmgr_peer *peer = objmgr->bss_peer; + + if (WLAN_ADDR_EQ(bssid_arg->peer_addr.bytes, + wlan_peer_get_macaddr(peer))) + bssid_arg->vdev_id = wlan_vdev_get_id(vdev); +} + +QDF_STATUS if_mgr_validate_candidate(struct wlan_objmgr_vdev *vdev, + struct if_mgr_event_data *event_data) +{ + struct wlan_objmgr_psoc *psoc; + struct wlan_objmgr_pdev *pdev; + enum QDF_OPMODE op_mode; + enum policy_mgr_con_mode mode; + struct bssid_search_arg bssid_arg; + uint32_t chan_freq = event_data->validate_bss_info.chan_freq; + + op_mode = wlan_vdev_mlme_get_opmode(vdev); + + pdev = wlan_vdev_get_pdev(vdev); + if (!pdev) + return QDF_STATUS_E_FAILURE; + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) + return QDF_STATUS_E_FAILURE; + + /* + * Ignore the BSS if any other vdev is already connected to it. + */ + qdf_copy_macaddr(&bssid_arg.peer_addr, + &event_data->validate_bss_info.peer_addr); + bssid_arg.vdev_id = WLAN_INVALID_VDEV_ID; + wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, + if_mgr_get_vdev_id_from_bssid, + &bssid_arg, 0, + WLAN_IF_MGR_ID); + + if (bssid_arg.vdev_id != WLAN_INVALID_VDEV_ID) { + ifmgr_info("vdev_id %d already connected to "QDF_MAC_ADDR_FMT". select next bss for vdev_id %d", + bssid_arg.vdev_id, + QDF_MAC_ADDR_REF(bssid_arg.peer_addr.bytes), + wlan_vdev_get_id(vdev)); + return QDF_STATUS_E_INVAL; + } + + /* + * If concurrency enabled take the concurrent connected channel first. + * Valid multichannel concurrent sessions exempted + */ + mode = policy_mgr_convert_device_mode_to_qdf_type(op_mode); + /* If concurrency is not allowed select next bss */ + if (!policy_mgr_is_concurrency_allowed(psoc, mode, chan_freq, + HW_MODE_20_MHZ)) { + ifmgr_info("Concurrency not allowed for this channel freq %d bssid "QDF_MAC_ADDR_FMT", selecting next", + chan_freq, QDF_MAC_ADDR_REF(bssid_arg.peer_addr.bytes)); + return QDF_STATUS_E_INVAL; + } + + /* + * check if channel is allowed for current hw mode, if not fetch + * next BSS. + */ + if (!policy_mgr_is_hwmode_set_for_given_chnl(psoc, chan_freq)) { + ifmgr_info("HW mode isn't properly set, freq %d BSSID "QDF_MAC_ADDR_FMT, + chan_freq, + QDF_MAC_ADDR_REF(bssid_arg.peer_addr.bytes)); + return QDF_STATUS_E_INVAL; + } + + return QDF_STATUS_SUCCESS; +} diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 2271112132d4..0896b7fe4305 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -75,6 +75,11 @@ #include "wlan_psoc_mlme_api.h" #include "wlan_cm_roam_api.h" +#ifdef WLAN_FEATURE_INTERFACE_MGR +#include "wlan_if_mgr_public_struct.h" +#include "wlan_if_mgr_ucfg_api.h" +#endif + #define RSN_AUTH_KEY_MGMT_SAE WLAN_RSN_SEL(WLAN_AKM_SAE) #define MAX_PWR_FCC_CHAN_12 8 #define MAX_PWR_FCC_CHAN_13 2 @@ -5367,14 +5372,20 @@ static bool csr_roam_select_bss(struct mac_context *mac_ctx, enum csr_join_state *roam_state, struct scan_result_list *bss_list) { - uint32_t conc_freq = 0, chan_freq, temp_vdev_id; + uint32_t conc_freq = 0, chan_freq; bool status = false; struct tag_csrscan_result *scan_result = NULL; tCsrScanResultInfo *result = NULL; enum QDF_OPMODE op_mode; struct wlan_objmgr_vdev *vdev; - enum policy_mgr_con_mode mode; QDF_STATUS qdf_status; +#ifdef WLAN_FEATURE_INTERFACE_MGR + struct if_mgr_event_data event_data; + struct validate_bss_data candidate_info; +#else + uint32_t temp_vdev_id; + enum policy_mgr_con_mode mode; +#endif vdev = wlan_objmgr_get_vdev_by_id_from_pdev(mac_ctx->pdev, vdev_id, @@ -5397,6 +5408,31 @@ static bool csr_roam_select_bss(struct mac_context *mac_ctx, * sessions exempted */ result = &scan_result->Result; + chan_freq = result->BssDescriptor.chan_freq; + + /* + * Following code will be cleaned once the interface manager + * module is enabled. + */ +#ifdef WLAN_FEATURE_INTERFACE_MGR + qdf_mem_copy(candidate_info.peer_addr.bytes, + result->BssDescriptor.bssId, + sizeof(tSirMacAddr)); + candidate_info.chan_freq = result->BssDescriptor.chan_freq; + event_data.validate_bss_info = candidate_info; + qdf_status = ucfg_if_mgr_deliver_event(vdev, + WLAN_IF_MGR_EV_VALIDATE_CANDIDATE, + &event_data); + + if (QDF_IS_STATUS_ERROR(qdf_status)) { + *roam_state = eCsrStopRoamingDueToConcurrency; + status = true; + *roam_bss_entry = csr_ll_next(&bss_list->List, + *roam_bss_entry, + LL_ACCESS_LOCK); + continue; + } +#else /* * Ignore the BSS if any other vdev is already connected * to it. @@ -5417,7 +5453,6 @@ static bool csr_roam_select_bss(struct mac_context *mac_ctx, continue; } - chan_freq = result->BssDescriptor.chan_freq; mode = policy_mgr_convert_device_mode_to_qdf_type(op_mode); /* If concurrency is not allowed select next bss */ if (!policy_mgr_is_concurrency_allowed(mac_ctx->psoc, @@ -5451,6 +5486,7 @@ static bool csr_roam_select_bss(struct mac_context *mac_ctx, LL_ACCESS_LOCK); continue; } +#endif if (policy_mgr_concurrent_open_sessions_running(mac_ctx->psoc) && !csr_is_valid_mc_concurrent_session(mac_ctx, vdev_id, &result->BssDescriptor)) {