1 /* 2 * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 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 #include "cdp_txrx_cmn_struct.h" 20 #include "dp_types.h" 21 #include "dp_tx.h" 22 #include "dp_li_tx.h" 23 #include "dp_tx_desc.h" 24 #include <dp_internal.h> 25 #include <dp_htt.h> 26 #include <hal_li_api.h> 27 #include <hal_li_tx.h> 28 #include "dp_peer.h" 29 #ifdef FEATURE_WDS 30 #include "dp_txrx_wds.h" 31 #endif 32 #include "dp_li.h" 33 34 extern uint8_t sec_type_map[MAX_CDP_SEC_TYPE]; 35 36 void dp_tx_comp_get_params_from_hal_desc_li(struct dp_soc *soc, 37 void *tx_comp_hal_desc, 38 struct dp_tx_desc_s **r_tx_desc) 39 { 40 uint8_t pool_id; 41 uint32_t tx_desc_id; 42 43 tx_desc_id = hal_tx_comp_get_desc_id(tx_comp_hal_desc); 44 pool_id = (tx_desc_id & DP_TX_DESC_ID_POOL_MASK) >> 45 DP_TX_DESC_ID_POOL_OS; 46 47 /* Find Tx descriptor */ 48 *r_tx_desc = dp_tx_desc_find(soc, pool_id, 49 (tx_desc_id & DP_TX_DESC_ID_PAGE_MASK) >> 50 DP_TX_DESC_ID_PAGE_OS, 51 (tx_desc_id & DP_TX_DESC_ID_OFFSET_MASK) >> 52 DP_TX_DESC_ID_OFFSET_OS); 53 /* Pool id is not matching. Error */ 54 if ((*r_tx_desc)->pool_id != pool_id) { 55 dp_tx_comp_alert("Tx Comp pool id %d not matched %d", 56 pool_id, (*r_tx_desc)->pool_id); 57 58 qdf_assert_always(0); 59 } 60 61 (*r_tx_desc)->peer_id = hal_tx_comp_get_peer_id(tx_comp_hal_desc); 62 } 63 64 static inline 65 void dp_tx_process_mec_notify_li(struct dp_soc *soc, uint8_t *status) 66 { 67 struct dp_vdev *vdev; 68 uint8_t vdev_id; 69 uint32_t *htt_desc = (uint32_t *)status; 70 71 /* 72 * Get vdev id from HTT status word in case of MEC 73 * notification 74 */ 75 vdev_id = HTT_TX_WBM_COMPLETION_V2_VDEV_ID_GET(htt_desc[3]); 76 if (qdf_unlikely(vdev_id >= MAX_VDEV_CNT)) 77 return; 78 79 vdev = dp_vdev_get_ref_by_id(soc, vdev_id, 80 DP_MOD_ID_HTT_COMP); 81 if (!vdev) 82 return; 83 dp_tx_mec_handler(vdev, status); 84 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_HTT_COMP); 85 } 86 87 void dp_tx_process_htt_completion_li(struct dp_soc *soc, 88 struct dp_tx_desc_s *tx_desc, 89 uint8_t *status, 90 uint8_t ring_id) 91 { 92 uint8_t tx_status; 93 struct dp_pdev *pdev; 94 struct dp_vdev *vdev = NULL; 95 struct hal_tx_completion_status ts = {0}; 96 uint32_t *htt_desc = (uint32_t *)status; 97 struct dp_txrx_peer *txrx_peer; 98 dp_txrx_ref_handle txrx_ref_handle = NULL; 99 struct cdp_tid_tx_stats *tid_stats = NULL; 100 struct htt_soc *htt_handle; 101 uint8_t vdev_id; 102 103 tx_status = HTT_TX_WBM_COMPLETION_V2_TX_STATUS_GET(htt_desc[0]); 104 htt_handle = (struct htt_soc *)soc->htt_handle; 105 htt_wbm_event_record(htt_handle->htt_logger_handle, tx_status, status); 106 107 /* 108 * There can be scenario where WBM consuming descriptor enqueued 109 * from TQM2WBM first and TQM completion can happen before MEC 110 * notification comes from FW2WBM. Avoid access any field of tx 111 * descriptor in case of MEC notify. 112 */ 113 if (tx_status == HTT_TX_FW2WBM_TX_STATUS_MEC_NOTIFY) 114 return dp_tx_process_mec_notify_li(soc, status); 115 116 /* 117 * If the descriptor is already freed in vdev_detach, 118 * continue to next descriptor 119 */ 120 if (qdf_unlikely(!tx_desc->flags)) { 121 dp_tx_comp_info_rl("Descriptor freed in vdev_detach %d", 122 tx_desc->id); 123 return; 124 } 125 126 if (qdf_unlikely(tx_desc->vdev_id == DP_INVALID_VDEV_ID)) { 127 dp_tx_comp_info_rl("Invalid vdev_id %d", tx_desc->id); 128 tx_desc->flags |= DP_TX_DESC_FLAG_TX_COMP_ERR; 129 goto release_tx_desc; 130 } 131 132 pdev = tx_desc->pdev; 133 134 if (qdf_unlikely(tx_desc->pdev->is_pdev_down)) { 135 dp_tx_comp_info_rl("pdev in down state %d", tx_desc->id); 136 tx_desc->flags |= DP_TX_DESC_FLAG_TX_COMP_ERR; 137 goto release_tx_desc; 138 } 139 140 qdf_assert(tx_desc->pdev); 141 142 vdev_id = tx_desc->vdev_id; 143 vdev = dp_vdev_get_ref_by_id(soc, vdev_id, 144 DP_MOD_ID_HTT_COMP); 145 146 if (qdf_unlikely(!vdev)) { 147 dp_tx_comp_info_rl("Unable to get vdev ref %d", tx_desc->id); 148 tx_desc->flags |= DP_TX_DESC_FLAG_TX_COMP_ERR; 149 goto release_tx_desc; 150 } 151 152 switch (tx_status) { 153 case HTT_TX_FW2WBM_TX_STATUS_OK: 154 case HTT_TX_FW2WBM_TX_STATUS_DROP: 155 case HTT_TX_FW2WBM_TX_STATUS_TTL: 156 { 157 uint8_t tid; 158 159 if (HTT_TX_WBM_COMPLETION_V2_VALID_GET(htt_desc[2])) { 160 ts.peer_id = 161 HTT_TX_WBM_COMPLETION_V2_SW_PEER_ID_GET( 162 htt_desc[2]); 163 ts.tid = 164 HTT_TX_WBM_COMPLETION_V2_TID_NUM_GET( 165 htt_desc[2]); 166 } else { 167 ts.peer_id = HTT_INVALID_PEER; 168 ts.tid = HTT_INVALID_TID; 169 } 170 ts.release_src = HAL_TX_COMP_RELEASE_SOURCE_FW; 171 ts.ppdu_id = 172 HTT_TX_WBM_COMPLETION_V2_SCH_CMD_ID_GET( 173 htt_desc[1]); 174 ts.ack_frame_rssi = 175 HTT_TX_WBM_COMPLETION_V2_ACK_FRAME_RSSI_GET( 176 htt_desc[1]); 177 178 ts.tsf = htt_desc[3]; 179 ts.first_msdu = 1; 180 ts.last_msdu = 1; 181 switch (tx_status) { 182 case HTT_TX_FW2WBM_TX_STATUS_OK: 183 ts.status = HAL_TX_TQM_RR_FRAME_ACKED; 184 break; 185 case HTT_TX_FW2WBM_TX_STATUS_DROP: 186 ts.status = HAL_TX_TQM_RR_REM_CMD_REM; 187 break; 188 case HTT_TX_FW2WBM_TX_STATUS_TTL: 189 ts.status = HAL_TX_TQM_RR_REM_CMD_TX; 190 break; 191 } 192 tid = ts.tid; 193 if (qdf_unlikely(tid >= CDP_MAX_DATA_TIDS)) 194 tid = CDP_MAX_DATA_TIDS - 1; 195 196 tid_stats = &pdev->stats.tid_stats.tid_tx_stats[ring_id][tid]; 197 198 if (qdf_unlikely(pdev->delay_stats_flag) || 199 qdf_unlikely(dp_is_vdev_tx_delay_stats_enabled(vdev))) 200 dp_tx_compute_delay(vdev, tx_desc, tid, ring_id); 201 if (tx_status < CDP_MAX_TX_HTT_STATUS) 202 tid_stats->htt_status_cnt[tx_status]++; 203 204 txrx_peer = dp_txrx_peer_get_ref_by_id(soc, ts.peer_id, 205 &txrx_ref_handle, 206 DP_MOD_ID_HTT_COMP); 207 if (qdf_likely(txrx_peer)) { 208 DP_PEER_STATS_FLAT_INC_PKT(txrx_peer, comp_pkt, 1, 209 qdf_nbuf_len(tx_desc->nbuf)); 210 if (tx_status != HTT_TX_FW2WBM_TX_STATUS_OK) 211 DP_PEER_STATS_FLAT_INC(txrx_peer, tx_failed, 1); 212 } 213 214 dp_tx_comp_process_tx_status(soc, tx_desc, &ts, txrx_peer, 215 ring_id); 216 dp_tx_comp_process_desc(soc, tx_desc, &ts, txrx_peer); 217 dp_tx_desc_release(tx_desc, tx_desc->pool_id); 218 219 if (qdf_likely(txrx_peer)) 220 dp_txrx_peer_unref_delete(txrx_ref_handle, 221 DP_MOD_ID_HTT_COMP); 222 223 break; 224 } 225 case HTT_TX_FW2WBM_TX_STATUS_REINJECT: 226 { 227 uint8_t reinject_reason; 228 229 reinject_reason = 230 HTT_TX_WBM_COMPLETION_V2_REINJECT_REASON_GET( 231 htt_desc[0]); 232 dp_tx_reinject_handler(soc, vdev, tx_desc, 233 status, reinject_reason); 234 break; 235 } 236 case HTT_TX_FW2WBM_TX_STATUS_INSPECT: 237 { 238 dp_tx_inspect_handler(soc, vdev, tx_desc, status); 239 break; 240 } 241 case HTT_TX_FW2WBM_TX_STATUS_VDEVID_MISMATCH: 242 { 243 DP_STATS_INC(vdev, tx_i.dropped.fail_per_pkt_vdev_id_check, 1); 244 goto release_tx_desc; 245 } 246 default: 247 dp_tx_comp_err("Invalid HTT tx_status %d\n", 248 tx_status); 249 goto release_tx_desc; 250 } 251 252 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_HTT_COMP); 253 return; 254 255 release_tx_desc: 256 dp_tx_comp_free_buf(soc, tx_desc, false); 257 dp_tx_desc_release(tx_desc, tx_desc->pool_id); 258 if (vdev) 259 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_HTT_COMP); 260 } 261 262 #ifdef QCA_OL_TX_MULTIQ_SUPPORT 263 /* 264 * dp_tx_get_rbm_id()- Get the RBM ID for data transmission completion. 265 * @dp_soc - DP soc structure pointer 266 * @ring_id - Transmit Queue/ring_id to be used when XPS is enabled 267 * 268 * Return - HAL ring handle 269 */ 270 #ifdef IPA_OFFLOAD 271 static inline uint8_t dp_tx_get_rbm_id_li(struct dp_soc *soc, 272 uint8_t ring_id) 273 { 274 return (ring_id + soc->wbm_sw0_bm_id); 275 } 276 #else 277 #ifndef QCA_DP_ENABLE_TX_COMP_RING4 278 static inline uint8_t dp_tx_get_rbm_id_li(struct dp_soc *soc, 279 uint8_t ring_id) 280 { 281 return (ring_id ? HAL_WBM_SW0_BM_ID + (ring_id - 1) : 282 HAL_WBM_SW2_BM_ID); 283 } 284 #else 285 static inline uint8_t dp_tx_get_rbm_id_li(struct dp_soc *soc, 286 uint8_t ring_id) 287 { 288 if (ring_id == soc->num_tcl_data_rings) 289 return HAL_WBM_SW4_BM_ID(soc->wbm_sw0_bm_id); 290 return (ring_id + HAL_WBM_SW0_BM_ID(soc->wbm_sw0_bm_id)); 291 } 292 #endif 293 #endif 294 #else 295 #ifdef TX_MULTI_TCL 296 #ifdef IPA_OFFLOAD 297 static inline uint8_t dp_tx_get_rbm_id_li(struct dp_soc *soc, 298 uint8_t ring_id) 299 { 300 if (soc->wlan_cfg_ctx->ipa_enabled) 301 return (ring_id + soc->wbm_sw0_bm_id); 302 303 return soc->wlan_cfg_ctx->tcl_wbm_map_array[ring_id].wbm_rbm_id; 304 } 305 #else 306 static inline uint8_t dp_tx_get_rbm_id_li(struct dp_soc *soc, 307 uint8_t ring_id) 308 { 309 return soc->wlan_cfg_ctx->tcl_wbm_map_array[ring_id].wbm_rbm_id; 310 } 311 #endif 312 #else 313 static inline uint8_t dp_tx_get_rbm_id_li(struct dp_soc *soc, 314 uint8_t ring_id) 315 { 316 return (ring_id + soc->wbm_sw0_bm_id); 317 } 318 #endif 319 #endif 320 321 #if defined(CLEAR_SW2TCL_CONSUMED_DESC) 322 /** 323 * dp_tx_clear_consumed_hw_descs - Reset all the consumed Tx ring descs to 0 324 * 325 * @soc: DP soc handle 326 * @hal_ring_hdl: Source ring pointer 327 * 328 * Return: void 329 */ 330 static inline 331 void dp_tx_clear_consumed_hw_descs(struct dp_soc *soc, 332 hal_ring_handle_t hal_ring_hdl) 333 { 334 void *desc = hal_srng_src_get_next_consumed(soc->hal_soc, hal_ring_hdl); 335 336 while (desc) { 337 hal_tx_desc_clear(desc); 338 desc = hal_srng_src_get_next_consumed(soc->hal_soc, 339 hal_ring_hdl); 340 } 341 } 342 343 #else 344 static inline 345 void dp_tx_clear_consumed_hw_descs(struct dp_soc *soc, 346 hal_ring_handle_t hal_ring_hdl) 347 { 348 } 349 #endif /* CLEAR_SW2TCL_CONSUMED_DESC */ 350 351 #ifdef WLAN_CONFIG_TX_DELAY 352 static inline 353 QDF_STATUS dp_tx_compute_hw_delay_li(struct dp_soc *soc, 354 struct dp_vdev *vdev, 355 struct hal_tx_completion_status *ts, 356 uint32_t *delay_us) 357 { 358 return dp_tx_compute_hw_delay_us(ts, vdev->delta_tsf, delay_us); 359 } 360 #else 361 static inline 362 QDF_STATUS dp_tx_compute_hw_delay_li(struct dp_soc *soc, 363 struct dp_vdev *vdev, 364 struct hal_tx_completion_status *ts, 365 uint32_t *delay_us) 366 { 367 return QDF_STATUS_SUCCESS; 368 } 369 #endif 370 371 #ifdef CONFIG_SAWF 372 /** 373 * dp_sawf_config_li - Configure sawf specific fields in tcl 374 * 375 * @soc: DP soc handle 376 * @hhal_tx_desc_cached: tx descriptor 377 * @vdev_id: vdev id 378 * @nbuf: skb buffer 379 * 380 * Return: void 381 */ 382 static inline 383 void dp_sawf_config_li(struct dp_soc *soc, uint32_t *hal_tx_desc_cached, 384 uint16_t *fw_metadata, uint16_t vdev_id, 385 qdf_nbuf_t nbuf) 386 { 387 uint8_t q_id = 0; 388 uint32_t search_index; 389 390 if (!wlan_cfg_get_sawf_config(soc->wlan_cfg_ctx)) 391 return; 392 393 q_id = dp_sawf_queue_id_get(nbuf); 394 if (q_id == DP_SAWF_DEFAULT_Q_INVALID) 395 return; 396 397 dp_sawf_tcl_cmd(fw_metadata, nbuf); 398 399 search_index = dp_sawf_get_search_index(soc, nbuf, vdev_id, 400 q_id); 401 hal_tx_desc_set_hlos_tid(hal_tx_desc_cached, 402 (q_id & (CDP_DATA_TID_MAX - 1))); 403 hal_tx_desc_set_search_type_li(soc->hal_soc, hal_tx_desc_cached, 404 HAL_TX_ADDR_INDEX_SEARCH); 405 hal_tx_desc_set_search_index_li(soc->hal_soc, hal_tx_desc_cached, 406 search_index); 407 } 408 #else 409 static inline 410 void dp_sawf_config_li(struct dp_soc *soc, uint32_t *hal_tx_desc_cached, 411 uint16_t *fw_metadata, uint16_t vdev_id, 412 qdf_nbuf_t nbuf) 413 { 414 } 415 416 #define dp_sawf_tx_enqueue_peer_stats(soc, tx_desc) 417 #define dp_sawf_tx_enqueue_fail_peer_stats(soc, tx_desc) 418 #endif 419 420 QDF_STATUS 421 dp_tx_hw_enqueue_li(struct dp_soc *soc, struct dp_vdev *vdev, 422 struct dp_tx_desc_s *tx_desc, uint16_t fw_metadata, 423 struct cdp_tx_exception_metadata *tx_exc_metadata, 424 struct dp_tx_msdu_info_s *msdu_info) 425 { 426 void *hal_tx_desc; 427 uint32_t *hal_tx_desc_cached; 428 int coalesce = 0; 429 struct dp_tx_queue *tx_q = &msdu_info->tx_queue; 430 uint8_t ring_id = tx_q->ring_id & DP_TX_QUEUE_MASK; 431 uint8_t tid = msdu_info->tid; 432 433 /* 434 * Setting it initialization statically here to avoid 435 * a memset call jump with qdf_mem_set call 436 */ 437 uint8_t cached_desc[HAL_TX_DESC_LEN_BYTES] = { 0 }; 438 439 enum cdp_sec_type sec_type = ((tx_exc_metadata && 440 tx_exc_metadata->sec_type != CDP_INVALID_SEC_TYPE) ? 441 tx_exc_metadata->sec_type : vdev->sec_type); 442 443 /* Return Buffer Manager ID */ 444 uint8_t bm_id = dp_tx_get_rbm_id_li(soc, ring_id); 445 446 hal_ring_handle_t hal_ring_hdl = NULL; 447 448 QDF_STATUS status = QDF_STATUS_E_RESOURCES; 449 450 if (!dp_tx_is_desc_id_valid(soc, tx_desc->id)) { 451 dp_err_rl("Invalid tx desc id:%d", tx_desc->id); 452 return QDF_STATUS_E_RESOURCES; 453 } 454 455 hal_tx_desc_cached = (void *)cached_desc; 456 457 hal_tx_desc_set_buf_addr(soc->hal_soc, hal_tx_desc_cached, 458 tx_desc->dma_addr, bm_id, tx_desc->id, 459 (tx_desc->flags & DP_TX_DESC_FLAG_FRAG)); 460 hal_tx_desc_set_lmac_id_li(soc->hal_soc, hal_tx_desc_cached, 461 vdev->lmac_id); 462 hal_tx_desc_set_search_type_li(soc->hal_soc, hal_tx_desc_cached, 463 vdev->search_type); 464 hal_tx_desc_set_search_index_li(soc->hal_soc, hal_tx_desc_cached, 465 vdev->bss_ast_idx); 466 hal_tx_desc_set_dscp_tid_table_id(soc->hal_soc, hal_tx_desc_cached, 467 vdev->dscp_tid_map_id); 468 469 hal_tx_desc_set_encrypt_type(hal_tx_desc_cached, 470 sec_type_map[sec_type]); 471 hal_tx_desc_set_cache_set_num(soc->hal_soc, hal_tx_desc_cached, 472 (vdev->bss_ast_hash & 0xF)); 473 474 if (dp_sawf_tag_valid_get(tx_desc->nbuf)) { 475 dp_sawf_config_li(soc, hal_tx_desc_cached, &fw_metadata, 476 vdev->vdev_id, tx_desc->nbuf); 477 dp_sawf_tx_enqueue_peer_stats(soc, tx_desc); 478 } 479 480 hal_tx_desc_set_fw_metadata(hal_tx_desc_cached, fw_metadata); 481 hal_tx_desc_set_buf_length(hal_tx_desc_cached, tx_desc->length); 482 hal_tx_desc_set_buf_offset(hal_tx_desc_cached, tx_desc->pkt_offset); 483 hal_tx_desc_set_encap_type(hal_tx_desc_cached, tx_desc->tx_encap_type); 484 hal_tx_desc_set_addr_search_flags(hal_tx_desc_cached, 485 vdev->hal_desc_addr_search_flags); 486 487 if (tx_desc->flags & DP_TX_DESC_FLAG_TO_FW) 488 hal_tx_desc_set_to_fw(hal_tx_desc_cached, 1); 489 490 /* verify checksum offload configuration*/ 491 if ((qdf_nbuf_get_tx_cksum(tx_desc->nbuf) == 492 QDF_NBUF_TX_CKSUM_TCP_UDP) || 493 qdf_nbuf_is_tso(tx_desc->nbuf)) { 494 hal_tx_desc_set_l3_checksum_en(hal_tx_desc_cached, 1); 495 hal_tx_desc_set_l4_checksum_en(hal_tx_desc_cached, 1); 496 } 497 498 if (tid != HTT_TX_EXT_TID_INVALID) 499 hal_tx_desc_set_hlos_tid(hal_tx_desc_cached, tid); 500 501 if (tx_desc->flags & DP_TX_DESC_FLAG_MESH) 502 hal_tx_desc_set_mesh_en(soc->hal_soc, hal_tx_desc_cached, 1); 503 504 if (!dp_tx_desc_set_ktimestamp(vdev, tx_desc)) 505 dp_tx_desc_set_timestamp(tx_desc); 506 507 dp_verbose_debug("length:%d , type = %d, dma_addr %llx, offset %d desc id %u", 508 tx_desc->length, 509 (tx_desc->flags & DP_TX_DESC_FLAG_FRAG), 510 (uint64_t)tx_desc->dma_addr, tx_desc->pkt_offset, 511 tx_desc->id); 512 513 hal_ring_hdl = dp_tx_get_hal_ring_hdl(soc, ring_id); 514 515 if (qdf_unlikely(dp_tx_hal_ring_access_start(soc, hal_ring_hdl))) { 516 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 517 "%s %d : HAL RING Access Failed -- %pK", 518 __func__, __LINE__, hal_ring_hdl); 519 DP_STATS_INC(soc, tx.tcl_ring_full[ring_id], 1); 520 DP_STATS_INC(vdev, tx_i.dropped.enqueue_fail, 1); 521 dp_sawf_tx_enqueue_fail_peer_stats(soc, tx_desc); 522 return status; 523 } 524 525 dp_tx_clear_consumed_hw_descs(soc, hal_ring_hdl); 526 527 /* Sync cached descriptor with HW */ 528 529 hal_tx_desc = hal_srng_src_get_next(soc->hal_soc, hal_ring_hdl); 530 if (qdf_unlikely(!hal_tx_desc)) { 531 dp_verbose_debug("TCL ring full ring_id:%d", ring_id); 532 DP_STATS_INC(soc, tx.tcl_ring_full[ring_id], 1); 533 DP_STATS_INC(vdev, tx_i.dropped.enqueue_fail, 1); 534 dp_sawf_tx_enqueue_fail_peer_stats(soc, tx_desc); 535 goto ring_access_fail; 536 } 537 538 tx_desc->flags |= DP_TX_DESC_FLAG_QUEUED_TX; 539 dp_vdev_peer_stats_update_protocol_cnt_tx(vdev, tx_desc->nbuf); 540 hal_tx_desc_sync(hal_tx_desc_cached, hal_tx_desc); 541 coalesce = dp_tx_attempt_coalescing(soc, vdev, tx_desc, tid, 542 msdu_info, ring_id); 543 DP_STATS_INC_PKT(vdev, tx_i.processed, 1, tx_desc->length); 544 DP_STATS_INC(soc, tx.tcl_enq[ring_id], 1); 545 dp_tx_update_stats(soc, tx_desc, ring_id); 546 status = QDF_STATUS_SUCCESS; 547 548 dp_tx_hw_desc_update_evt((uint8_t *)hal_tx_desc_cached, 549 hal_ring_hdl, soc, ring_id); 550 551 ring_access_fail: 552 dp_tx_ring_access_end_wrapper(soc, hal_ring_hdl, coalesce); 553 dp_pkt_add_timestamp(vdev, QDF_PKT_TX_DRIVER_EXIT, 554 qdf_get_log_timestamp(), tx_desc->nbuf); 555 556 return status; 557 } 558 559 QDF_STATUS dp_tx_desc_pool_init_li(struct dp_soc *soc, 560 uint32_t num_elem, 561 uint8_t pool_id) 562 { 563 uint32_t id, count, page_id, offset, pool_id_32; 564 struct dp_tx_desc_s *tx_desc; 565 struct dp_tx_desc_pool_s *tx_desc_pool; 566 uint16_t num_desc_per_page; 567 568 tx_desc_pool = &soc->tx_desc[pool_id]; 569 tx_desc = tx_desc_pool->freelist; 570 count = 0; 571 pool_id_32 = (uint32_t)pool_id; 572 num_desc_per_page = tx_desc_pool->desc_pages.num_element_per_page; 573 while (tx_desc) { 574 page_id = count / num_desc_per_page; 575 offset = count % num_desc_per_page; 576 id = ((pool_id_32 << DP_TX_DESC_ID_POOL_OS) | 577 (page_id << DP_TX_DESC_ID_PAGE_OS) | offset); 578 579 tx_desc->id = id; 580 tx_desc->pool_id = pool_id; 581 dp_tx_desc_set_magic(tx_desc, DP_TX_MAGIC_PATTERN_FREE); 582 tx_desc = tx_desc->next; 583 count++; 584 } 585 586 return QDF_STATUS_SUCCESS; 587 } 588 589 void dp_tx_desc_pool_deinit_li(struct dp_soc *soc, 590 struct dp_tx_desc_pool_s *tx_desc_pool, 591 uint8_t pool_id) 592 { 593 } 594 595 QDF_STATUS dp_tx_compute_tx_delay_li(struct dp_soc *soc, 596 struct dp_vdev *vdev, 597 struct hal_tx_completion_status *ts, 598 uint32_t *delay_us) 599 { 600 return dp_tx_compute_hw_delay_li(soc, vdev, ts, delay_us); 601 } 602