1 /* 2 * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 #include <dp_types.h> 18 #include "dp_rx.h" 19 #include "dp_peer.h" 20 #include <dp_htt.h> 21 #include <dp_mon_filter.h> 22 #include <dp_htt.h> 23 #include <dp_mon.h> 24 #include <dp_rx_mon.h> 25 #include <dp_internal.h> 26 #include "htt_ppdu_stats.h" 27 #include "dp_cal_client_api.h" 28 #if defined(DP_CON_MON) 29 #ifndef REMOVE_PKT_LOG 30 #include <pktlog_ac_api.h> 31 #include <pktlog_ac.h> 32 #endif 33 #endif 34 #ifdef FEATURE_PERPKT_INFO 35 #include "dp_ratetable.h" 36 #endif 37 #ifdef QCA_SUPPORT_LITE_MONITOR 38 #include "dp_lite_mon.h" 39 #endif 40 41 #define DP_INTR_POLL_TIMER_MS 5 42 #define INVALID_FREE_BUFF 0xffffffff 43 44 #ifdef WLAN_RX_PKT_CAPTURE_ENH 45 #include "dp_rx_mon_feature.h" 46 #endif /* WLAN_RX_PKT_CAPTURE_ENH */ 47 48 #ifdef QCA_UNDECODED_METADATA_SUPPORT 49 #define MAX_STRING_LEN_PER_FIELD 6 50 #define DP_UNDECODED_ERR_LENGTH (MAX_STRING_LEN_PER_FIELD * CDP_PHYRX_ERR_MAX) 51 #endif 52 53 #ifdef QCA_MCOPY_SUPPORT 54 static inline void 55 dp_pdev_disable_mcopy_code(struct dp_pdev *pdev) 56 { 57 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 58 59 mon_pdev->mcopy_mode = M_COPY_DISABLED; 60 mon_pdev->mvdev = NULL; 61 } 62 63 static inline void 64 dp_reset_mcopy_mode(struct dp_pdev *pdev) 65 { 66 QDF_STATUS status = QDF_STATUS_SUCCESS; 67 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 68 struct cdp_mon_ops *cdp_ops; 69 70 if (mon_pdev->mcopy_mode) { 71 cdp_ops = dp_mon_cdp_ops_get(pdev->soc); 72 if (cdp_ops && cdp_ops->config_full_mon_mode) 73 cdp_ops->soc_config_full_mon_mode((struct cdp_pdev *)pdev, 74 DP_FULL_MON_ENABLE); 75 dp_pdev_disable_mcopy_code(pdev); 76 dp_mon_filter_reset_mcopy_mode(pdev); 77 status = dp_mon_filter_update(pdev); 78 if (status != QDF_STATUS_SUCCESS) { 79 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 80 FL("Failed to reset AM copy mode filters")); 81 } 82 mon_pdev->monitor_configured = false; 83 } 84 } 85 86 static QDF_STATUS 87 dp_config_mcopy_mode(struct dp_pdev *pdev, int val) 88 { 89 QDF_STATUS status = QDF_STATUS_SUCCESS; 90 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 91 struct dp_mon_ops *mon_ops; 92 struct cdp_mon_ops *cdp_ops; 93 94 if (mon_pdev->mvdev) 95 return QDF_STATUS_E_RESOURCES; 96 97 mon_pdev->mcopy_mode = val; 98 mon_pdev->tx_sniffer_enable = 0; 99 mon_pdev->monitor_configured = true; 100 101 mon_ops = dp_mon_ops_get(pdev->soc); 102 if (!wlan_cfg_is_delay_mon_replenish(pdev->soc->wlan_cfg_ctx)) { 103 if (mon_ops && mon_ops->mon_vdev_set_monitor_mode_rings) 104 mon_ops->mon_vdev_set_monitor_mode_rings(pdev, true); 105 } 106 107 /* 108 * Setup the M copy mode filter. 109 */ 110 cdp_ops = dp_mon_cdp_ops_get(pdev->soc); 111 if (cdp_ops && cdp_ops->config_full_mon_mode) 112 cdp_ops->soc_config_full_mon_mode((struct cdp_pdev *)pdev, 113 DP_FULL_MON_ENABLE); 114 dp_mon_filter_setup_mcopy_mode(pdev); 115 status = dp_mon_filter_update(pdev); 116 if (status != QDF_STATUS_SUCCESS) { 117 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 118 FL("Failed to set M_copy mode filters")); 119 dp_mon_filter_reset_mcopy_mode(pdev); 120 dp_pdev_disable_mcopy_code(pdev); 121 return status; 122 } 123 124 if (!mon_pdev->pktlog_ppdu_stats) 125 dp_h2t_cfg_stats_msg_send(pdev, 126 DP_PPDU_STATS_CFG_SNIFFER, 127 pdev->pdev_id); 128 129 return status; 130 } 131 #else 132 static inline void 133 dp_reset_mcopy_mode(struct dp_pdev *pdev) 134 { 135 } 136 137 static inline QDF_STATUS 138 dp_config_mcopy_mode(struct dp_pdev *pdev, int val) 139 { 140 return QDF_STATUS_E_INVAL; 141 } 142 #endif /* QCA_MCOPY_SUPPORT */ 143 144 #ifdef QCA_UNDECODED_METADATA_SUPPORT 145 static QDF_STATUS 146 dp_reset_undecoded_metadata_capture(struct dp_pdev *pdev) 147 { 148 QDF_STATUS status = QDF_STATUS_SUCCESS; 149 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 150 151 if (mon_pdev->undecoded_metadata_capture) { 152 dp_mon_filter_reset_undecoded_metadata_mode(pdev); 153 status = dp_mon_filter_update(pdev); 154 if (status != QDF_STATUS_SUCCESS) { 155 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 156 FL("Undecoded capture filter reset failed")); 157 } 158 } 159 mon_pdev->undecoded_metadata_capture = 0; 160 return status; 161 } 162 163 static QDF_STATUS 164 dp_enable_undecoded_metadata_capture(struct dp_pdev *pdev, int val) 165 { 166 QDF_STATUS status = QDF_STATUS_SUCCESS; 167 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 168 169 if (!mon_pdev->mvdev) { 170 qdf_err("monitor_pdev is NULL"); 171 return QDF_STATUS_E_RESOURCES; 172 } 173 174 mon_pdev->undecoded_metadata_capture = val; 175 mon_pdev->monitor_configured = true; 176 177 178 /* Setup the undecoded metadata capture mode filter. */ 179 dp_mon_filter_setup_undecoded_metadata_mode(pdev); 180 status = dp_mon_filter_update(pdev); 181 if (status != QDF_STATUS_SUCCESS) { 182 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 183 FL("Failed to set Undecoded capture filters")); 184 dp_mon_filter_reset_undecoded_metadata_mode(pdev); 185 return status; 186 } 187 188 return status; 189 } 190 #else 191 static inline QDF_STATUS 192 dp_reset_undecoded_metadata_capture(struct dp_pdev *pdev) 193 { 194 return QDF_STATUS_E_INVAL; 195 } 196 197 static inline QDF_STATUS 198 dp_enable_undecoded_metadata_capture(struct dp_pdev *pdev, int val) 199 { 200 return QDF_STATUS_E_INVAL; 201 } 202 #endif /* QCA_UNDECODED_METADATA_SUPPORT */ 203 204 QDF_STATUS dp_reset_monitor_mode(struct cdp_soc_t *soc_hdl, 205 uint8_t pdev_id, 206 uint8_t special_monitor) 207 { 208 struct dp_soc *soc = (struct dp_soc *)soc_hdl; 209 struct dp_pdev *pdev = 210 dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, 211 pdev_id); 212 QDF_STATUS status = QDF_STATUS_SUCCESS; 213 struct dp_mon_pdev *mon_pdev; 214 struct cdp_mon_ops *cdp_ops; 215 216 if (!pdev) 217 return QDF_STATUS_E_FAILURE; 218 219 mon_pdev = pdev->monitor_pdev; 220 221 qdf_spin_lock_bh(&mon_pdev->mon_lock); 222 223 cdp_ops = dp_mon_cdp_ops_get(soc); 224 if (cdp_ops && cdp_ops->soc_config_full_mon_mode) 225 cdp_ops->soc_config_full_mon_mode((struct cdp_pdev *)pdev, 226 DP_FULL_MON_DISABLE); 227 mon_pdev->mvdev = NULL; 228 229 /* 230 * Lite monitor mode, smart monitor mode and monitor 231 * mode uses this APIs to filter reset and mode disable 232 */ 233 if (mon_pdev->mcopy_mode) { 234 #if defined(QCA_MCOPY_SUPPORT) 235 dp_pdev_disable_mcopy_code(pdev); 236 dp_mon_filter_reset_mcopy_mode(pdev); 237 #endif /* QCA_MCOPY_SUPPORT */ 238 } else if (special_monitor) { 239 #if defined(ATH_SUPPORT_NAC) 240 dp_mon_filter_reset_smart_monitor(pdev); 241 #endif /* ATH_SUPPORT_NAC */ 242 /* for mon 2.0 we make use of lite mon to 243 * set filters for smart monitor use case. 244 */ 245 dp_monitor_lite_mon_disable_rx(pdev); 246 } else if (mon_pdev->undecoded_metadata_capture) { 247 #ifdef QCA_UNDECODED_METADATA_SUPPORT 248 dp_reset_undecoded_metadata_capture(pdev); 249 #endif 250 } else { 251 dp_mon_filter_reset_mon_mode(pdev); 252 } 253 status = dp_mon_filter_update(pdev); 254 if (status != QDF_STATUS_SUCCESS) { 255 dp_rx_mon_dest_err("%pK: Failed to reset monitor filters", 256 soc); 257 } 258 259 mon_pdev->monitor_configured = false; 260 261 qdf_spin_unlock_bh(&mon_pdev->mon_lock); 262 return QDF_STATUS_SUCCESS; 263 } 264 265 #ifdef QCA_ADVANCE_MON_FILTER_SUPPORT 266 QDF_STATUS 267 dp_pdev_set_advance_monitor_filter(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, 268 struct cdp_monitor_filter *filter_val) 269 { 270 /* Many monitor VAPs can exists in a system but only one can be up at 271 * anytime 272 */ 273 struct dp_soc *soc = (struct dp_soc *)soc_hdl; 274 struct dp_vdev *vdev; 275 struct dp_pdev *pdev = 276 dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, 277 pdev_id); 278 QDF_STATUS status = QDF_STATUS_SUCCESS; 279 struct dp_mon_pdev *mon_pdev; 280 281 if (!pdev || !pdev->monitor_pdev) 282 return QDF_STATUS_E_FAILURE; 283 284 mon_pdev = pdev->monitor_pdev; 285 vdev = mon_pdev->mvdev; 286 287 if (!vdev) 288 return QDF_STATUS_E_FAILURE; 289 290 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_WARN, 291 "pdev=%pK, pdev_id=%d, soc=%pK vdev=%pK", 292 pdev, pdev_id, soc, vdev); 293 294 /*Check if current pdev's monitor_vdev exists */ 295 if (!mon_pdev->mvdev) { 296 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 297 "vdev=%pK", vdev); 298 qdf_assert(vdev); 299 } 300 301 /* update filter mode, type in pdev structure */ 302 mon_pdev->mon_filter_mode = filter_val->mode; 303 mon_pdev->fp_mgmt_filter = filter_val->fp_mgmt; 304 mon_pdev->fp_ctrl_filter = filter_val->fp_ctrl; 305 mon_pdev->fp_data_filter = filter_val->fp_data; 306 mon_pdev->mo_mgmt_filter = filter_val->mo_mgmt; 307 mon_pdev->mo_ctrl_filter = filter_val->mo_ctrl; 308 mon_pdev->mo_data_filter = filter_val->mo_data; 309 310 dp_mon_filter_setup_mon_mode(pdev); 311 status = dp_mon_filter_update(pdev); 312 if (status != QDF_STATUS_SUCCESS) { 313 dp_rx_mon_dest_err("%pK: Failed to set filter for adv mon mode", 314 soc); 315 dp_mon_filter_reset_mon_mode(pdev); 316 } 317 318 return status; 319 } 320 #endif 321 322 QDF_STATUS 323 dp_deliver_tx_mgmt(struct cdp_soc_t *cdp_soc, uint8_t pdev_id, qdf_nbuf_t nbuf) 324 { 325 struct dp_pdev *pdev = 326 dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)cdp_soc, 327 pdev_id); 328 329 if (!pdev) 330 return QDF_STATUS_E_FAILURE; 331 332 dp_deliver_mgmt_frm(pdev, nbuf); 333 334 return QDF_STATUS_SUCCESS; 335 } 336 337 #ifdef QCA_SUPPORT_SCAN_SPCL_VAP_STATS 338 /** 339 * dp_scan_spcl_vap_stats_attach() - alloc spcl vap stats struct 340 * @mon_vdev: Datapath mon VDEV handle 341 * 342 * Return: 0 on success, not 0 on failure 343 */ 344 static inline QDF_STATUS 345 dp_scan_spcl_vap_stats_attach(struct dp_mon_vdev *mon_vdev) 346 { 347 mon_vdev->scan_spcl_vap_stats = 348 qdf_mem_malloc(sizeof(struct cdp_scan_spcl_vap_stats)); 349 350 if (!mon_vdev->scan_spcl_vap_stats) { 351 dp_mon_err("scan spcl vap stats attach fail"); 352 return QDF_STATUS_E_NOMEM; 353 } 354 355 return QDF_STATUS_SUCCESS; 356 } 357 358 /** 359 * dp_scan_spcl_vap_stats_detach() - free spcl vap stats struct 360 * @mon_vdev: Datapath mon VDEV handle 361 * 362 * Return: void 363 */ 364 static inline void 365 dp_scan_spcl_vap_stats_detach(struct dp_mon_vdev *mon_vdev) 366 { 367 if (mon_vdev->scan_spcl_vap_stats) { 368 qdf_mem_free(mon_vdev->scan_spcl_vap_stats); 369 mon_vdev->scan_spcl_vap_stats = NULL; 370 } 371 } 372 373 /** 374 * dp_reset_scan_spcl_vap_stats() - reset spcl vap rx stats 375 * @vdev: Datapath VDEV handle 376 * 377 * Return: void 378 */ 379 static inline void 380 dp_reset_scan_spcl_vap_stats(struct dp_vdev *vdev) 381 { 382 struct dp_mon_vdev *mon_vdev; 383 struct dp_mon_pdev *mon_pdev; 384 385 mon_pdev = vdev->pdev->monitor_pdev; 386 if (!mon_pdev || !mon_pdev->reset_scan_spcl_vap_stats_enable) 387 return; 388 389 mon_vdev = vdev->monitor_vdev; 390 if (!mon_vdev || !mon_vdev->scan_spcl_vap_stats) 391 return; 392 393 qdf_mem_zero(mon_vdev->scan_spcl_vap_stats, 394 sizeof(struct cdp_scan_spcl_vap_stats)); 395 } 396 397 /** 398 * dp_get_scan_spcl_vap_stats() - get spcl vap rx stats 399 * @soc_hdl: Datapath soc handle 400 * @vdev_id: vdev id 401 * @stats: structure to hold spcl vap stats 402 * 403 * Return: 0 on success, not 0 on failure 404 */ 405 static QDF_STATUS 406 dp_get_scan_spcl_vap_stats(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, 407 struct cdp_scan_spcl_vap_stats *stats) 408 { 409 struct dp_mon_vdev *mon_vdev = NULL; 410 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); 411 struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id, 412 DP_MOD_ID_CDP); 413 414 if (!vdev || !stats) { 415 if (vdev) 416 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP); 417 return QDF_STATUS_E_INVAL; 418 } 419 420 mon_vdev = vdev->monitor_vdev; 421 if (!mon_vdev || !mon_vdev->scan_spcl_vap_stats) { 422 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP); 423 return QDF_STATUS_E_INVAL; 424 } 425 426 qdf_mem_copy(stats, mon_vdev->scan_spcl_vap_stats, 427 sizeof(struct cdp_scan_spcl_vap_stats)); 428 429 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP); 430 return QDF_STATUS_SUCCESS; 431 } 432 #else 433 static inline void 434 dp_reset_scan_spcl_vap_stats(struct dp_vdev *vdev) 435 { 436 } 437 438 static inline QDF_STATUS 439 dp_scan_spcl_vap_stats_attach(struct dp_mon_vdev *mon_vdev) 440 { 441 return QDF_STATUS_SUCCESS; 442 } 443 444 static inline void 445 dp_scan_spcl_vap_stats_detach(struct dp_mon_vdev *mon_vdev) 446 { 447 } 448 #endif 449 450 /** 451 * dp_vdev_set_monitor_mode() - Set DP VDEV to monitor mode 452 * @vdev_handle: Datapath VDEV handle 453 * @smart_monitor: Flag to denote if its smart monitor mode 454 * 455 * Return: 0 on success, not 0 on failure 456 */ 457 static QDF_STATUS dp_vdev_set_monitor_mode(struct cdp_soc_t *dp_soc, 458 uint8_t vdev_id, 459 uint8_t special_monitor) 460 { 461 struct dp_soc *soc = (struct dp_soc *)dp_soc; 462 struct dp_pdev *pdev; 463 struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id, 464 DP_MOD_ID_CDP); 465 QDF_STATUS status = QDF_STATUS_SUCCESS; 466 struct dp_mon_pdev *mon_pdev; 467 struct cdp_mon_ops *cdp_ops; 468 469 if (!vdev) 470 return QDF_STATUS_E_FAILURE; 471 472 pdev = vdev->pdev; 473 474 if (!pdev || !pdev->monitor_pdev) 475 return QDF_STATUS_E_FAILURE; 476 477 mon_pdev = pdev->monitor_pdev; 478 479 mon_pdev->mvdev = vdev; 480 481 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_WARN, 482 "pdev=%pK, pdev_id=%d, soc=%pK vdev=%pK\n", 483 pdev, pdev->pdev_id, pdev->soc, vdev); 484 485 /* 486 * do not configure monitor buf ring and filter for smart and 487 * lite monitor 488 * for smart monitor filters are added along with first NAC 489 * for lite monitor required configuration done through 490 * dp_set_pdev_param 491 */ 492 493 if (special_monitor) { 494 status = QDF_STATUS_SUCCESS; 495 goto fail; 496 } 497 498 if (mon_pdev->scan_spcl_vap_configured) 499 dp_reset_scan_spcl_vap_stats(vdev); 500 501 /*Check if current pdev's monitor_vdev exists */ 502 if (mon_pdev->monitor_configured) { 503 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, 504 "monitor vap already created vdev=%pK\n", vdev); 505 status = QDF_STATUS_E_RESOURCES; 506 goto fail; 507 } 508 509 mon_pdev->monitor_configured = true; 510 511 /* disable lite mon if configured, monitor vap takes 512 * priority over lite mon when its created. Lite mon 513 * can be configured later again. 514 */ 515 dp_monitor_lite_mon_disable_rx(pdev); 516 517 cdp_ops = dp_mon_cdp_ops_get(soc); 518 if (cdp_ops && cdp_ops->soc_config_full_mon_mode) 519 cdp_ops->soc_config_full_mon_mode((struct cdp_pdev *)pdev, 520 DP_FULL_MON_ENABLE); 521 dp_mon_filter_setup_mon_mode(pdev); 522 status = dp_mon_filter_update(pdev); 523 if (status != QDF_STATUS_SUCCESS) { 524 dp_cdp_err("%pK: Failed to reset monitor filters", soc); 525 dp_mon_filter_reset_mon_mode(pdev); 526 mon_pdev->monitor_configured = false; 527 mon_pdev->mvdev = NULL; 528 } 529 530 fail: 531 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP); 532 return status; 533 } 534 535 #ifdef QCA_TX_CAPTURE_SUPPORT 536 static QDF_STATUS 537 dp_config_tx_capture_mode(struct dp_pdev *pdev) 538 { 539 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 540 541 mon_pdev->tx_sniffer_enable = 1; 542 mon_pdev->monitor_configured = false; 543 544 if (!mon_pdev->pktlog_ppdu_stats) 545 dp_h2t_cfg_stats_msg_send(pdev, 546 DP_PPDU_STATS_CFG_SNIFFER, 547 pdev->pdev_id); 548 549 return QDF_STATUS_SUCCESS; 550 } 551 #else 552 #ifdef QCA_MCOPY_SUPPORT 553 static QDF_STATUS 554 dp_config_tx_capture_mode(struct dp_pdev *pdev) 555 { 556 return QDF_STATUS_E_INVAL; 557 } 558 #endif 559 #endif 560 561 #if defined(QCA_MCOPY_SUPPORT) || defined(QCA_TX_CAPTURE_SUPPORT) 562 QDF_STATUS 563 dp_config_debug_sniffer(struct dp_pdev *pdev, int val) 564 { 565 QDF_STATUS status = QDF_STATUS_SUCCESS; 566 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 567 568 /* 569 * Note: The mirror copy mode cannot co-exist with any other 570 * monitor modes. Hence disabling the filter for this mode will 571 * reset the monitor destination ring filters. 572 */ 573 dp_reset_mcopy_mode(pdev); 574 switch (val) { 575 case 0: 576 mon_pdev->tx_sniffer_enable = 0; 577 mon_pdev->monitor_configured = false; 578 579 /* 580 * We don't need to reset the Rx monitor status ring or call 581 * the API dp_ppdu_ring_reset() if all debug sniffer mode is 582 * disabled. The Rx monitor status ring will be disabled when 583 * the last mode using the monitor status ring get disabled. 584 */ 585 if (!mon_pdev->pktlog_ppdu_stats && 586 !mon_pdev->enhanced_stats_en && 587 !mon_pdev->bpr_enable) { 588 dp_h2t_cfg_stats_msg_send(pdev, 0, pdev->pdev_id); 589 } else if (mon_pdev->enhanced_stats_en && 590 !mon_pdev->bpr_enable) { 591 dp_h2t_cfg_stats_msg_send(pdev, 592 DP_PPDU_STATS_CFG_ENH_STATS, 593 pdev->pdev_id); 594 } else if (!mon_pdev->enhanced_stats_en && 595 mon_pdev->bpr_enable) { 596 dp_h2t_cfg_stats_msg_send(pdev, 597 DP_PPDU_STATS_CFG_BPR_ENH, 598 pdev->pdev_id); 599 } else { 600 dp_h2t_cfg_stats_msg_send(pdev, 601 DP_PPDU_STATS_CFG_BPR, 602 pdev->pdev_id); 603 } 604 break; 605 606 case 1: 607 status = dp_config_tx_capture_mode(pdev); 608 break; 609 case 2: 610 case 4: 611 status = dp_config_mcopy_mode(pdev, val); 612 break; 613 614 default: 615 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 616 "Invalid value, mode not supported"); 617 status = QDF_STATUS_E_INVAL; 618 break; 619 } 620 return status; 621 } 622 #endif 623 624 #ifdef QCA_UNDECODED_METADATA_SUPPORT 625 QDF_STATUS 626 dp_mon_config_undecoded_metadata_capture(struct dp_pdev *pdev, int val) 627 { 628 QDF_STATUS status = QDF_STATUS_SUCCESS; 629 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 630 631 if (!mon_pdev->mvdev && !mon_pdev->scan_spcl_vap_configured) { 632 qdf_err("No monitor or Special vap, undecoded capture not supported"); 633 return QDF_STATUS_E_RESOURCES; 634 } 635 636 if (val) 637 status = dp_enable_undecoded_metadata_capture(pdev, val); 638 else 639 status = dp_reset_undecoded_metadata_capture(pdev); 640 641 return status; 642 } 643 #endif 644 645 /** 646 * dp_monitor_mode_ring_config() - Send the tlv config to fw for monitor buffer 647 * ring based on target 648 * @soc: soc handle 649 * @mac_for_pdev: WIN- pdev_id, MCL- mac id 650 * @pdev: physical device handle 651 * @ring_num: mac id 652 * @htt_tlv_filter: tlv filter 653 * 654 * Return: zero on success, non-zero on failure 655 */ 656 static inline QDF_STATUS 657 dp_monitor_mode_ring_config(struct dp_soc *soc, uint8_t mac_for_pdev, 658 struct dp_pdev *pdev, uint8_t ring_num, 659 struct htt_rx_ring_tlv_filter htt_tlv_filter) 660 { 661 QDF_STATUS status; 662 663 if (soc->wlan_cfg_ctx->rxdma1_enable) 664 status = htt_h2t_rx_ring_cfg(soc->htt_handle, mac_for_pdev, 665 soc->rxdma_mon_buf_ring[ring_num] 666 .hal_srng, 667 RXDMA_MONITOR_BUF, 668 RX_MONITOR_BUFFER_SIZE, 669 &htt_tlv_filter); 670 else 671 status = htt_h2t_rx_ring_cfg(soc->htt_handle, mac_for_pdev, 672 pdev->rx_mac_buf_ring[ring_num] 673 .hal_srng, 674 RXDMA_BUF, RX_DATA_BUFFER_SIZE, 675 &htt_tlv_filter); 676 677 return status; 678 } 679 680 /** 681 * dp_get_mon_vdev_from_pdev_wifi3() - Get vdev id of monitor mode 682 * @soc_hdl: datapath soc handle 683 * @pdev_id: physical device instance id 684 * 685 * Return: virtual interface id 686 */ 687 static uint8_t dp_get_mon_vdev_from_pdev_wifi3(struct cdp_soc_t *soc_hdl, 688 uint8_t pdev_id) 689 { 690 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); 691 struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); 692 693 if (qdf_unlikely(!pdev || !pdev->monitor_pdev || 694 !pdev->monitor_pdev->mvdev)) 695 return -EINVAL; 696 697 return pdev->monitor_pdev->mvdev->vdev_id; 698 } 699 700 #if defined(QCA_TX_CAPTURE_SUPPORT) || defined(QCA_ENHANCED_STATS_SUPPORT) 701 #ifndef WLAN_TX_PKT_CAPTURE_ENH 702 void dp_deliver_mgmt_frm(struct dp_pdev *pdev, qdf_nbuf_t nbuf) 703 { 704 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 705 706 if (mon_pdev->tx_sniffer_enable || mon_pdev->mcopy_mode) { 707 dp_wdi_event_handler(WDI_EVENT_TX_MGMT_CTRL, pdev->soc, 708 nbuf, HTT_INVALID_PEER, 709 WDI_NO_VAL, pdev->pdev_id); 710 } else { 711 if (!mon_pdev->bpr_enable) 712 qdf_nbuf_free(nbuf); 713 } 714 } 715 #endif 716 #endif 717 718 QDF_STATUS dp_htt_ppdu_stats_attach(struct dp_pdev *pdev) 719 { 720 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 721 722 mon_pdev->ppdu_tlv_buf = qdf_mem_malloc(HTT_T2H_MAX_MSG_SIZE); 723 724 if (!mon_pdev->ppdu_tlv_buf) { 725 QDF_TRACE_ERROR(QDF_MODULE_ID_DP, "ppdu_tlv_buf alloc fail"); 726 return QDF_STATUS_E_NOMEM; 727 } 728 729 return QDF_STATUS_SUCCESS; 730 } 731 732 void dp_htt_ppdu_stats_detach(struct dp_pdev *pdev) 733 { 734 struct ppdu_info *ppdu_info, *ppdu_info_next; 735 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 736 737 738 TAILQ_FOREACH_SAFE(ppdu_info, &mon_pdev->ppdu_info_list, 739 ppdu_info_list_elem, ppdu_info_next) { 740 if (!ppdu_info) 741 break; 742 TAILQ_REMOVE(&mon_pdev->ppdu_info_list, 743 ppdu_info, ppdu_info_list_elem); 744 mon_pdev->list_depth--; 745 qdf_assert_always(ppdu_info->nbuf); 746 qdf_nbuf_free(ppdu_info->nbuf); 747 qdf_mem_free(ppdu_info); 748 } 749 750 TAILQ_FOREACH_SAFE(ppdu_info, &mon_pdev->sched_comp_ppdu_list, 751 ppdu_info_list_elem, ppdu_info_next) { 752 if (!ppdu_info) 753 break; 754 TAILQ_REMOVE(&mon_pdev->sched_comp_ppdu_list, 755 ppdu_info, ppdu_info_list_elem); 756 mon_pdev->sched_comp_list_depth--; 757 qdf_assert_always(ppdu_info->nbuf); 758 qdf_nbuf_free(ppdu_info->nbuf); 759 qdf_mem_free(ppdu_info); 760 } 761 762 if (mon_pdev->ppdu_tlv_buf) 763 qdf_mem_free(mon_pdev->ppdu_tlv_buf); 764 } 765 766 QDF_STATUS dp_pdev_get_rx_mon_stats(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, 767 struct cdp_pdev_mon_stats *stats) 768 { 769 struct dp_soc *soc = (struct dp_soc *)soc_hdl; 770 struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); 771 struct dp_mon_pdev *mon_pdev; 772 773 if (!pdev) 774 return QDF_STATUS_E_FAILURE; 775 776 mon_pdev = pdev->monitor_pdev; 777 if (!mon_pdev) 778 return QDF_STATUS_E_FAILURE; 779 780 qdf_mem_copy(stats, &mon_pdev->rx_mon_stats, 781 sizeof(struct cdp_pdev_mon_stats)); 782 783 return QDF_STATUS_SUCCESS; 784 } 785 786 #ifdef QCA_UNDECODED_METADATA_SUPPORT 787 /** 788 * dp_pdev_get_undecoded_capture_stats() - Get undecoded metadata captured 789 * monitor pdev stats 790 * @mon_pdev: Monitor PDEV handle 791 * @rx_mon_stats: Monitor pdev status/destination ring stats 792 * 793 * Return: None 794 */ 795 static inline void 796 dp_pdev_get_undecoded_capture_stats(struct dp_mon_pdev *mon_pdev, 797 struct cdp_pdev_mon_stats *rx_mon_stats) 798 { 799 char undecoded_error[DP_UNDECODED_ERR_LENGTH]; 800 uint8_t index = 0, i; 801 802 DP_PRINT_STATS("Rx Undecoded Frame count:%d", 803 rx_mon_stats->rx_undecoded_count); 804 index = 0; 805 for (i = 0; i < (CDP_PHYRX_ERR_MAX); i++) { 806 index += qdf_snprint(&undecoded_error[index], 807 DP_UNDECODED_ERR_LENGTH - index, 808 " %d", rx_mon_stats->rx_undecoded_error[i]); 809 } 810 DP_PRINT_STATS("Undecoded Error (0-63):%s", undecoded_error); 811 } 812 #else 813 static inline void 814 dp_pdev_get_undecoded_capture_stats(struct dp_mon_pdev *mon_pdev, 815 struct cdp_pdev_mon_stats *rx_mon_stats) 816 { 817 } 818 #endif 819 820 static const char * 821 dp_preamble_type_str[] = { 822 "preamble OFDMA ", 823 "preamble CCK ", 824 "preamble HT ", 825 "preamble VHT ", 826 "preamble HE ", 827 "preamble EHT ", 828 "preamble NO SUPPORT", 829 }; 830 831 static const char * 832 dp_reception_type_str[] = { 833 "reception su ", 834 "reception mu_mimo ", 835 "reception ofdma ", 836 "reception ofdma mimo", 837 }; 838 839 static const char * 840 dp_mu_dl_ul_str[] = { 841 "MU DL", 842 "MU UL", 843 }; 844 845 static inline void 846 dp_print_pdev_mpdu_fcs_ok_cnt(struct cdp_pdev_mon_stats *rx_mon_sts, 847 uint32_t pkt_t, uint32_t rx_t, 848 uint32_t dl_ul, uint32_t user) 849 { 850 DP_PRINT_STATS("%s, %s, %s, user=%d, mpdu_fcs_ok=%d", 851 dp_preamble_type_str[pkt_t], 852 dp_reception_type_str[rx_t], 853 dp_mu_dl_ul_str[dl_ul], 854 user, 855 rx_mon_sts->mpdu_cnt_fcs_ok[pkt_t][rx_t][dl_ul][user]); 856 } 857 858 static inline void 859 dp_print_pdev_mpdu_fcs_err_cnt(struct cdp_pdev_mon_stats *rx_mon_sts, 860 uint32_t pkt_t, uint32_t rx_t, 861 uint32_t dl_ul, uint32_t user) 862 { 863 DP_PRINT_STATS("%s, %s, %s, user=%d, mpdu_fcs_err=%d", 864 dp_preamble_type_str[pkt_t], 865 dp_reception_type_str[rx_t], 866 dp_mu_dl_ul_str[dl_ul], 867 user, 868 rx_mon_sts->mpdu_cnt_fcs_err[pkt_t][rx_t][dl_ul][user]); 869 } 870 871 static inline void 872 dp_print_pdev_mpdu_cnt(struct cdp_pdev_mon_stats *rx_mon_sts, 873 uint32_t pkt_t, uint32_t rx_t, 874 uint32_t dl_ul, uint32_t user) 875 { 876 if (rx_mon_sts->mpdu_cnt_fcs_ok[pkt_t][rx_t][dl_ul][user]) 877 dp_print_pdev_mpdu_fcs_ok_cnt(rx_mon_sts, pkt_t, rx_t, 878 dl_ul, user); 879 880 if (rx_mon_sts->mpdu_cnt_fcs_err[pkt_t][rx_t][dl_ul][user]) 881 dp_print_pdev_mpdu_fcs_err_cnt(rx_mon_sts, pkt_t, rx_t, 882 dl_ul, user); 883 } 884 885 static inline void 886 dp_print_pdev_mpdu_user(struct cdp_pdev_mon_stats *rx_mon_sts, 887 uint32_t pkt_t, uint32_t rx_t, 888 uint32_t dl_ul) 889 { 890 uint32_t user; 891 892 for (user = 0; user < CDP_MU_SNIF_USER_MAX; user++) 893 dp_print_pdev_mpdu_cnt(rx_mon_sts, pkt_t, rx_t, 894 dl_ul, user); 895 } 896 897 static inline void 898 dp_print_pdev_mpdu_dl_ul(struct cdp_pdev_mon_stats *rx_mon_sts, 899 uint32_t pkt_t, uint32_t rx_t) 900 { 901 uint32_t dl_ul; 902 903 for (dl_ul = CDP_MU_TYPE_DL; dl_ul < CDP_MU_TYPE_MAX; dl_ul++) 904 dp_print_pdev_mpdu_user(rx_mon_sts, pkt_t, rx_t, 905 dl_ul); 906 } 907 908 static inline void 909 dp_print_pdev_mpdu_rx_type(struct cdp_pdev_mon_stats *rx_mon_sts, 910 uint32_t pkt_t) 911 { 912 uint32_t rx_t; 913 914 for (rx_t = CDP_RX_TYPE_SU; rx_t < CDP_RX_TYPE_MAX; rx_t++) 915 dp_print_pdev_mpdu_dl_ul(rx_mon_sts, pkt_t, rx_t); 916 } 917 918 static inline void 919 dp_print_pdev_mpdu_pkt_type(struct cdp_pdev_mon_stats *rx_mon_sts) 920 { 921 uint32_t pkt_t; 922 923 for (pkt_t = CDP_PKT_TYPE_OFDM; pkt_t < CDP_PKT_TYPE_MAX; pkt_t++) 924 dp_print_pdev_mpdu_rx_type(rx_mon_sts, pkt_t); 925 } 926 927 static inline void 928 print_ppdu_eht_type_mode( 929 struct cdp_pdev_mon_stats *rx_mon_stats, 930 uint32_t ppdu_type_mode, 931 uint32_t dl_ul) 932 { 933 DP_PRINT_STATS("type_mode=%d, dl_ul=%d, cnt=%d", 934 ppdu_type_mode, 935 dl_ul, 936 rx_mon_stats->ppdu_eht_type_mode[ppdu_type_mode][dl_ul]); 937 } 938 939 static inline void 940 print_ppdu_eth_type_mode_dl_ul( 941 struct cdp_pdev_mon_stats *rx_mon_stats, 942 uint32_t ppdu_type_mode 943 ) 944 { 945 uint32_t dl_ul; 946 947 for (dl_ul = 0; dl_ul < CDP_MU_TYPE_MAX; dl_ul++) { 948 if (rx_mon_stats->ppdu_eht_type_mode[ppdu_type_mode][dl_ul]) 949 print_ppdu_eht_type_mode(rx_mon_stats, 950 ppdu_type_mode, dl_ul); 951 } 952 } 953 954 static inline void 955 dp_print_pdev_eht_ppdu_cnt(struct dp_pdev *pdev) 956 { 957 struct cdp_pdev_mon_stats *rx_mon_stats; 958 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 959 uint32_t ppdu_type_mode; 960 961 rx_mon_stats = &mon_pdev->rx_mon_stats; 962 DP_PRINT_STATS("Monitor EHT PPDU Count"); 963 for (ppdu_type_mode = 0; ppdu_type_mode < CDP_EHT_TYPE_MODE_MAX; 964 ppdu_type_mode++) { 965 print_ppdu_eth_type_mode_dl_ul(rx_mon_stats, 966 ppdu_type_mode); 967 } 968 } 969 970 static inline void 971 dp_print_pdev_mpdu_stats(struct dp_pdev *pdev) 972 { 973 struct cdp_pdev_mon_stats *rx_mon_stats; 974 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 975 976 rx_mon_stats = &mon_pdev->rx_mon_stats; 977 DP_PRINT_STATS("Monitor MPDU Count"); 978 dp_print_pdev_mpdu_pkt_type(rx_mon_stats); 979 } 980 981 void 982 dp_print_pdev_rx_mon_stats(struct dp_pdev *pdev) 983 { 984 struct cdp_pdev_mon_stats *rx_mon_stats; 985 uint32_t *stat_ring_ppdu_ids; 986 uint32_t *dest_ring_ppdu_ids; 987 int i, idx; 988 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 989 990 rx_mon_stats = &mon_pdev->rx_mon_stats; 991 992 DP_PRINT_STATS("PDEV Rx Monitor Stats:\n"); 993 994 DP_PRINT_STATS("status_ppdu_compl_cnt = %d", 995 rx_mon_stats->status_ppdu_compl); 996 DP_PRINT_STATS("status_ppdu_start_cnt = %d", 997 rx_mon_stats->status_ppdu_start); 998 DP_PRINT_STATS("status_ppdu_end_cnt = %d", 999 rx_mon_stats->status_ppdu_end); 1000 DP_PRINT_STATS("status_ppdu_start_mis_cnt = %d", 1001 rx_mon_stats->status_ppdu_start_mis); 1002 DP_PRINT_STATS("status_ppdu_end_mis_cnt = %d", 1003 rx_mon_stats->status_ppdu_end_mis); 1004 1005 DP_PRINT_STATS("start_user_info_cnt = %d", 1006 rx_mon_stats->start_user_info_cnt); 1007 DP_PRINT_STATS("end_user_stats_cnt = %d", 1008 rx_mon_stats->end_user_stats_cnt); 1009 1010 DP_PRINT_STATS("status_ppdu_done_cnt = %d", 1011 rx_mon_stats->status_ppdu_done); 1012 DP_PRINT_STATS("dest_ppdu_done_cnt = %d", 1013 rx_mon_stats->dest_ppdu_done); 1014 DP_PRINT_STATS("dest_mpdu_done_cnt = %d", 1015 rx_mon_stats->dest_mpdu_done); 1016 DP_PRINT_STATS("tlv_tag_status_err_cnt = %u", 1017 rx_mon_stats->tlv_tag_status_err); 1018 DP_PRINT_STATS("mon status DMA not done WAR count= %u", 1019 rx_mon_stats->status_buf_done_war); 1020 DP_PRINT_STATS("dest_mpdu_drop_cnt = %d", 1021 rx_mon_stats->dest_mpdu_drop); 1022 DP_PRINT_STATS("dup_mon_linkdesc_cnt = %d", 1023 rx_mon_stats->dup_mon_linkdesc_cnt); 1024 DP_PRINT_STATS("dup_mon_buf_cnt = %d", 1025 rx_mon_stats->dup_mon_buf_cnt); 1026 DP_PRINT_STATS("mon_rx_buf_reaped = %u", 1027 rx_mon_stats->mon_rx_bufs_reaped_dest); 1028 DP_PRINT_STATS("mon_rx_buf_replenished = %u", 1029 rx_mon_stats->mon_rx_bufs_replenished_dest); 1030 DP_PRINT_STATS("ppdu_id_mismatch = %u", 1031 rx_mon_stats->ppdu_id_mismatch); 1032 DP_PRINT_STATS("mpdu_ppdu_id_match_cnt = %d", 1033 rx_mon_stats->ppdu_id_match); 1034 DP_PRINT_STATS("ppdus dropped frm status ring = %d", 1035 rx_mon_stats->status_ppdu_drop); 1036 DP_PRINT_STATS("ppdus dropped frm dest ring = %d", 1037 rx_mon_stats->dest_ppdu_drop); 1038 DP_PRINT_STATS("mpdu_ppdu_id_mismatch_drop = %u", 1039 rx_mon_stats->mpdu_ppdu_id_mismatch_drop); 1040 DP_PRINT_STATS("mpdu_decap_type_invalid = %u", 1041 rx_mon_stats->mpdu_decap_type_invalid); 1042 stat_ring_ppdu_ids = 1043 (uint32_t *)qdf_mem_malloc(sizeof(uint32_t) * MAX_PPDU_ID_HIST); 1044 dest_ring_ppdu_ids = 1045 (uint32_t *)qdf_mem_malloc(sizeof(uint32_t) * MAX_PPDU_ID_HIST); 1046 1047 if (!stat_ring_ppdu_ids || !dest_ring_ppdu_ids) 1048 DP_PRINT_STATS("Unable to allocate ppdu id hist mem\n"); 1049 1050 qdf_spin_lock_bh(&mon_pdev->mon_lock); 1051 idx = rx_mon_stats->ppdu_id_hist_idx; 1052 qdf_mem_copy(stat_ring_ppdu_ids, 1053 rx_mon_stats->stat_ring_ppdu_id_hist, 1054 sizeof(uint32_t) * MAX_PPDU_ID_HIST); 1055 qdf_mem_copy(dest_ring_ppdu_ids, 1056 rx_mon_stats->dest_ring_ppdu_id_hist, 1057 sizeof(uint32_t) * MAX_PPDU_ID_HIST); 1058 qdf_spin_unlock_bh(&mon_pdev->mon_lock); 1059 1060 DP_PRINT_STATS("PPDU Id history:"); 1061 DP_PRINT_STATS("stat_ring_ppdu_ids\t dest_ring_ppdu_ids"); 1062 for (i = 0; i < MAX_PPDU_ID_HIST; i++) { 1063 idx = (idx + 1) & (MAX_PPDU_ID_HIST - 1); 1064 DP_PRINT_STATS("%*u\t%*u", 16, 1065 rx_mon_stats->stat_ring_ppdu_id_hist[idx], 16, 1066 rx_mon_stats->dest_ring_ppdu_id_hist[idx]); 1067 } 1068 qdf_mem_free(stat_ring_ppdu_ids); 1069 qdf_mem_free(dest_ring_ppdu_ids); 1070 DP_PRINT_STATS("mon_rx_dest_stuck = %d", 1071 rx_mon_stats->mon_rx_dest_stuck); 1072 1073 dp_pdev_get_undecoded_capture_stats(mon_pdev, rx_mon_stats); 1074 dp_mon_rx_print_advanced_stats(pdev->soc, pdev); 1075 1076 dp_print_pdev_mpdu_stats(pdev); 1077 dp_print_pdev_eht_ppdu_cnt(pdev); 1078 1079 } 1080 1081 #ifdef QCA_SUPPORT_BPR 1082 QDF_STATUS 1083 dp_set_bpr_enable(struct dp_pdev *pdev, int val) 1084 { 1085 struct dp_mon_ops *mon_ops; 1086 1087 mon_ops = dp_mon_ops_get(pdev->soc); 1088 if (mon_ops && mon_ops->mon_set_bpr_enable) 1089 return mon_ops->mon_set_bpr_enable(pdev, val); 1090 1091 return QDF_STATUS_E_FAILURE; 1092 } 1093 #endif 1094 1095 #ifdef WDI_EVENT_ENABLE 1096 #ifdef BE_PKTLOG_SUPPORT 1097 static bool 1098 dp_set_hybrid_pktlog_enable(struct dp_pdev *pdev, 1099 struct dp_mon_pdev *mon_pdev, 1100 struct dp_soc *soc) 1101 { 1102 struct wlan_cfg_dp_soc_ctxt *soc_cfg_ctx; 1103 struct dp_mon_ops *mon_ops = NULL; 1104 uint16_t num_buffers; 1105 1106 if (mon_pdev->mvdev) { 1107 /* Nothing needs to be done if monitor mode is 1108 * enabled 1109 */ 1110 mon_pdev->pktlog_hybrid_mode = true; 1111 return false; 1112 } 1113 1114 mon_ops = dp_mon_ops_get(pdev->soc); 1115 if (!mon_ops) { 1116 dp_mon_filter_err("Mon ops uninitialized"); 1117 return QDF_STATUS_E_FAILURE; 1118 } 1119 1120 if (!mon_pdev->pktlog_hybrid_mode) { 1121 mon_pdev->pktlog_hybrid_mode = true; 1122 soc_cfg_ctx = soc->wlan_cfg_ctx; 1123 num_buffers = 1124 wlan_cfg_get_dp_soc_tx_mon_buf_ring_size(soc_cfg_ctx); 1125 1126 if (mon_ops && mon_ops->set_mon_mode_buf_rings_tx) 1127 mon_ops->set_mon_mode_buf_rings_tx(pdev, num_buffers); 1128 1129 dp_mon_filter_setup_pktlog_hybrid(pdev); 1130 if (dp_tx_mon_filter_update(pdev) != 1131 QDF_STATUS_SUCCESS) { 1132 dp_cdp_err("Set hybrid filters failed"); 1133 dp_mon_filter_reset_pktlog_hybrid(pdev); 1134 mon_pdev->rx_pktlog_mode = 1135 DP_RX_PKTLOG_DISABLED; 1136 return false; 1137 } 1138 1139 dp_monitor_reap_timer_start(soc, CDP_MON_REAP_SOURCE_PKTLOG); 1140 } 1141 1142 return true; 1143 } 1144 1145 static void 1146 dp_set_hybrid_pktlog_disable(struct dp_mon_pdev *mon_pdev) 1147 { 1148 mon_pdev->pktlog_hybrid_mode = false; 1149 } 1150 #else 1151 static void 1152 dp_set_hybrid_pktlog_disable(struct dp_mon_pdev *mon_pdev) 1153 { 1154 } 1155 1156 static bool 1157 dp_set_hybrid_pktlog_enable(struct dp_pdev *pdev, 1158 struct dp_mon_pdev *mon_pdev, 1159 struct dp_soc *soc) 1160 { 1161 dp_cdp_err("Hybrid mode is supported only on beryllium"); 1162 return true; 1163 } 1164 #endif 1165 int dp_set_pktlog_wifi3(struct dp_pdev *pdev, uint32_t event, 1166 bool enable) 1167 { 1168 struct dp_soc *soc = NULL; 1169 int max_mac_rings = wlan_cfg_get_num_mac_rings 1170 (pdev->wlan_cfg_ctx); 1171 uint8_t mac_id = 0; 1172 struct dp_mon_ops *mon_ops; 1173 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 1174 1175 soc = pdev->soc; 1176 mon_ops = dp_mon_ops_get(soc); 1177 1178 if (!mon_ops) 1179 return 0; 1180 1181 dp_update_num_mac_rings_for_dbs(soc, &max_mac_rings); 1182 1183 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, 1184 FL("Max_mac_rings %d "), 1185 max_mac_rings); 1186 1187 if (enable) { 1188 switch (event) { 1189 case WDI_EVENT_RX_DESC: 1190 /* Nothing needs to be done if monitor mode is 1191 * enabled 1192 */ 1193 if (mon_pdev->mvdev) 1194 return 0; 1195 1196 if (mon_pdev->rx_pktlog_mode == DP_RX_PKTLOG_FULL) 1197 break; 1198 1199 mon_pdev->rx_pktlog_mode = DP_RX_PKTLOG_FULL; 1200 dp_mon_filter_setup_rx_pkt_log_full(pdev); 1201 if (dp_mon_filter_update(pdev) != QDF_STATUS_SUCCESS) { 1202 dp_cdp_err("%pK: Pktlog full filters set failed", 1203 soc); 1204 dp_mon_filter_reset_rx_pkt_log_full(pdev); 1205 mon_pdev->rx_pktlog_mode = 1206 DP_RX_PKTLOG_DISABLED; 1207 return 0; 1208 } 1209 1210 dp_monitor_reap_timer_start(soc, 1211 CDP_MON_REAP_SOURCE_PKTLOG); 1212 break; 1213 1214 case WDI_EVENT_LITE_RX: 1215 /* Nothing needs to be done if monitor mode is 1216 * enabled 1217 */ 1218 if (mon_pdev->mvdev) 1219 return 0; 1220 1221 if (mon_pdev->rx_pktlog_mode == DP_RX_PKTLOG_LITE) 1222 break; 1223 1224 mon_pdev->rx_pktlog_mode = DP_RX_PKTLOG_LITE; 1225 1226 /* 1227 * Set the packet log lite mode filter. 1228 */ 1229 dp_mon_filter_setup_rx_pkt_log_lite(pdev); 1230 if (dp_mon_filter_update(pdev) != QDF_STATUS_SUCCESS) { 1231 dp_cdp_err("%pK: Pktlog lite filters set failed", 1232 soc); 1233 dp_mon_filter_reset_rx_pkt_log_lite(pdev); 1234 mon_pdev->rx_pktlog_mode = 1235 DP_RX_PKTLOG_DISABLED; 1236 return 0; 1237 } 1238 1239 dp_monitor_reap_timer_start(soc, 1240 CDP_MON_REAP_SOURCE_PKTLOG); 1241 break; 1242 case WDI_EVENT_LITE_T2H: 1243 for (mac_id = 0; mac_id < max_mac_rings; mac_id++) { 1244 int mac_for_pdev = dp_get_mac_id_for_pdev( 1245 mac_id, pdev->pdev_id); 1246 1247 mon_pdev->pktlog_ppdu_stats = true; 1248 dp_h2t_cfg_stats_msg_send(pdev, 1249 DP_PPDU_TXLITE_STATS_BITMASK_CFG, 1250 mac_for_pdev); 1251 } 1252 break; 1253 1254 case WDI_EVENT_RX_CBF: 1255 /* Nothing needs to be done if monitor mode is 1256 * enabled 1257 */ 1258 if (mon_pdev->mvdev) 1259 return 0; 1260 1261 if (mon_pdev->rx_pktlog_cbf) 1262 break; 1263 1264 mon_pdev->rx_pktlog_cbf = true; 1265 mon_pdev->monitor_configured = true; 1266 if (mon_ops->mon_vdev_set_monitor_mode_buf_rings) 1267 mon_ops->mon_vdev_set_monitor_mode_buf_rings( 1268 pdev); 1269 1270 /* 1271 * Set the packet log lite mode filter. 1272 */ 1273 qdf_info("Non mon mode: Enable destination ring"); 1274 1275 dp_mon_filter_setup_rx_pkt_log_cbf(pdev); 1276 if (dp_mon_filter_update(pdev) != QDF_STATUS_SUCCESS) { 1277 dp_mon_err("Pktlog set CBF filters failed"); 1278 dp_mon_filter_reset_rx_pktlog_cbf(pdev); 1279 mon_pdev->rx_pktlog_mode = 1280 DP_RX_PKTLOG_DISABLED; 1281 mon_pdev->monitor_configured = false; 1282 return 0; 1283 } 1284 1285 dp_monitor_reap_timer_start(soc, 1286 CDP_MON_REAP_SOURCE_PKTLOG); 1287 break; 1288 case WDI_EVENT_HYBRID_TX: 1289 if (!dp_set_hybrid_pktlog_enable(pdev, mon_pdev, soc)) 1290 return 0; 1291 break; 1292 1293 default: 1294 /* Nothing needs to be done for other pktlog types */ 1295 break; 1296 } 1297 } else { 1298 switch (event) { 1299 case WDI_EVENT_RX_DESC: 1300 case WDI_EVENT_LITE_RX: 1301 /* Nothing needs to be done if monitor mode is 1302 * enabled 1303 */ 1304 if (mon_pdev->mvdev) 1305 return 0; 1306 1307 if (mon_pdev->rx_pktlog_mode == DP_RX_PKTLOG_DISABLED) 1308 break; 1309 1310 mon_pdev->rx_pktlog_mode = DP_RX_PKTLOG_DISABLED; 1311 dp_mon_filter_reset_rx_pkt_log_full(pdev); 1312 if (dp_mon_filter_update(pdev) != QDF_STATUS_SUCCESS) { 1313 dp_cdp_err("%pK: Pktlog filters reset failed", 1314 soc); 1315 return 0; 1316 } 1317 1318 dp_mon_filter_reset_rx_pkt_log_lite(pdev); 1319 if (dp_mon_filter_update(pdev) != QDF_STATUS_SUCCESS) { 1320 dp_cdp_err("%pK: Pktlog filters reset failed", 1321 soc); 1322 return 0; 1323 } 1324 1325 dp_monitor_reap_timer_stop(soc, 1326 CDP_MON_REAP_SOURCE_PKTLOG); 1327 break; 1328 case WDI_EVENT_LITE_T2H: 1329 /* 1330 * To disable HTT_H2T_MSG_TYPE_PPDU_STATS_CFG in FW 1331 * passing value 0. Once these macros will define in htt 1332 * header file will use proper macros 1333 */ 1334 for (mac_id = 0; mac_id < max_mac_rings; mac_id++) { 1335 int mac_for_pdev = 1336 dp_get_mac_id_for_pdev(mac_id, 1337 pdev->pdev_id); 1338 1339 mon_pdev->pktlog_ppdu_stats = false; 1340 if (!mon_pdev->enhanced_stats_en && 1341 !mon_pdev->tx_sniffer_enable && 1342 !mon_pdev->mcopy_mode) { 1343 dp_h2t_cfg_stats_msg_send(pdev, 0, 1344 mac_for_pdev); 1345 } else if (mon_pdev->tx_sniffer_enable || 1346 mon_pdev->mcopy_mode) { 1347 dp_h2t_cfg_stats_msg_send(pdev, 1348 DP_PPDU_STATS_CFG_SNIFFER, 1349 mac_for_pdev); 1350 } else if (mon_pdev->enhanced_stats_en) { 1351 dp_h2t_cfg_stats_msg_send(pdev, 1352 DP_PPDU_STATS_CFG_ENH_STATS, 1353 mac_for_pdev); 1354 } 1355 } 1356 1357 break; 1358 case WDI_EVENT_RX_CBF: 1359 mon_pdev->rx_pktlog_cbf = false; 1360 break; 1361 1362 case WDI_EVENT_HYBRID_TX: 1363 dp_set_hybrid_pktlog_disable(mon_pdev); 1364 break; 1365 1366 default: 1367 /* Nothing needs to be done for other pktlog types */ 1368 break; 1369 } 1370 } 1371 return 0; 1372 } 1373 #endif 1374 1375 /* MCL specific functions */ 1376 #if defined(DP_CON_MON) && !defined(REMOVE_PKT_LOG) 1377 void dp_pktlogmod_exit(struct dp_pdev *pdev) 1378 { 1379 struct dp_soc *soc = pdev->soc; 1380 struct hif_opaque_softc *scn = soc->hif_handle; 1381 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 1382 1383 if (!scn) { 1384 dp_mon_err("Invalid hif(scn) handle"); 1385 return; 1386 } 1387 1388 dp_monitor_reap_timer_stop(soc, CDP_MON_REAP_SOURCE_PKTLOG); 1389 pktlogmod_exit(scn); 1390 mon_pdev->pkt_log_init = false; 1391 } 1392 #endif /*DP_CON_MON*/ 1393 1394 #if defined(WDI_EVENT_ENABLE) && defined(QCA_ENHANCED_STATS_SUPPORT) 1395 #ifdef IPA_OFFLOAD 1396 void dp_peer_get_tx_rx_stats(struct dp_peer *peer, 1397 struct cdp_interface_peer_stats *peer_stats_intf) 1398 { 1399 struct dp_rx_tid *rx_tid = NULL; 1400 uint8_t i = 0; 1401 1402 for (i = 0; i < DP_MAX_TIDS; i++) { 1403 rx_tid = &peer->rx_tid[i]; 1404 peer_stats_intf->rx_byte_count += 1405 rx_tid->rx_msdu_cnt.bytes; 1406 peer_stats_intf->rx_packet_count += 1407 rx_tid->rx_msdu_cnt.num; 1408 } 1409 peer_stats_intf->tx_packet_count = 1410 peer->monitor_peer->stats.tx.tx_ucast_success.num; 1411 peer_stats_intf->tx_byte_count = 1412 peer->monitor_peer->stats.tx.tx_ucast_success.bytes; 1413 } 1414 #else 1415 void dp_peer_get_tx_rx_stats(struct dp_peer *peer, 1416 struct cdp_interface_peer_stats *peer_stats_intf) 1417 { 1418 struct dp_txrx_peer *txrx_peer = NULL; 1419 struct dp_peer *tgt_peer = NULL; 1420 1421 tgt_peer = dp_get_tgt_peer_from_peer(peer); 1422 txrx_peer = tgt_peer->txrx_peer; 1423 peer_stats_intf->rx_packet_count = txrx_peer->to_stack.num; 1424 peer_stats_intf->rx_byte_count = txrx_peer->to_stack.bytes; 1425 peer_stats_intf->tx_packet_count = 1426 txrx_peer->stats.per_pkt_stats.tx.ucast.num; 1427 peer_stats_intf->tx_byte_count = 1428 txrx_peer->stats.per_pkt_stats.tx.tx_success.bytes; 1429 } 1430 #endif 1431 1432 QDF_STATUS dp_peer_stats_notify(struct dp_pdev *dp_pdev, struct dp_peer *peer) 1433 { 1434 struct cdp_interface_peer_stats peer_stats_intf = {0}; 1435 struct dp_mon_peer_stats *mon_peer_stats = NULL; 1436 struct dp_peer *tgt_peer = NULL; 1437 struct dp_txrx_peer *txrx_peer = NULL; 1438 1439 if (qdf_unlikely(!peer || !peer->vdev || !peer->monitor_peer)) 1440 return QDF_STATUS_E_FAULT; 1441 1442 tgt_peer = dp_get_tgt_peer_from_peer(peer); 1443 if (qdf_unlikely(!tgt_peer)) 1444 return QDF_STATUS_E_FAULT; 1445 1446 txrx_peer = tgt_peer->txrx_peer; 1447 if (!qdf_unlikely(txrx_peer)) 1448 return QDF_STATUS_E_FAULT; 1449 1450 mon_peer_stats = &peer->monitor_peer->stats; 1451 1452 if (mon_peer_stats->rx.last_snr != mon_peer_stats->rx.snr) 1453 peer_stats_intf.rssi_changed = true; 1454 1455 if ((mon_peer_stats->rx.snr && peer_stats_intf.rssi_changed) || 1456 (mon_peer_stats->tx.tx_rate && 1457 mon_peer_stats->tx.tx_rate != mon_peer_stats->tx.last_tx_rate)) { 1458 qdf_mem_copy(peer_stats_intf.peer_mac, peer->mac_addr.raw, 1459 QDF_MAC_ADDR_SIZE); 1460 peer_stats_intf.vdev_id = peer->vdev->vdev_id; 1461 peer_stats_intf.last_peer_tx_rate = 1462 mon_peer_stats->tx.last_tx_rate; 1463 peer_stats_intf.peer_tx_rate = mon_peer_stats->tx.tx_rate; 1464 peer_stats_intf.peer_rssi = mon_peer_stats->rx.snr; 1465 peer_stats_intf.ack_rssi = mon_peer_stats->tx.last_ack_rssi; 1466 dp_peer_get_tx_rx_stats(peer, &peer_stats_intf); 1467 peer_stats_intf.per = tgt_peer->stats.tx.last_per; 1468 peer_stats_intf.free_buff = INVALID_FREE_BUFF; 1469 dp_wdi_event_handler(WDI_EVENT_PEER_STATS, dp_pdev->soc, 1470 (void *)&peer_stats_intf, 0, 1471 WDI_NO_VAL, dp_pdev->pdev_id); 1472 } 1473 1474 return QDF_STATUS_SUCCESS; 1475 } 1476 #endif 1477 1478 #ifdef FEATURE_NAC_RSSI 1479 /** 1480 * dp_rx_nac_filter(): Function to perform filtering of non-associated 1481 * clients 1482 * @pdev: DP pdev handle 1483 * @rx_pkt_hdr: Rx packet Header 1484 * 1485 * return: dp_vdev* 1486 */ 1487 static 1488 struct dp_vdev *dp_rx_nac_filter(struct dp_pdev *pdev, 1489 uint8_t *rx_pkt_hdr) 1490 { 1491 struct ieee80211_frame *wh; 1492 struct dp_neighbour_peer *peer = NULL; 1493 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 1494 1495 wh = (struct ieee80211_frame *)rx_pkt_hdr; 1496 1497 if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) != IEEE80211_FC1_DIR_TODS) 1498 return NULL; 1499 1500 qdf_spin_lock_bh(&mon_pdev->neighbour_peer_mutex); 1501 TAILQ_FOREACH(peer, &mon_pdev->neighbour_peers_list, 1502 neighbour_peer_list_elem) { 1503 if (qdf_mem_cmp(&peer->neighbour_peers_macaddr.raw[0], 1504 wh->i_addr2, QDF_MAC_ADDR_SIZE) == 0) { 1505 dp_rx_debug("%pK: NAC configuration matched for mac-%2x:%2x:%2x:%2x:%2x:%2x", 1506 pdev->soc, 1507 peer->neighbour_peers_macaddr.raw[0], 1508 peer->neighbour_peers_macaddr.raw[1], 1509 peer->neighbour_peers_macaddr.raw[2], 1510 peer->neighbour_peers_macaddr.raw[3], 1511 peer->neighbour_peers_macaddr.raw[4], 1512 peer->neighbour_peers_macaddr.raw[5]); 1513 1514 qdf_spin_unlock_bh(&mon_pdev->neighbour_peer_mutex); 1515 1516 return mon_pdev->mvdev; 1517 } 1518 } 1519 qdf_spin_unlock_bh(&mon_pdev->neighbour_peer_mutex); 1520 1521 return NULL; 1522 } 1523 1524 QDF_STATUS dp_filter_neighbour_peer(struct dp_pdev *pdev, 1525 uint8_t *rx_pkt_hdr) 1526 { 1527 struct dp_vdev *vdev = NULL; 1528 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 1529 1530 if (mon_pdev->filter_neighbour_peers) { 1531 /* Next Hop scenario not yet handle */ 1532 vdev = dp_rx_nac_filter(pdev, rx_pkt_hdr); 1533 if (vdev) { 1534 dp_rx_mon_deliver(pdev->soc, pdev->pdev_id, 1535 pdev->invalid_peer_head_msdu, 1536 pdev->invalid_peer_tail_msdu); 1537 1538 pdev->invalid_peer_head_msdu = NULL; 1539 pdev->invalid_peer_tail_msdu = NULL; 1540 return QDF_STATUS_SUCCESS; 1541 } 1542 } 1543 1544 return QDF_STATUS_E_FAILURE; 1545 } 1546 #endif 1547 1548 #if defined(ATH_SUPPORT_NAC_RSSI) || defined(ATH_SUPPORT_NAC) 1549 /* 1550 * dp_update_filter_neighbour_peers() - set neighbour peers(nac clients) 1551 * address for smart mesh filtering 1552 * @txrx_soc: cdp soc handle 1553 * @vdev_id: id of virtual device object 1554 * @cmd: Add/Del command 1555 * @macaddr: nac client mac address 1556 * 1557 * Return: success/failure 1558 */ 1559 static int dp_update_filter_neighbour_peers(struct cdp_soc_t *soc_hdl, 1560 uint8_t vdev_id, 1561 uint32_t cmd, uint8_t *macaddr) 1562 { 1563 struct dp_soc *soc = (struct dp_soc *)soc_hdl; 1564 struct dp_pdev *pdev; 1565 struct dp_neighbour_peer *peer = NULL; 1566 struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id, 1567 DP_MOD_ID_CDP); 1568 struct dp_mon_pdev *mon_pdev; 1569 1570 if (!vdev || !macaddr) 1571 goto fail0; 1572 1573 pdev = vdev->pdev; 1574 1575 if (!pdev) 1576 goto fail0; 1577 1578 mon_pdev = pdev->monitor_pdev; 1579 1580 /* Store address of NAC (neighbour peer) which will be checked 1581 * against TA of received packets. 1582 */ 1583 if (cmd == DP_NAC_PARAM_ADD) { 1584 peer = (struct dp_neighbour_peer *)qdf_mem_malloc( 1585 sizeof(*peer)); 1586 1587 if (!peer) { 1588 dp_cdp_err("%pK: DP neighbour peer node memory allocation failed" 1589 , soc); 1590 goto fail0; 1591 } 1592 1593 qdf_mem_copy(&peer->neighbour_peers_macaddr.raw[0], 1594 macaddr, QDF_MAC_ADDR_SIZE); 1595 peer->vdev = vdev; 1596 1597 qdf_spin_lock_bh(&mon_pdev->neighbour_peer_mutex); 1598 1599 /* add this neighbour peer into the list */ 1600 TAILQ_INSERT_TAIL(&mon_pdev->neighbour_peers_list, peer, 1601 neighbour_peer_list_elem); 1602 qdf_spin_unlock_bh(&mon_pdev->neighbour_peer_mutex); 1603 1604 /* first neighbour */ 1605 if (!mon_pdev->neighbour_peers_added) { 1606 QDF_STATUS status = QDF_STATUS_SUCCESS; 1607 1608 mon_pdev->neighbour_peers_added = true; 1609 dp_mon_filter_setup_smart_monitor(pdev); 1610 status = dp_mon_filter_update(pdev); 1611 if (status != QDF_STATUS_SUCCESS) { 1612 dp_cdp_err("%pK: smart mon filter setup failed", 1613 soc); 1614 dp_mon_filter_reset_smart_monitor(pdev); 1615 mon_pdev->neighbour_peers_added = false; 1616 } 1617 } 1618 1619 } else if (cmd == DP_NAC_PARAM_DEL) { 1620 qdf_spin_lock_bh(&mon_pdev->neighbour_peer_mutex); 1621 TAILQ_FOREACH(peer, &mon_pdev->neighbour_peers_list, 1622 neighbour_peer_list_elem) { 1623 if (!qdf_mem_cmp(&peer->neighbour_peers_macaddr.raw[0], 1624 macaddr, QDF_MAC_ADDR_SIZE)) { 1625 /* delete this peer from the list */ 1626 TAILQ_REMOVE(&mon_pdev->neighbour_peers_list, 1627 peer, neighbour_peer_list_elem); 1628 qdf_mem_free(peer); 1629 break; 1630 } 1631 } 1632 /* last neighbour deleted */ 1633 if (TAILQ_EMPTY(&mon_pdev->neighbour_peers_list)) { 1634 QDF_STATUS status = QDF_STATUS_SUCCESS; 1635 1636 dp_mon_filter_reset_smart_monitor(pdev); 1637 status = dp_mon_filter_update(pdev); 1638 if (status != QDF_STATUS_SUCCESS) { 1639 dp_cdp_err("%pK: smart mon filter clear failed", 1640 soc); 1641 } 1642 mon_pdev->neighbour_peers_added = false; 1643 } 1644 qdf_spin_unlock_bh(&mon_pdev->neighbour_peer_mutex); 1645 } 1646 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP); 1647 return 1; 1648 1649 fail0: 1650 if (vdev) 1651 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP); 1652 return 0; 1653 } 1654 #endif /* ATH_SUPPORT_NAC_RSSI || ATH_SUPPORT_NAC */ 1655 1656 /* 1657 * dp_update_mon_mac_filter() - Set/reset monitor mac filter 1658 * @soc_hdl: cdp soc handle 1659 * @vdev_id: id of virtual device object 1660 * @cmd: Add/Del command 1661 * 1662 * Return: 0 for success. nonzero for failure. 1663 */ 1664 static QDF_STATUS dp_update_mon_mac_filter(struct cdp_soc_t *soc_hdl, 1665 uint8_t vdev_id, uint32_t cmd) 1666 { 1667 struct dp_soc *soc = (struct dp_soc *)soc_hdl; 1668 struct dp_pdev *pdev; 1669 struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id, 1670 DP_MOD_ID_CDP); 1671 struct dp_mon_pdev *mon_pdev; 1672 QDF_STATUS status = QDF_STATUS_E_FAILURE; 1673 1674 if (!vdev) 1675 return status; 1676 1677 pdev = vdev->pdev; 1678 if (!pdev) { 1679 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP); 1680 return status; 1681 } 1682 1683 mon_pdev = pdev->monitor_pdev; 1684 if (cmd == DP_NAC_PARAM_ADD) { 1685 /* first neighbour added */ 1686 dp_mon_filter_set_reset_mon_mac_filter(pdev, true); 1687 status = dp_mon_filter_update(pdev); 1688 if (status != QDF_STATUS_SUCCESS) { 1689 dp_cdp_err("%pK: Mon mac filter set failed", soc); 1690 dp_mon_filter_set_reset_mon_mac_filter(pdev, false); 1691 } 1692 } else if (cmd == DP_NAC_PARAM_DEL) { 1693 /* last neighbour deleted */ 1694 dp_mon_filter_set_reset_mon_mac_filter(pdev, false); 1695 status = dp_mon_filter_update(pdev); 1696 if (status != QDF_STATUS_SUCCESS) 1697 dp_cdp_err("%pK: Mon mac filter reset failed", soc); 1698 } 1699 1700 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP); 1701 return status; 1702 } 1703 1704 #ifdef ATH_SUPPORT_NAC_RSSI 1705 /** 1706 * dp_vdev_get_neighbour_rssi(): Store RSSI for configured NAC 1707 * @soc_hdl: DP soc handle 1708 * @vdev_id: id of DP vdev handle 1709 * @mac_addr: neighbour mac 1710 * @rssi: rssi value 1711 * 1712 * Return: 0 for success. nonzero for failure. 1713 */ 1714 static QDF_STATUS dp_vdev_get_neighbour_rssi(struct cdp_soc_t *soc_hdl, 1715 uint8_t vdev_id, 1716 char *mac_addr, 1717 uint8_t *rssi) 1718 { 1719 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); 1720 struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id, 1721 DP_MOD_ID_CDP); 1722 struct dp_pdev *pdev; 1723 struct dp_neighbour_peer *peer = NULL; 1724 QDF_STATUS status = QDF_STATUS_E_FAILURE; 1725 struct dp_mon_pdev *mon_pdev; 1726 1727 if (!vdev) 1728 return status; 1729 1730 pdev = vdev->pdev; 1731 mon_pdev = pdev->monitor_pdev; 1732 1733 *rssi = 0; 1734 qdf_spin_lock_bh(&mon_pdev->neighbour_peer_mutex); 1735 TAILQ_FOREACH(peer, &mon_pdev->neighbour_peers_list, 1736 neighbour_peer_list_elem) { 1737 if (qdf_mem_cmp(&peer->neighbour_peers_macaddr.raw[0], 1738 mac_addr, QDF_MAC_ADDR_SIZE) == 0) { 1739 *rssi = peer->rssi; 1740 status = QDF_STATUS_SUCCESS; 1741 break; 1742 } 1743 } 1744 qdf_spin_unlock_bh(&mon_pdev->neighbour_peer_mutex); 1745 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP); 1746 return status; 1747 } 1748 1749 static QDF_STATUS 1750 dp_config_for_nac_rssi(struct cdp_soc_t *cdp_soc, 1751 uint8_t vdev_id, 1752 enum cdp_nac_param_cmd cmd, char *bssid, 1753 char *client_macaddr, 1754 uint8_t chan_num) 1755 { 1756 struct dp_soc *soc = (struct dp_soc *)cdp_soc; 1757 struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id, 1758 DP_MOD_ID_CDP); 1759 struct dp_pdev *pdev; 1760 struct dp_mon_pdev *mon_pdev; 1761 1762 if (!vdev) 1763 return QDF_STATUS_E_FAILURE; 1764 1765 pdev = (struct dp_pdev *)vdev->pdev; 1766 1767 mon_pdev = pdev->monitor_pdev; 1768 mon_pdev->nac_rssi_filtering = 1; 1769 /* Store address of NAC (neighbour peer) which will be checked 1770 * against TA of received packets. 1771 */ 1772 1773 if (cmd == CDP_NAC_PARAM_ADD) { 1774 dp_update_filter_neighbour_peers(cdp_soc, vdev->vdev_id, 1775 DP_NAC_PARAM_ADD, 1776 (uint8_t *)client_macaddr); 1777 } else if (cmd == CDP_NAC_PARAM_DEL) { 1778 dp_update_filter_neighbour_peers(cdp_soc, vdev->vdev_id, 1779 DP_NAC_PARAM_DEL, 1780 (uint8_t *)client_macaddr); 1781 } 1782 1783 if (soc->cdp_soc.ol_ops->config_bssid_in_fw_for_nac_rssi) 1784 soc->cdp_soc.ol_ops->config_bssid_in_fw_for_nac_rssi 1785 (soc->ctrl_psoc, pdev->pdev_id, 1786 vdev->vdev_id, cmd, bssid, client_macaddr); 1787 1788 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP); 1789 return QDF_STATUS_SUCCESS; 1790 } 1791 #endif 1792 1793 bool 1794 dp_enable_mon_reap_timer(struct cdp_soc_t *soc_hdl, 1795 enum cdp_mon_reap_source source, 1796 bool enable) 1797 { 1798 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); 1799 1800 if (enable) 1801 return dp_monitor_reap_timer_start(soc, source); 1802 else 1803 return dp_monitor_reap_timer_stop(soc, source); 1804 } 1805 1806 #if defined(DP_CON_MON) 1807 #ifndef REMOVE_PKT_LOG 1808 /** 1809 * dp_pkt_log_init() - API to initialize packet log 1810 * @soc_hdl: Datapath soc handle 1811 * @pdev_id: id of data path pdev handle 1812 * @scn: HIF context 1813 * 1814 * Return: none 1815 */ 1816 void dp_pkt_log_init(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, void *scn) 1817 { 1818 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); 1819 struct dp_pdev *handle = 1820 dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); 1821 struct dp_mon_pdev *mon_pdev; 1822 1823 if (!handle) { 1824 dp_mon_err("pdev handle is NULL"); 1825 return; 1826 } 1827 1828 mon_pdev = handle->monitor_pdev; 1829 1830 if (mon_pdev->pkt_log_init) { 1831 dp_mon_err("%pK: Packet log not initialized", soc); 1832 return; 1833 } 1834 1835 pktlog_sethandle(&mon_pdev->pl_dev, scn); 1836 pktlog_set_pdev_id(mon_pdev->pl_dev, pdev_id); 1837 pktlog_set_callback_regtype(PKTLOG_DEFAULT_CALLBACK_REGISTRATION); 1838 1839 if (pktlogmod_init(scn)) { 1840 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 1841 "%s: pktlogmod_init failed", __func__); 1842 mon_pdev->pkt_log_init = false; 1843 } else { 1844 mon_pdev->pkt_log_init = true; 1845 } 1846 } 1847 1848 /** 1849 * dp_pkt_log_con_service() - connect packet log service 1850 * @soc_hdl: Datapath soc handle 1851 * @pdev_id: id of data path pdev handle 1852 * @scn: device context 1853 * 1854 * Return: none 1855 */ 1856 static void dp_pkt_log_con_service(struct cdp_soc_t *soc_hdl, 1857 uint8_t pdev_id, void *scn) 1858 { 1859 dp_pkt_log_init(soc_hdl, pdev_id, scn); 1860 pktlog_htc_attach(); 1861 } 1862 1863 /** 1864 * dp_pkt_log_exit() - Wrapper API to cleanup pktlog info 1865 * @soc_hdl: Datapath soc handle 1866 * @pdev_id: id of data path pdev handle 1867 * 1868 * Return: none 1869 */ 1870 static void dp_pkt_log_exit(struct cdp_soc_t *soc_hdl, uint8_t pdev_id) 1871 { 1872 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); 1873 struct dp_pdev *pdev = 1874 dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); 1875 1876 if (!pdev) { 1877 dp_err("pdev handle is NULL"); 1878 return; 1879 } 1880 1881 dp_pktlogmod_exit(pdev); 1882 } 1883 1884 #else 1885 static void dp_pkt_log_con_service(struct cdp_soc_t *soc_hdl, 1886 uint8_t pdev_id, void *scn) 1887 { 1888 } 1889 1890 static void dp_pkt_log_exit(struct cdp_soc_t *soc_hdl, uint8_t pdev_id) 1891 { 1892 } 1893 #endif 1894 #endif 1895 1896 void dp_neighbour_peers_detach(struct dp_pdev *pdev) 1897 { 1898 struct dp_neighbour_peer *peer = NULL; 1899 struct dp_neighbour_peer *temp_peer = NULL; 1900 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 1901 1902 TAILQ_FOREACH_SAFE(peer, &mon_pdev->neighbour_peers_list, 1903 neighbour_peer_list_elem, temp_peer) { 1904 /* delete this peer from the list */ 1905 TAILQ_REMOVE(&mon_pdev->neighbour_peers_list, 1906 peer, neighbour_peer_list_elem); 1907 qdf_mem_free(peer); 1908 } 1909 1910 qdf_spinlock_destroy(&mon_pdev->neighbour_peer_mutex); 1911 } 1912 1913 #ifdef QCA_ENHANCED_STATS_SUPPORT 1914 /* 1915 * dp_mon_tx_enable_enhanced_stats() - Enable enhanced Tx stats 1916 * @pdev: Datapath pdev handle 1917 * 1918 * Return: void 1919 */ 1920 static void dp_mon_tx_enable_enhanced_stats(struct dp_pdev *pdev) 1921 { 1922 struct dp_soc *soc = pdev->soc; 1923 struct dp_mon_ops *mon_ops = NULL; 1924 1925 mon_ops = dp_mon_ops_get(soc); 1926 if (mon_ops && mon_ops->mon_tx_enable_enhanced_stats) 1927 mon_ops->mon_tx_enable_enhanced_stats(pdev); 1928 } 1929 1930 /* 1931 * dp_enable_enhanced_stats()- API to enable enhanced statistcs 1932 * @soc_handle: DP_SOC handle 1933 * @pdev_id: id of DP_PDEV handle 1934 * 1935 * Return: QDF_STATUS 1936 */ 1937 static QDF_STATUS 1938 dp_enable_enhanced_stats(struct cdp_soc_t *soc, uint8_t pdev_id) 1939 { 1940 struct dp_pdev *pdev = NULL; 1941 QDF_STATUS status = QDF_STATUS_SUCCESS; 1942 struct dp_mon_pdev *mon_pdev; 1943 1944 pdev = dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, 1945 pdev_id); 1946 1947 if (!pdev) 1948 return QDF_STATUS_E_FAILURE; 1949 1950 mon_pdev = pdev->monitor_pdev; 1951 1952 if (!mon_pdev) 1953 return QDF_STATUS_E_FAILURE; 1954 1955 if (mon_pdev->enhanced_stats_en == 0) 1956 dp_cal_client_timer_start(mon_pdev->cal_client_ctx); 1957 1958 mon_pdev->enhanced_stats_en = 1; 1959 pdev->enhanced_stats_en = true; 1960 1961 dp_mon_filter_setup_enhanced_stats(pdev); 1962 status = dp_mon_filter_update(pdev); 1963 if (status != QDF_STATUS_SUCCESS) { 1964 dp_cdp_err("%pK: Failed to set enhanced mode filters", soc); 1965 dp_mon_filter_reset_enhanced_stats(pdev); 1966 dp_cal_client_timer_stop(mon_pdev->cal_client_ctx); 1967 mon_pdev->enhanced_stats_en = 0; 1968 pdev->enhanced_stats_en = false; 1969 return QDF_STATUS_E_FAILURE; 1970 } 1971 1972 dp_mon_tx_enable_enhanced_stats(pdev); 1973 1974 return QDF_STATUS_SUCCESS; 1975 } 1976 1977 /* 1978 * dp_mon_tx_disable_enhanced_stats() - Disable enhanced Tx stats 1979 * @pdev: Datapath pdev handle 1980 * 1981 * Return: void 1982 */ 1983 static void dp_mon_tx_disable_enhanced_stats(struct dp_pdev *pdev) 1984 { 1985 struct dp_soc *soc = pdev->soc; 1986 struct dp_mon_ops *mon_ops = NULL; 1987 1988 mon_ops = dp_mon_ops_get(soc); 1989 if (mon_ops && mon_ops->mon_tx_disable_enhanced_stats) 1990 mon_ops->mon_tx_disable_enhanced_stats(pdev); 1991 } 1992 1993 /* 1994 * dp_disable_enhanced_stats()- API to disable enhanced statistcs 1995 * 1996 * @param soc - the soc handle 1997 * @param pdev_id - pdev_id of pdev 1998 * @return - QDF_STATUS 1999 */ 2000 static QDF_STATUS 2001 dp_disable_enhanced_stats(struct cdp_soc_t *soc, uint8_t pdev_id) 2002 { 2003 struct dp_pdev *pdev = 2004 dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, 2005 pdev_id); 2006 struct dp_mon_pdev *mon_pdev; 2007 2008 2009 if (!pdev || !pdev->monitor_pdev) 2010 return QDF_STATUS_E_FAILURE; 2011 2012 mon_pdev = pdev->monitor_pdev; 2013 2014 if (mon_pdev->enhanced_stats_en == 1) 2015 dp_cal_client_timer_stop(mon_pdev->cal_client_ctx); 2016 2017 mon_pdev->enhanced_stats_en = 0; 2018 pdev->enhanced_stats_en = false; 2019 2020 dp_mon_tx_disable_enhanced_stats(pdev); 2021 2022 dp_mon_filter_reset_enhanced_stats(pdev); 2023 if (dp_mon_filter_update(pdev) != QDF_STATUS_SUCCESS) { 2024 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 2025 FL("Failed to reset enhanced mode filters")); 2026 } 2027 2028 return QDF_STATUS_SUCCESS; 2029 } 2030 2031 #ifdef WDI_EVENT_ENABLE 2032 QDF_STATUS dp_peer_qos_stats_notify(struct dp_pdev *dp_pdev, 2033 struct cdp_rx_stats_ppdu_user *ppdu_user) 2034 { 2035 struct cdp_interface_peer_qos_stats qos_stats_intf = {0}; 2036 2037 if (qdf_unlikely(ppdu_user->peer_id == HTT_INVALID_PEER)) { 2038 dp_mon_warn("Invalid peer id"); 2039 return QDF_STATUS_E_FAILURE; 2040 } 2041 2042 qdf_mem_copy(qos_stats_intf.peer_mac, ppdu_user->mac_addr, 2043 QDF_MAC_ADDR_SIZE); 2044 qos_stats_intf.frame_control = ppdu_user->frame_control; 2045 qos_stats_intf.frame_control_info_valid = 2046 ppdu_user->frame_control_info_valid; 2047 qos_stats_intf.qos_control = ppdu_user->qos_control; 2048 qos_stats_intf.qos_control_info_valid = 2049 ppdu_user->qos_control_info_valid; 2050 qos_stats_intf.vdev_id = ppdu_user->vdev_id; 2051 dp_wdi_event_handler(WDI_EVENT_PEER_QOS_STATS, dp_pdev->soc, 2052 (void *)&qos_stats_intf, 0, 2053 WDI_NO_VAL, dp_pdev->pdev_id); 2054 2055 return QDF_STATUS_SUCCESS; 2056 } 2057 #else 2058 static inline QDF_STATUS 2059 dp_peer_qos_stats_notify(struct dp_pdev *dp_pdev, 2060 struct cdp_rx_stats_ppdu_user *ppdu_user) 2061 { 2062 return QDF_STATUS_SUCCESS; 2063 } 2064 #endif 2065 #endif /* QCA_ENHANCED_STATS_SUPPORT */ 2066 2067 /** 2068 * dp_enable_peer_based_pktlog() - Set Flag for peer based filtering 2069 * for pktlog 2070 * @soc: cdp_soc handle 2071 * @pdev_id: id of dp pdev handle 2072 * @mac_addr: Peer mac address 2073 * @enb_dsb: Enable or disable peer based filtering 2074 * 2075 * Return: QDF_STATUS 2076 */ 2077 static int 2078 dp_enable_peer_based_pktlog(struct cdp_soc_t *soc, uint8_t pdev_id, 2079 uint8_t *mac_addr, uint8_t enb_dsb) 2080 { 2081 struct dp_peer *peer; 2082 QDF_STATUS status = QDF_STATUS_E_FAILURE; 2083 struct dp_pdev *pdev = 2084 dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, 2085 pdev_id); 2086 struct dp_mon_pdev *mon_pdev; 2087 2088 if (!pdev) 2089 return QDF_STATUS_E_FAILURE; 2090 2091 mon_pdev = pdev->monitor_pdev; 2092 2093 peer = dp_peer_find_hash_find((struct dp_soc *)soc, mac_addr, 2094 0, DP_VDEV_ALL, DP_MOD_ID_CDP); 2095 2096 if (!peer) { 2097 dp_mon_err("Invalid Peer"); 2098 return QDF_STATUS_E_FAILURE; 2099 } 2100 2101 if (!IS_MLO_DP_MLD_PEER(peer) && peer->monitor_peer) { 2102 peer->monitor_peer->peer_based_pktlog_filter = enb_dsb; 2103 mon_pdev->dp_peer_based_pktlog = enb_dsb; 2104 status = QDF_STATUS_SUCCESS; 2105 } 2106 2107 dp_peer_unref_delete(peer, DP_MOD_ID_CDP); 2108 2109 return status; 2110 } 2111 2112 /** 2113 * dp_peer_update_pkt_capture_params: Set Rx & Tx Capture flags for a peer 2114 * @soc: DP_SOC handle 2115 * @pdev_id: id of DP_PDEV handle 2116 * @is_rx_pkt_cap_enable: enable/disable Rx packet capture in monitor mode 2117 * @is_tx_pkt_cap_enable: enable/disable/delete/print 2118 * Tx packet capture in monitor mode 2119 * @peer_mac: MAC address for which the above need to be enabled/disabled 2120 * 2121 * Return: Success if Rx & Tx capture is enabled for peer, false otherwise 2122 */ 2123 #if defined(WLAN_TX_PKT_CAPTURE_ENH) || defined(WLAN_RX_PKT_CAPTURE_ENH) 2124 static QDF_STATUS 2125 dp_peer_update_pkt_capture_params(ol_txrx_soc_handle soc, 2126 uint8_t pdev_id, 2127 bool is_rx_pkt_cap_enable, 2128 uint8_t is_tx_pkt_cap_enable, 2129 uint8_t *peer_mac) 2130 { 2131 struct dp_peer *peer; 2132 QDF_STATUS status = QDF_STATUS_E_FAILURE; 2133 struct dp_pdev *pdev = 2134 dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, 2135 pdev_id); 2136 if (!pdev) 2137 return QDF_STATUS_E_FAILURE; 2138 2139 peer = dp_peer_find_hash_find((struct dp_soc *)soc, 2140 peer_mac, 0, DP_VDEV_ALL, 2141 DP_MOD_ID_CDP); 2142 if (!peer) 2143 return QDF_STATUS_E_FAILURE; 2144 2145 /* we need to set tx pkt capture for non associated peer */ 2146 if (!IS_MLO_DP_MLD_PEER(peer)) { 2147 status = dp_monitor_tx_peer_filter(pdev, peer, 2148 is_tx_pkt_cap_enable, 2149 peer_mac); 2150 2151 status = dp_peer_set_rx_capture_enabled(pdev, peer, 2152 is_rx_pkt_cap_enable, 2153 peer_mac); 2154 } 2155 2156 dp_peer_unref_delete(peer, DP_MOD_ID_CDP); 2157 2158 return status; 2159 } 2160 #endif 2161 2162 #ifdef QCA_MCOPY_SUPPORT 2163 QDF_STATUS dp_mcopy_check_deliver(struct dp_pdev *pdev, 2164 uint16_t peer_id, 2165 uint32_t ppdu_id, 2166 uint8_t first_msdu) 2167 { 2168 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 2169 2170 if (mon_pdev->mcopy_mode) { 2171 if (mon_pdev->mcopy_mode == M_COPY) { 2172 if ((mon_pdev->m_copy_id.tx_ppdu_id == ppdu_id) && 2173 (mon_pdev->m_copy_id.tx_peer_id == peer_id)) { 2174 return QDF_STATUS_E_INVAL; 2175 } 2176 } 2177 2178 if (!first_msdu) 2179 return QDF_STATUS_E_INVAL; 2180 2181 mon_pdev->m_copy_id.tx_ppdu_id = ppdu_id; 2182 mon_pdev->m_copy_id.tx_peer_id = peer_id; 2183 } 2184 2185 return QDF_STATUS_SUCCESS; 2186 } 2187 #endif 2188 2189 #ifdef WDI_EVENT_ENABLE 2190 #ifndef REMOVE_PKT_LOG 2191 static void *dp_get_pldev(struct cdp_soc_t *soc_hdl, uint8_t pdev_id) 2192 { 2193 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); 2194 struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); 2195 2196 if (!pdev || !pdev->monitor_pdev) 2197 return NULL; 2198 2199 return pdev->monitor_pdev->pl_dev; 2200 } 2201 #else 2202 static void *dp_get_pldev(struct cdp_soc_t *soc_hdl, uint8_t pdev_id) 2203 { 2204 return NULL; 2205 } 2206 #endif 2207 #endif 2208 2209 QDF_STATUS dp_rx_populate_cbf_hdr(struct dp_soc *soc, 2210 uint32_t mac_id, 2211 uint32_t event, 2212 qdf_nbuf_t mpdu, 2213 uint32_t msdu_timestamp) 2214 { 2215 uint32_t data_size, hdr_size, ppdu_id, align4byte; 2216 struct dp_pdev *pdev = dp_get_pdev_for_lmac_id(soc, mac_id); 2217 uint32_t *msg_word; 2218 2219 if (!pdev) 2220 return QDF_STATUS_E_INVAL; 2221 2222 ppdu_id = pdev->monitor_pdev->ppdu_info.com_info.ppdu_id; 2223 2224 hdr_size = HTT_T2H_PPDU_STATS_IND_HDR_SIZE 2225 + qdf_offsetof(htt_ppdu_stats_rx_mgmtctrl_payload_tlv, payload); 2226 2227 data_size = qdf_nbuf_len(mpdu); 2228 2229 qdf_nbuf_push_head(mpdu, hdr_size); 2230 2231 msg_word = (uint32_t *)qdf_nbuf_data(mpdu); 2232 /* 2233 * Populate the PPDU Stats Indication header 2234 */ 2235 HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_T2H_MSG_TYPE_PPDU_STATS_IND); 2236 HTT_T2H_PPDU_STATS_MAC_ID_SET(*msg_word, mac_id); 2237 HTT_T2H_PPDU_STATS_PDEV_ID_SET(*msg_word, pdev->pdev_id); 2238 align4byte = ((data_size + 2239 qdf_offsetof(htt_ppdu_stats_rx_mgmtctrl_payload_tlv, payload) 2240 + 3) >> 2) << 2; 2241 HTT_T2H_PPDU_STATS_PAYLOAD_SIZE_SET(*msg_word, align4byte); 2242 msg_word++; 2243 HTT_T2H_PPDU_STATS_PPDU_ID_SET(*msg_word, ppdu_id); 2244 msg_word++; 2245 2246 *msg_word = msdu_timestamp; 2247 msg_word++; 2248 /* Skip reserved field */ 2249 msg_word++; 2250 /* 2251 * Populate MGMT_CTRL Payload TLV first 2252 */ 2253 HTT_STATS_TLV_TAG_SET(*msg_word, 2254 HTT_PPDU_STATS_RX_MGMTCTRL_PAYLOAD_TLV); 2255 2256 align4byte = ((data_size - sizeof(htt_tlv_hdr_t) + 2257 qdf_offsetof(htt_ppdu_stats_rx_mgmtctrl_payload_tlv, payload) 2258 + 3) >> 2) << 2; 2259 HTT_STATS_TLV_LENGTH_SET(*msg_word, align4byte); 2260 msg_word++; 2261 2262 HTT_PPDU_STATS_RX_MGMTCTRL_TLV_FRAME_LENGTH_SET( 2263 *msg_word, data_size); 2264 msg_word++; 2265 2266 dp_wdi_event_handler(event, soc, (void *)mpdu, 2267 HTT_INVALID_PEER, WDI_NO_VAL, pdev->pdev_id); 2268 2269 qdf_nbuf_pull_head(mpdu, hdr_size); 2270 2271 return QDF_STATUS_SUCCESS; 2272 } 2273 2274 #ifdef ATH_SUPPORT_EXT_STAT 2275 #ifdef WLAN_TELEMETRY_STATS_SUPPORT 2276 /* dp_pdev_clear_link_airtime_stats- clear pdev airtime stats for current index 2277 * @peer : Datapath peer 2278 */ 2279 static inline 2280 void dp_pdev_clear_link_airtime_stats(struct dp_pdev *pdev) 2281 { 2282 uint8_t ac; 2283 2284 for (ac = 0; ac < WME_AC_MAX; ac++) 2285 pdev->stats.telemetry_stats.link_airtime[ac] = 0; 2286 } 2287 2288 /* dp_peer_update_telemetry_stats- update peer telemetry stats 2289 * @peer : Datapath peer 2290 */ 2291 static inline 2292 void dp_peer_update_telemetry_stats(struct dp_peer *peer) 2293 { 2294 struct dp_pdev *pdev; 2295 struct dp_vdev *vdev; 2296 struct dp_mon_peer *mon_peer = NULL; 2297 uint8_t ac; 2298 2299 vdev = peer->vdev; 2300 if (!vdev) 2301 return; 2302 2303 pdev = vdev->pdev; 2304 if (!pdev) 2305 return; 2306 2307 mon_peer = peer->monitor_peer; 2308 if (qdf_likely(mon_peer)) { 2309 for (ac = 0; ac < WME_AC_MAX; ac++) { 2310 mon_peer->stats.airtime_consumption[ac].avg_consumption_per_sec = 2311 mon_peer->stats.airtime_consumption[ac].consumption; 2312 /* Store each peer airtime consumption in pdev 2313 * link_airtime to calculate pdev's total airtime 2314 * consumption 2315 */ 2316 DP_STATS_INC( 2317 pdev, 2318 telemetry_stats.link_airtime[ac], 2319 mon_peer->stats.airtime_consumption[ac].consumption); 2320 mon_peer->stats.airtime_consumption[ac].consumption = 0; 2321 } 2322 } 2323 } 2324 #else 2325 static inline 2326 void dp_pdev_clear_link_airtime_stats(struct dp_pdev *pdev) 2327 { } 2328 2329 static inline 2330 void dp_peer_update_telemetry_stats(struct dp_peer *peer) 2331 { } 2332 #endif 2333 2334 /*dp_peer_cal_clients_stats_update - update peer stats on cal client timer 2335 * @soc : Datapath SOC 2336 * @peer : Datapath peer 2337 * @arg : argument to iter function 2338 */ 2339 #ifdef IPA_OFFLOAD 2340 static void 2341 dp_peer_cal_clients_stats_update(struct dp_soc *soc, 2342 struct dp_peer *peer, 2343 void *arg) 2344 { 2345 struct cdp_calibr_stats_intf peer_stats_intf = {0}; 2346 struct dp_peer *tgt_peer = NULL; 2347 struct dp_txrx_peer *txrx_peer = NULL; 2348 2349 dp_peer_update_telemetry_stats(peer); 2350 2351 if (!dp_peer_is_primary_link_peer(peer)) 2352 return; 2353 2354 tgt_peer = dp_get_tgt_peer_from_peer(peer); 2355 if (!tgt_peer || !(tgt_peer->txrx_peer)) 2356 return; 2357 2358 txrx_peer = tgt_peer->txrx_peer; 2359 peer_stats_intf.to_stack = txrx_peer->to_stack; 2360 peer_stats_intf.tx_success = 2361 peer->monitor_peer->stats.tx.tx_ucast_success; 2362 peer_stats_intf.tx_ucast = 2363 peer->monitor_peer->stats.tx.tx_ucast_total; 2364 2365 dp_cal_client_update_peer_stats_wifi3(&peer_stats_intf, 2366 &tgt_peer->stats); 2367 dp_peer_get_rxtid_stats_ipa(peer, dp_peer_update_tid_stats_from_reo); 2368 } 2369 #else 2370 static void 2371 dp_peer_cal_clients_stats_update(struct dp_soc *soc, 2372 struct dp_peer *peer, 2373 void *arg) 2374 { 2375 struct cdp_calibr_stats_intf peer_stats_intf = {0}; 2376 struct dp_peer *tgt_peer = NULL; 2377 struct dp_txrx_peer *txrx_peer = NULL; 2378 2379 dp_peer_update_telemetry_stats(peer); 2380 2381 if (!dp_peer_is_primary_link_peer(peer)) 2382 return; 2383 2384 tgt_peer = dp_get_tgt_peer_from_peer(peer); 2385 if (!tgt_peer || !(tgt_peer->txrx_peer)) 2386 return; 2387 2388 txrx_peer = tgt_peer->txrx_peer; 2389 peer_stats_intf.to_stack = txrx_peer->to_stack; 2390 peer_stats_intf.tx_success = 2391 txrx_peer->stats.per_pkt_stats.tx.tx_success; 2392 peer_stats_intf.tx_ucast = 2393 txrx_peer->stats.per_pkt_stats.tx.ucast; 2394 2395 dp_cal_client_update_peer_stats_wifi3(&peer_stats_intf, 2396 &tgt_peer->stats); 2397 } 2398 #endif 2399 2400 /*dp_iterate_update_peer_list - update peer stats on cal client timer 2401 * @pdev_hdl: pdev handle 2402 */ 2403 static void dp_iterate_update_peer_list(struct cdp_pdev *pdev_hdl) 2404 { 2405 struct dp_pdev *pdev = (struct dp_pdev *)pdev_hdl; 2406 2407 /* Clear current airtime stats as the below API will increment the stats 2408 * for all peers on top of current value 2409 */ 2410 dp_pdev_clear_link_airtime_stats(pdev); 2411 dp_pdev_iterate_peer(pdev, dp_peer_cal_clients_stats_update, NULL, 2412 DP_MOD_ID_CDP); 2413 } 2414 #else 2415 static void dp_iterate_update_peer_list(struct cdp_pdev *pdev_hdl) 2416 { 2417 } 2418 #endif 2419 2420 #ifdef ATH_SUPPORT_NAC 2421 int dp_set_filter_neigh_peers(struct dp_pdev *pdev, 2422 bool val) 2423 { 2424 /* Enable/Disable smart mesh filtering. This flag will be checked 2425 * during rx processing to check if packets are from NAC clients. 2426 */ 2427 pdev->monitor_pdev->filter_neighbour_peers = val; 2428 return 0; 2429 } 2430 #endif /* ATH_SUPPORT_NAC */ 2431 2432 #ifdef WLAN_ATF_ENABLE 2433 void dp_set_atf_stats_enable(struct dp_pdev *pdev, bool value) 2434 { 2435 if (!pdev) { 2436 dp_cdp_err("Invalid pdev"); 2437 return; 2438 } 2439 2440 pdev->monitor_pdev->dp_atf_stats_enable = value; 2441 } 2442 #endif 2443 2444 #ifdef QCA_ENHANCED_STATS_SUPPORT 2445 /* 2446 * dp_process_ppdu_stats_tx_mgmtctrl_payload_tlv: Process 2447 * htt_ppdu_stats_tx_mgmtctrl_payload_tlv 2448 * @pdev: DP PDEV handle 2449 * @tag_buf: buffer containing the htt_ppdu_stats_tx_mgmtctrl_payload_tlv 2450 * @length: tlv_length 2451 * 2452 * return:QDF_STATUS_SUCCESS if nbuf has to be freed in caller 2453 */ 2454 QDF_STATUS 2455 dp_process_ppdu_stats_tx_mgmtctrl_payload_tlv(struct dp_pdev *pdev, 2456 qdf_nbuf_t tag_buf, 2457 uint32_t ppdu_id) 2458 { 2459 uint32_t *nbuf_ptr; 2460 uint8_t trim_size; 2461 size_t head_size; 2462 struct cdp_tx_mgmt_comp_info *ptr_mgmt_comp_info; 2463 uint32_t *msg_word; 2464 uint32_t tsf_hdr; 2465 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 2466 2467 if ((!mon_pdev->tx_sniffer_enable) && (!mon_pdev->mcopy_mode) && 2468 (!mon_pdev->bpr_enable) && (!mon_pdev->tx_capture_enabled)) 2469 return QDF_STATUS_SUCCESS; 2470 2471 /* 2472 * get timestamp from htt_t2h_ppdu_stats_ind_hdr_t 2473 */ 2474 msg_word = (uint32_t *)qdf_nbuf_data(tag_buf); 2475 msg_word = msg_word + 2; 2476 tsf_hdr = *msg_word; 2477 2478 trim_size = ((mon_pdev->mgmtctrl_frm_info.mgmt_buf + 2479 HTT_MGMT_CTRL_TLV_HDR_RESERVERD_LEN) - 2480 qdf_nbuf_data(tag_buf)); 2481 2482 if (!qdf_nbuf_pull_head(tag_buf, trim_size)) 2483 return QDF_STATUS_SUCCESS; 2484 2485 qdf_nbuf_trim_tail(tag_buf, qdf_nbuf_len(tag_buf) - 2486 mon_pdev->mgmtctrl_frm_info.mgmt_buf_len); 2487 2488 if (mon_pdev->tx_capture_enabled) { 2489 head_size = sizeof(struct cdp_tx_mgmt_comp_info); 2490 if (qdf_unlikely(qdf_nbuf_headroom(tag_buf) < head_size)) { 2491 qdf_err("Fail to get headroom h_sz %zu h_avail %d\n", 2492 head_size, qdf_nbuf_headroom(tag_buf)); 2493 qdf_assert_always(0); 2494 return QDF_STATUS_E_NOMEM; 2495 } 2496 ptr_mgmt_comp_info = (struct cdp_tx_mgmt_comp_info *) 2497 qdf_nbuf_push_head(tag_buf, head_size); 2498 qdf_assert_always(ptr_mgmt_comp_info); 2499 ptr_mgmt_comp_info->ppdu_id = ppdu_id; 2500 ptr_mgmt_comp_info->is_sgen_pkt = true; 2501 ptr_mgmt_comp_info->tx_tsf = tsf_hdr; 2502 } else { 2503 head_size = sizeof(ppdu_id); 2504 nbuf_ptr = (uint32_t *)qdf_nbuf_push_head(tag_buf, head_size); 2505 *nbuf_ptr = ppdu_id; 2506 } 2507 if (mon_pdev->bpr_enable) { 2508 dp_wdi_event_handler(WDI_EVENT_TX_BEACON, pdev->soc, 2509 tag_buf, HTT_INVALID_PEER, 2510 WDI_NO_VAL, pdev->pdev_id); 2511 } 2512 2513 dp_deliver_mgmt_frm(pdev, tag_buf); 2514 2515 return QDF_STATUS_E_ALREADY; 2516 } 2517 2518 /* 2519 * dp_htt_get_ppdu_sniffer_ampdu_tlv_bitmap() - Get ppdu stats tlv 2520 * bitmap for sniffer mode 2521 * @bitmap: received bitmap 2522 * 2523 * Return: expected bitmap value, returns zero if doesn't match with 2524 * either 64-bit Tx window or 256-bit window tlv bitmap 2525 */ 2526 int 2527 dp_htt_get_ppdu_sniffer_ampdu_tlv_bitmap(uint32_t bitmap) 2528 { 2529 if (bitmap == (HTT_PPDU_SNIFFER_AMPDU_TLV_BITMAP_64)) 2530 return HTT_PPDU_SNIFFER_AMPDU_TLV_BITMAP_64; 2531 else if (bitmap == (HTT_PPDU_SNIFFER_AMPDU_TLV_BITMAP_256)) 2532 return HTT_PPDU_SNIFFER_AMPDU_TLV_BITMAP_256; 2533 2534 return 0; 2535 } 2536 2537 /* 2538 * dp_peer_copy_delay_stats() - copy ppdu stats to peer delayed stats. 2539 * @peer: Datapath peer handle 2540 * @ppdu: User PPDU Descriptor 2541 * @cur_ppdu_id: PPDU_ID 2542 * 2543 * Return: None 2544 * 2545 * on Tx data frame, we may get delayed ba set 2546 * in htt_ppdu_stats_user_common_tlv. which mean we get Block Ack(BA) after we 2547 * request Block Ack Request(BAR). Successful msdu is received only after Block 2548 * Ack. To populate peer stats we need successful msdu(data frame). 2549 * So we hold the Tx data stats on delayed_ba for stats update. 2550 */ 2551 static void 2552 dp_peer_copy_delay_stats(struct dp_peer *peer, 2553 struct cdp_tx_completion_ppdu_user *ppdu, 2554 uint32_t cur_ppdu_id) 2555 { 2556 struct dp_pdev *pdev; 2557 struct dp_vdev *vdev; 2558 struct dp_mon_peer *mon_peer = peer->monitor_peer; 2559 2560 if (mon_peer->last_delayed_ba) { 2561 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 2562 "BA not yet recv for prev delayed ppdu[%d] - cur ppdu[%d]", 2563 mon_peer->last_delayed_ba_ppduid, cur_ppdu_id); 2564 vdev = peer->vdev; 2565 if (vdev) { 2566 pdev = vdev->pdev; 2567 pdev->stats.cdp_delayed_ba_not_recev++; 2568 } 2569 } 2570 2571 mon_peer->delayed_ba_ppdu_stats.ltf_size = ppdu->ltf_size; 2572 mon_peer->delayed_ba_ppdu_stats.stbc = ppdu->stbc; 2573 mon_peer->delayed_ba_ppdu_stats.he_re = ppdu->he_re; 2574 mon_peer->delayed_ba_ppdu_stats.txbf = ppdu->txbf; 2575 mon_peer->delayed_ba_ppdu_stats.bw = ppdu->bw; 2576 mon_peer->delayed_ba_ppdu_stats.nss = ppdu->nss; 2577 mon_peer->delayed_ba_ppdu_stats.gi = ppdu->gi; 2578 mon_peer->delayed_ba_ppdu_stats.dcm = ppdu->dcm; 2579 mon_peer->delayed_ba_ppdu_stats.ldpc = ppdu->ldpc; 2580 mon_peer->delayed_ba_ppdu_stats.dcm = ppdu->dcm; 2581 mon_peer->delayed_ba_ppdu_stats.mpdu_tried_ucast = 2582 ppdu->mpdu_tried_ucast; 2583 mon_peer->delayed_ba_ppdu_stats.mpdu_tried_mcast = 2584 ppdu->mpdu_tried_mcast; 2585 mon_peer->delayed_ba_ppdu_stats.frame_ctrl = ppdu->frame_ctrl; 2586 mon_peer->delayed_ba_ppdu_stats.qos_ctrl = ppdu->qos_ctrl; 2587 mon_peer->delayed_ba_ppdu_stats.dcm = ppdu->dcm; 2588 2589 mon_peer->delayed_ba_ppdu_stats.ru_start = ppdu->ru_start; 2590 mon_peer->delayed_ba_ppdu_stats.ru_tones = ppdu->ru_tones; 2591 mon_peer->delayed_ba_ppdu_stats.is_mcast = ppdu->is_mcast; 2592 2593 mon_peer->delayed_ba_ppdu_stats.user_pos = ppdu->user_pos; 2594 mon_peer->delayed_ba_ppdu_stats.mu_group_id = ppdu->mu_group_id; 2595 2596 mon_peer->last_delayed_ba = true; 2597 2598 ppdu->debug_copied = true; 2599 } 2600 2601 /* 2602 * dp_peer_copy_stats_to_bar() - copy delayed stats to ppdu stats. 2603 * @peer: Datapath peer handle 2604 * @ppdu: PPDU Descriptor 2605 * 2606 * Return: None 2607 * 2608 * For Tx BAR, PPDU stats TLV include Block Ack info. PPDU info 2609 * from Tx BAR frame not required to populate peer stats. 2610 * But we need successful MPDU and MSDU to update previous 2611 * transmitted Tx data frame. Overwrite ppdu stats with the previous 2612 * stored ppdu stats. 2613 */ 2614 static void 2615 dp_peer_copy_stats_to_bar(struct dp_peer *peer, 2616 struct cdp_tx_completion_ppdu_user *ppdu) 2617 { 2618 struct dp_mon_peer *mon_peer = peer->monitor_peer; 2619 2620 ppdu->ltf_size = mon_peer->delayed_ba_ppdu_stats.ltf_size; 2621 ppdu->stbc = mon_peer->delayed_ba_ppdu_stats.stbc; 2622 ppdu->he_re = mon_peer->delayed_ba_ppdu_stats.he_re; 2623 ppdu->txbf = mon_peer->delayed_ba_ppdu_stats.txbf; 2624 ppdu->bw = mon_peer->delayed_ba_ppdu_stats.bw; 2625 ppdu->nss = mon_peer->delayed_ba_ppdu_stats.nss; 2626 ppdu->gi = mon_peer->delayed_ba_ppdu_stats.gi; 2627 ppdu->dcm = mon_peer->delayed_ba_ppdu_stats.dcm; 2628 ppdu->ldpc = mon_peer->delayed_ba_ppdu_stats.ldpc; 2629 ppdu->dcm = mon_peer->delayed_ba_ppdu_stats.dcm; 2630 ppdu->mpdu_tried_ucast = 2631 mon_peer->delayed_ba_ppdu_stats.mpdu_tried_ucast; 2632 ppdu->mpdu_tried_mcast = 2633 mon_peer->delayed_ba_ppdu_stats.mpdu_tried_mcast; 2634 ppdu->frame_ctrl = mon_peer->delayed_ba_ppdu_stats.frame_ctrl; 2635 ppdu->qos_ctrl = mon_peer->delayed_ba_ppdu_stats.qos_ctrl; 2636 ppdu->dcm = mon_peer->delayed_ba_ppdu_stats.dcm; 2637 2638 ppdu->ru_start = mon_peer->delayed_ba_ppdu_stats.ru_start; 2639 ppdu->ru_tones = mon_peer->delayed_ba_ppdu_stats.ru_tones; 2640 ppdu->is_mcast = mon_peer->delayed_ba_ppdu_stats.is_mcast; 2641 2642 ppdu->user_pos = mon_peer->delayed_ba_ppdu_stats.user_pos; 2643 ppdu->mu_group_id = mon_peer->delayed_ba_ppdu_stats.mu_group_id; 2644 2645 mon_peer->last_delayed_ba = false; 2646 2647 ppdu->debug_copied = true; 2648 } 2649 2650 /* 2651 * dp_tx_rate_stats_update() - Update rate per-peer statistics 2652 * @peer: Datapath peer handle 2653 * @ppdu: PPDU Descriptor 2654 * 2655 * Return: None 2656 */ 2657 static void 2658 dp_tx_rate_stats_update(struct dp_peer *peer, 2659 struct cdp_tx_completion_ppdu_user *ppdu) 2660 { 2661 uint32_t ratekbps = 0; 2662 uint64_t ppdu_tx_rate = 0; 2663 uint32_t rix; 2664 uint16_t ratecode = 0; 2665 struct dp_mon_peer *mon_peer = NULL; 2666 2667 if (!peer || !ppdu) 2668 return; 2669 2670 if (ppdu->completion_status != HTT_PPDU_STATS_USER_STATUS_OK) 2671 return; 2672 2673 mon_peer = peer->monitor_peer; 2674 if (!mon_peer) 2675 return; 2676 2677 ratekbps = dp_getrateindex(ppdu->gi, 2678 ppdu->mcs, 2679 ppdu->nss, 2680 ppdu->preamble, 2681 ppdu->bw, 2682 ppdu->punc_mode, 2683 &rix, 2684 &ratecode); 2685 2686 if (!ratekbps) 2687 return; 2688 2689 /* Calculate goodput in non-training period 2690 * In training period, don't do anything as 2691 * pending pkt is send as goodput. 2692 */ 2693 if ((!peer->bss_peer) && (!ppdu->sa_is_training)) { 2694 ppdu->sa_goodput = ((ratekbps / CDP_NUM_KB_IN_MB) * 2695 (CDP_PERCENT_MACRO - ppdu->current_rate_per)); 2696 } 2697 ppdu->rix = rix; 2698 ppdu->tx_ratekbps = ratekbps; 2699 ppdu->tx_ratecode = ratecode; 2700 DP_STATS_UPD(mon_peer, tx.tx_rate, ratekbps); 2701 mon_peer->stats.tx.avg_tx_rate = 2702 dp_ath_rate_lpf(mon_peer->stats.tx.avg_tx_rate, ratekbps); 2703 ppdu_tx_rate = dp_ath_rate_out(mon_peer->stats.tx.avg_tx_rate); 2704 DP_STATS_UPD(mon_peer, tx.rnd_avg_tx_rate, ppdu_tx_rate); 2705 2706 mon_peer->stats.tx.bw_info = ppdu->bw; 2707 mon_peer->stats.tx.gi_info = ppdu->gi; 2708 mon_peer->stats.tx.nss_info = ppdu->nss; 2709 mon_peer->stats.tx.mcs_info = ppdu->mcs; 2710 mon_peer->stats.tx.preamble_info = ppdu->preamble; 2711 if (peer->vdev) { 2712 /* 2713 * In STA mode: 2714 * We get ucast stats as BSS peer stats. 2715 * 2716 * In AP mode: 2717 * We get mcast stats as BSS peer stats. 2718 * We get ucast stats as assoc peer stats. 2719 */ 2720 if (peer->vdev->opmode == wlan_op_mode_ap && peer->bss_peer) { 2721 peer->vdev->stats.tx.mcast_last_tx_rate = ratekbps; 2722 peer->vdev->stats.tx.mcast_last_tx_rate_mcs = ppdu->mcs; 2723 } else { 2724 peer->vdev->stats.tx.last_tx_rate = ratekbps; 2725 peer->vdev->stats.tx.last_tx_rate_mcs = ppdu->mcs; 2726 } 2727 } 2728 } 2729 2730 #if defined(FEATURE_PERPKT_INFO) && defined(WDI_EVENT_ENABLE) 2731 void dp_send_stats_event(struct dp_pdev *pdev, struct dp_peer *peer, 2732 uint16_t peer_id) 2733 { 2734 struct cdp_interface_peer_stats peer_stats_intf = {0}; 2735 struct dp_mon_peer *mon_peer = peer->monitor_peer; 2736 struct dp_txrx_peer *txrx_peer = NULL; 2737 2738 if (qdf_unlikely(!mon_peer)) 2739 return; 2740 2741 mon_peer->stats.rx.rx_snr_measured_time = qdf_system_ticks(); 2742 peer_stats_intf.rx_avg_snr = mon_peer->stats.rx.avg_snr; 2743 2744 txrx_peer = dp_get_txrx_peer(peer); 2745 if (qdf_likely(txrx_peer)) { 2746 peer_stats_intf.rx_byte_count = txrx_peer->to_stack.bytes; 2747 peer_stats_intf.tx_byte_count = 2748 txrx_peer->stats.per_pkt_stats.tx.tx_success.bytes; 2749 } 2750 2751 dp_wdi_event_handler(WDI_EVENT_UPDATE_DP_STATS, pdev->soc, 2752 &peer_stats_intf, peer_id, 2753 UPDATE_PEER_STATS, pdev->pdev_id); 2754 } 2755 #endif 2756 2757 #ifdef WLAN_FEATURE_11BE 2758 /* 2759 * dp_get_ru_index_frm_ru_tones() - get ru index 2760 * @ru_tones: ru tones 2761 * 2762 * Return: ru index 2763 */ 2764 static inline enum cdp_ru_index dp_get_ru_index_frm_ru_tones(uint16_t ru_tones) 2765 { 2766 enum cdp_ru_index ru_index; 2767 2768 switch (ru_tones) { 2769 case RU_26: 2770 ru_index = RU_26_INDEX; 2771 break; 2772 case RU_52: 2773 ru_index = RU_52_INDEX; 2774 break; 2775 case RU_52_26: 2776 ru_index = RU_52_26_INDEX; 2777 break; 2778 case RU_106: 2779 ru_index = RU_106_INDEX; 2780 break; 2781 case RU_106_26: 2782 ru_index = RU_106_26_INDEX; 2783 break; 2784 case RU_242: 2785 ru_index = RU_242_INDEX; 2786 break; 2787 case RU_484: 2788 ru_index = RU_484_INDEX; 2789 break; 2790 case RU_484_242: 2791 ru_index = RU_484_242_INDEX; 2792 break; 2793 case RU_996: 2794 ru_index = RU_996_INDEX; 2795 break; 2796 case RU_996_484: 2797 ru_index = RU_996_484_INDEX; 2798 break; 2799 case RU_996_484_242: 2800 ru_index = RU_996_484_242_INDEX; 2801 break; 2802 case RU_2X996: 2803 ru_index = RU_2X996_INDEX; 2804 break; 2805 case RU_2X996_484: 2806 ru_index = RU_2X996_484_INDEX; 2807 break; 2808 case RU_3X996: 2809 ru_index = RU_3X996_INDEX; 2810 break; 2811 case RU_3X996_484: 2812 ru_index = RU_2X996_484_INDEX; 2813 break; 2814 case RU_4X996: 2815 ru_index = RU_4X996_INDEX; 2816 break; 2817 default: 2818 ru_index = RU_INDEX_MAX; 2819 break; 2820 } 2821 2822 return ru_index; 2823 } 2824 2825 /* 2826 * dp_mon_get_ru_width_from_ru_size() - get ru_width from ru_size enum 2827 * @ru_size: HTT ru_size enum 2828 * 2829 * Return: ru_width of uint32_t type 2830 */ 2831 static uint32_t dp_mon_get_ru_width_from_ru_size(uint16_t ru_size) 2832 { 2833 uint32_t width = 0; 2834 2835 switch (ru_size) { 2836 case HTT_PPDU_STATS_RU_26: 2837 width = RU_26; 2838 break; 2839 case HTT_PPDU_STATS_RU_52: 2840 width = RU_52; 2841 break; 2842 case HTT_PPDU_STATS_RU_52_26: 2843 width = RU_52_26; 2844 break; 2845 case HTT_PPDU_STATS_RU_106: 2846 width = RU_106; 2847 break; 2848 case HTT_PPDU_STATS_RU_106_26: 2849 width = RU_106_26; 2850 break; 2851 case HTT_PPDU_STATS_RU_242: 2852 width = RU_242; 2853 break; 2854 case HTT_PPDU_STATS_RU_484: 2855 width = RU_484; 2856 break; 2857 case HTT_PPDU_STATS_RU_484_242: 2858 width = RU_484_242; 2859 break; 2860 case HTT_PPDU_STATS_RU_996: 2861 width = RU_996; 2862 break; 2863 case HTT_PPDU_STATS_RU_996_484: 2864 width = RU_996_484; 2865 break; 2866 case HTT_PPDU_STATS_RU_996_484_242: 2867 width = RU_996_484_242; 2868 break; 2869 case HTT_PPDU_STATS_RU_996x2: 2870 width = RU_2X996; 2871 break; 2872 case HTT_PPDU_STATS_RU_996x2_484: 2873 width = RU_2X996_484; 2874 break; 2875 case HTT_PPDU_STATS_RU_996x3: 2876 width = RU_3X996; 2877 break; 2878 case HTT_PPDU_STATS_RU_996x3_484: 2879 width = RU_3X996_484; 2880 break; 2881 case HTT_PPDU_STATS_RU_996x4: 2882 width = RU_4X996; 2883 break; 2884 default: 2885 dp_mon_debug("Unsupported ru_size: %d rcvd", ru_size); 2886 } 2887 2888 return width; 2889 } 2890 #else 2891 static inline enum cdp_ru_index dp_get_ru_index_frm_ru_tones(uint16_t ru_tones) 2892 { 2893 enum cdp_ru_index ru_index; 2894 2895 switch (ru_tones) { 2896 case RU_26: 2897 ru_index = RU_26_INDEX; 2898 break; 2899 case RU_52: 2900 ru_index = RU_52_INDEX; 2901 break; 2902 case RU_106: 2903 ru_index = RU_106_INDEX; 2904 break; 2905 case RU_242: 2906 ru_index = RU_242_INDEX; 2907 break; 2908 case RU_484: 2909 ru_index = RU_484_INDEX; 2910 break; 2911 case RU_996: 2912 ru_index = RU_996_INDEX; 2913 break; 2914 default: 2915 ru_index = RU_INDEX_MAX; 2916 break; 2917 } 2918 2919 return ru_index; 2920 } 2921 2922 static uint32_t dp_mon_get_ru_width_from_ru_size(uint16_t ru_size) 2923 { 2924 uint32_t width = 0; 2925 2926 switch (ru_size) { 2927 case HTT_PPDU_STATS_RU_26: 2928 width = RU_26; 2929 break; 2930 case HTT_PPDU_STATS_RU_52: 2931 width = RU_52; 2932 break; 2933 case HTT_PPDU_STATS_RU_106: 2934 width = RU_106; 2935 break; 2936 case HTT_PPDU_STATS_RU_242: 2937 width = RU_242; 2938 break; 2939 case HTT_PPDU_STATS_RU_484: 2940 width = RU_484; 2941 break; 2942 case HTT_PPDU_STATS_RU_996: 2943 width = RU_996; 2944 break; 2945 default: 2946 dp_mon_debug("Unsupported ru_size: %d rcvd", ru_size); 2947 } 2948 2949 return width; 2950 } 2951 #endif 2952 2953 #ifdef WLAN_TELEMETRY_STATS_SUPPORT 2954 /* 2955 * dp_pdev_telemetry_stats_update() - Update pdev telemetry stats 2956 * @pdev: Datapath pdev handle 2957 * @ppdu: PPDU Descriptor 2958 * 2959 * Return: None 2960 */ 2961 static void 2962 dp_pdev_telemetry_stats_update( 2963 struct dp_pdev *pdev, 2964 struct cdp_tx_completion_ppdu_user *ppdu) 2965 { 2966 uint16_t mpdu_tried; 2967 uint16_t mpdu_failed; 2968 uint16_t num_mpdu; 2969 uint8_t ac = 0; 2970 2971 num_mpdu = ppdu->mpdu_success; 2972 mpdu_tried = ppdu->mpdu_tried_ucast + ppdu->mpdu_tried_mcast; 2973 mpdu_failed = mpdu_tried - num_mpdu; 2974 2975 ac = TID_TO_WME_AC(ppdu->tid); 2976 2977 DP_STATS_INC(pdev, telemetry_stats.tx_mpdu_failed[ac], 2978 mpdu_failed); 2979 2980 DP_STATS_INC(pdev, telemetry_stats.tx_mpdu_total[ac], 2981 mpdu_tried); 2982 } 2983 #else 2984 static inline void 2985 dp_pdev_telemetry_stats_update( 2986 struct dp_pdev *pdev, 2987 struct cdp_tx_completion_ppdu_user *ppdu) 2988 { } 2989 #endif 2990 2991 /* 2992 * dp_tx_stats_update() - Update per-peer statistics 2993 * @pdev: Datapath pdev handle 2994 * @peer: Datapath peer handle 2995 * @ppdu: PPDU Descriptor 2996 * @ack_rssi: RSSI of last ack received 2997 * 2998 * Return: None 2999 */ 3000 static void 3001 dp_tx_stats_update(struct dp_pdev *pdev, struct dp_peer *peer, 3002 struct cdp_tx_completion_ppdu_user *ppdu, 3003 uint32_t ack_rssi) 3004 { 3005 uint8_t preamble, mcs; 3006 uint16_t num_msdu; 3007 uint16_t num_mpdu; 3008 uint16_t mpdu_tried; 3009 uint16_t mpdu_failed; 3010 struct dp_mon_ops *mon_ops; 3011 enum cdp_ru_index ru_index; 3012 struct dp_mon_peer *mon_peer = NULL; 3013 uint32_t ratekbps = 0; 3014 uint64_t tx_byte_count; 3015 3016 preamble = ppdu->preamble; 3017 mcs = ppdu->mcs; 3018 num_msdu = ppdu->num_msdu; 3019 num_mpdu = ppdu->mpdu_success; 3020 mpdu_tried = ppdu->mpdu_tried_ucast + ppdu->mpdu_tried_mcast; 3021 mpdu_failed = mpdu_tried - num_mpdu; 3022 tx_byte_count = ppdu->success_bytes; 3023 3024 /* If the peer statistics are already processed as part of 3025 * per-MSDU completion handler, do not process these again in per-PPDU 3026 * indications 3027 */ 3028 if (pdev->soc->process_tx_status) 3029 return; 3030 3031 mon_peer = peer->monitor_peer; 3032 if (!mon_peer) 3033 return; 3034 3035 if (!ppdu->is_mcast) { 3036 DP_STATS_INC(mon_peer, tx.tx_ucast_total.num, num_msdu); 3037 DP_STATS_INC(mon_peer, tx.tx_ucast_total.bytes, 3038 tx_byte_count); 3039 } 3040 3041 if (ppdu->completion_status != HTT_PPDU_STATS_USER_STATUS_OK) { 3042 /* 3043 * All failed mpdu will be retried, so incrementing 3044 * retries mpdu based on mpdu failed. Even for 3045 * ack failure i.e for long retries we get 3046 * mpdu failed equal mpdu tried. 3047 */ 3048 DP_STATS_INC(mon_peer, tx.retries, mpdu_failed); 3049 dp_pdev_telemetry_stats_update(pdev, ppdu); 3050 return; 3051 } 3052 3053 if (ppdu->is_ppdu_cookie_valid) 3054 DP_STATS_INC(mon_peer, tx.num_ppdu_cookie_valid, 1); 3055 3056 if (ppdu->mu_group_id <= MAX_MU_GROUP_ID && 3057 ppdu->ppdu_type != HTT_PPDU_STATS_PPDU_TYPE_SU) { 3058 if (qdf_unlikely(ppdu->mu_group_id && 3059 !(ppdu->mu_group_id & (MAX_MU_GROUP_ID - 1)))) 3060 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 3061 "mu_group_id out of bound!!\n"); 3062 else 3063 DP_STATS_UPD(mon_peer, tx.mu_group_id[ppdu->mu_group_id], 3064 (ppdu->user_pos + 1)); 3065 } 3066 3067 if (ppdu->ppdu_type == HTT_PPDU_STATS_PPDU_TYPE_MU_OFDMA || 3068 ppdu->ppdu_type == HTT_PPDU_STATS_PPDU_TYPE_MU_MIMO_OFDMA) { 3069 DP_STATS_UPD(mon_peer, tx.ru_tones, ppdu->ru_tones); 3070 DP_STATS_UPD(mon_peer, tx.ru_start, ppdu->ru_start); 3071 ru_index = dp_get_ru_index_frm_ru_tones(ppdu->ru_tones); 3072 if (ru_index != RU_INDEX_MAX) { 3073 DP_STATS_INC(mon_peer, tx.ru_loc[ru_index].num_msdu, 3074 num_msdu); 3075 DP_STATS_INC(mon_peer, tx.ru_loc[ru_index].num_mpdu, 3076 num_mpdu); 3077 DP_STATS_INC(mon_peer, tx.ru_loc[ru_index].mpdu_tried, 3078 mpdu_tried); 3079 } 3080 } 3081 3082 /* 3083 * All failed mpdu will be retried, so incrementing 3084 * retries mpdu based on mpdu failed. Even for 3085 * ack failure i.e for long retries we get 3086 * mpdu failed equal mpdu tried. 3087 */ 3088 DP_STATS_INC(mon_peer, tx.retries, mpdu_failed); 3089 3090 DP_STATS_INC(mon_peer, tx.transmit_type[ppdu->ppdu_type].num_msdu, 3091 num_msdu); 3092 DP_STATS_INC(mon_peer, tx.transmit_type[ppdu->ppdu_type].num_mpdu, 3093 num_mpdu); 3094 DP_STATS_INC(mon_peer, tx.transmit_type[ppdu->ppdu_type].mpdu_tried, 3095 mpdu_tried); 3096 3097 DP_STATS_INC(mon_peer, tx.sgi_count[ppdu->gi], num_msdu); 3098 DP_STATS_INC(mon_peer, tx.bw[ppdu->bw], num_msdu); 3099 DP_STATS_INC(mon_peer, tx.nss[ppdu->nss], num_msdu); 3100 if (ppdu->tid < CDP_DATA_TID_MAX) { 3101 DP_STATS_INC(mon_peer, tx.wme_ac_type[TID_TO_WME_AC(ppdu->tid)], 3102 num_msdu); 3103 DP_STATS_INC(mon_peer, 3104 tx.wme_ac_type_bytes[TID_TO_WME_AC(ppdu->tid)], 3105 tx_byte_count); 3106 } 3107 3108 DP_STATS_INCC(mon_peer, tx.stbc, num_msdu, ppdu->stbc); 3109 DP_STATS_INCC(mon_peer, tx.ldpc, num_msdu, ppdu->ldpc); 3110 if (!(ppdu->is_mcast) && ppdu->ack_rssi_valid) 3111 DP_STATS_UPD(mon_peer, tx.last_ack_rssi, ack_rssi); 3112 3113 if (!ppdu->is_mcast) { 3114 DP_STATS_INC(mon_peer, tx.tx_ucast_success.num, num_msdu); 3115 DP_STATS_INC(mon_peer, tx.tx_ucast_success.bytes, 3116 tx_byte_count); 3117 } 3118 3119 DP_STATS_INCC(mon_peer, 3120 tx.pkt_type[preamble].mcs_count[MAX_MCS - 1], num_msdu, 3121 ((mcs >= MAX_MCS_11A) && (preamble == DOT11_A))); 3122 DP_STATS_INCC(mon_peer, 3123 tx.pkt_type[preamble].mcs_count[mcs], num_msdu, 3124 ((mcs < MAX_MCS_11A) && (preamble == DOT11_A))); 3125 DP_STATS_INCC(mon_peer, 3126 tx.pkt_type[preamble].mcs_count[MAX_MCS - 1], num_msdu, 3127 ((mcs >= MAX_MCS_11B) && (preamble == DOT11_B))); 3128 DP_STATS_INCC(mon_peer, 3129 tx.pkt_type[preamble].mcs_count[mcs], num_msdu, 3130 ((mcs < (MAX_MCS_11B)) && (preamble == DOT11_B))); 3131 DP_STATS_INCC(mon_peer, 3132 tx.pkt_type[preamble].mcs_count[MAX_MCS - 1], num_msdu, 3133 ((mcs >= MAX_MCS_11A) && (preamble == DOT11_N))); 3134 DP_STATS_INCC(mon_peer, 3135 tx.pkt_type[preamble].mcs_count[mcs], num_msdu, 3136 ((mcs < MAX_MCS_11A) && (preamble == DOT11_N))); 3137 DP_STATS_INCC(mon_peer, 3138 tx.pkt_type[preamble].mcs_count[MAX_MCS - 1], num_msdu, 3139 ((mcs >= MAX_MCS_11AC) && (preamble == DOT11_AC))); 3140 DP_STATS_INCC(mon_peer, 3141 tx.pkt_type[preamble].mcs_count[mcs], num_msdu, 3142 ((mcs < MAX_MCS_11AC) && (preamble == DOT11_AC))); 3143 DP_STATS_INCC(mon_peer, 3144 tx.pkt_type[preamble].mcs_count[MAX_MCS - 1], num_msdu, 3145 ((mcs >= MAX_MCS_11AX) && (preamble == DOT11_AX))); 3146 DP_STATS_INCC(mon_peer, 3147 tx.pkt_type[preamble].mcs_count[mcs], num_msdu, 3148 ((mcs < MAX_MCS_11AX) && (preamble == DOT11_AX))); 3149 DP_STATS_INCC(mon_peer, tx.ampdu_cnt, num_mpdu, ppdu->is_ampdu); 3150 DP_STATS_INCC(mon_peer, tx.non_ampdu_cnt, num_mpdu, !(ppdu->is_ampdu)); 3151 DP_STATS_INCC(mon_peer, tx.pream_punct_cnt, 1, ppdu->pream_punct); 3152 DP_STATS_INC(mon_peer, tx.tx_ppdus, 1); 3153 DP_STATS_INC(mon_peer, tx.tx_mpdus_success, num_mpdu); 3154 DP_STATS_INC(mon_peer, tx.tx_mpdus_tried, mpdu_tried); 3155 3156 mon_ops = dp_mon_ops_get(pdev->soc); 3157 if (mon_ops && mon_ops->mon_tx_stats_update) 3158 mon_ops->mon_tx_stats_update(mon_peer, ppdu); 3159 3160 dp_tx_rate_stats_update(peer, ppdu); 3161 dp_pdev_telemetry_stats_update(pdev, ppdu); 3162 3163 dp_peer_stats_notify(pdev, peer); 3164 3165 ratekbps = mon_peer->stats.tx.tx_rate; 3166 DP_STATS_UPD(mon_peer, tx.last_tx_rate, ratekbps); 3167 3168 dp_send_stats_event(pdev, peer, ppdu->peer_id); 3169 } 3170 3171 /* 3172 * dp_get_ppdu_info_user_index: Find and allocate a per-user descriptor for a PPDU, 3173 * if a new peer id arrives in a PPDU 3174 * pdev: DP pdev handle 3175 * @peer_id : peer unique identifier 3176 * @ppdu_info: per ppdu tlv structure 3177 * 3178 * return:user index to be populated 3179 */ 3180 static uint8_t dp_get_ppdu_info_user_index(struct dp_pdev *pdev, 3181 uint16_t peer_id, 3182 struct ppdu_info *ppdu_info) 3183 { 3184 uint8_t user_index = 0; 3185 struct cdp_tx_completion_ppdu *ppdu_desc; 3186 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 3187 3188 ppdu_desc = 3189 (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 3190 3191 while ((user_index + 1) <= ppdu_info->last_user) { 3192 ppdu_user_desc = &ppdu_desc->user[user_index]; 3193 if (ppdu_user_desc->peer_id != peer_id) { 3194 user_index++; 3195 continue; 3196 } else { 3197 /* Max users possible is 8 so user array index should 3198 * not exceed 7 3199 */ 3200 qdf_assert_always(user_index <= (ppdu_desc->max_users - 1)); 3201 return user_index; 3202 } 3203 } 3204 3205 ppdu_info->last_user++; 3206 /* Max users possible is 8 so last user should not exceed 8 */ 3207 qdf_assert_always(ppdu_info->last_user <= ppdu_desc->max_users); 3208 return ppdu_info->last_user - 1; 3209 } 3210 3211 /* 3212 * dp_process_ppdu_stats_common_tlv: Process htt_ppdu_stats_common_tlv 3213 * pdev: DP pdev handle 3214 * @tag_buf: buffer containing the tlv htt_ppdu_stats_common_tlv 3215 * @ppdu_info: per ppdu tlv structure 3216 * 3217 * return:void 3218 */ 3219 static void 3220 dp_process_ppdu_stats_common_tlv(struct dp_pdev *pdev, 3221 uint32_t *tag_buf, 3222 struct ppdu_info *ppdu_info) 3223 { 3224 uint16_t frame_type; 3225 uint16_t frame_ctrl; 3226 uint16_t freq; 3227 struct dp_soc *soc = NULL; 3228 struct cdp_tx_completion_ppdu *ppdu_desc = NULL; 3229 uint64_t ppdu_start_timestamp; 3230 uint32_t *start_tag_buf; 3231 3232 start_tag_buf = tag_buf; 3233 ppdu_desc = 3234 (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 3235 3236 ppdu_desc->ppdu_id = ppdu_info->ppdu_id; 3237 3238 tag_buf = start_tag_buf + HTT_GET_STATS_CMN_INDEX(RING_ID_SCH_CMD_ID); 3239 ppdu_info->sched_cmdid = 3240 HTT_PPDU_STATS_COMMON_TLV_SCH_CMDID_GET(*tag_buf); 3241 ppdu_desc->num_users = 3242 HTT_PPDU_STATS_COMMON_TLV_NUM_USERS_GET(*tag_buf); 3243 3244 qdf_assert_always(ppdu_desc->num_users <= ppdu_desc->max_users); 3245 3246 tag_buf = start_tag_buf + HTT_GET_STATS_CMN_INDEX(QTYPE_FRM_TYPE); 3247 frame_type = HTT_PPDU_STATS_COMMON_TLV_FRM_TYPE_GET(*tag_buf); 3248 ppdu_desc->htt_frame_type = frame_type; 3249 3250 frame_ctrl = ppdu_desc->frame_ctrl; 3251 3252 ppdu_desc->bar_ppdu_id = ppdu_info->ppdu_id; 3253 3254 switch (frame_type) { 3255 case HTT_STATS_FTYPE_TIDQ_DATA_SU: 3256 case HTT_STATS_FTYPE_TIDQ_DATA_MU: 3257 case HTT_STATS_FTYPE_SGEN_QOS_NULL: 3258 /* 3259 * for management packet, frame type come as DATA_SU 3260 * need to check frame_ctrl before setting frame_type 3261 */ 3262 if (HTT_GET_FRAME_CTRL_TYPE(frame_ctrl) <= FRAME_CTRL_TYPE_CTRL) 3263 ppdu_desc->frame_type = CDP_PPDU_FTYPE_CTRL; 3264 else 3265 ppdu_desc->frame_type = CDP_PPDU_FTYPE_DATA; 3266 break; 3267 case HTT_STATS_FTYPE_SGEN_MU_BAR: 3268 case HTT_STATS_FTYPE_SGEN_BAR: 3269 case HTT_STATS_FTYPE_SGEN_BE_MU_BAR: 3270 ppdu_desc->frame_type = CDP_PPDU_FTYPE_BAR; 3271 break; 3272 default: 3273 ppdu_desc->frame_type = CDP_PPDU_FTYPE_CTRL; 3274 break; 3275 } 3276 3277 tag_buf = start_tag_buf + HTT_GET_STATS_CMN_INDEX(FES_DUR_US); 3278 ppdu_desc->tx_duration = *tag_buf; 3279 3280 tag_buf = start_tag_buf + HTT_GET_STATS_CMN_INDEX(START_TSTMP_L32_US); 3281 ppdu_desc->ppdu_start_timestamp = *tag_buf; 3282 3283 tag_buf = start_tag_buf + HTT_GET_STATS_CMN_INDEX(CHAN_MHZ_PHY_MODE); 3284 freq = HTT_PPDU_STATS_COMMON_TLV_CHAN_MHZ_GET(*tag_buf); 3285 if (freq != ppdu_desc->channel) { 3286 soc = pdev->soc; 3287 ppdu_desc->channel = freq; 3288 pdev->operating_channel.freq = freq; 3289 if (soc && soc->cdp_soc.ol_ops->freq_to_channel) 3290 pdev->operating_channel.num = 3291 soc->cdp_soc.ol_ops->freq_to_channel(soc->ctrl_psoc, 3292 pdev->pdev_id, 3293 freq); 3294 3295 if (soc && soc->cdp_soc.ol_ops->freq_to_band) 3296 pdev->operating_channel.band = 3297 soc->cdp_soc.ol_ops->freq_to_band(soc->ctrl_psoc, 3298 pdev->pdev_id, 3299 freq); 3300 } 3301 3302 ppdu_desc->phy_mode = HTT_PPDU_STATS_COMMON_TLV_PHY_MODE_GET(*tag_buf); 3303 3304 tag_buf = start_tag_buf + HTT_GET_STATS_CMN_INDEX(RESV_NUM_UL_BEAM); 3305 ppdu_desc->phy_ppdu_tx_time_us = 3306 HTT_PPDU_STATS_COMMON_TLV_PHY_PPDU_TX_TIME_US_GET(*tag_buf); 3307 ppdu_desc->beam_change = 3308 HTT_PPDU_STATS_COMMON_TLV_BEAM_CHANGE_GET(*tag_buf); 3309 ppdu_desc->doppler = 3310 HTT_PPDU_STATS_COMMON_TLV_DOPPLER_INDICATION_GET(*tag_buf); 3311 ppdu_desc->spatial_reuse = 3312 HTT_PPDU_STATS_COMMON_TLV_SPATIAL_REUSE_GET(*tag_buf); 3313 3314 dp_tx_capture_htt_frame_counter(pdev, frame_type); 3315 3316 tag_buf = start_tag_buf + HTT_GET_STATS_CMN_INDEX(START_TSTMP_U32_US); 3317 ppdu_start_timestamp = *tag_buf; 3318 ppdu_desc->ppdu_start_timestamp |= ((ppdu_start_timestamp << 3319 HTT_SHIFT_UPPER_TIMESTAMP) & 3320 HTT_MASK_UPPER_TIMESTAMP); 3321 3322 ppdu_desc->ppdu_end_timestamp = ppdu_desc->ppdu_start_timestamp + 3323 ppdu_desc->tx_duration; 3324 /* Ack time stamp is same as end time stamp*/ 3325 ppdu_desc->ack_timestamp = ppdu_desc->ppdu_end_timestamp; 3326 3327 ppdu_desc->ppdu_end_timestamp = ppdu_desc->ppdu_start_timestamp + 3328 ppdu_desc->tx_duration; 3329 3330 ppdu_desc->bar_ppdu_start_timestamp = ppdu_desc->ppdu_start_timestamp; 3331 ppdu_desc->bar_ppdu_end_timestamp = ppdu_desc->ppdu_end_timestamp; 3332 ppdu_desc->bar_tx_duration = ppdu_desc->tx_duration; 3333 3334 /* Ack time stamp is same as end time stamp*/ 3335 ppdu_desc->ack_timestamp = ppdu_desc->ppdu_end_timestamp; 3336 3337 tag_buf = start_tag_buf + HTT_GET_STATS_CMN_INDEX(BSSCOLOR_OBSS_PSR); 3338 ppdu_desc->bss_color = 3339 HTT_PPDU_STATS_COMMON_TLV_BSS_COLOR_ID_GET(*tag_buf); 3340 } 3341 3342 /* 3343 * dp_process_ppdu_stats_user_common_tlv: Process ppdu_stats_user_common 3344 * @tag_buf: buffer containing the tlv htt_ppdu_stats_user_common_tlv 3345 * @ppdu_info: per ppdu tlv structure 3346 * 3347 * return:void 3348 */ 3349 static void dp_process_ppdu_stats_user_common_tlv( 3350 struct dp_pdev *pdev, uint32_t *tag_buf, 3351 struct ppdu_info *ppdu_info) 3352 { 3353 uint16_t peer_id; 3354 struct cdp_tx_completion_ppdu *ppdu_desc; 3355 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 3356 uint8_t curr_user_index = 0; 3357 struct dp_peer *peer; 3358 struct dp_vdev *vdev; 3359 uint32_t tlv_type = HTT_STATS_TLV_TAG_GET(*tag_buf); 3360 3361 ppdu_desc = 3362 (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 3363 3364 tag_buf++; 3365 peer_id = HTT_PPDU_STATS_USER_RATE_TLV_SW_PEER_ID_GET(*tag_buf); 3366 3367 curr_user_index = 3368 dp_get_ppdu_info_user_index(pdev, 3369 peer_id, ppdu_info); 3370 ppdu_user_desc = &ppdu_desc->user[curr_user_index]; 3371 ppdu_user_desc->tlv_bitmap |= (1 << tlv_type); 3372 3373 ppdu_desc->vdev_id = 3374 HTT_PPDU_STATS_USER_COMMON_TLV_VAP_ID_GET(*tag_buf); 3375 3376 ppdu_user_desc->peer_id = peer_id; 3377 3378 tag_buf++; 3379 3380 if (HTT_PPDU_STATS_USER_COMMON_TLV_DELAYED_BA_GET(*tag_buf)) { 3381 ppdu_user_desc->delayed_ba = 1; 3382 ppdu_desc->delayed_ba = 1; 3383 } 3384 3385 if (HTT_PPDU_STATS_USER_COMMON_TLV_MCAST_GET(*tag_buf)) { 3386 ppdu_user_desc->is_mcast = true; 3387 ppdu_user_desc->mpdu_tried_mcast = 3388 HTT_PPDU_STATS_USER_COMMON_TLV_MPDUS_TRIED_GET(*tag_buf); 3389 ppdu_user_desc->num_mpdu = ppdu_user_desc->mpdu_tried_mcast; 3390 } else { 3391 ppdu_user_desc->mpdu_tried_ucast = 3392 HTT_PPDU_STATS_USER_COMMON_TLV_MPDUS_TRIED_GET(*tag_buf); 3393 } 3394 3395 ppdu_user_desc->is_seq_num_valid = 3396 HTT_PPDU_STATS_USER_COMMON_TLV_IS_SQNUM_VALID_IN_BUFFER_GET(*tag_buf); 3397 tag_buf++; 3398 3399 ppdu_user_desc->qos_ctrl = 3400 HTT_PPDU_STATS_USER_COMMON_TLV_QOS_CTRL_GET(*tag_buf); 3401 ppdu_user_desc->frame_ctrl = 3402 HTT_PPDU_STATS_USER_COMMON_TLV_FRAME_CTRL_GET(*tag_buf); 3403 ppdu_desc->frame_ctrl = ppdu_user_desc->frame_ctrl; 3404 3405 if (ppdu_user_desc->delayed_ba) 3406 ppdu_user_desc->mpdu_success = 0; 3407 3408 tag_buf += 3; 3409 3410 if (HTT_PPDU_STATS_IS_OPAQUE_VALID_GET(*tag_buf)) { 3411 ppdu_user_desc->ppdu_cookie = 3412 HTT_PPDU_STATS_HOST_OPAQUE_COOKIE_GET(*tag_buf); 3413 ppdu_user_desc->is_ppdu_cookie_valid = 1; 3414 } 3415 3416 /* returning earlier causes other feilds unpopulated */ 3417 if (peer_id == DP_SCAN_PEER_ID) { 3418 vdev = dp_vdev_get_ref_by_id(pdev->soc, ppdu_desc->vdev_id, 3419 DP_MOD_ID_TX_PPDU_STATS); 3420 if (!vdev) 3421 return; 3422 qdf_mem_copy(ppdu_user_desc->mac_addr, vdev->mac_addr.raw, 3423 QDF_MAC_ADDR_SIZE); 3424 dp_vdev_unref_delete(pdev->soc, vdev, DP_MOD_ID_TX_PPDU_STATS); 3425 } else { 3426 peer = dp_peer_get_ref_by_id(pdev->soc, peer_id, 3427 DP_MOD_ID_TX_PPDU_STATS); 3428 if (!peer) { 3429 /* 3430 * fw sends peer_id which is about to removed but 3431 * it was already removed in host. 3432 * eg: for disassoc, fw send ppdu stats 3433 * with peer id equal to previously associated 3434 * peer's peer_id but it was removed 3435 */ 3436 vdev = dp_vdev_get_ref_by_id(pdev->soc, 3437 ppdu_desc->vdev_id, 3438 DP_MOD_ID_TX_PPDU_STATS); 3439 if (!vdev) 3440 return; 3441 qdf_mem_copy(ppdu_user_desc->mac_addr, 3442 vdev->mac_addr.raw, QDF_MAC_ADDR_SIZE); 3443 dp_vdev_unref_delete(pdev->soc, vdev, 3444 DP_MOD_ID_TX_PPDU_STATS); 3445 return; 3446 } 3447 qdf_mem_copy(ppdu_user_desc->mac_addr, 3448 peer->mac_addr.raw, QDF_MAC_ADDR_SIZE); 3449 dp_peer_unref_delete(peer, DP_MOD_ID_TX_PPDU_STATS); 3450 } 3451 } 3452 3453 /** 3454 * dp_process_ppdu_stats_user_rate_tlv() - Process htt_ppdu_stats_user_rate_tlv 3455 * @pdev: DP pdev handle 3456 * @tag_buf: T2H message buffer carrying the user rate TLV 3457 * @ppdu_info: per ppdu tlv structure 3458 * 3459 * return:void 3460 */ 3461 static void 3462 dp_process_ppdu_stats_user_rate_tlv(struct dp_pdev *pdev, 3463 uint32_t *tag_buf, 3464 struct ppdu_info *ppdu_info) 3465 { 3466 uint16_t peer_id; 3467 struct cdp_tx_completion_ppdu *ppdu_desc; 3468 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 3469 uint8_t curr_user_index = 0; 3470 struct dp_vdev *vdev; 3471 uint32_t tlv_type = HTT_STATS_TLV_TAG_GET(*tag_buf); 3472 uint8_t bw, ru_format; 3473 uint16_t ru_size; 3474 3475 ppdu_desc = 3476 (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 3477 3478 tag_buf++; 3479 peer_id = HTT_PPDU_STATS_USER_RATE_TLV_SW_PEER_ID_GET(*tag_buf); 3480 3481 curr_user_index = 3482 dp_get_ppdu_info_user_index(pdev, 3483 peer_id, ppdu_info); 3484 ppdu_user_desc = &ppdu_desc->user[curr_user_index]; 3485 ppdu_user_desc->tlv_bitmap |= (1 << tlv_type); 3486 if (peer_id == DP_SCAN_PEER_ID) { 3487 vdev = dp_vdev_get_ref_by_id(pdev->soc, ppdu_desc->vdev_id, 3488 DP_MOD_ID_TX_PPDU_STATS); 3489 if (!vdev) 3490 return; 3491 dp_vdev_unref_delete(pdev->soc, vdev, 3492 DP_MOD_ID_TX_PPDU_STATS); 3493 } 3494 ppdu_user_desc->peer_id = peer_id; 3495 3496 ppdu_user_desc->tid = 3497 HTT_PPDU_STATS_USER_RATE_TLV_TID_NUM_GET(*tag_buf); 3498 3499 tag_buf += 1; 3500 3501 ppdu_user_desc->user_pos = 3502 HTT_PPDU_STATS_USER_RATE_TLV_USER_POS_GET(*tag_buf); 3503 ppdu_user_desc->mu_group_id = 3504 HTT_PPDU_STATS_USER_RATE_TLV_MU_GROUPID_GET(*tag_buf); 3505 3506 ru_format = HTT_PPDU_STATS_USER_RATE_TLV_RU_FORMAT_GET(*tag_buf); 3507 3508 tag_buf += 1; 3509 3510 if (!ru_format) { 3511 /* ru_format = 0: ru_end, ru_start */ 3512 ppdu_user_desc->ru_start = 3513 HTT_PPDU_STATS_USER_RATE_TLV_RU_START_GET(*tag_buf); 3514 ppdu_user_desc->ru_tones = 3515 (HTT_PPDU_STATS_USER_RATE_TLV_RU_END_GET(*tag_buf) - 3516 HTT_PPDU_STATS_USER_RATE_TLV_RU_START_GET(*tag_buf)) + 1; 3517 } else if (ru_format == 1) { 3518 /* ru_format = 1: ru_index, ru_size */ 3519 ru_size = HTT_PPDU_STATS_USER_RATE_TLV_RU_SIZE_GET(*tag_buf); 3520 ppdu_user_desc->ru_tones = 3521 dp_mon_get_ru_width_from_ru_size(ru_size); 3522 } else { 3523 dp_mon_debug("Unsupported ru_format: %d rcvd", ru_format); 3524 } 3525 ppdu_desc->usr_ru_tones_sum += ppdu_user_desc->ru_tones; 3526 3527 tag_buf += 2; 3528 3529 ppdu_user_desc->ppdu_type = 3530 HTT_PPDU_STATS_USER_RATE_TLV_PPDU_TYPE_GET(*tag_buf); 3531 3532 tag_buf++; 3533 ppdu_user_desc->tx_rate = *tag_buf; 3534 3535 ppdu_user_desc->ltf_size = 3536 HTT_PPDU_STATS_USER_RATE_TLV_LTF_SIZE_GET(*tag_buf); 3537 ppdu_user_desc->stbc = 3538 HTT_PPDU_STATS_USER_RATE_TLV_STBC_GET(*tag_buf); 3539 ppdu_user_desc->he_re = 3540 HTT_PPDU_STATS_USER_RATE_TLV_HE_RE_GET(*tag_buf); 3541 ppdu_user_desc->txbf = 3542 HTT_PPDU_STATS_USER_RATE_TLV_TXBF_GET(*tag_buf); 3543 bw = HTT_PPDU_STATS_USER_RATE_TLV_BW_GET(*tag_buf); 3544 /* Align bw value as per host data structures */ 3545 if (bw == HTT_PPDU_STATS_BANDWIDTH_320MHZ) 3546 ppdu_user_desc->bw = bw - 3; 3547 else 3548 ppdu_user_desc->bw = bw - 2; 3549 ppdu_user_desc->nss = HTT_PPDU_STATS_USER_RATE_TLV_NSS_GET(*tag_buf); 3550 ppdu_desc->usr_nss_sum += ppdu_user_desc->nss; 3551 ppdu_user_desc->mcs = HTT_PPDU_STATS_USER_RATE_TLV_MCS_GET(*tag_buf); 3552 ppdu_user_desc->preamble = 3553 HTT_PPDU_STATS_USER_RATE_TLV_PREAMBLE_GET(*tag_buf); 3554 ppdu_user_desc->gi = HTT_PPDU_STATS_USER_RATE_TLV_GI_GET(*tag_buf); 3555 ppdu_user_desc->dcm = HTT_PPDU_STATS_USER_RATE_TLV_DCM_GET(*tag_buf); 3556 ppdu_user_desc->ldpc = HTT_PPDU_STATS_USER_RATE_TLV_LDPC_GET(*tag_buf); 3557 3558 tag_buf += 2; 3559 ppdu_user_desc->punc_pattern_bitmap = 3560 HTT_PPDU_STATS_USER_RATE_TLV_PUNC_PATTERN_BITMAP_GET(*tag_buf); 3561 } 3562 3563 /* 3564 * dp_process_ppdu_stats_enq_mpdu_bitmap_64_tlv: Process 3565 * htt_ppdu_stats_enq_mpdu_bitmap_64_tlv 3566 * pdev: DP PDEV handle 3567 * @tag_buf: buffer containing the tlv htt_ppdu_stats_enq_mpdu_bitmap_64_tlv 3568 * @ppdu_info: per ppdu tlv structure 3569 * 3570 * return:void 3571 */ 3572 static void dp_process_ppdu_stats_enq_mpdu_bitmap_64_tlv( 3573 struct dp_pdev *pdev, uint32_t *tag_buf, 3574 struct ppdu_info *ppdu_info) 3575 { 3576 htt_ppdu_stats_enq_mpdu_bitmap_64_tlv *dp_stats_buf = 3577 (htt_ppdu_stats_enq_mpdu_bitmap_64_tlv *)tag_buf; 3578 3579 struct cdp_tx_completion_ppdu *ppdu_desc; 3580 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 3581 uint8_t curr_user_index = 0; 3582 uint16_t peer_id; 3583 uint32_t size = CDP_BA_64_BIT_MAP_SIZE_DWORDS; 3584 uint32_t tlv_type = HTT_STATS_TLV_TAG_GET(*tag_buf); 3585 3586 ppdu_desc = 3587 (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 3588 3589 tag_buf++; 3590 3591 peer_id = 3592 HTT_PPDU_STATS_ENQ_MPDU_BITMAP_TLV_SW_PEER_ID_GET(*tag_buf); 3593 3594 curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info); 3595 ppdu_user_desc = &ppdu_desc->user[curr_user_index]; 3596 ppdu_user_desc->tlv_bitmap |= (1 << tlv_type); 3597 ppdu_user_desc->peer_id = peer_id; 3598 3599 ppdu_user_desc->start_seq = dp_stats_buf->start_seq; 3600 qdf_mem_copy(&ppdu_user_desc->enq_bitmap, &dp_stats_buf->enq_bitmap, 3601 sizeof(uint32_t) * CDP_BA_64_BIT_MAP_SIZE_DWORDS); 3602 3603 dp_process_ppdu_stats_update_failed_bitmap(pdev, 3604 (void *)ppdu_user_desc, 3605 ppdu_info->ppdu_id, 3606 size); 3607 } 3608 3609 /* 3610 * dp_process_ppdu_stats_enq_mpdu_bitmap_256_tlv: Process 3611 * htt_ppdu_stats_enq_mpdu_bitmap_256_tlv 3612 * soc: DP SOC handle 3613 * @tag_buf: buffer containing the tlv htt_ppdu_stats_enq_mpdu_bitmap_256_tlv 3614 * @ppdu_info: per ppdu tlv structure 3615 * 3616 * return:void 3617 */ 3618 static void dp_process_ppdu_stats_enq_mpdu_bitmap_256_tlv( 3619 struct dp_pdev *pdev, uint32_t *tag_buf, 3620 struct ppdu_info *ppdu_info) 3621 { 3622 htt_ppdu_stats_enq_mpdu_bitmap_256_tlv *dp_stats_buf = 3623 (htt_ppdu_stats_enq_mpdu_bitmap_256_tlv *)tag_buf; 3624 3625 struct cdp_tx_completion_ppdu *ppdu_desc; 3626 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 3627 uint8_t curr_user_index = 0; 3628 uint16_t peer_id; 3629 uint32_t size = CDP_BA_256_BIT_MAP_SIZE_DWORDS; 3630 uint32_t tlv_type = HTT_STATS_TLV_TAG_GET(*tag_buf); 3631 3632 ppdu_desc = 3633 (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 3634 3635 tag_buf++; 3636 3637 peer_id = 3638 HTT_PPDU_STATS_ENQ_MPDU_BITMAP_TLV_SW_PEER_ID_GET(*tag_buf); 3639 3640 curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info); 3641 ppdu_user_desc = &ppdu_desc->user[curr_user_index]; 3642 ppdu_user_desc->tlv_bitmap |= (1 << tlv_type); 3643 ppdu_user_desc->peer_id = peer_id; 3644 3645 ppdu_user_desc->start_seq = dp_stats_buf->start_seq; 3646 qdf_mem_copy(&ppdu_user_desc->enq_bitmap, &dp_stats_buf->enq_bitmap, 3647 sizeof(uint32_t) * CDP_BA_256_BIT_MAP_SIZE_DWORDS); 3648 3649 dp_process_ppdu_stats_update_failed_bitmap(pdev, 3650 (void *)ppdu_user_desc, 3651 ppdu_info->ppdu_id, 3652 size); 3653 } 3654 3655 /* 3656 * dp_process_ppdu_stats_user_cmpltn_common_tlv: Process 3657 * htt_ppdu_stats_user_cmpltn_common_tlv 3658 * soc: DP SOC handle 3659 * @tag_buf: buffer containing the tlv htt_ppdu_stats_user_cmpltn_common_tlv 3660 * @ppdu_info: per ppdu tlv structure 3661 * 3662 * return:void 3663 */ 3664 static void dp_process_ppdu_stats_user_cmpltn_common_tlv( 3665 struct dp_pdev *pdev, uint32_t *tag_buf, 3666 struct ppdu_info *ppdu_info) 3667 { 3668 uint16_t peer_id; 3669 struct cdp_tx_completion_ppdu *ppdu_desc; 3670 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 3671 uint8_t curr_user_index = 0; 3672 uint8_t bw_iter; 3673 htt_ppdu_stats_user_cmpltn_common_tlv *dp_stats_buf = 3674 (htt_ppdu_stats_user_cmpltn_common_tlv *)tag_buf; 3675 uint32_t tlv_type = HTT_STATS_TLV_TAG_GET(*tag_buf); 3676 3677 ppdu_desc = 3678 (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 3679 3680 tag_buf++; 3681 peer_id = 3682 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_SW_PEER_ID_GET(*tag_buf); 3683 3684 curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info); 3685 ppdu_user_desc = &ppdu_desc->user[curr_user_index]; 3686 ppdu_user_desc->tlv_bitmap |= (1 << tlv_type); 3687 ppdu_user_desc->peer_id = peer_id; 3688 3689 ppdu_user_desc->completion_status = 3690 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_COMPLETION_STATUS_GET( 3691 *tag_buf); 3692 3693 ppdu_user_desc->tid = 3694 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_TID_NUM_GET(*tag_buf); 3695 3696 tag_buf++; 3697 if (qdf_likely(ppdu_user_desc->completion_status == 3698 HTT_PPDU_STATS_USER_STATUS_OK)) { 3699 ppdu_desc->ack_rssi = dp_stats_buf->ack_rssi; 3700 ppdu_user_desc->usr_ack_rssi = dp_stats_buf->ack_rssi; 3701 ppdu_user_desc->ack_rssi_valid = 1; 3702 } else { 3703 ppdu_user_desc->ack_rssi_valid = 0; 3704 } 3705 3706 tag_buf++; 3707 3708 ppdu_user_desc->mpdu_success = 3709 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_MPDU_SUCCESS_GET(*tag_buf); 3710 3711 ppdu_user_desc->mpdu_failed = 3712 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_MPDU_TRIED_GET(*tag_buf) - 3713 ppdu_user_desc->mpdu_success; 3714 3715 tag_buf++; 3716 3717 ppdu_user_desc->long_retries = 3718 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_LONG_RETRY_GET(*tag_buf); 3719 3720 ppdu_user_desc->short_retries = 3721 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_SHORT_RETRY_GET(*tag_buf); 3722 ppdu_user_desc->retry_mpdus = 3723 ppdu_user_desc->long_retries + ppdu_user_desc->short_retries; 3724 3725 ppdu_user_desc->is_ampdu = 3726 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_IS_AMPDU_GET(*tag_buf); 3727 ppdu_info->is_ampdu = ppdu_user_desc->is_ampdu; 3728 3729 ppdu_desc->resp_type = 3730 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_RESP_TYPE_GET(*tag_buf); 3731 ppdu_desc->mprot_type = 3732 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_MPROT_TYPE_GET(*tag_buf); 3733 ppdu_desc->rts_success = 3734 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_RTS_SUCCESS_GET(*tag_buf); 3735 ppdu_desc->rts_failure = 3736 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_RTS_FAILURE_GET(*tag_buf); 3737 3738 ppdu_user_desc->mprot_type = ppdu_desc->mprot_type; 3739 ppdu_user_desc->rts_success = ppdu_desc->rts_success; 3740 ppdu_user_desc->rts_failure = ppdu_desc->rts_failure; 3741 3742 ppdu_user_desc->pream_punct = 3743 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_PREAM_PUNC_TX_GET(*tag_buf); 3744 3745 ppdu_info->compltn_common_tlv++; 3746 3747 /* 3748 * MU BAR may send request to n users but we may received ack only from 3749 * m users. To have count of number of users respond back, we have a 3750 * separate counter bar_num_users per PPDU that get increment for every 3751 * htt_ppdu_stats_user_cmpltn_common_tlv 3752 */ 3753 ppdu_desc->bar_num_users++; 3754 3755 tag_buf++; 3756 for (bw_iter = 0; bw_iter < CDP_RSSI_CHAIN_LEN; bw_iter++) { 3757 ppdu_user_desc->rssi_chain[bw_iter] = 3758 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_CHAIN_RSSI_GET(*tag_buf); 3759 tag_buf++; 3760 } 3761 3762 ppdu_user_desc->sa_tx_antenna = 3763 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_TX_ANTENNA_MASK_GET(*tag_buf); 3764 3765 tag_buf++; 3766 ppdu_user_desc->sa_is_training = 3767 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_IS_TRAINING_GET(*tag_buf); 3768 if (ppdu_user_desc->sa_is_training) { 3769 ppdu_user_desc->sa_goodput = 3770 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_PENDING_TRAINING_PKTS_GET(*tag_buf); 3771 } 3772 3773 tag_buf++; 3774 for (bw_iter = 0; bw_iter < CDP_NUM_SA_BW; bw_iter++) { 3775 ppdu_user_desc->sa_max_rates[bw_iter] = 3776 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_MAX_RATES_GET(tag_buf[bw_iter]); 3777 } 3778 3779 tag_buf += CDP_NUM_SA_BW; 3780 ppdu_user_desc->current_rate_per = 3781 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_CURRENT_RATE_PER_GET(*tag_buf); 3782 } 3783 3784 /* 3785 * dp_process_ppdu_stats_user_compltn_ba_bitmap_64_tlv: Process 3786 * htt_ppdu_stats_user_compltn_ba_bitmap_64_tlv 3787 * pdev: DP PDEV handle 3788 * @tag_buf: buffer containing the htt_ppdu_stats_user_compltn_ba_bitmap_64_tlv 3789 * @ppdu_info: per ppdu tlv structure 3790 * 3791 * return:void 3792 */ 3793 static void dp_process_ppdu_stats_user_compltn_ba_bitmap_64_tlv( 3794 struct dp_pdev *pdev, uint32_t *tag_buf, 3795 struct ppdu_info *ppdu_info) 3796 { 3797 htt_ppdu_stats_user_compltn_ba_bitmap_64_tlv *dp_stats_buf = 3798 (htt_ppdu_stats_user_compltn_ba_bitmap_64_tlv *)tag_buf; 3799 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 3800 struct cdp_tx_completion_ppdu *ppdu_desc; 3801 uint8_t curr_user_index = 0; 3802 uint16_t peer_id; 3803 uint32_t tlv_type = HTT_STATS_TLV_TAG_GET(*tag_buf); 3804 3805 ppdu_desc = 3806 (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 3807 3808 tag_buf++; 3809 3810 peer_id = 3811 HTT_PPDU_STATS_USER_CMPLTN_BA_BITMAP_TLV_SW_PEER_ID_GET(*tag_buf); 3812 3813 curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info); 3814 ppdu_user_desc = &ppdu_desc->user[curr_user_index]; 3815 ppdu_user_desc->tlv_bitmap |= (1 << tlv_type); 3816 ppdu_user_desc->peer_id = peer_id; 3817 3818 ppdu_user_desc->ba_seq_no = dp_stats_buf->ba_seq_no; 3819 qdf_mem_copy(&ppdu_user_desc->ba_bitmap, &dp_stats_buf->ba_bitmap, 3820 sizeof(uint32_t) * CDP_BA_64_BIT_MAP_SIZE_DWORDS); 3821 ppdu_user_desc->ba_size = CDP_BA_64_BIT_MAP_SIZE_DWORDS * 32; 3822 } 3823 3824 /* 3825 * dp_process_ppdu_stats_user_compltn_ba_bitmap_256_tlv: Process 3826 * htt_ppdu_stats_user_compltn_ba_bitmap_256_tlv 3827 * pdev: DP PDEV handle 3828 * @tag_buf: buffer containing the htt_ppdu_stats_user_compltn_ba_bitmap_256_tlv 3829 * @ppdu_info: per ppdu tlv structure 3830 * 3831 * return:void 3832 */ 3833 static void dp_process_ppdu_stats_user_compltn_ba_bitmap_256_tlv( 3834 struct dp_pdev *pdev, uint32_t *tag_buf, 3835 struct ppdu_info *ppdu_info) 3836 { 3837 htt_ppdu_stats_user_compltn_ba_bitmap_256_tlv *dp_stats_buf = 3838 (htt_ppdu_stats_user_compltn_ba_bitmap_256_tlv *)tag_buf; 3839 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 3840 struct cdp_tx_completion_ppdu *ppdu_desc; 3841 uint8_t curr_user_index = 0; 3842 uint16_t peer_id; 3843 uint32_t tlv_type = HTT_STATS_TLV_TAG_GET(*tag_buf); 3844 3845 ppdu_desc = 3846 (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 3847 3848 tag_buf++; 3849 3850 peer_id = 3851 HTT_PPDU_STATS_USER_CMPLTN_BA_BITMAP_TLV_SW_PEER_ID_GET(*tag_buf); 3852 3853 curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info); 3854 ppdu_user_desc = &ppdu_desc->user[curr_user_index]; 3855 ppdu_user_desc->tlv_bitmap |= (1 << tlv_type); 3856 ppdu_user_desc->peer_id = peer_id; 3857 3858 ppdu_user_desc->ba_seq_no = dp_stats_buf->ba_seq_no; 3859 qdf_mem_copy(&ppdu_user_desc->ba_bitmap, &dp_stats_buf->ba_bitmap, 3860 sizeof(uint32_t) * CDP_BA_256_BIT_MAP_SIZE_DWORDS); 3861 ppdu_user_desc->ba_size = CDP_BA_256_BIT_MAP_SIZE_DWORDS * 32; 3862 } 3863 3864 /* 3865 * dp_process_ppdu_stats_user_compltn_ack_ba_status_tlv: Process 3866 * htt_ppdu_stats_user_compltn_ack_ba_status_tlv 3867 * pdev: DP PDE handle 3868 * @tag_buf: buffer containing the htt_ppdu_stats_user_compltn_ack_ba_status_tlv 3869 * @ppdu_info: per ppdu tlv structure 3870 * 3871 * return:void 3872 */ 3873 static void dp_process_ppdu_stats_user_compltn_ack_ba_status_tlv( 3874 struct dp_pdev *pdev, uint32_t *tag_buf, 3875 struct ppdu_info *ppdu_info) 3876 { 3877 uint16_t peer_id; 3878 struct cdp_tx_completion_ppdu *ppdu_desc; 3879 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 3880 uint8_t curr_user_index = 0; 3881 uint32_t tlv_type = HTT_STATS_TLV_TAG_GET(*tag_buf); 3882 3883 ppdu_desc = 3884 (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 3885 3886 tag_buf += 2; 3887 peer_id = 3888 HTT_PPDU_STATS_USER_CMPLTN_ACK_BA_STATUS_TLV_SW_PEER_ID_GET(*tag_buf); 3889 3890 curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info); 3891 ppdu_user_desc = &ppdu_desc->user[curr_user_index]; 3892 ppdu_user_desc->tlv_bitmap |= (1 << tlv_type); 3893 if (!ppdu_user_desc->ack_ba_tlv) { 3894 ppdu_user_desc->ack_ba_tlv = 1; 3895 } else { 3896 pdev->stats.ack_ba_comes_twice++; 3897 return; 3898 } 3899 3900 ppdu_user_desc->peer_id = peer_id; 3901 3902 tag_buf++; 3903 /* not to update ppdu_desc->tid from this TLV */ 3904 ppdu_user_desc->num_mpdu = 3905 HTT_PPDU_STATS_USER_CMPLTN_ACK_BA_STATUS_TLV_NUM_MPDU_GET(*tag_buf); 3906 3907 ppdu_user_desc->num_msdu = 3908 HTT_PPDU_STATS_USER_CMPLTN_ACK_BA_STATUS_TLV_NUM_MSDU_GET(*tag_buf); 3909 3910 ppdu_user_desc->success_msdus = ppdu_user_desc->num_msdu; 3911 3912 tag_buf++; 3913 ppdu_user_desc->start_seq = 3914 HTT_PPDU_STATS_USER_CMPLTN_ACK_BA_STATUS_TLV_START_SEQ_GET( 3915 *tag_buf); 3916 3917 tag_buf++; 3918 ppdu_user_desc->success_bytes = *tag_buf; 3919 3920 /* increase ack ba tlv counter on successful mpdu */ 3921 if (ppdu_user_desc->num_mpdu) 3922 ppdu_info->ack_ba_tlv++; 3923 3924 if (ppdu_user_desc->ba_size == 0) { 3925 ppdu_user_desc->ba_seq_no = ppdu_user_desc->start_seq; 3926 ppdu_user_desc->ba_bitmap[0] = 1; 3927 ppdu_user_desc->ba_size = 1; 3928 } 3929 } 3930 3931 /* 3932 * dp_process_ppdu_stats_user_common_array_tlv: Process 3933 * htt_ppdu_stats_user_common_array_tlv 3934 * pdev: DP PDEV handle 3935 * @tag_buf: buffer containing the htt_ppdu_stats_user_compltn_ack_ba_status_tlv 3936 * @ppdu_info: per ppdu tlv structure 3937 * 3938 * return:void 3939 */ 3940 static void dp_process_ppdu_stats_user_common_array_tlv( 3941 struct dp_pdev *pdev, uint32_t *tag_buf, 3942 struct ppdu_info *ppdu_info) 3943 { 3944 uint32_t peer_id; 3945 struct cdp_tx_completion_ppdu *ppdu_desc; 3946 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 3947 uint8_t curr_user_index = 0; 3948 struct htt_tx_ppdu_stats_info *dp_stats_buf; 3949 uint32_t tlv_type = HTT_STATS_TLV_TAG_GET(*tag_buf); 3950 3951 ppdu_desc = 3952 (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 3953 3954 tag_buf++; 3955 dp_stats_buf = (struct htt_tx_ppdu_stats_info *)tag_buf; 3956 tag_buf += 3; 3957 peer_id = 3958 HTT_PPDU_STATS_ARRAY_ITEM_TLV_PEERID_GET(*tag_buf); 3959 3960 if (!dp_peer_find_by_id_valid(pdev->soc, peer_id)) { 3961 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 3962 "Invalid peer"); 3963 return; 3964 } 3965 3966 curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info); 3967 3968 ppdu_user_desc = &ppdu_desc->user[curr_user_index]; 3969 ppdu_user_desc->tlv_bitmap |= (1 << tlv_type); 3970 3971 ppdu_user_desc->retry_bytes = dp_stats_buf->tx_retry_bytes; 3972 ppdu_user_desc->failed_bytes = dp_stats_buf->tx_failed_bytes; 3973 3974 tag_buf++; 3975 3976 ppdu_user_desc->success_msdus = 3977 HTT_PPDU_STATS_ARRAY_ITEM_TLV_TX_SUCC_MSDUS_GET(*tag_buf); 3978 ppdu_user_desc->retry_msdus = 3979 HTT_PPDU_STATS_ARRAY_ITEM_TLV_TX_RETRY_MSDUS_GET(*tag_buf); 3980 tag_buf++; 3981 ppdu_user_desc->failed_msdus = 3982 HTT_PPDU_STATS_ARRAY_ITEM_TLV_TX_FAILED_MSDUS_GET(*tag_buf); 3983 } 3984 3985 /* 3986 * dp_process_ppdu_stats_flush_tlv: Process 3987 * htt_ppdu_stats_flush_tlv 3988 * @pdev: DP PDEV handle 3989 * @tag_buf: buffer containing the htt_ppdu_stats_flush_tlv 3990 * @ppdu_info: per ppdu tlv structure 3991 * 3992 * return:void 3993 */ 3994 static void 3995 dp_process_ppdu_stats_user_compltn_flush_tlv(struct dp_pdev *pdev, 3996 uint32_t *tag_buf, 3997 struct ppdu_info *ppdu_info) 3998 { 3999 struct cdp_tx_completion_ppdu *ppdu_desc; 4000 uint32_t peer_id; 4001 uint8_t tid; 4002 struct dp_peer *peer; 4003 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 4004 struct dp_mon_peer *mon_peer = NULL; 4005 4006 ppdu_desc = (struct cdp_tx_completion_ppdu *) 4007 qdf_nbuf_data(ppdu_info->nbuf); 4008 ppdu_desc->is_flush = 1; 4009 4010 tag_buf++; 4011 ppdu_desc->drop_reason = *tag_buf; 4012 4013 tag_buf++; 4014 ppdu_desc->num_msdu = HTT_PPDU_STATS_FLUSH_TLV_NUM_MSDU_GET(*tag_buf); 4015 ppdu_desc->num_mpdu = HTT_PPDU_STATS_FLUSH_TLV_NUM_MPDU_GET(*tag_buf); 4016 ppdu_desc->flow_type = HTT_PPDU_STATS_FLUSH_TLV_FLOW_TYPE_GET(*tag_buf); 4017 4018 tag_buf++; 4019 peer_id = HTT_PPDU_STATS_FLUSH_TLV_SW_PEER_ID_GET(*tag_buf); 4020 tid = HTT_PPDU_STATS_FLUSH_TLV_TID_NUM_GET(*tag_buf); 4021 4022 ppdu_desc->num_users = 1; 4023 ppdu_desc->user[0].peer_id = peer_id; 4024 ppdu_desc->user[0].tid = tid; 4025 4026 ppdu_desc->queue_type = 4027 HTT_PPDU_STATS_FLUSH_TLV_QUEUE_TYPE_GET(*tag_buf); 4028 4029 peer = dp_peer_get_ref_by_id(pdev->soc, peer_id, 4030 DP_MOD_ID_TX_PPDU_STATS); 4031 if (!peer) 4032 goto add_ppdu_to_sched_list; 4033 4034 if (ppdu_desc->drop_reason == HTT_FLUSH_EXCESS_RETRIES) { 4035 mon_peer = peer->monitor_peer; 4036 DP_STATS_INC(mon_peer, 4037 tx.excess_retries_per_ac[TID_TO_WME_AC(tid)], 4038 ppdu_desc->num_msdu); 4039 } 4040 4041 dp_peer_unref_delete(peer, DP_MOD_ID_TX_PPDU_STATS); 4042 4043 add_ppdu_to_sched_list: 4044 ppdu_info->done = 1; 4045 TAILQ_REMOVE(&mon_pdev->ppdu_info_list, ppdu_info, ppdu_info_list_elem); 4046 mon_pdev->list_depth--; 4047 TAILQ_INSERT_TAIL(&mon_pdev->sched_comp_ppdu_list, ppdu_info, 4048 ppdu_info_list_elem); 4049 mon_pdev->sched_comp_list_depth++; 4050 } 4051 4052 /** 4053 * dp_process_ppdu_stats_sch_cmd_status_tlv: Process schedule command status tlv 4054 * Here we are not going to process the buffer. 4055 * @pdev: DP PDEV handle 4056 * @ppdu_info: per ppdu tlv structure 4057 * 4058 * return:void 4059 */ 4060 static void 4061 dp_process_ppdu_stats_sch_cmd_status_tlv(struct dp_pdev *pdev, 4062 struct ppdu_info *ppdu_info) 4063 { 4064 struct cdp_tx_completion_ppdu *ppdu_desc; 4065 struct dp_peer *peer; 4066 uint8_t num_users; 4067 uint8_t i; 4068 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 4069 4070 ppdu_desc = (struct cdp_tx_completion_ppdu *) 4071 qdf_nbuf_data(ppdu_info->nbuf); 4072 4073 num_users = ppdu_desc->bar_num_users; 4074 4075 for (i = 0; i < num_users; i++) { 4076 if (ppdu_desc->user[i].user_pos == 0) { 4077 if (ppdu_desc->frame_type == CDP_PPDU_FTYPE_BAR) { 4078 /* update phy mode for bar frame */ 4079 ppdu_desc->phy_mode = 4080 ppdu_desc->user[i].preamble; 4081 ppdu_desc->user[0].mcs = ppdu_desc->user[i].mcs; 4082 break; 4083 } 4084 if (ppdu_desc->frame_type == CDP_PPDU_FTYPE_CTRL) { 4085 ppdu_desc->frame_ctrl = 4086 ppdu_desc->user[i].frame_ctrl; 4087 break; 4088 } 4089 } 4090 } 4091 4092 if (ppdu_desc->frame_type == CDP_PPDU_FTYPE_DATA && 4093 ppdu_desc->delayed_ba) { 4094 qdf_assert_always(ppdu_desc->num_users <= ppdu_desc->max_users); 4095 4096 for (i = 0; i < ppdu_desc->num_users; i++) { 4097 struct cdp_delayed_tx_completion_ppdu_user *delay_ppdu; 4098 uint64_t start_tsf; 4099 uint64_t end_tsf; 4100 uint32_t ppdu_id; 4101 struct dp_mon_peer *mon_peer; 4102 4103 ppdu_id = ppdu_desc->ppdu_id; 4104 peer = dp_peer_get_ref_by_id 4105 (pdev->soc, ppdu_desc->user[i].peer_id, 4106 DP_MOD_ID_TX_PPDU_STATS); 4107 /** 4108 * This check is to make sure peer is not deleted 4109 * after processing the TLVs. 4110 */ 4111 if (!peer) 4112 continue; 4113 4114 if (!peer->monitor_peer) { 4115 dp_peer_unref_delete(peer, 4116 DP_MOD_ID_TX_PPDU_STATS); 4117 continue; 4118 } 4119 4120 mon_peer = peer->monitor_peer; 4121 delay_ppdu = &mon_peer->delayed_ba_ppdu_stats; 4122 start_tsf = ppdu_desc->ppdu_start_timestamp; 4123 end_tsf = ppdu_desc->ppdu_end_timestamp; 4124 /** 4125 * save delayed ba user info 4126 */ 4127 if (ppdu_desc->user[i].delayed_ba) { 4128 dp_peer_copy_delay_stats(peer, 4129 &ppdu_desc->user[i], 4130 ppdu_id); 4131 mon_peer->last_delayed_ba_ppduid = ppdu_id; 4132 delay_ppdu->ppdu_start_timestamp = start_tsf; 4133 delay_ppdu->ppdu_end_timestamp = end_tsf; 4134 } 4135 ppdu_desc->user[i].peer_last_delayed_ba = 4136 mon_peer->last_delayed_ba; 4137 4138 dp_peer_unref_delete(peer, DP_MOD_ID_TX_PPDU_STATS); 4139 4140 if (ppdu_desc->user[i].delayed_ba && 4141 !ppdu_desc->user[i].debug_copied) { 4142 QDF_TRACE(QDF_MODULE_ID_TXRX, 4143 QDF_TRACE_LEVEL_INFO_MED, 4144 "%s: %d ppdu_id[%d] bar_ppdu_id[%d] num_users[%d] usr[%d] htt_frame_type[%d]\n", 4145 __func__, __LINE__, 4146 ppdu_desc->ppdu_id, 4147 ppdu_desc->bar_ppdu_id, 4148 ppdu_desc->num_users, 4149 i, 4150 ppdu_desc->htt_frame_type); 4151 } 4152 } 4153 } 4154 4155 /* 4156 * when frame type is BAR and STATS_COMMON_TLV is set 4157 * copy the store peer delayed info to BAR status 4158 */ 4159 if (ppdu_desc->frame_type == CDP_PPDU_FTYPE_BAR) { 4160 for (i = 0; i < ppdu_desc->bar_num_users; i++) { 4161 struct cdp_delayed_tx_completion_ppdu_user *delay_ppdu; 4162 uint64_t start_tsf; 4163 uint64_t end_tsf; 4164 struct dp_mon_peer *mon_peer; 4165 4166 peer = dp_peer_get_ref_by_id 4167 (pdev->soc, 4168 ppdu_desc->user[i].peer_id, 4169 DP_MOD_ID_TX_PPDU_STATS); 4170 /** 4171 * This check is to make sure peer is not deleted 4172 * after processing the TLVs. 4173 */ 4174 if (!peer) 4175 continue; 4176 4177 if (!peer->monitor_peer) { 4178 dp_peer_unref_delete(peer, 4179 DP_MOD_ID_TX_PPDU_STATS); 4180 continue; 4181 } 4182 4183 mon_peer = peer->monitor_peer; 4184 if (ppdu_desc->user[i].completion_status != 4185 HTT_PPDU_STATS_USER_STATUS_OK) { 4186 dp_peer_unref_delete(peer, 4187 DP_MOD_ID_TX_PPDU_STATS); 4188 continue; 4189 } 4190 4191 delay_ppdu = &mon_peer->delayed_ba_ppdu_stats; 4192 start_tsf = delay_ppdu->ppdu_start_timestamp; 4193 end_tsf = delay_ppdu->ppdu_end_timestamp; 4194 4195 if (mon_peer->last_delayed_ba) { 4196 dp_peer_copy_stats_to_bar(peer, 4197 &ppdu_desc->user[i]); 4198 ppdu_desc->ppdu_id = 4199 mon_peer->last_delayed_ba_ppduid; 4200 ppdu_desc->ppdu_start_timestamp = start_tsf; 4201 ppdu_desc->ppdu_end_timestamp = end_tsf; 4202 } 4203 ppdu_desc->user[i].peer_last_delayed_ba = 4204 mon_peer->last_delayed_ba; 4205 dp_peer_unref_delete(peer, DP_MOD_ID_TX_PPDU_STATS); 4206 } 4207 } 4208 4209 TAILQ_REMOVE(&mon_pdev->ppdu_info_list, ppdu_info, ppdu_info_list_elem); 4210 mon_pdev->list_depth--; 4211 TAILQ_INSERT_TAIL(&mon_pdev->sched_comp_ppdu_list, ppdu_info, 4212 ppdu_info_list_elem); 4213 mon_pdev->sched_comp_list_depth++; 4214 } 4215 4216 /** 4217 * dp_validate_fix_ppdu_tlv(): Function to validate the length of PPDU 4218 * 4219 * If the TLV length sent as part of PPDU TLV is less that expected size i.e 4220 * size of corresponding data structure, pad the remaining bytes with zeros 4221 * and continue processing the TLVs 4222 * 4223 * @pdev: DP pdev handle 4224 * @tag_buf: TLV buffer 4225 * @tlv_expected_size: Expected size of Tag 4226 * @tlv_len: TLV length received from FW 4227 * 4228 * Return: Pointer to updated TLV 4229 */ 4230 static inline uint32_t *dp_validate_fix_ppdu_tlv(struct dp_pdev *pdev, 4231 uint32_t *tag_buf, 4232 uint16_t tlv_expected_size, 4233 uint16_t tlv_len) 4234 { 4235 uint32_t *tlv_desc = tag_buf; 4236 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 4237 4238 qdf_assert_always(tlv_len != 0); 4239 4240 if (tlv_len < tlv_expected_size) { 4241 qdf_mem_zero(mon_pdev->ppdu_tlv_buf, tlv_expected_size); 4242 qdf_mem_copy(mon_pdev->ppdu_tlv_buf, tag_buf, tlv_len); 4243 tlv_desc = mon_pdev->ppdu_tlv_buf; 4244 } 4245 4246 return tlv_desc; 4247 } 4248 4249 /** 4250 * dp_process_ppdu_tag(): Function to process the PPDU TLVs 4251 * @pdev: DP pdev handle 4252 * @tag_buf: TLV buffer 4253 * @tlv_len: length of tlv 4254 * @ppdu_info: per ppdu tlv structure 4255 * 4256 * return: void 4257 */ 4258 static void dp_process_ppdu_tag(struct dp_pdev *pdev, 4259 uint32_t *tag_buf, 4260 uint32_t tlv_len, 4261 struct ppdu_info *ppdu_info) 4262 { 4263 uint32_t tlv_type = HTT_STATS_TLV_TAG_GET(*tag_buf); 4264 uint16_t tlv_expected_size; 4265 uint32_t *tlv_desc; 4266 4267 switch (tlv_type) { 4268 case HTT_PPDU_STATS_COMMON_TLV: 4269 tlv_expected_size = sizeof(htt_ppdu_stats_common_tlv); 4270 tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf, 4271 tlv_expected_size, tlv_len); 4272 dp_process_ppdu_stats_common_tlv(pdev, tlv_desc, ppdu_info); 4273 break; 4274 case HTT_PPDU_STATS_USR_COMMON_TLV: 4275 tlv_expected_size = sizeof(htt_ppdu_stats_user_common_tlv); 4276 tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf, 4277 tlv_expected_size, tlv_len); 4278 dp_process_ppdu_stats_user_common_tlv(pdev, tlv_desc, 4279 ppdu_info); 4280 break; 4281 case HTT_PPDU_STATS_USR_RATE_TLV: 4282 tlv_expected_size = sizeof(htt_ppdu_stats_user_rate_tlv); 4283 tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf, 4284 tlv_expected_size, tlv_len); 4285 dp_process_ppdu_stats_user_rate_tlv(pdev, tlv_desc, 4286 ppdu_info); 4287 break; 4288 case HTT_PPDU_STATS_USR_MPDU_ENQ_BITMAP_64_TLV: 4289 tlv_expected_size = 4290 sizeof(htt_ppdu_stats_enq_mpdu_bitmap_64_tlv); 4291 tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf, 4292 tlv_expected_size, tlv_len); 4293 dp_process_ppdu_stats_enq_mpdu_bitmap_64_tlv( 4294 pdev, tlv_desc, ppdu_info); 4295 break; 4296 case HTT_PPDU_STATS_USR_MPDU_ENQ_BITMAP_256_TLV: 4297 tlv_expected_size = 4298 sizeof(htt_ppdu_stats_enq_mpdu_bitmap_256_tlv); 4299 tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf, 4300 tlv_expected_size, tlv_len); 4301 dp_process_ppdu_stats_enq_mpdu_bitmap_256_tlv( 4302 pdev, tlv_desc, ppdu_info); 4303 break; 4304 case HTT_PPDU_STATS_USR_COMPLTN_COMMON_TLV: 4305 tlv_expected_size = 4306 sizeof(htt_ppdu_stats_user_cmpltn_common_tlv); 4307 tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf, 4308 tlv_expected_size, tlv_len); 4309 dp_process_ppdu_stats_user_cmpltn_common_tlv( 4310 pdev, tlv_desc, ppdu_info); 4311 break; 4312 case HTT_PPDU_STATS_USR_COMPLTN_BA_BITMAP_64_TLV: 4313 tlv_expected_size = 4314 sizeof(htt_ppdu_stats_user_compltn_ba_bitmap_64_tlv); 4315 tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf, 4316 tlv_expected_size, tlv_len); 4317 dp_process_ppdu_stats_user_compltn_ba_bitmap_64_tlv( 4318 pdev, tlv_desc, ppdu_info); 4319 break; 4320 case HTT_PPDU_STATS_USR_COMPLTN_BA_BITMAP_256_TLV: 4321 tlv_expected_size = 4322 sizeof(htt_ppdu_stats_user_compltn_ba_bitmap_256_tlv); 4323 tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf, 4324 tlv_expected_size, tlv_len); 4325 dp_process_ppdu_stats_user_compltn_ba_bitmap_256_tlv( 4326 pdev, tlv_desc, ppdu_info); 4327 break; 4328 case HTT_PPDU_STATS_USR_COMPLTN_ACK_BA_STATUS_TLV: 4329 tlv_expected_size = 4330 sizeof(htt_ppdu_stats_user_compltn_ack_ba_status_tlv); 4331 tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf, 4332 tlv_expected_size, tlv_len); 4333 dp_process_ppdu_stats_user_compltn_ack_ba_status_tlv( 4334 pdev, tlv_desc, ppdu_info); 4335 break; 4336 case HTT_PPDU_STATS_USR_COMMON_ARRAY_TLV: 4337 tlv_expected_size = 4338 sizeof(htt_ppdu_stats_usr_common_array_tlv_v); 4339 tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf, 4340 tlv_expected_size, tlv_len); 4341 dp_process_ppdu_stats_user_common_array_tlv( 4342 pdev, tlv_desc, ppdu_info); 4343 break; 4344 case HTT_PPDU_STATS_USR_COMPLTN_FLUSH_TLV: 4345 tlv_expected_size = sizeof(htt_ppdu_stats_flush_tlv); 4346 tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf, 4347 tlv_expected_size, tlv_len); 4348 dp_process_ppdu_stats_user_compltn_flush_tlv(pdev, tlv_desc, 4349 ppdu_info); 4350 break; 4351 case HTT_PPDU_STATS_SCH_CMD_STATUS_TLV: 4352 dp_process_ppdu_stats_sch_cmd_status_tlv(pdev, ppdu_info); 4353 break; 4354 default: 4355 break; 4356 } 4357 } 4358 4359 #ifdef WLAN_TELEMETRY_STATS_SUPPORT 4360 static inline 4361 void dp_ppdu_desc_user_airtime_consumption_update( 4362 struct dp_peer *peer, 4363 struct cdp_tx_completion_ppdu_user *user) 4364 { 4365 struct dp_mon_peer *mon_peer = NULL; 4366 uint8_t ac = 0; 4367 4368 mon_peer = peer->monitor_peer; 4369 if (qdf_unlikely(!mon_peer)) 4370 return; 4371 4372 ac = TID_TO_WME_AC(user->tid); 4373 DP_STATS_INC(mon_peer, airtime_consumption[ac].consumption, 4374 user->phy_tx_time_us); 4375 } 4376 #else 4377 static inline 4378 void dp_ppdu_desc_user_airtime_consumption_update( 4379 struct dp_peer *peer, 4380 struct cdp_tx_completion_ppdu_user *user) 4381 { } 4382 #endif 4383 4384 #if defined(WLAN_ATF_ENABLE) || defined(WLAN_TELEMETRY_STATS_SUPPORT) 4385 static void 4386 dp_ppdu_desc_user_phy_tx_time_update(struct dp_pdev *pdev, 4387 struct dp_peer *peer, 4388 struct cdp_tx_completion_ppdu *ppdu_desc, 4389 struct cdp_tx_completion_ppdu_user *user) 4390 { 4391 uint32_t nss_ru_width_sum = 0; 4392 struct dp_mon_peer *mon_peer = NULL; 4393 4394 if (!pdev || !ppdu_desc || !user || !peer) 4395 return; 4396 4397 if (ppdu_desc->frame_type != CDP_PPDU_FTYPE_DATA) 4398 return; 4399 4400 mon_peer = peer->monitor_peer; 4401 if (qdf_unlikely(!mon_peer)) 4402 return; 4403 4404 nss_ru_width_sum = ppdu_desc->usr_nss_sum * ppdu_desc->usr_ru_tones_sum; 4405 if (!nss_ru_width_sum) 4406 nss_ru_width_sum = 1; 4407 4408 /** 4409 * For SU-MIMO PPDU phy Tx time is same for the single user. 4410 * For MU-MIMO phy Tx time is calculated per user as below 4411 * user phy tx time = 4412 * Entire PPDU duration * MU Ratio * OFDMA Ratio 4413 * MU Ratio = usr_nss / Sum_of_nss_of_all_users 4414 * OFDMA_ratio = usr_ru_width / Sum_of_ru_width_of_all_users 4415 * usr_ru_widt = ru_end – ru_start + 1 4416 */ 4417 if (ppdu_desc->htt_frame_type == HTT_STATS_FTYPE_TIDQ_DATA_SU) { 4418 user->phy_tx_time_us = ppdu_desc->phy_ppdu_tx_time_us; 4419 } else { 4420 user->phy_tx_time_us = (ppdu_desc->phy_ppdu_tx_time_us * 4421 user->nss * user->ru_tones) / nss_ru_width_sum; 4422 } 4423 4424 dp_ppdu_desc_user_airtime_consumption_update(peer, user); 4425 } 4426 #else 4427 static void 4428 dp_ppdu_desc_user_phy_tx_time_update(struct dp_pdev *pdev, 4429 struct dp_peer *peer, 4430 struct cdp_tx_completion_ppdu *ppdu_desc, 4431 struct cdp_tx_completion_ppdu_user *user) 4432 { 4433 } 4434 #endif 4435 4436 #ifdef WLAN_SUPPORT_CTRL_FRAME_STATS 4437 static void 4438 dp_tx_ctrl_stats_update(struct dp_pdev *pdev, struct dp_peer *peer, 4439 struct cdp_tx_completion_ppdu_user *user) 4440 { 4441 struct dp_mon_peer *mon_peer = NULL; 4442 uint16_t fc = 0; 4443 4444 if (!pdev || !peer || !user) 4445 return; 4446 4447 mon_peer = peer->monitor_peer; 4448 if (qdf_unlikely(!mon_peer)) 4449 return; 4450 4451 if (user->mprot_type) { 4452 DP_STATS_INCC(mon_peer, 4453 tx.rts_success, 1, user->rts_success); 4454 DP_STATS_INCC(mon_peer, 4455 tx.rts_failure, 1, user->rts_failure); 4456 } 4457 fc = user->frame_ctrl; 4458 if ((qdf_cpu_to_le16(fc) & QDF_IEEE80211_FC0_TYPE_MASK) == 4459 QDF_IEEE80211_FC0_TYPE_CTL) { 4460 if ((qdf_cpu_to_le16(fc) & QDF_IEEE80211_FC0_SUBTYPE_MASK) == 4461 QDF_IEEE80211_FC0_SUBTYPE_VHT_NDP_AN) 4462 DP_STATS_INC(mon_peer, tx.ndpa_cnt, 1); 4463 if ((qdf_cpu_to_le16(fc) & QDF_IEEE80211_FC0_SUBTYPE_MASK) == 4464 QDF_IEEE80211_FC0_SUBTYPE_BAR) 4465 DP_STATS_INC(mon_peer, tx.bar_cnt, 1); 4466 } 4467 } 4468 #else 4469 static void 4470 dp_tx_ctrl_stats_update(struct dp_pdev *pdev, struct dp_peer *peer, 4471 struct cdp_tx_completion_ppdu_user *user) 4472 { 4473 } 4474 #endif /* WLAN_SUPPORT_CTRL_FRAME_STATS */ 4475 4476 /** 4477 * dp_ppdu_desc_user_stats_update(): Function to update TX user stats 4478 * @pdev: DP pdev handle 4479 * @ppdu_info: per PPDU TLV descriptor 4480 * 4481 * return: void 4482 */ 4483 void 4484 dp_ppdu_desc_user_stats_update(struct dp_pdev *pdev, 4485 struct ppdu_info *ppdu_info) 4486 { 4487 struct cdp_tx_completion_ppdu *ppdu_desc = NULL; 4488 struct dp_peer *peer = NULL; 4489 uint32_t tlv_bitmap_expected; 4490 uint32_t tlv_bitmap_default; 4491 uint16_t i; 4492 uint32_t num_users; 4493 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 4494 4495 ppdu_desc = (struct cdp_tx_completion_ppdu *) 4496 qdf_nbuf_data(ppdu_info->nbuf); 4497 4498 if (ppdu_desc->frame_type != CDP_PPDU_FTYPE_BAR) 4499 ppdu_desc->ppdu_id = ppdu_info->ppdu_id; 4500 4501 tlv_bitmap_expected = HTT_PPDU_DEFAULT_TLV_BITMAP; 4502 if (mon_pdev->tx_sniffer_enable || mon_pdev->mcopy_mode || 4503 mon_pdev->tx_capture_enabled) { 4504 if (ppdu_info->is_ampdu) 4505 tlv_bitmap_expected = 4506 dp_htt_get_ppdu_sniffer_ampdu_tlv_bitmap( 4507 ppdu_info->tlv_bitmap); 4508 } 4509 4510 tlv_bitmap_default = tlv_bitmap_expected; 4511 4512 if (ppdu_desc->frame_type == CDP_PPDU_FTYPE_BAR) { 4513 num_users = ppdu_desc->bar_num_users; 4514 ppdu_desc->num_users = ppdu_desc->bar_num_users; 4515 } else { 4516 num_users = ppdu_desc->num_users; 4517 } 4518 qdf_assert_always(ppdu_desc->num_users <= ppdu_desc->max_users); 4519 4520 for (i = 0; i < num_users; i++) { 4521 ppdu_desc->num_mpdu += ppdu_desc->user[i].num_mpdu; 4522 ppdu_desc->num_msdu += ppdu_desc->user[i].num_msdu; 4523 4524 peer = dp_peer_get_ref_by_id(pdev->soc, 4525 ppdu_desc->user[i].peer_id, 4526 DP_MOD_ID_TX_PPDU_STATS); 4527 /** 4528 * This check is to make sure peer is not deleted 4529 * after processing the TLVs. 4530 */ 4531 if (!peer) 4532 continue; 4533 4534 ppdu_desc->user[i].is_bss_peer = peer->bss_peer; 4535 4536 dp_ppdu_desc_user_phy_tx_time_update(pdev, peer, ppdu_desc, 4537 &ppdu_desc->user[i]); 4538 4539 dp_tx_ctrl_stats_update(pdev, peer, &ppdu_desc->user[i]); 4540 4541 /* 4542 * different frame like DATA, BAR or CTRL has different 4543 * tlv bitmap expected. Apart from ACK_BA_STATUS TLV, we 4544 * receive other tlv in-order/sequential from fw. 4545 * Since ACK_BA_STATUS TLV come from Hardware it is 4546 * asynchronous So we need to depend on some tlv to confirm 4547 * all tlv is received for a ppdu. 4548 * So we depend on both SCHED_CMD_STATUS_TLV and 4549 * ACK_BA_STATUS_TLV. for failure packet we won't get 4550 * ACK_BA_STATUS_TLV. 4551 */ 4552 if (!(ppdu_info->tlv_bitmap & 4553 (1 << HTT_PPDU_STATS_SCH_CMD_STATUS_TLV)) || 4554 (!(ppdu_info->tlv_bitmap & 4555 (1 << HTT_PPDU_STATS_USR_COMPLTN_ACK_BA_STATUS_TLV)) && 4556 (ppdu_desc->user[i].completion_status == 4557 HTT_PPDU_STATS_USER_STATUS_OK))) { 4558 dp_peer_unref_delete(peer, DP_MOD_ID_TX_PPDU_STATS); 4559 continue; 4560 } 4561 4562 /** 4563 * Update tx stats for data frames having Qos as well as 4564 * non-Qos data tid 4565 */ 4566 4567 if ((ppdu_desc->user[i].tid < CDP_DATA_TID_MAX || 4568 (ppdu_desc->user[i].tid == CDP_DATA_NON_QOS_TID) || 4569 (ppdu_desc->htt_frame_type == 4570 HTT_STATS_FTYPE_SGEN_QOS_NULL) || 4571 ((ppdu_desc->frame_type == CDP_PPDU_FTYPE_BAR) && 4572 (ppdu_desc->num_mpdu > 1))) && 4573 (ppdu_desc->frame_type != CDP_PPDU_FTYPE_CTRL)) { 4574 dp_tx_stats_update(pdev, peer, 4575 &ppdu_desc->user[i], 4576 ppdu_desc->ack_rssi); 4577 } 4578 4579 dp_peer_unref_delete(peer, DP_MOD_ID_TX_PPDU_STATS); 4580 tlv_bitmap_expected = tlv_bitmap_default; 4581 } 4582 } 4583 4584 #if !defined(WLAN_TX_PKT_CAPTURE_ENH) || defined(QCA_MONITOR_2_0_SUPPORT) 4585 /* 4586 * dp_tx_ppdu_desc_notify() - Notify to upper layer about PPDU via WDI 4587 * 4588 * @pdev: Datapath pdev handle 4589 * @nbuf: Buffer to be delivered to upper layer 4590 * 4591 * Return: void 4592 */ 4593 static void dp_tx_ppdu_desc_notify(struct dp_pdev *pdev, qdf_nbuf_t nbuf) 4594 { 4595 struct dp_soc *soc = pdev->soc; 4596 struct dp_mon_ops *mon_ops = NULL; 4597 4598 mon_ops = dp_mon_ops_get(soc); 4599 if (mon_ops && mon_ops->mon_ppdu_desc_notify) 4600 mon_ops->mon_ppdu_desc_notify(pdev, nbuf); 4601 else 4602 qdf_nbuf_free(nbuf); 4603 } 4604 4605 void dp_ppdu_desc_deliver(struct dp_pdev *pdev, 4606 struct ppdu_info *ppdu_info) 4607 { 4608 struct ppdu_info *s_ppdu_info = NULL; 4609 struct ppdu_info *ppdu_info_next = NULL; 4610 struct cdp_tx_completion_ppdu *ppdu_desc = NULL; 4611 qdf_nbuf_t nbuf; 4612 uint32_t time_delta = 0; 4613 bool starved = 0; 4614 bool matched = 0; 4615 bool recv_ack_ba_done = 0; 4616 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 4617 4618 if (ppdu_info->tlv_bitmap & 4619 (1 << HTT_PPDU_STATS_USR_COMPLTN_ACK_BA_STATUS_TLV) && 4620 ppdu_info->done) 4621 recv_ack_ba_done = 1; 4622 4623 mon_pdev->last_sched_cmdid = ppdu_info->sched_cmdid; 4624 4625 s_ppdu_info = TAILQ_FIRST(&mon_pdev->sched_comp_ppdu_list); 4626 4627 TAILQ_FOREACH_SAFE(s_ppdu_info, &mon_pdev->sched_comp_ppdu_list, 4628 ppdu_info_list_elem, ppdu_info_next) { 4629 if (s_ppdu_info->tsf_l32 > ppdu_info->tsf_l32) 4630 time_delta = (MAX_TSF_32 - s_ppdu_info->tsf_l32) + 4631 ppdu_info->tsf_l32; 4632 else 4633 time_delta = ppdu_info->tsf_l32 - s_ppdu_info->tsf_l32; 4634 4635 if (!s_ppdu_info->done && !recv_ack_ba_done) { 4636 if (time_delta < MAX_SCHED_STARVE) { 4637 dp_mon_info("pdev[%d] ppdu_id[%d] sched_cmdid[%d] TLV_B[0x%x] TSF[%u] D[%d]", 4638 pdev->pdev_id, 4639 s_ppdu_info->ppdu_id, 4640 s_ppdu_info->sched_cmdid, 4641 s_ppdu_info->tlv_bitmap, 4642 s_ppdu_info->tsf_l32, 4643 s_ppdu_info->done); 4644 break; 4645 } 4646 starved = 1; 4647 } 4648 4649 mon_pdev->delivered_sched_cmdid = s_ppdu_info->sched_cmdid; 4650 TAILQ_REMOVE(&mon_pdev->sched_comp_ppdu_list, s_ppdu_info, 4651 ppdu_info_list_elem); 4652 mon_pdev->sched_comp_list_depth--; 4653 4654 nbuf = s_ppdu_info->nbuf; 4655 qdf_assert_always(nbuf); 4656 ppdu_desc = (struct cdp_tx_completion_ppdu *) 4657 qdf_nbuf_data(nbuf); 4658 ppdu_desc->tlv_bitmap = s_ppdu_info->tlv_bitmap; 4659 4660 if (starved) { 4661 dp_mon_info("ppdu starved fc[0x%x] h_ftype[%d] tlv_bitmap[0x%x] cs[%d]\n", 4662 ppdu_desc->frame_ctrl, 4663 ppdu_desc->htt_frame_type, 4664 ppdu_desc->tlv_bitmap, 4665 ppdu_desc->user[0].completion_status); 4666 starved = 0; 4667 } 4668 4669 if (ppdu_info->ppdu_id == s_ppdu_info->ppdu_id && 4670 ppdu_info->sched_cmdid == s_ppdu_info->sched_cmdid) 4671 matched = 1; 4672 4673 dp_ppdu_desc_user_stats_update(pdev, s_ppdu_info); 4674 4675 qdf_mem_free(s_ppdu_info); 4676 4677 dp_tx_ppdu_desc_notify(pdev, nbuf); 4678 4679 if (matched) 4680 break; 4681 } 4682 } 4683 #endif 4684 4685 /* 4686 * dp_tx_ppdu_desc_deliver() - Deliver PPDU desc to upper layer 4687 * 4688 * @pdev: Datapath pdev handle 4689 * @ppdu_info: per PPDU TLV descriptor 4690 * 4691 * Return: void 4692 */ 4693 static void dp_tx_ppdu_desc_deliver(struct dp_pdev *pdev, 4694 struct ppdu_info *ppdu_info) 4695 { 4696 struct dp_soc *soc = pdev->soc; 4697 struct dp_mon_ops *mon_ops = NULL; 4698 4699 mon_ops = dp_mon_ops_get(soc); 4700 4701 if (mon_ops && mon_ops->mon_ppdu_desc_deliver) { 4702 mon_ops->mon_ppdu_desc_deliver(pdev, ppdu_info); 4703 } else { 4704 qdf_nbuf_free(ppdu_info->nbuf); 4705 ppdu_info->nbuf = NULL; 4706 qdf_mem_free(ppdu_info); 4707 } 4708 } 4709 4710 /** 4711 * dp_get_ppdu_desc(): Function to allocate new PPDU status 4712 * desc for new ppdu id 4713 * @pdev: DP pdev handle 4714 * @ppdu_id: PPDU unique identifier 4715 * @tlv_type: TLV type received 4716 * @tsf_l32: timestamp received along with ppdu stats indication header 4717 * @max_users: Maximum user for that particular ppdu 4718 * 4719 * return: ppdu_info per ppdu tlv structure 4720 */ 4721 static 4722 struct ppdu_info *dp_get_ppdu_desc(struct dp_pdev *pdev, uint32_t ppdu_id, 4723 uint8_t tlv_type, uint32_t tsf_l32, 4724 uint8_t max_users) 4725 { 4726 struct ppdu_info *ppdu_info = NULL; 4727 struct ppdu_info *s_ppdu_info = NULL; 4728 struct ppdu_info *ppdu_info_next = NULL; 4729 struct cdp_tx_completion_ppdu *ppdu_desc = NULL; 4730 uint32_t size = 0; 4731 struct cdp_tx_completion_ppdu *tmp_ppdu_desc = NULL; 4732 struct cdp_tx_completion_ppdu_user *tmp_user; 4733 uint32_t time_delta; 4734 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 4735 4736 /* 4737 * Find ppdu_id node exists or not 4738 */ 4739 TAILQ_FOREACH_SAFE(ppdu_info, &mon_pdev->ppdu_info_list, 4740 ppdu_info_list_elem, ppdu_info_next) { 4741 if (ppdu_info && (ppdu_info->ppdu_id == ppdu_id)) { 4742 if (ppdu_info->tsf_l32 > tsf_l32) 4743 time_delta = (MAX_TSF_32 - 4744 ppdu_info->tsf_l32) + tsf_l32; 4745 else 4746 time_delta = tsf_l32 - ppdu_info->tsf_l32; 4747 4748 if (time_delta > WRAP_DROP_TSF_DELTA) { 4749 TAILQ_REMOVE(&mon_pdev->ppdu_info_list, 4750 ppdu_info, ppdu_info_list_elem); 4751 mon_pdev->list_depth--; 4752 pdev->stats.ppdu_wrap_drop++; 4753 tmp_ppdu_desc = 4754 (struct cdp_tx_completion_ppdu *) 4755 qdf_nbuf_data(ppdu_info->nbuf); 4756 tmp_user = &tmp_ppdu_desc->user[0]; 4757 dp_htt_tx_stats_info("S_PID [%d] S_TSF[%u] TLV_BITMAP[0x%x] [CMPLTN - %d ACK_BA - %d] CS[%d] - R_PID[%d] R_TSF[%u] R_TLV_TAG[0x%x]\n", 4758 ppdu_info->ppdu_id, 4759 ppdu_info->tsf_l32, 4760 ppdu_info->tlv_bitmap, 4761 tmp_user->completion_status, 4762 ppdu_info->compltn_common_tlv, 4763 ppdu_info->ack_ba_tlv, 4764 ppdu_id, tsf_l32, 4765 tlv_type); 4766 qdf_nbuf_free(ppdu_info->nbuf); 4767 ppdu_info->nbuf = NULL; 4768 qdf_mem_free(ppdu_info); 4769 } else { 4770 break; 4771 } 4772 } 4773 } 4774 4775 /* 4776 * check if it is ack ba tlv and if it is not there in ppdu info 4777 * list then check it in sched completion ppdu list 4778 */ 4779 if (!ppdu_info && 4780 tlv_type == HTT_PPDU_STATS_USR_COMPLTN_ACK_BA_STATUS_TLV) { 4781 TAILQ_FOREACH(s_ppdu_info, 4782 &mon_pdev->sched_comp_ppdu_list, 4783 ppdu_info_list_elem) { 4784 if (s_ppdu_info && (s_ppdu_info->ppdu_id == ppdu_id)) { 4785 if (s_ppdu_info->tsf_l32 > tsf_l32) 4786 time_delta = (MAX_TSF_32 - 4787 s_ppdu_info->tsf_l32) + 4788 tsf_l32; 4789 else 4790 time_delta = tsf_l32 - 4791 s_ppdu_info->tsf_l32; 4792 if (time_delta < WRAP_DROP_TSF_DELTA) { 4793 ppdu_info = s_ppdu_info; 4794 break; 4795 } 4796 } else { 4797 /* 4798 * ACK BA STATUS TLV comes sequential order 4799 * if we received ack ba status tlv for second 4800 * ppdu and first ppdu is still waiting for 4801 * ACK BA STATUS TLV. Based on fw comment 4802 * we won't receive it tlv later. So we can 4803 * set ppdu info done. 4804 */ 4805 if (s_ppdu_info) 4806 s_ppdu_info->done = 1; 4807 } 4808 } 4809 } 4810 4811 if (ppdu_info) { 4812 if (ppdu_info->tlv_bitmap & (1 << tlv_type)) { 4813 /** 4814 * if we get tlv_type that is already been processed 4815 * for ppdu, that means we got a new ppdu with same 4816 * ppdu id. Hence Flush the older ppdu 4817 * for MUMIMO and OFDMA, In a PPDU we have 4818 * multiple user with same tlv types. tlv bitmap is 4819 * used to check whether SU or MU_MIMO/OFDMA 4820 */ 4821 if (!(ppdu_info->tlv_bitmap & 4822 (1 << HTT_PPDU_STATS_SCH_CMD_STATUS_TLV))) 4823 return ppdu_info; 4824 4825 ppdu_desc = (struct cdp_tx_completion_ppdu *) 4826 qdf_nbuf_data(ppdu_info->nbuf); 4827 4828 /** 4829 * apart from ACK BA STATUS TLV rest all comes in order 4830 * so if tlv type not ACK BA STATUS TLV we can deliver 4831 * ppdu_info 4832 */ 4833 if ((tlv_type == 4834 HTT_PPDU_STATS_USR_COMPLTN_ACK_BA_STATUS_TLV) && 4835 ((ppdu_desc->htt_frame_type == 4836 HTT_STATS_FTYPE_SGEN_MU_BAR) || 4837 (ppdu_desc->htt_frame_type == 4838 HTT_STATS_FTYPE_SGEN_BE_MU_BAR))) 4839 return ppdu_info; 4840 4841 dp_tx_ppdu_desc_deliver(pdev, ppdu_info); 4842 } else { 4843 return ppdu_info; 4844 } 4845 } 4846 4847 /** 4848 * Flush the head ppdu descriptor if ppdu desc list reaches max 4849 * threshold 4850 */ 4851 if (mon_pdev->list_depth > HTT_PPDU_DESC_MAX_DEPTH) { 4852 ppdu_info = TAILQ_FIRST(&mon_pdev->ppdu_info_list); 4853 TAILQ_REMOVE(&mon_pdev->ppdu_info_list, 4854 ppdu_info, ppdu_info_list_elem); 4855 mon_pdev->list_depth--; 4856 pdev->stats.ppdu_drop++; 4857 qdf_nbuf_free(ppdu_info->nbuf); 4858 ppdu_info->nbuf = NULL; 4859 qdf_mem_free(ppdu_info); 4860 } 4861 4862 size = sizeof(struct cdp_tx_completion_ppdu) + 4863 (max_users * sizeof(struct cdp_tx_completion_ppdu_user)); 4864 4865 /* 4866 * Allocate new ppdu_info node 4867 */ 4868 ppdu_info = qdf_mem_malloc(sizeof(struct ppdu_info)); 4869 if (!ppdu_info) 4870 return NULL; 4871 4872 ppdu_info->nbuf = qdf_nbuf_alloc(pdev->soc->osdev, size, 4873 0, 4, TRUE); 4874 if (!ppdu_info->nbuf) { 4875 qdf_mem_free(ppdu_info); 4876 return NULL; 4877 } 4878 4879 ppdu_info->ppdu_desc = 4880 (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 4881 qdf_mem_zero(qdf_nbuf_data(ppdu_info->nbuf), size); 4882 4883 if (!qdf_nbuf_put_tail(ppdu_info->nbuf, size)) { 4884 dp_mon_err("No tailroom for HTT PPDU"); 4885 qdf_nbuf_free(ppdu_info->nbuf); 4886 ppdu_info->nbuf = NULL; 4887 ppdu_info->last_user = 0; 4888 qdf_mem_free(ppdu_info); 4889 return NULL; 4890 } 4891 4892 ppdu_info->ppdu_desc->max_users = max_users; 4893 ppdu_info->tsf_l32 = tsf_l32; 4894 /** 4895 * No lock is needed because all PPDU TLVs are processed in 4896 * same context and this list is updated in same context 4897 */ 4898 TAILQ_INSERT_TAIL(&mon_pdev->ppdu_info_list, ppdu_info, 4899 ppdu_info_list_elem); 4900 mon_pdev->list_depth++; 4901 return ppdu_info; 4902 } 4903 4904 /** 4905 * dp_htt_process_tlv(): Function to process each PPDU TLVs 4906 * @pdev: DP pdev handle 4907 * @htt_t2h_msg: HTT target to host message 4908 * 4909 * return: ppdu_info per ppdu tlv structure 4910 */ 4911 static struct ppdu_info *dp_htt_process_tlv(struct dp_pdev *pdev, 4912 qdf_nbuf_t htt_t2h_msg) 4913 { 4914 uint32_t length; 4915 uint32_t ppdu_id; 4916 uint8_t tlv_type; 4917 uint32_t tlv_length, tlv_bitmap_expected; 4918 uint8_t *tlv_buf; 4919 struct ppdu_info *ppdu_info = NULL; 4920 struct cdp_tx_completion_ppdu *ppdu_desc = NULL; 4921 uint8_t max_users = CDP_MU_MAX_USERS; 4922 uint32_t tsf_l32; 4923 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 4924 4925 uint32_t *msg_word = (uint32_t *)qdf_nbuf_data(htt_t2h_msg); 4926 4927 length = HTT_T2H_PPDU_STATS_PAYLOAD_SIZE_GET(*msg_word); 4928 4929 msg_word = msg_word + 1; 4930 ppdu_id = HTT_T2H_PPDU_STATS_PPDU_ID_GET(*msg_word); 4931 4932 msg_word = msg_word + 1; 4933 tsf_l32 = (uint32_t)(*msg_word); 4934 4935 msg_word = msg_word + 2; 4936 while (length > 0) { 4937 tlv_buf = (uint8_t *)msg_word; 4938 tlv_type = HTT_STATS_TLV_TAG_GET(*msg_word); 4939 tlv_length = HTT_STATS_TLV_LENGTH_GET(*msg_word); 4940 if (qdf_likely(tlv_type < CDP_PPDU_STATS_MAX_TAG)) 4941 pdev->stats.ppdu_stats_counter[tlv_type]++; 4942 4943 if (tlv_length == 0) 4944 break; 4945 4946 tlv_length += HTT_TLV_HDR_LEN; 4947 4948 /** 4949 * Not allocating separate ppdu descriptor for MGMT Payload 4950 * TLV as this is sent as separate WDI indication and it 4951 * doesn't contain any ppdu information 4952 */ 4953 if (tlv_type == HTT_PPDU_STATS_TX_MGMTCTRL_PAYLOAD_TLV) { 4954 mon_pdev->mgmtctrl_frm_info.mgmt_buf = tlv_buf; 4955 mon_pdev->mgmtctrl_frm_info.ppdu_id = ppdu_id; 4956 mon_pdev->mgmtctrl_frm_info.mgmt_buf_len = 4957 HTT_PPDU_STATS_TX_MGMTCTRL_TLV_FRAME_LENGTH_GET 4958 (*(msg_word + 1)); 4959 msg_word = 4960 (uint32_t *)((uint8_t *)tlv_buf + tlv_length); 4961 length -= (tlv_length); 4962 continue; 4963 } 4964 4965 /* 4966 * retrieve max_users if it's USERS_INFO, 4967 * else, it's 1 for COMPLTN_FLUSH, 4968 * else, use CDP_MU_MAX_USERS 4969 */ 4970 if (tlv_type == HTT_PPDU_STATS_USERS_INFO_TLV) { 4971 max_users = 4972 HTT_PPDU_STATS_USERS_INFO_TLV_MAX_USERS_GET(*(msg_word + 1)); 4973 } else if (tlv_type == HTT_PPDU_STATS_USR_COMPLTN_FLUSH_TLV) { 4974 max_users = 1; 4975 } 4976 4977 ppdu_info = dp_get_ppdu_desc(pdev, ppdu_id, tlv_type, 4978 tsf_l32, max_users); 4979 if (!ppdu_info) 4980 return NULL; 4981 4982 ppdu_info->ppdu_id = ppdu_id; 4983 ppdu_info->tlv_bitmap |= (1 << tlv_type); 4984 4985 dp_process_ppdu_tag(pdev, msg_word, tlv_length, ppdu_info); 4986 4987 /** 4988 * Increment pdev level tlv count to monitor 4989 * missing TLVs 4990 */ 4991 mon_pdev->tlv_count++; 4992 ppdu_info->last_tlv_cnt = mon_pdev->tlv_count; 4993 msg_word = (uint32_t *)((uint8_t *)tlv_buf + tlv_length); 4994 length -= (tlv_length); 4995 } 4996 4997 if (!ppdu_info) 4998 return NULL; 4999 5000 mon_pdev->last_ppdu_id = ppdu_id; 5001 5002 tlv_bitmap_expected = HTT_PPDU_DEFAULT_TLV_BITMAP; 5003 5004 if (mon_pdev->tx_sniffer_enable || mon_pdev->mcopy_mode || 5005 mon_pdev->tx_capture_enabled) { 5006 if (ppdu_info->is_ampdu) 5007 tlv_bitmap_expected = 5008 dp_htt_get_ppdu_sniffer_ampdu_tlv_bitmap( 5009 ppdu_info->tlv_bitmap); 5010 } 5011 5012 ppdu_desc = ppdu_info->ppdu_desc; 5013 5014 if (!ppdu_desc) 5015 return NULL; 5016 5017 if (ppdu_desc->user[ppdu_desc->last_usr_index].completion_status != 5018 HTT_PPDU_STATS_USER_STATUS_OK) { 5019 tlv_bitmap_expected = tlv_bitmap_expected & 0xFF; 5020 } 5021 5022 /* 5023 * for frame type DATA and BAR, we update stats based on MSDU, 5024 * successful msdu and mpdu are populate from ACK BA STATUS TLV 5025 * which comes out of order. successful mpdu also populated from 5026 * COMPLTN COMMON TLV which comes in order. for every ppdu_info 5027 * we store successful mpdu from both tlv and compare before delivering 5028 * to make sure we received ACK BA STATUS TLV. For some self generated 5029 * frame we won't get ack ba status tlv so no need to wait for 5030 * ack ba status tlv. 5031 */ 5032 if (ppdu_desc->frame_type != CDP_PPDU_FTYPE_CTRL && 5033 ppdu_desc->htt_frame_type != HTT_STATS_FTYPE_SGEN_QOS_NULL) { 5034 /* 5035 * most of the time bar frame will have duplicate ack ba 5036 * status tlv 5037 */ 5038 if (ppdu_desc->frame_type == CDP_PPDU_FTYPE_BAR && 5039 (ppdu_info->compltn_common_tlv != ppdu_info->ack_ba_tlv)) 5040 return NULL; 5041 /* 5042 * For data frame, compltn common tlv should match ack ba status 5043 * tlv and completion status. Reason we are checking first user 5044 * for ofdma, completion seen at next MU BAR frm, for mimo 5045 * only for first user completion will be immediate. 5046 */ 5047 if (ppdu_desc->frame_type == CDP_PPDU_FTYPE_DATA && 5048 (ppdu_desc->user[0].completion_status == 0 && 5049 (ppdu_info->compltn_common_tlv != ppdu_info->ack_ba_tlv))) 5050 return NULL; 5051 } 5052 5053 /** 5054 * Once all the TLVs for a given PPDU has been processed, 5055 * return PPDU status to be delivered to higher layer. 5056 * tlv_bitmap_expected can't be available for different frame type. 5057 * But SCHED CMD STATS TLV is the last TLV from the FW for a ppdu. 5058 * apart from ACK BA TLV, FW sends other TLV in sequential order. 5059 * flush tlv comes separate. 5060 */ 5061 if ((ppdu_info->tlv_bitmap != 0 && 5062 (ppdu_info->tlv_bitmap & 5063 (1 << HTT_PPDU_STATS_SCH_CMD_STATUS_TLV))) || 5064 (ppdu_info->tlv_bitmap & 5065 (1 << HTT_PPDU_STATS_USR_COMPLTN_FLUSH_TLV))) { 5066 ppdu_info->done = 1; 5067 return ppdu_info; 5068 } 5069 5070 return NULL; 5071 } 5072 #endif /* QCA_ENHANCED_STATS_SUPPORT */ 5073 5074 #ifdef QCA_ENHANCED_STATS_SUPPORT 5075 /** 5076 * dp_tx_ppdu_stats_feat_enable_check() - Check if feature(s) is enabled to 5077 * consume stats received from FW via HTT 5078 * @pdev: Datapath pdev handle 5079 * 5080 * Return: void 5081 */ 5082 static bool dp_tx_ppdu_stats_feat_enable_check(struct dp_pdev *pdev) 5083 { 5084 struct dp_soc *soc = pdev->soc; 5085 struct dp_mon_ops *mon_ops = NULL; 5086 5087 mon_ops = dp_mon_ops_get(soc); 5088 if (mon_ops && mon_ops->mon_ppdu_stats_feat_enable_check) 5089 return mon_ops->mon_ppdu_stats_feat_enable_check(pdev); 5090 else 5091 return false; 5092 } 5093 #endif 5094 5095 #if defined(WDI_EVENT_ENABLE) 5096 #ifdef QCA_ENHANCED_STATS_SUPPORT 5097 /** 5098 * dp_txrx_ppdu_stats_handler() - Function to process HTT PPDU stats from FW 5099 * @soc: DP SOC handle 5100 * @pdev_id: pdev id 5101 * @htt_t2h_msg: HTT message nbuf 5102 * 5103 * return:void 5104 */ 5105 static bool dp_txrx_ppdu_stats_handler(struct dp_soc *soc, 5106 uint8_t pdev_id, qdf_nbuf_t htt_t2h_msg) 5107 { 5108 struct dp_pdev *pdev; 5109 struct ppdu_info *ppdu_info = NULL; 5110 bool free_buf = true; 5111 struct dp_mon_pdev *mon_pdev; 5112 5113 if (pdev_id >= MAX_PDEV_CNT) 5114 return true; 5115 5116 pdev = soc->pdev_list[pdev_id]; 5117 if (!pdev) 5118 return true; 5119 5120 mon_pdev = pdev->monitor_pdev; 5121 if (!mon_pdev) 5122 return true; 5123 5124 if (!dp_tx_ppdu_stats_feat_enable_check(pdev)) 5125 return free_buf; 5126 5127 qdf_spin_lock_bh(&mon_pdev->ppdu_stats_lock); 5128 ppdu_info = dp_htt_process_tlv(pdev, htt_t2h_msg); 5129 5130 if (mon_pdev->mgmtctrl_frm_info.mgmt_buf) { 5131 if (dp_process_ppdu_stats_tx_mgmtctrl_payload_tlv 5132 (pdev, htt_t2h_msg, mon_pdev->mgmtctrl_frm_info.ppdu_id) != 5133 QDF_STATUS_SUCCESS) 5134 free_buf = false; 5135 } 5136 5137 if (ppdu_info) 5138 dp_tx_ppdu_desc_deliver(pdev, ppdu_info); 5139 5140 mon_pdev->mgmtctrl_frm_info.mgmt_buf = NULL; 5141 mon_pdev->mgmtctrl_frm_info.mgmt_buf_len = 0; 5142 mon_pdev->mgmtctrl_frm_info.ppdu_id = 0; 5143 5144 qdf_spin_unlock_bh(&mon_pdev->ppdu_stats_lock); 5145 5146 return free_buf; 5147 } 5148 #elif (!defined(REMOVE_PKT_LOG)) 5149 static bool dp_txrx_ppdu_stats_handler(struct dp_soc *soc, 5150 uint8_t pdev_id, qdf_nbuf_t htt_t2h_msg) 5151 { 5152 return true; 5153 } 5154 #endif/* QCA_ENHANCED_STATS_SUPPORT */ 5155 #endif 5156 5157 #if defined(WDI_EVENT_ENABLE) &&\ 5158 (defined(QCA_ENHANCED_STATS_SUPPORT) || !defined(REMOVE_PKT_LOG)) 5159 /* 5160 * dp_ppdu_stats_ind_handler() - PPDU stats msg handler 5161 * @htt_soc: HTT SOC handle 5162 * @msg_word: Pointer to payload 5163 * @htt_t2h_msg: HTT msg nbuf 5164 * 5165 * Return: True if buffer should be freed by caller. 5166 */ 5167 bool 5168 dp_ppdu_stats_ind_handler(struct htt_soc *soc, 5169 uint32_t *msg_word, 5170 qdf_nbuf_t htt_t2h_msg) 5171 { 5172 u_int8_t pdev_id; 5173 u_int8_t target_pdev_id; 5174 bool free_buf; 5175 5176 target_pdev_id = HTT_T2H_PPDU_STATS_PDEV_ID_GET(*msg_word); 5177 pdev_id = dp_get_host_pdev_id_for_target_pdev_id(soc->dp_soc, 5178 target_pdev_id); 5179 dp_wdi_event_handler(WDI_EVENT_LITE_T2H, soc->dp_soc, 5180 htt_t2h_msg, HTT_INVALID_PEER, WDI_NO_VAL, 5181 pdev_id); 5182 5183 free_buf = dp_txrx_ppdu_stats_handler(soc->dp_soc, pdev_id, 5184 htt_t2h_msg); 5185 5186 return free_buf; 5187 } 5188 #endif 5189 5190 void 5191 dp_mon_set_bsscolor(struct dp_pdev *pdev, uint8_t bsscolor) 5192 { 5193 pdev->monitor_pdev->rx_mon_recv_status.bsscolor = bsscolor; 5194 } 5195 5196 bool dp_pdev_get_filter_ucast_data(struct cdp_pdev *pdev_handle) 5197 { 5198 struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; 5199 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 5200 5201 if ((mon_pdev->fp_data_filter & FILTER_DATA_UCAST) || 5202 (mon_pdev->mo_data_filter & FILTER_DATA_UCAST)) 5203 return true; 5204 5205 return false; 5206 } 5207 5208 bool dp_pdev_get_filter_mcast_data(struct cdp_pdev *pdev_handle) 5209 { 5210 struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; 5211 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 5212 5213 if ((mon_pdev->fp_data_filter & FILTER_DATA_MCAST) || 5214 (mon_pdev->mo_data_filter & FILTER_DATA_MCAST)) 5215 return true; 5216 5217 return false; 5218 } 5219 5220 bool dp_pdev_get_filter_non_data(struct cdp_pdev *pdev_handle) 5221 { 5222 struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; 5223 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 5224 5225 if ((mon_pdev->fp_mgmt_filter & FILTER_MGMT_ALL) || 5226 (mon_pdev->mo_mgmt_filter & FILTER_MGMT_ALL)) { 5227 if ((mon_pdev->fp_ctrl_filter & FILTER_CTRL_ALL) || 5228 (mon_pdev->mo_ctrl_filter & FILTER_CTRL_ALL)) { 5229 return true; 5230 } 5231 } 5232 5233 return false; 5234 } 5235 5236 QDF_STATUS dp_mon_soc_cfg_init(struct dp_soc *soc) 5237 { 5238 int target_type; 5239 struct dp_mon_soc *mon_soc = soc->monitor_soc; 5240 struct cdp_mon_ops *cdp_ops; 5241 5242 cdp_ops = dp_mon_cdp_ops_get(soc); 5243 target_type = hal_get_target_type(soc->hal_soc); 5244 switch (target_type) { 5245 case TARGET_TYPE_QCA6290: 5246 case TARGET_TYPE_QCA6390: 5247 case TARGET_TYPE_QCA6490: 5248 case TARGET_TYPE_QCA6750: 5249 case TARGET_TYPE_KIWI: 5250 case TARGET_TYPE_MANGO: 5251 /* do nothing */ 5252 break; 5253 case TARGET_TYPE_QCA8074: 5254 wlan_cfg_set_mon_delayed_replenish_entries(soc->wlan_cfg_ctx, 5255 MON_BUF_MIN_ENTRIES); 5256 break; 5257 case TARGET_TYPE_QCA8074V2: 5258 case TARGET_TYPE_QCA6018: 5259 case TARGET_TYPE_QCA9574: 5260 wlan_cfg_set_mon_delayed_replenish_entries(soc->wlan_cfg_ctx, 5261 MON_BUF_MIN_ENTRIES); 5262 mon_soc->hw_nac_monitor_support = 1; 5263 break; 5264 case TARGET_TYPE_QCN9000: 5265 wlan_cfg_set_mon_delayed_replenish_entries(soc->wlan_cfg_ctx, 5266 MON_BUF_MIN_ENTRIES); 5267 mon_soc->hw_nac_monitor_support = 1; 5268 if (cfg_get(soc->ctrl_psoc, CFG_DP_FULL_MON_MODE)) { 5269 if (cdp_ops && cdp_ops->config_full_mon_mode) 5270 cdp_ops->config_full_mon_mode((struct cdp_soc_t *)soc, 1); 5271 } 5272 break; 5273 case TARGET_TYPE_QCA5018: 5274 case TARGET_TYPE_QCN6122: 5275 case TARGET_TYPE_QCN9160: 5276 wlan_cfg_set_mon_delayed_replenish_entries(soc->wlan_cfg_ctx, 5277 MON_BUF_MIN_ENTRIES); 5278 mon_soc->hw_nac_monitor_support = 1; 5279 break; 5280 case TARGET_TYPE_QCN9224: 5281 case TARGET_TYPE_QCA5332: 5282 wlan_cfg_set_mon_delayed_replenish_entries(soc->wlan_cfg_ctx, 5283 MON_BUF_MIN_ENTRIES); 5284 mon_soc->hw_nac_monitor_support = 1; 5285 mon_soc->monitor_mode_v2 = 1; 5286 break; 5287 default: 5288 dp_mon_info("%s: Unknown tgt type %d\n", __func__, target_type); 5289 qdf_assert_always(0); 5290 break; 5291 } 5292 5293 dp_mon_info("hw_nac_monitor_support = %d", 5294 mon_soc->hw_nac_monitor_support); 5295 5296 return QDF_STATUS_SUCCESS; 5297 } 5298 5299 /** 5300 * dp_mon_pdev_per_target_config() - Target specific monitor pdev configuration 5301 * @pdev: PDEV handle [Should be valid] 5302 * 5303 * Return: None 5304 */ 5305 static void dp_mon_pdev_per_target_config(struct dp_pdev *pdev) 5306 { 5307 struct dp_soc *soc = pdev->soc; 5308 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 5309 int target_type; 5310 5311 target_type = hal_get_target_type(soc->hal_soc); 5312 switch (target_type) { 5313 case TARGET_TYPE_KIWI: 5314 case TARGET_TYPE_MANGO: 5315 mon_pdev->is_tlv_hdr_64_bit = true; 5316 break; 5317 default: 5318 mon_pdev->is_tlv_hdr_64_bit = false; 5319 break; 5320 } 5321 } 5322 5323 QDF_STATUS dp_mon_pdev_attach(struct dp_pdev *pdev) 5324 { 5325 struct dp_soc *soc; 5326 struct dp_mon_pdev *mon_pdev; 5327 struct dp_mon_ops *mon_ops; 5328 qdf_size_t mon_pdev_context_size; 5329 5330 if (!pdev) { 5331 dp_mon_err("pdev is NULL"); 5332 goto fail0; 5333 } 5334 5335 soc = pdev->soc; 5336 5337 mon_pdev_context_size = soc->arch_ops.txrx_get_mon_context_size(DP_CONTEXT_TYPE_MON_PDEV); 5338 mon_pdev = dp_context_alloc_mem(soc, DP_MON_PDEV_TYPE, mon_pdev_context_size); 5339 if (!mon_pdev) { 5340 dp_mon_err("%pK: MONITOR pdev allocation failed", pdev); 5341 goto fail0; 5342 } 5343 5344 pdev->monitor_pdev = mon_pdev; 5345 mon_ops = dp_mon_ops_get(pdev->soc); 5346 if (!mon_ops) { 5347 dp_mon_err("%pK: Invalid monitor ops", pdev); 5348 goto fail1; 5349 } 5350 5351 if (mon_ops->mon_pdev_alloc) { 5352 if (mon_ops->mon_pdev_alloc(pdev)) { 5353 dp_mon_err("%pK: MONITOR pdev alloc failed", pdev); 5354 goto fail1; 5355 } 5356 } 5357 5358 if (mon_ops->mon_rings_alloc) { 5359 if (mon_ops->mon_rings_alloc(pdev)) { 5360 dp_mon_err("%pK: MONITOR rings setup failed", pdev); 5361 goto fail2; 5362 } 5363 } 5364 5365 /* Rx monitor mode specific init */ 5366 if (mon_ops->rx_mon_desc_pool_alloc) { 5367 if (mon_ops->rx_mon_desc_pool_alloc(pdev)) { 5368 dp_mon_err("%pK: dp_rx_pdev_mon_attach failed", pdev); 5369 goto fail3; 5370 } 5371 } 5372 5373 if (mon_ops->mon_rx_ppdu_info_cache_create) { 5374 if (mon_ops->mon_rx_ppdu_info_cache_create(pdev)) { 5375 dp_mon_err("%pK: dp_rx_pdev_mon_attach failed", pdev); 5376 goto fail4; 5377 } 5378 } 5379 pdev->monitor_pdev = mon_pdev; 5380 dp_mon_pdev_per_target_config(pdev); 5381 5382 return QDF_STATUS_SUCCESS; 5383 fail4: 5384 if (mon_ops->rx_mon_desc_pool_free) 5385 mon_ops->rx_mon_desc_pool_free(pdev); 5386 fail3: 5387 if (mon_ops->mon_rings_free) 5388 mon_ops->mon_rings_free(pdev); 5389 fail2: 5390 if (mon_ops->mon_pdev_free) 5391 mon_ops->mon_pdev_free(pdev); 5392 fail1: 5393 pdev->monitor_pdev = NULL; 5394 dp_context_free_mem(soc, DP_MON_PDEV_TYPE, mon_pdev); 5395 fail0: 5396 return QDF_STATUS_E_NOMEM; 5397 } 5398 5399 QDF_STATUS dp_mon_pdev_detach(struct dp_pdev *pdev) 5400 { 5401 struct dp_mon_pdev *mon_pdev; 5402 struct dp_mon_ops *mon_ops = NULL; 5403 5404 if (!pdev) { 5405 dp_mon_err("pdev is NULL"); 5406 return QDF_STATUS_E_FAILURE; 5407 } 5408 5409 mon_pdev = pdev->monitor_pdev; 5410 if (!mon_pdev) { 5411 dp_mon_err("Monitor pdev is NULL"); 5412 return QDF_STATUS_E_FAILURE; 5413 } 5414 5415 mon_ops = dp_mon_ops_get(pdev->soc); 5416 if (!mon_ops) { 5417 dp_mon_err("Monitor ops is NULL"); 5418 return QDF_STATUS_E_FAILURE; 5419 } 5420 5421 if (mon_ops->mon_rx_ppdu_info_cache_destroy) 5422 mon_ops->mon_rx_ppdu_info_cache_destroy(pdev); 5423 if (mon_ops->rx_mon_desc_pool_free) 5424 mon_ops->rx_mon_desc_pool_free(pdev); 5425 if (mon_ops->mon_rings_free) 5426 mon_ops->mon_rings_free(pdev); 5427 if (mon_ops->mon_pdev_free) 5428 mon_ops->mon_pdev_free(pdev); 5429 5430 dp_context_free_mem(pdev->soc, DP_MON_PDEV_TYPE, mon_pdev); 5431 pdev->monitor_pdev = NULL; 5432 return QDF_STATUS_SUCCESS; 5433 } 5434 5435 QDF_STATUS dp_mon_pdev_init(struct dp_pdev *pdev) 5436 { 5437 struct dp_mon_pdev *mon_pdev; 5438 struct dp_mon_ops *mon_ops = NULL; 5439 5440 if (!pdev) { 5441 dp_mon_err("pdev is NULL"); 5442 return QDF_STATUS_E_FAILURE; 5443 } 5444 5445 mon_pdev = pdev->monitor_pdev; 5446 5447 mon_pdev->invalid_mon_peer = qdf_mem_malloc(sizeof(struct dp_mon_peer)); 5448 if (!mon_pdev->invalid_mon_peer) { 5449 dp_mon_err("%pK: Memory allocation failed for invalid " 5450 "monitor peer", pdev); 5451 return QDF_STATUS_E_NOMEM; 5452 } 5453 5454 mon_ops = dp_mon_ops_get(pdev->soc); 5455 if (!mon_ops) { 5456 dp_mon_err("Monitor ops is NULL"); 5457 goto fail0; 5458 } 5459 5460 mon_pdev->filter = dp_mon_filter_alloc(mon_pdev); 5461 if (!mon_pdev->filter) { 5462 dp_mon_err("%pK: Memory allocation failed for monitor filter", 5463 pdev); 5464 goto fail0; 5465 } 5466 5467 if (mon_ops->tx_mon_filter_alloc) { 5468 if (mon_ops->tx_mon_filter_alloc(pdev)) { 5469 dp_mon_err("%pK: Memory allocation failed for tx monitor " 5470 "filter", pdev); 5471 goto fail1; 5472 } 5473 } 5474 5475 qdf_spinlock_create(&mon_pdev->ppdu_stats_lock); 5476 qdf_spinlock_create(&mon_pdev->neighbour_peer_mutex); 5477 mon_pdev->monitor_configured = false; 5478 mon_pdev->mon_chan_band = REG_BAND_UNKNOWN; 5479 5480 TAILQ_INIT(&mon_pdev->neighbour_peers_list); 5481 mon_pdev->neighbour_peers_added = false; 5482 mon_pdev->monitor_configured = false; 5483 /* Monitor filter init */ 5484 mon_pdev->mon_filter_mode = MON_FILTER_ALL; 5485 mon_pdev->fp_mgmt_filter = FILTER_MGMT_ALL; 5486 mon_pdev->fp_ctrl_filter = FILTER_CTRL_ALL; 5487 mon_pdev->fp_data_filter = FILTER_DATA_ALL; 5488 mon_pdev->mo_mgmt_filter = FILTER_MGMT_ALL; 5489 mon_pdev->mo_ctrl_filter = FILTER_CTRL_ALL; 5490 mon_pdev->mo_data_filter = FILTER_DATA_ALL; 5491 5492 /* 5493 * initialize ppdu tlv list 5494 */ 5495 TAILQ_INIT(&mon_pdev->ppdu_info_list); 5496 TAILQ_INIT(&mon_pdev->sched_comp_ppdu_list); 5497 5498 mon_pdev->list_depth = 0; 5499 mon_pdev->tlv_count = 0; 5500 /* initlialize cal client timer */ 5501 dp_cal_client_attach(&mon_pdev->cal_client_ctx, 5502 dp_pdev_to_cdp_pdev(pdev), 5503 pdev->soc->osdev, 5504 &dp_iterate_update_peer_list); 5505 if (dp_htt_ppdu_stats_attach(pdev) != QDF_STATUS_SUCCESS) 5506 goto fail2; 5507 5508 if (mon_ops->mon_lite_mon_alloc) { 5509 if (mon_ops->mon_lite_mon_alloc(pdev) != QDF_STATUS_SUCCESS) { 5510 dp_mon_err("%pK: lite mon alloc failed", pdev); 5511 goto fail3; 5512 } 5513 } 5514 5515 if (mon_ops->mon_rings_init) { 5516 if (mon_ops->mon_rings_init(pdev)) { 5517 dp_mon_err("%pK: MONITOR rings setup failed", pdev); 5518 goto fail4; 5519 } 5520 } 5521 5522 /* initialize sw monitor rx descriptors */ 5523 if (mon_ops->rx_mon_desc_pool_init) 5524 mon_ops->rx_mon_desc_pool_init(pdev); 5525 5526 /* allocate buffers and replenish the monitor RxDMA ring */ 5527 if (mon_ops->rx_mon_buffers_alloc) { 5528 if (mon_ops->rx_mon_buffers_alloc(pdev)) { 5529 dp_mon_err("%pK: rx mon buffers alloc failed", pdev); 5530 goto fail5; 5531 } 5532 } 5533 5534 /* attach monitor function */ 5535 dp_monitor_tx_ppdu_stats_attach(pdev); 5536 5537 /* mon pdev extended init */ 5538 if (mon_ops->mon_pdev_ext_init) 5539 mon_ops->mon_pdev_ext_init(pdev); 5540 5541 mon_pdev->is_dp_mon_pdev_initialized = true; 5542 5543 return QDF_STATUS_SUCCESS; 5544 5545 fail5: 5546 if (mon_ops->rx_mon_desc_pool_deinit) 5547 mon_ops->rx_mon_desc_pool_deinit(pdev); 5548 5549 if (mon_ops->mon_rings_deinit) 5550 mon_ops->mon_rings_deinit(pdev); 5551 fail4: 5552 if (mon_ops->mon_lite_mon_dealloc) 5553 mon_ops->mon_lite_mon_dealloc(pdev); 5554 fail3: 5555 dp_htt_ppdu_stats_detach(pdev); 5556 fail2: 5557 qdf_spinlock_destroy(&mon_pdev->neighbour_peer_mutex); 5558 qdf_spinlock_destroy(&mon_pdev->ppdu_stats_lock); 5559 if (mon_ops->tx_mon_filter_dealloc) 5560 mon_ops->tx_mon_filter_dealloc(pdev); 5561 fail1: 5562 dp_mon_filter_dealloc(mon_pdev); 5563 fail0: 5564 qdf_mem_free(mon_pdev->invalid_mon_peer); 5565 return QDF_STATUS_E_FAILURE; 5566 } 5567 5568 QDF_STATUS dp_mon_pdev_deinit(struct dp_pdev *pdev) 5569 { 5570 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 5571 struct dp_mon_ops *mon_ops = NULL; 5572 5573 mon_ops = dp_mon_ops_get(pdev->soc); 5574 if (!mon_ops) { 5575 dp_mon_err("Monitor ops is NULL"); 5576 return QDF_STATUS_E_FAILURE; 5577 } 5578 5579 if (!mon_pdev->is_dp_mon_pdev_initialized) 5580 return QDF_STATUS_SUCCESS; 5581 5582 dp_mon_filters_reset(pdev); 5583 5584 /* mon pdev extended deinit */ 5585 if (mon_ops->mon_pdev_ext_deinit) 5586 mon_ops->mon_pdev_ext_deinit(pdev); 5587 5588 /* detach monitor function */ 5589 dp_monitor_tx_ppdu_stats_detach(pdev); 5590 5591 if (mon_ops->rx_mon_buffers_free) 5592 mon_ops->rx_mon_buffers_free(pdev); 5593 if (mon_ops->rx_mon_desc_pool_deinit) 5594 mon_ops->rx_mon_desc_pool_deinit(pdev); 5595 if (mon_ops->mon_rings_deinit) 5596 mon_ops->mon_rings_deinit(pdev); 5597 dp_cal_client_detach(&mon_pdev->cal_client_ctx); 5598 if (mon_ops->mon_lite_mon_dealloc) 5599 mon_ops->mon_lite_mon_dealloc(pdev); 5600 dp_htt_ppdu_stats_detach(pdev); 5601 qdf_spinlock_destroy(&mon_pdev->ppdu_stats_lock); 5602 dp_neighbour_peers_detach(pdev); 5603 dp_pktlogmod_exit(pdev); 5604 if (mon_ops->tx_mon_filter_dealloc) 5605 mon_ops->tx_mon_filter_dealloc(pdev); 5606 if (mon_pdev->filter) 5607 dp_mon_filter_dealloc(mon_pdev); 5608 if (mon_ops->mon_rings_deinit) 5609 mon_ops->mon_rings_deinit(pdev); 5610 if (mon_pdev->invalid_mon_peer) 5611 qdf_mem_free(mon_pdev->invalid_mon_peer); 5612 mon_pdev->is_dp_mon_pdev_initialized = false; 5613 5614 return QDF_STATUS_SUCCESS; 5615 } 5616 5617 QDF_STATUS dp_mon_vdev_attach(struct dp_vdev *vdev) 5618 { 5619 struct dp_mon_vdev *mon_vdev; 5620 struct dp_pdev *pdev = vdev->pdev; 5621 5622 mon_vdev = (struct dp_mon_vdev *)qdf_mem_malloc(sizeof(*mon_vdev)); 5623 if (!mon_vdev) { 5624 dp_mon_err("%pK: Monitor vdev allocation failed", vdev); 5625 return QDF_STATUS_E_NOMEM; 5626 } 5627 5628 if (pdev && pdev->monitor_pdev && 5629 pdev->monitor_pdev->scan_spcl_vap_configured) 5630 dp_scan_spcl_vap_stats_attach(mon_vdev); 5631 5632 vdev->monitor_vdev = mon_vdev; 5633 5634 return QDF_STATUS_SUCCESS; 5635 } 5636 5637 QDF_STATUS dp_mon_vdev_detach(struct dp_vdev *vdev) 5638 { 5639 struct dp_mon_vdev *mon_vdev = vdev->monitor_vdev; 5640 struct dp_pdev *pdev = vdev->pdev; 5641 struct dp_mon_ops *mon_ops = dp_mon_ops_get(pdev->soc); 5642 5643 if (!mon_ops) 5644 return QDF_STATUS_E_FAILURE; 5645 5646 if (!mon_vdev) 5647 return QDF_STATUS_E_FAILURE; 5648 5649 if (pdev->monitor_pdev->scan_spcl_vap_configured) 5650 dp_scan_spcl_vap_stats_detach(mon_vdev); 5651 5652 qdf_mem_free(mon_vdev); 5653 vdev->monitor_vdev = NULL; 5654 /* set mvdev to NULL only if detach is called for monitor/special vap 5655 */ 5656 if (pdev->monitor_pdev->mvdev == vdev) 5657 pdev->monitor_pdev->mvdev = NULL; 5658 5659 if (mon_ops->mon_lite_mon_vdev_delete) 5660 mon_ops->mon_lite_mon_vdev_delete(pdev, vdev); 5661 5662 return QDF_STATUS_SUCCESS; 5663 } 5664 5665 #if defined(FEATURE_PERPKT_INFO) && WDI_EVENT_ENABLE 5666 /** 5667 * dp_mon_peer_attach_notify() - Raise WDI event for peer create 5668 * @peer: DP Peer handle 5669 * 5670 * Return: none 5671 */ 5672 static inline 5673 void dp_mon_peer_attach_notify(struct dp_peer *peer) 5674 { 5675 struct dp_mon_peer *mon_peer = peer->monitor_peer; 5676 struct dp_pdev *pdev; 5677 struct dp_soc *soc; 5678 struct cdp_peer_cookie peer_cookie; 5679 5680 pdev = peer->vdev->pdev; 5681 soc = pdev->soc; 5682 5683 qdf_mem_copy(peer_cookie.mac_addr, peer->mac_addr.raw, 5684 QDF_MAC_ADDR_SIZE); 5685 5686 peer_cookie.ctx = NULL; 5687 peer_cookie.pdev_id = pdev->pdev_id; 5688 peer_cookie.cookie = pdev->next_peer_cookie++; 5689 5690 dp_wdi_event_handler(WDI_EVENT_PEER_CREATE, soc, 5691 (void *)&peer_cookie, 5692 peer->peer_id, WDI_NO_VAL, pdev->pdev_id); 5693 5694 if (soc->peerstats_enabled) { 5695 if (!peer_cookie.ctx) { 5696 pdev->next_peer_cookie--; 5697 qdf_err("Failed to initialize peer rate stats"); 5698 mon_peer->peerstats_ctx = NULL; 5699 } else { 5700 mon_peer->peerstats_ctx = 5701 (struct cdp_peer_rate_stats_ctx *) 5702 peer_cookie.ctx; 5703 } 5704 } 5705 } 5706 5707 /** 5708 * dp_mon_peer_detach_notify() - Raise WDI event for peer destroy 5709 * @peer: DP Peer handle 5710 * 5711 * Return: none 5712 */ 5713 static inline 5714 void dp_mon_peer_detach_notify(struct dp_peer *peer) 5715 { 5716 struct dp_mon_peer *mon_peer = peer->monitor_peer; 5717 struct dp_pdev *pdev; 5718 struct dp_soc *soc; 5719 struct cdp_peer_cookie peer_cookie; 5720 5721 pdev = peer->vdev->pdev; 5722 soc = pdev->soc; 5723 /* send peer destroy event to upper layer */ 5724 qdf_mem_copy(peer_cookie.mac_addr, peer->mac_addr.raw, 5725 QDF_MAC_ADDR_SIZE); 5726 peer_cookie.ctx = NULL; 5727 peer_cookie.ctx = (struct cdp_stats_cookie *)mon_peer->peerstats_ctx; 5728 5729 dp_wdi_event_handler(WDI_EVENT_PEER_DESTROY, 5730 soc, 5731 (void *)&peer_cookie, 5732 peer->peer_id, 5733 WDI_NO_VAL, 5734 pdev->pdev_id); 5735 5736 mon_peer->peerstats_ctx = NULL; 5737 } 5738 #else 5739 static inline 5740 void dp_mon_peer_attach_notify(struct dp_peer *peer) 5741 { 5742 peer->monitor_peer->peerstats_ctx = NULL; 5743 } 5744 5745 static inline 5746 void dp_mon_peer_detach_notify(struct dp_peer *peer) 5747 { 5748 peer->monitor_peer->peerstats_ctx = NULL; 5749 } 5750 #endif 5751 5752 #if defined(WLAN_TX_PKT_CAPTURE_ENH) || defined(FEATURE_PERPKT_INFO) 5753 QDF_STATUS dp_mon_peer_attach(struct dp_peer *peer) 5754 { 5755 struct dp_mon_peer *mon_peer; 5756 struct dp_pdev *pdev; 5757 5758 mon_peer = (struct dp_mon_peer *)qdf_mem_malloc(sizeof(*mon_peer)); 5759 if (!mon_peer) { 5760 dp_mon_err("%pK: MONITOR peer allocation failed", peer); 5761 return QDF_STATUS_E_NOMEM; 5762 } 5763 5764 peer->monitor_peer = mon_peer; 5765 pdev = peer->vdev->pdev; 5766 /* 5767 * In tx_monitor mode, filter may be set for unassociated peer 5768 * when unassociated peer get associated peer need to 5769 * update tx_cap_enabled flag to support peer filter. 5770 */ 5771 dp_monitor_peer_tx_capture_filter_check(pdev, peer); 5772 5773 DP_STATS_INIT(mon_peer); 5774 DP_STATS_UPD(mon_peer, rx.avg_snr, CDP_INVALID_SNR); 5775 5776 dp_mon_peer_attach_notify(peer); 5777 5778 return QDF_STATUS_SUCCESS; 5779 } 5780 #endif 5781 5782 QDF_STATUS dp_mon_peer_detach(struct dp_peer *peer) 5783 { 5784 struct dp_mon_peer *mon_peer = peer->monitor_peer; 5785 5786 if (!mon_peer) 5787 return QDF_STATUS_SUCCESS; 5788 5789 dp_mon_peer_detach_notify(peer); 5790 5791 qdf_mem_free(mon_peer); 5792 peer->monitor_peer = NULL; 5793 5794 return QDF_STATUS_SUCCESS; 5795 } 5796 5797 #ifndef DISABLE_MON_CONFIG 5798 void dp_mon_register_intr_ops(struct dp_soc *soc) 5799 { 5800 struct dp_mon_ops *mon_ops = NULL; 5801 5802 mon_ops = dp_mon_ops_get(soc); 5803 if (!mon_ops) { 5804 dp_mon_err("Monitor ops is NULL"); 5805 return; 5806 } 5807 if (mon_ops->mon_register_intr_ops) 5808 mon_ops->mon_register_intr_ops(soc); 5809 } 5810 #endif 5811 5812 struct cdp_peer_rate_stats_ctx *dp_mon_peer_get_peerstats_ctx(struct 5813 dp_peer *peer) 5814 { 5815 struct dp_mon_peer *mon_peer = peer->monitor_peer; 5816 5817 if (mon_peer) 5818 return mon_peer->peerstats_ctx; 5819 else 5820 return NULL; 5821 } 5822 5823 #ifdef QCA_ENHANCED_STATS_SUPPORT 5824 void dp_mon_peer_reset_stats(struct dp_peer *peer) 5825 { 5826 struct dp_mon_peer *mon_peer = NULL; 5827 5828 mon_peer = peer->monitor_peer; 5829 if (!mon_peer) 5830 return; 5831 5832 DP_STATS_CLR(mon_peer); 5833 DP_STATS_UPD(mon_peer, rx.avg_snr, CDP_INVALID_SNR); 5834 } 5835 5836 void dp_mon_peer_get_stats(struct dp_peer *peer, void *arg, 5837 enum cdp_stat_update_type type) 5838 { 5839 struct dp_mon_peer *mon_peer = peer->monitor_peer; 5840 struct dp_mon_peer_stats *mon_peer_stats; 5841 5842 if (!mon_peer || !arg) 5843 return; 5844 5845 mon_peer_stats = &mon_peer->stats; 5846 5847 switch (type) { 5848 case UPDATE_PEER_STATS: 5849 { 5850 struct cdp_peer_stats *peer_stats = 5851 (struct cdp_peer_stats *)arg; 5852 DP_UPDATE_MON_STATS(peer_stats, mon_peer_stats); 5853 break; 5854 } 5855 case UPDATE_VDEV_STATS: 5856 { 5857 struct cdp_vdev_stats *vdev_stats = 5858 (struct cdp_vdev_stats *)arg; 5859 DP_UPDATE_MON_STATS(vdev_stats, mon_peer_stats); 5860 break; 5861 } 5862 default: 5863 dp_mon_err("Invalid stats_update_type"); 5864 } 5865 } 5866 5867 void dp_mon_invalid_peer_update_pdev_stats(struct dp_pdev *pdev) 5868 { 5869 struct dp_mon_peer *mon_peer; 5870 struct dp_mon_peer_stats *mon_peer_stats; 5871 struct cdp_pdev_stats *pdev_stats; 5872 5873 if (!pdev || !pdev->monitor_pdev) 5874 return; 5875 5876 mon_peer = pdev->monitor_pdev->invalid_mon_peer; 5877 if (!mon_peer) 5878 return; 5879 5880 mon_peer_stats = &mon_peer->stats; 5881 pdev_stats = &pdev->stats; 5882 DP_UPDATE_MON_STATS(pdev_stats, mon_peer_stats); 5883 } 5884 5885 QDF_STATUS 5886 dp_mon_peer_get_stats_param(struct dp_peer *peer, enum cdp_peer_stats_type type, 5887 cdp_peer_stats_param_t *buf) 5888 { 5889 QDF_STATUS ret = QDF_STATUS_SUCCESS; 5890 struct dp_mon_peer *mon_peer; 5891 5892 mon_peer = peer->monitor_peer; 5893 if (!mon_peer) 5894 return QDF_STATUS_E_FAILURE; 5895 5896 switch (type) { 5897 case cdp_peer_tx_rate: 5898 buf->tx_rate = mon_peer->stats.tx.tx_rate; 5899 break; 5900 case cdp_peer_tx_last_tx_rate: 5901 buf->last_tx_rate = mon_peer->stats.tx.last_tx_rate; 5902 break; 5903 case cdp_peer_tx_ratecode: 5904 buf->tx_ratecode = mon_peer->stats.tx.tx_ratecode; 5905 break; 5906 case cdp_peer_rx_rate: 5907 buf->rx_rate = mon_peer->stats.rx.rx_rate; 5908 break; 5909 case cdp_peer_rx_last_rx_rate: 5910 buf->last_rx_rate = mon_peer->stats.rx.last_rx_rate; 5911 break; 5912 case cdp_peer_rx_ratecode: 5913 buf->rx_ratecode = mon_peer->stats.rx.rx_ratecode; 5914 break; 5915 case cdp_peer_rx_avg_snr: 5916 buf->rx_avg_snr = mon_peer->stats.rx.avg_snr; 5917 break; 5918 case cdp_peer_rx_snr: 5919 buf->rx_snr = mon_peer->stats.rx.snr; 5920 break; 5921 default: 5922 dp_err("Invalid stats type requested"); 5923 ret = QDF_STATUS_E_FAILURE; 5924 } 5925 5926 return ret; 5927 } 5928 #endif 5929 5930 void dp_mon_ops_register(struct dp_soc *soc) 5931 { 5932 struct dp_mon_soc *mon_soc = soc->monitor_soc; 5933 uint32_t target_type; 5934 5935 target_type = hal_get_target_type(soc->hal_soc); 5936 switch (target_type) { 5937 case TARGET_TYPE_QCA6290: 5938 case TARGET_TYPE_QCA6390: 5939 case TARGET_TYPE_QCA6490: 5940 case TARGET_TYPE_QCA6750: 5941 case TARGET_TYPE_KIWI: 5942 case TARGET_TYPE_MANGO: 5943 case TARGET_TYPE_QCA8074: 5944 case TARGET_TYPE_QCA8074V2: 5945 case TARGET_TYPE_QCA6018: 5946 case TARGET_TYPE_QCA9574: 5947 case TARGET_TYPE_QCN9160: 5948 case TARGET_TYPE_QCN9000: 5949 case TARGET_TYPE_QCA5018: 5950 case TARGET_TYPE_QCN6122: 5951 dp_mon_ops_register_1_0(mon_soc); 5952 break; 5953 case TARGET_TYPE_QCN9224: 5954 case TARGET_TYPE_QCA5332: 5955 #ifdef QCA_MONITOR_2_0_SUPPORT 5956 dp_mon_ops_register_2_0(mon_soc); 5957 #endif 5958 break; 5959 default: 5960 dp_mon_err("%s: Unknown tgt type %d", __func__, target_type); 5961 qdf_assert_always(0); 5962 break; 5963 } 5964 } 5965 5966 #ifdef QCA_MONITOR_OPS_PER_SOC_SUPPORT 5967 void dp_mon_ops_free(struct dp_soc *soc) 5968 { 5969 struct cdp_ops *ops = soc->cdp_soc.ops; 5970 struct cdp_mon_ops *cdp_mon_ops = ops->mon_ops; 5971 struct dp_mon_soc *mon_soc = soc->monitor_soc; 5972 struct dp_mon_ops *mon_ops = mon_soc->mon_ops; 5973 5974 if (cdp_mon_ops) 5975 qdf_mem_free(cdp_mon_ops); 5976 5977 if (mon_ops) 5978 qdf_mem_free(mon_ops); 5979 } 5980 #else 5981 void dp_mon_ops_free(struct dp_soc *soc) 5982 { 5983 } 5984 #endif 5985 5986 void dp_mon_cdp_ops_register(struct dp_soc *soc) 5987 { 5988 struct cdp_ops *ops = soc->cdp_soc.ops; 5989 uint32_t target_type; 5990 5991 if (!ops) { 5992 dp_mon_err("cdp_ops is NULL"); 5993 return; 5994 } 5995 5996 target_type = hal_get_target_type(soc->hal_soc); 5997 switch (target_type) { 5998 case TARGET_TYPE_QCA6290: 5999 case TARGET_TYPE_QCA6390: 6000 case TARGET_TYPE_QCA6490: 6001 case TARGET_TYPE_QCA6750: 6002 case TARGET_TYPE_KIWI: 6003 case TARGET_TYPE_MANGO: 6004 case TARGET_TYPE_QCA8074: 6005 case TARGET_TYPE_QCA8074V2: 6006 case TARGET_TYPE_QCA6018: 6007 case TARGET_TYPE_QCA9574: 6008 case TARGET_TYPE_QCN9160: 6009 case TARGET_TYPE_QCN9000: 6010 case TARGET_TYPE_QCA5018: 6011 case TARGET_TYPE_QCN6122: 6012 dp_mon_cdp_ops_register_1_0(ops); 6013 #ifdef ATH_SUPPORT_NAC_RSSI 6014 ops->ctrl_ops->txrx_vdev_config_for_nac_rssi = 6015 dp_config_for_nac_rssi; 6016 ops->ctrl_ops->txrx_vdev_get_neighbour_rssi = 6017 dp_vdev_get_neighbour_rssi; 6018 #endif 6019 #if defined(ATH_SUPPORT_NAC_RSSI) || defined(ATH_SUPPORT_NAC) 6020 ops->ctrl_ops->txrx_update_filter_neighbour_peers = 6021 dp_update_filter_neighbour_peers; 6022 #endif /* ATH_SUPPORT_NAC_RSSI || ATH_SUPPORT_NAC */ 6023 #if defined(WLAN_CFR_ENABLE) && defined(WLAN_ENH_CFR_ENABLE) 6024 dp_cfr_filter_register_1_0(ops); 6025 #endif 6026 if (target_type == TARGET_TYPE_QCN9000) 6027 ops->ctrl_ops->txrx_update_mon_mac_filter = 6028 dp_update_mon_mac_filter; 6029 break; 6030 case TARGET_TYPE_QCN9224: 6031 case TARGET_TYPE_QCA5332: 6032 #ifdef QCA_MONITOR_2_0_SUPPORT 6033 dp_mon_cdp_ops_register_2_0(ops); 6034 #ifdef ATH_SUPPORT_NAC_RSSI 6035 ops->ctrl_ops->txrx_vdev_config_for_nac_rssi = 6036 dp_lite_mon_config_nac_rssi_peer; 6037 ops->ctrl_ops->txrx_vdev_get_neighbour_rssi = 6038 dp_lite_mon_get_nac_peer_rssi; 6039 #endif 6040 #if defined(ATH_SUPPORT_NAC_RSSI) || defined(ATH_SUPPORT_NAC) 6041 ops->ctrl_ops->txrx_update_filter_neighbour_peers = 6042 dp_lite_mon_config_nac_peer; 6043 #endif /* ATH_SUPPORT_NAC_RSSI || ATH_SUPPORT_NAC */ 6044 #if defined(WLAN_CFR_ENABLE) && defined(WLAN_ENH_CFR_ENABLE) 6045 dp_cfr_filter_register_2_0(ops); 6046 #endif 6047 #endif /* QCA_MONITOR_2_0_SUPPORT */ 6048 break; 6049 default: 6050 dp_mon_err("%s: Unknown tgt type %d", __func__, target_type); 6051 qdf_assert_always(0); 6052 break; 6053 } 6054 6055 ops->cmn_drv_ops->txrx_set_monitor_mode = dp_vdev_set_monitor_mode; 6056 ops->cmn_drv_ops->txrx_get_mon_vdev_from_pdev = 6057 dp_get_mon_vdev_from_pdev_wifi3; 6058 #ifdef DP_PEER_EXTENDED_API 6059 ops->misc_ops->pkt_log_init = dp_pkt_log_init; 6060 ops->misc_ops->pkt_log_con_service = dp_pkt_log_con_service; 6061 ops->misc_ops->pkt_log_exit = dp_pkt_log_exit; 6062 #endif 6063 ops->ctrl_ops->enable_peer_based_pktlog = 6064 dp_enable_peer_based_pktlog; 6065 #if defined(WLAN_TX_PKT_CAPTURE_ENH) || defined(WLAN_RX_PKT_CAPTURE_ENH) 6066 ops->ctrl_ops->txrx_update_peer_pkt_capture_params = 6067 dp_peer_update_pkt_capture_params; 6068 #endif /* WLAN_TX_PKT_CAPTURE_ENH || WLAN_RX_PKT_CAPTURE_ENH */ 6069 #ifdef QCA_ENHANCED_STATS_SUPPORT 6070 ops->host_stats_ops->txrx_enable_enhanced_stats = 6071 dp_enable_enhanced_stats; 6072 ops->host_stats_ops->txrx_disable_enhanced_stats = 6073 dp_disable_enhanced_stats; 6074 #endif /* QCA_ENHANCED_STATS_SUPPORT */ 6075 #ifdef WDI_EVENT_ENABLE 6076 ops->ctrl_ops->txrx_get_pldev = dp_get_pldev; 6077 #endif 6078 #ifdef QCA_SUPPORT_SCAN_SPCL_VAP_STATS 6079 ops->host_stats_ops->txrx_get_scan_spcl_vap_stats = 6080 dp_get_scan_spcl_vap_stats; 6081 #endif 6082 return; 6083 } 6084 6085 #ifdef QCA_MONITOR_OPS_PER_SOC_SUPPORT 6086 static inline void 6087 dp_mon_cdp_mon_ops_deregister(struct cdp_ops *ops) 6088 { 6089 if (ops->mon_ops) { 6090 qdf_mem_free(ops->mon_ops); 6091 ops->mon_ops = NULL; 6092 } 6093 } 6094 #else 6095 static inline void 6096 dp_mon_cdp_mon_ops_deregister(struct cdp_ops *ops) 6097 { 6098 ops->mon_ops = NULL; 6099 } 6100 #endif 6101 6102 void dp_mon_cdp_ops_deregister(struct dp_soc *soc) 6103 { 6104 struct cdp_ops *ops = soc->cdp_soc.ops; 6105 6106 if (!ops) { 6107 dp_mon_err("cdp_ops is NULL"); 6108 return; 6109 } 6110 6111 dp_mon_cdp_mon_ops_deregister(ops); 6112 6113 #if defined(WLAN_CFR_ENABLE) && defined(WLAN_ENH_CFR_ENABLE) 6114 ops->cfr_ops->txrx_cfr_filter = NULL; 6115 #endif 6116 ops->cmn_drv_ops->txrx_set_monitor_mode = NULL; 6117 ops->cmn_drv_ops->txrx_get_mon_vdev_from_pdev = NULL; 6118 #ifdef DP_PEER_EXTENDED_API 6119 ops->misc_ops->pkt_log_init = NULL; 6120 ops->misc_ops->pkt_log_con_service = NULL; 6121 ops->misc_ops->pkt_log_exit = NULL; 6122 #endif 6123 #ifdef ATH_SUPPORT_NAC_RSSI 6124 ops->ctrl_ops->txrx_vdev_config_for_nac_rssi = NULL; 6125 ops->ctrl_ops->txrx_vdev_get_neighbour_rssi = NULL; 6126 #endif 6127 #if defined(ATH_SUPPORT_NAC_RSSI) || defined(ATH_SUPPORT_NAC) 6128 ops->ctrl_ops->txrx_update_filter_neighbour_peers = NULL; 6129 #endif /* ATH_SUPPORT_NAC_RSSI || ATH_SUPPORT_NAC */ 6130 ops->ctrl_ops->enable_peer_based_pktlog = NULL; 6131 #if defined(WLAN_TX_PKT_CAPTURE_ENH) || defined(WLAN_RX_PKT_CAPTURE_ENH) 6132 ops->ctrl_ops->txrx_update_peer_pkt_capture_params = NULL; 6133 #endif /* WLAN_TX_PKT_CAPTURE_ENH || WLAN_RX_PKT_CAPTURE_ENH */ 6134 #ifdef FEATURE_PERPKT_INFO 6135 ops->host_stats_ops->txrx_enable_enhanced_stats = NULL; 6136 ops->host_stats_ops->txrx_disable_enhanced_stats = NULL; 6137 #endif /* FEATURE_PERPKT_INFO */ 6138 #ifdef WDI_EVENT_ENABLE 6139 ops->ctrl_ops->txrx_get_pldev = NULL; 6140 #endif 6141 return; 6142 } 6143 6144 #if defined(WDI_EVENT_ENABLE) &&\ 6145 (defined(QCA_ENHANCED_STATS_SUPPORT) || !defined(REMOVE_PKT_LOG)) 6146 static inline 6147 void dp_mon_ppdu_stats_handler_deregister(struct dp_mon_soc *mon_soc) 6148 { 6149 mon_soc->mon_ops->mon_ppdu_stats_ind_handler = NULL; 6150 } 6151 #else 6152 static inline 6153 void dp_mon_ppdu_stats_handler_deregister(struct dp_mon_soc *mon_soc) 6154 { 6155 } 6156 #endif 6157 6158 #ifdef QCA_RSSI_DB2DBM 6159 /* 6160 * dp_mon_compute_min_nf() - calculate the min nf value in the 6161 * active chains 20MHZ subbands. 6162 * computation: Need to calculate nfInDbm[][] to A_MIN(nfHwDbm[][]) 6163 * considering row index as active chains and column 6164 * index as 20MHZ subbands per chain. 6165 * example: chain_mask = 0x07 (consider 3 active chains 0,1,2 index) 6166 * BandWidth = 40MHZ (40MHZ includes two 20MHZ subbands so need to 6167 * consider 0,1 index calculate min_nf value) 6168 * 6169 *@conv_params: cdp_rssi_dbm_conv_param_dp structure value 6170 *@chain_idx: active chain index in nfHwdbm array 6171 * 6172 * Return: QDF_STATUS_SUCCESS if value set successfully 6173 * QDF_STATUS_E_INVAL false if error 6174 */ 6175 static QDF_STATUS 6176 dp_mon_compute_min_nf(struct cdp_rssi_dbm_conv_param_dp *conv_params, 6177 int8_t *min_nf, int chain_idx) 6178 { 6179 int j; 6180 *min_nf = conv_params->nf_hw_dbm[chain_idx][0]; 6181 6182 switch (conv_params->curr_bw) { 6183 case CHAN_WIDTH_20: 6184 case CHAN_WIDTH_5: 6185 case CHAN_WIDTH_10: 6186 break; 6187 case CHAN_WIDTH_40: 6188 for (j = 1; j < SUB40BW; j++) { 6189 if (conv_params->nf_hw_dbm[chain_idx][j] < *min_nf) 6190 *min_nf = conv_params->nf_hw_dbm[chain_idx][j]; 6191 } 6192 break; 6193 case CHAN_WIDTH_80: 6194 for (j = 1; j < SUB80BW; j++) { 6195 if (conv_params->nf_hw_dbm[chain_idx][j] < *min_nf) 6196 *min_nf = conv_params->nf_hw_dbm[chain_idx][j]; 6197 } 6198 break; 6199 case CHAN_WIDTH_160: 6200 case CHAN_WIDTH_80P80: 6201 case CHAN_WIDTH_165: 6202 for (j = 1; j < SUB160BW; j++) { 6203 if (conv_params->nf_hw_dbm[chain_idx][j] < *min_nf) 6204 *min_nf = conv_params->nf_hw_dbm[chain_idx][j]; 6205 } 6206 break; 6207 case CHAN_WIDTH_160P160: 6208 case CHAN_WIDTH_320: 6209 for (j = 1; j < SUB320BW; j++) { 6210 if (conv_params->nf_hw_dbm[chain_idx][j] < *min_nf) 6211 *min_nf = conv_params->nf_hw_dbm[chain_idx][j]; 6212 } 6213 break; 6214 default: 6215 dp_cdp_err("Invalid bandwidth %u", conv_params->curr_bw); 6216 return QDF_STATUS_E_INVAL; 6217 } 6218 return QDF_STATUS_SUCCESS; 6219 } 6220 6221 /* 6222 * dp_mon_pdev_params_rssi_dbm_conv() --> to set rssi in dbm conversion 6223 * params into monitor pdev. 6224 *@cdp_soc: dp soc handle. 6225 *@params: cdp_rssi_db2dbm_param_dp structure value. 6226 * 6227 * Return: QDF_STATUS_SUCCESS if value set successfully 6228 * QDF_STATUS_E_INVAL false if error 6229 */ 6230 QDF_STATUS 6231 dp_mon_pdev_params_rssi_dbm_conv(struct cdp_soc_t *cdp_soc, 6232 struct cdp_rssi_db2dbm_param_dp *params) 6233 { 6234 struct cdp_rssi_db2dbm_param_dp *dp_rssi_params = params; 6235 uint8_t pdev_id = params->pdev_id; 6236 struct dp_soc *soc = (struct dp_soc *)cdp_soc; 6237 struct dp_pdev *pdev = 6238 dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); 6239 struct dp_mon_pdev *mon_pdev; 6240 struct cdp_rssi_temp_off_param_dp temp_off_param; 6241 struct cdp_rssi_dbm_conv_param_dp conv_params; 6242 int8_t min_nf = 0; 6243 int i; 6244 6245 if (!soc->features.rssi_dbm_conv_support) { 6246 dp_cdp_err("rssi dbm conversion support is false"); 6247 return QDF_STATUS_E_INVAL; 6248 } 6249 if (!pdev || !pdev->monitor_pdev) { 6250 dp_cdp_err("Invalid pdev_id %u", pdev_id); 6251 return QDF_STATUS_E_FAILURE; 6252 } 6253 6254 mon_pdev = pdev->monitor_pdev; 6255 mon_pdev->rssi_dbm_conv_support = 6256 soc->features.rssi_dbm_conv_support; 6257 6258 if (dp_rssi_params->rssi_temp_off_present) { 6259 temp_off_param = dp_rssi_params->temp_off_param; 6260 mon_pdev->rssi_offsets.rssi_temp_offset = 6261 temp_off_param.rssi_temp_offset; 6262 } 6263 if (dp_rssi_params->rssi_dbm_info_present) { 6264 conv_params = dp_rssi_params->rssi_dbm_param; 6265 for (i = 0; i < CDP_MAX_NUM_ANTENNA; i++) { 6266 if (conv_params.curr_rx_chainmask & (0x01 << i)) { 6267 if (QDF_STATUS_E_INVAL == dp_mon_compute_min_nf 6268 (&conv_params, &min_nf, i)) 6269 return QDF_STATUS_E_INVAL; 6270 } else { 6271 continue; 6272 } 6273 } 6274 mon_pdev->rssi_offsets.xlna_bypass_offset = 6275 conv_params.xlna_bypass_offset; 6276 mon_pdev->rssi_offsets.xlna_bypass_threshold = 6277 conv_params.xlna_bypass_threshold; 6278 mon_pdev->rssi_offsets.xbar_config = conv_params.xbar_config; 6279 mon_pdev->rssi_offsets.min_nf_dbm = min_nf; 6280 mon_pdev->rssi_offsets.rssi_offset = 6281 mon_pdev->rssi_offsets.min_nf_dbm + 6282 mon_pdev->rssi_offsets.rssi_temp_offset; 6283 } 6284 return QDF_STATUS_SUCCESS; 6285 } 6286 #endif 6287 6288 void dp_mon_intr_ops_deregister(struct dp_soc *soc) 6289 { 6290 struct dp_mon_soc *mon_soc = soc->monitor_soc; 6291 6292 mon_soc->mon_rx_process = NULL; 6293 dp_mon_ppdu_stats_handler_deregister(mon_soc); 6294 } 6295 6296 void dp_mon_feature_ops_deregister(struct dp_soc *soc) 6297 { 6298 struct dp_mon_ops *mon_ops = dp_mon_ops_get(soc); 6299 6300 if (!mon_ops) { 6301 dp_err("mon_ops is NULL"); 6302 return; 6303 } 6304 6305 mon_ops->mon_config_debug_sniffer = NULL; 6306 mon_ops->mon_peer_tx_init = NULL; 6307 mon_ops->mon_peer_tx_cleanup = NULL; 6308 mon_ops->mon_htt_ppdu_stats_attach = NULL; 6309 mon_ops->mon_htt_ppdu_stats_detach = NULL; 6310 mon_ops->mon_print_pdev_rx_mon_stats = NULL; 6311 mon_ops->mon_set_bsscolor = NULL; 6312 mon_ops->mon_pdev_get_filter_ucast_data = NULL; 6313 mon_ops->mon_pdev_get_filter_mcast_data = NULL; 6314 mon_ops->mon_pdev_get_filter_non_data = NULL; 6315 mon_ops->mon_neighbour_peer_add_ast = NULL; 6316 #ifdef WLAN_TX_PKT_CAPTURE_ENH 6317 mon_ops->mon_peer_tid_peer_id_update = NULL; 6318 mon_ops->mon_tx_ppdu_stats_attach = NULL; 6319 mon_ops->mon_tx_ppdu_stats_detach = NULL; 6320 mon_ops->mon_tx_capture_debugfs_init = NULL; 6321 mon_ops->mon_tx_add_to_comp_queue = NULL; 6322 mon_ops->mon_peer_tx_capture_filter_check = NULL; 6323 mon_ops->mon_print_pdev_tx_capture_stats = NULL; 6324 mon_ops->mon_config_enh_tx_capture = NULL; 6325 #endif 6326 #ifdef WLAN_RX_PKT_CAPTURE_ENH 6327 mon_ops->mon_config_enh_rx_capture = NULL; 6328 #endif 6329 #ifdef QCA_SUPPORT_BPR 6330 mon_ops->mon_set_bpr_enable = NULL; 6331 #endif 6332 #ifdef ATH_SUPPORT_NAC 6333 mon_ops->mon_set_filter_neigh_peers = NULL; 6334 #endif 6335 #ifdef WLAN_ATF_ENABLE 6336 mon_ops->mon_set_atf_stats_enable = NULL; 6337 #endif 6338 #ifdef FEATURE_NAC_RSSI 6339 mon_ops->mon_filter_neighbour_peer = NULL; 6340 #endif 6341 #ifdef QCA_MCOPY_SUPPORT 6342 mon_ops->mon_filter_setup_mcopy_mode = NULL; 6343 mon_ops->mon_filter_reset_mcopy_mode = NULL; 6344 mon_ops->mon_mcopy_check_deliver = NULL; 6345 #endif 6346 #ifdef QCA_ENHANCED_STATS_SUPPORT 6347 mon_ops->mon_filter_setup_enhanced_stats = NULL; 6348 mon_ops->mon_tx_enable_enhanced_stats = NULL; 6349 mon_ops->mon_tx_disable_enhanced_stats = NULL; 6350 mon_ops->mon_ppdu_desc_deliver = NULL; 6351 mon_ops->mon_ppdu_desc_notify = NULL; 6352 mon_ops->mon_ppdu_stats_feat_enable_check = NULL; 6353 #ifdef WLAN_FEATURE_11BE 6354 mon_ops->mon_tx_stats_update = NULL; 6355 #endif 6356 #endif 6357 #if defined(ATH_SUPPORT_NAC_RSSI) || defined(ATH_SUPPORT_NAC) 6358 mon_ops->mon_filter_setup_smart_monitor = NULL; 6359 #endif 6360 mon_ops->mon_filter_set_reset_mon_mac_filter = NULL; 6361 #ifdef WLAN_RX_PKT_CAPTURE_ENH 6362 mon_ops->mon_filter_setup_rx_enh_capture = NULL; 6363 #endif 6364 #ifdef WDI_EVENT_ENABLE 6365 mon_ops->mon_set_pktlog_wifi3 = NULL; 6366 mon_ops->mon_filter_setup_rx_pkt_log_full = NULL; 6367 mon_ops->mon_filter_reset_rx_pkt_log_full = NULL; 6368 mon_ops->mon_filter_setup_rx_pkt_log_lite = NULL; 6369 mon_ops->mon_filter_reset_rx_pkt_log_lite = NULL; 6370 mon_ops->mon_filter_setup_rx_pkt_log_cbf = NULL; 6371 mon_ops->mon_filter_reset_rx_pkt_log_cbf = NULL; 6372 #ifdef BE_PKTLOG_SUPPORT 6373 mon_ops->mon_filter_setup_pktlog_hybrid = NULL; 6374 mon_ops->mon_filter_reset_pktlog_hybrid = NULL; 6375 #endif 6376 #endif 6377 #if defined(DP_CON_MON) && !defined(REMOVE_PKT_LOG) 6378 mon_ops->mon_pktlogmod_exit = NULL; 6379 #endif 6380 mon_ops->rx_hdr_length_set = NULL; 6381 mon_ops->rx_packet_length_set = NULL; 6382 mon_ops->rx_wmask_subscribe = NULL; 6383 mon_ops->rx_enable_mpdu_logging = NULL; 6384 mon_ops->rx_enable_fpmo = NULL; 6385 mon_ops->mon_neighbour_peers_detach = NULL; 6386 mon_ops->mon_vdev_set_monitor_mode_buf_rings = NULL; 6387 mon_ops->mon_vdev_set_monitor_mode_rings = NULL; 6388 #ifdef QCA_ENHANCED_STATS_SUPPORT 6389 mon_ops->mon_rx_stats_update = NULL; 6390 mon_ops->mon_rx_populate_ppdu_usr_info = NULL; 6391 mon_ops->mon_rx_populate_ppdu_info = NULL; 6392 #endif 6393 } 6394 6395 QDF_STATUS dp_mon_soc_attach(struct dp_soc *soc) 6396 { 6397 struct dp_mon_soc *mon_soc; 6398 6399 if (!soc) { 6400 dp_mon_err("dp_soc is NULL"); 6401 return QDF_STATUS_E_FAILURE; 6402 } 6403 6404 mon_soc = (struct dp_mon_soc *)qdf_mem_malloc(sizeof(*mon_soc)); 6405 if (!mon_soc) { 6406 dp_mon_err("%pK: mem allocation failed", soc); 6407 return QDF_STATUS_E_NOMEM; 6408 } 6409 /* register monitor ops */ 6410 soc->monitor_soc = mon_soc; 6411 dp_mon_ops_register(soc); 6412 dp_mon_register_intr_ops(soc); 6413 6414 dp_mon_cdp_ops_register(soc); 6415 dp_mon_register_feature_ops(soc); 6416 return QDF_STATUS_SUCCESS; 6417 } 6418 6419 QDF_STATUS dp_mon_soc_detach(struct dp_soc *soc) 6420 { 6421 struct dp_mon_soc *mon_soc; 6422 6423 if (!soc) { 6424 dp_mon_err("dp_soc is NULL"); 6425 return QDF_STATUS_E_FAILURE; 6426 } 6427 6428 mon_soc = soc->monitor_soc; 6429 dp_monitor_vdev_timer_deinit(soc); 6430 dp_mon_cdp_ops_deregister(soc); 6431 soc->monitor_soc = NULL; 6432 qdf_mem_free(mon_soc); 6433 return QDF_STATUS_SUCCESS; 6434 } 6435