mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-08 12:58:12 -04:00
qcacld-3.0: Isolate roaming related scan functionality
Move the scanning related code which is pertinent to roaming into a separate file so that any future maintenace would be easy across different projects CRs-Fixed: 978905 Change-Id: Ia8c81726eb843d0a5aa89affa89d84d77994932e
This commit is contained in:
parent
883c4f20f9
commit
86459d63ca
6 changed files with 835 additions and 760 deletions
3
Kbuild
3
Kbuild
|
|
@ -505,7 +505,8 @@ SME_CSR_OBJS := $(SME_SRC_DIR)/csr/csr_api_roam.o \
|
|||
$(SME_SRC_DIR)/csr/csr_cmd_process.o \
|
||||
$(SME_SRC_DIR)/csr/csr_link_list.o \
|
||||
$(SME_SRC_DIR)/csr/csr_neighbor_roam.o \
|
||||
$(SME_SRC_DIR)/csr/csr_util.o
|
||||
$(SME_SRC_DIR)/csr/csr_util.o \
|
||||
$(SME_SRC_DIR)/csr/csr_host_scan_roam.o
|
||||
|
||||
ifeq ($(CONFIG_QCOM_TDLS),y)
|
||||
SME_CSR_OBJS += $(SME_SRC_DIR)/csr/csr_tdls_process.o
|
||||
|
|
|
|||
|
|
@ -1383,4 +1383,7 @@ bool csr_wait_for_connection_update(tpAniSirGlobal mac,
|
|||
bool do_release_reacquire_lock);
|
||||
enum tQDF_ADAPTER_MODE csr_get_session_persona(tpAniSirGlobal pmac,
|
||||
uint32_t session_id);
|
||||
void csr_roam_substate_change(tpAniSirGlobal pMac, eCsrRoamSubState NewSubstate,
|
||||
uint32_t sessionId);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -320,5 +320,19 @@ static inline void csr_neighbor_roam_send_lfr_metric_event(
|
|||
tSirMacAddr bssid, eRoamCmdStatus status)
|
||||
{}
|
||||
#endif
|
||||
void csr_neighbor_roam_free_roamable_bss_list(tpAniSirGlobal mac_ctx,
|
||||
tDblLinkList * llist);
|
||||
QDF_STATUS csr_neighbor_roam_process_scan_complete(tpAniSirGlobal pMac,
|
||||
uint8_t sessionId);
|
||||
QDF_STATUS csr_roam_stop_wait_for_key_timer(tpAniSirGlobal pMac);
|
||||
uint32_t csr_get_current_ap_rssi(tpAniSirGlobal pMac,
|
||||
tScanResultHandle *pScanResultList, uint8_t sessionId);
|
||||
QDF_STATUS csr_roam_issue_reassociate(tpAniSirGlobal pMac,
|
||||
uint32_t sessionId, tSirBssDescription *pSirBssDesc,
|
||||
tDot11fBeaconIEs *pIes, tCsrRoamProfile *pProfile);
|
||||
QDF_STATUS csr_roam_issue_reassociate_cmd(tpAniSirGlobal pMac,
|
||||
uint32_t sessionId);
|
||||
QDF_STATUS csr_roam_copy_connected_profile(tpAniSirGlobal pMac,
|
||||
uint32_t sessionId, tCsrRoamProfile *pDstProfile);
|
||||
|
||||
#endif /* CSR_NEIGHBOR_ROAM_H */
|
||||
|
|
|
|||
|
|
@ -204,7 +204,6 @@ static QDF_STATUS csr_roam_stop_roaming_timer(tpAniSirGlobal pMac,
|
|||
uint32_t sessionId);
|
||||
static void csr_roam_roaming_timer_handler(void *pv);
|
||||
QDF_STATUS csr_roam_start_wait_for_key_timer(tpAniSirGlobal pMac, uint32_t interval);
|
||||
QDF_STATUS csr_roam_stop_wait_for_key_timer(tpAniSirGlobal pMac);
|
||||
static void csr_roam_wait_for_key_time_out_handler(void *pv);
|
||||
static QDF_STATUS csr_init11d_info(tpAniSirGlobal pMac, tCsr11dinfo *ps11dinfo);
|
||||
static QDF_STATUS csr_init_channel_power_list(tpAniSirGlobal pMac,
|
||||
|
|
@ -220,11 +219,6 @@ QDF_STATUS csr_send_mb_set_context_req_msg(tpAniSirGlobal pMac, uint32_t session
|
|||
uint8_t keyId, uint8_t keyLength,
|
||||
uint8_t *pKey, uint8_t paeRole,
|
||||
uint8_t *pKeyRsc);
|
||||
static QDF_STATUS csr_roam_issue_reassociate(tpAniSirGlobal pMac,
|
||||
uint32_t sessionId,
|
||||
tSirBssDescription *pSirBssDesc,
|
||||
tDot11fBeaconIEs *pIes,
|
||||
tCsrRoamProfile *pProfile);
|
||||
void csr_roamStatisticsTimerHandler(void *pv);
|
||||
void csr_roamStatsGlobalClassDTimerHandler(void *pv);
|
||||
static void csr_roam_link_up(tpAniSirGlobal pMac, struct qdf_mac_addr bssid);
|
||||
|
|
@ -8316,22 +8310,6 @@ QDF_STATUS csr_roam_issue_join(tpAniSirGlobal pMac, uint32_t sessionId,
|
|||
return status;
|
||||
}
|
||||
|
||||
static QDF_STATUS csr_roam_issue_reassociate(tpAniSirGlobal pMac,
|
||||
uint32_t sessionId,
|
||||
tSirBssDescription *pSirBssDesc,
|
||||
tDot11fBeaconIEs *pIes,
|
||||
tCsrRoamProfile *pProfile)
|
||||
{
|
||||
csr_roam_state_change(pMac, eCSR_ROAMING_STATE_JOINING, sessionId);
|
||||
/* Set the roaming substate to 'join attempt'... */
|
||||
csr_roam_substate_change(pMac, eCSR_ROAM_SUBSTATE_REASSOC_REQ, sessionId);
|
||||
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
|
||||
FL(" calling csr_send_join_req_msg (eWNI_SME_REASSOC_REQ)"));
|
||||
/* attempt to Join this BSS... */
|
||||
return csr_send_join_req_msg(pMac, sessionId, pSirBssDesc, pProfile, pIes,
|
||||
eWNI_SME_REASSOC_REQ);
|
||||
}
|
||||
|
||||
void csr_roam_reissue_roam_command(tpAniSirGlobal pMac)
|
||||
{
|
||||
tListElem *pEntry;
|
||||
|
|
@ -8501,67 +8479,6 @@ bool csr_is_scan_for_roam_command_active(tpAniSirGlobal pMac)
|
|||
return fRet;
|
||||
}
|
||||
|
||||
QDF_STATUS csr_roam_issue_reassociate_cmd(tpAniSirGlobal pMac, uint32_t sessionId)
|
||||
{
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
tSmeCmd *pCommand = NULL;
|
||||
bool fHighPriority = true;
|
||||
bool fRemoveCmd = false;
|
||||
tListElem *pEntry;
|
||||
/* Delete the old assoc command. All is setup for reassoc to be serialized */
|
||||
pEntry = csr_ll_peek_head(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK);
|
||||
if (pEntry) {
|
||||
pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
|
||||
if (!pCommand) {
|
||||
sms_log(pMac, LOGE, FL(" fail to get command buffer"));
|
||||
return QDF_STATUS_E_RESOURCES;
|
||||
}
|
||||
if (eSmeCommandRoam == pCommand->command) {
|
||||
if (pCommand->u.roamCmd.roamReason ==
|
||||
eCsrSmeIssuedAssocToSimilarAP) {
|
||||
fRemoveCmd =
|
||||
csr_ll_remove_entry(&pMac->sme.
|
||||
smeCmdActiveList, pEntry,
|
||||
LL_ACCESS_LOCK);
|
||||
} else {
|
||||
sms_log(pMac, LOGE,
|
||||
FL
|
||||
(" Unexpected active roam command present "));
|
||||
}
|
||||
if (fRemoveCmd == false) {
|
||||
/* Implies we did not get the serialized assoc command we */
|
||||
/* were expecting */
|
||||
pCommand = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (NULL == pCommand) {
|
||||
sms_log(pMac, LOGE,
|
||||
FL
|
||||
(" fail to get command buffer as expected based on previous connect roam command"));
|
||||
return QDF_STATUS_E_RESOURCES;
|
||||
}
|
||||
do {
|
||||
/* Change the substate in case it is wait-for-key */
|
||||
if (CSR_IS_WAIT_FOR_KEY(pMac, sessionId)) {
|
||||
csr_roam_stop_wait_for_key_timer(pMac);
|
||||
csr_roam_substate_change(pMac, eCSR_ROAM_SUBSTATE_NONE,
|
||||
sessionId);
|
||||
}
|
||||
pCommand->command = eSmeCommandRoam;
|
||||
pCommand->sessionId = (uint8_t) sessionId;
|
||||
pCommand->u.roamCmd.roamReason = eCsrSmeIssuedFTReassoc;
|
||||
status = csr_queue_sme_command(pMac, pCommand, fHighPriority);
|
||||
if (!QDF_IS_STATUS_SUCCESS(status)) {
|
||||
sms_log(pMac, LOGE,
|
||||
FL(" fail to send message status = %d"), status);
|
||||
csr_release_command_roam(pMac, pCommand);
|
||||
}
|
||||
} while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
csr_roaming_state_config_cnf_processor(tpAniSirGlobal mac_ctx,
|
||||
uint32_t result)
|
||||
|
|
|
|||
816
core/sme/src/csr/csr_host_scan_roam.c
Normal file
816
core/sme/src/csr/csr_host_scan_roam.c
Normal file
|
|
@ -0,0 +1,816 @@
|
|||
/*
|
||||
* Copyright (c) 2016 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for
|
||||
* any purpose with or without fee is hereby granted, provided that the
|
||||
* above copyright notice and this permission notice appear in all
|
||||
* copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* DOC: csr_host_scan_roam.c
|
||||
*
|
||||
* Host based roaming processing scan results and initiating the roaming
|
||||
*/
|
||||
|
||||
#include "wma_types.h"
|
||||
#include "cds_mq.h"
|
||||
#include "csr_inside_api.h"
|
||||
#include "sms_debug.h"
|
||||
#include "sme_qos_internal.h"
|
||||
#include "sme_inside.h"
|
||||
#include "host_diag_core_event.h"
|
||||
#include "host_diag_core_log.h"
|
||||
#include "csr_api.h"
|
||||
#include "sme_api.h"
|
||||
#include "csr_neighbor_roam.h"
|
||||
#include "mac_trace.h"
|
||||
#include "cds_concurrency.h"
|
||||
|
||||
/**
|
||||
* csr_roam_issue_reassociate() - Issue Reassociate
|
||||
* @pMac: Global MAC Context
|
||||
* @sessionId: SME Session ID
|
||||
* @pSirBssDesc: BSS Descriptor
|
||||
* @pIes: Pointer to the IE's
|
||||
* @pProfile: Roaming profile
|
||||
*
|
||||
* Return: Success or Failure
|
||||
*/
|
||||
QDF_STATUS csr_roam_issue_reassociate(tpAniSirGlobal pMac,
|
||||
uint32_t sessionId, tSirBssDescription *pSirBssDesc,
|
||||
tDot11fBeaconIEs *pIes, tCsrRoamProfile *pProfile)
|
||||
{
|
||||
csr_roam_state_change(pMac, eCSR_ROAMING_STATE_JOINING, sessionId);
|
||||
/* Set the roaming substate to 'join attempt'... */
|
||||
csr_roam_substate_change(pMac, eCSR_ROAM_SUBSTATE_REASSOC_REQ,
|
||||
sessionId);
|
||||
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
|
||||
FL(" calling csr_send_join_req_msg (eWNI_SME_REASSOC_REQ)"));
|
||||
/* attempt to Join this BSS... */
|
||||
return csr_send_join_req_msg(pMac, sessionId, pSirBssDesc, pProfile,
|
||||
pIes, eWNI_SME_REASSOC_REQ);
|
||||
}
|
||||
|
||||
/**
|
||||
* csr_roam_issue_reassociate_cmd() - Issue the reassociate command
|
||||
* @pMac: Global MAC Context
|
||||
* @sessionId: SME Session ID
|
||||
*
|
||||
* Return: Success or Failure status
|
||||
*/
|
||||
QDF_STATUS csr_roam_issue_reassociate_cmd(tpAniSirGlobal pMac,
|
||||
uint32_t sessionId)
|
||||
{
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
tSmeCmd *pCommand = NULL;
|
||||
bool fHighPriority = true;
|
||||
bool fRemoveCmd = false;
|
||||
tListElem *pEntry;
|
||||
pEntry = csr_ll_peek_head(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK);
|
||||
if (pEntry) {
|
||||
pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
|
||||
if (!pCommand) {
|
||||
sms_log(pMac, LOGE, FL(" fail to get command buffer"));
|
||||
return QDF_STATUS_E_RESOURCES;
|
||||
}
|
||||
if (eSmeCommandRoam == pCommand->command) {
|
||||
if (pCommand->u.roamCmd.roamReason ==
|
||||
eCsrSmeIssuedAssocToSimilarAP)
|
||||
fRemoveCmd =
|
||||
csr_ll_remove_entry(&pMac->sme.
|
||||
smeCmdActiveList,
|
||||
pEntry,
|
||||
LL_ACCESS_LOCK);
|
||||
else
|
||||
sms_log(pMac, LOGE,
|
||||
FL(" Unexpected roam cmd present"));
|
||||
if (fRemoveCmd == false)
|
||||
pCommand = NULL;
|
||||
}
|
||||
}
|
||||
if (NULL == pCommand) {
|
||||
sms_log(pMac, LOGE,
|
||||
FL(" fail to get cmd buf based on prev roam command"));
|
||||
return QDF_STATUS_E_RESOURCES;
|
||||
}
|
||||
do {
|
||||
/* Change the substate in case it is wait-for-key */
|
||||
if (CSR_IS_WAIT_FOR_KEY(pMac, sessionId)) {
|
||||
csr_roam_stop_wait_for_key_timer(pMac);
|
||||
csr_roam_substate_change(pMac, eCSR_ROAM_SUBSTATE_NONE,
|
||||
sessionId);
|
||||
}
|
||||
pCommand->command = eSmeCommandRoam;
|
||||
pCommand->sessionId = (uint8_t) sessionId;
|
||||
pCommand->u.roamCmd.roamReason = eCsrSmeIssuedFTReassoc;
|
||||
status = csr_queue_sme_command(pMac, pCommand, fHighPriority);
|
||||
if (!QDF_IS_STATUS_SUCCESS(status)) {
|
||||
sms_log(pMac, LOGE,
|
||||
FL("fail to send message status=%d"), status);
|
||||
csr_release_command_roam(pMac, pCommand);
|
||||
}
|
||||
} while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* csr_neighbor_roam_process_scan_results() - build roaming candidate list
|
||||
*
|
||||
* @mac_ctx: The handle returned by mac_open.
|
||||
* @sessionid: Session information
|
||||
* @scan_results_list: List obtained from csr_scan_get_result()
|
||||
*
|
||||
* This function applies various candidate checks like LFR, 11r, preauth, ESE
|
||||
* and builds a roamable AP list. It applies age limit only if no suitable
|
||||
* recent candidates are found.
|
||||
*
|
||||
* Output list is built in mac_ctx->roam.neighborRoamInfo[sessionid].
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
|
||||
static void
|
||||
csr_neighbor_roam_process_scan_results(tpAniSirGlobal mac_ctx,
|
||||
uint8_t sessionid,
|
||||
tScanResultHandle *scan_results_list)
|
||||
{
|
||||
tCsrScanResultInfo *scan_result;
|
||||
tpCsrNeighborRoamControlInfo n_roam_info =
|
||||
&mac_ctx->roam.neighborRoamInfo[sessionid];
|
||||
tpCsrNeighborRoamBSSInfo bss_info;
|
||||
uint32_t cur_ap_rssi;
|
||||
uint32_t age_ticks = 0;
|
||||
uint32_t limit_ticks =
|
||||
qdf_system_msecs_to_ticks(ROAM_AP_AGE_LIMIT_MS);
|
||||
uint8_t num_candidates = 0;
|
||||
uint8_t num_dropped = 0;
|
||||
/*
|
||||
* first iteration of scan list should consider
|
||||
* age constraint for candidates
|
||||
*/
|
||||
bool age_constraint = true;
|
||||
#ifdef FEATURE_WLAN_ESE
|
||||
uint16_t qpresent;
|
||||
uint16_t qavail;
|
||||
bool voadmitted;
|
||||
#endif
|
||||
/*
|
||||
* Find out the Current AP RSSI and keep it handy to check if
|
||||
* it is better than the RSSI of the AP which we are
|
||||
* going to roam.If so, we are going to continue with the
|
||||
* current AP.
|
||||
*/
|
||||
cur_ap_rssi = csr_get_current_ap_rssi(mac_ctx, scan_results_list,
|
||||
sessionid);
|
||||
|
||||
/*
|
||||
* Expecting the scan result already to be in the sorted order based on
|
||||
* RSSI. Based on the previous state we need to check whether the list
|
||||
* should be sorted again taking neighbor score into consideration. If
|
||||
* previous state is CFG_CHAN_LIST_SCAN, there should not be a neighbor
|
||||
* score associated with any of the BSS. If the previous state is
|
||||
* REPORT_QUERY, then there will be neighbor score for each of the APs.
|
||||
* For now, let us take top of the list provided as it is by CSR Scan
|
||||
* result API. Hence it is assumed that neighbor score and rssi score
|
||||
* are in the same order. This will be taken care later.
|
||||
*/
|
||||
|
||||
do {
|
||||
while (true) {
|
||||
tSirBssDescription *descr;
|
||||
|
||||
scan_result = csr_scan_result_get_next(
|
||||
mac_ctx, *scan_results_list);
|
||||
if (NULL == scan_result)
|
||||
break;
|
||||
descr = &scan_result->BssDescriptor;
|
||||
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
|
||||
FL("Scan result: BSSID " MAC_ADDRESS_STR
|
||||
" (Rssi %ld, Ch:%d)"),
|
||||
MAC_ADDR_ARRAY(descr->bssId),
|
||||
abs(descr->rssi), descr->channelId);
|
||||
|
||||
if (!qdf_mem_cmp(descr->bssId,
|
||||
n_roam_info->currAPbssid.bytes,
|
||||
sizeof(tSirMacAddr))) {
|
||||
/*
|
||||
* currently associated AP. Do not have this
|
||||
* in the roamable AP list
|
||||
*/
|
||||
QDF_TRACE(QDF_MODULE_ID_SME,
|
||||
QDF_TRACE_LEVEL_INFO,
|
||||
"SKIP-currently associated AP");
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* In case of reassoc requested by upper layer, look
|
||||
* for exact match of bssid & channel. csr cache might
|
||||
* have duplicates
|
||||
*/
|
||||
if ((n_roam_info->uOsRequestedHandoff) &&
|
||||
((qdf_mem_cmp(descr->bssId,
|
||||
n_roam_info->handoffReqInfo.bssid.bytes,
|
||||
sizeof(tSirMacAddr)))
|
||||
|| (descr->channelId !=
|
||||
n_roam_info->handoffReqInfo.channel))) {
|
||||
QDF_TRACE(QDF_MODULE_ID_SME,
|
||||
QDF_TRACE_LEVEL_INFO,
|
||||
"SKIP-not a candidate AP for OS requested roam");
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((n_roam_info->is11rAssoc) &&
|
||||
(!csr_neighbor_roam_is_preauth_candidate(mac_ctx,
|
||||
sessionid, descr->bssId))) {
|
||||
sms_log(mac_ctx, LOGE,
|
||||
FL("BSSID in preauth faillist.Ignore"));
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef FEATURE_WLAN_ESE
|
||||
if (!csr_roam_is_roam_offload_scan_enabled(mac_ctx) &&
|
||||
(n_roam_info->isESEAssoc) &&
|
||||
!csr_neighbor_roam_is_preauth_candidate(mac_ctx,
|
||||
sessionid, descr->bssId)) {
|
||||
sms_log(mac_ctx, LOGE,
|
||||
FL("BSSID in preauth faillist.Ignore"));
|
||||
continue;
|
||||
}
|
||||
|
||||
qpresent = descr->QBSSLoad_present;
|
||||
qavail = descr->QBSSLoad_avail;
|
||||
voadmitted = n_roam_info->isVOAdmitted;
|
||||
if (voadmitted)
|
||||
sms_log(mac_ctx, LOG1,
|
||||
FL("New QBSS=%s,BWavail=0x%x,req=0x%x"),
|
||||
((qpresent) ? "yes" : "no"), qavail,
|
||||
n_roam_info->MinQBssLoadRequired);
|
||||
if (voadmitted && qpresent &&
|
||||
(qavail < n_roam_info->MinQBssLoadRequired)) {
|
||||
QDF_TRACE(QDF_MODULE_ID_SME,
|
||||
QDF_TRACE_LEVEL_INFO,
|
||||
"BSSID:" MAC_ADDRESS_STR "has no BW",
|
||||
MAC_ADDR_ARRAY(descr->bssId));
|
||||
continue;
|
||||
}
|
||||
if (voadmitted && !qpresent) {
|
||||
QDF_TRACE(QDF_MODULE_ID_SME,
|
||||
QDF_TRACE_LEVEL_INFO,
|
||||
"BSSID:" MAC_ADDRESS_STR "no LOAD IE",
|
||||
MAC_ADDR_ARRAY(descr->bssId));
|
||||
continue;
|
||||
}
|
||||
#endif /* FEATURE_WLAN_ESE */
|
||||
|
||||
/*
|
||||
* If we are supporting legacy roaming, and
|
||||
* if the candidate is on the "pre-auth failed" list,
|
||||
* ignore it.
|
||||
*/
|
||||
if (csr_roam_is_fast_roam_enabled(mac_ctx, sessionid) &&
|
||||
!csr_neighbor_roam_is_preauth_candidate(mac_ctx,
|
||||
sessionid, descr->bssId)) {
|
||||
sms_log(mac_ctx, LOGE,
|
||||
FL("BSSID in preauth faillist Ignore"));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check the age of the AP */
|
||||
age_ticks = (uint32_t) qdf_mc_timer_get_system_ticks() -
|
||||
descr->nReceivedTime;
|
||||
if (age_constraint == true && age_ticks > limit_ticks) {
|
||||
num_dropped++;
|
||||
QDF_TRACE(QDF_MODULE_ID_SME,
|
||||
QDF_TRACE_LEVEL_WARN,
|
||||
FL("Old AP (probe rsp/beacon) skipped.")
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Finished all checks, now add it to candidate list */
|
||||
bss_info =
|
||||
qdf_mem_malloc(sizeof(tCsrNeighborRoamBSSInfo));
|
||||
if (NULL == bss_info) {
|
||||
sms_log(mac_ctx, LOGE,
|
||||
FL("Memory alloc fail. Ignored cnd."));
|
||||
continue;
|
||||
}
|
||||
bss_info->pBssDescription =
|
||||
qdf_mem_malloc(descr->length +
|
||||
sizeof(descr->length));
|
||||
if (bss_info->pBssDescription != NULL) {
|
||||
qdf_mem_copy(bss_info->pBssDescription, descr,
|
||||
descr->length + sizeof(descr->length));
|
||||
} else {
|
||||
sms_log(mac_ctx, LOGE,
|
||||
FL("Mem alloc failed. Ignore cand."));
|
||||
qdf_mem_free(bss_info);
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* Assign some preference value for now. Need to
|
||||
* calculate theactual score based on RSSI and neighbor
|
||||
* AP score
|
||||
*/
|
||||
bss_info->apPreferenceVal = 10;
|
||||
num_candidates++;
|
||||
csr_ll_insert_tail(&n_roam_info->roamableAPList,
|
||||
&bss_info->List, LL_ACCESS_LOCK);
|
||||
} /* end of while (csr_scan_result_get_next) */
|
||||
|
||||
/* if some candidates were found, then no need to repeat */
|
||||
if (num_candidates)
|
||||
break;
|
||||
/*
|
||||
* if age_constraint is already false, we have done two
|
||||
* iterations and no candidate were found
|
||||
*/
|
||||
if (age_constraint == false) {
|
||||
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
|
||||
"%s: No roam able candidates found",
|
||||
__func__);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* if all candidates were dropped rescan the scan
|
||||
* list but this time without age constraint.
|
||||
*/
|
||||
age_constraint = false;
|
||||
/* if no candidates were dropped no need to repeat */
|
||||
} while (num_dropped);
|
||||
|
||||
/*
|
||||
* Now we have all the scan results in our local list. Good time to free
|
||||
* up the the list we got as a part of csrGetScanResult
|
||||
*/
|
||||
csr_scan_result_purge(mac_ctx, *scan_results_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* csr_neighbor_roam_trigger_handoff() - Start roaming
|
||||
* @mac_ctx: Global MAC Context
|
||||
* @session_id: SME Session ID
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void csr_neighbor_roam_trigger_handoff(tpAniSirGlobal mac_ctx,
|
||||
uint8_t session_id)
|
||||
{
|
||||
if (csr_roam_is_fast_roam_enabled(mac_ctx, session_id))
|
||||
csr_neighbor_roam_issue_preauth_req(mac_ctx, session_id);
|
||||
else
|
||||
sms_log(mac_ctx, LOGE, FL("Roaming is disabled"));
|
||||
}
|
||||
|
||||
/**
|
||||
* csr_neighbor_roam_process_scan_complete() - Post process the scan results
|
||||
* @pMac: Global MAC Context
|
||||
* @sessionId: SME Session ID
|
||||
*
|
||||
* Return: Success or Failure
|
||||
*/
|
||||
QDF_STATUS csr_neighbor_roam_process_scan_complete(tpAniSirGlobal pMac,
|
||||
uint8_t sessionId)
|
||||
{
|
||||
tpCsrNeighborRoamControlInfo pNeighborRoamInfo =
|
||||
&pMac->roam.neighborRoamInfo[sessionId];
|
||||
tCsrScanResultFilter scanFilter;
|
||||
tScanResultHandle scanResult;
|
||||
uint32_t tempVal = 0;
|
||||
QDF_STATUS hstatus;
|
||||
|
||||
hstatus = csr_neighbor_roam_prepare_scan_profile_filter(pMac,
|
||||
&scanFilter,
|
||||
sessionId);
|
||||
sms_log(pMac, LOGW,
|
||||
FL("Prepare scan to find neighbor AP filter status = %d"),
|
||||
hstatus);
|
||||
if (QDF_STATUS_SUCCESS != hstatus) {
|
||||
sms_log(pMac, LOGE,
|
||||
FL("Scan Filter prep fail for Assoc %d Bail out"),
|
||||
tempVal);
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
hstatus = csr_scan_get_result(pMac, &scanFilter, &scanResult);
|
||||
if (hstatus != QDF_STATUS_SUCCESS) {
|
||||
sms_log(pMac, LOGE,
|
||||
FL("Get Scan Result status code %d"),
|
||||
hstatus);
|
||||
}
|
||||
/* Process the scan results and update roamable AP list */
|
||||
csr_neighbor_roam_process_scan_results(pMac, sessionId, &scanResult);
|
||||
|
||||
/* Free the scan filter */
|
||||
csr_free_scan_filter(pMac, &scanFilter);
|
||||
|
||||
tempVal = csr_ll_count(&pNeighborRoamInfo->roamableAPList);
|
||||
|
||||
if (tempVal) {
|
||||
csr_neighbor_roam_trigger_handoff(pMac, sessionId);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (csr_roam_is_roam_offload_scan_enabled(pMac)) {
|
||||
if (pNeighborRoamInfo->uOsRequestedHandoff) {
|
||||
csr_roam_offload_scan(pMac, sessionId,
|
||||
ROAM_SCAN_OFFLOAD_START,
|
||||
REASON_NO_CAND_FOUND_OR_NOT_ROAMING_NOW);
|
||||
pNeighborRoamInfo->uOsRequestedHandoff = 0;
|
||||
} else {
|
||||
/* There is no candidate or We are not roaming Now.
|
||||
* Inform the FW to restart Roam Offload Scan */
|
||||
csr_roam_offload_scan(pMac, sessionId,
|
||||
ROAM_SCAN_OFFLOAD_RESTART,
|
||||
REASON_NO_CAND_FOUND_OR_NOT_ROAMING_NOW);
|
||||
}
|
||||
csr_neighbor_roam_state_transition(pMac,
|
||||
eCSR_NEIGHBOR_ROAM_STATE_CONNECTED, sessionId);
|
||||
}
|
||||
return QDF_STATUS_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* csr_neighbor_roam_candidate_found_ind_hdlr()
|
||||
*
|
||||
* @mac_ctx: Pointer to Global MAC structure
|
||||
* @msg_buf: pointer to msg buff
|
||||
*
|
||||
* This function is called by CSR as soon as TL posts the candidate
|
||||
* found indication to SME via MC thread
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success, corresponding error code otherwise
|
||||
*/
|
||||
QDF_STATUS csr_neighbor_roam_candidate_found_ind_hdlr(tpAniSirGlobal pMac,
|
||||
void *pMsg)
|
||||
{
|
||||
tSirSmeCandidateFoundInd *pSirSmeCandidateFoundInd =
|
||||
(tSirSmeCandidateFoundInd *) pMsg;
|
||||
uint32_t sessionId = pSirSmeCandidateFoundInd->sessionId;
|
||||
tpCsrNeighborRoamControlInfo pNeighborRoamInfo =
|
||||
&pMac->roam.neighborRoamInfo[sessionId];
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
|
||||
sms_log(pMac, LOG1, FL("Received indication from firmware"));
|
||||
|
||||
/* we must be in connected state, if not ignore it */
|
||||
if ((eCSR_NEIGHBOR_ROAM_STATE_CONNECTED !=
|
||||
pNeighborRoamInfo->neighborRoamState)
|
||||
|| (pNeighborRoamInfo->uOsRequestedHandoff)) {
|
||||
sms_log(pMac, LOGE,
|
||||
FL("Recvd in NotCONNECTED or OsReqHandoff. Ignore"));
|
||||
status = QDF_STATUS_E_FAILURE;
|
||||
} else {
|
||||
/* Firmware indicated that roaming candidate is found. Beacons
|
||||
* are already in the SME scan results table.
|
||||
* Process the results for choosing best roaming candidate.
|
||||
*/
|
||||
csr_save_scan_results(pMac, eCsrScanCandidateFound,
|
||||
sessionId);
|
||||
/* Future enhancements:
|
||||
* If firmware tags candidate beacons, give them preference
|
||||
* for roaming.
|
||||
* Age out older entries so that new candidate beacons
|
||||
* will get preference.
|
||||
*/
|
||||
status = csr_neighbor_roam_process_scan_complete(pMac,
|
||||
sessionId);
|
||||
if (QDF_STATUS_SUCCESS != status) {
|
||||
sms_log(pMac, LOGE,
|
||||
FL("scan process complete failed, status %d"),
|
||||
status);
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* csr_neighbor_roam_free_roamable_bss_list() - Frees roamable APs list
|
||||
* @mac_ctx: The handle returned by mac_open.
|
||||
* @llist: Neighbor Roam BSS List to be emptied
|
||||
*
|
||||
* Empties and frees all the nodes in the roamable AP list
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
void csr_neighbor_roam_free_roamable_bss_list(tpAniSirGlobal mac_ctx,
|
||||
tDblLinkList *llist)
|
||||
{
|
||||
tpCsrNeighborRoamBSSInfo result = NULL;
|
||||
|
||||
sms_log(mac_ctx, LOG2,
|
||||
FL("Emptying the BSS list. Current count = %d"),
|
||||
csr_ll_count(llist));
|
||||
|
||||
/*
|
||||
* Pick up the head, remove and free the node till
|
||||
* the list becomes empty
|
||||
*/
|
||||
while ((result = csr_neighbor_roam_next_roamable_ap(mac_ctx, llist,
|
||||
NULL)) != NULL) {
|
||||
csr_neighbor_roam_remove_roamable_ap_list_entry(mac_ctx,
|
||||
llist, result);
|
||||
csr_neighbor_roam_free_neighbor_roam_bss_node(mac_ctx, result);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* csr_neighbor_roam_remove_roamable_ap_list_entry()
|
||||
*
|
||||
* @mac_ctx: Pointer to Global MAC structure
|
||||
* @pList: The list from which the entry should be removed
|
||||
* @pNeighborEntry: Neighbor Roam BSS Node to be removed
|
||||
*
|
||||
* This function removes a given entry from the given list
|
||||
*
|
||||
* Return: true if successfully removed, else false
|
||||
*/
|
||||
bool csr_neighbor_roam_remove_roamable_ap_list_entry(tpAniSirGlobal pMac,
|
||||
tDblLinkList *pList,
|
||||
tpCsrNeighborRoamBSSInfo
|
||||
pNeighborEntry)
|
||||
{
|
||||
if (pList) {
|
||||
return csr_ll_remove_entry(pList, &pNeighborEntry->List,
|
||||
LL_ACCESS_LOCK);
|
||||
}
|
||||
|
||||
sms_log(pMac, LOGE,
|
||||
FL("Remove neigh BSS node from fail list. Current count = %d"),
|
||||
csr_ll_count(pList));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* csr_neighbor_roam_next_roamable_ap() - Get next AP from roamable AP list
|
||||
* @mac_ctx - The handle returned by mac_open.
|
||||
* @plist - The list from which the entry should be returned
|
||||
* @neighbor_entry - Neighbor Roam BSS Node whose next entry should be returned
|
||||
*
|
||||
* Gets the entry next to passed entry. If NULL is passed, return the entry
|
||||
* in the head of the list
|
||||
*
|
||||
* Return: Neighbor Roam BSS Node to be returned
|
||||
*/
|
||||
tpCsrNeighborRoamBSSInfo csr_neighbor_roam_next_roamable_ap(
|
||||
tpAniSirGlobal mac_ctx, tDblLinkList *llist,
|
||||
tpCsrNeighborRoamBSSInfo neighbor_entry)
|
||||
{
|
||||
tListElem *entry = NULL;
|
||||
tpCsrNeighborRoamBSSInfo result = NULL;
|
||||
|
||||
if (llist) {
|
||||
if (NULL == neighbor_entry)
|
||||
entry = csr_ll_peek_head(llist, LL_ACCESS_LOCK);
|
||||
else
|
||||
entry = csr_ll_next(llist, &neighbor_entry->List,
|
||||
LL_ACCESS_LOCK);
|
||||
if (entry)
|
||||
result = GET_BASE_ADDR(entry, tCsrNeighborRoamBSSInfo,
|
||||
List);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* csr_neighbor_roam_request_handoff() - Handoff to a different AP
|
||||
* @mac_ctx: Pointer to Global MAC structure
|
||||
* @session_id: Session ID
|
||||
*
|
||||
* This function triggers actual switching from one AP to the new AP.
|
||||
* It issues disassociate with reason code as Handoff and CSR as a part of
|
||||
* handling disassoc rsp, issues reassociate to the new AP
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
void csr_neighbor_roam_request_handoff(tpAniSirGlobal mac_ctx,
|
||||
uint8_t session_id)
|
||||
{
|
||||
tCsrRoamInfo roam_info;
|
||||
tpCsrNeighborRoamControlInfo neighbor_roam_info =
|
||||
&mac_ctx->roam.neighborRoamInfo[session_id];
|
||||
tCsrNeighborRoamBSSInfo handoff_node;
|
||||
uint32_t roamid = 0;
|
||||
QDF_STATUS status;
|
||||
|
||||
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, "%s session_id=%d",
|
||||
__func__, session_id);
|
||||
|
||||
if (neighbor_roam_info->neighborRoamState !=
|
||||
eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE) {
|
||||
sms_log(mac_ctx, LOGE,
|
||||
FL("Roam requested when Neighbor roam is in %s state"),
|
||||
mac_trace_get_neighbour_roam_state(
|
||||
neighbor_roam_info->neighborRoamState));
|
||||
return;
|
||||
}
|
||||
|
||||
if (false == csr_neighbor_roam_get_handoff_ap_info(mac_ctx,
|
||||
&handoff_node, session_id)) {
|
||||
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
|
||||
FL("failed to obtain handoff AP"));
|
||||
return;
|
||||
}
|
||||
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
|
||||
FL("HANDOFF CANDIDATE BSSID "MAC_ADDRESS_STR),
|
||||
MAC_ADDR_ARRAY(handoff_node.pBssDescription->bssId));
|
||||
|
||||
qdf_mem_zero(&roam_info, sizeof(tCsrRoamInfo));
|
||||
csr_roam_call_callback(mac_ctx, session_id, &roam_info, roamid,
|
||||
eCSR_ROAM_FT_START, eSIR_SME_SUCCESS);
|
||||
|
||||
qdf_mem_zero(&roam_info, sizeof(tCsrRoamInfo));
|
||||
csr_neighbor_roam_state_transition(mac_ctx,
|
||||
eCSR_NEIGHBOR_ROAM_STATE_REASSOCIATING, session_id);
|
||||
|
||||
csr_neighbor_roam_send_lfr_metric_event(mac_ctx, session_id,
|
||||
handoff_node.pBssDescription->bssId,
|
||||
eCSR_ROAM_HANDOVER_SUCCESS);
|
||||
/* Free the profile.. Just to make sure we dont leak memory here */
|
||||
csr_release_profile(mac_ctx,
|
||||
&neighbor_roam_info->csrNeighborRoamProfile);
|
||||
/*
|
||||
* Create the Handoff AP profile. Copy the currently connected profile
|
||||
* and update only the BSSID and channel number. This should happen
|
||||
* before issuing disconnect
|
||||
*/
|
||||
status = csr_roam_copy_connected_profile(mac_ctx, session_id,
|
||||
&neighbor_roam_info->csrNeighborRoamProfile);
|
||||
if (QDF_STATUS_SUCCESS != status) {
|
||||
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
|
||||
FL("csr_roam_copy_connected_profile failed %d"),
|
||||
status);
|
||||
return;
|
||||
}
|
||||
qdf_mem_copy(neighbor_roam_info->csrNeighborRoamProfile.BSSIDs.bssid,
|
||||
handoff_node.pBssDescription->bssId, sizeof(tSirMacAddr));
|
||||
neighbor_roam_info->csrNeighborRoamProfile.ChannelInfo.ChannelList[0] =
|
||||
handoff_node.pBssDescription->channelId;
|
||||
|
||||
sms_log(mac_ctx, LOGW,
|
||||
" csr_roamHandoffRequested: disassociating with current AP");
|
||||
|
||||
if (!QDF_IS_STATUS_SUCCESS
|
||||
(csr_roam_issue_disassociate_cmd
|
||||
(mac_ctx, session_id,
|
||||
eCSR_DISCONNECT_REASON_HANDOFF))) {
|
||||
sms_log(mac_ctx, LOGW,
|
||||
"csr_roamHandoffRequested: fail to issue disassoc");
|
||||
return;
|
||||
}
|
||||
/* notify HDD for handoff, providing the BSSID too */
|
||||
roam_info.reasonCode = eCsrRoamReasonBetterAP;
|
||||
|
||||
qdf_mem_copy(roam_info.bssid.bytes,
|
||||
handoff_node.pBssDescription->bssId,
|
||||
sizeof(struct qdf_mac_addr));
|
||||
|
||||
csr_roam_call_callback(mac_ctx, session_id, &roam_info, 0,
|
||||
eCSR_ROAM_ROAMING_START, eCSR_ROAM_RESULT_NONE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* csr_neighbor_roam_get_handoff_ap_info - Identifies the best AP for roaming
|
||||
*
|
||||
* @pMac: mac context
|
||||
* @session_id: Session Id
|
||||
* @hand_off_node: AP node that is the handoff candidate returned
|
||||
*
|
||||
* This function returns the best possible AP for handoff. For 11R case, it
|
||||
* returns the 1st entry from pre-auth done list. For non-11r case, it returns
|
||||
* the 1st entry from roamable AP list
|
||||
*
|
||||
* Return: true if able find handoff AP, false otherwise
|
||||
*/
|
||||
|
||||
bool csr_neighbor_roam_get_handoff_ap_info(tpAniSirGlobal pMac,
|
||||
tpCsrNeighborRoamBSSInfo hand_off_node,
|
||||
uint8_t session_id)
|
||||
{
|
||||
tpCsrNeighborRoamControlInfo ngbr_roam_info =
|
||||
&pMac->roam.neighborRoamInfo[session_id];
|
||||
tpCsrNeighborRoamBSSInfo bss_node = NULL;
|
||||
|
||||
if (NULL == hand_off_node) {
|
||||
QDF_ASSERT(NULL != hand_off_node);
|
||||
return false;
|
||||
}
|
||||
if (ngbr_roam_info->is11rAssoc) {
|
||||
/* Always the BSS info in the head is the handoff candidate */
|
||||
bss_node = csr_neighbor_roam_next_roamable_ap(
|
||||
pMac,
|
||||
&ngbr_roam_info->FTRoamInfo.preAuthDoneList,
|
||||
NULL);
|
||||
sms_log(pMac, LOG1,
|
||||
FL("Number of Handoff candidates = %d"),
|
||||
csr_ll_count(&
|
||||
ngbr_roam_info->FTRoamInfo.preAuthDoneList));
|
||||
} else
|
||||
#ifdef FEATURE_WLAN_ESE
|
||||
if (ngbr_roam_info->isESEAssoc) {
|
||||
/* Always the BSS info in the head is the handoff candidate */
|
||||
bss_node =
|
||||
csr_neighbor_roam_next_roamable_ap(pMac,
|
||||
&ngbr_roam_info->FTRoamInfo.preAuthDoneList,
|
||||
NULL);
|
||||
sms_log(pMac, LOG1,
|
||||
FL("Number of Handoff candidates = %d"),
|
||||
csr_ll_count(&ngbr_roam_info->FTRoamInfo.
|
||||
preAuthDoneList));
|
||||
} else
|
||||
#endif
|
||||
if (csr_roam_is_fast_roam_enabled(pMac, session_id)) {
|
||||
/* Always the BSS info in the head is the handoff candidate */
|
||||
bss_node =
|
||||
csr_neighbor_roam_next_roamable_ap(pMac,
|
||||
&ngbr_roam_info->FTRoamInfo.preAuthDoneList,
|
||||
NULL);
|
||||
sms_log(pMac, LOG1,
|
||||
FL("Number of Handoff candidates = %d"),
|
||||
csr_ll_count(
|
||||
&ngbr_roam_info->FTRoamInfo.preAuthDoneList));
|
||||
} else {
|
||||
bss_node =
|
||||
csr_neighbor_roam_next_roamable_ap(pMac,
|
||||
&ngbr_roam_info->roamableAPList,
|
||||
NULL);
|
||||
sms_log(pMac, LOG1,
|
||||
FL("Number of Handoff candidates = %d"),
|
||||
csr_ll_count(&ngbr_roam_info->roamableAPList));
|
||||
}
|
||||
if (NULL == bss_node)
|
||||
return false;
|
||||
qdf_mem_copy(hand_off_node, bss_node, sizeof(tCsrNeighborRoamBSSInfo));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* csr_neighbor_roam_is_handoff_in_progress()
|
||||
*
|
||||
* @mac_ctx: Pointer to Global MAC structure
|
||||
* @session_id: Session ID
|
||||
*
|
||||
* This function returns whether handoff is in progress or not based on
|
||||
* the current neighbor roam state
|
||||
*
|
||||
* Return: true if reassoc in progress, false otherwise
|
||||
*/
|
||||
bool csr_neighbor_roam_is_handoff_in_progress(tpAniSirGlobal pMac,
|
||||
uint8_t sessionId)
|
||||
{
|
||||
if (eCSR_NEIGHBOR_ROAM_STATE_REASSOCIATING ==
|
||||
pMac->roam.neighborRoamInfo[sessionId].neighborRoamState)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* csr_neighbor_roam_free_neighbor_roam_bss_node()
|
||||
*
|
||||
* @mac_ctx: Pointer to Global MAC structure
|
||||
* @neighborRoamBSSNode: Neighbor Roam BSS Node to be freed
|
||||
*
|
||||
* This function frees all the internal pointers CSR NeighborRoam BSS Info
|
||||
* and also frees the node itself
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void csr_neighbor_roam_free_neighbor_roam_bss_node(tpAniSirGlobal pMac,
|
||||
tpCsrNeighborRoamBSSInfo
|
||||
neighborRoamBSSNode)
|
||||
{
|
||||
if (neighborRoamBSSNode) {
|
||||
if (neighborRoamBSSNode->pBssDescription) {
|
||||
qdf_mem_free(neighborRoamBSSNode->pBssDescription);
|
||||
neighborRoamBSSNode->pBssDescription = NULL;
|
||||
}
|
||||
qdf_mem_free(neighborRoamBSSNode);
|
||||
neighborRoamBSSNode = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -119,135 +119,6 @@ void csr_neighbor_roam_send_lfr_metric_event(
|
|||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* csr_neighbor_roam_free_neighbor_roam_bss_node()
|
||||
*
|
||||
* @mac_ctx: Pointer to Global MAC structure
|
||||
* @neighborRoamBSSNode: Neighbor Roam BSS Node to be freed
|
||||
*
|
||||
* This function frees all the internal pointers CSR NeighborRoam BSS Info
|
||||
* and also frees the node itself
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void csr_neighbor_roam_free_neighbor_roam_bss_node(tpAniSirGlobal pMac,
|
||||
tpCsrNeighborRoamBSSInfo
|
||||
neighborRoamBSSNode)
|
||||
{
|
||||
if (neighborRoamBSSNode) {
|
||||
if (neighborRoamBSSNode->pBssDescription) {
|
||||
qdf_mem_free(neighborRoamBSSNode->pBssDescription);
|
||||
neighborRoamBSSNode->pBssDescription = NULL;
|
||||
}
|
||||
qdf_mem_free(neighborRoamBSSNode);
|
||||
neighborRoamBSSNode = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* csr_neighbor_roam_remove_roamable_ap_list_entry()
|
||||
*
|
||||
* @mac_ctx: Pointer to Global MAC structure
|
||||
* @pList: The list from which the entry should be removed
|
||||
* @pNeighborEntry: Neighbor Roam BSS Node to be removed
|
||||
*
|
||||
* This function removes a given entry from the given list
|
||||
*
|
||||
* Return: true if successfully removed, else false
|
||||
*/
|
||||
bool csr_neighbor_roam_remove_roamable_ap_list_entry(tpAniSirGlobal pMac,
|
||||
tDblLinkList *pList,
|
||||
tpCsrNeighborRoamBSSInfo
|
||||
pNeighborEntry)
|
||||
{
|
||||
if (pList) {
|
||||
return csr_ll_remove_entry(pList, &pNeighborEntry->List,
|
||||
LL_ACCESS_LOCK);
|
||||
}
|
||||
|
||||
sms_log(pMac, LOGE,
|
||||
FL
|
||||
("Removing neighbor BSS node from list failed. Current count = %d"),
|
||||
csr_ll_count(pList));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* csr_neighbor_roam_next_roamable_ap() - Get next AP from roamable AP list
|
||||
* @mac_ctx - The handle returned by mac_open.
|
||||
* @plist - The list from which the entry should be returned
|
||||
* @neighbor_entry - Neighbor Roam BSS Node whose next entry should be returned
|
||||
*
|
||||
* Gets the entry next to passed entry. If NULL is passed, return the entry
|
||||
* in the head of the list
|
||||
*
|
||||
* Return: Neighbor Roam BSS Node to be returned
|
||||
*/
|
||||
tpCsrNeighborRoamBSSInfo csr_neighbor_roam_next_roamable_ap(
|
||||
tpAniSirGlobal mac_ctx, tDblLinkList *llist,
|
||||
tpCsrNeighborRoamBSSInfo neighbor_entry)
|
||||
{
|
||||
tListElem *entry = NULL;
|
||||
tpCsrNeighborRoamBSSInfo result = NULL;
|
||||
|
||||
if (llist) {
|
||||
if (NULL == neighbor_entry)
|
||||
entry = csr_ll_peek_head(llist, LL_ACCESS_LOCK);
|
||||
else
|
||||
entry = csr_ll_next(llist, &neighbor_entry->List,
|
||||
LL_ACCESS_LOCK);
|
||||
if (entry)
|
||||
result = GET_BASE_ADDR(entry, tCsrNeighborRoamBSSInfo,
|
||||
List);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* csr_neighbor_roam_free_roamable_bss_list() - Frees roamable APs list
|
||||
* @mac_ctx: The handle returned by mac_open.
|
||||
* @llist: Neighbor Roam BSS List to be emptied
|
||||
*
|
||||
* Empties and frees all the nodes in the roamable AP list
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
void csr_neighbor_roam_free_roamable_bss_list(tpAniSirGlobal mac_ctx,
|
||||
tDblLinkList *llist)
|
||||
{
|
||||
tpCsrNeighborRoamBSSInfo result = NULL;
|
||||
|
||||
NEIGHBOR_ROAM_DEBUG(mac_ctx, LOG2,
|
||||
FL("Emptying the BSS list. Current count = %d"),
|
||||
csr_ll_count(llist));
|
||||
|
||||
/*
|
||||
* Pick up the head, remove and free the node till
|
||||
* the list becomes empty
|
||||
*/
|
||||
while ((result = csr_neighbor_roam_next_roamable_ap(mac_ctx, llist,
|
||||
NULL)) != NULL) {
|
||||
csr_neighbor_roam_remove_roamable_ap_list_entry(mac_ctx,
|
||||
llist, result);
|
||||
csr_neighbor_roam_free_neighbor_roam_bss_node(mac_ctx, result);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void csr_neighbor_roam_trigger_handoff(tpAniSirGlobal pMac,
|
||||
uint8_t sessionId)
|
||||
{
|
||||
if (csr_roam_is_fast_roam_enabled(pMac, sessionId)) {
|
||||
csr_neighbor_roam_issue_preauth_req(pMac, sessionId);
|
||||
} else {
|
||||
sms_log(pMac, LOGE, FL("Roaming is diisabled"));
|
||||
}
|
||||
}
|
||||
|
||||
QDF_STATUS
|
||||
csr_neighbor_roam_update_fast_roaming_enabled(tpAniSirGlobal pMac,
|
||||
uint8_t sessionId,
|
||||
|
|
@ -955,303 +826,6 @@ uint32_t csr_get_current_ap_rssi(tpAniSirGlobal pMac,
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* csr_neighbor_roam_process_scan_results() - build roaming candidate list
|
||||
*
|
||||
* @mac_ctx: The handle returned by mac_open.
|
||||
* @sessionid: Session information
|
||||
* @scan_results_list: List obtained from csr_scan_get_result()
|
||||
*
|
||||
* This function applies various candidate checks like LFR, 11r, preauth, ESE
|
||||
* and builds a roamable AP list. It applies age limit only if no suitable
|
||||
* recent candidates are found.
|
||||
*
|
||||
* Output list is built in mac_ctx->roam.neighborRoamInfo[sessionid].
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
|
||||
static void
|
||||
csr_neighbor_roam_process_scan_results(tpAniSirGlobal mac_ctx,
|
||||
uint8_t sessionid,
|
||||
tScanResultHandle *scan_results_list)
|
||||
{
|
||||
tCsrScanResultInfo *scan_result;
|
||||
tpCsrNeighborRoamControlInfo n_roam_info =
|
||||
&mac_ctx->roam.neighborRoamInfo[sessionid];
|
||||
tpCsrNeighborRoamBSSInfo bss_info;
|
||||
uint32_t cur_ap_rssi;
|
||||
uint32_t age_ticks = 0;
|
||||
uint32_t limit_ticks =
|
||||
qdf_system_msecs_to_ticks(ROAM_AP_AGE_LIMIT_MS);
|
||||
uint8_t num_candidates = 0;
|
||||
uint8_t num_dropped = 0;
|
||||
/*
|
||||
* first iteration of scan list should consider
|
||||
* age constraint for candidates
|
||||
*/
|
||||
bool age_constraint = true;
|
||||
#ifdef FEATURE_WLAN_ESE
|
||||
uint16_t qpresent;
|
||||
uint16_t qavail;
|
||||
bool voadmitted;
|
||||
#endif
|
||||
/*
|
||||
* Find out the Current AP RSSI and keep it handy to check if
|
||||
* it is better than the RSSI of the AP which we are
|
||||
* going to roam.If so, we are going to continue with the
|
||||
* current AP.
|
||||
*/
|
||||
cur_ap_rssi = csr_get_current_ap_rssi(mac_ctx, scan_results_list,
|
||||
sessionid);
|
||||
|
||||
/*
|
||||
* Expecting the scan result already to be in the sorted order based on
|
||||
* RSSI. Based on the previous state we need to check whether the list
|
||||
* should be sorted again taking neighbor score into consideration. If
|
||||
* previous state is CFG_CHAN_LIST_SCAN, there should not be a neighbor
|
||||
* score associated with any of the BSS. If the previous state is
|
||||
* REPORT_QUERY, then there will be neighbor score for each of the APs.
|
||||
* For now, let us take top of the list provided as it is by CSR Scan
|
||||
* result API. Hence it is assumed that neighbor score and rssi score
|
||||
* are in the same order. This will be taken care later.
|
||||
*/
|
||||
|
||||
do {
|
||||
while (true) {
|
||||
tSirBssDescription *descr;
|
||||
|
||||
scan_result = csr_scan_result_get_next(
|
||||
mac_ctx, *scan_results_list);
|
||||
if (NULL == scan_result)
|
||||
break;
|
||||
descr = &scan_result->BssDescriptor;
|
||||
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
|
||||
FL("Scan result: BSSID " MAC_ADDRESS_STR
|
||||
" (Rssi %ld, Ch:%d)"),
|
||||
MAC_ADDR_ARRAY(descr->bssId),
|
||||
abs(descr->rssi), descr->channelId);
|
||||
|
||||
if (true != qdf_mem_cmp(descr->bssId,
|
||||
n_roam_info->currAPbssid.bytes,
|
||||
sizeof(tSirMacAddr))) {
|
||||
/*
|
||||
* currently associated AP. Do not have this
|
||||
* in the roamable AP list
|
||||
*/
|
||||
QDF_TRACE(QDF_MODULE_ID_SME,
|
||||
QDF_TRACE_LEVEL_INFO,
|
||||
"SKIP-currently associated AP");
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* In case of reassoc requested by upper layer, look
|
||||
* for exact match of bssid & channel. csr cache might
|
||||
* have duplicates
|
||||
*/
|
||||
if ((n_roam_info->uOsRequestedHandoff) &&
|
||||
((false != qdf_mem_cmp(descr->bssId,
|
||||
n_roam_info->handoffReqInfo.bssid.bytes,
|
||||
sizeof(tSirMacAddr)))
|
||||
|| (descr->channelId !=
|
||||
n_roam_info->handoffReqInfo.channel))) {
|
||||
QDF_TRACE(QDF_MODULE_ID_SME,
|
||||
QDF_TRACE_LEVEL_INFO,
|
||||
"SKIP-not a candidate AP for OS requested roam");
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((n_roam_info->is11rAssoc) &&
|
||||
(!csr_neighbor_roam_is_preauth_candidate(mac_ctx,
|
||||
sessionid, descr->bssId))) {
|
||||
sms_log(mac_ctx, LOGE,
|
||||
FL("BSSID present in pre-auth fail list.. Ignoring"));
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef FEATURE_WLAN_ESE
|
||||
if (!csr_roam_is_roam_offload_scan_enabled(mac_ctx) &&
|
||||
(n_roam_info->isESEAssoc) &&
|
||||
!csr_neighbor_roam_is_preauth_candidate(mac_ctx,
|
||||
sessionid, descr->bssId)) {
|
||||
sms_log(mac_ctx, LOGE,
|
||||
FL("BSSID present in pre-auth fail list.. Ignoring"));
|
||||
continue;
|
||||
}
|
||||
|
||||
qpresent = descr->QBSSLoad_present;
|
||||
qavail = descr->QBSSLoad_avail;
|
||||
voadmitted = n_roam_info->isVOAdmitted;
|
||||
if (voadmitted)
|
||||
sms_log(mac_ctx, LOG1,
|
||||
FL("New AP QBSS present = %s, BW available = 0x%x, required = 0x%x"),
|
||||
((qpresent) ? "yes" : "no"), qavail,
|
||||
n_roam_info->MinQBssLoadRequired);
|
||||
if (voadmitted && qpresent &&
|
||||
(qavail < n_roam_info->MinQBssLoadRequired)) {
|
||||
QDF_TRACE(QDF_MODULE_ID_SME,
|
||||
QDF_TRACE_LEVEL_INFO,
|
||||
"BSSID : " MAC_ADDRESS_STR " has no bandwidth, ignoring",
|
||||
MAC_ADDR_ARRAY(descr->bssId));
|
||||
continue;
|
||||
}
|
||||
if (voadmitted && !qpresent) {
|
||||
QDF_TRACE(QDF_MODULE_ID_SME,
|
||||
QDF_TRACE_LEVEL_INFO,
|
||||
"BSSID : " MAC_ADDRESS_STR " has no QBSS LOAD IE, ignoring",
|
||||
MAC_ADDR_ARRAY(descr->bssId));
|
||||
continue;
|
||||
}
|
||||
#endif /* FEATURE_WLAN_ESE */
|
||||
|
||||
/*
|
||||
* If we are supporting legacy roaming, and
|
||||
* if the candidate is on the "pre-auth failed" list,
|
||||
* ignore it.
|
||||
*/
|
||||
if (csr_roam_is_fast_roam_enabled(mac_ctx, sessionid) &&
|
||||
!csr_neighbor_roam_is_preauth_candidate(mac_ctx,
|
||||
sessionid, descr->bssId)) {
|
||||
sms_log(mac_ctx, LOGE,
|
||||
FL("BSSID present in pre-auth fail list.. Ignoring"));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check the age of the AP */
|
||||
age_ticks = (uint32_t) qdf_mc_timer_get_system_ticks() -
|
||||
descr->nReceivedTime;
|
||||
if (age_constraint == true && age_ticks > limit_ticks) {
|
||||
num_dropped++;
|
||||
QDF_TRACE(QDF_MODULE_ID_SME,
|
||||
QDF_TRACE_LEVEL_WARN,
|
||||
FL("Old AP (probe rsp/beacon) skipped.")
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Finished all checks, now add it to candidate list */
|
||||
bss_info =
|
||||
qdf_mem_malloc(sizeof(tCsrNeighborRoamBSSInfo));
|
||||
if (NULL == bss_info) {
|
||||
sms_log(mac_ctx, LOGE,
|
||||
FL("Memory allocation failed. Ignored candidate."));
|
||||
continue;
|
||||
}
|
||||
bss_info->pBssDescription =
|
||||
qdf_mem_malloc(descr->length +
|
||||
sizeof(descr->length));
|
||||
if (bss_info->pBssDescription != NULL) {
|
||||
qdf_mem_copy(bss_info->pBssDescription, descr,
|
||||
descr->length + sizeof(descr->length));
|
||||
} else {
|
||||
sms_log(mac_ctx, LOGE,
|
||||
FL("Memory allocation failed. Ignored candidate."));
|
||||
qdf_mem_free(bss_info);
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* Assign some preference value for now. Need to
|
||||
* calculate theactual score based on RSSI and neighbor
|
||||
* AP score
|
||||
*/
|
||||
bss_info->apPreferenceVal = 10;
|
||||
num_candidates++;
|
||||
csr_ll_insert_tail(&n_roam_info->roamableAPList,
|
||||
&bss_info->List, LL_ACCESS_LOCK);
|
||||
} /* end of while (csr_scan_result_get_next) */
|
||||
|
||||
/* if some candidates were found, then no need to repeat */
|
||||
if (num_candidates)
|
||||
break;
|
||||
/*
|
||||
* if age_constraint is already false, we have done two
|
||||
* iterations and no candidate were found
|
||||
*/
|
||||
if (age_constraint == false) {
|
||||
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
|
||||
"%s: No roam able candidates found",
|
||||
__func__);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* if all candidates were dropped rescan the scan
|
||||
* list but this time without age constraint.
|
||||
*/
|
||||
age_constraint = false;
|
||||
/* if no candidates were dropped no need to repeat */
|
||||
} while (num_dropped);
|
||||
|
||||
/*
|
||||
* Now we have all the scan results in our local list. Good time to free
|
||||
* up the the list we got as a part of csrGetScanResult
|
||||
*/
|
||||
csr_scan_result_purge(mac_ctx, *scan_results_list);
|
||||
}
|
||||
|
||||
static QDF_STATUS csr_neighbor_roam_process_scan_complete(tpAniSirGlobal pMac,
|
||||
uint8_t sessionId)
|
||||
{
|
||||
tpCsrNeighborRoamControlInfo pNeighborRoamInfo =
|
||||
&pMac->roam.neighborRoamInfo[sessionId];
|
||||
tCsrScanResultFilter scanFilter;
|
||||
tScanResultHandle scanResult;
|
||||
uint32_t tempVal = 0;
|
||||
QDF_STATUS hstatus;
|
||||
|
||||
hstatus = csr_neighbor_roam_prepare_scan_profile_filter(pMac,
|
||||
&scanFilter,
|
||||
sessionId);
|
||||
NEIGHBOR_ROAM_DEBUG(pMac, LOGW,
|
||||
FL
|
||||
("11R/ESE/Other Association: Prepare scan to find neighbor AP filter status = %d"),
|
||||
hstatus);
|
||||
if (QDF_STATUS_SUCCESS != hstatus) {
|
||||
sms_log(pMac, LOGE,
|
||||
FL
|
||||
("Scan Filter preparation failed for Assoc type %d.. Bailing out.."),
|
||||
tempVal);
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
hstatus = csr_scan_get_result(pMac, &scanFilter, &scanResult);
|
||||
if (hstatus != QDF_STATUS_SUCCESS) {
|
||||
NEIGHBOR_ROAM_DEBUG(pMac, LOGE,
|
||||
FL("Get Scan Result status code %d"),
|
||||
hstatus);
|
||||
}
|
||||
/* Process the scan results and update roamable AP list */
|
||||
csr_neighbor_roam_process_scan_results(pMac, sessionId, &scanResult);
|
||||
|
||||
/* Free the scan filter */
|
||||
csr_free_scan_filter(pMac, &scanFilter);
|
||||
|
||||
tempVal = csr_ll_count(&pNeighborRoamInfo->roamableAPList);
|
||||
|
||||
if (tempVal) {
|
||||
csr_neighbor_roam_trigger_handoff(pMac, sessionId);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (csr_roam_is_roam_offload_scan_enabled(pMac)) {
|
||||
if (pNeighborRoamInfo->uOsRequestedHandoff) {
|
||||
csr_roam_offload_scan(pMac, sessionId,
|
||||
ROAM_SCAN_OFFLOAD_START,
|
||||
REASON_NO_CAND_FOUND_OR_NOT_ROAMING_NOW);
|
||||
pNeighborRoamInfo->uOsRequestedHandoff = 0;
|
||||
} else {
|
||||
/* There is no candidate or We are not roaming Now.
|
||||
* Inform the FW to restart Roam Offload Scan */
|
||||
csr_roam_offload_scan(pMac, sessionId,
|
||||
ROAM_SCAN_OFFLOAD_RESTART,
|
||||
REASON_NO_CAND_FOUND_OR_NOT_ROAMING_NOW);
|
||||
}
|
||||
csr_neighbor_roam_state_transition(pMac,
|
||||
eCSR_NEIGHBOR_ROAM_STATE_CONNECTED, sessionId);
|
||||
}
|
||||
return QDF_STATUS_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* csr_neighbor_roam_channels_filter_by_current_band()
|
||||
*
|
||||
|
|
@ -2429,124 +2003,6 @@ void csr_neighbor_roam_close(tpAniSirGlobal pMac, uint8_t sessionId)
|
|||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* csr_neighbor_roam_request_handoff() - Handoff to a different AP
|
||||
* @mac_ctx: Pointer to Global MAC structure
|
||||
* @session_id: Session ID
|
||||
*
|
||||
* This function triggers actual switching from one AP to the new AP.
|
||||
* It issues disassociate with reason code as Handoff and CSR as a part of
|
||||
* handling disassoc rsp, issues reassociate to the new AP
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
void csr_neighbor_roam_request_handoff(tpAniSirGlobal mac_ctx,
|
||||
uint8_t session_id)
|
||||
{
|
||||
tCsrRoamInfo roam_info;
|
||||
tpCsrNeighborRoamControlInfo neighbor_roam_info =
|
||||
&mac_ctx->roam.neighborRoamInfo[session_id];
|
||||
tCsrNeighborRoamBSSInfo handoff_node;
|
||||
uint32_t roamid = 0;
|
||||
QDF_STATUS status;
|
||||
|
||||
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, "%s session_id=%d",
|
||||
__func__, session_id);
|
||||
|
||||
if (neighbor_roam_info->neighborRoamState !=
|
||||
eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE) {
|
||||
sms_log(mac_ctx, LOGE,
|
||||
FL("Roam requested when Neighbor roam is in %s state"),
|
||||
mac_trace_get_neighbour_roam_state(
|
||||
neighbor_roam_info->neighborRoamState));
|
||||
return;
|
||||
}
|
||||
|
||||
if (false == csr_neighbor_roam_get_handoff_ap_info(mac_ctx,
|
||||
&handoff_node, session_id)) {
|
||||
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
|
||||
FL("failed to obtain handoff AP"));
|
||||
return;
|
||||
}
|
||||
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
|
||||
FL("HANDOFF CANDIDATE BSSID "MAC_ADDRESS_STR),
|
||||
MAC_ADDR_ARRAY(handoff_node.pBssDescription->bssId));
|
||||
|
||||
qdf_mem_zero(&roam_info, sizeof(tCsrRoamInfo));
|
||||
csr_roam_call_callback(mac_ctx, session_id, &roam_info, roamid,
|
||||
eCSR_ROAM_FT_START, eSIR_SME_SUCCESS);
|
||||
|
||||
qdf_mem_zero(&roam_info, sizeof(tCsrRoamInfo));
|
||||
csr_neighbor_roam_state_transition(mac_ctx,
|
||||
eCSR_NEIGHBOR_ROAM_STATE_REASSOCIATING, session_id);
|
||||
|
||||
csr_neighbor_roam_send_lfr_metric_event(mac_ctx, session_id,
|
||||
handoff_node.pBssDescription->bssId,
|
||||
eCSR_ROAM_HANDOVER_SUCCESS);
|
||||
/* Free the profile.. Just to make sure we dont leak memory here */
|
||||
csr_release_profile(mac_ctx,
|
||||
&neighbor_roam_info->csrNeighborRoamProfile);
|
||||
/*
|
||||
* Create the Handoff AP profile. Copy the currently connected profile
|
||||
* and update only the BSSID and channel number. This should happen
|
||||
* before issuing disconnect
|
||||
*/
|
||||
status = csr_roam_copy_connected_profile(mac_ctx, session_id,
|
||||
&neighbor_roam_info->csrNeighborRoamProfile);
|
||||
if (QDF_STATUS_SUCCESS != status) {
|
||||
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
|
||||
FL("csr_roam_copy_connected_profile failed %d"),
|
||||
status);
|
||||
return;
|
||||
}
|
||||
qdf_mem_copy(neighbor_roam_info->csrNeighborRoamProfile.BSSIDs.bssid,
|
||||
handoff_node.pBssDescription->bssId, sizeof(tSirMacAddr));
|
||||
neighbor_roam_info->csrNeighborRoamProfile.ChannelInfo.ChannelList[0] =
|
||||
handoff_node.pBssDescription->channelId;
|
||||
|
||||
NEIGHBOR_ROAM_DEBUG(mac_ctx, LOGW,
|
||||
" csr_roamHandoffRequested: disassociating with current AP");
|
||||
|
||||
if (!QDF_IS_STATUS_SUCCESS
|
||||
(csr_roam_issue_disassociate_cmd
|
||||
(mac_ctx, session_id,
|
||||
eCSR_DISCONNECT_REASON_HANDOFF))) {
|
||||
sms_log(mac_ctx, LOGW,
|
||||
"csr_roamHandoffRequested: fail to issue disassociate");
|
||||
return;
|
||||
}
|
||||
/* notify HDD for handoff, providing the BSSID too */
|
||||
roam_info.reasonCode = eCsrRoamReasonBetterAP;
|
||||
|
||||
qdf_mem_copy(roam_info.bssid.bytes,
|
||||
handoff_node.pBssDescription->bssId,
|
||||
sizeof(struct qdf_mac_addr));
|
||||
|
||||
csr_roam_call_callback(mac_ctx, session_id, &roam_info, 0,
|
||||
eCSR_ROAM_ROAMING_START, eCSR_ROAM_RESULT_NONE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* csr_neighbor_roam_is_handoff_in_progress()
|
||||
*
|
||||
* @mac_ctx: Pointer to Global MAC structure
|
||||
* @session_id: Session ID
|
||||
*
|
||||
* This function returns whether handoff is in progress or not based on
|
||||
* the current neighbor roam state
|
||||
*
|
||||
* Return: true if reassoc in progress, false otherwise
|
||||
*/
|
||||
bool csr_neighbor_roam_is_handoff_in_progress(tpAniSirGlobal pMac, uint8_t sessionId)
|
||||
{
|
||||
if (eCSR_NEIGHBOR_ROAM_STATE_REASSOCIATING ==
|
||||
pMac->roam.neighborRoamInfo[sessionId].neighborRoamState)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* csr_neighbor_roam_is11r_assoc() - Check if association type is 11R
|
||||
* @mac_ctx: MAC Global context
|
||||
|
|
@ -2559,82 +2015,6 @@ bool csr_neighbor_roam_is11r_assoc(tpAniSirGlobal mac_ctx, uint8_t session_id)
|
|||
return mac_ctx->roam.neighborRoamInfo[session_id].is11rAssoc;
|
||||
}
|
||||
|
||||
/**
|
||||
* csr_neighbor_roam_get_handoff_ap_info - Identifies the best AP for roaming
|
||||
*
|
||||
* @pMac: mac context
|
||||
* @session_id: Session Id
|
||||
* @hand_off_node: AP node that is the handoff candidate returned
|
||||
*
|
||||
* This function returns the best possible AP for handoff. For 11R case, it
|
||||
* returns the 1st entry from pre-auth done list. For non-11r case, it returns
|
||||
* the 1st entry from roamable AP list
|
||||
*
|
||||
* Return: true if able find handoff AP, false otherwise
|
||||
*/
|
||||
|
||||
bool csr_neighbor_roam_get_handoff_ap_info(tpAniSirGlobal pMac,
|
||||
tpCsrNeighborRoamBSSInfo hand_off_node,
|
||||
uint8_t session_id)
|
||||
{
|
||||
tpCsrNeighborRoamControlInfo ngbr_roam_info =
|
||||
&pMac->roam.neighborRoamInfo[session_id];
|
||||
tpCsrNeighborRoamBSSInfo bss_node = NULL;
|
||||
|
||||
if (NULL == hand_off_node) {
|
||||
QDF_ASSERT(NULL != hand_off_node);
|
||||
return false;
|
||||
}
|
||||
if (ngbr_roam_info->is11rAssoc) {
|
||||
/* Always the BSS info in the head is the handoff candidate */
|
||||
bss_node = csr_neighbor_roam_next_roamable_ap(
|
||||
pMac,
|
||||
&ngbr_roam_info->FTRoamInfo.preAuthDoneList,
|
||||
NULL);
|
||||
NEIGHBOR_ROAM_DEBUG(pMac, LOG1,
|
||||
FL("Number of Handoff candidates = %d"),
|
||||
csr_ll_count(&
|
||||
ngbr_roam_info->FTRoamInfo.preAuthDoneList));
|
||||
} else
|
||||
#ifdef FEATURE_WLAN_ESE
|
||||
if (ngbr_roam_info->isESEAssoc) {
|
||||
/* Always the BSS info in the head is the handoff candidate */
|
||||
bss_node =
|
||||
csr_neighbor_roam_next_roamable_ap(pMac,
|
||||
&ngbr_roam_info->FTRoamInfo.preAuthDoneList,
|
||||
NULL);
|
||||
NEIGHBOR_ROAM_DEBUG(pMac, LOG1,
|
||||
FL("Number of Handoff candidates = %d"),
|
||||
csr_ll_count(&ngbr_roam_info->FTRoamInfo.
|
||||
preAuthDoneList));
|
||||
} else
|
||||
#endif
|
||||
if (csr_roam_is_fast_roam_enabled(pMac, session_id)) {
|
||||
/* Always the BSS info in the head is the handoff candidate */
|
||||
bss_node =
|
||||
csr_neighbor_roam_next_roamable_ap(pMac,
|
||||
&ngbr_roam_info->FTRoamInfo.preAuthDoneList,
|
||||
NULL);
|
||||
NEIGHBOR_ROAM_DEBUG(pMac, LOG1,
|
||||
FL("Number of Handoff candidates = %d"),
|
||||
csr_ll_count(
|
||||
&ngbr_roam_info->FTRoamInfo.preAuthDoneList));
|
||||
} else {
|
||||
bss_node =
|
||||
csr_neighbor_roam_next_roamable_ap(pMac,
|
||||
&ngbr_roam_info->roamableAPList,
|
||||
NULL);
|
||||
NEIGHBOR_ROAM_DEBUG(pMac, LOG1,
|
||||
FL("Number of Handoff candidates = %d"),
|
||||
csr_ll_count(&ngbr_roam_info->roamableAPList));
|
||||
}
|
||||
if (NULL == bss_node)
|
||||
return false;
|
||||
qdf_mem_copy(hand_off_node, bss_node, sizeof(tCsrNeighborRoamBSSInfo));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
\brief This function returns true if STA is in the middle of roaming states
|
||||
|
||||
|
|
@ -2657,62 +2037,6 @@ bool csr_neighbor_middle_of_roaming(tpAniSirGlobal pMac, uint8_t sessionId)
|
|||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* csr_neighbor_roam_candidate_found_ind_hdlr()
|
||||
*
|
||||
* @mac_ctx: Pointer to Global MAC structure
|
||||
* @msg_buf: pointer to msg buff
|
||||
*
|
||||
* This function is called by CSR as soon as TL posts the candidate
|
||||
* found indication to SME via MC thread
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success, corresponding error code otherwise
|
||||
*/
|
||||
QDF_STATUS csr_neighbor_roam_candidate_found_ind_hdlr(tpAniSirGlobal pMac, void *pMsg)
|
||||
{
|
||||
tSirSmeCandidateFoundInd *pSirSmeCandidateFoundInd =
|
||||
(tSirSmeCandidateFoundInd *) pMsg;
|
||||
uint32_t sessionId = pSirSmeCandidateFoundInd->sessionId;
|
||||
tpCsrNeighborRoamControlInfo pNeighborRoamInfo =
|
||||
&pMac->roam.neighborRoamInfo[sessionId];
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
|
||||
sms_log(pMac, LOG1, FL("Received indication from firmware"));
|
||||
|
||||
/* we must be in connected state, if not ignore it */
|
||||
if ((eCSR_NEIGHBOR_ROAM_STATE_CONNECTED !=
|
||||
pNeighborRoamInfo->neighborRoamState)
|
||||
|| (pNeighborRoamInfo->uOsRequestedHandoff)) {
|
||||
sms_log(pMac, LOGE,
|
||||
FL
|
||||
("Received in not CONNECTED state OR uOsRequestedHandoff is set. Ignore it"));
|
||||
status = QDF_STATUS_E_FAILURE;
|
||||
} else {
|
||||
/* Firmware indicated that roaming candidate is found. Beacons
|
||||
* are already in the SME scan results table.
|
||||
* Process the results for choosing best roaming candidate.
|
||||
*/
|
||||
csr_save_scan_results(pMac, eCsrScanCandidateFound,
|
||||
sessionId);
|
||||
/* Future enhancements:
|
||||
* If firmware tags candidate beacons, give them preference
|
||||
* for roaming.
|
||||
* Age out older entries so that new candidate beacons
|
||||
* will get preference.
|
||||
*/
|
||||
status = csr_neighbor_roam_process_scan_complete(pMac,
|
||||
sessionId);
|
||||
if (QDF_STATUS_SUCCESS != status) {
|
||||
sms_log(pMac, LOGE,
|
||||
FL("Neighbor scan process complete failed with status %d"),
|
||||
status);
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* csr_neighbor_roam_process_handoff_req - Processes handoff request
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in a new issue