diff --git a/umac/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h b/umac/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h index 192f32db31c0..d676607acd69 100644 --- a/umac/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h +++ b/umac/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h @@ -395,6 +395,31 @@ bool policy_mgr_allow_concurrency(struct wlan_objmgr_psoc *psoc, enum policy_mgr_con_mode mode, uint8_t channel, enum hw_mode_bandwidth bw); +/** + * policy_mgr_allow_concurrency_csa() - Check for allowed concurrency + * combination when channel switch + * @psoc: PSOC object information + * @mode: connection mode + * @channel: target channel to switch + * @vdev_id: vdev id of channel switch interface + * + * There is already existing SAP+GO combination but due to upper layer + * notifying LTE-COEX event or sending command to move one of the connections + * to different channel. In such cases before moving existing connection to new + * channel, check if new channel can co-exist with the other existing + * connection. For example, one SAP1 is on channel-6 and second SAP2 is on + * channel-36 and lets say they are doing DBS, and lets say upper layer sends + * LTE-COEX to move SAP1 from channel-6 to channel-149. In this case, SAP1 and + * SAP2 will end up doing MCC which may not be desirable result. such cases + * will be prevented with this API. + * + * Return: True/False + */ +bool policy_mgr_allow_concurrency_csa(struct wlan_objmgr_psoc *psoc, + enum policy_mgr_con_mode mode, + uint8_t channel, + uint32_t vdev_id); + /** * policy_mgr_get_first_connection_pcl_table_index() - provides the * row index to firstConnectionPclTable to get to the correct diff --git a/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_core.c b/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_core.c index e7f2303e8fa1..2ddbbd3f3986 100644 --- a/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_core.c +++ b/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_core.c @@ -720,6 +720,48 @@ void policy_mgr_store_and_del_conn_info(struct wlan_objmgr_psoc *psoc, */ } +void policy_mgr_store_and_del_conn_info_by_vdev_id( + struct wlan_objmgr_psoc *psoc, + uint32_t vdev_id, + struct policy_mgr_conc_connection_info *info, + uint8_t *num_cxn_del) +{ + uint32_t conn_index = 0; + struct policy_mgr_psoc_priv_obj *pm_ctx; + + if (!info || !num_cxn_del) { + policy_mgr_err("Invalid parameters"); + return; + } + *num_cxn_del = 0; + pm_ctx = policy_mgr_get_context(psoc); + if (!pm_ctx) { + policy_mgr_err("Invalid Context"); + return; + } + qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock); + for (conn_index = 0; conn_index < MAX_NUMBER_OF_CONC_CONNECTIONS; + conn_index++) { + if ((pm_conc_connection_list[conn_index].vdev_id == vdev_id) && + pm_conc_connection_list[conn_index].in_use) { + *num_cxn_del = 1; + break; + } + } + /* + * Storing the connection entry which will be + * temporarily deleted. + */ + if (*num_cxn_del == 1) { + *info = pm_conc_connection_list[conn_index]; + /* Deleting the connection entry */ + policy_mgr_decr_connection_count( + psoc, + pm_conc_connection_list[conn_index].vdev_id); + } + qdf_mutex_release(&pm_ctx->qdf_conc_list_lock); +} + /** * policy_mgr_restore_deleted_conn_info() - Restore connection info * @info: An array saving connection info that is to be restored diff --git a/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c b/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c index 58fb43f4b187..e4490593758d 100644 --- a/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c +++ b/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c @@ -1862,6 +1862,37 @@ bool policy_mgr_allow_concurrency(struct wlan_objmgr_psoc *psoc, return policy_mgr_is_concurrency_allowed(psoc, mode, channel, bw); } +bool policy_mgr_allow_concurrency_csa(struct wlan_objmgr_psoc *psoc, + enum policy_mgr_con_mode mode, + uint8_t channel, + uint32_t vdev_id) +{ + bool allow = false; + struct policy_mgr_conc_connection_info info; + uint8_t num_cxn_del = 0; + + /* + * Store the connection's parameter and temporarily delete it + * from the concurrency table. This way the allow concurrency + * check can be used as though a new connection is coming up, + * after check, restore the connection to concurrency table. + */ + policy_mgr_store_and_del_conn_info_by_vdev_id(psoc, vdev_id, + &info, &num_cxn_del); + allow = policy_mgr_allow_concurrency( + psoc, + mode, + channel, + HW_MODE_20_MHZ); + if (!allow) + policy_mgr_err("CSA concurrency check failed"); + /* Restore the connection entry */ + if (num_cxn_del > 0) + policy_mgr_restore_deleted_conn_info(psoc, &info, num_cxn_del); + + return allow; +} + /** * policy_mgr_get_concurrency_mode() - return concurrency mode * @psoc: PSOC object information diff --git a/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_i.h b/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_i.h index cf6ac6d943af..ba2f708ae1d2 100644 --- a/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_i.h +++ b/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_i.h @@ -382,6 +382,27 @@ void policy_mgr_store_and_del_conn_info(struct wlan_objmgr_psoc *psoc, bool all_matching_cxn_to_del, struct policy_mgr_conc_connection_info *info, uint8_t *num_cxn_del); + +/** + * policy_mgr_store_and_del_conn_info_by_vdev_id() - Store and del a + * connection info by vdev id + * @psoc: PSOC object information + * @vdev_id: vdev id whose entry has to be deleted + * @info: struture array pointer where the connection info will be saved + * @num_cxn_del: number of connection which are going to be deleted + * + * Saves the connection info corresponding to the provided mode + * and deleted that corresponding entry based on vdev from the + * connection info structure + * + * Return: None + */ +void policy_mgr_store_and_del_conn_info_by_vdev_id( + struct wlan_objmgr_psoc *psoc, + uint32_t vdev_id, + struct policy_mgr_conc_connection_info *info, + uint8_t *num_cxn_del); + void policy_mgr_restore_deleted_conn_info(struct wlan_objmgr_psoc *psoc, struct policy_mgr_conc_connection_info *info, uint8_t num_cxn_del);