1 /* 2 * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /* 20 * DOC: sme_rrm.c 21 * 22 * Implementation for SME RRM APIs 23 */ 24 25 #include "ani_global.h" 26 #include "sme_inside.h" 27 #include "sme_api.h" 28 #include "cfg_api.h" 29 30 #ifdef FEATURE_WLAN_DIAG_SUPPORT 31 #include "host_diag_core_event.h" 32 #include "host_diag_core_log.h" 33 #endif /* FEATURE_WLAN_DIAG_SUPPORT */ 34 35 #include "csr_inside_api.h" 36 37 #include "rrm_global.h" 38 #include <wlan_scan_ucfg_api.h> 39 #include <wlan_scan_utils_api.h> 40 #include <wlan_utility.h> 41 42 /* Roam score for a neighbor AP will be calculated based on the below 43 * definitions. The calculated roam score will be used to select the 44 * roamable candidate from neighbor AP list 45 */ 46 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_REACHABILITY 0 47 /* When we support 11r over the DS, this should have a non-zero value */ 48 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_SECURITY 10 49 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_KEY_SCOPE 20 50 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_SPECTRUM_MGMT 0 51 /* Not used */ 52 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_QOS 5 53 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_APSD 3 54 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_RRM 8 55 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_DELAYED_BA 0 56 /* We dont support delayed BA */ 57 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_IMMEDIATE_BA 3 58 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_MOBILITY_DOMAIN 30 59 60 #ifdef FEATURE_WLAN_ESE 61 #define RRM_ROAM_SCORE_NEIGHBOR_IAPP_LIST 30 62 #endif 63 64 uint64_t rrm_scan_timer; 65 66 /** 67 * rrm_ll_purge_neighbor_cache() -Purges all the entries in the neighbor cache 68 * 69 * @pMac: Pointer to the Hal Handle. 70 * @pList: Pointer the List that should be purged. 71 * 72 * This function purges all the entries in the neighbor cache and frees up all 73 * the internal nodes 74 * 75 * Return: void 76 */ 77 static void rrm_ll_purge_neighbor_cache(tpAniSirGlobal pMac, 78 tDblLinkList *pList) 79 { 80 tListElem *pEntry; 81 tRrmNeighborReportDesc *pNeighborReportDesc; 82 83 csr_ll_lock(pList); 84 while ((pEntry = csr_ll_remove_head(pList, LL_ACCESS_NOLOCK)) != NULL) { 85 pNeighborReportDesc = 86 GET_BASE_ADDR(pEntry, tRrmNeighborReportDesc, List); 87 qdf_mem_free(pNeighborReportDesc->pNeighborBssDescription); 88 qdf_mem_free(pNeighborReportDesc); 89 } 90 csr_ll_unlock(pList); 91 } 92 93 /** 94 * rrm_indicate_neighbor_report_result() -calls the callback registered for 95 * neighbor report 96 * @pMac: Pointer to the Hal Handle. 97 * @qdf_status - QDF_STATUS_SUCCESS/QDF_STATUS_FAILURE based on whether a valid 98 * report is received or neighbor timer expired 99 * 100 * This function calls the callback register by the caller while requesting for 101 * neighbor report. This function gets invoked if a neighbor report is received 102 * from an AP or neighbor response wait timer expires. 103 * 104 * Return: void 105 */ 106 static void rrm_indicate_neighbor_report_result(tpAniSirGlobal pMac, 107 QDF_STATUS qdf_status) 108 { 109 NeighborReportRspCallback callback; 110 void *callbackContext; 111 112 /* Reset the neighbor response pending status */ 113 pMac->rrm.rrmSmeContext.neighborReqControlInfo.isNeighborRspPending = 114 false; 115 116 /* Stop the timer if it is already running. 117 * The timer should be running only in the SUCCESS case. 118 */ 119 if (QDF_TIMER_STATE_RUNNING == 120 qdf_mc_timer_get_current_state(&pMac->rrm.rrmSmeContext. 121 neighborReqControlInfo. 122 neighborRspWaitTimer)) { 123 sme_debug("No entry in neighbor report cache"); 124 qdf_mc_timer_stop(&pMac->rrm.rrmSmeContext. 125 neighborReqControlInfo.neighborRspWaitTimer); 126 } 127 callback = 128 pMac->rrm.rrmSmeContext.neighborReqControlInfo. 129 neighborRspCallbackInfo.neighborRspCallback; 130 callbackContext = 131 pMac->rrm.rrmSmeContext.neighborReqControlInfo. 132 neighborRspCallbackInfo.neighborRspCallbackContext; 133 134 /* Reset the callback and the callback context before calling the 135 * callback. It is very likely that there may be a registration in 136 * callback itself. 137 */ 138 pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo. 139 neighborRspCallback = NULL; 140 pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo. 141 neighborRspCallbackContext = NULL; 142 143 /* Call the callback with the status received from caller */ 144 if (callback) 145 callback(callbackContext, qdf_status); 146 147 148 } 149 150 /** 151 * sme_RrmBeaconReportXmitInd () - Send beacon report 152 * @mac_ctx Pointer to mac context 153 * @result_arr scan results 154 * @msrmnt_status flag to indicate that the measurement is done. 155 * @bss_count bss count 156 * 157 * Create and send the beacon report Xmit ind message to PE. 158 * 159 * Return: status 160 */ 161 162 static QDF_STATUS 163 sme_rrm_send_beacon_report_xmit_ind(tpAniSirGlobal mac_ctx, 164 tCsrScanResultInfo **result_arr, uint8_t msrmnt_status, 165 uint8_t bss_count) 166 { 167 tpSirBssDescription bss_desc = NULL; 168 tpSirBeaconReportXmitInd beacon_rep; 169 uint16_t length; 170 uint32_t size; 171 uint8_t i = 0, j = 0, counter = 0; 172 tCsrScanResultInfo *cur_result = NULL; 173 QDF_STATUS status = QDF_STATUS_E_FAILURE; 174 tpRrmSMEContext rrm_ctx = &mac_ctx->rrm.rrmSmeContext; 175 tpSirBssDescription bss_desc_to_free[SIR_BCN_REPORT_MAX_BSS_DESC] = {0}; 176 177 if (NULL == result_arr && !msrmnt_status) { 178 sme_err("Beacon report xmit Ind to PE Failed"); 179 return QDF_STATUS_E_FAILURE; 180 } 181 182 if (result_arr) 183 cur_result = result_arr[j]; 184 185 do { 186 length = sizeof(tSirBeaconReportXmitInd); 187 beacon_rep = qdf_mem_malloc(length); 188 if (NULL == beacon_rep) { 189 sme_err("Unable to allocate memory for beacon report"); 190 return QDF_STATUS_E_NOMEM; 191 } 192 beacon_rep->messageType = eWNI_SME_BEACON_REPORT_RESP_XMIT_IND; 193 beacon_rep->length = length; 194 beacon_rep->uDialogToken = rrm_ctx->token; 195 beacon_rep->duration = rrm_ctx->duration[0]; 196 beacon_rep->regClass = rrm_ctx->regClass; 197 qdf_mem_copy(beacon_rep->bssId, rrm_ctx->sessionBssId.bytes, 198 QDF_MAC_ADDR_SIZE); 199 200 i = 0; 201 while (cur_result) { 202 bss_desc = &cur_result->BssDescriptor; 203 if (bss_desc == NULL) 204 break; 205 size = bss_desc->length + sizeof(bss_desc->length); 206 beacon_rep->pBssDescription[i] = qdf_mem_malloc(size); 207 if (NULL == 208 beacon_rep->pBssDescription[i]) 209 break; 210 qdf_mem_copy(beacon_rep->pBssDescription[i], 211 bss_desc, size); 212 bss_desc_to_free[i] = 213 beacon_rep->pBssDescription[i]; 214 sme_debug("RRM Result Bssid = " MAC_ADDRESS_STR 215 " chan= %d, rssi = -%d", 216 MAC_ADDR_ARRAY( 217 beacon_rep->pBssDescription[i]->bssId), 218 beacon_rep->pBssDescription[i]->channelId, 219 beacon_rep->pBssDescription[i]->rssi * (-1)); 220 beacon_rep->numBssDesc++; 221 if (++i >= SIR_BCN_REPORT_MAX_BSS_DESC) 222 break; 223 cur_result = 224 result_arr[j + i]; 225 } 226 227 j += i; 228 if (!result_arr || (cur_result == NULL) 229 || (j >= bss_count)) { 230 cur_result = NULL; 231 sme_debug("Reached to max/last BSS in cur_result list"); 232 } else { 233 cur_result = result_arr[j]; 234 sme_debug("Move to the next BSS set in cur_result list"); 235 } 236 beacon_rep->fMeasureDone = 237 (cur_result) ? false : msrmnt_status; 238 sme_debug("SME Sending BcnRepXmit to PE numBss %d i %d j %d", 239 beacon_rep->numBssDesc, i, j); 240 status = umac_send_mb_message_to_mac(beacon_rep); 241 if (status != QDF_STATUS_SUCCESS) 242 for (counter = 0; counter < i; ++counter) 243 qdf_mem_free(bss_desc_to_free[counter]); 244 } while (cur_result); 245 246 return status; 247 } 248 249 #ifdef FEATURE_WLAN_ESE 250 /** 251 * sme_ese_send_beacon_req_scan_results () - Send beacon report 252 * @mac_ctx Pointer to mac context 253 * @session_id - session id 254 * @result_arr scan results 255 * @msrmnt_status flag to indicate that the measurement is done. 256 * @bss_count number of bss found 257 * 258 * This function sends up the scan results received as a part of 259 * beacon request scanning. 260 * This function is called after receiving the scan results per channel 261 * Due to the limitation on the size of the IWEVCUSTOM buffer, we send 262 * 3 BSSIDs of beacon report information in one custom event; 263 * 264 * Return: status 265 */ 266 static QDF_STATUS sme_ese_send_beacon_req_scan_results( 267 tpAniSirGlobal mac_ctx, uint32_t session_id, 268 uint8_t channel, tCsrScanResultInfo **result_arr, 269 uint8_t msrmnt_status, uint8_t bss_count) 270 { 271 QDF_STATUS status = QDF_STATUS_E_FAILURE; 272 QDF_STATUS fill_ie_status; 273 tpSirBssDescription bss_desc = NULL; 274 uint32_t ie_len = 0; 275 uint32_t out_ie_len = 0; 276 uint8_t bss_counter = 0; 277 tCsrScanResultInfo *cur_result = NULL; 278 tpRrmSMEContext rrm_ctx = &mac_ctx->rrm.rrmSmeContext; 279 struct csr_roam_info roam_info; 280 tSirEseBcnReportRsp bcn_rpt_rsp; 281 tpSirEseBcnReportRsp bcn_report = &bcn_rpt_rsp; 282 tpCsrEseBeaconReqParams cur_meas_req = NULL; 283 uint8_t i = 0, j = 0; 284 tBcnReportFields *bcn_rpt_fields; 285 286 if (NULL == rrm_ctx) { 287 sme_err("rrm_ctx is NULL"); 288 return QDF_STATUS_E_FAILURE; 289 } 290 291 if (NULL == result_arr && !msrmnt_status) { 292 sme_err("Beacon report xmit Ind to HDD Failed"); 293 return QDF_STATUS_E_FAILURE; 294 } 295 296 if (result_arr) 297 cur_result = result_arr[bss_counter]; 298 299 qdf_mem_zero(&bcn_rpt_rsp, sizeof(tSirEseBcnReportRsp)); 300 do { 301 cur_meas_req = NULL; 302 for (i = 0; i < rrm_ctx->eseBcnReqInfo.numBcnReqIe; i++) { 303 if (rrm_ctx->eseBcnReqInfo.bcnReq[i].channel == 304 channel) { 305 cur_meas_req = 306 &rrm_ctx->eseBcnReqInfo.bcnReq[i]; 307 break; 308 } 309 } 310 if (NULL != cur_meas_req) 311 bcn_report->measurementToken = 312 cur_meas_req->measurementToken; 313 sme_debug("Channel: %d MeasToken: %d", channel, 314 bcn_report->measurementToken); 315 316 j = 0; 317 while (cur_result) { 318 bss_desc = &cur_result->BssDescriptor; 319 if (NULL == bss_desc) { 320 cur_result = NULL; 321 break; 322 } 323 ie_len = GET_IE_LEN_IN_BSS(bss_desc->length); 324 bcn_rpt_fields = 325 &bcn_report->bcnRepBssInfo[j].bcnReportFields; 326 bcn_rpt_fields->ChanNum = 327 bss_desc->channelId; 328 bcn_report->bcnRepBssInfo[j].bcnReportFields.Spare = 0; 329 if (NULL != cur_meas_req) 330 bcn_rpt_fields->MeasDuration = 331 cur_meas_req->measurementDuration; 332 bcn_rpt_fields->PhyType = bss_desc->nwType; 333 bcn_rpt_fields->RecvSigPower = bss_desc->rssi; 334 bcn_rpt_fields->ParentTsf = bss_desc->parentTSF; 335 bcn_rpt_fields->TargetTsf[0] = bss_desc->timeStamp[0]; 336 bcn_rpt_fields->TargetTsf[1] = bss_desc->timeStamp[1]; 337 bcn_rpt_fields->BcnInterval = bss_desc->beaconInterval; 338 bcn_rpt_fields->CapabilityInfo = 339 bss_desc->capabilityInfo; 340 341 qdf_mem_copy(bcn_rpt_fields->Bssid, 342 bss_desc->bssId, sizeof(tSirMacAddr)); 343 fill_ie_status = 344 sir_beacon_ie_ese_bcn_report(mac_ctx, 345 (uint8_t *) bss_desc->ieFields, 346 ie_len, 347 &(bcn_report->bcnRepBssInfo[j]. 348 pBuf), 349 &out_ie_len); 350 if (QDF_STATUS_E_FAILURE == fill_ie_status) 351 continue; 352 bcn_report->bcnRepBssInfo[j].ieLen = out_ie_len; 353 354 sme_debug("Bssid"MAC_ADDRESS_STR" Channel: %d Rssi: %d", 355 MAC_ADDR_ARRAY(bss_desc->bssId), 356 bss_desc->channelId, (-1) * bss_desc->rssi); 357 bcn_report->numBss++; 358 if (++j >= SIR_BCN_REPORT_MAX_BSS_DESC) 359 break; 360 cur_result = result_arr[j]; 361 } 362 363 bss_counter += j; 364 if (!result_arr || !cur_result 365 || (bss_counter >= SIR_BCN_REPORT_MAX_BSS_DESC)) { 366 cur_result = NULL; 367 sme_err("Reached to the max/last BSS in cur_result list"); 368 } else { 369 cur_result = result_arr[bss_counter]; 370 sme_err("Move to the next BSS set in cur_result list"); 371 } 372 373 bcn_report->flag = 374 (msrmnt_status << 1) | ((cur_result) ? true : false); 375 376 sme_debug("SME Sending BcnRep to HDD numBss: %d j: %d bss_counter: %d flag: %d", 377 bcn_report->numBss, j, bss_counter, 378 bcn_report->flag); 379 380 roam_info.pEseBcnReportRsp = bcn_report; 381 status = csr_roam_call_callback(mac_ctx, session_id, &roam_info, 382 0, eCSR_ROAM_ESE_BCN_REPORT_IND, 0); 383 384 /* Free the memory allocated to IE */ 385 for (i = 0; i < j; i++) 386 if (bcn_report->bcnRepBssInfo[i].pBuf) 387 qdf_mem_free(bcn_report->bcnRepBssInfo[i].pBuf); 388 } while (cur_result); 389 return status; 390 } 391 392 #endif /* FEATURE_WLAN_ESE */ 393 394 /** 395 * sme_rrm_send_scan_result() - to get scan result and send the beacon report 396 * @mac_ctx: pointer to mac context 397 * @num_chan: number of channels 398 * @chan_list: list of channels to fetch the result from 399 * @measurementdone: Flag to indicate measurement done or no 400 * 401 * This function is called to get the scan result from CSR and send the beacon 402 * report xmit ind message to PE 403 * 404 * Return: QDF_STATUS 405 */ 406 static QDF_STATUS sme_rrm_send_scan_result(tpAniSirGlobal mac_ctx, 407 uint8_t num_chan, 408 uint8_t *chan_list, 409 uint8_t measurementdone) 410 { 411 mac_handle_t mac_handle = MAC_HANDLE(mac_ctx); 412 tCsrScanResultFilter filter; 413 tScanResultHandle result_handle; 414 tCsrScanResultInfo *scan_results, *next_result; 415 tCsrScanResultInfo *scanresults_arr[SIR_BCN_REPORT_MAX_BSS_DESC]; 416 QDF_STATUS status; 417 uint8_t counter = 0; 418 tpRrmSMEContext rrm_ctx = &mac_ctx->rrm.rrmSmeContext; 419 uint32_t session_id; 420 struct csr_roam_info *roam_info; 421 tSirScanType scan_type; 422 struct csr_roam_session *session; 423 424 qdf_mem_zero(&filter, sizeof(filter)); 425 qdf_mem_zero(scanresults_arr, 426 sizeof(next_result) * SIR_BCN_REPORT_MAX_BSS_DESC); 427 filter.BSSIDs.numOfBSSIDs = 1; 428 filter.BSSIDs.bssid = (struct qdf_mac_addr *)&rrm_ctx->bssId; 429 430 if (rrm_ctx->ssId.length) { 431 filter.SSIDs.SSIDList = 432 (tCsrSSIDInfo *) qdf_mem_malloc(sizeof(tCsrSSIDInfo)); 433 if (filter.SSIDs.SSIDList == NULL) { 434 sme_err("qdf_mem_malloc failed"); 435 return QDF_STATUS_E_NOMEM; 436 } 437 438 filter.SSIDs.SSIDList->SSID.length = 439 rrm_ctx->ssId.length; 440 qdf_mem_copy(filter.SSIDs.SSIDList->SSID.ssId, 441 rrm_ctx->ssId.ssId, rrm_ctx->ssId.length); 442 filter.SSIDs.numOfSSIDs = 1; 443 } else { 444 filter.SSIDs.numOfSSIDs = 0; 445 } 446 447 filter.ChannelInfo.numOfChannels = num_chan; 448 filter.ChannelInfo.ChannelList = chan_list; 449 filter.fMeasurement = true; 450 451 /* 452 * In case this is beacon report request from last AP (before roaming) 453 * following call to csr_roam_get_session_id_from_bssid will fail, 454 * hence use current session ID instead of one stored in SME rrm context 455 */ 456 if (QDF_STATUS_E_FAILURE == csr_roam_get_session_id_from_bssid(mac_ctx, 457 &rrm_ctx->sessionBssId, &session_id)) { 458 sme_debug("BSSID mismatch, using current session_id"); 459 session_id = mac_ctx->roam.roamSession->sessionId; 460 } 461 status = sme_scan_get_result(mac_handle, (uint8_t)session_id, 462 &filter, &result_handle); 463 464 if (filter.SSIDs.SSIDList) 465 qdf_mem_free(filter.SSIDs.SSIDList); 466 467 sme_debug("RRM Measurement Done %d", measurementdone); 468 if (NULL == result_handle) { 469 /* 470 * no scan results 471 * Spec. doesn't say anything about such condition 472 * Since section 7.4.6.2 (IEEE802.11k-2008) says-rrm report 473 * frame should contain one or more report IEs. It probably 474 * means dont send any respose if no matching BSS found. 475 * Moreover, there is no flag or field in measurement report 476 * IE(7.3.2.22) OR beacon report IE(7.3.2.22.6) that can be set 477 * to indicate no BSS found on a given channel. If we finished 478 * measurement on all the channels, we still need to send a 479 * xmit indication with moreToFollow set to MEASURMENT_DONE so 480 * that PE can clean any context allocated. 481 */ 482 if (!measurementdone) 483 return status; 484 #ifdef FEATURE_WLAN_ESE 485 if (eRRM_MSG_SOURCE_ESE_UPLOAD == rrm_ctx->msgSource) 486 status = sme_ese_send_beacon_req_scan_results(mac_ctx, 487 session_id, chan_list[0], 488 NULL, measurementdone, 0); 489 else 490 #endif /* FEATURE_WLAN_ESE */ 491 status = sme_rrm_send_beacon_report_xmit_ind(mac_ctx, 492 NULL, measurementdone, 0); 493 return status; 494 } 495 scan_results = sme_scan_result_get_first(mac_handle, result_handle); 496 if (NULL == scan_results && measurementdone) { 497 #ifdef FEATURE_WLAN_ESE 498 if (eRRM_MSG_SOURCE_ESE_UPLOAD == rrm_ctx->msgSource) { 499 status = sme_ese_send_beacon_req_scan_results(mac_ctx, 500 session_id, 501 chan_list[0], 502 NULL, 503 measurementdone, 504 0); 505 } else 506 #endif /* FEATURE_WLAN_ESE */ 507 status = sme_rrm_send_beacon_report_xmit_ind(mac_ctx, 508 NULL, measurementdone, 0); 509 } 510 counter = 0; 511 512 roam_info = qdf_mem_malloc(sizeof(*roam_info)); 513 if (NULL == roam_info) { 514 sme_err("malloc failed"); 515 status = QDF_STATUS_E_NOMEM; 516 goto rrm_send_scan_results_done; 517 } 518 519 session = CSR_GET_SESSION(mac_ctx, session_id); 520 if ((!session) || (!csr_is_conn_state_connected_infra( 521 mac_ctx, session_id)) || 522 (NULL == session->pConnectBssDesc)) { 523 sme_err("Invaild session"); 524 status = QDF_STATUS_E_FAILURE; 525 goto rrm_send_scan_results_done; 526 } 527 528 if (eRRM_MSG_SOURCE_ESE_UPLOAD == rrm_ctx->msgSource || 529 eRRM_MSG_SOURCE_LEGACY_ESE == rrm_ctx->msgSource) 530 scan_type = rrm_ctx->measMode[rrm_ctx->currentIndex]; 531 else 532 scan_type = rrm_ctx->measMode[0]; 533 534 while (scan_results) { 535 /* 536 * In passive scan, sta listens beacon. Connected AP beacon 537 * is offloaded to firmware. Firmware will discard 538 * connected AP beacon except that special IE exists. 539 * Connected AP beacon will not be sent to host. Hence, timer 540 * of connected AP in scan results is not updated and can 541 * not meet "pScanResult->timer >= RRM_scan_timer". 542 */ 543 uint8_t is_conn_bss_found = false; 544 545 if ((scan_type == eSIR_PASSIVE_SCAN) && 546 (!qdf_mem_cmp(scan_results->BssDescriptor.bssId, 547 session->pConnectBssDesc->bssId, 548 sizeof(struct qdf_mac_addr)))) { 549 is_conn_bss_found = true; 550 sme_debug("Connected BSS in scan results"); 551 } 552 next_result = sme_scan_result_get_next(mac_handle, 553 result_handle); 554 sme_debug("Scan res timer:%lu, rrm scan timer:%llu", 555 scan_results->timer, rrm_scan_timer); 556 if ((scan_results->timer >= rrm_scan_timer) || 557 (is_conn_bss_found == true)) { 558 roam_info->pBssDesc = &scan_results->BssDescriptor; 559 csr_roam_call_callback(mac_ctx, session_id, roam_info, 560 0, eCSR_ROAM_UPDATE_SCAN_RESULT, 561 eCSR_ROAM_RESULT_NONE); 562 scanresults_arr[counter++] = scan_results; 563 } 564 scan_results = next_result; 565 if (counter >= SIR_BCN_REPORT_MAX_BSS_DESC) 566 break; 567 } 568 qdf_mem_free(roam_info); 569 /* 570 * The beacon report should be sent whether the counter is zero or 571 * non-zero. There might be a few scan results in the cache but not 572 * actually are a result of this scan. During that scenario, the 573 * counter will be zero. The report should be sent and LIM will further 574 * cleanup the RRM to accept the further incoming requests 575 * In case the counter is Zero, the pScanResultsArr will be NULL. 576 * The next level routine does a check for the measurementDone to 577 * determine whether to send a report or not. 578 */ 579 sme_debug("Number of BSS Desc with RRM Scan %d", counter); 580 if (counter || measurementdone) { 581 #ifdef FEATURE_WLAN_ESE 582 if (eRRM_MSG_SOURCE_ESE_UPLOAD == rrm_ctx->msgSource) 583 status = sme_ese_send_beacon_req_scan_results(mac_ctx, 584 session_id, chan_list[0], 585 scanresults_arr, measurementdone, 586 counter); 587 else 588 #endif /* FEATURE_WLAN_ESE */ 589 status = sme_rrm_send_beacon_report_xmit_ind(mac_ctx, 590 scanresults_arr, measurementdone, 591 counter); 592 } 593 594 rrm_send_scan_results_done: 595 sme_scan_result_purge(result_handle); 596 return status; 597 } 598 599 600 /** 601 * sme_rrm_scan_request_callback() -Sends the beacon report xmit to PE 602 * @halHandle: Pointer to the Hal Handle. 603 * @sessionId: session id 604 * @scanId: Scan ID. 605 * @status: CSR Status. 606 * 607 * The sme module calls this callback function once it finish the scan request 608 * and this function send the beacon report xmit to PE and starts a timer of 609 * random interval to issue next request. 610 * 611 * Return : 0 for success, non zero for failure 612 */ 613 static QDF_STATUS sme_rrm_scan_request_callback(tHalHandle halHandle, 614 uint8_t sessionId, 615 uint32_t scanId, 616 eCsrScanStatus status) 617 { 618 uint16_t interval; 619 tpAniSirGlobal pMac = (tpAniSirGlobal) halHandle; 620 tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; 621 uint32_t time_tick; 622 623 /* if any more channels are pending, start a timer of a random value 624 * within randomization interval. 625 */ 626 if ((pSmeRrmContext->currentIndex + 1) < 627 pSmeRrmContext->channelList.numOfChannels) { 628 sme_rrm_send_scan_result(pMac, 1, 629 &pSmeRrmContext->channelList. 630 ChannelList[pSmeRrmContext 631 ->currentIndex], 632 false); 633 /* Advance the current index. */ 634 pSmeRrmContext->currentIndex++; 635 /* start the timer to issue next request. */ 636 /* From timer tick get a random number within 10ms and max 637 * randmization interval. 638 */ 639 time_tick = qdf_mc_timer_get_system_ticks(); 640 interval = 641 time_tick % (pSmeRrmContext->randnIntvl - 10 + 1) + 10; 642 643 sme_debug("Set timer for interval %d ", interval); 644 qdf_mc_timer_start(&pSmeRrmContext->IterMeasTimer, interval); 645 646 } else { 647 /* Done with the measurement. Clean up all context and send a 648 * message to PE with measurement done flag set. 649 */ 650 sme_rrm_send_scan_result(pMac, 1, 651 &pSmeRrmContext->channelList. 652 ChannelList[pSmeRrmContext 653 ->currentIndex], 654 true); 655 qdf_mem_free(pSmeRrmContext->channelList.ChannelList); 656 #ifdef FEATURE_WLAN_ESE 657 pSmeRrmContext->eseBcnReqInProgress = false; 658 #endif 659 } 660 661 return QDF_STATUS_SUCCESS; 662 } 663 664 static void sme_rrm_scan_event_callback(struct wlan_objmgr_vdev *vdev, 665 struct scan_event *event, void *arg) 666 { 667 uint32_t scan_id; 668 uint8_t session_id; 669 eCsrScanStatus scan_status = eCSR_SCAN_FAILURE; 670 tHalHandle hal_handle; 671 bool success = false; 672 session_id = wlan_vdev_get_id(vdev); 673 scan_id = event->scan_id; 674 hal_handle = cds_get_context(QDF_MODULE_ID_SME); 675 if (!hal_handle) { 676 QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_FATAL, 677 FL("invalid h_hal")); 678 return; 679 } 680 681 qdf_mtrace(QDF_MODULE_ID_SCAN, QDF_MODULE_ID_SME, event->type, 682 event->vdev_id, event->scan_id); 683 684 if (!util_is_scan_completed(event, &success)) 685 return; 686 687 if (success) 688 scan_status = eCSR_SCAN_SUCCESS; 689 690 sme_rrm_scan_request_callback(hal_handle, session_id, 691 scan_id, scan_status); 692 } 693 694 695 /** 696 * sme_rrm_issue_scan_req() - To issue rrm scan request 697 * @mac_ctx: pointer to mac context 698 * 699 * This routine is called to issue rrm scan request 700 * 701 * Return: QDF_STATUS 702 */ 703 static QDF_STATUS sme_rrm_issue_scan_req(tpAniSirGlobal mac_ctx) 704 { 705 QDF_STATUS status = QDF_STATUS_SUCCESS; 706 tpRrmSMEContext sme_rrm_ctx = &mac_ctx->rrm.rrmSmeContext; 707 uint32_t session_id; 708 tSirScanType scan_type; 709 710 status = csr_roam_get_session_id_from_bssid(mac_ctx, 711 &sme_rrm_ctx->sessionBssId, &session_id); 712 if (status != QDF_STATUS_SUCCESS) { 713 sme_err("sme session ID not found for bssid= "MAC_ADDRESS_STR, 714 MAC_ADDR_ARRAY(sme_rrm_ctx->sessionBssId.bytes)); 715 status = QDF_STATUS_E_FAILURE; 716 goto free_ch_lst; 717 } 718 719 if ((sme_rrm_ctx->currentIndex) >= 720 sme_rrm_ctx->channelList.numOfChannels) { 721 sme_rrm_send_beacon_report_xmit_ind(mac_ctx, NULL, true, 0); 722 sme_debug("done with the complete ch lt. finish and fee now"); 723 goto free_ch_lst; 724 } 725 726 if (eRRM_MSG_SOURCE_ESE_UPLOAD == sme_rrm_ctx->msgSource || 727 eRRM_MSG_SOURCE_LEGACY_ESE == sme_rrm_ctx->msgSource) 728 scan_type = sme_rrm_ctx->measMode[sme_rrm_ctx->currentIndex]; 729 else 730 scan_type = sme_rrm_ctx->measMode[0]; 731 732 if ((eSIR_ACTIVE_SCAN == scan_type) || 733 (eSIR_PASSIVE_SCAN == scan_type)) { 734 uint32_t max_chan_time; 735 uint64_t current_time; 736 struct scan_start_request *req; 737 struct wlan_objmgr_vdev *vdev; 738 uint32_t chan_num; 739 740 req = qdf_mem_malloc(sizeof(*req)); 741 if (!req) { 742 sme_debug("Failed to allocate memory"); 743 return QDF_STATUS_E_NOMEM; 744 } 745 vdev = wlan_objmgr_get_vdev_by_id_from_psoc( 746 mac_ctx->psoc, 747 session_id, 748 WLAN_LEGACY_SME_ID); 749 if (!vdev) { 750 sme_err("VDEV is null %d", session_id); 751 return QDF_STATUS_E_INVAL; 752 } 753 ucfg_scan_init_default_params(vdev, req); 754 req->scan_req.dwell_time_active = 0; 755 req->scan_req.scan_id = ucfg_scan_get_scan_id(mac_ctx->psoc); 756 req->scan_req.scan_f_passive = 757 (scan_type == eSIR_ACTIVE_SCAN) ? false : true; 758 req->scan_req.vdev_id = wlan_vdev_get_id(vdev); 759 req->scan_req.scan_req_id = sme_rrm_ctx->req_id; 760 qdf_mem_copy(&req->scan_req.bssid_list[0], sme_rrm_ctx->bssId, 761 QDF_MAC_ADDR_SIZE); 762 req->scan_req.num_bssid = 1; 763 if (sme_rrm_ctx->ssId.length) { 764 req->scan_req.num_ssids = 1; 765 qdf_mem_copy(&req->scan_req.ssid[0].ssid, 766 sme_rrm_ctx->ssId.ssId, 767 sme_rrm_ctx->ssId.length); 768 req->scan_req.ssid[0].length = sme_rrm_ctx->ssId.length; 769 } 770 771 /* 772 * set min and max channel time 773 * sme_rrm_ctx->duration; Dont use min timeout. 774 */ 775 if (eRRM_MSG_SOURCE_ESE_UPLOAD == sme_rrm_ctx->msgSource || 776 eRRM_MSG_SOURCE_LEGACY_ESE == sme_rrm_ctx->msgSource) 777 req->scan_req.dwell_time_active = sme_rrm_ctx->duration[ 778 sme_rrm_ctx->currentIndex]; 779 else 780 req->scan_req.dwell_time_active = 781 sme_rrm_ctx->duration[0]; 782 783 sme_debug("Scan Type(%d) Max Dwell Time(%d)", 784 scan_type, 785 req->scan_req.dwell_time_active); 786 /* 787 * Use gPassive/gActiveMaxChannelTime if maxChanTime is less 788 * than default. 789 */ 790 if (eSIR_ACTIVE_SCAN == scan_type) 791 max_chan_time = 792 mac_ctx->roam.configParam.nActiveMaxChnTime; 793 else 794 max_chan_time = 795 mac_ctx->roam.configParam.nPassiveMaxChnTime; 796 797 if (req->scan_req.dwell_time_active < max_chan_time) { 798 req->scan_req.dwell_time_active = max_chan_time; 799 sme_debug("Setting default max %d ChanTime", 800 max_chan_time); 801 } 802 803 req->scan_req.adaptive_dwell_time_mode = SCAN_DWELL_MODE_STATIC; 804 /* 805 * For RRM scans timing is very important especially when the 806 * request is for limited channels. There is no need for 807 * firmware to rest for about 100-200 ms on the home channel. 808 * Instead, it can start the scan right away which will make the 809 * host to respond with the beacon report as quickly as 810 * possible. Ensure that the scan requests are not back to back 811 * and hence there is a check to see if the requests are atleast 812 * 1 second apart. 813 */ 814 current_time = (uint64_t)qdf_mc_timer_get_system_time(); 815 sme_debug("prev scan triggered before %llu ms, totalchannels %d", 816 current_time - rrm_scan_timer, 817 sme_rrm_ctx->channelList.numOfChannels); 818 if ((abs(current_time - rrm_scan_timer) > 1000) && 819 (sme_rrm_ctx->channelList.numOfChannels == 1)) { 820 req->scan_req.max_rest_time = 1; 821 req->scan_req.min_rest_time = 1; 822 req->scan_req.idle_time = 1; 823 } 824 825 rrm_scan_timer = (uint64_t)qdf_mc_timer_get_system_time(); 826 827 /* set requestType to full scan */ 828 req->scan_req.chan_list.num_chan = 1; 829 chan_num = sme_rrm_ctx->channelList.ChannelList[ 830 sme_rrm_ctx->currentIndex]; 831 req->scan_req.chan_list.chan[0].freq = 832 wlan_chan_to_freq(chan_num); 833 sme_debug("Duration %d On channel %d freq %d", 834 req->scan_req.dwell_time_active, 835 chan_num, 836 req->scan_req.chan_list.chan[0].freq); 837 status = ucfg_scan_start(req); 838 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID); 839 840 return status; 841 } else if (eSIR_BEACON_TABLE == scan_type) { 842 /* 843 * In beacon table mode, scan results are taken directly from 844 * scan cache without issuing any scan request. So, it is not 845 * proper to update rrm_scan_timer with latest time and hence 846 * made it to zero to satisfy 847 * pScanResult->timer >= rrm_scan_timer 848 */ 849 rrm_scan_timer = 0; 850 if ((sme_rrm_ctx->currentIndex + 1) < 851 sme_rrm_ctx->channelList.numOfChannels) { 852 sme_rrm_send_scan_result(mac_ctx, 1, 853 &sme_rrm_ctx->channelList.ChannelList[ 854 sme_rrm_ctx->currentIndex], false); 855 /* Advance the current index. */ 856 sme_rrm_ctx->currentIndex++; 857 sme_rrm_issue_scan_req(mac_ctx); 858 #ifdef FEATURE_WLAN_ESE 859 sme_rrm_ctx->eseBcnReqInProgress = false; 860 #endif 861 return status; 862 } else { 863 /* 864 * Done with the measurement. Clean up all context and 865 * send a message to PE with measurement done flag set. 866 */ 867 sme_rrm_send_scan_result(mac_ctx, 1, 868 &sme_rrm_ctx->channelList.ChannelList[ 869 sme_rrm_ctx->currentIndex], true); 870 goto free_ch_lst; 871 } 872 } else { 873 sme_err("Unknown beacon report req mode(%d)", scan_type); 874 /* 875 * Indicate measurement completion to PE 876 * If this is not done, pCurrentReq pointer will not be freed 877 * and PE will not handle subsequent Beacon requests 878 */ 879 sme_rrm_send_beacon_report_xmit_ind(mac_ctx, NULL, true, 0); 880 goto free_ch_lst; 881 } 882 883 free_ch_lst: 884 qdf_mem_free(sme_rrm_ctx->channelList.ChannelList); 885 sme_rrm_ctx->channelList.ChannelList = NULL; 886 return status; 887 } 888 889 /** 890 * sme_rrm_process_beacon_report_req_ind() -Process beacon report request 891 * @pMac:- Global Mac structure 892 * @pMsgBuf:- a pointer to a buffer that maps to various structures base 893 * on the message type.The beginning of the buffer can always 894 * map to tSirSmeRsp. 895 * 896 * This is called to process the Beacon 897 * report request from peer AP forwarded through PE . 898 * 899 * Return : QDF_STATUS_SUCCESS - Validation is successful. 900 */ 901 QDF_STATUS sme_rrm_process_beacon_report_req_ind(tpAniSirGlobal pMac, 902 void *pMsgBuf) 903 { 904 tpSirBeaconReportReqInd pBeaconReq = (tpSirBeaconReportReqInd) pMsgBuf; 905 tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; 906 uint32_t len = 0, i = 0; 907 908 sme_debug("Received Beacon report request ind Channel = %d", 909 pBeaconReq->channelInfo.channelNum); 910 /* section 11.10.8.1 (IEEE Std 802.11k-2008) */ 911 /* channel 0 and 255 has special meaning. */ 912 if ((pBeaconReq->channelInfo.channelNum == 0) || 913 ((pBeaconReq->channelInfo.channelNum == 255) 914 && (pBeaconReq->channelList.numChannels == 0))) { 915 /* Add all the channel in the regulatory domain. */ 916 wlan_cfg_get_str_len(pMac, WNI_CFG_VALID_CHANNEL_LIST, &len); 917 pSmeRrmContext->channelList.ChannelList = qdf_mem_malloc(len); 918 if (pSmeRrmContext->channelList.ChannelList == NULL) { 919 sme_err("qdf_mem_malloc failed"); 920 return QDF_STATUS_E_NOMEM; 921 } 922 csr_get_cfg_valid_channels(pMac, pSmeRrmContext->channelList. 923 ChannelList, &len); 924 pSmeRrmContext->channelList.numOfChannels = (uint8_t) len; 925 } else { 926 len = 0; 927 pSmeRrmContext->channelList.numOfChannels = 0; 928 929 /* If valid channel is present. We first Measure on the given 930 * channel and if there are additional channels present in 931 * APchannelreport, measure on these also. 932 */ 933 if (pBeaconReq->channelInfo.channelNum != 255) 934 len = 1; 935 936 len += pBeaconReq->channelList.numChannels; 937 938 pSmeRrmContext->channelList.ChannelList = qdf_mem_malloc(len); 939 if (pSmeRrmContext->channelList.ChannelList == NULL) { 940 sme_err("qdf_mem_malloc failed"); 941 return QDF_STATUS_E_NOMEM; 942 } 943 944 if (pBeaconReq->channelInfo.channelNum != 255) { 945 if (csr_roam_is_channel_valid 946 (pMac, pBeaconReq->channelInfo.channelNum)) 947 pSmeRrmContext->channelList. 948 ChannelList[pSmeRrmContext->channelList. 949 numOfChannels++] = 950 pBeaconReq->channelInfo.channelNum; 951 else 952 sme_err("Invalid channel: %d", 953 pBeaconReq->channelInfo.channelNum); 954 } 955 956 for (i = 0; i < pBeaconReq->channelList.numChannels; i++) { 957 if (csr_roam_is_channel_valid(pMac, pBeaconReq-> 958 channelList.channelNumber[i])) { 959 pSmeRrmContext->channelList. 960 ChannelList[pSmeRrmContext->channelList. 961 numOfChannels] = pBeaconReq->channelList. 962 channelNumber[i]; 963 pSmeRrmContext->channelList.numOfChannels++; 964 } 965 } 966 } 967 968 /* Copy session bssid */ 969 qdf_mem_copy(pSmeRrmContext->sessionBssId.bytes, pBeaconReq->bssId, 970 sizeof(tSirMacAddr)); 971 972 /* copy measurement bssid */ 973 qdf_mem_copy(pSmeRrmContext->bssId, pBeaconReq->macaddrBssid, 974 sizeof(tSirMacAddr)); 975 976 /* Copy ssid */ 977 qdf_mem_copy(&pSmeRrmContext->ssId, &pBeaconReq->ssId, 978 sizeof(tAniSSID)); 979 980 pSmeRrmContext->token = pBeaconReq->uDialogToken; 981 pSmeRrmContext->regClass = pBeaconReq->channelInfo.regulatoryClass; 982 pSmeRrmContext->randnIntvl = 983 QDF_MAX(pBeaconReq->randomizationInterval, 984 pSmeRrmContext->rrmConfig.max_randn_interval); 985 pSmeRrmContext->currentIndex = 0; 986 pSmeRrmContext->msgSource = pBeaconReq->msgSource; 987 qdf_mem_copy((uint8_t *) &pSmeRrmContext->measMode, 988 (uint8_t *) &pBeaconReq->fMeasurementtype, 989 SIR_ESE_MAX_MEAS_IE_REQS); 990 qdf_mem_copy((uint8_t *) &pSmeRrmContext->duration, 991 (uint8_t *) &pBeaconReq->measurementDuration, 992 SIR_ESE_MAX_MEAS_IE_REQS); 993 994 sme_debug("token: %d regClass: %d randnIntvl: %d msgSource: %d", 995 pSmeRrmContext->token, pSmeRrmContext->regClass, 996 pSmeRrmContext->randnIntvl, pSmeRrmContext->msgSource); 997 998 return sme_rrm_issue_scan_req(pMac); 999 } 1000 1001 /** 1002 * sme_rrm_neighbor_report_request() - This is API can be used to trigger a 1003 * Neighbor report from the peer. 1004 * @sessionId: session identifier on which the request should be made. 1005 * @pNeighborReq: a pointer to a neighbor report request. 1006 * 1007 * This is API can be used to trigger a Neighbor report from the peer. 1008 * 1009 * Return: QDF_STATUS_SUCCESS - Validation is successful. 1010 */ 1011 QDF_STATUS sme_rrm_neighbor_report_request(tpAniSirGlobal pMac, uint8_t 1012 sessionId, tpRrmNeighborReq 1013 pNeighborReq, 1014 tpRrmNeighborRspCallbackInfo 1015 callbackInfo) 1016 { 1017 QDF_STATUS status = QDF_STATUS_SUCCESS; 1018 tpSirNeighborReportReqInd pMsg; 1019 struct csr_roam_session *pSession; 1020 1021 sme_debug("Request to send Neighbor report request received "); 1022 if (!CSR_IS_SESSION_VALID(pMac, sessionId)) { 1023 sme_err("Invalid session %d", sessionId); 1024 return QDF_STATUS_E_INVAL; 1025 } 1026 pSession = CSR_GET_SESSION(pMac, sessionId); 1027 1028 /* If already a report is pending, return failure */ 1029 if (true == 1030 pMac->rrm.rrmSmeContext.neighborReqControlInfo. 1031 isNeighborRspPending) { 1032 sme_err("Neighbor request already pending.. Not allowed"); 1033 return QDF_STATUS_E_AGAIN; 1034 } 1035 1036 pMsg = qdf_mem_malloc(sizeof(tSirNeighborReportReqInd)); 1037 if (NULL == pMsg) { 1038 sme_err("Unable to allocate memory for Neighbor request"); 1039 return QDF_STATUS_E_NOMEM; 1040 } 1041 1042 rrm_ll_purge_neighbor_cache(pMac, 1043 &pMac->rrm.rrmSmeContext.neighborReportCache); 1044 1045 pMsg->messageType = eWNI_SME_NEIGHBOR_REPORT_REQ_IND; 1046 pMsg->length = sizeof(tSirNeighborReportReqInd); 1047 qdf_mem_copy(&pMsg->bssId, &pSession->connectedProfile.bssid, 1048 sizeof(tSirMacAddr)); 1049 pMsg->noSSID = pNeighborReq->no_ssid; 1050 qdf_mem_copy(&pMsg->ucSSID, &pNeighborReq->ssid, sizeof(tSirMacSSid)); 1051 1052 status = umac_send_mb_message_to_mac(pMsg); 1053 if (status != QDF_STATUS_SUCCESS) 1054 return QDF_STATUS_E_FAILURE; 1055 1056 /* Neighbor report request message sent successfully to PE. 1057 * Now register the callbacks 1058 */ 1059 pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo. 1060 neighborRspCallback = callbackInfo->neighborRspCallback; 1061 pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo. 1062 neighborRspCallbackContext = 1063 callbackInfo->neighborRspCallbackContext; 1064 pMac->rrm.rrmSmeContext.neighborReqControlInfo.isNeighborRspPending = 1065 true; 1066 1067 /* Start neighbor response wait timer now */ 1068 qdf_mc_timer_start(&pMac->rrm.rrmSmeContext.neighborReqControlInfo. 1069 neighborRspWaitTimer, callbackInfo->timeout); 1070 1071 return QDF_STATUS_SUCCESS; 1072 } 1073 1074 /** 1075 * rrm_calculate_neighbor_ap_roam_score() - caclulates roam score 1076 * @mac_ctx: mac global context 1077 * @pNeighborReportDesc: Neighbor BSS Descriptor node for which roam score 1078 * should be calculated 1079 * 1080 * This API is called while handling individual neighbor reports from the APs 1081 * neighbor AP report to calculate the cumulative roam score before storing it 1082 * in neighbor cache. 1083 * 1084 * Return: void 1085 */ 1086 static void 1087 rrm_calculate_neighbor_ap_roam_score(tpAniSirGlobal mac_ctx, 1088 tpRrmNeighborReportDesc nbr_report_desc) 1089 { 1090 tpSirNeighborBssDescripton nbr_bss_desc; 1091 uint32_t roam_score = 0; 1092 #ifdef FEATURE_WLAN_ESE 1093 uint8_t session_id; 1094 #endif 1095 if (NULL == nbr_report_desc) { 1096 QDF_ASSERT(0); 1097 return; 1098 } 1099 1100 if (NULL == nbr_report_desc->pNeighborBssDescription) { 1101 QDF_ASSERT(0); 1102 return; 1103 } 1104 1105 nbr_bss_desc = nbr_report_desc->pNeighborBssDescription; 1106 if (!nbr_bss_desc->bssidInfo.rrmInfo.fMobilityDomain) 1107 goto check_11r_assoc; 1108 1109 roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_MOBILITY_DOMAIN; 1110 if (!nbr_bss_desc->bssidInfo.rrmInfo.fSameSecurityMode) 1111 goto check_11r_assoc; 1112 1113 roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_SECURITY; 1114 if (!nbr_bss_desc->bssidInfo.rrmInfo.fSameAuthenticator) 1115 goto check_11r_assoc; 1116 1117 roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_KEY_SCOPE; 1118 if (!nbr_bss_desc->bssidInfo.rrmInfo.fCapRadioMeasurement) 1119 goto check_11r_assoc; 1120 1121 roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_RRM; 1122 if (nbr_bss_desc->bssidInfo.rrmInfo.fCapSpectrumMeasurement) 1123 roam_score += 1124 RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_SPECTRUM_MGMT; 1125 1126 if (nbr_bss_desc->bssidInfo.rrmInfo.fCapQos) 1127 roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_QOS; 1128 1129 if (nbr_bss_desc->bssidInfo.rrmInfo.fCapApsd) 1130 roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_APSD; 1131 1132 if (nbr_bss_desc->bssidInfo.rrmInfo.fCapDelayedBlockAck) 1133 roam_score += 1134 RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_DELAYED_BA; 1135 1136 if (nbr_bss_desc->bssidInfo.rrmInfo.fCapImmediateBlockAck) 1137 roam_score += 1138 RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_IMMEDIATE_BA; 1139 1140 if (nbr_bss_desc->bssidInfo.rrmInfo.fApPreauthReachable) 1141 roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_REACHABILITY; 1142 1143 check_11r_assoc: 1144 #ifdef FEATURE_WLAN_ESE 1145 session_id = nbr_report_desc->sessionId; 1146 /* It has come in the report so its the best score */ 1147 if (csr_neighbor_roam_is11r_assoc(mac_ctx, session_id) == false) { 1148 /* IAPP Route so lets make use of this info save all AP, as the 1149 * list does not come all the time. Save and reuse till the next 1150 * AP List comes to us. Even save our own MAC address. Will be 1151 * useful next time around. 1152 */ 1153 roam_score += RRM_ROAM_SCORE_NEIGHBOR_IAPP_LIST; 1154 } 1155 #endif 1156 nbr_report_desc->roamScore = roam_score; 1157 } 1158 1159 /** 1160 * rrm_store_neighbor_rpt_by_roam_score()-store Neighbor BSS descriptor 1161 * @pNeighborReportDesc - Neighbor BSS Descriptor node to be stored in cache 1162 * 1163 * This API is called to store a given 1164 * Neighbor BSS descriptor to the neighbor cache. This function 1165 * stores the neighbor BSS descriptors in such a way that descriptors 1166 * are sorted by roamScore in descending order 1167 * 1168 * Return: void. 1169 */ 1170 static void rrm_store_neighbor_rpt_by_roam_score(tpAniSirGlobal pMac, 1171 tpRrmNeighborReportDesc pNeighborReportDesc) 1172 { 1173 tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; 1174 tListElem *pEntry; 1175 tRrmNeighborReportDesc *pTempNeighborReportDesc; 1176 1177 if (NULL == pNeighborReportDesc) { 1178 QDF_ASSERT(0); 1179 return; 1180 } 1181 if (NULL == pNeighborReportDesc->pNeighborBssDescription) { 1182 QDF_ASSERT(0); 1183 return; 1184 } 1185 1186 if (csr_ll_is_list_empty 1187 (&pSmeRrmContext->neighborReportCache, LL_ACCESS_LOCK)) { 1188 sme_err("Neighbor report cache is empty.. Adding a entry now"); 1189 /* Neighbor list cache is empty. Insert this entry 1190 * in the tail 1191 */ 1192 csr_ll_insert_tail(&pSmeRrmContext->neighborReportCache, 1193 &pNeighborReportDesc->List, LL_ACCESS_LOCK); 1194 return; 1195 } 1196 /* Should store the neighbor BSS description in the order 1197 * sorted by roamScore in descending order. APs with highest 1198 * roamScore should be the 1st entry in the list 1199 */ 1200 pEntry = csr_ll_peek_head(&pSmeRrmContext->neighborReportCache, 1201 LL_ACCESS_LOCK); 1202 while (pEntry != NULL) { 1203 pTempNeighborReportDesc = GET_BASE_ADDR(pEntry, 1204 tRrmNeighborReportDesc, List); 1205 if (pTempNeighborReportDesc->roamScore < 1206 pNeighborReportDesc->roamScore) 1207 break; 1208 pEntry = csr_ll_next(&pSmeRrmContext-> 1209 neighborReportCache, pEntry, LL_ACCESS_LOCK); 1210 } 1211 1212 if (pEntry) 1213 /* This BSS roamscore is better than something in the 1214 * list. Insert this before that one 1215 */ 1216 csr_ll_insert_entry(&pSmeRrmContext->neighborReportCache, 1217 pEntry, &pNeighborReportDesc->List, 1218 LL_ACCESS_LOCK); 1219 else 1220 /* All the entries in the list has a better roam Score 1221 * than this one. Insert this at the last 1222 */ 1223 csr_ll_insert_tail(&pSmeRrmContext->neighborReportCache, 1224 &pNeighborReportDesc->List, 1225 LL_ACCESS_LOCK); 1226 } 1227 1228 /** 1229 * sme_rrm_process_neighbor_report() -Process the Neighbor report received 1230 * from PE 1231 * @pMac - Global MAC structure 1232 * @pMsgBuf - a pointer to a buffer that maps to various structures base 1233 * on the message type. 1234 * The beginning of the buffer can always map to tSirSmeRsp. 1235 * This is called to process the Neighbor report received from PE. 1236 * 1237 * Return: QDF_STATUS_SUCCESS - Validation is successful 1238 */ 1239 static QDF_STATUS sme_rrm_process_neighbor_report(tpAniSirGlobal pMac, 1240 void *pMsgBuf) 1241 { 1242 QDF_STATUS status = QDF_STATUS_SUCCESS; 1243 tpSirNeighborReportInd pNeighborRpt = (tpSirNeighborReportInd) pMsgBuf; 1244 tpRrmNeighborReportDesc pNeighborReportDesc; 1245 uint8_t i = 0; 1246 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; 1247 uint32_t sessionId; 1248 1249 /* Get the session id */ 1250 status = 1251 csr_roam_get_session_id_from_bssid(pMac, 1252 (struct qdf_mac_addr *) pNeighborRpt->bssId, 1253 &sessionId); 1254 if (QDF_IS_STATUS_SUCCESS(status)) { 1255 #ifdef FEATURE_WLAN_ESE 1256 /* Clear the cache for ESE. */ 1257 if (csr_roam_is_ese_assoc(pMac, sessionId)) { 1258 rrm_ll_purge_neighbor_cache(pMac, 1259 &pMac->rrm.rrmSmeContext. 1260 neighborReportCache); 1261 } 1262 #endif 1263 } 1264 1265 for (i = 0; i < pNeighborRpt->numNeighborReports; i++) { 1266 pNeighborReportDesc = 1267 qdf_mem_malloc(sizeof(tRrmNeighborReportDesc)); 1268 if (NULL == pNeighborReportDesc) { 1269 sme_err("Failed to alloc memory for RRM report desc"); 1270 status = QDF_STATUS_E_NOMEM; 1271 goto end; 1272 1273 } 1274 1275 pNeighborReportDesc->pNeighborBssDescription = 1276 qdf_mem_malloc(sizeof(tSirNeighborBssDescription)); 1277 if (NULL == pNeighborReportDesc->pNeighborBssDescription) { 1278 sme_err("Failed to alloc mem for RRM BSS Description"); 1279 qdf_mem_free(pNeighborReportDesc); 1280 status = QDF_STATUS_E_NOMEM; 1281 goto end; 1282 } 1283 qdf_mem_copy(pNeighborReportDesc->pNeighborBssDescription, 1284 &pNeighborRpt->sNeighborBssDescription[i], 1285 sizeof(tSirNeighborBssDescription)); 1286 1287 sme_debug("Received neighbor report with Neighbor BSSID: " 1288 MAC_ADDRESS_STR, 1289 MAC_ADDR_ARRAY( 1290 pNeighborRpt->sNeighborBssDescription[i].bssId)); 1291 1292 rrm_calculate_neighbor_ap_roam_score(pMac, pNeighborReportDesc); 1293 1294 if (pNeighborReportDesc->roamScore > 0) { 1295 rrm_store_neighbor_rpt_by_roam_score(pMac, 1296 pNeighborReportDesc); 1297 } else { 1298 sme_err("Roam score of BSSID " MAC_ADDRESS_STR 1299 " is 0, Ignoring..", 1300 MAC_ADDR_ARRAY(pNeighborRpt-> 1301 sNeighborBssDescription[i]. 1302 bssId)); 1303 1304 qdf_mem_free( 1305 pNeighborReportDesc->pNeighborBssDescription); 1306 qdf_mem_free(pNeighborReportDesc); 1307 } 1308 } 1309 end: 1310 1311 if (!csr_ll_count(&pMac->rrm.rrmSmeContext.neighborReportCache)) 1312 qdf_status = QDF_STATUS_E_FAILURE; 1313 1314 rrm_indicate_neighbor_report_result(pMac, qdf_status); 1315 return status; 1316 } 1317 1318 /** 1319 * sme_rrm_msg_processor()-Process RRM message 1320 * @pMac - Pointer to the global MAC parameter structure. 1321 * @msg_type - the type of msg passed by PE as defined in wni_api.h 1322 * @pMsgBuf - a pointer to a buffer that maps to various structures base 1323 * on the message type. 1324 * The beginning of the buffer can always map to tSirSmeRsp. 1325 * sme_process_msg() calls this function for the 1326 * messages that are handled by SME RRM module. 1327 * 1328 * Return: QDF_STATUS_SUCCESS - Validation is successful. 1329 */ 1330 QDF_STATUS sme_rrm_msg_processor(tpAniSirGlobal pMac, uint16_t msg_type, 1331 void *pMsgBuf) 1332 { 1333 sme_debug("Msg = %d for RRM measurement", msg_type); 1334 1335 /* switch on the msg type & make the state transition accordingly */ 1336 switch (msg_type) { 1337 case eWNI_SME_NEIGHBOR_REPORT_IND: 1338 sme_rrm_process_neighbor_report(pMac, pMsgBuf); 1339 break; 1340 1341 case eWNI_SME_BEACON_REPORT_REQ_IND: 1342 sme_rrm_process_beacon_report_req_ind(pMac, pMsgBuf); 1343 break; 1344 1345 default: 1346 sme_err("Unknown msg type: %d", msg_type); 1347 break; 1348 } 1349 1350 return QDF_STATUS_SUCCESS; 1351 } 1352 1353 /** 1354 * rrm_iter_meas_timer_handle() - Timer handler to handlet the timeout 1355 * @ pMac - The handle returned by mac_open. 1356 * 1357 * Timer handler to handlet the timeout condition when a specific BT 1358 * stop event does not come back, in which case to restore back the 1359 * heartbeat timer. 1360 * 1361 * Return: NULL 1362 */ 1363 static void rrm_iter_meas_timer_handle(void *userData) 1364 { 1365 tpAniSirGlobal pMac = (tpAniSirGlobal) userData; 1366 1367 sme_warn("Randomization timer expired...send on next channel"); 1368 /* Issue a scan req for next channel. */ 1369 sme_rrm_issue_scan_req(pMac); 1370 } 1371 /** 1372 * rrm_neighbor_rsp_timeout_handler() - Timer handler to handlet the timeout 1373 * @pMac - The handle returned by mac_open. 1374 * 1375 * Timer handler to handle the timeout condition when a neighbor request is sent 1376 * and no neighbor response is received from the AP 1377 * 1378 * Return: NULL 1379 */ 1380 static void rrm_neighbor_rsp_timeout_handler(void *userData) 1381 { 1382 tpAniSirGlobal pMac = (tpAniSirGlobal) userData; 1383 1384 sme_warn("Neighbor Response timed out"); 1385 rrm_indicate_neighbor_report_result(pMac, QDF_STATUS_E_FAILURE); 1386 } 1387 1388 /** 1389 * rrm_open() - Initialze all RRM module 1390 * @ pMac: The handle returned by mac_open. 1391 * 1392 * Initialze all RRM module. 1393 * 1394 * Return: QDF_STATUS 1395 */ 1396 QDF_STATUS rrm_open(tpAniSirGlobal pMac) 1397 { 1398 1399 QDF_STATUS qdf_status; 1400 tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; 1401 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS; 1402 1403 pSmeRrmContext->rrmConfig.max_randn_interval = 50; /* ms */ 1404 1405 qdf_status = qdf_mc_timer_init(&pSmeRrmContext->IterMeasTimer, 1406 QDF_TIMER_TYPE_SW, 1407 rrm_iter_meas_timer_handle, 1408 (void *)pMac); 1409 1410 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 1411 sme_err("Fail to init measurement timer"); 1412 return QDF_STATUS_E_FAILURE; 1413 } 1414 1415 qdf_status = 1416 qdf_mc_timer_init(&pSmeRrmContext->neighborReqControlInfo. 1417 neighborRspWaitTimer, QDF_TIMER_TYPE_SW, 1418 rrm_neighbor_rsp_timeout_handler, 1419 (void *)pMac); 1420 1421 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 1422 sme_err("Fail to init neighbor rsp wait timer"); 1423 return QDF_STATUS_E_FAILURE; 1424 } 1425 1426 pSmeRrmContext->neighborReqControlInfo.isNeighborRspPending = false; 1427 1428 qdf_ret_status = csr_ll_open(&pSmeRrmContext->neighborReportCache); 1429 if (QDF_STATUS_SUCCESS != qdf_ret_status) { 1430 sme_err("Fail to open neighbor cache result"); 1431 return QDF_STATUS_E_FAILURE; 1432 } 1433 1434 return QDF_STATUS_SUCCESS; 1435 } 1436 1437 /** 1438 * rrm_close() - Release all RRM modules and their resources. 1439 * @pMac - The handle returned by mac_open. 1440 * 1441 * Release all RRM modules and their resources. 1442 * 1443 * Return: QDF_STATUS 1444 * QDF_STATUS_E_FAILURE success 1445 * QDF_STATUS_SUCCESS failure 1446 */ 1447 1448 QDF_STATUS rrm_close(tpAniSirGlobal pMac) 1449 { 1450 1451 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; 1452 tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; 1453 1454 if (QDF_TIMER_STATE_RUNNING == 1455 qdf_mc_timer_get_current_state(&pSmeRrmContext->IterMeasTimer)) { 1456 qdf_status = qdf_mc_timer_stop(&pSmeRrmContext->IterMeasTimer); 1457 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 1458 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, 1459 FL("Timer stop fail")); 1460 } 1461 } 1462 1463 qdf_status = qdf_mc_timer_destroy(&pSmeRrmContext->IterMeasTimer); 1464 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 1465 1466 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, 1467 FL("Fail to destroy timer")); 1468 1469 } 1470 1471 if (QDF_TIMER_STATE_RUNNING == 1472 qdf_mc_timer_get_current_state(&pSmeRrmContext-> 1473 neighborReqControlInfo. 1474 neighborRspWaitTimer)) { 1475 qdf_status = qdf_mc_timer_stop(&pSmeRrmContext-> 1476 neighborReqControlInfo. 1477 neighborRspWaitTimer); 1478 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 1479 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, 1480 FL("Timer stop fail")); 1481 } 1482 } 1483 1484 qdf_status = 1485 qdf_mc_timer_destroy(&pSmeRrmContext->neighborReqControlInfo. 1486 neighborRspWaitTimer); 1487 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 1488 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, 1489 FL("Fail to destroy timer")); 1490 1491 } 1492 1493 rrm_ll_purge_neighbor_cache(pMac, &pSmeRrmContext->neighborReportCache); 1494 1495 csr_ll_close(&pSmeRrmContext->neighborReportCache); 1496 1497 return qdf_status; 1498 1499 } 1500 1501 /** 1502 * rrm_change_default_config_param() - Changing default config param to new 1503 * @pMac - The handle returned by mac_open. 1504 * param pRrmConfig - pointer to new rrm configs. 1505 * 1506 * Return: QDF_STATUS 1507 * QDF_STATUS_SUCCESS success 1508 */ 1509 QDF_STATUS rrm_change_default_config_param(tpAniSirGlobal pMac, 1510 struct rrm_config_param *rrm_config) 1511 { 1512 qdf_mem_copy(&pMac->rrm.rrmSmeContext.rrmConfig, rrm_config, 1513 sizeof(struct rrm_config_param)); 1514 1515 return QDF_STATUS_SUCCESS; 1516 } 1517 1518 QDF_STATUS rrm_start(tpAniSirGlobal mac_ctx) 1519 { 1520 tpRrmSMEContext smerrmctx = &mac_ctx->rrm.rrmSmeContext; 1521 1522 /* Register with scan component */ 1523 smerrmctx->req_id = ucfg_scan_register_requester(mac_ctx->psoc, 1524 "RRM", 1525 sme_rrm_scan_event_callback, 1526 smerrmctx); 1527 1528 return QDF_STATUS_SUCCESS; 1529 } 1530 1531 QDF_STATUS rrm_stop(tpAniSirGlobal mac_ctx) 1532 { 1533 tpRrmSMEContext smerrmctx = &mac_ctx->rrm.rrmSmeContext; 1534 1535 ucfg_scan_unregister_requester(mac_ctx->psoc, smerrmctx->req_id); 1536 1537 return QDF_STATUS_SUCCESS; 1538 } 1539