1 /* 2 * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include "htt.h" 21 #include "dp_htt.h" 22 #include "hal_hw_headers.h" 23 #include "dp_tx.h" 24 #include "dp_tx_desc.h" 25 #include "dp_peer.h" 26 #include "dp_types.h" 27 #include "hal_tx.h" 28 #include "qdf_mem.h" 29 #include "qdf_nbuf.h" 30 #include "qdf_net_types.h" 31 #include "qdf_module.h" 32 #include <wlan_cfg.h> 33 #include "dp_ipa.h" 34 #if defined(MESH_MODE_SUPPORT) || defined(FEATURE_PERPKT_INFO) 35 #include "if_meta_hdr.h" 36 #endif 37 #include "enet.h" 38 #include "dp_internal.h" 39 #ifdef ATH_SUPPORT_IQUE 40 #include "dp_txrx_me.h" 41 #endif 42 #include "dp_hist.h" 43 #ifdef WLAN_DP_FEATURE_SW_LATENCY_MGR 44 #include <wlan_dp_swlm.h> 45 #endif 46 #ifdef WIFI_MONITOR_SUPPORT 47 #include <dp_mon.h> 48 #endif 49 #ifdef FEATURE_WDS 50 #include "dp_txrx_wds.h" 51 #endif 52 #include "cdp_txrx_cmn_reg.h" 53 #ifdef CONFIG_SAWF 54 #include <dp_sawf.h> 55 #endif 56 57 /* Flag to skip CCE classify when mesh or tid override enabled */ 58 #define DP_TX_SKIP_CCE_CLASSIFY \ 59 (DP_TXRX_HLOS_TID_OVERRIDE_ENABLED | DP_TX_MESH_ENABLED) 60 61 /* TODO Add support in TSO */ 62 #define DP_DESC_NUM_FRAG(x) 0 63 64 /* disable TQM_BYPASS */ 65 #define TQM_BYPASS_WAR 0 66 67 #define DP_RETRY_COUNT 7 68 #ifdef WLAN_PEER_JITTER 69 #define DP_AVG_JITTER_WEIGHT_DENOM 4 70 #define DP_AVG_DELAY_WEIGHT_DENOM 3 71 #endif 72 73 #ifdef QCA_DP_TX_FW_METADATA_V2 74 #define DP_TX_TCL_METADATA_PDEV_ID_SET(_var, _val)\ 75 HTT_TX_TCL_METADATA_V2_PDEV_ID_SET(_var, _val) 76 #define DP_TX_TCL_METADATA_VALID_HTT_SET(_var, _val) \ 77 HTT_TX_TCL_METADATA_V2_VALID_HTT_SET(_var, _val) 78 #define DP_TX_TCL_METADATA_TYPE_SET(_var, _val) \ 79 HTT_TX_TCL_METADATA_TYPE_V2_SET(_var, _val) 80 #define DP_TX_TCL_METADATA_HOST_INSPECTED_SET(_var, _val) \ 81 HTT_TX_TCL_METADATA_V2_HOST_INSPECTED_SET(_var, _val) 82 #define DP_TX_TCL_METADATA_PEER_ID_SET(_var, _val) \ 83 HTT_TX_TCL_METADATA_V2_PEER_ID_SET(_var, _val) 84 #define DP_TX_TCL_METADATA_VDEV_ID_SET(_var, _val) \ 85 HTT_TX_TCL_METADATA_V2_VDEV_ID_SET(_var, _val) 86 #define DP_TCL_METADATA_TYPE_PEER_BASED \ 87 HTT_TCL_METADATA_V2_TYPE_PEER_BASED 88 #define DP_TCL_METADATA_TYPE_VDEV_BASED \ 89 HTT_TCL_METADATA_V2_TYPE_VDEV_BASED 90 #else 91 #define DP_TX_TCL_METADATA_PDEV_ID_SET(_var, _val)\ 92 HTT_TX_TCL_METADATA_PDEV_ID_SET(_var, _val) 93 #define DP_TX_TCL_METADATA_VALID_HTT_SET(_var, _val) \ 94 HTT_TX_TCL_METADATA_VALID_HTT_SET(_var, _val) 95 #define DP_TX_TCL_METADATA_TYPE_SET(_var, _val) \ 96 HTT_TX_TCL_METADATA_TYPE_SET(_var, _val) 97 #define DP_TX_TCL_METADATA_HOST_INSPECTED_SET(_var, _val) \ 98 HTT_TX_TCL_METADATA_HOST_INSPECTED_SET(_var, _val) 99 #define DP_TX_TCL_METADATA_PEER_ID_SET(_var, _val) \ 100 HTT_TX_TCL_METADATA_PEER_ID_SET(_var, _val) 101 #define DP_TX_TCL_METADATA_VDEV_ID_SET(_var, _val) \ 102 HTT_TX_TCL_METADATA_VDEV_ID_SET(_var, _val) 103 #define DP_TCL_METADATA_TYPE_PEER_BASED \ 104 HTT_TCL_METADATA_TYPE_PEER_BASED 105 #define DP_TCL_METADATA_TYPE_VDEV_BASED \ 106 HTT_TCL_METADATA_TYPE_VDEV_BASED 107 #endif 108 109 #define DP_GET_HW_LINK_ID_FRM_PPDU_ID(PPDU_ID, LINK_ID_OFFSET, LINK_ID_BITS) \ 110 (((PPDU_ID) >> (LINK_ID_OFFSET)) & ((1 << (LINK_ID_BITS)) - 1)) 111 112 /*mapping between hal encrypt type and cdp_sec_type*/ 113 uint8_t sec_type_map[MAX_CDP_SEC_TYPE] = {HAL_TX_ENCRYPT_TYPE_NO_CIPHER, 114 HAL_TX_ENCRYPT_TYPE_WEP_128, 115 HAL_TX_ENCRYPT_TYPE_WEP_104, 116 HAL_TX_ENCRYPT_TYPE_WEP_40, 117 HAL_TX_ENCRYPT_TYPE_TKIP_WITH_MIC, 118 HAL_TX_ENCRYPT_TYPE_TKIP_NO_MIC, 119 HAL_TX_ENCRYPT_TYPE_AES_CCMP_128, 120 HAL_TX_ENCRYPT_TYPE_WAPI, 121 HAL_TX_ENCRYPT_TYPE_AES_CCMP_256, 122 HAL_TX_ENCRYPT_TYPE_AES_GCMP_128, 123 HAL_TX_ENCRYPT_TYPE_AES_GCMP_256, 124 HAL_TX_ENCRYPT_TYPE_WAPI_GCM_SM4}; 125 qdf_export_symbol(sec_type_map); 126 127 #ifdef WLAN_FEATURE_DP_TX_DESC_HISTORY 128 static inline enum dp_tx_event_type dp_tx_get_event_type(uint32_t flags) 129 { 130 enum dp_tx_event_type type; 131 132 if (flags & DP_TX_DESC_FLAG_FLUSH) 133 type = DP_TX_DESC_FLUSH; 134 else if (flags & DP_TX_DESC_FLAG_TX_COMP_ERR) 135 type = DP_TX_COMP_UNMAP_ERR; 136 else if (flags & DP_TX_DESC_FLAG_COMPLETED_TX) 137 type = DP_TX_COMP_UNMAP; 138 else 139 type = DP_TX_DESC_UNMAP; 140 141 return type; 142 } 143 144 static inline void 145 dp_tx_desc_history_add(struct dp_soc *soc, dma_addr_t paddr, 146 qdf_nbuf_t skb, uint32_t sw_cookie, 147 enum dp_tx_event_type type) 148 { 149 struct dp_tx_tcl_history *tx_tcl_history = &soc->tx_tcl_history; 150 struct dp_tx_comp_history *tx_comp_history = &soc->tx_comp_history; 151 struct dp_tx_desc_event *entry; 152 uint32_t idx; 153 uint16_t slot; 154 155 switch (type) { 156 case DP_TX_COMP_UNMAP: 157 case DP_TX_COMP_UNMAP_ERR: 158 case DP_TX_COMP_MSDU_EXT: 159 if (qdf_unlikely(!tx_comp_history->allocated)) 160 return; 161 162 dp_get_frag_hist_next_atomic_idx(&tx_comp_history->index, &idx, 163 &slot, 164 DP_TX_COMP_HIST_SLOT_SHIFT, 165 DP_TX_COMP_HIST_PER_SLOT_MAX, 166 DP_TX_COMP_HISTORY_SIZE); 167 entry = &tx_comp_history->entry[slot][idx]; 168 break; 169 case DP_TX_DESC_MAP: 170 case DP_TX_DESC_UNMAP: 171 case DP_TX_DESC_COOKIE: 172 case DP_TX_DESC_FLUSH: 173 if (qdf_unlikely(!tx_tcl_history->allocated)) 174 return; 175 176 dp_get_frag_hist_next_atomic_idx(&tx_tcl_history->index, &idx, 177 &slot, 178 DP_TX_TCL_HIST_SLOT_SHIFT, 179 DP_TX_TCL_HIST_PER_SLOT_MAX, 180 DP_TX_TCL_HISTORY_SIZE); 181 entry = &tx_tcl_history->entry[slot][idx]; 182 break; 183 default: 184 dp_info_rl("Invalid dp_tx_event_type: %d", type); 185 return; 186 } 187 188 entry->skb = skb; 189 entry->paddr = paddr; 190 entry->sw_cookie = sw_cookie; 191 entry->type = type; 192 entry->ts = qdf_get_log_timestamp(); 193 } 194 195 static inline void 196 dp_tx_tso_seg_history_add(struct dp_soc *soc, 197 struct qdf_tso_seg_elem_t *tso_seg, 198 qdf_nbuf_t skb, uint32_t sw_cookie, 199 enum dp_tx_event_type type) 200 { 201 int i; 202 203 for (i = 1; i < tso_seg->seg.num_frags; i++) { 204 dp_tx_desc_history_add(soc, tso_seg->seg.tso_frags[i].paddr, 205 skb, sw_cookie, type); 206 } 207 208 if (!tso_seg->next) 209 dp_tx_desc_history_add(soc, tso_seg->seg.tso_frags[0].paddr, 210 skb, 0xFFFFFFFF, type); 211 } 212 213 static inline void 214 dp_tx_tso_history_add(struct dp_soc *soc, struct qdf_tso_info_t tso_info, 215 qdf_nbuf_t skb, uint32_t sw_cookie, 216 enum dp_tx_event_type type) 217 { 218 struct qdf_tso_seg_elem_t *curr_seg = tso_info.tso_seg_list; 219 uint32_t num_segs = tso_info.num_segs; 220 221 while (num_segs) { 222 dp_tx_tso_seg_history_add(soc, curr_seg, skb, sw_cookie, type); 223 curr_seg = curr_seg->next; 224 num_segs--; 225 } 226 } 227 228 #else 229 static inline enum dp_tx_event_type dp_tx_get_event_type(uint32_t flags) 230 { 231 return DP_TX_DESC_INVAL_EVT; 232 } 233 234 static inline void 235 dp_tx_desc_history_add(struct dp_soc *soc, dma_addr_t paddr, 236 qdf_nbuf_t skb, uint32_t sw_cookie, 237 enum dp_tx_event_type type) 238 { 239 } 240 241 static inline void 242 dp_tx_tso_seg_history_add(struct dp_soc *soc, 243 struct qdf_tso_seg_elem_t *tso_seg, 244 qdf_nbuf_t skb, uint32_t sw_cookie, 245 enum dp_tx_event_type type) 246 { 247 } 248 249 static inline void 250 dp_tx_tso_history_add(struct dp_soc *soc, struct qdf_tso_info_t tso_info, 251 qdf_nbuf_t skb, uint32_t sw_cookie, 252 enum dp_tx_event_type type) 253 { 254 } 255 #endif /* WLAN_FEATURE_DP_TX_DESC_HISTORY */ 256 257 /** 258 * dp_is_tput_high() - Check if throughput is high 259 * 260 * @soc: core txrx main context 261 * 262 * The current function is based of the RTPM tput policy variable where RTPM is 263 * avoided based on throughput. 264 */ 265 static inline int dp_is_tput_high(struct dp_soc *soc) 266 { 267 return dp_get_rtpm_tput_policy_requirement(soc); 268 } 269 270 #if defined(FEATURE_TSO) 271 /** 272 * dp_tx_tso_unmap_segment() - Unmap TSO segment 273 * 274 * @soc: core txrx main context 275 * @seg_desc: tso segment descriptor 276 * @num_seg_desc: tso number segment descriptor 277 */ 278 static void dp_tx_tso_unmap_segment( 279 struct dp_soc *soc, 280 struct qdf_tso_seg_elem_t *seg_desc, 281 struct qdf_tso_num_seg_elem_t *num_seg_desc) 282 { 283 TSO_DEBUG("%s: Unmap the tso segment", __func__); 284 if (qdf_unlikely(!seg_desc)) { 285 DP_TRACE(ERROR, "%s %d TSO desc is NULL!", 286 __func__, __LINE__); 287 qdf_assert(0); 288 } else if (qdf_unlikely(!num_seg_desc)) { 289 DP_TRACE(ERROR, "%s %d TSO num desc is NULL!", 290 __func__, __LINE__); 291 qdf_assert(0); 292 } else { 293 bool is_last_seg; 294 /* no tso segment left to do dma unmap */ 295 if (num_seg_desc->num_seg.tso_cmn_num_seg < 1) 296 return; 297 298 is_last_seg = (num_seg_desc->num_seg.tso_cmn_num_seg == 1) ? 299 true : false; 300 qdf_nbuf_unmap_tso_segment(soc->osdev, 301 seg_desc, is_last_seg); 302 num_seg_desc->num_seg.tso_cmn_num_seg--; 303 } 304 } 305 306 /** 307 * dp_tx_tso_desc_release() - Release the tso segment and tso_cmn_num_seg 308 * back to the freelist 309 * 310 * @soc: soc device handle 311 * @tx_desc: Tx software descriptor 312 */ 313 static void dp_tx_tso_desc_release(struct dp_soc *soc, 314 struct dp_tx_desc_s *tx_desc) 315 { 316 TSO_DEBUG("%s: Free the tso descriptor", __func__); 317 if (qdf_unlikely(!tx_desc->msdu_ext_desc->tso_desc)) { 318 dp_tx_err("SO desc is NULL!"); 319 qdf_assert(0); 320 } else if (qdf_unlikely(!tx_desc->msdu_ext_desc->tso_num_desc)) { 321 dp_tx_err("TSO num desc is NULL!"); 322 qdf_assert(0); 323 } else { 324 struct qdf_tso_num_seg_elem_t *tso_num_desc = 325 (struct qdf_tso_num_seg_elem_t *)tx_desc-> 326 msdu_ext_desc->tso_num_desc; 327 328 /* Add the tso num segment into the free list */ 329 if (tso_num_desc->num_seg.tso_cmn_num_seg == 0) { 330 dp_tso_num_seg_free(soc, tx_desc->pool_id, 331 tx_desc->msdu_ext_desc-> 332 tso_num_desc); 333 tx_desc->msdu_ext_desc->tso_num_desc = NULL; 334 DP_STATS_INC(tx_desc->pdev, tso_stats.tso_comp, 1); 335 } 336 337 /* Add the tso segment into the free list*/ 338 dp_tx_tso_desc_free(soc, 339 tx_desc->pool_id, tx_desc->msdu_ext_desc-> 340 tso_desc); 341 tx_desc->msdu_ext_desc->tso_desc = NULL; 342 } 343 } 344 #else 345 static void dp_tx_tso_unmap_segment( 346 struct dp_soc *soc, 347 struct qdf_tso_seg_elem_t *seg_desc, 348 struct qdf_tso_num_seg_elem_t *num_seg_desc) 349 350 { 351 } 352 353 static void dp_tx_tso_desc_release(struct dp_soc *soc, 354 struct dp_tx_desc_s *tx_desc) 355 { 356 } 357 #endif 358 359 #ifdef WLAN_SUPPORT_PPEDS 360 static inline int 361 dp_tx_release_ds_tx_desc(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc, 362 uint8_t desc_pool_id) 363 { 364 if (tx_desc->flags & DP_TX_DESC_FLAG_PPEDS) { 365 __dp_tx_outstanding_dec(soc); 366 dp_tx_desc_free(soc, tx_desc, desc_pool_id); 367 368 return 1; 369 } 370 371 return 0; 372 } 373 #else 374 static inline int 375 dp_tx_release_ds_tx_desc(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc, 376 uint8_t desc_pool_id) 377 { 378 return 0; 379 } 380 #endif 381 382 void 383 dp_tx_desc_release(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc, 384 uint8_t desc_pool_id) 385 { 386 struct dp_pdev *pdev = tx_desc->pdev; 387 uint8_t comp_status = 0; 388 389 if (dp_tx_release_ds_tx_desc(soc, tx_desc, desc_pool_id)) 390 return; 391 392 qdf_assert(pdev); 393 394 soc = pdev->soc; 395 396 dp_tx_outstanding_dec(pdev); 397 398 if (tx_desc->msdu_ext_desc) { 399 if (tx_desc->frm_type == dp_tx_frm_tso) 400 dp_tx_tso_desc_release(soc, tx_desc); 401 402 if (tx_desc->flags & DP_TX_DESC_FLAG_ME) 403 dp_tx_me_free_buf(tx_desc->pdev, 404 tx_desc->msdu_ext_desc->me_buffer); 405 406 dp_tx_ext_desc_free(soc, tx_desc->msdu_ext_desc, desc_pool_id); 407 408 tx_desc->msdu_ext_desc = NULL; 409 } 410 411 if (tx_desc->flags & DP_TX_DESC_FLAG_TO_FW) 412 qdf_atomic_dec(&soc->num_tx_exception); 413 414 if (HAL_TX_COMP_RELEASE_SOURCE_TQM == 415 tx_desc->buffer_src) 416 comp_status = hal_tx_comp_get_release_reason(&tx_desc->comp, 417 soc->hal_soc); 418 else 419 comp_status = HAL_TX_COMP_RELEASE_REASON_FW; 420 if (soc->dp_debug_log_en) { 421 dp_tx_debug("Tx Completion Release desc %d status %d outstanding %d", 422 tx_desc->id, comp_status, 423 qdf_atomic_read(&pdev->num_tx_outstanding)); 424 } 425 426 if (tx_desc->flags & DP_TX_DESC_FLAG_SPECIAL) 427 dp_tx_spcl_desc_free(soc, tx_desc, desc_pool_id); 428 else 429 dp_tx_desc_free(soc, tx_desc, desc_pool_id); 430 return; 431 } 432 433 /** 434 * dp_tx_prepare_htt_metadata() - Prepare HTT metadata for special frames 435 * @vdev: DP vdev Handle 436 * @nbuf: skb 437 * @msdu_info: msdu_info required to create HTT metadata 438 * 439 * Prepares and fills HTT metadata in the frame pre-header for special frames 440 * that should be transmitted using varying transmit parameters. 441 * There are 2 VDEV modes that currently needs this special metadata - 442 * 1) Mesh Mode 443 * 2) DSRC Mode 444 * 445 * Return: HTT metadata size 446 * 447 */ 448 static uint8_t dp_tx_prepare_htt_metadata(struct dp_vdev *vdev, qdf_nbuf_t nbuf, 449 struct dp_tx_msdu_info_s *msdu_info) 450 { 451 uint32_t *meta_data = msdu_info->meta_data; 452 struct htt_tx_msdu_desc_ext2_t *desc_ext = 453 (struct htt_tx_msdu_desc_ext2_t *) meta_data; 454 455 uint8_t htt_desc_size; 456 457 /* Size rounded of multiple of 8 bytes */ 458 uint8_t htt_desc_size_aligned; 459 460 uint8_t *hdr = NULL; 461 462 /* 463 * Metadata - HTT MSDU Extension header 464 */ 465 htt_desc_size = sizeof(struct htt_tx_msdu_desc_ext2_t); 466 htt_desc_size_aligned = (htt_desc_size + 7) & ~0x7; 467 468 if (vdev->mesh_vdev || msdu_info->is_tx_sniffer || 469 HTT_TX_MSDU_EXT2_DESC_FLAG_VALID_KEY_FLAGS_GET(msdu_info-> 470 meta_data[0]) || 471 msdu_info->exception_fw) { 472 if (qdf_unlikely(qdf_nbuf_headroom(nbuf) < 473 htt_desc_size_aligned)) { 474 nbuf = qdf_nbuf_realloc_headroom(nbuf, 475 htt_desc_size_aligned); 476 if (!nbuf) { 477 /* 478 * qdf_nbuf_realloc_headroom won't do skb_clone 479 * as skb_realloc_headroom does. so, no free is 480 * needed here. 481 */ 482 DP_STATS_INC(vdev, 483 tx_i[msdu_info->xmit_type].dropped.headroom_insufficient, 484 1); 485 qdf_print(" %s[%d] skb_realloc_headroom failed", 486 __func__, __LINE__); 487 return 0; 488 } 489 } 490 /* Fill and add HTT metaheader */ 491 hdr = qdf_nbuf_push_head(nbuf, htt_desc_size_aligned); 492 if (!hdr) { 493 dp_tx_err("Error in filling HTT metadata"); 494 495 return 0; 496 } 497 qdf_mem_copy(hdr, desc_ext, htt_desc_size); 498 499 } else if (vdev->opmode == wlan_op_mode_ocb) { 500 /* Todo - Add support for DSRC */ 501 } 502 503 return htt_desc_size_aligned; 504 } 505 506 /** 507 * dp_tx_prepare_tso_ext_desc() - Prepare MSDU extension descriptor for TSO 508 * @tso_seg: TSO segment to process 509 * @ext_desc: Pointer to MSDU extension descriptor 510 * 511 * Return: void 512 */ 513 #if defined(FEATURE_TSO) 514 static void dp_tx_prepare_tso_ext_desc(struct qdf_tso_seg_t *tso_seg, 515 void *ext_desc) 516 { 517 uint8_t num_frag; 518 uint32_t tso_flags; 519 520 /* 521 * Set tso_en, tcp_flags(NS, CWR, ECE, URG, ACK, PSH, RST, SYN, FIN), 522 * tcp_flag_mask 523 * 524 * Checksum enable flags are set in TCL descriptor and not in Extension 525 * Descriptor (H/W ignores checksum_en flags in MSDU ext descriptor) 526 */ 527 tso_flags = *(uint32_t *) &tso_seg->tso_flags; 528 529 hal_tx_ext_desc_set_tso_flags(ext_desc, tso_flags); 530 531 hal_tx_ext_desc_set_msdu_length(ext_desc, tso_seg->tso_flags.l2_len, 532 tso_seg->tso_flags.ip_len); 533 534 hal_tx_ext_desc_set_tcp_seq(ext_desc, tso_seg->tso_flags.tcp_seq_num); 535 hal_tx_ext_desc_set_ip_id(ext_desc, tso_seg->tso_flags.ip_id); 536 537 for (num_frag = 0; num_frag < tso_seg->num_frags; num_frag++) { 538 uint32_t lo = 0; 539 uint32_t hi = 0; 540 541 qdf_assert_always((tso_seg->tso_frags[num_frag].paddr) && 542 (tso_seg->tso_frags[num_frag].length)); 543 544 qdf_dmaaddr_to_32s( 545 tso_seg->tso_frags[num_frag].paddr, &lo, &hi); 546 hal_tx_ext_desc_set_buffer(ext_desc, num_frag, lo, hi, 547 tso_seg->tso_frags[num_frag].length); 548 } 549 550 return; 551 } 552 #else 553 static void dp_tx_prepare_tso_ext_desc(struct qdf_tso_seg_t *tso_seg, 554 void *ext_desc) 555 { 556 return; 557 } 558 #endif 559 560 #if defined(FEATURE_TSO) 561 /** 562 * dp_tx_free_tso_seg_list() - Loop through the tso segments 563 * allocated and free them 564 * @soc: soc handle 565 * @free_seg: list of tso segments 566 * @msdu_info: msdu descriptor 567 * 568 * Return: void 569 */ 570 static void dp_tx_free_tso_seg_list( 571 struct dp_soc *soc, 572 struct qdf_tso_seg_elem_t *free_seg, 573 struct dp_tx_msdu_info_s *msdu_info) 574 { 575 struct qdf_tso_seg_elem_t *next_seg; 576 577 while (free_seg) { 578 next_seg = free_seg->next; 579 dp_tx_tso_desc_free(soc, 580 msdu_info->tx_queue.desc_pool_id, 581 free_seg); 582 free_seg = next_seg; 583 } 584 } 585 586 /** 587 * dp_tx_free_tso_num_seg_list() - Loop through the tso num segments 588 * allocated and free them 589 * @soc: soc handle 590 * @free_num_seg: list of tso number segments 591 * @msdu_info: msdu descriptor 592 * 593 * Return: void 594 */ 595 static void dp_tx_free_tso_num_seg_list( 596 struct dp_soc *soc, 597 struct qdf_tso_num_seg_elem_t *free_num_seg, 598 struct dp_tx_msdu_info_s *msdu_info) 599 { 600 struct qdf_tso_num_seg_elem_t *next_num_seg; 601 602 while (free_num_seg) { 603 next_num_seg = free_num_seg->next; 604 dp_tso_num_seg_free(soc, 605 msdu_info->tx_queue.desc_pool_id, 606 free_num_seg); 607 free_num_seg = next_num_seg; 608 } 609 } 610 611 /** 612 * dp_tx_unmap_tso_seg_list() - Loop through the tso segments 613 * do dma unmap for each segment 614 * @soc: soc handle 615 * @free_seg: list of tso segments 616 * @num_seg_desc: tso number segment descriptor 617 * 618 * Return: void 619 */ 620 static void dp_tx_unmap_tso_seg_list( 621 struct dp_soc *soc, 622 struct qdf_tso_seg_elem_t *free_seg, 623 struct qdf_tso_num_seg_elem_t *num_seg_desc) 624 { 625 struct qdf_tso_seg_elem_t *next_seg; 626 627 if (qdf_unlikely(!num_seg_desc)) { 628 DP_TRACE(ERROR, "TSO number seg desc is NULL!"); 629 return; 630 } 631 632 while (free_seg) { 633 next_seg = free_seg->next; 634 dp_tx_tso_unmap_segment(soc, free_seg, num_seg_desc); 635 free_seg = next_seg; 636 } 637 } 638 639 #ifdef FEATURE_TSO_STATS 640 /** 641 * dp_tso_get_stats_idx() - Retrieve the tso packet id 642 * @pdev: pdev handle 643 * 644 * Return: id 645 */ 646 static uint32_t dp_tso_get_stats_idx(struct dp_pdev *pdev) 647 { 648 uint32_t stats_idx; 649 650 stats_idx = (((uint32_t)qdf_atomic_inc_return(&pdev->tso_idx)) 651 % CDP_MAX_TSO_PACKETS); 652 return stats_idx; 653 } 654 #else 655 static int dp_tso_get_stats_idx(struct dp_pdev *pdev) 656 { 657 return 0; 658 } 659 #endif /* FEATURE_TSO_STATS */ 660 661 /** 662 * dp_tx_free_remaining_tso_desc() - do dma unmap for tso segments if any, 663 * free the tso segments descriptor and 664 * tso num segments descriptor 665 * @soc: soc handle 666 * @msdu_info: msdu descriptor 667 * @tso_seg_unmap: flag to show if dma unmap is necessary 668 * 669 * Return: void 670 */ 671 static void dp_tx_free_remaining_tso_desc(struct dp_soc *soc, 672 struct dp_tx_msdu_info_s *msdu_info, 673 bool tso_seg_unmap) 674 { 675 struct qdf_tso_info_t *tso_info = &msdu_info->u.tso_info; 676 struct qdf_tso_seg_elem_t *free_seg = tso_info->tso_seg_list; 677 struct qdf_tso_num_seg_elem_t *tso_num_desc = 678 tso_info->tso_num_seg_list; 679 680 /* do dma unmap for each segment */ 681 if (tso_seg_unmap) 682 dp_tx_unmap_tso_seg_list(soc, free_seg, tso_num_desc); 683 684 /* free all tso number segment descriptor though looks only have 1 */ 685 dp_tx_free_tso_num_seg_list(soc, tso_num_desc, msdu_info); 686 687 /* free all tso segment descriptor */ 688 dp_tx_free_tso_seg_list(soc, free_seg, msdu_info); 689 } 690 691 /** 692 * dp_tx_prepare_tso() - Given a jumbo msdu, prepare the TSO info 693 * @vdev: virtual device handle 694 * @msdu: network buffer 695 * @msdu_info: meta data associated with the msdu 696 * 697 * Return: QDF_STATUS_SUCCESS success 698 */ 699 static QDF_STATUS dp_tx_prepare_tso(struct dp_vdev *vdev, 700 qdf_nbuf_t msdu, struct dp_tx_msdu_info_s *msdu_info) 701 { 702 struct qdf_tso_seg_elem_t *tso_seg; 703 int num_seg = qdf_nbuf_get_tso_num_seg(msdu); 704 struct dp_soc *soc = vdev->pdev->soc; 705 struct dp_pdev *pdev = vdev->pdev; 706 struct qdf_tso_info_t *tso_info; 707 struct qdf_tso_num_seg_elem_t *tso_num_seg; 708 tso_info = &msdu_info->u.tso_info; 709 tso_info->curr_seg = NULL; 710 tso_info->tso_seg_list = NULL; 711 tso_info->num_segs = num_seg; 712 msdu_info->frm_type = dp_tx_frm_tso; 713 tso_info->tso_num_seg_list = NULL; 714 715 TSO_DEBUG(" %s: num_seg: %d", __func__, num_seg); 716 717 while (num_seg) { 718 tso_seg = dp_tx_tso_desc_alloc( 719 soc, msdu_info->tx_queue.desc_pool_id); 720 if (tso_seg) { 721 tso_seg->next = tso_info->tso_seg_list; 722 tso_info->tso_seg_list = tso_seg; 723 num_seg--; 724 } else { 725 dp_err_rl("Failed to alloc tso seg desc"); 726 DP_STATS_INC_PKT(vdev->pdev, 727 tso_stats.tso_no_mem_dropped, 1, 728 qdf_nbuf_len(msdu)); 729 dp_tx_free_remaining_tso_desc(soc, msdu_info, false); 730 731 return QDF_STATUS_E_NOMEM; 732 } 733 } 734 735 TSO_DEBUG(" %s: num_seg: %d", __func__, num_seg); 736 737 tso_num_seg = dp_tso_num_seg_alloc(soc, 738 msdu_info->tx_queue.desc_pool_id); 739 740 if (tso_num_seg) { 741 tso_num_seg->next = tso_info->tso_num_seg_list; 742 tso_info->tso_num_seg_list = tso_num_seg; 743 } else { 744 DP_TRACE(ERROR, "%s: Failed to alloc - Number of segs desc", 745 __func__); 746 dp_tx_free_remaining_tso_desc(soc, msdu_info, false); 747 748 return QDF_STATUS_E_NOMEM; 749 } 750 751 msdu_info->num_seg = 752 qdf_nbuf_get_tso_info(soc->osdev, msdu, tso_info); 753 754 TSO_DEBUG(" %s: msdu_info->num_seg: %d", __func__, 755 msdu_info->num_seg); 756 757 if (!(msdu_info->num_seg)) { 758 /* 759 * Free allocated TSO seg desc and number seg desc, 760 * do unmap for segments if dma map has done. 761 */ 762 DP_TRACE(ERROR, "%s: Failed to get tso info", __func__); 763 dp_tx_free_remaining_tso_desc(soc, msdu_info, true); 764 765 return QDF_STATUS_E_INVAL; 766 } 767 dp_tx_tso_history_add(soc, msdu_info->u.tso_info, 768 msdu, 0, DP_TX_DESC_MAP); 769 770 tso_info->curr_seg = tso_info->tso_seg_list; 771 772 tso_info->msdu_stats_idx = dp_tso_get_stats_idx(pdev); 773 dp_tso_packet_update(pdev, tso_info->msdu_stats_idx, 774 msdu, msdu_info->num_seg); 775 dp_tso_segment_stats_update(pdev, tso_info->tso_seg_list, 776 tso_info->msdu_stats_idx); 777 dp_stats_tso_segment_histogram_update(pdev, msdu_info->num_seg); 778 return QDF_STATUS_SUCCESS; 779 } 780 #else 781 static QDF_STATUS dp_tx_prepare_tso(struct dp_vdev *vdev, 782 qdf_nbuf_t msdu, struct dp_tx_msdu_info_s *msdu_info) 783 { 784 return QDF_STATUS_E_NOMEM; 785 } 786 #endif 787 788 QDF_COMPILE_TIME_ASSERT(dp_tx_htt_metadata_len_check, 789 (DP_TX_MSDU_INFO_META_DATA_DWORDS * 4 >= 790 sizeof(struct htt_tx_msdu_desc_ext2_t))); 791 792 /** 793 * dp_tx_prepare_ext_desc() - Allocate and prepare MSDU extension descriptor 794 * @vdev: DP Vdev handle 795 * @msdu_info: MSDU info to be setup in MSDU extension descriptor 796 * @desc_pool_id: Descriptor Pool ID 797 * 798 * Return: 799 */ 800 static 801 struct dp_tx_ext_desc_elem_s *dp_tx_prepare_ext_desc(struct dp_vdev *vdev, 802 struct dp_tx_msdu_info_s *msdu_info, uint8_t desc_pool_id) 803 { 804 uint8_t i; 805 uint8_t cached_ext_desc[HAL_TX_EXT_DESC_WITH_META_DATA]; 806 struct dp_tx_seg_info_s *seg_info; 807 struct dp_tx_ext_desc_elem_s *msdu_ext_desc; 808 struct dp_soc *soc = vdev->pdev->soc; 809 810 /* Allocate an extension descriptor */ 811 msdu_ext_desc = dp_tx_ext_desc_alloc(soc, desc_pool_id); 812 qdf_mem_zero(&cached_ext_desc[0], HAL_TX_EXT_DESC_WITH_META_DATA); 813 814 if (!msdu_ext_desc) { 815 DP_STATS_INC(vdev, 816 tx_i[msdu_info->xmit_type].dropped.desc_na.num, 1); 817 return NULL; 818 } 819 820 if (msdu_info->exception_fw && 821 qdf_unlikely(vdev->mesh_vdev)) { 822 qdf_mem_copy(&cached_ext_desc[HAL_TX_EXTENSION_DESC_LEN_BYTES], 823 &msdu_info->meta_data[0], 824 sizeof(struct htt_tx_msdu_desc_ext2_t)); 825 qdf_atomic_inc(&soc->num_tx_exception); 826 msdu_ext_desc->flags |= DP_TX_EXT_DESC_FLAG_METADATA_VALID; 827 } 828 829 switch (msdu_info->frm_type) { 830 case dp_tx_frm_sg: 831 case dp_tx_frm_me: 832 case dp_tx_frm_raw: 833 seg_info = msdu_info->u.sg_info.curr_seg; 834 /* Update the buffer pointers in MSDU Extension Descriptor */ 835 for (i = 0; i < seg_info->frag_cnt; i++) { 836 hal_tx_ext_desc_set_buffer(&cached_ext_desc[0], i, 837 seg_info->frags[i].paddr_lo, 838 seg_info->frags[i].paddr_hi, 839 seg_info->frags[i].len); 840 } 841 842 break; 843 844 case dp_tx_frm_tso: 845 dp_tx_prepare_tso_ext_desc(&msdu_info->u.tso_info.curr_seg->seg, 846 &cached_ext_desc[0]); 847 break; 848 849 850 default: 851 break; 852 } 853 854 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, 855 cached_ext_desc, HAL_TX_EXT_DESC_WITH_META_DATA); 856 857 hal_tx_ext_desc_sync(&cached_ext_desc[0], 858 msdu_ext_desc->vaddr); 859 860 return msdu_ext_desc; 861 } 862 863 /** 864 * dp_tx_trace_pkt() - Trace TX packet at DP layer 865 * @soc: datapath SOC 866 * @skb: skb to be traced 867 * @msdu_id: msdu_id of the packet 868 * @vdev_id: vdev_id of the packet 869 * @op_mode: Vdev Operation mode 870 * 871 * Return: None 872 */ 873 #ifdef DP_DISABLE_TX_PKT_TRACE 874 static void dp_tx_trace_pkt(struct dp_soc *soc, 875 qdf_nbuf_t skb, uint16_t msdu_id, 876 uint8_t vdev_id, enum QDF_OPMODE op_mode) 877 { 878 } 879 #else 880 static void dp_tx_trace_pkt(struct dp_soc *soc, 881 qdf_nbuf_t skb, uint16_t msdu_id, 882 uint8_t vdev_id, enum QDF_OPMODE op_mode) 883 { 884 if (dp_is_tput_high(soc)) 885 return; 886 887 QDF_NBUF_CB_TX_PACKET_TRACK(skb) = QDF_NBUF_TX_PKT_DATA_TRACK; 888 QDF_NBUF_CB_TX_DP_TRACE(skb) = 1; 889 DPTRACE(qdf_dp_trace_ptr(skb, 890 QDF_DP_TRACE_LI_DP_TX_PACKET_PTR_RECORD, 891 QDF_TRACE_DEFAULT_PDEV_ID, 892 qdf_nbuf_data_addr(skb), 893 sizeof(qdf_nbuf_data(skb)), 894 msdu_id, vdev_id, 0, 895 op_mode)); 896 897 qdf_dp_trace_log_pkt(vdev_id, skb, QDF_TX, QDF_TRACE_DEFAULT_PDEV_ID, 898 op_mode); 899 900 DPTRACE(qdf_dp_trace_data_pkt(skb, QDF_TRACE_DEFAULT_PDEV_ID, 901 QDF_DP_TRACE_LI_DP_TX_PACKET_RECORD, 902 msdu_id, QDF_TX)); 903 } 904 #endif 905 906 #ifdef WLAN_DP_FEATURE_MARK_ICMP_REQ_TO_FW 907 /** 908 * dp_tx_is_nbuf_marked_exception() - Check if the packet has been marked as 909 * exception by the upper layer (OS_IF) 910 * @soc: DP soc handle 911 * @nbuf: packet to be transmitted 912 * 913 * Return: 1 if the packet is marked as exception, 914 * 0, if the packet is not marked as exception. 915 */ 916 static inline int dp_tx_is_nbuf_marked_exception(struct dp_soc *soc, 917 qdf_nbuf_t nbuf) 918 { 919 return QDF_NBUF_CB_TX_PACKET_TO_FW(nbuf); 920 } 921 #else 922 static inline int dp_tx_is_nbuf_marked_exception(struct dp_soc *soc, 923 qdf_nbuf_t nbuf) 924 { 925 return 0; 926 } 927 #endif 928 929 #ifdef DP_TRAFFIC_END_INDICATION 930 /** 931 * dp_tx_get_traffic_end_indication_pkt() - Allocate and prepare packet to send 932 * as indication to fw to inform that 933 * data stream has ended 934 * @vdev: DP vdev handle 935 * @nbuf: original buffer from network stack 936 * 937 * Return: NULL on failure, 938 * nbuf on success 939 */ 940 static inline qdf_nbuf_t 941 dp_tx_get_traffic_end_indication_pkt(struct dp_vdev *vdev, 942 qdf_nbuf_t nbuf) 943 { 944 /* Packet length should be enough to copy upto L3 header */ 945 uint8_t end_nbuf_len = 64; 946 uint8_t htt_desc_size_aligned; 947 uint8_t htt_desc_size; 948 qdf_nbuf_t end_nbuf; 949 950 if (qdf_unlikely(QDF_NBUF_CB_GET_PACKET_TYPE(nbuf) == 951 QDF_NBUF_CB_PACKET_TYPE_END_INDICATION)) { 952 htt_desc_size = sizeof(struct htt_tx_msdu_desc_ext2_t); 953 htt_desc_size_aligned = (htt_desc_size + 7) & ~0x7; 954 955 end_nbuf = qdf_nbuf_queue_remove(&vdev->end_ind_pkt_q); 956 if (!end_nbuf) { 957 end_nbuf = qdf_nbuf_alloc(NULL, 958 (htt_desc_size_aligned + 959 end_nbuf_len), 960 htt_desc_size_aligned, 961 8, false); 962 if (!end_nbuf) { 963 dp_err("Packet allocation failed"); 964 goto out; 965 } 966 } else { 967 qdf_nbuf_reset(end_nbuf, htt_desc_size_aligned, 8); 968 } 969 qdf_mem_copy(qdf_nbuf_data(end_nbuf), qdf_nbuf_data(nbuf), 970 end_nbuf_len); 971 qdf_nbuf_set_pktlen(end_nbuf, end_nbuf_len); 972 973 return end_nbuf; 974 } 975 out: 976 return NULL; 977 } 978 979 /** 980 * dp_tx_send_traffic_end_indication_pkt() - Send indication packet to FW 981 * via exception path. 982 * @vdev: DP vdev handle 983 * @end_nbuf: skb to send as indication 984 * @msdu_info: msdu_info of original nbuf 985 * @peer_id: peer id 986 * 987 * Return: None 988 */ 989 static inline void 990 dp_tx_send_traffic_end_indication_pkt(struct dp_vdev *vdev, 991 qdf_nbuf_t end_nbuf, 992 struct dp_tx_msdu_info_s *msdu_info, 993 uint16_t peer_id) 994 { 995 struct dp_tx_msdu_info_s e_msdu_info = {0}; 996 qdf_nbuf_t nbuf; 997 struct htt_tx_msdu_desc_ext2_t *desc_ext = 998 (struct htt_tx_msdu_desc_ext2_t *)(e_msdu_info.meta_data); 999 e_msdu_info.tx_queue = msdu_info->tx_queue; 1000 e_msdu_info.tid = msdu_info->tid; 1001 e_msdu_info.exception_fw = 1; 1002 e_msdu_info.xmit_type = msdu_info->xmit_type; 1003 desc_ext->host_tx_desc_pool = 1; 1004 desc_ext->traffic_end_indication = 1; 1005 nbuf = dp_tx_send_msdu_single(vdev, end_nbuf, &e_msdu_info, 1006 peer_id, NULL); 1007 if (nbuf) { 1008 dp_err("Traffic end indication packet tx failed"); 1009 qdf_nbuf_free(nbuf); 1010 } 1011 } 1012 1013 /** 1014 * dp_tx_traffic_end_indication_set_desc_flag() - Set tx descriptor flag to 1015 * mark it traffic end indication 1016 * packet. 1017 * @tx_desc: Tx descriptor pointer 1018 * @msdu_info: msdu_info structure pointer 1019 * 1020 * Return: None 1021 */ 1022 static inline void 1023 dp_tx_traffic_end_indication_set_desc_flag(struct dp_tx_desc_s *tx_desc, 1024 struct dp_tx_msdu_info_s *msdu_info) 1025 { 1026 struct htt_tx_msdu_desc_ext2_t *desc_ext = 1027 (struct htt_tx_msdu_desc_ext2_t *)(msdu_info->meta_data); 1028 1029 if (qdf_unlikely(desc_ext->traffic_end_indication)) 1030 tx_desc->flags |= DP_TX_DESC_FLAG_TRAFFIC_END_IND; 1031 } 1032 1033 /** 1034 * dp_tx_traffic_end_indication_enq_ind_pkt() - Enqueue the packet instead of 1035 * freeing which are associated 1036 * with traffic end indication 1037 * flagged descriptor. 1038 * @soc: dp soc handle 1039 * @desc: Tx descriptor pointer 1040 * @nbuf: buffer pointer 1041 * 1042 * Return: True if packet gets enqueued else false 1043 */ 1044 static bool 1045 dp_tx_traffic_end_indication_enq_ind_pkt(struct dp_soc *soc, 1046 struct dp_tx_desc_s *desc, 1047 qdf_nbuf_t nbuf) 1048 { 1049 struct dp_vdev *vdev = NULL; 1050 1051 if (qdf_unlikely((desc->flags & 1052 DP_TX_DESC_FLAG_TRAFFIC_END_IND) != 0)) { 1053 vdev = dp_vdev_get_ref_by_id(soc, desc->vdev_id, 1054 DP_MOD_ID_TX_COMP); 1055 if (vdev) { 1056 qdf_nbuf_queue_add(&vdev->end_ind_pkt_q, nbuf); 1057 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_TX_COMP); 1058 return true; 1059 } 1060 } 1061 return false; 1062 } 1063 1064 /** 1065 * dp_tx_traffic_end_indication_is_enabled() - get the feature 1066 * enable/disable status 1067 * @vdev: dp vdev handle 1068 * 1069 * Return: True if feature is enable else false 1070 */ 1071 static inline bool 1072 dp_tx_traffic_end_indication_is_enabled(struct dp_vdev *vdev) 1073 { 1074 return qdf_unlikely(vdev->traffic_end_ind_en); 1075 } 1076 1077 static inline qdf_nbuf_t 1078 dp_tx_send_msdu_single_wrapper(struct dp_vdev *vdev, qdf_nbuf_t nbuf, 1079 struct dp_tx_msdu_info_s *msdu_info, 1080 uint16_t peer_id, qdf_nbuf_t end_nbuf) 1081 { 1082 if (dp_tx_traffic_end_indication_is_enabled(vdev)) 1083 end_nbuf = dp_tx_get_traffic_end_indication_pkt(vdev, nbuf); 1084 1085 nbuf = dp_tx_send_msdu_single(vdev, nbuf, msdu_info, peer_id, NULL); 1086 1087 if (qdf_unlikely(end_nbuf)) 1088 dp_tx_send_traffic_end_indication_pkt(vdev, end_nbuf, 1089 msdu_info, peer_id); 1090 return nbuf; 1091 } 1092 #else 1093 static inline qdf_nbuf_t 1094 dp_tx_get_traffic_end_indication_pkt(struct dp_vdev *vdev, 1095 qdf_nbuf_t nbuf) 1096 { 1097 return NULL; 1098 } 1099 1100 static inline void 1101 dp_tx_send_traffic_end_indication_pkt(struct dp_vdev *vdev, 1102 qdf_nbuf_t end_nbuf, 1103 struct dp_tx_msdu_info_s *msdu_info, 1104 uint16_t peer_id) 1105 {} 1106 1107 static inline void 1108 dp_tx_traffic_end_indication_set_desc_flag(struct dp_tx_desc_s *tx_desc, 1109 struct dp_tx_msdu_info_s *msdu_info) 1110 {} 1111 1112 static inline bool 1113 dp_tx_traffic_end_indication_enq_ind_pkt(struct dp_soc *soc, 1114 struct dp_tx_desc_s *desc, 1115 qdf_nbuf_t nbuf) 1116 { 1117 return false; 1118 } 1119 1120 static inline bool 1121 dp_tx_traffic_end_indication_is_enabled(struct dp_vdev *vdev) 1122 { 1123 return false; 1124 } 1125 1126 static inline qdf_nbuf_t 1127 dp_tx_send_msdu_single_wrapper(struct dp_vdev *vdev, qdf_nbuf_t nbuf, 1128 struct dp_tx_msdu_info_s *msdu_info, 1129 uint16_t peer_id, qdf_nbuf_t end_nbuf) 1130 { 1131 return dp_tx_send_msdu_single(vdev, nbuf, msdu_info, peer_id, NULL); 1132 } 1133 #endif 1134 1135 #if defined(QCA_SUPPORT_WDS_EXTENDED) 1136 static bool 1137 dp_tx_is_wds_ast_override_en(struct dp_soc *soc, 1138 struct cdp_tx_exception_metadata *tx_exc_metadata) 1139 { 1140 if (soc->features.wds_ext_ast_override_enable && 1141 tx_exc_metadata && tx_exc_metadata->is_wds_extended) 1142 return true; 1143 1144 return false; 1145 } 1146 #else 1147 static bool 1148 dp_tx_is_wds_ast_override_en(struct dp_soc *soc, 1149 struct cdp_tx_exception_metadata *tx_exc_metadata) 1150 { 1151 return false; 1152 } 1153 #endif 1154 1155 /** 1156 * dp_tx_prepare_desc_single() - Allocate and prepare Tx descriptor 1157 * @vdev: DP vdev handle 1158 * @nbuf: skb 1159 * @desc_pool_id: Descriptor pool ID 1160 * @msdu_info: Metadata to the fw 1161 * @tx_exc_metadata: Handle that holds exception path metadata 1162 * 1163 * Allocate and prepare Tx descriptor with msdu information. 1164 * 1165 * Return: Pointer to Tx Descriptor on success, 1166 * NULL on failure 1167 */ 1168 static 1169 struct dp_tx_desc_s *dp_tx_prepare_desc_single(struct dp_vdev *vdev, 1170 qdf_nbuf_t nbuf, uint8_t desc_pool_id, 1171 struct dp_tx_msdu_info_s *msdu_info, 1172 struct cdp_tx_exception_metadata *tx_exc_metadata) 1173 { 1174 uint8_t align_pad; 1175 uint8_t is_exception = 0; 1176 uint8_t htt_hdr_size; 1177 struct dp_tx_desc_s *tx_desc; 1178 struct dp_pdev *pdev = vdev->pdev; 1179 struct dp_soc *soc = pdev->soc; 1180 uint8_t xmit_type = msdu_info->xmit_type; 1181 1182 if (dp_tx_limit_check(vdev, nbuf)) 1183 return NULL; 1184 1185 /* Allocate software Tx descriptor */ 1186 if (nbuf->protocol == QDF_NBUF_TRAC_EAPOL_ETH_TYPE) 1187 tx_desc = dp_tx_spcl_desc_alloc(soc, desc_pool_id); 1188 else 1189 tx_desc = dp_tx_desc_alloc(soc, desc_pool_id); 1190 1191 if (qdf_unlikely(!tx_desc)) { 1192 DP_STATS_INC(vdev, 1193 tx_i[xmit_type].dropped.desc_na.num, 1); 1194 DP_STATS_INC(vdev, 1195 tx_i[xmit_type].dropped.desc_na_exc_alloc_fail.num, 1196 1); 1197 return NULL; 1198 } 1199 1200 dp_tx_outstanding_inc(pdev); 1201 1202 /* Initialize the SW tx descriptor */ 1203 tx_desc->nbuf = nbuf; 1204 tx_desc->frm_type = dp_tx_frm_std; 1205 tx_desc->tx_encap_type = ((tx_exc_metadata && 1206 (tx_exc_metadata->tx_encap_type != CDP_INVALID_TX_ENCAP_TYPE)) ? 1207 tx_exc_metadata->tx_encap_type : vdev->tx_encap_type); 1208 tx_desc->vdev_id = vdev->vdev_id; 1209 tx_desc->pdev = pdev; 1210 tx_desc->msdu_ext_desc = NULL; 1211 tx_desc->pkt_offset = 0; 1212 tx_desc->length = qdf_nbuf_headlen(nbuf); 1213 1214 dp_tx_trace_pkt(soc, nbuf, tx_desc->id, vdev->vdev_id, 1215 vdev->qdf_opmode); 1216 1217 if (qdf_unlikely(vdev->multipass_en)) { 1218 if (!dp_tx_multipass_process(soc, vdev, nbuf, msdu_info)) 1219 goto failure; 1220 } 1221 1222 /* Packets marked by upper layer (OS-IF) to be sent to FW */ 1223 if (dp_tx_is_nbuf_marked_exception(soc, nbuf)) 1224 is_exception = 1; 1225 1226 /* for BE chipsets if wds extension was enbled will not mark FW 1227 * in desc will mark ast index based search for ast index. 1228 */ 1229 if (dp_tx_is_wds_ast_override_en(soc, tx_exc_metadata)) 1230 return tx_desc; 1231 1232 /* 1233 * For special modes (vdev_type == ocb or mesh), data frames should be 1234 * transmitted using varying transmit parameters (tx spec) which include 1235 * transmit rate, power, priority, channel, channel bandwidth , nss etc. 1236 * These are filled in HTT MSDU descriptor and sent in frame pre-header. 1237 * These frames are sent as exception packets to firmware. 1238 * 1239 * HW requirement is that metadata should always point to a 1240 * 8-byte aligned address. So we add alignment pad to start of buffer. 1241 * HTT Metadata should be ensured to be multiple of 8-bytes, 1242 * to get 8-byte aligned start address along with align_pad added 1243 * 1244 * |-----------------------------| 1245 * | | 1246 * |-----------------------------| <-----Buffer Pointer Address given 1247 * | | ^ in HW descriptor (aligned) 1248 * | HTT Metadata | | 1249 * | | | 1250 * | | | Packet Offset given in descriptor 1251 * | | | 1252 * |-----------------------------| | 1253 * | Alignment Pad | v 1254 * |-----------------------------| <----- Actual buffer start address 1255 * | SKB Data | (Unaligned) 1256 * | | 1257 * | | 1258 * | | 1259 * | | 1260 * | | 1261 * |-----------------------------| 1262 */ 1263 if (qdf_unlikely((msdu_info->exception_fw)) || 1264 (vdev->opmode == wlan_op_mode_ocb) || 1265 (tx_exc_metadata && 1266 tx_exc_metadata->is_tx_sniffer)) { 1267 align_pad = ((unsigned long) qdf_nbuf_data(nbuf)) & 0x7; 1268 1269 if (qdf_unlikely(qdf_nbuf_headroom(nbuf) < align_pad)) { 1270 DP_STATS_INC(vdev, 1271 tx_i[xmit_type].dropped.headroom_insufficient, 1272 1); 1273 goto failure; 1274 } 1275 1276 if (qdf_nbuf_push_head(nbuf, align_pad) == NULL) { 1277 dp_tx_err("qdf_nbuf_push_head failed"); 1278 goto failure; 1279 } 1280 1281 htt_hdr_size = dp_tx_prepare_htt_metadata(vdev, nbuf, 1282 msdu_info); 1283 if (htt_hdr_size == 0) 1284 goto failure; 1285 1286 tx_desc->length = qdf_nbuf_headlen(nbuf); 1287 tx_desc->pkt_offset = align_pad + htt_hdr_size; 1288 tx_desc->flags |= DP_TX_DESC_FLAG_TO_FW; 1289 dp_tx_traffic_end_indication_set_desc_flag(tx_desc, 1290 msdu_info); 1291 is_exception = 1; 1292 tx_desc->length -= tx_desc->pkt_offset; 1293 } 1294 1295 #if !TQM_BYPASS_WAR 1296 if (is_exception || tx_exc_metadata) 1297 #endif 1298 { 1299 /* Temporary WAR due to TQM VP issues */ 1300 tx_desc->flags |= DP_TX_DESC_FLAG_TO_FW; 1301 qdf_atomic_inc(&soc->num_tx_exception); 1302 } 1303 1304 return tx_desc; 1305 1306 failure: 1307 dp_tx_desc_release(soc, tx_desc, desc_pool_id); 1308 return NULL; 1309 } 1310 1311 /** 1312 * dp_tx_prepare_desc() - Allocate and prepare Tx descriptor for multisegment 1313 * frame 1314 * @vdev: DP vdev handle 1315 * @nbuf: skb 1316 * @msdu_info: Info to be setup in MSDU descriptor and MSDU extension descriptor 1317 * @desc_pool_id : Descriptor Pool ID 1318 * 1319 * Allocate and prepare Tx descriptor with msdu and fragment descritor 1320 * information. For frames with fragments, allocate and prepare 1321 * an MSDU extension descriptor 1322 * 1323 * Return: Pointer to Tx Descriptor on success, 1324 * NULL on failure 1325 */ 1326 static struct dp_tx_desc_s *dp_tx_prepare_desc(struct dp_vdev *vdev, 1327 qdf_nbuf_t nbuf, struct dp_tx_msdu_info_s *msdu_info, 1328 uint8_t desc_pool_id) 1329 { 1330 struct dp_tx_desc_s *tx_desc; 1331 struct dp_tx_ext_desc_elem_s *msdu_ext_desc; 1332 struct dp_pdev *pdev = vdev->pdev; 1333 struct dp_soc *soc = pdev->soc; 1334 1335 if (dp_tx_limit_check(vdev, nbuf)) 1336 return NULL; 1337 1338 /* Allocate software Tx descriptor */ 1339 if (nbuf->protocol == QDF_NBUF_TRAC_EAPOL_ETH_TYPE) 1340 tx_desc = dp_tx_spcl_desc_alloc(soc, desc_pool_id); 1341 else 1342 tx_desc = dp_tx_desc_alloc(soc, desc_pool_id); 1343 1344 if (!tx_desc) { 1345 DP_STATS_INC(vdev, 1346 tx_i[msdu_info->xmit_type].dropped.desc_na.num, 1); 1347 return NULL; 1348 } 1349 dp_tx_tso_seg_history_add(soc, msdu_info->u.tso_info.curr_seg, 1350 nbuf, tx_desc->id, DP_TX_DESC_COOKIE); 1351 1352 dp_tx_outstanding_inc(pdev); 1353 1354 /* Initialize the SW tx descriptor */ 1355 tx_desc->nbuf = nbuf; 1356 tx_desc->frm_type = msdu_info->frm_type; 1357 tx_desc->tx_encap_type = vdev->tx_encap_type; 1358 tx_desc->vdev_id = vdev->vdev_id; 1359 tx_desc->pdev = pdev; 1360 tx_desc->pkt_offset = 0; 1361 1362 dp_tx_trace_pkt(soc, nbuf, tx_desc->id, vdev->vdev_id, 1363 vdev->qdf_opmode); 1364 1365 /* Handle scattered frames - TSO/SG/ME */ 1366 /* Allocate and prepare an extension descriptor for scattered frames */ 1367 msdu_ext_desc = dp_tx_prepare_ext_desc(vdev, msdu_info, desc_pool_id); 1368 if (!msdu_ext_desc) { 1369 dp_tx_info("Tx Extension Descriptor Alloc Fail"); 1370 goto failure; 1371 } 1372 1373 #if !TQM_BYPASS_WAR 1374 if (qdf_unlikely(msdu_info->exception_fw) || 1375 dp_tx_is_nbuf_marked_exception(soc, nbuf)) 1376 #endif 1377 { 1378 /* Temporary WAR due to TQM VP issues */ 1379 tx_desc->flags |= DP_TX_DESC_FLAG_TO_FW; 1380 qdf_atomic_inc(&soc->num_tx_exception); 1381 } 1382 1383 1384 tx_desc->msdu_ext_desc = msdu_ext_desc; 1385 tx_desc->flags |= DP_TX_DESC_FLAG_FRAG; 1386 1387 msdu_ext_desc->tso_desc = msdu_info->u.tso_info.curr_seg; 1388 msdu_ext_desc->tso_num_desc = msdu_info->u.tso_info.tso_num_seg_list; 1389 1390 tx_desc->dma_addr = msdu_ext_desc->paddr; 1391 1392 if (msdu_ext_desc->flags & DP_TX_EXT_DESC_FLAG_METADATA_VALID) 1393 tx_desc->length = HAL_TX_EXT_DESC_WITH_META_DATA; 1394 else 1395 tx_desc->length = HAL_TX_EXTENSION_DESC_LEN_BYTES; 1396 1397 return tx_desc; 1398 failure: 1399 dp_tx_desc_release(soc, tx_desc, desc_pool_id); 1400 return NULL; 1401 } 1402 1403 /** 1404 * dp_tx_prepare_raw() - Prepare RAW packet TX 1405 * @vdev: DP vdev handle 1406 * @nbuf: buffer pointer 1407 * @seg_info: Pointer to Segment info Descriptor to be prepared 1408 * @msdu_info: MSDU info to be setup in MSDU descriptor and MSDU extension 1409 * descriptor 1410 * 1411 * Return: 1412 */ 1413 static qdf_nbuf_t dp_tx_prepare_raw(struct dp_vdev *vdev, qdf_nbuf_t nbuf, 1414 struct dp_tx_seg_info_s *seg_info, struct dp_tx_msdu_info_s *msdu_info) 1415 { 1416 qdf_nbuf_t curr_nbuf = NULL; 1417 uint16_t total_len = 0; 1418 qdf_dma_addr_t paddr; 1419 int32_t i; 1420 int32_t mapped_buf_num = 0; 1421 1422 struct dp_tx_sg_info_s *sg_info = &msdu_info->u.sg_info; 1423 qdf_dot3_qosframe_t *qos_wh = (qdf_dot3_qosframe_t *) nbuf->data; 1424 1425 DP_STATS_INC_PKT(vdev, tx_i[msdu_info->xmit_type].raw.raw_pkt, 1426 1, qdf_nbuf_len(nbuf)); 1427 1428 /* Continue only if frames are of DATA type */ 1429 if (!DP_FRAME_IS_DATA(qos_wh)) { 1430 DP_STATS_INC(vdev, 1431 tx_i[msdu_info->xmit_type].raw.invalid_raw_pkt_datatype, 1432 1); 1433 dp_tx_debug("Pkt. recd is of not data type"); 1434 goto error; 1435 } 1436 /* SWAR for HW: Enable WEP bit in the AMSDU frames for RAW mode */ 1437 if (vdev->raw_mode_war && 1438 (qos_wh->i_fc[0] & QDF_IEEE80211_FC0_SUBTYPE_QOS) && 1439 (qos_wh->i_qos[0] & IEEE80211_QOS_AMSDU)) 1440 qos_wh->i_fc[1] |= IEEE80211_FC1_WEP; 1441 1442 for (curr_nbuf = nbuf, i = 0; curr_nbuf; 1443 curr_nbuf = qdf_nbuf_next(curr_nbuf), i++) { 1444 /* 1445 * Number of nbuf's must not exceed the size of the frags 1446 * array in seg_info. 1447 */ 1448 if (i >= DP_TX_MAX_NUM_FRAGS) { 1449 dp_err_rl("nbuf cnt exceeds the max number of segs"); 1450 DP_STATS_INC(vdev, 1451 tx_i[msdu_info->xmit_type].raw.num_frags_overflow_err, 1452 1); 1453 goto error; 1454 } 1455 if (QDF_STATUS_SUCCESS != 1456 qdf_nbuf_map_nbytes_single(vdev->osdev, 1457 curr_nbuf, 1458 QDF_DMA_TO_DEVICE, 1459 curr_nbuf->len)) { 1460 dp_tx_err("%s dma map error ", __func__); 1461 DP_STATS_INC(vdev, 1462 tx_i[msdu_info->xmit_type].raw.dma_map_error, 1463 1); 1464 goto error; 1465 } 1466 /* Update the count of mapped nbuf's */ 1467 mapped_buf_num++; 1468 paddr = qdf_nbuf_get_frag_paddr(curr_nbuf, 0); 1469 seg_info->frags[i].paddr_lo = paddr; 1470 seg_info->frags[i].paddr_hi = ((uint64_t)paddr >> 32); 1471 seg_info->frags[i].len = qdf_nbuf_len(curr_nbuf); 1472 seg_info->frags[i].vaddr = (void *) curr_nbuf; 1473 total_len += qdf_nbuf_len(curr_nbuf); 1474 } 1475 1476 seg_info->frag_cnt = i; 1477 seg_info->total_len = total_len; 1478 seg_info->next = NULL; 1479 1480 sg_info->curr_seg = seg_info; 1481 1482 msdu_info->frm_type = dp_tx_frm_raw; 1483 msdu_info->num_seg = 1; 1484 1485 return nbuf; 1486 1487 error: 1488 i = 0; 1489 while (nbuf) { 1490 curr_nbuf = nbuf; 1491 if (i < mapped_buf_num) { 1492 qdf_nbuf_unmap_nbytes_single(vdev->osdev, curr_nbuf, 1493 QDF_DMA_TO_DEVICE, 1494 curr_nbuf->len); 1495 i++; 1496 } 1497 nbuf = qdf_nbuf_next(nbuf); 1498 qdf_nbuf_free(curr_nbuf); 1499 } 1500 return NULL; 1501 1502 } 1503 1504 /** 1505 * dp_tx_raw_prepare_unset() - unmap the chain of nbufs belonging to RAW frame. 1506 * @soc: DP soc handle 1507 * @nbuf: Buffer pointer 1508 * 1509 * unmap the chain of nbufs that belong to this RAW frame. 1510 * 1511 * Return: None 1512 */ 1513 static void dp_tx_raw_prepare_unset(struct dp_soc *soc, 1514 qdf_nbuf_t nbuf) 1515 { 1516 qdf_nbuf_t cur_nbuf = nbuf; 1517 1518 do { 1519 qdf_nbuf_unmap_nbytes_single(soc->osdev, cur_nbuf, 1520 QDF_DMA_TO_DEVICE, 1521 cur_nbuf->len); 1522 cur_nbuf = qdf_nbuf_next(cur_nbuf); 1523 } while (cur_nbuf); 1524 } 1525 1526 #ifdef VDEV_PEER_PROTOCOL_COUNT 1527 void dp_vdev_peer_stats_update_protocol_cnt_tx(struct dp_vdev *vdev_hdl, 1528 qdf_nbuf_t nbuf) 1529 { 1530 qdf_nbuf_t nbuf_local; 1531 struct dp_vdev *vdev_local = vdev_hdl; 1532 1533 do { 1534 if (qdf_likely(!((vdev_local)->peer_protocol_count_track))) 1535 break; 1536 nbuf_local = nbuf; 1537 if (qdf_unlikely(((vdev_local)->tx_encap_type) == 1538 htt_cmn_pkt_type_raw)) 1539 break; 1540 else if (qdf_unlikely(qdf_nbuf_is_nonlinear((nbuf_local)))) 1541 break; 1542 else if (qdf_nbuf_is_tso((nbuf_local))) 1543 break; 1544 dp_vdev_peer_stats_update_protocol_cnt((vdev_local), 1545 (nbuf_local), 1546 NULL, 1, 0); 1547 } while (0); 1548 } 1549 #endif 1550 1551 #ifdef WLAN_DP_FEATURE_SW_LATENCY_MGR 1552 void dp_tx_update_stats(struct dp_soc *soc, 1553 struct dp_tx_desc_s *tx_desc, 1554 uint8_t ring_id) 1555 { 1556 uint32_t stats_len = dp_tx_get_pkt_len(tx_desc); 1557 1558 DP_STATS_INC_PKT(soc, tx.egress[ring_id], 1, stats_len); 1559 } 1560 1561 int 1562 dp_tx_attempt_coalescing(struct dp_soc *soc, struct dp_vdev *vdev, 1563 struct dp_tx_desc_s *tx_desc, 1564 uint8_t tid, 1565 struct dp_tx_msdu_info_s *msdu_info, 1566 uint8_t ring_id) 1567 { 1568 struct dp_swlm *swlm = &soc->swlm; 1569 union swlm_data swlm_query_data; 1570 struct dp_swlm_tcl_data tcl_data; 1571 QDF_STATUS status; 1572 int ret; 1573 1574 if (!swlm->is_enabled) 1575 return msdu_info->skip_hp_update; 1576 1577 tcl_data.nbuf = tx_desc->nbuf; 1578 tcl_data.tid = tid; 1579 tcl_data.ring_id = ring_id; 1580 tcl_data.pkt_len = dp_tx_get_pkt_len(tx_desc); 1581 tcl_data.num_ll_connections = vdev->num_latency_critical_conn; 1582 swlm_query_data.tcl_data = &tcl_data; 1583 1584 status = dp_swlm_tcl_pre_check(soc, &tcl_data); 1585 if (QDF_IS_STATUS_ERROR(status)) { 1586 dp_swlm_tcl_reset_session_data(soc, ring_id); 1587 DP_STATS_INC(swlm, tcl[ring_id].coalesce_fail, 1); 1588 return 0; 1589 } 1590 1591 ret = dp_swlm_query_policy(soc, TCL_DATA, swlm_query_data); 1592 if (ret) { 1593 DP_STATS_INC(swlm, tcl[ring_id].coalesce_success, 1); 1594 } else { 1595 DP_STATS_INC(swlm, tcl[ring_id].coalesce_fail, 1); 1596 } 1597 1598 return ret; 1599 } 1600 1601 void 1602 dp_tx_ring_access_end(struct dp_soc *soc, hal_ring_handle_t hal_ring_hdl, 1603 int coalesce) 1604 { 1605 if (coalesce) 1606 dp_tx_hal_ring_access_end_reap(soc, hal_ring_hdl); 1607 else 1608 dp_tx_hal_ring_access_end(soc, hal_ring_hdl); 1609 } 1610 1611 static inline void 1612 dp_tx_is_hp_update_required(uint32_t i, struct dp_tx_msdu_info_s *msdu_info) 1613 { 1614 if (((i + 1) < msdu_info->num_seg)) 1615 msdu_info->skip_hp_update = 1; 1616 else 1617 msdu_info->skip_hp_update = 0; 1618 } 1619 1620 static inline void 1621 dp_flush_tcp_hp(struct dp_soc *soc, uint8_t ring_id) 1622 { 1623 hal_ring_handle_t hal_ring_hdl = 1624 dp_tx_get_hal_ring_hdl(soc, ring_id); 1625 1626 if (dp_tx_hal_ring_access_start(soc, hal_ring_hdl)) { 1627 dp_err("Fillmore: SRNG access start failed"); 1628 return; 1629 } 1630 1631 dp_tx_ring_access_end_wrapper(soc, hal_ring_hdl, 0); 1632 } 1633 1634 static inline void 1635 dp_tx_check_and_flush_hp(struct dp_soc *soc, 1636 QDF_STATUS status, 1637 struct dp_tx_msdu_info_s *msdu_info) 1638 { 1639 if (QDF_IS_STATUS_ERROR(status) && !msdu_info->skip_hp_update) { 1640 dp_flush_tcp_hp(soc, 1641 (msdu_info->tx_queue.ring_id & DP_TX_QUEUE_MASK)); 1642 } 1643 } 1644 #else 1645 static inline void 1646 dp_tx_is_hp_update_required(uint32_t i, struct dp_tx_msdu_info_s *msdu_info) 1647 { 1648 } 1649 1650 static inline void 1651 dp_tx_check_and_flush_hp(struct dp_soc *soc, 1652 QDF_STATUS status, 1653 struct dp_tx_msdu_info_s *msdu_info) 1654 { 1655 } 1656 #endif 1657 1658 #ifdef FEATURE_RUNTIME_PM 1659 void 1660 dp_tx_ring_access_end_wrapper(struct dp_soc *soc, 1661 hal_ring_handle_t hal_ring_hdl, 1662 int coalesce) 1663 { 1664 int ret; 1665 1666 /* 1667 * Avoid runtime get and put APIs under high throughput scenarios. 1668 */ 1669 if (dp_get_rtpm_tput_policy_requirement(soc)) { 1670 dp_tx_ring_access_end(soc, hal_ring_hdl, coalesce); 1671 return; 1672 } 1673 1674 ret = hif_rtpm_get(HIF_RTPM_GET_ASYNC, HIF_RTPM_ID_DP); 1675 if (QDF_IS_STATUS_SUCCESS(ret)) { 1676 if (hif_system_pm_state_check(soc->hif_handle)) { 1677 dp_tx_hal_ring_access_end_reap(soc, hal_ring_hdl); 1678 hal_srng_set_event(hal_ring_hdl, HAL_SRNG_FLUSH_EVENT); 1679 hal_srng_inc_flush_cnt(hal_ring_hdl); 1680 } else { 1681 dp_tx_ring_access_end(soc, hal_ring_hdl, coalesce); 1682 } 1683 hif_rtpm_put(HIF_RTPM_PUT_ASYNC, HIF_RTPM_ID_DP); 1684 } else { 1685 dp_runtime_get(soc); 1686 dp_tx_hal_ring_access_end_reap(soc, hal_ring_hdl); 1687 hal_srng_set_event(hal_ring_hdl, HAL_SRNG_FLUSH_EVENT); 1688 qdf_atomic_inc(&soc->tx_pending_rtpm); 1689 hal_srng_inc_flush_cnt(hal_ring_hdl); 1690 dp_runtime_put(soc); 1691 } 1692 } 1693 #else 1694 1695 #ifdef DP_POWER_SAVE 1696 void 1697 dp_tx_ring_access_end_wrapper(struct dp_soc *soc, 1698 hal_ring_handle_t hal_ring_hdl, 1699 int coalesce) 1700 { 1701 if (hif_system_pm_state_check(soc->hif_handle)) { 1702 dp_tx_hal_ring_access_end_reap(soc, hal_ring_hdl); 1703 hal_srng_set_event(hal_ring_hdl, HAL_SRNG_FLUSH_EVENT); 1704 hal_srng_inc_flush_cnt(hal_ring_hdl); 1705 } else { 1706 dp_tx_ring_access_end(soc, hal_ring_hdl, coalesce); 1707 } 1708 } 1709 #endif 1710 #endif 1711 1712 /** 1713 * dp_tx_get_tid() - Obtain TID to be used for this frame 1714 * @vdev: DP vdev handle 1715 * @nbuf: skb 1716 * @msdu_info: msdu descriptor 1717 * 1718 * Extract the DSCP or PCP information from frame and map into TID value. 1719 * 1720 * Return: void 1721 */ 1722 static void dp_tx_get_tid(struct dp_vdev *vdev, qdf_nbuf_t nbuf, 1723 struct dp_tx_msdu_info_s *msdu_info) 1724 { 1725 uint8_t tos = 0, dscp_tid_override = 0; 1726 uint8_t *hdr_ptr, *L3datap; 1727 uint8_t is_mcast = 0; 1728 qdf_ether_header_t *eh = NULL; 1729 qdf_ethervlan_header_t *evh = NULL; 1730 uint16_t ether_type; 1731 qdf_llc_t *llcHdr; 1732 struct dp_pdev *pdev = (struct dp_pdev *)vdev->pdev; 1733 1734 DP_TX_TID_OVERRIDE(msdu_info, nbuf); 1735 if (qdf_likely(vdev->tx_encap_type != htt_cmn_pkt_type_raw)) { 1736 eh = (qdf_ether_header_t *)nbuf->data; 1737 hdr_ptr = (uint8_t *)(eh->ether_dhost); 1738 L3datap = hdr_ptr + sizeof(qdf_ether_header_t); 1739 } else { 1740 qdf_dot3_qosframe_t *qos_wh = 1741 (qdf_dot3_qosframe_t *) nbuf->data; 1742 msdu_info->tid = qos_wh->i_fc[0] & DP_FC0_SUBTYPE_QOS ? 1743 qos_wh->i_qos[0] & DP_QOS_TID : 0; 1744 return; 1745 } 1746 1747 is_mcast = DP_FRAME_IS_MULTICAST(hdr_ptr); 1748 ether_type = eh->ether_type; 1749 1750 llcHdr = (qdf_llc_t *)(nbuf->data + sizeof(qdf_ether_header_t)); 1751 /* 1752 * Check if packet is dot3 or eth2 type. 1753 */ 1754 if (DP_FRAME_IS_LLC(ether_type) && DP_FRAME_IS_SNAP(llcHdr)) { 1755 ether_type = (uint16_t)*(nbuf->data + 2*QDF_MAC_ADDR_SIZE + 1756 sizeof(*llcHdr)); 1757 1758 if (ether_type == htons(ETHERTYPE_VLAN)) { 1759 L3datap = hdr_ptr + sizeof(qdf_ethervlan_header_t) + 1760 sizeof(*llcHdr); 1761 ether_type = (uint16_t)*(nbuf->data + 2*QDF_MAC_ADDR_SIZE 1762 + sizeof(*llcHdr) + 1763 sizeof(qdf_net_vlanhdr_t)); 1764 } else { 1765 L3datap = hdr_ptr + sizeof(qdf_ether_header_t) + 1766 sizeof(*llcHdr); 1767 } 1768 } else { 1769 if (ether_type == htons(ETHERTYPE_VLAN)) { 1770 evh = (qdf_ethervlan_header_t *) eh; 1771 ether_type = evh->ether_type; 1772 L3datap = hdr_ptr + sizeof(qdf_ethervlan_header_t); 1773 } 1774 } 1775 1776 /* 1777 * Find priority from IP TOS DSCP field 1778 */ 1779 if (qdf_nbuf_is_ipv4_pkt(nbuf)) { 1780 qdf_net_iphdr_t *ip = (qdf_net_iphdr_t *) L3datap; 1781 if (qdf_nbuf_is_ipv4_dhcp_pkt(nbuf)) { 1782 /* Only for unicast frames */ 1783 if (!is_mcast) { 1784 /* send it on VO queue */ 1785 msdu_info->tid = DP_VO_TID; 1786 } 1787 } else { 1788 /* 1789 * IP frame: exclude ECN bits 0-1 and map DSCP bits 2-7 1790 * from TOS byte. 1791 */ 1792 tos = ip->ip_tos; 1793 dscp_tid_override = 1; 1794 1795 } 1796 } else if (qdf_nbuf_is_ipv6_pkt(nbuf)) { 1797 /* TODO 1798 * use flowlabel 1799 *igmpmld cases to be handled in phase 2 1800 */ 1801 unsigned long ver_pri_flowlabel; 1802 unsigned long pri; 1803 ver_pri_flowlabel = *(unsigned long *) L3datap; 1804 pri = (ntohl(ver_pri_flowlabel) & IPV6_FLOWINFO_PRIORITY) >> 1805 DP_IPV6_PRIORITY_SHIFT; 1806 tos = pri; 1807 dscp_tid_override = 1; 1808 } else if (qdf_nbuf_is_ipv4_eapol_pkt(nbuf)) 1809 msdu_info->tid = DP_VO_TID; 1810 else if (qdf_nbuf_is_ipv4_arp_pkt(nbuf)) { 1811 /* Only for unicast frames */ 1812 if (!is_mcast) { 1813 /* send ucast arp on VO queue */ 1814 msdu_info->tid = DP_VO_TID; 1815 } 1816 } 1817 1818 /* 1819 * Assign all MCAST packets to BE 1820 */ 1821 if (qdf_unlikely(vdev->tx_encap_type != htt_cmn_pkt_type_raw)) { 1822 if (is_mcast) { 1823 tos = 0; 1824 dscp_tid_override = 1; 1825 } 1826 } 1827 1828 if (dscp_tid_override == 1) { 1829 tos = (tos >> DP_IP_DSCP_SHIFT) & DP_IP_DSCP_MASK; 1830 msdu_info->tid = pdev->dscp_tid_map[vdev->dscp_tid_map_id][tos]; 1831 } 1832 1833 if (msdu_info->tid >= CDP_MAX_DATA_TIDS) 1834 msdu_info->tid = CDP_MAX_DATA_TIDS - 1; 1835 1836 return; 1837 } 1838 1839 /** 1840 * dp_tx_classify_tid() - Obtain TID to be used for this frame 1841 * @vdev: DP vdev handle 1842 * @nbuf: skb 1843 * @msdu_info: msdu descriptor 1844 * 1845 * Software based TID classification is required when more than 2 DSCP-TID 1846 * mapping tables are needed. 1847 * Hardware supports 2 DSCP-TID mapping tables for HKv1 and 48 for HKv2. 1848 * 1849 * Return: void 1850 */ 1851 static inline void dp_tx_classify_tid(struct dp_vdev *vdev, qdf_nbuf_t nbuf, 1852 struct dp_tx_msdu_info_s *msdu_info) 1853 { 1854 DP_TX_TID_OVERRIDE(msdu_info, nbuf); 1855 1856 /* 1857 * skip_sw_tid_classification flag will set in below cases- 1858 * 1. vdev->dscp_tid_map_id < pdev->soc->num_hw_dscp_tid_map 1859 * 2. hlos_tid_override enabled for vdev 1860 * 3. mesh mode enabled for vdev 1861 */ 1862 if (qdf_likely(vdev->skip_sw_tid_classification)) { 1863 /* Update tid in msdu_info from skb priority */ 1864 if (qdf_unlikely(vdev->skip_sw_tid_classification 1865 & DP_TXRX_HLOS_TID_OVERRIDE_ENABLED)) { 1866 uint32_t tid = qdf_nbuf_get_priority(nbuf); 1867 1868 if (tid == DP_TX_INVALID_QOS_TAG) 1869 return; 1870 1871 msdu_info->tid = tid; 1872 return; 1873 } 1874 return; 1875 } 1876 1877 dp_tx_get_tid(vdev, nbuf, msdu_info); 1878 } 1879 1880 #ifdef FEATURE_WLAN_TDLS 1881 /** 1882 * dp_tx_update_tdls_flags() - Update descriptor flags for TDLS frame 1883 * @soc: datapath SOC 1884 * @vdev: datapath vdev 1885 * @tx_desc: TX descriptor 1886 * 1887 * Return: None 1888 */ 1889 static void dp_tx_update_tdls_flags(struct dp_soc *soc, 1890 struct dp_vdev *vdev, 1891 struct dp_tx_desc_s *tx_desc) 1892 { 1893 if (vdev) { 1894 if (vdev->is_tdls_frame) { 1895 tx_desc->flags |= DP_TX_DESC_FLAG_TDLS_FRAME; 1896 vdev->is_tdls_frame = false; 1897 } 1898 } 1899 } 1900 1901 static uint8_t dp_htt_tx_comp_get_status(struct dp_soc *soc, char *htt_desc) 1902 { 1903 uint8_t tx_status = HTT_TX_FW2WBM_TX_STATUS_MAX; 1904 1905 switch (soc->arch_id) { 1906 case CDP_ARCH_TYPE_LI: 1907 tx_status = HTT_TX_WBM_COMPLETION_V2_TX_STATUS_GET(htt_desc[0]); 1908 break; 1909 1910 case CDP_ARCH_TYPE_BE: 1911 tx_status = HTT_TX_WBM_COMPLETION_V3_TX_STATUS_GET(htt_desc[0]); 1912 break; 1913 1914 case CDP_ARCH_TYPE_RH: 1915 { 1916 uint32_t *msg_word = (uint32_t *)htt_desc; 1917 1918 tx_status = HTT_TX_MSDU_INFO_RELEASE_REASON_GET( 1919 *(msg_word + 3)); 1920 } 1921 break; 1922 default: 1923 dp_err("Incorrect CDP_ARCH %d", soc->arch_id); 1924 QDF_BUG(0); 1925 } 1926 1927 return tx_status; 1928 } 1929 1930 /** 1931 * dp_non_std_htt_tx_comp_free_buff() - Free the non std tx packet buffer 1932 * @soc: dp_soc handle 1933 * @tx_desc: TX descriptor 1934 * 1935 * Return: None 1936 */ 1937 static void dp_non_std_htt_tx_comp_free_buff(struct dp_soc *soc, 1938 struct dp_tx_desc_s *tx_desc) 1939 { 1940 uint8_t tx_status = 0; 1941 uint8_t htt_tx_status[HAL_TX_COMP_HTT_STATUS_LEN]; 1942 1943 qdf_nbuf_t nbuf = tx_desc->nbuf; 1944 struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, tx_desc->vdev_id, 1945 DP_MOD_ID_TDLS); 1946 1947 if (qdf_unlikely(!vdev)) { 1948 dp_err_rl("vdev is null!"); 1949 goto error; 1950 } 1951 1952 hal_tx_comp_get_htt_desc(&tx_desc->comp, htt_tx_status); 1953 tx_status = dp_htt_tx_comp_get_status(soc, htt_tx_status); 1954 dp_debug("vdev_id: %d tx_status: %d", tx_desc->vdev_id, tx_status); 1955 1956 if (vdev->tx_non_std_data_callback.func) { 1957 qdf_nbuf_set_next(nbuf, NULL); 1958 vdev->tx_non_std_data_callback.func( 1959 vdev->tx_non_std_data_callback.ctxt, 1960 nbuf, tx_status); 1961 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_TDLS); 1962 return; 1963 } else { 1964 dp_err_rl("callback func is null"); 1965 } 1966 1967 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_TDLS); 1968 error: 1969 qdf_nbuf_unmap_single(soc->osdev, nbuf, QDF_DMA_TO_DEVICE); 1970 qdf_nbuf_free(nbuf); 1971 } 1972 1973 /** 1974 * dp_tx_msdu_single_map() - do nbuf map 1975 * @vdev: DP vdev handle 1976 * @tx_desc: DP TX descriptor pointer 1977 * @nbuf: skb pointer 1978 * 1979 * For TDLS frame, use qdf_nbuf_map_single() to align with the unmap 1980 * operation done in other component. 1981 * 1982 * Return: QDF_STATUS 1983 */ 1984 static inline QDF_STATUS dp_tx_msdu_single_map(struct dp_vdev *vdev, 1985 struct dp_tx_desc_s *tx_desc, 1986 qdf_nbuf_t nbuf) 1987 { 1988 if (qdf_likely(!(tx_desc->flags & DP_TX_DESC_FLAG_TDLS_FRAME))) 1989 return qdf_nbuf_map_nbytes_single(vdev->osdev, 1990 nbuf, 1991 QDF_DMA_TO_DEVICE, 1992 nbuf->len); 1993 else 1994 return qdf_nbuf_map_single(vdev->osdev, nbuf, 1995 QDF_DMA_TO_DEVICE); 1996 } 1997 #else 1998 static inline void dp_tx_update_tdls_flags(struct dp_soc *soc, 1999 struct dp_vdev *vdev, 2000 struct dp_tx_desc_s *tx_desc) 2001 { 2002 } 2003 2004 static inline void dp_non_std_htt_tx_comp_free_buff(struct dp_soc *soc, 2005 struct dp_tx_desc_s *tx_desc) 2006 { 2007 } 2008 2009 static inline QDF_STATUS dp_tx_msdu_single_map(struct dp_vdev *vdev, 2010 struct dp_tx_desc_s *tx_desc, 2011 qdf_nbuf_t nbuf) 2012 { 2013 return qdf_nbuf_map_nbytes_single(vdev->osdev, 2014 nbuf, 2015 QDF_DMA_TO_DEVICE, 2016 nbuf->len); 2017 } 2018 #endif 2019 2020 static inline 2021 qdf_dma_addr_t dp_tx_nbuf_map_regular(struct dp_vdev *vdev, 2022 struct dp_tx_desc_s *tx_desc, 2023 qdf_nbuf_t nbuf) 2024 { 2025 QDF_STATUS ret = QDF_STATUS_E_FAILURE; 2026 2027 ret = dp_tx_msdu_single_map(vdev, tx_desc, nbuf); 2028 if (qdf_unlikely(QDF_IS_STATUS_ERROR(ret))) 2029 return 0; 2030 2031 return qdf_nbuf_mapped_paddr_get(nbuf); 2032 } 2033 2034 static inline 2035 void dp_tx_nbuf_unmap_regular(struct dp_soc *soc, struct dp_tx_desc_s *desc) 2036 { 2037 qdf_nbuf_unmap_nbytes_single_paddr(soc->osdev, 2038 desc->nbuf, 2039 desc->dma_addr, 2040 QDF_DMA_TO_DEVICE, 2041 desc->length); 2042 } 2043 2044 #ifdef QCA_DP_TX_RMNET_OPTIMIZATION 2045 static inline bool 2046 is_nbuf_frm_rmnet(qdf_nbuf_t nbuf, struct dp_tx_msdu_info_s *msdu_info) 2047 { 2048 struct net_device *ingress_dev; 2049 skb_frag_t *frag; 2050 uint16_t buf_len = 0; 2051 uint16_t linear_data_len = 0; 2052 uint8_t *payload_addr = NULL; 2053 2054 ingress_dev = dev_get_by_index(dev_net(nbuf->dev), nbuf->skb_iif); 2055 2056 if (!ingress_dev) 2057 return false; 2058 2059 if ((ingress_dev->priv_flags & IFF_PHONY_HEADROOM)) { 2060 qdf_net_if_release_dev((struct qdf_net_if *)ingress_dev); 2061 frag = &(skb_shinfo(nbuf)->frags[0]); 2062 buf_len = skb_frag_size(frag); 2063 payload_addr = (uint8_t *)skb_frag_address(frag); 2064 linear_data_len = skb_headlen(nbuf); 2065 2066 buf_len += linear_data_len; 2067 payload_addr = payload_addr - linear_data_len; 2068 memcpy(payload_addr, nbuf->data, linear_data_len); 2069 2070 msdu_info->frm_type = dp_tx_frm_rmnet; 2071 msdu_info->buf_len = buf_len; 2072 msdu_info->payload_addr = payload_addr; 2073 2074 return true; 2075 } 2076 qdf_net_if_release_dev((struct qdf_net_if *)ingress_dev); 2077 return false; 2078 } 2079 2080 static inline 2081 qdf_dma_addr_t dp_tx_rmnet_nbuf_map(struct dp_tx_msdu_info_s *msdu_info, 2082 struct dp_tx_desc_s *tx_desc) 2083 { 2084 qdf_dma_addr_t paddr; 2085 2086 paddr = (qdf_dma_addr_t)qdf_mem_virt_to_phys(msdu_info->payload_addr); 2087 tx_desc->length = msdu_info->buf_len; 2088 2089 qdf_nbuf_dma_clean_range((void *)msdu_info->payload_addr, 2090 (void *)(msdu_info->payload_addr + 2091 msdu_info->buf_len)); 2092 2093 tx_desc->flags |= DP_TX_DESC_FLAG_RMNET; 2094 return paddr; 2095 } 2096 #else 2097 static inline bool 2098 is_nbuf_frm_rmnet(qdf_nbuf_t nbuf, struct dp_tx_msdu_info_s *msdu_info) 2099 { 2100 return false; 2101 } 2102 2103 static inline 2104 qdf_dma_addr_t dp_tx_rmnet_nbuf_map(struct dp_tx_msdu_info_s *msdu_info, 2105 struct dp_tx_desc_s *tx_desc) 2106 { 2107 return 0; 2108 } 2109 #endif 2110 2111 #if defined(QCA_DP_TX_NBUF_NO_MAP_UNMAP) && !defined(BUILD_X86) 2112 static inline 2113 qdf_dma_addr_t dp_tx_nbuf_map(struct dp_vdev *vdev, 2114 struct dp_tx_desc_s *tx_desc, 2115 qdf_nbuf_t nbuf) 2116 { 2117 if (qdf_likely(tx_desc->flags & DP_TX_DESC_FLAG_FAST)) { 2118 qdf_nbuf_dma_clean_range((void *)nbuf->data, 2119 (void *)(nbuf->data + nbuf->len)); 2120 return (qdf_dma_addr_t)qdf_mem_virt_to_phys(nbuf->data); 2121 } else { 2122 return dp_tx_nbuf_map_regular(vdev, tx_desc, nbuf); 2123 } 2124 } 2125 2126 static inline 2127 void dp_tx_nbuf_unmap(struct dp_soc *soc, 2128 struct dp_tx_desc_s *desc) 2129 { 2130 if (qdf_unlikely(!(desc->flags & 2131 (DP_TX_DESC_FLAG_SIMPLE | DP_TX_DESC_FLAG_RMNET)))) 2132 return dp_tx_nbuf_unmap_regular(soc, desc); 2133 } 2134 #else 2135 static inline 2136 qdf_dma_addr_t dp_tx_nbuf_map(struct dp_vdev *vdev, 2137 struct dp_tx_desc_s *tx_desc, 2138 qdf_nbuf_t nbuf) 2139 { 2140 return dp_tx_nbuf_map_regular(vdev, tx_desc, nbuf); 2141 } 2142 2143 static inline 2144 void dp_tx_nbuf_unmap(struct dp_soc *soc, 2145 struct dp_tx_desc_s *desc) 2146 { 2147 return dp_tx_nbuf_unmap_regular(soc, desc); 2148 } 2149 #endif 2150 2151 #if defined(WLAN_TX_PKT_CAPTURE_ENH) || defined(FEATURE_PERPKT_INFO) 2152 static inline 2153 void dp_tx_enh_unmap(struct dp_soc *soc, struct dp_tx_desc_s *desc) 2154 { 2155 if (qdf_likely(!(desc->flags & DP_TX_DESC_FLAG_UNMAP_DONE))) { 2156 dp_tx_nbuf_unmap(soc, desc); 2157 desc->flags |= DP_TX_DESC_FLAG_UNMAP_DONE; 2158 } 2159 } 2160 2161 static inline void dp_tx_unmap(struct dp_soc *soc, struct dp_tx_desc_s *desc) 2162 { 2163 if (qdf_likely(!(desc->flags & DP_TX_DESC_FLAG_UNMAP_DONE))) 2164 dp_tx_nbuf_unmap(soc, desc); 2165 } 2166 #else 2167 static inline 2168 void dp_tx_enh_unmap(struct dp_soc *soc, struct dp_tx_desc_s *desc) 2169 { 2170 } 2171 2172 static inline void dp_tx_unmap(struct dp_soc *soc, struct dp_tx_desc_s *desc) 2173 { 2174 dp_tx_nbuf_unmap(soc, desc); 2175 } 2176 #endif 2177 2178 #ifdef MESH_MODE_SUPPORT 2179 /** 2180 * dp_tx_update_mesh_flags() - Update descriptor flags for mesh VAP 2181 * @soc: datapath SOC 2182 * @vdev: datapath vdev 2183 * @tx_desc: TX descriptor 2184 * 2185 * Return: None 2186 */ 2187 static inline void dp_tx_update_mesh_flags(struct dp_soc *soc, 2188 struct dp_vdev *vdev, 2189 struct dp_tx_desc_s *tx_desc) 2190 { 2191 if (qdf_unlikely(vdev->mesh_vdev)) 2192 tx_desc->flags |= DP_TX_DESC_FLAG_MESH_MODE; 2193 } 2194 2195 /** 2196 * dp_mesh_tx_comp_free_buff() - Free the mesh tx packet buffer 2197 * @soc: dp_soc handle 2198 * @tx_desc: TX descriptor 2199 * @delayed_free: delay the nbuf free 2200 * 2201 * Return: nbuf to be freed late 2202 */ 2203 static inline qdf_nbuf_t dp_mesh_tx_comp_free_buff(struct dp_soc *soc, 2204 struct dp_tx_desc_s *tx_desc, 2205 bool delayed_free) 2206 { 2207 qdf_nbuf_t nbuf = tx_desc->nbuf; 2208 struct dp_vdev *vdev = NULL; 2209 uint8_t xmit_type = qdf_nbuf_get_vdev_xmit_type(nbuf); 2210 2211 vdev = dp_vdev_get_ref_by_id(soc, tx_desc->vdev_id, DP_MOD_ID_MESH); 2212 if (tx_desc->flags & DP_TX_DESC_FLAG_TO_FW) { 2213 if (vdev) 2214 DP_STATS_INC(vdev, 2215 tx_i[xmit_type].mesh.completion_fw, 1); 2216 2217 if (delayed_free) 2218 return nbuf; 2219 2220 qdf_nbuf_free(nbuf); 2221 } else { 2222 if (vdev && vdev->osif_tx_free_ext) { 2223 vdev->osif_tx_free_ext((nbuf)); 2224 } else { 2225 if (delayed_free) 2226 return nbuf; 2227 2228 qdf_nbuf_free(nbuf); 2229 } 2230 } 2231 2232 if (vdev) 2233 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_MESH); 2234 2235 return NULL; 2236 } 2237 #else 2238 static inline void dp_tx_update_mesh_flags(struct dp_soc *soc, 2239 struct dp_vdev *vdev, 2240 struct dp_tx_desc_s *tx_desc) 2241 { 2242 } 2243 2244 static inline qdf_nbuf_t dp_mesh_tx_comp_free_buff(struct dp_soc *soc, 2245 struct dp_tx_desc_s *tx_desc, 2246 bool delayed_free) 2247 { 2248 return NULL; 2249 } 2250 #endif 2251 2252 int dp_tx_frame_is_drop(struct dp_vdev *vdev, uint8_t *srcmac, uint8_t *dstmac) 2253 { 2254 struct dp_pdev *pdev = NULL; 2255 struct dp_ast_entry *src_ast_entry = NULL; 2256 struct dp_ast_entry *dst_ast_entry = NULL; 2257 struct dp_soc *soc = NULL; 2258 2259 qdf_assert(vdev); 2260 pdev = vdev->pdev; 2261 qdf_assert(pdev); 2262 soc = pdev->soc; 2263 2264 dst_ast_entry = dp_peer_ast_hash_find_by_pdevid 2265 (soc, dstmac, vdev->pdev->pdev_id); 2266 2267 src_ast_entry = dp_peer_ast_hash_find_by_pdevid 2268 (soc, srcmac, vdev->pdev->pdev_id); 2269 if (dst_ast_entry && src_ast_entry) { 2270 if (dst_ast_entry->peer_id == 2271 src_ast_entry->peer_id) 2272 return 1; 2273 } 2274 2275 return 0; 2276 } 2277 2278 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) && \ 2279 defined(WLAN_MCAST_MLO) 2280 /* MLO peer id for reinject*/ 2281 #define DP_MLO_MCAST_REINJECT_PEER_ID 0XFFFD 2282 /* MLO vdev id inc offset */ 2283 #define DP_MLO_VDEV_ID_OFFSET 0x80 2284 2285 #ifdef QCA_SUPPORT_WDS_EXTENDED 2286 static inline bool 2287 dp_tx_wds_ext_check(struct cdp_tx_exception_metadata *tx_exc_metadata) 2288 { 2289 if (tx_exc_metadata && tx_exc_metadata->is_wds_extended) 2290 return true; 2291 2292 return false; 2293 } 2294 #else 2295 static inline bool 2296 dp_tx_wds_ext_check(struct cdp_tx_exception_metadata *tx_exc_metadata) 2297 { 2298 return false; 2299 } 2300 #endif 2301 2302 static inline void 2303 dp_tx_bypass_reinjection(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc, 2304 struct cdp_tx_exception_metadata *tx_exc_metadata) 2305 { 2306 /* wds ext enabled will not set the TO_FW bit */ 2307 if (dp_tx_wds_ext_check(tx_exc_metadata)) 2308 return; 2309 2310 if (!(tx_desc->flags & DP_TX_DESC_FLAG_TO_FW)) { 2311 tx_desc->flags |= DP_TX_DESC_FLAG_TO_FW; 2312 qdf_atomic_inc(&soc->num_tx_exception); 2313 } 2314 } 2315 2316 static inline void 2317 dp_tx_update_mcast_param(uint16_t peer_id, 2318 uint16_t *htt_tcl_metadata, 2319 struct dp_vdev *vdev, 2320 struct dp_tx_msdu_info_s *msdu_info) 2321 { 2322 if (peer_id == DP_MLO_MCAST_REINJECT_PEER_ID) { 2323 *htt_tcl_metadata = 0; 2324 DP_TX_TCL_METADATA_TYPE_SET( 2325 *htt_tcl_metadata, 2326 HTT_TCL_METADATA_V2_TYPE_GLOBAL_SEQ_BASED); 2327 HTT_TX_TCL_METADATA_GLBL_SEQ_NO_SET(*htt_tcl_metadata, 2328 msdu_info->gsn); 2329 2330 msdu_info->vdev_id = vdev->vdev_id + DP_MLO_VDEV_ID_OFFSET; 2331 HTT_TX_TCL_METADATA_GLBL_SEQ_HOST_INSPECTED_SET( 2332 *htt_tcl_metadata, 1); 2333 } else { 2334 msdu_info->vdev_id = vdev->vdev_id; 2335 } 2336 } 2337 #else 2338 static inline void 2339 dp_tx_bypass_reinjection(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc, 2340 struct cdp_tx_exception_metadata *tx_exc_metadata) 2341 { 2342 } 2343 2344 static inline void 2345 dp_tx_update_mcast_param(uint16_t peer_id, 2346 uint16_t *htt_tcl_metadata, 2347 struct dp_vdev *vdev, 2348 struct dp_tx_msdu_info_s *msdu_info) 2349 { 2350 } 2351 #endif 2352 2353 #ifdef DP_TX_SW_DROP_STATS_INC 2354 static void tx_sw_drop_stats_inc(struct dp_pdev *pdev, 2355 qdf_nbuf_t nbuf, 2356 enum cdp_tx_sw_drop drop_code) 2357 { 2358 /* EAPOL Drop stats */ 2359 if (qdf_nbuf_is_ipv4_eapol_pkt(nbuf)) { 2360 switch (drop_code) { 2361 case TX_DESC_ERR: 2362 DP_STATS_INC(pdev, eap_drop_stats.tx_desc_err, 1); 2363 break; 2364 case TX_HAL_RING_ACCESS_ERR: 2365 DP_STATS_INC(pdev, 2366 eap_drop_stats.tx_hal_ring_access_err, 1); 2367 break; 2368 case TX_DMA_MAP_ERR: 2369 DP_STATS_INC(pdev, eap_drop_stats.tx_dma_map_err, 1); 2370 break; 2371 case TX_HW_ENQUEUE: 2372 DP_STATS_INC(pdev, eap_drop_stats.tx_hw_enqueue, 1); 2373 break; 2374 case TX_SW_ENQUEUE: 2375 DP_STATS_INC(pdev, eap_drop_stats.tx_sw_enqueue, 1); 2376 break; 2377 default: 2378 dp_info_rl("Invalid eapol_drop code: %d", drop_code); 2379 break; 2380 } 2381 } 2382 } 2383 #else 2384 static void tx_sw_drop_stats_inc(struct dp_pdev *pdev, 2385 qdf_nbuf_t nbuf, 2386 enum cdp_tx_sw_drop drop_code) 2387 { 2388 } 2389 #endif 2390 2391 #ifdef WLAN_FEATURE_TX_LATENCY_STATS 2392 /** 2393 * dp_tx_latency_stats_enabled() - check enablement of transmit latency 2394 * statistics 2395 * @vdev: DP vdev handle 2396 * 2397 * Return: true if transmit latency statistics is enabled, false otherwise. 2398 */ 2399 static inline bool dp_tx_latency_stats_enabled(struct dp_vdev *vdev) 2400 { 2401 return qdf_atomic_read(&vdev->tx_latency_cfg.enabled); 2402 } 2403 2404 /** 2405 * dp_tx_latency_stats_report_enabled() - check enablement of async report 2406 * for transmit latency statistics 2407 * @vdev: DP vdev handle 2408 * 2409 * Return: true if transmit latency statistics is enabled, false otherwise. 2410 */ 2411 static inline bool dp_tx_latency_stats_report_enabled(struct dp_vdev *vdev) 2412 { 2413 return qdf_atomic_read(&vdev->tx_latency_cfg.report); 2414 } 2415 2416 /** 2417 * dp_tx_get_driver_ingress_ts() - get driver ingress timestamp from nbuf 2418 * @vdev: DP vdev handle 2419 * @msdu_info: pointer to MSDU Descriptor 2420 * @nbuf: original buffer from network stack 2421 * 2422 * Return: None 2423 */ 2424 static inline void 2425 dp_tx_get_driver_ingress_ts(struct dp_vdev *vdev, 2426 struct dp_tx_msdu_info_s *msdu_info, 2427 qdf_nbuf_t nbuf) 2428 { 2429 if (!dp_tx_latency_stats_enabled(vdev)) 2430 return; 2431 2432 msdu_info->driver_ingress_ts = qdf_nbuf_get_tx_ts(nbuf, true); 2433 } 2434 2435 /** 2436 * dp_tx_update_ts_on_enqueued() - set driver ingress/egress timestamp in 2437 * tx descriptor 2438 * @vdev: DP vdev handle 2439 * @msdu_info: pointer to MSDU Descriptor 2440 * @tx_desc: pointer to tx descriptor 2441 * 2442 * Return: None 2443 */ 2444 static inline void 2445 dp_tx_update_ts_on_enqueued(struct dp_vdev *vdev, 2446 struct dp_tx_msdu_info_s *msdu_info, 2447 struct dp_tx_desc_s *tx_desc) 2448 { 2449 if (!dp_tx_latency_stats_enabled(vdev)) 2450 return; 2451 2452 tx_desc->driver_ingress_ts = msdu_info->driver_ingress_ts; 2453 tx_desc->driver_egress_ts = qdf_ktime_real_get(); 2454 } 2455 2456 /** 2457 * dp_tx_latency_stats_update_bucket() - update transmit latency statistics 2458 * for specified type 2459 * @vdev: DP vdev handle 2460 * @tx_latency: pointer to transmit latency stats 2461 * @idx: index of the statistics 2462 * @type: transmit latency type 2463 * @value: latency to be recorded 2464 * 2465 * Return: None 2466 */ 2467 static inline void 2468 dp_tx_latency_stats_update_bucket(struct dp_vdev *vdev, 2469 struct dp_tx_latency *tx_latency, 2470 int idx, enum cdp_tx_latency_type type, 2471 uint32_t value) 2472 { 2473 int32_t granularity; 2474 int lvl; 2475 2476 granularity = 2477 qdf_atomic_read(&vdev->tx_latency_cfg.granularity[type]); 2478 if (qdf_unlikely(!granularity)) 2479 return; 2480 2481 lvl = value / granularity; 2482 if (lvl >= CDP_TX_LATENCY_DISTR_LV_MAX) 2483 lvl = CDP_TX_LATENCY_DISTR_LV_MAX - 1; 2484 2485 qdf_atomic_inc(&tx_latency->stats[idx][type].msdus_accum); 2486 qdf_atomic_add(value, &tx_latency->stats[idx][type].latency_accum); 2487 qdf_atomic_inc(&tx_latency->stats[idx][type].distribution[lvl]); 2488 } 2489 2490 /** 2491 * dp_tx_latency_stats_update() - update transmit latency statistics on 2492 * msdu transmit completed 2493 * @soc: dp soc handle 2494 * @txrx_peer: txrx peer handle 2495 * @tx_desc: pointer to tx descriptor 2496 * @ts: tx completion status 2497 * @link_id: link id 2498 * 2499 * Return: None 2500 */ 2501 static inline void 2502 dp_tx_latency_stats_update(struct dp_soc *soc, 2503 struct dp_txrx_peer *txrx_peer, 2504 struct dp_tx_desc_s *tx_desc, 2505 struct hal_tx_completion_status *ts, 2506 uint8_t link_id) 2507 { 2508 uint32_t driver_latency, ring_buf_latency, hw_latency; 2509 QDF_STATUS status = QDF_STATUS_E_INVAL; 2510 int64_t current_ts, ingress, egress; 2511 struct dp_vdev *vdev = txrx_peer->vdev; 2512 struct dp_tx_latency *tx_latency; 2513 uint8_t idx; 2514 2515 if (!dp_tx_latency_stats_enabled(vdev)) 2516 return; 2517 2518 if (!tx_desc->driver_ingress_ts || !tx_desc->driver_egress_ts) 2519 return; 2520 2521 status = dp_tx_compute_hw_delay_us(ts, vdev->delta_tsf, &hw_latency); 2522 if (QDF_IS_STATUS_ERROR(status)) 2523 return; 2524 2525 ingress = qdf_ktime_to_us(tx_desc->driver_ingress_ts); 2526 egress = qdf_ktime_to_us(tx_desc->driver_egress_ts); 2527 driver_latency = (uint32_t)(egress - ingress); 2528 2529 current_ts = qdf_ktime_to_us(qdf_ktime_real_get()); 2530 ring_buf_latency = (uint32_t)(current_ts - egress); 2531 2532 tx_latency = &txrx_peer->stats[link_id].tx_latency; 2533 idx = tx_latency->cur_idx; 2534 dp_tx_latency_stats_update_bucket(txrx_peer->vdev, tx_latency, idx, 2535 CDP_TX_LATENCY_TYPE_DRIVER, 2536 driver_latency); 2537 dp_tx_latency_stats_update_bucket(txrx_peer->vdev, tx_latency, idx, 2538 CDP_TX_LATENCY_TYPE_RING_BUF, 2539 ring_buf_latency); 2540 dp_tx_latency_stats_update_bucket(txrx_peer->vdev, tx_latency, idx, 2541 CDP_TX_LATENCY_TYPE_HW, hw_latency); 2542 } 2543 2544 /** 2545 * dp_tx_latency_stats_clear_bucket() - clear specified transmit latency 2546 * statistics for specified type 2547 * @tx_latency: pointer to transmit latency stats 2548 * @idx: index of the statistics 2549 * @type: transmit latency type 2550 * 2551 * Return: None 2552 */ 2553 static inline void 2554 dp_tx_latency_stats_clear_bucket(struct dp_tx_latency *tx_latency, 2555 int idx, enum cdp_tx_latency_type type) 2556 { 2557 int lvl; 2558 struct dp_tx_latency_stats *stats; 2559 2560 stats = &tx_latency->stats[idx][type]; 2561 qdf_atomic_init(&stats->msdus_accum); 2562 qdf_atomic_init(&stats->latency_accum); 2563 for (lvl = 0; lvl < CDP_TX_LATENCY_DISTR_LV_MAX; lvl++) 2564 qdf_atomic_init(&stats->distribution[lvl]); 2565 } 2566 2567 /** 2568 * dp_tx_latency_stats_clear_buckets() - clear specified transmit latency 2569 * statistics 2570 * @tx_latency: pointer to transmit latency stats 2571 * @idx: index of the statistics 2572 * 2573 * Return: None 2574 */ 2575 static void 2576 dp_tx_latency_stats_clear_buckets(struct dp_tx_latency *tx_latency, 2577 int idx) 2578 { 2579 int type; 2580 2581 for (type = 0; type < CDP_TX_LATENCY_TYPE_MAX; type++) 2582 dp_tx_latency_stats_clear_bucket(tx_latency, idx, type); 2583 } 2584 2585 /** 2586 * dp_tx_latency_stats_update_cca() - update transmit latency statistics for 2587 * CCA 2588 * @soc: dp soc handle 2589 * @peer_id: peer id 2590 * @granularity: granularity of distribution 2591 * @distribution: distribution of transmit latency statistics 2592 * @avg: average of CCA latency(in microseconds) within a cycle 2593 * 2594 * Return: None 2595 */ 2596 void 2597 dp_tx_latency_stats_update_cca(struct dp_soc *soc, uint16_t peer_id, 2598 uint32_t granularity, uint32_t *distribution, 2599 uint32_t avg) 2600 { 2601 int lvl, idx; 2602 uint8_t link_id; 2603 struct dp_tx_latency *tx_latency; 2604 struct dp_tx_latency_stats *stats; 2605 int32_t cur_granularity; 2606 struct dp_vdev *vdev; 2607 struct dp_tx_latency_config *cfg; 2608 struct dp_txrx_peer *txrx_peer; 2609 struct dp_peer *peer; 2610 2611 peer = dp_peer_get_ref_by_id(soc, peer_id, DP_MOD_ID_HTT); 2612 if (!peer) { 2613 dp_err_rl("Peer not found peer id %d", peer_id); 2614 return; 2615 } 2616 2617 if (IS_MLO_DP_MLD_PEER(peer)) 2618 goto out; 2619 2620 vdev = peer->vdev; 2621 if (!dp_tx_latency_stats_enabled(vdev)) 2622 goto out; 2623 2624 cfg = &vdev->tx_latency_cfg; 2625 cur_granularity = 2626 qdf_atomic_read(&cfg->granularity[CDP_TX_LATENCY_TYPE_CCA]); 2627 2628 /* in unit of ms */ 2629 cur_granularity /= 1000; 2630 if (cur_granularity != granularity) { 2631 dp_info_rl("invalid granularity, cur %d report %d", 2632 cur_granularity, granularity); 2633 goto out; 2634 } 2635 2636 txrx_peer = dp_get_txrx_peer(peer); 2637 if (qdf_unlikely(!txrx_peer)) { 2638 dp_err_rl("txrx_peer NULL for MAC: " QDF_MAC_ADDR_FMT, 2639 QDF_MAC_ADDR_REF(peer->mac_addr.raw)); 2640 goto out; 2641 } 2642 2643 link_id = dp_get_peer_link_id(peer); 2644 if (link_id >= txrx_peer->stats_arr_size) 2645 goto out; 2646 2647 tx_latency = &txrx_peer->stats[link_id].tx_latency; 2648 idx = tx_latency->cur_idx; 2649 stats = &tx_latency->stats[idx][CDP_TX_LATENCY_TYPE_CCA]; 2650 qdf_atomic_set(&stats->latency_accum, avg); 2651 qdf_atomic_set(&stats->msdus_accum, (avg ? 1 : 0)); 2652 for (lvl = 0; lvl < CDP_TX_LATENCY_DISTR_LV_MAX; lvl++) 2653 qdf_atomic_set(&stats->distribution[lvl], 2654 distribution[lvl]); 2655 2656 /* prepare for the next cycle */ 2657 tx_latency->cur_idx = 1 - idx; 2658 dp_tx_latency_stats_clear_buckets(tx_latency, tx_latency->cur_idx); 2659 2660 out: 2661 dp_peer_unref_delete(peer, DP_MOD_ID_HTT); 2662 } 2663 2664 /** 2665 * dp_tx_latency_stats_get_per_peer() - get transmit latency statistics for a 2666 * peer 2667 * @soc: dp soc handle 2668 * @peer: dp peer Handle 2669 * @latency: buffer to hold transmit latency statistics 2670 * 2671 * Return: QDF_STATUS 2672 */ 2673 static QDF_STATUS 2674 dp_tx_latency_stats_get_per_peer(struct dp_soc *soc, struct dp_peer *peer, 2675 struct cdp_tx_latency *latency) 2676 { 2677 int lvl, type, link_id; 2678 int32_t latency_accum, msdus_accum; 2679 struct dp_vdev *vdev; 2680 struct dp_txrx_peer *txrx_peer; 2681 struct dp_tx_latency *tx_latency; 2682 struct dp_tx_latency_config *cfg; 2683 struct dp_tx_latency_stats *stats; 2684 uint8_t last_idx; 2685 2686 if (unlikely(!latency)) 2687 return QDF_STATUS_E_INVAL; 2688 2689 /* Authenticated link/legacy peer only */ 2690 if (IS_MLO_DP_MLD_PEER(peer) || peer->state != OL_TXRX_PEER_STATE_AUTH) 2691 return QDF_STATUS_E_INVAL; 2692 2693 vdev = peer->vdev; 2694 if (peer->bss_peer && vdev->opmode == wlan_op_mode_ap) 2695 return QDF_STATUS_E_INVAL; 2696 2697 txrx_peer = dp_get_txrx_peer(peer); 2698 if (!txrx_peer) 2699 return QDF_STATUS_E_INVAL; 2700 2701 link_id = dp_get_peer_link_id(peer); 2702 if (link_id >= txrx_peer->stats_arr_size) 2703 return QDF_STATUS_E_INVAL; 2704 2705 tx_latency = &txrx_peer->stats[link_id].tx_latency; 2706 qdf_mem_zero(latency, sizeof(*latency)); 2707 qdf_mem_copy(latency->mac_remote.bytes, 2708 peer->mac_addr.raw, QDF_MAC_ADDR_SIZE); 2709 last_idx = 1 - tx_latency->cur_idx; 2710 cfg = &vdev->tx_latency_cfg; 2711 for (type = 0; type < CDP_TX_LATENCY_TYPE_MAX; type++) { 2712 latency->stats[type].granularity = 2713 qdf_atomic_read(&cfg->granularity[type]); 2714 stats = &tx_latency->stats[last_idx][type]; 2715 msdus_accum = qdf_atomic_read(&stats->msdus_accum); 2716 if (!msdus_accum) 2717 continue; 2718 2719 latency_accum = qdf_atomic_read(&stats->latency_accum); 2720 latency->stats[type].average = latency_accum / msdus_accum; 2721 for (lvl = 0; lvl < CDP_TX_LATENCY_DISTR_LV_MAX; lvl++) { 2722 latency->stats[type].distribution[lvl] = 2723 qdf_atomic_read(&stats->distribution[lvl]); 2724 } 2725 } 2726 2727 return QDF_STATUS_SUCCESS; 2728 } 2729 2730 /** 2731 * dp_tx_latency_stats_get_peer_iter() - iterator to get transmit latency 2732 * statistics for specified peer 2733 * @soc: dp soc handle 2734 * @peer: dp peer Handle 2735 * @arg: list to hold transmit latency statistics for peers 2736 * 2737 * Return: None 2738 */ 2739 static void 2740 dp_tx_latency_stats_get_peer_iter(struct dp_soc *soc, 2741 struct dp_peer *peer, 2742 void *arg) 2743 { 2744 struct dp_vdev *vdev; 2745 struct dp_txrx_peer *txrx_peer; 2746 struct cdp_tx_latency *latency; 2747 QDF_STATUS status; 2748 qdf_list_t *stats_list = (qdf_list_t *)arg; 2749 2750 /* Authenticated link/legacy peer only */ 2751 if (IS_MLO_DP_MLD_PEER(peer) || peer->state != OL_TXRX_PEER_STATE_AUTH) 2752 return; 2753 2754 txrx_peer = dp_get_txrx_peer(peer); 2755 if (!txrx_peer) 2756 return; 2757 2758 vdev = peer->vdev; 2759 latency = qdf_mem_malloc(sizeof(*latency)); 2760 if (!latency) 2761 return; 2762 2763 status = dp_tx_latency_stats_get_per_peer(soc, peer, latency); 2764 if (QDF_IS_STATUS_ERROR(status)) 2765 goto out; 2766 2767 status = qdf_list_insert_back(stats_list, &latency->node); 2768 if (QDF_IS_STATUS_ERROR(status)) 2769 goto out; 2770 2771 return; 2772 2773 out: 2774 qdf_mem_free(latency); 2775 } 2776 2777 /** 2778 * dp_tx_latency_stats_rpt_per_vdev() - report transmit latency statistics for 2779 * specified vdev 2780 * @soc: dp soc handle 2781 * @vdev: dp vdev Handle 2782 * 2783 * Return: None 2784 */ 2785 static void 2786 dp_tx_latency_stats_rpt_per_vdev(struct dp_soc *soc, struct dp_vdev *vdev) 2787 { 2788 qdf_list_t stats_list; 2789 struct cdp_tx_latency *entry, *next; 2790 2791 if (!soc->tx_latency_cb || !dp_tx_latency_stats_report_enabled(vdev)) 2792 return; 2793 2794 qdf_list_create(&stats_list, 0); 2795 dp_vdev_iterate_peer(vdev, dp_tx_latency_stats_get_peer_iter, 2796 &stats_list, DP_MOD_ID_CDP); 2797 if (qdf_list_empty(&stats_list)) 2798 goto out; 2799 2800 soc->tx_latency_cb(vdev->vdev_id, &stats_list); 2801 2802 qdf_list_for_each_del(&stats_list, entry, next, node) { 2803 qdf_list_remove_node(&stats_list, &entry->node); 2804 qdf_mem_free(entry); 2805 } 2806 2807 out: 2808 qdf_list_destroy(&stats_list); 2809 } 2810 2811 /** 2812 * dp_tx_latency_stats_report() - report transmit latency statistics for each 2813 * vdev of specified pdev 2814 * @soc: dp soc handle 2815 * @pdev: dp pdev Handle 2816 * 2817 * Return: None 2818 */ 2819 void dp_tx_latency_stats_report(struct dp_soc *soc, struct dp_pdev *pdev) 2820 { 2821 struct dp_vdev *vdev; 2822 2823 if (!soc->tx_latency_cb) 2824 return; 2825 2826 qdf_spin_lock_bh(&pdev->vdev_list_lock); 2827 DP_PDEV_ITERATE_VDEV_LIST(pdev, vdev) { 2828 dp_tx_latency_stats_rpt_per_vdev(soc, vdev); 2829 } 2830 2831 qdf_spin_unlock_bh(&pdev->vdev_list_lock); 2832 } 2833 2834 /** 2835 * dp_tx_latency_stats_clear_per_peer() - iterator to clear transmit latency 2836 * statistics for specified peer 2837 * @soc: dp soc handle 2838 * @peer: dp pdev Handle 2839 * @arg: argument from iterator 2840 * 2841 * Return: None 2842 */ 2843 static void 2844 dp_tx_latency_stats_clear_per_peer(struct dp_soc *soc, struct dp_peer *peer, 2845 void *arg) 2846 { 2847 int link_id; 2848 struct dp_tx_latency *tx_latency; 2849 struct dp_txrx_peer *txrx_peer = dp_get_txrx_peer(peer); 2850 2851 if (!txrx_peer) { 2852 dp_err("no txrx peer, skip"); 2853 return; 2854 } 2855 2856 for (link_id = 0; link_id < txrx_peer->stats_arr_size; link_id++) { 2857 tx_latency = &txrx_peer->stats[link_id].tx_latency; 2858 dp_tx_latency_stats_clear_buckets(tx_latency, 0); 2859 dp_tx_latency_stats_clear_buckets(tx_latency, 1); 2860 } 2861 } 2862 2863 /** 2864 * dp_tx_latency_stats_clear_per_vdev() - clear transmit latency statistics 2865 * for specified vdev 2866 * @vdev: dp vdev handle 2867 * 2868 * Return: None 2869 */ 2870 static inline void dp_tx_latency_stats_clear_per_vdev(struct dp_vdev *vdev) 2871 { 2872 dp_vdev_iterate_peer(vdev, dp_tx_latency_stats_clear_per_peer, 2873 NULL, DP_MOD_ID_CDP); 2874 } 2875 2876 /** 2877 * dp_tx_latency_stats_fetch() - fetch transmit latency statistics for 2878 * specified link mac address 2879 * @soc_hdl: Handle to struct dp_soc 2880 * @vdev_id: vdev id 2881 * @mac: link mac address of remote peer 2882 * @latency: buffer to hold per-link transmit latency statistics 2883 * 2884 * Return: QDF_STATUS 2885 */ 2886 QDF_STATUS 2887 dp_tx_latency_stats_fetch(struct cdp_soc_t *soc_hdl, 2888 uint8_t vdev_id, uint8_t *mac, 2889 struct cdp_tx_latency *latency) 2890 { 2891 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); 2892 struct cdp_peer_info peer_info = {0}; 2893 struct dp_peer *peer; 2894 QDF_STATUS status; 2895 2896 /* MAC addr of link peer may be the same as MLD peer, 2897 * so specify the type as CDP_LINK_PEER_TYPE here to 2898 * get link peer explicitly. 2899 */ 2900 DP_PEER_INFO_PARAMS_INIT(&peer_info, vdev_id, mac, false, 2901 CDP_LINK_PEER_TYPE); 2902 peer = dp_peer_hash_find_wrapper(soc, &peer_info, DP_MOD_ID_CDP); 2903 if (!peer) { 2904 dp_err_rl("peer(vdev id %d mac " QDF_MAC_ADDR_FMT ") not found", 2905 vdev_id, QDF_MAC_ADDR_REF(mac)); 2906 return QDF_STATUS_E_INVAL; 2907 } 2908 2909 status = dp_tx_latency_stats_get_per_peer(soc, peer, latency); 2910 dp_peer_unref_delete(peer, DP_MOD_ID_CDP); 2911 return status; 2912 } 2913 2914 /** 2915 * dp_tx_latency_stats_config() - config transmit latency statistics for 2916 * specified vdev 2917 * @soc_hdl: Handle to struct dp_soc 2918 * @vdev_id: vdev id 2919 * @cfg: configuration for transmit latency statistics 2920 * 2921 * Return: QDF_STATUS 2922 */ 2923 QDF_STATUS 2924 dp_tx_latency_stats_config(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, 2925 struct cdp_tx_latency_config *cfg) 2926 { 2927 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); 2928 struct dp_vdev *vdev; 2929 QDF_STATUS status = QDF_STATUS_E_INVAL; 2930 uint32_t cca_granularity; 2931 int type; 2932 2933 vdev = dp_vdev_get_ref_by_id(soc, vdev_id, DP_MOD_ID_CDP); 2934 if (!vdev) { 2935 dp_err_rl("vdev %d does not exist", vdev_id); 2936 return QDF_STATUS_E_FAILURE; 2937 } 2938 2939 /* disable to ignore upcoming updates */ 2940 qdf_atomic_set(&vdev->tx_latency_cfg.enabled, 0); 2941 dp_tx_latency_stats_clear_per_vdev(vdev); 2942 2943 if (!cfg->enable) 2944 goto send_htt; 2945 2946 qdf_atomic_set(&vdev->tx_latency_cfg.report, (cfg->report ? 1 : 0)); 2947 for (type = 0; type < CDP_TX_LATENCY_TYPE_MAX; type++) 2948 qdf_atomic_set(&vdev->tx_latency_cfg.granularity[type], 2949 cfg->granularity[type]); 2950 2951 send_htt: 2952 /* in units of ms */ 2953 cca_granularity = cfg->granularity[CDP_TX_LATENCY_TYPE_CCA] / 1000; 2954 status = dp_h2t_tx_latency_stats_cfg_msg_send(soc, vdev_id, 2955 cfg->enable, cfg->period, 2956 cca_granularity); 2957 if (QDF_IS_STATUS_ERROR(status)) { 2958 dp_err_rl("failed to send htt msg: %d", status); 2959 goto out; 2960 } 2961 2962 qdf_atomic_set(&vdev->tx_latency_cfg.enabled, (cfg->enable ? 1 : 0)); 2963 2964 out: 2965 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP); 2966 return status; 2967 } 2968 2969 /** 2970 * dp_tx_latency_stats_register_cb() - register transmit latency statistics 2971 * callback 2972 * @handle: Handle to struct dp_soc 2973 * @cb: callback function for transmit latency statistics 2974 * 2975 * Return: QDF_STATUS 2976 */ 2977 QDF_STATUS 2978 dp_tx_latency_stats_register_cb(struct cdp_soc_t *handle, cdp_tx_latency_cb cb) 2979 { 2980 struct dp_soc *soc = (struct dp_soc *)handle; 2981 2982 if (!soc || !cb) { 2983 dp_err("soc or cb is NULL"); 2984 return QDF_STATUS_E_INVAL; 2985 } 2986 2987 soc->tx_latency_cb = cb; 2988 return QDF_STATUS_SUCCESS; 2989 } 2990 2991 #else 2992 static inline void 2993 dp_tx_get_driver_ingress_ts(struct dp_vdev *vdev, 2994 struct dp_tx_msdu_info_s *msdu_info, 2995 qdf_nbuf_t nbuf) 2996 { 2997 } 2998 2999 static inline void 3000 dp_tx_update_ts_on_enqueued(struct dp_vdev *vdev, 3001 struct dp_tx_msdu_info_s *msdu_info, 3002 struct dp_tx_desc_s *tx_desc) 3003 { 3004 } 3005 3006 static inline void 3007 dp_tx_latency_stats_update(struct dp_soc *soc, 3008 struct dp_txrx_peer *txrx_peer, 3009 struct dp_tx_desc_s *tx_desc, 3010 struct hal_tx_completion_status *ts, 3011 uint8_t link_id) 3012 { 3013 } 3014 #endif 3015 3016 qdf_nbuf_t 3017 dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf, 3018 struct dp_tx_msdu_info_s *msdu_info, uint16_t peer_id, 3019 struct cdp_tx_exception_metadata *tx_exc_metadata) 3020 { 3021 struct dp_pdev *pdev = vdev->pdev; 3022 struct dp_soc *soc = pdev->soc; 3023 struct dp_tx_desc_s *tx_desc; 3024 QDF_STATUS status; 3025 struct dp_tx_queue *tx_q = &(msdu_info->tx_queue); 3026 uint16_t htt_tcl_metadata = 0; 3027 enum cdp_tx_sw_drop drop_code = TX_MAX_DROP; 3028 uint8_t tid = msdu_info->tid; 3029 struct cdp_tid_tx_stats *tid_stats = NULL; 3030 qdf_dma_addr_t paddr; 3031 3032 /* Setup Tx descriptor for an MSDU, and MSDU extension descriptor */ 3033 tx_desc = dp_tx_prepare_desc_single(vdev, nbuf, tx_q->desc_pool_id, 3034 msdu_info, tx_exc_metadata); 3035 if (!tx_desc) { 3036 dp_err_rl("Tx_desc prepare Fail vdev_id %d vdev %pK queue %d", 3037 vdev->vdev_id, vdev, tx_q->desc_pool_id); 3038 drop_code = TX_DESC_ERR; 3039 goto fail_return; 3040 } 3041 3042 dp_tx_update_tdls_flags(soc, vdev, tx_desc); 3043 3044 if (qdf_unlikely(peer_id == DP_INVALID_PEER)) { 3045 htt_tcl_metadata = vdev->htt_tcl_metadata; 3046 DP_TX_TCL_METADATA_HOST_INSPECTED_SET(htt_tcl_metadata, 1); 3047 } else if (qdf_unlikely(peer_id != HTT_INVALID_PEER)) { 3048 DP_TX_TCL_METADATA_TYPE_SET(htt_tcl_metadata, 3049 DP_TCL_METADATA_TYPE_PEER_BASED); 3050 DP_TX_TCL_METADATA_PEER_ID_SET(htt_tcl_metadata, 3051 peer_id); 3052 dp_tx_bypass_reinjection(soc, tx_desc, tx_exc_metadata); 3053 } else 3054 htt_tcl_metadata = vdev->htt_tcl_metadata; 3055 3056 if (msdu_info->exception_fw) 3057 DP_TX_TCL_METADATA_VALID_HTT_SET(htt_tcl_metadata, 1); 3058 3059 dp_tx_desc_update_fast_comp_flag(soc, tx_desc, 3060 !pdev->enhanced_stats_en); 3061 3062 dp_tx_update_mesh_flags(soc, vdev, tx_desc); 3063 3064 if (qdf_unlikely(msdu_info->frm_type == dp_tx_frm_rmnet)) 3065 paddr = dp_tx_rmnet_nbuf_map(msdu_info, tx_desc); 3066 else 3067 paddr = dp_tx_nbuf_map(vdev, tx_desc, nbuf); 3068 3069 if (!paddr) { 3070 /* Handle failure */ 3071 dp_err("qdf_nbuf_map failed"); 3072 DP_STATS_INC(vdev, 3073 tx_i[msdu_info->xmit_type].dropped.dma_error, 1); 3074 drop_code = TX_DMA_MAP_ERR; 3075 goto release_desc; 3076 } 3077 3078 tx_desc->dma_addr = paddr; 3079 dp_tx_desc_history_add(soc, tx_desc->dma_addr, nbuf, 3080 tx_desc->id, DP_TX_DESC_MAP); 3081 dp_tx_update_mcast_param(peer_id, &htt_tcl_metadata, vdev, msdu_info); 3082 /* Enqueue the Tx MSDU descriptor to HW for transmit */ 3083 status = soc->arch_ops.tx_hw_enqueue(soc, vdev, tx_desc, 3084 htt_tcl_metadata, 3085 tx_exc_metadata, msdu_info); 3086 3087 if (status != QDF_STATUS_SUCCESS) { 3088 dp_tx_err_rl("Tx_hw_enqueue Fail tx_desc %pK queue %d", 3089 tx_desc, tx_q->ring_id); 3090 dp_tx_desc_history_add(soc, tx_desc->dma_addr, nbuf, 3091 tx_desc->id, DP_TX_DESC_UNMAP); 3092 dp_tx_nbuf_unmap(soc, tx_desc); 3093 drop_code = TX_HW_ENQUEUE; 3094 goto release_desc; 3095 } 3096 3097 dp_tx_update_ts_on_enqueued(vdev, msdu_info, tx_desc); 3098 3099 tx_sw_drop_stats_inc(pdev, nbuf, drop_code); 3100 return NULL; 3101 3102 release_desc: 3103 dp_tx_desc_release(soc, tx_desc, tx_q->desc_pool_id); 3104 3105 fail_return: 3106 dp_tx_get_tid(vdev, nbuf, msdu_info); 3107 tx_sw_drop_stats_inc(pdev, nbuf, drop_code); 3108 tid_stats = &pdev->stats.tid_stats. 3109 tid_tx_stats[tx_q->ring_id][tid]; 3110 tid_stats->swdrop_cnt[drop_code]++; 3111 return nbuf; 3112 } 3113 3114 /** 3115 * dp_tdls_tx_comp_free_buff() - Free non std buffer when TDLS flag is set 3116 * @soc: Soc handle 3117 * @desc: software Tx descriptor to be processed 3118 * 3119 * Return: 0 if Success 3120 */ 3121 #ifdef FEATURE_WLAN_TDLS 3122 static inline int 3123 dp_tdls_tx_comp_free_buff(struct dp_soc *soc, struct dp_tx_desc_s *desc) 3124 { 3125 /* If it is TDLS mgmt, don't unmap or free the frame */ 3126 if (desc->flags & DP_TX_DESC_FLAG_TDLS_FRAME) { 3127 dp_non_std_htt_tx_comp_free_buff(soc, desc); 3128 return 0; 3129 } 3130 return 1; 3131 } 3132 #else 3133 static inline int 3134 dp_tdls_tx_comp_free_buff(struct dp_soc *soc, struct dp_tx_desc_s *desc) 3135 { 3136 return 1; 3137 } 3138 #endif 3139 3140 qdf_nbuf_t dp_tx_comp_free_buf(struct dp_soc *soc, struct dp_tx_desc_s *desc, 3141 bool delayed_free) 3142 { 3143 qdf_nbuf_t nbuf = desc->nbuf; 3144 enum dp_tx_event_type type = dp_tx_get_event_type(desc->flags); 3145 3146 /* nbuf already freed in vdev detach path */ 3147 if (!nbuf) 3148 return NULL; 3149 3150 if (!dp_tdls_tx_comp_free_buff(soc, desc)) 3151 return NULL; 3152 3153 /* 0 : MSDU buffer, 1 : MLE */ 3154 if (desc->msdu_ext_desc) { 3155 /* TSO free */ 3156 if (hal_tx_ext_desc_get_tso_enable( 3157 desc->msdu_ext_desc->vaddr)) { 3158 dp_tx_desc_history_add(soc, desc->dma_addr, desc->nbuf, 3159 desc->id, DP_TX_COMP_MSDU_EXT); 3160 dp_tx_tso_seg_history_add(soc, 3161 desc->msdu_ext_desc->tso_desc, 3162 desc->nbuf, desc->id, type); 3163 /* unmap eash TSO seg before free the nbuf */ 3164 dp_tx_tso_unmap_segment(soc, 3165 desc->msdu_ext_desc->tso_desc, 3166 desc->msdu_ext_desc-> 3167 tso_num_desc); 3168 goto nbuf_free; 3169 } 3170 3171 if (qdf_unlikely(desc->frm_type == dp_tx_frm_sg)) { 3172 void *msdu_ext_desc = desc->msdu_ext_desc->vaddr; 3173 qdf_dma_addr_t iova; 3174 uint32_t frag_len; 3175 uint32_t i; 3176 3177 qdf_nbuf_unmap_nbytes_single(soc->osdev, nbuf, 3178 QDF_DMA_TO_DEVICE, 3179 qdf_nbuf_headlen(nbuf)); 3180 3181 for (i = 1; i < DP_TX_MAX_NUM_FRAGS; i++) { 3182 hal_tx_ext_desc_get_frag_info(msdu_ext_desc, i, 3183 &iova, 3184 &frag_len); 3185 if (!iova || !frag_len) 3186 break; 3187 3188 qdf_mem_unmap_page(soc->osdev, iova, frag_len, 3189 QDF_DMA_TO_DEVICE); 3190 } 3191 3192 goto nbuf_free; 3193 } 3194 } 3195 /* If it's ME frame, dont unmap the cloned nbuf's */ 3196 if ((desc->flags & DP_TX_DESC_FLAG_ME) && qdf_nbuf_is_cloned(nbuf)) 3197 goto nbuf_free; 3198 3199 dp_tx_desc_history_add(soc, desc->dma_addr, desc->nbuf, desc->id, type); 3200 dp_tx_unmap(soc, desc); 3201 3202 if (desc->flags & DP_TX_DESC_FLAG_MESH_MODE) 3203 return dp_mesh_tx_comp_free_buff(soc, desc, delayed_free); 3204 3205 if (dp_tx_traffic_end_indication_enq_ind_pkt(soc, desc, nbuf)) 3206 return NULL; 3207 3208 nbuf_free: 3209 if (delayed_free) 3210 return nbuf; 3211 3212 qdf_nbuf_free(nbuf); 3213 3214 return NULL; 3215 } 3216 3217 /** 3218 * dp_tx_sg_unmap_buf() - Unmap scatter gather fragments 3219 * @soc: DP soc handle 3220 * @nbuf: skb 3221 * @msdu_info: MSDU info 3222 * 3223 * Return: None 3224 */ 3225 static inline void 3226 dp_tx_sg_unmap_buf(struct dp_soc *soc, qdf_nbuf_t nbuf, 3227 struct dp_tx_msdu_info_s *msdu_info) 3228 { 3229 uint32_t cur_idx; 3230 struct dp_tx_seg_info_s *seg = msdu_info->u.sg_info.curr_seg; 3231 3232 qdf_nbuf_unmap_nbytes_single(soc->osdev, nbuf, QDF_DMA_TO_DEVICE, 3233 qdf_nbuf_headlen(nbuf)); 3234 3235 for (cur_idx = 1; cur_idx < seg->frag_cnt; cur_idx++) 3236 qdf_mem_unmap_page(soc->osdev, (qdf_dma_addr_t) 3237 (seg->frags[cur_idx].paddr_lo | ((uint64_t) 3238 seg->frags[cur_idx].paddr_hi) << 32), 3239 seg->frags[cur_idx].len, 3240 QDF_DMA_TO_DEVICE); 3241 } 3242 3243 #if QDF_LOCK_STATS 3244 noinline 3245 #else 3246 #endif 3247 qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf, 3248 struct dp_tx_msdu_info_s *msdu_info) 3249 { 3250 uint32_t i; 3251 struct dp_pdev *pdev = vdev->pdev; 3252 struct dp_soc *soc = pdev->soc; 3253 struct dp_tx_desc_s *tx_desc; 3254 bool is_cce_classified = false; 3255 QDF_STATUS status; 3256 uint16_t htt_tcl_metadata = 0; 3257 struct dp_tx_queue *tx_q = &msdu_info->tx_queue; 3258 struct cdp_tid_tx_stats *tid_stats = NULL; 3259 uint8_t prep_desc_fail = 0, hw_enq_fail = 0; 3260 3261 if (msdu_info->frm_type == dp_tx_frm_me) 3262 nbuf = msdu_info->u.sg_info.curr_seg->nbuf; 3263 3264 i = 0; 3265 /* Print statement to track i and num_seg */ 3266 /* 3267 * For each segment (maps to 1 MSDU) , prepare software and hardware 3268 * descriptors using information in msdu_info 3269 */ 3270 while (i < msdu_info->num_seg) { 3271 /* 3272 * Setup Tx descriptor for an MSDU, and MSDU extension 3273 * descriptor 3274 */ 3275 tx_desc = dp_tx_prepare_desc(vdev, nbuf, msdu_info, 3276 tx_q->desc_pool_id); 3277 3278 if (!tx_desc) { 3279 if (msdu_info->frm_type == dp_tx_frm_me) { 3280 prep_desc_fail++; 3281 dp_tx_me_free_buf(pdev, 3282 (void *)(msdu_info->u.sg_info 3283 .curr_seg->frags[0].vaddr)); 3284 if (prep_desc_fail == msdu_info->num_seg) { 3285 /* 3286 * Unmap is needed only if descriptor 3287 * preparation failed for all segments. 3288 */ 3289 qdf_nbuf_unmap(soc->osdev, 3290 msdu_info->u.sg_info. 3291 curr_seg->nbuf, 3292 QDF_DMA_TO_DEVICE); 3293 } 3294 /* 3295 * Free the nbuf for the current segment 3296 * and make it point to the next in the list. 3297 * For me, there are as many segments as there 3298 * are no of clients. 3299 */ 3300 qdf_nbuf_free(msdu_info->u.sg_info 3301 .curr_seg->nbuf); 3302 if (msdu_info->u.sg_info.curr_seg->next) { 3303 msdu_info->u.sg_info.curr_seg = 3304 msdu_info->u.sg_info 3305 .curr_seg->next; 3306 nbuf = msdu_info->u.sg_info 3307 .curr_seg->nbuf; 3308 } 3309 i++; 3310 continue; 3311 } 3312 3313 if (msdu_info->frm_type == dp_tx_frm_tso) { 3314 dp_tx_tso_seg_history_add( 3315 soc, 3316 msdu_info->u.tso_info.curr_seg, 3317 nbuf, 0, DP_TX_DESC_UNMAP); 3318 dp_tx_tso_unmap_segment(soc, 3319 msdu_info->u.tso_info. 3320 curr_seg, 3321 msdu_info->u.tso_info. 3322 tso_num_seg_list); 3323 3324 if (msdu_info->u.tso_info.curr_seg->next) { 3325 msdu_info->u.tso_info.curr_seg = 3326 msdu_info->u.tso_info.curr_seg->next; 3327 i++; 3328 continue; 3329 } 3330 } 3331 3332 if (msdu_info->frm_type == dp_tx_frm_sg) 3333 dp_tx_sg_unmap_buf(soc, nbuf, msdu_info); 3334 3335 goto done; 3336 } 3337 3338 if (msdu_info->frm_type == dp_tx_frm_me) { 3339 tx_desc->msdu_ext_desc->me_buffer = 3340 (struct dp_tx_me_buf_t *)msdu_info-> 3341 u.sg_info.curr_seg->frags[0].vaddr; 3342 tx_desc->flags |= DP_TX_DESC_FLAG_ME; 3343 } 3344 3345 if (is_cce_classified) 3346 tx_desc->flags |= DP_TX_DESC_FLAG_TO_FW; 3347 3348 htt_tcl_metadata = vdev->htt_tcl_metadata; 3349 if (msdu_info->exception_fw) { 3350 DP_TX_TCL_METADATA_VALID_HTT_SET(htt_tcl_metadata, 1); 3351 } 3352 3353 dp_tx_is_hp_update_required(i, msdu_info); 3354 3355 /* 3356 * For frames with multiple segments (TSO, ME), jump to next 3357 * segment. 3358 */ 3359 if (msdu_info->frm_type == dp_tx_frm_tso) { 3360 if (msdu_info->u.tso_info.curr_seg->next) { 3361 msdu_info->u.tso_info.curr_seg = 3362 msdu_info->u.tso_info.curr_seg->next; 3363 3364 /* 3365 * If this is a jumbo nbuf, then increment the 3366 * number of nbuf users for each additional 3367 * segment of the msdu. This will ensure that 3368 * the skb is freed only after receiving tx 3369 * completion for all segments of an nbuf 3370 */ 3371 qdf_nbuf_inc_users(nbuf); 3372 3373 /* Check with MCL if this is needed */ 3374 /* nbuf = msdu_info->u.tso_info.curr_seg->nbuf; 3375 */ 3376 } 3377 } 3378 3379 dp_tx_update_mcast_param(DP_INVALID_PEER, 3380 &htt_tcl_metadata, 3381 vdev, 3382 msdu_info); 3383 /* 3384 * Enqueue the Tx MSDU descriptor to HW for transmit 3385 */ 3386 status = soc->arch_ops.tx_hw_enqueue(soc, vdev, tx_desc, 3387 htt_tcl_metadata, 3388 NULL, msdu_info); 3389 3390 dp_tx_check_and_flush_hp(soc, status, msdu_info); 3391 3392 if (status != QDF_STATUS_SUCCESS) { 3393 dp_info_rl("Tx_hw_enqueue Fail tx_desc %pK queue %d", 3394 tx_desc, tx_q->ring_id); 3395 3396 dp_tx_get_tid(vdev, nbuf, msdu_info); 3397 tid_stats = &pdev->stats.tid_stats. 3398 tid_tx_stats[tx_q->ring_id][msdu_info->tid]; 3399 tid_stats->swdrop_cnt[TX_HW_ENQUEUE]++; 3400 3401 if (msdu_info->frm_type == dp_tx_frm_me) { 3402 hw_enq_fail++; 3403 if (hw_enq_fail == msdu_info->num_seg) { 3404 /* 3405 * Unmap is needed only if enqueue 3406 * failed for all segments. 3407 */ 3408 qdf_nbuf_unmap(soc->osdev, 3409 msdu_info->u.sg_info. 3410 curr_seg->nbuf, 3411 QDF_DMA_TO_DEVICE); 3412 } 3413 /* 3414 * Free the nbuf for the current segment 3415 * and make it point to the next in the list. 3416 * For me, there are as many segments as there 3417 * are no of clients. 3418 */ 3419 qdf_nbuf_free(msdu_info->u.sg_info 3420 .curr_seg->nbuf); 3421 dp_tx_desc_release(soc, tx_desc, 3422 tx_q->desc_pool_id); 3423 if (msdu_info->u.sg_info.curr_seg->next) { 3424 msdu_info->u.sg_info.curr_seg = 3425 msdu_info->u.sg_info 3426 .curr_seg->next; 3427 nbuf = msdu_info->u.sg_info 3428 .curr_seg->nbuf; 3429 } else 3430 break; 3431 i++; 3432 continue; 3433 } 3434 3435 /* 3436 * For TSO frames, the nbuf users increment done for 3437 * the current segment has to be reverted, since the 3438 * hw enqueue for this segment failed 3439 */ 3440 if (msdu_info->frm_type == dp_tx_frm_tso && 3441 msdu_info->u.tso_info.curr_seg) { 3442 /* 3443 * unmap and free current, 3444 * retransmit remaining segments 3445 */ 3446 dp_tx_comp_free_buf(soc, tx_desc, false); 3447 i++; 3448 dp_tx_desc_release(soc, tx_desc, 3449 tx_q->desc_pool_id); 3450 continue; 3451 } 3452 3453 if (msdu_info->frm_type == dp_tx_frm_sg) 3454 dp_tx_sg_unmap_buf(soc, nbuf, msdu_info); 3455 3456 dp_tx_desc_release(soc, tx_desc, tx_q->desc_pool_id); 3457 goto done; 3458 } 3459 3460 dp_tx_update_ts_on_enqueued(vdev, msdu_info, tx_desc); 3461 3462 /* 3463 * TODO 3464 * if tso_info structure can be modified to have curr_seg 3465 * as first element, following 2 blocks of code (for TSO and SG) 3466 * can be combined into 1 3467 */ 3468 3469 /* 3470 * For Multicast-Unicast converted packets, 3471 * each converted frame (for a client) is represented as 3472 * 1 segment 3473 */ 3474 if ((msdu_info->frm_type == dp_tx_frm_sg) || 3475 (msdu_info->frm_type == dp_tx_frm_me)) { 3476 if (msdu_info->u.sg_info.curr_seg->next) { 3477 msdu_info->u.sg_info.curr_seg = 3478 msdu_info->u.sg_info.curr_seg->next; 3479 nbuf = msdu_info->u.sg_info.curr_seg->nbuf; 3480 } else 3481 break; 3482 } 3483 i++; 3484 } 3485 3486 nbuf = NULL; 3487 3488 done: 3489 return nbuf; 3490 } 3491 3492 /** 3493 * dp_tx_prepare_sg()- Extract SG info from NBUF and prepare msdu_info 3494 * for SG frames 3495 * @vdev: DP vdev handle 3496 * @nbuf: skb 3497 * @seg_info: Pointer to Segment info Descriptor to be prepared 3498 * @msdu_info: MSDU info to be setup in MSDU descriptor and MSDU extension desc. 3499 * 3500 * Return: NULL on success, 3501 * nbuf when it fails to send 3502 */ 3503 static qdf_nbuf_t dp_tx_prepare_sg(struct dp_vdev *vdev, qdf_nbuf_t nbuf, 3504 struct dp_tx_seg_info_s *seg_info, struct dp_tx_msdu_info_s *msdu_info) 3505 { 3506 uint32_t cur_frag, nr_frags, i; 3507 qdf_dma_addr_t paddr; 3508 struct dp_tx_sg_info_s *sg_info; 3509 uint8_t xmit_type = msdu_info->xmit_type; 3510 3511 sg_info = &msdu_info->u.sg_info; 3512 nr_frags = qdf_nbuf_get_nr_frags(nbuf); 3513 3514 if (QDF_STATUS_SUCCESS != 3515 qdf_nbuf_map_nbytes_single(vdev->osdev, nbuf, 3516 QDF_DMA_TO_DEVICE, 3517 qdf_nbuf_headlen(nbuf))) { 3518 dp_tx_err("dma map error"); 3519 DP_STATS_INC(vdev, tx_i[xmit_type].sg.dma_map_error, 3520 1); 3521 qdf_nbuf_free(nbuf); 3522 return NULL; 3523 } 3524 3525 paddr = qdf_nbuf_mapped_paddr_get(nbuf); 3526 seg_info->frags[0].paddr_lo = paddr; 3527 seg_info->frags[0].paddr_hi = ((uint64_t) paddr) >> 32; 3528 seg_info->frags[0].len = qdf_nbuf_headlen(nbuf); 3529 seg_info->frags[0].vaddr = (void *) nbuf; 3530 3531 for (cur_frag = 0; cur_frag < nr_frags; cur_frag++) { 3532 if (QDF_STATUS_SUCCESS != qdf_nbuf_frag_map(vdev->osdev, 3533 nbuf, 0, 3534 QDF_DMA_TO_DEVICE, 3535 cur_frag)) { 3536 dp_tx_err("frag dma map error"); 3537 DP_STATS_INC(vdev, 3538 tx_i[xmit_type].sg.dma_map_error, 3539 1); 3540 goto map_err; 3541 } 3542 3543 paddr = qdf_nbuf_get_tx_frag_paddr(nbuf); 3544 seg_info->frags[cur_frag + 1].paddr_lo = paddr; 3545 seg_info->frags[cur_frag + 1].paddr_hi = 3546 ((uint64_t) paddr) >> 32; 3547 seg_info->frags[cur_frag + 1].len = 3548 qdf_nbuf_get_frag_size(nbuf, cur_frag); 3549 } 3550 3551 seg_info->frag_cnt = (cur_frag + 1); 3552 seg_info->total_len = qdf_nbuf_len(nbuf); 3553 seg_info->next = NULL; 3554 3555 sg_info->curr_seg = seg_info; 3556 3557 msdu_info->frm_type = dp_tx_frm_sg; 3558 msdu_info->num_seg = 1; 3559 3560 return nbuf; 3561 map_err: 3562 /* restore paddr into nbuf before calling unmap */ 3563 qdf_nbuf_mapped_paddr_set(nbuf, 3564 (qdf_dma_addr_t)(seg_info->frags[0].paddr_lo | 3565 ((uint64_t) 3566 seg_info->frags[0].paddr_hi) << 32)); 3567 qdf_nbuf_unmap_nbytes_single(vdev->osdev, nbuf, 3568 QDF_DMA_TO_DEVICE, 3569 seg_info->frags[0].len); 3570 for (i = 1; i <= cur_frag; i++) { 3571 qdf_mem_unmap_page(vdev->osdev, (qdf_dma_addr_t) 3572 (seg_info->frags[i].paddr_lo | ((uint64_t) 3573 seg_info->frags[i].paddr_hi) << 32), 3574 seg_info->frags[i].len, 3575 QDF_DMA_TO_DEVICE); 3576 } 3577 qdf_nbuf_free(nbuf); 3578 return NULL; 3579 } 3580 3581 /** 3582 * dp_tx_add_tx_sniffer_meta_data()- Add tx_sniffer meta hdr info 3583 * @vdev: DP vdev handle 3584 * @msdu_info: MSDU info to be setup in MSDU descriptor and MSDU extension desc. 3585 * @ppdu_cookie: PPDU cookie that should be replayed in the ppdu completions 3586 * 3587 * Return: NULL on failure, 3588 * nbuf when extracted successfully 3589 */ 3590 static 3591 void dp_tx_add_tx_sniffer_meta_data(struct dp_vdev *vdev, 3592 struct dp_tx_msdu_info_s *msdu_info, 3593 uint16_t ppdu_cookie) 3594 { 3595 struct htt_tx_msdu_desc_ext2_t *meta_data = 3596 (struct htt_tx_msdu_desc_ext2_t *)&msdu_info->meta_data[0]; 3597 3598 qdf_mem_zero(meta_data, sizeof(struct htt_tx_msdu_desc_ext2_t)); 3599 3600 HTT_TX_MSDU_EXT2_DESC_FLAG_SEND_AS_STANDALONE_SET 3601 (msdu_info->meta_data[5], 1); 3602 HTT_TX_MSDU_EXT2_DESC_FLAG_HOST_OPAQUE_VALID_SET 3603 (msdu_info->meta_data[5], 1); 3604 HTT_TX_MSDU_EXT2_DESC_HOST_OPAQUE_COOKIE_SET 3605 (msdu_info->meta_data[6], ppdu_cookie); 3606 3607 msdu_info->exception_fw = 1; 3608 msdu_info->is_tx_sniffer = 1; 3609 } 3610 3611 #ifdef MESH_MODE_SUPPORT 3612 3613 /** 3614 * dp_tx_extract_mesh_meta_data()- Extract mesh meta hdr info from nbuf 3615 * and prepare msdu_info for mesh frames. 3616 * @vdev: DP vdev handle 3617 * @nbuf: skb 3618 * @msdu_info: MSDU info to be setup in MSDU descriptor and MSDU extension desc. 3619 * 3620 * Return: NULL on failure, 3621 * nbuf when extracted successfully 3622 */ 3623 static 3624 qdf_nbuf_t dp_tx_extract_mesh_meta_data(struct dp_vdev *vdev, qdf_nbuf_t nbuf, 3625 struct dp_tx_msdu_info_s *msdu_info) 3626 { 3627 struct meta_hdr_s *mhdr; 3628 struct htt_tx_msdu_desc_ext2_t *meta_data = 3629 (struct htt_tx_msdu_desc_ext2_t *)&msdu_info->meta_data[0]; 3630 3631 mhdr = (struct meta_hdr_s *)qdf_nbuf_data(nbuf); 3632 3633 if (CB_FTYPE_MESH_TX_INFO != qdf_nbuf_get_tx_ftype(nbuf)) { 3634 msdu_info->exception_fw = 0; 3635 goto remove_meta_hdr; 3636 } 3637 3638 msdu_info->exception_fw = 1; 3639 3640 qdf_mem_zero(meta_data, sizeof(struct htt_tx_msdu_desc_ext2_t)); 3641 3642 meta_data->host_tx_desc_pool = 1; 3643 meta_data->update_peer_cache = 1; 3644 meta_data->learning_frame = 1; 3645 3646 if (!(mhdr->flags & METAHDR_FLAG_AUTO_RATE)) { 3647 meta_data->power = mhdr->power; 3648 3649 meta_data->mcs_mask = 1 << mhdr->rate_info[0].mcs; 3650 meta_data->nss_mask = 1 << mhdr->rate_info[0].nss; 3651 meta_data->pream_type = mhdr->rate_info[0].preamble_type; 3652 meta_data->retry_limit = mhdr->rate_info[0].max_tries; 3653 3654 meta_data->dyn_bw = 1; 3655 3656 meta_data->valid_pwr = 1; 3657 meta_data->valid_mcs_mask = 1; 3658 meta_data->valid_nss_mask = 1; 3659 meta_data->valid_preamble_type = 1; 3660 meta_data->valid_retries = 1; 3661 meta_data->valid_bw_info = 1; 3662 } 3663 3664 if (mhdr->flags & METAHDR_FLAG_NOENCRYPT) { 3665 meta_data->encrypt_type = 0; 3666 meta_data->valid_encrypt_type = 1; 3667 meta_data->learning_frame = 0; 3668 } 3669 3670 meta_data->valid_key_flags = 1; 3671 meta_data->key_flags = (mhdr->keyix & 0x3); 3672 3673 remove_meta_hdr: 3674 if (qdf_nbuf_pull_head(nbuf, sizeof(struct meta_hdr_s)) == NULL) { 3675 dp_tx_err("qdf_nbuf_pull_head failed"); 3676 qdf_nbuf_free(nbuf); 3677 return NULL; 3678 } 3679 3680 msdu_info->tid = qdf_nbuf_get_priority(nbuf); 3681 3682 dp_tx_info("Meta hdr %0x %0x %0x %0x %0x %0x" 3683 " tid %d to_fw %d", 3684 msdu_info->meta_data[0], 3685 msdu_info->meta_data[1], 3686 msdu_info->meta_data[2], 3687 msdu_info->meta_data[3], 3688 msdu_info->meta_data[4], 3689 msdu_info->meta_data[5], 3690 msdu_info->tid, msdu_info->exception_fw); 3691 3692 return nbuf; 3693 } 3694 #else 3695 static 3696 qdf_nbuf_t dp_tx_extract_mesh_meta_data(struct dp_vdev *vdev, qdf_nbuf_t nbuf, 3697 struct dp_tx_msdu_info_s *msdu_info) 3698 { 3699 return nbuf; 3700 } 3701 3702 #endif 3703 3704 /** 3705 * dp_check_exc_metadata() - Checks if parameters are valid 3706 * @tx_exc: holds all exception path parameters 3707 * 3708 * Return: true when all the parameters are valid else false 3709 * 3710 */ 3711 static bool dp_check_exc_metadata(struct cdp_tx_exception_metadata *tx_exc) 3712 { 3713 bool invalid_tid = (tx_exc->tid >= DP_MAX_TIDS && tx_exc->tid != 3714 HTT_INVALID_TID); 3715 bool invalid_encap_type = 3716 (tx_exc->tx_encap_type > htt_cmn_pkt_num_types && 3717 tx_exc->tx_encap_type != CDP_INVALID_TX_ENCAP_TYPE); 3718 bool invalid_sec_type = (tx_exc->sec_type > cdp_num_sec_types && 3719 tx_exc->sec_type != CDP_INVALID_SEC_TYPE); 3720 bool invalid_cookie = (tx_exc->is_tx_sniffer == 1 && 3721 tx_exc->ppdu_cookie == 0); 3722 3723 if (tx_exc->is_intrabss_fwd) 3724 return true; 3725 3726 if (invalid_tid || invalid_encap_type || invalid_sec_type || 3727 invalid_cookie) { 3728 return false; 3729 } 3730 3731 return true; 3732 } 3733 3734 #ifdef ATH_SUPPORT_IQUE 3735 bool dp_tx_mcast_enhance(struct dp_vdev *vdev, qdf_nbuf_t nbuf) 3736 { 3737 qdf_ether_header_t *eh; 3738 uint8_t xmit_type = qdf_nbuf_get_vdev_xmit_type(nbuf); 3739 /* Mcast to Ucast Conversion*/ 3740 if (qdf_likely(!vdev->mcast_enhancement_en)) 3741 return true; 3742 3743 eh = (qdf_ether_header_t *)qdf_nbuf_data(nbuf); 3744 if (DP_FRAME_IS_MULTICAST((eh)->ether_dhost) && 3745 !DP_FRAME_IS_BROADCAST((eh)->ether_dhost)) { 3746 dp_verbose_debug("Mcast frm for ME %pK", vdev); 3747 qdf_nbuf_set_next(nbuf, NULL); 3748 3749 DP_STATS_INC_PKT(vdev, tx_i[xmit_type].mcast_en.mcast_pkt, 1, 3750 qdf_nbuf_len(nbuf)); 3751 if (dp_tx_prepare_send_me(vdev, nbuf) == 3752 QDF_STATUS_SUCCESS) { 3753 return false; 3754 } 3755 3756 if (qdf_unlikely(vdev->igmp_mcast_enhanc_en > 0)) { 3757 if (dp_tx_prepare_send_igmp_me(vdev, nbuf) == 3758 QDF_STATUS_SUCCESS) { 3759 return false; 3760 } 3761 } 3762 } 3763 3764 return true; 3765 } 3766 #else 3767 bool dp_tx_mcast_enhance(struct dp_vdev *vdev, qdf_nbuf_t nbuf) 3768 { 3769 return true; 3770 } 3771 #endif 3772 3773 #ifdef QCA_SUPPORT_WDS_EXTENDED 3774 /** 3775 * dp_tx_mcast_drop() - Drop mcast frame if drop_tx_mcast is set in WDS_EXT 3776 * @vdev: vdev handle 3777 * @nbuf: skb 3778 * 3779 * Return: true if frame is dropped, false otherwise 3780 */ 3781 static inline bool dp_tx_mcast_drop(struct dp_vdev *vdev, qdf_nbuf_t nbuf) 3782 { 3783 uint8_t xmit_type = qdf_nbuf_get_vdev_xmit_type(nbuf); 3784 3785 /* Drop tx mcast and WDS Extended feature check */ 3786 if (qdf_unlikely((vdev->drop_tx_mcast) && (vdev->wds_ext_enabled))) { 3787 qdf_ether_header_t *eh = (qdf_ether_header_t *) 3788 qdf_nbuf_data(nbuf); 3789 if (DP_FRAME_IS_MULTICAST((eh)->ether_dhost)) { 3790 DP_STATS_INC(vdev, 3791 tx_i[xmit_type].dropped.tx_mcast_drop, 1); 3792 return true; 3793 } 3794 } 3795 3796 return false; 3797 } 3798 #else 3799 static inline bool dp_tx_mcast_drop(struct dp_vdev *vdev, qdf_nbuf_t nbuf) 3800 { 3801 return false; 3802 } 3803 #endif 3804 /** 3805 * dp_tx_per_pkt_vdev_id_check() - vdev id check for frame 3806 * @nbuf: qdf_nbuf_t 3807 * @vdev: struct dp_vdev * 3808 * 3809 * Allow packet for processing only if it is for peer client which is 3810 * connected with same vap. Drop packet if client is connected to 3811 * different vap. 3812 * 3813 * Return: QDF_STATUS 3814 */ 3815 static inline QDF_STATUS 3816 dp_tx_per_pkt_vdev_id_check(qdf_nbuf_t nbuf, struct dp_vdev *vdev) 3817 { 3818 struct dp_ast_entry *dst_ast_entry = NULL; 3819 qdf_ether_header_t *eh = (qdf_ether_header_t *)qdf_nbuf_data(nbuf); 3820 3821 if (DP_FRAME_IS_MULTICAST((eh)->ether_dhost) || 3822 DP_FRAME_IS_BROADCAST((eh)->ether_dhost)) 3823 return QDF_STATUS_SUCCESS; 3824 3825 qdf_spin_lock_bh(&vdev->pdev->soc->ast_lock); 3826 dst_ast_entry = dp_peer_ast_hash_find_by_vdevid(vdev->pdev->soc, 3827 eh->ether_dhost, 3828 vdev->vdev_id); 3829 3830 /* If there is no ast entry, return failure */ 3831 if (qdf_unlikely(!dst_ast_entry)) { 3832 qdf_spin_unlock_bh(&vdev->pdev->soc->ast_lock); 3833 return QDF_STATUS_E_FAILURE; 3834 } 3835 qdf_spin_unlock_bh(&vdev->pdev->soc->ast_lock); 3836 3837 return QDF_STATUS_SUCCESS; 3838 } 3839 3840 /** 3841 * dp_tx_nawds_handler() - NAWDS handler 3842 * 3843 * @soc: DP soc handle 3844 * @vdev: DP vdev handle 3845 * @msdu_info: msdu_info required to create HTT metadata 3846 * @nbuf: skb 3847 * @sa_peer_id: 3848 * 3849 * This API transfers the multicast frames with the peer id 3850 * on NAWDS enabled peer. 3851 * 3852 * Return: none 3853 */ 3854 3855 void dp_tx_nawds_handler(struct dp_soc *soc, struct dp_vdev *vdev, 3856 struct dp_tx_msdu_info_s *msdu_info, 3857 qdf_nbuf_t nbuf, uint16_t sa_peer_id) 3858 { 3859 struct dp_peer *peer = NULL; 3860 qdf_nbuf_t nbuf_clone = NULL; 3861 uint16_t peer_id = DP_INVALID_PEER; 3862 struct dp_txrx_peer *txrx_peer; 3863 uint8_t link_id = 0; 3864 3865 /* This check avoids pkt forwarding which is entered 3866 * in the ast table but still doesn't have valid peerid. 3867 */ 3868 if (sa_peer_id == HTT_INVALID_PEER) 3869 return; 3870 3871 qdf_spin_lock_bh(&vdev->peer_list_lock); 3872 TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) { 3873 txrx_peer = dp_get_txrx_peer(peer); 3874 if (!txrx_peer) 3875 continue; 3876 3877 if (!txrx_peer->bss_peer && txrx_peer->nawds_enabled) { 3878 peer_id = peer->peer_id; 3879 3880 if (!dp_peer_is_primary_link_peer(peer)) 3881 continue; 3882 3883 /* In the case of wds ext peer mcast traffic will be 3884 * sent as part of VLAN interface 3885 */ 3886 if (dp_peer_is_wds_ext_peer(txrx_peer)) 3887 continue; 3888 3889 /* Multicast packets needs to be 3890 * dropped in case of intra bss forwarding 3891 */ 3892 if (sa_peer_id == txrx_peer->peer_id) { 3893 dp_tx_debug("multicast packet"); 3894 DP_PEER_PER_PKT_STATS_INC(txrx_peer, 3895 tx.nawds_mcast_drop, 3896 1, link_id); 3897 continue; 3898 } 3899 3900 nbuf_clone = qdf_nbuf_clone(nbuf); 3901 3902 if (!nbuf_clone) { 3903 QDF_TRACE(QDF_MODULE_ID_DP, 3904 QDF_TRACE_LEVEL_ERROR, 3905 FL("nbuf clone failed")); 3906 break; 3907 } 3908 3909 nbuf_clone = dp_tx_send_msdu_single(vdev, nbuf_clone, 3910 msdu_info, peer_id, 3911 NULL); 3912 3913 if (nbuf_clone) { 3914 dp_tx_debug("pkt send failed"); 3915 qdf_nbuf_free(nbuf_clone); 3916 } else { 3917 if (peer_id != DP_INVALID_PEER) 3918 DP_PEER_PER_PKT_STATS_INC_PKT(txrx_peer, 3919 tx.nawds_mcast, 3920 1, qdf_nbuf_len(nbuf), link_id); 3921 } 3922 } 3923 } 3924 3925 qdf_spin_unlock_bh(&vdev->peer_list_lock); 3926 } 3927 3928 #ifdef WLAN_MCAST_MLO 3929 static inline bool 3930 dp_tx_check_mesh_vdev(struct dp_vdev *vdev, 3931 struct cdp_tx_exception_metadata *tx_exc_metadata) 3932 { 3933 if (!tx_exc_metadata->is_mlo_mcast && qdf_unlikely(vdev->mesh_vdev)) 3934 return true; 3935 3936 return false; 3937 } 3938 #else 3939 static inline bool 3940 dp_tx_check_mesh_vdev(struct dp_vdev *vdev, 3941 struct cdp_tx_exception_metadata *tx_exc_metadata) 3942 { 3943 if (qdf_unlikely(vdev->mesh_vdev)) 3944 return true; 3945 3946 return false; 3947 } 3948 #endif 3949 3950 qdf_nbuf_t 3951 dp_tx_send_exception(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, 3952 qdf_nbuf_t nbuf, 3953 struct cdp_tx_exception_metadata *tx_exc_metadata) 3954 { 3955 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); 3956 struct dp_tx_msdu_info_s msdu_info; 3957 struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id, 3958 DP_MOD_ID_TX_EXCEPTION); 3959 uint8_t xmit_type = qdf_nbuf_get_vdev_xmit_type(nbuf); 3960 3961 if (qdf_unlikely(!vdev)) 3962 goto fail; 3963 3964 qdf_mem_zero(&msdu_info, sizeof(msdu_info)); 3965 3966 if (!tx_exc_metadata) 3967 goto fail; 3968 3969 msdu_info.tid = tx_exc_metadata->tid; 3970 msdu_info.xmit_type = xmit_type; 3971 dp_verbose_debug("skb "QDF_MAC_ADDR_FMT, 3972 QDF_MAC_ADDR_REF(nbuf->data)); 3973 3974 DP_STATS_INC_PKT(vdev, tx_i[xmit_type].rcvd, 1, qdf_nbuf_len(nbuf)); 3975 3976 if (qdf_unlikely(!dp_check_exc_metadata(tx_exc_metadata))) { 3977 dp_tx_err("Invalid parameters in exception path"); 3978 goto fail; 3979 } 3980 3981 /* for peer based metadata check if peer is valid */ 3982 if (tx_exc_metadata->peer_id != CDP_INVALID_PEER) { 3983 struct dp_peer *peer = NULL; 3984 3985 peer = dp_peer_get_ref_by_id(vdev->pdev->soc, 3986 tx_exc_metadata->peer_id, 3987 DP_MOD_ID_TX_EXCEPTION); 3988 if (qdf_unlikely(!peer)) { 3989 DP_STATS_INC(vdev, 3990 tx_i[xmit_type].dropped.invalid_peer_id_in_exc_path, 3991 1); 3992 goto fail; 3993 } 3994 dp_peer_unref_delete(peer, DP_MOD_ID_TX_EXCEPTION); 3995 } 3996 /* Basic sanity checks for unsupported packets */ 3997 3998 /* MESH mode */ 3999 if (dp_tx_check_mesh_vdev(vdev, tx_exc_metadata)) { 4000 dp_tx_err("Mesh mode is not supported in exception path"); 4001 goto fail; 4002 } 4003 4004 /* 4005 * Classify the frame and call corresponding 4006 * "prepare" function which extracts the segment (TSO) 4007 * and fragmentation information (for TSO , SG, ME, or Raw) 4008 * into MSDU_INFO structure which is later used to fill 4009 * SW and HW descriptors. 4010 */ 4011 if (qdf_nbuf_is_tso(nbuf)) { 4012 dp_verbose_debug("TSO frame %pK", vdev); 4013 DP_STATS_INC_PKT(vdev->pdev, tso_stats.num_tso_pkts, 1, 4014 qdf_nbuf_len(nbuf)); 4015 4016 if (dp_tx_prepare_tso(vdev, nbuf, &msdu_info)) { 4017 DP_STATS_INC_PKT(vdev->pdev, tso_stats.dropped_host, 1, 4018 qdf_nbuf_len(nbuf)); 4019 goto fail; 4020 } 4021 4022 DP_STATS_INC(vdev, 4023 tx_i[xmit_type].rcvd.num, msdu_info.num_seg - 1); 4024 4025 goto send_multiple; 4026 } 4027 4028 /* SG */ 4029 if (qdf_unlikely(qdf_nbuf_is_nonlinear(nbuf))) { 4030 struct dp_tx_seg_info_s seg_info = {0}; 4031 4032 nbuf = dp_tx_prepare_sg(vdev, nbuf, &seg_info, &msdu_info); 4033 if (!nbuf) 4034 goto fail; 4035 4036 dp_verbose_debug("non-TSO SG frame %pK", vdev); 4037 4038 DP_STATS_INC_PKT(vdev, tx_i[xmit_type].sg.sg_pkt, 1, 4039 qdf_nbuf_len(nbuf)); 4040 4041 goto send_multiple; 4042 } 4043 4044 if (qdf_likely(tx_exc_metadata->is_tx_sniffer)) { 4045 DP_STATS_INC_PKT(vdev, tx_i[xmit_type].sniffer_rcvd, 1, 4046 qdf_nbuf_len(nbuf)); 4047 4048 dp_tx_add_tx_sniffer_meta_data(vdev, &msdu_info, 4049 tx_exc_metadata->ppdu_cookie); 4050 } 4051 4052 /* 4053 * Get HW Queue to use for this frame. 4054 * TCL supports upto 4 DMA rings, out of which 3 rings are 4055 * dedicated for data and 1 for command. 4056 * "queue_id" maps to one hardware ring. 4057 * With each ring, we also associate a unique Tx descriptor pool 4058 * to minimize lock contention for these resources. 4059 */ 4060 dp_tx_get_queue(vdev, nbuf, &msdu_info.tx_queue); 4061 DP_STATS_INC(vdev, 4062 tx_i[xmit_type].rcvd_per_core[msdu_info.tx_queue.desc_pool_id], 4063 1); 4064 4065 /* 4066 * if the packet is mcast packet send through mlo_macst handler 4067 * for all prnt_vdevs 4068 */ 4069 4070 if (soc->arch_ops.dp_tx_mlo_mcast_send) { 4071 nbuf = soc->arch_ops.dp_tx_mlo_mcast_send(soc, vdev, 4072 nbuf, 4073 tx_exc_metadata); 4074 if (!nbuf) 4075 goto fail; 4076 } 4077 4078 if (qdf_likely(tx_exc_metadata->is_intrabss_fwd)) { 4079 if (qdf_unlikely(vdev->nawds_enabled)) { 4080 /* 4081 * This is a multicast packet 4082 */ 4083 dp_tx_nawds_handler(soc, vdev, &msdu_info, nbuf, 4084 tx_exc_metadata->peer_id); 4085 DP_STATS_INC_PKT(vdev, tx_i[xmit_type].nawds_mcast, 4086 1, qdf_nbuf_len(nbuf)); 4087 } 4088 4089 nbuf = dp_tx_send_msdu_single(vdev, nbuf, &msdu_info, 4090 DP_INVALID_PEER, NULL); 4091 } else { 4092 /* 4093 * Check exception descriptors 4094 */ 4095 if (dp_tx_exception_limit_check(vdev, xmit_type)) 4096 goto fail; 4097 4098 /* Single linear frame */ 4099 /* 4100 * If nbuf is a simple linear frame, use send_single function to 4101 * prepare direct-buffer type TCL descriptor and enqueue to TCL 4102 * SRNG. There is no need to setup a MSDU extension descriptor. 4103 */ 4104 nbuf = dp_tx_send_msdu_single(vdev, nbuf, &msdu_info, 4105 tx_exc_metadata->peer_id, 4106 tx_exc_metadata); 4107 } 4108 4109 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_TX_EXCEPTION); 4110 return nbuf; 4111 4112 send_multiple: 4113 nbuf = dp_tx_send_msdu_multiple(vdev, nbuf, &msdu_info); 4114 4115 fail: 4116 if (vdev) 4117 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_TX_EXCEPTION); 4118 dp_verbose_debug("pkt send failed"); 4119 return nbuf; 4120 } 4121 4122 qdf_nbuf_t 4123 dp_tx_send_exception_vdev_id_check(struct cdp_soc_t *soc_hdl, 4124 uint8_t vdev_id, qdf_nbuf_t nbuf, 4125 struct cdp_tx_exception_metadata *tx_exc_metadata) 4126 { 4127 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); 4128 struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id, 4129 DP_MOD_ID_TX_EXCEPTION); 4130 uint8_t xmit_type = qdf_nbuf_get_vdev_xmit_type(nbuf); 4131 4132 if (qdf_unlikely(!vdev)) 4133 goto fail; 4134 4135 if (qdf_unlikely(dp_tx_per_pkt_vdev_id_check(nbuf, vdev) 4136 == QDF_STATUS_E_FAILURE)) { 4137 DP_STATS_INC(vdev, 4138 tx_i[xmit_type].dropped.fail_per_pkt_vdev_id_check, 4139 1); 4140 goto fail; 4141 } 4142 4143 /* Unref count as it will again be taken inside dp_tx_exception */ 4144 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_TX_EXCEPTION); 4145 4146 return dp_tx_send_exception(soc_hdl, vdev_id, nbuf, tx_exc_metadata); 4147 4148 fail: 4149 if (vdev) 4150 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_TX_EXCEPTION); 4151 dp_verbose_debug("pkt send failed"); 4152 return nbuf; 4153 } 4154 4155 #ifdef MESH_MODE_SUPPORT 4156 qdf_nbuf_t dp_tx_send_mesh(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, 4157 qdf_nbuf_t nbuf) 4158 { 4159 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); 4160 struct meta_hdr_s *mhdr; 4161 qdf_nbuf_t nbuf_mesh = NULL; 4162 qdf_nbuf_t nbuf_clone = NULL; 4163 struct dp_vdev *vdev; 4164 uint8_t no_enc_frame = 0; 4165 uint8_t xmit_type = qdf_nbuf_get_vdev_xmit_type(nbuf); 4166 4167 nbuf_mesh = qdf_nbuf_unshare(nbuf); 4168 if (!nbuf_mesh) { 4169 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 4170 "qdf_nbuf_unshare failed"); 4171 return nbuf; 4172 } 4173 4174 vdev = dp_vdev_get_ref_by_id(soc, vdev_id, DP_MOD_ID_MESH); 4175 if (!vdev) { 4176 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 4177 "vdev is NULL for vdev_id %d", vdev_id); 4178 return nbuf; 4179 } 4180 4181 nbuf = nbuf_mesh; 4182 4183 mhdr = (struct meta_hdr_s *)qdf_nbuf_data(nbuf); 4184 4185 if ((vdev->sec_type != cdp_sec_type_none) && 4186 (mhdr->flags & METAHDR_FLAG_NOENCRYPT)) 4187 no_enc_frame = 1; 4188 4189 if (mhdr->flags & METAHDR_FLAG_NOQOS) 4190 qdf_nbuf_set_priority(nbuf, HTT_TX_EXT_TID_NON_QOS_MCAST_BCAST); 4191 4192 if ((mhdr->flags & METAHDR_FLAG_INFO_UPDATED) && 4193 !no_enc_frame) { 4194 nbuf_clone = qdf_nbuf_clone(nbuf); 4195 if (!nbuf_clone) { 4196 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 4197 "qdf_nbuf_clone failed"); 4198 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_MESH); 4199 return nbuf; 4200 } 4201 qdf_nbuf_set_tx_ftype(nbuf_clone, CB_FTYPE_MESH_TX_INFO); 4202 } 4203 4204 if (nbuf_clone) { 4205 if (!dp_tx_send(soc_hdl, vdev_id, nbuf_clone)) { 4206 DP_STATS_INC(vdev, tx_i[xmit_type].mesh.exception_fw, 4207 1); 4208 } else { 4209 qdf_nbuf_free(nbuf_clone); 4210 } 4211 } 4212 4213 if (no_enc_frame) 4214 qdf_nbuf_set_tx_ftype(nbuf, CB_FTYPE_MESH_TX_INFO); 4215 else 4216 qdf_nbuf_set_tx_ftype(nbuf, CB_FTYPE_INVALID); 4217 4218 nbuf = dp_tx_send(soc_hdl, vdev_id, nbuf); 4219 if ((!nbuf) && no_enc_frame) { 4220 DP_STATS_INC(vdev, tx_i[xmit_type].mesh.exception_fw, 1); 4221 } 4222 4223 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_MESH); 4224 return nbuf; 4225 } 4226 4227 #else 4228 4229 qdf_nbuf_t dp_tx_send_mesh(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, 4230 qdf_nbuf_t nbuf) 4231 { 4232 return dp_tx_send(soc_hdl, vdev_id, nbuf); 4233 } 4234 4235 #endif 4236 4237 #ifdef DP_UMAC_HW_RESET_SUPPORT 4238 qdf_nbuf_t dp_tx_drop(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, 4239 qdf_nbuf_t nbuf) 4240 { 4241 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); 4242 struct dp_vdev *vdev = NULL; 4243 uint8_t xmit_type = qdf_nbuf_get_vdev_xmit_type(nbuf); 4244 4245 vdev = soc->vdev_id_map[vdev_id]; 4246 if (qdf_unlikely(!vdev)) 4247 return nbuf; 4248 4249 DP_STATS_INC(vdev, tx_i[xmit_type].dropped.drop_ingress, 1); 4250 return nbuf; 4251 } 4252 4253 qdf_nbuf_t dp_tx_exc_drop(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, 4254 qdf_nbuf_t nbuf, 4255 struct cdp_tx_exception_metadata *tx_exc_metadata) 4256 { 4257 return dp_tx_drop(soc_hdl, vdev_id, nbuf); 4258 } 4259 #endif 4260 4261 #ifdef FEATURE_DIRECT_LINK 4262 /** 4263 * dp_vdev_tx_mark_to_fw() - Mark to_fw bit for the tx packet 4264 * @nbuf: skb 4265 * @vdev: DP vdev handle 4266 * 4267 * Return: None 4268 */ 4269 static inline void dp_vdev_tx_mark_to_fw(qdf_nbuf_t nbuf, struct dp_vdev *vdev) 4270 { 4271 if (qdf_unlikely(vdev->to_fw)) 4272 QDF_NBUF_CB_TX_PACKET_TO_FW(nbuf) = 1; 4273 } 4274 #else 4275 static inline void dp_vdev_tx_mark_to_fw(qdf_nbuf_t nbuf, struct dp_vdev *vdev) 4276 { 4277 } 4278 #endif 4279 4280 qdf_nbuf_t dp_tx_send(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, 4281 qdf_nbuf_t nbuf) 4282 { 4283 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); 4284 uint16_t peer_id = HTT_INVALID_PEER; 4285 /* 4286 * doing a memzero is causing additional function call overhead 4287 * so doing static stack clearing 4288 */ 4289 struct dp_tx_msdu_info_s msdu_info = {0}; 4290 struct dp_vdev *vdev = NULL; 4291 qdf_nbuf_t end_nbuf = NULL; 4292 uint8_t xmit_type; 4293 4294 if (qdf_unlikely(vdev_id >= MAX_VDEV_CNT)) 4295 return nbuf; 4296 4297 /* 4298 * dp_vdev_get_ref_by_id does does a atomic operation avoid using 4299 * this in per packet path. 4300 * 4301 * As in this path vdev memory is already protected with netdev 4302 * tx lock 4303 */ 4304 vdev = soc->vdev_id_map[vdev_id]; 4305 if (qdf_unlikely(!vdev)) 4306 return nbuf; 4307 4308 dp_tx_get_driver_ingress_ts(vdev, &msdu_info, nbuf); 4309 4310 dp_vdev_tx_mark_to_fw(nbuf, vdev); 4311 4312 /* 4313 * Set Default Host TID value to invalid TID 4314 * (TID override disabled) 4315 */ 4316 msdu_info.tid = HTT_TX_EXT_TID_INVALID; 4317 xmit_type = qdf_nbuf_get_vdev_xmit_type(nbuf); 4318 msdu_info.xmit_type = xmit_type; 4319 DP_STATS_INC_PKT(vdev, tx_i[xmit_type].rcvd, 1, qdf_nbuf_len(nbuf)); 4320 4321 if (qdf_unlikely(vdev->mesh_vdev)) { 4322 qdf_nbuf_t nbuf_mesh = dp_tx_extract_mesh_meta_data(vdev, nbuf, 4323 &msdu_info); 4324 if (!nbuf_mesh) { 4325 dp_verbose_debug("Extracting mesh metadata failed"); 4326 return nbuf; 4327 } 4328 nbuf = nbuf_mesh; 4329 } 4330 4331 /* 4332 * Get HW Queue to use for this frame. 4333 * TCL supports upto 4 DMA rings, out of which 3 rings are 4334 * dedicated for data and 1 for command. 4335 * "queue_id" maps to one hardware ring. 4336 * With each ring, we also associate a unique Tx descriptor pool 4337 * to minimize lock contention for these resources. 4338 */ 4339 dp_tx_get_queue(vdev, nbuf, &msdu_info.tx_queue); 4340 DP_STATS_INC(vdev, 4341 tx_i[xmit_type].rcvd_per_core[msdu_info.tx_queue.desc_pool_id], 4342 1); 4343 4344 /* 4345 * TCL H/W supports 2 DSCP-TID mapping tables. 4346 * Table 1 - Default DSCP-TID mapping table 4347 * Table 2 - 1 DSCP-TID override table 4348 * 4349 * If we need a different DSCP-TID mapping for this vap, 4350 * call tid_classify to extract DSCP/ToS from frame and 4351 * map to a TID and store in msdu_info. This is later used 4352 * to fill in TCL Input descriptor (per-packet TID override). 4353 */ 4354 dp_tx_classify_tid(vdev, nbuf, &msdu_info); 4355 4356 /* 4357 * Classify the frame and call corresponding 4358 * "prepare" function which extracts the segment (TSO) 4359 * and fragmentation information (for TSO , SG, ME, or Raw) 4360 * into MSDU_INFO structure which is later used to fill 4361 * SW and HW descriptors. 4362 */ 4363 if (qdf_nbuf_is_tso(nbuf)) { 4364 dp_verbose_debug("TSO frame %pK", vdev); 4365 DP_STATS_INC_PKT(vdev->pdev, tso_stats.num_tso_pkts, 1, 4366 qdf_nbuf_len(nbuf)); 4367 4368 if (dp_tx_prepare_tso(vdev, nbuf, &msdu_info)) { 4369 DP_STATS_INC_PKT(vdev->pdev, tso_stats.dropped_host, 1, 4370 qdf_nbuf_len(nbuf)); 4371 return nbuf; 4372 } 4373 4374 DP_STATS_INC(vdev, tx_i[xmit_type].rcvd.num, 4375 msdu_info.num_seg - 1); 4376 4377 goto send_multiple; 4378 } 4379 4380 /* SG */ 4381 if (qdf_unlikely(qdf_nbuf_is_nonlinear(nbuf))) { 4382 if (qdf_nbuf_get_nr_frags(nbuf) > DP_TX_MAX_NUM_FRAGS - 1) { 4383 if (qdf_unlikely(qdf_nbuf_linearize(nbuf))) 4384 return nbuf; 4385 } else { 4386 struct dp_tx_seg_info_s seg_info = {0}; 4387 4388 if (qdf_unlikely(is_nbuf_frm_rmnet(nbuf, &msdu_info))) 4389 goto send_single; 4390 4391 nbuf = dp_tx_prepare_sg(vdev, nbuf, &seg_info, 4392 &msdu_info); 4393 if (!nbuf) 4394 return NULL; 4395 4396 dp_verbose_debug("non-TSO SG frame %pK", vdev); 4397 4398 DP_STATS_INC_PKT(vdev, tx_i[xmit_type].sg.sg_pkt, 1, 4399 qdf_nbuf_len(nbuf)); 4400 4401 goto send_multiple; 4402 } 4403 } 4404 4405 if (qdf_unlikely(!dp_tx_mcast_enhance(vdev, nbuf))) 4406 return NULL; 4407 4408 if (qdf_unlikely(dp_tx_mcast_drop(vdev, nbuf))) 4409 return nbuf; 4410 4411 /* RAW */ 4412 if (qdf_unlikely(vdev->tx_encap_type == htt_cmn_pkt_type_raw)) { 4413 struct dp_tx_seg_info_s seg_info = {0}; 4414 4415 nbuf = dp_tx_prepare_raw(vdev, nbuf, &seg_info, &msdu_info); 4416 if (!nbuf) 4417 return NULL; 4418 4419 dp_verbose_debug("Raw frame %pK", vdev); 4420 4421 goto send_multiple; 4422 4423 } 4424 4425 if (qdf_unlikely(vdev->nawds_enabled)) { 4426 qdf_ether_header_t *eh = (qdf_ether_header_t *) 4427 qdf_nbuf_data(nbuf); 4428 if (DP_FRAME_IS_MULTICAST((eh)->ether_dhost)) { 4429 uint16_t sa_peer_id = DP_INVALID_PEER; 4430 4431 if (!soc->ast_offload_support) { 4432 struct dp_ast_entry *ast_entry = NULL; 4433 4434 qdf_spin_lock_bh(&soc->ast_lock); 4435 ast_entry = dp_peer_ast_hash_find_by_pdevid 4436 (soc, 4437 (uint8_t *)(eh->ether_shost), 4438 vdev->pdev->pdev_id); 4439 if (ast_entry) 4440 sa_peer_id = ast_entry->peer_id; 4441 qdf_spin_unlock_bh(&soc->ast_lock); 4442 } 4443 4444 dp_tx_nawds_handler(soc, vdev, &msdu_info, nbuf, 4445 sa_peer_id); 4446 } 4447 peer_id = DP_INVALID_PEER; 4448 DP_STATS_INC_PKT(vdev, tx_i[xmit_type].nawds_mcast, 4449 1, qdf_nbuf_len(nbuf)); 4450 } 4451 4452 send_single: 4453 /* Single linear frame */ 4454 /* 4455 * If nbuf is a simple linear frame, use send_single function to 4456 * prepare direct-buffer type TCL descriptor and enqueue to TCL 4457 * SRNG. There is no need to setup a MSDU extension descriptor. 4458 */ 4459 nbuf = dp_tx_send_msdu_single_wrapper(vdev, nbuf, &msdu_info, 4460 peer_id, end_nbuf); 4461 return nbuf; 4462 4463 send_multiple: 4464 nbuf = dp_tx_send_msdu_multiple(vdev, nbuf, &msdu_info); 4465 4466 if (qdf_unlikely(nbuf && msdu_info.frm_type == dp_tx_frm_raw)) 4467 dp_tx_raw_prepare_unset(vdev->pdev->soc, nbuf); 4468 4469 return nbuf; 4470 } 4471 4472 qdf_nbuf_t dp_tx_send_vdev_id_check(struct cdp_soc_t *soc_hdl, 4473 uint8_t vdev_id, qdf_nbuf_t nbuf) 4474 { 4475 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); 4476 struct dp_vdev *vdev = NULL; 4477 uint8_t xmit_type = qdf_nbuf_get_vdev_xmit_type(nbuf); 4478 4479 if (qdf_unlikely(vdev_id >= MAX_VDEV_CNT)) 4480 return nbuf; 4481 4482 /* 4483 * dp_vdev_get_ref_by_id does does a atomic operation avoid using 4484 * this in per packet path. 4485 * 4486 * As in this path vdev memory is already protected with netdev 4487 * tx lock 4488 */ 4489 vdev = soc->vdev_id_map[vdev_id]; 4490 if (qdf_unlikely(!vdev)) 4491 return nbuf; 4492 4493 if (qdf_unlikely(dp_tx_per_pkt_vdev_id_check(nbuf, vdev) 4494 == QDF_STATUS_E_FAILURE)) { 4495 DP_STATS_INC(vdev, 4496 tx_i[xmit_type].dropped.fail_per_pkt_vdev_id_check, 4497 1); 4498 return nbuf; 4499 } 4500 4501 return dp_tx_send(soc_hdl, vdev_id, nbuf); 4502 } 4503 4504 #ifdef UMAC_SUPPORT_PROXY_ARP 4505 /** 4506 * dp_tx_proxy_arp() - Tx proxy arp handler 4507 * @vdev: datapath vdev handle 4508 * @nbuf: sk buffer 4509 * 4510 * Return: status 4511 */ 4512 int dp_tx_proxy_arp(struct dp_vdev *vdev, qdf_nbuf_t nbuf) 4513 { 4514 if (vdev->osif_proxy_arp) 4515 return vdev->osif_proxy_arp(vdev->osif_vdev, nbuf); 4516 4517 /* 4518 * when UMAC_SUPPORT_PROXY_ARP is defined, we expect 4519 * osif_proxy_arp has a valid function pointer assigned 4520 * to it 4521 */ 4522 dp_tx_err("valid function pointer for osif_proxy_arp is expected!!\n"); 4523 4524 return QDF_STATUS_NOT_INITIALIZED; 4525 } 4526 #else 4527 int dp_tx_proxy_arp(struct dp_vdev *vdev, qdf_nbuf_t nbuf) 4528 { 4529 return QDF_STATUS_SUCCESS; 4530 } 4531 #endif 4532 4533 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) && \ 4534 !defined(CONFIG_MLO_SINGLE_DEV) 4535 #ifdef WLAN_MCAST_MLO 4536 static bool 4537 dp_tx_reinject_mlo_hdl(struct dp_soc *soc, struct dp_vdev *vdev, 4538 struct dp_tx_desc_s *tx_desc, 4539 qdf_nbuf_t nbuf, 4540 uint8_t reinject_reason) 4541 { 4542 if (reinject_reason == HTT_TX_FW2WBM_REINJECT_REASON_MLO_MCAST) { 4543 if (soc->arch_ops.dp_tx_mcast_handler) 4544 soc->arch_ops.dp_tx_mcast_handler(soc, vdev, nbuf); 4545 4546 dp_tx_desc_release(soc, tx_desc, tx_desc->pool_id); 4547 return true; 4548 } 4549 4550 return false; 4551 } 4552 #else /* WLAN_MCAST_MLO */ 4553 static inline bool 4554 dp_tx_reinject_mlo_hdl(struct dp_soc *soc, struct dp_vdev *vdev, 4555 struct dp_tx_desc_s *tx_desc, 4556 qdf_nbuf_t nbuf, 4557 uint8_t reinject_reason) 4558 { 4559 return false; 4560 } 4561 #endif /* WLAN_MCAST_MLO */ 4562 #else 4563 static inline bool 4564 dp_tx_reinject_mlo_hdl(struct dp_soc *soc, struct dp_vdev *vdev, 4565 struct dp_tx_desc_s *tx_desc, 4566 qdf_nbuf_t nbuf, 4567 uint8_t reinject_reason) 4568 { 4569 return false; 4570 } 4571 #endif 4572 4573 void dp_tx_reinject_handler(struct dp_soc *soc, 4574 struct dp_vdev *vdev, 4575 struct dp_tx_desc_s *tx_desc, 4576 uint8_t *status, 4577 uint8_t reinject_reason) 4578 { 4579 struct dp_peer *peer = NULL; 4580 uint32_t peer_id = HTT_INVALID_PEER; 4581 qdf_nbuf_t nbuf = tx_desc->nbuf; 4582 qdf_nbuf_t nbuf_copy = NULL; 4583 struct dp_tx_msdu_info_s msdu_info; 4584 #ifdef WDS_VENDOR_EXTENSION 4585 int is_mcast = 0, is_ucast = 0; 4586 int num_peers_3addr = 0; 4587 qdf_ether_header_t *eth_hdr = (qdf_ether_header_t *)(qdf_nbuf_data(nbuf)); 4588 struct ieee80211_frame_addr4 *wh = (struct ieee80211_frame_addr4 *)(qdf_nbuf_data(nbuf)); 4589 #endif 4590 struct dp_txrx_peer *txrx_peer; 4591 uint8_t xmit_type = qdf_nbuf_get_vdev_xmit_type(nbuf); 4592 4593 qdf_assert(vdev); 4594 4595 dp_tx_debug("Tx reinject path"); 4596 4597 DP_STATS_INC_PKT(vdev, tx_i[xmit_type].reinject_pkts, 1, 4598 qdf_nbuf_len(tx_desc->nbuf)); 4599 4600 if (dp_tx_reinject_mlo_hdl(soc, vdev, tx_desc, nbuf, reinject_reason)) 4601 return; 4602 4603 #ifdef WDS_VENDOR_EXTENSION 4604 if (qdf_unlikely(vdev->tx_encap_type != htt_cmn_pkt_type_raw)) { 4605 is_mcast = (IS_MULTICAST(wh->i_addr1)) ? 1 : 0; 4606 } else { 4607 is_mcast = (IS_MULTICAST(eth_hdr->ether_dhost)) ? 1 : 0; 4608 } 4609 is_ucast = !is_mcast; 4610 4611 qdf_spin_lock_bh(&vdev->peer_list_lock); 4612 TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) { 4613 txrx_peer = dp_get_txrx_peer(peer); 4614 4615 if (!txrx_peer || txrx_peer->bss_peer) 4616 continue; 4617 4618 /* Detect wds peers that use 3-addr framing for mcast. 4619 * if there are any, the bss_peer is used to send the 4620 * the mcast frame using 3-addr format. all wds enabled 4621 * peers that use 4-addr framing for mcast frames will 4622 * be duplicated and sent as 4-addr frames below. 4623 */ 4624 if (!txrx_peer->wds_enabled || 4625 !txrx_peer->wds_ecm.wds_tx_mcast_4addr) { 4626 num_peers_3addr = 1; 4627 break; 4628 } 4629 } 4630 qdf_spin_unlock_bh(&vdev->peer_list_lock); 4631 #endif 4632 4633 if (qdf_unlikely(vdev->mesh_vdev)) { 4634 DP_TX_FREE_SINGLE_BUF(vdev->pdev->soc, tx_desc->nbuf); 4635 } else { 4636 qdf_spin_lock_bh(&vdev->peer_list_lock); 4637 TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) { 4638 txrx_peer = dp_get_txrx_peer(peer); 4639 if (!txrx_peer) 4640 continue; 4641 4642 if ((txrx_peer->peer_id != HTT_INVALID_PEER) && 4643 #ifdef WDS_VENDOR_EXTENSION 4644 /* 4645 * . if 3-addr STA, then send on BSS Peer 4646 * . if Peer WDS enabled and accept 4-addr mcast, 4647 * send mcast on that peer only 4648 * . if Peer WDS enabled and accept 4-addr ucast, 4649 * send ucast on that peer only 4650 */ 4651 ((txrx_peer->bss_peer && num_peers_3addr && is_mcast) || 4652 (txrx_peer->wds_enabled && 4653 ((is_mcast && txrx_peer->wds_ecm.wds_tx_mcast_4addr) || 4654 (is_ucast && 4655 txrx_peer->wds_ecm.wds_tx_ucast_4addr))))) { 4656 #else 4657 (txrx_peer->bss_peer && 4658 (dp_tx_proxy_arp(vdev, nbuf) == QDF_STATUS_SUCCESS))) { 4659 #endif 4660 peer_id = DP_INVALID_PEER; 4661 4662 nbuf_copy = qdf_nbuf_copy(nbuf); 4663 4664 if (!nbuf_copy) { 4665 dp_tx_debug("nbuf copy failed"); 4666 break; 4667 } 4668 qdf_mem_zero(&msdu_info, sizeof(msdu_info)); 4669 dp_tx_get_queue(vdev, nbuf, 4670 &msdu_info.tx_queue); 4671 msdu_info.xmit_type = 4672 qdf_nbuf_get_vdev_xmit_type(nbuf); 4673 nbuf_copy = dp_tx_send_msdu_single(vdev, 4674 nbuf_copy, 4675 &msdu_info, 4676 peer_id, 4677 NULL); 4678 4679 if (nbuf_copy) { 4680 dp_tx_debug("pkt send failed"); 4681 qdf_nbuf_free(nbuf_copy); 4682 } 4683 } 4684 } 4685 qdf_spin_unlock_bh(&vdev->peer_list_lock); 4686 4687 qdf_nbuf_unmap_nbytes_single(vdev->osdev, nbuf, 4688 QDF_DMA_TO_DEVICE, nbuf->len); 4689 qdf_nbuf_free(nbuf); 4690 } 4691 4692 dp_tx_desc_release(soc, tx_desc, tx_desc->pool_id); 4693 } 4694 4695 void dp_tx_inspect_handler(struct dp_soc *soc, 4696 struct dp_vdev *vdev, 4697 struct dp_tx_desc_s *tx_desc, 4698 uint8_t *status) 4699 { 4700 uint8_t xmit_type = qdf_nbuf_get_vdev_xmit_type(tx_desc->nbuf); 4701 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, 4702 "%s Tx inspect path", 4703 __func__); 4704 4705 DP_STATS_INC_PKT(vdev, tx_i[xmit_type].inspect_pkts, 1, 4706 qdf_nbuf_len(tx_desc->nbuf)); 4707 4708 DP_TX_FREE_SINGLE_BUF(soc, tx_desc->nbuf); 4709 dp_tx_desc_release(soc, tx_desc, tx_desc->pool_id); 4710 } 4711 4712 #ifdef MESH_MODE_SUPPORT 4713 /** 4714 * dp_tx_comp_fill_tx_completion_stats() - Fill per packet Tx completion stats 4715 * in mesh meta header 4716 * @tx_desc: software descriptor head pointer 4717 * @ts: pointer to tx completion stats 4718 * Return: none 4719 */ 4720 static 4721 void dp_tx_comp_fill_tx_completion_stats(struct dp_tx_desc_s *tx_desc, 4722 struct hal_tx_completion_status *ts) 4723 { 4724 qdf_nbuf_t netbuf = tx_desc->nbuf; 4725 4726 if (!tx_desc->msdu_ext_desc) { 4727 if (qdf_nbuf_pull_head(netbuf, tx_desc->pkt_offset) == NULL) { 4728 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 4729 "netbuf %pK offset %d", 4730 netbuf, tx_desc->pkt_offset); 4731 return; 4732 } 4733 } 4734 } 4735 4736 #else 4737 static 4738 void dp_tx_comp_fill_tx_completion_stats(struct dp_tx_desc_s *tx_desc, 4739 struct hal_tx_completion_status *ts) 4740 { 4741 } 4742 4743 #endif 4744 4745 #ifdef CONFIG_SAWF 4746 static void dp_tx_update_peer_sawf_stats(struct dp_soc *soc, 4747 struct dp_vdev *vdev, 4748 struct dp_txrx_peer *txrx_peer, 4749 struct dp_tx_desc_s *tx_desc, 4750 struct hal_tx_completion_status *ts, 4751 uint8_t tid) 4752 { 4753 dp_sawf_tx_compl_update_peer_stats(soc, vdev, txrx_peer, tx_desc, 4754 ts, tid); 4755 } 4756 4757 static void dp_tx_compute_delay_avg(struct cdp_delay_tx_stats *tx_delay, 4758 uint32_t nw_delay, 4759 uint32_t sw_delay, 4760 uint32_t hw_delay) 4761 { 4762 dp_peer_tid_delay_avg(tx_delay, 4763 nw_delay, 4764 sw_delay, 4765 hw_delay); 4766 } 4767 #else 4768 static void dp_tx_update_peer_sawf_stats(struct dp_soc *soc, 4769 struct dp_vdev *vdev, 4770 struct dp_txrx_peer *txrx_peer, 4771 struct dp_tx_desc_s *tx_desc, 4772 struct hal_tx_completion_status *ts, 4773 uint8_t tid) 4774 { 4775 } 4776 4777 static inline void 4778 dp_tx_compute_delay_avg(struct cdp_delay_tx_stats *tx_delay, 4779 uint32_t nw_delay, uint32_t sw_delay, 4780 uint32_t hw_delay) 4781 { 4782 } 4783 #endif 4784 4785 #ifdef QCA_PEER_EXT_STATS 4786 #ifdef WLAN_CONFIG_TX_DELAY 4787 static void dp_tx_compute_tid_delay(struct cdp_delay_tid_stats *stats, 4788 struct dp_tx_desc_s *tx_desc, 4789 struct hal_tx_completion_status *ts, 4790 struct dp_vdev *vdev) 4791 { 4792 struct dp_soc *soc = vdev->pdev->soc; 4793 struct cdp_delay_tx_stats *tx_delay = &stats->tx_delay; 4794 int64_t timestamp_ingress, timestamp_hw_enqueue; 4795 uint32_t sw_enqueue_delay, fwhw_transmit_delay = 0; 4796 4797 if (!ts->valid) 4798 return; 4799 4800 timestamp_ingress = qdf_nbuf_get_timestamp_us(tx_desc->nbuf); 4801 timestamp_hw_enqueue = qdf_ktime_to_us(tx_desc->timestamp); 4802 4803 sw_enqueue_delay = (uint32_t)(timestamp_hw_enqueue - timestamp_ingress); 4804 dp_hist_update_stats(&tx_delay->tx_swq_delay, sw_enqueue_delay); 4805 4806 if (soc->arch_ops.dp_tx_compute_hw_delay) 4807 if (!soc->arch_ops.dp_tx_compute_hw_delay(soc, vdev, ts, 4808 &fwhw_transmit_delay)) 4809 dp_hist_update_stats(&tx_delay->hwtx_delay, 4810 fwhw_transmit_delay); 4811 4812 dp_tx_compute_delay_avg(tx_delay, 0, sw_enqueue_delay, 4813 fwhw_transmit_delay); 4814 } 4815 #else 4816 /** 4817 * dp_tx_compute_tid_delay() - Compute per TID delay 4818 * @stats: Per TID delay stats 4819 * @tx_desc: Software Tx descriptor 4820 * @ts: Tx completion status 4821 * @vdev: vdev 4822 * 4823 * Compute the software enqueue and hw enqueue delays and 4824 * update the respective histograms 4825 * 4826 * Return: void 4827 */ 4828 static void dp_tx_compute_tid_delay(struct cdp_delay_tid_stats *stats, 4829 struct dp_tx_desc_s *tx_desc, 4830 struct hal_tx_completion_status *ts, 4831 struct dp_vdev *vdev) 4832 { 4833 struct cdp_delay_tx_stats *tx_delay = &stats->tx_delay; 4834 int64_t current_timestamp, timestamp_ingress, timestamp_hw_enqueue; 4835 uint32_t sw_enqueue_delay, fwhw_transmit_delay; 4836 4837 current_timestamp = qdf_ktime_to_ms(qdf_ktime_real_get()); 4838 timestamp_ingress = qdf_nbuf_get_timestamp(tx_desc->nbuf); 4839 timestamp_hw_enqueue = qdf_ktime_to_ms(tx_desc->timestamp); 4840 sw_enqueue_delay = (uint32_t)(timestamp_hw_enqueue - timestamp_ingress); 4841 fwhw_transmit_delay = (uint32_t)(current_timestamp - 4842 timestamp_hw_enqueue); 4843 4844 /* 4845 * Update the Tx software enqueue delay and HW enque-Completion delay. 4846 */ 4847 dp_hist_update_stats(&tx_delay->tx_swq_delay, sw_enqueue_delay); 4848 dp_hist_update_stats(&tx_delay->hwtx_delay, fwhw_transmit_delay); 4849 } 4850 #endif 4851 4852 /** 4853 * dp_tx_update_peer_delay_stats() - Update the peer delay stats 4854 * @txrx_peer: DP peer context 4855 * @tx_desc: Tx software descriptor 4856 * @ts: Tx completion status 4857 * @ring_id: Rx CPU context ID/CPU_ID 4858 * 4859 * Update the peer extended stats. These are enhanced other 4860 * delay stats per msdu level. 4861 * 4862 * Return: void 4863 */ 4864 static void dp_tx_update_peer_delay_stats(struct dp_txrx_peer *txrx_peer, 4865 struct dp_tx_desc_s *tx_desc, 4866 struct hal_tx_completion_status *ts, 4867 uint8_t ring_id) 4868 { 4869 struct dp_pdev *pdev = txrx_peer->vdev->pdev; 4870 struct dp_soc *soc = NULL; 4871 struct dp_peer_delay_stats *delay_stats = NULL; 4872 uint8_t tid; 4873 4874 soc = pdev->soc; 4875 if (qdf_likely(!wlan_cfg_is_peer_ext_stats_enabled(soc->wlan_cfg_ctx))) 4876 return; 4877 4878 if (!txrx_peer->delay_stats) 4879 return; 4880 4881 tid = ts->tid; 4882 delay_stats = txrx_peer->delay_stats; 4883 4884 /* 4885 * For non-TID packets use the TID 9 4886 */ 4887 if (qdf_unlikely(tid >= CDP_MAX_DATA_TIDS)) 4888 tid = CDP_MAX_DATA_TIDS - 1; 4889 4890 dp_tx_compute_tid_delay(&delay_stats->delay_tid_stats[tid][ring_id], 4891 tx_desc, ts, txrx_peer->vdev); 4892 } 4893 #else 4894 static inline 4895 void dp_tx_update_peer_delay_stats(struct dp_txrx_peer *txrx_peer, 4896 struct dp_tx_desc_s *tx_desc, 4897 struct hal_tx_completion_status *ts, 4898 uint8_t ring_id) 4899 { 4900 } 4901 #endif 4902 4903 #ifdef WLAN_PEER_JITTER 4904 /** 4905 * dp_tx_jitter_get_avg_jitter() - compute the average jitter 4906 * @curr_delay: Current delay 4907 * @prev_delay: Previous delay 4908 * @avg_jitter: Average Jitter 4909 * Return: Newly Computed Average Jitter 4910 */ 4911 static uint32_t dp_tx_jitter_get_avg_jitter(uint32_t curr_delay, 4912 uint32_t prev_delay, 4913 uint32_t avg_jitter) 4914 { 4915 uint32_t curr_jitter; 4916 int32_t jitter_diff; 4917 4918 curr_jitter = qdf_abs(curr_delay - prev_delay); 4919 if (!avg_jitter) 4920 return curr_jitter; 4921 4922 jitter_diff = curr_jitter - avg_jitter; 4923 if (jitter_diff < 0) 4924 avg_jitter = avg_jitter - 4925 (qdf_abs(jitter_diff) >> DP_AVG_JITTER_WEIGHT_DENOM); 4926 else 4927 avg_jitter = avg_jitter + 4928 (qdf_abs(jitter_diff) >> DP_AVG_JITTER_WEIGHT_DENOM); 4929 4930 return avg_jitter; 4931 } 4932 4933 /** 4934 * dp_tx_jitter_get_avg_delay() - compute the average delay 4935 * @curr_delay: Current delay 4936 * @avg_delay: Average delay 4937 * Return: Newly Computed Average Delay 4938 */ 4939 static uint32_t dp_tx_jitter_get_avg_delay(uint32_t curr_delay, 4940 uint32_t avg_delay) 4941 { 4942 int32_t delay_diff; 4943 4944 if (!avg_delay) 4945 return curr_delay; 4946 4947 delay_diff = curr_delay - avg_delay; 4948 if (delay_diff < 0) 4949 avg_delay = avg_delay - (qdf_abs(delay_diff) >> 4950 DP_AVG_DELAY_WEIGHT_DENOM); 4951 else 4952 avg_delay = avg_delay + (qdf_abs(delay_diff) >> 4953 DP_AVG_DELAY_WEIGHT_DENOM); 4954 4955 return avg_delay; 4956 } 4957 4958 #ifdef WLAN_CONFIG_TX_DELAY 4959 /** 4960 * dp_tx_compute_cur_delay() - get the current delay 4961 * @soc: soc handle 4962 * @vdev: vdev structure for data path state 4963 * @ts: Tx completion status 4964 * @curr_delay: current delay 4965 * @tx_desc: tx descriptor 4966 * Return: void 4967 */ 4968 static 4969 QDF_STATUS dp_tx_compute_cur_delay(struct dp_soc *soc, 4970 struct dp_vdev *vdev, 4971 struct hal_tx_completion_status *ts, 4972 uint32_t *curr_delay, 4973 struct dp_tx_desc_s *tx_desc) 4974 { 4975 QDF_STATUS status = QDF_STATUS_E_FAILURE; 4976 4977 if (soc->arch_ops.dp_tx_compute_hw_delay) 4978 status = soc->arch_ops.dp_tx_compute_hw_delay(soc, vdev, ts, 4979 curr_delay); 4980 return status; 4981 } 4982 #else 4983 static 4984 QDF_STATUS dp_tx_compute_cur_delay(struct dp_soc *soc, 4985 struct dp_vdev *vdev, 4986 struct hal_tx_completion_status *ts, 4987 uint32_t *curr_delay, 4988 struct dp_tx_desc_s *tx_desc) 4989 { 4990 int64_t current_timestamp, timestamp_hw_enqueue; 4991 4992 current_timestamp = qdf_ktime_to_us(qdf_ktime_real_get()); 4993 timestamp_hw_enqueue = qdf_ktime_to_us(tx_desc->timestamp); 4994 *curr_delay = (uint32_t)(current_timestamp - timestamp_hw_enqueue); 4995 4996 return QDF_STATUS_SUCCESS; 4997 } 4998 #endif 4999 5000 /** 5001 * dp_tx_compute_tid_jitter() - compute per tid per ring jitter 5002 * @jitter: per tid per ring jitter stats 5003 * @ts: Tx completion status 5004 * @vdev: vdev structure for data path state 5005 * @tx_desc: tx descriptor 5006 * Return: void 5007 */ 5008 static void dp_tx_compute_tid_jitter(struct cdp_peer_tid_stats *jitter, 5009 struct hal_tx_completion_status *ts, 5010 struct dp_vdev *vdev, 5011 struct dp_tx_desc_s *tx_desc) 5012 { 5013 uint32_t curr_delay, avg_delay, avg_jitter, prev_delay; 5014 struct dp_soc *soc = vdev->pdev->soc; 5015 QDF_STATUS status = QDF_STATUS_E_FAILURE; 5016 5017 if (ts->status != HAL_TX_TQM_RR_FRAME_ACKED) { 5018 jitter->tx_drop += 1; 5019 return; 5020 } 5021 5022 status = dp_tx_compute_cur_delay(soc, vdev, ts, &curr_delay, 5023 tx_desc); 5024 5025 if (QDF_IS_STATUS_SUCCESS(status)) { 5026 avg_delay = jitter->tx_avg_delay; 5027 avg_jitter = jitter->tx_avg_jitter; 5028 prev_delay = jitter->tx_prev_delay; 5029 avg_jitter = dp_tx_jitter_get_avg_jitter(curr_delay, 5030 prev_delay, 5031 avg_jitter); 5032 avg_delay = dp_tx_jitter_get_avg_delay(curr_delay, avg_delay); 5033 jitter->tx_avg_delay = avg_delay; 5034 jitter->tx_avg_jitter = avg_jitter; 5035 jitter->tx_prev_delay = curr_delay; 5036 jitter->tx_total_success += 1; 5037 } else if (status == QDF_STATUS_E_FAILURE) { 5038 jitter->tx_avg_err += 1; 5039 } 5040 } 5041 5042 /* dp_tx_update_peer_jitter_stats() - Update the peer jitter stats 5043 * @txrx_peer: DP peer context 5044 * @tx_desc: Tx software descriptor 5045 * @ts: Tx completion status 5046 * @ring_id: Rx CPU context ID/CPU_ID 5047 * Return: void 5048 */ 5049 static void dp_tx_update_peer_jitter_stats(struct dp_txrx_peer *txrx_peer, 5050 struct dp_tx_desc_s *tx_desc, 5051 struct hal_tx_completion_status *ts, 5052 uint8_t ring_id) 5053 { 5054 struct dp_pdev *pdev = txrx_peer->vdev->pdev; 5055 struct dp_soc *soc = pdev->soc; 5056 struct cdp_peer_tid_stats *jitter_stats = NULL; 5057 uint8_t tid; 5058 struct cdp_peer_tid_stats *rx_tid = NULL; 5059 5060 if (qdf_likely(!wlan_cfg_is_peer_jitter_stats_enabled(soc->wlan_cfg_ctx))) 5061 return; 5062 5063 if (!txrx_peer->jitter_stats) 5064 return; 5065 5066 tid = ts->tid; 5067 jitter_stats = txrx_peer->jitter_stats; 5068 5069 /* 5070 * For non-TID packets use the TID 9 5071 */ 5072 if (qdf_unlikely(tid >= CDP_MAX_DATA_TIDS)) 5073 tid = CDP_MAX_DATA_TIDS - 1; 5074 5075 rx_tid = &jitter_stats[tid * CDP_MAX_TXRX_CTX + ring_id]; 5076 dp_tx_compute_tid_jitter(rx_tid, 5077 ts, txrx_peer->vdev, tx_desc); 5078 } 5079 #else 5080 static void dp_tx_update_peer_jitter_stats(struct dp_txrx_peer *txrx_peer, 5081 struct dp_tx_desc_s *tx_desc, 5082 struct hal_tx_completion_status *ts, 5083 uint8_t ring_id) 5084 { 5085 } 5086 #endif 5087 5088 #ifdef HW_TX_DELAY_STATS_ENABLE 5089 /** 5090 * dp_update_tx_delay_stats() - update the delay stats 5091 * @vdev: vdev handle 5092 * @delay: delay in ms or us based on the flag delay_in_us 5093 * @tid: tid value 5094 * @mode: type of tx delay mode 5095 * @ring_id: ring number 5096 * @delay_in_us: flag to indicate whether the delay is in ms or us 5097 * 5098 * Return: none 5099 */ 5100 static inline 5101 void dp_update_tx_delay_stats(struct dp_vdev *vdev, uint32_t delay, uint8_t tid, 5102 uint8_t mode, uint8_t ring_id, bool delay_in_us) 5103 { 5104 struct cdp_tid_tx_stats *tstats = 5105 &vdev->stats.tid_tx_stats[ring_id][tid]; 5106 5107 dp_update_delay_stats(tstats, NULL, delay, tid, mode, ring_id, 5108 delay_in_us); 5109 } 5110 #else 5111 static inline 5112 void dp_update_tx_delay_stats(struct dp_vdev *vdev, uint32_t delay, uint8_t tid, 5113 uint8_t mode, uint8_t ring_id, bool delay_in_us) 5114 { 5115 struct cdp_tid_tx_stats *tstats = 5116 &vdev->pdev->stats.tid_stats.tid_tx_stats[ring_id][tid]; 5117 5118 dp_update_delay_stats(tstats, NULL, delay, tid, mode, ring_id, 5119 delay_in_us); 5120 } 5121 #endif 5122 5123 void dp_tx_compute_delay(struct dp_vdev *vdev, struct dp_tx_desc_s *tx_desc, 5124 uint8_t tid, uint8_t ring_id) 5125 { 5126 int64_t current_timestamp, timestamp_ingress, timestamp_hw_enqueue; 5127 uint32_t sw_enqueue_delay, fwhw_transmit_delay, interframe_delay; 5128 uint32_t fwhw_transmit_delay_us; 5129 5130 if (qdf_likely(!vdev->pdev->delay_stats_flag) && 5131 qdf_likely(!dp_is_vdev_tx_delay_stats_enabled(vdev))) 5132 return; 5133 5134 if (dp_is_vdev_tx_delay_stats_enabled(vdev)) { 5135 fwhw_transmit_delay_us = 5136 qdf_ktime_to_us(qdf_ktime_real_get()) - 5137 qdf_ktime_to_us(tx_desc->timestamp); 5138 5139 /* 5140 * Delay between packet enqueued to HW and Tx completion in us 5141 */ 5142 dp_update_tx_delay_stats(vdev, fwhw_transmit_delay_us, tid, 5143 CDP_DELAY_STATS_FW_HW_TRANSMIT, 5144 ring_id, true); 5145 /* 5146 * For MCL, only enqueue to completion delay is required 5147 * so return if the vdev flag is enabled. 5148 */ 5149 return; 5150 } 5151 5152 current_timestamp = qdf_ktime_to_ms(qdf_ktime_real_get()); 5153 timestamp_hw_enqueue = qdf_ktime_to_ms(tx_desc->timestamp); 5154 fwhw_transmit_delay = (uint32_t)(current_timestamp - 5155 timestamp_hw_enqueue); 5156 5157 if (!timestamp_hw_enqueue) 5158 return; 5159 /* 5160 * Delay between packet enqueued to HW and Tx completion in ms 5161 */ 5162 dp_update_tx_delay_stats(vdev, fwhw_transmit_delay, tid, 5163 CDP_DELAY_STATS_FW_HW_TRANSMIT, ring_id, 5164 false); 5165 5166 timestamp_ingress = qdf_nbuf_get_timestamp(tx_desc->nbuf); 5167 sw_enqueue_delay = (uint32_t)(timestamp_hw_enqueue - timestamp_ingress); 5168 interframe_delay = (uint32_t)(timestamp_ingress - 5169 vdev->prev_tx_enq_tstamp); 5170 5171 /* 5172 * Delay in software enqueue 5173 */ 5174 dp_update_tx_delay_stats(vdev, sw_enqueue_delay, tid, 5175 CDP_DELAY_STATS_SW_ENQ, ring_id, 5176 false); 5177 5178 /* 5179 * Update interframe delay stats calculated at hardstart receive point. 5180 * Value of vdev->prev_tx_enq_tstamp will be 0 for 1st frame, so 5181 * interframe delay will not be calculate correctly for 1st frame. 5182 * On the other side, this will help in avoiding extra per packet check 5183 * of !vdev->prev_tx_enq_tstamp. 5184 */ 5185 dp_update_tx_delay_stats(vdev, interframe_delay, tid, 5186 CDP_DELAY_STATS_TX_INTERFRAME, ring_id, 5187 false); 5188 vdev->prev_tx_enq_tstamp = timestamp_ingress; 5189 } 5190 5191 #ifdef DISABLE_DP_STATS 5192 static 5193 inline void dp_update_no_ack_stats(qdf_nbuf_t nbuf, 5194 struct dp_txrx_peer *txrx_peer, 5195 uint8_t link_id) 5196 { 5197 } 5198 #else 5199 static inline void 5200 dp_update_no_ack_stats(qdf_nbuf_t nbuf, struct dp_txrx_peer *txrx_peer, 5201 uint8_t link_id) 5202 { 5203 enum qdf_proto_subtype subtype = QDF_PROTO_INVALID; 5204 5205 DPTRACE(qdf_dp_track_noack_check(nbuf, &subtype)); 5206 if (subtype != QDF_PROTO_INVALID) 5207 DP_PEER_PER_PKT_STATS_INC(txrx_peer, tx.no_ack_count[subtype], 5208 1, link_id); 5209 } 5210 #endif 5211 5212 #ifndef QCA_ENHANCED_STATS_SUPPORT 5213 #ifdef DP_PEER_EXTENDED_API 5214 static inline uint8_t 5215 dp_tx_get_mpdu_retry_threshold(struct dp_txrx_peer *txrx_peer) 5216 { 5217 return txrx_peer->mpdu_retry_threshold; 5218 } 5219 #else 5220 static inline uint8_t 5221 dp_tx_get_mpdu_retry_threshold(struct dp_txrx_peer *txrx_peer) 5222 { 5223 return 0; 5224 } 5225 #endif 5226 5227 /** 5228 * dp_tx_update_peer_extd_stats()- Update Tx extended path stats for peer 5229 * 5230 * @ts: Tx compltion status 5231 * @txrx_peer: datapath txrx_peer handle 5232 * @link_id: Link id 5233 * 5234 * Return: void 5235 */ 5236 static inline void 5237 dp_tx_update_peer_extd_stats(struct hal_tx_completion_status *ts, 5238 struct dp_txrx_peer *txrx_peer, uint8_t link_id) 5239 { 5240 uint8_t mcs, pkt_type, dst_mcs_idx; 5241 uint8_t retry_threshold = dp_tx_get_mpdu_retry_threshold(txrx_peer); 5242 5243 mcs = ts->mcs; 5244 pkt_type = ts->pkt_type; 5245 /* do HW to SW pkt type conversion */ 5246 pkt_type = (pkt_type >= HAL_DOT11_MAX ? DOT11_MAX : 5247 hal_2_dp_pkt_type_map[pkt_type]); 5248 5249 dst_mcs_idx = dp_get_mcs_array_index_by_pkt_type_mcs(pkt_type, mcs); 5250 if (MCS_INVALID_ARRAY_INDEX != dst_mcs_idx) 5251 DP_PEER_EXTD_STATS_INC(txrx_peer, 5252 tx.pkt_type[pkt_type].mcs_count[dst_mcs_idx], 5253 1, link_id); 5254 5255 DP_PEER_EXTD_STATS_INC(txrx_peer, tx.sgi_count[ts->sgi], 1, link_id); 5256 DP_PEER_EXTD_STATS_INC(txrx_peer, tx.bw[ts->bw], 1, link_id); 5257 DP_PEER_EXTD_STATS_UPD(txrx_peer, tx.last_ack_rssi, ts->ack_frame_rssi, 5258 link_id); 5259 DP_PEER_EXTD_STATS_INC(txrx_peer, 5260 tx.wme_ac_type[TID_TO_WME_AC(ts->tid)], 1, 5261 link_id); 5262 DP_PEER_EXTD_STATS_INCC(txrx_peer, tx.stbc, 1, ts->stbc, link_id); 5263 DP_PEER_EXTD_STATS_INCC(txrx_peer, tx.ldpc, 1, ts->ldpc, link_id); 5264 DP_PEER_EXTD_STATS_INCC(txrx_peer, tx.retries, 1, ts->transmit_cnt > 1, 5265 link_id); 5266 if (ts->first_msdu) { 5267 DP_PEER_EXTD_STATS_INCC(txrx_peer, tx.retries_mpdu, 1, 5268 ts->transmit_cnt > 1, link_id); 5269 5270 if (!retry_threshold) 5271 return; 5272 DP_PEER_EXTD_STATS_INCC(txrx_peer, tx.mpdu_success_with_retries, 5273 qdf_do_div(ts->transmit_cnt, 5274 retry_threshold), 5275 ts->transmit_cnt > retry_threshold, 5276 link_id); 5277 } 5278 } 5279 #else 5280 static inline void 5281 dp_tx_update_peer_extd_stats(struct hal_tx_completion_status *ts, 5282 struct dp_txrx_peer *txrx_peer, uint8_t link_id) 5283 { 5284 } 5285 #endif 5286 5287 #if defined(WLAN_FEATURE_11BE_MLO) && \ 5288 (defined(QCA_ENHANCED_STATS_SUPPORT) || \ 5289 defined(DP_MLO_LINK_STATS_SUPPORT)) 5290 static inline uint8_t 5291 dp_tx_get_link_id_from_ppdu_id(struct dp_soc *soc, 5292 struct hal_tx_completion_status *ts, 5293 struct dp_txrx_peer *txrx_peer, 5294 struct dp_vdev *vdev) 5295 { 5296 uint8_t hw_link_id = 0; 5297 uint32_t ppdu_id; 5298 uint8_t link_id_offset, link_id_bits; 5299 5300 if (!txrx_peer->is_mld_peer || !vdev->pdev->link_peer_stats) 5301 return 0; 5302 5303 link_id_offset = soc->link_id_offset; 5304 link_id_bits = soc->link_id_bits; 5305 ppdu_id = ts->ppdu_id; 5306 hw_link_id = ((DP_GET_HW_LINK_ID_FRM_PPDU_ID(ppdu_id, link_id_offset, 5307 link_id_bits)) + 1); 5308 if (hw_link_id > DP_MAX_MLO_LINKS) { 5309 hw_link_id = 0; 5310 DP_PEER_PER_PKT_STATS_INC( 5311 txrx_peer, 5312 tx.inval_link_id_pkt_cnt, 1, hw_link_id); 5313 } 5314 5315 return hw_link_id; 5316 } 5317 #else 5318 static inline uint8_t 5319 dp_tx_get_link_id_from_ppdu_id(struct dp_soc *soc, 5320 struct hal_tx_completion_status *ts, 5321 struct dp_txrx_peer *txrx_peer, 5322 struct dp_vdev *vdev) 5323 { 5324 return 0; 5325 } 5326 #endif 5327 5328 /** 5329 * dp_tx_update_peer_stats() - Update peer stats from Tx completion indications 5330 * per wbm ring 5331 * 5332 * @tx_desc: software descriptor head pointer 5333 * @ts: Tx completion status 5334 * @txrx_peer: peer handle 5335 * @ring_id: ring number 5336 * @link_id: Link id 5337 * 5338 * Return: None 5339 */ 5340 static inline void 5341 dp_tx_update_peer_stats(struct dp_tx_desc_s *tx_desc, 5342 struct hal_tx_completion_status *ts, 5343 struct dp_txrx_peer *txrx_peer, uint8_t ring_id, 5344 uint8_t link_id) 5345 { 5346 struct dp_pdev *pdev = txrx_peer->vdev->pdev; 5347 uint8_t tid = ts->tid; 5348 uint32_t length; 5349 struct cdp_tid_tx_stats *tid_stats; 5350 5351 if (!pdev) 5352 return; 5353 5354 if (qdf_unlikely(tid >= CDP_MAX_DATA_TIDS)) 5355 tid = CDP_MAX_DATA_TIDS - 1; 5356 5357 tid_stats = &pdev->stats.tid_stats.tid_tx_stats[ring_id][tid]; 5358 5359 if (ts->release_src != HAL_TX_COMP_RELEASE_SOURCE_TQM) { 5360 dp_err_rl("Release source:%d is not from TQM", ts->release_src); 5361 DP_PEER_PER_PKT_STATS_INC(txrx_peer, tx.release_src_not_tqm, 1, 5362 link_id); 5363 return; 5364 } 5365 5366 length = qdf_nbuf_len(tx_desc->nbuf); 5367 DP_PEER_STATS_FLAT_INC_PKT(txrx_peer, comp_pkt, 1, length); 5368 5369 if (qdf_unlikely(pdev->delay_stats_flag) || 5370 qdf_unlikely(dp_is_vdev_tx_delay_stats_enabled(txrx_peer->vdev))) 5371 dp_tx_compute_delay(txrx_peer->vdev, tx_desc, tid, ring_id); 5372 5373 if (ts->status < CDP_MAX_TX_TQM_STATUS) { 5374 tid_stats->tqm_status_cnt[ts->status]++; 5375 } 5376 5377 if (qdf_likely(ts->status == HAL_TX_TQM_RR_FRAME_ACKED)) { 5378 DP_PEER_PER_PKT_STATS_INCC(txrx_peer, tx.retry_count, 1, 5379 ts->transmit_cnt > 1, link_id); 5380 5381 DP_PEER_PER_PKT_STATS_INCC(txrx_peer, tx.multiple_retry_count, 5382 1, ts->transmit_cnt > 2, link_id); 5383 5384 DP_PEER_PER_PKT_STATS_INCC(txrx_peer, tx.ofdma, 1, ts->ofdma, 5385 link_id); 5386 5387 DP_PEER_PER_PKT_STATS_INCC(txrx_peer, tx.amsdu_cnt, 1, 5388 ts->msdu_part_of_amsdu, link_id); 5389 DP_PEER_PER_PKT_STATS_INCC(txrx_peer, tx.non_amsdu_cnt, 1, 5390 !ts->msdu_part_of_amsdu, link_id); 5391 5392 txrx_peer->stats[link_id].per_pkt_stats.tx.last_tx_ts = 5393 qdf_system_ticks(); 5394 5395 dp_tx_update_peer_extd_stats(ts, txrx_peer, link_id); 5396 5397 return; 5398 } 5399 5400 /* 5401 * tx_failed is ideally supposed to be updated from HTT ppdu 5402 * completion stats. But in IPQ807X/IPQ6018 chipsets owing to 5403 * hw limitation there are no completions for failed cases. 5404 * Hence updating tx_failed from data path. Please note that 5405 * if tx_failed is fixed to be from ppdu, then this has to be 5406 * removed 5407 */ 5408 DP_PEER_STATS_FLAT_INC(txrx_peer, tx_failed, 1); 5409 5410 DP_PEER_PER_PKT_STATS_INCC(txrx_peer, tx.failed_retry_count, 1, 5411 ts->transmit_cnt > DP_RETRY_COUNT, 5412 link_id); 5413 dp_update_no_ack_stats(tx_desc->nbuf, txrx_peer, link_id); 5414 5415 if (ts->status == HAL_TX_TQM_RR_REM_CMD_AGED) { 5416 DP_PEER_PER_PKT_STATS_INC(txrx_peer, tx.dropped.age_out, 1, 5417 link_id); 5418 } else if (ts->status == HAL_TX_TQM_RR_REM_CMD_REM) { 5419 DP_PEER_PER_PKT_STATS_INC_PKT(txrx_peer, tx.dropped.fw_rem, 1, 5420 length, link_id); 5421 } else if (ts->status == HAL_TX_TQM_RR_REM_CMD_NOTX) { 5422 DP_PEER_PER_PKT_STATS_INC(txrx_peer, tx.dropped.fw_rem_notx, 1, 5423 link_id); 5424 } else if (ts->status == HAL_TX_TQM_RR_REM_CMD_TX) { 5425 DP_PEER_PER_PKT_STATS_INC(txrx_peer, tx.dropped.fw_rem_tx, 1, 5426 link_id); 5427 } else if (ts->status == HAL_TX_TQM_RR_FW_REASON1) { 5428 DP_PEER_PER_PKT_STATS_INC(txrx_peer, tx.dropped.fw_reason1, 1, 5429 link_id); 5430 } else if (ts->status == HAL_TX_TQM_RR_FW_REASON2) { 5431 DP_PEER_PER_PKT_STATS_INC(txrx_peer, tx.dropped.fw_reason2, 1, 5432 link_id); 5433 } else if (ts->status == HAL_TX_TQM_RR_FW_REASON3) { 5434 DP_PEER_PER_PKT_STATS_INC(txrx_peer, tx.dropped.fw_reason3, 1, 5435 link_id); 5436 } else if (ts->status == HAL_TX_TQM_RR_REM_CMD_DISABLE_QUEUE) { 5437 DP_PEER_PER_PKT_STATS_INC(txrx_peer, 5438 tx.dropped.fw_rem_queue_disable, 1, 5439 link_id); 5440 } else if (ts->status == HAL_TX_TQM_RR_REM_CMD_TILL_NONMATCHING) { 5441 DP_PEER_PER_PKT_STATS_INC(txrx_peer, 5442 tx.dropped.fw_rem_no_match, 1, 5443 link_id); 5444 } else if (ts->status == HAL_TX_TQM_RR_DROP_THRESHOLD) { 5445 DP_PEER_PER_PKT_STATS_INC(txrx_peer, 5446 tx.dropped.drop_threshold, 1, 5447 link_id); 5448 } else if (ts->status == HAL_TX_TQM_RR_LINK_DESC_UNAVAILABLE) { 5449 DP_PEER_PER_PKT_STATS_INC(txrx_peer, 5450 tx.dropped.drop_link_desc_na, 1, 5451 link_id); 5452 } else if (ts->status == HAL_TX_TQM_RR_DROP_OR_INVALID_MSDU) { 5453 DP_PEER_PER_PKT_STATS_INC(txrx_peer, 5454 tx.dropped.invalid_drop, 1, 5455 link_id); 5456 } else if (ts->status == HAL_TX_TQM_RR_MULTICAST_DROP) { 5457 DP_PEER_PER_PKT_STATS_INC(txrx_peer, 5458 tx.dropped.mcast_vdev_drop, 1, 5459 link_id); 5460 } else { 5461 DP_PEER_PER_PKT_STATS_INC(txrx_peer, tx.dropped.invalid_rr, 1, 5462 link_id); 5463 } 5464 } 5465 5466 #ifdef QCA_LL_TX_FLOW_CONTROL_V2 5467 /** 5468 * dp_tx_flow_pool_lock() - take flow pool lock 5469 * @soc: core txrx main context 5470 * @tx_desc: tx desc 5471 * 5472 * Return: None 5473 */ 5474 static inline 5475 void dp_tx_flow_pool_lock(struct dp_soc *soc, 5476 struct dp_tx_desc_s *tx_desc) 5477 { 5478 struct dp_tx_desc_pool_s *pool; 5479 uint8_t desc_pool_id; 5480 5481 desc_pool_id = tx_desc->pool_id; 5482 pool = &soc->tx_desc[desc_pool_id]; 5483 5484 qdf_spin_lock_bh(&pool->flow_pool_lock); 5485 } 5486 5487 /** 5488 * dp_tx_flow_pool_unlock() - release flow pool lock 5489 * @soc: core txrx main context 5490 * @tx_desc: tx desc 5491 * 5492 * Return: None 5493 */ 5494 static inline 5495 void dp_tx_flow_pool_unlock(struct dp_soc *soc, 5496 struct dp_tx_desc_s *tx_desc) 5497 { 5498 struct dp_tx_desc_pool_s *pool; 5499 uint8_t desc_pool_id; 5500 5501 desc_pool_id = tx_desc->pool_id; 5502 pool = &soc->tx_desc[desc_pool_id]; 5503 5504 qdf_spin_unlock_bh(&pool->flow_pool_lock); 5505 } 5506 #else 5507 static inline 5508 void dp_tx_flow_pool_lock(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc) 5509 { 5510 } 5511 5512 static inline 5513 void dp_tx_flow_pool_unlock(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc) 5514 { 5515 } 5516 #endif 5517 5518 /** 5519 * dp_tx_notify_completion() - Notify tx completion for this desc 5520 * @soc: core txrx main context 5521 * @vdev: datapath vdev handle 5522 * @tx_desc: tx desc 5523 * @netbuf: buffer 5524 * @status: tx status 5525 * 5526 * Return: none 5527 */ 5528 static inline void dp_tx_notify_completion(struct dp_soc *soc, 5529 struct dp_vdev *vdev, 5530 struct dp_tx_desc_s *tx_desc, 5531 qdf_nbuf_t netbuf, 5532 uint8_t status) 5533 { 5534 void *osif_dev; 5535 ol_txrx_completion_fp tx_compl_cbk = NULL; 5536 uint16_t flag = BIT(QDF_TX_RX_STATUS_DOWNLOAD_SUCC); 5537 5538 qdf_assert(tx_desc); 5539 5540 if (!vdev || 5541 !vdev->osif_vdev) { 5542 return; 5543 } 5544 5545 osif_dev = vdev->osif_vdev; 5546 tx_compl_cbk = vdev->tx_comp; 5547 5548 if (status == HAL_TX_TQM_RR_FRAME_ACKED) 5549 flag |= BIT(QDF_TX_RX_STATUS_OK); 5550 5551 if (tx_compl_cbk) 5552 tx_compl_cbk(netbuf, osif_dev, flag); 5553 } 5554 5555 /** 5556 * dp_tx_sojourn_stats_process() - Collect sojourn stats 5557 * @pdev: pdev handle 5558 * @txrx_peer: DP peer context 5559 * @tid: tid value 5560 * @txdesc_ts: timestamp from txdesc 5561 * @ppdu_id: ppdu id 5562 * @link_id: link id 5563 * 5564 * Return: none 5565 */ 5566 #ifdef FEATURE_PERPKT_INFO 5567 static inline void dp_tx_sojourn_stats_process(struct dp_pdev *pdev, 5568 struct dp_txrx_peer *txrx_peer, 5569 uint8_t tid, 5570 uint64_t txdesc_ts, 5571 uint32_t ppdu_id, 5572 uint8_t link_id) 5573 { 5574 uint64_t delta_ms; 5575 struct cdp_tx_sojourn_stats *sojourn_stats; 5576 struct dp_peer *primary_link_peer = NULL; 5577 struct dp_soc *link_peer_soc = NULL; 5578 5579 if (qdf_unlikely(!pdev->enhanced_stats_en)) 5580 return; 5581 5582 if (qdf_unlikely(tid == HTT_INVALID_TID || 5583 tid >= CDP_DATA_TID_MAX)) 5584 return; 5585 5586 if (qdf_unlikely(!pdev->sojourn_buf)) 5587 return; 5588 5589 primary_link_peer = dp_get_primary_link_peer_by_id(pdev->soc, 5590 txrx_peer->peer_id, 5591 DP_MOD_ID_TX_COMP); 5592 5593 if (qdf_unlikely(!primary_link_peer)) 5594 return; 5595 5596 sojourn_stats = (struct cdp_tx_sojourn_stats *) 5597 qdf_nbuf_data(pdev->sojourn_buf); 5598 5599 link_peer_soc = primary_link_peer->vdev->pdev->soc; 5600 sojourn_stats->cookie = (void *) 5601 dp_monitor_peer_get_peerstats_ctx(link_peer_soc, 5602 primary_link_peer); 5603 5604 delta_ms = qdf_ktime_to_ms(qdf_ktime_real_get()) - 5605 txdesc_ts; 5606 qdf_ewma_tx_lag_add(&txrx_peer->stats[link_id].per_pkt_stats.tx.avg_sojourn_msdu[tid], 5607 delta_ms); 5608 sojourn_stats->sum_sojourn_msdu[tid] = delta_ms; 5609 sojourn_stats->num_msdus[tid] = 1; 5610 sojourn_stats->avg_sojourn_msdu[tid].internal = 5611 txrx_peer->stats[link_id]. 5612 per_pkt_stats.tx.avg_sojourn_msdu[tid].internal; 5613 dp_wdi_event_handler(WDI_EVENT_TX_SOJOURN_STAT, pdev->soc, 5614 pdev->sojourn_buf, HTT_INVALID_PEER, 5615 WDI_NO_VAL, pdev->pdev_id); 5616 sojourn_stats->sum_sojourn_msdu[tid] = 0; 5617 sojourn_stats->num_msdus[tid] = 0; 5618 sojourn_stats->avg_sojourn_msdu[tid].internal = 0; 5619 5620 dp_peer_unref_delete(primary_link_peer, DP_MOD_ID_TX_COMP); 5621 } 5622 #else 5623 static inline void dp_tx_sojourn_stats_process(struct dp_pdev *pdev, 5624 struct dp_txrx_peer *txrx_peer, 5625 uint8_t tid, 5626 uint64_t txdesc_ts, 5627 uint32_t ppdu_id) 5628 { 5629 } 5630 #endif 5631 5632 #ifdef WLAN_FEATURE_PKT_CAPTURE_V2 5633 void dp_send_completion_to_pkt_capture(struct dp_soc *soc, 5634 struct dp_tx_desc_s *desc, 5635 struct hal_tx_completion_status *ts) 5636 { 5637 dp_wdi_event_handler(WDI_EVENT_PKT_CAPTURE_TX_DATA, soc, 5638 desc, ts->peer_id, 5639 WDI_NO_VAL, desc->pdev->pdev_id); 5640 } 5641 #endif 5642 5643 void 5644 dp_tx_comp_process_desc(struct dp_soc *soc, 5645 struct dp_tx_desc_s *desc, 5646 struct hal_tx_completion_status *ts, 5647 struct dp_txrx_peer *txrx_peer) 5648 { 5649 uint64_t time_latency = 0; 5650 uint16_t peer_id = DP_INVALID_PEER_ID; 5651 5652 /* 5653 * m_copy/tx_capture modes are not supported for 5654 * scatter gather packets 5655 */ 5656 if (qdf_unlikely(!!desc->pdev->latency_capture_enable)) { 5657 time_latency = (qdf_ktime_to_ms(qdf_ktime_real_get()) - 5658 qdf_ktime_to_ms(desc->timestamp)); 5659 } 5660 5661 dp_send_completion_to_pkt_capture(soc, desc, ts); 5662 5663 if (dp_tx_pkt_tracepoints_enabled()) 5664 qdf_trace_dp_packet(desc->nbuf, QDF_TX, 5665 desc->msdu_ext_desc ? 5666 desc->msdu_ext_desc->tso_desc : NULL, 5667 qdf_ktime_to_us(desc->timestamp)); 5668 5669 if (!(desc->msdu_ext_desc)) { 5670 dp_tx_enh_unmap(soc, desc); 5671 if (txrx_peer) 5672 peer_id = txrx_peer->peer_id; 5673 5674 if (QDF_STATUS_SUCCESS == 5675 dp_monitor_tx_add_to_comp_queue(soc, desc, ts, peer_id)) { 5676 return; 5677 } 5678 5679 if (QDF_STATUS_SUCCESS == 5680 dp_get_completion_indication_for_stack(soc, 5681 desc->pdev, 5682 txrx_peer, ts, 5683 desc->nbuf, 5684 time_latency)) { 5685 dp_send_completion_to_stack(soc, 5686 desc->pdev, 5687 ts->peer_id, 5688 ts->ppdu_id, 5689 desc->nbuf); 5690 return; 5691 } 5692 } 5693 5694 desc->flags |= DP_TX_DESC_FLAG_COMPLETED_TX; 5695 dp_tx_comp_free_buf(soc, desc, false); 5696 } 5697 5698 #ifdef DISABLE_DP_STATS 5699 /** 5700 * dp_tx_update_connectivity_stats() - update tx connectivity stats 5701 * @soc: core txrx main context 5702 * @vdev: virtual device instance 5703 * @tx_desc: tx desc 5704 * @status: tx status 5705 * 5706 * Return: none 5707 */ 5708 static inline 5709 void dp_tx_update_connectivity_stats(struct dp_soc *soc, 5710 struct dp_vdev *vdev, 5711 struct dp_tx_desc_s *tx_desc, 5712 uint8_t status) 5713 { 5714 } 5715 #else 5716 static inline 5717 void dp_tx_update_connectivity_stats(struct dp_soc *soc, 5718 struct dp_vdev *vdev, 5719 struct dp_tx_desc_s *tx_desc, 5720 uint8_t status) 5721 { 5722 void *osif_dev; 5723 ol_txrx_stats_rx_fp stats_cbk; 5724 uint8_t pkt_type; 5725 5726 qdf_assert(tx_desc); 5727 5728 if (!vdev || vdev->delete.pending || !vdev->osif_vdev || 5729 !vdev->stats_cb) 5730 return; 5731 5732 osif_dev = vdev->osif_vdev; 5733 stats_cbk = vdev->stats_cb; 5734 5735 stats_cbk(tx_desc->nbuf, osif_dev, PKT_TYPE_TX_HOST_FW_SENT, &pkt_type); 5736 if (status == HAL_TX_TQM_RR_FRAME_ACKED) 5737 stats_cbk(tx_desc->nbuf, osif_dev, PKT_TYPE_TX_ACK_CNT, 5738 &pkt_type); 5739 } 5740 #endif 5741 5742 #if defined(WLAN_FEATURE_TSF_AUTO_REPORT) || defined(WLAN_CONFIG_TX_DELAY) 5743 /* Mask for bit29 ~ bit31 */ 5744 #define DP_TX_TS_BIT29_31_MASK 0xE0000000 5745 /* Timestamp value (unit us) if bit29 is set */ 5746 #define DP_TX_TS_BIT29_SET_VALUE BIT(29) 5747 /** 5748 * dp_tx_adjust_enqueue_buffer_ts() - adjust the enqueue buffer_timestamp 5749 * @ack_ts: OTA ack timestamp, unit us. 5750 * @enqueue_ts: TCL enqueue TX data to TQM timestamp, unit us. 5751 * @base_delta_ts: base timestamp delta for ack_ts and enqueue_ts 5752 * 5753 * this function will restore the bit29 ~ bit31 3 bits value for 5754 * buffer_timestamp in wbm2sw ring entry, currently buffer_timestamp only 5755 * can support 0x7FFF * 1024 us (29 bits), but if the timestamp is > 5756 * 0x7FFF * 1024 us, bit29~ bit31 will be lost. 5757 * 5758 * Return: the adjusted buffer_timestamp value 5759 */ 5760 static inline 5761 uint32_t dp_tx_adjust_enqueue_buffer_ts(uint32_t ack_ts, 5762 uint32_t enqueue_ts, 5763 uint32_t base_delta_ts) 5764 { 5765 uint32_t ack_buffer_ts; 5766 uint32_t ack_buffer_ts_bit29_31; 5767 uint32_t adjusted_enqueue_ts; 5768 5769 /* corresponding buffer_timestamp value when receive OTA Ack */ 5770 ack_buffer_ts = ack_ts - base_delta_ts; 5771 ack_buffer_ts_bit29_31 = ack_buffer_ts & DP_TX_TS_BIT29_31_MASK; 5772 5773 /* restore the bit29 ~ bit31 value */ 5774 adjusted_enqueue_ts = ack_buffer_ts_bit29_31 | enqueue_ts; 5775 5776 /* 5777 * if actual enqueue_ts value occupied 29 bits only, this enqueue_ts 5778 * value + real UL delay overflow 29 bits, then 30th bit (bit-29) 5779 * should not be marked, otherwise extra 0x20000000 us is added to 5780 * enqueue_ts. 5781 */ 5782 if (qdf_unlikely(adjusted_enqueue_ts > ack_buffer_ts)) 5783 adjusted_enqueue_ts -= DP_TX_TS_BIT29_SET_VALUE; 5784 5785 return adjusted_enqueue_ts; 5786 } 5787 5788 QDF_STATUS 5789 dp_tx_compute_hw_delay_us(struct hal_tx_completion_status *ts, 5790 uint32_t delta_tsf, 5791 uint32_t *delay_us) 5792 { 5793 uint32_t buffer_ts; 5794 uint32_t delay; 5795 5796 if (!delay_us) 5797 return QDF_STATUS_E_INVAL; 5798 5799 /* Tx_rate_stats_info_valid is 0 and tsf is invalid then */ 5800 if (!ts->valid) 5801 return QDF_STATUS_E_INVAL; 5802 5803 /* buffer_timestamp is in units of 1024 us and is [31:13] of 5804 * WBM_RELEASE_RING_4. After left shift 10 bits, it's 5805 * valid up to 29 bits. 5806 */ 5807 buffer_ts = ts->buffer_timestamp << 10; 5808 buffer_ts = dp_tx_adjust_enqueue_buffer_ts(ts->tsf, 5809 buffer_ts, delta_tsf); 5810 5811 delay = ts->tsf - buffer_ts - delta_tsf; 5812 5813 if (qdf_unlikely(delay & 0x80000000)) { 5814 dp_err_rl("delay = 0x%x (-ve)\n" 5815 "release_src = %d\n" 5816 "ppdu_id = 0x%x\n" 5817 "peer_id = 0x%x\n" 5818 "tid = 0x%x\n" 5819 "release_reason = %d\n" 5820 "tsf = %u (0x%x)\n" 5821 "buffer_timestamp = %u (0x%x)\n" 5822 "delta_tsf = %u (0x%x)\n", 5823 delay, ts->release_src, ts->ppdu_id, ts->peer_id, 5824 ts->tid, ts->status, ts->tsf, ts->tsf, 5825 ts->buffer_timestamp, ts->buffer_timestamp, 5826 delta_tsf, delta_tsf); 5827 5828 delay = 0; 5829 goto end; 5830 } 5831 5832 delay &= 0x1FFFFFFF; /* mask 29 BITS */ 5833 if (delay > 0x1000000) { 5834 dp_info_rl("----------------------\n" 5835 "Tx completion status:\n" 5836 "----------------------\n" 5837 "release_src = %d\n" 5838 "ppdu_id = 0x%x\n" 5839 "release_reason = %d\n" 5840 "tsf = %u (0x%x)\n" 5841 "buffer_timestamp = %u (0x%x)\n" 5842 "delta_tsf = %u (0x%x)\n", 5843 ts->release_src, ts->ppdu_id, ts->status, 5844 ts->tsf, ts->tsf, ts->buffer_timestamp, 5845 ts->buffer_timestamp, delta_tsf, delta_tsf); 5846 return QDF_STATUS_E_FAILURE; 5847 } 5848 5849 5850 end: 5851 *delay_us = delay; 5852 5853 return QDF_STATUS_SUCCESS; 5854 } 5855 5856 void dp_set_delta_tsf(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, 5857 uint32_t delta_tsf) 5858 { 5859 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); 5860 struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id, 5861 DP_MOD_ID_CDP); 5862 5863 if (!vdev) { 5864 dp_err_rl("vdev %d does not exist", vdev_id); 5865 return; 5866 } 5867 5868 vdev->delta_tsf = delta_tsf; 5869 dp_debug("vdev id %u delta_tsf %u", vdev_id, delta_tsf); 5870 5871 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP); 5872 } 5873 #endif 5874 #ifdef WLAN_FEATURE_TSF_UPLINK_DELAY 5875 QDF_STATUS dp_set_tsf_ul_delay_report(struct cdp_soc_t *soc_hdl, 5876 uint8_t vdev_id, bool enable) 5877 { 5878 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); 5879 struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id, 5880 DP_MOD_ID_CDP); 5881 5882 if (!vdev) { 5883 dp_err_rl("vdev %d does not exist", vdev_id); 5884 return QDF_STATUS_E_FAILURE; 5885 } 5886 5887 qdf_atomic_set(&vdev->ul_delay_report, enable); 5888 5889 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP); 5890 5891 return QDF_STATUS_SUCCESS; 5892 } 5893 5894 QDF_STATUS dp_get_uplink_delay(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, 5895 uint32_t *val) 5896 { 5897 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); 5898 struct dp_vdev *vdev; 5899 uint32_t delay_accum; 5900 uint32_t pkts_accum; 5901 5902 vdev = dp_vdev_get_ref_by_id(soc, vdev_id, DP_MOD_ID_CDP); 5903 if (!vdev) { 5904 dp_err_rl("vdev %d does not exist", vdev_id); 5905 return QDF_STATUS_E_FAILURE; 5906 } 5907 5908 if (!qdf_atomic_read(&vdev->ul_delay_report)) { 5909 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP); 5910 return QDF_STATUS_E_FAILURE; 5911 } 5912 5913 /* Average uplink delay based on current accumulated values */ 5914 delay_accum = qdf_atomic_read(&vdev->ul_delay_accum); 5915 pkts_accum = qdf_atomic_read(&vdev->ul_pkts_accum); 5916 5917 *val = delay_accum / pkts_accum; 5918 dp_debug("uplink_delay %u delay_accum %u pkts_accum %u", *val, 5919 delay_accum, pkts_accum); 5920 5921 /* Reset accumulated values to 0 */ 5922 qdf_atomic_set(&vdev->ul_delay_accum, 0); 5923 qdf_atomic_set(&vdev->ul_pkts_accum, 0); 5924 5925 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP); 5926 5927 return QDF_STATUS_SUCCESS; 5928 } 5929 5930 static void dp_tx_update_uplink_delay(struct dp_soc *soc, struct dp_vdev *vdev, 5931 struct hal_tx_completion_status *ts) 5932 { 5933 uint32_t ul_delay; 5934 5935 if (qdf_unlikely(!vdev)) { 5936 dp_info_rl("vdev is null or delete in progress"); 5937 return; 5938 } 5939 5940 if (!qdf_atomic_read(&vdev->ul_delay_report)) 5941 return; 5942 5943 if (QDF_IS_STATUS_ERROR(dp_tx_compute_hw_delay_us(ts, 5944 vdev->delta_tsf, 5945 &ul_delay))) 5946 return; 5947 5948 ul_delay /= 1000; /* in unit of ms */ 5949 5950 qdf_atomic_add(ul_delay, &vdev->ul_delay_accum); 5951 qdf_atomic_inc(&vdev->ul_pkts_accum); 5952 } 5953 #else /* !WLAN_FEATURE_TSF_UPLINK_DELAY */ 5954 static inline 5955 void dp_tx_update_uplink_delay(struct dp_soc *soc, struct dp_vdev *vdev, 5956 struct hal_tx_completion_status *ts) 5957 { 5958 } 5959 #endif /* WLAN_FEATURE_TSF_UPLINK_DELAY */ 5960 5961 #ifndef CONFIG_AP_PLATFORM 5962 /** 5963 * dp_update_mcast_stats() - Update Tx Mcast stats 5964 * @txrx_peer: txrx_peer pointer 5965 * @link_id: Link ID 5966 * @length: packet length 5967 * @nbuf: nbuf handle 5968 * 5969 * Return: None 5970 */ 5971 static inline void 5972 dp_update_mcast_stats(struct dp_txrx_peer *txrx_peer, uint8_t link_id, 5973 uint32_t length, qdf_nbuf_t nbuf) 5974 { 5975 if (QDF_NBUF_CB_GET_IS_MCAST(nbuf)) 5976 DP_PEER_PER_PKT_STATS_INC_PKT(txrx_peer, tx.mcast, 1, 5977 length, link_id); 5978 } 5979 #else 5980 static inline void 5981 dp_update_mcast_stats(struct dp_txrx_peer *txrx_peer, uint8_t link_id, 5982 uint32_t length, qdf_nbuf_t nbuf) 5983 { 5984 } 5985 #endif 5986 #if defined(WLAN_FEATURE_11BE_MLO) && defined(DP_MLO_LINK_STATS_SUPPORT) 5987 /** 5988 * dp_tx_comp_set_nbuf_band() - set nbuf band. 5989 * @soc: dp soc handle 5990 * @nbuf: nbuf handle 5991 * @ts: tx completion status 5992 * 5993 * Return: None 5994 */ 5995 static inline void 5996 dp_tx_comp_set_nbuf_band(struct dp_soc *soc, qdf_nbuf_t nbuf, 5997 struct hal_tx_completion_status *ts) 5998 { 5999 struct qdf_mac_addr *mac_addr; 6000 struct dp_peer *peer; 6001 struct dp_txrx_peer *txrx_peer; 6002 uint8_t link_id; 6003 6004 if ((QDF_NBUF_CB_GET_PACKET_TYPE(nbuf) != 6005 QDF_NBUF_CB_PACKET_TYPE_EAPOL && 6006 QDF_NBUF_CB_GET_PACKET_TYPE(nbuf) != 6007 QDF_NBUF_CB_PACKET_TYPE_DHCP && 6008 QDF_NBUF_CB_GET_PACKET_TYPE(nbuf) != 6009 QDF_NBUF_CB_PACKET_TYPE_DHCPV6) || 6010 QDF_NBUF_CB_GET_IS_BCAST(nbuf)) 6011 return; 6012 6013 mac_addr = (struct qdf_mac_addr *)(qdf_nbuf_data(nbuf) + 6014 QDF_NBUF_DEST_MAC_OFFSET); 6015 6016 peer = dp_mld_peer_find_hash_find(soc, mac_addr->bytes, 0, 6017 DP_VDEV_ALL, DP_MOD_ID_TX_COMP); 6018 if (qdf_likely(peer)) { 6019 txrx_peer = dp_get_txrx_peer(peer); 6020 if (qdf_likely(txrx_peer)) { 6021 link_id = 6022 dp_tx_get_link_id_from_ppdu_id(soc, ts, 6023 txrx_peer, 6024 txrx_peer->vdev); 6025 qdf_nbuf_tx_set_band(nbuf, txrx_peer->ll_band[link_id]); 6026 } 6027 dp_peer_unref_delete(peer, DP_MOD_ID_TX_COMP); 6028 } 6029 } 6030 #else 6031 static inline void 6032 dp_tx_comp_set_nbuf_band(struct dp_soc *soc, qdf_nbuf_t nbuf, 6033 struct hal_tx_completion_status *ts) 6034 { 6035 } 6036 #endif 6037 6038 void dp_tx_comp_process_tx_status(struct dp_soc *soc, 6039 struct dp_tx_desc_s *tx_desc, 6040 struct hal_tx_completion_status *ts, 6041 struct dp_txrx_peer *txrx_peer, 6042 uint8_t ring_id) 6043 { 6044 uint32_t length; 6045 qdf_ether_header_t *eh; 6046 struct dp_vdev *vdev = NULL; 6047 qdf_nbuf_t nbuf = tx_desc->nbuf; 6048 enum qdf_dp_tx_rx_status dp_status; 6049 uint8_t link_id = 0; 6050 enum QDF_OPMODE op_mode = QDF_MAX_NO_OF_MODE; 6051 6052 if (!nbuf) { 6053 dp_info_rl("invalid tx descriptor. nbuf NULL"); 6054 goto out; 6055 } 6056 6057 eh = (qdf_ether_header_t *)qdf_nbuf_data(nbuf); 6058 length = dp_tx_get_pkt_len(tx_desc); 6059 6060 dp_status = dp_tx_hw_to_qdf(ts->status); 6061 if (soc->dp_debug_log_en) { 6062 dp_tx_comp_debug("--------------------\n" 6063 "Tx Completion Stats:\n" 6064 "--------------------\n" 6065 "ack_frame_rssi = %d\n" 6066 "first_msdu = %d\n" 6067 "last_msdu = %d\n" 6068 "msdu_part_of_amsdu = %d\n" 6069 "rate_stats valid = %d\n" 6070 "bw = %d\n" 6071 "pkt_type = %d\n" 6072 "stbc = %d\n" 6073 "ldpc = %d\n" 6074 "sgi = %d\n" 6075 "mcs = %d\n" 6076 "ofdma = %d\n" 6077 "tones_in_ru = %d\n" 6078 "tsf = %d\n" 6079 "ppdu_id = %d\n" 6080 "transmit_cnt = %d\n" 6081 "tid = %d\n" 6082 "peer_id = %d\n" 6083 "tx_status = %d\n" 6084 "tx_release_source = %d\n", 6085 ts->ack_frame_rssi, ts->first_msdu, 6086 ts->last_msdu, ts->msdu_part_of_amsdu, 6087 ts->valid, ts->bw, ts->pkt_type, ts->stbc, 6088 ts->ldpc, ts->sgi, ts->mcs, ts->ofdma, 6089 ts->tones_in_ru, ts->tsf, ts->ppdu_id, 6090 ts->transmit_cnt, ts->tid, ts->peer_id, 6091 ts->status, ts->release_src); 6092 } 6093 6094 /* Update SoC level stats */ 6095 DP_STATS_INCC(soc, tx.dropped_fw_removed, 1, 6096 (ts->status == HAL_TX_TQM_RR_REM_CMD_REM)); 6097 6098 if (!txrx_peer) { 6099 dp_tx_comp_set_nbuf_band(soc, nbuf, ts); 6100 dp_info_rl("peer is null or deletion in progress"); 6101 DP_STATS_INC_PKT(soc, tx.tx_invalid_peer, 1, length); 6102 6103 vdev = dp_vdev_get_ref_by_id(soc, tx_desc->vdev_id, 6104 DP_MOD_ID_CDP); 6105 if (qdf_likely(vdev)) { 6106 op_mode = vdev->qdf_opmode; 6107 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP); 6108 } 6109 6110 goto out_log; 6111 } 6112 vdev = txrx_peer->vdev; 6113 6114 link_id = dp_tx_get_link_id_from_ppdu_id(soc, ts, txrx_peer, vdev); 6115 6116 dp_tx_set_nbuf_band(nbuf, txrx_peer, link_id); 6117 6118 op_mode = vdev->qdf_opmode; 6119 dp_tx_update_connectivity_stats(soc, vdev, tx_desc, ts->status); 6120 dp_tx_update_uplink_delay(soc, vdev, ts); 6121 6122 /* check tx complete notification */ 6123 if (qdf_nbuf_tx_notify_comp_get(nbuf)) 6124 dp_tx_notify_completion(soc, vdev, tx_desc, 6125 nbuf, ts->status); 6126 6127 /* Update per-packet stats for mesh mode */ 6128 if (qdf_unlikely(vdev->mesh_vdev) && 6129 !(tx_desc->flags & DP_TX_DESC_FLAG_TO_FW)) 6130 dp_tx_comp_fill_tx_completion_stats(tx_desc, ts); 6131 6132 /* Update peer level stats */ 6133 if (qdf_unlikely(txrx_peer->bss_peer && 6134 vdev->opmode == wlan_op_mode_ap)) { 6135 if (ts->status != HAL_TX_TQM_RR_REM_CMD_REM) { 6136 DP_PEER_PER_PKT_STATS_INC_PKT(txrx_peer, tx.mcast, 1, 6137 length, link_id); 6138 6139 if (txrx_peer->vdev->tx_encap_type == 6140 htt_cmn_pkt_type_ethernet && 6141 QDF_IS_ADDR_BROADCAST(eh->ether_dhost)) { 6142 DP_PEER_PER_PKT_STATS_INC_PKT(txrx_peer, 6143 tx.bcast, 1, 6144 length, link_id); 6145 } 6146 } 6147 } else { 6148 DP_PEER_PER_PKT_STATS_INC_PKT(txrx_peer, tx.ucast, 1, length, 6149 link_id); 6150 if (ts->status == HAL_TX_TQM_RR_FRAME_ACKED) { 6151 DP_PEER_PER_PKT_STATS_INC_PKT(txrx_peer, tx.tx_success, 6152 1, length, link_id); 6153 if (qdf_unlikely(txrx_peer->in_twt)) { 6154 DP_PEER_PER_PKT_STATS_INC_PKT(txrx_peer, 6155 tx.tx_success_twt, 6156 1, length, 6157 link_id); 6158 } 6159 6160 dp_update_mcast_stats(txrx_peer, link_id, length, nbuf); 6161 } 6162 } 6163 6164 dp_tx_update_peer_stats(tx_desc, ts, txrx_peer, ring_id, link_id); 6165 dp_tx_update_peer_delay_stats(txrx_peer, tx_desc, ts, ring_id); 6166 dp_tx_update_peer_jitter_stats(txrx_peer, tx_desc, ts, ring_id); 6167 dp_tx_update_peer_sawf_stats(soc, vdev, txrx_peer, tx_desc, 6168 ts, ts->tid); 6169 dp_tx_send_pktlog(soc, vdev->pdev, tx_desc, nbuf, dp_status); 6170 dp_tx_latency_stats_update(soc, txrx_peer, tx_desc, ts, link_id); 6171 6172 #ifdef QCA_SUPPORT_RDK_STATS 6173 if (soc->peerstats_enabled) 6174 dp_tx_sojourn_stats_process(vdev->pdev, txrx_peer, ts->tid, 6175 qdf_ktime_to_ms(tx_desc->timestamp), 6176 ts->ppdu_id, link_id); 6177 #endif 6178 6179 out_log: 6180 DPTRACE(qdf_dp_trace_ptr(tx_desc->nbuf, 6181 QDF_DP_TRACE_LI_DP_FREE_PACKET_PTR_RECORD, 6182 QDF_TRACE_DEFAULT_PDEV_ID, 6183 qdf_nbuf_data_addr(nbuf), 6184 sizeof(qdf_nbuf_data(nbuf)), 6185 tx_desc->id, ts->status, dp_status, op_mode)); 6186 out: 6187 return; 6188 } 6189 6190 #if defined(QCA_VDEV_STATS_HW_OFFLOAD_SUPPORT) && \ 6191 defined(QCA_ENHANCED_STATS_SUPPORT) 6192 void dp_tx_update_peer_basic_stats(struct dp_txrx_peer *txrx_peer, 6193 uint32_t length, uint8_t tx_status, 6194 bool update) 6195 { 6196 if (update || (!txrx_peer->hw_txrx_stats_en)) { 6197 DP_PEER_STATS_FLAT_INC_PKT(txrx_peer, comp_pkt, 1, length); 6198 6199 if (tx_status != HAL_TX_TQM_RR_FRAME_ACKED) 6200 DP_PEER_STATS_FLAT_INC(txrx_peer, tx_failed, 1); 6201 } 6202 } 6203 #elif defined(QCA_VDEV_STATS_HW_OFFLOAD_SUPPORT) 6204 void dp_tx_update_peer_basic_stats(struct dp_txrx_peer *txrx_peer, 6205 uint32_t length, uint8_t tx_status, 6206 bool update) 6207 { 6208 if (!txrx_peer->hw_txrx_stats_en) { 6209 DP_PEER_STATS_FLAT_INC_PKT(txrx_peer, comp_pkt, 1, length); 6210 6211 if (tx_status != HAL_TX_TQM_RR_FRAME_ACKED) 6212 DP_PEER_STATS_FLAT_INC(txrx_peer, tx_failed, 1); 6213 } 6214 } 6215 6216 #else 6217 void dp_tx_update_peer_basic_stats(struct dp_txrx_peer *txrx_peer, 6218 uint32_t length, uint8_t tx_status, 6219 bool update) 6220 { 6221 DP_PEER_STATS_FLAT_INC_PKT(txrx_peer, comp_pkt, 1, length); 6222 6223 if (tx_status != HAL_TX_TQM_RR_FRAME_ACKED) 6224 DP_PEER_STATS_FLAT_INC(txrx_peer, tx_failed, 1); 6225 } 6226 #endif 6227 6228 /** 6229 * dp_tx_prefetch_next_nbuf_data(): Prefetch nbuf and nbuf data 6230 * @next: descriptor of the nrxt buffer 6231 * 6232 * Return: none 6233 */ 6234 #ifdef QCA_DP_RX_NBUF_AND_NBUF_DATA_PREFETCH 6235 static inline 6236 void dp_tx_prefetch_next_nbuf_data(struct dp_tx_desc_s *next) 6237 { 6238 qdf_nbuf_t nbuf = NULL; 6239 6240 if (next) 6241 nbuf = next->nbuf; 6242 if (nbuf) 6243 qdf_prefetch(nbuf); 6244 } 6245 #else 6246 static inline 6247 void dp_tx_prefetch_next_nbuf_data(struct dp_tx_desc_s *next) 6248 { 6249 } 6250 #endif 6251 6252 /** 6253 * dp_tx_mcast_reinject_handler() - Tx reinjected multicast packets handler 6254 * @soc: core txrx main context 6255 * @desc: software descriptor 6256 * 6257 * Return: true when packet is reinjected 6258 */ 6259 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) && \ 6260 defined(WLAN_MCAST_MLO) && !defined(CONFIG_MLO_SINGLE_DEV) 6261 static inline bool 6262 dp_tx_mcast_reinject_handler(struct dp_soc *soc, struct dp_tx_desc_s *desc) 6263 { 6264 struct dp_vdev *vdev = NULL; 6265 uint8_t xmit_type; 6266 6267 if (desc->tx_status == HAL_TX_TQM_RR_MULTICAST_DROP) { 6268 if (!soc->arch_ops.dp_tx_mcast_handler || 6269 !soc->arch_ops.dp_tx_is_mcast_primary) 6270 return false; 6271 6272 vdev = dp_vdev_get_ref_by_id(soc, desc->vdev_id, 6273 DP_MOD_ID_REINJECT); 6274 6275 if (qdf_unlikely(!vdev)) { 6276 dp_tx_comp_info_rl("Unable to get vdev ref %d", 6277 desc->id); 6278 return false; 6279 } 6280 6281 if (!(soc->arch_ops.dp_tx_is_mcast_primary(soc, vdev))) { 6282 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_REINJECT); 6283 return false; 6284 } 6285 xmit_type = qdf_nbuf_get_vdev_xmit_type(desc->nbuf); 6286 DP_STATS_INC_PKT(vdev, tx_i[xmit_type].reinject_pkts, 1, 6287 qdf_nbuf_len(desc->nbuf)); 6288 soc->arch_ops.dp_tx_mcast_handler(soc, vdev, desc->nbuf); 6289 dp_tx_desc_release(soc, desc, desc->pool_id); 6290 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_REINJECT); 6291 return true; 6292 } 6293 6294 return false; 6295 } 6296 #else 6297 static inline bool 6298 dp_tx_mcast_reinject_handler(struct dp_soc *soc, struct dp_tx_desc_s *desc) 6299 { 6300 return false; 6301 } 6302 #endif 6303 6304 #ifdef QCA_DP_TX_NBUF_LIST_FREE 6305 static inline void 6306 dp_tx_nbuf_queue_head_init(qdf_nbuf_queue_head_t *nbuf_queue_head) 6307 { 6308 qdf_nbuf_queue_head_init(nbuf_queue_head); 6309 } 6310 6311 static inline void 6312 dp_tx_nbuf_dev_queue_free(qdf_nbuf_queue_head_t *nbuf_queue_head, 6313 struct dp_tx_desc_s *desc) 6314 { 6315 qdf_nbuf_t nbuf = NULL; 6316 6317 nbuf = desc->nbuf; 6318 if (qdf_likely(desc->flags & DP_TX_DESC_FLAG_FAST)) 6319 qdf_nbuf_dev_queue_head(nbuf_queue_head, nbuf); 6320 else 6321 qdf_nbuf_free(nbuf); 6322 } 6323 6324 static inline void 6325 dp_tx_nbuf_dev_queue_free_no_flag(qdf_nbuf_queue_head_t *nbuf_queue_head, 6326 qdf_nbuf_t nbuf) 6327 { 6328 if (!nbuf) 6329 return; 6330 6331 if (nbuf->is_from_recycler) 6332 qdf_nbuf_dev_queue_head(nbuf_queue_head, nbuf); 6333 else 6334 qdf_nbuf_free(nbuf); 6335 } 6336 6337 static inline void 6338 dp_tx_nbuf_dev_kfree_list(qdf_nbuf_queue_head_t *nbuf_queue_head) 6339 { 6340 qdf_nbuf_dev_kfree_list(nbuf_queue_head); 6341 } 6342 #else 6343 static inline void 6344 dp_tx_nbuf_queue_head_init(qdf_nbuf_queue_head_t *nbuf_queue_head) 6345 { 6346 } 6347 6348 static inline void 6349 dp_tx_nbuf_dev_queue_free(qdf_nbuf_queue_head_t *nbuf_queue_head, 6350 struct dp_tx_desc_s *desc) 6351 { 6352 qdf_nbuf_free(desc->nbuf); 6353 } 6354 6355 static inline void 6356 dp_tx_nbuf_dev_queue_free_no_flag(qdf_nbuf_queue_head_t *nbuf_queue_head, 6357 qdf_nbuf_t nbuf) 6358 { 6359 qdf_nbuf_free(nbuf); 6360 } 6361 6362 static inline void 6363 dp_tx_nbuf_dev_kfree_list(qdf_nbuf_queue_head_t *nbuf_queue_head) 6364 { 6365 } 6366 #endif 6367 6368 #ifdef WLAN_SUPPORT_PPEDS 6369 static inline void 6370 dp_tx_update_ppeds_tx_comp_stats(struct dp_soc *soc, 6371 struct dp_txrx_peer *txrx_peer, 6372 struct hal_tx_completion_status *ts, 6373 struct dp_tx_desc_s *desc, 6374 uint8_t ring_id) 6375 { 6376 uint8_t link_id = 0; 6377 struct dp_vdev *vdev = NULL; 6378 6379 if (qdf_likely(txrx_peer)) { 6380 if (!(desc->flags & DP_TX_DESC_FLAG_SIMPLE)) { 6381 hal_tx_comp_get_status(&desc->comp, 6382 ts, 6383 soc->hal_soc); 6384 vdev = txrx_peer->vdev; 6385 link_id = dp_tx_get_link_id_from_ppdu_id(soc, 6386 ts, 6387 txrx_peer, 6388 vdev); 6389 if (link_id < 1 || link_id > DP_MAX_MLO_LINKS) 6390 link_id = 0; 6391 dp_tx_update_peer_stats(desc, ts, 6392 txrx_peer, 6393 ring_id, 6394 link_id); 6395 } else { 6396 dp_tx_update_peer_basic_stats(txrx_peer, desc->length, 6397 desc->tx_status, false); 6398 } 6399 } 6400 } 6401 #else 6402 static inline void 6403 dp_tx_update_ppeds_tx_comp_stats(struct dp_soc *soc, 6404 struct dp_txrx_peer *txrx_peer, 6405 struct hal_tx_completion_status *ts, 6406 struct dp_tx_desc_s *desc, 6407 uint8_t ring_id) 6408 { 6409 } 6410 #endif 6411 6412 void 6413 dp_tx_comp_process_desc_list_fast(struct dp_soc *soc, 6414 struct dp_tx_desc_s *head_desc, 6415 struct dp_tx_desc_s *tail_desc, 6416 uint8_t ring_id, 6417 uint32_t fast_desc_count) 6418 { 6419 struct dp_tx_desc_pool_s *pool = NULL; 6420 6421 pool = dp_get_tx_desc_pool(soc, head_desc->pool_id); 6422 dp_tx_outstanding_sub(head_desc->pdev, fast_desc_count); 6423 dp_tx_desc_free_list(pool, head_desc, tail_desc, fast_desc_count); 6424 } 6425 6426 void 6427 dp_tx_comp_process_desc_list(struct dp_soc *soc, 6428 struct dp_tx_desc_s *comp_head, uint8_t ring_id) 6429 { 6430 struct dp_tx_desc_s *desc; 6431 struct dp_tx_desc_s *next; 6432 struct hal_tx_completion_status ts; 6433 struct dp_txrx_peer *txrx_peer = NULL; 6434 uint16_t peer_id = DP_INVALID_PEER; 6435 dp_txrx_ref_handle txrx_ref_handle = NULL; 6436 qdf_nbuf_queue_head_t h; 6437 6438 desc = comp_head; 6439 6440 dp_tx_nbuf_queue_head_init(&h); 6441 6442 while (desc) { 6443 next = desc->next; 6444 dp_tx_prefetch_next_nbuf_data(next); 6445 6446 if (peer_id != desc->peer_id) { 6447 if (txrx_peer) 6448 dp_txrx_peer_unref_delete(txrx_ref_handle, 6449 DP_MOD_ID_TX_COMP); 6450 peer_id = desc->peer_id; 6451 txrx_peer = 6452 dp_txrx_peer_get_ref_by_id(soc, peer_id, 6453 &txrx_ref_handle, 6454 DP_MOD_ID_TX_COMP); 6455 } 6456 6457 if (dp_tx_mcast_reinject_handler(soc, desc)) { 6458 desc = next; 6459 continue; 6460 } 6461 6462 if (desc->flags & DP_TX_DESC_FLAG_PPEDS) { 6463 qdf_nbuf_t nbuf; 6464 dp_tx_update_ppeds_tx_comp_stats(soc, txrx_peer, &ts, 6465 desc, ring_id); 6466 6467 if (desc->pool_id != DP_TX_PPEDS_POOL_ID) { 6468 nbuf = desc->nbuf; 6469 dp_tx_nbuf_dev_queue_free_no_flag(&h, nbuf); 6470 if (desc->flags & DP_TX_DESC_FLAG_SPECIAL) 6471 dp_tx_spcl_desc_free(soc, desc, 6472 desc->pool_id); 6473 else 6474 dp_tx_desc_free(soc, desc, 6475 desc->pool_id); 6476 6477 __dp_tx_outstanding_dec(soc); 6478 } else { 6479 nbuf = dp_ppeds_tx_desc_free(soc, desc); 6480 dp_tx_nbuf_dev_queue_free_no_flag(&h, nbuf); 6481 } 6482 desc = next; 6483 continue; 6484 } 6485 6486 if (qdf_likely(desc->flags & DP_TX_DESC_FLAG_SIMPLE)) { 6487 struct dp_pdev *pdev = desc->pdev; 6488 6489 if (qdf_likely(txrx_peer)) 6490 dp_tx_update_peer_basic_stats(txrx_peer, 6491 desc->length, 6492 desc->tx_status, 6493 false); 6494 qdf_assert(pdev); 6495 dp_tx_outstanding_dec(pdev); 6496 /* 6497 * Calling a QDF WRAPPER here is creating significant 6498 * performance impact so avoided the wrapper call here 6499 */ 6500 dp_tx_desc_history_add(soc, desc->dma_addr, desc->nbuf, 6501 desc->id, DP_TX_COMP_UNMAP); 6502 dp_tx_nbuf_unmap(soc, desc); 6503 dp_tx_nbuf_dev_queue_free(&h, desc); 6504 dp_tx_desc_free(soc, desc, desc->pool_id); 6505 desc = next; 6506 continue; 6507 } 6508 6509 hal_tx_comp_get_status(&desc->comp, &ts, soc->hal_soc); 6510 6511 dp_tx_comp_process_tx_status(soc, desc, &ts, txrx_peer, 6512 ring_id); 6513 6514 dp_tx_comp_process_desc(soc, desc, &ts, txrx_peer); 6515 6516 dp_tx_desc_release(soc, desc, desc->pool_id); 6517 desc = next; 6518 } 6519 dp_tx_nbuf_dev_kfree_list(&h); 6520 if (txrx_peer) 6521 dp_txrx_peer_unref_delete(txrx_ref_handle, DP_MOD_ID_TX_COMP); 6522 } 6523 6524 #ifndef WLAN_SOFTUMAC_SUPPORT 6525 /** 6526 * dp_tx_dump_tx_desc() - Dump tx desc for debugging 6527 * @tx_desc: software descriptor head pointer 6528 * 6529 * This function will dump tx desc for further debugging 6530 * 6531 * Return: none 6532 */ 6533 static 6534 void dp_tx_dump_tx_desc(struct dp_tx_desc_s *tx_desc) 6535 { 6536 if (tx_desc) { 6537 dp_tx_comp_warn("tx_desc->nbuf: %pK", tx_desc->nbuf); 6538 dp_tx_comp_warn("tx_desc->flags: 0x%x", tx_desc->flags); 6539 dp_tx_comp_warn("tx_desc->id: %u", tx_desc->id); 6540 dp_tx_comp_warn("tx_desc->dma_addr: 0x%x", 6541 (unsigned int)tx_desc->dma_addr); 6542 dp_tx_comp_warn("tx_desc->vdev_id: %u", 6543 tx_desc->vdev_id); 6544 dp_tx_comp_warn("tx_desc->tx_status: %u", 6545 tx_desc->tx_status); 6546 dp_tx_comp_warn("tx_desc->pdev: %pK", 6547 tx_desc->pdev); 6548 dp_tx_comp_warn("tx_desc->tx_encap_type: %u", 6549 tx_desc->tx_encap_type); 6550 dp_tx_comp_warn("tx_desc->buffer_src: %u", 6551 tx_desc->buffer_src); 6552 dp_tx_comp_warn("tx_desc->frm_type: %u", 6553 tx_desc->frm_type); 6554 dp_tx_comp_warn("tx_desc->pkt_offset: %u", 6555 tx_desc->pkt_offset); 6556 dp_tx_comp_warn("tx_desc->pool_id: %u", 6557 tx_desc->pool_id); 6558 } 6559 } 6560 #endif 6561 6562 #ifdef WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT 6563 static inline 6564 bool dp_tx_comp_loop_pkt_limit_hit(struct dp_soc *soc, int num_reaped, 6565 int max_reap_limit) 6566 { 6567 bool limit_hit = false; 6568 6569 limit_hit = 6570 (num_reaped >= max_reap_limit) ? true : false; 6571 6572 if (limit_hit) 6573 DP_STATS_INC(soc, tx.tx_comp_loop_pkt_limit_hit, 1); 6574 6575 return limit_hit; 6576 } 6577 6578 static inline bool dp_tx_comp_enable_eol_data_check(struct dp_soc *soc) 6579 { 6580 return soc->wlan_cfg_ctx->tx_comp_enable_eol_data_check; 6581 } 6582 6583 static inline int dp_tx_comp_get_loop_pkt_limit(struct dp_soc *soc) 6584 { 6585 struct wlan_cfg_dp_soc_ctxt *cfg = soc->wlan_cfg_ctx; 6586 6587 return cfg->tx_comp_loop_pkt_limit; 6588 } 6589 #else 6590 static inline 6591 bool dp_tx_comp_loop_pkt_limit_hit(struct dp_soc *soc, int num_reaped, 6592 int max_reap_limit) 6593 { 6594 return false; 6595 } 6596 6597 static inline bool dp_tx_comp_enable_eol_data_check(struct dp_soc *soc) 6598 { 6599 return false; 6600 } 6601 6602 static inline int dp_tx_comp_get_loop_pkt_limit(struct dp_soc *soc) 6603 { 6604 return 0; 6605 } 6606 #endif 6607 6608 #ifdef WLAN_FEATURE_NEAR_FULL_IRQ 6609 static inline int 6610 dp_srng_test_and_update_nf_params(struct dp_soc *soc, struct dp_srng *dp_srng, 6611 int *max_reap_limit) 6612 { 6613 return soc->arch_ops.dp_srng_test_and_update_nf_params(soc, dp_srng, 6614 max_reap_limit); 6615 } 6616 #else 6617 static inline int 6618 dp_srng_test_and_update_nf_params(struct dp_soc *soc, struct dp_srng *dp_srng, 6619 int *max_reap_limit) 6620 { 6621 return 0; 6622 } 6623 #endif 6624 6625 #ifdef DP_TX_TRACKING 6626 void dp_tx_desc_check_corruption(struct dp_tx_desc_s *tx_desc) 6627 { 6628 if ((tx_desc->magic != DP_TX_MAGIC_PATTERN_INUSE) && 6629 (tx_desc->magic != DP_TX_MAGIC_PATTERN_FREE)) { 6630 dp_err_rl("tx_desc %u is corrupted", tx_desc->id); 6631 qdf_trigger_self_recovery(NULL, QDF_TX_DESC_LEAK); 6632 } 6633 } 6634 #endif 6635 6636 #ifndef WLAN_SOFTUMAC_SUPPORT 6637 #ifdef DP_TX_COMP_RING_DESC_SANITY_CHECK 6638 6639 /* Increasing this value, runs the risk of srng backpressure */ 6640 #define DP_STALE_TX_COMP_WAIT_TIMEOUT_US 1000 6641 6642 static inline void 6643 dp_tx_comp_reset_stale_entry_detection(struct dp_soc *soc, uint32_t ring_num) 6644 { 6645 soc->stale_entry[ring_num].detected = 0; 6646 } 6647 6648 /** 6649 * dp_tx_comp_stale_entry_handle() - Detect stale entry condition in tx 6650 * completion srng. 6651 * @soc: DP SoC handle 6652 * @ring_num: tx completion ring number 6653 * @status: QDF_STATUS from tx_comp_get_params_from_hal_desc arch ops 6654 * 6655 * Return: QDF_STATUS_SUCCESS if stale entry is detected and handled 6656 * QDF_STATUS error code in other cases. 6657 */ 6658 static inline QDF_STATUS 6659 dp_tx_comp_stale_entry_handle(struct dp_soc *soc, uint32_t ring_num, 6660 QDF_STATUS status) 6661 { 6662 uint64_t curr_timestamp = qdf_get_log_timestamp_usecs(); 6663 uint64_t delta_us; 6664 6665 if (status != QDF_STATUS_E_PENDING) { 6666 dp_tx_comp_reset_stale_entry_detection(soc, ring_num); 6667 return QDF_STATUS_E_INVAL; 6668 } 6669 6670 if (soc->stale_entry[ring_num].detected) { 6671 /* stale entry process continuation */ 6672 delta_us = curr_timestamp - 6673 soc->stale_entry[ring_num].start_time; 6674 if (delta_us > DP_STALE_TX_COMP_WAIT_TIMEOUT_US) { 6675 dp_err("Stale tx comp desc, waited %d us", delta_us); 6676 return QDF_STATUS_E_FAILURE; 6677 } 6678 } else { 6679 /* This is the start of stale entry detection */ 6680 soc->stale_entry[ring_num].detected = 1; 6681 soc->stale_entry[ring_num].start_time = curr_timestamp; 6682 } 6683 6684 return QDF_STATUS_SUCCESS; 6685 } 6686 #else 6687 6688 static inline void 6689 dp_tx_comp_reset_stale_entry_detection(struct dp_soc *soc, uint32_t ring_num) 6690 { 6691 } 6692 6693 static inline QDF_STATUS 6694 dp_tx_comp_stale_entry_handle(struct dp_soc *soc, uint32_t ring_num, 6695 QDF_STATUS status) 6696 { 6697 return QDF_STATUS_SUCCESS; 6698 } 6699 #endif 6700 6701 uint32_t dp_tx_comp_handler(struct dp_intr *int_ctx, struct dp_soc *soc, 6702 hal_ring_handle_t hal_ring_hdl, uint8_t ring_id, 6703 uint32_t quota) 6704 { 6705 void *tx_comp_hal_desc; 6706 void *last_prefetched_hw_desc = NULL; 6707 void *last_hw_desc = NULL; 6708 struct dp_tx_desc_s *last_prefetched_sw_desc = NULL; 6709 hal_soc_handle_t hal_soc; 6710 uint8_t buffer_src; 6711 struct dp_tx_desc_s *tx_desc = NULL; 6712 struct dp_tx_desc_s *head_desc = NULL; 6713 struct dp_tx_desc_s *tail_desc = NULL; 6714 struct dp_tx_desc_s *fast_head_desc = NULL; 6715 struct dp_tx_desc_s *fast_tail_desc = NULL; 6716 uint32_t num_processed = 0; 6717 uint32_t fast_desc_count = 0; 6718 uint32_t count; 6719 uint32_t num_avail_for_reap = 0; 6720 bool force_break = false; 6721 struct dp_srng *tx_comp_ring = &soc->tx_comp_ring[ring_id]; 6722 int max_reap_limit, ring_near_full; 6723 uint32_t num_entries; 6724 qdf_nbuf_queue_head_t h; 6725 QDF_STATUS status; 6726 6727 DP_HIST_INIT(); 6728 6729 num_entries = hal_srng_get_num_entries(soc->hal_soc, hal_ring_hdl); 6730 6731 more_data: 6732 6733 hal_soc = soc->hal_soc; 6734 /* Re-initialize local variables to be re-used */ 6735 head_desc = NULL; 6736 tail_desc = NULL; 6737 count = 0; 6738 max_reap_limit = dp_tx_comp_get_loop_pkt_limit(soc); 6739 6740 ring_near_full = dp_srng_test_and_update_nf_params(soc, tx_comp_ring, 6741 &max_reap_limit); 6742 6743 if (qdf_unlikely(dp_srng_access_start(int_ctx, soc, hal_ring_hdl))) { 6744 dp_err("HAL RING Access Failed -- %pK", hal_ring_hdl); 6745 return 0; 6746 } 6747 6748 hal_srng_update_ring_usage_wm_no_lock(soc->hal_soc, hal_ring_hdl); 6749 6750 if (!num_avail_for_reap) 6751 num_avail_for_reap = hal_srng_dst_num_valid(hal_soc, 6752 hal_ring_hdl, 0); 6753 6754 if (num_avail_for_reap >= quota) 6755 num_avail_for_reap = quota; 6756 6757 last_hw_desc = dp_srng_dst_inv_cached_descs(soc, hal_ring_hdl, 6758 num_avail_for_reap); 6759 last_prefetched_hw_desc = dp_srng_dst_prefetch_32_byte_desc(hal_soc, 6760 hal_ring_hdl, 6761 num_avail_for_reap); 6762 6763 dp_tx_nbuf_queue_head_init(&h); 6764 6765 /* Find head descriptor from completion ring */ 6766 while (qdf_likely(num_avail_for_reap--)) { 6767 6768 tx_comp_hal_desc = dp_srng_dst_get_next(soc, hal_ring_hdl); 6769 if (qdf_unlikely(!tx_comp_hal_desc)) 6770 break; 6771 buffer_src = hal_tx_comp_get_buffer_source(hal_soc, 6772 tx_comp_hal_desc); 6773 6774 /* If this buffer was not released by TQM or FW, then it is not 6775 * Tx completion indication, assert */ 6776 if (qdf_unlikely(buffer_src != 6777 HAL_TX_COMP_RELEASE_SOURCE_TQM) && 6778 (qdf_unlikely(buffer_src != 6779 HAL_TX_COMP_RELEASE_SOURCE_FW))) { 6780 uint8_t wbm_internal_error; 6781 6782 dp_err_rl( 6783 "Tx comp release_src != TQM | FW but from %d", 6784 buffer_src); 6785 hal_dump_comp_desc(tx_comp_hal_desc); 6786 DP_STATS_INC(soc, tx.invalid_release_source, 1); 6787 6788 /* When WBM sees NULL buffer_addr_info in any of 6789 * ingress rings it sends an error indication, 6790 * with wbm_internal_error=1, to a specific ring. 6791 * The WBM2SW ring used to indicate these errors is 6792 * fixed in HW, and that ring is being used as Tx 6793 * completion ring. These errors are not related to 6794 * Tx completions, and should just be ignored 6795 */ 6796 wbm_internal_error = hal_get_wbm_internal_error( 6797 hal_soc, 6798 tx_comp_hal_desc); 6799 6800 if (wbm_internal_error) { 6801 dp_err_rl("Tx comp wbm_internal_error!!"); 6802 DP_STATS_INC(soc, tx.wbm_internal_error[WBM_INT_ERROR_ALL], 1); 6803 6804 if (HAL_TX_COMP_RELEASE_SOURCE_REO == 6805 buffer_src) 6806 dp_handle_wbm_internal_error( 6807 soc, 6808 tx_comp_hal_desc, 6809 hal_tx_comp_get_buffer_type( 6810 tx_comp_hal_desc)); 6811 6812 } else { 6813 dp_err_rl("Tx comp wbm_internal_error false"); 6814 DP_STATS_INC(soc, tx.non_wbm_internal_err, 1); 6815 } 6816 continue; 6817 } 6818 6819 status = soc->arch_ops.tx_comp_get_params_from_hal_desc( 6820 soc, tx_comp_hal_desc, 6821 &tx_desc); 6822 if (qdf_unlikely(!tx_desc)) { 6823 if (QDF_IS_STATUS_SUCCESS( 6824 dp_tx_comp_stale_entry_handle(soc, ring_id, 6825 status))) { 6826 hal_srng_dst_dec_tp(hal_soc, hal_ring_hdl); 6827 break; 6828 } 6829 6830 dp_err("unable to retrieve tx_desc!"); 6831 hal_dump_comp_desc(tx_comp_hal_desc); 6832 DP_STATS_INC(soc, tx.invalid_tx_comp_desc, 1); 6833 QDF_BUG(0); 6834 continue; 6835 } 6836 6837 dp_tx_comp_reset_stale_entry_detection(soc, ring_id); 6838 tx_desc->buffer_src = buffer_src; 6839 6840 /* 6841 * If the release source is FW, process the HTT status 6842 */ 6843 if (qdf_unlikely(buffer_src == 6844 HAL_TX_COMP_RELEASE_SOURCE_FW)) { 6845 uint8_t htt_tx_status[HAL_TX_COMP_HTT_STATUS_LEN]; 6846 6847 hal_tx_comp_get_htt_desc(tx_comp_hal_desc, 6848 htt_tx_status); 6849 /* Collect hw completion contents */ 6850 hal_tx_comp_desc_sync(tx_comp_hal_desc, 6851 &tx_desc->comp, 1); 6852 soc->arch_ops.dp_tx_process_htt_completion( 6853 soc, 6854 tx_desc, 6855 htt_tx_status, 6856 ring_id); 6857 if (qdf_unlikely(!tx_desc->pdev)) { 6858 dp_tx_dump_tx_desc(tx_desc); 6859 } 6860 } else { 6861 if (tx_desc->flags & DP_TX_DESC_FLAG_FASTPATH_SIMPLE || 6862 tx_desc->flags & DP_TX_DESC_FLAG_PPEDS) 6863 goto add_to_pool2; 6864 6865 tx_desc->tx_status = 6866 hal_tx_comp_get_tx_status(tx_comp_hal_desc); 6867 tx_desc->buffer_src = buffer_src; 6868 /* 6869 * If the fast completion mode is enabled extended 6870 * metadata from descriptor is not copied 6871 */ 6872 if (qdf_likely(tx_desc->flags & 6873 DP_TX_DESC_FLAG_SIMPLE)) 6874 goto add_to_pool; 6875 6876 /* 6877 * If the descriptor is already freed in vdev_detach, 6878 * continue to next descriptor 6879 */ 6880 if (qdf_unlikely 6881 ((tx_desc->vdev_id == DP_INVALID_VDEV_ID) && 6882 !tx_desc->flags)) { 6883 dp_tx_comp_info_rl("Descriptor freed in vdev_detach %d", 6884 tx_desc->id); 6885 DP_STATS_INC(soc, tx.tx_comp_exception, 1); 6886 dp_tx_desc_check_corruption(tx_desc); 6887 continue; 6888 } 6889 6890 if (qdf_unlikely(!tx_desc->pdev)) { 6891 dp_tx_comp_warn("The pdev is NULL in TX desc, ignored."); 6892 dp_tx_dump_tx_desc(tx_desc); 6893 DP_STATS_INC(soc, tx.tx_comp_exception, 1); 6894 continue; 6895 } 6896 6897 if (qdf_unlikely(tx_desc->pdev->is_pdev_down)) { 6898 dp_tx_comp_info_rl("pdev in down state %d", 6899 tx_desc->id); 6900 tx_desc->flags |= DP_TX_DESC_FLAG_TX_COMP_ERR; 6901 dp_tx_comp_free_buf(soc, tx_desc, false); 6902 dp_tx_desc_release(soc, tx_desc, 6903 tx_desc->pool_id); 6904 goto next_desc; 6905 } 6906 6907 if (!(tx_desc->flags & DP_TX_DESC_FLAG_ALLOCATED) || 6908 !(tx_desc->flags & DP_TX_DESC_FLAG_QUEUED_TX)) { 6909 dp_tx_comp_alert("Txdesc invalid, flgs = %x,id = %d", 6910 tx_desc->flags, tx_desc->id); 6911 qdf_assert_always(0); 6912 } 6913 6914 /* Collect hw completion contents */ 6915 hal_tx_comp_desc_sync(tx_comp_hal_desc, 6916 &tx_desc->comp, 1); 6917 add_to_pool: 6918 DP_HIST_PACKET_COUNT_INC(tx_desc->pdev->pdev_id); 6919 6920 add_to_pool2: 6921 /* First ring descriptor on the cycle */ 6922 6923 if (tx_desc->flags & DP_TX_DESC_FLAG_FASTPATH_SIMPLE || 6924 tx_desc->flags & DP_TX_DESC_FLAG_PPEDS) { 6925 dp_tx_nbuf_dev_queue_free(&h, tx_desc); 6926 fast_desc_count++; 6927 if (!fast_head_desc) { 6928 fast_head_desc = tx_desc; 6929 fast_tail_desc = tx_desc; 6930 } 6931 fast_tail_desc->next = tx_desc; 6932 fast_tail_desc = tx_desc; 6933 dp_tx_desc_clear(tx_desc); 6934 } else { 6935 if (!head_desc) { 6936 head_desc = tx_desc; 6937 tail_desc = tx_desc; 6938 } 6939 6940 tail_desc->next = tx_desc; 6941 tx_desc->next = NULL; 6942 tail_desc = tx_desc; 6943 } 6944 } 6945 next_desc: 6946 num_processed += !(count & DP_TX_NAPI_BUDGET_DIV_MASK); 6947 6948 /* 6949 * Processed packet count is more than given quota 6950 * stop to processing 6951 */ 6952 6953 count++; 6954 6955 dp_tx_prefetch_hw_sw_nbuf_desc(soc, hal_soc, 6956 num_avail_for_reap, 6957 hal_ring_hdl, 6958 &last_prefetched_hw_desc, 6959 &last_prefetched_sw_desc, 6960 last_hw_desc); 6961 6962 if (dp_tx_comp_loop_pkt_limit_hit(soc, count, max_reap_limit)) 6963 break; 6964 } 6965 6966 dp_srng_access_end(int_ctx, soc, hal_ring_hdl); 6967 6968 /* Process the reaped descriptors that were sent via fast path */ 6969 if (fast_head_desc) { 6970 dp_tx_comp_process_desc_list_fast(soc, fast_head_desc, 6971 fast_tail_desc, ring_id, 6972 fast_desc_count); 6973 dp_tx_nbuf_dev_kfree_list(&h); 6974 } 6975 6976 /* Process the reaped descriptors */ 6977 if (head_desc) 6978 dp_tx_comp_process_desc_list(soc, head_desc, ring_id); 6979 6980 DP_STATS_INC(soc, tx.tx_comp[ring_id], count); 6981 6982 /* 6983 * If we are processing in near-full condition, there are 3 scenario 6984 * 1) Ring entries has reached critical state 6985 * 2) Ring entries are still near high threshold 6986 * 3) Ring entries are below the safe level 6987 * 6988 * One more loop will move the state to normal processing and yield 6989 */ 6990 if (ring_near_full) 6991 goto more_data; 6992 6993 if (dp_tx_comp_enable_eol_data_check(soc)) { 6994 6995 if (num_processed >= quota) 6996 force_break = true; 6997 6998 if (!force_break && 6999 hal_srng_dst_peek_sync_locked(soc->hal_soc, 7000 hal_ring_hdl)) { 7001 DP_STATS_INC(soc, tx.hp_oos2, 1); 7002 if (!hif_exec_should_yield(soc->hif_handle, 7003 int_ctx->dp_intr_id)) 7004 goto more_data; 7005 7006 num_avail_for_reap = 7007 hal_srng_dst_num_valid_locked(soc->hal_soc, 7008 hal_ring_hdl, 7009 true); 7010 if (qdf_unlikely(num_entries && 7011 (num_avail_for_reap >= 7012 num_entries >> 1))) { 7013 DP_STATS_INC(soc, tx.near_full, 1); 7014 goto more_data; 7015 } 7016 } 7017 } 7018 DP_TX_HIST_STATS_PER_PDEV(); 7019 7020 return num_processed; 7021 } 7022 #endif 7023 7024 #ifdef FEATURE_WLAN_TDLS 7025 qdf_nbuf_t dp_tx_non_std(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, 7026 enum ol_tx_spec tx_spec, qdf_nbuf_t msdu_list) 7027 { 7028 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); 7029 struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id, 7030 DP_MOD_ID_TDLS); 7031 7032 if (!vdev) { 7033 dp_err("vdev handle for id %d is NULL", vdev_id); 7034 return NULL; 7035 } 7036 7037 if (tx_spec & OL_TX_SPEC_NO_FREE) 7038 vdev->is_tdls_frame = true; 7039 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_TDLS); 7040 7041 return dp_tx_send(soc_hdl, vdev_id, msdu_list); 7042 } 7043 #endif 7044 7045 QDF_STATUS dp_tx_vdev_attach(struct dp_vdev *vdev) 7046 { 7047 int pdev_id; 7048 /* 7049 * Fill HTT TCL Metadata with Vdev ID and MAC ID 7050 */ 7051 DP_TX_TCL_METADATA_TYPE_SET(vdev->htt_tcl_metadata, 7052 DP_TCL_METADATA_TYPE_VDEV_BASED); 7053 7054 DP_TX_TCL_METADATA_VDEV_ID_SET(vdev->htt_tcl_metadata, 7055 vdev->vdev_id); 7056 7057 pdev_id = 7058 dp_get_target_pdev_id_for_host_pdev_id(vdev->pdev->soc, 7059 vdev->pdev->pdev_id); 7060 DP_TX_TCL_METADATA_PDEV_ID_SET(vdev->htt_tcl_metadata, pdev_id); 7061 7062 /* 7063 * Set HTT Extension Valid bit to 0 by default 7064 */ 7065 DP_TX_TCL_METADATA_VALID_HTT_SET(vdev->htt_tcl_metadata, 0); 7066 7067 dp_tx_vdev_update_search_flags(vdev); 7068 7069 return QDF_STATUS_SUCCESS; 7070 } 7071 7072 #ifndef FEATURE_WDS 7073 static inline bool dp_tx_da_search_override(struct dp_vdev *vdev) 7074 { 7075 return false; 7076 } 7077 #endif 7078 7079 void dp_tx_vdev_update_search_flags(struct dp_vdev *vdev) 7080 { 7081 struct dp_soc *soc = vdev->pdev->soc; 7082 7083 /* 7084 * Enable both AddrY (SA based search) and AddrX (Da based search) 7085 * for TDLS link 7086 * 7087 * Enable AddrY (SA based search) only for non-WDS STA and 7088 * ProxySTA VAP (in HKv1) modes. 7089 * 7090 * In all other VAP modes, only DA based search should be 7091 * enabled 7092 */ 7093 if (vdev->opmode == wlan_op_mode_sta && 7094 vdev->tdls_link_connected) 7095 vdev->hal_desc_addr_search_flags = 7096 (HAL_TX_DESC_ADDRX_EN | HAL_TX_DESC_ADDRY_EN); 7097 else if ((vdev->opmode == wlan_op_mode_sta) && 7098 !dp_tx_da_search_override(vdev)) 7099 vdev->hal_desc_addr_search_flags = HAL_TX_DESC_ADDRY_EN; 7100 else 7101 vdev->hal_desc_addr_search_flags = HAL_TX_DESC_ADDRX_EN; 7102 7103 if (vdev->opmode == wlan_op_mode_sta && !vdev->tdls_link_connected) 7104 vdev->search_type = soc->sta_mode_search_policy; 7105 else 7106 vdev->search_type = HAL_TX_ADDR_SEARCH_DEFAULT; 7107 } 7108 7109 #ifdef WLAN_SUPPORT_PPEDS 7110 static inline bool 7111 dp_is_tx_desc_flush_match(struct dp_pdev *pdev, 7112 struct dp_vdev *vdev, 7113 struct dp_tx_desc_s *tx_desc) 7114 { 7115 if (!(tx_desc && (tx_desc->flags & DP_TX_DESC_FLAG_ALLOCATED))) 7116 return false; 7117 7118 if (tx_desc->flags & DP_TX_DESC_FLAG_PPEDS) 7119 return true; 7120 /* 7121 * if vdev is given, then only check whether desc 7122 * vdev match. if vdev is NULL, then check whether 7123 * desc pdev match. 7124 */ 7125 return vdev ? (tx_desc->vdev_id == vdev->vdev_id) : 7126 (tx_desc->pdev == pdev); 7127 } 7128 #else 7129 static inline bool 7130 dp_is_tx_desc_flush_match(struct dp_pdev *pdev, 7131 struct dp_vdev *vdev, 7132 struct dp_tx_desc_s *tx_desc) 7133 { 7134 if (!(tx_desc && (tx_desc->flags & DP_TX_DESC_FLAG_ALLOCATED))) 7135 return false; 7136 7137 /* 7138 * if vdev is given, then only check whether desc 7139 * vdev match. if vdev is NULL, then check whether 7140 * desc pdev match. 7141 */ 7142 return vdev ? (tx_desc->vdev_id == vdev->vdev_id) : 7143 (tx_desc->pdev == pdev); 7144 } 7145 #endif 7146 7147 #ifdef QCA_LL_TX_FLOW_CONTROL_V2 7148 void dp_tx_desc_flush(struct dp_pdev *pdev, struct dp_vdev *vdev, 7149 bool force_free) 7150 { 7151 uint8_t i; 7152 uint32_t j; 7153 uint32_t num_desc, page_id, offset; 7154 uint16_t num_desc_per_page; 7155 struct dp_soc *soc = pdev->soc; 7156 struct dp_tx_desc_s *tx_desc = NULL; 7157 struct dp_tx_desc_pool_s *tx_desc_pool = NULL; 7158 7159 if (!vdev && !force_free) { 7160 dp_err("Reset TX desc vdev, Vdev param is required!"); 7161 return; 7162 } 7163 7164 for (i = 0; i < MAX_TXDESC_POOLS; i++) { 7165 tx_desc_pool = &soc->tx_desc[i]; 7166 if (!(tx_desc_pool->pool_size) || 7167 IS_TX_DESC_POOL_STATUS_INACTIVE(tx_desc_pool) || 7168 !(tx_desc_pool->desc_pages.cacheable_pages)) 7169 continue; 7170 7171 /* 7172 * Add flow pool lock protection in case pool is freed 7173 * due to all tx_desc is recycled when handle TX completion. 7174 * this is not necessary when do force flush as: 7175 * a. double lock will happen if dp_tx_desc_release is 7176 * also trying to acquire it. 7177 * b. dp interrupt has been disabled before do force TX desc 7178 * flush in dp_pdev_deinit(). 7179 */ 7180 if (!force_free) 7181 qdf_spin_lock_bh(&tx_desc_pool->flow_pool_lock); 7182 num_desc = tx_desc_pool->pool_size; 7183 num_desc_per_page = 7184 tx_desc_pool->desc_pages.num_element_per_page; 7185 for (j = 0; j < num_desc; j++) { 7186 page_id = j / num_desc_per_page; 7187 offset = j % num_desc_per_page; 7188 7189 if (qdf_unlikely(!(tx_desc_pool-> 7190 desc_pages.cacheable_pages))) 7191 break; 7192 7193 tx_desc = dp_tx_desc_find(soc, i, page_id, offset, 7194 false); 7195 7196 if (dp_is_tx_desc_flush_match(pdev, vdev, tx_desc)) { 7197 /* 7198 * Free TX desc if force free is 7199 * required, otherwise only reset vdev 7200 * in this TX desc. 7201 */ 7202 if (force_free) { 7203 tx_desc->flags |= DP_TX_DESC_FLAG_FLUSH; 7204 dp_tx_comp_free_buf(soc, tx_desc, 7205 false); 7206 dp_tx_desc_release(soc, tx_desc, i); 7207 } else { 7208 tx_desc->vdev_id = DP_INVALID_VDEV_ID; 7209 } 7210 } 7211 } 7212 if (!force_free) 7213 qdf_spin_unlock_bh(&tx_desc_pool->flow_pool_lock); 7214 } 7215 } 7216 #else /* QCA_LL_TX_FLOW_CONTROL_V2! */ 7217 /** 7218 * dp_tx_desc_reset_vdev() - reset vdev to NULL in TX Desc 7219 * 7220 * @soc: Handle to DP soc structure 7221 * @tx_desc: pointer of one TX desc 7222 * @desc_pool_id: TX Desc pool id 7223 * @spcl_pool: Special pool 7224 */ 7225 static inline void 7226 dp_tx_desc_reset_vdev(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc, 7227 uint8_t desc_pool_id, bool spcl_pool) 7228 { 7229 struct dp_tx_desc_pool_s *pool = NULL; 7230 7231 pool = spcl_pool ? dp_get_spcl_tx_desc_pool(soc, desc_pool_id) : 7232 dp_get_tx_desc_pool(soc, desc_pool_id); 7233 TX_DESC_LOCK_LOCK(&pool->lock); 7234 7235 tx_desc->vdev_id = DP_INVALID_VDEV_ID; 7236 7237 TX_DESC_LOCK_UNLOCK(&pool->lock); 7238 } 7239 7240 void __dp_tx_desc_flush(struct dp_pdev *pdev, struct dp_vdev *vdev, 7241 bool force_free, bool spcl_pool) 7242 { 7243 uint8_t i, num_pool; 7244 uint32_t j; 7245 uint32_t num_desc_t, page_id, offset; 7246 uint16_t num_desc_per_page; 7247 struct dp_soc *soc = pdev->soc; 7248 struct dp_tx_desc_s *tx_desc = NULL; 7249 struct dp_tx_desc_pool_s *tx_desc_pool = NULL; 7250 7251 if (!vdev && !force_free) { 7252 dp_err("Reset TX desc vdev, Vdev param is required!"); 7253 return; 7254 } 7255 7256 num_pool = wlan_cfg_get_num_tx_desc_pool(soc->wlan_cfg_ctx); 7257 7258 for (i = 0; i < num_pool; i++) { 7259 tx_desc_pool = spcl_pool ? dp_get_spcl_tx_desc_pool(soc, i) : 7260 dp_get_tx_desc_pool(soc, i); 7261 7262 num_desc_t = tx_desc_pool->elem_count; 7263 if (!tx_desc_pool->desc_pages.cacheable_pages) 7264 continue; 7265 7266 num_desc_per_page = 7267 tx_desc_pool->desc_pages.num_element_per_page; 7268 for (j = 0; j < num_desc_t; j++) { 7269 page_id = j / num_desc_per_page; 7270 offset = j % num_desc_per_page; 7271 tx_desc = dp_tx_desc_find(soc, i, page_id, offset, 7272 spcl_pool); 7273 7274 if (dp_is_tx_desc_flush_match(pdev, vdev, tx_desc)) { 7275 if (force_free) { 7276 dp_tx_comp_free_buf(soc, tx_desc, 7277 false); 7278 dp_tx_desc_release(soc, tx_desc, i); 7279 } else { 7280 dp_tx_desc_reset_vdev(soc, tx_desc, 7281 i, spcl_pool); 7282 } 7283 } 7284 } 7285 } 7286 } 7287 7288 void dp_tx_desc_flush(struct dp_pdev *pdev, struct dp_vdev *vdev, 7289 bool force_free) 7290 { 7291 __dp_tx_desc_flush(pdev, vdev, force_free, false); 7292 __dp_tx_desc_flush(pdev, vdev, force_free, true); 7293 } 7294 #endif /* !QCA_LL_TX_FLOW_CONTROL_V2 */ 7295 7296 QDF_STATUS dp_tx_vdev_detach(struct dp_vdev *vdev) 7297 { 7298 struct dp_pdev *pdev = vdev->pdev; 7299 7300 /* Reset TX desc associated to this Vdev as NULL */ 7301 dp_tx_desc_flush(pdev, vdev, false); 7302 7303 return QDF_STATUS_SUCCESS; 7304 } 7305 7306 #ifdef QCA_LL_TX_FLOW_CONTROL_V2 7307 /* Pools will be allocated dynamically */ 7308 static QDF_STATUS dp_tx_alloc_static_pools(struct dp_soc *soc, int num_pool, 7309 int num_desc) 7310 { 7311 uint8_t i; 7312 7313 for (i = 0; i < num_pool; i++) { 7314 qdf_spinlock_create(&soc->tx_desc[i].flow_pool_lock); 7315 soc->tx_desc[i].status = FLOW_POOL_INACTIVE; 7316 } 7317 7318 return QDF_STATUS_SUCCESS; 7319 } 7320 7321 static QDF_STATUS dp_tx_spcl_alloc_static_pools(struct dp_soc *soc, 7322 int num_pool, 7323 int num_spcl_desc) 7324 { 7325 return QDF_STATUS_SUCCESS; 7326 } 7327 7328 static QDF_STATUS dp_tx_init_static_pools(struct dp_soc *soc, int num_pool, 7329 uint32_t num_desc) 7330 { 7331 return QDF_STATUS_SUCCESS; 7332 } 7333 7334 static QDF_STATUS dp_tx_spcl_init_static_pools(struct dp_soc *soc, int num_pool, 7335 uint32_t num_spcl_desc) 7336 { 7337 return QDF_STATUS_SUCCESS; 7338 } 7339 7340 static void dp_tx_deinit_static_pools(struct dp_soc *soc, int num_pool) 7341 { 7342 } 7343 7344 static void dp_tx_spcl_deinit_static_pools(struct dp_soc *soc, int num_pool) 7345 { 7346 } 7347 static void dp_tx_delete_static_pools(struct dp_soc *soc, int num_pool) 7348 { 7349 uint8_t i; 7350 7351 for (i = 0; i < num_pool; i++) 7352 qdf_spinlock_destroy(&soc->tx_desc[i].flow_pool_lock); 7353 } 7354 7355 static void dp_tx_spcl_delete_static_pools(struct dp_soc *soc, int num_pool) 7356 { 7357 } 7358 #else /* QCA_LL_TX_FLOW_CONTROL_V2! */ 7359 static QDF_STATUS dp_tx_alloc_static_pools(struct dp_soc *soc, int num_pool, 7360 uint32_t num_desc) 7361 { 7362 uint8_t i, count; 7363 struct dp_global_context *dp_global; 7364 7365 dp_global = wlan_objmgr_get_global_ctx(); 7366 7367 /* Allocate software Tx descriptor pools */ 7368 7369 if (dp_global->tx_desc_pool_alloc_cnt[soc->arch_id] == 0) { 7370 for (i = 0; i < num_pool; i++) { 7371 if (dp_tx_desc_pool_alloc(soc, i, num_desc, false)) { 7372 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 7373 FL("Tx Desc Pool alloc %d failed %pK"), 7374 i, soc); 7375 goto fail; 7376 } 7377 } 7378 } 7379 dp_global->tx_desc_pool_alloc_cnt[soc->arch_id]++; 7380 return QDF_STATUS_SUCCESS; 7381 7382 fail: 7383 for (count = 0; count < i; count++) 7384 dp_tx_desc_pool_free(soc, count, false); 7385 return QDF_STATUS_E_NOMEM; 7386 } 7387 7388 static QDF_STATUS dp_tx_spcl_alloc_static_pools(struct dp_soc *soc, 7389 int num_pool, 7390 uint32_t num_spcl_desc) 7391 { 7392 uint8_t j, count; 7393 struct dp_global_context *dp_global; 7394 7395 dp_global = wlan_objmgr_get_global_ctx(); 7396 7397 /* Allocate software Tx descriptor pools */ 7398 if (dp_global->spcl_tx_desc_pool_alloc_cnt[soc->arch_id] == 0) { 7399 for (j = 0; j < num_pool; j++) { 7400 if (dp_tx_desc_pool_alloc(soc, j, num_spcl_desc, true)) { 7401 QDF_TRACE(QDF_MODULE_ID_DP, 7402 QDF_TRACE_LEVEL_ERROR, 7403 FL("Tx special Desc Pool alloc %d failed %pK"), 7404 j, soc); 7405 goto fail; 7406 } 7407 } 7408 } 7409 dp_global->spcl_tx_desc_pool_alloc_cnt[soc->arch_id]++; 7410 return QDF_STATUS_SUCCESS; 7411 7412 fail: 7413 for (count = 0; count < j; count++) 7414 dp_tx_desc_pool_free(soc, count, true); 7415 return QDF_STATUS_E_NOMEM; 7416 } 7417 7418 static QDF_STATUS dp_tx_init_static_pools(struct dp_soc *soc, int num_pool, 7419 uint32_t num_desc) 7420 { 7421 uint8_t i; 7422 struct dp_global_context *dp_global; 7423 7424 dp_global = wlan_objmgr_get_global_ctx(); 7425 7426 if (dp_global->tx_desc_pool_init_cnt[soc->arch_id] == 0) { 7427 for (i = 0; i < num_pool; i++) { 7428 if (dp_tx_desc_pool_init(soc, i, num_desc, false)) { 7429 QDF_TRACE(QDF_MODULE_ID_DP, 7430 QDF_TRACE_LEVEL_ERROR, 7431 FL("Tx Desc Pool init %d failed %pK"), 7432 i, soc); 7433 return QDF_STATUS_E_NOMEM; 7434 } 7435 } 7436 } 7437 dp_global->tx_desc_pool_init_cnt[soc->arch_id]++; 7438 return QDF_STATUS_SUCCESS; 7439 } 7440 7441 static QDF_STATUS dp_tx_spcl_init_static_pools(struct dp_soc *soc, int num_pool, 7442 uint32_t num_spcl_desc) 7443 { 7444 uint8_t i; 7445 struct dp_global_context *dp_global; 7446 7447 dp_global = wlan_objmgr_get_global_ctx(); 7448 7449 if (dp_global->spcl_tx_desc_pool_init_cnt[soc->arch_id] == 0) { 7450 for (i = 0; i < num_pool; i++) { 7451 if (dp_tx_desc_pool_init(soc, i, num_spcl_desc, true)) { 7452 QDF_TRACE(QDF_MODULE_ID_DP, 7453 QDF_TRACE_LEVEL_ERROR, 7454 FL("Tx special Desc Pool init %d failed %pK"), 7455 i, soc); 7456 return QDF_STATUS_E_NOMEM; 7457 } 7458 } 7459 } 7460 dp_global->spcl_tx_desc_pool_init_cnt[soc->arch_id]++; 7461 return QDF_STATUS_SUCCESS; 7462 } 7463 7464 static void dp_tx_deinit_static_pools(struct dp_soc *soc, int num_pool) 7465 { 7466 uint8_t i; 7467 struct dp_global_context *dp_global; 7468 7469 dp_global = wlan_objmgr_get_global_ctx(); 7470 7471 dp_global->tx_desc_pool_init_cnt[soc->arch_id]--; 7472 if (dp_global->tx_desc_pool_init_cnt[soc->arch_id] == 0) { 7473 for (i = 0; i < num_pool; i++) 7474 dp_tx_desc_pool_deinit(soc, i, false); 7475 } 7476 } 7477 7478 static void dp_tx_spcl_deinit_static_pools(struct dp_soc *soc, int num_pool) 7479 { 7480 uint8_t i; 7481 struct dp_global_context *dp_global; 7482 7483 dp_global = wlan_objmgr_get_global_ctx(); 7484 7485 dp_global->spcl_tx_desc_pool_init_cnt[soc->arch_id]--; 7486 if (dp_global->spcl_tx_desc_pool_init_cnt[soc->arch_id] == 0) { 7487 for (i = 0; i < num_pool; i++) 7488 dp_tx_desc_pool_deinit(soc, i, true); 7489 } 7490 } 7491 7492 static void dp_tx_delete_static_pools(struct dp_soc *soc, int num_pool) 7493 { 7494 uint8_t i; 7495 struct dp_global_context *dp_global; 7496 7497 dp_global = wlan_objmgr_get_global_ctx(); 7498 7499 dp_global->tx_desc_pool_alloc_cnt[soc->arch_id]--; 7500 if (dp_global->tx_desc_pool_alloc_cnt[soc->arch_id] == 0) { 7501 for (i = 0; i < num_pool; i++) 7502 dp_tx_desc_pool_free(soc, i, false); 7503 } 7504 } 7505 7506 static void dp_tx_spcl_delete_static_pools(struct dp_soc *soc, int num_pool) 7507 { 7508 uint8_t i; 7509 struct dp_global_context *dp_global; 7510 7511 dp_global = wlan_objmgr_get_global_ctx(); 7512 7513 dp_global->spcl_tx_desc_pool_alloc_cnt[soc->arch_id]--; 7514 if (dp_global->spcl_tx_desc_pool_alloc_cnt[soc->arch_id] == 0) { 7515 for (i = 0; i < num_pool; i++) 7516 dp_tx_desc_pool_free(soc, i, true); 7517 } 7518 } 7519 #endif /* !QCA_LL_TX_FLOW_CONTROL_V2 */ 7520 7521 /** 7522 * dp_tx_tso_cmn_desc_pool_deinit() - de-initialize TSO descriptors 7523 * @soc: core txrx main context 7524 * @num_pool: number of pools 7525 * 7526 */ 7527 static void dp_tx_tso_cmn_desc_pool_deinit(struct dp_soc *soc, uint8_t num_pool) 7528 { 7529 dp_tx_tso_desc_pool_deinit(soc, num_pool); 7530 dp_tx_tso_num_seg_pool_deinit(soc, num_pool); 7531 } 7532 7533 /** 7534 * dp_tx_tso_cmn_desc_pool_free() - free TSO descriptors 7535 * @soc: core txrx main context 7536 * @num_pool: number of pools 7537 * 7538 */ 7539 static void dp_tx_tso_cmn_desc_pool_free(struct dp_soc *soc, uint8_t num_pool) 7540 { 7541 dp_tx_tso_desc_pool_free(soc, num_pool); 7542 dp_tx_tso_num_seg_pool_free(soc, num_pool); 7543 } 7544 7545 #ifndef WLAN_SOFTUMAC_SUPPORT 7546 void dp_soc_tx_desc_sw_pools_free(struct dp_soc *soc) 7547 { 7548 uint8_t num_pool, num_ext_pool; 7549 7550 if (wlan_cfg_get_dp_soc_nss_cfg(soc->wlan_cfg_ctx)) 7551 return; 7552 7553 num_pool = wlan_cfg_get_num_tx_desc_pool(soc->wlan_cfg_ctx); 7554 num_ext_pool = dp_get_ext_tx_desc_pool_num(soc); 7555 7556 dp_tx_tso_cmn_desc_pool_free(soc, num_pool); 7557 dp_tx_ext_desc_pool_free(soc, num_ext_pool); 7558 dp_tx_delete_static_pools(soc, num_pool); 7559 dp_tx_spcl_delete_static_pools(soc, num_pool); 7560 } 7561 7562 void dp_soc_tx_desc_sw_pools_deinit(struct dp_soc *soc) 7563 { 7564 uint8_t num_pool, num_ext_pool; 7565 7566 if (wlan_cfg_get_dp_soc_nss_cfg(soc->wlan_cfg_ctx)) 7567 return; 7568 7569 num_pool = wlan_cfg_get_num_tx_desc_pool(soc->wlan_cfg_ctx); 7570 num_ext_pool = dp_get_ext_tx_desc_pool_num(soc); 7571 7572 dp_tx_flow_control_deinit(soc); 7573 dp_tx_tso_cmn_desc_pool_deinit(soc, num_pool); 7574 dp_tx_ext_desc_pool_deinit(soc, num_ext_pool); 7575 dp_tx_deinit_static_pools(soc, num_pool); 7576 dp_tx_spcl_deinit_static_pools(soc, num_pool); 7577 } 7578 #else 7579 void dp_soc_tx_desc_sw_pools_free(struct dp_soc *soc) 7580 { 7581 uint8_t num_pool; 7582 7583 if (wlan_cfg_get_dp_soc_nss_cfg(soc->wlan_cfg_ctx)) 7584 return; 7585 7586 num_pool = wlan_cfg_get_num_tx_desc_pool(soc->wlan_cfg_ctx); 7587 7588 dp_tx_delete_static_pools(soc, num_pool); 7589 dp_tx_spcl_delete_static_pools(soc, num_pool); 7590 } 7591 7592 void dp_soc_tx_desc_sw_pools_deinit(struct dp_soc *soc) 7593 { 7594 uint8_t num_pool; 7595 7596 if (wlan_cfg_get_dp_soc_nss_cfg(soc->wlan_cfg_ctx)) 7597 return; 7598 7599 num_pool = wlan_cfg_get_num_tx_desc_pool(soc->wlan_cfg_ctx); 7600 7601 dp_tx_flow_control_deinit(soc); 7602 dp_tx_deinit_static_pools(soc, num_pool); 7603 dp_tx_spcl_deinit_static_pools(soc, num_pool); 7604 } 7605 #endif /*WLAN_SOFTUMAC_SUPPORT*/ 7606 7607 /** 7608 * dp_tx_tso_cmn_desc_pool_alloc() - TSO cmn desc pool allocator 7609 * @soc: DP soc handle 7610 * @num_pool: Number of pools 7611 * @num_desc: Number of descriptors 7612 * 7613 * Reserve TSO descriptor buffers 7614 * 7615 * Return: QDF_STATUS_E_FAILURE on failure or 7616 * QDF_STATUS_SUCCESS on success 7617 */ 7618 static QDF_STATUS dp_tx_tso_cmn_desc_pool_alloc(struct dp_soc *soc, 7619 uint8_t num_pool, 7620 uint32_t num_desc) 7621 { 7622 if (dp_tx_tso_desc_pool_alloc(soc, num_pool, num_desc)) { 7623 dp_err("TSO Desc Pool alloc %d failed %pK", num_pool, soc); 7624 return QDF_STATUS_E_FAILURE; 7625 } 7626 7627 if (dp_tx_tso_num_seg_pool_alloc(soc, num_pool, num_desc)) { 7628 dp_err("TSO Num of seg Pool alloc %d failed %pK", 7629 num_pool, soc); 7630 return QDF_STATUS_E_FAILURE; 7631 } 7632 return QDF_STATUS_SUCCESS; 7633 } 7634 7635 /** 7636 * dp_tx_tso_cmn_desc_pool_init() - TSO cmn desc pool init 7637 * @soc: DP soc handle 7638 * @num_pool: Number of pools 7639 * @num_desc: Number of descriptors 7640 * 7641 * Initialize TSO descriptor pools 7642 * 7643 * Return: QDF_STATUS_E_FAILURE on failure or 7644 * QDF_STATUS_SUCCESS on success 7645 */ 7646 7647 static QDF_STATUS dp_tx_tso_cmn_desc_pool_init(struct dp_soc *soc, 7648 uint8_t num_pool, 7649 uint32_t num_desc) 7650 { 7651 if (dp_tx_tso_desc_pool_init(soc, num_pool, num_desc)) { 7652 dp_err("TSO Desc Pool alloc %d failed %pK", num_pool, soc); 7653 return QDF_STATUS_E_FAILURE; 7654 } 7655 7656 if (dp_tx_tso_num_seg_pool_init(soc, num_pool, num_desc)) { 7657 dp_err("TSO Num of seg Pool alloc %d failed %pK", 7658 num_pool, soc); 7659 return QDF_STATUS_E_FAILURE; 7660 } 7661 return QDF_STATUS_SUCCESS; 7662 } 7663 7664 #ifndef WLAN_SOFTUMAC_SUPPORT 7665 QDF_STATUS dp_soc_tx_desc_sw_pools_alloc(struct dp_soc *soc) 7666 { 7667 uint8_t num_pool, num_ext_pool; 7668 uint32_t num_desc; 7669 uint32_t num_spcl_desc; 7670 uint32_t num_ext_desc; 7671 7672 if (wlan_cfg_get_dp_soc_nss_cfg(soc->wlan_cfg_ctx)) 7673 return QDF_STATUS_SUCCESS; 7674 7675 num_pool = wlan_cfg_get_num_tx_desc_pool(soc->wlan_cfg_ctx); 7676 num_ext_pool = dp_get_ext_tx_desc_pool_num(soc); 7677 num_desc = wlan_cfg_get_num_tx_desc(soc->wlan_cfg_ctx); 7678 num_spcl_desc = wlan_cfg_get_num_tx_spl_desc(soc->wlan_cfg_ctx); 7679 num_ext_desc = wlan_cfg_get_num_tx_ext_desc(soc->wlan_cfg_ctx); 7680 7681 dp_info("Tx Desc Alloc num_pool: %d descs: %d", num_pool, num_desc); 7682 7683 if ((num_pool > MAX_TXDESC_POOLS) || 7684 (num_ext_pool > MAX_TXDESC_POOLS) || 7685 (num_desc > WLAN_CFG_NUM_TX_DESC_MAX) || 7686 (num_spcl_desc > WLAN_CFG_NUM_TX_SPL_DESC_MAX)) 7687 goto fail1; 7688 7689 if (dp_tx_alloc_static_pools(soc, num_pool, num_desc)) 7690 goto fail1; 7691 7692 if (dp_tx_spcl_alloc_static_pools(soc, num_pool, num_spcl_desc)) 7693 goto fail2; 7694 7695 if (dp_tx_ext_desc_pool_alloc(soc, num_ext_pool, num_ext_desc)) 7696 goto fail3; 7697 7698 if (wlan_cfg_is_tso_desc_attach_defer(soc->wlan_cfg_ctx)) 7699 return QDF_STATUS_SUCCESS; 7700 7701 if (dp_tx_tso_cmn_desc_pool_alloc(soc, num_ext_pool, num_ext_desc)) 7702 goto fail4; 7703 7704 return QDF_STATUS_SUCCESS; 7705 7706 fail4: 7707 dp_tx_ext_desc_pool_free(soc, num_ext_pool); 7708 fail3: 7709 dp_tx_spcl_delete_static_pools(soc, num_pool); 7710 fail2: 7711 dp_tx_delete_static_pools(soc, num_pool); 7712 fail1: 7713 return QDF_STATUS_E_RESOURCES; 7714 } 7715 7716 QDF_STATUS dp_soc_tx_desc_sw_pools_init(struct dp_soc *soc) 7717 { 7718 uint8_t num_pool, num_ext_pool; 7719 uint32_t num_desc; 7720 uint32_t num_spcl_desc; 7721 uint32_t num_ext_desc; 7722 7723 if (wlan_cfg_get_dp_soc_nss_cfg(soc->wlan_cfg_ctx)) 7724 return QDF_STATUS_SUCCESS; 7725 7726 num_pool = wlan_cfg_get_num_tx_desc_pool(soc->wlan_cfg_ctx); 7727 num_ext_pool = dp_get_ext_tx_desc_pool_num(soc); 7728 num_desc = wlan_cfg_get_num_tx_desc(soc->wlan_cfg_ctx); 7729 num_spcl_desc = wlan_cfg_get_num_tx_spl_desc(soc->wlan_cfg_ctx); 7730 num_ext_desc = wlan_cfg_get_num_tx_ext_desc(soc->wlan_cfg_ctx); 7731 7732 if (dp_tx_init_static_pools(soc, num_pool, num_desc)) 7733 goto fail1; 7734 7735 if (dp_tx_spcl_init_static_pools(soc, num_pool, num_spcl_desc)) 7736 goto fail2; 7737 7738 if (dp_tx_ext_desc_pool_init(soc, num_ext_pool, num_ext_desc)) 7739 goto fail3; 7740 7741 if (wlan_cfg_is_tso_desc_attach_defer(soc->wlan_cfg_ctx)) 7742 return QDF_STATUS_SUCCESS; 7743 7744 if (dp_tx_tso_cmn_desc_pool_init(soc, num_ext_pool, num_ext_desc)) 7745 goto fail4; 7746 7747 dp_tx_flow_control_init(soc); 7748 soc->process_tx_status = CONFIG_PROCESS_TX_STATUS; 7749 return QDF_STATUS_SUCCESS; 7750 7751 fail4: 7752 dp_tx_ext_desc_pool_deinit(soc, num_ext_pool); 7753 fail3: 7754 dp_tx_spcl_deinit_static_pools(soc, num_pool); 7755 fail2: 7756 dp_tx_deinit_static_pools(soc, num_pool); 7757 fail1: 7758 return QDF_STATUS_E_RESOURCES; 7759 } 7760 7761 #else 7762 QDF_STATUS dp_soc_tx_desc_sw_pools_alloc(struct dp_soc *soc) 7763 { 7764 uint8_t num_pool; 7765 uint32_t num_desc; 7766 uint32_t num_spcl_desc; 7767 7768 if (wlan_cfg_get_dp_soc_nss_cfg(soc->wlan_cfg_ctx)) 7769 return QDF_STATUS_SUCCESS; 7770 7771 num_pool = wlan_cfg_get_num_tx_desc_pool(soc->wlan_cfg_ctx); 7772 num_desc = wlan_cfg_get_num_tx_desc(soc->wlan_cfg_ctx); 7773 num_spcl_desc = wlan_cfg_get_num_tx_spl_desc(soc->wlan_cfg_ctx); 7774 7775 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, 7776 "%s Tx Desc Alloc num_pool = %d, descs = %d", 7777 __func__, num_pool, num_desc); 7778 7779 if ((num_pool > MAX_TXDESC_POOLS) || 7780 (num_desc > WLAN_CFG_NUM_TX_DESC_MAX) || 7781 (num_spcl_desc > WLAN_CFG_NUM_TX_SPL_DESC_MAX)) 7782 goto fail1; 7783 7784 if (dp_tx_alloc_static_pools(soc, num_pool, num_desc)) 7785 goto fail1; 7786 7787 if (dp_tx_spcl_alloc_static_pools(soc, num_pool, num_spcl_desc)) 7788 goto fail2; 7789 return QDF_STATUS_SUCCESS; 7790 7791 fail2: 7792 dp_tx_delete_static_pools(soc, num_pool); 7793 fail1: 7794 return QDF_STATUS_E_RESOURCES; 7795 } 7796 7797 QDF_STATUS dp_soc_tx_desc_sw_pools_init(struct dp_soc *soc) 7798 { 7799 uint8_t num_pool; 7800 uint32_t num_desc; 7801 uint32_t num_spcl_desc; 7802 7803 if (wlan_cfg_get_dp_soc_nss_cfg(soc->wlan_cfg_ctx)) 7804 return QDF_STATUS_SUCCESS; 7805 7806 num_pool = wlan_cfg_get_num_tx_desc_pool(soc->wlan_cfg_ctx); 7807 num_desc = wlan_cfg_get_num_tx_desc(soc->wlan_cfg_ctx); 7808 num_spcl_desc = wlan_cfg_get_num_tx_spl_desc(soc->wlan_cfg_ctx); 7809 7810 if (dp_tx_init_static_pools(soc, num_pool, num_desc)) 7811 goto fail; 7812 7813 if (dp_tx_spcl_init_static_pools(soc, num_pool, num_spcl_desc)) 7814 goto fail1; 7815 7816 dp_tx_flow_control_init(soc); 7817 soc->process_tx_status = CONFIG_PROCESS_TX_STATUS; 7818 return QDF_STATUS_SUCCESS; 7819 fail1: 7820 dp_tx_deinit_static_pools(soc, num_pool); 7821 fail: 7822 return QDF_STATUS_E_RESOURCES; 7823 } 7824 #endif 7825 7826 QDF_STATUS dp_tso_soc_attach(struct cdp_soc_t *txrx_soc) 7827 { 7828 struct dp_soc *soc = (struct dp_soc *)txrx_soc; 7829 uint8_t num_ext_desc_pool; 7830 uint32_t num_ext_desc; 7831 7832 num_ext_desc_pool = dp_get_ext_tx_desc_pool_num(soc); 7833 num_ext_desc = wlan_cfg_get_num_tx_ext_desc(soc->wlan_cfg_ctx); 7834 7835 if (dp_tx_tso_cmn_desc_pool_alloc(soc, num_ext_desc_pool, num_ext_desc)) 7836 return QDF_STATUS_E_FAILURE; 7837 7838 if (dp_tx_tso_cmn_desc_pool_init(soc, num_ext_desc_pool, num_ext_desc)) 7839 return QDF_STATUS_E_FAILURE; 7840 7841 return QDF_STATUS_SUCCESS; 7842 } 7843 7844 QDF_STATUS dp_tso_soc_detach(struct cdp_soc_t *txrx_soc) 7845 { 7846 struct dp_soc *soc = (struct dp_soc *)txrx_soc; 7847 uint8_t num_ext_desc_pool = dp_get_ext_tx_desc_pool_num(soc); 7848 7849 dp_tx_tso_cmn_desc_pool_deinit(soc, num_ext_desc_pool); 7850 dp_tx_tso_cmn_desc_pool_free(soc, num_ext_desc_pool); 7851 7852 return QDF_STATUS_SUCCESS; 7853 } 7854 7855 #ifdef CONFIG_DP_PKT_ADD_TIMESTAMP 7856 void dp_pkt_add_timestamp(struct dp_vdev *vdev, 7857 enum qdf_pkt_timestamp_index index, uint64_t time, 7858 qdf_nbuf_t nbuf) 7859 { 7860 if (qdf_unlikely(qdf_is_dp_pkt_timestamp_enabled())) { 7861 uint64_t tsf_time; 7862 7863 if (vdev->get_tsf_time) { 7864 vdev->get_tsf_time(vdev->osif_vdev, time, &tsf_time); 7865 qdf_add_dp_pkt_timestamp(nbuf, index, tsf_time); 7866 } 7867 } 7868 } 7869 7870 void dp_pkt_get_timestamp(uint64_t *time) 7871 { 7872 if (qdf_unlikely(qdf_is_dp_pkt_timestamp_enabled())) 7873 *time = qdf_get_log_timestamp(); 7874 } 7875 #endif 7876 7877 #ifdef QCA_MULTIPASS_SUPPORT 7878 void dp_tx_add_groupkey_metadata(struct dp_vdev *vdev, 7879 struct dp_tx_msdu_info_s *msdu_info, 7880 uint16_t group_key) 7881 { 7882 struct htt_tx_msdu_desc_ext2_t *meta_data = 7883 (struct htt_tx_msdu_desc_ext2_t *)&msdu_info->meta_data[0]; 7884 7885 qdf_mem_zero(meta_data, sizeof(struct htt_tx_msdu_desc_ext2_t)); 7886 7887 /* 7888 * When attempting to send a multicast packet with multi-passphrase, 7889 * host shall add HTT EXT meta data "struct htt_tx_msdu_desc_ext2_t" 7890 * ref htt.h indicating the group_id field in "key_flags" also having 7891 * "valid_key_flags" as 1. Assign “key_flags = group_key_ix”. 7892 */ 7893 HTT_TX_MSDU_EXT2_DESC_FLAG_VALID_KEY_FLAGS_SET(msdu_info->meta_data[0], 7894 1); 7895 HTT_TX_MSDU_EXT2_DESC_KEY_FLAGS_SET(msdu_info->meta_data[2], group_key); 7896 } 7897 7898 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) && \ 7899 defined(WLAN_MCAST_MLO) 7900 /** 7901 * dp_tx_need_mcast_reinject() - If frame needs to be processed in reinject path 7902 * @vdev: DP vdev handle 7903 * 7904 * Return: true if reinject handling is required else false 7905 */ 7906 static inline bool 7907 dp_tx_need_mcast_reinject(struct dp_vdev *vdev) 7908 { 7909 if (vdev->mlo_vdev && vdev->opmode == wlan_op_mode_ap) 7910 return true; 7911 7912 return false; 7913 } 7914 #else 7915 static inline bool 7916 dp_tx_need_mcast_reinject(struct dp_vdev *vdev) 7917 { 7918 return false; 7919 } 7920 #endif 7921 7922 /** 7923 * dp_tx_need_multipass_process() - If frame needs multipass phrase processing 7924 * @soc: dp soc handle 7925 * @vdev: DP vdev handle 7926 * @buf: frame 7927 * @vlan_id: vlan id of frame 7928 * 7929 * Return: whether peer is special or classic 7930 */ 7931 static 7932 uint8_t dp_tx_need_multipass_process(struct dp_soc *soc, struct dp_vdev *vdev, 7933 qdf_nbuf_t buf, uint16_t *vlan_id) 7934 { 7935 struct dp_txrx_peer *txrx_peer = NULL; 7936 struct dp_peer *peer = NULL; 7937 qdf_ether_header_t *eh = (qdf_ether_header_t *)qdf_nbuf_data(buf); 7938 struct vlan_ethhdr *veh = NULL; 7939 bool not_vlan = ((vdev->tx_encap_type == htt_cmn_pkt_type_raw) || 7940 (htons(eh->ether_type) != ETH_P_8021Q)); 7941 struct cdp_peer_info peer_info = { 0 }; 7942 7943 if (qdf_unlikely(not_vlan)) 7944 return DP_VLAN_UNTAGGED; 7945 7946 veh = (struct vlan_ethhdr *)eh; 7947 *vlan_id = (ntohs(veh->h_vlan_TCI) & VLAN_VID_MASK); 7948 7949 if (qdf_unlikely(DP_FRAME_IS_MULTICAST((eh)->ether_dhost))) { 7950 /* look for handling of multicast packets in reinject path */ 7951 if (dp_tx_need_mcast_reinject(vdev)) 7952 return DP_VLAN_UNTAGGED; 7953 7954 qdf_spin_lock_bh(&vdev->mpass_peer_mutex); 7955 TAILQ_FOREACH(txrx_peer, &vdev->mpass_peer_list, 7956 mpass_peer_list_elem) { 7957 if (*vlan_id == txrx_peer->vlan_id) { 7958 qdf_spin_unlock_bh(&vdev->mpass_peer_mutex); 7959 return DP_VLAN_TAGGED_MULTICAST; 7960 } 7961 } 7962 qdf_spin_unlock_bh(&vdev->mpass_peer_mutex); 7963 return DP_VLAN_UNTAGGED; 7964 } 7965 7966 DP_PEER_INFO_PARAMS_INIT(&peer_info, DP_VDEV_ALL, eh->ether_dhost, 7967 false, CDP_WILD_PEER_TYPE); 7968 peer = dp_peer_hash_find_wrapper((struct dp_soc *)soc, &peer_info, 7969 DP_MOD_ID_TX_MULTIPASS); 7970 if (qdf_unlikely(!peer)) 7971 return DP_VLAN_UNTAGGED; 7972 7973 /* 7974 * Do not drop the frame when vlan_id doesn't match. 7975 * Send the frame as it is. 7976 */ 7977 if (*vlan_id == peer->txrx_peer->vlan_id) { 7978 dp_peer_unref_delete(peer, DP_MOD_ID_TX_MULTIPASS); 7979 return DP_VLAN_TAGGED_UNICAST; 7980 } 7981 7982 dp_peer_unref_delete(peer, DP_MOD_ID_TX_MULTIPASS); 7983 return DP_VLAN_UNTAGGED; 7984 } 7985 7986 #ifndef WLAN_REPEATER_NOT_SUPPORTED 7987 static inline void 7988 dp_tx_multipass_send_pkt_to_repeater(struct dp_soc *soc, struct dp_vdev *vdev, 7989 qdf_nbuf_t nbuf, 7990 struct dp_tx_msdu_info_s *msdu_info) 7991 { 7992 qdf_nbuf_t nbuf_copy = NULL; 7993 7994 /* AP can have classic clients, special clients & 7995 * classic repeaters. 7996 * 1. Classic clients & special client: 7997 * Remove vlan header, find corresponding group key 7998 * index, fill in metaheader and enqueue multicast 7999 * frame to TCL. 8000 * 2. Classic repeater: 8001 * Pass through to classic repeater with vlan tag 8002 * intact without any group key index. Hardware 8003 * will know which key to use to send frame to 8004 * repeater. 8005 */ 8006 nbuf_copy = qdf_nbuf_copy(nbuf); 8007 8008 /* 8009 * Send multicast frame to special peers even 8010 * if pass through to classic repeater fails. 8011 */ 8012 if (nbuf_copy) { 8013 struct dp_tx_msdu_info_s msdu_info_copy; 8014 8015 qdf_mem_zero(&msdu_info_copy, sizeof(msdu_info_copy)); 8016 msdu_info_copy.tid = HTT_TX_EXT_TID_INVALID; 8017 msdu_info_copy.xmit_type = 8018 qdf_nbuf_get_vdev_xmit_type(nbuf); 8019 HTT_TX_MSDU_EXT2_DESC_FLAG_VALID_KEY_FLAGS_SET(msdu_info_copy.meta_data[0], 1); 8020 nbuf_copy = dp_tx_send_msdu_single(vdev, nbuf_copy, 8021 &msdu_info_copy, 8022 HTT_INVALID_PEER, NULL); 8023 if (nbuf_copy) { 8024 qdf_nbuf_free(nbuf_copy); 8025 dp_info_rl("nbuf_copy send failed"); 8026 } 8027 } 8028 } 8029 #else 8030 static inline void 8031 dp_tx_multipass_send_pkt_to_repeater(struct dp_soc *soc, struct dp_vdev *vdev, 8032 qdf_nbuf_t nbuf, 8033 struct dp_tx_msdu_info_s *msdu_info) 8034 { 8035 } 8036 #endif 8037 8038 bool dp_tx_multipass_process(struct dp_soc *soc, struct dp_vdev *vdev, 8039 qdf_nbuf_t nbuf, 8040 struct dp_tx_msdu_info_s *msdu_info) 8041 { 8042 uint16_t vlan_id = 0; 8043 uint16_t group_key = 0; 8044 uint8_t is_spcl_peer = DP_VLAN_UNTAGGED; 8045 8046 if (HTT_TX_MSDU_EXT2_DESC_FLAG_VALID_KEY_FLAGS_GET(msdu_info->meta_data[0])) 8047 return true; 8048 8049 is_spcl_peer = dp_tx_need_multipass_process(soc, vdev, nbuf, &vlan_id); 8050 8051 if ((is_spcl_peer != DP_VLAN_TAGGED_MULTICAST) && 8052 (is_spcl_peer != DP_VLAN_TAGGED_UNICAST)) 8053 return true; 8054 8055 if (is_spcl_peer == DP_VLAN_TAGGED_UNICAST) { 8056 dp_tx_remove_vlan_tag(vdev, nbuf); 8057 return true; 8058 } 8059 8060 dp_tx_multipass_send_pkt_to_repeater(soc, vdev, nbuf, msdu_info); 8061 group_key = vdev->iv_vlan_map[vlan_id]; 8062 8063 /* 8064 * If group key is not installed, drop the frame. 8065 */ 8066 if (!group_key) 8067 return false; 8068 8069 dp_tx_remove_vlan_tag(vdev, nbuf); 8070 dp_tx_add_groupkey_metadata(vdev, msdu_info, group_key); 8071 msdu_info->exception_fw = 1; 8072 return true; 8073 } 8074 #endif /* QCA_MULTIPASS_SUPPORT */ 8075