From c65575e5437b002564ee2acc0ec9a4fb061aa222 Mon Sep 17 00:00:00 2001 From: Ajit Pal Singh Date: Mon, 17 Apr 2017 16:49:01 +0530 Subject: [PATCH] qcacmn: Add API to check Do Not Break Stream eligibility 1) Adds new policy mgr API 'policy_mgr_is_chan_ok_for_dnbs' to check if a channel is OK for "Do Not Break Stream". It means that if Do_Not_Switch_Channel is set for AP/GO vdev, the channel passed should be either the AP/GO channel or a channel from the other band. 2) Adds a new function policy_mgr_get_mode_specific_conn_info() to get the mode specific connection count. Change-Id: I4da6f7d56d01b01761a5f3557b8acbb84226a6fd CRs-Fixed: 2037302 --- inc/wlan_policy_mgr_api.h | 14 +++++ src/wlan_policy_mgr_get_set_utils.c | 87 +++++++++++++++++++++++++++-- src/wlan_policy_mgr_i.h | 28 ++++++++++ src/wlan_policy_mgr_pcl.c | 42 ++++++++++++++ 4 files changed, 166 insertions(+), 5 deletions(-) diff --git a/inc/wlan_policy_mgr_api.h b/inc/wlan_policy_mgr_api.h index fd618266564f..783bf78d165d 100644 --- a/inc/wlan_policy_mgr_api.h +++ b/inc/wlan_policy_mgr_api.h @@ -1845,4 +1845,18 @@ void policy_mgr_update_old_hw_mode_index(struct wlan_objmgr_psoc *psoc, */ void policy_mgr_update_new_hw_mode_index(struct wlan_objmgr_psoc *psoc, uint32_t new_hw_mode_index); + +/** + * policy_mgr_is_chan_ok_for_dnbs() - Function to check if a channel + * is OK for "Do Not Break Stream" + * @psoc: PSOC object information + * @channel: Channel to check. + * @ok: Pointer to flag in which status will be stored + * This function checks if a channel is OK for + * "Do Not Break Stream" + * Return: SUCCESS or FAILURE + */ +QDF_STATUS policy_mgr_is_chan_ok_for_dnbs(struct wlan_objmgr_psoc *psoc, + uint8_t channel, bool *ok); + #endif /* __WLAN_POLICY_MGR_API_H */ diff --git a/src/wlan_policy_mgr_get_set_utils.c b/src/wlan_policy_mgr_get_set_utils.c index 380dae5a07d7..9c2f9054e491 100644 --- a/src/wlan_policy_mgr_get_set_utils.c +++ b/src/wlan_policy_mgr_get_set_utils.c @@ -39,6 +39,8 @@ #include "qdf_types.h" #include "qdf_trace.h" #include "wlan_objmgr_global_obj.h" +#include "wlan_objmgr_pdev_obj.h" +#include "wlan_objmgr_vdev_obj.h" /* invalid channel id. */ #define INVALID_CHANNEL_ID 0 @@ -1355,9 +1357,11 @@ bool policy_mgr_is_ibss_conn_exist(struct wlan_objmgr_psoc *psoc, return status; } -bool policy_mgr_get_sap_conn_info(struct wlan_objmgr_psoc *psoc, - uint8_t *channel, uint8_t *vdev_id) +bool policy_mgr_get_mode_specific_conn_info(struct wlan_objmgr_psoc *psoc, + uint8_t *channel, uint8_t *vdev_id, + enum policy_mgr_con_mode mode) { + uint32_t count, index = 0; uint32_t list[MAX_NUMBER_OF_CONC_CONNECTIONS]; bool status = false; @@ -1374,10 +1378,10 @@ bool policy_mgr_get_sap_conn_info(struct wlan_objmgr_psoc *psoc, } count = policy_mgr_mode_specific_connection_count( - psoc, PM_SAP_MODE, list); + psoc, mode, list); qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock); if (count == 0) { - policy_mgr_err("No SAP connection"); + policy_mgr_err("No mode:[%d] connection", mode); status = false; } else if (count == 1) { *channel = pm_conc_connection_list[list[index]].chan; @@ -1393,7 +1397,8 @@ bool policy_mgr_get_sap_conn_info(struct wlan_objmgr_psoc *psoc, *channel = pm_conc_connection_list[list[index]].chan; *vdev_id = pm_conc_connection_list[list[index]].vdev_id; - policy_mgr_notice("Multiple SAP connections, picking first one"); + policy_mgr_notice("Multiple mode:[%d] connections, picking first one", + mode); status = true; } qdf_mutex_release(&pm_ctx->qdf_conc_list_lock); @@ -1401,6 +1406,15 @@ bool policy_mgr_get_sap_conn_info(struct wlan_objmgr_psoc *psoc, return status; } +bool policy_mgr_get_sap_conn_info(struct wlan_objmgr_psoc *psoc, + uint8_t *channel, uint8_t *vdev_id) +{ + return policy_mgr_get_mode_specific_conn_info(psoc, + channel, + vdev_id, + PM_SAP_MODE); +} + bool policy_mgr_max_concurrent_connections_reached( struct wlan_objmgr_psoc *psoc) { @@ -2358,3 +2372,66 @@ bool policy_mgr_is_hw_mode_change_after_vdev_up(struct wlan_objmgr_psoc *psoc) return flag; } + +bool policy_mgr_vdev_mlme_is_dnsc_set(struct wlan_objmgr_vdev *vdev) +{ + /* TODO : Check Dont_Switch_Channel status from vdev mlme caps*/ + return false; +} + +QDF_STATUS policy_mgr_is_chan_ok_for_dnbs(struct wlan_objmgr_psoc *psoc, + uint8_t channel, bool *ok) +{ + uint8_t operating_channel = 0, vdev_id = 0; + struct wlan_objmgr_vdev *vdev; + + if (!channel || !ok) { + policy_mgr_err("Invalid parameter"); + return QDF_STATUS_E_INVAL; + } + + if (policy_mgr_get_mode_specific_conn_info(psoc, + &operating_channel, + &vdev_id, + PM_SAP_MODE)) + policy_mgr_debug("SAP mode active"); + else if (policy_mgr_get_mode_specific_conn_info(psoc, + &operating_channel, + &vdev_id, + PM_P2P_GO_MODE)) + policy_mgr_debug("P2P_GO_MODE mode active"); + else { + *ok = true; + return QDF_STATUS_SUCCESS; + } + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, + WLAN_POLICY_MGR_ID); + if (!vdev) { + policy_mgr_err("vdev is NULL"); + return QDF_STATUS_E_INVAL; + } + + /** + * If channel passed is same as AP/GO operating channel, then + * return true. + * If channel is different from operating channel but in same band. + * return false. + * If operating channel in different band. + * return true. + */ + /* TODO: To be enhanced for SBS */ + if (policy_mgr_vdev_mlme_is_dnsc_set(vdev)) { + if (operating_channel == channel) + *ok = true; + else if (WLAN_REG_IS_SAME_BAND_CHANNELS(operating_channel, + channel)) + *ok = false; + else + *ok = true; + } else { + *ok = true; + } + wlan_objmgr_vdev_release_ref(vdev, WLAN_POLICY_MGR_ID); + return QDF_STATUS_SUCCESS; +} diff --git a/src/wlan_policy_mgr_i.h b/src/wlan_policy_mgr_i.h index 8dd4e4ddb457..9a48a16fc32e 100644 --- a/src/wlan_policy_mgr_i.h +++ b/src/wlan_policy_mgr_i.h @@ -398,4 +398,32 @@ QDF_STATUS policy_mgr_reset_sap_mandatory_channels( */ bool policy_mgr_get_sap_conn_info(struct wlan_objmgr_psoc *psoc, uint8_t *channel, uint8_t *vdev_id); + +/** + * policy_mgr_get_mode_specific_conn_info() - Get active mode specific + * channel and vdev id + * @psoc: PSOC object information + * @channel: Mode specific channel + * @vdev_id: Mode specific vdev id + * @mode: Connection Mode + * + * Get active mode specific channel and vdev id + * + * Return: true for success, else false + */ +bool policy_mgr_get_mode_specific_conn_info(struct wlan_objmgr_psoc *psoc, + uint8_t *channel, uint8_t *vdev_id, + enum policy_mgr_con_mode mode); + +/** + * policy_mgr_vdev_mlme_is_dnsc_set - Check if user has set + * "Do_Not_Switch_Channel" for this vdev + * @vdev: vdev pointer + * + * Get "Do_Not_Switch_Channel" setting for this vdev + * + * Return: true for success, else false + */ +bool policy_mgr_vdev_mlme_is_dnsc_set(struct wlan_objmgr_vdev *vdev); + #endif diff --git a/src/wlan_policy_mgr_pcl.c b/src/wlan_policy_mgr_pcl.c index 364bced7357d..88f35b2ad34e 100644 --- a/src/wlan_policy_mgr_pcl.c +++ b/src/wlan_policy_mgr_pcl.c @@ -166,6 +166,41 @@ static QDF_STATUS policy_mgr_modify_pcl_based_on_enabled_channels( return QDF_STATUS_SUCCESS; } +static QDF_STATUS policy_mgr_modify_pcl_based_on_dnbs( + struct wlan_objmgr_psoc *psoc, + uint8_t *pcl_list_org, + uint8_t *weight_list_org, + uint32_t *pcl_len_org) +{ + uint32_t i, pcl_len = 0; + uint8_t pcl_list[QDF_MAX_NUM_CHAN]; + uint8_t weight_list[QDF_MAX_NUM_CHAN]; + bool ok; + int ret; + + for (i = 0; i < *pcl_len_org; i++) { + ret = policy_mgr_is_chan_ok_for_dnbs(psoc, pcl_list_org[i], + &ok); + + if (QDF_IS_STATUS_ERROR(ret)) { + policy_mgr_err("Not able to check DNBS eligibility"); + return ret; + } + if (ok) { + pcl_list[pcl_len] = pcl_list_org[i]; + weight_list[pcl_len++] = weight_list_org[i]; + } + } + + qdf_mem_zero(pcl_list_org, QDF_ARRAY_SIZE(pcl_list_org)); + qdf_mem_zero(weight_list_org, QDF_ARRAY_SIZE(weight_list_org)); + qdf_mem_copy(pcl_list_org, pcl_list, pcl_len); + qdf_mem_copy(weight_list_org, weight_list, pcl_len); + *pcl_len_org = pcl_len; + + return QDF_STATUS_SUCCESS; +} + uint8_t policy_mgr_get_channel(struct wlan_objmgr_psoc *psoc, enum policy_mgr_con_mode mode, uint32_t *vdev_id) { @@ -333,6 +368,13 @@ QDF_STATUS policy_mgr_get_pcl(struct wlan_objmgr_psoc *psoc, pcl_channels[i], pcl_weight[i]); } + status = policy_mgr_modify_pcl_based_on_dnbs(psoc, pcl_channels, + pcl_weight, len); + + if (QDF_IS_STATUS_ERROR(status)) { + policy_mgr_err("failed to get modified pcl based on DNBS"); + return status; + } return QDF_STATUS_SUCCESS; }