1 /* 2 * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. 3 * 4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc. 5 * 6 * 7 * Permission to use, copy, modify, and/or distribute this software for 8 * any purpose with or without fee is hereby granted, provided that the 9 * above copyright notice and this permission notice appear in all 10 * copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 19 * PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22 /* 23 * This file was originally distributed by Qualcomm Atheros, Inc. 24 * under proprietary terms before Copyright ownership was assigned 25 * to the Linux Foundation. 26 */ 27 28 /**========================================================================= 29 30 \file rrm_api.c 31 32 \brief implementation for PE RRM APIs 33 34 ========================================================================*/ 35 36 /* $Header$ */ 37 38 39 /*-------------------------------------------------------------------------- 40 Include Files 41 ------------------------------------------------------------------------*/ 42 #include "cds_api.h" 43 #include "wni_api.h" 44 #include "sir_api.h" 45 #include "ani_global.h" 46 #include "wni_cfg.h" 47 #include "lim_types.h" 48 #include "lim_utils.h" 49 #include "lim_send_sme_rsp_messages.h" 50 #include "parser_api.h" 51 #include "lim_send_messages.h" 52 #include "rrm_global.h" 53 #include "rrm_api.h" 54 55 #define MAX_RRM_TX_PWR_CAP 22 56 57 uint8_t 58 rrm_get_min_of_max_tx_power(tpAniSirGlobal pMac, 59 int8_t regMax, int8_t apTxPower) 60 { 61 uint8_t maxTxPower = 0; 62 uint8_t txPower = QDF_MIN(regMax, (apTxPower)); 63 if ((txPower >= RRM_MIN_TX_PWR_CAP) && (txPower <= RRM_MAX_TX_PWR_CAP)) 64 maxTxPower = txPower; 65 else if (txPower < RRM_MIN_TX_PWR_CAP) 66 maxTxPower = RRM_MIN_TX_PWR_CAP; 67 else 68 maxTxPower = RRM_MAX_TX_PWR_CAP; 69 70 pe_debug("regulatoryMax: %d, apTxPwr: %d, maxTxpwr: %d", 71 regMax, apTxPower, maxTxPower); 72 return maxTxPower; 73 } 74 75 /* -------------------------------------------------------------------- */ 76 /** 77 * rrm_cache_mgmt_tx_power 78 ** 79 * FUNCTION: Store Tx power for management frames. 80 * 81 * LOGIC: 82 * 83 * ASSUMPTIONS: 84 * 85 * NOTE: 86 * 87 * @param pSessionEntry session entry. 88 * @return None 89 */ 90 void 91 rrm_cache_mgmt_tx_power(tpAniSirGlobal pMac, int8_t txPower, 92 tpPESession pSessionEntry) 93 { 94 pe_debug("Cache Mgmt Tx Power: %d", txPower); 95 96 if (pSessionEntry == NULL) 97 pMac->rrm.rrmPEContext.txMgmtPower = txPower; 98 else 99 pSessionEntry->txMgmtPower = txPower; 100 } 101 102 /* -------------------------------------------------------------------- */ 103 /** 104 * rrm_get_mgmt_tx_power 105 * 106 * FUNCTION: Get the Tx power for management frames. 107 * 108 * LOGIC: 109 * 110 * ASSUMPTIONS: 111 * 112 * NOTE: 113 * 114 * @param pSessionEntry session entry. 115 * @return txPower 116 */ 117 int8_t rrm_get_mgmt_tx_power(tpAniSirGlobal pMac, tpPESession pSessionEntry) 118 { 119 if (pSessionEntry == NULL) 120 return pMac->rrm.rrmPEContext.txMgmtPower; 121 122 pe_debug("tx mgmt pwr %d", pSessionEntry->txMgmtPower); 123 124 return pSessionEntry->txMgmtPower; 125 } 126 127 /* -------------------------------------------------------------------- */ 128 /** 129 * rrm_send_set_max_tx_power_req 130 * 131 * FUNCTION: Send WMA_SET_MAX_TX_POWER_REQ message to change the max tx power. 132 * 133 * LOGIC: 134 * 135 * ASSUMPTIONS: 136 * 137 * NOTE: 138 * 139 * @param txPower txPower to be set. 140 * @param pSessionEntry session entry. 141 * @return None 142 */ 143 tSirRetStatus 144 rrm_send_set_max_tx_power_req(tpAniSirGlobal pMac, int8_t txPower, 145 tpPESession pSessionEntry) 146 { 147 tpMaxTxPowerParams pMaxTxParams; 148 tSirRetStatus retCode = eSIR_SUCCESS; 149 struct scheduler_msg msgQ = {0}; 150 151 if (pSessionEntry == NULL) { 152 pe_err("Invalid parameters"); 153 return eSIR_FAILURE; 154 } 155 pMaxTxParams = qdf_mem_malloc(sizeof(tMaxTxPowerParams)); 156 if (NULL == pMaxTxParams) { 157 pe_err("Unable to allocate memory for pMaxTxParams"); 158 return eSIR_MEM_ALLOC_FAILED; 159 160 } 161 /* Allocated memory for pMaxTxParams...will be freed in other module */ 162 pMaxTxParams->power = txPower; 163 qdf_mem_copy(pMaxTxParams->bssId.bytes, pSessionEntry->bssId, 164 QDF_MAC_ADDR_SIZE); 165 qdf_mem_copy(pMaxTxParams->selfStaMacAddr.bytes, 166 pSessionEntry->selfMacAddr, 167 QDF_MAC_ADDR_SIZE); 168 169 msgQ.type = WMA_SET_MAX_TX_POWER_REQ; 170 msgQ.reserved = 0; 171 msgQ.bodyptr = pMaxTxParams; 172 msgQ.bodyval = 0; 173 174 pe_debug("Sending WMA_SET_MAX_TX_POWER_REQ with power(%d) to HAL", 175 txPower); 176 177 MTRACE(mac_trace_msg_tx(pMac, pSessionEntry->peSessionId, msgQ.type)); 178 retCode = wma_post_ctrl_msg(pMac, &msgQ); 179 if (eSIR_SUCCESS != retCode) { 180 pe_err("Posting WMA_SET_MAX_TX_POWER_REQ to HAL failed, reason=%X", 181 retCode); 182 qdf_mem_free(pMaxTxParams); 183 return retCode; 184 } 185 return retCode; 186 } 187 188 /* -------------------------------------------------------------------- */ 189 /** 190 * rrm_set_max_tx_power_rsp 191 * 192 * FUNCTION: Process WMA_SET_MAX_TX_POWER_RSP message. 193 * 194 * LOGIC: 195 * 196 * ASSUMPTIONS: 197 * 198 * NOTE: 199 * 200 * @param txPower txPower to be set. 201 * @param pSessionEntry session entry. 202 * @return None 203 */ 204 tSirRetStatus rrm_set_max_tx_power_rsp(tpAniSirGlobal pMac, 205 struct scheduler_msg *limMsgQ) 206 { 207 tSirRetStatus retCode = eSIR_SUCCESS; 208 tpMaxTxPowerParams pMaxTxParams = (tpMaxTxPowerParams) limMsgQ->bodyptr; 209 tpPESession pSessionEntry; 210 uint8_t sessionId, i; 211 212 if (qdf_is_macaddr_broadcast(&pMaxTxParams->bssId)) { 213 for (i = 0; i < pMac->lim.maxBssId; i++) { 214 if (pMac->lim.gpSession[i].valid == true) { 215 pSessionEntry = &pMac->lim.gpSession[i]; 216 rrm_cache_mgmt_tx_power(pMac, pMaxTxParams->power, 217 pSessionEntry); 218 } 219 } 220 } else { 221 pSessionEntry = pe_find_session_by_bssid(pMac, 222 pMaxTxParams->bssId.bytes, 223 &sessionId); 224 if (pSessionEntry == NULL) { 225 retCode = eSIR_FAILURE; 226 } else { 227 rrm_cache_mgmt_tx_power(pMac, pMaxTxParams->power, 228 pSessionEntry); 229 } 230 } 231 232 qdf_mem_free(limMsgQ->bodyptr); 233 limMsgQ->bodyptr = NULL; 234 return retCode; 235 } 236 237 /* -------------------------------------------------------------------- */ 238 /** 239 * rrm_process_link_measurement_request 240 * 241 * FUNCTION: Processes the Link measurement request and send the report. 242 * 243 * LOGIC: 244 * 245 * ASSUMPTIONS: 246 * 247 * NOTE: 248 * 249 * @param pBd pointer to BD to extract RSSI and SNR 250 * @param pLinkReq pointer to the Link request frame structure. 251 * @param pSessionEntry session entry. 252 * @return None 253 */ 254 tSirRetStatus 255 rrm_process_link_measurement_request(tpAniSirGlobal pMac, 256 uint8_t *pRxPacketInfo, 257 tDot11fLinkMeasurementRequest *pLinkReq, 258 tpPESession pSessionEntry) 259 { 260 tSirMacLinkReport LinkReport; 261 tpSirMacMgmtHdr pHdr; 262 int8_t currentRSSI = 0; 263 264 pe_debug("Received Link measurement request"); 265 266 if (pRxPacketInfo == NULL || pLinkReq == NULL || pSessionEntry == NULL) { 267 pe_err("Invalid parameters - Ignoring the request"); 268 return eSIR_FAILURE; 269 } 270 pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); 271 272 LinkReport.txPower = lim_get_max_tx_power(pSessionEntry->maxTxPower, 273 pLinkReq->MaxTxPower.maxTxPower, 274 pMac->roam.configParam. 275 nTxPowerCap); 276 277 if ((LinkReport.txPower != (uint8_t) (pSessionEntry->maxTxPower)) && 278 (eSIR_SUCCESS == rrm_send_set_max_tx_power_req(pMac, 279 LinkReport.txPower, 280 pSessionEntry))) { 281 pe_warn("maxTx power in link report is not same as local..." 282 " Local: %d Link Request TxPower: %d" 283 " Link Report TxPower: %d", 284 pSessionEntry->maxTxPower, LinkReport.txPower, 285 pLinkReq->MaxTxPower.maxTxPower); 286 pSessionEntry->maxTxPower = 287 LinkReport.txPower; 288 } 289 290 LinkReport.dialogToken = pLinkReq->DialogToken.token; 291 LinkReport.rxAntenna = 0; 292 LinkReport.txAntenna = 0; 293 currentRSSI = WMA_GET_RX_RSSI_RAW(pRxPacketInfo); 294 295 pe_info("Received Link report frame with %d", currentRSSI); 296 297 /* 2008 11k spec reference: 18.4.8.5 RCPI Measurement */ 298 if ((currentRSSI) <= RCPI_LOW_RSSI_VALUE) 299 LinkReport.rcpi = 0; 300 else if ((currentRSSI > RCPI_LOW_RSSI_VALUE) && (currentRSSI <= 0)) 301 LinkReport.rcpi = CALCULATE_RCPI(currentRSSI); 302 else 303 LinkReport.rcpi = RCPI_MAX_VALUE; 304 305 LinkReport.rsni = WMA_GET_RX_SNR(pRxPacketInfo); 306 307 pe_debug("Sending Link report frame"); 308 309 return lim_send_link_report_action_frame(pMac, &LinkReport, pHdr->sa, 310 pSessionEntry); 311 } 312 313 /* -------------------------------------------------------------------- */ 314 /** 315 * rrm_process_neighbor_report_response 316 * 317 * FUNCTION: Processes the Neighbor Report response from the peer AP. 318 * 319 * LOGIC: 320 * 321 * ASSUMPTIONS: 322 * 323 * NOTE: 324 * 325 * @param pNeighborRep pointer to the Neighbor report frame structure. 326 * @param pSessionEntry session entry. 327 * @return None 328 */ 329 tSirRetStatus 330 rrm_process_neighbor_report_response(tpAniSirGlobal pMac, 331 tDot11fNeighborReportResponse *pNeighborRep, 332 tpPESession pSessionEntry) 333 { 334 tSirRetStatus status = eSIR_FAILURE; 335 tpSirNeighborReportInd pSmeNeighborRpt = NULL; 336 uint16_t length; 337 uint8_t i; 338 struct scheduler_msg mmhMsg = {0}; 339 340 if (pNeighborRep == NULL || pSessionEntry == NULL) { 341 pe_err("Invalid parameters"); 342 return status; 343 } 344 345 pe_debug("Neighbor report response received"); 346 347 /* Dialog token */ 348 if (pMac->rrm.rrmPEContext.DialogToken != 349 pNeighborRep->DialogToken.token) { 350 pe_err("Dialog token mismatch in the received Neighbor report"); 351 return eSIR_FAILURE; 352 } 353 if (pNeighborRep->num_NeighborReport == 0) { 354 pe_err("No neighbor report in the frame...Dropping it"); 355 return eSIR_FAILURE; 356 } 357 pe_debug("RRM:received num neighbor reports: %d", 358 pNeighborRep->num_NeighborReport); 359 if (pNeighborRep->num_NeighborReport > MAX_SUPPORTED_NEIGHBOR_RPT) 360 pNeighborRep->num_NeighborReport = MAX_SUPPORTED_NEIGHBOR_RPT; 361 length = (sizeof(tSirNeighborReportInd)) + 362 (sizeof(tSirNeighborBssDescription) * 363 (pNeighborRep->num_NeighborReport - 1)); 364 365 /* Prepare the request to send to SME. */ 366 pSmeNeighborRpt = qdf_mem_malloc(length); 367 if (NULL == pSmeNeighborRpt) { 368 pe_err("Unable to allocate memory"); 369 return eSIR_MEM_ALLOC_FAILED; 370 } 371 372 /* Allocated memory for pSmeNeighborRpt...will be freed by other module */ 373 374 for (i = 0; i < pNeighborRep->num_NeighborReport; i++) { 375 pSmeNeighborRpt->sNeighborBssDescription[i].length = sizeof(tSirNeighborBssDescription); /*+ any optional ies */ 376 qdf_mem_copy(pSmeNeighborRpt->sNeighborBssDescription[i].bssId, 377 pNeighborRep->NeighborReport[i].bssid, 378 sizeof(tSirMacAddr)); 379 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo. 380 fApPreauthReachable = 381 pNeighborRep->NeighborReport[i].APReachability; 382 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo. 383 fSameSecurityMode = 384 pNeighborRep->NeighborReport[i].Security; 385 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo. 386 fSameAuthenticator = 387 pNeighborRep->NeighborReport[i].KeyScope; 388 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo. 389 fCapSpectrumMeasurement = 390 pNeighborRep->NeighborReport[i].SpecMgmtCap; 391 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo. 392 fCapQos = pNeighborRep->NeighborReport[i].QosCap; 393 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo. 394 fCapApsd = pNeighborRep->NeighborReport[i].apsd; 395 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo. 396 fCapRadioMeasurement = pNeighborRep->NeighborReport[i].rrm; 397 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo. 398 fCapDelayedBlockAck = 399 pNeighborRep->NeighborReport[i].DelayedBA; 400 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo. 401 fCapImmediateBlockAck = 402 pNeighborRep->NeighborReport[i].ImmBA; 403 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo. 404 fMobilityDomain = 405 pNeighborRep->NeighborReport[i].MobilityDomain; 406 407 pSmeNeighborRpt->sNeighborBssDescription[i].regClass = 408 pNeighborRep->NeighborReport[i].regulatoryClass; 409 pSmeNeighborRpt->sNeighborBssDescription[i].channel = 410 pNeighborRep->NeighborReport[i].channel; 411 pSmeNeighborRpt->sNeighborBssDescription[i].phyType = 412 pNeighborRep->NeighborReport[i].PhyType; 413 } 414 415 pSmeNeighborRpt->messageType = eWNI_SME_NEIGHBOR_REPORT_IND; 416 pSmeNeighborRpt->length = length; 417 pSmeNeighborRpt->sessionId = pSessionEntry->smeSessionId; 418 pSmeNeighborRpt->numNeighborReports = pNeighborRep->num_NeighborReport; 419 qdf_mem_copy(pSmeNeighborRpt->bssId, pSessionEntry->bssId, 420 sizeof(tSirMacAddr)); 421 422 /* Send request to SME. */ 423 mmhMsg.type = pSmeNeighborRpt->messageType; 424 mmhMsg.bodyptr = pSmeNeighborRpt; 425 MTRACE(mac_trace(pMac, TRACE_CODE_TX_SME_MSG, 426 pSessionEntry->peSessionId, mmhMsg.type)); 427 status = lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); 428 429 return status; 430 431 } 432 433 /* -------------------------------------------------------------------- */ 434 /** 435 * rrm_process_neighbor_report_req 436 * 437 * FUNCTION: 438 * 439 * LOGIC: Create a Neighbor report request and send it to peer. 440 * 441 * ASSUMPTIONS: 442 * 443 * NOTE: 444 * 445 * @param pNeighborReq Neighbor report request params . 446 * @return None 447 */ 448 tSirRetStatus 449 rrm_process_neighbor_report_req(tpAniSirGlobal pMac, 450 tpSirNeighborReportReqInd pNeighborReq) 451 { 452 tSirRetStatus status = eSIR_SUCCESS; 453 tSirMacNeighborReportReq NeighborReportReq; 454 tpPESession pSessionEntry; 455 uint8_t sessionId; 456 457 if (pNeighborReq == NULL) { 458 pe_err("NeighborReq is NULL"); 459 return eSIR_FAILURE; 460 } 461 pSessionEntry = pe_find_session_by_bssid(pMac, pNeighborReq->bssId, 462 &sessionId); 463 if (pSessionEntry == NULL) { 464 pe_err("session does not exist for given bssId"); 465 return eSIR_FAILURE; 466 } 467 468 pe_debug("SSID present: %d", pNeighborReq->noSSID); 469 470 qdf_mem_set(&NeighborReportReq, sizeof(tSirMacNeighborReportReq), 0); 471 472 NeighborReportReq.dialogToken = ++pMac->rrm.rrmPEContext.DialogToken; 473 NeighborReportReq.ssid_present = !pNeighborReq->noSSID; 474 if (NeighborReportReq.ssid_present) { 475 qdf_mem_copy(&NeighborReportReq.ssid, &pNeighborReq->ucSSID, 476 sizeof(tSirMacSSid)); 477 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, 478 QDF_TRACE_LEVEL_DEBUG, 479 (uint8_t *) NeighborReportReq.ssid.ssId, 480 NeighborReportReq.ssid.length); 481 } 482 483 status = 484 lim_send_neighbor_report_request_frame(pMac, &NeighborReportReq, 485 pNeighborReq->bssId, 486 pSessionEntry); 487 488 return status; 489 } 490 491 #define ABS(x) ((x < 0) ? -x : x) 492 /* -------------------------------------------------------------------- */ 493 /** 494 * rrm_process_beacon_report_req 495 * 496 * FUNCTION: Processes the Beacon report request from the peer AP. 497 * 498 * LOGIC: 499 * 500 * ASSUMPTIONS: 501 * 502 * NOTE: 503 * 504 * @param pCurrentReq pointer to the current Req comtext. 505 * @param pBeaconReq pointer to the beacon report request IE from the peer. 506 * @param pSessionEntry session entry. 507 * @return None 508 */ 509 static tRrmRetStatus 510 rrm_process_beacon_report_req(tpAniSirGlobal pMac, 511 tpRRMReq pCurrentReq, 512 tDot11fIEMeasurementRequest *pBeaconReq, 513 tpPESession pSessionEntry) 514 { 515 struct scheduler_msg mmhMsg = {0}; 516 tpSirBeaconReportReqInd pSmeBcnReportReq; 517 uint8_t num_channels = 0, num_APChanReport; 518 uint16_t measDuration, maxMeasduration; 519 int8_t maxDuration; 520 uint8_t sign; 521 522 if (pBeaconReq->measurement_request.Beacon.BeaconReporting.present && 523 (pBeaconReq->measurement_request.Beacon.BeaconReporting. 524 reportingCondition != 0)) { 525 /* Repeated measurement is not supported. This means number of repetitions should be zero.(Already checked) */ 526 /* All test case in VoWifi(as of version 0.36) use zero for number of repetitions. */ 527 /* Beacon reporting should not be included in request if number of repetitons is zero. */ 528 /* IEEE Std 802.11k-2008 Table 7-29g and section 11.10.8.1 */ 529 530 pe_err("Dropping the request: Reporting condition included in beacon report request and it is not zero"); 531 return eRRM_INCAPABLE; 532 } 533 534 /* The logic here is to check the measurement duration passed in the beacon request. Following are the cases handled. 535 Case 1: If measurement duration received in the beacon request is greater than the max measurement duration advertised 536 in the RRM capabilities(Assoc Req), and Duration Mandatory bit is set to 1, REFUSE the beacon request 537 Case 2: If measurement duration received in the beacon request is greater than the max measurement duration advertised 538 in the RRM capabilities(Assoc Req), and Duration Mandatory bit is set to 0, perform measurement for 539 the duration advertised in the RRM capabilities 540 541 maxMeasurementDuration = 2^(nonOperatingChanMax - 4) * BeaconInterval 542 */ 543 maxDuration = 544 pMac->rrm.rrmPEContext.rrmEnabledCaps.nonOperatingChanMax - 4; 545 sign = (maxDuration < 0) ? 1 : 0; 546 maxDuration = (1L << ABS(maxDuration)); 547 if (!sign) 548 maxMeasduration = 549 maxDuration * pSessionEntry->beaconParams.beaconInterval; 550 else 551 maxMeasduration = 552 pSessionEntry->beaconParams.beaconInterval / maxDuration; 553 554 measDuration = pBeaconReq->measurement_request.Beacon.meas_duration; 555 556 pe_info("maxDuration = %d sign = %d maxMeasduration = %d measDuration = %d", 557 maxDuration, sign, maxMeasduration, measDuration); 558 559 if (maxMeasduration < measDuration) { 560 if (pBeaconReq->durationMandatory) { 561 pe_err("Dropping the request: duration mandatory and maxduration > measduration"); 562 return eRRM_REFUSED; 563 } else 564 measDuration = maxMeasduration; 565 } 566 /* Cache the data required for sending report. */ 567 pCurrentReq->request.Beacon.reportingDetail = 568 pBeaconReq->measurement_request.Beacon.BcnReportingDetail. 569 present ? pBeaconReq->measurement_request.Beacon.BcnReportingDetail. 570 reportingDetail : BEACON_REPORTING_DETAIL_ALL_FF_IE; 571 572 if (pBeaconReq->measurement_request.Beacon.RequestedInfo.present) { 573 pCurrentReq->request.Beacon.reqIes.pElementIds = 574 qdf_mem_malloc(sizeof(uint8_t) * 575 pBeaconReq->measurement_request.Beacon. 576 RequestedInfo.num_requested_eids); 577 if (NULL == pCurrentReq->request.Beacon.reqIes.pElementIds) { 578 pe_err("Unable to allocate memory for request IEs buffer"); 579 return eRRM_FAILURE; 580 } 581 pCurrentReq->request.Beacon.reqIes.num = 582 pBeaconReq->measurement_request.Beacon.RequestedInfo. 583 num_requested_eids; 584 qdf_mem_copy(pCurrentReq->request.Beacon.reqIes.pElementIds, 585 pBeaconReq->measurement_request.Beacon. 586 RequestedInfo.requested_eids, 587 pCurrentReq->request.Beacon.reqIes.num); 588 } 589 590 if (pBeaconReq->measurement_request.Beacon.num_APChannelReport) { 591 for (num_APChanReport = 0; 592 num_APChanReport < 593 pBeaconReq->measurement_request.Beacon.num_APChannelReport; 594 num_APChanReport++) 595 num_channels += 596 pBeaconReq->measurement_request.Beacon. 597 APChannelReport[num_APChanReport].num_channelList; 598 } 599 /* Prepare the request to send to SME. */ 600 pSmeBcnReportReq = qdf_mem_malloc(sizeof(tSirBeaconReportReqInd)); 601 if (NULL == pSmeBcnReportReq) { 602 pe_err("Unable to allocate memory during Beacon Report Req Ind to SME"); 603 return eRRM_FAILURE; 604 605 } 606 607 /* Allocated memory for pSmeBcnReportReq....will be freed by other modulea */ 608 qdf_mem_copy(pSmeBcnReportReq->bssId, pSessionEntry->bssId, 609 sizeof(tSirMacAddr)); 610 pSmeBcnReportReq->messageType = eWNI_SME_BEACON_REPORT_REQ_IND; 611 pSmeBcnReportReq->length = sizeof(tSirBeaconReportReqInd); 612 pSmeBcnReportReq->uDialogToken = pBeaconReq->measurement_token; 613 pSmeBcnReportReq->msgSource = eRRM_MSG_SOURCE_11K; 614 pSmeBcnReportReq->randomizationInterval = 615 SYS_TU_TO_MS(pBeaconReq->measurement_request.Beacon.randomization); 616 pSmeBcnReportReq->channelInfo.regulatoryClass = 617 pBeaconReq->measurement_request.Beacon.regClass; 618 pSmeBcnReportReq->channelInfo.channelNum = 619 pBeaconReq->measurement_request.Beacon.channel; 620 pSmeBcnReportReq->measurementDuration[0] = SYS_TU_TO_MS(measDuration); 621 pSmeBcnReportReq->fMeasurementtype[0] = 622 pBeaconReq->measurement_request.Beacon.meas_mode; 623 qdf_mem_copy(pSmeBcnReportReq->macaddrBssid, 624 pBeaconReq->measurement_request.Beacon.BSSID, 625 sizeof(tSirMacAddr)); 626 627 if (pBeaconReq->measurement_request.Beacon.SSID.present) { 628 pSmeBcnReportReq->ssId.length = 629 pBeaconReq->measurement_request.Beacon.SSID.num_ssid; 630 qdf_mem_copy(pSmeBcnReportReq->ssId.ssId, 631 pBeaconReq->measurement_request.Beacon.SSID.ssid, 632 pSmeBcnReportReq->ssId.length); 633 } 634 635 pCurrentReq->token = pBeaconReq->measurement_token; 636 637 pSmeBcnReportReq->channelList.numChannels = num_channels; 638 if (pBeaconReq->measurement_request.Beacon.num_APChannelReport) { 639 uint8_t *ch_lst = pSmeBcnReportReq->channelList.channelNumber; 640 uint8_t len; 641 uint16_t ch_ctr = 0; 642 for (num_APChanReport = 0; 643 num_APChanReport < 644 pBeaconReq->measurement_request.Beacon.num_APChannelReport; 645 num_APChanReport++) { 646 len = pBeaconReq->measurement_request.Beacon. 647 APChannelReport[num_APChanReport].num_channelList; 648 if (ch_ctr + len > 649 sizeof(pSmeBcnReportReq->channelList.channelNumber)) 650 break; 651 652 qdf_mem_copy(&ch_lst[ch_ctr], 653 pBeaconReq->measurement_request.Beacon. 654 APChannelReport[num_APChanReport]. 655 channelList, len); 656 657 ch_ctr += len; 658 } 659 } 660 /* Send request to SME. */ 661 mmhMsg.type = eWNI_SME_BEACON_REPORT_REQ_IND; 662 mmhMsg.bodyptr = pSmeBcnReportReq; 663 MTRACE(mac_trace(pMac, TRACE_CODE_TX_SME_MSG, 664 pSessionEntry->peSessionId, mmhMsg.type)); 665 if (eSIR_SUCCESS != lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT)) 666 return eRRM_FAILURE; 667 return eRRM_SUCCESS; 668 } 669 670 /* -------------------------------------------------------------------- */ 671 /** 672 * rrm_fill_beacon_ies 673 * 674 * FUNCTION: 675 * 676 * LOGIC: Fills Fixed fields and Ies in bss description to an array of uint8_t. 677 * 678 * ASSUMPTIONS: 679 * 680 * NOTE: 681 * 682 * @param pIes - pointer to the buffer that should be populated with ies. 683 * @param pNumIes - returns the num of ies filled in this param. 684 * @param pIesMaxSize - Max size of the buffer pIes. 685 * @param eids - pointer to array of eids. If NULL, all ies will be populated. 686 * @param numEids - number of elements in array eids. 687 * @param pBssDesc - pointer to Bss Description. 688 * @return None 689 */ 690 static void 691 rrm_fill_beacon_ies(tpAniSirGlobal pMac, 692 uint8_t *pIes, uint8_t *pNumIes, uint8_t pIesMaxSize, 693 uint8_t *eids, uint8_t numEids, tpSirBssDescription pBssDesc) 694 { 695 uint8_t len, *pBcnIes, count = 0, i; 696 uint8_t BcnNumIes; 697 698 if ((pIes == NULL) || (pNumIes == NULL) || (pBssDesc == NULL)) { 699 pe_err("Invalid parameters"); 700 return; 701 } 702 /* Make sure that if eid is null, numEids is set to zero. */ 703 numEids = (eids == NULL) ? 0 : numEids; 704 705 pBcnIes = (uint8_t *) &pBssDesc->ieFields[0]; 706 BcnNumIes = (uint8_t) GET_IE_LEN_IN_BSS(pBssDesc->length); 707 708 *pNumIes = 0; 709 710 *((uint32_t *) pIes) = pBssDesc->timeStamp[0]; 711 *pNumIes += sizeof(uint32_t); 712 pIes += sizeof(uint32_t); 713 *((uint32_t *) pIes) = pBssDesc->timeStamp[1]; 714 *pNumIes += sizeof(uint32_t); 715 pIes += sizeof(uint32_t); 716 *((uint16_t *) pIes) = pBssDesc->beaconInterval; 717 *pNumIes += sizeof(uint16_t); 718 pIes += sizeof(uint16_t); 719 *((uint16_t *) pIes) = pBssDesc->capabilityInfo; 720 *pNumIes += sizeof(uint16_t); 721 pIes += sizeof(uint16_t); 722 723 while (BcnNumIes > 0) { 724 len = *(pBcnIes + 1) + 2; /* element id + length. */ 725 pe_debug("EID = %d, len = %d total = %d", 726 *pBcnIes, *(pBcnIes + 1), len); 727 728 i = 0; 729 do { 730 if (((eids == NULL) || (*pBcnIes == eids[i])) && 731 ((*pNumIes) + len) < pIesMaxSize) { 732 pe_debug("Adding Eid %d, len=%d", 733 *pBcnIes, len); 734 735 qdf_mem_copy(pIes, pBcnIes, len); 736 pIes += len; 737 *pNumIes += len; 738 count++; 739 break; 740 } 741 i++; 742 } while (i < numEids); 743 744 pBcnIes += len; 745 BcnNumIes -= len; 746 } 747 pe_debug("Total length of Ies added = %d", *pNumIes); 748 } 749 750 /** 751 * rrm_process_beacon_report_xmit() - create a rrm action frame 752 * @mac_ctx: Global pointer to MAC context 753 * @beacon_xmit_ind: Data for beacon report IE from SME. 754 * 755 * Create a Radio measurement report action frame and send it to peer. 756 * 757 * Return: tSirRetStatus 758 */ 759 tSirRetStatus 760 rrm_process_beacon_report_xmit(tpAniSirGlobal mac_ctx, 761 tpSirBeaconReportXmitInd beacon_xmit_ind) 762 { 763 tSirRetStatus status = eSIR_SUCCESS; 764 tSirMacRadioMeasureReport *report = NULL; 765 tSirMacBeaconReport *beacon_report; 766 tpSirBssDescription bss_desc; 767 tpRRMReq curr_req = mac_ctx->rrm.rrmPEContext.pCurrentReq; 768 tpPESession session_entry; 769 uint8_t session_id, counter; 770 uint8_t bss_desc_count = 0; 771 772 pe_debug("Received beacon report xmit indication"); 773 774 if (NULL == beacon_xmit_ind) { 775 pe_err("Received beacon_xmit_ind is NULL in PE"); 776 return eSIR_FAILURE; 777 } 778 779 if (NULL == curr_req) { 780 pe_err("Received report xmit while there is no request pending in PE"); 781 status = eSIR_FAILURE; 782 goto end; 783 } 784 785 if ((beacon_xmit_ind->numBssDesc) || curr_req->sendEmptyBcnRpt) { 786 beacon_xmit_ind->numBssDesc = (beacon_xmit_ind->numBssDesc == 787 RRM_BCN_RPT_NO_BSS_INFO) ? RRM_BCN_RPT_MIN_RPT : 788 beacon_xmit_ind->numBssDesc; 789 790 session_entry = pe_find_session_by_bssid(mac_ctx, 791 beacon_xmit_ind->bssId, &session_id); 792 if (NULL == session_entry) { 793 pe_err("session does not exist for given bssId"); 794 status = eSIR_FAILURE; 795 goto end; 796 } 797 798 report = qdf_mem_malloc(beacon_xmit_ind->numBssDesc * 799 sizeof(*report)); 800 801 if (NULL == report) { 802 pe_err("RRM Report is NULL, allocation failed"); 803 status = eSIR_MEM_ALLOC_FAILED; 804 goto end; 805 } 806 807 for (bss_desc_count = 0; bss_desc_count < 808 beacon_xmit_ind->numBssDesc; bss_desc_count++) { 809 beacon_report = 810 &report[bss_desc_count].report.beaconReport; 811 /* 812 * If the scan result is NULL then send report request 813 * with option subelement as NULL. 814 */ 815 bss_desc = beacon_xmit_ind-> 816 pBssDescription[bss_desc_count]; 817 /* Prepare the beacon report and send it to the peer.*/ 818 report[bss_desc_count].token = 819 beacon_xmit_ind->uDialogToken; 820 report[bss_desc_count].refused = 0; 821 report[bss_desc_count].incapable = 0; 822 report[bss_desc_count].type = SIR_MAC_RRM_BEACON_TYPE; 823 824 /* 825 * Valid response is included if the size of 826 * becon xmit is == size of beacon xmit ind + ies 827 */ 828 if (beacon_xmit_ind->length < sizeof(*beacon_xmit_ind)) 829 continue; 830 beacon_report->regClass = beacon_xmit_ind->regClass; 831 if (bss_desc) { 832 beacon_report->channel = bss_desc->channelId; 833 qdf_mem_copy(beacon_report->measStartTime, 834 bss_desc->startTSF, 835 sizeof(bss_desc->startTSF)); 836 beacon_report->measDuration = 837 SYS_MS_TO_TU(beacon_xmit_ind->duration); 838 beacon_report->phyType = bss_desc->nwType; 839 beacon_report->bcnProbeRsp = 1; 840 beacon_report->rsni = bss_desc->sinr; 841 beacon_report->rcpi = bss_desc->rssi; 842 beacon_report->antennaId = 0; 843 beacon_report->parentTSF = bss_desc->parentTSF; 844 qdf_mem_copy(beacon_report->bssid, 845 bss_desc->bssId, sizeof(tSirMacAddr)); 846 } 847 848 switch (curr_req->request.Beacon.reportingDetail) { 849 case BEACON_REPORTING_DETAIL_NO_FF_IE: 850 /* 0: No need to include any elements. */ 851 pe_debug("No reporting detail requested"); 852 break; 853 case BEACON_REPORTING_DETAIL_ALL_FF_REQ_IE: 854 /* 1: Include all FFs and Requested Ies. */ 855 pe_debug("Only requested IEs in reporting detail requested"); 856 857 if (bss_desc) { 858 rrm_fill_beacon_ies(mac_ctx, 859 (uint8_t *) &beacon_report->Ies[0], 860 (uint8_t *) &beacon_report->numIes, 861 BEACON_REPORT_MAX_IES, 862 curr_req->request.Beacon.reqIes. 863 pElementIds, 864 curr_req->request.Beacon.reqIes.num, 865 bss_desc); 866 } 867 break; 868 case BEACON_REPORTING_DETAIL_ALL_FF_IE: 869 /* 2: default - Include all FFs and all Ies. */ 870 default: 871 pe_debug("Default all IEs and FFs"); 872 if (bss_desc) { 873 rrm_fill_beacon_ies(mac_ctx, 874 (uint8_t *) &beacon_report->Ies[0], 875 (uint8_t *) &beacon_report->numIes, 876 BEACON_REPORT_MAX_IES, 877 NULL, 878 0, 879 bss_desc); 880 } 881 break; 882 } 883 } 884 pe_info("Sending Action frame with %d bss info", 885 bss_desc_count); 886 lim_send_radio_measure_report_action_frame(mac_ctx, 887 curr_req->dialog_token, bss_desc_count, report, 888 beacon_xmit_ind->bssId, session_entry); 889 890 curr_req->sendEmptyBcnRpt = false; 891 } 892 893 end: 894 for (counter = 0; counter < beacon_xmit_ind->numBssDesc; counter++) 895 qdf_mem_free(beacon_xmit_ind->pBssDescription[counter]); 896 897 if (beacon_xmit_ind->fMeasureDone) { 898 pe_debug("Measurement done....cleanup the context"); 899 rrm_cleanup(mac_ctx); 900 } 901 902 if (NULL != report) 903 qdf_mem_free(report); 904 905 return status; 906 } 907 908 static void rrm_process_beacon_request_failure(tpAniSirGlobal pMac, 909 tpPESession pSessionEntry, 910 tSirMacAddr peer, 911 tRrmRetStatus status) 912 { 913 tpSirMacRadioMeasureReport pReport = NULL; 914 tpRRMReq pCurrentReq = pMac->rrm.rrmPEContext.pCurrentReq; 915 916 pReport = qdf_mem_malloc(sizeof(tSirMacRadioMeasureReport)); 917 if (NULL == pReport) { 918 pe_err("Unable to allocate memory during RRM Req processing"); 919 return; 920 } 921 pReport->token = pCurrentReq->token; 922 pReport->type = SIR_MAC_RRM_BEACON_TYPE; 923 924 pe_debug("status %d token %d", status, pReport->token); 925 926 switch (status) { 927 case eRRM_REFUSED: 928 pReport->refused = 1; 929 break; 930 case eRRM_INCAPABLE: 931 pReport->incapable = 1; 932 break; 933 default: 934 pe_err("Beacon request processing failed no report sent with status %d", 935 status); 936 qdf_mem_free(pReport); 937 return; 938 } 939 940 lim_send_radio_measure_report_action_frame(pMac, pCurrentReq->dialog_token, 1, 941 pReport, peer, pSessionEntry); 942 943 qdf_mem_free(pReport); 944 return; 945 } 946 947 /** 948 * rrm_process_beacon_req() - Update curr_req and report 949 * @mac_ctx: Global pointer to MAC context 950 * @peer: Macaddress of the peer requesting the radio measurement 951 * @session_entry: session entry 952 * @curr_req: Pointer to RRM request 953 * @report: Pointer to radio measurement report 954 * @rrm_req: Array of Measurement request IEs 955 * @num_report: No.of reports 956 * @index: Index for Measurement request 957 * 958 * Update structure sRRMReq and sSirMacRadioMeasureReport and pass it to 959 * rrm_process_beacon_report_req(). 960 * 961 * Return: tSirRetStatus 962 */ 963 static 964 tSirRetStatus rrm_process_beacon_req(tpAniSirGlobal mac_ctx, tSirMacAddr peer, 965 tpPESession session_entry, tpRRMReq curr_req, 966 tpSirMacRadioMeasureReport report, 967 tDot11fRadioMeasurementRequest *rrm_req, 968 uint8_t *num_report, int index) 969 { 970 tRrmRetStatus rrm_status = eRRM_SUCCESS; 971 972 if (curr_req) { 973 if (report == NULL) { 974 /* 975 * Allocate memory to send reports for 976 * any subsequent requests. 977 */ 978 report = qdf_mem_malloc(sizeof(*report) * 979 (rrm_req->num_MeasurementRequest - index)); 980 if (NULL == report) { 981 pe_err("Unable to allocate memory during RRM Req processing"); 982 return eSIR_MEM_ALLOC_FAILED; 983 } 984 pe_debug("rrm beacon type refused of %d report in beacon table", 985 *num_report); 986 } 987 report[*num_report].refused = 1; 988 report[*num_report].type = SIR_MAC_RRM_BEACON_TYPE; 989 report[*num_report].token = 990 rrm_req->MeasurementRequest[index].measurement_token; 991 (*num_report)++; 992 return eSIR_SUCCESS; 993 } else { 994 curr_req = qdf_mem_malloc(sizeof(*curr_req)); 995 if (NULL == curr_req) { 996 pe_err("Unable to allocate memory during RRM Req processing"); 997 qdf_mem_free(report); 998 return eSIR_MEM_ALLOC_FAILED; 999 } 1000 pe_debug("Processing Beacon Report request"); 1001 curr_req->dialog_token = rrm_req->DialogToken.token; 1002 curr_req->token = rrm_req-> 1003 MeasurementRequest[index].measurement_token; 1004 curr_req->sendEmptyBcnRpt = true; 1005 mac_ctx->rrm.rrmPEContext.pCurrentReq = curr_req; 1006 rrm_status = rrm_process_beacon_report_req(mac_ctx, curr_req, 1007 &rrm_req->MeasurementRequest[index], session_entry); 1008 if (eRRM_SUCCESS != rrm_status) { 1009 rrm_process_beacon_request_failure(mac_ctx, 1010 session_entry, peer, rrm_status); 1011 rrm_cleanup(mac_ctx); 1012 } 1013 } 1014 return eSIR_SUCCESS; 1015 } 1016 1017 /** 1018 * update_rrm_report() - Set incapable bit 1019 * @mac_ctx: Global pointer to MAC context 1020 * @report: Pointer to radio measurement report 1021 * @rrm_req: Array of Measurement request IEs 1022 * @num_report: No.of reports 1023 * @index: Index for Measurement request 1024 * 1025 * Send a report with incapabale bit set 1026 * 1027 * Return: tSirRetStatus 1028 */ 1029 static 1030 tSirRetStatus update_rrm_report(tpAniSirGlobal mac_ctx, 1031 tpSirMacRadioMeasureReport report, 1032 tDot11fRadioMeasurementRequest *rrm_req, 1033 uint8_t *num_report, int index) 1034 { 1035 if (report == NULL) { 1036 /* 1037 * Allocate memory to send reports for 1038 * any subsequent requests. 1039 */ 1040 report = qdf_mem_malloc(sizeof(*report) * 1041 (rrm_req->num_MeasurementRequest - index)); 1042 if (NULL == report) { 1043 pe_err("Unable to allocate memory during RRM Req processing"); 1044 return eSIR_MEM_ALLOC_FAILED; 1045 } 1046 pe_debug("rrm beacon type incapable of %d report", 1047 *num_report); 1048 } 1049 report[*num_report].incapable = 1; 1050 report[*num_report].type = 1051 rrm_req->MeasurementRequest[index].measurement_type; 1052 report[*num_report].token = 1053 rrm_req->MeasurementRequest[index].measurement_token; 1054 (*num_report)++; 1055 return eSIR_SUCCESS; 1056 } 1057 1058 /* -------------------------------------------------------------------- */ 1059 /** 1060 * rrm_process_radio_measurement_request - Process rrm request 1061 * @mac_ctx: Global pointer to MAC context 1062 * @peer: Macaddress of the peer requesting the radio measurement. 1063 * @rrm_req: Array of Measurement request IEs 1064 * @session_entry: session entry. 1065 * 1066 * Processes the Radio Resource Measurement request. 1067 * 1068 * Return: tSirRetStatus 1069 */ 1070 tSirRetStatus 1071 rrm_process_radio_measurement_request(tpAniSirGlobal mac_ctx, 1072 tSirMacAddr peer, 1073 tDot11fRadioMeasurementRequest *rrm_req, 1074 tpPESession session_entry) 1075 { 1076 uint8_t i; 1077 tSirRetStatus status = eSIR_SUCCESS; 1078 tpSirMacRadioMeasureReport report = NULL; 1079 uint8_t num_report = 0; 1080 tpRRMReq curr_req = mac_ctx->rrm.rrmPEContext.pCurrentReq; 1081 1082 if (!rrm_req->num_MeasurementRequest) { 1083 report = qdf_mem_malloc(sizeof(tSirMacRadioMeasureReport)); 1084 if (NULL == report) { 1085 pe_err("Unable to allocate memory during RRM Req processing"); 1086 return eSIR_MEM_ALLOC_FAILED; 1087 } 1088 pe_err("No requestIes in the measurement request, sending incapable report"); 1089 report->incapable = 1; 1090 num_report = 1; 1091 lim_send_radio_measure_report_action_frame(mac_ctx, 1092 rrm_req->DialogToken.token, num_report, report, peer, 1093 session_entry); 1094 qdf_mem_free(report); 1095 return eSIR_FAILURE; 1096 } 1097 /* PF Fix */ 1098 if (rrm_req->NumOfRepetitions.repetitions > 0) { 1099 pe_info("number of repetitions %d", 1100 rrm_req->NumOfRepetitions.repetitions); 1101 /* 1102 * Send a report with incapable bit set. 1103 * Not supporting repetitions. 1104 */ 1105 report = qdf_mem_malloc(sizeof(tSirMacRadioMeasureReport)); 1106 if (NULL == report) { 1107 pe_err("Unable to allocate memory during RRM Req processing"); 1108 return eSIR_MEM_ALLOC_FAILED; 1109 } 1110 report->incapable = 1; 1111 report->type = rrm_req->MeasurementRequest[0].measurement_type; 1112 num_report = 1; 1113 goto end; 1114 } 1115 1116 for (i = 0; i < rrm_req->num_MeasurementRequest; i++) { 1117 switch (rrm_req->MeasurementRequest[i].measurement_type) { 1118 case SIR_MAC_RRM_BEACON_TYPE: 1119 /* Process beacon request. */ 1120 status = rrm_process_beacon_req(mac_ctx, peer, 1121 session_entry, curr_req, report, rrm_req, 1122 &num_report, i); 1123 if (eSIR_SUCCESS != status) 1124 return status; 1125 break; 1126 case SIR_MAC_RRM_LCI_TYPE: 1127 case SIR_MAC_RRM_LOCATION_CIVIC_TYPE: 1128 case SIR_MAC_RRM_FINE_TIME_MEAS_TYPE: 1129 pe_debug("RRM with type: %d sent to userspace", 1130 rrm_req->MeasurementRequest[i].measurement_type); 1131 break; 1132 default: 1133 /* Send a report with incapabale bit set. */ 1134 status = update_rrm_report(mac_ctx, report, rrm_req, 1135 &num_report, i); 1136 if (eSIR_SUCCESS != status) 1137 return status; 1138 break; 1139 } 1140 } 1141 1142 end: 1143 if (report) { 1144 lim_send_radio_measure_report_action_frame(mac_ctx, 1145 rrm_req->DialogToken.token, num_report, report, 1146 peer, session_entry); 1147 qdf_mem_free(report); 1148 } 1149 return status; 1150 } 1151 1152 /* -------------------------------------------------------------------- */ 1153 /** 1154 * rrm_update_start_tsf 1155 ** 1156 * FUNCTION: Store start TSF of measurement. 1157 * 1158 * LOGIC: 1159 * 1160 * ASSUMPTIONS: 1161 * 1162 * NOTE: 1163 * 1164 * @param startTSF - TSF value at the start of measurement. 1165 * @return None 1166 */ 1167 void rrm_update_start_tsf(tpAniSirGlobal pMac, uint32_t startTSF[2]) 1168 { 1169 pMac->rrm.rrmPEContext.startTSF[0] = startTSF[0]; 1170 pMac->rrm.rrmPEContext.startTSF[1] = startTSF[1]; 1171 } 1172 1173 /* -------------------------------------------------------------------- */ 1174 /** 1175 * rrm_get_start_tsf 1176 * 1177 * FUNCTION: Get the Start TSF. 1178 * 1179 * LOGIC: 1180 * 1181 * ASSUMPTIONS: 1182 * 1183 * NOTE: 1184 * 1185 * @param startTSF - store star TSF in this buffer. 1186 * @return txPower 1187 */ 1188 void rrm_get_start_tsf(tpAniSirGlobal pMac, uint32_t *pStartTSF) 1189 { 1190 pStartTSF[0] = pMac->rrm.rrmPEContext.startTSF[0]; 1191 pStartTSF[1] = pMac->rrm.rrmPEContext.startTSF[1]; 1192 1193 } 1194 1195 /* -------------------------------------------------------------------- */ 1196 /** 1197 * rrm_get_capabilities 1198 * 1199 * FUNCTION: 1200 * Returns a pointer to tpRRMCaps with all the caps enabled in RRM 1201 * 1202 * LOGIC: 1203 * 1204 * ASSUMPTIONS: 1205 * 1206 * NOTE: 1207 * 1208 * @param pSessionEntry 1209 * @return pointer to tRRMCaps 1210 */ 1211 tpRRMCaps rrm_get_capabilities(tpAniSirGlobal pMac, tpPESession pSessionEntry) 1212 { 1213 return &pMac->rrm.rrmPEContext.rrmEnabledCaps; 1214 } 1215 1216 /* -------------------------------------------------------------------- */ 1217 /** 1218 * rrm_initialize 1219 * 1220 * FUNCTION: 1221 * Initialize RRM module 1222 * 1223 * LOGIC: 1224 * 1225 * ASSUMPTIONS: 1226 * 1227 * NOTE: 1228 * 1229 * @return None 1230 */ 1231 1232 tSirRetStatus rrm_initialize(tpAniSirGlobal pMac) 1233 { 1234 tpRRMCaps pRRMCaps = &pMac->rrm.rrmPEContext.rrmEnabledCaps; 1235 1236 pMac->rrm.rrmPEContext.pCurrentReq = NULL; 1237 pMac->rrm.rrmPEContext.txMgmtPower = 0; 1238 pMac->rrm.rrmPEContext.DialogToken = 0; 1239 1240 pMac->rrm.rrmPEContext.rrmEnable = 0; 1241 1242 qdf_mem_set(pRRMCaps, sizeof(tRRMCaps), 0); 1243 pRRMCaps->LinkMeasurement = 1; 1244 pRRMCaps->NeighborRpt = 1; 1245 pRRMCaps->BeaconPassive = 1; 1246 pRRMCaps->BeaconActive = 1; 1247 pRRMCaps->BeaconTable = 1; 1248 pRRMCaps->APChanReport = 1; 1249 pRRMCaps->fine_time_meas_rpt = 1; 1250 pRRMCaps->lci_capability = 1; 1251 1252 pRRMCaps->operatingChanMax = 3; 1253 pRRMCaps->nonOperatingChanMax = 3; 1254 1255 return eSIR_SUCCESS; 1256 } 1257 1258 /* -------------------------------------------------------------------- */ 1259 /** 1260 * rrm_cleanup 1261 * 1262 * FUNCTION: 1263 * cleanup RRM module 1264 * 1265 * LOGIC: 1266 * 1267 * ASSUMPTIONS: 1268 * 1269 * NOTE: 1270 * 1271 * @param mode 1272 * @param rate 1273 * @return None 1274 */ 1275 1276 tSirRetStatus rrm_cleanup(tpAniSirGlobal pMac) 1277 { 1278 if (pMac->rrm.rrmPEContext.pCurrentReq) { 1279 if (pMac->rrm.rrmPEContext.pCurrentReq->request.Beacon.reqIes. 1280 pElementIds) { 1281 qdf_mem_free(pMac->rrm.rrmPEContext.pCurrentReq-> 1282 request.Beacon.reqIes.pElementIds); 1283 } 1284 1285 qdf_mem_free(pMac->rrm.rrmPEContext.pCurrentReq); 1286 } 1287 1288 pMac->rrm.rrmPEContext.pCurrentReq = NULL; 1289 return eSIR_SUCCESS; 1290 } 1291 1292 /** 1293 * lim_update_rrm_capability() - Update PE context's rrm capability 1294 * @mac_ctx: Global pointer to MAC context 1295 * @join_req: Pointer to SME join request. 1296 * 1297 * Update PE context's rrm capability based on SME join request. 1298 * 1299 * Return: None 1300 */ 1301 void lim_update_rrm_capability(tpAniSirGlobal mac_ctx, 1302 tpSirSmeJoinReq join_req) 1303 { 1304 mac_ctx->rrm.rrmPEContext.rrmEnable = join_req->rrm_config.rrm_enabled; 1305 qdf_mem_copy(&mac_ctx->rrm.rrmPEContext.rrmEnabledCaps, 1306 &join_req->rrm_config.rm_capability, 1307 RMENABLEDCAP_MAX_LEN); 1308 1309 return; 1310 } 1311