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