qcacld-3.0: Changes for early stop scan

Early stop scan is a feature for roaming to stop the scans at
an early stage as soon as we find a better AP to roam. This
would make the roaming happen quickly.

Apart from sending the configuration items, the host also
has to send down the channel list in a sorted order
to optimize the scans and meet the requirement of this
feature.

This feature is currently applicable only to roaming
scans. However the sorted order of scan list will be
the same used by all the scans.

CRs-Fixed: 932431
Change-Id: I9c7300e4922cb0d517c248bcf60f681a5872a315
This commit is contained in:
Varun Reddy Yeturu 2015-09-28 17:12:33 -07:00 committed by Prakash Dhavali
parent b43fda1ddd
commit 0518629d50
9 changed files with 264 additions and 0 deletions

View File

@ -2700,6 +2700,37 @@ enum dot11p_mode {
#define CFG_CHANNEL_PREDICTION_FULL_SCAN_MS_MAX (0x7fffffff)
#define CFG_CHANNEL_PREDICTION_FULL_SCAN_MS_DEFAULT (60000)
/*
* Early stop scan is a feature for roaming to stop the scans at
* an early stage as soon as we find a better AP to roam. This
* would make the roaming happen quickly.
*/
#define CFG_EARLY_STOP_SCAN_ENABLE "gEnableEarlyStopScan"
#define CFG_EARLY_STOP_SCAN_ENABLE_MIN (0)
#define CFG_EARLY_STOP_SCAN_ENABLE_MAX (1)
#define CFG_EARLY_STOP_SCAN_ENABLE_DEFAULT (0)
/*
* Early stop scan minimum threshold is the minimum threshold
* at which the candidate AP should be to be qualified as a
* potential roam candidate and good enough to stop the roaming scan
*/
#define CFG_EARLY_STOP_SCAN_MIN_THRESHOLD "gEarlyStopScanMinThreshold"
#define CFG_EARLY_STOP_SCAN_MIN_THRESHOLD_MIN (-60)
#define CFG_EARLY_STOP_SCAN_MIN_THRESHOLD_MAX (-40)
#define CFG_EARLY_STOP_SCAN_MIN_THRESHOLD_DEFAULT (-45)
/*
* Early stop scan maximum threshold is the maximum threshold
* to be considered for stopping the scan. The algorithm starts
* with a scan on the greedy channel list with the minimum threshold
* and steps up the threshold by 20% for each further channel.
* It can step up on each channel but cannot exceed the maximum
* threshold.
*/
#define CFG_EARLY_STOP_SCAN_MAX_THRESHOLD "gEarlyStopScanMaxThreshold"
#define CFG_EARLY_STOP_SCAN_MAX_THRESHOLD_MIN (-80)
#define CFG_EARLY_STOP_SCAN_MAX_THRESHOLD_MAX (-70)
#define CFG_EARLY_STOP_SCAN_MAX_THRESHOLD_DEFAULT (-78)
/*---------------------------------------------------------------------------
Type declarations
-------------------------------------------------------------------------*/
@ -3264,6 +3295,9 @@ struct hdd_config {
uint8_t stationary_thresh;
uint32_t channel_prediction_full_scan;
#endif
bool early_stop_scan_enable;
int8_t early_stop_scan_min_threshold;
int8_t early_stop_scan_max_threshold;
};
#define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var))

View File

@ -3517,6 +3517,29 @@ REG_TABLE_ENTRY g_registry_table[] = {
CFG_SELF_GEN_FRM_PWR_MIN,
CFG_SELF_GEN_FRM_PWR_MAX),
REG_VARIABLE(CFG_EARLY_STOP_SCAN_ENABLE, WLAN_PARAM_Integer,
struct hdd_config, early_stop_scan_enable,
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
CFG_EARLY_STOP_SCAN_ENABLE_DEFAULT,
CFG_EARLY_STOP_SCAN_ENABLE_MIN,
CFG_EARLY_STOP_SCAN_ENABLE_MAX),
REG_VARIABLE(CFG_EARLY_STOP_SCAN_MIN_THRESHOLD,
WLAN_PARAM_SignedInteger, struct hdd_config,
early_stop_scan_min_threshold,
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
CFG_EARLY_STOP_SCAN_MIN_THRESHOLD_DEFAULT,
CFG_EARLY_STOP_SCAN_MIN_THRESHOLD_MIN,
CFG_EARLY_STOP_SCAN_MIN_THRESHOLD_MAX),
REG_VARIABLE(CFG_EARLY_STOP_SCAN_MAX_THRESHOLD,
WLAN_PARAM_SignedInteger, struct hdd_config,
early_stop_scan_max_threshold,
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
CFG_EARLY_STOP_SCAN_MAX_THRESHOLD_DEFAULT,
CFG_EARLY_STOP_SCAN_MAX_THRESHOLD_MIN,
CFG_EARLY_STOP_SCAN_MAX_THRESHOLD_MAX),
};
@ -5050,6 +5073,16 @@ void hdd_cfg_print(hdd_context_t *pHddCtx)
CFG_CHANNEL_PREDICTION_FULL_SCAN_MS_NAME,
pHddCtx->config->channel_prediction_full_scan);
#endif
hddLog(LOGE, "Name = [%s] Value = [%d]",
CFG_EARLY_STOP_SCAN_ENABLE,
pHddCtx->config->early_stop_scan_enable);
hddLog(LOGE, "Name = [%s] Value = [%d]",
CFG_EARLY_STOP_SCAN_MIN_THRESHOLD,
pHddCtx->config->early_stop_scan_min_threshold);
hddLog(LOGE, "Name = [%s] Value = [%d]",
CFG_EARLY_STOP_SCAN_MAX_THRESHOLD,
pHddCtx->config->early_stop_scan_max_threshold);
}
@ -6462,6 +6495,12 @@ CDF_STATUS hdd_set_sme_config(hdd_context_t *pHddCtx)
(pHddCtx->config->dot11p_mode != WLAN_HDD_11P_DISABLED);
hdd_set_pno_channel_prediction_config(smeConfig, pHddCtx);
smeConfig->early_stop_scan_enable =
pHddCtx->config->early_stop_scan_enable;
smeConfig->early_stop_scan_min_threshold =
pHddCtx->config->early_stop_scan_min_threshold;
smeConfig->early_stop_scan_max_threshold =
pHddCtx->config->early_stop_scan_max_threshold;
status = sme_update_config(pHddCtx->hHal, smeConfig);
if (!CDF_IS_STATUS_SUCCESS(status)) {
hddLog(LOGE, "sme_update_config() return failure %d",

View File

@ -2900,6 +2900,9 @@ typedef struct sSirRoamOffloadScanReq {
uint32_t hi_rssi_scan_rssi_delta;
uint32_t hi_rssi_scan_delay;
int32_t hi_rssi_scan_rssi_ub;
uint8_t early_stop_scan_enable;
int8_t early_stop_scan_min_threshold;
int8_t early_stop_scan_max_threshold;
} tSirRoamOffloadScanReq, *tpSirRoamOffloadScanReq;
typedef struct sSirRoamOffloadScanRsp {

View File

@ -1269,6 +1269,9 @@ typedef struct tagCsrConfigParam {
uint8_t stationary_thresh;
uint32_t channel_prediction_full_scan;
#endif
bool early_stop_scan_enable;
int8_t early_stop_scan_min_threshold;
int8_t early_stop_scan_max_threshold;
} tCsrConfigParam;
/* Tush */

View File

@ -651,6 +651,9 @@ typedef struct tagCsrConfig {
uint8_t stationary_thresh;
uint32_t channel_prediction_full_scan;
#endif
bool early_stop_scan_enable;
int8_t early_stop_scan_min_threshold;
int8_t early_stop_scan_max_threshold;
} tCsrConfig;
typedef struct tagCsrChannelPowerInfo {

View File

@ -130,6 +130,9 @@ typedef struct _smeConfigParams {
uint8_t stationary_thresh;
uint32_t channel_prediction_full_scan;
#endif
bool early_stop_scan_enable;
int8_t early_stop_scan_min_threshold;
int8_t early_stop_scan_max_threshold;
} tSmeConfigParams, *tpSmeConfigParams;
#ifdef FEATURE_WLAN_TDLS

View File

@ -1349,6 +1349,12 @@ CDF_STATUS sme_update_config(tHalHandle hHal, tpSmeConfigParams pSmeConfigParams
pSmeConfigParams->dual_mac_feature_disable;
sme_update_roam_pno_channel_prediction_config(pMac, pSmeConfigParams,
SME_CONFIG_TO_ROAM_CONFIG);
pMac->roam.configParam.early_stop_scan_enable =
pSmeConfigParams->early_stop_scan_enable;
pMac->roam.configParam.early_stop_scan_min_threshold =
pSmeConfigParams->early_stop_scan_min_threshold;
pMac->roam.configParam.early_stop_scan_max_threshold =
pSmeConfigParams->early_stop_scan_max_threshold;
return status;
}
@ -4192,6 +4198,12 @@ CDF_STATUS sme_get_config_param(tHalHandle hHal, tSmeConfigParams *pParam)
pMac->f_sta_miracast_mcc_rest_time_val;
sme_update_roam_pno_channel_prediction_config(pMac, pParam,
ROAM_CONFIG_TO_SME_CONFIG);
pParam->early_stop_scan_enable =
pMac->roam.configParam.early_stop_scan_enable;
pParam->early_stop_scan_min_threshold =
pMac->roam.configParam.early_stop_scan_min_threshold;
pParam->early_stop_scan_max_threshold =
pMac->roam.configParam.early_stop_scan_max_threshold;
sme_release_global_lock(&pMac->sme);
}

View File

@ -474,6 +474,121 @@ static tPowerdBm csr_find_channel_pwr(tChannelListWithPower *
CDF_ASSERT(0);
return 0;
}
/**
* csr_roam_sort_channel_for_early_stop() - Sort the channels
* @chan_list: Original channel list from the upper layers
* @num_channel: Number of original channels
*
* For Early stop scan feature, the channel list should be in an order,
* where-in there is a maximum chance to detect an AP in the initial
* channels in the list so that the scanning can be stopped early as the
* feature demands.
* Below fixed greedy channel list has been provided
* based on most of the enterprise wifi installations across the globe.
*
* Identify all the greedy channels within the channel list from user space.
* Identify all the non-greedy channels in the user space channel list.
* Merge greedy channels followed by non-greedy channels back into the
* chan_list.
*
* Return: None
*/
void csr_roam_sort_channel_for_early_stop(tSirUpdateChanList *chan_list,
uint8_t num_channel)
{
tSirUpdateChanList *chan_list_greedy, *chan_list_non_greedy;
uint8_t i, j;
static const uint8_t fixed_greedy_chan_list[] = {1, 6, 11, 36, 48, 40,
44, 10, 2, 9, 149, 157, 161, 3, 4, 8, 153, 165, 7, 5, 136, 140,
52, 116, 56, 104, 64, 60, 100, 120, 13, 14, 112, 132, 151, 155};
uint8_t num_fixed_greedy_chan;
uint8_t num_greedy_chan = 0;
uint8_t num_non_greedy_chan = 0;
uint8_t match_found = false;
uint32_t buf_size;
buf_size = sizeof(tSirUpdateChanList) +
(sizeof(tSirUpdateChanParam) * num_channel);
chan_list_greedy = cdf_mem_malloc(buf_size);
chan_list_non_greedy = cdf_mem_malloc(buf_size);
if (!chan_list_greedy || !chan_list_non_greedy) {
CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
"Failed to allocate memory for tSirUpdateChanList");
return;
}
cdf_mem_zero(chan_list_greedy, buf_size);
cdf_mem_zero(chan_list_non_greedy, buf_size);
/*
* fixed_greedy_chan_list is an evaluated channel list based on most of
* the enterprise wifi deployments and the order of the channels
* determines the highest possibility of finding an AP.
* chan_list is the channel list provided by upper layers based on the
* regulatory domain.
*/
num_fixed_greedy_chan = sizeof(fixed_greedy_chan_list)/sizeof(uint8_t);
/*
* Browse through the chan_list and put all the non-greedy channels
* into a seperate list by name chan_list_non_greedy
*/
for (i = 0; i < num_channel; i++) {
for (j = 0; j < num_fixed_greedy_chan; j++) {
if (chan_list->chanParam[i].chanId ==
fixed_greedy_chan_list[j]) {
match_found = true;
break;
}
}
if (!match_found) {
cdf_mem_copy(
&chan_list_non_greedy->chanParam[num_non_greedy_chan],
&chan_list->chanParam[i],
sizeof(tSirUpdateChanParam));
num_non_greedy_chan++;
} else {
match_found = false;
}
}
/*
* Browse through the fixed_greedy_chan_list and put all the greedy
* channels in the chan_list into a seperate list by name
* chan_list_greedy
*/
for (i = 0; i < num_fixed_greedy_chan; i++) {
for (j = 0; j < num_channel; j++) {
if (fixed_greedy_chan_list[i] ==
chan_list->chanParam[j].chanId) {
cdf_mem_copy(
&chan_list_greedy->chanParam[num_greedy_chan],
&chan_list->chanParam[j],
sizeof(tSirUpdateChanParam));
num_greedy_chan++;
break;
}
}
}
CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_DEBUG,
"greedy=%d, non-greedy=%d, tot=%d",
num_greedy_chan, num_non_greedy_chan, num_channel);
if ((num_greedy_chan + num_non_greedy_chan) != num_channel) {
CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
"incorrect sorting of channels");
goto scan_list_sort_error;
}
/* Copy the Greedy channels first */
i = 0;
cdf_mem_copy(&chan_list->chanParam[i],
&chan_list_greedy->chanParam[i],
num_greedy_chan * sizeof(tSirUpdateChanParam));
/* Copy the remaining Non Greedy channels */
i = num_greedy_chan;
j = 0;
cdf_mem_copy(&chan_list->chanParam[i],
&chan_list_non_greedy->chanParam[j],
num_non_greedy_chan * sizeof(tSirUpdateChanParam));
scan_list_sort_error:
cdf_mem_free(chan_list_greedy);
cdf_mem_free(chan_list_non_greedy);
}
CDF_STATUS csr_update_channel_list(tpAniSirGlobal pMac)
{
@ -532,6 +647,11 @@ CDF_STATUS csr_update_channel_list(tpAniSirGlobal pMac)
else
pChanList->chanParam[num_channel].dfsSet =
true;
CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO,
"channel:%d, pwr=%d, DFS=%d\n",
pChanList->chanParam[num_channel].chanId,
pChanList->chanParam[num_channel].pwr,
pChanList->chanParam[num_channel].dfsSet);
num_channel++;
}
}
@ -550,6 +670,11 @@ CDF_STATUS csr_update_channel_list(tpAniSirGlobal pMac)
}
}
}
if (pMac->roam.configParam.early_stop_scan_enable)
csr_roam_sort_channel_for_early_stop(pChanList, num_channel);
else
CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO,
FL("Early Stop Scan Feature not supported"));
msg.type = WMA_UPDATE_CHAN_LIST_REQ;
msg.reserved = 0;
@ -1869,6 +1994,13 @@ CDF_STATUS csr_change_default_config_param(tpAniSirGlobal pMac,
pParam->sendDeauthBeforeCon;
pMac->enable_dot11p = pParam->enable_dot11p;
pMac->roam.configParam.early_stop_scan_enable =
pParam->early_stop_scan_enable;
pMac->roam.configParam.early_stop_scan_min_threshold =
pParam->early_stop_scan_min_threshold;
pMac->roam.configParam.early_stop_scan_max_threshold =
pParam->early_stop_scan_max_threshold;
}
return status;
@ -16773,6 +16905,17 @@ csr_create_roam_scan_offload_request(tpAniSirGlobal mac_ctx,
session);
req_buf->allowDFSChannelRoam =
mac_ctx->roam.configParam.allowDFSChannelRoam;
req_buf->early_stop_scan_enable =
mac_ctx->roam.configParam.early_stop_scan_enable;
req_buf->early_stop_scan_min_threshold =
mac_ctx->roam.configParam.early_stop_scan_min_threshold;
req_buf->early_stop_scan_max_threshold =
mac_ctx->roam.configParam.early_stop_scan_max_threshold;
CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG,
FL("EarlyStopFeature Enable=%d, MinThresh=%d, MaxThresh=%d"),
req_buf->early_stop_scan_enable,
req_buf->early_stop_scan_min_threshold,
req_buf->early_stop_scan_max_threshold);
#ifdef WLAN_FEATURE_ROAM_OFFLOAD
req_buf->RoamOffloadEnabled = csr_roamIsRoamOffloadEnabled(mac_ctx);
req_buf->RoamKeyMgmtOffloadEnabled = session->RoamKeyMgmtOffloadEnabled;

