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