xref: /wlan-driver/qca-wifi-host-cmn/dp/wifi3.0/dp_tx.c (revision 5113495b16420b49004c444715d2daae2066e7dc) !
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
dp_tx_get_event_type(uint32_t flags)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
dp_tx_desc_history_add(struct dp_soc * soc,dma_addr_t paddr,qdf_nbuf_t skb,uint32_t sw_cookie,enum dp_tx_event_type type)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
dp_tx_tso_seg_history_add(struct dp_soc * soc,struct qdf_tso_seg_elem_t * tso_seg,qdf_nbuf_t skb,uint32_t sw_cookie,enum dp_tx_event_type type)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
dp_tx_tso_history_add(struct dp_soc * soc,struct qdf_tso_info_t tso_info,qdf_nbuf_t skb,uint32_t sw_cookie,enum dp_tx_event_type type)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
dp_tx_get_event_type(uint32_t flags)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
dp_tx_desc_history_add(struct dp_soc * soc,dma_addr_t paddr,qdf_nbuf_t skb,uint32_t sw_cookie,enum dp_tx_event_type type)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
dp_tx_tso_seg_history_add(struct dp_soc * soc,struct qdf_tso_seg_elem_t * tso_seg,qdf_nbuf_t skb,uint32_t sw_cookie,enum dp_tx_event_type type)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
dp_tx_tso_history_add(struct dp_soc * soc,struct qdf_tso_info_t tso_info,qdf_nbuf_t skb,uint32_t sw_cookie,enum dp_tx_event_type type)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  */
dp_is_tput_high(struct dp_soc * soc)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  */
dp_tx_tso_unmap_segment(struct dp_soc * soc,struct qdf_tso_seg_elem_t * seg_desc,struct qdf_tso_num_seg_elem_t * num_seg_desc)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  */
dp_tx_tso_desc_release(struct dp_soc * soc,struct dp_tx_desc_s * tx_desc)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
dp_tx_tso_unmap_segment(struct dp_soc * soc,struct qdf_tso_seg_elem_t * seg_desc,struct qdf_tso_num_seg_elem_t * num_seg_desc)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 
dp_tx_tso_desc_release(struct dp_soc * soc,struct dp_tx_desc_s * tx_desc)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
dp_tx_release_ds_tx_desc(struct dp_soc * soc,struct dp_tx_desc_s * tx_desc,uint8_t desc_pool_id)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
dp_tx_release_ds_tx_desc(struct dp_soc * soc,struct dp_tx_desc_s * tx_desc,uint8_t desc_pool_id)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
dp_tx_desc_release(struct dp_soc * soc,struct dp_tx_desc_s * tx_desc,uint8_t desc_pool_id)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  */
dp_tx_prepare_htt_metadata(struct dp_vdev * vdev,qdf_nbuf_t nbuf,struct dp_tx_msdu_info_s * msdu_info)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)
dp_tx_prepare_tso_ext_desc(struct qdf_tso_seg_t * tso_seg,void * ext_desc)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
dp_tx_prepare_tso_ext_desc(struct qdf_tso_seg_t * tso_seg,void * ext_desc)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  */
dp_tx_free_tso_seg_list(struct dp_soc * soc,struct qdf_tso_seg_elem_t * free_seg,struct dp_tx_msdu_info_s * msdu_info)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  */
dp_tx_free_tso_num_seg_list(struct dp_soc * soc,struct qdf_tso_num_seg_elem_t * free_num_seg,struct dp_tx_msdu_info_s * msdu_info)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  */
dp_tx_unmap_tso_seg_list(struct dp_soc * soc,struct qdf_tso_seg_elem_t * free_seg,struct qdf_tso_num_seg_elem_t * num_seg_desc)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  */
dp_tso_get_stats_idx(struct dp_pdev * pdev)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
dp_tso_get_stats_idx(struct dp_pdev * pdev)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  */
dp_tx_free_remaining_tso_desc(struct dp_soc * soc,struct dp_tx_msdu_info_s * msdu_info,bool tso_seg_unmap)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  */
dp_tx_prepare_tso(struct dp_vdev * vdev,qdf_nbuf_t msdu,struct dp_tx_msdu_info_s * msdu_info)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
dp_tx_prepare_tso(struct dp_vdev * vdev,qdf_nbuf_t msdu,struct dp_tx_msdu_info_s * msdu_info)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
dp_tx_prepare_ext_desc(struct dp_vdev * vdev,struct dp_tx_msdu_info_s * msdu_info,uint8_t desc_pool_id)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
dp_tx_trace_pkt(struct dp_soc * soc,qdf_nbuf_t skb,uint16_t msdu_id,uint8_t vdev_id,enum QDF_OPMODE op_mode)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
dp_tx_trace_pkt(struct dp_soc * soc,qdf_nbuf_t skb,uint16_t msdu_id,uint8_t vdev_id,enum QDF_OPMODE op_mode)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  */
dp_tx_is_nbuf_marked_exception(struct dp_soc * soc,qdf_nbuf_t nbuf)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
dp_tx_is_nbuf_marked_exception(struct dp_soc * soc,qdf_nbuf_t nbuf)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
dp_tx_get_traffic_end_indication_pkt(struct dp_vdev * vdev,qdf_nbuf_t nbuf)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
dp_tx_send_traffic_end_indication_pkt(struct dp_vdev * vdev,qdf_nbuf_t end_nbuf,struct dp_tx_msdu_info_s * msdu_info,uint16_t peer_id)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
dp_tx_traffic_end_indication_set_desc_flag(struct dp_tx_desc_s * tx_desc,struct dp_tx_msdu_info_s * msdu_info)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
dp_tx_traffic_end_indication_enq_ind_pkt(struct dp_soc * soc,struct dp_tx_desc_s * desc,qdf_nbuf_t nbuf)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
dp_tx_traffic_end_indication_is_enabled(struct dp_vdev * vdev)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
dp_tx_send_msdu_single_wrapper(struct dp_vdev * vdev,qdf_nbuf_t nbuf,struct dp_tx_msdu_info_s * msdu_info,uint16_t peer_id,qdf_nbuf_t end_nbuf)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
dp_tx_get_traffic_end_indication_pkt(struct dp_vdev * vdev,qdf_nbuf_t nbuf)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
dp_tx_send_traffic_end_indication_pkt(struct dp_vdev * vdev,qdf_nbuf_t end_nbuf,struct dp_tx_msdu_info_s * msdu_info,uint16_t peer_id)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
dp_tx_traffic_end_indication_set_desc_flag(struct dp_tx_desc_s * tx_desc,struct dp_tx_msdu_info_s * msdu_info)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
dp_tx_traffic_end_indication_enq_ind_pkt(struct dp_soc * soc,struct dp_tx_desc_s * desc,qdf_nbuf_t nbuf)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
dp_tx_traffic_end_indication_is_enabled(struct dp_vdev * vdev)1121 dp_tx_traffic_end_indication_is_enabled(struct dp_vdev *vdev)
1122 {
1123 	return false;
1124 }
1125 
1126 static inline qdf_nbuf_t
dp_tx_send_msdu_single_wrapper(struct dp_vdev * vdev,qdf_nbuf_t nbuf,struct dp_tx_msdu_info_s * msdu_info,uint16_t peer_id,qdf_nbuf_t end_nbuf)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
dp_tx_is_wds_ast_override_en(struct dp_soc * soc,struct cdp_tx_exception_metadata * tx_exc_metadata)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
dp_tx_is_wds_ast_override_en(struct dp_soc * soc,struct cdp_tx_exception_metadata * tx_exc_metadata)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
dp_tx_prepare_desc_single(struct dp_vdev * vdev,qdf_nbuf_t nbuf,uint8_t desc_pool_id,struct dp_tx_msdu_info_s * msdu_info,struct cdp_tx_exception_metadata * tx_exc_metadata)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  */
dp_tx_prepare_desc(struct dp_vdev * vdev,qdf_nbuf_t nbuf,struct dp_tx_msdu_info_s * msdu_info,uint8_t desc_pool_id)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  */
dp_tx_prepare_raw(struct dp_vdev * vdev,qdf_nbuf_t nbuf,struct dp_tx_seg_info_s * seg_info,struct dp_tx_msdu_info_s * msdu_info)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  */
dp_tx_raw_prepare_unset(struct dp_soc * soc,qdf_nbuf_t nbuf)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
dp_vdev_peer_stats_update_protocol_cnt_tx(struct dp_vdev * vdev_hdl,qdf_nbuf_t nbuf)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
dp_tx_update_stats(struct dp_soc * soc,struct dp_tx_desc_s * tx_desc,uint8_t ring_id)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
dp_tx_attempt_coalescing(struct dp_soc * soc,struct dp_vdev * vdev,struct dp_tx_desc_s * tx_desc,uint8_t tid,struct dp_tx_msdu_info_s * msdu_info,uint8_t ring_id)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
dp_tx_ring_access_end(struct dp_soc * soc,hal_ring_handle_t hal_ring_hdl,int coalesce)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
dp_tx_is_hp_update_required(uint32_t i,struct dp_tx_msdu_info_s * msdu_info)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
dp_flush_tcp_hp(struct dp_soc * soc,uint8_t ring_id)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
dp_tx_check_and_flush_hp(struct dp_soc * soc,QDF_STATUS status,struct dp_tx_msdu_info_s * msdu_info)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
dp_tx_is_hp_update_required(uint32_t i,struct dp_tx_msdu_info_s * msdu_info)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
dp_tx_check_and_flush_hp(struct dp_soc * soc,QDF_STATUS status,struct dp_tx_msdu_info_s * msdu_info)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
dp_tx_ring_access_end_wrapper(struct dp_soc * soc,hal_ring_handle_t hal_ring_hdl,int coalesce)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
dp_tx_ring_access_end_wrapper(struct dp_soc * soc,hal_ring_handle_t hal_ring_hdl,int coalesce)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  */
dp_tx_get_tid(struct dp_vdev * vdev,qdf_nbuf_t nbuf,struct dp_tx_msdu_info_s * msdu_info)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  */
dp_tx_classify_tid(struct dp_vdev * vdev,qdf_nbuf_t nbuf,struct dp_tx_msdu_info_s * msdu_info)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  */
dp_tx_update_tdls_flags(struct dp_soc * soc,struct dp_vdev * vdev,struct dp_tx_desc_s * tx_desc)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 
dp_htt_tx_comp_get_status(struct dp_soc * soc,char * htt_desc)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  */
dp_non_std_htt_tx_comp_free_buff(struct dp_soc * soc,struct dp_tx_desc_s * tx_desc)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  */
dp_tx_msdu_single_map(struct dp_vdev * vdev,struct dp_tx_desc_s * tx_desc,qdf_nbuf_t nbuf)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
dp_tx_update_tdls_flags(struct dp_soc * soc,struct dp_vdev * vdev,struct dp_tx_desc_s * tx_desc)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 
dp_non_std_htt_tx_comp_free_buff(struct dp_soc * soc,struct dp_tx_desc_s * tx_desc)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 
dp_tx_msdu_single_map(struct dp_vdev * vdev,struct dp_tx_desc_s * tx_desc,qdf_nbuf_t nbuf)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
dp_tx_nbuf_map_regular(struct dp_vdev * vdev,struct dp_tx_desc_s * tx_desc,qdf_nbuf_t nbuf)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
dp_tx_nbuf_unmap_regular(struct dp_soc * soc,struct dp_tx_desc_s * desc)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
is_nbuf_frm_rmnet(qdf_nbuf_t nbuf,struct dp_tx_msdu_info_s * msdu_info)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
dp_tx_rmnet_nbuf_map(struct dp_tx_msdu_info_s * msdu_info,struct dp_tx_desc_s * tx_desc)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
is_nbuf_frm_rmnet(qdf_nbuf_t nbuf,struct dp_tx_msdu_info_s * msdu_info)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
dp_tx_rmnet_nbuf_map(struct dp_tx_msdu_info_s * msdu_info,struct dp_tx_desc_s * tx_desc)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
dp_tx_nbuf_map(struct dp_vdev * vdev,struct dp_tx_desc_s * tx_desc,qdf_nbuf_t nbuf)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
dp_tx_nbuf_unmap(struct dp_soc * soc,struct dp_tx_desc_s * desc)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
dp_tx_nbuf_map(struct dp_vdev * vdev,struct dp_tx_desc_s * tx_desc,qdf_nbuf_t nbuf)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
dp_tx_nbuf_unmap(struct dp_soc * soc,struct dp_tx_desc_s * desc)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
dp_tx_enh_unmap(struct dp_soc * soc,struct dp_tx_desc_s * desc)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 
dp_tx_unmap(struct dp_soc * soc,struct dp_tx_desc_s * desc)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
dp_tx_enh_unmap(struct dp_soc * soc,struct dp_tx_desc_s * desc)2168 void dp_tx_enh_unmap(struct dp_soc *soc, struct dp_tx_desc_s *desc)
2169 {
2170 }
2171 
dp_tx_unmap(struct dp_soc * soc,struct dp_tx_desc_s * desc)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  */
dp_tx_update_mesh_flags(struct dp_soc * soc,struct dp_vdev * vdev,struct dp_tx_desc_s * tx_desc)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  */
dp_mesh_tx_comp_free_buff(struct dp_soc * soc,struct dp_tx_desc_s * tx_desc,bool delayed_free)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
dp_tx_update_mesh_flags(struct dp_soc * soc,struct dp_vdev * vdev,struct dp_tx_desc_s * tx_desc)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 
dp_mesh_tx_comp_free_buff(struct dp_soc * soc,struct dp_tx_desc_s * tx_desc,bool delayed_free)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 
dp_tx_frame_is_drop(struct dp_vdev * vdev,uint8_t * srcmac,uint8_t * dstmac)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
dp_tx_wds_ext_check(struct cdp_tx_exception_metadata * tx_exc_metadata)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
dp_tx_wds_ext_check(struct cdp_tx_exception_metadata * tx_exc_metadata)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
dp_tx_bypass_reinjection(struct dp_soc * soc,struct dp_tx_desc_s * tx_desc,struct cdp_tx_exception_metadata * tx_exc_metadata)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
dp_tx_update_mcast_param(uint16_t peer_id,uint16_t * htt_tcl_metadata,struct dp_vdev * vdev,struct dp_tx_msdu_info_s * msdu_info)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
dp_tx_bypass_reinjection(struct dp_soc * soc,struct dp_tx_desc_s * tx_desc,struct cdp_tx_exception_metadata * tx_exc_metadata)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
dp_tx_update_mcast_param(uint16_t peer_id,uint16_t * htt_tcl_metadata,struct dp_vdev * vdev,struct dp_tx_msdu_info_s * msdu_info)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
tx_sw_drop_stats_inc(struct dp_pdev * pdev,qdf_nbuf_t nbuf,enum cdp_tx_sw_drop drop_code)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
tx_sw_drop_stats_inc(struct dp_pdev * pdev,qdf_nbuf_t nbuf,enum cdp_tx_sw_drop drop_code)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  */
dp_tx_latency_stats_enabled(struct dp_vdev * vdev)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  */
dp_tx_latency_stats_report_enabled(struct dp_vdev * vdev)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
dp_tx_get_driver_ingress_ts(struct dp_vdev * vdev,struct dp_tx_msdu_info_s * msdu_info,qdf_nbuf_t nbuf)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
dp_tx_update_ts_on_enqueued(struct dp_vdev * vdev,struct dp_tx_msdu_info_s * msdu_info,struct dp_tx_desc_s * tx_desc)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
dp_tx_latency_stats_update_bucket(struct dp_vdev * vdev,struct dp_tx_latency * tx_latency,int idx,enum cdp_tx_latency_type type,uint32_t value)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
dp_tx_latency_stats_update(struct dp_soc * soc,struct dp_txrx_peer * txrx_peer,struct dp_tx_desc_s * tx_desc,struct hal_tx_completion_status * ts,uint8_t link_id)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
dp_tx_latency_stats_clear_bucket(struct dp_tx_latency * tx_latency,int idx,enum cdp_tx_latency_type type)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
dp_tx_latency_stats_clear_buckets(struct dp_tx_latency * tx_latency,int idx)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
dp_tx_latency_stats_update_cca(struct dp_soc * soc,uint16_t peer_id,uint32_t granularity,uint32_t * distribution,uint32_t avg)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
dp_tx_latency_stats_get_per_peer(struct dp_soc * soc,struct dp_peer * peer,struct cdp_tx_latency * latency)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
dp_tx_latency_stats_get_peer_iter(struct dp_soc * soc,struct dp_peer * peer,void * arg)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
dp_tx_latency_stats_rpt_per_vdev(struct dp_soc * soc,struct dp_vdev * vdev)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  */
dp_tx_latency_stats_report(struct dp_soc * soc,struct dp_pdev * pdev)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
dp_tx_latency_stats_clear_per_peer(struct dp_soc * soc,struct dp_peer * peer,void * arg)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  */
dp_tx_latency_stats_clear_per_vdev(struct dp_vdev * vdev)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
dp_tx_latency_stats_fetch(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,uint8_t * mac,struct cdp_tx_latency * latency)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
dp_tx_latency_stats_config(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,struct cdp_tx_latency_config * cfg)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
dp_tx_latency_stats_register_cb(struct cdp_soc_t * handle,cdp_tx_latency_cb cb)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
dp_tx_get_driver_ingress_ts(struct dp_vdev * vdev,struct dp_tx_msdu_info_s * msdu_info,qdf_nbuf_t nbuf)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
dp_tx_update_ts_on_enqueued(struct dp_vdev * vdev,struct dp_tx_msdu_info_s * msdu_info,struct dp_tx_desc_s * tx_desc)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
dp_tx_latency_stats_update(struct dp_soc * soc,struct dp_txrx_peer * txrx_peer,struct dp_tx_desc_s * tx_desc,struct hal_tx_completion_status * ts,uint8_t link_id)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
dp_tx_send_msdu_single(struct dp_vdev * vdev,qdf_nbuf_t nbuf,struct dp_tx_msdu_info_s * msdu_info,uint16_t peer_id,struct cdp_tx_exception_metadata * tx_exc_metadata)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
dp_tdls_tx_comp_free_buff(struct dp_soc * soc,struct dp_tx_desc_s * desc)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
dp_tdls_tx_comp_free_buff(struct dp_soc * soc,struct dp_tx_desc_s * desc)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 
dp_tx_comp_free_buf(struct dp_soc * soc,struct dp_tx_desc_s * desc,bool delayed_free)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
dp_tx_sg_unmap_buf(struct dp_soc * soc,qdf_nbuf_t nbuf,struct dp_tx_msdu_info_s * msdu_info)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
dp_tx_send_msdu_multiple(struct dp_vdev * vdev,qdf_nbuf_t nbuf,struct dp_tx_msdu_info_s * msdu_info)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  */
dp_tx_prepare_sg(struct dp_vdev * vdev,qdf_nbuf_t nbuf,struct dp_tx_seg_info_s * seg_info,struct dp_tx_msdu_info_s * msdu_info)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
dp_tx_add_tx_sniffer_meta_data(struct dp_vdev * vdev,struct dp_tx_msdu_info_s * msdu_info,uint16_t ppdu_cookie)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
dp_tx_extract_mesh_meta_data(struct dp_vdev * vdev,qdf_nbuf_t nbuf,struct dp_tx_msdu_info_s * msdu_info)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
dp_tx_extract_mesh_meta_data(struct dp_vdev * vdev,qdf_nbuf_t nbuf,struct dp_tx_msdu_info_s * msdu_info)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  */
dp_check_exc_metadata(struct cdp_tx_exception_metadata * tx_exc)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
dp_tx_mcast_enhance(struct dp_vdev * vdev,qdf_nbuf_t nbuf)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
dp_tx_mcast_enhance(struct dp_vdev * vdev,qdf_nbuf_t nbuf)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  */
dp_tx_mcast_drop(struct dp_vdev * vdev,qdf_nbuf_t nbuf)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
dp_tx_mcast_drop(struct dp_vdev * vdev,qdf_nbuf_t nbuf)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
dp_tx_per_pkt_vdev_id_check(qdf_nbuf_t nbuf,struct dp_vdev * vdev)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 
dp_tx_nawds_handler(struct dp_soc * soc,struct dp_vdev * vdev,struct dp_tx_msdu_info_s * msdu_info,qdf_nbuf_t nbuf,uint16_t sa_peer_id)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
dp_tx_check_mesh_vdev(struct dp_vdev * vdev,struct cdp_tx_exception_metadata * tx_exc_metadata)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
dp_tx_check_mesh_vdev(struct dp_vdev * vdev,struct cdp_tx_exception_metadata * tx_exc_metadata)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
dp_tx_send_exception(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,qdf_nbuf_t nbuf,struct cdp_tx_exception_metadata * tx_exc_metadata)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
dp_tx_send_exception_vdev_id_check(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,qdf_nbuf_t nbuf,struct cdp_tx_exception_metadata * tx_exc_metadata)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
dp_tx_send_mesh(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,qdf_nbuf_t nbuf)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 
dp_tx_send_mesh(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,qdf_nbuf_t nbuf)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
dp_tx_drop(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,qdf_nbuf_t nbuf)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 
dp_tx_exc_drop(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,qdf_nbuf_t nbuf,struct cdp_tx_exception_metadata * tx_exc_metadata)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  */
dp_vdev_tx_mark_to_fw(qdf_nbuf_t nbuf,struct dp_vdev * vdev)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
dp_vdev_tx_mark_to_fw(qdf_nbuf_t nbuf,struct dp_vdev * vdev)4275 static inline void dp_vdev_tx_mark_to_fw(qdf_nbuf_t nbuf, struct dp_vdev *vdev)
4276 {
4277 }
4278 #endif
4279 
dp_tx_send(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,qdf_nbuf_t nbuf)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 
dp_tx_send_vdev_id_check(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,qdf_nbuf_t nbuf)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  */
dp_tx_proxy_arp(struct dp_vdev * vdev,qdf_nbuf_t nbuf)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
dp_tx_proxy_arp(struct dp_vdev * vdev,qdf_nbuf_t nbuf)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
dp_tx_reinject_mlo_hdl(struct dp_soc * soc,struct dp_vdev * vdev,struct dp_tx_desc_s * tx_desc,qdf_nbuf_t nbuf,uint8_t reinject_reason)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
dp_tx_reinject_mlo_hdl(struct dp_soc * soc,struct dp_vdev * vdev,struct dp_tx_desc_s * tx_desc,qdf_nbuf_t nbuf,uint8_t reinject_reason)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
dp_tx_reinject_mlo_hdl(struct dp_soc * soc,struct dp_vdev * vdev,struct dp_tx_desc_s * tx_desc,qdf_nbuf_t nbuf,uint8_t reinject_reason)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 
dp_tx_reinject_handler(struct dp_soc * soc,struct dp_vdev * vdev,struct dp_tx_desc_s * tx_desc,uint8_t * status,uint8_t reinject_reason)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