View File

@ -1122,6 +1122,7 @@ CDF_STATUS wma_roam_scan_offload_rssi_thresh(tp_wma_handle wma_handle,
uint8_t *buf_ptr;
wmi_roam_scan_rssi_threshold_fixed_param *rssi_threshold_fp;
wmi_roam_scan_extended_threshold_param *ext_thresholds = NULL;
wmi_roam_earlystop_rssi_thres_param *early_stop_thresholds = NULL;
struct roam_ext_params *roam_params;
int32_t good_rssi_threshold;
uint32_t hirssi_scan_max_count;
@ -1139,6 +1140,8 @@ CDF_STATUS wma_roam_scan_offload_rssi_thresh(tp_wma_handle wma_handle,
len = sizeof(wmi_roam_scan_rssi_threshold_fixed_param);
len += WMI_TLV_HDR_SIZE; /* TLV for ext_thresholds*/
len += sizeof(wmi_roam_scan_extended_threshold_param);
len += WMI_TLV_HDR_SIZE;
len += sizeof(wmi_roam_earlystop_rssi_thres_param);
buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
if (!buf) {
WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
@ -1209,6 +1212,27 @@ CDF_STATUS wma_roam_scan_offload_rssi_thresh(tp_wma_handle wma_handle,
WMITLV_TAG_STRUC_wmi_roam_scan_extended_threshold_param,
WMITLV_GET_STRUCT_TLVLEN
(wmi_roam_scan_extended_threshold_param));
buf_ptr += sizeof(wmi_roam_scan_extended_threshold_param);
WMITLV_SET_HDR(buf_ptr,
WMITLV_TAG_ARRAY_STRUC,
sizeof(wmi_roam_earlystop_rssi_thres_param));
buf_ptr += WMI_TLV_HDR_SIZE;
early_stop_thresholds = (wmi_roam_earlystop_rssi_thres_param *) buf_ptr;
early_stop_thresholds->roam_earlystop_thres_min =
roam_req->early_stop_scan_min_threshold -
WMA_NOISE_FLOOR_DBM_DEFAULT;
early_stop_thresholds->roam_earlystop_thres_max =
roam_req->early_stop_scan_max_threshold -
WMA_NOISE_FLOOR_DBM_DEFAULT;
WMITLV_SET_HDR(&early_stop_thresholds->tlv_header,
WMITLV_TAG_STRUC_wmi_roam_earlystop_rssi_thres_param,
WMITLV_GET_STRUCT_TLVLEN
(wmi_roam_earlystop_rssi_thres_param));
WMA_LOGD("early_stop_thresholds en=%d, min=%d, max=%d",
roam_req->early_stop_scan_enable,
early_stop_thresholds->roam_earlystop_thres_min,
early_stop_thresholds->roam_earlystop_thres_max);
status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
len, WMI_ROAM_SCAN_RSSI_THRESHOLD);
if (status != EOK) {