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