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
This commit is contained in:
Ajit Pal Singh 2017-04-17 16:49:01 +05:30 • committed by snandini
commit ec973b0aa7
5 changed files with 192 additions and 6 deletions

View file

@ -34,6 +34,7 @@
#include <wlan_cfg80211_scan.h>
#include <qdf_mem.h>
#include <wlan_utility.h>
#include <wlan_policy_mgr_api.h>
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
static uint32_t hdd_config_sched_scan_start_delay(
@ -945,10 +946,35 @@ int wlan_cfg80211_scan(struct wlan_objmgr_pdev *pdev,
if (request->n_channels) {
char chl[(request->n_channels * 5) + 1];
int len = 0;
bool ap_or_go_present =
policy_mgr_mode_specific_connection_count(
psoc, QDF_SAP_MODE, NULL) ||
policy_mgr_mode_specific_connection_count(
psoc, QDF_P2P_GO_MODE, NULL);
for (i = 0; i < request->n_channels; i++) {
channel = request->channels[i]->hw_value;
if (wlan_is_dsrc_channel(wlan_chan_to_freq(channel)))
continue;
if (ap_or_go_present) {
bool ok;
int ret;
ret = policy_mgr_is_chan_ok_for_dnbs(psoc,
channel,
&ok);
if (QDF_IS_STATUS_ERROR(ret)) {
cfg80211_err("DNBS check failed");
qdf_mem_free(req);
status = -EINVAL;
goto end;
}
if (!ok)
continue;
}
len += snprintf(chl + len, 5, "%d ", channel);
req->scan_req.chan_list[i] = wlan_chan_to_freq(channel);
num_chan++;
@ -1296,4 +1322,3 @@ void wlan_cfg80211_inform_bss_frame(struct wlan_objmgr_pdev *pdev,
frame_len, rssi, GFP_KERNEL);
qdf_mem_free(mgmt);
}

View file

@ -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 */

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}