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_pdev_clear_link_airtime_stats- clear pdev airtime stats for current index 2055 * @peer : Datapath peer 2056 */ 2057 static inline 2058 void dp_pdev_clear_link_airtime_stats(struct dp_pdev *pdev) 2059 { 2060 uint8_t ac; 2061 2062 for (ac = 0; ac < WME_AC_MAX; ac++) 2063 pdev->stats.telemetry_stats.link_airtime[ac] = 0; 2064 } 2065 2066 /* dp_peer_update_telemetry_stats- update peer telemetry stats 2067 * @peer : Datapath peer 2068 */ 2069 static inline 2070 void dp_peer_update_telemetry_stats(struct dp_peer *peer) 2071 { 2072 struct dp_pdev *pdev; 2073 struct dp_vdev *vdev; 2074 struct dp_mon_peer *mon_peer = NULL; 2075 uint8_t ac; 2076 2077 vdev = peer->vdev; 2078 if (!vdev) 2079 return; 2080 2081 pdev = vdev->pdev; 2082 if (!pdev) 2083 return; 2084 2085 mon_peer = peer->monitor_peer; 2086 if (qdf_likely(mon_peer)) { 2087 DP_STATS_INC(pdev, telemetry_stats.tx_mpdu_failed, 2088 mon_peer->stats.tx.retries); 2089 DP_STATS_INC(pdev, telemetry_stats.tx_mpdu_total, 2090 mon_peer->stats.tx.tx_mpdus_tried); 2091 for (ac = 0; ac < WME_AC_MAX; ac++) { 2092 mon_peer->stats.airtime_consumption[ac].avg_consumption_per_sec = 2093 mon_peer->stats.airtime_consumption[ac].consumption; 2094 /* Store each peer airtime consumption in pdev 2095 * link_airtime to calculate pdev's total airtime 2096 * consumption 2097 */ 2098 DP_STATS_INC( 2099 pdev, 2100 telemetry_stats.link_airtime[ac], 2101 mon_peer->stats.airtime_consumption[ac].consumption); 2102 mon_peer->stats.airtime_consumption[ac].consumption = 0; 2103 } 2104 } 2105 } 2106 #else 2107 static inline 2108 void dp_pdev_clear_link_airtime_stats(struct dp_pdev *pdev) 2109 { } 2110 2111 static inline 2112 void dp_peer_update_telemetry_stats(struct dp_peer *peer) 2113 { } 2114 #endif 2115 2116 /*dp_peer_cal_clients_stats_update - update peer stats on cal client timer 2117 * @soc : Datapath SOC 2118 * @peer : Datapath peer 2119 * @arg : argument to iter function 2120 */ 2121 #ifdef IPA_OFFLOAD 2122 static void 2123 dp_peer_cal_clients_stats_update(struct dp_soc *soc, 2124 struct dp_peer *peer, 2125 void *arg) 2126 { 2127 struct cdp_calibr_stats_intf peer_stats_intf = {0}; 2128 struct dp_peer *tgt_peer = NULL; 2129 struct dp_txrx_peer *txrx_peer = NULL; 2130 2131 dp_peer_update_telemetry_stats(peer); 2132 2133 if (!dp_peer_is_primary_link_peer(peer)) 2134 return; 2135 2136 tgt_peer = dp_get_tgt_peer_from_peer(peer); 2137 if (!tgt_peer || !(tgt_peer->txrx_peer)) 2138 return; 2139 2140 txrx_peer = tgt_peer->txrx_peer; 2141 peer_stats_intf.to_stack = txrx_peer->to_stack; 2142 peer_stats_intf.tx_success = 2143 peer->monitor_peer->stats.tx.tx_ucast_success; 2144 peer_stats_intf.tx_ucast = 2145 peer->monitor_peer->stats.tx.tx_ucast_total; 2146 2147 dp_cal_client_update_peer_stats_wifi3(&peer_stats_intf, 2148 &tgt_peer->stats); 2149 dp_peer_get_rxtid_stats_ipa(peer, dp_peer_update_tid_stats_from_reo); 2150 } 2151 #else 2152 static void 2153 dp_peer_cal_clients_stats_update(struct dp_soc *soc, 2154 struct dp_peer *peer, 2155 void *arg) 2156 { 2157 struct cdp_calibr_stats_intf peer_stats_intf = {0}; 2158 struct dp_peer *tgt_peer = NULL; 2159 struct dp_txrx_peer *txrx_peer = NULL; 2160 2161 dp_peer_update_telemetry_stats(peer); 2162 2163 if (!dp_peer_is_primary_link_peer(peer)) 2164 return; 2165 2166 tgt_peer = dp_get_tgt_peer_from_peer(peer); 2167 if (!tgt_peer || !(tgt_peer->txrx_peer)) 2168 return; 2169 2170 txrx_peer = tgt_peer->txrx_peer; 2171 peer_stats_intf.to_stack = txrx_peer->to_stack; 2172 peer_stats_intf.tx_success = 2173 txrx_peer->stats.per_pkt_stats.tx.tx_success; 2174 peer_stats_intf.tx_ucast = 2175 txrx_peer->stats.per_pkt_stats.tx.ucast; 2176 2177 dp_cal_client_update_peer_stats_wifi3(&peer_stats_intf, 2178 &tgt_peer->stats); 2179 } 2180 #endif 2181 2182 /*dp_iterate_update_peer_list - update peer stats on cal client timer 2183 * @pdev_hdl: pdev handle 2184 */ 2185 static void dp_iterate_update_peer_list(struct cdp_pdev *pdev_hdl) 2186 { 2187 struct dp_pdev *pdev = (struct dp_pdev *)pdev_hdl; 2188 2189 /* Clear current airtime stats as the below API will increment the stats 2190 * for all peers on top of current value 2191 */ 2192 dp_pdev_clear_link_airtime_stats(pdev); 2193 dp_pdev_iterate_peer(pdev, dp_peer_cal_clients_stats_update, NULL, 2194 DP_MOD_ID_CDP); 2195 } 2196 #else 2197 static void dp_iterate_update_peer_list(struct cdp_pdev *pdev_hdl) 2198 { 2199 } 2200 #endif 2201 2202 #ifdef ATH_SUPPORT_NAC 2203 int dp_set_filter_neigh_peers(struct dp_pdev *pdev, 2204 bool val) 2205 { 2206 /* Enable/Disable smart mesh filtering. This flag will be checked 2207 * during rx processing to check if packets are from NAC clients. 2208 */ 2209 pdev->monitor_pdev->filter_neighbour_peers = val; 2210 return 0; 2211 } 2212 #endif /* ATH_SUPPORT_NAC */ 2213 2214 #ifdef WLAN_ATF_ENABLE 2215 void dp_set_atf_stats_enable(struct dp_pdev *pdev, bool value) 2216 { 2217 if (!pdev) { 2218 dp_cdp_err("Invalid pdev"); 2219 return; 2220 } 2221 2222 pdev->monitor_pdev->dp_atf_stats_enable = value; 2223 } 2224 #endif 2225 2226 #ifdef QCA_ENHANCED_STATS_SUPPORT 2227 /* 2228 * dp_process_ppdu_stats_tx_mgmtctrl_payload_tlv: Process 2229 * htt_ppdu_stats_tx_mgmtctrl_payload_tlv 2230 * @pdev: DP PDEV handle 2231 * @tag_buf: buffer containing the htt_ppdu_stats_tx_mgmtctrl_payload_tlv 2232 * @length: tlv_length 2233 * 2234 * return:QDF_STATUS_SUCCESS if nbuf has to be freed in caller 2235 */ 2236 QDF_STATUS 2237 dp_process_ppdu_stats_tx_mgmtctrl_payload_tlv(struct dp_pdev *pdev, 2238 qdf_nbuf_t tag_buf, 2239 uint32_t ppdu_id) 2240 { 2241 uint32_t *nbuf_ptr; 2242 uint8_t trim_size; 2243 size_t head_size; 2244 struct cdp_tx_mgmt_comp_info *ptr_mgmt_comp_info; 2245 uint32_t *msg_word; 2246 uint32_t tsf_hdr; 2247 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 2248 2249 if ((!mon_pdev->tx_sniffer_enable) && (!mon_pdev->mcopy_mode) && 2250 (!mon_pdev->bpr_enable) && (!mon_pdev->tx_capture_enabled)) 2251 return QDF_STATUS_SUCCESS; 2252 2253 /* 2254 * get timestamp from htt_t2h_ppdu_stats_ind_hdr_t 2255 */ 2256 msg_word = (uint32_t *)qdf_nbuf_data(tag_buf); 2257 msg_word = msg_word + 2; 2258 tsf_hdr = *msg_word; 2259 2260 trim_size = ((mon_pdev->mgmtctrl_frm_info.mgmt_buf + 2261 HTT_MGMT_CTRL_TLV_HDR_RESERVERD_LEN) - 2262 qdf_nbuf_data(tag_buf)); 2263 2264 if (!qdf_nbuf_pull_head(tag_buf, trim_size)) 2265 return QDF_STATUS_SUCCESS; 2266 2267 qdf_nbuf_trim_tail(tag_buf, qdf_nbuf_len(tag_buf) - 2268 mon_pdev->mgmtctrl_frm_info.mgmt_buf_len); 2269 2270 if (mon_pdev->tx_capture_enabled) { 2271 head_size = sizeof(struct cdp_tx_mgmt_comp_info); 2272 if (qdf_unlikely(qdf_nbuf_headroom(tag_buf) < head_size)) { 2273 qdf_err("Fail to get headroom h_sz %zu h_avail %d\n", 2274 head_size, qdf_nbuf_headroom(tag_buf)); 2275 qdf_assert_always(0); 2276 return QDF_STATUS_E_NOMEM; 2277 } 2278 ptr_mgmt_comp_info = (struct cdp_tx_mgmt_comp_info *) 2279 qdf_nbuf_push_head(tag_buf, head_size); 2280 qdf_assert_always(ptr_mgmt_comp_info); 2281 ptr_mgmt_comp_info->ppdu_id = ppdu_id; 2282 ptr_mgmt_comp_info->is_sgen_pkt = true; 2283 ptr_mgmt_comp_info->tx_tsf = tsf_hdr; 2284 } else { 2285 head_size = sizeof(ppdu_id); 2286 nbuf_ptr = (uint32_t *)qdf_nbuf_push_head(tag_buf, head_size); 2287 *nbuf_ptr = ppdu_id; 2288 } 2289 if (mon_pdev->bpr_enable) { 2290 dp_wdi_event_handler(WDI_EVENT_TX_BEACON, pdev->soc, 2291 tag_buf, HTT_INVALID_PEER, 2292 WDI_NO_VAL, pdev->pdev_id); 2293 } 2294 2295 dp_deliver_mgmt_frm(pdev, tag_buf); 2296 2297 return QDF_STATUS_E_ALREADY; 2298 } 2299 2300 /* 2301 * dp_htt_get_ppdu_sniffer_ampdu_tlv_bitmap() - Get ppdu stats tlv 2302 * bitmap for sniffer mode 2303 * @bitmap: received bitmap 2304 * 2305 * Return: expected bitmap value, returns zero if doesn't match with 2306 * either 64-bit Tx window or 256-bit window tlv bitmap 2307 */ 2308 int 2309 dp_htt_get_ppdu_sniffer_ampdu_tlv_bitmap(uint32_t bitmap) 2310 { 2311 if (bitmap == (HTT_PPDU_SNIFFER_AMPDU_TLV_BITMAP_64)) 2312 return HTT_PPDU_SNIFFER_AMPDU_TLV_BITMAP_64; 2313 else if (bitmap == (HTT_PPDU_SNIFFER_AMPDU_TLV_BITMAP_256)) 2314 return HTT_PPDU_SNIFFER_AMPDU_TLV_BITMAP_256; 2315 2316 return 0; 2317 } 2318 2319 /* 2320 * dp_peer_copy_delay_stats() - copy ppdu stats to peer delayed stats. 2321 * @peer: Datapath peer handle 2322 * @ppdu: User PPDU Descriptor 2323 * @cur_ppdu_id: PPDU_ID 2324 * 2325 * Return: None 2326 * 2327 * on Tx data frame, we may get delayed ba set 2328 * in htt_ppdu_stats_user_common_tlv. which mean we get Block Ack(BA) after we 2329 * request Block Ack Request(BAR). Successful msdu is received only after Block 2330 * Ack. To populate peer stats we need successful msdu(data frame). 2331 * So we hold the Tx data stats on delayed_ba for stats update. 2332 */ 2333 static void 2334 dp_peer_copy_delay_stats(struct dp_peer *peer, 2335 struct cdp_tx_completion_ppdu_user *ppdu, 2336 uint32_t cur_ppdu_id) 2337 { 2338 struct dp_pdev *pdev; 2339 struct dp_vdev *vdev; 2340 struct dp_mon_peer *mon_peer = peer->monitor_peer; 2341 2342 if (mon_peer->last_delayed_ba) { 2343 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 2344 "BA not yet recv for prev delayed ppdu[%d] - cur ppdu[%d]", 2345 mon_peer->last_delayed_ba_ppduid, cur_ppdu_id); 2346 vdev = peer->vdev; 2347 if (vdev) { 2348 pdev = vdev->pdev; 2349 pdev->stats.cdp_delayed_ba_not_recev++; 2350 } 2351 } 2352 2353 mon_peer->delayed_ba_ppdu_stats.ltf_size = ppdu->ltf_size; 2354 mon_peer->delayed_ba_ppdu_stats.stbc = ppdu->stbc; 2355 mon_peer->delayed_ba_ppdu_stats.he_re = ppdu->he_re; 2356 mon_peer->delayed_ba_ppdu_stats.txbf = ppdu->txbf; 2357 mon_peer->delayed_ba_ppdu_stats.bw = ppdu->bw; 2358 mon_peer->delayed_ba_ppdu_stats.nss = ppdu->nss; 2359 mon_peer->delayed_ba_ppdu_stats.gi = ppdu->gi; 2360 mon_peer->delayed_ba_ppdu_stats.dcm = ppdu->dcm; 2361 mon_peer->delayed_ba_ppdu_stats.ldpc = ppdu->ldpc; 2362 mon_peer->delayed_ba_ppdu_stats.dcm = ppdu->dcm; 2363 mon_peer->delayed_ba_ppdu_stats.mpdu_tried_ucast = 2364 ppdu->mpdu_tried_ucast; 2365 mon_peer->delayed_ba_ppdu_stats.mpdu_tried_mcast = 2366 ppdu->mpdu_tried_mcast; 2367 mon_peer->delayed_ba_ppdu_stats.frame_ctrl = ppdu->frame_ctrl; 2368 mon_peer->delayed_ba_ppdu_stats.qos_ctrl = ppdu->qos_ctrl; 2369 mon_peer->delayed_ba_ppdu_stats.dcm = ppdu->dcm; 2370 2371 mon_peer->delayed_ba_ppdu_stats.ru_start = ppdu->ru_start; 2372 mon_peer->delayed_ba_ppdu_stats.ru_tones = ppdu->ru_tones; 2373 mon_peer->delayed_ba_ppdu_stats.is_mcast = ppdu->is_mcast; 2374 2375 mon_peer->delayed_ba_ppdu_stats.user_pos = ppdu->user_pos; 2376 mon_peer->delayed_ba_ppdu_stats.mu_group_id = ppdu->mu_group_id; 2377 2378 mon_peer->last_delayed_ba = true; 2379 2380 ppdu->debug_copied = true; 2381 } 2382 2383 /* 2384 * dp_peer_copy_stats_to_bar() - copy delayed stats to ppdu stats. 2385 * @peer: Datapath peer handle 2386 * @ppdu: PPDU Descriptor 2387 * 2388 * Return: None 2389 * 2390 * For Tx BAR, PPDU stats TLV include Block Ack info. PPDU info 2391 * from Tx BAR frame not required to populate peer stats. 2392 * But we need successful MPDU and MSDU to update previous 2393 * transmitted Tx data frame. Overwrite ppdu stats with the previous 2394 * stored ppdu stats. 2395 */ 2396 static void 2397 dp_peer_copy_stats_to_bar(struct dp_peer *peer, 2398 struct cdp_tx_completion_ppdu_user *ppdu) 2399 { 2400 struct dp_mon_peer *mon_peer = peer->monitor_peer; 2401 2402 ppdu->ltf_size = mon_peer->delayed_ba_ppdu_stats.ltf_size; 2403 ppdu->stbc = mon_peer->delayed_ba_ppdu_stats.stbc; 2404 ppdu->he_re = mon_peer->delayed_ba_ppdu_stats.he_re; 2405 ppdu->txbf = mon_peer->delayed_ba_ppdu_stats.txbf; 2406 ppdu->bw = mon_peer->delayed_ba_ppdu_stats.bw; 2407 ppdu->nss = mon_peer->delayed_ba_ppdu_stats.nss; 2408 ppdu->gi = mon_peer->delayed_ba_ppdu_stats.gi; 2409 ppdu->dcm = mon_peer->delayed_ba_ppdu_stats.dcm; 2410 ppdu->ldpc = mon_peer->delayed_ba_ppdu_stats.ldpc; 2411 ppdu->dcm = mon_peer->delayed_ba_ppdu_stats.dcm; 2412 ppdu->mpdu_tried_ucast = 2413 mon_peer->delayed_ba_ppdu_stats.mpdu_tried_ucast; 2414 ppdu->mpdu_tried_mcast = 2415 mon_peer->delayed_ba_ppdu_stats.mpdu_tried_mcast; 2416 ppdu->frame_ctrl = mon_peer->delayed_ba_ppdu_stats.frame_ctrl; 2417 ppdu->qos_ctrl = mon_peer->delayed_ba_ppdu_stats.qos_ctrl; 2418 ppdu->dcm = mon_peer->delayed_ba_ppdu_stats.dcm; 2419 2420 ppdu->ru_start = mon_peer->delayed_ba_ppdu_stats.ru_start; 2421 ppdu->ru_tones = mon_peer->delayed_ba_ppdu_stats.ru_tones; 2422 ppdu->is_mcast = mon_peer->delayed_ba_ppdu_stats.is_mcast; 2423 2424 ppdu->user_pos = mon_peer->delayed_ba_ppdu_stats.user_pos; 2425 ppdu->mu_group_id = mon_peer->delayed_ba_ppdu_stats.mu_group_id; 2426 2427 mon_peer->last_delayed_ba = false; 2428 2429 ppdu->debug_copied = true; 2430 } 2431 2432 /* 2433 * dp_tx_rate_stats_update() - Update rate per-peer statistics 2434 * @peer: Datapath peer handle 2435 * @ppdu: PPDU Descriptor 2436 * 2437 * Return: None 2438 */ 2439 static void 2440 dp_tx_rate_stats_update(struct dp_peer *peer, 2441 struct cdp_tx_completion_ppdu_user *ppdu) 2442 { 2443 uint32_t ratekbps = 0; 2444 uint64_t ppdu_tx_rate = 0; 2445 uint32_t rix; 2446 uint16_t ratecode = 0; 2447 struct dp_mon_peer *mon_peer = NULL; 2448 2449 if (!peer || !ppdu) 2450 return; 2451 2452 if (ppdu->completion_status != HTT_PPDU_STATS_USER_STATUS_OK) 2453 return; 2454 2455 mon_peer = peer->monitor_peer; 2456 if (!mon_peer) 2457 return; 2458 2459 ratekbps = dp_getrateindex(ppdu->gi, 2460 ppdu->mcs, 2461 ppdu->nss, 2462 ppdu->preamble, 2463 ppdu->bw, 2464 ppdu->punc_mode, 2465 &rix, 2466 &ratecode); 2467 2468 if (!ratekbps) 2469 return; 2470 2471 /* Calculate goodput in non-training period 2472 * In training period, don't do anything as 2473 * pending pkt is send as goodput. 2474 */ 2475 if ((!peer->bss_peer) && (!ppdu->sa_is_training)) { 2476 ppdu->sa_goodput = ((ratekbps / CDP_NUM_KB_IN_MB) * 2477 (CDP_PERCENT_MACRO - ppdu->current_rate_per)); 2478 } 2479 ppdu->rix = rix; 2480 ppdu->tx_ratekbps = ratekbps; 2481 ppdu->tx_ratecode = ratecode; 2482 DP_STATS_UPD(mon_peer, tx.tx_rate, ratekbps); 2483 mon_peer->stats.tx.avg_tx_rate = 2484 dp_ath_rate_lpf(mon_peer->stats.tx.avg_tx_rate, ratekbps); 2485 ppdu_tx_rate = dp_ath_rate_out(mon_peer->stats.tx.avg_tx_rate); 2486 DP_STATS_UPD(mon_peer, tx.rnd_avg_tx_rate, ppdu_tx_rate); 2487 2488 mon_peer->stats.tx.bw_info = ppdu->bw; 2489 mon_peer->stats.tx.gi_info = ppdu->gi; 2490 mon_peer->stats.tx.nss_info = ppdu->nss; 2491 mon_peer->stats.tx.mcs_info = ppdu->mcs; 2492 mon_peer->stats.tx.preamble_info = ppdu->preamble; 2493 if (peer->vdev) { 2494 /* 2495 * In STA mode: 2496 * We get ucast stats as BSS peer stats. 2497 * 2498 * In AP mode: 2499 * We get mcast stats as BSS peer stats. 2500 * We get ucast stats as assoc peer stats. 2501 */ 2502 if (peer->vdev->opmode == wlan_op_mode_ap && peer->bss_peer) { 2503 peer->vdev->stats.tx.mcast_last_tx_rate = ratekbps; 2504 peer->vdev->stats.tx.mcast_last_tx_rate_mcs = ppdu->mcs; 2505 } else { 2506 peer->vdev->stats.tx.last_tx_rate = ratekbps; 2507 peer->vdev->stats.tx.last_tx_rate_mcs = ppdu->mcs; 2508 } 2509 } 2510 } 2511 2512 #if defined(FEATURE_PERPKT_INFO) && defined(WDI_EVENT_ENABLE) 2513 void dp_send_stats_event(struct dp_pdev *pdev, struct dp_peer *peer, 2514 uint16_t peer_id) 2515 { 2516 struct cdp_interface_peer_stats peer_stats_intf = {0}; 2517 struct dp_mon_peer *mon_peer = peer->monitor_peer; 2518 struct dp_txrx_peer *txrx_peer = NULL; 2519 2520 if (qdf_unlikely(!mon_peer)) 2521 return; 2522 2523 mon_peer->stats.rx.rx_snr_measured_time = qdf_system_ticks(); 2524 peer_stats_intf.rx_avg_snr = mon_peer->stats.rx.avg_snr; 2525 2526 txrx_peer = dp_get_txrx_peer(peer); 2527 if (qdf_likely(txrx_peer)) { 2528 peer_stats_intf.rx_byte_count = txrx_peer->to_stack.bytes; 2529 peer_stats_intf.tx_byte_count = 2530 txrx_peer->stats.per_pkt_stats.tx.tx_success.bytes; 2531 } 2532 2533 dp_wdi_event_handler(WDI_EVENT_UPDATE_DP_STATS, pdev->soc, 2534 &peer_stats_intf, peer_id, 2535 UPDATE_PEER_STATS, pdev->pdev_id); 2536 } 2537 #endif 2538 2539 #ifdef WLAN_FEATURE_11BE 2540 /* 2541 * dp_get_ru_index_frm_ru_tones() - get ru index 2542 * @ru_tones: ru tones 2543 * 2544 * Return: ru index 2545 */ 2546 static inline enum cdp_ru_index dp_get_ru_index_frm_ru_tones(uint16_t ru_tones) 2547 { 2548 enum cdp_ru_index ru_index; 2549 2550 switch (ru_tones) { 2551 case RU_26: 2552 ru_index = RU_26_INDEX; 2553 break; 2554 case RU_52: 2555 ru_index = RU_52_INDEX; 2556 break; 2557 case RU_52_26: 2558 ru_index = RU_52_26_INDEX; 2559 break; 2560 case RU_106: 2561 ru_index = RU_106_INDEX; 2562 break; 2563 case RU_106_26: 2564 ru_index = RU_106_26_INDEX; 2565 break; 2566 case RU_242: 2567 ru_index = RU_242_INDEX; 2568 break; 2569 case RU_484: 2570 ru_index = RU_484_INDEX; 2571 break; 2572 case RU_484_242: 2573 ru_index = RU_484_242_INDEX; 2574 break; 2575 case RU_996: 2576 ru_index = RU_996_INDEX; 2577 break; 2578 case RU_996_484: 2579 ru_index = RU_996_484_INDEX; 2580 break; 2581 case RU_996_484_242: 2582 ru_index = RU_996_484_242_INDEX; 2583 break; 2584 case RU_2X996: 2585 ru_index = RU_2X996_INDEX; 2586 break; 2587 case RU_2X996_484: 2588 ru_index = RU_2X996_484_INDEX; 2589 break; 2590 case RU_3X996: 2591 ru_index = RU_3X996_INDEX; 2592 break; 2593 case RU_3X996_484: 2594 ru_index = RU_2X996_484_INDEX; 2595 break; 2596 case RU_4X996: 2597 ru_index = RU_4X996_INDEX; 2598 break; 2599 default: 2600 ru_index = RU_INDEX_MAX; 2601 break; 2602 } 2603 2604 return ru_index; 2605 } 2606 2607 /* 2608 * dp_mon_get_ru_width_from_ru_size() - get ru_width from ru_size enum 2609 * @ru_size: HTT ru_size enum 2610 * 2611 * Return: ru_width of uint32_t type 2612 */ 2613 static uint32_t dp_mon_get_ru_width_from_ru_size(uint16_t ru_size) 2614 { 2615 uint32_t width = 0; 2616 2617 switch (ru_size) { 2618 case HTT_PPDU_STATS_RU_26: 2619 width = RU_26; 2620 break; 2621 case HTT_PPDU_STATS_RU_52: 2622 width = RU_52; 2623 break; 2624 case HTT_PPDU_STATS_RU_52_26: 2625 width = RU_52_26; 2626 break; 2627 case HTT_PPDU_STATS_RU_106: 2628 width = RU_106; 2629 break; 2630 case HTT_PPDU_STATS_RU_106_26: 2631 width = RU_106_26; 2632 break; 2633 case HTT_PPDU_STATS_RU_242: 2634 width = RU_242; 2635 break; 2636 case HTT_PPDU_STATS_RU_484: 2637 width = RU_484; 2638 break; 2639 case HTT_PPDU_STATS_RU_484_242: 2640 width = RU_484_242; 2641 break; 2642 case HTT_PPDU_STATS_RU_996: 2643 width = RU_996; 2644 break; 2645 case HTT_PPDU_STATS_RU_996_484: 2646 width = RU_996_484; 2647 break; 2648 case HTT_PPDU_STATS_RU_996_484_242: 2649 width = RU_996_484_242; 2650 break; 2651 case HTT_PPDU_STATS_RU_996x2: 2652 width = RU_2X996; 2653 break; 2654 case HTT_PPDU_STATS_RU_996x2_484: 2655 width = RU_2X996_484; 2656 break; 2657 case HTT_PPDU_STATS_RU_996x3: 2658 width = RU_3X996; 2659 break; 2660 case HTT_PPDU_STATS_RU_996x3_484: 2661 width = RU_3X996_484; 2662 break; 2663 case HTT_PPDU_STATS_RU_996x4: 2664 width = RU_4X996; 2665 break; 2666 default: 2667 dp_mon_debug("Unsupported ru_size: %d rcvd", ru_size); 2668 } 2669 2670 return width; 2671 } 2672 #else 2673 static inline enum cdp_ru_index dp_get_ru_index_frm_ru_tones(uint16_t ru_tones) 2674 { 2675 enum cdp_ru_index ru_index; 2676 2677 switch (ru_tones) { 2678 case RU_26: 2679 ru_index = RU_26_INDEX; 2680 break; 2681 case RU_52: 2682 ru_index = RU_52_INDEX; 2683 break; 2684 case RU_106: 2685 ru_index = RU_106_INDEX; 2686 break; 2687 case RU_242: 2688 ru_index = RU_242_INDEX; 2689 break; 2690 case RU_484: 2691 ru_index = RU_484_INDEX; 2692 break; 2693 case RU_996: 2694 ru_index = RU_996_INDEX; 2695 break; 2696 default: 2697 ru_index = RU_INDEX_MAX; 2698 break; 2699 } 2700 2701 return ru_index; 2702 } 2703 2704 static uint32_t dp_mon_get_ru_width_from_ru_size(uint16_t ru_size) 2705 { 2706 uint32_t width = 0; 2707 2708 switch (ru_size) { 2709 case HTT_PPDU_STATS_RU_26: 2710 width = RU_26; 2711 break; 2712 case HTT_PPDU_STATS_RU_52: 2713 width = RU_52; 2714 break; 2715 case HTT_PPDU_STATS_RU_106: 2716 width = RU_106; 2717 break; 2718 case HTT_PPDU_STATS_RU_242: 2719 width = RU_242; 2720 break; 2721 case HTT_PPDU_STATS_RU_484: 2722 width = RU_484; 2723 break; 2724 case HTT_PPDU_STATS_RU_996: 2725 width = RU_996; 2726 break; 2727 default: 2728 dp_mon_debug("Unsupported ru_size: %d rcvd", ru_size); 2729 } 2730 2731 return width; 2732 } 2733 #endif 2734 2735 /* 2736 * dp_tx_stats_update() - Update per-peer statistics 2737 * @pdev: Datapath pdev handle 2738 * @peer: Datapath peer handle 2739 * @ppdu: PPDU Descriptor 2740 * @ack_rssi: RSSI of last ack received 2741 * 2742 * Return: None 2743 */ 2744 static void 2745 dp_tx_stats_update(struct dp_pdev *pdev, struct dp_peer *peer, 2746 struct cdp_tx_completion_ppdu_user *ppdu, 2747 uint32_t ack_rssi) 2748 { 2749 uint8_t preamble, mcs; 2750 uint16_t num_msdu; 2751 uint16_t num_mpdu; 2752 uint16_t mpdu_tried; 2753 uint16_t mpdu_failed; 2754 struct dp_mon_ops *mon_ops; 2755 enum cdp_ru_index ru_index; 2756 struct dp_mon_peer *mon_peer = NULL; 2757 uint32_t ratekbps = 0; 2758 uint64_t tx_byte_count; 2759 2760 preamble = ppdu->preamble; 2761 mcs = ppdu->mcs; 2762 num_msdu = ppdu->num_msdu; 2763 num_mpdu = ppdu->mpdu_success; 2764 mpdu_tried = ppdu->mpdu_tried_ucast + ppdu->mpdu_tried_mcast; 2765 mpdu_failed = mpdu_tried - num_mpdu; 2766 tx_byte_count = ppdu->success_bytes; 2767 2768 /* If the peer statistics are already processed as part of 2769 * per-MSDU completion handler, do not process these again in per-PPDU 2770 * indications 2771 */ 2772 if (pdev->soc->process_tx_status) 2773 return; 2774 2775 mon_peer = peer->monitor_peer; 2776 if (!mon_peer) 2777 return; 2778 2779 if (!ppdu->is_mcast) { 2780 DP_STATS_INC(mon_peer, tx.tx_ucast_total.num, num_msdu); 2781 DP_STATS_INC(mon_peer, tx.tx_ucast_total.bytes, 2782 tx_byte_count); 2783 } 2784 2785 if (ppdu->completion_status != HTT_PPDU_STATS_USER_STATUS_OK) { 2786 /* 2787 * All failed mpdu will be retried, so incrementing 2788 * retries mpdu based on mpdu failed. Even for 2789 * ack failure i.e for long retries we get 2790 * mpdu failed equal mpdu tried. 2791 */ 2792 DP_STATS_INC(mon_peer, tx.retries, mpdu_failed); 2793 return; 2794 } 2795 2796 if (ppdu->is_ppdu_cookie_valid) 2797 DP_STATS_INC(mon_peer, tx.num_ppdu_cookie_valid, 1); 2798 2799 if (ppdu->mu_group_id <= MAX_MU_GROUP_ID && 2800 ppdu->ppdu_type != HTT_PPDU_STATS_PPDU_TYPE_SU) { 2801 if (qdf_unlikely(ppdu->mu_group_id && 2802 !(ppdu->mu_group_id & (MAX_MU_GROUP_ID - 1)))) 2803 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 2804 "mu_group_id out of bound!!\n"); 2805 else 2806 DP_STATS_UPD(mon_peer, tx.mu_group_id[ppdu->mu_group_id], 2807 (ppdu->user_pos + 1)); 2808 } 2809 2810 if (ppdu->ppdu_type == HTT_PPDU_STATS_PPDU_TYPE_MU_OFDMA || 2811 ppdu->ppdu_type == HTT_PPDU_STATS_PPDU_TYPE_MU_MIMO_OFDMA) { 2812 DP_STATS_UPD(mon_peer, tx.ru_tones, ppdu->ru_tones); 2813 DP_STATS_UPD(mon_peer, tx.ru_start, ppdu->ru_start); 2814 ru_index = dp_get_ru_index_frm_ru_tones(ppdu->ru_tones); 2815 if (ru_index != RU_INDEX_MAX) { 2816 DP_STATS_INC(mon_peer, tx.ru_loc[ru_index].num_msdu, 2817 num_msdu); 2818 DP_STATS_INC(mon_peer, tx.ru_loc[ru_index].num_mpdu, 2819 num_mpdu); 2820 DP_STATS_INC(mon_peer, tx.ru_loc[ru_index].mpdu_tried, 2821 mpdu_tried); 2822 } 2823 } 2824 2825 /* 2826 * All failed mpdu will be retried, so incrementing 2827 * retries mpdu based on mpdu failed. Even for 2828 * ack failure i.e for long retries we get 2829 * mpdu failed equal mpdu tried. 2830 */ 2831 DP_STATS_INC(mon_peer, tx.retries, mpdu_failed); 2832 2833 DP_STATS_INC(mon_peer, tx.transmit_type[ppdu->ppdu_type].num_msdu, 2834 num_msdu); 2835 DP_STATS_INC(mon_peer, tx.transmit_type[ppdu->ppdu_type].num_mpdu, 2836 num_mpdu); 2837 DP_STATS_INC(mon_peer, tx.transmit_type[ppdu->ppdu_type].mpdu_tried, 2838 mpdu_tried); 2839 2840 DP_STATS_INC(mon_peer, tx.sgi_count[ppdu->gi], num_msdu); 2841 DP_STATS_INC(mon_peer, tx.bw[ppdu->bw], num_msdu); 2842 DP_STATS_INC(mon_peer, tx.nss[ppdu->nss], num_msdu); 2843 if (ppdu->tid < CDP_DATA_TID_MAX) 2844 DP_STATS_INC(mon_peer, tx.wme_ac_type[TID_TO_WME_AC(ppdu->tid)], 2845 num_msdu); 2846 DP_STATS_INCC(mon_peer, tx.stbc, num_msdu, ppdu->stbc); 2847 DP_STATS_INCC(mon_peer, tx.ldpc, num_msdu, ppdu->ldpc); 2848 if (!(ppdu->is_mcast) && ppdu->ack_rssi_valid) 2849 DP_STATS_UPD(mon_peer, tx.last_ack_rssi, ack_rssi); 2850 2851 if (!ppdu->is_mcast) { 2852 DP_STATS_INC(mon_peer, tx.tx_ucast_success.num, num_msdu); 2853 DP_STATS_INC(mon_peer, tx.tx_ucast_success.bytes, 2854 tx_byte_count); 2855 } 2856 2857 DP_STATS_INCC(mon_peer, 2858 tx.pkt_type[preamble].mcs_count[MAX_MCS - 1], num_msdu, 2859 ((mcs >= MAX_MCS_11A) && (preamble == DOT11_A))); 2860 DP_STATS_INCC(mon_peer, 2861 tx.pkt_type[preamble].mcs_count[mcs], num_msdu, 2862 ((mcs < MAX_MCS_11A) && (preamble == DOT11_A))); 2863 DP_STATS_INCC(mon_peer, 2864 tx.pkt_type[preamble].mcs_count[MAX_MCS - 1], num_msdu, 2865 ((mcs >= MAX_MCS_11B) && (preamble == DOT11_B))); 2866 DP_STATS_INCC(mon_peer, 2867 tx.pkt_type[preamble].mcs_count[mcs], num_msdu, 2868 ((mcs < (MAX_MCS_11B)) && (preamble == DOT11_B))); 2869 DP_STATS_INCC(mon_peer, 2870 tx.pkt_type[preamble].mcs_count[MAX_MCS - 1], num_msdu, 2871 ((mcs >= MAX_MCS_11A) && (preamble == DOT11_N))); 2872 DP_STATS_INCC(mon_peer, 2873 tx.pkt_type[preamble].mcs_count[mcs], num_msdu, 2874 ((mcs < MAX_MCS_11A) && (preamble == DOT11_N))); 2875 DP_STATS_INCC(mon_peer, 2876 tx.pkt_type[preamble].mcs_count[MAX_MCS - 1], num_msdu, 2877 ((mcs >= MAX_MCS_11AC) && (preamble == DOT11_AC))); 2878 DP_STATS_INCC(mon_peer, 2879 tx.pkt_type[preamble].mcs_count[mcs], num_msdu, 2880 ((mcs < MAX_MCS_11AC) && (preamble == DOT11_AC))); 2881 DP_STATS_INCC(mon_peer, 2882 tx.pkt_type[preamble].mcs_count[MAX_MCS - 1], num_msdu, 2883 ((mcs >= MAX_MCS_11AX) && (preamble == DOT11_AX))); 2884 DP_STATS_INCC(mon_peer, 2885 tx.pkt_type[preamble].mcs_count[mcs], num_msdu, 2886 ((mcs < MAX_MCS_11AX) && (preamble == DOT11_AX))); 2887 DP_STATS_INCC(mon_peer, tx.ampdu_cnt, num_mpdu, ppdu->is_ampdu); 2888 DP_STATS_INCC(mon_peer, tx.non_ampdu_cnt, num_mpdu, !(ppdu->is_ampdu)); 2889 DP_STATS_INCC(mon_peer, tx.pream_punct_cnt, 1, ppdu->pream_punct); 2890 DP_STATS_INC(mon_peer, tx.tx_ppdus, 1); 2891 DP_STATS_INC(mon_peer, tx.tx_mpdus_success, num_mpdu); 2892 DP_STATS_INC(mon_peer, tx.tx_mpdus_tried, mpdu_tried); 2893 2894 mon_ops = dp_mon_ops_get(pdev->soc); 2895 if (mon_ops && mon_ops->mon_tx_stats_update) 2896 mon_ops->mon_tx_stats_update(mon_peer, ppdu); 2897 2898 dp_tx_rate_stats_update(peer, ppdu); 2899 2900 dp_peer_stats_notify(pdev, peer); 2901 2902 ratekbps = mon_peer->stats.tx.tx_rate; 2903 DP_STATS_UPD(mon_peer, tx.last_tx_rate, ratekbps); 2904 2905 dp_send_stats_event(pdev, peer, ppdu->peer_id); 2906 } 2907 2908 /* 2909 * dp_get_ppdu_info_user_index: Find and allocate a per-user descriptor for a PPDU, 2910 * if a new peer id arrives in a PPDU 2911 * pdev: DP pdev handle 2912 * @peer_id : peer unique identifier 2913 * @ppdu_info: per ppdu tlv structure 2914 * 2915 * return:user index to be populated 2916 */ 2917 static uint8_t dp_get_ppdu_info_user_index(struct dp_pdev *pdev, 2918 uint16_t peer_id, 2919 struct ppdu_info *ppdu_info) 2920 { 2921 uint8_t user_index = 0; 2922 struct cdp_tx_completion_ppdu *ppdu_desc; 2923 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 2924 2925 ppdu_desc = 2926 (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 2927 2928 while ((user_index + 1) <= ppdu_info->last_user) { 2929 ppdu_user_desc = &ppdu_desc->user[user_index]; 2930 if (ppdu_user_desc->peer_id != peer_id) { 2931 user_index++; 2932 continue; 2933 } else { 2934 /* Max users possible is 8 so user array index should 2935 * not exceed 7 2936 */ 2937 qdf_assert_always(user_index <= (ppdu_desc->max_users - 1)); 2938 return user_index; 2939 } 2940 } 2941 2942 ppdu_info->last_user++; 2943 /* Max users possible is 8 so last user should not exceed 8 */ 2944 qdf_assert_always(ppdu_info->last_user <= ppdu_desc->max_users); 2945 return ppdu_info->last_user - 1; 2946 } 2947 2948 /* 2949 * dp_process_ppdu_stats_common_tlv: Process htt_ppdu_stats_common_tlv 2950 * pdev: DP pdev handle 2951 * @tag_buf: buffer containing the tlv htt_ppdu_stats_common_tlv 2952 * @ppdu_info: per ppdu tlv structure 2953 * 2954 * return:void 2955 */ 2956 static void 2957 dp_process_ppdu_stats_common_tlv(struct dp_pdev *pdev, 2958 uint32_t *tag_buf, 2959 struct ppdu_info *ppdu_info) 2960 { 2961 uint16_t frame_type; 2962 uint16_t frame_ctrl; 2963 uint16_t freq; 2964 struct dp_soc *soc = NULL; 2965 struct cdp_tx_completion_ppdu *ppdu_desc = NULL; 2966 uint64_t ppdu_start_timestamp; 2967 uint32_t *start_tag_buf; 2968 2969 start_tag_buf = tag_buf; 2970 ppdu_desc = 2971 (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 2972 2973 ppdu_desc->ppdu_id = ppdu_info->ppdu_id; 2974 2975 tag_buf = start_tag_buf + HTT_GET_STATS_CMN_INDEX(RING_ID_SCH_CMD_ID); 2976 ppdu_info->sched_cmdid = 2977 HTT_PPDU_STATS_COMMON_TLV_SCH_CMDID_GET(*tag_buf); 2978 ppdu_desc->num_users = 2979 HTT_PPDU_STATS_COMMON_TLV_NUM_USERS_GET(*tag_buf); 2980 2981 qdf_assert_always(ppdu_desc->num_users <= ppdu_desc->max_users); 2982 2983 tag_buf = start_tag_buf + HTT_GET_STATS_CMN_INDEX(QTYPE_FRM_TYPE); 2984 frame_type = HTT_PPDU_STATS_COMMON_TLV_FRM_TYPE_GET(*tag_buf); 2985 ppdu_desc->htt_frame_type = frame_type; 2986 2987 frame_ctrl = ppdu_desc->frame_ctrl; 2988 2989 ppdu_desc->bar_ppdu_id = ppdu_info->ppdu_id; 2990 2991 switch (frame_type) { 2992 case HTT_STATS_FTYPE_TIDQ_DATA_SU: 2993 case HTT_STATS_FTYPE_TIDQ_DATA_MU: 2994 case HTT_STATS_FTYPE_SGEN_QOS_NULL: 2995 /* 2996 * for management packet, frame type come as DATA_SU 2997 * need to check frame_ctrl before setting frame_type 2998 */ 2999 if (HTT_GET_FRAME_CTRL_TYPE(frame_ctrl) <= FRAME_CTRL_TYPE_CTRL) 3000 ppdu_desc->frame_type = CDP_PPDU_FTYPE_CTRL; 3001 else 3002 ppdu_desc->frame_type = CDP_PPDU_FTYPE_DATA; 3003 break; 3004 case HTT_STATS_FTYPE_SGEN_MU_BAR: 3005 case HTT_STATS_FTYPE_SGEN_BAR: 3006 case HTT_STATS_FTYPE_SGEN_BE_MU_BAR: 3007 ppdu_desc->frame_type = CDP_PPDU_FTYPE_BAR; 3008 break; 3009 default: 3010 ppdu_desc->frame_type = CDP_PPDU_FTYPE_CTRL; 3011 break; 3012 } 3013 3014 tag_buf = start_tag_buf + HTT_GET_STATS_CMN_INDEX(FES_DUR_US); 3015 ppdu_desc->tx_duration = *tag_buf; 3016 3017 tag_buf = start_tag_buf + HTT_GET_STATS_CMN_INDEX(START_TSTMP_L32_US); 3018 ppdu_desc->ppdu_start_timestamp = *tag_buf; 3019 3020 tag_buf = start_tag_buf + HTT_GET_STATS_CMN_INDEX(CHAN_MHZ_PHY_MODE); 3021 freq = HTT_PPDU_STATS_COMMON_TLV_CHAN_MHZ_GET(*tag_buf); 3022 if (freq != ppdu_desc->channel) { 3023 soc = pdev->soc; 3024 ppdu_desc->channel = freq; 3025 pdev->operating_channel.freq = freq; 3026 if (soc && soc->cdp_soc.ol_ops->freq_to_channel) 3027 pdev->operating_channel.num = 3028 soc->cdp_soc.ol_ops->freq_to_channel(soc->ctrl_psoc, 3029 pdev->pdev_id, 3030 freq); 3031 3032 if (soc && soc->cdp_soc.ol_ops->freq_to_band) 3033 pdev->operating_channel.band = 3034 soc->cdp_soc.ol_ops->freq_to_band(soc->ctrl_psoc, 3035 pdev->pdev_id, 3036 freq); 3037 } 3038 3039 ppdu_desc->phy_mode = HTT_PPDU_STATS_COMMON_TLV_PHY_MODE_GET(*tag_buf); 3040 3041 tag_buf = start_tag_buf + HTT_GET_STATS_CMN_INDEX(RESV_NUM_UL_BEAM); 3042 ppdu_desc->phy_ppdu_tx_time_us = 3043 HTT_PPDU_STATS_COMMON_TLV_PHY_PPDU_TX_TIME_US_GET(*tag_buf); 3044 ppdu_desc->beam_change = 3045 HTT_PPDU_STATS_COMMON_TLV_BEAM_CHANGE_GET(*tag_buf); 3046 ppdu_desc->doppler = 3047 HTT_PPDU_STATS_COMMON_TLV_DOPPLER_INDICATION_GET(*tag_buf); 3048 ppdu_desc->spatial_reuse = 3049 HTT_PPDU_STATS_COMMON_TLV_SPATIAL_REUSE_GET(*tag_buf); 3050 3051 dp_tx_capture_htt_frame_counter(pdev, frame_type); 3052 3053 tag_buf = start_tag_buf + HTT_GET_STATS_CMN_INDEX(START_TSTMP_U32_US); 3054 ppdu_start_timestamp = *tag_buf; 3055 ppdu_desc->ppdu_start_timestamp |= ((ppdu_start_timestamp << 3056 HTT_SHIFT_UPPER_TIMESTAMP) & 3057 HTT_MASK_UPPER_TIMESTAMP); 3058 3059 ppdu_desc->ppdu_end_timestamp = ppdu_desc->ppdu_start_timestamp + 3060 ppdu_desc->tx_duration; 3061 /* Ack time stamp is same as end time stamp*/ 3062 ppdu_desc->ack_timestamp = ppdu_desc->ppdu_end_timestamp; 3063 3064 ppdu_desc->ppdu_end_timestamp = ppdu_desc->ppdu_start_timestamp + 3065 ppdu_desc->tx_duration; 3066 3067 ppdu_desc->bar_ppdu_start_timestamp = ppdu_desc->ppdu_start_timestamp; 3068 ppdu_desc->bar_ppdu_end_timestamp = ppdu_desc->ppdu_end_timestamp; 3069 ppdu_desc->bar_tx_duration = ppdu_desc->tx_duration; 3070 3071 /* Ack time stamp is same as end time stamp*/ 3072 ppdu_desc->ack_timestamp = ppdu_desc->ppdu_end_timestamp; 3073 3074 tag_buf = start_tag_buf + HTT_GET_STATS_CMN_INDEX(BSSCOLOR_OBSS_PSR); 3075 ppdu_desc->bss_color = 3076 HTT_PPDU_STATS_COMMON_TLV_BSS_COLOR_ID_GET(*tag_buf); 3077 } 3078 3079 /* 3080 * dp_process_ppdu_stats_user_common_tlv: Process ppdu_stats_user_common 3081 * @tag_buf: buffer containing the tlv htt_ppdu_stats_user_common_tlv 3082 * @ppdu_info: per ppdu tlv structure 3083 * 3084 * return:void 3085 */ 3086 static void dp_process_ppdu_stats_user_common_tlv( 3087 struct dp_pdev *pdev, uint32_t *tag_buf, 3088 struct ppdu_info *ppdu_info) 3089 { 3090 uint16_t peer_id; 3091 struct cdp_tx_completion_ppdu *ppdu_desc; 3092 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 3093 uint8_t curr_user_index = 0; 3094 struct dp_peer *peer; 3095 struct dp_vdev *vdev; 3096 uint32_t tlv_type = HTT_STATS_TLV_TAG_GET(*tag_buf); 3097 3098 ppdu_desc = 3099 (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 3100 3101 tag_buf++; 3102 peer_id = HTT_PPDU_STATS_USER_RATE_TLV_SW_PEER_ID_GET(*tag_buf); 3103 3104 curr_user_index = 3105 dp_get_ppdu_info_user_index(pdev, 3106 peer_id, ppdu_info); 3107 ppdu_user_desc = &ppdu_desc->user[curr_user_index]; 3108 ppdu_user_desc->tlv_bitmap |= (1 << tlv_type); 3109 3110 ppdu_desc->vdev_id = 3111 HTT_PPDU_STATS_USER_COMMON_TLV_VAP_ID_GET(*tag_buf); 3112 3113 ppdu_user_desc->peer_id = peer_id; 3114 3115 tag_buf++; 3116 3117 if (HTT_PPDU_STATS_USER_COMMON_TLV_DELAYED_BA_GET(*tag_buf)) { 3118 ppdu_user_desc->delayed_ba = 1; 3119 ppdu_desc->delayed_ba = 1; 3120 } 3121 3122 if (HTT_PPDU_STATS_USER_COMMON_TLV_MCAST_GET(*tag_buf)) { 3123 ppdu_user_desc->is_mcast = true; 3124 ppdu_user_desc->mpdu_tried_mcast = 3125 HTT_PPDU_STATS_USER_COMMON_TLV_MPDUS_TRIED_GET(*tag_buf); 3126 ppdu_user_desc->num_mpdu = ppdu_user_desc->mpdu_tried_mcast; 3127 } else { 3128 ppdu_user_desc->mpdu_tried_ucast = 3129 HTT_PPDU_STATS_USER_COMMON_TLV_MPDUS_TRIED_GET(*tag_buf); 3130 } 3131 3132 ppdu_user_desc->is_seq_num_valid = 3133 HTT_PPDU_STATS_USER_COMMON_TLV_IS_SQNUM_VALID_IN_BUFFER_GET(*tag_buf); 3134 tag_buf++; 3135 3136 ppdu_user_desc->qos_ctrl = 3137 HTT_PPDU_STATS_USER_COMMON_TLV_QOS_CTRL_GET(*tag_buf); 3138 ppdu_user_desc->frame_ctrl = 3139 HTT_PPDU_STATS_USER_COMMON_TLV_FRAME_CTRL_GET(*tag_buf); 3140 ppdu_desc->frame_ctrl = ppdu_user_desc->frame_ctrl; 3141 3142 if (ppdu_user_desc->delayed_ba) 3143 ppdu_user_desc->mpdu_success = 0; 3144 3145 tag_buf += 3; 3146 3147 if (HTT_PPDU_STATS_IS_OPAQUE_VALID_GET(*tag_buf)) { 3148 ppdu_user_desc->ppdu_cookie = 3149 HTT_PPDU_STATS_HOST_OPAQUE_COOKIE_GET(*tag_buf); 3150 ppdu_user_desc->is_ppdu_cookie_valid = 1; 3151 } 3152 3153 /* returning earlier causes other feilds unpopulated */ 3154 if (peer_id == DP_SCAN_PEER_ID) { 3155 vdev = dp_vdev_get_ref_by_id(pdev->soc, ppdu_desc->vdev_id, 3156 DP_MOD_ID_TX_PPDU_STATS); 3157 if (!vdev) 3158 return; 3159 qdf_mem_copy(ppdu_user_desc->mac_addr, vdev->mac_addr.raw, 3160 QDF_MAC_ADDR_SIZE); 3161 dp_vdev_unref_delete(pdev->soc, vdev, DP_MOD_ID_TX_PPDU_STATS); 3162 } else { 3163 peer = dp_peer_get_ref_by_id(pdev->soc, peer_id, 3164 DP_MOD_ID_TX_PPDU_STATS); 3165 if (!peer) { 3166 /* 3167 * fw sends peer_id which is about to removed but 3168 * it was already removed in host. 3169 * eg: for disassoc, fw send ppdu stats 3170 * with peer id equal to previously associated 3171 * peer's peer_id but it was removed 3172 */ 3173 vdev = dp_vdev_get_ref_by_id(pdev->soc, 3174 ppdu_desc->vdev_id, 3175 DP_MOD_ID_TX_PPDU_STATS); 3176 if (!vdev) 3177 return; 3178 qdf_mem_copy(ppdu_user_desc->mac_addr, 3179 vdev->mac_addr.raw, QDF_MAC_ADDR_SIZE); 3180 dp_vdev_unref_delete(pdev->soc, vdev, 3181 DP_MOD_ID_TX_PPDU_STATS); 3182 return; 3183 } 3184 qdf_mem_copy(ppdu_user_desc->mac_addr, 3185 peer->mac_addr.raw, QDF_MAC_ADDR_SIZE); 3186 dp_peer_unref_delete(peer, DP_MOD_ID_TX_PPDU_STATS); 3187 } 3188 } 3189 3190 /** 3191 * dp_process_ppdu_stats_user_rate_tlv() - Process htt_ppdu_stats_user_rate_tlv 3192 * @pdev: DP pdev handle 3193 * @tag_buf: T2H message buffer carrying the user rate TLV 3194 * @ppdu_info: per ppdu tlv structure 3195 * 3196 * return:void 3197 */ 3198 static void 3199 dp_process_ppdu_stats_user_rate_tlv(struct dp_pdev *pdev, 3200 uint32_t *tag_buf, 3201 struct ppdu_info *ppdu_info) 3202 { 3203 uint16_t peer_id; 3204 struct cdp_tx_completion_ppdu *ppdu_desc; 3205 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 3206 uint8_t curr_user_index = 0; 3207 struct dp_vdev *vdev; 3208 uint32_t tlv_type = HTT_STATS_TLV_TAG_GET(*tag_buf); 3209 uint8_t bw, ru_format; 3210 uint16_t ru_size; 3211 3212 ppdu_desc = 3213 (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 3214 3215 tag_buf++; 3216 peer_id = HTT_PPDU_STATS_USER_RATE_TLV_SW_PEER_ID_GET(*tag_buf); 3217 3218 curr_user_index = 3219 dp_get_ppdu_info_user_index(pdev, 3220 peer_id, ppdu_info); 3221 ppdu_user_desc = &ppdu_desc->user[curr_user_index]; 3222 ppdu_user_desc->tlv_bitmap |= (1 << tlv_type); 3223 if (peer_id == DP_SCAN_PEER_ID) { 3224 vdev = dp_vdev_get_ref_by_id(pdev->soc, ppdu_desc->vdev_id, 3225 DP_MOD_ID_TX_PPDU_STATS); 3226 if (!vdev) 3227 return; 3228 dp_vdev_unref_delete(pdev->soc, vdev, 3229 DP_MOD_ID_TX_PPDU_STATS); 3230 } 3231 ppdu_user_desc->peer_id = peer_id; 3232 3233 ppdu_user_desc->tid = 3234 HTT_PPDU_STATS_USER_RATE_TLV_TID_NUM_GET(*tag_buf); 3235 3236 tag_buf += 1; 3237 3238 ppdu_user_desc->user_pos = 3239 HTT_PPDU_STATS_USER_RATE_TLV_USER_POS_GET(*tag_buf); 3240 ppdu_user_desc->mu_group_id = 3241 HTT_PPDU_STATS_USER_RATE_TLV_MU_GROUPID_GET(*tag_buf); 3242 3243 ru_format = HTT_PPDU_STATS_USER_RATE_TLV_RU_FORMAT_GET(*tag_buf); 3244 3245 tag_buf += 1; 3246 3247 if (!ru_format) { 3248 /* ru_format = 0: ru_end, ru_start */ 3249 ppdu_user_desc->ru_start = 3250 HTT_PPDU_STATS_USER_RATE_TLV_RU_START_GET(*tag_buf); 3251 ppdu_user_desc->ru_tones = 3252 (HTT_PPDU_STATS_USER_RATE_TLV_RU_END_GET(*tag_buf) - 3253 HTT_PPDU_STATS_USER_RATE_TLV_RU_START_GET(*tag_buf)) + 1; 3254 } else if (ru_format == 1) { 3255 /* ru_format = 1: ru_index, ru_size */ 3256 ru_size = HTT_PPDU_STATS_USER_RATE_TLV_RU_SIZE_GET(*tag_buf); 3257 ppdu_user_desc->ru_tones = 3258 dp_mon_get_ru_width_from_ru_size(ru_size); 3259 } else { 3260 dp_mon_debug("Unsupported ru_format: %d rcvd", ru_format); 3261 } 3262 ppdu_desc->usr_ru_tones_sum += ppdu_user_desc->ru_tones; 3263 3264 tag_buf += 2; 3265 3266 ppdu_user_desc->ppdu_type = 3267 HTT_PPDU_STATS_USER_RATE_TLV_PPDU_TYPE_GET(*tag_buf); 3268 3269 tag_buf++; 3270 ppdu_user_desc->tx_rate = *tag_buf; 3271 3272 ppdu_user_desc->ltf_size = 3273 HTT_PPDU_STATS_USER_RATE_TLV_LTF_SIZE_GET(*tag_buf); 3274 ppdu_user_desc->stbc = 3275 HTT_PPDU_STATS_USER_RATE_TLV_STBC_GET(*tag_buf); 3276 ppdu_user_desc->he_re = 3277 HTT_PPDU_STATS_USER_RATE_TLV_HE_RE_GET(*tag_buf); 3278 ppdu_user_desc->txbf = 3279 HTT_PPDU_STATS_USER_RATE_TLV_TXBF_GET(*tag_buf); 3280 bw = HTT_PPDU_STATS_USER_RATE_TLV_BW_GET(*tag_buf); 3281 /* Align bw value as per host data structures */ 3282 if (bw == HTT_PPDU_STATS_BANDWIDTH_320MHZ) 3283 ppdu_user_desc->bw = bw - 3; 3284 else 3285 ppdu_user_desc->bw = bw - 2; 3286 ppdu_user_desc->nss = HTT_PPDU_STATS_USER_RATE_TLV_NSS_GET(*tag_buf); 3287 ppdu_desc->usr_nss_sum += ppdu_user_desc->nss; 3288 ppdu_user_desc->mcs = HTT_PPDU_STATS_USER_RATE_TLV_MCS_GET(*tag_buf); 3289 ppdu_user_desc->preamble = 3290 HTT_PPDU_STATS_USER_RATE_TLV_PREAMBLE_GET(*tag_buf); 3291 ppdu_user_desc->gi = HTT_PPDU_STATS_USER_RATE_TLV_GI_GET(*tag_buf); 3292 ppdu_user_desc->dcm = HTT_PPDU_STATS_USER_RATE_TLV_DCM_GET(*tag_buf); 3293 ppdu_user_desc->ldpc = HTT_PPDU_STATS_USER_RATE_TLV_LDPC_GET(*tag_buf); 3294 3295 tag_buf += 2; 3296 ppdu_user_desc->punc_pattern_bitmap = 3297 HTT_PPDU_STATS_USER_RATE_TLV_PUNC_PATTERN_BITMAP_GET(*tag_buf); 3298 } 3299 3300 /* 3301 * dp_process_ppdu_stats_enq_mpdu_bitmap_64_tlv: Process 3302 * htt_ppdu_stats_enq_mpdu_bitmap_64_tlv 3303 * pdev: DP PDEV handle 3304 * @tag_buf: buffer containing the tlv htt_ppdu_stats_enq_mpdu_bitmap_64_tlv 3305 * @ppdu_info: per ppdu tlv structure 3306 * 3307 * return:void 3308 */ 3309 static void dp_process_ppdu_stats_enq_mpdu_bitmap_64_tlv( 3310 struct dp_pdev *pdev, uint32_t *tag_buf, 3311 struct ppdu_info *ppdu_info) 3312 { 3313 htt_ppdu_stats_enq_mpdu_bitmap_64_tlv *dp_stats_buf = 3314 (htt_ppdu_stats_enq_mpdu_bitmap_64_tlv *)tag_buf; 3315 3316 struct cdp_tx_completion_ppdu *ppdu_desc; 3317 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 3318 uint8_t curr_user_index = 0; 3319 uint16_t peer_id; 3320 uint32_t size = CDP_BA_64_BIT_MAP_SIZE_DWORDS; 3321 uint32_t tlv_type = HTT_STATS_TLV_TAG_GET(*tag_buf); 3322 3323 ppdu_desc = 3324 (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 3325 3326 tag_buf++; 3327 3328 peer_id = 3329 HTT_PPDU_STATS_ENQ_MPDU_BITMAP_TLV_SW_PEER_ID_GET(*tag_buf); 3330 3331 curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info); 3332 ppdu_user_desc = &ppdu_desc->user[curr_user_index]; 3333 ppdu_user_desc->tlv_bitmap |= (1 << tlv_type); 3334 ppdu_user_desc->peer_id = peer_id; 3335 3336 ppdu_user_desc->start_seq = dp_stats_buf->start_seq; 3337 qdf_mem_copy(&ppdu_user_desc->enq_bitmap, &dp_stats_buf->enq_bitmap, 3338 sizeof(uint32_t) * CDP_BA_64_BIT_MAP_SIZE_DWORDS); 3339 3340 dp_process_ppdu_stats_update_failed_bitmap(pdev, 3341 (void *)ppdu_user_desc, 3342 ppdu_info->ppdu_id, 3343 size); 3344 } 3345 3346 /* 3347 * dp_process_ppdu_stats_enq_mpdu_bitmap_256_tlv: Process 3348 * htt_ppdu_stats_enq_mpdu_bitmap_256_tlv 3349 * soc: DP SOC handle 3350 * @tag_buf: buffer containing the tlv htt_ppdu_stats_enq_mpdu_bitmap_256_tlv 3351 * @ppdu_info: per ppdu tlv structure 3352 * 3353 * return:void 3354 */ 3355 static void dp_process_ppdu_stats_enq_mpdu_bitmap_256_tlv( 3356 struct dp_pdev *pdev, uint32_t *tag_buf, 3357 struct ppdu_info *ppdu_info) 3358 { 3359 htt_ppdu_stats_enq_mpdu_bitmap_256_tlv *dp_stats_buf = 3360 (htt_ppdu_stats_enq_mpdu_bitmap_256_tlv *)tag_buf; 3361 3362 struct cdp_tx_completion_ppdu *ppdu_desc; 3363 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 3364 uint8_t curr_user_index = 0; 3365 uint16_t peer_id; 3366 uint32_t size = CDP_BA_256_BIT_MAP_SIZE_DWORDS; 3367 uint32_t tlv_type = HTT_STATS_TLV_TAG_GET(*tag_buf); 3368 3369 ppdu_desc = 3370 (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 3371 3372 tag_buf++; 3373 3374 peer_id = 3375 HTT_PPDU_STATS_ENQ_MPDU_BITMAP_TLV_SW_PEER_ID_GET(*tag_buf); 3376 3377 curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info); 3378 ppdu_user_desc = &ppdu_desc->user[curr_user_index]; 3379 ppdu_user_desc->tlv_bitmap |= (1 << tlv_type); 3380 ppdu_user_desc->peer_id = peer_id; 3381 3382 ppdu_user_desc->start_seq = dp_stats_buf->start_seq; 3383 qdf_mem_copy(&ppdu_user_desc->enq_bitmap, &dp_stats_buf->enq_bitmap, 3384 sizeof(uint32_t) * CDP_BA_256_BIT_MAP_SIZE_DWORDS); 3385 3386 dp_process_ppdu_stats_update_failed_bitmap(pdev, 3387 (void *)ppdu_user_desc, 3388 ppdu_info->ppdu_id, 3389 size); 3390 } 3391 3392 /* 3393 * dp_process_ppdu_stats_user_cmpltn_common_tlv: Process 3394 * htt_ppdu_stats_user_cmpltn_common_tlv 3395 * soc: DP SOC handle 3396 * @tag_buf: buffer containing the tlv htt_ppdu_stats_user_cmpltn_common_tlv 3397 * @ppdu_info: per ppdu tlv structure 3398 * 3399 * return:void 3400 */ 3401 static void dp_process_ppdu_stats_user_cmpltn_common_tlv( 3402 struct dp_pdev *pdev, uint32_t *tag_buf, 3403 struct ppdu_info *ppdu_info) 3404 { 3405 uint16_t peer_id; 3406 struct cdp_tx_completion_ppdu *ppdu_desc; 3407 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 3408 uint8_t curr_user_index = 0; 3409 uint8_t bw_iter; 3410 htt_ppdu_stats_user_cmpltn_common_tlv *dp_stats_buf = 3411 (htt_ppdu_stats_user_cmpltn_common_tlv *)tag_buf; 3412 uint32_t tlv_type = HTT_STATS_TLV_TAG_GET(*tag_buf); 3413 3414 ppdu_desc = 3415 (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 3416 3417 tag_buf++; 3418 peer_id = 3419 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_SW_PEER_ID_GET(*tag_buf); 3420 3421 curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info); 3422 ppdu_user_desc = &ppdu_desc->user[curr_user_index]; 3423 ppdu_user_desc->tlv_bitmap |= (1 << tlv_type); 3424 ppdu_user_desc->peer_id = peer_id; 3425 3426 ppdu_user_desc->completion_status = 3427 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_COMPLETION_STATUS_GET( 3428 *tag_buf); 3429 3430 ppdu_user_desc->tid = 3431 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_TID_NUM_GET(*tag_buf); 3432 3433 tag_buf++; 3434 if (qdf_likely(ppdu_user_desc->completion_status == 3435 HTT_PPDU_STATS_USER_STATUS_OK)) { 3436 ppdu_desc->ack_rssi = dp_stats_buf->ack_rssi; 3437 ppdu_user_desc->usr_ack_rssi = dp_stats_buf->ack_rssi; 3438 ppdu_user_desc->ack_rssi_valid = 1; 3439 } else { 3440 ppdu_user_desc->ack_rssi_valid = 0; 3441 } 3442 3443 tag_buf++; 3444 3445 ppdu_user_desc->mpdu_success = 3446 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_MPDU_SUCCESS_GET(*tag_buf); 3447 3448 ppdu_user_desc->mpdu_failed = 3449 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_MPDU_TRIED_GET(*tag_buf) - 3450 ppdu_user_desc->mpdu_success; 3451 3452 tag_buf++; 3453 3454 ppdu_user_desc->long_retries = 3455 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_LONG_RETRY_GET(*tag_buf); 3456 3457 ppdu_user_desc->short_retries = 3458 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_SHORT_RETRY_GET(*tag_buf); 3459 ppdu_user_desc->retry_mpdus = 3460 ppdu_user_desc->long_retries + ppdu_user_desc->short_retries; 3461 3462 ppdu_user_desc->is_ampdu = 3463 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_IS_AMPDU_GET(*tag_buf); 3464 ppdu_info->is_ampdu = ppdu_user_desc->is_ampdu; 3465 3466 ppdu_desc->resp_type = 3467 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_RESP_TYPE_GET(*tag_buf); 3468 ppdu_desc->mprot_type = 3469 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_MPROT_TYPE_GET(*tag_buf); 3470 ppdu_desc->rts_success = 3471 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_RTS_SUCCESS_GET(*tag_buf); 3472 ppdu_desc->rts_failure = 3473 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_RTS_FAILURE_GET(*tag_buf); 3474 ppdu_user_desc->pream_punct = 3475 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_PREAM_PUNC_TX_GET(*tag_buf); 3476 3477 ppdu_info->compltn_common_tlv++; 3478 3479 /* 3480 * MU BAR may send request to n users but we may received ack only from 3481 * m users. To have count of number of users respond back, we have a 3482 * separate counter bar_num_users per PPDU that get increment for every 3483 * htt_ppdu_stats_user_cmpltn_common_tlv 3484 */ 3485 ppdu_desc->bar_num_users++; 3486 3487 tag_buf++; 3488 for (bw_iter = 0; bw_iter < CDP_RSSI_CHAIN_LEN; bw_iter++) { 3489 ppdu_user_desc->rssi_chain[bw_iter] = 3490 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_CHAIN_RSSI_GET(*tag_buf); 3491 tag_buf++; 3492 } 3493 3494 ppdu_user_desc->sa_tx_antenna = 3495 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_TX_ANTENNA_MASK_GET(*tag_buf); 3496 3497 tag_buf++; 3498 ppdu_user_desc->sa_is_training = 3499 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_IS_TRAINING_GET(*tag_buf); 3500 if (ppdu_user_desc->sa_is_training) { 3501 ppdu_user_desc->sa_goodput = 3502 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_PENDING_TRAINING_PKTS_GET(*tag_buf); 3503 } 3504 3505 tag_buf++; 3506 for (bw_iter = 0; bw_iter < CDP_NUM_SA_BW; bw_iter++) { 3507 ppdu_user_desc->sa_max_rates[bw_iter] = 3508 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_MAX_RATES_GET(tag_buf[bw_iter]); 3509 } 3510 3511 tag_buf += CDP_NUM_SA_BW; 3512 ppdu_user_desc->current_rate_per = 3513 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_CURRENT_RATE_PER_GET(*tag_buf); 3514 } 3515 3516 /* 3517 * dp_process_ppdu_stats_user_compltn_ba_bitmap_64_tlv: Process 3518 * htt_ppdu_stats_user_compltn_ba_bitmap_64_tlv 3519 * pdev: DP PDEV handle 3520 * @tag_buf: buffer containing the htt_ppdu_stats_user_compltn_ba_bitmap_64_tlv 3521 * @ppdu_info: per ppdu tlv structure 3522 * 3523 * return:void 3524 */ 3525 static void dp_process_ppdu_stats_user_compltn_ba_bitmap_64_tlv( 3526 struct dp_pdev *pdev, uint32_t *tag_buf, 3527 struct ppdu_info *ppdu_info) 3528 { 3529 htt_ppdu_stats_user_compltn_ba_bitmap_64_tlv *dp_stats_buf = 3530 (htt_ppdu_stats_user_compltn_ba_bitmap_64_tlv *)tag_buf; 3531 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 3532 struct cdp_tx_completion_ppdu *ppdu_desc; 3533 uint8_t curr_user_index = 0; 3534 uint16_t peer_id; 3535 uint32_t tlv_type = HTT_STATS_TLV_TAG_GET(*tag_buf); 3536 3537 ppdu_desc = 3538 (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 3539 3540 tag_buf++; 3541 3542 peer_id = 3543 HTT_PPDU_STATS_USER_CMPLTN_BA_BITMAP_TLV_SW_PEER_ID_GET(*tag_buf); 3544 3545 curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info); 3546 ppdu_user_desc = &ppdu_desc->user[curr_user_index]; 3547 ppdu_user_desc->tlv_bitmap |= (1 << tlv_type); 3548 ppdu_user_desc->peer_id = peer_id; 3549 3550 ppdu_user_desc->ba_seq_no = dp_stats_buf->ba_seq_no; 3551 qdf_mem_copy(&ppdu_user_desc->ba_bitmap, &dp_stats_buf->ba_bitmap, 3552 sizeof(uint32_t) * CDP_BA_64_BIT_MAP_SIZE_DWORDS); 3553 ppdu_user_desc->ba_size = CDP_BA_64_BIT_MAP_SIZE_DWORDS * 32; 3554 } 3555 3556 /* 3557 * dp_process_ppdu_stats_user_compltn_ba_bitmap_256_tlv: Process 3558 * htt_ppdu_stats_user_compltn_ba_bitmap_256_tlv 3559 * pdev: DP PDEV handle 3560 * @tag_buf: buffer containing the htt_ppdu_stats_user_compltn_ba_bitmap_256_tlv 3561 * @ppdu_info: per ppdu tlv structure 3562 * 3563 * return:void 3564 */ 3565 static void dp_process_ppdu_stats_user_compltn_ba_bitmap_256_tlv( 3566 struct dp_pdev *pdev, uint32_t *tag_buf, 3567 struct ppdu_info *ppdu_info) 3568 { 3569 htt_ppdu_stats_user_compltn_ba_bitmap_256_tlv *dp_stats_buf = 3570 (htt_ppdu_stats_user_compltn_ba_bitmap_256_tlv *)tag_buf; 3571 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 3572 struct cdp_tx_completion_ppdu *ppdu_desc; 3573 uint8_t curr_user_index = 0; 3574 uint16_t peer_id; 3575 uint32_t tlv_type = HTT_STATS_TLV_TAG_GET(*tag_buf); 3576 3577 ppdu_desc = 3578 (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 3579 3580 tag_buf++; 3581 3582 peer_id = 3583 HTT_PPDU_STATS_USER_CMPLTN_BA_BITMAP_TLV_SW_PEER_ID_GET(*tag_buf); 3584 3585 curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info); 3586 ppdu_user_desc = &ppdu_desc->user[curr_user_index]; 3587 ppdu_user_desc->tlv_bitmap |= (1 << tlv_type); 3588 ppdu_user_desc->peer_id = peer_id; 3589 3590 ppdu_user_desc->ba_seq_no = dp_stats_buf->ba_seq_no; 3591 qdf_mem_copy(&ppdu_user_desc->ba_bitmap, &dp_stats_buf->ba_bitmap, 3592 sizeof(uint32_t) * CDP_BA_256_BIT_MAP_SIZE_DWORDS); 3593 ppdu_user_desc->ba_size = CDP_BA_256_BIT_MAP_SIZE_DWORDS * 32; 3594 } 3595 3596 /* 3597 * dp_process_ppdu_stats_user_compltn_ack_ba_status_tlv: Process 3598 * htt_ppdu_stats_user_compltn_ack_ba_status_tlv 3599 * pdev: DP PDE handle 3600 * @tag_buf: buffer containing the htt_ppdu_stats_user_compltn_ack_ba_status_tlv 3601 * @ppdu_info: per ppdu tlv structure 3602 * 3603 * return:void 3604 */ 3605 static void dp_process_ppdu_stats_user_compltn_ack_ba_status_tlv( 3606 struct dp_pdev *pdev, uint32_t *tag_buf, 3607 struct ppdu_info *ppdu_info) 3608 { 3609 uint16_t peer_id; 3610 struct cdp_tx_completion_ppdu *ppdu_desc; 3611 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 3612 uint8_t curr_user_index = 0; 3613 uint32_t tlv_type = HTT_STATS_TLV_TAG_GET(*tag_buf); 3614 3615 ppdu_desc = 3616 (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 3617 3618 tag_buf += 2; 3619 peer_id = 3620 HTT_PPDU_STATS_USER_CMPLTN_ACK_BA_STATUS_TLV_SW_PEER_ID_GET(*tag_buf); 3621 3622 curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info); 3623 ppdu_user_desc = &ppdu_desc->user[curr_user_index]; 3624 ppdu_user_desc->tlv_bitmap |= (1 << tlv_type); 3625 if (!ppdu_user_desc->ack_ba_tlv) { 3626 ppdu_user_desc->ack_ba_tlv = 1; 3627 } else { 3628 pdev->stats.ack_ba_comes_twice++; 3629 return; 3630 } 3631 3632 ppdu_user_desc->peer_id = peer_id; 3633 3634 tag_buf++; 3635 /* not to update ppdu_desc->tid from this TLV */ 3636 ppdu_user_desc->num_mpdu = 3637 HTT_PPDU_STATS_USER_CMPLTN_ACK_BA_STATUS_TLV_NUM_MPDU_GET(*tag_buf); 3638 3639 ppdu_user_desc->num_msdu = 3640 HTT_PPDU_STATS_USER_CMPLTN_ACK_BA_STATUS_TLV_NUM_MSDU_GET(*tag_buf); 3641 3642 ppdu_user_desc->success_msdus = ppdu_user_desc->num_msdu; 3643 3644 tag_buf++; 3645 ppdu_user_desc->start_seq = 3646 HTT_PPDU_STATS_USER_CMPLTN_ACK_BA_STATUS_TLV_START_SEQ_GET( 3647 *tag_buf); 3648 3649 tag_buf++; 3650 ppdu_user_desc->success_bytes = *tag_buf; 3651 3652 /* increase ack ba tlv counter on successful mpdu */ 3653 if (ppdu_user_desc->num_mpdu) 3654 ppdu_info->ack_ba_tlv++; 3655 3656 if (ppdu_user_desc->ba_size == 0) { 3657 ppdu_user_desc->ba_seq_no = ppdu_user_desc->start_seq; 3658 ppdu_user_desc->ba_bitmap[0] = 1; 3659 ppdu_user_desc->ba_size = 1; 3660 } 3661 } 3662 3663 /* 3664 * dp_process_ppdu_stats_user_common_array_tlv: Process 3665 * htt_ppdu_stats_user_common_array_tlv 3666 * pdev: DP PDEV handle 3667 * @tag_buf: buffer containing the htt_ppdu_stats_user_compltn_ack_ba_status_tlv 3668 * @ppdu_info: per ppdu tlv structure 3669 * 3670 * return:void 3671 */ 3672 static void dp_process_ppdu_stats_user_common_array_tlv( 3673 struct dp_pdev *pdev, uint32_t *tag_buf, 3674 struct ppdu_info *ppdu_info) 3675 { 3676 uint32_t peer_id; 3677 struct cdp_tx_completion_ppdu *ppdu_desc; 3678 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 3679 uint8_t curr_user_index = 0; 3680 struct htt_tx_ppdu_stats_info *dp_stats_buf; 3681 uint32_t tlv_type = HTT_STATS_TLV_TAG_GET(*tag_buf); 3682 3683 ppdu_desc = 3684 (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 3685 3686 tag_buf++; 3687 dp_stats_buf = (struct htt_tx_ppdu_stats_info *)tag_buf; 3688 tag_buf += 3; 3689 peer_id = 3690 HTT_PPDU_STATS_ARRAY_ITEM_TLV_PEERID_GET(*tag_buf); 3691 3692 if (!dp_peer_find_by_id_valid(pdev->soc, peer_id)) { 3693 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 3694 "Invalid peer"); 3695 return; 3696 } 3697 3698 curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info); 3699 3700 ppdu_user_desc = &ppdu_desc->user[curr_user_index]; 3701 ppdu_user_desc->tlv_bitmap |= (1 << tlv_type); 3702 3703 ppdu_user_desc->retry_bytes = dp_stats_buf->tx_retry_bytes; 3704 ppdu_user_desc->failed_bytes = dp_stats_buf->tx_failed_bytes; 3705 3706 tag_buf++; 3707 3708 ppdu_user_desc->success_msdus = 3709 HTT_PPDU_STATS_ARRAY_ITEM_TLV_TX_SUCC_MSDUS_GET(*tag_buf); 3710 ppdu_user_desc->retry_msdus = 3711 HTT_PPDU_STATS_ARRAY_ITEM_TLV_TX_RETRY_MSDUS_GET(*tag_buf); 3712 tag_buf++; 3713 ppdu_user_desc->failed_msdus = 3714 HTT_PPDU_STATS_ARRAY_ITEM_TLV_TX_FAILED_MSDUS_GET(*tag_buf); 3715 } 3716 3717 /* 3718 * dp_process_ppdu_stats_flush_tlv: Process 3719 * htt_ppdu_stats_flush_tlv 3720 * @pdev: DP PDEV handle 3721 * @tag_buf: buffer containing the htt_ppdu_stats_flush_tlv 3722 * @ppdu_info: per ppdu tlv structure 3723 * 3724 * return:void 3725 */ 3726 static void 3727 dp_process_ppdu_stats_user_compltn_flush_tlv(struct dp_pdev *pdev, 3728 uint32_t *tag_buf, 3729 struct ppdu_info *ppdu_info) 3730 { 3731 struct cdp_tx_completion_ppdu *ppdu_desc; 3732 uint32_t peer_id; 3733 uint8_t tid; 3734 struct dp_peer *peer; 3735 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 3736 struct dp_mon_peer *mon_peer = NULL; 3737 3738 ppdu_desc = (struct cdp_tx_completion_ppdu *) 3739 qdf_nbuf_data(ppdu_info->nbuf); 3740 ppdu_desc->is_flush = 1; 3741 3742 tag_buf++; 3743 ppdu_desc->drop_reason = *tag_buf; 3744 3745 tag_buf++; 3746 ppdu_desc->num_msdu = HTT_PPDU_STATS_FLUSH_TLV_NUM_MSDU_GET(*tag_buf); 3747 ppdu_desc->num_mpdu = HTT_PPDU_STATS_FLUSH_TLV_NUM_MPDU_GET(*tag_buf); 3748 ppdu_desc->flow_type = HTT_PPDU_STATS_FLUSH_TLV_FLOW_TYPE_GET(*tag_buf); 3749 3750 tag_buf++; 3751 peer_id = HTT_PPDU_STATS_FLUSH_TLV_SW_PEER_ID_GET(*tag_buf); 3752 tid = HTT_PPDU_STATS_FLUSH_TLV_TID_NUM_GET(*tag_buf); 3753 3754 ppdu_desc->num_users = 1; 3755 ppdu_desc->user[0].peer_id = peer_id; 3756 ppdu_desc->user[0].tid = tid; 3757 3758 ppdu_desc->queue_type = 3759 HTT_PPDU_STATS_FLUSH_TLV_QUEUE_TYPE_GET(*tag_buf); 3760 3761 peer = dp_peer_get_ref_by_id(pdev->soc, peer_id, 3762 DP_MOD_ID_TX_PPDU_STATS); 3763 if (!peer) 3764 goto add_ppdu_to_sched_list; 3765 3766 if (ppdu_desc->drop_reason == HTT_FLUSH_EXCESS_RETRIES) { 3767 mon_peer = peer->monitor_peer; 3768 DP_STATS_INC(mon_peer, 3769 tx.excess_retries_per_ac[TID_TO_WME_AC(tid)], 3770 ppdu_desc->num_msdu); 3771 } 3772 3773 dp_peer_unref_delete(peer, DP_MOD_ID_TX_PPDU_STATS); 3774 3775 add_ppdu_to_sched_list: 3776 ppdu_info->done = 1; 3777 TAILQ_REMOVE(&mon_pdev->ppdu_info_list, ppdu_info, ppdu_info_list_elem); 3778 mon_pdev->list_depth--; 3779 TAILQ_INSERT_TAIL(&mon_pdev->sched_comp_ppdu_list, ppdu_info, 3780 ppdu_info_list_elem); 3781 mon_pdev->sched_comp_list_depth++; 3782 } 3783 3784 /** 3785 * dp_process_ppdu_stats_sch_cmd_status_tlv: Process schedule command status tlv 3786 * Here we are not going to process the buffer. 3787 * @pdev: DP PDEV handle 3788 * @ppdu_info: per ppdu tlv structure 3789 * 3790 * return:void 3791 */ 3792 static void 3793 dp_process_ppdu_stats_sch_cmd_status_tlv(struct dp_pdev *pdev, 3794 struct ppdu_info *ppdu_info) 3795 { 3796 struct cdp_tx_completion_ppdu *ppdu_desc; 3797 struct dp_peer *peer; 3798 uint8_t num_users; 3799 uint8_t i; 3800 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 3801 3802 ppdu_desc = (struct cdp_tx_completion_ppdu *) 3803 qdf_nbuf_data(ppdu_info->nbuf); 3804 3805 num_users = ppdu_desc->bar_num_users; 3806 3807 for (i = 0; i < num_users; i++) { 3808 if (ppdu_desc->user[i].user_pos == 0) { 3809 if (ppdu_desc->frame_type == CDP_PPDU_FTYPE_BAR) { 3810 /* update phy mode for bar frame */ 3811 ppdu_desc->phy_mode = 3812 ppdu_desc->user[i].preamble; 3813 ppdu_desc->user[0].mcs = ppdu_desc->user[i].mcs; 3814 break; 3815 } 3816 if (ppdu_desc->frame_type == CDP_PPDU_FTYPE_CTRL) { 3817 ppdu_desc->frame_ctrl = 3818 ppdu_desc->user[i].frame_ctrl; 3819 break; 3820 } 3821 } 3822 } 3823 3824 if (ppdu_desc->frame_type == CDP_PPDU_FTYPE_DATA && 3825 ppdu_desc->delayed_ba) { 3826 qdf_assert_always(ppdu_desc->num_users <= ppdu_desc->max_users); 3827 3828 for (i = 0; i < ppdu_desc->num_users; i++) { 3829 struct cdp_delayed_tx_completion_ppdu_user *delay_ppdu; 3830 uint64_t start_tsf; 3831 uint64_t end_tsf; 3832 uint32_t ppdu_id; 3833 struct dp_mon_peer *mon_peer; 3834 3835 ppdu_id = ppdu_desc->ppdu_id; 3836 peer = dp_peer_get_ref_by_id 3837 (pdev->soc, ppdu_desc->user[i].peer_id, 3838 DP_MOD_ID_TX_PPDU_STATS); 3839 /** 3840 * This check is to make sure peer is not deleted 3841 * after processing the TLVs. 3842 */ 3843 if (!peer) 3844 continue; 3845 3846 if (!peer->monitor_peer) { 3847 dp_peer_unref_delete(peer, 3848 DP_MOD_ID_TX_PPDU_STATS); 3849 continue; 3850 } 3851 3852 mon_peer = peer->monitor_peer; 3853 delay_ppdu = &mon_peer->delayed_ba_ppdu_stats; 3854 start_tsf = ppdu_desc->ppdu_start_timestamp; 3855 end_tsf = ppdu_desc->ppdu_end_timestamp; 3856 /** 3857 * save delayed ba user info 3858 */ 3859 if (ppdu_desc->user[i].delayed_ba) { 3860 dp_peer_copy_delay_stats(peer, 3861 &ppdu_desc->user[i], 3862 ppdu_id); 3863 mon_peer->last_delayed_ba_ppduid = ppdu_id; 3864 delay_ppdu->ppdu_start_timestamp = start_tsf; 3865 delay_ppdu->ppdu_end_timestamp = end_tsf; 3866 } 3867 ppdu_desc->user[i].peer_last_delayed_ba = 3868 mon_peer->last_delayed_ba; 3869 3870 dp_peer_unref_delete(peer, DP_MOD_ID_TX_PPDU_STATS); 3871 3872 if (ppdu_desc->user[i].delayed_ba && 3873 !ppdu_desc->user[i].debug_copied) { 3874 QDF_TRACE(QDF_MODULE_ID_TXRX, 3875 QDF_TRACE_LEVEL_INFO_MED, 3876 "%s: %d ppdu_id[%d] bar_ppdu_id[%d] num_users[%d] usr[%d] htt_frame_type[%d]\n", 3877 __func__, __LINE__, 3878 ppdu_desc->ppdu_id, 3879 ppdu_desc->bar_ppdu_id, 3880 ppdu_desc->num_users, 3881 i, 3882 ppdu_desc->htt_frame_type); 3883 } 3884 } 3885 } 3886 3887 /* 3888 * when frame type is BAR and STATS_COMMON_TLV is set 3889 * copy the store peer delayed info to BAR status 3890 */ 3891 if (ppdu_desc->frame_type == CDP_PPDU_FTYPE_BAR) { 3892 for (i = 0; i < ppdu_desc->bar_num_users; i++) { 3893 struct cdp_delayed_tx_completion_ppdu_user *delay_ppdu; 3894 uint64_t start_tsf; 3895 uint64_t end_tsf; 3896 struct dp_mon_peer *mon_peer; 3897 3898 peer = dp_peer_get_ref_by_id 3899 (pdev->soc, 3900 ppdu_desc->user[i].peer_id, 3901 DP_MOD_ID_TX_PPDU_STATS); 3902 /** 3903 * This check is to make sure peer is not deleted 3904 * after processing the TLVs. 3905 */ 3906 if (!peer) 3907 continue; 3908 3909 if (!peer->monitor_peer) { 3910 dp_peer_unref_delete(peer, 3911 DP_MOD_ID_TX_PPDU_STATS); 3912 continue; 3913 } 3914 3915 mon_peer = peer->monitor_peer; 3916 if (ppdu_desc->user[i].completion_status != 3917 HTT_PPDU_STATS_USER_STATUS_OK) { 3918 dp_peer_unref_delete(peer, 3919 DP_MOD_ID_TX_PPDU_STATS); 3920 continue; 3921 } 3922 3923 delay_ppdu = &mon_peer->delayed_ba_ppdu_stats; 3924 start_tsf = delay_ppdu->ppdu_start_timestamp; 3925 end_tsf = delay_ppdu->ppdu_end_timestamp; 3926 3927 if (mon_peer->last_delayed_ba) { 3928 dp_peer_copy_stats_to_bar(peer, 3929 &ppdu_desc->user[i]); 3930 ppdu_desc->ppdu_id = 3931 mon_peer->last_delayed_ba_ppduid; 3932 ppdu_desc->ppdu_start_timestamp = start_tsf; 3933 ppdu_desc->ppdu_end_timestamp = end_tsf; 3934 } 3935 ppdu_desc->user[i].peer_last_delayed_ba = 3936 mon_peer->last_delayed_ba; 3937 dp_peer_unref_delete(peer, DP_MOD_ID_TX_PPDU_STATS); 3938 } 3939 } 3940 3941 TAILQ_REMOVE(&mon_pdev->ppdu_info_list, ppdu_info, ppdu_info_list_elem); 3942 mon_pdev->list_depth--; 3943 TAILQ_INSERT_TAIL(&mon_pdev->sched_comp_ppdu_list, ppdu_info, 3944 ppdu_info_list_elem); 3945 mon_pdev->sched_comp_list_depth++; 3946 } 3947 3948 /** 3949 * dp_validate_fix_ppdu_tlv(): Function to validate the length of PPDU 3950 * 3951 * If the TLV length sent as part of PPDU TLV is less that expected size i.e 3952 * size of corresponding data structure, pad the remaining bytes with zeros 3953 * and continue processing the TLVs 3954 * 3955 * @pdev: DP pdev handle 3956 * @tag_buf: TLV buffer 3957 * @tlv_expected_size: Expected size of Tag 3958 * @tlv_len: TLV length received from FW 3959 * 3960 * Return: Pointer to updated TLV 3961 */ 3962 static inline uint32_t *dp_validate_fix_ppdu_tlv(struct dp_pdev *pdev, 3963 uint32_t *tag_buf, 3964 uint16_t tlv_expected_size, 3965 uint16_t tlv_len) 3966 { 3967 uint32_t *tlv_desc = tag_buf; 3968 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 3969 3970 qdf_assert_always(tlv_len != 0); 3971 3972 if (tlv_len < tlv_expected_size) { 3973 qdf_mem_zero(mon_pdev->ppdu_tlv_buf, tlv_expected_size); 3974 qdf_mem_copy(mon_pdev->ppdu_tlv_buf, tag_buf, tlv_len); 3975 tlv_desc = mon_pdev->ppdu_tlv_buf; 3976 } 3977 3978 return tlv_desc; 3979 } 3980 3981 /** 3982 * dp_process_ppdu_tag(): Function to process the PPDU TLVs 3983 * @pdev: DP pdev handle 3984 * @tag_buf: TLV buffer 3985 * @tlv_len: length of tlv 3986 * @ppdu_info: per ppdu tlv structure 3987 * 3988 * return: void 3989 */ 3990 static void dp_process_ppdu_tag(struct dp_pdev *pdev, 3991 uint32_t *tag_buf, 3992 uint32_t tlv_len, 3993 struct ppdu_info *ppdu_info) 3994 { 3995 uint32_t tlv_type = HTT_STATS_TLV_TAG_GET(*tag_buf); 3996 uint16_t tlv_expected_size; 3997 uint32_t *tlv_desc; 3998 3999 switch (tlv_type) { 4000 case HTT_PPDU_STATS_COMMON_TLV: 4001 tlv_expected_size = sizeof(htt_ppdu_stats_common_tlv); 4002 tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf, 4003 tlv_expected_size, tlv_len); 4004 dp_process_ppdu_stats_common_tlv(pdev, tlv_desc, ppdu_info); 4005 break; 4006 case HTT_PPDU_STATS_USR_COMMON_TLV: 4007 tlv_expected_size = sizeof(htt_ppdu_stats_user_common_tlv); 4008 tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf, 4009 tlv_expected_size, tlv_len); 4010 dp_process_ppdu_stats_user_common_tlv(pdev, tlv_desc, 4011 ppdu_info); 4012 break; 4013 case HTT_PPDU_STATS_USR_RATE_TLV: 4014 tlv_expected_size = sizeof(htt_ppdu_stats_user_rate_tlv); 4015 tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf, 4016 tlv_expected_size, tlv_len); 4017 dp_process_ppdu_stats_user_rate_tlv(pdev, tlv_desc, 4018 ppdu_info); 4019 break; 4020 case HTT_PPDU_STATS_USR_MPDU_ENQ_BITMAP_64_TLV: 4021 tlv_expected_size = 4022 sizeof(htt_ppdu_stats_enq_mpdu_bitmap_64_tlv); 4023 tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf, 4024 tlv_expected_size, tlv_len); 4025 dp_process_ppdu_stats_enq_mpdu_bitmap_64_tlv( 4026 pdev, tlv_desc, ppdu_info); 4027 break; 4028 case HTT_PPDU_STATS_USR_MPDU_ENQ_BITMAP_256_TLV: 4029 tlv_expected_size = 4030 sizeof(htt_ppdu_stats_enq_mpdu_bitmap_256_tlv); 4031 tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf, 4032 tlv_expected_size, tlv_len); 4033 dp_process_ppdu_stats_enq_mpdu_bitmap_256_tlv( 4034 pdev, tlv_desc, ppdu_info); 4035 break; 4036 case HTT_PPDU_STATS_USR_COMPLTN_COMMON_TLV: 4037 tlv_expected_size = 4038 sizeof(htt_ppdu_stats_user_cmpltn_common_tlv); 4039 tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf, 4040 tlv_expected_size, tlv_len); 4041 dp_process_ppdu_stats_user_cmpltn_common_tlv( 4042 pdev, tlv_desc, ppdu_info); 4043 break; 4044 case HTT_PPDU_STATS_USR_COMPLTN_BA_BITMAP_64_TLV: 4045 tlv_expected_size = 4046 sizeof(htt_ppdu_stats_user_compltn_ba_bitmap_64_tlv); 4047 tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf, 4048 tlv_expected_size, tlv_len); 4049 dp_process_ppdu_stats_user_compltn_ba_bitmap_64_tlv( 4050 pdev, tlv_desc, ppdu_info); 4051 break; 4052 case HTT_PPDU_STATS_USR_COMPLTN_BA_BITMAP_256_TLV: 4053 tlv_expected_size = 4054 sizeof(htt_ppdu_stats_user_compltn_ba_bitmap_256_tlv); 4055 tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf, 4056 tlv_expected_size, tlv_len); 4057 dp_process_ppdu_stats_user_compltn_ba_bitmap_256_tlv( 4058 pdev, tlv_desc, ppdu_info); 4059 break; 4060 case HTT_PPDU_STATS_USR_COMPLTN_ACK_BA_STATUS_TLV: 4061 tlv_expected_size = 4062 sizeof(htt_ppdu_stats_user_compltn_ack_ba_status_tlv); 4063 tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf, 4064 tlv_expected_size, tlv_len); 4065 dp_process_ppdu_stats_user_compltn_ack_ba_status_tlv( 4066 pdev, tlv_desc, ppdu_info); 4067 break; 4068 case HTT_PPDU_STATS_USR_COMMON_ARRAY_TLV: 4069 tlv_expected_size = 4070 sizeof(htt_ppdu_stats_usr_common_array_tlv_v); 4071 tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf, 4072 tlv_expected_size, tlv_len); 4073 dp_process_ppdu_stats_user_common_array_tlv( 4074 pdev, tlv_desc, ppdu_info); 4075 break; 4076 case HTT_PPDU_STATS_USR_COMPLTN_FLUSH_TLV: 4077 tlv_expected_size = sizeof(htt_ppdu_stats_flush_tlv); 4078 tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf, 4079 tlv_expected_size, tlv_len); 4080 dp_process_ppdu_stats_user_compltn_flush_tlv(pdev, tlv_desc, 4081 ppdu_info); 4082 break; 4083 case HTT_PPDU_STATS_SCH_CMD_STATUS_TLV: 4084 dp_process_ppdu_stats_sch_cmd_status_tlv(pdev, ppdu_info); 4085 break; 4086 default: 4087 break; 4088 } 4089 } 4090 4091 #ifdef WLAN_TELEMETRY_STATS_SUPPORT 4092 static inline 4093 void dp_ppdu_desc_user_airtime_consumption_update( 4094 struct dp_peer *peer, 4095 struct cdp_tx_completion_ppdu_user *user) 4096 { 4097 struct dp_mon_peer *mon_peer = NULL; 4098 uint8_t ac = 0; 4099 4100 mon_peer = peer->monitor_peer; 4101 if (qdf_unlikely(!mon_peer)) 4102 return; 4103 4104 ac = TID_TO_WME_AC(user->tid); 4105 DP_STATS_INC(mon_peer, airtime_consumption[ac].consumption, 4106 user->phy_tx_time_us); 4107 } 4108 #else 4109 static inline 4110 void dp_ppdu_desc_user_airtime_consumption_update( 4111 struct dp_peer *peer, 4112 struct cdp_tx_completion_ppdu_user *user) 4113 { } 4114 #endif 4115 #if defined(WLAN_ATF_ENABLE) || defined(WLAN_TELEMETRY_STATS_SUPPORT) 4116 static void 4117 dp_ppdu_desc_user_phy_tx_time_update(struct dp_pdev *pdev, 4118 struct dp_peer *peer, 4119 struct cdp_tx_completion_ppdu *ppdu_desc, 4120 struct cdp_tx_completion_ppdu_user *user) 4121 { 4122 uint32_t nss_ru_width_sum = 0; 4123 struct dp_mon_peer *mon_peer = NULL; 4124 4125 if (!pdev || !ppdu_desc || !user || !peer) 4126 return; 4127 4128 if (ppdu_desc->frame_type != CDP_PPDU_FTYPE_DATA) 4129 return; 4130 4131 mon_peer = peer->monitor_peer; 4132 if (qdf_unlikely(!mon_peer)) 4133 return; 4134 4135 nss_ru_width_sum = ppdu_desc->usr_nss_sum * ppdu_desc->usr_ru_tones_sum; 4136 if (!nss_ru_width_sum) 4137 nss_ru_width_sum = 1; 4138 4139 /** 4140 * For SU-MIMO PPDU phy Tx time is same for the single user. 4141 * For MU-MIMO phy Tx time is calculated per user as below 4142 * user phy tx time = 4143 * Entire PPDU duration * MU Ratio * OFDMA Ratio 4144 * MU Ratio = usr_nss / Sum_of_nss_of_all_users 4145 * OFDMA_ratio = usr_ru_width / Sum_of_ru_width_of_all_users 4146 * usr_ru_widt = ru_end – ru_start + 1 4147 */ 4148 if (ppdu_desc->htt_frame_type == HTT_STATS_FTYPE_TIDQ_DATA_SU) { 4149 user->phy_tx_time_us = ppdu_desc->phy_ppdu_tx_time_us; 4150 } else { 4151 user->phy_tx_time_us = (ppdu_desc->phy_ppdu_tx_time_us * 4152 user->nss * user->ru_tones) / nss_ru_width_sum; 4153 } 4154 4155 dp_ppdu_desc_user_airtime_consumption_update(peer, user); 4156 } 4157 #else 4158 static void 4159 dp_ppdu_desc_user_phy_tx_time_update(struct dp_pdev *pdev, 4160 struct dp_peer *peer, 4161 struct cdp_tx_completion_ppdu *ppdu_desc, 4162 struct cdp_tx_completion_ppdu_user *user) 4163 { 4164 } 4165 #endif 4166 4167 /** 4168 * dp_ppdu_desc_user_stats_update(): Function to update TX user stats 4169 * @pdev: DP pdev handle 4170 * @ppdu_info: per PPDU TLV descriptor 4171 * 4172 * return: void 4173 */ 4174 void 4175 dp_ppdu_desc_user_stats_update(struct dp_pdev *pdev, 4176 struct ppdu_info *ppdu_info) 4177 { 4178 struct cdp_tx_completion_ppdu *ppdu_desc = NULL; 4179 struct dp_peer *peer = NULL; 4180 uint32_t tlv_bitmap_expected; 4181 uint32_t tlv_bitmap_default; 4182 uint16_t i; 4183 uint32_t num_users; 4184 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 4185 4186 ppdu_desc = (struct cdp_tx_completion_ppdu *) 4187 qdf_nbuf_data(ppdu_info->nbuf); 4188 4189 if (ppdu_desc->frame_type != CDP_PPDU_FTYPE_BAR) 4190 ppdu_desc->ppdu_id = ppdu_info->ppdu_id; 4191 4192 tlv_bitmap_expected = HTT_PPDU_DEFAULT_TLV_BITMAP; 4193 if (mon_pdev->tx_sniffer_enable || mon_pdev->mcopy_mode || 4194 mon_pdev->tx_capture_enabled) { 4195 if (ppdu_info->is_ampdu) 4196 tlv_bitmap_expected = 4197 dp_htt_get_ppdu_sniffer_ampdu_tlv_bitmap( 4198 ppdu_info->tlv_bitmap); 4199 } 4200 4201 tlv_bitmap_default = tlv_bitmap_expected; 4202 4203 if (ppdu_desc->frame_type == CDP_PPDU_FTYPE_BAR) { 4204 num_users = ppdu_desc->bar_num_users; 4205 ppdu_desc->num_users = ppdu_desc->bar_num_users; 4206 } else { 4207 num_users = ppdu_desc->num_users; 4208 } 4209 qdf_assert_always(ppdu_desc->num_users <= ppdu_desc->max_users); 4210 4211 for (i = 0; i < num_users; i++) { 4212 ppdu_desc->num_mpdu += ppdu_desc->user[i].num_mpdu; 4213 ppdu_desc->num_msdu += ppdu_desc->user[i].num_msdu; 4214 4215 peer = dp_peer_get_ref_by_id(pdev->soc, 4216 ppdu_desc->user[i].peer_id, 4217 DP_MOD_ID_TX_PPDU_STATS); 4218 /** 4219 * This check is to make sure peer is not deleted 4220 * after processing the TLVs. 4221 */ 4222 if (!peer) 4223 continue; 4224 4225 ppdu_desc->user[i].is_bss_peer = peer->bss_peer; 4226 4227 dp_ppdu_desc_user_phy_tx_time_update(pdev, peer, ppdu_desc, 4228 &ppdu_desc->user[i]); 4229 /* 4230 * different frame like DATA, BAR or CTRL has different 4231 * tlv bitmap expected. Apart from ACK_BA_STATUS TLV, we 4232 * receive other tlv in-order/sequential from fw. 4233 * Since ACK_BA_STATUS TLV come from Hardware it is 4234 * asynchronous So we need to depend on some tlv to confirm 4235 * all tlv is received for a ppdu. 4236 * So we depend on both SCHED_CMD_STATUS_TLV and 4237 * ACK_BA_STATUS_TLV. for failure packet we won't get 4238 * ACK_BA_STATUS_TLV. 4239 */ 4240 if (!(ppdu_info->tlv_bitmap & 4241 (1 << HTT_PPDU_STATS_SCH_CMD_STATUS_TLV)) || 4242 (!(ppdu_info->tlv_bitmap & 4243 (1 << HTT_PPDU_STATS_USR_COMPLTN_ACK_BA_STATUS_TLV)) && 4244 (ppdu_desc->user[i].completion_status == 4245 HTT_PPDU_STATS_USER_STATUS_OK))) { 4246 dp_peer_unref_delete(peer, DP_MOD_ID_TX_PPDU_STATS); 4247 continue; 4248 } 4249 4250 /** 4251 * Update tx stats for data frames having Qos as well as 4252 * non-Qos data tid 4253 */ 4254 4255 if ((ppdu_desc->user[i].tid < CDP_DATA_TID_MAX || 4256 (ppdu_desc->user[i].tid == CDP_DATA_NON_QOS_TID) || 4257 (ppdu_desc->htt_frame_type == 4258 HTT_STATS_FTYPE_SGEN_QOS_NULL) || 4259 ((ppdu_desc->frame_type == CDP_PPDU_FTYPE_BAR) && 4260 (ppdu_desc->num_mpdu > 1))) && 4261 (ppdu_desc->frame_type != CDP_PPDU_FTYPE_CTRL)) { 4262 dp_tx_stats_update(pdev, peer, 4263 &ppdu_desc->user[i], 4264 ppdu_desc->ack_rssi); 4265 } 4266 4267 dp_peer_unref_delete(peer, DP_MOD_ID_TX_PPDU_STATS); 4268 tlv_bitmap_expected = tlv_bitmap_default; 4269 } 4270 } 4271 4272 #if !defined(WLAN_TX_PKT_CAPTURE_ENH) || defined(QCA_MONITOR_2_0_SUPPORT) 4273 /* 4274 * dp_tx_ppdu_desc_notify() - Notify to upper layer about PPDU via WDI 4275 * 4276 * @pdev: Datapath pdev handle 4277 * @nbuf: Buffer to be delivered to upper layer 4278 * 4279 * Return: void 4280 */ 4281 static void dp_tx_ppdu_desc_notify(struct dp_pdev *pdev, qdf_nbuf_t nbuf) 4282 { 4283 struct dp_soc *soc = pdev->soc; 4284 struct dp_mon_ops *mon_ops = NULL; 4285 4286 mon_ops = dp_mon_ops_get(soc); 4287 if (mon_ops && mon_ops->mon_ppdu_desc_notify) 4288 mon_ops->mon_ppdu_desc_notify(pdev, nbuf); 4289 else 4290 qdf_nbuf_free(nbuf); 4291 } 4292 4293 void dp_ppdu_desc_deliver(struct dp_pdev *pdev, 4294 struct ppdu_info *ppdu_info) 4295 { 4296 struct ppdu_info *s_ppdu_info = NULL; 4297 struct ppdu_info *ppdu_info_next = NULL; 4298 struct cdp_tx_completion_ppdu *ppdu_desc = NULL; 4299 qdf_nbuf_t nbuf; 4300 uint32_t time_delta = 0; 4301 bool starved = 0; 4302 bool matched = 0; 4303 bool recv_ack_ba_done = 0; 4304 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 4305 4306 if (ppdu_info->tlv_bitmap & 4307 (1 << HTT_PPDU_STATS_USR_COMPLTN_ACK_BA_STATUS_TLV) && 4308 ppdu_info->done) 4309 recv_ack_ba_done = 1; 4310 4311 mon_pdev->last_sched_cmdid = ppdu_info->sched_cmdid; 4312 4313 s_ppdu_info = TAILQ_FIRST(&mon_pdev->sched_comp_ppdu_list); 4314 4315 TAILQ_FOREACH_SAFE(s_ppdu_info, &mon_pdev->sched_comp_ppdu_list, 4316 ppdu_info_list_elem, ppdu_info_next) { 4317 if (s_ppdu_info->tsf_l32 > ppdu_info->tsf_l32) 4318 time_delta = (MAX_TSF_32 - s_ppdu_info->tsf_l32) + 4319 ppdu_info->tsf_l32; 4320 else 4321 time_delta = ppdu_info->tsf_l32 - s_ppdu_info->tsf_l32; 4322 4323 if (!s_ppdu_info->done && !recv_ack_ba_done) { 4324 if (time_delta < MAX_SCHED_STARVE) { 4325 dp_mon_info("pdev[%d] ppdu_id[%d] sched_cmdid[%d] TLV_B[0x%x] TSF[%u] D[%d]", 4326 pdev->pdev_id, 4327 s_ppdu_info->ppdu_id, 4328 s_ppdu_info->sched_cmdid, 4329 s_ppdu_info->tlv_bitmap, 4330 s_ppdu_info->tsf_l32, 4331 s_ppdu_info->done); 4332 break; 4333 } 4334 starved = 1; 4335 } 4336 4337 mon_pdev->delivered_sched_cmdid = s_ppdu_info->sched_cmdid; 4338 TAILQ_REMOVE(&mon_pdev->sched_comp_ppdu_list, s_ppdu_info, 4339 ppdu_info_list_elem); 4340 mon_pdev->sched_comp_list_depth--; 4341 4342 nbuf = s_ppdu_info->nbuf; 4343 qdf_assert_always(nbuf); 4344 ppdu_desc = (struct cdp_tx_completion_ppdu *) 4345 qdf_nbuf_data(nbuf); 4346 ppdu_desc->tlv_bitmap = s_ppdu_info->tlv_bitmap; 4347 4348 if (starved) { 4349 dp_mon_info("ppdu starved fc[0x%x] h_ftype[%d] tlv_bitmap[0x%x] cs[%d]\n", 4350 ppdu_desc->frame_ctrl, 4351 ppdu_desc->htt_frame_type, 4352 ppdu_desc->tlv_bitmap, 4353 ppdu_desc->user[0].completion_status); 4354 starved = 0; 4355 } 4356 4357 if (ppdu_info->ppdu_id == s_ppdu_info->ppdu_id && 4358 ppdu_info->sched_cmdid == s_ppdu_info->sched_cmdid) 4359 matched = 1; 4360 4361 dp_ppdu_desc_user_stats_update(pdev, s_ppdu_info); 4362 4363 qdf_mem_free(s_ppdu_info); 4364 4365 dp_tx_ppdu_desc_notify(pdev, nbuf); 4366 4367 if (matched) 4368 break; 4369 } 4370 } 4371 #endif 4372 4373 /* 4374 * dp_tx_ppdu_desc_deliver() - Deliver PPDU desc to upper layer 4375 * 4376 * @pdev: Datapath pdev handle 4377 * @ppdu_info: per PPDU TLV descriptor 4378 * 4379 * Return: void 4380 */ 4381 static void dp_tx_ppdu_desc_deliver(struct dp_pdev *pdev, 4382 struct ppdu_info *ppdu_info) 4383 { 4384 struct dp_soc *soc = pdev->soc; 4385 struct dp_mon_ops *mon_ops = NULL; 4386 4387 mon_ops = dp_mon_ops_get(soc); 4388 4389 if (mon_ops && mon_ops->mon_ppdu_desc_deliver) { 4390 mon_ops->mon_ppdu_desc_deliver(pdev, ppdu_info); 4391 } else { 4392 qdf_nbuf_free(ppdu_info->nbuf); 4393 ppdu_info->nbuf = NULL; 4394 qdf_mem_free(ppdu_info); 4395 } 4396 } 4397 4398 /** 4399 * dp_get_ppdu_desc(): Function to allocate new PPDU status 4400 * desc for new ppdu id 4401 * @pdev: DP pdev handle 4402 * @ppdu_id: PPDU unique identifier 4403 * @tlv_type: TLV type received 4404 * @tsf_l32: timestamp received along with ppdu stats indication header 4405 * @max_users: Maximum user for that particular ppdu 4406 * 4407 * return: ppdu_info per ppdu tlv structure 4408 */ 4409 static 4410 struct ppdu_info *dp_get_ppdu_desc(struct dp_pdev *pdev, uint32_t ppdu_id, 4411 uint8_t tlv_type, uint32_t tsf_l32, 4412 uint8_t max_users) 4413 { 4414 struct ppdu_info *ppdu_info = NULL; 4415 struct ppdu_info *s_ppdu_info = NULL; 4416 struct ppdu_info *ppdu_info_next = NULL; 4417 struct cdp_tx_completion_ppdu *ppdu_desc = NULL; 4418 uint32_t size = 0; 4419 struct cdp_tx_completion_ppdu *tmp_ppdu_desc = NULL; 4420 struct cdp_tx_completion_ppdu_user *tmp_user; 4421 uint32_t time_delta; 4422 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 4423 4424 /* 4425 * Find ppdu_id node exists or not 4426 */ 4427 TAILQ_FOREACH_SAFE(ppdu_info, &mon_pdev->ppdu_info_list, 4428 ppdu_info_list_elem, ppdu_info_next) { 4429 if (ppdu_info && (ppdu_info->ppdu_id == ppdu_id)) { 4430 if (ppdu_info->tsf_l32 > tsf_l32) 4431 time_delta = (MAX_TSF_32 - 4432 ppdu_info->tsf_l32) + tsf_l32; 4433 else 4434 time_delta = tsf_l32 - ppdu_info->tsf_l32; 4435 4436 if (time_delta > WRAP_DROP_TSF_DELTA) { 4437 TAILQ_REMOVE(&mon_pdev->ppdu_info_list, 4438 ppdu_info, ppdu_info_list_elem); 4439 mon_pdev->list_depth--; 4440 pdev->stats.ppdu_wrap_drop++; 4441 tmp_ppdu_desc = 4442 (struct cdp_tx_completion_ppdu *) 4443 qdf_nbuf_data(ppdu_info->nbuf); 4444 tmp_user = &tmp_ppdu_desc->user[0]; 4445 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", 4446 ppdu_info->ppdu_id, 4447 ppdu_info->tsf_l32, 4448 ppdu_info->tlv_bitmap, 4449 tmp_user->completion_status, 4450 ppdu_info->compltn_common_tlv, 4451 ppdu_info->ack_ba_tlv, 4452 ppdu_id, tsf_l32, 4453 tlv_type); 4454 qdf_nbuf_free(ppdu_info->nbuf); 4455 ppdu_info->nbuf = NULL; 4456 qdf_mem_free(ppdu_info); 4457 } else { 4458 break; 4459 } 4460 } 4461 } 4462 4463 /* 4464 * check if it is ack ba tlv and if it is not there in ppdu info 4465 * list then check it in sched completion ppdu list 4466 */ 4467 if (!ppdu_info && 4468 tlv_type == HTT_PPDU_STATS_USR_COMPLTN_ACK_BA_STATUS_TLV) { 4469 TAILQ_FOREACH(s_ppdu_info, 4470 &mon_pdev->sched_comp_ppdu_list, 4471 ppdu_info_list_elem) { 4472 if (s_ppdu_info && (s_ppdu_info->ppdu_id == ppdu_id)) { 4473 if (s_ppdu_info->tsf_l32 > tsf_l32) 4474 time_delta = (MAX_TSF_32 - 4475 s_ppdu_info->tsf_l32) + 4476 tsf_l32; 4477 else 4478 time_delta = tsf_l32 - 4479 s_ppdu_info->tsf_l32; 4480 if (time_delta < WRAP_DROP_TSF_DELTA) { 4481 ppdu_info = s_ppdu_info; 4482 break; 4483 } 4484 } else { 4485 /* 4486 * ACK BA STATUS TLV comes sequential order 4487 * if we received ack ba status tlv for second 4488 * ppdu and first ppdu is still waiting for 4489 * ACK BA STATUS TLV. Based on fw comment 4490 * we won't receive it tlv later. So we can 4491 * set ppdu info done. 4492 */ 4493 if (s_ppdu_info) 4494 s_ppdu_info->done = 1; 4495 } 4496 } 4497 } 4498 4499 if (ppdu_info) { 4500 if (ppdu_info->tlv_bitmap & (1 << tlv_type)) { 4501 /** 4502 * if we get tlv_type that is already been processed 4503 * for ppdu, that means we got a new ppdu with same 4504 * ppdu id. Hence Flush the older ppdu 4505 * for MUMIMO and OFDMA, In a PPDU we have 4506 * multiple user with same tlv types. tlv bitmap is 4507 * used to check whether SU or MU_MIMO/OFDMA 4508 */ 4509 if (!(ppdu_info->tlv_bitmap & 4510 (1 << HTT_PPDU_STATS_SCH_CMD_STATUS_TLV))) 4511 return ppdu_info; 4512 4513 ppdu_desc = (struct cdp_tx_completion_ppdu *) 4514 qdf_nbuf_data(ppdu_info->nbuf); 4515 4516 /** 4517 * apart from ACK BA STATUS TLV rest all comes in order 4518 * so if tlv type not ACK BA STATUS TLV we can deliver 4519 * ppdu_info 4520 */ 4521 if ((tlv_type == 4522 HTT_PPDU_STATS_USR_COMPLTN_ACK_BA_STATUS_TLV) && 4523 ((ppdu_desc->htt_frame_type == 4524 HTT_STATS_FTYPE_SGEN_MU_BAR) || 4525 (ppdu_desc->htt_frame_type == 4526 HTT_STATS_FTYPE_SGEN_BE_MU_BAR))) 4527 return ppdu_info; 4528 4529 dp_tx_ppdu_desc_deliver(pdev, ppdu_info); 4530 } else { 4531 return ppdu_info; 4532 } 4533 } 4534 4535 /** 4536 * Flush the head ppdu descriptor if ppdu desc list reaches max 4537 * threshold 4538 */ 4539 if (mon_pdev->list_depth > HTT_PPDU_DESC_MAX_DEPTH) { 4540 ppdu_info = TAILQ_FIRST(&mon_pdev->ppdu_info_list); 4541 TAILQ_REMOVE(&mon_pdev->ppdu_info_list, 4542 ppdu_info, ppdu_info_list_elem); 4543 mon_pdev->list_depth--; 4544 pdev->stats.ppdu_drop++; 4545 qdf_nbuf_free(ppdu_info->nbuf); 4546 ppdu_info->nbuf = NULL; 4547 qdf_mem_free(ppdu_info); 4548 } 4549 4550 size = sizeof(struct cdp_tx_completion_ppdu) + 4551 (max_users * sizeof(struct cdp_tx_completion_ppdu_user)); 4552 4553 /* 4554 * Allocate new ppdu_info node 4555 */ 4556 ppdu_info = qdf_mem_malloc(sizeof(struct ppdu_info)); 4557 if (!ppdu_info) 4558 return NULL; 4559 4560 ppdu_info->nbuf = qdf_nbuf_alloc(pdev->soc->osdev, size, 4561 0, 4, TRUE); 4562 if (!ppdu_info->nbuf) { 4563 qdf_mem_free(ppdu_info); 4564 return NULL; 4565 } 4566 4567 ppdu_info->ppdu_desc = 4568 (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 4569 qdf_mem_zero(qdf_nbuf_data(ppdu_info->nbuf), size); 4570 4571 if (!qdf_nbuf_put_tail(ppdu_info->nbuf, size)) { 4572 dp_mon_err("No tailroom for HTT PPDU"); 4573 qdf_nbuf_free(ppdu_info->nbuf); 4574 ppdu_info->nbuf = NULL; 4575 ppdu_info->last_user = 0; 4576 qdf_mem_free(ppdu_info); 4577 return NULL; 4578 } 4579 4580 ppdu_info->ppdu_desc->max_users = max_users; 4581 ppdu_info->tsf_l32 = tsf_l32; 4582 /** 4583 * No lock is needed because all PPDU TLVs are processed in 4584 * same context and this list is updated in same context 4585 */ 4586 TAILQ_INSERT_TAIL(&mon_pdev->ppdu_info_list, ppdu_info, 4587 ppdu_info_list_elem); 4588 mon_pdev->list_depth++; 4589 return ppdu_info; 4590 } 4591 4592 /** 4593 * dp_htt_process_tlv(): Function to process each PPDU TLVs 4594 * @pdev: DP pdev handle 4595 * @htt_t2h_msg: HTT target to host message 4596 * 4597 * return: ppdu_info per ppdu tlv structure 4598 */ 4599 static struct ppdu_info *dp_htt_process_tlv(struct dp_pdev *pdev, 4600 qdf_nbuf_t htt_t2h_msg) 4601 { 4602 uint32_t length; 4603 uint32_t ppdu_id; 4604 uint8_t tlv_type; 4605 uint32_t tlv_length, tlv_bitmap_expected; 4606 uint8_t *tlv_buf; 4607 struct ppdu_info *ppdu_info = NULL; 4608 struct cdp_tx_completion_ppdu *ppdu_desc = NULL; 4609 uint8_t max_users = CDP_MU_MAX_USERS; 4610 uint32_t tsf_l32; 4611 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 4612 4613 uint32_t *msg_word = (uint32_t *)qdf_nbuf_data(htt_t2h_msg); 4614 4615 length = HTT_T2H_PPDU_STATS_PAYLOAD_SIZE_GET(*msg_word); 4616 4617 msg_word = msg_word + 1; 4618 ppdu_id = HTT_T2H_PPDU_STATS_PPDU_ID_GET(*msg_word); 4619 4620 msg_word = msg_word + 1; 4621 tsf_l32 = (uint32_t)(*msg_word); 4622 4623 msg_word = msg_word + 2; 4624 while (length > 0) { 4625 tlv_buf = (uint8_t *)msg_word; 4626 tlv_type = HTT_STATS_TLV_TAG_GET(*msg_word); 4627 tlv_length = HTT_STATS_TLV_LENGTH_GET(*msg_word); 4628 if (qdf_likely(tlv_type < CDP_PPDU_STATS_MAX_TAG)) 4629 pdev->stats.ppdu_stats_counter[tlv_type]++; 4630 4631 if (tlv_length == 0) 4632 break; 4633 4634 tlv_length += HTT_TLV_HDR_LEN; 4635 4636 /** 4637 * Not allocating separate ppdu descriptor for MGMT Payload 4638 * TLV as this is sent as separate WDI indication and it 4639 * doesn't contain any ppdu information 4640 */ 4641 if (tlv_type == HTT_PPDU_STATS_TX_MGMTCTRL_PAYLOAD_TLV) { 4642 mon_pdev->mgmtctrl_frm_info.mgmt_buf = tlv_buf; 4643 mon_pdev->mgmtctrl_frm_info.ppdu_id = ppdu_id; 4644 mon_pdev->mgmtctrl_frm_info.mgmt_buf_len = 4645 HTT_PPDU_STATS_TX_MGMTCTRL_TLV_FRAME_LENGTH_GET 4646 (*(msg_word + 1)); 4647 msg_word = 4648 (uint32_t *)((uint8_t *)tlv_buf + tlv_length); 4649 length -= (tlv_length); 4650 continue; 4651 } 4652 4653 /* 4654 * retrieve max_users if it's USERS_INFO, 4655 * else, it's 1 for COMPLTN_FLUSH, 4656 * else, use CDP_MU_MAX_USERS 4657 */ 4658 if (tlv_type == HTT_PPDU_STATS_USERS_INFO_TLV) { 4659 max_users = 4660 HTT_PPDU_STATS_USERS_INFO_TLV_MAX_USERS_GET(*(msg_word + 1)); 4661 } else if (tlv_type == HTT_PPDU_STATS_USR_COMPLTN_FLUSH_TLV) { 4662 max_users = 1; 4663 } 4664 4665 ppdu_info = dp_get_ppdu_desc(pdev, ppdu_id, tlv_type, 4666 tsf_l32, max_users); 4667 if (!ppdu_info) 4668 return NULL; 4669 4670 ppdu_info->ppdu_id = ppdu_id; 4671 ppdu_info->tlv_bitmap |= (1 << tlv_type); 4672 4673 dp_process_ppdu_tag(pdev, msg_word, tlv_length, ppdu_info); 4674 4675 /** 4676 * Increment pdev level tlv count to monitor 4677 * missing TLVs 4678 */ 4679 mon_pdev->tlv_count++; 4680 ppdu_info->last_tlv_cnt = mon_pdev->tlv_count; 4681 msg_word = (uint32_t *)((uint8_t *)tlv_buf + tlv_length); 4682 length -= (tlv_length); 4683 } 4684 4685 if (!ppdu_info) 4686 return NULL; 4687 4688 mon_pdev->last_ppdu_id = ppdu_id; 4689 4690 tlv_bitmap_expected = HTT_PPDU_DEFAULT_TLV_BITMAP; 4691 4692 if (mon_pdev->tx_sniffer_enable || mon_pdev->mcopy_mode || 4693 mon_pdev->tx_capture_enabled) { 4694 if (ppdu_info->is_ampdu) 4695 tlv_bitmap_expected = 4696 dp_htt_get_ppdu_sniffer_ampdu_tlv_bitmap( 4697 ppdu_info->tlv_bitmap); 4698 } 4699 4700 ppdu_desc = ppdu_info->ppdu_desc; 4701 4702 if (!ppdu_desc) 4703 return NULL; 4704 4705 if (ppdu_desc->user[ppdu_desc->last_usr_index].completion_status != 4706 HTT_PPDU_STATS_USER_STATUS_OK) { 4707 tlv_bitmap_expected = tlv_bitmap_expected & 0xFF; 4708 } 4709 4710 /* 4711 * for frame type DATA and BAR, we update stats based on MSDU, 4712 * successful msdu and mpdu are populate from ACK BA STATUS TLV 4713 * which comes out of order. successful mpdu also populated from 4714 * COMPLTN COMMON TLV which comes in order. for every ppdu_info 4715 * we store successful mpdu from both tlv and compare before delivering 4716 * to make sure we received ACK BA STATUS TLV. For some self generated 4717 * frame we won't get ack ba status tlv so no need to wait for 4718 * ack ba status tlv. 4719 */ 4720 if (ppdu_desc->frame_type != CDP_PPDU_FTYPE_CTRL && 4721 ppdu_desc->htt_frame_type != HTT_STATS_FTYPE_SGEN_QOS_NULL) { 4722 /* 4723 * most of the time bar frame will have duplicate ack ba 4724 * status tlv 4725 */ 4726 if (ppdu_desc->frame_type == CDP_PPDU_FTYPE_BAR && 4727 (ppdu_info->compltn_common_tlv != ppdu_info->ack_ba_tlv)) 4728 return NULL; 4729 /* 4730 * For data frame, compltn common tlv should match ack ba status 4731 * tlv and completion status. Reason we are checking first user 4732 * for ofdma, completion seen at next MU BAR frm, for mimo 4733 * only for first user completion will be immediate. 4734 */ 4735 if (ppdu_desc->frame_type == CDP_PPDU_FTYPE_DATA && 4736 (ppdu_desc->user[0].completion_status == 0 && 4737 (ppdu_info->compltn_common_tlv != ppdu_info->ack_ba_tlv))) 4738 return NULL; 4739 } 4740 4741 /** 4742 * Once all the TLVs for a given PPDU has been processed, 4743 * return PPDU status to be delivered to higher layer. 4744 * tlv_bitmap_expected can't be available for different frame type. 4745 * But SCHED CMD STATS TLV is the last TLV from the FW for a ppdu. 4746 * apart from ACK BA TLV, FW sends other TLV in sequential order. 4747 * flush tlv comes separate. 4748 */ 4749 if ((ppdu_info->tlv_bitmap != 0 && 4750 (ppdu_info->tlv_bitmap & 4751 (1 << HTT_PPDU_STATS_SCH_CMD_STATUS_TLV))) || 4752 (ppdu_info->tlv_bitmap & 4753 (1 << HTT_PPDU_STATS_USR_COMPLTN_FLUSH_TLV))) { 4754 ppdu_info->done = 1; 4755 return ppdu_info; 4756 } 4757 4758 return NULL; 4759 } 4760 #endif /* QCA_ENHANCED_STATS_SUPPORT */ 4761 4762 #ifdef QCA_ENHANCED_STATS_SUPPORT 4763 /** 4764 * dp_tx_ppdu_stats_feat_enable_check() - Check if feature(s) is enabled to 4765 * consume stats received from FW via HTT 4766 * @pdev: Datapath pdev handle 4767 * 4768 * Return: void 4769 */ 4770 static bool dp_tx_ppdu_stats_feat_enable_check(struct dp_pdev *pdev) 4771 { 4772 struct dp_soc *soc = pdev->soc; 4773 struct dp_mon_ops *mon_ops = NULL; 4774 4775 mon_ops = dp_mon_ops_get(soc); 4776 if (mon_ops && mon_ops->mon_ppdu_stats_feat_enable_check) 4777 return mon_ops->mon_ppdu_stats_feat_enable_check(pdev); 4778 else 4779 return false; 4780 } 4781 #endif 4782 4783 #if defined(WDI_EVENT_ENABLE) 4784 #ifdef QCA_ENHANCED_STATS_SUPPORT 4785 /** 4786 * dp_txrx_ppdu_stats_handler() - Function to process HTT PPDU stats from FW 4787 * @soc: DP SOC handle 4788 * @pdev_id: pdev id 4789 * @htt_t2h_msg: HTT message nbuf 4790 * 4791 * return:void 4792 */ 4793 static bool dp_txrx_ppdu_stats_handler(struct dp_soc *soc, 4794 uint8_t pdev_id, qdf_nbuf_t htt_t2h_msg) 4795 { 4796 struct dp_pdev *pdev; 4797 struct ppdu_info *ppdu_info = NULL; 4798 bool free_buf = true; 4799 struct dp_mon_pdev *mon_pdev; 4800 4801 if (pdev_id >= MAX_PDEV_CNT) 4802 return true; 4803 4804 pdev = soc->pdev_list[pdev_id]; 4805 if (!pdev) 4806 return true; 4807 4808 mon_pdev = pdev->monitor_pdev; 4809 if (!mon_pdev) 4810 return true; 4811 4812 if (!dp_tx_ppdu_stats_feat_enable_check(pdev)) 4813 return free_buf; 4814 4815 qdf_spin_lock_bh(&mon_pdev->ppdu_stats_lock); 4816 ppdu_info = dp_htt_process_tlv(pdev, htt_t2h_msg); 4817 4818 if (mon_pdev->mgmtctrl_frm_info.mgmt_buf) { 4819 if (dp_process_ppdu_stats_tx_mgmtctrl_payload_tlv 4820 (pdev, htt_t2h_msg, mon_pdev->mgmtctrl_frm_info.ppdu_id) != 4821 QDF_STATUS_SUCCESS) 4822 free_buf = false; 4823 } 4824 4825 if (ppdu_info) 4826 dp_tx_ppdu_desc_deliver(pdev, ppdu_info); 4827 4828 mon_pdev->mgmtctrl_frm_info.mgmt_buf = NULL; 4829 mon_pdev->mgmtctrl_frm_info.mgmt_buf_len = 0; 4830 mon_pdev->mgmtctrl_frm_info.ppdu_id = 0; 4831 4832 qdf_spin_unlock_bh(&mon_pdev->ppdu_stats_lock); 4833 4834 return free_buf; 4835 } 4836 #elif (!defined(REMOVE_PKT_LOG)) 4837 static bool dp_txrx_ppdu_stats_handler(struct dp_soc *soc, 4838 uint8_t pdev_id, qdf_nbuf_t htt_t2h_msg) 4839 { 4840 return true; 4841 } 4842 #endif/* QCA_ENHANCED_STATS_SUPPORT */ 4843 #endif 4844 4845 #if defined(WDI_EVENT_ENABLE) &&\ 4846 (defined(QCA_ENHANCED_STATS_SUPPORT) || !defined(REMOVE_PKT_LOG)) 4847 /* 4848 * dp_ppdu_stats_ind_handler() - PPDU stats msg handler 4849 * @htt_soc: HTT SOC handle 4850 * @msg_word: Pointer to payload 4851 * @htt_t2h_msg: HTT msg nbuf 4852 * 4853 * Return: True if buffer should be freed by caller. 4854 */ 4855 bool 4856 dp_ppdu_stats_ind_handler(struct htt_soc *soc, 4857 uint32_t *msg_word, 4858 qdf_nbuf_t htt_t2h_msg) 4859 { 4860 u_int8_t pdev_id; 4861 u_int8_t target_pdev_id; 4862 bool free_buf; 4863 4864 target_pdev_id = HTT_T2H_PPDU_STATS_PDEV_ID_GET(*msg_word); 4865 pdev_id = dp_get_host_pdev_id_for_target_pdev_id(soc->dp_soc, 4866 target_pdev_id); 4867 dp_wdi_event_handler(WDI_EVENT_LITE_T2H, soc->dp_soc, 4868 htt_t2h_msg, HTT_INVALID_PEER, WDI_NO_VAL, 4869 pdev_id); 4870 4871 free_buf = dp_txrx_ppdu_stats_handler(soc->dp_soc, pdev_id, 4872 htt_t2h_msg); 4873 4874 return free_buf; 4875 } 4876 #endif 4877 4878 void 4879 dp_mon_set_bsscolor(struct dp_pdev *pdev, uint8_t bsscolor) 4880 { 4881 pdev->monitor_pdev->rx_mon_recv_status.bsscolor = bsscolor; 4882 } 4883 4884 bool dp_pdev_get_filter_ucast_data(struct cdp_pdev *pdev_handle) 4885 { 4886 struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; 4887 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 4888 4889 if ((mon_pdev->fp_data_filter & FILTER_DATA_UCAST) || 4890 (mon_pdev->mo_data_filter & FILTER_DATA_UCAST)) 4891 return true; 4892 4893 return false; 4894 } 4895 4896 bool dp_pdev_get_filter_mcast_data(struct cdp_pdev *pdev_handle) 4897 { 4898 struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; 4899 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 4900 4901 if ((mon_pdev->fp_data_filter & FILTER_DATA_MCAST) || 4902 (mon_pdev->mo_data_filter & FILTER_DATA_MCAST)) 4903 return true; 4904 4905 return false; 4906 } 4907 4908 bool dp_pdev_get_filter_non_data(struct cdp_pdev *pdev_handle) 4909 { 4910 struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; 4911 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 4912 4913 if ((mon_pdev->fp_mgmt_filter & FILTER_MGMT_ALL) || 4914 (mon_pdev->mo_mgmt_filter & FILTER_MGMT_ALL)) { 4915 if ((mon_pdev->fp_ctrl_filter & FILTER_CTRL_ALL) || 4916 (mon_pdev->mo_ctrl_filter & FILTER_CTRL_ALL)) { 4917 return true; 4918 } 4919 } 4920 4921 return false; 4922 } 4923 4924 QDF_STATUS dp_mon_soc_cfg_init(struct dp_soc *soc) 4925 { 4926 int target_type; 4927 struct dp_mon_soc *mon_soc = soc->monitor_soc; 4928 struct cdp_mon_ops *cdp_ops; 4929 4930 cdp_ops = dp_mon_cdp_ops_get(soc); 4931 target_type = hal_get_target_type(soc->hal_soc); 4932 switch (target_type) { 4933 case TARGET_TYPE_QCA6290: 4934 case TARGET_TYPE_QCA6390: 4935 case TARGET_TYPE_QCA6490: 4936 case TARGET_TYPE_QCA6750: 4937 case TARGET_TYPE_KIWI: 4938 case TARGET_TYPE_MANGO: 4939 /* do nothing */ 4940 break; 4941 case TARGET_TYPE_QCA8074: 4942 wlan_cfg_set_mon_delayed_replenish_entries(soc->wlan_cfg_ctx, 4943 MON_BUF_MIN_ENTRIES); 4944 break; 4945 case TARGET_TYPE_QCA8074V2: 4946 case TARGET_TYPE_QCA6018: 4947 case TARGET_TYPE_QCA9574: 4948 wlan_cfg_set_mon_delayed_replenish_entries(soc->wlan_cfg_ctx, 4949 MON_BUF_MIN_ENTRIES); 4950 mon_soc->hw_nac_monitor_support = 1; 4951 break; 4952 case TARGET_TYPE_QCN9000: 4953 wlan_cfg_set_mon_delayed_replenish_entries(soc->wlan_cfg_ctx, 4954 MON_BUF_MIN_ENTRIES); 4955 mon_soc->hw_nac_monitor_support = 1; 4956 if (cfg_get(soc->ctrl_psoc, CFG_DP_FULL_MON_MODE)) { 4957 if (cdp_ops && cdp_ops->config_full_mon_mode) 4958 cdp_ops->config_full_mon_mode((struct cdp_soc_t *)soc, 1); 4959 } 4960 break; 4961 case TARGET_TYPE_QCA5018: 4962 case TARGET_TYPE_QCN6122: 4963 wlan_cfg_set_mon_delayed_replenish_entries(soc->wlan_cfg_ctx, 4964 MON_BUF_MIN_ENTRIES); 4965 mon_soc->hw_nac_monitor_support = 1; 4966 break; 4967 case TARGET_TYPE_QCN9224: 4968 case TARGET_TYPE_QCA5332: 4969 wlan_cfg_set_mon_delayed_replenish_entries(soc->wlan_cfg_ctx, 4970 MON_BUF_MIN_ENTRIES); 4971 mon_soc->hw_nac_monitor_support = 1; 4972 mon_soc->monitor_mode_v2 = 1; 4973 break; 4974 default: 4975 dp_mon_info("%s: Unknown tgt type %d\n", __func__, target_type); 4976 qdf_assert_always(0); 4977 break; 4978 } 4979 4980 dp_mon_info("hw_nac_monitor_support = %d", 4981 mon_soc->hw_nac_monitor_support); 4982 4983 return QDF_STATUS_SUCCESS; 4984 } 4985 4986 /** 4987 * dp_mon_pdev_per_target_config() - Target specific monitor pdev configuration 4988 * @pdev: PDEV handle [Should be valid] 4989 * 4990 * Return: None 4991 */ 4992 static void dp_mon_pdev_per_target_config(struct dp_pdev *pdev) 4993 { 4994 struct dp_soc *soc = pdev->soc; 4995 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 4996 int target_type; 4997 4998 target_type = hal_get_target_type(soc->hal_soc); 4999 switch (target_type) { 5000 case TARGET_TYPE_KIWI: 5001 case TARGET_TYPE_MANGO: 5002 mon_pdev->is_tlv_hdr_64_bit = true; 5003 break; 5004 default: 5005 mon_pdev->is_tlv_hdr_64_bit = false; 5006 break; 5007 } 5008 } 5009 5010 QDF_STATUS dp_mon_pdev_attach(struct dp_pdev *pdev) 5011 { 5012 struct dp_soc *soc; 5013 struct dp_mon_pdev *mon_pdev; 5014 struct dp_mon_ops *mon_ops; 5015 qdf_size_t mon_pdev_context_size; 5016 5017 if (!pdev) { 5018 dp_mon_err("pdev is NULL"); 5019 goto fail0; 5020 } 5021 5022 soc = pdev->soc; 5023 5024 mon_pdev_context_size = soc->arch_ops.txrx_get_mon_context_size(DP_CONTEXT_TYPE_MON_PDEV); 5025 mon_pdev = dp_context_alloc_mem(soc, DP_MON_PDEV_TYPE, mon_pdev_context_size); 5026 if (!mon_pdev) { 5027 dp_mon_err("%pK: MONITOR pdev allocation failed", pdev); 5028 goto fail0; 5029 } 5030 5031 pdev->monitor_pdev = mon_pdev; 5032 mon_ops = dp_mon_ops_get(pdev->soc); 5033 if (!mon_ops) { 5034 dp_mon_err("%pK: Invalid monitor ops", pdev); 5035 goto fail1; 5036 } 5037 5038 if (mon_ops->mon_pdev_alloc) { 5039 if (mon_ops->mon_pdev_alloc(pdev)) { 5040 dp_mon_err("%pK: MONITOR pdev alloc failed", pdev); 5041 goto fail1; 5042 } 5043 } 5044 5045 if (mon_ops->mon_rings_alloc) { 5046 if (mon_ops->mon_rings_alloc(pdev)) { 5047 dp_mon_err("%pK: MONITOR rings setup failed", pdev); 5048 goto fail2; 5049 } 5050 } 5051 5052 /* Rx monitor mode specific init */ 5053 if (mon_ops->rx_mon_desc_pool_alloc) { 5054 if (mon_ops->rx_mon_desc_pool_alloc(pdev)) { 5055 dp_mon_err("%pK: dp_rx_pdev_mon_attach failed", pdev); 5056 goto fail3; 5057 } 5058 } 5059 5060 if (mon_ops->mon_rx_ppdu_info_cache_create) { 5061 if (mon_ops->mon_rx_ppdu_info_cache_create(pdev)) { 5062 dp_mon_err("%pK: dp_rx_pdev_mon_attach failed", pdev); 5063 goto fail4; 5064 } 5065 } 5066 pdev->monitor_pdev = mon_pdev; 5067 dp_mon_pdev_per_target_config(pdev); 5068 5069 return QDF_STATUS_SUCCESS; 5070 fail4: 5071 if (mon_ops->rx_mon_desc_pool_free) 5072 mon_ops->rx_mon_desc_pool_free(pdev); 5073 fail3: 5074 if (mon_ops->mon_rings_free) 5075 mon_ops->mon_rings_free(pdev); 5076 fail2: 5077 if (mon_ops->mon_pdev_free) 5078 mon_ops->mon_pdev_free(pdev); 5079 fail1: 5080 pdev->monitor_pdev = NULL; 5081 qdf_mem_free(mon_pdev); 5082 fail0: 5083 return QDF_STATUS_E_NOMEM; 5084 } 5085 5086 QDF_STATUS dp_mon_pdev_detach(struct dp_pdev *pdev) 5087 { 5088 struct dp_mon_pdev *mon_pdev; 5089 struct dp_mon_ops *mon_ops = NULL; 5090 5091 if (!pdev) { 5092 dp_mon_err("pdev is NULL"); 5093 return QDF_STATUS_E_FAILURE; 5094 } 5095 5096 mon_pdev = pdev->monitor_pdev; 5097 if (!mon_pdev) { 5098 dp_mon_err("Monitor pdev is NULL"); 5099 return QDF_STATUS_E_FAILURE; 5100 } 5101 5102 mon_ops = dp_mon_ops_get(pdev->soc); 5103 if (!mon_ops) { 5104 dp_mon_err("Monitor ops is NULL"); 5105 return QDF_STATUS_E_FAILURE; 5106 } 5107 5108 if (mon_ops->mon_rx_ppdu_info_cache_destroy) 5109 mon_ops->mon_rx_ppdu_info_cache_destroy(pdev); 5110 if (mon_ops->rx_mon_desc_pool_free) 5111 mon_ops->rx_mon_desc_pool_free(pdev); 5112 if (mon_ops->mon_rings_free) 5113 mon_ops->mon_rings_free(pdev); 5114 if (mon_ops->mon_pdev_free) 5115 mon_ops->mon_pdev_free(pdev); 5116 5117 qdf_mem_free(mon_pdev); 5118 pdev->monitor_pdev = NULL; 5119 return QDF_STATUS_SUCCESS; 5120 } 5121 5122 QDF_STATUS dp_mon_pdev_init(struct dp_pdev *pdev) 5123 { 5124 struct dp_soc *soc; 5125 struct dp_mon_pdev *mon_pdev; 5126 struct dp_mon_ops *mon_ops = NULL; 5127 5128 if (!pdev) { 5129 dp_mon_err("pdev is NULL"); 5130 return QDF_STATUS_E_FAILURE; 5131 } 5132 5133 soc = pdev->soc; 5134 mon_pdev = pdev->monitor_pdev; 5135 5136 mon_pdev->invalid_mon_peer = qdf_mem_malloc(sizeof(struct dp_mon_peer)); 5137 if (!mon_pdev->invalid_mon_peer) { 5138 dp_mon_err("%pK: Memory allocation failed for invalid " 5139 "monitor peer", pdev); 5140 return QDF_STATUS_E_NOMEM; 5141 } 5142 5143 mon_ops = dp_mon_ops_get(pdev->soc); 5144 if (!mon_ops) { 5145 dp_mon_err("Monitor ops is NULL"); 5146 goto fail0; 5147 } 5148 5149 mon_pdev->filter = dp_mon_filter_alloc(mon_pdev); 5150 if (!mon_pdev->filter) { 5151 dp_mon_err("%pK: Memory allocation failed for monitor filter", 5152 pdev); 5153 goto fail0; 5154 } 5155 5156 if (mon_ops->tx_mon_filter_alloc) { 5157 if (mon_ops->tx_mon_filter_alloc(pdev)) { 5158 dp_mon_err("%pK: Memory allocation failed for tx monitor " 5159 "filter", pdev); 5160 goto fail1; 5161 } 5162 } 5163 5164 qdf_spinlock_create(&mon_pdev->ppdu_stats_lock); 5165 qdf_spinlock_create(&mon_pdev->neighbour_peer_mutex); 5166 mon_pdev->monitor_configured = false; 5167 mon_pdev->mon_chan_band = REG_BAND_UNKNOWN; 5168 5169 TAILQ_INIT(&mon_pdev->neighbour_peers_list); 5170 mon_pdev->neighbour_peers_added = false; 5171 mon_pdev->monitor_configured = false; 5172 /* Monitor filter init */ 5173 mon_pdev->mon_filter_mode = MON_FILTER_ALL; 5174 mon_pdev->fp_mgmt_filter = FILTER_MGMT_ALL; 5175 mon_pdev->fp_ctrl_filter = FILTER_CTRL_ALL; 5176 mon_pdev->fp_data_filter = FILTER_DATA_ALL; 5177 mon_pdev->mo_mgmt_filter = FILTER_MGMT_ALL; 5178 mon_pdev->mo_ctrl_filter = FILTER_CTRL_ALL; 5179 mon_pdev->mo_data_filter = FILTER_DATA_ALL; 5180 5181 /* 5182 * initialize ppdu tlv list 5183 */ 5184 TAILQ_INIT(&mon_pdev->ppdu_info_list); 5185 TAILQ_INIT(&mon_pdev->sched_comp_ppdu_list); 5186 5187 mon_pdev->list_depth = 0; 5188 mon_pdev->tlv_count = 0; 5189 /* initlialize cal client timer */ 5190 dp_cal_client_attach(&mon_pdev->cal_client_ctx, 5191 dp_pdev_to_cdp_pdev(pdev), 5192 pdev->soc->osdev, 5193 &dp_iterate_update_peer_list); 5194 if (dp_htt_ppdu_stats_attach(pdev) != QDF_STATUS_SUCCESS) 5195 goto fail2; 5196 5197 if (mon_ops->mon_lite_mon_alloc) { 5198 if (mon_ops->mon_lite_mon_alloc(pdev) != QDF_STATUS_SUCCESS) { 5199 dp_mon_err("%pK: lite mon alloc failed", pdev); 5200 goto fail3; 5201 } 5202 } 5203 5204 if (mon_ops->mon_rings_init) { 5205 if (mon_ops->mon_rings_init(pdev)) { 5206 dp_mon_err("%pK: MONITOR rings setup failed", pdev); 5207 goto fail4; 5208 } 5209 } 5210 5211 /* initialize sw monitor rx descriptors */ 5212 if (mon_ops->rx_mon_desc_pool_init) 5213 mon_ops->rx_mon_desc_pool_init(pdev); 5214 5215 /* allocate buffers and replenish the monitor RxDMA ring */ 5216 if (mon_ops->rx_mon_buffers_alloc) { 5217 if (mon_ops->rx_mon_buffers_alloc(pdev)) { 5218 dp_mon_err("%pK: rx mon buffers alloc failed", pdev); 5219 goto fail5; 5220 } 5221 } 5222 5223 /* attach monitor function */ 5224 dp_monitor_tx_ppdu_stats_attach(pdev); 5225 5226 /* mon pdev extended init */ 5227 if (mon_ops->mon_pdev_ext_init) 5228 mon_ops->mon_pdev_ext_init(pdev); 5229 5230 mon_pdev->is_dp_mon_pdev_initialized = true; 5231 5232 return QDF_STATUS_SUCCESS; 5233 5234 fail5: 5235 if (mon_ops->rx_mon_desc_pool_deinit) 5236 mon_ops->rx_mon_desc_pool_deinit(pdev); 5237 5238 if (mon_ops->mon_rings_deinit) 5239 mon_ops->mon_rings_deinit(pdev); 5240 fail4: 5241 if (mon_ops->mon_lite_mon_dealloc) 5242 mon_ops->mon_lite_mon_dealloc(pdev); 5243 fail3: 5244 dp_htt_ppdu_stats_detach(pdev); 5245 fail2: 5246 qdf_spinlock_destroy(&mon_pdev->neighbour_peer_mutex); 5247 qdf_spinlock_destroy(&mon_pdev->ppdu_stats_lock); 5248 if (mon_ops->tx_mon_filter_dealloc) 5249 mon_ops->tx_mon_filter_dealloc(pdev); 5250 fail1: 5251 dp_mon_filter_dealloc(mon_pdev); 5252 fail0: 5253 qdf_mem_free(mon_pdev->invalid_mon_peer); 5254 return QDF_STATUS_E_FAILURE; 5255 } 5256 5257 QDF_STATUS dp_mon_pdev_deinit(struct dp_pdev *pdev) 5258 { 5259 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; 5260 struct dp_mon_ops *mon_ops = NULL; 5261 5262 mon_ops = dp_mon_ops_get(pdev->soc); 5263 if (!mon_ops) { 5264 dp_mon_err("Monitor ops is NULL"); 5265 return QDF_STATUS_E_FAILURE; 5266 } 5267 5268 if (!mon_pdev->is_dp_mon_pdev_initialized) 5269 return QDF_STATUS_SUCCESS; 5270 5271 dp_mon_filters_reset(pdev); 5272 5273 /* mon pdev extended deinit */ 5274 if (mon_ops->mon_pdev_ext_deinit) 5275 mon_ops->mon_pdev_ext_deinit(pdev); 5276 5277 /* detach monitor function */ 5278 dp_monitor_tx_ppdu_stats_detach(pdev); 5279 5280 if (mon_ops->rx_mon_buffers_free) 5281 mon_ops->rx_mon_buffers_free(pdev); 5282 if (mon_ops->rx_mon_desc_pool_deinit) 5283 mon_ops->rx_mon_desc_pool_deinit(pdev); 5284 if (mon_ops->mon_rings_deinit) 5285 mon_ops->mon_rings_deinit(pdev); 5286 dp_cal_client_detach(&mon_pdev->cal_client_ctx); 5287 if (mon_ops->mon_lite_mon_dealloc) 5288 mon_ops->mon_lite_mon_dealloc(pdev); 5289 dp_htt_ppdu_stats_detach(pdev); 5290 qdf_spinlock_destroy(&mon_pdev->ppdu_stats_lock); 5291 dp_neighbour_peers_detach(pdev); 5292 dp_pktlogmod_exit(pdev); 5293 if (mon_ops->tx_mon_filter_dealloc) 5294 mon_ops->tx_mon_filter_dealloc(pdev); 5295 if (mon_pdev->filter) 5296 dp_mon_filter_dealloc(mon_pdev); 5297 if (mon_ops->mon_rings_deinit) 5298 mon_ops->mon_rings_deinit(pdev); 5299 if (mon_pdev->invalid_mon_peer) 5300 qdf_mem_free(mon_pdev->invalid_mon_peer); 5301 mon_pdev->is_dp_mon_pdev_initialized = false; 5302 5303 return QDF_STATUS_SUCCESS; 5304 } 5305 5306 QDF_STATUS dp_mon_vdev_attach(struct dp_vdev *vdev) 5307 { 5308 struct dp_mon_vdev *mon_vdev; 5309 struct dp_pdev *pdev = vdev->pdev; 5310 5311 mon_vdev = (struct dp_mon_vdev *)qdf_mem_malloc(sizeof(*mon_vdev)); 5312 if (!mon_vdev) { 5313 dp_mon_err("%pK: Monitor vdev allocation failed", vdev); 5314 return QDF_STATUS_E_NOMEM; 5315 } 5316 5317 if (pdev && pdev->monitor_pdev && 5318 pdev->monitor_pdev->scan_spcl_vap_configured) 5319 dp_scan_spcl_vap_stats_attach(mon_vdev); 5320 5321 vdev->monitor_vdev = mon_vdev; 5322 5323 return QDF_STATUS_SUCCESS; 5324 } 5325 5326 QDF_STATUS dp_mon_vdev_detach(struct dp_vdev *vdev) 5327 { 5328 struct dp_mon_vdev *mon_vdev = vdev->monitor_vdev; 5329 struct dp_pdev *pdev = vdev->pdev; 5330 struct dp_mon_ops *mon_ops = dp_mon_ops_get(pdev->soc); 5331 5332 if (!mon_ops) 5333 return QDF_STATUS_E_FAILURE; 5334 5335 if (!mon_vdev) 5336 return QDF_STATUS_E_FAILURE; 5337 5338 if (pdev->monitor_pdev->scan_spcl_vap_configured) 5339 dp_scan_spcl_vap_stats_detach(mon_vdev); 5340 5341 qdf_mem_free(mon_vdev); 5342 vdev->monitor_vdev = NULL; 5343 /* set mvdev to NULL only if detach is called for monitor/special vap 5344 */ 5345 if (pdev->monitor_pdev->mvdev == vdev) 5346 pdev->monitor_pdev->mvdev = NULL; 5347 5348 if (mon_ops->mon_lite_mon_vdev_delete) 5349 mon_ops->mon_lite_mon_vdev_delete(pdev, vdev); 5350 5351 return QDF_STATUS_SUCCESS; 5352 } 5353 5354 #if defined(FEATURE_PERPKT_INFO) && WDI_EVENT_ENABLE 5355 /** 5356 * dp_mon_peer_attach_notify() - Raise WDI event for peer create 5357 * @peer: DP Peer handle 5358 * 5359 * Return: none 5360 */ 5361 static inline 5362 void dp_mon_peer_attach_notify(struct dp_peer *peer) 5363 { 5364 struct dp_mon_peer *mon_peer = peer->monitor_peer; 5365 struct dp_pdev *pdev; 5366 struct dp_soc *soc; 5367 struct cdp_peer_cookie peer_cookie; 5368 5369 pdev = peer->vdev->pdev; 5370 soc = pdev->soc; 5371 5372 qdf_mem_copy(peer_cookie.mac_addr, peer->mac_addr.raw, 5373 QDF_MAC_ADDR_SIZE); 5374 5375 peer_cookie.ctx = NULL; 5376 peer_cookie.pdev_id = pdev->pdev_id; 5377 peer_cookie.cookie = pdev->next_peer_cookie++; 5378 5379 dp_wdi_event_handler(WDI_EVENT_PEER_CREATE, soc, 5380 (void *)&peer_cookie, 5381 peer->peer_id, WDI_NO_VAL, pdev->pdev_id); 5382 5383 if (soc->peerstats_enabled) { 5384 if (!peer_cookie.ctx) { 5385 pdev->next_peer_cookie--; 5386 qdf_err("Failed to initialize peer rate stats"); 5387 mon_peer->peerstats_ctx = NULL; 5388 } else { 5389 mon_peer->peerstats_ctx = 5390 (struct cdp_peer_rate_stats_ctx *) 5391 peer_cookie.ctx; 5392 } 5393 } 5394 } 5395 5396 /** 5397 * dp_mon_peer_detach_notify() - Raise WDI event for peer destroy 5398 * @peer: DP Peer handle 5399 * 5400 * Return: none 5401 */ 5402 static inline 5403 void dp_mon_peer_detach_notify(struct dp_peer *peer) 5404 { 5405 struct dp_mon_peer *mon_peer = peer->monitor_peer; 5406 struct dp_pdev *pdev; 5407 struct dp_soc *soc; 5408 struct cdp_peer_cookie peer_cookie; 5409 5410 pdev = peer->vdev->pdev; 5411 soc = pdev->soc; 5412 /* send peer destroy event to upper layer */ 5413 qdf_mem_copy(peer_cookie.mac_addr, peer->mac_addr.raw, 5414 QDF_MAC_ADDR_SIZE); 5415 peer_cookie.ctx = NULL; 5416 peer_cookie.ctx = (struct cdp_stats_cookie *)mon_peer->peerstats_ctx; 5417 5418 dp_wdi_event_handler(WDI_EVENT_PEER_DESTROY, 5419 soc, 5420 (void *)&peer_cookie, 5421 peer->peer_id, 5422 WDI_NO_VAL, 5423 pdev->pdev_id); 5424 5425 mon_peer->peerstats_ctx = NULL; 5426 } 5427 #else 5428 static inline 5429 void dp_mon_peer_attach_notify(struct dp_peer *peer) 5430 { 5431 peer->monitor_peer->peerstats_ctx = NULL; 5432 } 5433 5434 static inline 5435 void dp_mon_peer_detach_notify(struct dp_peer *peer) 5436 { 5437 peer->monitor_peer->peerstats_ctx = NULL; 5438 } 5439 #endif 5440 5441 #if defined(WLAN_TX_PKT_CAPTURE_ENH) || defined(FEATURE_PERPKT_INFO) 5442 QDF_STATUS dp_mon_peer_attach(struct dp_peer *peer) 5443 { 5444 struct dp_mon_peer *mon_peer; 5445 struct dp_pdev *pdev; 5446 5447 mon_peer = (struct dp_mon_peer *)qdf_mem_malloc(sizeof(*mon_peer)); 5448 if (!mon_peer) { 5449 dp_mon_err("%pK: MONITOR peer allocation failed", peer); 5450 return QDF_STATUS_E_NOMEM; 5451 } 5452 5453 peer->monitor_peer = mon_peer; 5454 pdev = peer->vdev->pdev; 5455 /* 5456 * In tx_monitor mode, filter may be set for unassociated peer 5457 * when unassociated peer get associated peer need to 5458 * update tx_cap_enabled flag to support peer filter. 5459 */ 5460 dp_monitor_peer_tx_capture_filter_check(pdev, peer); 5461 5462 DP_STATS_INIT(mon_peer); 5463 DP_STATS_UPD(mon_peer, rx.avg_snr, CDP_INVALID_SNR); 5464 5465 dp_mon_peer_attach_notify(peer); 5466 5467 return QDF_STATUS_SUCCESS; 5468 } 5469 #endif 5470 5471 QDF_STATUS dp_mon_peer_detach(struct dp_peer *peer) 5472 { 5473 struct dp_mon_peer *mon_peer = peer->monitor_peer; 5474 5475 if (!mon_peer) 5476 return QDF_STATUS_SUCCESS; 5477 5478 dp_mon_peer_detach_notify(peer); 5479 5480 qdf_mem_free(mon_peer); 5481 peer->monitor_peer = NULL; 5482 5483 return QDF_STATUS_SUCCESS; 5484 } 5485 5486 #ifndef DISABLE_MON_CONFIG 5487 void dp_mon_register_intr_ops(struct dp_soc *soc) 5488 { 5489 struct dp_mon_ops *mon_ops = NULL; 5490 5491 mon_ops = dp_mon_ops_get(soc); 5492 if (!mon_ops) { 5493 dp_mon_err("Monitor ops is NULL"); 5494 return; 5495 } 5496 if (mon_ops->mon_register_intr_ops) 5497 mon_ops->mon_register_intr_ops(soc); 5498 } 5499 #endif 5500 5501 struct cdp_peer_rate_stats_ctx *dp_mon_peer_get_peerstats_ctx(struct 5502 dp_peer *peer) 5503 { 5504 struct dp_mon_peer *mon_peer = peer->monitor_peer; 5505 5506 if (mon_peer) 5507 return mon_peer->peerstats_ctx; 5508 else 5509 return NULL; 5510 } 5511 5512 #ifdef QCA_ENHANCED_STATS_SUPPORT 5513 void dp_mon_peer_reset_stats(struct dp_peer *peer) 5514 { 5515 struct dp_mon_peer *mon_peer = NULL; 5516 5517 mon_peer = peer->monitor_peer; 5518 if (!mon_peer) 5519 return; 5520 5521 DP_STATS_CLR(mon_peer); 5522 DP_STATS_UPD(mon_peer, rx.avg_snr, CDP_INVALID_SNR); 5523 } 5524 5525 void dp_mon_peer_get_stats(struct dp_peer *peer, void *arg, 5526 enum cdp_stat_update_type type) 5527 { 5528 struct dp_mon_peer *mon_peer = peer->monitor_peer; 5529 struct dp_mon_peer_stats *mon_peer_stats; 5530 5531 if (!mon_peer || !arg) 5532 return; 5533 5534 mon_peer_stats = &mon_peer->stats; 5535 5536 switch (type) { 5537 case UPDATE_PEER_STATS: 5538 { 5539 struct cdp_peer_stats *peer_stats = 5540 (struct cdp_peer_stats *)arg; 5541 DP_UPDATE_MON_STATS(peer_stats, mon_peer_stats); 5542 break; 5543 } 5544 case UPDATE_VDEV_STATS: 5545 { 5546 struct cdp_vdev_stats *vdev_stats = 5547 (struct cdp_vdev_stats *)arg; 5548 DP_UPDATE_MON_STATS(vdev_stats, mon_peer_stats); 5549 break; 5550 } 5551 default: 5552 dp_mon_err("Invalid stats_update_type"); 5553 } 5554 } 5555 5556 void dp_mon_invalid_peer_update_pdev_stats(struct dp_pdev *pdev) 5557 { 5558 struct dp_mon_peer *mon_peer; 5559 struct dp_mon_peer_stats *mon_peer_stats; 5560 struct cdp_pdev_stats *pdev_stats; 5561 5562 if (!pdev || !pdev->monitor_pdev) 5563 return; 5564 5565 mon_peer = pdev->monitor_pdev->invalid_mon_peer; 5566 if (!mon_peer) 5567 return; 5568 5569 mon_peer_stats = &mon_peer->stats; 5570 pdev_stats = &pdev->stats; 5571 DP_UPDATE_MON_STATS(pdev_stats, mon_peer_stats); 5572 } 5573 5574 QDF_STATUS 5575 dp_mon_peer_get_stats_param(struct dp_peer *peer, enum cdp_peer_stats_type type, 5576 cdp_peer_stats_param_t *buf) 5577 { 5578 QDF_STATUS ret = QDF_STATUS_SUCCESS; 5579 struct dp_mon_peer *mon_peer; 5580 5581 mon_peer = peer->monitor_peer; 5582 if (!mon_peer) 5583 return QDF_STATUS_E_FAILURE; 5584 5585 switch (type) { 5586 case cdp_peer_tx_rate: 5587 buf->tx_rate = mon_peer->stats.tx.tx_rate; 5588 break; 5589 case cdp_peer_tx_last_tx_rate: 5590 buf->last_tx_rate = mon_peer->stats.tx.last_tx_rate; 5591 break; 5592 case cdp_peer_tx_ratecode: 5593 buf->tx_ratecode = mon_peer->stats.tx.tx_ratecode; 5594 break; 5595 case cdp_peer_rx_rate: 5596 buf->rx_rate = mon_peer->stats.rx.rx_rate; 5597 break; 5598 case cdp_peer_rx_last_rx_rate: 5599 buf->last_rx_rate = mon_peer->stats.rx.last_rx_rate; 5600 break; 5601 case cdp_peer_rx_ratecode: 5602 buf->rx_ratecode = mon_peer->stats.rx.rx_ratecode; 5603 break; 5604 case cdp_peer_rx_avg_snr: 5605 buf->rx_avg_snr = mon_peer->stats.rx.avg_snr; 5606 break; 5607 case cdp_peer_rx_snr: 5608 buf->rx_snr = mon_peer->stats.rx.snr; 5609 break; 5610 default: 5611 dp_err("Invalid stats type requested"); 5612 ret = QDF_STATUS_E_FAILURE; 5613 } 5614 5615 return ret; 5616 } 5617 #endif 5618 5619 void dp_mon_ops_register(struct dp_soc *soc) 5620 { 5621 struct dp_mon_soc *mon_soc = soc->monitor_soc; 5622 uint32_t target_type; 5623 5624 target_type = hal_get_target_type(soc->hal_soc); 5625 switch (target_type) { 5626 case TARGET_TYPE_QCA6290: 5627 case TARGET_TYPE_QCA6390: 5628 case TARGET_TYPE_QCA6490: 5629 case TARGET_TYPE_QCA6750: 5630 case TARGET_TYPE_KIWI: 5631 case TARGET_TYPE_MANGO: 5632 case TARGET_TYPE_QCA8074: 5633 case TARGET_TYPE_QCA8074V2: 5634 case TARGET_TYPE_QCA6018: 5635 case TARGET_TYPE_QCA9574: 5636 case TARGET_TYPE_QCN9000: 5637 case TARGET_TYPE_QCA5018: 5638 case TARGET_TYPE_QCN6122: 5639 dp_mon_ops_register_1_0(mon_soc); 5640 break; 5641 case TARGET_TYPE_QCN9224: 5642 case TARGET_TYPE_QCA5332: 5643 #ifdef QCA_MONITOR_2_0_SUPPORT 5644 dp_mon_ops_register_2_0(mon_soc); 5645 #endif 5646 break; 5647 default: 5648 dp_mon_err("%s: Unknown tgt type %d", __func__, target_type); 5649 qdf_assert_always(0); 5650 break; 5651 } 5652 } 5653 5654 #ifdef QCA_MONITOR_OPS_PER_SOC_SUPPORT 5655 void dp_mon_ops_free(struct dp_soc *soc) 5656 { 5657 struct cdp_ops *ops = soc->cdp_soc.ops; 5658 struct cdp_mon_ops *cdp_mon_ops = ops->mon_ops; 5659 struct dp_mon_soc *mon_soc = soc->monitor_soc; 5660 struct dp_mon_ops *mon_ops = mon_soc->mon_ops; 5661 5662 if (cdp_mon_ops) 5663 qdf_mem_free(cdp_mon_ops); 5664 5665 if (mon_ops) 5666 qdf_mem_free(mon_ops); 5667 } 5668 #else 5669 void dp_mon_ops_free(struct dp_soc *soc) 5670 { 5671 } 5672 #endif 5673 5674 void dp_mon_cdp_ops_register(struct dp_soc *soc) 5675 { 5676 struct cdp_ops *ops = soc->cdp_soc.ops; 5677 uint32_t target_type; 5678 5679 if (!ops) { 5680 dp_mon_err("cdp_ops is NULL"); 5681 return; 5682 } 5683 5684 target_type = hal_get_target_type(soc->hal_soc); 5685 switch (target_type) { 5686 case TARGET_TYPE_QCA6290: 5687 case TARGET_TYPE_QCA6390: 5688 case TARGET_TYPE_QCA6490: 5689 case TARGET_TYPE_QCA6750: 5690 case TARGET_TYPE_KIWI: 5691 case TARGET_TYPE_MANGO: 5692 case TARGET_TYPE_QCA8074: 5693 case TARGET_TYPE_QCA8074V2: 5694 case TARGET_TYPE_QCA6018: 5695 case TARGET_TYPE_QCA9574: 5696 case TARGET_TYPE_QCN9000: 5697 case TARGET_TYPE_QCA5018: 5698 case TARGET_TYPE_QCN6122: 5699 dp_mon_cdp_ops_register_1_0(ops); 5700 #ifdef ATH_SUPPORT_NAC_RSSI 5701 ops->ctrl_ops->txrx_vdev_config_for_nac_rssi = 5702 dp_config_for_nac_rssi; 5703 ops->ctrl_ops->txrx_vdev_get_neighbour_rssi = 5704 dp_vdev_get_neighbour_rssi; 5705 #endif 5706 #if defined(ATH_SUPPORT_NAC_RSSI) || defined(ATH_SUPPORT_NAC) 5707 ops->ctrl_ops->txrx_update_filter_neighbour_peers = 5708 dp_update_filter_neighbour_peers; 5709 #endif /* ATH_SUPPORT_NAC_RSSI || ATH_SUPPORT_NAC */ 5710 #if defined(WLAN_CFR_ENABLE) && defined(WLAN_ENH_CFR_ENABLE) 5711 dp_cfr_filter_register_1_0(ops); 5712 #endif 5713 break; 5714 case TARGET_TYPE_QCN9224: 5715 case TARGET_TYPE_QCA5332: 5716 #ifdef QCA_MONITOR_2_0_SUPPORT 5717 dp_mon_cdp_ops_register_2_0(ops); 5718 #ifdef ATH_SUPPORT_NAC_RSSI 5719 ops->ctrl_ops->txrx_vdev_config_for_nac_rssi = 5720 dp_lite_mon_config_nac_rssi_peer; 5721 ops->ctrl_ops->txrx_vdev_get_neighbour_rssi = 5722 dp_lite_mon_get_nac_peer_rssi; 5723 #endif 5724 #if defined(ATH_SUPPORT_NAC_RSSI) || defined(ATH_SUPPORT_NAC) 5725 ops->ctrl_ops->txrx_update_filter_neighbour_peers = 5726 dp_lite_mon_config_nac_peer; 5727 #endif /* ATH_SUPPORT_NAC_RSSI || ATH_SUPPORT_NAC */ 5728 #if defined(WLAN_CFR_ENABLE) && defined(WLAN_ENH_CFR_ENABLE) 5729 dp_cfr_filter_register_2_0(ops); 5730 #endif 5731 #endif /* QCA_MONITOR_2_0_SUPPORT */ 5732 break; 5733 default: 5734 dp_mon_err("%s: Unknown tgt type %d", __func__, target_type); 5735 qdf_assert_always(0); 5736 break; 5737 } 5738 5739 ops->cmn_drv_ops->txrx_set_monitor_mode = dp_vdev_set_monitor_mode; 5740 ops->cmn_drv_ops->txrx_get_mon_vdev_from_pdev = 5741 dp_get_mon_vdev_from_pdev_wifi3; 5742 #ifdef DP_PEER_EXTENDED_API 5743 ops->misc_ops->pkt_log_init = dp_pkt_log_init; 5744 ops->misc_ops->pkt_log_con_service = dp_pkt_log_con_service; 5745 ops->misc_ops->pkt_log_exit = dp_pkt_log_exit; 5746 #endif 5747 ops->ctrl_ops->enable_peer_based_pktlog = 5748 dp_enable_peer_based_pktlog; 5749 #if defined(WLAN_TX_PKT_CAPTURE_ENH) || defined(WLAN_RX_PKT_CAPTURE_ENH) 5750 ops->ctrl_ops->txrx_update_peer_pkt_capture_params = 5751 dp_peer_update_pkt_capture_params; 5752 #endif /* WLAN_TX_PKT_CAPTURE_ENH || WLAN_RX_PKT_CAPTURE_ENH */ 5753 #ifdef QCA_ENHANCED_STATS_SUPPORT 5754 ops->host_stats_ops->txrx_enable_enhanced_stats = 5755 dp_enable_enhanced_stats; 5756 ops->host_stats_ops->txrx_disable_enhanced_stats = 5757 dp_disable_enhanced_stats; 5758 #endif /* QCA_ENHANCED_STATS_SUPPORT */ 5759 #ifdef WDI_EVENT_ENABLE 5760 ops->ctrl_ops->txrx_get_pldev = dp_get_pldev; 5761 #endif 5762 #ifdef QCA_SUPPORT_SCAN_SPCL_VAP_STATS 5763 ops->host_stats_ops->txrx_get_scan_spcl_vap_stats = 5764 dp_get_scan_spcl_vap_stats; 5765 #endif 5766 return; 5767 } 5768 5769 #ifdef QCA_MONITOR_OPS_PER_SOC_SUPPORT 5770 static inline void 5771 dp_mon_cdp_mon_ops_deregister(struct cdp_ops *ops) 5772 { 5773 if (ops->mon_ops) { 5774 qdf_mem_free(ops->mon_ops); 5775 ops->mon_ops = NULL; 5776 } 5777 } 5778 #else 5779 static inline void 5780 dp_mon_cdp_mon_ops_deregister(struct cdp_ops *ops) 5781 { 5782 ops->mon_ops = NULL; 5783 } 5784 #endif 5785 5786 void dp_mon_cdp_ops_deregister(struct dp_soc *soc) 5787 { 5788 struct cdp_ops *ops = soc->cdp_soc.ops; 5789 5790 if (!ops) { 5791 dp_mon_err("cdp_ops is NULL"); 5792 return; 5793 } 5794 5795 dp_mon_cdp_mon_ops_deregister(ops); 5796 5797 #if defined(WLAN_CFR_ENABLE) && defined(WLAN_ENH_CFR_ENABLE) 5798 ops->cfr_ops->txrx_cfr_filter = NULL; 5799 #endif 5800 ops->cmn_drv_ops->txrx_set_monitor_mode = NULL; 5801 ops->cmn_drv_ops->txrx_get_mon_vdev_from_pdev = NULL; 5802 #ifdef DP_PEER_EXTENDED_API 5803 ops->misc_ops->pkt_log_init = NULL; 5804 ops->misc_ops->pkt_log_con_service = NULL; 5805 ops->misc_ops->pkt_log_exit = NULL; 5806 #endif 5807 #ifdef ATH_SUPPORT_NAC_RSSI 5808 ops->ctrl_ops->txrx_vdev_config_for_nac_rssi = NULL; 5809 ops->ctrl_ops->txrx_vdev_get_neighbour_rssi = NULL; 5810 #endif 5811 #if defined(ATH_SUPPORT_NAC_RSSI) || defined(ATH_SUPPORT_NAC) 5812 ops->ctrl_ops->txrx_update_filter_neighbour_peers = NULL; 5813 #endif /* ATH_SUPPORT_NAC_RSSI || ATH_SUPPORT_NAC */ 5814 ops->ctrl_ops->enable_peer_based_pktlog = NULL; 5815 #if defined(WLAN_TX_PKT_CAPTURE_ENH) || defined(WLAN_RX_PKT_CAPTURE_ENH) 5816 ops->ctrl_ops->txrx_update_peer_pkt_capture_params = NULL; 5817 #endif /* WLAN_TX_PKT_CAPTURE_ENH || WLAN_RX_PKT_CAPTURE_ENH */ 5818 #ifdef FEATURE_PERPKT_INFO 5819 ops->host_stats_ops->txrx_enable_enhanced_stats = NULL; 5820 ops->host_stats_ops->txrx_disable_enhanced_stats = NULL; 5821 #endif /* FEATURE_PERPKT_INFO */ 5822 #ifdef WDI_EVENT_ENABLE 5823 ops->ctrl_ops->txrx_get_pldev = NULL; 5824 #endif 5825 return; 5826 } 5827 5828 #if defined(WDI_EVENT_ENABLE) &&\ 5829 (defined(QCA_ENHANCED_STATS_SUPPORT) || !defined(REMOVE_PKT_LOG)) 5830 static inline 5831 void dp_mon_ppdu_stats_handler_deregister(struct dp_mon_soc *mon_soc) 5832 { 5833 mon_soc->mon_ops->mon_ppdu_stats_ind_handler = NULL; 5834 } 5835 #else 5836 static inline 5837 void dp_mon_ppdu_stats_handler_deregister(struct dp_mon_soc *mon_soc) 5838 { 5839 } 5840 #endif 5841 5842 #ifdef QCA_RSSI_DB2DBM 5843 /* 5844 * dp_mon_compute_min_nf() - calculate the min nf value in the 5845 * active chains 20MHZ subbands. 5846 * computation: Need to calculate nfInDbm[][] to A_MIN(nfHwDbm[][]) 5847 * considering row index as active chains and column 5848 * index as 20MHZ subbands per chain. 5849 * example: chain_mask = 0x07 (consider 3 active chains 0,1,2 index) 5850 * BandWidth = 40MHZ (40MHZ includes two 20MHZ subbands so need to 5851 * consider 0,1 index calculate min_nf value) 5852 * 5853 *@conv_params: cdp_rssi_dbm_conv_param_dp structure value 5854 *@chain_idx: active chain index in nfHwdbm array 5855 * 5856 * Return: QDF_STATUS_SUCCESS if value set successfully 5857 * QDF_STATUS_E_INVAL false if error 5858 */ 5859 static QDF_STATUS 5860 dp_mon_compute_min_nf(struct cdp_rssi_dbm_conv_param_dp *conv_params, 5861 int8_t *min_nf, int chain_idx) 5862 { 5863 int j; 5864 *min_nf = conv_params->nf_hw_dbm[chain_idx][0]; 5865 5866 switch (conv_params->curr_bw) { 5867 case CHAN_WIDTH_20: 5868 case CHAN_WIDTH_5: 5869 case CHAN_WIDTH_10: 5870 break; 5871 case CHAN_WIDTH_40: 5872 for (j = 1; j < SUB40BW; j++) { 5873 if (conv_params->nf_hw_dbm[chain_idx][j] < *min_nf) 5874 *min_nf = conv_params->nf_hw_dbm[chain_idx][j]; 5875 } 5876 break; 5877 case CHAN_WIDTH_80: 5878 for (j = 1; j < SUB80BW; j++) { 5879 if (conv_params->nf_hw_dbm[chain_idx][j] < *min_nf) 5880 *min_nf = conv_params->nf_hw_dbm[chain_idx][j]; 5881 } 5882 break; 5883 case CHAN_WIDTH_160: 5884 case CHAN_WIDTH_80P80: 5885 case CHAN_WIDTH_165: 5886 for (j = 1; j < SUB160BW; j++) { 5887 if (conv_params->nf_hw_dbm[chain_idx][j] < *min_nf) 5888 *min_nf = conv_params->nf_hw_dbm[chain_idx][j]; 5889 } 5890 break; 5891 case CHAN_WIDTH_160P160: 5892 case CHAN_WIDTH_320: 5893 for (j = 1; j < SUB320BW; j++) { 5894 if (conv_params->nf_hw_dbm[chain_idx][j] < *min_nf) 5895 *min_nf = conv_params->nf_hw_dbm[chain_idx][j]; 5896 } 5897 break; 5898 default: 5899 dp_cdp_err("Invalid bandwidth %u", conv_params->curr_bw); 5900 return QDF_STATUS_E_INVAL; 5901 } 5902 return QDF_STATUS_SUCCESS; 5903 } 5904 5905 /* 5906 * dp_mon_pdev_params_rssi_dbm_conv() --> to set rssi in dbm conversion 5907 * params into monitor pdev. 5908 *@cdp_soc: dp soc handle. 5909 *@params: cdp_rssi_db2dbm_param_dp structure value. 5910 * 5911 * Return: QDF_STATUS_SUCCESS if value set successfully 5912 * QDF_STATUS_E_INVAL false if error 5913 */ 5914 QDF_STATUS 5915 dp_mon_pdev_params_rssi_dbm_conv(struct cdp_soc_t *cdp_soc, 5916 struct cdp_rssi_db2dbm_param_dp *params) 5917 { 5918 struct cdp_rssi_db2dbm_param_dp *dp_rssi_params = params; 5919 uint8_t pdev_id = params->pdev_id; 5920 struct dp_soc *soc = (struct dp_soc *)cdp_soc; 5921 struct dp_pdev *pdev = 5922 dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); 5923 struct dp_mon_pdev *mon_pdev; 5924 struct cdp_rssi_temp_off_param_dp temp_off_param; 5925 struct cdp_rssi_dbm_conv_param_dp conv_params; 5926 int8_t min_nf = 0; 5927 int i; 5928 5929 if (!soc->features.rssi_dbm_conv_support) { 5930 dp_cdp_err("rssi dbm conversion support is false"); 5931 return QDF_STATUS_E_INVAL; 5932 } 5933 if (!pdev || !pdev->monitor_pdev) { 5934 dp_cdp_err("Invalid pdev_id %u", pdev_id); 5935 return QDF_STATUS_E_FAILURE; 5936 } 5937 5938 mon_pdev = pdev->monitor_pdev; 5939 5940 if (dp_rssi_params->rssi_temp_off_present) { 5941 temp_off_param = dp_rssi_params->temp_off_param; 5942 mon_pdev->ppdu_info.rx_status.rssi_temp_offset = 5943 temp_off_param.rssi_temp_offset; 5944 } 5945 if (dp_rssi_params->rssi_dbm_info_present) { 5946 conv_params = dp_rssi_params->rssi_dbm_param; 5947 for (i = 0; i < CDP_MAX_NUM_ANTENNA; i++) { 5948 if (conv_params.curr_rx_chainmask & (0x01 << i)) { 5949 if (QDF_STATUS_E_INVAL == dp_mon_compute_min_nf 5950 (&conv_params, &min_nf, i)) 5951 return QDF_STATUS_E_INVAL; 5952 } else { 5953 continue; 5954 } 5955 } 5956 mon_pdev->ppdu_info.rx_status.xlna_bypass_offset = 5957 conv_params.xlna_bypass_offset; 5958 mon_pdev->ppdu_info.rx_status.xlna_bypass_threshold = 5959 conv_params.xlna_bypass_threshold; 5960 mon_pdev->ppdu_info.rx_status.xbar_config = 5961 conv_params.xbar_config; 5962 5963 mon_pdev->ppdu_info.rx_status.min_nf_dbm = min_nf; 5964 mon_pdev->ppdu_info.rx_status.rssi_dbm_conv_support = 5965 soc->features.rssi_dbm_conv_support; 5966 } 5967 return QDF_STATUS_SUCCESS; 5968 } 5969 #endif 5970 5971 void dp_mon_intr_ops_deregister(struct dp_soc *soc) 5972 { 5973 struct dp_mon_soc *mon_soc = soc->monitor_soc; 5974 5975 mon_soc->mon_rx_process = NULL; 5976 dp_mon_ppdu_stats_handler_deregister(mon_soc); 5977 } 5978 5979 void dp_mon_feature_ops_deregister(struct dp_soc *soc) 5980 { 5981 struct dp_mon_ops *mon_ops = dp_mon_ops_get(soc); 5982 5983 if (!mon_ops) { 5984 dp_err("mon_ops is NULL"); 5985 return; 5986 } 5987 5988 mon_ops->mon_config_debug_sniffer = NULL; 5989 mon_ops->mon_peer_tx_init = NULL; 5990 mon_ops->mon_peer_tx_cleanup = NULL; 5991 mon_ops->mon_htt_ppdu_stats_attach = NULL; 5992 mon_ops->mon_htt_ppdu_stats_detach = NULL; 5993 mon_ops->mon_print_pdev_rx_mon_stats = NULL; 5994 mon_ops->mon_set_bsscolor = NULL; 5995 mon_ops->mon_pdev_get_filter_ucast_data = NULL; 5996 mon_ops->mon_pdev_get_filter_mcast_data = NULL; 5997 mon_ops->mon_pdev_get_filter_non_data = NULL; 5998 mon_ops->mon_neighbour_peer_add_ast = NULL; 5999 #ifdef WLAN_TX_PKT_CAPTURE_ENH 6000 mon_ops->mon_peer_tid_peer_id_update = NULL; 6001 mon_ops->mon_tx_ppdu_stats_attach = NULL; 6002 mon_ops->mon_tx_ppdu_stats_detach = NULL; 6003 mon_ops->mon_tx_capture_debugfs_init = NULL; 6004 mon_ops->mon_tx_add_to_comp_queue = NULL; 6005 mon_ops->mon_peer_tx_capture_filter_check = NULL; 6006 mon_ops->mon_print_pdev_tx_capture_stats = NULL; 6007 mon_ops->mon_config_enh_tx_capture = NULL; 6008 #endif 6009 #ifdef WLAN_RX_PKT_CAPTURE_ENH 6010 mon_ops->mon_config_enh_rx_capture = NULL; 6011 #endif 6012 #ifdef QCA_SUPPORT_BPR 6013 mon_ops->mon_set_bpr_enable = NULL; 6014 #endif 6015 #ifdef ATH_SUPPORT_NAC 6016 mon_ops->mon_set_filter_neigh_peers = NULL; 6017 #endif 6018 #ifdef WLAN_ATF_ENABLE 6019 mon_ops->mon_set_atf_stats_enable = NULL; 6020 #endif 6021 #ifdef FEATURE_NAC_RSSI 6022 mon_ops->mon_filter_neighbour_peer = NULL; 6023 #endif 6024 #ifdef QCA_MCOPY_SUPPORT 6025 mon_ops->mon_filter_setup_mcopy_mode = NULL; 6026 mon_ops->mon_filter_reset_mcopy_mode = NULL; 6027 mon_ops->mon_mcopy_check_deliver = NULL; 6028 #endif 6029 #ifdef QCA_ENHANCED_STATS_SUPPORT 6030 mon_ops->mon_filter_setup_enhanced_stats = NULL; 6031 mon_ops->mon_tx_enable_enhanced_stats = NULL; 6032 mon_ops->mon_tx_disable_enhanced_stats = NULL; 6033 mon_ops->mon_ppdu_desc_deliver = NULL; 6034 mon_ops->mon_ppdu_desc_notify = NULL; 6035 mon_ops->mon_ppdu_stats_feat_enable_check = NULL; 6036 #ifdef WLAN_FEATURE_11BE 6037 mon_ops->mon_tx_stats_update = NULL; 6038 #endif 6039 #endif 6040 #if defined(ATH_SUPPORT_NAC_RSSI) || defined(ATH_SUPPORT_NAC) 6041 mon_ops->mon_filter_setup_smart_monitor = NULL; 6042 #endif 6043 #ifdef WLAN_RX_PKT_CAPTURE_ENH 6044 mon_ops->mon_filter_setup_rx_enh_capture = NULL; 6045 #endif 6046 #ifdef WDI_EVENT_ENABLE 6047 mon_ops->mon_set_pktlog_wifi3 = NULL; 6048 mon_ops->mon_filter_setup_rx_pkt_log_full = NULL; 6049 mon_ops->mon_filter_reset_rx_pkt_log_full = NULL; 6050 mon_ops->mon_filter_setup_rx_pkt_log_lite = NULL; 6051 mon_ops->mon_filter_reset_rx_pkt_log_lite = NULL; 6052 mon_ops->mon_filter_setup_rx_pkt_log_cbf = NULL; 6053 mon_ops->mon_filter_reset_rx_pkt_log_cbf = NULL; 6054 #ifdef BE_PKTLOG_SUPPORT 6055 mon_ops->mon_filter_setup_pktlog_hybrid = NULL; 6056 mon_ops->mon_filter_reset_pktlog_hybrid = NULL; 6057 #endif 6058 #endif 6059 #if defined(DP_CON_MON) && !defined(REMOVE_PKT_LOG) 6060 mon_ops->mon_pktlogmod_exit = NULL; 6061 #endif 6062 mon_ops->rx_hdr_length_set = NULL; 6063 mon_ops->rx_packet_length_set = NULL; 6064 mon_ops->rx_wmask_subscribe = NULL; 6065 mon_ops->rx_enable_mpdu_logging = NULL; 6066 mon_ops->rx_enable_fpmo = NULL; 6067 mon_ops->mon_neighbour_peers_detach = NULL; 6068 mon_ops->mon_vdev_set_monitor_mode_buf_rings = NULL; 6069 mon_ops->mon_vdev_set_monitor_mode_rings = NULL; 6070 #ifdef QCA_ENHANCED_STATS_SUPPORT 6071 mon_ops->mon_rx_stats_update = NULL; 6072 mon_ops->mon_rx_populate_ppdu_usr_info = NULL; 6073 mon_ops->mon_rx_populate_ppdu_info = NULL; 6074 #endif 6075 } 6076 6077 QDF_STATUS dp_mon_soc_attach(struct dp_soc *soc) 6078 { 6079 struct dp_mon_soc *mon_soc; 6080 6081 if (!soc) { 6082 dp_mon_err("dp_soc is NULL"); 6083 return QDF_STATUS_E_FAILURE; 6084 } 6085 6086 mon_soc = (struct dp_mon_soc *)qdf_mem_malloc(sizeof(*mon_soc)); 6087 if (!mon_soc) { 6088 dp_mon_err("%pK: mem allocation failed", soc); 6089 return QDF_STATUS_E_NOMEM; 6090 } 6091 /* register monitor ops */ 6092 soc->monitor_soc = mon_soc; 6093 dp_mon_ops_register(soc); 6094 dp_mon_register_intr_ops(soc); 6095 6096 dp_mon_cdp_ops_register(soc); 6097 dp_mon_register_feature_ops(soc); 6098 return QDF_STATUS_SUCCESS; 6099 } 6100 6101 QDF_STATUS dp_mon_soc_detach(struct dp_soc *soc) 6102 { 6103 struct dp_mon_soc *mon_soc; 6104 6105 if (!soc) { 6106 dp_mon_err("dp_soc is NULL"); 6107 return QDF_STATUS_E_FAILURE; 6108 } 6109 6110 mon_soc = soc->monitor_soc; 6111 dp_monitor_vdev_timer_deinit(soc); 6112 dp_mon_cdp_ops_deregister(soc); 6113 soc->monitor_soc = NULL; 6114 qdf_mem_free(mon_soc); 6115 return QDF_STATUS_SUCCESS; 6116 } 6117