diff --git a/components/cmn_services/interface_mgr/src/wlan_if_mgr_sta.c b/components/cmn_services/interface_mgr/src/wlan_if_mgr_sta.c index 9d8525bcb5..f8c3a186ff 100644 --- a/components/cmn_services/interface_mgr/src/wlan_if_mgr_sta.c +++ b/components/cmn_services/interface_mgr/src/wlan_if_mgr_sta.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -32,7 +32,7 @@ #include #include #include -#include +#include QDF_STATUS if_mgr_connect_start(struct wlan_objmgr_vdev *vdev, struct if_mgr_event_data *event_data) @@ -155,24 +155,26 @@ if_mgr_mlo_get_affected_links_for_sbs(struct wlan_objmgr_psoc *psoc, uint8_t *mlo_idx, qdf_freq_t freq) { uint8_t i = 0; + bool same_band_sta_allowed; /* - * STA freq: STA ML combo: SBS Action + * STA freq: ML STA combo: SBS Action * --------------------------------------------------- * 2Ghz 2Ghz+5/6Ghz Disable 2Ghz(Same MAC) - * 5Ghz 2Ghz+5/6Ghz Disable 2.4Ghz if 5Ghz lead to SBS - * (SBS, same MAC), else disable 5/6Ghz + * 5Ghz 2Ghz+5/6Ghz Disable 2.4Ghz if 5Ghz lead to SBS + * (SBS, same MAC) and same band STA + * allowed, else disable 5/6Ghz * (NON SBS, same MAC) * 5Ghz(lower) 5Ghz+6Ghz Disable 5Ghz (NON SBS, same MAC) * 5Ghz(higher) 5Ghz+6Ghz Disable 6Ghz (NON SBS, Same MAC) * 2Ghz 5Ghz+6Ghz Disable Any */ - /* If legacy STA is 2.4Ghz disable 2.4Ghz if present OR disable any */ + /* If non-ML STA is 2.4Ghz disable 2.4Ghz if present OR disable any */ if (wlan_reg_is_24ghz_ch_freq(freq)) { while (i < num_mlo) { if (wlan_reg_is_24ghz_ch_freq(freq_list[mlo_idx[i]])) { - /* Affected MLO link on 2.4Ghz */ + /* Affected ML STA link on 2.4Ghz */ mlo_vdev_lst[0] = vdev_id_list[mlo_idx[i]]; return 1; } @@ -184,7 +186,23 @@ if_mgr_mlo_get_affected_links_for_sbs(struct wlan_objmgr_psoc *psoc, return i; } - /* This mean legasy STA is 5Ghz */ + /* This mean non-ML STA is 5Ghz */ + + /* check if ML STA is DBS */ + i = 0; + while (i < num_mlo && + !wlan_reg_is_24ghz_ch_freq(freq_list[mlo_idx[i]])) + i++; + + same_band_sta_allowed = wlan_cm_same_band_sta_allowed(psoc); + + /* + * if ML STA is DBS ie 2.4Ghz link present and if same_band_sta_allowed + * is false, disable 5/6Ghz link to make sure we dont have all link + * on 5Ghz + */ + if (i < num_mlo && !same_band_sta_allowed) + goto check_dbs_mlo; /* check if any link lead to SBS, so that we can disable the other*/ i = 0; @@ -194,14 +212,14 @@ if_mgr_mlo_get_affected_links_for_sbs(struct wlan_objmgr_psoc *psoc, /* * if i < num_mlo then i is the SBS link, in this case disable the other - * non SBS link, this mean MLO is 5+6 or 2+5/6. + * non SBS link, this mean ML STA is 5+6 or 2+5/6. */ if (i < num_mlo) { i = 0; while (i < num_mlo) { if (!policy_mgr_are_sbs_chan(psoc, freq, freq_list[mlo_idx[i]])) { - /* Affected non SBS MLO link */ + /* Affected non SBS ML STA link */ mlo_vdev_lst[0] = vdev_id_list[mlo_idx[i]]; return 1; } @@ -213,14 +231,15 @@ if_mgr_mlo_get_affected_links_for_sbs(struct wlan_objmgr_psoc *psoc, return i; } +check_dbs_mlo: /* - * None of the link can lead to SBS, i.e. its 2+ 5/6 MLO in this case - * disabel 5Ghz link. + * None of the link can lead to SBS, i.e. its 2+ 5/6 ML STA in this case + * disable 5Ghz link. */ i = 0; while (i < num_mlo) { if (!wlan_reg_is_24ghz_ch_freq(freq_list[mlo_idx[i]])) { - /* Affected 5/6Ghz MLO link */ + /* Affected 5/6Ghz ML STA link */ mlo_vdev_lst[0] = vdev_id_list[mlo_idx[i]]; return 1; } diff --git a/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_api.h b/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_api.h index a112c29e09..aae31b3ccd 100644 --- a/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_api.h +++ b/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_api.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -812,23 +812,6 @@ void wlan_cm_roam_activate_pcl_per_vdev(struct wlan_objmgr_psoc *psoc, bool wlan_cm_roam_is_pcl_per_vdev_active(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id); -/** - * wlan_cm_dual_sta_is_freq_allowed() - This API is used to check if the - * provided frequency is allowed for the 2nd STA vdev for connection. - * @psoc: Pointer to PSOC object - * @freq: Frequency in the given frequency list for the STA that is about to - * connect - * @opmode: Operational mode - * - * This API will be called while filling scan filter channels during connection. - * - * Return: True if this channel is allowed for connection when dual sta roaming - * is enabled - */ -bool -wlan_cm_dual_sta_is_freq_allowed(struct wlan_objmgr_psoc *psoc, uint32_t freq, - enum QDF_OPMODE opmode); - /** * wlan_cm_dual_sta_roam_update_connect_channels() - Fill the allowed channels * for connection of the 2nd STA based on the 1st STA connected band if dual @@ -1150,13 +1133,6 @@ bool wlan_cm_roam_is_pcl_per_vdev_active(struct wlan_objmgr_psoc *psoc, return false; } -static inline bool -wlan_cm_dual_sta_is_freq_allowed(struct wlan_objmgr_psoc *psoc, uint32_t freq, - enum QDF_OPMODE opmode) -{ - return true; -} - static inline void wlan_cm_dual_sta_roam_update_connect_channels(struct wlan_objmgr_psoc *psoc, struct scan_filter *filter) @@ -1572,4 +1548,14 @@ wlan_cm_fw_to_host_phymode(WMI_HOST_WLAN_PHY_MODE phymode); QDF_STATUS wlan_cm_sta_mlme_vdev_roam_notify(struct vdev_mlme_obj *vdev_mlme, uint16_t data_len, void *data); + +/** + * wlan_cm_same_band_sta_allowed() - check if same band STA +STA is allowed + * + * @psoc: psoc ptr + * + * Return: true if same band STA+STA is allowed + */ +bool wlan_cm_same_band_sta_allowed(struct wlan_objmgr_psoc *psoc); + #endif /* WLAN_CM_ROAM_API_H__ */ diff --git a/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_api.c b/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_api.c index cb54c03084..c0b68d7b39 100644 --- a/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_api.c +++ b/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_api.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -294,6 +294,25 @@ QDF_STATUS wlan_cm_roam_stop_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, return cm_roam_stop_req(psoc, vdev_id, reason); } +bool wlan_cm_same_band_sta_allowed(struct wlan_objmgr_psoc *psoc) +{ + struct wlan_mlme_psoc_ext_obj *mlme_obj; + struct dual_sta_policy *dual_sta_policy; + + if (!wlan_mlme_get_dual_sta_roaming_enabled(psoc)) + return true; + + mlme_obj = mlme_get_psoc_ext_obj(psoc); + if (!mlme_obj) + return true; + + dual_sta_policy = &mlme_obj->cfg.gen.dual_sta_policy; + if (dual_sta_policy->primary_vdev_id != WLAN_UMAC_VDEV_ID_MAX) + return true; + + return false; +} + #ifdef WLAN_FEATURE_ROAM_OFFLOAD QDF_STATUS wlan_cm_fw_roam_abort_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id) @@ -414,62 +433,34 @@ bool wlan_cm_roam_is_pcl_per_vdev_active(struct wlan_objmgr_psoc *psoc, return mlme_priv->cm_roam.pcl_vdev_cmd_active; } -bool +/** + * wlan_cm_dual_sta_is_freq_allowed() - This API is used to check if the + * provided frequency is allowed for the 2nd STA vdev for connection. + * @psoc: Pointer to PSOC object + * @freq: Frequency in the given frequency list for the STA that is about to + * connect + * @connected_sta_freq: 1st connected sta freq + * @opmode: Operational mode + * + * Make sure to validate the STA+STA condition before calling this + * + * Return: True if this channel is allowed for connection when dual sta roaming + * is enabled + */ +static bool wlan_cm_dual_sta_is_freq_allowed(struct wlan_objmgr_psoc *psoc, - uint32_t freq, + uint32_t freq, qdf_freq_t connected_sta_freq, enum QDF_OPMODE opmode) { - uint32_t op_ch_freq_list[MAX_NUMBER_OF_CONC_CONNECTIONS]; - uint8_t vdev_id_list[MAX_NUMBER_OF_CONC_CONNECTIONS]; enum reg_wifi_band band; - uint32_t count, connected_sta_freq; - struct wlan_mlme_psoc_ext_obj *mlme_obj; - struct dual_sta_policy *dual_sta_policy; - mlme_obj = mlme_get_psoc_ext_obj(psoc); - if (!mlme_obj) - return QDF_STATUS_E_FAILURE; - - /* - * Check if primary iface is configured. If yes, - * then allow further STA connection to all - * available bands/channels irrespective of first - * STA connection band, which allow driver to - * connect with the best available AP present in - * environment, so that user can switch to second - * connection and mark it as primary. - */ - dual_sta_policy = &mlme_obj->cfg.gen.dual_sta_policy; - if (dual_sta_policy->primary_vdev_id != WLAN_UMAC_VDEV_ID_MAX) { - mlme_debug("primary iface is configured, vdev_id: %d", - dual_sta_policy->primary_vdev_id); - return true; - } - - /* - * Check if already there is 1 STA connected. If this API is - * called for 2nd STA and if dual sta roaming is enabled, then - * don't allow the intra band frequencies of the 1st sta for - * connection on 2nd STA. - */ - count = policy_mgr_get_mode_specific_conn_info(psoc, op_ch_freq_list, - vdev_id_list, - PM_STA_MODE); - if (!count || !wlan_mlme_get_dual_sta_roaming_enabled(psoc) || - opmode != QDF_STA_MODE) + if (opmode != QDF_STA_MODE || !connected_sta_freq) return true; - /* - * For MLO STA scenario, allow further STA connections to all available - * bands/channels irrespective of existing STA connection band. - */ - if (policy_mgr_is_mlo_sta_present(psoc)) - return true; - - connected_sta_freq = op_ch_freq_list[0]; band = wlan_reg_freq_to_band(connected_sta_freq); + /* Reject if both are 2.4Ghz or both are not 2.4Ghz (5Ghz or 6Ghz) */ if ((band == REG_BAND_2G && WLAN_REG_IS_24GHZ_CH_FREQ(freq)) || - (band == REG_BAND_5G && !WLAN_REG_IS_24GHZ_CH_FREQ(freq))) + (band != REG_BAND_2G && !WLAN_REG_IS_24GHZ_CH_FREQ(freq))) return false; return true; @@ -489,10 +480,14 @@ wlan_cm_dual_sta_roam_update_connect_channels(struct wlan_objmgr_psoc *psoc, char *chan_buff; uint32_t len = 0; uint32_t sta_count; + bool mlo_sta_present, sbs_mlo_sta_present = false; + qdf_freq_t op_ch_freq_list[MAX_NUMBER_OF_CONC_CONNECTIONS] = {0}; + uint8_t vdev_id_list[MAX_NUMBER_OF_CONC_CONNECTIONS] = {0}; filter->num_of_channels = 0; - sta_count = policy_mgr_mode_specific_connection_count(psoc, - PM_STA_MODE, NULL); + sta_count = policy_mgr_get_mode_specific_conn_info(psoc, op_ch_freq_list, + vdev_id_list, + PM_STA_MODE); /* No need to fill freq list, if no other STA is in conencted state */ if (!sta_count) @@ -523,6 +518,26 @@ wlan_cm_dual_sta_roam_update_connect_channels(struct wlan_objmgr_psoc *psoc, if (dual_sta_policy->primary_vdev_id != WLAN_UMAC_VDEV_ID_MAX) return; + mlo_sta_present = policy_mgr_is_mlo_sta_present(psoc); + /* check for SBS mlo if MLO sta is present and sta cnt > 1 */ + if (mlo_sta_present && sta_count > 1) + sbs_mlo_sta_present = + policy_mgr_is_mlo_in_mode_sbs(psoc, PM_STA_MODE, + NULL, NULL); + + mlme_debug("mlo_sta_present %d sbs_mlo_sta_present %d", + mlo_sta_present, sbs_mlo_sta_present); + + /* + * For ML STA (non-SBS) scenario, allow further STA connections to + * all available bands/channels irrespective of existing STA + * connection band. + * But if ML STA is SBS (both link 5Ghz), allow only 2.4Ghz STA + * connection + */ + if (mlo_sta_present && !sbs_mlo_sta_present) + return; + /* * Get Reg domain valid channels and update to the scan filter * if already 1st sta is in connected state. Don't allow channels @@ -544,6 +559,7 @@ wlan_cm_dual_sta_roam_update_connect_channels(struct wlan_objmgr_psoc *psoc, for (i = 0; i < num_channels; i++) { is_ch_allowed = wlan_cm_dual_sta_is_freq_allowed(psoc, channel_list[i], + op_ch_freq_list[0], QDF_STA_MODE); if (!is_ch_allowed) continue;