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