1 /* 2 * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /**========================================================================= 21 22 \file rrm_api.c 23 24 \brief implementation for PE RRM APIs 25 26 ========================================================================*/ 27 28 /* $Header$ */ 29 30 31 /*-------------------------------------------------------------------------- 32 Include Files 33 ------------------------------------------------------------------------*/ 34 #include "cds_api.h" 35 #include "wni_api.h" 36 #include "sir_api.h" 37 #include "ani_global.h" 38 #include "wni_cfg.h" 39 #include "lim_types.h" 40 #include "lim_utils.h" 41 #include "lim_send_sme_rsp_messages.h" 42 #include "parser_api.h" 43 #include "lim_send_messages.h" 44 #include "rrm_global.h" 45 #include "rrm_api.h" 46 #include "wlan_lmac_if_def.h" 47 #include "wlan_reg_services_api.h" 48 #include "wlan_cp_stats_utils_api.h" 49 #include "../../core/src/wlan_cp_stats_obj_mgr_handler.h" 50 #include "../../core/src/wlan_cp_stats_defs.h" 51 #include "cdp_txrx_host_stats.h" 52 #include "utils_mlo.h" 53 #include "wlan_mlo_mgr_sta.h" 54 #include <wlan_policy_mgr_ll_sap.h> 55 56 #define MAX_CTRL_STAT_VDEV_ENTRIES 1 57 #define MAX_CTRL_STAT_MAC_ADDR_ENTRIES 1 58 #define MAX_RMM_STA_STATS_REQUESTED 2 59 #define MIN_MEAS_DURATION_FOR_STA_STATS 10 60 61 /* Max passive scan dwell for wide band rrm scan, in milliseconds */ 62 #define RRM_SCAN_MAX_DWELL_TIME 110 63 64 /* -------------------------------------------------------------------- */ 65 /** 66 * rrm_cache_mgmt_tx_power 67 ** 68 * FUNCTION: Store Tx power for management frames. 69 * 70 * LOGIC: 71 * 72 * ASSUMPTIONS: 73 * 74 * NOTE: 75 * 76 * @param pe_session session entry. 77 * @return None 78 */ 79 void 80 rrm_cache_mgmt_tx_power(struct mac_context *mac, int8_t txPower, 81 struct pe_session *pe_session) 82 { 83 pe_debug("Cache Mgmt Tx Power: %d", txPower); 84 85 if (!pe_session) 86 mac->rrm.rrmPEContext.txMgmtPower = txPower; 87 else 88 pe_session->txMgmtPower = txPower; 89 } 90 91 /* -------------------------------------------------------------------- */ 92 /** 93 * rrm_get_mgmt_tx_power 94 * 95 * FUNCTION: Get the Tx power for management frames. 96 * 97 * LOGIC: 98 * 99 * ASSUMPTIONS: 100 * 101 * NOTE: 102 * 103 * @param pe_session session entry. 104 * @return txPower 105 */ 106 int8_t rrm_get_mgmt_tx_power(struct mac_context *mac, struct pe_session *pe_session) 107 { 108 if (!pe_session) 109 return mac->rrm.rrmPEContext.txMgmtPower; 110 111 pe_debug("tx mgmt pwr %d", pe_session->txMgmtPower); 112 113 return pe_session->txMgmtPower; 114 } 115 116 /* -------------------------------------------------------------------- */ 117 /** 118 * rrm_send_set_max_tx_power_req 119 * 120 * FUNCTION: Send WMA_SET_MAX_TX_POWER_REQ message to change the max tx power. 121 * 122 * LOGIC: 123 * 124 * ASSUMPTIONS: 125 * 126 * NOTE: 127 * 128 * @param txPower txPower to be set. 129 * @param pe_session session entry. 130 * @return None 131 */ 132 QDF_STATUS 133 rrm_send_set_max_tx_power_req(struct mac_context *mac, int8_t txPower, 134 struct pe_session *pe_session) 135 { 136 tpMaxTxPowerParams pMaxTxParams; 137 QDF_STATUS retCode = QDF_STATUS_SUCCESS; 138 struct scheduler_msg msgQ = {0}; 139 140 if (!pe_session) { 141 pe_err("Invalid parameters"); 142 return QDF_STATUS_E_FAILURE; 143 } 144 pMaxTxParams = qdf_mem_malloc(sizeof(tMaxTxPowerParams)); 145 if (!pMaxTxParams) 146 return QDF_STATUS_E_NOMEM; 147 /* Allocated memory for pMaxTxParams...will be freed in other module */ 148 pMaxTxParams->power = txPower; 149 qdf_mem_copy(pMaxTxParams->bssId.bytes, pe_session->bssId, 150 QDF_MAC_ADDR_SIZE); 151 qdf_mem_copy(pMaxTxParams->selfStaMacAddr.bytes, 152 pe_session->self_mac_addr, 153 QDF_MAC_ADDR_SIZE); 154 155 msgQ.type = WMA_SET_MAX_TX_POWER_REQ; 156 msgQ.reserved = 0; 157 msgQ.bodyptr = pMaxTxParams; 158 msgQ.bodyval = 0; 159 160 pe_debug("Sending WMA_SET_MAX_TX_POWER_REQ with power(%d) to HAL", 161 txPower); 162 163 MTRACE(mac_trace_msg_tx(mac, pe_session->peSessionId, msgQ.type)); 164 retCode = wma_post_ctrl_msg(mac, &msgQ); 165 if (QDF_STATUS_SUCCESS != retCode) { 166 pe_err("Posting WMA_SET_MAX_TX_POWER_REQ to HAL failed, reason=%X", 167 retCode); 168 qdf_mem_free(pMaxTxParams); 169 return retCode; 170 } 171 return retCode; 172 } 173 174 /* -------------------------------------------------------------------- */ 175 /** 176 * rrm_set_max_tx_power_rsp 177 * 178 * FUNCTION: Process WMA_SET_MAX_TX_POWER_RSP message. 179 * 180 * LOGIC: 181 * 182 * ASSUMPTIONS: 183 * 184 * NOTE: 185 * 186 * @param txPower txPower to be set. 187 * @param pe_session session entry. 188 * @return None 189 */ 190 QDF_STATUS rrm_set_max_tx_power_rsp(struct mac_context *mac, 191 struct scheduler_msg *limMsgQ) 192 { 193 QDF_STATUS retCode = QDF_STATUS_SUCCESS; 194 tpMaxTxPowerParams pMaxTxParams = (tpMaxTxPowerParams) limMsgQ->bodyptr; 195 struct pe_session *pe_session; 196 uint8_t sessionId, i; 197 198 if (qdf_is_macaddr_broadcast(&pMaxTxParams->bssId)) { 199 for (i = 0; i < mac->lim.maxBssId; i++) { 200 if (mac->lim.gpSession[i].valid == true) { 201 pe_session = &mac->lim.gpSession[i]; 202 rrm_cache_mgmt_tx_power(mac, pMaxTxParams->power, 203 pe_session); 204 } 205 } 206 } else { 207 pe_session = pe_find_session_by_bssid(mac, 208 pMaxTxParams->bssId.bytes, 209 &sessionId); 210 if (!pe_session) { 211 retCode = QDF_STATUS_E_FAILURE; 212 } else { 213 rrm_cache_mgmt_tx_power(mac, pMaxTxParams->power, 214 pe_session); 215 } 216 } 217 218 qdf_mem_free(limMsgQ->bodyptr); 219 limMsgQ->bodyptr = NULL; 220 return retCode; 221 } 222 223 /** 224 * rrm_calculate_and_fill_rcpi() - calculates and fills RCPI value 225 * @rcpi: pointer to hold calculated RCPI value 226 * @cur_rssi: value of current RSSI 227 * 228 * @return None 229 */ 230 static void rrm_calculate_and_fill_rcpi(uint8_t *rcpi, int8_t cur_rssi) 231 { 232 /* 2008 11k spec reference: 18.4.8.5 RCPI Measurement */ 233 if (cur_rssi <= RCPI_LOW_RSSI_VALUE) 234 *rcpi = 0; 235 else if ((cur_rssi > RCPI_LOW_RSSI_VALUE) && (cur_rssi <= 0)) 236 *rcpi = CALCULATE_RCPI(cur_rssi); 237 else 238 *rcpi = RCPI_MAX_VALUE; 239 } 240 241 /* -------------------------------------------------------------------- */ 242 /** 243 * rrm_process_link_measurement_request 244 * 245 * FUNCTION: Processes the Link measurement request and send the report. 246 * 247 * LOGIC: 248 * 249 * ASSUMPTIONS: 250 * 251 * NOTE: 252 * 253 * @param pBd pointer to BD to extract RSSI and SNR 254 * @param pLinkReq pointer to the Link request frame structure. 255 * @param pe_session session entry. 256 * @return None 257 */ 258 QDF_STATUS 259 rrm_process_link_measurement_request(struct mac_context *mac, 260 uint8_t *pRxPacketInfo, 261 tDot11fLinkMeasurementRequest *pLinkReq, 262 struct pe_session *pe_session) 263 { 264 tSirMacLinkReport LinkReport = {0}; 265 tpSirMacMgmtHdr pHdr; 266 int8_t currentRSSI = 0; 267 struct vdev_mlme_obj *mlme_obj; 268 struct wlan_lmac_if_reg_tx_ops *tx_ops; 269 uint8_t ap_pwr_constraint = 0; 270 271 pe_debug("Received Link measurement request"); 272 273 if (!pRxPacketInfo || !pLinkReq || !pe_session) { 274 pe_err("Invalid parameters - Ignoring the request"); 275 return QDF_STATUS_E_FAILURE; 276 } 277 pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); 278 279 mlme_obj = wlan_vdev_mlme_get_cmpt_obj(pe_session->vdev); 280 if (!mlme_obj) { 281 pe_err("vdev component object is NULL"); 282 return QDF_STATUS_E_INVAL; 283 } 284 285 /* 286 * STA LPI + SAP VLP is supported. For this STA should operate in VLP 287 * power level of the SAP. 288 * If STA is operating in VLP power of SAP, do not update STA power. 289 */ 290 if (wlan_reg_is_ext_tpc_supported(mac->psoc) && 291 !pe_session->sta_follows_sap_power) { 292 ap_pwr_constraint = mlme_obj->reg_tpc_obj.ap_constraint_power; 293 mlme_obj->reg_tpc_obj.ap_constraint_power = 294 pLinkReq->MaxTxPower.maxTxPower; 295 /* Set is_power_constraint_abs to true to calculate tpc power */ 296 mlme_obj->reg_tpc_obj.is_power_constraint_abs = true; 297 lim_calculate_tpc(mac, pe_session); 298 299 LinkReport.txPower = 300 mlme_obj->reg_tpc_obj.chan_power_info[0].tx_power; 301 /** If hardware limit received from FW is non zero, use it 302 * to limit the link tx power. 303 */ 304 if (mlme_obj->mgmt.generic.tx_pwrlimit) { 305 LinkReport.txPower = 306 QDF_MIN(LinkReport.txPower, 307 mlme_obj->mgmt.generic.tx_pwrlimit); 308 pe_debug("HW power limit: %d, Link tx power: %d", 309 mlme_obj->mgmt.generic.tx_pwrlimit, 310 LinkReport.txPower); 311 } 312 if (LinkReport.txPower < MIN_TX_PWR_CAP) 313 LinkReport.txPower = MIN_TX_PWR_CAP; 314 else if (LinkReport.txPower > MAX_TX_PWR_CAP) 315 LinkReport.txPower = MAX_TX_PWR_CAP; 316 317 if (pLinkReq->MaxTxPower.maxTxPower != ap_pwr_constraint) { 318 tx_ops = wlan_reg_get_tx_ops(mac->psoc); 319 320 if (tx_ops->set_tpc_power) 321 tx_ops->set_tpc_power(mac->psoc, 322 pe_session->vdev_id, 323 &mlme_obj->reg_tpc_obj); 324 } 325 } else if (!pe_session->sta_follows_sap_power) { 326 mlme_obj->reg_tpc_obj.reg_max[0] = 327 pe_session->def_max_tx_pwr; 328 mlme_obj->reg_tpc_obj.ap_constraint_power = 329 pLinkReq->MaxTxPower.maxTxPower; 330 331 LinkReport.txPower = lim_get_max_tx_power(mac, mlme_obj); 332 333 /** If firmware updated max tx power is non zero, respond to 334 * rrm link measurement request with min of firmware updated 335 * ap tx power and max power derived from lim_get_max_tx_power 336 * API. 337 */ 338 if (mlme_obj && mlme_obj->mgmt.generic.tx_pwrlimit) 339 LinkReport.txPower = QDF_MIN(LinkReport.txPower, 340 mlme_obj->mgmt.generic.tx_pwrlimit); 341 342 if ((LinkReport.txPower != (uint8_t)pe_session->maxTxPower) && 343 (QDF_STATUS_SUCCESS == 344 rrm_send_set_max_tx_power_req(mac, LinkReport.txPower, 345 pe_session))) { 346 pe_warn("Local: %d", pe_session->maxTxPower); 347 pe_session->maxTxPower = LinkReport.txPower; 348 } 349 } 350 pe_warn_rl("Link Request Tx Pwr: %d Link Report Tx Pwr: %d", 351 pLinkReq->MaxTxPower.maxTxPower, LinkReport.txPower); 352 353 LinkReport.dialogToken = pLinkReq->DialogToken.token; 354 LinkReport.rxAntenna = 0; 355 LinkReport.txAntenna = 0; 356 currentRSSI = WMA_GET_RX_RSSI_RAW(pRxPacketInfo); 357 358 pe_info_rl("Received Link report frame with %d", currentRSSI); 359 360 rrm_calculate_and_fill_rcpi(&LinkReport.rcpi, currentRSSI); 361 LinkReport.rsni = WMA_GET_RX_SNR(pRxPacketInfo); 362 363 pe_debug("Sending Link report frame"); 364 365 return lim_send_link_report_action_frame(mac, &LinkReport, pHdr->sa, 366 pe_session); 367 } 368 369 /* -------------------------------------------------------------------- */ 370 /** 371 * rrm_process_neighbor_report_response 372 * 373 * FUNCTION: Processes the Neighbor Report response from the peer AP. 374 * 375 * LOGIC: 376 * 377 * ASSUMPTIONS: 378 * 379 * NOTE: 380 * 381 * @param pNeighborRep pointer to the Neighbor report frame structure. 382 * @param pe_session session entry. 383 * @return None 384 */ 385 QDF_STATUS 386 rrm_process_neighbor_report_response(struct mac_context *mac, 387 tDot11fNeighborReportResponse *pNeighborRep, 388 struct pe_session *pe_session) 389 { 390 QDF_STATUS status = QDF_STATUS_SUCCESS; 391 tpSirNeighborReportInd pSmeNeighborRpt = NULL; 392 uint16_t length; 393 uint8_t i; 394 struct scheduler_msg mmhMsg = {0}; 395 396 if (!pNeighborRep || !pe_session) { 397 pe_err("Invalid parameters"); 398 return status; 399 } 400 401 pe_debug("Neighbor report response received"); 402 403 /* Dialog token */ 404 if (mac->rrm.rrmPEContext.DialogToken != 405 pNeighborRep->DialogToken.token) { 406 pe_err("Dialog token mismatch in the received Neighbor report"); 407 return QDF_STATUS_E_FAILURE; 408 } 409 if (pNeighborRep->num_NeighborReport == 0) { 410 pe_err("No neighbor report in the frame...Dropping it"); 411 return QDF_STATUS_E_FAILURE; 412 } 413 pe_debug("RRM:received num neighbor reports: %d", 414 pNeighborRep->num_NeighborReport); 415 if (pNeighborRep->num_NeighborReport > MAX_SUPPORTED_NEIGHBOR_RPT) 416 pNeighborRep->num_NeighborReport = MAX_SUPPORTED_NEIGHBOR_RPT; 417 length = (sizeof(tSirNeighborReportInd)) + 418 (sizeof(tSirNeighborBssDescription) * 419 (pNeighborRep->num_NeighborReport - 1)); 420 421 /* Prepare the request to send to SME. */ 422 pSmeNeighborRpt = qdf_mem_malloc(length); 423 if (!pSmeNeighborRpt) 424 return QDF_STATUS_E_NOMEM; 425 426 /* Allocated memory for pSmeNeighborRpt...will be freed by other module */ 427 428 for (i = 0; i < pNeighborRep->num_NeighborReport; i++) { 429 pSmeNeighborRpt->sNeighborBssDescription[i].length = sizeof(tSirNeighborBssDescription); /*+ any optional ies */ 430 qdf_mem_copy(pSmeNeighborRpt->sNeighborBssDescription[i].bssId, 431 pNeighborRep->NeighborReport[i].bssid, 432 sizeof(tSirMacAddr)); 433 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo. 434 fApPreauthReachable = 435 pNeighborRep->NeighborReport[i].APReachability; 436 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo. 437 fSameSecurityMode = 438 pNeighborRep->NeighborReport[i].Security; 439 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo. 440 fSameAuthenticator = 441 pNeighborRep->NeighborReport[i].KeyScope; 442 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo. 443 fCapSpectrumMeasurement = 444 pNeighborRep->NeighborReport[i].SpecMgmtCap; 445 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo. 446 fCapQos = pNeighborRep->NeighborReport[i].QosCap; 447 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo. 448 fCapApsd = pNeighborRep->NeighborReport[i].apsd; 449 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo. 450 fCapRadioMeasurement = pNeighborRep->NeighborReport[i].rrm; 451 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo. 452 fCapDelayedBlockAck = 453 pNeighborRep->NeighborReport[i].DelayedBA; 454 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo. 455 fCapImmediateBlockAck = 456 pNeighborRep->NeighborReport[i].ImmBA; 457 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo. 458 fMobilityDomain = 459 pNeighborRep->NeighborReport[i].MobilityDomain; 460 461 if (!wlan_reg_is_6ghz_supported(mac->psoc) && 462 (wlan_reg_is_6ghz_op_class(mac->pdev, 463 pNeighborRep->NeighborReport[i]. 464 regulatoryClass))) { 465 pe_err("channel belongs to 6 ghz spectrum, abort"); 466 qdf_mem_free(pSmeNeighborRpt); 467 return QDF_STATUS_E_FAILURE; 468 } 469 470 pSmeNeighborRpt->sNeighborBssDescription[i].regClass = 471 pNeighborRep->NeighborReport[i].regulatoryClass; 472 pSmeNeighborRpt->sNeighborBssDescription[i].channel = 473 pNeighborRep->NeighborReport[i].channel; 474 pSmeNeighborRpt->sNeighborBssDescription[i].phyType = 475 pNeighborRep->NeighborReport[i].PhyType; 476 } 477 478 pSmeNeighborRpt->messageType = eWNI_SME_NEIGHBOR_REPORT_IND; 479 pSmeNeighborRpt->length = length; 480 pSmeNeighborRpt->measurement_idx = DEFAULT_RRM_IDX; 481 pSmeNeighborRpt->sessionId = pe_session->smeSessionId; 482 pSmeNeighborRpt->numNeighborReports = pNeighborRep->num_NeighborReport; 483 qdf_mem_copy(pSmeNeighborRpt->bssId, pe_session->bssId, 484 sizeof(tSirMacAddr)); 485 486 /* Send request to SME. */ 487 mmhMsg.type = pSmeNeighborRpt->messageType; 488 mmhMsg.bodyptr = pSmeNeighborRpt; 489 MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG, 490 pe_session->peSessionId, mmhMsg.type)); 491 lim_sys_process_mmh_msg_api(mac, &mmhMsg); 492 493 return status; 494 495 } 496 497 /* -------------------------------------------------------------------- */ 498 /** 499 * rrm_process_neighbor_report_req 500 * 501 * FUNCTION: 502 * 503 * LOGIC: Create a Neighbor report request and send it to peer. 504 * 505 * ASSUMPTIONS: 506 * 507 * NOTE: 508 * 509 * @param pNeighborReq Neighbor report request params . 510 * @return None 511 */ 512 QDF_STATUS 513 rrm_process_neighbor_report_req(struct mac_context *mac, 514 tpSirNeighborReportReqInd pNeighborReq) 515 { 516 QDF_STATUS status = QDF_STATUS_SUCCESS; 517 tSirMacNeighborReportReq NeighborReportReq; 518 struct pe_session *pe_session; 519 uint8_t sessionId; 520 521 if (!pNeighborReq) { 522 pe_err("NeighborReq is NULL"); 523 return QDF_STATUS_E_FAILURE; 524 } 525 pe_session = pe_find_session_by_bssid(mac, pNeighborReq->bssId, 526 &sessionId); 527 if (!pe_session) { 528 pe_err("session does not exist for given bssId"); 529 return QDF_STATUS_E_FAILURE; 530 } 531 532 pe_debug("SSID present: %d", pNeighborReq->noSSID); 533 534 qdf_mem_zero(&NeighborReportReq, sizeof(tSirMacNeighborReportReq)); 535 536 NeighborReportReq.dialogToken = ++mac->rrm.rrmPEContext.DialogToken; 537 NeighborReportReq.ssid_present = !pNeighborReq->noSSID; 538 if (NeighborReportReq.ssid_present) { 539 qdf_mem_copy(&NeighborReportReq.ssid, &pNeighborReq->ucSSID, 540 sizeof(tSirMacSSid)); 541 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, 542 QDF_TRACE_LEVEL_DEBUG, 543 (uint8_t *) NeighborReportReq.ssid.ssId, 544 NeighborReportReq.ssid.length); 545 } 546 547 status = 548 lim_send_neighbor_report_request_frame(mac, &NeighborReportReq, 549 pNeighborReq->bssId, 550 pe_session); 551 552 return status; 553 } 554 555 void rrm_get_country_code_from_connected_profile(struct mac_context *mac, 556 uint8_t vdev_id, 557 uint8_t *country_code) 558 { 559 QDF_STATUS status; 560 561 status = wlan_cm_get_country_code(mac->pdev, vdev_id, country_code); 562 563 pe_debug("Country info from bcn:%c%c 0x%x", country_code[0], 564 country_code[1], country_code[2]); 565 566 if (QDF_IS_STATUS_ERROR(status)) 567 qdf_mem_zero(country_code, REG_ALPHA2_LEN + 1); 568 569 if (!country_code[0]) { 570 wlan_reg_read_current_country(mac->psoc, country_code); 571 country_code[2] = OP_CLASS_GLOBAL; 572 pe_debug("Current country info %c%c 0x%x", country_code[0], 573 country_code[1], country_code[2]); 574 } 575 } 576 577 #ifdef CONNECTIVITY_DIAG_EVENT 578 /** 579 * wlan_diag_log_beacon_rpt_req_event() - Send Beacon Report Request logging 580 * event. 581 * @token: Dialog token 582 * @mode: Measurement mode 583 * @op_class: operating class 584 * @chan: channel number 585 * @req_mode: Request mode 586 * @duration: The duration over which the Beacon report was measured 587 * @pe_session: pe session pointer 588 */ 589 static void 590 wlan_diag_log_beacon_rpt_req_event(uint8_t token, uint8_t mode, 591 uint8_t op_class, uint8_t chan, 592 uint8_t req_mode, uint32_t duration, 593 struct pe_session *pe_session) 594 { 595 WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, struct wlan_diag_bcn_rpt); 596 597 qdf_mem_zero(&wlan_diag_event, sizeof(wlan_diag_event)); 598 599 wlan_diag_event.diag_cmn.vdev_id = wlan_vdev_get_id(pe_session->vdev); 600 wlan_diag_event.diag_cmn.timestamp_us = qdf_get_time_of_the_day_us(); 601 wlan_diag_event.diag_cmn.ktime_us = qdf_ktime_to_us(qdf_ktime_get()); 602 603 wlan_diag_event.subtype = WLAN_CONN_DIAG_BCN_RPT_REQ_EVENT; 604 wlan_diag_event.version = DIAG_BCN_RPT_VERSION_2; 605 606 if (mlo_is_mld_sta(pe_session->vdev)) 607 wlan_diag_event.band = 608 wlan_convert_freq_to_diag_band(pe_session->curr_op_freq); 609 610 wlan_diag_event.meas_token = token; 611 wlan_diag_event.mode = mode; 612 wlan_diag_event.op_class = op_class; 613 wlan_diag_event.chan = chan; 614 wlan_diag_event.duration = duration; 615 wlan_diag_event.req_mode = req_mode; 616 617 WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_BCN_RPT); 618 } 619 #else 620 static void 621 wlan_diag_log_beacon_rpt_req_event(uint8_t token, uint8_t mode, 622 uint8_t op_class, uint8_t chan, 623 uint8_t req_mode, uint32_t duration, 624 struct pe_session *pe_session) 625 { 626 } 627 #endif 628 629 #define ABS(x) ((x < 0) ? -x : x) 630 631 #ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS 632 /** 633 * rrm_update_mac_cp_stats: update stats of rrm structure of mac 634 * @ev: cp stats event 635 * @mac_ctx: mac context 636 * 637 * Return: None 638 */ 639 static inline void 640 rrm_update_mac_cp_stats(struct infra_cp_stats_event *ev, 641 struct mac_context *mac_ctx) 642 { 643 tpSirMacRadioMeasureReport rrm_report; 644 struct counter_stats *counter_stats; 645 struct group_id_0 ev_counter_stats; 646 struct mac_stats *mac_stats; 647 struct group_id_1 ev_mac_stats; 648 649 rrm_report = &mac_ctx->rrm.rrmPEContext.rrm_sta_stats.rrm_report; 650 651 counter_stats = 652 &rrm_report->report.statistics_report.group_stats.counter_stats; 653 mac_stats = 654 &rrm_report->report.statistics_report.group_stats.mac_stats; 655 656 ev_counter_stats = ev->sta_stats->group.counter_stats; 657 ev_mac_stats = ev->sta_stats->group.mac_stats; 658 659 switch (rrm_report->report.statistics_report.group_id) { 660 /* 661 * Assign count diff in mac rrm sta stats report. 662 * For first event callback stats will be same as 663 * send by FW because memset is done for mac rrm sta 664 * stats before sending rrm sta stats request to FW and 665 * for second request stats will be the diff of stats send 666 * by FW and previous stats. 667 */ 668 case STA_STAT_GROUP_ID_COUNTER_STATS: 669 counter_stats->failed_count = 670 ev_counter_stats.failed_count - 671 counter_stats->failed_count; 672 counter_stats->group_received_frame_count = 673 ev_counter_stats.group_received_frame_count - 674 counter_stats->group_received_frame_count; 675 counter_stats->fcs_error_count = 676 ev_counter_stats.fcs_error_count - 677 counter_stats->fcs_error_count; 678 counter_stats->transmitted_frame_count = 679 ev_counter_stats.transmitted_frame_count - 680 counter_stats->transmitted_frame_count; 681 break; 682 case STA_STAT_GROUP_ID_MAC_STATS: 683 mac_stats->rts_success_count = 684 ev_mac_stats.rts_success_count - 685 mac_stats->rts_success_count; 686 mac_stats->rts_failure_count = 687 ev_mac_stats.rts_failure_count - 688 mac_stats->rts_failure_count; 689 mac_stats->ack_failure_count = 690 ev_mac_stats.ack_failure_count - 691 mac_stats->ack_failure_count; 692 break; 693 default: 694 pe_debug("group id not supported"); 695 } 696 pe_nofl_debug("counter stats: group rx frame count %d failed_count %d fcs_error %d tx frame count %d mac stats: rts success count %d rts fail count %d ack fail count %d", 697 counter_stats->group_received_frame_count, 698 counter_stats->failed_count, 699 counter_stats->fcs_error_count, 700 counter_stats->transmitted_frame_count, 701 mac_stats->rts_success_count, 702 mac_stats->rts_failure_count, 703 mac_stats->ack_failure_count); 704 } 705 706 /** 707 * rmm_sta_stats_response_cb: RRM sta stats response callback 708 * @ev: cp stats event 709 * @cookie: NULL 710 * 711 * Return: None 712 */ 713 static inline 714 void rmm_sta_stats_response_cb(struct infra_cp_stats_event *ev, void *cookie) 715 { 716 struct mac_context *mac; 717 struct pe_session *session; 718 uint8_t vdev_id, index; 719 QDF_STATUS status; 720 tpRRMReq pcurrent_req; 721 tSirMacRadioMeasureReport *rrm_report; 722 723 mac = cds_get_context(QDF_MODULE_ID_PE); 724 if (!mac) 725 return; 726 index = mac->rrm.rrmPEContext.rrm_sta_stats.index; 727 728 /* Deregister callback registered in request */ 729 status = wlan_cp_stats_infra_cp_deregister_resp_cb(mac->psoc); 730 if (QDF_IS_STATUS_ERROR(status)) 731 pe_err("failed to deregister callback %d", status); 732 733 pcurrent_req = mac->rrm.rrmPEContext.pCurrentReq[index]; 734 if (!pcurrent_req) { 735 pe_err("Current request is NULL"); 736 qdf_mem_zero(&mac->rrm.rrmPEContext.rrm_sta_stats, 737 sizeof(mac->rrm.rrmPEContext.rrm_sta_stats)); 738 return; 739 } 740 741 vdev_id = mac->rrm.rrmPEContext.rrm_sta_stats.vdev_id; 742 session = pe_find_session_by_vdev_id(mac, vdev_id); 743 if (!session) { 744 pe_err("Session does not exist for given vdev id %d", vdev_id); 745 rrm_cleanup(mac, mac->rrm.rrmPEContext.rrm_sta_stats.index); 746 return; 747 } 748 749 rrm_report = &mac->rrm.rrmPEContext.rrm_sta_stats.rrm_report; 750 rrm_update_mac_cp_stats(ev, mac); 751 752 /* Update resp counter for every response to find second resp*/ 753 mac->rrm.rrmPEContext.rrm_sta_stats.rrm_sta_stats_res_count++; 754 /* Send current stats if meas duration is 0. */ 755 if (mac->rrm.rrmPEContext.rrm_sta_stats.rrm_sta_stats_res_count == 756 MAX_RMM_STA_STATS_REQUESTED || 757 !rrm_report->report.statistics_report.meas_duration) { 758 lim_send_radio_measure_report_action_frame( 759 mac, pcurrent_req->dialog_token, 1, true, 760 &mac->rrm.rrmPEContext.rrm_sta_stats.rrm_report, 761 mac->rrm.rrmPEContext.rrm_sta_stats.peer, session); 762 763 rrm_cleanup(mac, index); 764 } 765 } 766 767 /** 768 * rrm_update_vdev_stats: Update RRM stats from DP 769 * @rrm_report: RRM Measurement Report 770 * @vdev_id: vdev_id 771 * 772 * Return: QDF STATUS 773 */ 774 static QDF_STATUS 775 rrm_update_vdev_stats(tpSirMacRadioMeasureReport rrm_report, uint8_t vdev_id) 776 { 777 struct cdp_vdev_stats *stats; 778 QDF_STATUS status; 779 struct counter_stats *counter_stats; 780 struct mac_stats *mac_stats; 781 782 counter_stats = 783 &rrm_report->report.statistics_report.group_stats.counter_stats; 784 mac_stats = 785 &rrm_report->report.statistics_report.group_stats.mac_stats; 786 787 stats = qdf_mem_malloc(sizeof(*stats)); 788 if (!stats) 789 return QDF_STATUS_E_NOMEM; 790 791 status = 792 cdp_host_get_vdev_stats(cds_get_context(QDF_MODULE_ID_SOC), 793 vdev_id, stats, true); 794 if (QDF_IS_STATUS_ERROR(status)) { 795 pe_err("Failed to get stats %d", status); 796 qdf_mem_free(stats); 797 return QDF_STATUS_E_FAILURE; 798 } 799 800 pe_nofl_debug("counter stats count: fragment (tx: %d rx: %d) group tx: %d mac stats count: retry : %d multiple retry: %d frame duplicate %d", 801 stats->tx.fragment_count, stats->rx.fragment_count, 802 stats->tx.mcast.num, stats->tx.retry_count, 803 stats->tx.multiple_retry_count, 804 stats->rx.duplicate_count); 805 806 switch (rrm_report->report.statistics_report.group_id) { 807 case STA_STAT_GROUP_ID_COUNTER_STATS: 808 counter_stats->transmitted_fragment_count = 809 stats->tx.fragment_count - 810 counter_stats->transmitted_fragment_count; 811 counter_stats->received_fragment_count = 812 stats->rx.fragment_count - 813 counter_stats->received_fragment_count; 814 counter_stats->group_transmitted_frame_count = 815 stats->tx.mcast.num - 816 counter_stats->group_transmitted_frame_count; 817 break; 818 case STA_STAT_GROUP_ID_MAC_STATS: 819 mac_stats->retry_count = 820 stats->tx.retry_count - mac_stats->retry_count; 821 mac_stats->multiple_retry_count = 822 stats->tx.multiple_retry_count - 823 mac_stats->multiple_retry_count; 824 mac_stats->frame_duplicate_count = 825 stats->rx.duplicate_count - 826 mac_stats->frame_duplicate_count; 827 break; 828 } 829 qdf_mem_free(stats); 830 831 return QDF_STATUS_SUCCESS; 832 } 833 834 QDF_STATUS 835 rrm_send_sta_stats_req(struct mac_context *mac, 836 struct pe_session *session, 837 tSirMacAddr peer_mac) 838 { 839 struct infra_cp_stats_cmd_info info = {0}; 840 get_infra_cp_stats_cb resp_cb = NULL; 841 void *context; 842 QDF_STATUS status; 843 tpSirMacRadioMeasureReport report; 844 845 status = wlan_cp_stats_infra_cp_get_context(mac->psoc, &resp_cb, 846 &context); 847 if (resp_cb) { 848 pe_err("another request already in progress"); 849 return QDF_STATUS_E_FAILURE; 850 } 851 852 info.request_cookie = NULL; 853 info.stats_id = TYPE_REQ_CTRL_PATH_RRM_STA_STAT; 854 info.action = ACTION_REQ_CTRL_PATH_STAT_GET; 855 info.infra_cp_stats_resp_cb = rmm_sta_stats_response_cb; 856 info.num_pdev_ids = 0; 857 info.num_vdev_ids = MAX_CTRL_STAT_VDEV_ENTRIES; 858 info.vdev_id[0] = wlan_vdev_get_id(session->vdev); 859 info.num_mac_addr_list = MAX_CTRL_STAT_MAC_ADDR_ENTRIES; 860 info.num_pdev_ids = 0; 861 /* 862 * FW doesn't send vdev id in response path. 863 * So, vdev id will be used to get session 864 * in callback. 865 */ 866 mac->rrm.rrmPEContext.rrm_sta_stats.vdev_id = 867 wlan_vdev_get_id(session->vdev); 868 qdf_mem_copy(&info.peer_mac_addr[0], peer_mac, QDF_MAC_ADDR_SIZE); 869 report = &mac->rrm.rrmPEContext.rrm_sta_stats.rrm_report; 870 871 status = rrm_update_vdev_stats(report, wlan_vdev_get_id(session->vdev)); 872 if (QDF_IS_STATUS_ERROR(status)) { 873 pe_err("Failed to register resp callback: %d", status); 874 return status; 875 } 876 877 status = wlan_cp_stats_infra_cp_register_resp_cb(mac->psoc, &info); 878 if (QDF_IS_STATUS_ERROR(status)) { 879 pe_err("Failed to register resp callback: %d", status); 880 return status; 881 } 882 883 status = wlan_cp_stats_send_infra_cp_req(mac->psoc, &info); 884 if (QDF_IS_STATUS_ERROR(status)) { 885 pe_err("Failed to send stats request status: %d", status); 886 goto get_stats_fail; 887 } 888 889 return QDF_STATUS_SUCCESS; 890 891 get_stats_fail: 892 status = wlan_cp_stats_infra_cp_deregister_resp_cb(mac->psoc); 893 if (QDF_IS_STATUS_ERROR(status)) 894 pe_err("failed to deregister callback %d", status); 895 return status; 896 } 897 #endif 898 899 /* -------------------------------------------------------------------- */ 900 /** 901 * rrm_get_max_meas_duration() - calculate max measurement duration for a 902 * rrm req 903 * @mac: global mac context 904 * @pe_session: per vdev pe context 905 * 906 * Return: max measurement duration 907 */ 908 static uint16_t rrm_get_max_meas_duration(struct mac_context *mac, 909 struct pe_session *pe_session) 910 { 911 int8_t max_dur; 912 uint16_t max_meas_dur, sign; 913 914 /* 915 * The logic here is to check the measurement duration passed in the 916 * beacon request. Following are the cases handled. 917 * Case 1: If measurement duration received in the beacon request is 918 * greater than the max measurement duration advertised in the RRM 919 * capabilities(Assoc Req), and Duration Mandatory bit is set to 1, 920 * REFUSE the beacon request. 921 * Case 2: If measurement duration received in the beacon request is 922 * greater than the max measurement duration advertised in the RRM 923 * capabilities(Assoc Req), and Duration Mandatory bit is set to 0, 924 * perform measurement for the duration advertised in the 925 * RRM capabilities 926 * maxMeasurementDuration = 2^(nonOperatingChanMax - 4) * BeaconInterval 927 */ 928 max_dur = mac->rrm.rrmPEContext.rrmEnabledCaps.nonOperatingChanMax - 4; 929 sign = (max_dur < 0) ? 1 : 0; 930 max_dur = (1L << ABS(max_dur)); 931 if (!sign) 932 max_meas_dur = 933 max_dur * pe_session->beaconParams.beaconInterval; 934 else 935 max_meas_dur = 936 pe_session->beaconParams.beaconInterval / max_dur; 937 938 return max_meas_dur; 939 } 940 941 /** 942 * rrm_process_sta_stats_report_req: Process RRM sta stats request 943 * @mac: mac context 944 * @pCurrentReq: Current RRM request 945 * @pStaStatsReq: RRM Measurement Request 946 * @pe_session: pe session 947 * 948 * Return: rrm status 949 */ 950 static tRrmRetStatus 951 rrm_process_sta_stats_report_req(struct mac_context *mac, 952 tpRRMReq pCurrentReq, 953 tDot11fIEMeasurementRequest *sta_stats_req, 954 struct pe_session *pe_session) 955 { 956 QDF_STATUS status; 957 uint16_t meas_duration = MIN_MEAS_DURATION_FOR_STA_STATS; 958 uint8_t max_meas_duration; 959 struct rrm_sta_stats *rrm_sta_statistics; 960 961 max_meas_duration = rrm_get_max_meas_duration(mac, pe_session); 962 963 /* 964 * Keep timer value atleast of 10 ms even if measurement duration 965 * provided in meas request is < 10 ms because FW takes some time to 966 * calculate and respond stats. 967 * Start timer of 10 ms even if meas duration is 0. 968 * To get stats from FW. 969 */ 970 if (sta_stats_req->measurement_request.sta_stats.meas_duration > 971 MIN_MEAS_DURATION_FOR_STA_STATS) 972 meas_duration = 973 sta_stats_req->measurement_request.sta_stats.meas_duration; 974 975 if (meas_duration > max_meas_duration) { 976 if (sta_stats_req->durationMandatory) { 977 pe_nofl_err("Dropping the req: duration mandatory & max duration > meas duration"); 978 return eRRM_REFUSED; 979 } 980 meas_duration = max_meas_duration; 981 } 982 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) 983 sta_stats_req->measurement_request.sta_stats.peer_mac_addr)) { 984 pe_err("Dropping req: broadcast address not supported"); 985 return eRRM_INCAPABLE; 986 } 987 988 rrm_sta_statistics = &mac->rrm.rrmPEContext.rrm_sta_stats; 989 990 rrm_sta_statistics->rrm_report.token = pCurrentReq->token; 991 rrm_sta_statistics->rrm_report.type = pCurrentReq->type; 992 rrm_sta_statistics->rrm_report.refused = 0; 993 rrm_sta_statistics->rrm_report.incapable = 0; 994 rrm_sta_statistics->rrm_report.report.statistics_report.group_id = 995 sta_stats_req->measurement_request.sta_stats.group_identity; 996 rrm_sta_statistics->rrm_report.report.statistics_report.meas_duration 997 = sta_stats_req->measurement_request.sta_stats.meas_duration; 998 999 switch (sta_stats_req->measurement_request.sta_stats.group_identity) { 1000 case STA_STAT_GROUP_ID_COUNTER_STATS: 1001 case STA_STAT_GROUP_ID_MAC_STATS: 1002 status = 1003 rrm_send_sta_stats_req( 1004 mac, pe_session, 1005 sta_stats_req->measurement_request.sta_stats.peer_mac_addr); 1006 if (!QDF_IS_STATUS_SUCCESS(status)) 1007 return eRRM_REFUSED; 1008 mac->lim.lim_timers.rrm_sta_stats_resp_timer.sessionId = 1009 pe_session->peSessionId; 1010 tx_timer_change(&mac->lim.lim_timers.rrm_sta_stats_resp_timer, 1011 SYS_MS_TO_TICKS(meas_duration), 0); 1012 /* Activate sta stats resp timer */ 1013 if (tx_timer_activate( 1014 &mac->lim.lim_timers.rrm_sta_stats_resp_timer) != 1015 TX_SUCCESS) { 1016 pe_err("failed to start sta stats timer"); 1017 return eRRM_REFUSED; 1018 } 1019 break; 1020 case STA_STAT_GROUP_ID_DELAY_STATS: 1021 /* TODO: update access delay from scan IE */ 1022 default: 1023 pe_nofl_err("group id %d not supported", 1024 sta_stats_req->measurement_request.sta_stats.group_identity); 1025 return eRRM_INCAPABLE; 1026 } 1027 return eRRM_SUCCESS; 1028 } 1029 1030 void 1031 rrm_process_rrm_sta_stats_request_failure(struct mac_context *mac, 1032 struct pe_session *pe_session, 1033 tSirMacAddr peer, 1034 tRrmRetStatus status, uint8_t index) 1035 { 1036 tpSirMacRadioMeasureReport p_report = NULL; 1037 tpRRMReq p_current_req = mac->rrm.rrmPEContext.pCurrentReq[index]; 1038 1039 if (!p_current_req) { 1040 pe_err("Current request is NULL"); 1041 return; 1042 } 1043 1044 p_report = qdf_mem_malloc(sizeof(tSirMacRadioMeasureReport)); 1045 if (!p_report) 1046 return; 1047 p_report->token = p_current_req->token; 1048 p_report->type = SIR_MAC_RRM_STA_STATISTICS_TYPE; 1049 1050 pe_debug("Measurement index:%d status %d token %d", index, status, 1051 p_report->token); 1052 1053 switch (status) { 1054 case eRRM_FAILURE: /* fallthrough */ 1055 case eRRM_REFUSED: 1056 p_report->refused = 1; 1057 break; 1058 case eRRM_INCAPABLE: 1059 p_report->incapable = 1; 1060 break; 1061 default: 1062 pe_err("Invalid RRM status, failed to send report"); 1063 qdf_mem_free(p_report); 1064 return; 1065 } 1066 1067 lim_send_radio_measure_report_action_frame(mac, 1068 p_current_req->dialog_token, 1069 1, true, 1070 p_report, peer, 1071 pe_session); 1072 1073 qdf_mem_free(p_report); 1074 } 1075 1076 /** 1077 * rrm_check_other_sta_sats_req_in_progress: To check if any other sta stats req 1078 * in progress 1079 * @rrm_req: measurement request 1080 * 1081 * To avoid any conflict between multiple sta stats request at time of callback 1082 * response from FW handle one sta stats request at a time. 1083 * 1084 * Return: true/false 1085 */ 1086 static bool 1087 rrm_check_other_sta_sats_req_in_progress( 1088 tDot11fRadioMeasurementRequest *rrm_req) 1089 { 1090 uint8_t count = 0, i = 0; 1091 1092 for (i = 0; i < MAX_MEASUREMENT_REQUEST; i++) { 1093 if (rrm_req->MeasurementRequest[i].measurement_type == 1094 SIR_MAC_RRM_STA_STATISTICS_TYPE) 1095 count++; 1096 if (count > 1) 1097 return true; 1098 } 1099 return false; 1100 } 1101 1102 /** 1103 * rrm_process_sta_stats_req: Process RRM sta stats request 1104 * @mac: mac context 1105 * @session_entry: pe session 1106 * @radiomes_report: measurement report 1107 * @rrm_req: measurement request 1108 * @num_report: no of reports 1109 * @index: index of request 1110 * 1111 * Return: QDF_STATUS 1112 */ 1113 static 1114 QDF_STATUS rrm_process_sta_stats_req( 1115 struct mac_context *mac, tSirMacAddr peer, 1116 struct pe_session *session_entry, 1117 tpSirMacRadioMeasureReport *radiomes_report, 1118 tDot11fRadioMeasurementRequest *rrm_req, 1119 uint8_t *num_report, int index) 1120 { 1121 tRrmRetStatus rrm_status = eRRM_SUCCESS; 1122 tpRRMReq curr_req; 1123 QDF_STATUS status = QDF_STATUS_SUCCESS; 1124 1125 if (index >= MAX_MEASUREMENT_REQUEST) { 1126 status = rrm_reject_req(radiomes_report, 1127 rrm_req, num_report, index, 1128 rrm_req->MeasurementRequest[0]. 1129 measurement_type); 1130 return status; 1131 } 1132 1133 if (rrm_check_other_sta_sats_req_in_progress(rrm_req)) { 1134 pe_debug("another sta stats request already in progress"); 1135 return QDF_STATUS_E_FAILURE; 1136 } 1137 1138 curr_req = qdf_mem_malloc(sizeof(*curr_req)); 1139 if (!curr_req) { 1140 mac->rrm.rrmPEContext.pCurrentReq[index] = NULL; 1141 qdf_mem_zero(&mac->rrm.rrmPEContext.rrm_sta_stats, 1142 sizeof(mac->rrm.rrmPEContext.rrm_sta_stats)); 1143 return QDF_STATUS_E_NOMEM; 1144 } 1145 1146 curr_req->dialog_token = rrm_req->DialogToken.token; 1147 curr_req->token = 1148 rrm_req->MeasurementRequest[index].measurement_token; 1149 curr_req->measurement_idx = index; 1150 curr_req->type = rrm_req->MeasurementRequest[index].measurement_type; 1151 1152 1153 qdf_mem_set(&mac->rrm.rrmPEContext.rrm_sta_stats, 1154 sizeof(mac->rrm.rrmPEContext.rrm_sta_stats), 0); 1155 1156 mac->rrm.rrmPEContext.rrm_sta_stats.index = index; 1157 mac->rrm.rrmPEContext.pCurrentReq[index] = curr_req; 1158 mac->rrm.rrmPEContext.num_active_request++; 1159 qdf_mem_copy(mac->rrm.rrmPEContext.rrm_sta_stats.peer, 1160 peer, 1161 QDF_MAC_ADDR_SIZE); 1162 1163 pe_debug("Processing sta stats Report req %d num_active_req:%d", 1164 index, mac->rrm.rrmPEContext.num_active_request); 1165 1166 rrm_status = rrm_process_sta_stats_report_req(mac, curr_req, 1167 &rrm_req->MeasurementRequest[index], session_entry); 1168 if (eRRM_SUCCESS != rrm_status) 1169 goto failure; 1170 1171 return QDF_STATUS_SUCCESS; 1172 failure: 1173 rrm_process_rrm_sta_stats_request_failure( 1174 mac, session_entry, peer, rrm_status, index); 1175 1176 rrm_cleanup(mac, index); 1177 return QDF_STATUS_E_FAILURE; 1178 } 1179 1180 /** 1181 * rrm_process_beacon_report_req 1182 * 1183 * FUNCTION: Processes the Beacon report request from the peer AP. 1184 * 1185 * LOGIC: 1186 * 1187 * ASSUMPTIONS: 1188 * 1189 * NOTE: 1190 * 1191 * @param pCurrentReq pointer to the current Req comtext. 1192 * @param pBeaconReq pointer to the beacon report request IE from the peer. 1193 * @param pe_session session entry. 1194 * @return None 1195 */ 1196 static tRrmRetStatus 1197 rrm_process_beacon_report_req(struct mac_context *mac, 1198 tpRRMReq pCurrentReq, 1199 tDot11fIEMeasurementRequest *pBeaconReq, 1200 struct pe_session *pe_session) 1201 { 1202 struct scheduler_msg mmh_msg = {0}; 1203 tpSirBeaconReportReqInd psbrr; 1204 uint8_t num_rpt, idx_rpt; 1205 uint16_t measDuration, maxMeasduration; 1206 tDot11fIEAPChannelReport *ie_ap_chan_rpt; 1207 uint8_t tmp_idx, buf_left, buf_cons; 1208 uint16_t ch_ctr = 0; 1209 char ch_buf[RRM_CH_BUF_LEN]; 1210 char *tmp_buf = NULL; 1211 uint8_t country[WNI_CFG_COUNTRY_CODE_LEN]; 1212 uint8_t req_mode; 1213 uint8_t i; 1214 1215 if (!pe_session) { 1216 pe_err("pe_session is NULL"); 1217 return eRRM_INCAPABLE; 1218 } 1219 1220 if (wlan_policy_mgr_get_ll_lt_sap_vdev_id(mac->psoc) != WLAN_INVALID_VDEV_ID) { 1221 pe_debug("RX: [802.11 BCN_RPT] reject req as ll_lt_sap is present"); 1222 return eRRM_REFUSED; 1223 } 1224 1225 if (pBeaconReq->measurement_request.Beacon.rrm_reporting.present && 1226 (pBeaconReq->measurement_request.Beacon.rrm_reporting.reporting_condition != 0)) { 1227 /* Repeated measurement is not supported. This means number of repetitions should be zero.(Already checked) */ 1228 /* All test case in VoWifi(as of version 0.36) use zero for number of repetitions. */ 1229 /* Beacon reporting should not be included in request if number of repetitons is zero. */ 1230 /* IEEE Std 802.11k-2008 Table 7-29g and section 11.10.8.1 */ 1231 1232 pe_nofl_err("RX: [802.11 BCN_RPT] Dropping req: Reporting condition included is not zero"); 1233 return eRRM_INCAPABLE; 1234 } 1235 1236 maxMeasduration = rrm_get_max_meas_duration(mac, pe_session); 1237 if( pBeaconReq->measurement_request.Beacon.meas_mode == 1238 eSIR_PASSIVE_SCAN) 1239 maxMeasduration += 10; 1240 1241 measDuration = pBeaconReq->measurement_request.Beacon.meas_duration; 1242 1243 pe_nofl_rl_info("RX: [802.11 BCN_RPT] seq:%d SSID:" QDF_SSID_FMT " BSSID:" QDF_MAC_ADDR_FMT " Token:%d op_class:%d ch:%d meas_mode:%d meas_duration:%d max_meas_dur: %d", 1244 mac->rrm.rrmPEContext.prev_rrm_report_seq_num, 1245 QDF_SSID_REF( 1246 pBeaconReq->measurement_request.Beacon.SSID.num_ssid, 1247 pBeaconReq->measurement_request.Beacon.SSID.ssid), 1248 QDF_MAC_ADDR_REF( 1249 pBeaconReq->measurement_request.Beacon.BSSID), 1250 pBeaconReq->measurement_token, 1251 pBeaconReq->measurement_request.Beacon.regClass, 1252 pBeaconReq->measurement_request.Beacon.channel, 1253 pBeaconReq->measurement_request.Beacon.meas_mode, 1254 measDuration, maxMeasduration); 1255 1256 req_mode = (pBeaconReq->parallel << 0) | (pBeaconReq->enable << 1) | 1257 (pBeaconReq->request << 2) | (pBeaconReq->report << 3) | 1258 (pBeaconReq->durationMandatory << 4); 1259 1260 wlan_diag_log_beacon_rpt_req_event(pBeaconReq->measurement_token, 1261 pBeaconReq->measurement_request.Beacon.meas_mode, 1262 pBeaconReq->measurement_request.Beacon.regClass, 1263 pBeaconReq->measurement_request.Beacon.channel, 1264 req_mode, measDuration, pe_session); 1265 1266 if (measDuration == 0 && 1267 pBeaconReq->measurement_request.Beacon.meas_mode != 1268 eSIR_BEACON_TABLE) { 1269 pe_nofl_err("RX: [802.11 BCN_RPT] Invalid measurement duration"); 1270 return eRRM_REFUSED; 1271 } 1272 1273 if (maxMeasduration < measDuration) { 1274 if (pBeaconReq->durationMandatory) { 1275 pe_nofl_err("RX: [802.11 BCN_RPT] Dropping the req: duration mandatory & maxduration > measduration"); 1276 return eRRM_REFUSED; 1277 } 1278 measDuration = maxMeasduration; 1279 } 1280 1281 pe_debug("measurement duration %d", measDuration); 1282 1283 /* Cache the data required for sending report. */ 1284 pCurrentReq->request.Beacon.reportingDetail = 1285 pBeaconReq->measurement_request.Beacon.BcnReportingDetail. 1286 present ? pBeaconReq->measurement_request.Beacon.BcnReportingDetail. 1287 reportingDetail : BEACON_REPORTING_DETAIL_ALL_FF_IE; 1288 1289 if (pBeaconReq->measurement_request.Beacon. 1290 last_beacon_report_indication.present) { 1291 pCurrentReq->request.Beacon.last_beacon_report_indication = 1292 pBeaconReq->measurement_request.Beacon. 1293 last_beacon_report_indication.last_fragment; 1294 pe_debug("RX: [802.11 BCN_RPT] Last Bcn Report in the req: %d", 1295 pCurrentReq->request.Beacon.last_beacon_report_indication); 1296 } else { 1297 pCurrentReq->request.Beacon.last_beacon_report_indication = 0; 1298 pe_debug("RX: [802.11 BCN_RPT] Last Bcn rpt ind not present"); 1299 } 1300 1301 if (pBeaconReq->measurement_request.Beacon.RequestedInfo.present) { 1302 if (!pBeaconReq->measurement_request.Beacon.RequestedInfo. 1303 num_requested_eids) { 1304 pe_debug("RX: [802.11 BCN_RPT]: Requested num of EID is 0"); 1305 return eRRM_FAILURE; 1306 } 1307 pCurrentReq->request.Beacon.reqIes.pElementIds = 1308 qdf_mem_malloc(sizeof(uint8_t) * 1309 pBeaconReq->measurement_request.Beacon. 1310 RequestedInfo.num_requested_eids); 1311 if (!pCurrentReq->request.Beacon.reqIes.pElementIds) 1312 return eRRM_FAILURE; 1313 1314 pCurrentReq->request.Beacon.reqIes.num = 1315 pBeaconReq->measurement_request.Beacon.RequestedInfo. 1316 num_requested_eids; 1317 qdf_mem_copy(pCurrentReq->request.Beacon.reqIes.pElementIds, 1318 pBeaconReq->measurement_request.Beacon. 1319 RequestedInfo.requested_eids, 1320 pCurrentReq->request.Beacon.reqIes.num); 1321 for (i = 0; i < pCurrentReq->request.Beacon.reqIes.num; i++) 1322 pe_debug("RX: [802.11 BCN_RPT]:Requested EID is %d", 1323 pBeaconReq->measurement_request.Beacon.RequestedInfo.requested_eids[i]); 1324 } 1325 1326 if (pBeaconReq->measurement_request.Beacon.ExtRequestedInfo.present) { 1327 if (!pBeaconReq->measurement_request.Beacon.ExtRequestedInfo.num_req_element_id_ext) { 1328 pe_err("RX: [802.11 BCN_RPT]: Requested num of Extn EID is 0"); 1329 return eRRM_FAILURE; 1330 } 1331 if (pBeaconReq->measurement_request.Beacon.ExtRequestedInfo.req_element_id != 1332 WLAN_ELEMID_EXTN_ELEM) { 1333 pe_err("RX: [802.11 BCN_RPT]: Extn Element ID is not 0xFF"); 1334 return eRRM_FAILURE; 1335 } 1336 1337 pCurrentReq->request.Beacon.reqIes.ext_info.eid = 1338 pBeaconReq->measurement_request.Beacon.ExtRequestedInfo.req_element_id; 1339 pCurrentReq->request.Beacon.reqIes.ext_info.num_eid_ext = 1340 pBeaconReq->measurement_request.Beacon.ExtRequestedInfo.num_req_element_id_ext; 1341 qdf_mem_copy(pCurrentReq->request.Beacon.reqIes.ext_info.eid_ext, 1342 pBeaconReq->measurement_request.Beacon.ExtRequestedInfo.req_element_id_ext, 1343 pCurrentReq->request.Beacon.reqIes.ext_info.num_eid_ext); 1344 pe_debug("RX: [802.11 BCN_RPT]: EID is %d", 1345 pCurrentReq->request.Beacon.reqIes.ext_info.eid); 1346 pe_debug("RX: [802.11 BCN_RPT]:Num of Extn EID is %d", 1347 pCurrentReq->request.Beacon.reqIes.ext_info.num_eid_ext); 1348 for (i = 0; i < pCurrentReq->request.Beacon.reqIes.ext_info.num_eid_ext; i++) 1349 pe_debug("RX: [802.11 BCN_RPT]:Requested Extn EID is %d", 1350 pBeaconReq->measurement_request.Beacon.ExtRequestedInfo.req_element_id_ext[i]); 1351 } 1352 1353 /* Prepare the request to send to SME. */ 1354 psbrr = qdf_mem_malloc(sizeof(tSirBeaconReportReqInd)); 1355 if (!psbrr) 1356 return eRRM_FAILURE; 1357 1358 /* Alloc memory for pSmeBcnReportReq, will be freed by other modules */ 1359 qdf_mem_copy(psbrr->bssId, pe_session->bssId, 1360 sizeof(tSirMacAddr)); 1361 psbrr->messageType = eWNI_SME_BEACON_REPORT_REQ_IND; 1362 psbrr->length = sizeof(tSirBeaconReportReqInd); 1363 psbrr->uDialogToken = pBeaconReq->measurement_token; 1364 psbrr->msgSource = eRRM_MSG_SOURCE_11K; 1365 psbrr->randomizationInterval = 1366 SYS_TU_TO_MS(pBeaconReq->measurement_request.Beacon.randomization); 1367 psbrr->measurement_idx = pCurrentReq->measurement_idx; 1368 1369 if (!wlan_reg_is_6ghz_supported(mac->psoc) && 1370 (wlan_reg_is_6ghz_op_class(mac->pdev, 1371 pBeaconReq->measurement_request.Beacon.regClass))) { 1372 pe_nofl_err("RX: [802.11 BCN_RPT] Ch belongs to 6 ghz spectrum, abort"); 1373 qdf_mem_free(psbrr); 1374 return eRRM_FAILURE; 1375 } 1376 1377 rrm_get_country_code_from_connected_profile(mac, pe_session->vdev_id, 1378 country); 1379 psbrr->channel_info.chan_num = 1380 pBeaconReq->measurement_request.Beacon.channel; 1381 psbrr->channel_info.reg_class = 1382 pBeaconReq->measurement_request.Beacon.regClass; 1383 if (psbrr->channel_info.chan_num && 1384 psbrr->channel_info.chan_num != 255) { 1385 psbrr->channel_info.chan_freq = 1386 wlan_reg_country_chan_opclass_to_freq( 1387 mac->pdev, 1388 country, 1389 psbrr->channel_info.chan_num, 1390 psbrr->channel_info.reg_class, 1391 false); 1392 if (!psbrr->channel_info.chan_freq) { 1393 pe_debug("invalid ch freq, chan_num %d", 1394 psbrr->channel_info.chan_num); 1395 qdf_mem_free(psbrr); 1396 return eRRM_FAILURE; 1397 } 1398 } else { 1399 psbrr->channel_info.chan_freq = 0; 1400 } 1401 sme_debug("opclass %d, ch %d freq %d AP's country code %c%c 0x%x index:%d", 1402 psbrr->channel_info.reg_class, 1403 psbrr->channel_info.chan_num, 1404 psbrr->channel_info.chan_freq, 1405 country[0], country[1], country[2], 1406 psbrr->measurement_idx); 1407 1408 psbrr->measurementDuration[0] = measDuration; 1409 psbrr->fMeasurementtype[0] = 1410 pBeaconReq->measurement_request.Beacon.meas_mode; 1411 qdf_mem_copy(psbrr->macaddrBssid, 1412 pBeaconReq->measurement_request.Beacon.BSSID, 1413 sizeof(tSirMacAddr)); 1414 1415 if (pBeaconReq->measurement_request.Beacon.SSID.present) { 1416 psbrr->ssId.length = 1417 pBeaconReq->measurement_request.Beacon.SSID.num_ssid; 1418 qdf_mem_copy(psbrr->ssId.ssId, 1419 pBeaconReq->measurement_request.Beacon.SSID.ssid, 1420 psbrr->ssId.length); 1421 } 1422 1423 pCurrentReq->token = pBeaconReq->measurement_token; 1424 1425 num_rpt = pBeaconReq->measurement_request.Beacon.num_APChannelReport; 1426 for (idx_rpt = 0; idx_rpt < num_rpt; idx_rpt++) { 1427 ie_ap_chan_rpt = 1428 &pBeaconReq->measurement_request.Beacon.APChannelReport[idx_rpt]; 1429 for (tmp_idx = 0; 1430 tmp_idx < ie_ap_chan_rpt->num_channelList; 1431 tmp_idx++) { 1432 if (!wlan_reg_is_6ghz_supported(mac->psoc) && 1433 (wlan_reg_is_6ghz_op_class(mac->pdev, 1434 ie_ap_chan_rpt->regulatoryClass))) { 1435 pe_nofl_err("RX: [802.11 BCN_RPT] Ch belongs to 6 ghz spectrum, abort"); 1436 qdf_mem_free(psbrr); 1437 return eRRM_FAILURE; 1438 } 1439 1440 psbrr->channel_list.chan_freq_lst[ch_ctr++] = 1441 wlan_reg_country_chan_opclass_to_freq( 1442 mac->pdev, country, 1443 ie_ap_chan_rpt->channelList[tmp_idx], 1444 ie_ap_chan_rpt->regulatoryClass, true); 1445 1446 if (ch_ctr >= QDF_ARRAY_SIZE(psbrr->channel_list.chan_freq_lst)) 1447 break; 1448 } 1449 if (ch_ctr >= QDF_ARRAY_SIZE(psbrr->channel_list.chan_freq_lst)) 1450 break; 1451 } 1452 1453 psbrr->channel_list.num_channels = ch_ctr; 1454 buf_left = sizeof(ch_buf); 1455 tmp_buf = ch_buf; 1456 for (idx_rpt = 0; idx_rpt < ch_ctr; idx_rpt++) { 1457 buf_cons = qdf_snprint(tmp_buf, buf_left, "%d ", 1458 psbrr->channel_list.chan_freq_lst[idx_rpt]); 1459 buf_left -= buf_cons; 1460 tmp_buf += buf_cons; 1461 } 1462 1463 if (ch_ctr) 1464 pe_nofl_info("RX: [802.11 BCN_RPT] Ch-list:%s", ch_buf); 1465 1466 /* Send request to SME. */ 1467 mmh_msg.type = eWNI_SME_BEACON_REPORT_REQ_IND; 1468 mmh_msg.bodyptr = psbrr; 1469 MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG, 1470 pe_session->peSessionId, mmh_msg.type)); 1471 lim_sys_process_mmh_msg_api(mac, &mmh_msg); 1472 return eRRM_SUCCESS; 1473 } 1474 1475 #ifdef WLAN_FEATURE_11BE_MLO 1476 static uint8_t * 1477 rrm_check_ml_ie(uint8_t *ies, uint16_t len, uint8_t *mlie_copy_len) 1478 { 1479 uint8_t *ml_ie = NULL; 1480 qdf_size_t ml_ie_total_len = 0; 1481 uint8_t *mlie_copy = NULL; 1482 uint8_t ml_common_info_length = 0; 1483 uint8_t ml_bv_ie_len = 0; 1484 1485 util_find_mlie(ies, len, &ml_ie, &ml_ie_total_len); 1486 if (!ml_ie) { 1487 mlo_debug("[802.11 BCN_RPT]: Not ML AP total_len:%d", len); 1488 return NULL; 1489 } 1490 1491 mlo_debug("[802.11 BCN_RPT]: ML IE is present ml_ie_total_len:%d", ml_ie_total_len); 1492 1493 util_get_mlie_common_info_len(ml_ie, ml_ie_total_len, 1494 &ml_common_info_length); 1495 1496 ml_bv_ie_len = sizeof(struct wlan_ie_multilink) + ml_common_info_length; 1497 if (ml_bv_ie_len) { 1498 mlie_copy = qdf_mem_malloc(ml_bv_ie_len); 1499 if (!mlie_copy) { 1500 mlo_err("malloc failed"); 1501 goto end; 1502 } 1503 qdf_mem_copy(mlie_copy, ml_ie, ml_bv_ie_len); 1504 mlie_copy[TAG_LEN_POS] = ml_bv_ie_len - sizeof(struct ie_header); 1505 *mlie_copy_len = ml_bv_ie_len; 1506 } 1507 1508 end: 1509 return mlie_copy; 1510 } 1511 1512 static bool 1513 rrm_copy_ml_ie(uint8_t eid, uint8_t extn_eid, 1514 uint8_t *ml_ie, uint16_t ml_len, uint8_t *pIes) 1515 { 1516 if ((eid == WLAN_ELEMID_EXTN_ELEM || !eid) && 1517 extn_eid == WLAN_EXTN_ELEMID_MULTI_LINK) { 1518 if (ml_ie && ml_len && pIes) { 1519 qdf_mem_copy(pIes, ml_ie, ml_len); 1520 return true; 1521 } 1522 } 1523 1524 return false; 1525 } 1526 1527 #else 1528 static inline uint8_t * 1529 rrm_check_ml_ie(uint8_t *ies, uint16_t len, uint8_t *mlie_copy_len) { 1530 return NULL; 1531 } 1532 1533 static inline bool 1534 rrm_copy_ml_ie(uint8_t eid, uint8_t extn_eid, uint8_t *ml_ie, 1535 uint16_t ml_len, uint8_t *pIes) { 1536 return false; 1537 } 1538 #endif 1539 /** 1540 * rrm_fill_beacon_ies() - Fills fixed fields and Ies in bss description to an 1541 * array of uint8_t. 1542 * @pIes - pointer to the buffer that should be populated with ies. 1543 * @pNumIes - returns the num of ies filled in this param. 1544 * @pIesMaxSize - Max size of the buffer pIes. 1545 * @eids - pointer to array of eids. If NULL, all ies will be populated. 1546 * @numEids - number of elements in array eids. 1547 * @start_offset: Offset from where the IEs in the bss_desc should be parsed 1548 * @bss_desc - pointer to Bss Description. 1549 * 1550 * Return: Remaining length of IEs in current bss_desc which are not included 1551 * in pIes. 1552 */ 1553 static uint16_t 1554 rrm_fill_beacon_ies(struct mac_context *mac, uint8_t *pIes, 1555 uint8_t *pNumIes, uint8_t pIesMaxSize, uint8_t *eids, 1556 uint8_t numEids, uint8_t eid, uint8_t *extn_eids, 1557 uint8_t extn_eids_count, uint16_t start_offset, 1558 struct bss_description *bss_desc) 1559 { 1560 uint8_t *pBcnIes, i; 1561 uint16_t BcnNumIes, total_ies_len, len; 1562 uint16_t rem_len = 0; 1563 uint8_t num_eids = 0; 1564 uint8_t ml_len = 0; 1565 uint8_t *ml_copy = NULL; 1566 1567 if ((!pIes) || (!pNumIes) || (!bss_desc)) { 1568 pe_err("Invalid parameters"); 1569 return 0; 1570 } 1571 /* Make sure that if eid is null, numEids is set to zero. */ 1572 num_eids = (!eids) ? 0 : numEids; 1573 num_eids += (!extn_eids) ? 0 : extn_eids_count; 1574 pe_err("extn_eids_count %d", extn_eids_count); 1575 1576 total_ies_len = GET_IE_LEN_IN_BSS(bss_desc->length); 1577 BcnNumIes = total_ies_len; 1578 if (start_offset > BcnNumIes) { 1579 pe_err("Invalid start offset %d Bcn IE len %d", 1580 start_offset, total_ies_len); 1581 return 0; 1582 } 1583 1584 pBcnIes = (uint8_t *)&bss_desc->ieFields[0]; 1585 ml_copy = rrm_check_ml_ie(pBcnIes, total_ies_len, &ml_len); 1586 pBcnIes += start_offset; 1587 BcnNumIes = BcnNumIes - start_offset; 1588 1589 *pNumIes = 0; 1590 1591 /* 1592 * If start_offset is 0, this is the first fragment of the current 1593 * beacon. Include the Beacon Fixed Fields of length 12 bytes 1594 * (BEACON_FRAME_IES_OFFSET) in the first fragment. 1595 */ 1596 if (start_offset == 0) { 1597 *((uint32_t *)pIes) = bss_desc->timeStamp[0]; 1598 *pNumIes += sizeof(uint32_t); 1599 pIes += sizeof(uint32_t); 1600 *((uint32_t *)pIes) = bss_desc->timeStamp[1]; 1601 *pNumIes += sizeof(uint32_t); 1602 pIes += sizeof(uint32_t); 1603 *((uint16_t *)pIes) = bss_desc->beaconInterval; 1604 *pNumIes += sizeof(uint16_t); 1605 pIes += sizeof(uint16_t); 1606 *((uint16_t *)pIes) = bss_desc->capabilityInfo; 1607 *pNumIes += sizeof(uint16_t); 1608 pIes += sizeof(uint16_t); 1609 } 1610 1611 while (BcnNumIes >= 2) { 1612 len = *(pBcnIes + 1); 1613 len += 2; /* element id + length. */ 1614 pe_debug("EID = %d, len = %d total = %d", 1615 *pBcnIes, *(pBcnIes + 1), len); 1616 if (*pBcnIes == WLAN_ELEMID_EXTN_ELEM && *(pBcnIes + 2) > 0) 1617 pe_debug("Extended EID = %d", *(pBcnIes + 2)); 1618 1619 if (BcnNumIes < len || len <= 2) { 1620 pe_err("RRM: Invalid IE len:%d exp_len:%d", 1621 len, BcnNumIes); 1622 break; 1623 } 1624 1625 i = 0; 1626 do { 1627 if (((!eids) || (*pBcnIes == eids[i])) || 1628 ((*pBcnIes == eid) && *(pBcnIes + 2) == extn_eids[i])) { 1629 if (((*pNumIes) + len) < pIesMaxSize) { 1630 qdf_mem_copy(pIes, pBcnIes, len); 1631 pIes += len; 1632 *pNumIes += len; 1633 } else { 1634 if (rrm_copy_ml_ie(*pBcnIes, *(pBcnIes + 2), ml_copy, ml_len, pIes)) { 1635 pIes += ml_len; 1636 *pNumIes += ml_len; 1637 start_offset = start_offset + len - ml_len; 1638 } else { 1639 /* 1640 * If max size of fragment is reached, 1641 * calculate the remaining length and 1642 * break. For first fragment, account 1643 * for the fixed fields also. 1644 */ 1645 rem_len = total_ies_len - *pNumIes - 1646 start_offset; 1647 if (start_offset == 0) 1648 rem_len = rem_len + 1649 BEACON_FRAME_IES_OFFSET; 1650 pe_debug("rem_len %d ies added %d", 1651 rem_len, *pNumIes); 1652 } 1653 } 1654 break; 1655 } 1656 i++; 1657 } while (i < num_eids); 1658 1659 if (rem_len) 1660 break; 1661 1662 pBcnIes += len; 1663 BcnNumIes -= len; 1664 } 1665 1666 if (ml_copy) 1667 qdf_mem_free(ml_copy); 1668 1669 pe_debug("Total length of Ies added = %d rem_len %d", 1670 *pNumIes, rem_len); 1671 1672 return rem_len; 1673 } 1674 1675 /** 1676 * rrm_process_beacon_report_xmit() - create a rrm action frame 1677 * @mac_ctx: Global pointer to MAC context 1678 * @beacon_xmit_ind: Data for beacon report IE from SME. 1679 * 1680 * Create a Radio measurement report action frame and send it to peer. 1681 * 1682 * Return: QDF_STATUS 1683 */ 1684 QDF_STATUS 1685 rrm_process_beacon_report_xmit(struct mac_context *mac_ctx, 1686 tpSirBeaconReportXmitInd beacon_xmit_ind) 1687 { 1688 QDF_STATUS status = QDF_STATUS_SUCCESS; 1689 tSirMacRadioMeasureReport *report = NULL; 1690 tSirMacBeaconReport *beacon_report; 1691 struct bss_description *bss_desc; 1692 tpRRMReq curr_req; 1693 struct pe_session *session_entry; 1694 uint8_t session_id, counter; 1695 uint8_t i, j; 1696 uint8_t bss_desc_count = 0; 1697 uint8_t report_index = 0; 1698 uint16_t rem_len = 0; 1699 uint16_t offset = 0; 1700 uint8_t frag_id = 0; 1701 uint8_t num_frames, num_reports_in_frame, final_measurement_index; 1702 uint32_t populated_beacon_report_size = 0; 1703 uint32_t max_reports_in_frame = 0; 1704 uint32_t radio_meas_rpt_size = 0, dot11_meas_rpt_size = 0; 1705 bool is_last_measurement_frame; 1706 1707 1708 if (!beacon_xmit_ind) { 1709 pe_err("Received beacon_xmit_ind is NULL in PE"); 1710 return QDF_STATUS_E_FAILURE; 1711 } 1712 1713 if (beacon_xmit_ind->measurement_idx >= 1714 QDF_ARRAY_SIZE(mac_ctx->rrm.rrmPEContext.pCurrentReq)) { 1715 pe_err("Received measurement_idx is out of range: %u - %zu", 1716 beacon_xmit_ind->measurement_idx, 1717 QDF_ARRAY_SIZE(mac_ctx->rrm.rrmPEContext.pCurrentReq)); 1718 return QDF_STATUS_E_FAILURE; 1719 } 1720 1721 curr_req = mac_ctx->rrm.rrmPEContext. 1722 pCurrentReq[beacon_xmit_ind->measurement_idx]; 1723 if (!curr_req) { 1724 pe_err("Received report xmit while there is no request pending in PE"); 1725 status = QDF_STATUS_E_FAILURE; 1726 goto end; 1727 } 1728 1729 pe_debug("Received beacon report xmit indication on idx:%d", 1730 beacon_xmit_ind->measurement_idx); 1731 1732 /* 1733 * Send empty report only if all channels on a measurement index has 1734 * no scan results or if the AP requests for last beacon report 1735 * indication and last channel of the last index has empty report 1736 */ 1737 if (beacon_xmit_ind->numBssDesc || curr_req->sendEmptyBcnRpt || 1738 (beacon_xmit_ind->fMeasureDone && 1739 curr_req->request.Beacon.last_beacon_report_indication && 1740 (mac_ctx->rrm.rrmPEContext.num_active_request - 1) == 0)) { 1741 beacon_xmit_ind->numBssDesc = (beacon_xmit_ind->numBssDesc == 1742 RRM_BCN_RPT_NO_BSS_INFO) ? RRM_BCN_RPT_MIN_RPT : 1743 beacon_xmit_ind->numBssDesc; 1744 1745 session_entry = pe_find_session_by_bssid(mac_ctx, 1746 beacon_xmit_ind->bssId, &session_id); 1747 if (!session_entry) { 1748 pe_err("TX: [802.11 BCN_RPT] Session does not exist for bssId:"QDF_MAC_ADDR_FMT"", 1749 QDF_MAC_ADDR_REF(beacon_xmit_ind->bssId)); 1750 status = QDF_STATUS_E_FAILURE; 1751 goto end; 1752 } 1753 1754 report = qdf_mem_malloc(MAX_BEACON_REPORTS * sizeof(*report)); 1755 if (!report) { 1756 status = QDF_STATUS_E_NOMEM; 1757 goto end; 1758 } 1759 1760 for (i = 0; i < MAX_BEACON_REPORTS && 1761 bss_desc_count < beacon_xmit_ind->numBssDesc; i++) { 1762 beacon_report = &report[i].report.beaconReport; 1763 /* 1764 * If the scan result is NULL then send report request 1765 * with option subelement as NULL. 1766 */ 1767 pe_debug("TX: [802.11 BCN_RPT] report %d bss %d", i, 1768 bss_desc_count); 1769 bss_desc = beacon_xmit_ind-> 1770 pBssDescription[bss_desc_count]; 1771 1772 /* Prepare the beacon report and send it to the peer.*/ 1773 report[i].token = beacon_xmit_ind->uDialogToken; 1774 report[i].refused = 0; 1775 report[i].incapable = 0; 1776 report[i].type = SIR_MAC_RRM_BEACON_TYPE; 1777 1778 /* 1779 * Valid response is included if the size of 1780 * becon xmit is == size of beacon xmit ind + ies 1781 */ 1782 if (beacon_xmit_ind->length < sizeof(*beacon_xmit_ind)) 1783 continue; 1784 beacon_report->regClass = beacon_xmit_ind->regClass; 1785 if (bss_desc) { 1786 beacon_report->channel = 1787 wlan_reg_freq_to_chan( 1788 mac_ctx->pdev, 1789 bss_desc->chan_freq); 1790 qdf_mem_copy(beacon_report->measStartTime, 1791 bss_desc->startTSF, 1792 sizeof(bss_desc->startTSF)); 1793 beacon_report->measDuration = 1794 beacon_xmit_ind->duration; 1795 beacon_report->phyType = bss_desc->nwType; 1796 beacon_report->bcnProbeRsp = 1; 1797 beacon_report->rsni = bss_desc->sinr; 1798 1799 rrm_calculate_and_fill_rcpi(&beacon_report->rcpi, 1800 bss_desc->rssi); 1801 beacon_report->antennaId = 0; 1802 beacon_report->parentTSF = bss_desc->parentTSF; 1803 qdf_mem_copy(beacon_report->bssid, 1804 bss_desc->bssId, sizeof(tSirMacAddr)); 1805 } 1806 1807 pe_debug("TX: [802.11 BCN_RPT] reporting detail requested %d", 1808 curr_req->request.Beacon.reportingDetail); 1809 switch (curr_req->request.Beacon.reportingDetail) { 1810 case BEACON_REPORTING_DETAIL_NO_FF_IE: 1811 /* 0: No need to include any elements. */ 1812 break; 1813 case BEACON_REPORTING_DETAIL_ALL_FF_REQ_IE: 1814 /* 1: Include all FFs and Requested Ies. */ 1815 if (!bss_desc) 1816 break; 1817 1818 rem_len = rrm_fill_beacon_ies(mac_ctx, 1819 (uint8_t *)&beacon_report->Ies[0], 1820 (uint8_t *)&beacon_report->numIes, 1821 BEACON_REPORT_MAX_IES, 1822 curr_req->request.Beacon.reqIes. 1823 pElementIds, 1824 curr_req->request.Beacon.reqIes.num, 1825 curr_req->request.Beacon.reqIes.ext_info.eid, 1826 &curr_req->request.Beacon.reqIes.ext_info.eid_ext[0], 1827 curr_req->request.Beacon.reqIes.ext_info.num_eid_ext, 1828 offset, bss_desc); 1829 break; 1830 case BEACON_REPORTING_DETAIL_ALL_FF_IE: 1831 /* 2: default - Include all FFs and all Ies. */ 1832 default: 1833 if (!bss_desc) 1834 break; 1835 1836 rem_len = rrm_fill_beacon_ies(mac_ctx, 1837 (uint8_t *) &beacon_report->Ies[0], 1838 (uint8_t *) &beacon_report->numIes, 1839 BEACON_REPORT_MAX_IES, 1840 NULL, 1841 0, 1842 0, 1843 NULL, 1844 0, 1845 offset, bss_desc); 1846 break; 1847 } 1848 beacon_report->frame_body_frag_id.id = bss_desc_count; 1849 beacon_report->frame_body_frag_id.frag_id = frag_id; 1850 /* 1851 * If remaining length is non-zero, the beacon needs to 1852 * be fragmented only if the current request supports 1853 * last beacon report indication. 1854 * If last beacon report indication is not supported, 1855 * truncate and move on to the next beacon. 1856 */ 1857 if (rem_len && 1858 curr_req->request.Beacon. 1859 last_beacon_report_indication) { 1860 offset = GET_IE_LEN_IN_BSS( 1861 bss_desc->length) - rem_len; 1862 pe_debug("TX: [802.11 BCN_RPT] offset %d ie_len %lu rem_len %d frag_id %d", 1863 offset, 1864 GET_IE_LEN_IN_BSS(bss_desc->length), 1865 rem_len, frag_id); 1866 frag_id++; 1867 beacon_report->frame_body_frag_id.more_frags = 1868 true; 1869 } else { 1870 offset = 0; 1871 beacon_report->frame_body_frag_id.more_frags = 1872 false; 1873 frag_id = 0; 1874 bss_desc_count++; 1875 pe_debug("TX: [802.11 BCN_RPT] No remaining IEs"); 1876 } 1877 1878 if (curr_req->request.Beacon.last_beacon_report_indication) 1879 beacon_report->last_bcn_report_ind_support = 1; 1880 1881 } 1882 1883 pe_debug("TX: [802.11 BCN_RPT] Total reports filled %d, last bcn_rpt ind:%d", 1884 i , curr_req->request.Beacon.last_beacon_report_indication); 1885 1886 /* Calculate size of populated beacon reports */ 1887 radio_meas_rpt_size = sizeof(tSirMacRadioMeasureReport); 1888 populated_beacon_report_size = (i * radio_meas_rpt_size); 1889 1890 /* Calculate num of mgmt frames to send */ 1891 num_frames = populated_beacon_report_size / MAX_MGMT_MPDU_LEN; 1892 if (populated_beacon_report_size % MAX_MGMT_MPDU_LEN) 1893 num_frames++; 1894 1895 /* Calculate num of maximum mgmt reports per frame */ 1896 dot11_meas_rpt_size = sizeof(tDot11fRadioMeasurementReport); 1897 max_reports_in_frame = MAX_MGMT_MPDU_LEN / dot11_meas_rpt_size; 1898 1899 for (j = 0; j < num_frames; j++) { 1900 num_reports_in_frame = QDF_MIN((i - report_index), 1901 max_reports_in_frame); 1902 1903 final_measurement_index = 1904 mac_ctx->rrm.rrmPEContext.num_active_request; 1905 is_last_measurement_frame = 1906 ((j == num_frames - 1) && 1907 beacon_xmit_ind->fMeasureDone && 1908 !(final_measurement_index - 1)); 1909 1910 lim_send_radio_measure_report_action_frame(mac_ctx, 1911 curr_req->dialog_token, num_reports_in_frame, 1912 is_last_measurement_frame, 1913 &report[report_index], 1914 beacon_xmit_ind->bssId, session_entry); 1915 report_index += num_reports_in_frame; 1916 } 1917 curr_req->sendEmptyBcnRpt = false; 1918 } 1919 1920 end: 1921 for (counter = 0; counter < beacon_xmit_ind->numBssDesc; counter++) 1922 qdf_mem_free(beacon_xmit_ind->pBssDescription[counter]); 1923 1924 if (beacon_xmit_ind->fMeasureDone) { 1925 pe_debug("Measurement done idx:%d", 1926 beacon_xmit_ind->measurement_idx); 1927 rrm_cleanup(mac_ctx, beacon_xmit_ind->measurement_idx); 1928 } 1929 1930 if (report) 1931 qdf_mem_free(report); 1932 1933 return status; 1934 } 1935 1936 static void 1937 rrm_process_beacon_request_failure(struct mac_context *mac, 1938 struct pe_session *pe_session, 1939 tSirMacAddr peer, 1940 tRrmRetStatus status, uint8_t index) 1941 { 1942 tpSirMacRadioMeasureReport pReport = NULL; 1943 tpRRMReq pCurrentReq = mac->rrm.rrmPEContext.pCurrentReq[index]; 1944 1945 if (!pCurrentReq) { 1946 pe_err("Current request is NULL"); 1947 return; 1948 } 1949 1950 pReport = qdf_mem_malloc(sizeof(tSirMacRadioMeasureReport)); 1951 if (!pReport) 1952 return; 1953 pReport->token = pCurrentReq->token; 1954 pReport->type = SIR_MAC_RRM_BEACON_TYPE; 1955 1956 pe_debug("Measurement index:%d status %d token %d", index, status, 1957 pReport->token); 1958 1959 switch (status) { 1960 case eRRM_REFUSED: 1961 pReport->refused = 1; 1962 break; 1963 case eRRM_INCAPABLE: 1964 pReport->incapable = 1; 1965 break; 1966 default: 1967 pe_err("RX [802.11 BCN_RPT] Beacon request processing failed no report sent"); 1968 qdf_mem_free(pReport); 1969 return; 1970 } 1971 1972 if (pCurrentReq->request.Beacon.last_beacon_report_indication) 1973 pReport->report.beaconReport.last_bcn_report_ind_support = 1; 1974 1975 lim_send_radio_measure_report_action_frame(mac, 1976 pCurrentReq->dialog_token, 1977 1, true, 1978 pReport, peer, 1979 pe_session); 1980 1981 qdf_mem_free(pReport); 1982 return; 1983 } 1984 1985 /** 1986 * rrm_process_beacon_req() - Update curr_req and report 1987 * @mac_ctx: Global pointer to MAC context 1988 * @peer: Macaddress of the peer requesting the radio measurement 1989 * @session_entry: session entry 1990 * @radiomes_report: Pointer to radio measurement report 1991 * @rrm_req: Array of Measurement request IEs 1992 * @num_report: No.of reports 1993 * @index: Index for Measurement request 1994 * 1995 * Update structure sRRMReq and sSirMacRadioMeasureReport and pass it to 1996 * rrm_process_beacon_report_req(). 1997 * 1998 * Return: QDF_STATUS 1999 */ 2000 static 2001 QDF_STATUS rrm_process_beacon_req(struct mac_context *mac_ctx, tSirMacAddr peer, 2002 struct pe_session *session_entry, 2003 tpSirMacRadioMeasureReport *radiomes_report, 2004 tDot11fRadioMeasurementRequest *rrm_req, 2005 uint8_t *num_report, int index) 2006 { 2007 tRrmRetStatus rrm_status = eRRM_SUCCESS; 2008 tpSirMacRadioMeasureReport report = NULL; 2009 tpRRMReq curr_req; 2010 QDF_STATUS status = QDF_STATUS_SUCCESS; 2011 2012 if (index >= MAX_MEASUREMENT_REQUEST) { 2013 status = rrm_reject_req(&report, rrm_req, num_report, index, 2014 rrm_req->MeasurementRequest[0]. 2015 measurement_type); 2016 return status; 2017 } 2018 2019 curr_req = qdf_mem_malloc(sizeof(*curr_req)); 2020 if (!curr_req) { 2021 mac_ctx->rrm.rrmPEContext.pCurrentReq[index] = NULL; 2022 return QDF_STATUS_E_NOMEM; 2023 } 2024 pe_debug("Processing Beacon Report request %d", index); 2025 curr_req->dialog_token = rrm_req->DialogToken.token; 2026 curr_req->token = 2027 rrm_req->MeasurementRequest[index].measurement_token; 2028 curr_req->sendEmptyBcnRpt = true; 2029 curr_req->measurement_idx = index; 2030 mac_ctx->rrm.rrmPEContext.pCurrentReq[index] = curr_req; 2031 mac_ctx->rrm.rrmPEContext.num_active_request++; 2032 pe_debug("Processing Bcn Report req %d num_active_req:%d", 2033 index, mac_ctx->rrm.rrmPEContext.num_active_request); 2034 rrm_status = rrm_process_beacon_report_req(mac_ctx, curr_req, 2035 &rrm_req->MeasurementRequest[index], session_entry); 2036 if (eRRM_SUCCESS != rrm_status) { 2037 rrm_process_beacon_request_failure(mac_ctx, 2038 session_entry, peer, rrm_status, index); 2039 rrm_cleanup(mac_ctx, index); 2040 } 2041 2042 return QDF_STATUS_SUCCESS; 2043 } 2044 2045 2046 /** 2047 * rrm_process_channel_load_req() - process channel load request from AP 2048 * @mac: global mac context 2049 * @pe_session: per-vdev PE context 2050 * @curr_req: current measurement req in progress 2051 * @peer: Macaddress of the peer requesting the radio measurement 2052 * @chan_load_req: channel load request received from AP 2053 * 2054 * return tRrmRetStatus 2055 */ 2056 static tRrmRetStatus 2057 rrm_process_channel_load_req(struct mac_context *mac, 2058 struct pe_session *pe_session, 2059 tpRRMReq curr_req, tSirMacAddr peer, 2060 tDot11fIEMeasurementRequest *chan_load_req) 2061 { 2062 struct scheduler_msg msg = {0}; 2063 struct ch_load_ind *load_ind; 2064 struct bw_ind_element bw_ind = {0}; 2065 struct wide_bw_chan_switch wide_bw = {0}; 2066 struct rrm_reporting rrm_report; 2067 uint8_t op_class, channel; 2068 uint16_t randomization_intv, meas_duration, max_meas_duration; 2069 bool is_rrm_reporting, is_wide_bw_chan_switch; 2070 uint8_t country[WNI_CFG_COUNTRY_CODE_LEN]; 2071 qdf_freq_t chan_freq; 2072 bool is_freq_enabled, is_bw_ind; 2073 2074 if (wlan_policy_mgr_get_ll_lt_sap_vdev_id(mac->psoc) != WLAN_INVALID_VDEV_ID) { 2075 pe_debug("RX:[802.11 CH_LOAD] reject req as ll_lt_sap is present"); 2076 return eRRM_REFUSED; 2077 } 2078 2079 is_rrm_reporting = chan_load_req->measurement_request.channel_load.rrm_reporting.present; 2080 is_wide_bw_chan_switch = chan_load_req->measurement_request.channel_load.wide_bw_chan_switch.present; 2081 is_bw_ind = chan_load_req->measurement_request.channel_load.bw_indication.present; 2082 2083 pe_debug("RX:[802.11 CH_LOAD] vdev: %d, is_rrm_reporting: %d, is_wide_bw_chan_switch: %d, is_bw_ind: %d", 2084 pe_session->vdev_id, is_rrm_reporting, is_wide_bw_chan_switch, 2085 is_bw_ind); 2086 2087 if (is_rrm_reporting) { 2088 rrm_report.threshold = chan_load_req->measurement_request.channel_load.rrm_reporting.threshold; 2089 rrm_report.reporting_condition = chan_load_req->measurement_request.channel_load.rrm_reporting.reporting_condition; 2090 pe_debug("RX:[802.11 CH_LOAD] threshold:%d reporting_c:%d", 2091 rrm_report.threshold, rrm_report.reporting_condition); 2092 if (rrm_report.reporting_condition != 0) { 2093 pe_debug("RX:[802.11 CH_LOAD]: Dropping req"); 2094 return eRRM_INCAPABLE; 2095 } 2096 } 2097 2098 if (is_bw_ind) { 2099 bw_ind.is_bw_ind_element = true; 2100 bw_ind.channel_width = chan_load_req->measurement_request.channel_load.bw_indication.channel_width; 2101 bw_ind.ccfi0 = chan_load_req->measurement_request.channel_load.bw_indication.ccfs0; 2102 bw_ind.ccfi1 = chan_load_req->measurement_request.channel_load.bw_indication.ccfs1; 2103 bw_ind.center_freq = wlan_reg_compute_6g_center_freq_from_cfi(bw_ind.ccfi0); 2104 pe_debug("RX:[802.11 CH_LOAD] chan_width:%d ccfs0:%d, ccfs1:%d, center_freq:%d", 2105 bw_ind.channel_width, bw_ind.ccfi0, 2106 bw_ind.ccfi1, bw_ind.center_freq); 2107 2108 if (bw_ind.channel_width == 0 || !bw_ind.ccfi0 || 2109 bw_ind.channel_width < CH_WIDTH_320MHZ || !bw_ind.center_freq) { 2110 pe_debug("Dropping req: invalid is_bw_ind_element IE"); 2111 return eRRM_REFUSED; 2112 } 2113 } 2114 2115 if (is_wide_bw_chan_switch) { 2116 wide_bw.is_wide_bw_chan_switch = true; 2117 wide_bw.channel_width = chan_load_req->measurement_request.channel_load.wide_bw_chan_switch.new_chan_width; 2118 wide_bw.center_chan_freq0 = chan_load_req->measurement_request.channel_load.wide_bw_chan_switch.new_center_chan_freq0; 2119 wide_bw.center_chan_freq1 = chan_load_req->measurement_request.channel_load.wide_bw_chan_switch.new_center_chan_freq1; 2120 pe_debug("RX:[802.11 CH_LOAD] cw:%d ccf0:%d, ccf1:%d", 2121 wide_bw.channel_width, wide_bw.center_chan_freq0, 2122 wide_bw.center_chan_freq1); 2123 if (wide_bw.channel_width < CH_WIDTH_20MHZ || 2124 wide_bw.channel_width >= CH_WIDTH_320MHZ) { 2125 pe_debug("Dropping req: invalid wide_bw IE"); 2126 return eRRM_REFUSED; 2127 } 2128 } 2129 2130 op_class = chan_load_req->measurement_request.channel_load.op_class; 2131 channel = chan_load_req->measurement_request.channel_load.channel; 2132 meas_duration = 2133 chan_load_req->measurement_request.channel_load.meas_duration; 2134 randomization_intv = 2135 chan_load_req->measurement_request.channel_load.randomization_intv; 2136 max_meas_duration = rrm_get_max_meas_duration(mac, pe_session); 2137 2138 if (max_meas_duration < meas_duration) { 2139 if (chan_load_req->durationMandatory) { 2140 pe_nofl_err("RX:[802.11 CH_LOAD] Dropping the req: duration mandatory & max duration > meas duration"); 2141 return eRRM_REFUSED; 2142 } 2143 meas_duration = max_meas_duration; 2144 } 2145 2146 pe_debug("RX:[802.11 CH_LOAD] vdev :%d, seq:%d Token:%d op_c:%d ch:%d meas_dur:%d, rand intv: %d, max_dur:%d", 2147 pe_session->vdev_id, 2148 mac->rrm.rrmPEContext.prev_rrm_report_seq_num, 2149 chan_load_req->measurement_token, op_class, 2150 channel, meas_duration, randomization_intv, 2151 max_meas_duration); 2152 2153 if (!meas_duration || meas_duration > RRM_SCAN_MAX_DWELL_TIME) 2154 return eRRM_REFUSED; 2155 2156 if (!wlan_reg_is_6ghz_supported(mac->psoc) && 2157 (wlan_reg_is_6ghz_op_class(mac->pdev, op_class))) { 2158 pe_debug("RX: [802.11 CH_LOAD] Ch belongs to 6 ghz spectrum, abort"); 2159 return eRRM_INCAPABLE; 2160 } 2161 2162 rrm_get_country_code_from_connected_profile(mac, pe_session->vdev_id, 2163 country); 2164 chan_freq = wlan_reg_country_chan_opclass_to_freq(mac->pdev, 2165 country, channel, 2166 op_class, false); 2167 if (!chan_freq) { 2168 pe_debug("Invalid ch freq for country code %c%c 0x%x", 2169 country[0], country[1], country[2]); 2170 return eRRM_INCAPABLE; 2171 } 2172 2173 pe_debug("freq:%d, country code %c%c 0x%x", chan_freq, country[0], 2174 country[1], country[2]); 2175 2176 is_freq_enabled = wlan_reg_is_freq_enabled(mac->pdev, chan_freq, 2177 REG_CURRENT_PWR_MODE); 2178 if (!is_freq_enabled) { 2179 pe_debug("No channels populated with requested operation class and current country, Hence abort the rrm operation"); 2180 return eRRM_INCAPABLE; 2181 } 2182 2183 /* Prepare the request to send to SME. */ 2184 load_ind = qdf_mem_malloc(sizeof(struct ch_load_ind)); 2185 if (!load_ind) 2186 return eRRM_FAILURE; 2187 2188 qdf_mem_copy(load_ind->peer_addr.bytes, peer, 2189 sizeof(struct qdf_mac_addr)); 2190 load_ind->message_type = eWNI_SME_CHAN_LOAD_REQ_IND; 2191 load_ind->length = sizeof(struct ch_load_ind); 2192 load_ind->dialog_token = chan_load_req->measurement_token; 2193 load_ind->msg_source = eRRM_MSG_SOURCE_11K; 2194 load_ind->randomization_intv = SYS_TU_TO_MS(randomization_intv); 2195 load_ind->measurement_idx = curr_req->measurement_idx; 2196 load_ind->channel = channel; 2197 load_ind->req_freq = chan_freq; 2198 load_ind->op_class = op_class; 2199 load_ind->meas_duration = meas_duration; 2200 curr_req->token = chan_load_req->measurement_token; 2201 2202 if (is_wide_bw_chan_switch) 2203 load_ind->wide_bw = wide_bw; 2204 2205 if (is_bw_ind) 2206 load_ind->bw_ind = bw_ind; 2207 2208 /* Send request to SME. */ 2209 msg.type = eWNI_SME_CHAN_LOAD_REQ_IND; 2210 msg.bodyptr = load_ind; 2211 MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG, 2212 pe_session->vdev_id, msg.type)); 2213 lim_sys_process_mmh_msg_api(mac, &msg); 2214 return eRRM_SUCCESS; 2215 } 2216 2217 /** 2218 * rrm_process_chan_load_request_failure() - process channel load request 2219 * in case of failure 2220 * @mac: global mac context 2221 * @pe_session: per-vdev PE context 2222 * @peer: peer mac address 2223 * @status:failure status of channel load request 2224 * @index: request index 2225 * 2226 * return none 2227 */ 2228 static void 2229 rrm_process_chan_load_request_failure(struct mac_context *mac, 2230 struct pe_session *pe_session, 2231 tSirMacAddr peer, 2232 tRrmRetStatus status, uint8_t index) 2233 { 2234 tpSirMacRadioMeasureReport report = NULL; 2235 tpRRMReq curr_req = mac->rrm.rrmPEContext.pCurrentReq[index]; 2236 2237 if (!curr_req) { 2238 pe_debug("Current request is NULL"); 2239 goto cleanup; 2240 } 2241 report = qdf_mem_malloc(sizeof(tSirMacRadioMeasureReport)); 2242 if (!report) 2243 goto cleanup; 2244 report->token = curr_req->token; 2245 report->type = SIR_MAC_RRM_CHANNEL_LOAD_TYPE; 2246 pe_debug("vdev:%d measurement index:%d status %d token %d", 2247 pe_session->vdev_id, index, status, report->token); 2248 switch (status) { 2249 case eRRM_REFUSED: 2250 case eRRM_FAILURE: 2251 report->refused = 1; 2252 break; 2253 case eRRM_INCAPABLE: 2254 report->incapable = 1; 2255 break; 2256 default: 2257 goto free; 2258 } 2259 2260 lim_send_radio_measure_report_action_frame(mac, curr_req->dialog_token, 2261 1, true, report, peer, 2262 pe_session); 2263 free: 2264 qdf_mem_free(report); 2265 cleanup: 2266 rrm_cleanup(mac, index); 2267 } 2268 2269 void 2270 rrm_process_chan_load_report_xmit(struct mac_context *mac_ctx, 2271 struct chan_load_xmit_ind *chan_load_ind) 2272 { 2273 tSirMacRadioMeasureReport *report = NULL; 2274 struct chan_load_report *channel_load_report; 2275 tpRRMReq curr_req; 2276 struct pe_session *session_entry; 2277 uint8_t session_id, idx; 2278 struct qdf_mac_addr sessionBssId; 2279 2280 if (!chan_load_ind) { 2281 pe_err("Received chan_load_xmit_ind is NULL in PE"); 2282 return; 2283 } 2284 2285 idx = chan_load_ind->measurement_idx; 2286 2287 if (idx >= QDF_ARRAY_SIZE(mac_ctx->rrm.rrmPEContext.pCurrentReq)) { 2288 pe_err("Received measurement_idx is out of range: %u - %zu", 2289 idx, 2290 QDF_ARRAY_SIZE(mac_ctx->rrm.rrmPEContext.pCurrentReq)); 2291 return; 2292 } 2293 2294 curr_req = mac_ctx->rrm.rrmPEContext.pCurrentReq[idx]; 2295 if (!curr_req) { 2296 pe_err("no request pending in PE"); 2297 goto end; 2298 } 2299 2300 pe_debug("Received chan load report xmit indication on idx:%d", idx); 2301 2302 sessionBssId = mac_ctx->rrm.rrmSmeContext[idx].sessionBssId; 2303 2304 session_entry = pe_find_session_by_bssid(mac_ctx, sessionBssId.bytes, 2305 &session_id); 2306 if (!session_entry) { 2307 pe_err("NULL session for bssId "QDF_MAC_ADDR_FMT"", 2308 QDF_MAC_ADDR_REF(sessionBssId.bytes)); 2309 goto end; 2310 } 2311 2312 if (!chan_load_ind->is_report_success) { 2313 rrm_process_chan_load_request_failure(mac_ctx, session_entry, 2314 sessionBssId.bytes, 2315 eRRM_REFUSED, idx); 2316 return; 2317 } 2318 2319 report = qdf_mem_malloc(sizeof(*report)); 2320 if (!report) 2321 goto end; 2322 2323 /* Prepare the channel load report and send it to the peer.*/ 2324 report->token = chan_load_ind->dialog_token; 2325 report->refused = 0; 2326 report->incapable = 0; 2327 report->type = SIR_MAC_RRM_CHANNEL_LOAD_TYPE; 2328 2329 channel_load_report = &report[0].report.channel_load_report; 2330 channel_load_report->op_class = chan_load_ind->op_class; 2331 channel_load_report->channel = chan_load_ind->channel; 2332 channel_load_report->rrm_scan_tsf = chan_load_ind->rrm_scan_tsf; 2333 channel_load_report->meas_duration = chan_load_ind->duration; 2334 channel_load_report->chan_load = chan_load_ind->chan_load; 2335 qdf_mem_copy(&channel_load_report->bw_ind, &chan_load_ind->bw_ind, 2336 sizeof(channel_load_report->bw_ind)); 2337 qdf_mem_copy(&channel_load_report->wide_bw, &chan_load_ind->wide_bw, 2338 sizeof(channel_load_report->wide_bw)); 2339 pe_err("send chan load report for bssId:"QDF_MAC_ADDR_FMT" reg_class:%d, channel:%d, measStartTime:%llu, measDuration:%d, chan_load:%d", 2340 QDF_MAC_ADDR_REF(sessionBssId.bytes), 2341 channel_load_report->op_class, 2342 channel_load_report->channel, 2343 channel_load_report->rrm_scan_tsf, 2344 channel_load_report->meas_duration, 2345 channel_load_report->chan_load); 2346 2347 lim_send_radio_measure_report_action_frame(mac_ctx, 2348 curr_req->dialog_token, 1, 2349 true, &report[0], 2350 sessionBssId.bytes, 2351 session_entry); 2352 2353 end: 2354 pe_debug("Measurement done idx:%d", idx); 2355 rrm_cleanup(mac_ctx, idx); 2356 qdf_mem_free(report); 2357 2358 return; 2359 } 2360 2361 /** 2362 * rrm_process_chan_load_req() - process channel load request 2363 * @mac_ctx: Global pointer to MAC context 2364 * @session_entry: session entry 2365 * @report: Pointer to radio measurement report 2366 * @rrm_req: Array of Measurement request IEs 2367 * @peer: mac address of the peer requesting the radio measurement 2368 * @num_report: No.of reports 2369 * @index: Index for Measurement request 2370 * 2371 * Update structure sRRMReq and struct chan_load_req_ind and pass it to 2372 * rrm_process_channel_load_req(). 2373 * 2374 * Return: QDF_STATUS 2375 */ 2376 static QDF_STATUS 2377 rrm_process_chan_load_req(struct mac_context *mac_ctx, 2378 struct pe_session *session_entry, 2379 tpSirMacRadioMeasureReport *report, 2380 tDot11fRadioMeasurementRequest *rrm_req, 2381 tSirMacAddr peer, uint8_t *num_report, int index) 2382 { 2383 tRrmRetStatus rrm_status = eRRM_SUCCESS; 2384 tpRRMReq curr_req; 2385 QDF_STATUS status = QDF_STATUS_SUCCESS; 2386 2387 if (index >= MAX_MEASUREMENT_REQUEST) { 2388 status = rrm_reject_req(report, rrm_req, num_report, index, 2389 rrm_req->MeasurementRequest[0].measurement_type); 2390 return status; 2391 } 2392 2393 curr_req = qdf_mem_malloc(sizeof(*curr_req)); 2394 if (!curr_req) { 2395 mac_ctx->rrm.rrmPEContext.pCurrentReq[index] = NULL; 2396 return QDF_STATUS_E_NOMEM; 2397 } 2398 2399 curr_req->dialog_token = rrm_req->DialogToken.token; 2400 curr_req->token = 2401 rrm_req->MeasurementRequest[index].measurement_token; 2402 curr_req->measurement_idx = index; 2403 mac_ctx->rrm.rrmPEContext.pCurrentReq[index] = curr_req; 2404 mac_ctx->rrm.rrmPEContext.num_active_request++; 2405 pe_debug("Processing channel load req index: %d num_active_req:%d", 2406 index, mac_ctx->rrm.rrmPEContext.num_active_request); 2407 rrm_status = rrm_process_channel_load_req(mac_ctx, session_entry, 2408 curr_req, peer, 2409 &rrm_req->MeasurementRequest[index]); 2410 if (eRRM_SUCCESS != rrm_status) 2411 rrm_process_chan_load_request_failure(mac_ctx, session_entry, 2412 peer, rrm_status, index); 2413 2414 return QDF_STATUS_SUCCESS; 2415 } 2416 2417 /** 2418 * update_rrm_report() - Set incapable bit 2419 * @mac_ctx: Global pointer to MAC context 2420 * @report: Pointer to radio measurement report 2421 * @rrm_req: Array of Measurement request IEs 2422 * @num_report: No.of reports 2423 * @index: Index for Measurement request 2424 * 2425 * Send a report with incapabale bit set 2426 * 2427 * Return: QDF_STATUS 2428 */ 2429 static 2430 QDF_STATUS update_rrm_report(struct mac_context *mac_ctx, 2431 tpSirMacRadioMeasureReport *report, 2432 tDot11fRadioMeasurementRequest *rrm_req, 2433 uint8_t *num_report, int index) 2434 { 2435 tpSirMacRadioMeasureReport rrm_report; 2436 2437 if (!*report) { 2438 /* 2439 * Allocate memory to send reports for 2440 * any subsequent requests. 2441 */ 2442 *report = qdf_mem_malloc(sizeof(tSirMacRadioMeasureReport) * 2443 (rrm_req->num_MeasurementRequest - index)); 2444 if (!*report) 2445 return QDF_STATUS_E_NOMEM; 2446 pe_debug("rrm beacon type incapable of %d report", *num_report); 2447 } 2448 rrm_report = *report; 2449 rrm_report[*num_report].incapable = 1; 2450 rrm_report[*num_report].type = 2451 rrm_req->MeasurementRequest[index].measurement_type; 2452 rrm_report[*num_report].token = 2453 rrm_req->MeasurementRequest[index].measurement_token; 2454 (*num_report)++; 2455 return QDF_STATUS_SUCCESS; 2456 } 2457 2458 QDF_STATUS rrm_reject_req(tpSirMacRadioMeasureReport *radiomes_report, 2459 tDot11fRadioMeasurementRequest *rrm_req, 2460 uint8_t *num_report, uint8_t index, 2461 uint8_t measurement_type) 2462 { 2463 tpSirMacRadioMeasureReport report; 2464 2465 if (!*radiomes_report) { 2466 /* 2467 * Allocate memory to send reports for 2468 * any subsequent requests. 2469 */ 2470 *radiomes_report = qdf_mem_malloc(sizeof(*report) * 2471 (rrm_req->num_MeasurementRequest - index)); 2472 if (!*radiomes_report) 2473 return QDF_STATUS_E_NOMEM; 2474 2475 pe_debug("rrm beacon refused of %d report, index: %d in beacon table", 2476 *num_report, index); 2477 } 2478 report = *radiomes_report; 2479 report[*num_report].refused = 1; 2480 report[*num_report].type = measurement_type; 2481 report[*num_report].token = 2482 rrm_req->MeasurementRequest[index].measurement_token; 2483 (*num_report)++; 2484 2485 return QDF_STATUS_SUCCESS; 2486 2487 } 2488 2489 /* -------------------------------------------------------------------- */ 2490 /** 2491 * rrm_process_radio_measurement_request - Process rrm request 2492 * @mac_ctx: Global pointer to MAC context 2493 * @peer: Macaddress of the peer requesting the radio measurement. 2494 * @rrm_req: Array of Measurement request IEs 2495 * @session_entry: session entry. 2496 * 2497 * Processes the Radio Resource Measurement request. 2498 * 2499 * Return: QDF_STATUS 2500 */ 2501 QDF_STATUS 2502 rrm_process_radio_measurement_request(struct mac_context *mac_ctx, 2503 tSirMacAddr peer, 2504 tDot11fRadioMeasurementRequest *rrm_req, 2505 struct pe_session *session_entry) 2506 { 2507 uint8_t i, index; 2508 QDF_STATUS status = QDF_STATUS_SUCCESS; 2509 tpSirMacRadioMeasureReport report = NULL; 2510 uint8_t num_report = 0; 2511 bool reject = false; 2512 2513 if (!rrm_req->num_MeasurementRequest) { 2514 report = qdf_mem_malloc(sizeof(tSirMacRadioMeasureReport)); 2515 if (!report) 2516 return QDF_STATUS_E_NOMEM; 2517 pe_err("RX: [802.11 RRM] No requestIes in the measurement request, sending incapable report"); 2518 report->incapable = 1; 2519 num_report = 1; 2520 lim_send_radio_measure_report_action_frame(mac_ctx, 2521 rrm_req->DialogToken.token, num_report, true, 2522 report, peer, session_entry); 2523 qdf_mem_free(report); 2524 return QDF_STATUS_E_FAILURE; 2525 } 2526 /* PF Fix */ 2527 if (rrm_req->NumOfRepetitions.repetitions > 0) { 2528 pe_info("RX: [802.11 RRM] number of repetitions %d, sending incapable report", 2529 rrm_req->NumOfRepetitions.repetitions); 2530 /* 2531 * Send a report with incapable bit set. 2532 * Not supporting repetitions. 2533 */ 2534 report = qdf_mem_malloc(sizeof(tSirMacRadioMeasureReport)); 2535 if (!report) 2536 return QDF_STATUS_E_NOMEM; 2537 report->incapable = 1; 2538 report->type = rrm_req->MeasurementRequest[0].measurement_type; 2539 num_report = 1; 2540 goto end; 2541 } 2542 2543 for (index = 0; index < MAX_MEASUREMENT_REQUEST; index++) { 2544 if (mac_ctx->rrm.rrmPEContext.pCurrentReq[index]) { 2545 reject = true; 2546 pe_debug("RRM req for index: %d is already in progress", 2547 index); 2548 break; 2549 } 2550 } 2551 2552 if (reject) { 2553 for (i = 0; i < rrm_req->num_MeasurementRequest; i++) { 2554 status = 2555 rrm_reject_req(&report, rrm_req, &num_report, i, 2556 rrm_req->MeasurementRequest[i]. 2557 measurement_type); 2558 if (QDF_IS_STATUS_ERROR(status)) { 2559 pe_debug("Fail to Reject rrm req for index: %d", 2560 i); 2561 return status; 2562 } 2563 } 2564 2565 goto end; 2566 } 2567 2568 /* 2569 * Clear global beacon_rpt_chan_list before processing every new 2570 * beacon report request. 2571 */ 2572 qdf_mem_zero(mac_ctx->rrm.rrmPEContext.beacon_rpt_chan_list, 2573 sizeof(uint8_t) * MAX_NUM_CHANNELS); 2574 mac_ctx->rrm.rrmPEContext.beacon_rpt_chan_num = 0; 2575 2576 for (i = 0; i < rrm_req->num_MeasurementRequest; i++) { 2577 switch (rrm_req->MeasurementRequest[i].measurement_type) { 2578 case SIR_MAC_RRM_CHANNEL_LOAD_TYPE: 2579 /* Process channel load request */ 2580 status = rrm_process_chan_load_req(mac_ctx, 2581 session_entry, 2582 &report, 2583 rrm_req, peer, 2584 &num_report, i); 2585 if (QDF_IS_STATUS_ERROR(status)) 2586 return status; 2587 break; 2588 case SIR_MAC_RRM_BEACON_TYPE: 2589 /* Process beacon request. */ 2590 status = rrm_process_beacon_req(mac_ctx, peer, 2591 session_entry, &report, 2592 rrm_req, &num_report, 2593 i); 2594 if (QDF_IS_STATUS_ERROR(status)) 2595 return status; 2596 break; 2597 case SIR_MAC_RRM_STA_STATISTICS_TYPE: 2598 status = rrm_process_sta_stats_req(mac_ctx, peer, 2599 session_entry, &report, 2600 rrm_req, &num_report, 2601 i); 2602 break; 2603 case SIR_MAC_RRM_LCI_TYPE: 2604 case SIR_MAC_RRM_LOCATION_CIVIC_TYPE: 2605 case SIR_MAC_RRM_FINE_TIME_MEAS_TYPE: 2606 pe_debug("RRM with type: %d sent to userspace", 2607 rrm_req->MeasurementRequest[i].measurement_type); 2608 break; 2609 default: 2610 /* Send a report with incapabale bit set. */ 2611 status = update_rrm_report(mac_ctx, &report, rrm_req, 2612 &num_report, i); 2613 if (QDF_STATUS_SUCCESS != status) 2614 return status; 2615 break; 2616 } 2617 } 2618 2619 end: 2620 if (report) { 2621 lim_send_radio_measure_report_action_frame(mac_ctx, 2622 rrm_req->DialogToken.token, num_report, true, 2623 report, peer, session_entry); 2624 qdf_mem_free(report); 2625 } 2626 return status; 2627 } 2628 2629 /** 2630 * rrm_get_start_tsf 2631 * 2632 * FUNCTION: Get the Start TSF. 2633 * 2634 * LOGIC: 2635 * 2636 * ASSUMPTIONS: 2637 * 2638 * NOTE: 2639 * 2640 * @param startTSF - store star TSF in this buffer. 2641 * @return txPower 2642 */ 2643 void rrm_get_start_tsf(struct mac_context *mac, uint32_t *pStartTSF) 2644 { 2645 pStartTSF[0] = mac->rrm.rrmPEContext.startTSF[0]; 2646 pStartTSF[1] = mac->rrm.rrmPEContext.startTSF[1]; 2647 2648 } 2649 2650 /* -------------------------------------------------------------------- */ 2651 /** 2652 * rrm_get_capabilities 2653 * 2654 * FUNCTION: 2655 * Returns a pointer to tpRRMCaps with all the caps enabled in RRM 2656 * 2657 * LOGIC: 2658 * 2659 * ASSUMPTIONS: 2660 * 2661 * NOTE: 2662 * 2663 * @param pe_session 2664 * @return pointer to tRRMCaps 2665 */ 2666 tpRRMCaps rrm_get_capabilities(struct mac_context *mac, struct pe_session *pe_session) 2667 { 2668 return &mac->rrm.rrmPEContext.rrmEnabledCaps; 2669 } 2670 2671 /** 2672 * rrm_initialize() - Initialize PE RRM parameters 2673 * @mac: Pointer to mac context 2674 * 2675 * Return: QDF_STATUS 2676 */ 2677 QDF_STATUS rrm_initialize(struct mac_context *mac) 2678 { 2679 tpRRMCaps pRRMCaps = &mac->rrm.rrmPEContext.rrmEnabledCaps; 2680 uint8_t i; 2681 2682 for (i = 0; i < MAX_MEASUREMENT_REQUEST; i++) 2683 mac->rrm.rrmPEContext.pCurrentReq[i] = NULL; 2684 2685 mac->rrm.rrmPEContext.txMgmtPower = 0; 2686 mac->rrm.rrmPEContext.DialogToken = 0; 2687 2688 mac->rrm.rrmPEContext.rrmEnable = 0; 2689 mac->rrm.rrmPEContext.prev_rrm_report_seq_num = 0xFFFF; 2690 mac->rrm.rrmPEContext.num_active_request = 0; 2691 2692 qdf_mem_zero(pRRMCaps, sizeof(tRRMCaps)); 2693 pRRMCaps->LinkMeasurement = 1; 2694 pRRMCaps->NeighborRpt = 1; 2695 pRRMCaps->BeaconPassive = 1; 2696 pRRMCaps->BeaconActive = 1; 2697 pRRMCaps->BeaconTable = 1; 2698 pRRMCaps->APChanReport = 1; 2699 pRRMCaps->fine_time_meas_rpt = 1; 2700 pRRMCaps->lci_capability = 1; 2701 pRRMCaps->ChannelLoad = 1; 2702 pRRMCaps->statistics = 1; 2703 2704 pRRMCaps->operatingChanMax = 3; 2705 pRRMCaps->nonOperatingChanMax = 3; 2706 2707 return QDF_STATUS_SUCCESS; 2708 } 2709 2710 void rrm_cleanup(struct mac_context *mac, uint8_t idx) 2711 { 2712 tpRRMReq cur_rrm_req = NULL; 2713 2714 if (mac->rrm.rrmPEContext.num_active_request) 2715 mac->rrm.rrmPEContext.num_active_request--; 2716 2717 cur_rrm_req = mac->rrm.rrmPEContext.pCurrentReq[idx]; 2718 if (!cur_rrm_req) 2719 return; 2720 if (cur_rrm_req->request.Beacon.reqIes.num) { 2721 qdf_mem_free(cur_rrm_req->request.Beacon.reqIes.pElementIds); 2722 cur_rrm_req->request.Beacon.reqIes.pElementIds = NULL; 2723 cur_rrm_req->request.Beacon.reqIes.num = 0; 2724 } 2725 2726 if (cur_rrm_req->type == SIR_MAC_RRM_STA_STATISTICS_TYPE) { 2727 pe_debug("deactivate rrm sta stats timer"); 2728 lim_deactivate_and_change_timer(mac, 2729 eLIM_RRM_STA_STATS_RSP_TIMER); 2730 qdf_mem_zero(&mac->rrm.rrmPEContext.rrm_sta_stats, 2731 sizeof(mac->rrm.rrmPEContext.rrm_sta_stats)); 2732 } 2733 qdf_mem_free(cur_rrm_req); 2734 mac->rrm.rrmPEContext.pCurrentReq[idx] = NULL; 2735 2736 pe_debug("cleanup rrm req idx:%d, num_active_request:%d", 2737 idx, mac->rrm.rrmPEContext.num_active_request); 2738 } 2739 2740 /** 2741 * lim_update_rrm_capability() - Update PE context's rrm capability 2742 * @mac_ctx: Global pointer to MAC context 2743 * @join_req: Pointer to SME join request. 2744 * 2745 * Update PE context's rrm capability based on SME join request. 2746 * 2747 * Return: None 2748 */ 2749 void lim_update_rrm_capability(struct mac_context *mac_ctx) 2750 { 2751 mac_ctx->rrm.rrmPEContext.rrmEnable = 2752 mac_ctx->rrm.rrmConfig.rrm_enabled; 2753 qdf_mem_copy(&mac_ctx->rrm.rrmPEContext.rrmEnabledCaps, 2754 &mac_ctx->rrm.rrmConfig.rm_capability, 2755 RMENABLEDCAP_MAX_LEN); 2756 } 2757