diff options
| author | Varun Reddy Yeturu <varunreddy.yeturu@codeaurora.org> | 2016-02-22 10:07:02 -0800 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2016-04-17 18:10:26 -0700 |
| commit | 86459d63ca6d141bf3045af9166f8a3fc1bcb3a1 (patch) | |
| tree | c0e2a9fef75990b0fee20e5a930ce8eb5892e82b /core | |
| parent | 883c4f20f9f3073e49d1a68c1b4d2e91c55d3d3c (diff) | |
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
Diffstat (limited to 'core')
| -rw-r--r-- | core/sme/inc/csr_internal.h | 3 | ||||
| -rw-r--r-- | core/sme/inc/csr_neighbor_roam.h | 14 | ||||
| -rw-r--r-- | core/sme/src/csr/csr_api_roam.c | 83 | ||||
| -rw-r--r-- | core/sme/src/csr/csr_host_scan_roam.c | 816 | ||||
| -rw-r--r-- | core/sme/src/csr/csr_neighbor_roam.c | 676 |
5 files changed, 833 insertions, 759 deletions
diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index 3b5616280317..a476d8d493aa 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -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 diff --git a/core/sme/inc/csr_neighbor_roam.h b/core/sme/inc/csr_neighbor_roam.h index 00fc97725f9a..5bae53f64cf1 100644 --- a/core/sme/inc/csr_neighbor_roam.h +++ b/core/sme/inc/csr_neighbor_roam.h @@ -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 */ diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 800a28d71f84..310dd9a251f0 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -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) diff --git a/core/sme/src/csr/csr_host_scan_roam.c b/core/sme/src/csr/csr_host_scan_roam.c new file mode 100644 index 000000000000..fb29ee10db7f --- /dev/null +++ b/core/sme/src/csr/csr_host_scan_roam.c @@ -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; +} + diff --git a/core/sme/src/csr/csr_neighbor_roam.c b/core/sme/src/csr/csr_neighbor_roam.c index 76781a8bb692..469e788c76af 100644 --- a/core/sme/src/csr/csr_neighbor_roam.c +++ b/core/sme/src/csr/csr_neighbor_roam.c @@ -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, @@ -956,303 +827,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() * * @mac_ctx: Pointer to Global MAC structure @@ -2430,124 +2004,6 @@ void csr_neighbor_roam_close(tpAniSirGlobal pMac, uint8_t sessionId) } /** - * 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 * @session_id: Session ID @@ -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 @@ -2658,62 +2038,6 @@ bool csr_neighbor_middle_of_roaming(tpAniSirGlobal pMac, uint8_t sessionId) } /** - * 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 * * @mac_ctx Pointer to mac context |
