1 /* 2 * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <target_if_cfr.h> 20 #include <wlan_tgt_def_config.h> 21 #include <target_type.h> 22 #include <hif_hw_version.h> 23 #include <target_if.h> 24 #include <wlan_lmac_if_def.h> 25 #include <wlan_osif_priv.h> 26 #include <init_deinit_lmac.h> 27 #include <wlan_cfr_utils_api.h> 28 #include <target_if_direct_buf_rx_api.h> 29 #include <target_if_cfr_enh.h> 30 #include "cdp_txrx_ctrl.h" 31 32 #define CMN_NOISE_FLOOR (-96) 33 #define NUM_CHAINS_FW_TO_HOST(n) ((1 << ((n) + 1)) - 1) 34 35 #define CFR_INVALID_SNR 0x80 36 37 static u_int32_t end_magic = 0xBEAFDEAD; 38 39 /** 40 * snr_to_signal_strength() - Convert SNR(dB) to signal strength(dBm) 41 * @snr: SNR in dB 42 * 43 * Return: signal strength in dBm 44 */ 45 #if defined(QCA_WIFI_QCA6490) || defined(QCA_WIFI_WCN7850) 46 static inline 47 u_int32_t snr_to_signal_strength(uint8_t snr) 48 { 49 /* target onverts snr to dBm */ 50 return snr; 51 } 52 #else 53 static inline 54 u_int32_t snr_to_signal_strength(uint8_t snr) 55 { 56 /* SNR value 0x80 indicates -128dB which is not a valid value */ 57 return (snr != CFR_INVALID_SNR) ? 58 (((int8_t)snr) + CMN_NOISE_FLOOR) : 59 ((int8_t)snr); 60 } 61 #endif 62 63 /** 64 * get_lut_entry() - Retrieve LUT entry using cookie number 65 * @pcfr: PDEV CFR object 66 * @offset: cookie number 67 * 68 * Return: look up table entry 69 */ 70 static struct look_up_table *get_lut_entry(struct pdev_cfr *pcfr, 71 int offset) 72 { 73 if (offset >= pcfr->lut_num) { 74 cfr_err("Invalid offset %d, lut_num %d", 75 offset, pcfr->lut_num); 76 return NULL; 77 } 78 79 return pcfr->lut[offset]; 80 } 81 82 /** 83 * release_lut_entry_enh() - Clear all params in an LUT entry 84 * @pdev: objmgr PDEV 85 * @lut: pointer to LUT 86 * 87 * Return: status 88 */ 89 static int release_lut_entry_enh(struct wlan_objmgr_pdev *pdev, 90 struct look_up_table *lut) 91 { 92 lut->dbr_recv = false; 93 lut->tx_recv = false; 94 lut->data = NULL; 95 lut->data_len = 0; 96 lut->dbr_ppdu_id = 0; 97 lut->tx_ppdu_id = 0; 98 lut->dbr_tstamp = 0; 99 lut->txrx_tstamp = 0; 100 lut->tx_address1 = 0; 101 lut->tx_address2 = 0; 102 lut->dbr_address = 0; 103 qdf_mem_zero(&lut->header, sizeof(struct csi_cfr_header)); 104 105 return 0; 106 } 107 108 /** 109 * target_if_cfr_dump_lut_enh() - dump all valid lut entries 110 * @pdev: objmgr pdev 111 * 112 * return: none 113 */ 114 void target_if_cfr_dump_lut_enh(struct wlan_objmgr_pdev *pdev) 115 { 116 struct pdev_cfr *pcfr; 117 struct look_up_table *lut = NULL; 118 int i = 0; 119 uint64_t diff; 120 QDF_STATUS retval = 0; 121 122 retval = wlan_objmgr_pdev_try_get_ref(pdev, WLAN_CFR_ID); 123 if (retval != QDF_STATUS_SUCCESS) { 124 cfr_err("failed to get pdev reference"); 125 return; 126 } 127 128 pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev, 129 WLAN_UMAC_COMP_CFR); 130 if (!pcfr) { 131 cfr_err("pdev object for CFR is null"); 132 wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); 133 return; 134 } 135 136 qdf_spin_lock_bh(&pcfr->lut_lock); 137 138 for (i = 0; i < pcfr->lut_num; i++) { 139 lut = get_lut_entry(pcfr, i); 140 if (!lut) 141 continue; 142 if (lut->dbr_recv ^ lut->tx_recv) { 143 diff = (lut->dbr_tstamp > lut->txrx_tstamp) ? 144 (lut->dbr_tstamp - lut->txrx_tstamp) : 145 (lut->txrx_tstamp - lut->dbr_tstamp); 146 } 147 } 148 149 qdf_spin_unlock_bh(&pcfr->lut_lock); 150 151 wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); 152 } 153 154 /** 155 * cfr_free_pending_dbr_events() - Flush all pending DBR events. This is useful 156 * in cases where for RXTLV drops in host monitor status ring is huge. 157 * @pdev: objmgr pdev 158 * 159 * return: none 160 */ 161 static void cfr_free_pending_dbr_events(struct wlan_objmgr_pdev *pdev) 162 { 163 struct pdev_cfr *pcfr; 164 struct look_up_table *lut = NULL; 165 int i = 0; 166 QDF_STATUS retval = 0; 167 168 retval = wlan_objmgr_pdev_try_get_ref(pdev, WLAN_CFR_ID); 169 if (retval != QDF_STATUS_SUCCESS) { 170 cfr_err("failed to get pdev reference"); 171 return; 172 } 173 174 pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev, 175 WLAN_UMAC_COMP_CFR); 176 if (!pcfr) { 177 cfr_err("pdev object for CFR is null"); 178 wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); 179 return; 180 } 181 182 for (i = 0; i < pcfr->lut_num; i++) { 183 lut = get_lut_entry(pcfr, i); 184 if (!lut) 185 continue; 186 187 if (lut->dbr_recv && !lut->tx_recv && 188 (lut->dbr_tstamp < pcfr->last_success_tstamp)) { 189 target_if_dbr_buf_release(pdev, DBR_MODULE_CFR, 190 lut->dbr_address, 191 i, 0); 192 pcfr->flush_dbr_cnt++; 193 release_lut_entry_enh(pdev, lut); 194 } 195 } 196 wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); 197 } 198 199 /** 200 * dump_freeze_tlv() - Dump freeze TLV sent in enhanced DMA header 201 * @freeze_tlv: Freeze TLV sent from MAC to PHY 202 * @cookie: Index into lookup table 203 * 204 * Return: none 205 */ 206 static void dump_freeze_tlv(void *freeze_tlv, uint32_t cookie) 207 { 208 struct macrx_freeze_capture_channel *freeze = 209 (struct macrx_freeze_capture_channel *)freeze_tlv; 210 211 cfr_debug("<DBRCOMP><FREEZE><%u>\n" 212 "freeze: %d capture_reason: %d packet_type: 0x%x\n" 213 "packet_subtype: 0x%x sw_peer_id_valid: %d sw_peer_id: %d\n" 214 "phy_ppdu_id: 0x%04x packet_ta_upper_16: 0x%04x\n" 215 "packet_ta_mid_16: 0x%04x packet_ta_lower_16: 0x%04x\n" 216 "packet_ra_upper_16: 0x%04x packet_ra_mid_16: 0x%04x\n" 217 "packet_ra_lower_16: 0x%04x tsf_timestamp_63_48: 0x%04x\n" 218 "tsf_timestamp_47_32: 0x%04x tsf_timestamp_31_16: 0x%04x\n" 219 "tsf_timestamp_15_0: 0x%04x user_index_or_user_mask_5_0: %d\n" 220 "directed: %d\n", 221 cookie, 222 freeze->freeze, 223 freeze->capture_reason, 224 freeze->packet_type, 225 freeze->packet_sub_type, 226 freeze->sw_peer_id_valid, 227 freeze->sw_peer_id, 228 freeze->phy_ppdu_id, 229 freeze->packet_ta_upper_16, 230 freeze->packet_ta_mid_16, 231 freeze->packet_ta_lower_16, 232 freeze->packet_ra_upper_16, 233 freeze->packet_ra_mid_16, 234 freeze->packet_ra_lower_16, 235 freeze->tsf_timestamp_63_48, 236 freeze->tsf_timestamp_47_32, 237 freeze->tsf_timestamp_31_16, 238 freeze->tsf_timestamp_15_0, 239 freeze->user_index_or_user_mask_5_0, 240 freeze->directed); 241 } 242 243 /** 244 * dump_freeze_tlv_v3() - Dump freeze TLV v2 sent in enhanced DMA header 245 * @freeze_tlv: Freeze TLV sent from MAC to PHY 246 * @cookie: Index into lookup table 247 * 248 * Return: none 249 */ 250 static void dump_freeze_tlv_v3(void *freeze_tlv, uint32_t cookie) 251 { 252 struct macrx_freeze_capture_channel_v3 *freeze = 253 (struct macrx_freeze_capture_channel_v3 *)freeze_tlv; 254 255 cfr_debug("<DBRCOMP><FREEZE><%u>\n" 256 "freeze: %d capture_reason: %d packet_type: 0x%x\n" 257 "packet_subtype: 0x%x sw_peer_id_valid: %d sw_peer_id: %d\n" 258 "phy_ppdu_id: 0x%04x packet_ta_upper_16: 0x%04x\n" 259 "packet_ta_mid_16: 0x%04x packet_ta_lower_16: 0x%04x\n" 260 "packet_ra_upper_16: 0x%04x packet_ra_mid_16: 0x%04x\n" 261 "packet_ra_lower_16: 0x%04x\n" 262 "tsf_63_48_or_user_mask_36_32: 0x%04x\n" 263 "tsf_timestamp_47_32: 0x%04x\n" 264 "tsf_timestamp_31_16: 0x%04x\n" 265 "tsf_timestamp_15_0: 0x%04x\n" 266 "user_index_or_user_mask_15_0: 0x%04x\n" 267 "user_mask_31_16: 0x%04x\n" 268 "directed: %d\n", 269 cookie, 270 freeze->freeze, 271 freeze->capture_reason, 272 freeze->packet_type, 273 freeze->packet_sub_type, 274 freeze->sw_peer_id_valid, 275 freeze->sw_peer_id, 276 freeze->phy_ppdu_id, 277 freeze->packet_ta_upper_16, 278 freeze->packet_ta_mid_16, 279 freeze->packet_ta_lower_16, 280 freeze->packet_ra_upper_16, 281 freeze->packet_ra_mid_16, 282 freeze->packet_ra_lower_16, 283 freeze->tsf_63_48_or_user_mask_36_32, 284 freeze->tsf_timestamp_47_32, 285 freeze->tsf_timestamp_31_16, 286 freeze->tsf_timestamp_15_0, 287 freeze->user_index_or_user_mask_15_0, 288 freeze->user_mask_31_16, 289 freeze->directed); 290 } 291 292 /** 293 * dump_mu_rx_info() - Dump MU info in enhanced DMA header 294 * @mu_rx_user_info: MU info sent by ucode 295 * @mu_rx_num_users: Number of MU users in UL-MU-PPDU 296 * @cookie: Index into lookup table 297 * 298 * Return: none 299 */ 300 static void dump_mu_rx_info(void *mu_rx_user_info, 301 uint8_t mu_rx_num_users, 302 uint32_t cookie) 303 { 304 uint8_t i; 305 struct uplink_user_setup_info *ul_mu_user_info = 306 (struct uplink_user_setup_info *)mu_rx_user_info; 307 308 for (i = 0 ; i < mu_rx_num_users; i++) { 309 cfr_debug("<DBRCOMP><MU><%u>\n" 310 "<user_id:%d>\n" 311 "bw_info_valid = %d\n" 312 "uplink_receive_type = %d\n" 313 "uplink_11ax_mcs = %d\n" 314 "ru_width = %d\n" 315 "nss = %d\n" 316 "stream_offset = %d\n" 317 "sta_dcm = %d\n" 318 "sta_coding = %d\n" 319 "ru_start_index = %d\n", 320 cookie, 321 i, 322 ul_mu_user_info->bw_info_valid, 323 ul_mu_user_info->uplink_receive_type, 324 ul_mu_user_info->uplink_11ax_mcs, 325 ul_mu_user_info->ru_width, 326 ul_mu_user_info->nss, 327 ul_mu_user_info->stream_offset, 328 ul_mu_user_info->sta_dcm, 329 ul_mu_user_info->sta_coding, 330 ul_mu_user_info->ru_start_index); 331 ul_mu_user_info += sizeof(struct uplink_user_setup_info); 332 } 333 } 334 335 static void dump_metadata(struct csi_cfr_header *header, uint32_t cookie) 336 { 337 uint8_t user_id, chain_id; 338 struct enh_cfr_metadata *meta = &header->u.meta_enh; 339 uint8_t *usermac = NULL; 340 341 cfr_debug("<METADATA><%u>\n" 342 "start_magic_num = 0x%x\n" 343 "vendorid = 0x%x\n" 344 "cfr_metadata_version = %d\n" 345 "cfr_data_version = %d\n" 346 "cfr_metadata_len = %d\n" 347 "chip_type = %d\n" 348 "platform_type = %d\n" 349 "status = %d\n" 350 "capture_bw = %d\n" 351 "channel_bw = %d\n" 352 "phy_mode = %d\n" 353 "prim20_chan = %d\n" 354 "center_freq1 = %d\n" 355 "center_freq2 = %d\n" 356 "ack_capture_mode = %d\n" 357 "cfr_capture_type = %d\n" 358 "sts_count = %d\n" 359 "num_rx_chain = %d\n" 360 "timestamp = %llu\n" 361 "length = %d\n" 362 "is_mu_ppdu = %d\n" 363 "num_users = %d\n", 364 cookie, 365 header->cmn.start_magic_num, 366 header->cmn.vendorid, 367 header->cmn.cfr_metadata_version, 368 header->cmn.cfr_data_version, 369 header->cmn.cfr_metadata_len, 370 header->cmn.chip_type, 371 header->cmn.pltform_type, 372 meta->status, 373 meta->capture_bw, 374 meta->channel_bw, 375 meta->phy_mode, 376 meta->prim20_chan, 377 meta->center_freq1, 378 meta->center_freq2, 379 meta->capture_mode, 380 meta->capture_type, 381 meta->sts_count, 382 meta->num_rx_chain, 383 meta->timestamp, 384 meta->length, 385 meta->is_mu_ppdu, 386 meta->num_mu_users); 387 388 if (meta->is_mu_ppdu) { 389 for (user_id = 0; user_id < meta->num_mu_users; user_id++) { 390 usermac = meta->peer_addr.mu_peer_addr[user_id]; 391 cfr_debug("peermac[%d]: " QDF_MAC_ADDR_FMT, 392 user_id, QDF_MAC_ADDR_REF(usermac)); 393 } 394 } else { 395 cfr_debug("peermac: " QDF_MAC_ADDR_FMT, 396 QDF_MAC_ADDR_REF(meta->peer_addr.su_peer_addr)); 397 } 398 399 for (chain_id = 0; chain_id < HOST_MAX_CHAINS; chain_id++) { 400 cfr_debug("chain_rssi[%d] = %d\n", 401 chain_id, 402 meta->chain_rssi[chain_id]); 403 } 404 405 for (chain_id = 0; chain_id < HOST_MAX_CHAINS; chain_id++) { 406 cfr_debug("chain_phase[%d] = %d\n", 407 chain_id, 408 meta->chain_phase[chain_id]); 409 } 410 411 if (header->cmn.cfr_metadata_version >= CFR_META_VERSION_5) { 412 cfr_debug("rtt_cfo_measurement = %d\n", 413 meta->rtt_cfo_measurement); 414 cfr_debug("rx_start_ts = %u\n", meta->rx_start_ts); 415 416 for (chain_id = 0; chain_id < HOST_MAX_CHAINS; chain_id++) { 417 cfr_debug("agc_gain[%d] = %d\n", 418 chain_id, 419 meta->agc_gain[chain_id]); 420 } 421 422 cfr_debug("mcs_rate = %u\n", meta->mcs_rate); 423 cfr_debug("gi_type = %u\n", meta->gi_type); 424 } 425 } 426 427 /** 428 * dump_enh_dma_hdr() - Dump enhanced DMA header populated by ucode 429 * @dma_hdr: pointer to enhanced DMA header 430 * @freeze_tlv: pointer to MACRX_FREEZE_CAPTURE_CHANNEL TLV 431 * @mu_rx_user_info: UPLINK_USER_SETUP_INFO TLV 432 * @header: pointer to metadata passed to userspace 433 * @error: Indicates whether it is an error 434 * @cookie: Index into lookup table 435 * 436 * Return: none 437 */ 438 static void dump_enh_dma_hdr(struct whal_cfir_enhanced_hdr *dma_hdr, 439 void *freeze_tlv, void *mu_rx_user_info, 440 struct csi_cfr_header *header, int error, 441 uint32_t cookie) 442 { 443 if (!error) { 444 cfr_debug("<DBRCOMP><%u>\n" 445 "Tag: 0x%02x Length: %d udone: %d\n" 446 "ctype: %d preamble: %d Nss: %d\n" 447 "num_chains: %d bw: %d peervalid: %d\n" 448 "peer_id: %d ppdu_id: 0x%04x total_bytes: %d\n" 449 "header_version: %d target_id: %d cfr_fmt: %d\n" 450 "mu_rx_data_incl: %d freeze_data_incl: %d\n" 451 "mu_rx_num_users: %d decimation_factor: %d\n" 452 "freeze_tlv_version: %d\n", 453 cookie, 454 dma_hdr->tag, 455 dma_hdr->length, 456 dma_hdr->upload_done, 457 dma_hdr->capture_type, 458 dma_hdr->preamble_type, 459 dma_hdr->nss, 460 dma_hdr->num_chains, 461 dma_hdr->upload_pkt_bw, 462 dma_hdr->sw_peer_id_valid, 463 dma_hdr->sw_peer_id, 464 dma_hdr->phy_ppdu_id, 465 dma_hdr->total_bytes, 466 dma_hdr->header_version, 467 dma_hdr->target_id, 468 dma_hdr->cfr_fmt, 469 dma_hdr->mu_rx_data_incl, 470 dma_hdr->freeze_data_incl, 471 dma_hdr->mu_rx_num_users, 472 dma_hdr->decimation_factor, 473 dma_hdr->freeze_tlv_version); 474 475 if (dma_hdr->freeze_data_incl) { 476 if (dma_hdr->freeze_tlv_version == 477 MACRX_FREEZE_TLV_VERSION_3) 478 dump_freeze_tlv_v3(freeze_tlv, cookie); 479 else 480 dump_freeze_tlv(freeze_tlv, cookie); 481 } 482 483 if (dma_hdr->mu_rx_data_incl) 484 dump_mu_rx_info(mu_rx_user_info, 485 dma_hdr->mu_rx_num_users, 486 cookie); 487 } else { 488 cfr_err("<DBRCOMP><%u>\n" 489 "Tag: 0x%02x Length: %d udone: %d\n" 490 "ctype: %d preamble: %d Nss: %d\n" 491 "num_chains: %d bw: %d peervalid: %d\n" 492 "peer_id: %d ppdu_id: 0x%04x total_bytes: %d\n" 493 "header_version: %d target_id: %d cfr_fmt: %d\n" 494 "mu_rx_data_incl: %d freeze_data_incl: %d\n" 495 "mu_rx_num_users: %d decimation_factor: %d\n" 496 "freeze_tlv_version: %d\n", 497 cookie, 498 dma_hdr->tag, 499 dma_hdr->length, 500 dma_hdr->upload_done, 501 dma_hdr->capture_type, 502 dma_hdr->preamble_type, 503 dma_hdr->nss, 504 dma_hdr->num_chains, 505 dma_hdr->upload_pkt_bw, 506 dma_hdr->sw_peer_id_valid, 507 dma_hdr->sw_peer_id, 508 dma_hdr->phy_ppdu_id, 509 dma_hdr->total_bytes, 510 dma_hdr->header_version, 511 dma_hdr->target_id, 512 dma_hdr->cfr_fmt, 513 dma_hdr->mu_rx_data_incl, 514 dma_hdr->freeze_data_incl, 515 dma_hdr->mu_rx_num_users, 516 dma_hdr->decimation_factor, 517 dma_hdr->freeze_tlv_version); 518 } 519 } 520 521 /** 522 * extract_peer_mac_from_freeze_tlv() - extract macaddr from freeze tlv 523 * @freeze_tlv: Freeze TLV sent from MAC to PHY 524 * @peermac: macaddr of the peer 525 * 526 * Return: none 527 */ 528 static void 529 extract_peer_mac_from_freeze_tlv(void *freeze_tlv, uint8_t *peermac) 530 { 531 /* 532 * Packet_ta fields position is common between freeze tlv v1 533 * and v2, hence typecasting to v1 is also fine 534 */ 535 struct macrx_freeze_capture_channel *freeze = 536 (struct macrx_freeze_capture_channel *)freeze_tlv; 537 538 peermac[0] = freeze->packet_ta_lower_16 & 0x00FF; 539 peermac[1] = (freeze->packet_ta_lower_16 & 0xFF00) >> 8; 540 peermac[2] = freeze->packet_ta_mid_16 & 0x00FF; 541 peermac[3] = (freeze->packet_ta_mid_16 & 0xFF00) >> 8; 542 peermac[4] = freeze->packet_ta_upper_16 & 0x00FF; 543 peermac[5] = (freeze->packet_ta_upper_16 & 0xFF00) >> 8; 544 } 545 546 /** 547 * check_dma_length() - Sanity check DMA header and payload length 548 * @dma_hdr: pointer to enhanced DMA header 549 * 550 * Return: QDF_STATUS 551 */ 552 static QDF_STATUS check_dma_length(struct look_up_table *lut, 553 uint32_t target_type) 554 { 555 if (target_type == TARGET_TYPE_QCN9000) { 556 if (lut->header_length <= PINE_MAX_HEADER_LENGTH_WORDS && 557 lut->payload_length <= PINE_MAX_DATA_LENGTH_BYTES) { 558 return QDF_STATUS_SUCCESS; 559 } 560 } else if (target_type == TARGET_TYPE_QCN6122) { 561 if (lut->header_length <= SPRUCE_MAX_HEADER_LENGTH_WORDS && 562 lut->payload_length <= SPRUCE_MAX_DATA_LENGTH_BYTES) { 563 return QDF_STATUS_SUCCESS; 564 } 565 } else if (target_type == TARGET_TYPE_QCA5018) { 566 if (lut->header_length <= MAPLE_MAX_HEADER_LENGTH_WORDS && 567 lut->payload_length <= MAPLE_MAX_DATA_LENGTH_BYTES) { 568 return QDF_STATUS_SUCCESS; 569 } 570 } else { 571 if (lut->header_length <= CYP_MAX_HEADER_LENGTH_WORDS && 572 lut->payload_length <= CYP_MAX_DATA_LENGTH_BYTES) { 573 return QDF_STATUS_SUCCESS; 574 } 575 } 576 return QDF_STATUS_E_FAILURE; 577 } 578 579 /** 580 * correlate_and_relay_enh() - Correlate TXRX and DBR events and stream CFR 581 * data to userspace 582 * @pdev: objmgr PDEV 583 * @cookie: Index into lookup table 584 * @lut: pointer to lookup table 585 * @module_id: ID of the event received 586 * 0 - DBR event 587 * 1 - TXRX event 588 * 589 * Return: 590 * - STATUS_ERROR 591 * - STATUS_HOLD 592 * - STATUS_STREAM_AND_RELEASE 593 */ 594 static int correlate_and_relay_enh(struct wlan_objmgr_pdev *pdev, 595 uint32_t cookie, 596 struct look_up_table *lut, 597 uint8_t module_id) 598 { 599 struct pdev_cfr *pcfr; 600 uint64_t diff; 601 int status = STATUS_ERROR; 602 struct wlan_objmgr_psoc *psoc; 603 uint32_t target_type; 604 605 if (module_id > 1) { 606 cfr_err("Received request with invalid mod id. Investigate!!"); 607 QDF_ASSERT(0); 608 status = STATUS_ERROR; 609 goto done; 610 } 611 612 pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev, 613 WLAN_UMAC_COMP_CFR); 614 615 psoc = wlan_pdev_get_psoc(pdev); 616 if (qdf_unlikely(!psoc)) { 617 cfr_err("psoc is null\n"); 618 status = STATUS_ERROR; 619 goto done; 620 } 621 622 target_type = target_if_cfr_get_target_type(psoc); 623 624 if (module_id == CORRELATE_TX_EV_MODULE_ID) { 625 if (lut->tx_recv) 626 pcfr->cfr_dma_aborts++; 627 lut->tx_recv = true; 628 } else if (module_id == CORRELATE_DBR_MODULE_ID) { 629 pcfr->dbr_evt_cnt++; 630 lut->dbr_recv = true; 631 } 632 633 if ((lut->dbr_recv) && (lut->tx_recv)) { 634 if (lut->dbr_ppdu_id == lut->tx_ppdu_id) { 635 pcfr->last_success_tstamp = lut->dbr_tstamp; 636 if (lut->dbr_tstamp > lut->txrx_tstamp) { 637 diff = lut->dbr_tstamp - lut->txrx_tstamp; 638 cfr_debug("<CORRELATE><%u>: " 639 "TXRX evt -> DBR evt" 640 "(delay = %llu ms)\n", cookie, diff); 641 } else if (lut->txrx_tstamp > lut->dbr_tstamp) { 642 diff = lut->txrx_tstamp - lut->dbr_tstamp; 643 cfr_debug("<CORRELATE><%u>: " 644 "DBR evt -> TXRX evt" 645 "(delay = %llu ms)\n", cookie, diff); 646 } 647 648 /* 649 * Flush pending dbr events, if newer PPDU TLV is 650 * received 651 */ 652 cfr_free_pending_dbr_events(pdev); 653 654 if (check_dma_length(lut, target_type) == 655 QDF_STATUS_SUCCESS) { 656 pcfr->release_cnt++; 657 cfr_debug("<CORRELATE><%u>:Stream and release " 658 "CFR data for " 659 "ppdu_id:0x%04x\n", cookie, 660 lut->tx_ppdu_id); 661 status = STATUS_STREAM_AND_RELEASE; 662 goto done; 663 } else { 664 pcfr->invalid_dma_length_cnt++; 665 cfr_err("<CORRELATE><%u>:CFR buffers " 666 "received with invalid length " 667 "header_length_words = %d " 668 "cfr_payload_length_bytes = %d " 669 "ppdu_id:0x%04x\n", 670 cookie, 671 lut->header_length, 672 lut->payload_length, 673 lut->tx_ppdu_id); 674 /* 675 * Assert here as length exceeding the allowed 676 * limit would anyway manifest as random crash 677 */ 678 QDF_ASSERT(0); 679 status = STATUS_ERROR; 680 goto done; 681 } 682 } else { 683 /* 684 * When there is a ppdu id mismatch, discard the TXRX 685 * event since multiple PPDUs are likely to have same 686 * dma addr, due to ucode aborts 687 */ 688 cfr_debug("Received new dbr event for same " 689 "cookie %u", 690 cookie); 691 lut->tx_recv = false; 692 lut->tx_ppdu_id = 0; 693 pcfr->clear_txrx_event++; 694 pcfr->cfr_dma_aborts++; 695 status = STATUS_HOLD; 696 } 697 } else { 698 status = STATUS_HOLD; 699 } 700 done: 701 return status; 702 } 703 704 /** 705 * target_if_cfr_rx_tlv_process() - Process PPDU status TLVs and store info in 706 * lookup table 707 * @pdev_obj: PDEV object 708 * @nbuf: ppdu info 709 * 710 * Return: none 711 */ 712 void target_if_cfr_rx_tlv_process(struct wlan_objmgr_pdev *pdev, void *nbuf) 713 { 714 struct cdp_rx_indication_ppdu *cdp_rx_ppdu; 715 struct cdp_rx_stats_ppdu_user *rx_stats_peruser; 716 struct cdp_rx_ppdu_cfr_info *cfr_info; 717 qdf_dma_addr_t buf_addr = 0, buf_addr_extn = 0; 718 struct pdev_cfr *pcfr; 719 struct look_up_table *lut = NULL; 720 struct csi_cfr_header *header = NULL; 721 uint32_t cookie; 722 struct wlan_objmgr_psoc *psoc; 723 struct wlan_channel *bss_chan; 724 enum wlan_phymode ch_phymode; 725 uint16_t ch_freq; 726 uint32_t ch_cfreq1; 727 uint32_t ch_cfreq2; 728 struct wlan_objmgr_vdev *vdev = NULL; 729 int i, status = 0; 730 QDF_STATUS retval = 0; 731 struct wlan_lmac_if_cfr_rx_ops *cfr_rx_ops = NULL; 732 struct enh_cfr_metadata *meta = NULL; 733 uint8_t srng_id = 0; 734 struct wlan_lmac_if_rx_ops *rx_ops; 735 uint32_t target_type; 736 uint16_t pdelta, gain; 737 uint16_t gain_info[HOST_MAX_CHAINS]; 738 bool invalid_gain_table_idx = false; 739 740 if (qdf_unlikely(!pdev)) { 741 cfr_err("pdev is null\n"); 742 qdf_nbuf_free(nbuf); 743 return; 744 } 745 746 retval = wlan_objmgr_pdev_try_get_ref(pdev, WLAN_CFR_ID); 747 if (qdf_unlikely(retval != QDF_STATUS_SUCCESS)) { 748 cfr_err("failed to get pdev reference"); 749 qdf_nbuf_free(nbuf); 750 return; 751 } 752 753 pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev, 754 WLAN_UMAC_COMP_CFR); 755 if (qdf_unlikely(!pcfr)) { 756 cfr_err("pdev object for CFR is NULL"); 757 goto relref; 758 } 759 760 cdp_rx_ppdu = (struct cdp_rx_indication_ppdu *)qdf_nbuf_data(nbuf); 761 cfr_info = &cdp_rx_ppdu->cfr_info; 762 763 if (!cfr_info->bb_captured_channel) 764 goto relref; 765 766 psoc = wlan_pdev_get_psoc(pdev); 767 if (qdf_unlikely(!psoc)) { 768 cfr_err("psoc is null\n"); 769 goto relref; 770 } 771 772 rx_ops = wlan_psoc_get_lmac_if_rxops(psoc); 773 if (!rx_ops) { 774 cfr_err("rx_ops is NULL"); 775 goto relref; 776 } 777 target_type = target_if_cfr_get_target_type(psoc); 778 cfr_rx_ops = &rx_ops->cfr_rx_ops; 779 buf_addr_extn = cfr_info->rtt_che_buffer_pointer_high8 & 0xF; 780 buf_addr = (cfr_info->rtt_che_buffer_pointer_low32 | 781 ((uint64_t)buf_addr_extn << 32)); 782 783 srng_id = pcfr->rcc_param.srng_id; 784 if (target_if_dbr_cookie_lookup(pdev, DBR_MODULE_CFR, buf_addr, 785 &cookie, srng_id)) { 786 cfr_debug("Cookie lookup failure for addr: 0x%pK", 787 (void *)((uintptr_t)buf_addr)); 788 goto relref; 789 } 790 791 cfr_debug("<RXTLV><%u>:buffer address: 0x%pK\n" 792 "<WIFIRX_PPDU_START_E> ppdu_id: 0x%04x\n" 793 "<WIFIRXPCU_PPDU_END_INFO_E> BB_CAPTURED_CHANNEL = %d\n" 794 "<WIFIPHYRX_PKT_END_E> RX_LOCATION_INFO_VALID = %d\n" 795 "<WIFIPHYRX_PKT_END_E> RTT_CHE_BUFFER_POINTER_LOW32 = %x\n" 796 "<WIFIPHYRX_PKT_END_E> RTT_CHE_BUFFER_POINTER_HIGH8 = %x\n" 797 "<WIFIPHYRX_PKT_END_E> CHAN_CAPTURE_STATUS = %d\n", 798 cookie, 799 (void *)((uintptr_t)buf_addr), 800 cdp_rx_ppdu->ppdu_id, 801 cfr_info->bb_captured_channel, 802 cfr_info->rx_location_info_valid, 803 cfr_info->rtt_che_buffer_pointer_low32, 804 cfr_info->rtt_che_buffer_pointer_high8, 805 cfr_info->chan_capture_status); 806 807 qdf_spin_lock_bh(&pcfr->lut_lock); 808 809 lut = get_lut_entry(pcfr, cookie); 810 if (qdf_unlikely(!lut)) { 811 cfr_err("lut is NULL"); 812 goto unlock; 813 } 814 815 if (pcfr->rcc_param.vdev_id == CFR_INVALID_VDEV_ID) 816 vdev = wlan_objmgr_pdev_get_first_vdev(pdev, WLAN_CFR_ID); 817 else 818 vdev = wlan_objmgr_get_vdev_by_id_from_pdev( 819 pdev, pcfr->rcc_param.vdev_id, WLAN_CFR_ID); 820 if (qdf_unlikely(!vdev)) { 821 cfr_debug("vdev is null\n"); 822 goto unlock; 823 } 824 825 bss_chan = wlan_vdev_mlme_get_bss_chan(vdev); 826 ch_freq = bss_chan->ch_freq; 827 ch_cfreq1 = bss_chan->ch_cfreq1; 828 ch_cfreq2 = bss_chan->ch_cfreq2; 829 ch_phymode = bss_chan->ch_phymode; 830 wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID); 831 832 pcfr->rx_tlv_evt_cnt++; 833 lut->tx_ppdu_id = cdp_rx_ppdu->ppdu_id; 834 lut->tx_address1 = cfr_info->rtt_che_buffer_pointer_low32; 835 lut->tx_address2 = cfr_info->rtt_che_buffer_pointer_high8; 836 lut->txrx_tstamp = qdf_ktime_to_ms(qdf_ktime_get()); 837 header = &lut->header; 838 meta = &header->u.meta_enh; 839 840 target_if_cfr_fill_header(header, false, target_type, true); 841 842 meta->status = 1; 843 meta->phy_mode = ch_phymode; 844 meta->prim20_chan = ch_freq; 845 meta->center_freq1 = ch_cfreq1; 846 meta->center_freq2 = ch_cfreq2; 847 meta->capture_mode = 0; 848 849 meta->timestamp = cdp_rx_ppdu->timestamp; 850 meta->is_mu_ppdu = (cdp_rx_ppdu->u.ppdu_type == CDP_RX_TYPE_SU) ? 0 : 1; 851 meta->num_mu_users = (meta->is_mu_ppdu) ? (cdp_rx_ppdu->num_users) : 0; 852 853 meta->rtt_cfo_measurement = cfr_info->rtt_cfo_measurement; 854 meta->rx_start_ts = cfr_info->rx_start_ts; 855 856 gain_info[0] = get_u16_lsb(cfr_info->agc_gain_info0); 857 gain_info[1] = get_u16_msb(cfr_info->agc_gain_info0); 858 gain_info[2] = get_u16_lsb(cfr_info->agc_gain_info1); 859 gain_info[3] = get_u16_msb(cfr_info->agc_gain_info1); 860 gain_info[4] = get_u16_lsb(cfr_info->agc_gain_info2); 861 gain_info[5] = get_u16_msb(cfr_info->agc_gain_info2); 862 gain_info[6] = get_u16_lsb(cfr_info->agc_gain_info3); 863 gain_info[7] = get_u16_msb(cfr_info->agc_gain_info3); 864 865 for (i = 0; i < HOST_MAX_CHAINS; i++) { 866 meta->agc_gain[i] = get_gain_db(gain_info[i]); 867 868 if (pcfr->is_aoa_for_rcc_support && 869 (i < pcfr->max_aoa_chains) && 870 (get_gain_table_idx(gain_info[i]) != 0)) { 871 cfr_debug("Invalid gain table index reported"); 872 invalid_gain_table_idx = true; 873 } 874 875 if (meta->agc_gain[i] > MAX_AGC_GAIN) 876 meta->agc_gain[i] = MAX_AGC_GAIN; 877 } 878 879 /** 880 * Do not derive the chain phase when capability is not set Or 881 * when an invalid gain table index is reported by Hardware. 882 */ 883 if (pcfr->is_aoa_for_rcc_support && !invalid_gain_table_idx) { 884 for (i = 0; i < pcfr->max_aoa_chains; i++) { 885 /** 886 * phase delta stored in reverse order by FW. 887 * Hence, index accordingly 888 */ 889 gain = meta->agc_gain[i]; 890 if (gain < MAX_AGC_GAIN) { 891 pdelta = pcfr->phase_delta[i][MAX_AGC_GAIN - 892 1 - 893 gain]; 894 } else { 895 pdelta = 0; 896 } 897 /** 898 * FW sets 0xFFFF as invalid phase delta in 899 * invalid cases. Retain same in HOST as well. 900 * In case of valid phase, add the ibf cal value 901 * to the delta & ensure the derived phase value 902 * is in the range of 0 - 1024 indicating 0 - 360 903 * degrees 904 */ 905 if (pdelta == INVALID_PHASE_DELTA) 906 meta->chain_phase[i] = INVALID_PHASE_DELTA; 907 else 908 meta->chain_phase[i] = ((pcfr->ibf_cal_val[i] + 909 pdelta) % 1024); 910 } 911 } else if (pcfr->is_aoa_for_rcc_support) { 912 /** 913 * When AoA is enabled but invalid gain table index is reported 914 * by HW, it indicates the AoA result is not reliable. Hence, 915 * set the chain_phase to 0xFFFF indicating an error. 916 */ 917 for (i = 0; i < pcfr->max_aoa_chains; i++) { 918 meta->chain_phase[i] = INVALID_PHASE_DELTA; 919 } 920 } 921 922 meta->mcs_rate = cfr_info->mcs_rate; 923 meta->gi_type = cfr_info->gi_type; 924 meta->sig_info.ltf_size = cdp_rx_ppdu->u.ltf_size; 925 meta->sig_info.stbc = cdp_rx_ppdu->u.stbc; 926 meta->sig_info.sgi = (cdp_rx_ppdu->u.gi == CDP_SGI_0_4_US) ? 1 : 0; 927 meta->sig_info.dcm = cdp_rx_ppdu->u.dcm; 928 meta->sig_info.coding = cdp_rx_ppdu->u.ldpc; 929 meta->sig_info.beamformed = cdp_rx_ppdu->beamformed; 930 931 if (meta->num_mu_users > pcfr->max_mu_users) 932 meta->num_mu_users = pcfr->max_mu_users; 933 934 for (i = 0; i < MAX_CHAIN; i++) 935 meta->chain_rssi[i] = 936 snr_to_signal_strength(cdp_rx_ppdu->per_chain_rssi[i]); 937 938 if (cdp_rx_ppdu->u.ppdu_type != CDP_RX_TYPE_SU) { 939 for (i = 0 ; i < meta->num_mu_users; i++) { 940 rx_stats_peruser = &cdp_rx_ppdu->user[i]; 941 qdf_mem_copy(meta->peer_addr.mu_peer_addr[i], 942 rx_stats_peruser->mac_addr, 943 QDF_MAC_ADDR_SIZE); 944 } 945 } 946 status = correlate_and_relay_enh(pdev, cookie, lut, 947 CORRELATE_TX_EV_MODULE_ID); 948 if (status == STATUS_STREAM_AND_RELEASE) { 949 if (cfr_rx_ops->cfr_info_send) 950 status = cfr_rx_ops->cfr_info_send(pdev, 951 &lut->header, 952 sizeof(struct 953 csi_cfr_header), 954 lut->data, 955 lut->data_len, 956 &end_magic, 4); 957 dump_metadata(header, cookie); 958 release_lut_entry_enh(pdev, lut); 959 target_if_dbr_buf_release(pdev, DBR_MODULE_CFR, buf_addr, 960 cookie, srng_id); 961 } 962 963 unlock: 964 qdf_spin_unlock_bh(&pcfr->lut_lock); 965 relref: 966 qdf_nbuf_free(nbuf); 967 wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); 968 } 969 970 /** 971 * freeze_reason_to_capture_type() - Convert capture type enum in freeze tlv 972 * to the cfr type enum shared with userspace 973 * @freeze_tlv: pointer to MACRX_FREEZE_CAPTURE_CHANNEL TLV 974 * 975 * Return: cfr type enum 976 */ 977 static uint8_t freeze_reason_to_capture_type(void *freeze_tlv) 978 { 979 /* 980 * Capture_reason field position is common between freeze_tlv v1 981 * and v2, hence typcasting to any one is fine 982 */ 983 struct macrx_freeze_capture_channel *freeze = 984 (struct macrx_freeze_capture_channel *)freeze_tlv; 985 986 switch (freeze->capture_reason) { 987 case FREEZE_REASON_TM: 988 return CFR_TYPE_METHOD_TM; 989 case FREEZE_REASON_FTM: 990 return CFR_TYPE_METHOD_FTM; 991 case FREEZE_REASON_TA_RA_TYPE_FILTER: 992 return CFR_TYPE_METHOD_TA_RA_TYPE_FILTER; 993 case FREEZE_REASON_NDPA_NDP: 994 return CFR_TYPE_METHOD_NDPA_NDP; 995 case FREEZE_REASON_ALL_PACKET: 996 return CFR_TYPE_METHOD_ALL_PACKET; 997 case FREEZE_REASON_ACK_RESP_TO_TM_FTM: 998 return CFR_TYPE_METHOD_ACK_RESP_TO_TM_FTM; 999 default: 1000 return CFR_TYPE_METHOD_AUTO; 1001 } 1002 return CFR_TYPE_METHOD_AUTO; 1003 } 1004 1005 #ifdef DIRECT_BUF_RX_ENABLE 1006 /** 1007 * enh_cfr_dbr_event_handler() - Process DBR event for CFR data DMA completion 1008 * @pdev: PDEV object 1009 * @payload: pointer to CFR data 1010 * 1011 * Return: status 1012 */ 1013 static bool enh_cfr_dbr_event_handler(struct wlan_objmgr_pdev *pdev, 1014 struct direct_buf_rx_data *payload) 1015 { 1016 uint8_t *data = NULL; 1017 uint32_t cookie = 0; 1018 struct whal_cfir_enhanced_hdr dma_hdr = {0}; 1019 int length, status = 0; 1020 struct wlan_objmgr_psoc *psoc; 1021 struct pdev_cfr *pcfr; 1022 struct look_up_table *lut = NULL; 1023 struct csi_cfr_header *header = NULL; 1024 void *mu_rx_user_info = NULL, *freeze_tlv = NULL; 1025 uint8_t capture_type = CFR_TYPE_METHOD_AUTO; 1026 uint8_t *peer_macaddr = NULL; 1027 struct wlan_lmac_if_cfr_rx_ops *cfr_rx_ops = NULL; 1028 struct enh_cfr_metadata *meta = NULL; 1029 struct wlan_lmac_if_rx_ops *rx_ops; 1030 1031 if ((!pdev) || (!payload)) { 1032 cfr_err("pdev or payload is null"); 1033 return true; 1034 } 1035 1036 psoc = wlan_pdev_get_psoc(pdev); 1037 if (!psoc) { 1038 cfr_err("psoc is null"); 1039 return true; 1040 } 1041 1042 rx_ops = wlan_psoc_get_lmac_if_rxops(psoc); 1043 if (!rx_ops) { 1044 cfr_err("rx_ops is NULL"); 1045 return true; 1046 } 1047 cfr_rx_ops = &rx_ops->cfr_rx_ops; 1048 1049 pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev, 1050 WLAN_UMAC_COMP_CFR); 1051 if (!pcfr) { 1052 cfr_err("pdev object for CFR is null"); 1053 return true; 1054 } 1055 1056 data = payload->vaddr; 1057 cookie = payload->cookie; 1058 1059 cfr_debug("<DBRCOMP><%u>:bufferaddr: 0x%pK cookie: %u\n", cookie, 1060 (void *)((uintptr_t)payload->paddr), cookie); 1061 1062 qdf_mem_copy(&dma_hdr, &data[0], 1063 sizeof(struct whal_cfir_enhanced_hdr)); 1064 1065 if (dma_hdr.freeze_data_incl) { 1066 freeze_tlv = data + sizeof(struct whal_cfir_enhanced_hdr); 1067 capture_type = freeze_reason_to_capture_type(freeze_tlv); 1068 } 1069 1070 if (dma_hdr.mu_rx_data_incl) { 1071 uint8_t freeze_tlv_len; 1072 1073 if (dma_hdr.freeze_tlv_version == MACRX_FREEZE_TLV_VERSION_3) { 1074 freeze_tlv_len = 1075 sizeof(struct macrx_freeze_capture_channel_v3); 1076 } else { 1077 freeze_tlv_len = 1078 sizeof(struct macrx_freeze_capture_channel); 1079 } 1080 mu_rx_user_info = data + 1081 sizeof(struct whal_cfir_enhanced_hdr) + 1082 (dma_hdr.freeze_data_incl ? freeze_tlv_len : 0); 1083 } 1084 1085 length = dma_hdr.length * 4; 1086 length += dma_hdr.total_bytes; /* size of cfr data */ 1087 1088 qdf_spin_lock_bh(&pcfr->lut_lock); 1089 1090 lut = get_lut_entry(pcfr, cookie); 1091 if (!lut) { 1092 cfr_err("lut is NULL"); 1093 qdf_spin_unlock_bh(&pcfr->lut_lock); 1094 return true; 1095 } 1096 1097 lut->data = data; 1098 lut->data_len = length; 1099 lut->dbr_ppdu_id = dma_hdr.phy_ppdu_id; 1100 lut->dbr_address = payload->paddr; 1101 lut->dbr_tstamp = qdf_ktime_to_ms(qdf_ktime_get()); 1102 lut->header_length = dma_hdr.length; 1103 lut->payload_length = dma_hdr.total_bytes; 1104 qdf_mem_copy(&lut->dma_hdr, &dma_hdr, 1105 sizeof(struct whal_cfir_dma_hdr)); 1106 1107 header = &lut->header; 1108 header->cmn.chip_type = pcfr->chip_type; 1109 meta = &header->u.meta_enh; 1110 meta->channel_bw = dma_hdr.upload_pkt_bw; 1111 meta->num_rx_chain = NUM_CHAINS_FW_TO_HOST(dma_hdr.num_chains); 1112 meta->length = length; 1113 /* For Tx based captures, capture type is sent from FW */ 1114 if (capture_type != CFR_TYPE_METHOD_ACK_RESP_TO_TM_FTM) { 1115 meta->capture_type = capture_type; 1116 meta->sts_count = (dma_hdr.nss + 1); 1117 if (!dma_hdr.mu_rx_data_incl) { 1118 /* extract peer addr from freeze tlv */ 1119 peer_macaddr = meta->peer_addr.su_peer_addr; 1120 if (dma_hdr.freeze_data_incl) { 1121 extract_peer_mac_from_freeze_tlv(freeze_tlv, 1122 peer_macaddr); 1123 } 1124 } 1125 } 1126 1127 if (dma_hdr.freeze_data_incl) { 1128 dump_enh_dma_hdr(&dma_hdr, freeze_tlv, mu_rx_user_info, 1129 header, 0, cookie); 1130 } 1131 1132 status = correlate_and_relay_enh(pdev, cookie, lut, 1133 CORRELATE_DBR_MODULE_ID); 1134 if (status == STATUS_STREAM_AND_RELEASE) { 1135 /* 1136 * Message format 1137 * Meta data Header + actual payload + trailer 1138 */ 1139 if (cfr_rx_ops->cfr_info_send) 1140 status = cfr_rx_ops->cfr_info_send(pdev, 1141 &lut->header, 1142 sizeof(struct 1143 csi_cfr_header), 1144 lut->data, 1145 lut->data_len, 1146 &end_magic, 4); 1147 dump_metadata(header, cookie); 1148 release_lut_entry_enh(pdev, lut); 1149 status = true; 1150 } else if (status == STATUS_HOLD) { 1151 status = false; 1152 } else { 1153 status = true; 1154 } 1155 1156 qdf_spin_unlock_bh(&pcfr->lut_lock); 1157 return status; 1158 } 1159 1160 /** 1161 * target_if_register_to_dbr_enh() - Initialize DBR ring and register callback 1162 * for DBR events 1163 * @pdev: PDEV object 1164 * 1165 * Return: status 1166 */ 1167 static QDF_STATUS 1168 target_if_register_to_dbr_enh(struct wlan_objmgr_pdev *pdev) 1169 { 1170 struct wlan_objmgr_psoc *psoc; 1171 struct wlan_lmac_if_direct_buf_rx_tx_ops *dbr_tx_ops = NULL; 1172 struct dbr_module_config dbr_config; 1173 struct wlan_lmac_if_tx_ops *tx_ops; 1174 1175 psoc = wlan_pdev_get_psoc(pdev); 1176 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 1177 if (!tx_ops) { 1178 cfr_err("tx_ops is NULL"); 1179 return QDF_STATUS_SUCCESS; 1180 } 1181 dbr_tx_ops = &tx_ops->dbr_tx_ops; 1182 dbr_config.num_resp_per_event = DBR_NUM_RESP_PER_EVENT_CFR; 1183 dbr_config.event_timeout_in_ms = DBR_EVENT_TIMEOUT_IN_MS_CFR; 1184 if (dbr_tx_ops->direct_buf_rx_module_register) { 1185 return dbr_tx_ops->direct_buf_rx_module_register 1186 (pdev, DBR_MODULE_CFR, &dbr_config, 1187 enh_cfr_dbr_event_handler); 1188 } 1189 1190 return QDF_STATUS_SUCCESS; 1191 } 1192 1193 /** 1194 * target_if_unregister_to_dbr_enh() - Unregister callback for DBR events 1195 * @pdev: PDEV object 1196 * 1197 * Return: status 1198 */ 1199 static QDF_STATUS 1200 target_if_unregister_to_dbr_enh(struct wlan_objmgr_pdev *pdev) 1201 { 1202 struct wlan_objmgr_psoc *psoc; 1203 struct wlan_lmac_if_direct_buf_rx_tx_ops *dbr_tx_ops = NULL; 1204 struct wlan_lmac_if_tx_ops *tx_ops; 1205 1206 psoc = wlan_pdev_get_psoc(pdev); 1207 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 1208 if (!tx_ops) { 1209 cfr_err("tx_ops is NULL"); 1210 return QDF_STATUS_SUCCESS; 1211 } 1212 dbr_tx_ops = &tx_ops->dbr_tx_ops; 1213 if (dbr_tx_ops->direct_buf_rx_module_unregister) { 1214 return dbr_tx_ops->direct_buf_rx_module_unregister 1215 (pdev, DBR_MODULE_CFR); 1216 } 1217 1218 return QDF_STATUS_SUCCESS; 1219 } 1220 #endif 1221 1222 /** 1223 * dump_cfr_peer_tx_event_enh() - Dump TX completion event 1224 * @event: ptr to WMI TX completion event for QOS frames sent during 1225 * one-shot capture 1226 * @cookie: Index into lookup table 1227 * 1228 * Return: none 1229 */ 1230 static void dump_cfr_peer_tx_event_enh(wmi_cfr_peer_tx_event_param *event, 1231 uint32_t cookie) 1232 { 1233 cfr_debug("<TXCOMP><%u>CFR capture method: %d vdev_id: %d mac: " 1234 QDF_MAC_ADDR_FMT, cookie, 1235 event->capture_method, event->vdev_id, 1236 QDF_MAC_ADDR_REF(event->peer_mac_addr.bytes)); 1237 1238 cfr_debug("<TXCOMP><%u>Chan: %d bw: %d phymode: %d cfreq1: %d cfrq2: %d " 1239 "nss: %d\n", 1240 cookie, 1241 event->primary_20mhz_chan, event->bandwidth, 1242 event->phy_mode, event->band_center_freq1, 1243 event->band_center_freq2, event->spatial_streams); 1244 1245 cfr_debug("<TXCOMP><%u>Correlation_info1: 0x%08x " 1246 "Correlation_info2: 0x%08x\n", 1247 cookie, 1248 event->correlation_info_1, event->correlation_info_2); 1249 1250 cfr_debug("<TXCOMP><%u>status: 0x%x ts: %d counter: %d rssi0: 0x%08x\n", 1251 cookie, 1252 event->status, event->timestamp_us, event->counter, 1253 event->chain_rssi[0]); 1254 } 1255 1256 static void 1257 populate_phase_delta(struct pdev_cfr *pcfr, 1258 struct wmi_cfr_phase_delta_param param) 1259 { 1260 int c, g, pc, pg; 1261 uint32_t c_mask = param.chain_phase_mask; 1262 1263 pc = 0; 1264 1265 /* populate phase delta for max chains indicated by target */ 1266 for (c = 0; c < pcfr->max_aoa_chains; c++) { 1267 pg = 0; 1268 if (((0x1 << c) & c_mask) && (pc < WMI_MAX_CHAINS_PHASE)) { 1269 pcfr->ibf_cal_val[c] = param.ibf_cal_val[pc]; 1270 for (g = 0; g < MAX_AGC_GAIN; g = g + 2) { 1271 if (pg < WMI_MAX_AOA_PHASE_DELTA) { 1272 pcfr->phase_delta[c][g] = get_u16_lsb 1273 (param.phase_delta[pc][pg]); 1274 pcfr->phase_delta[c][g + 1] = get_u16_msb 1275 (param.phase_delta[pc][pg]); 1276 pg++; 1277 } 1278 } 1279 pc++; 1280 } 1281 } 1282 } 1283 1284 static int 1285 target_if_pdev_aoa_phasedaelta_event_handler(ol_scn_t sc, 1286 uint8_t *data, 1287 uint32_t datalen) 1288 { 1289 struct wmi_unified *wmi_handle; 1290 struct wlan_objmgr_psoc *psoc; 1291 struct wlan_objmgr_pdev *pdev; 1292 struct pdev_cfr *pcfr; 1293 QDF_STATUS retval = 0; 1294 struct wmi_cfr_phase_delta_param param = {0}; 1295 1296 if (!sc || !data) { 1297 cfr_err("sc or data is null"); 1298 return -EINVAL; 1299 } 1300 1301 psoc = target_if_get_psoc_from_scn_hdl(sc); 1302 if (!psoc) { 1303 cfr_err("psoc is null"); 1304 return -EINVAL; 1305 } 1306 1307 retval = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_CFR_ID); 1308 if (QDF_IS_STATUS_ERROR(retval)) { 1309 cfr_err("unable to get psoc reference"); 1310 return -EINVAL; 1311 } 1312 1313 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 1314 if (!wmi_handle) { 1315 cfr_err("wmi_handle is null"); 1316 wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID); 1317 return -EINVAL; 1318 } 1319 1320 retval = wmi_extract_cfr_pdev_phase_delta_event 1321 (wmi_handle, data, ¶m); 1322 1323 if (QDF_IS_STATUS_ERROR(retval)) { 1324 cfr_err("Failed to extract phase params"); 1325 wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID); 1326 return -EINVAL; 1327 } 1328 1329 pdev = wlan_objmgr_get_pdev_by_id(psoc, param.pdev_id, WLAN_CFR_ID); 1330 if (!pdev) { 1331 cfr_err("pdev is null"); 1332 wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID); 1333 return -EINVAL; 1334 } 1335 1336 pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR); 1337 if (!pcfr) { 1338 cfr_err("pdev object for CFR is NULL"); 1339 wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID); 1340 wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); 1341 return -EINVAL; 1342 } 1343 1344 if (!pcfr->is_aoa_for_rcc_support) { 1345 cfr_err("AoA data event from unsupported target"); 1346 } 1347 1348 pcfr->freq = param.freq; 1349 pcfr->max_aoa_chains = (param.max_chains <= HOST_MAX_CHAINS) ? 1350 param.max_chains : HOST_MAX_CHAINS; 1351 1352 populate_phase_delta(pcfr, param); 1353 1354 wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID); 1355 wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); 1356 1357 return retval; 1358 } 1359 1360 #ifdef DIRECT_BUF_RX_ENABLE 1361 /** 1362 * enh_prepare_cfr_header_txstatus() - Prepare CFR metadata for TX failures 1363 * @tx_evt_param: ptr to WMI TX completion event 1364 * @header: pointer to metadata 1365 * 1366 * Return: none 1367 */ 1368 static void enh_prepare_cfr_header_txstatus(wmi_cfr_peer_tx_event_param 1369 *tx_evt_param, 1370 struct csi_cfr_header *header, 1371 uint32_t target_type) 1372 { 1373 target_if_cfr_fill_header(header, false, target_type, false); 1374 header->u.meta_enh.status = 0; /* failure */ 1375 header->u.meta_enh.length = 0; 1376 header->u.meta_enh.rtt_cfo_measurement = tx_evt_param->cfo_measurement; 1377 header->u.meta_enh.rx_start_ts = tx_evt_param->rx_start_ts; 1378 1379 qdf_mem_copy(&header->u.meta_enh.peer_addr.su_peer_addr[0], 1380 &tx_evt_param->peer_mac_addr.bytes[0], QDF_MAC_ADDR_SIZE); 1381 } 1382 1383 /** 1384 * target_if_peer_capture_event() - WMI TX completion event for one-shot 1385 * capture 1386 * @sc: pointer to offload soc object 1387 * @data: WMI TX completion event buffer 1388 * @datalen: WMI Tx completion event buffer length 1389 * 1390 * Return: status 1391 */ 1392 static int 1393 target_if_peer_capture_event(ol_scn_t sc, uint8_t *data, uint32_t datalen) 1394 { 1395 QDF_STATUS retval = 0; 1396 struct wmi_unified *wmi_handle; 1397 struct wlan_objmgr_psoc *psoc; 1398 struct wlan_objmgr_pdev *pdev; 1399 struct wlan_objmgr_vdev *vdev; 1400 uint32_t cookie; 1401 struct pdev_cfr *pcfr; 1402 struct look_up_table *lut = NULL; 1403 struct csi_cfr_header *header = NULL; 1404 struct csi_cfr_header header_error = {{0} }; 1405 wmi_cfr_peer_tx_event_param tx_evt_param = {0}; 1406 qdf_dma_addr_t buf_addr = 0, buf_addr_temp = 0; 1407 int status; 1408 struct wlan_channel *bss_chan; 1409 struct wlan_lmac_if_cfr_rx_ops *cfr_rx_ops = NULL; 1410 struct wlan_lmac_if_rx_ops *rx_ops; 1411 uint32_t target_type; 1412 1413 if (!sc || !data) { 1414 cfr_err("sc or data is null"); 1415 return -EINVAL; 1416 } 1417 1418 psoc = target_if_get_psoc_from_scn_hdl(sc); 1419 if (!psoc) { 1420 cfr_err("psoc is null"); 1421 return -EINVAL; 1422 } 1423 1424 rx_ops = wlan_psoc_get_lmac_if_rxops(psoc); 1425 if (!rx_ops) { 1426 cfr_err("rx_ops is NULL"); 1427 return -EINVAL; 1428 } 1429 cfr_rx_ops = &rx_ops->cfr_rx_ops; 1430 1431 retval = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_CFR_ID); 1432 if (QDF_IS_STATUS_ERROR(retval)) { 1433 cfr_err("unable to get psoc reference"); 1434 return -EINVAL; 1435 } 1436 1437 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 1438 if (!wmi_handle) { 1439 cfr_err("wmi_handle is null"); 1440 wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID); 1441 return -EINVAL; 1442 } 1443 1444 retval = wmi_extract_cfr_peer_tx_event_param(wmi_handle, data, 1445 &tx_evt_param); 1446 1447 if (retval != QDF_STATUS_SUCCESS) { 1448 cfr_err("Failed to extract cfr tx event param"); 1449 wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID); 1450 return -EINVAL; 1451 } 1452 1453 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, tx_evt_param.vdev_id, 1454 WLAN_CFR_ID); 1455 if (!vdev) { 1456 cfr_err("vdev is null"); 1457 wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID); 1458 return -EINVAL; 1459 } 1460 1461 pdev = wlan_vdev_get_pdev(vdev); 1462 if (!pdev) { 1463 cfr_err("pdev is null"); 1464 wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID); 1465 wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID); 1466 return -EINVAL; 1467 } 1468 1469 retval = wlan_objmgr_pdev_try_get_ref(pdev, WLAN_CFR_ID); 1470 if (retval != QDF_STATUS_SUCCESS) { 1471 cfr_err("failed to get pdev reference"); 1472 wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID); 1473 wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID); 1474 return -EINVAL; 1475 } 1476 1477 pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev, 1478 WLAN_UMAC_COMP_CFR); 1479 if (!pcfr) { 1480 cfr_err("pdev object for CFR is NULL"); 1481 retval = -EINVAL; 1482 goto relref; 1483 } 1484 1485 target_type = target_if_cfr_get_target_type(psoc); 1486 1487 if (tx_evt_param.status & PEER_CFR_CAPTURE_EVT_PS_STATUS_MASK) { 1488 cfr_err("CFR capture failed as peer is in powersave: " 1489 QDF_MAC_ADDR_FMT, 1490 QDF_MAC_ADDR_REF(tx_evt_param.peer_mac_addr.bytes)); 1491 1492 enh_prepare_cfr_header_txstatus(&tx_evt_param, 1493 &header_error, 1494 target_type); 1495 if (cfr_rx_ops->cfr_info_send) 1496 cfr_rx_ops->cfr_info_send(pdev, 1497 &header_error, 1498 sizeof(struct 1499 csi_cfr_header), 1500 NULL, 0, &end_magic, 4); 1501 1502 retval = -EINVAL; 1503 goto relref; 1504 } 1505 1506 if ((tx_evt_param.status & PEER_CFR_CAPTURE_EVT_STATUS_MASK) == 0) { 1507 cfr_debug("CFR capture failed for peer: " QDF_MAC_ADDR_FMT, 1508 QDF_MAC_ADDR_REF(tx_evt_param.peer_mac_addr.bytes)); 1509 pcfr->tx_peer_status_cfr_fail++; 1510 retval = -EINVAL; 1511 goto relref; 1512 } 1513 1514 if (tx_evt_param.status & CFR_TX_EVT_STATUS_MASK) { 1515 cfr_debug("TX packet returned status %d for peer: " 1516 QDF_MAC_ADDR_FMT, 1517 tx_evt_param.status & CFR_TX_EVT_STATUS_MASK, 1518 QDF_MAC_ADDR_REF(tx_evt_param.peer_mac_addr.bytes)); 1519 pcfr->tx_evt_status_cfr_fail++; 1520 retval = -EINVAL; 1521 goto relref; 1522 } 1523 1524 buf_addr_temp = (tx_evt_param.correlation_info_2 & 0x0f); 1525 buf_addr = (tx_evt_param.correlation_info_1 | 1526 ((uint64_t)buf_addr_temp << 32)); 1527 1528 if (target_if_dbr_cookie_lookup(pdev, DBR_MODULE_CFR, buf_addr, 1529 &cookie, 0)) { 1530 cfr_debug("Cookie lookup failure for addr: 0x%pK status: 0x%x", 1531 (void *)((uintptr_t)buf_addr), tx_evt_param.status); 1532 pcfr->tx_dbr_cookie_lookup_fail++; 1533 retval = -EINVAL; 1534 goto relref; 1535 } 1536 1537 cfr_debug("buffer address: 0x%pK cookie: %u", 1538 (void *)((uintptr_t)buf_addr), cookie); 1539 1540 dump_cfr_peer_tx_event_enh(&tx_evt_param, cookie); 1541 1542 qdf_spin_lock_bh(&pcfr->lut_lock); 1543 1544 lut = get_lut_entry(pcfr, cookie); 1545 if (!lut) { 1546 cfr_err("lut is NULL\n"); 1547 retval = -EINVAL; 1548 goto unlock; 1549 } 1550 1551 pcfr->tx_evt_cnt++; 1552 pcfr->total_tx_evt_cnt++; 1553 1554 lut->tx_ppdu_id = (tx_evt_param.correlation_info_2 >> 16); 1555 lut->tx_address1 = tx_evt_param.correlation_info_1; 1556 lut->tx_address2 = tx_evt_param.correlation_info_2; 1557 lut->txrx_tstamp = qdf_ktime_to_ms(qdf_ktime_get()); 1558 1559 header = &lut->header; 1560 target_if_cfr_fill_header(header, false, target_type, false); 1561 header->u.meta_enh.status = (tx_evt_param.status & 1562 PEER_CFR_CAPTURE_EVT_STATUS_MASK) ? 1563 1 : 0; 1564 header->u.meta_enh.capture_bw = tx_evt_param.bandwidth; 1565 1566 bss_chan = wlan_vdev_mlme_get_bss_chan(vdev); 1567 header->u.meta_enh.phy_mode = bss_chan->ch_phymode; 1568 1569 header->u.meta_enh.prim20_chan = tx_evt_param.primary_20mhz_chan; 1570 header->u.meta_enh.center_freq1 = tx_evt_param.band_center_freq1; 1571 header->u.meta_enh.center_freq2 = tx_evt_param.band_center_freq2; 1572 1573 /* Currently CFR data is captured on ACK of a Qos NULL frame. 1574 * For 20 MHz, ACK is Legacy and for 40/80/160, ACK is DUP Legacy. 1575 */ 1576 header->u.meta_enh.capture_mode = tx_evt_param.bandwidth ? 1577 CFR_DUP_LEGACY_ACK : CFR_LEGACY_ACK; 1578 header->u.meta_enh.capture_type = tx_evt_param.capture_method; 1579 header->u.meta_enh.num_rx_chain = wlan_vdev_mlme_get_rxchainmask(vdev); 1580 header->u.meta_enh.sts_count = tx_evt_param.spatial_streams; 1581 header->u.meta_enh.timestamp = tx_evt_param.timestamp_us; 1582 1583 qdf_mem_copy(&header->u.meta_enh.peer_addr.su_peer_addr[0], 1584 &tx_evt_param.peer_mac_addr.bytes[0], QDF_MAC_ADDR_SIZE); 1585 qdf_mem_copy(&header->u.meta_enh.chain_rssi[0], 1586 &tx_evt_param.chain_rssi[0], 1587 HOST_MAX_CHAINS * sizeof(tx_evt_param.chain_rssi[0])); 1588 qdf_mem_copy(&header->u.meta_enh.chain_phase[0], 1589 &tx_evt_param.chain_phase[0], 1590 HOST_MAX_CHAINS * sizeof(tx_evt_param.chain_phase[0])); 1591 qdf_mem_copy(&header->u.meta_enh.agc_gain[0], 1592 &tx_evt_param.agc_gain[0], 1593 HOST_MAX_CHAINS * sizeof(tx_evt_param.agc_gain[0])); 1594 header->u.meta_enh.rtt_cfo_measurement = tx_evt_param.cfo_measurement; 1595 header->u.meta_enh.rx_start_ts = tx_evt_param.rx_start_ts; 1596 header->u.meta_enh.mcs_rate = tx_evt_param.mcs_rate; 1597 header->u.meta_enh.gi_type = tx_evt_param.gi_type; 1598 1599 status = correlate_and_relay_enh(pdev, cookie, lut, 1600 CORRELATE_TX_EV_MODULE_ID); 1601 if (status == STATUS_STREAM_AND_RELEASE) { 1602 if (cfr_rx_ops->cfr_info_send) 1603 status = cfr_rx_ops->cfr_info_send(pdev, 1604 &lut->header, 1605 sizeof( 1606 struct 1607 csi_cfr_header), 1608 lut->data, 1609 lut->data_len, 1610 &end_magic, 4); 1611 dump_metadata(header, cookie); 1612 release_lut_entry_enh(pdev, lut); 1613 target_if_dbr_buf_release(pdev, DBR_MODULE_CFR, buf_addr, 1614 cookie, 0); 1615 } else { 1616 retval = -EINVAL; 1617 } 1618 1619 unlock: 1620 qdf_spin_unlock_bh(&pcfr->lut_lock); 1621 relref: 1622 1623 wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID); 1624 wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID); 1625 wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); 1626 1627 return retval; 1628 } 1629 #else 1630 static int 1631 target_if_peer_capture_event(ol_scn_t sc, uint8_t *data, uint32_t datalen) 1632 { 1633 return 0; 1634 } 1635 #endif 1636 1637 /** 1638 * target_if_register_phase_delta_for_rcc_event_handler() - Register callback 1639 * for WMI phase delta event 1640 * @psoc: PSOC object 1641 * 1642 * Return: Success/Failure status 1643 */ 1644 static QDF_STATUS 1645 target_if_register_phase_delta_for_rcc_event_handler(struct wlan_objmgr_psoc 1646 *psoc) 1647 { 1648 wmi_unified_t wmi_hdl; 1649 QDF_STATUS ret = QDF_STATUS_SUCCESS; 1650 1651 wmi_hdl = get_wmi_unified_hdl_from_psoc(psoc); 1652 if (!wmi_hdl) { 1653 cfr_err("Unable to get wmi handle"); 1654 return QDF_STATUS_E_NULL_VALUE; 1655 } 1656 1657 ret = wmi_unified_register_event_handler 1658 (wmi_hdl, wmi_pdev_aoa_phasedelta_event_id, 1659 target_if_pdev_aoa_phasedaelta_event_handler, 1660 WMI_RX_UMAC_CTX); 1661 1662 /* 1663 * Event registration is called per pdev 1664 * Ignore erorr if event is alreday registred. 1665 */ 1666 if (ret == QDF_STATUS_E_FAILURE) 1667 ret = QDF_STATUS_SUCCESS; 1668 1669 return ret; 1670 } 1671 1672 /** 1673 * target_if_unregister_phase_delta_for_rcc_event_handler() - Unregister 1674 * call back for WMI phase delta for rcc event 1675 * @psoc: PSOC object 1676 * 1677 * Return Success/Failure status 1678 */ 1679 static QDF_STATUS 1680 target_if_unregister_phase_delta_for_rcc_event_handler(struct wlan_objmgr_psoc 1681 *psoc) 1682 { 1683 wmi_unified_t wmi_hdl; 1684 QDF_STATUS status = QDF_STATUS_SUCCESS; 1685 1686 wmi_hdl = get_wmi_unified_hdl_from_psoc(psoc); 1687 if (!wmi_hdl) { 1688 cfr_err("Unable to get wmi handle"); 1689 return QDF_STATUS_E_NULL_VALUE; 1690 } 1691 1692 status = wmi_unified_unregister_event 1693 (wmi_hdl, wmi_pdev_aoa_phasedelta_event_id); 1694 1695 return status; 1696 } 1697 1698 /** 1699 * target_if_register_tx_completion_enh_event_handler() - Register callback for 1700 * WMI TX completion event 1701 * @psoc: PSOC object 1702 * 1703 * Return: Success/Failure status 1704 */ 1705 static QDF_STATUS 1706 target_if_register_tx_completion_enh_event_handler(struct wlan_objmgr_psoc 1707 *psoc) 1708 { 1709 /* Register completion handler here */ 1710 wmi_unified_t wmi_hdl; 1711 QDF_STATUS ret = QDF_STATUS_SUCCESS; 1712 1713 wmi_hdl = get_wmi_unified_hdl_from_psoc(psoc); 1714 if (!wmi_hdl) { 1715 cfr_err("Unable to get wmi handle"); 1716 return QDF_STATUS_E_NULL_VALUE; 1717 } 1718 1719 ret = wmi_unified_register_event_handler(wmi_hdl, 1720 wmi_peer_cfr_capture_event_id, 1721 target_if_peer_capture_event, 1722 WMI_RX_UMAC_CTX); 1723 /* 1724 * Event registration is called per pdev 1725 * Ignore erorr if event is alreday registred. 1726 */ 1727 if (ret == QDF_STATUS_E_FAILURE) 1728 ret = QDF_STATUS_SUCCESS; 1729 1730 return ret; 1731 } 1732 1733 /** 1734 * target_if_unregister_tx_completion_enh_event_handler() - Unregister callback 1735 * for WMI TX completion event 1736 * @psoc: PSOC object 1737 * 1738 * Return: Success/Failure status 1739 */ 1740 static QDF_STATUS 1741 target_if_unregister_tx_completion_enh_event_handler(struct wlan_objmgr_psoc 1742 *psoc) 1743 { 1744 /* Unregister completion handler here */ 1745 wmi_unified_t wmi_hdl; 1746 QDF_STATUS status = QDF_STATUS_SUCCESS; 1747 1748 wmi_hdl = get_wmi_unified_hdl_from_psoc(psoc); 1749 if (!wmi_hdl) { 1750 cfr_err("Unable to get wmi handle"); 1751 return QDF_STATUS_E_NULL_VALUE; 1752 } 1753 1754 status = wmi_unified_unregister_event(wmi_hdl, 1755 wmi_peer_cfr_capture_event_id); 1756 return status; 1757 } 1758 1759 /** 1760 * lut_ageout_timer_task() - Timer to flush pending TXRX/DBR events 1761 * 1762 * Return: none 1763 */ 1764 static os_timer_func(lut_ageout_timer_task) 1765 { 1766 int i = 0; 1767 struct pdev_cfr *pcfr = NULL; 1768 struct wlan_objmgr_pdev *pdev = NULL; 1769 struct look_up_table *lut = NULL; 1770 uint64_t diff, cur_tstamp; 1771 uint8_t srng_id = 0; 1772 1773 OS_GET_TIMER_ARG(pcfr, struct pdev_cfr*); 1774 1775 if (!pcfr) { 1776 cfr_err("pdev object for CFR is null"); 1777 return; 1778 } 1779 1780 pdev = pcfr->pdev_obj; 1781 if (!pdev) { 1782 cfr_err("pdev is null"); 1783 return; 1784 } 1785 1786 srng_id = pcfr->rcc_param.srng_id; 1787 if (wlan_objmgr_pdev_try_get_ref(pdev, WLAN_CFR_ID) 1788 != QDF_STATUS_SUCCESS) { 1789 cfr_err("failed to get pdev reference"); 1790 return; 1791 } 1792 1793 cur_tstamp = qdf_ktime_to_ms(qdf_ktime_get()); 1794 1795 qdf_spin_lock_bh(&pcfr->lut_lock); 1796 1797 for (i = 0; i < pcfr->lut_num; i++) { 1798 lut = get_lut_entry(pcfr, i); 1799 if (!lut) 1800 continue; 1801 1802 if (lut->dbr_recv && !lut->tx_recv) { 1803 diff = cur_tstamp - lut->dbr_tstamp; 1804 if (diff > LUT_AGE_THRESHOLD) { 1805 target_if_dbr_buf_release(pdev, DBR_MODULE_CFR, 1806 lut->dbr_address, 1807 i, srng_id); 1808 pcfr->flush_timeout_dbr_cnt++; 1809 release_lut_entry_enh(pdev, lut); 1810 } 1811 } 1812 } 1813 1814 qdf_spin_unlock_bh(&pcfr->lut_lock); 1815 1816 if (pcfr->lut_timer_init) 1817 qdf_timer_mod(&pcfr->lut_age_timer, LUT_AGE_TIMER); 1818 wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); 1819 } 1820 1821 /** 1822 * target_if_cfr_start_lut_age_timer() - Start timer to flush aged-out LUT 1823 * entries 1824 * @pdev: pointer to pdev object 1825 * 1826 * Return: None 1827 */ 1828 void target_if_cfr_start_lut_age_timer(struct wlan_objmgr_pdev *pdev) 1829 { 1830 struct pdev_cfr *pcfr; 1831 1832 pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev, 1833 WLAN_UMAC_COMP_CFR); 1834 if (pcfr->lut_timer_init) 1835 qdf_timer_mod(&pcfr->lut_age_timer, LUT_AGE_TIMER); 1836 } 1837 1838 /** 1839 * target_if_cfr_stop_lut_age_timer() - Stop timer to flush aged-out LUT 1840 * entries 1841 * @pdev: pointer to pdev object 1842 * 1843 * Return: None 1844 */ 1845 void target_if_cfr_stop_lut_age_timer(struct wlan_objmgr_pdev *pdev) 1846 { 1847 struct pdev_cfr *pcfr; 1848 1849 pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev, 1850 WLAN_UMAC_COMP_CFR); 1851 if (pcfr->lut_timer_init) 1852 qdf_timer_stop(&pcfr->lut_age_timer); 1853 } 1854 1855 /** 1856 * target_if_cfr_update_global_cfg() - Update global config after a successful 1857 * commit 1858 * @pdev: pointer to pdev object 1859 * 1860 * Return: None 1861 */ 1862 void target_if_cfr_update_global_cfg(struct wlan_objmgr_pdev *pdev) 1863 { 1864 int grp_id; 1865 struct pdev_cfr *pcfr; 1866 struct ta_ra_cfr_cfg *curr_cfg = NULL; 1867 struct ta_ra_cfr_cfg *glbl_cfg = NULL; 1868 1869 pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev, 1870 WLAN_UMAC_COMP_CFR); 1871 1872 for (grp_id = 0; grp_id < MAX_TA_RA_ENTRIES; grp_id++) { 1873 if (qdf_test_bit(grp_id, 1874 &pcfr->rcc_param.modified_in_curr_session)) { 1875 /* Populating global config based on user's input */ 1876 glbl_cfg = &pcfr->global[grp_id]; 1877 curr_cfg = &pcfr->rcc_param.curr[grp_id]; 1878 1879 if (curr_cfg->valid_ta) 1880 qdf_mem_copy(glbl_cfg->tx_addr, 1881 curr_cfg->tx_addr, 1882 QDF_MAC_ADDR_SIZE); 1883 1884 if (curr_cfg->valid_ra) 1885 qdf_mem_copy(glbl_cfg->rx_addr, 1886 curr_cfg->rx_addr, 1887 QDF_MAC_ADDR_SIZE); 1888 1889 if (curr_cfg->valid_ta_mask) 1890 qdf_mem_copy(glbl_cfg->tx_addr_mask, 1891 curr_cfg->tx_addr_mask, 1892 QDF_MAC_ADDR_SIZE); 1893 1894 if (curr_cfg->valid_ra_mask) 1895 qdf_mem_copy(glbl_cfg->rx_addr_mask, 1896 curr_cfg->rx_addr_mask, 1897 QDF_MAC_ADDR_SIZE); 1898 1899 if (curr_cfg->valid_bw_mask) 1900 glbl_cfg->bw = curr_cfg->bw; 1901 1902 if (curr_cfg->valid_nss_mask) 1903 glbl_cfg->nss = curr_cfg->nss; 1904 1905 if (curr_cfg->valid_mgmt_subtype) 1906 glbl_cfg->mgmt_subtype_filter = 1907 curr_cfg->mgmt_subtype_filter; 1908 1909 if (curr_cfg->valid_ctrl_subtype) 1910 glbl_cfg->ctrl_subtype_filter = 1911 curr_cfg->ctrl_subtype_filter; 1912 1913 if (curr_cfg->valid_data_subtype) 1914 glbl_cfg->data_subtype_filter = 1915 curr_cfg->data_subtype_filter; 1916 } 1917 } 1918 } 1919 1920 /** 1921 * cfr_enh_init_pdev() - Inits cfr pdev and registers necessary handlers. 1922 * @psoc: pointer to psoc object 1923 * @pdev: pointer to pdev object 1924 * 1925 * Return: Registration status for necessary handlers 1926 */ 1927 QDF_STATUS cfr_enh_init_pdev(struct wlan_objmgr_psoc *psoc, 1928 struct wlan_objmgr_pdev *pdev) 1929 { 1930 QDF_STATUS status = QDF_STATUS_SUCCESS; 1931 struct pdev_cfr *pcfr; 1932 uint32_t target_type; 1933 struct psoc_cfr *cfr_sc; 1934 1935 if (!pdev) { 1936 cfr_err("PDEV is NULL!"); 1937 return QDF_STATUS_E_NULL_VALUE; 1938 } 1939 1940 if (!psoc) { 1941 cfr_err("PSOC is NULL"); 1942 return QDF_STATUS_E_NULL_VALUE; 1943 } 1944 1945 pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev, 1946 WLAN_UMAC_COMP_CFR); 1947 if (!pcfr) { 1948 cfr_err("pcfr is NULL!"); 1949 return QDF_STATUS_E_NULL_VALUE; 1950 } 1951 1952 cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 1953 WLAN_UMAC_COMP_CFR); 1954 1955 if (!cfr_sc) { 1956 cfr_err("cfr_sc is NULL"); 1957 return QDF_STATUS_E_NULL_VALUE; 1958 } 1959 1960 target_type = target_if_cfr_get_target_type(psoc); 1961 1962 #if DIRECT_BUF_RX_ENABLE 1963 status = target_if_register_to_dbr_enh(pdev); 1964 if (status != QDF_STATUS_SUCCESS) { 1965 cfr_err("Failed to register with dbr"); 1966 return status; 1967 } 1968 #endif 1969 1970 status = target_if_register_tx_completion_enh_event_handler(psoc); 1971 if (status != QDF_STATUS_SUCCESS) { 1972 cfr_err("Failed to register with tx event handler"); 1973 return status; 1974 } 1975 1976 status = target_if_register_phase_delta_for_rcc_event_handler(psoc); 1977 if (status != QDF_STATUS_SUCCESS) { 1978 cfr_err("Failed to register with phase delta event handler"); 1979 return status; 1980 } 1981 1982 pcfr->is_cfr_rcc_capable = 1; 1983 pcfr->rcc_param.pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 1984 pcfr->rcc_param.modified_in_curr_session = MAX_RESET_CFG_ENTRY; 1985 pcfr->rcc_param.num_grp_tlvs = MAX_TA_RA_ENTRIES; 1986 pcfr->rcc_param.vdev_id = CFR_INVALID_VDEV_ID; 1987 pcfr->rcc_param.srng_id = DEFAULT_SRNGID_CFR; 1988 pcfr->is_cap_interval_mode_sel_support = 1989 cfr_sc->is_cap_interval_mode_sel_support; 1990 pcfr->is_mo_marking_support = cfr_sc->is_mo_marking_support; 1991 pcfr->is_aoa_for_rcc_support = cfr_sc->is_aoa_for_rcc_support; 1992 1993 if (pcfr->is_aoa_for_rcc_support) { 1994 qdf_mem_set(pcfr->ibf_cal_val, 1995 sizeof(uint32_t) * HOST_MAX_CHAINS, 1996 0); 1997 qdf_mem_set(pcfr->phase_delta, 1998 sizeof(uint16_t) * HOST_MAX_CHAINS * MAX_AGC_GAIN, 1999 0); 2000 pcfr->max_aoa_chains = 0; 2001 } 2002 2003 target_if_cfr_default_ta_ra_config(&pcfr->rcc_param, 2004 true, MAX_RESET_CFG_ENTRY); 2005 2006 status = target_if_cfr_config_rcc(pdev, &pcfr->rcc_param); 2007 if (status == QDF_STATUS_SUCCESS) { 2008 /* Update global configuration */ 2009 target_if_cfr_update_global_cfg(pdev); 2010 } else { 2011 cfr_err("Sending WMI to configure default has failed"); 2012 return status; 2013 } 2014 2015 pcfr->rcc_param.modified_in_curr_session = 0; 2016 2017 pcfr->cfr_max_sta_count = MAX_CFR_ENABLED_CLIENTS; 2018 2019 if (target_type == TARGET_TYPE_QCN9000) { 2020 pcfr->subbuf_size = STREAMFS_MAX_SUBBUF_PINE; 2021 pcfr->num_subbufs = STREAMFS_NUM_SUBBUF_PINE; 2022 pcfr->chip_type = CFR_CAPTURE_RADIO_PINE; 2023 pcfr->max_mu_users = PINE_CFR_MU_USERS; 2024 } else if (target_type == TARGET_TYPE_QCA5018) { 2025 pcfr->subbuf_size = STREAMFS_MAX_SUBBUF_MAPLE; 2026 pcfr->num_subbufs = STREAMFS_NUM_SUBBUF_MAPLE; 2027 pcfr->chip_type = CFR_CAPTURE_RADIO_MAPLE; 2028 pcfr->max_mu_users = MAPLE_CFR_MU_USERS; 2029 } else if (target_type == TARGET_TYPE_QCN6122) { 2030 pcfr->subbuf_size = STREAMFS_MAX_SUBBUF_SPRUCE; 2031 pcfr->num_subbufs = STREAMFS_NUM_SUBBUF_SPRUCE; 2032 pcfr->chip_type = CFR_CAPTURE_RADIO_SPRUCE; 2033 pcfr->max_mu_users = SPRUCE_CFR_MU_USERS; 2034 } else { 2035 pcfr->subbuf_size = STREAMFS_MAX_SUBBUF_CYP; 2036 pcfr->num_subbufs = STREAMFS_NUM_SUBBUF_CYP; 2037 pcfr->chip_type = CFR_CAPTURE_RADIO_CYP; 2038 pcfr->max_mu_users = CYP_CFR_MU_USERS; 2039 } 2040 2041 if (!pcfr->lut_timer_init) { 2042 qdf_timer_init(NULL, 2043 &(pcfr->lut_age_timer), 2044 lut_ageout_timer_task, (void *)pcfr, 2045 QDF_TIMER_TYPE_WAKE_APPS); 2046 pcfr->lut_timer_init = 1; 2047 } 2048 2049 qdf_spinlock_create(&pcfr->lut_lock); 2050 2051 return status; 2052 } 2053 2054 /** 2055 * cfr_enh_deinit_pdev() - De-inits corresponding pdev and handlers. 2056 * @psoc: pointer to psoc object 2057 * @pdev: pointer to pdev object 2058 * 2059 * Return: De-registration status for necessary handlers 2060 */ 2061 QDF_STATUS cfr_enh_deinit_pdev(struct wlan_objmgr_psoc *psoc, 2062 struct wlan_objmgr_pdev *pdev) 2063 { 2064 QDF_STATUS status; 2065 struct pdev_cfr *pcfr; 2066 2067 pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev, 2068 WLAN_UMAC_COMP_CFR); 2069 if (!pcfr) { 2070 cfr_err("pcfr is NULL"); 2071 return QDF_STATUS_E_NULL_VALUE; 2072 } 2073 2074 if (pcfr->lut_timer_init) { 2075 qdf_timer_stop(&pcfr->lut_age_timer); 2076 qdf_timer_free(&(pcfr->lut_age_timer)); 2077 pcfr->lut_timer_init = 0; 2078 } 2079 2080 pcfr->tx_evt_cnt = 0; 2081 pcfr->dbr_evt_cnt = 0; 2082 pcfr->release_cnt = 0; 2083 pcfr->total_tx_evt_cnt = 0; 2084 pcfr->rx_tlv_evt_cnt = 0; 2085 pcfr->flush_dbr_cnt = 0; 2086 pcfr->flush_timeout_dbr_cnt = 0; 2087 pcfr->invalid_dma_length_cnt = 0; 2088 pcfr->clear_txrx_event = 0; 2089 pcfr->cfr_dma_aborts = 0; 2090 pcfr->tx_peer_status_cfr_fail = 0; 2091 pcfr->tx_evt_status_cfr_fail = 0; 2092 pcfr->tx_dbr_cookie_lookup_fail = 0; 2093 qdf_mem_zero(&pcfr->rcc_param, sizeof(struct cfr_rcc_param)); 2094 qdf_mem_zero(&pcfr->global, (sizeof(struct ta_ra_cfr_cfg) * 2095 MAX_TA_RA_ENTRIES)); 2096 pcfr->cfr_timer_enable = 0; 2097 2098 #ifdef DIRECT_BUF_RX_ENABLE 2099 status = target_if_unregister_to_dbr_enh(pdev); 2100 if (status != QDF_STATUS_SUCCESS) 2101 cfr_err("Failed to register with dbr"); 2102 #endif 2103 2104 status = target_if_unregister_tx_completion_enh_event_handler(psoc); 2105 if (status != QDF_STATUS_SUCCESS) 2106 cfr_err("Failed to register with dbr"); 2107 2108 status = target_if_unregister_phase_delta_for_rcc_event_handler(psoc); 2109 if (status != QDF_STATUS_SUCCESS) 2110 cfr_err("Failed to unregister phase delta handler"); 2111 2112 qdf_spinlock_destroy(&pcfr->lut_lock); 2113 2114 return status; 2115 } 2116