xref: /wlan-dirver/qca-wifi-host-cmn/dp/wifi3.0/monitor/2.0/dp_tx_mon_status_2.0.c (revision 410a2ae521186f1b1da58f3a6b2b6789e2117a3c)
1 /*
2  * Copyright (c) 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 any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 #include "dp_types.h"
18 #include "qdf_nbuf.h"
19 #include "dp_internal.h"
20 #include "qdf_mem.h"   /* qdf_mem_malloc,free */
21 #include <dp_be.h>
22 #include <qdf_nbuf_frag.h>
23 #include <hal_be_api_mon.h>
24 #include <dp_mon.h>
25 #include <dp_tx_mon_2.0.h>
26 #include <dp_mon_2.0.h>
27 #ifdef QCA_SUPPORT_LITE_MONITOR
28 #include <dp_lite_mon.h>
29 #endif
30 
31 #define MAX_PPDU_INFO_LIST_DEPTH 64
32 
33 #if defined(WLAN_TX_PKT_CAPTURE_ENH_BE) || defined(WLAN_PKT_CAPTURE_TX_2_0) ||\
34 	defined(WLAN_TX_MON_CORE_DEBUG)
35 void
36 dp_tx_mon_status_free_packet_buf(struct dp_pdev *pdev,
37 				 qdf_frag_t status_frag, uint32_t end_offset,
38 				 struct dp_tx_mon_desc_list *mon_desc_list_ref)
39 {
40 	struct dp_mon_pdev *mon_pdev;
41 	struct dp_mon_pdev_be *mon_pdev_be;
42 	struct dp_pdev_tx_monitor_be *tx_mon_be;
43 	struct hal_mon_packet_info packet_info = {0};
44 	uint8_t *tx_tlv;
45 	uint8_t *mon_buf_tx_tlv;
46 	uint8_t *tx_tlv_start;
47 
48 	if (qdf_unlikely(!pdev))
49 		return;
50 
51 	mon_pdev = pdev->monitor_pdev;
52 	if (qdf_unlikely(!mon_pdev))
53 		return;
54 
55 	mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
56 	if (qdf_unlikely(!mon_pdev_be))
57 		return;
58 
59 	tx_mon_be = &mon_pdev_be->tx_monitor_be;
60 	tx_tlv = status_frag;
61 	tx_tlv_start = tx_tlv;
62 	/*
63 	 * parse each status buffer and find packet buffer in it
64 	 */
65 	do {
66 		if (hal_txmon_is_mon_buf_addr_tlv(pdev->soc->hal_soc, tx_tlv)) {
67 			struct dp_mon_desc *mon_desc = NULL;
68 			qdf_frag_t packet_buffer = NULL;
69 
70 			mon_buf_tx_tlv = ((uint8_t *)tx_tlv +
71 					  HAL_RX_TLV64_HDR_SIZE);
72 			hal_txmon_populate_packet_info(pdev->soc->hal_soc,
73 						       mon_buf_tx_tlv,
74 						       &packet_info);
75 
76 			mon_desc = (struct dp_mon_desc *)(uintptr_t)packet_info.sw_cookie;
77 
78 			qdf_assert_always(mon_desc);
79 
80 			if (mon_desc->magic != DP_MON_DESC_MAGIC)
81 				qdf_assert_always(0);
82 
83 			if (!mon_desc->unmapped) {
84 				qdf_mem_unmap_page(pdev->soc->osdev,
85 						   (qdf_dma_addr_t)mon_desc->paddr,
86 						   DP_MON_DATA_BUFFER_SIZE,
87 						   QDF_DMA_FROM_DEVICE);
88 				mon_desc->unmapped = 1;
89 			}
90 
91 			packet_buffer = (qdf_frag_t)(mon_desc->buf_addr);
92 			mon_desc->buf_addr = NULL;
93 
94 			qdf_assert_always(packet_buffer);
95 			/* increment reap count */
96 			mon_desc_list_ref->tx_mon_reap_cnt++;
97 
98 			/* add the mon_desc to free list */
99 			dp_mon_add_to_free_desc_list(&mon_desc_list_ref->desc_list,
100 						     &mon_desc_list_ref->tail,
101 						     mon_desc);
102 
103 			tx_mon_be->stats.pkt_buf_recv++;
104 			tx_mon_be->stats.pkt_buf_free++;
105 
106 			/* free buffer, mapped to descriptor */
107 			qdf_frag_free(packet_buffer);
108 		}
109 
110 		/* need api definition for hal_tx_status_get_next_tlv */
111 		tx_tlv = hal_tx_status_get_next_tlv(tx_tlv,
112 						   mon_pdev->is_tlv_hdr_64_bit);
113 	} while ((tx_tlv - tx_tlv_start) < end_offset);
114 }
115 #endif
116 
117 #if defined(WLAN_TX_PKT_CAPTURE_ENH_BE) && defined(WLAN_PKT_CAPTURE_TX_2_0)
118 /**
119  * dp_tx_mon_status_queue_free() - API to free status buffer
120  * @pdev: pdev Handle
121  * @tx_mon_be: pointer to tx_monitor_be
122  * @mon_desc_list_ref: tx monitor descriptor list reference
123  *
124  * Return: void
125  */
126 static void
127 dp_tx_mon_status_queue_free(struct dp_pdev *pdev,
128 			    struct dp_pdev_tx_monitor_be *tx_mon_be,
129 			    struct dp_tx_mon_desc_list *mon_desc_list_ref)
130 {
131 	uint8_t last_frag_q_idx = tx_mon_be->last_frag_q_idx;
132 	qdf_frag_t status_frag = NULL;
133 	uint8_t i = tx_mon_be->cur_frag_q_idx;
134 	uint32_t end_offset = 0;
135 
136 	if (last_frag_q_idx > MAX_STATUS_BUFFER_IN_PPDU)
137 		last_frag_q_idx = MAX_STATUS_BUFFER_IN_PPDU;
138 
139 	for (; i < last_frag_q_idx; i++) {
140 		status_frag = tx_mon_be->frag_q_vec[i].frag_buf;
141 
142 		if (qdf_unlikely(!status_frag))
143 			continue;
144 
145 		end_offset = tx_mon_be->frag_q_vec[i].end_offset;
146 		dp_tx_mon_status_free_packet_buf(pdev, status_frag, end_offset,
147 						 mon_desc_list_ref);
148 		tx_mon_be->stats.status_buf_free++;
149 		qdf_frag_free(status_frag);
150 		tx_mon_be->frag_q_vec[i].frag_buf = NULL;
151 		tx_mon_be->frag_q_vec[i].end_offset = 0;
152 	}
153 	tx_mon_be->last_frag_q_idx = 0;
154 	tx_mon_be->cur_frag_q_idx = 0;
155 }
156 
157 /**
158  * dp_tx_mon_enqueue_mpdu_nbuf() - API to enqueue nbuf from per user mpdu queue
159  * @pdev: pdev Handle
160  * @tx_ppdu_info: pointer to tx ppdu info structure
161  * @user_id: user index
162  * @mpdu_nbuf: nbuf to be enqueue
163  *
164  * Return: void
165  */
166 static void
167 dp_tx_mon_enqueue_mpdu_nbuf(struct dp_pdev *pdev,
168 			    struct dp_tx_ppdu_info *tx_ppdu_info,
169 			    uint8_t user_id, qdf_nbuf_t mpdu_nbuf)
170 {
171 	qdf_nbuf_t radiotap = NULL;
172 	/* enqueue mpdu_nbuf to the per user mpdu_q */
173 	qdf_nbuf_queue_t *usr_mpdu_q = NULL;
174 
175 	if (!TXMON_PPDU_HAL(tx_ppdu_info, num_users))
176 		QDF_BUG(0);
177 
178 	usr_mpdu_q = &TXMON_PPDU_USR(tx_ppdu_info, user_id, mpdu_q);
179 
180 	radiotap = qdf_nbuf_alloc(pdev->soc->osdev, MAX_MONITOR_HEADER,
181 				  MAX_MONITOR_HEADER,
182 				  4, FALSE);
183 	if (qdf_unlikely(!radiotap)) {
184 		qdf_err("Unable to allocate radiotap buffer\n");
185 		qdf_nbuf_free(mpdu_nbuf);
186 		return;
187 	}
188 
189 	/* append ext list */
190 	qdf_nbuf_append_ext_list(radiotap, mpdu_nbuf, qdf_nbuf_len(mpdu_nbuf));
191 	qdf_nbuf_queue_add(usr_mpdu_q, radiotap);
192 }
193 
194 /*
195  * TX MONITOR
196  *
197  * frame format
198  * -------------------------------------------------------------------------
199  *  FUNC   | ToDS | FromDS | ADDRESS 1 | ADDRESS 2 | ADDRESS 3 | ADDRESS 4 |
200  *  ------------------------------------------------------------------------
201  *  IBSS   |  0   |    0   | DA        | SA        | BSSID     | NOT USED  |
202  *  TO AP  |  1   |    0   | BSSID     | SA        | DA        | NOT USED  |
203  *  From AP|  0   |    1   | DA        | BSSID     | SA        | NOT USED  |
204  *  WDS    |  1   |    1   | RA        | TA        | DA        | SA        |
205  *  ------------------------------------------------------------------------
206  *
207  *  HOST GENERATED FRAME:
208  *  =====================
209  *     1. RTS
210  *     2. CTS
211  *     3. ACK
212  *     4. BA
213  *     5. Multi STA BA
214  *
215  *  control frame
216  *  ------------------------------------------------------------
217  *  | protocol 2b | Type 2b | subtype 4b | ToDS 1b | FromDS 1b |
218  *                | Morefrag 1b | Retry 1b | pwr_mgmt 1b | More data 1b |
219  *                              | protected frm 1b | order 1b |
220  *  -----------------------------------------------------------
221  *  control frame originated from wireless station so ToDS = FromDS = 0,
222  *
223  *  RTS
224  *  ---------------------------------------------------------------------------
225  *  | FrameCtl 2 | Duration 2 | Receiver Address 6 | Transmit address 6 | FCS |
226  *  ---------------------------------------------------------------------------
227  *  subtype in FC is RTS - 1101
228  *  type in FC is control frame - 10
229  *
230  *  CTS
231  *  --------------------------------------------------------
232  *  | FrameCtl 2 | Duration 2 | Receiver Address 6 | FCS 4 |
233  *  --------------------------------------------------------
234  *  subtype in FC is CTS - 0011
235  *  type in FC is control frame - 10
236  *
237  *  ACK
238  *  --------------------------------------------------------
239  *  | FrameCtl 2 | Duration 2 | Receiver Address 6 | FCS 4 |
240  *  --------------------------------------------------------
241  *  subtype in FC is ACK - 1011
242  *  type in FC is control frame - 10
243  *
244  *  Block ACK
245  *  --------------------------------------------------------------------------
246  *  | FC 2 | Dur 2 | RA 6 | TA 6 | BA CTRL 2 | BA Information variable | FCS |
247  *  --------------------------------------------------------------------------
248  *
249  *	Block Ack control
250  *	---------------------------------------------------------------
251  *	| BA ACK POLICY B0 | BA TYPE B1-B4 | Rsv B5-B11 | TID B12-B15 |
252  *	---------------------------------------------------------------
253  *
254  *	BA ack policy
255  *	0 - Normal Ack
256  *	1 - No Ack
257  *
258  *	Block Ack Type
259  *	0     - Reserved
260  *	1     - extended compressed
261  *	2     - compressed
262  *	3     - Multi TID
263  *	4-5   - Reserved
264  *	6     - GCR
265  *	7-9   - Reserved
266  *	10    - GLK-GCR
267  *	11    - Multi-STA
268  *	12-15 - Reserved
269  *
270  *	Block Ack information
271  *	----------------------------------------------------------
272  *	| Block ack start seq ctrl 2 | Block ack bitmap variable |
273  *	----------------------------------------------------------
274  *
275  *	Multi STA Block Ack Information
276  *	-----------------------------------------------------------------
277  *	| Per STA TID info 2 | BA start seq ctrl 2 | BA bitmap variable |
278  *	-----------------------------------------------------------------
279  *
280  *		Per STA TID info
281  *		------------------------------------
282  *		| AID11 11b | Ack Type 1b | TID 4b |
283  *		------------------------------------
284  *		AID11 - 2045 means unassociated STA, then ACK Type and TID 0, 15
285  *
286  *		Mgmt/PS-POLL frame ack
287  *		Ack type - 1 and TID - 15, BA_seq_ctrl & BA_bitmap - not present
288  *
289  *		All ack context - with no bitmap (all AMPDU success)
290  *		Ack type - 1 and TID - 14, BA_seq_ctrl & BA_bitmap - not present
291  *
292  *		Block ack context
293  *		Ack type - 0 and  TID - 0~7 BA_seq_ctrl & BA_bitmap - present
294  *
295  *		Ack context
296  *		Ack type - 1 and TID - 0~7 BA_seq_ctrl & BA_bitmap - not present
297  *
298  *
299  */
300 
301 /**
302  * dp_tx_mon_generate_cts2self_frm() - API to generate cts2self frame
303  * @pdev: pdev Handle
304  * @tx_ppdu_info: pointer to tx ppdu info structure
305  * @window_flag: frame generated window
306  *
307  * Return: void
308  */
309 static void
310 dp_tx_mon_generate_cts2self_frm(struct dp_pdev *pdev,
311 				struct dp_tx_ppdu_info *tx_ppdu_info,
312 				uint8_t window_flag)
313 {
314 	/* allocate and populate CTS/ CTS2SELF frame */
315 	/* enqueue 802.11 payload to per user mpdu_q */
316 	struct dp_mon_pdev *mon_pdev;
317 	struct dp_mon_pdev_be *mon_pdev_be;
318 	struct dp_pdev_tx_monitor_be *tx_mon_be;
319 	struct hal_tx_status_info *tx_status_info;
320 	uint16_t duration_le = 0;
321 	struct ieee80211_frame_min_one *wh_min = NULL;
322 	qdf_nbuf_t mpdu_nbuf = NULL;
323 	uint8_t frm_ctl;
324 
325 	/* sanity check */
326 	if (qdf_unlikely(!pdev))
327 		return;
328 
329 	mon_pdev = pdev->monitor_pdev;
330 	if (qdf_unlikely(!mon_pdev))
331 		return;
332 
333 	mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
334 	if (qdf_unlikely(!mon_pdev_be))
335 		return;
336 
337 	tx_mon_be = &mon_pdev_be->tx_monitor_be;
338 
339 	if (window_flag == INITIATOR_WINDOW)
340 		tx_status_info = &tx_mon_be->prot_status_info;
341 	else
342 		tx_status_info = &tx_mon_be->data_status_info;
343 
344 	/*
345 	 * for radiotap we allocate new skb,
346 	 * so we don't need reserver skb header
347 	 */
348 	mpdu_nbuf = qdf_nbuf_alloc(pdev->soc->osdev,
349 				   MAX_DUMMY_FRM_BODY, 0, 4, FALSE);
350 	if (!mpdu_nbuf)
351 		return;
352 
353 	wh_min = (struct ieee80211_frame_min_one *)qdf_nbuf_data(mpdu_nbuf);
354 	qdf_mem_zero(wh_min, MAX_DUMMY_FRM_BODY);
355 
356 	frm_ctl = (QDF_IEEE80211_FC0_VERSION_0 | QDF_IEEE80211_FC0_TYPE_CTL |
357 		   QDF_IEEE80211_FC0_SUBTYPE_CTS);
358 	TXMON_PPDU_COM(tx_ppdu_info, frame_control) = frm_ctl;
359 	TXMON_PPDU_COM(tx_ppdu_info, frame_control_info_valid) = 1;
360 	wh_min->i_fc[1] = 0;
361 	wh_min->i_fc[0] = frm_ctl;
362 
363 	duration_le = qdf_cpu_to_le16(TXMON_PPDU_COM(tx_ppdu_info, duration));
364 	wh_min->i_dur[1] = (duration_le & 0xFF00) >> 8;
365 	wh_min->i_dur[0] = (duration_le & 0xFF);
366 
367 	if (window_flag == INITIATOR_WINDOW) {
368 		qdf_mem_copy(wh_min->i_addr1,
369 			     TXMON_STATUS_INFO(tx_status_info, addr1),
370 			     QDF_MAC_ADDR_SIZE);
371 	} else {
372 		qdf_mem_copy(wh_min->i_addr1,
373 			     TXMON_STATUS_INFO(tx_status_info, addr2),
374 			     QDF_MAC_ADDR_SIZE);
375 	}
376 
377 	qdf_nbuf_set_pktlen(mpdu_nbuf, sizeof(*wh_min));
378 	dp_tx_mon_enqueue_mpdu_nbuf(pdev, tx_ppdu_info, 0, mpdu_nbuf);
379 	TXMON_PPDU_HAL(tx_ppdu_info, is_used) = 1;
380 }
381 
382 /**
383  * dp_tx_mon_generate_rts_frm() - API to generate rts frame
384  * @pdev: pdev Handle
385  * @tx_ppdu_info: pointer to tx ppdu info structure
386  * @window_flag: frame generated window
387  *
388  * Return: void
389  */
390 static void
391 dp_tx_mon_generate_rts_frm(struct dp_pdev *pdev,
392 			   struct dp_tx_ppdu_info *tx_ppdu_info,
393 			   uint8_t window_flag)
394 {
395 	/* allocate and populate RTS frame */
396 	/* enqueue 802.11 payload to per user mpdu_q */
397 	struct dp_mon_pdev *mon_pdev;
398 	struct dp_mon_pdev_be *mon_pdev_be;
399 	struct dp_pdev_tx_monitor_be *tx_mon_be;
400 	struct hal_tx_status_info *tx_status_info;
401 	uint16_t duration_le = 0;
402 	struct ieee80211_ctlframe_addr2 *wh_min = NULL;
403 	qdf_nbuf_t mpdu_nbuf = NULL;
404 	uint8_t frm_ctl;
405 
406 	/* sanity check */
407 	if (qdf_unlikely(!pdev))
408 		return;
409 
410 	mon_pdev = pdev->monitor_pdev;
411 	if (qdf_unlikely(!mon_pdev))
412 		return;
413 
414 	mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
415 	if (qdf_unlikely(!mon_pdev_be))
416 		return;
417 
418 	tx_mon_be = &mon_pdev_be->tx_monitor_be;
419 	tx_status_info = &tx_mon_be->prot_status_info;
420 	/*
421 	 * for radiotap we allocate new skb,
422 	 * so we don't need reserver skb header
423 	 */
424 	mpdu_nbuf = qdf_nbuf_alloc(pdev->soc->osdev,
425 				   MAX_DUMMY_FRM_BODY, 0, 4, FALSE);
426 	if (!mpdu_nbuf)
427 		return;
428 
429 	wh_min = (struct ieee80211_ctlframe_addr2 *)qdf_nbuf_data(mpdu_nbuf);
430 	qdf_mem_zero(wh_min, MAX_DUMMY_FRM_BODY);
431 
432 	frm_ctl = (QDF_IEEE80211_FC0_VERSION_0 | QDF_IEEE80211_FC0_TYPE_CTL |
433 		   QDF_IEEE80211_FC0_SUBTYPE_RTS);
434 	TXMON_PPDU_COM(tx_ppdu_info, frame_control) = frm_ctl;
435 	TXMON_PPDU_COM(tx_ppdu_info, frame_control_info_valid) = 1;
436 	wh_min->i_fc[1] = 0;
437 	wh_min->i_fc[0] = frm_ctl;
438 
439 	duration_le = qdf_cpu_to_le16(TXMON_PPDU_COM(tx_ppdu_info, duration));
440 	wh_min->i_aidordur[1] = (duration_le & 0xFF00) >> 8;
441 	wh_min->i_aidordur[0] = (duration_le & 0xFF);
442 
443 	if (!tx_status_info->protection_addr)
444 		tx_status_info = &tx_mon_be->data_status_info;
445 
446 	if (window_flag == INITIATOR_WINDOW) {
447 		qdf_mem_copy(wh_min->i_addr1,
448 			     TXMON_STATUS_INFO(tx_status_info, addr1),
449 			     QDF_MAC_ADDR_SIZE);
450 		qdf_mem_copy(wh_min->i_addr2,
451 			     TXMON_STATUS_INFO(tx_status_info, addr2),
452 			     QDF_MAC_ADDR_SIZE);
453 	} else {
454 		qdf_mem_copy(wh_min->i_addr1,
455 			     TXMON_STATUS_INFO(tx_status_info, addr2),
456 			     QDF_MAC_ADDR_SIZE);
457 		qdf_mem_copy(wh_min->i_addr2,
458 			     TXMON_STATUS_INFO(tx_status_info, addr1),
459 			     QDF_MAC_ADDR_SIZE);
460 	}
461 
462 	qdf_nbuf_set_pktlen(mpdu_nbuf, sizeof(*wh_min));
463 	dp_tx_mon_enqueue_mpdu_nbuf(pdev, tx_ppdu_info, 0, mpdu_nbuf);
464 	TXMON_PPDU_HAL(tx_ppdu_info, is_used) = 1;
465 }
466 
467 /**
468  * dp_tx_mon_generate_ack_frm() - API to generate ack frame
469  * @pdev: pdev Handle
470  * @tx_ppdu_info: pointer to tx ppdu info structure
471  *
472  * Return: void
473  */
474 static void
475 dp_tx_mon_generate_ack_frm(struct dp_pdev *pdev,
476 			   struct dp_tx_ppdu_info *tx_ppdu_info)
477 {
478 	/* allocate and populate ACK frame */
479 	/* enqueue 802.11 payload to per user mpdu_q */
480 	struct dp_mon_pdev *mon_pdev;
481 	struct dp_mon_pdev_be *mon_pdev_be;
482 	struct dp_pdev_tx_monitor_be *tx_mon_be;
483 	struct hal_tx_status_info *tx_status_info;
484 	struct ieee80211_frame_min_one *wh_addr1 = NULL;
485 	qdf_nbuf_t mpdu_nbuf = NULL;
486 	uint8_t user_id = TXMON_PPDU(tx_ppdu_info, cur_usr_idx);
487 	uint8_t frm_ctl;
488 
489 	/* sanity check */
490 	if (qdf_unlikely(!pdev))
491 		return;
492 
493 	mon_pdev = pdev->monitor_pdev;
494 	if (qdf_unlikely(!mon_pdev))
495 		return;
496 
497 	mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
498 	if (qdf_unlikely(!mon_pdev_be))
499 		return;
500 
501 	tx_mon_be = &mon_pdev_be->tx_monitor_be;
502 	tx_status_info = &tx_mon_be->data_status_info;
503 	/*
504 	 * for radiotap we allocate new skb,
505 	 * so we don't need reserver skb header
506 	 */
507 	mpdu_nbuf = qdf_nbuf_alloc(pdev->soc->osdev,
508 				   MAX_DUMMY_FRM_BODY, 0, 4, FALSE);
509 	if (!mpdu_nbuf)
510 		return;
511 
512 	wh_addr1 = (struct ieee80211_frame_min_one *)qdf_nbuf_data(mpdu_nbuf);
513 
514 	frm_ctl = (QDF_IEEE80211_FC0_VERSION_0 | QDF_IEEE80211_FC0_TYPE_CTL |
515 		   QDF_IEEE80211_FC0_SUBTYPE_ACK);
516 	TXMON_PPDU_COM(tx_ppdu_info, frame_control) = frm_ctl;
517 	TXMON_PPDU_COM(tx_ppdu_info, frame_control_info_valid) = 1;
518 	wh_addr1->i_fc[1] = 0;
519 	wh_addr1->i_fc[0] = frm_ctl;
520 
521 	qdf_mem_copy(wh_addr1->i_addr1,
522 		     TXMON_STATUS_INFO(tx_status_info, addr1),
523 		     QDF_MAC_ADDR_SIZE);
524 
525 	/* set duration zero for ack frame */
526 	*(u_int16_t *)(&wh_addr1->i_dur) = qdf_cpu_to_le16(0x0000);
527 
528 	qdf_nbuf_set_pktlen(mpdu_nbuf, sizeof(*wh_addr1));
529 
530 	dp_tx_mon_enqueue_mpdu_nbuf(pdev, tx_ppdu_info, user_id, mpdu_nbuf);
531 	TXMON_PPDU_HAL(tx_ppdu_info, is_used) = 1;
532 }
533 
534 /**
535  * dp_tx_mon_generate_3addr_qos_null_frm() - API to generate
536  * 3 address qosnull frame
537  *
538  * @pdev: pdev Handle
539  * @tx_ppdu_info: pointer to tx ppdu info structure
540  *
541  * Return: void
542  */
543 static void
544 dp_tx_mon_generate_3addr_qos_null_frm(struct dp_pdev *pdev,
545 				      struct dp_tx_ppdu_info *tx_ppdu_info)
546 {
547 	/* allocate and populate 3 address qos null frame */
548 	/* enqueue 802.11 payload to per user mpdu_q */
549 	struct dp_mon_pdev *mon_pdev;
550 	struct dp_mon_pdev_be *mon_pdev_be;
551 	struct dp_pdev_tx_monitor_be *tx_mon_be;
552 	struct hal_tx_status_info *tx_status_info;
553 	struct ieee80211_qosframe *wh_addr3 = NULL;
554 	qdf_nbuf_t mpdu_nbuf = NULL;
555 	uint16_t duration_le = 0;
556 	uint8_t num_users = 0;
557 	uint8_t frm_ctl;
558 
559 	/* sanity check */
560 	if (qdf_unlikely(!pdev))
561 		return;
562 
563 	mon_pdev = pdev->monitor_pdev;
564 	if (qdf_unlikely(!mon_pdev))
565 		return;
566 
567 	mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
568 	if (qdf_unlikely(!mon_pdev_be))
569 		return;
570 
571 	tx_mon_be = &mon_pdev_be->tx_monitor_be;
572 	tx_status_info = &tx_mon_be->data_status_info;
573 	/*
574 	 * for radiotap we allocate new skb,
575 	 * so we don't need reserver skb header
576 	 */
577 	mpdu_nbuf = qdf_nbuf_alloc(pdev->soc->osdev,
578 				   MAX_DUMMY_FRM_BODY, 0, 4, FALSE);
579 	if (!mpdu_nbuf)
580 		return;
581 
582 	wh_addr3 = (struct ieee80211_qosframe *)qdf_nbuf_data(mpdu_nbuf);
583 	qdf_mem_zero(wh_addr3, sizeof(struct ieee80211_qosframe));
584 
585 	frm_ctl = (QDF_IEEE80211_FC0_VERSION_0 | QDF_IEEE80211_FC0_TYPE_DATA |
586 		   QDF_IEEE80211_FC0_SUBTYPE_QOS_NULL);
587 	TXMON_PPDU_COM(tx_ppdu_info, frame_control) = frm_ctl;
588 	TXMON_PPDU_COM(tx_ppdu_info, frame_control_info_valid) = 1;
589 	wh_addr3->i_fc[1] = 0;
590 	wh_addr3->i_fc[0] = frm_ctl;
591 
592 	duration_le = qdf_cpu_to_le16(TXMON_PPDU_COM(tx_ppdu_info, duration));
593 	wh_addr3->i_dur[1] = (duration_le & 0xFF00) >> 8;
594 	wh_addr3->i_dur[0] = (duration_le & 0xFF);
595 
596 	qdf_mem_copy(wh_addr3->i_addr1,
597 		     TXMON_STATUS_INFO(tx_status_info, addr1),
598 		     QDF_MAC_ADDR_SIZE);
599 	qdf_mem_copy(wh_addr3->i_addr2,
600 		     TXMON_STATUS_INFO(tx_status_info, addr2),
601 		     QDF_MAC_ADDR_SIZE);
602 	qdf_mem_copy(wh_addr3->i_addr3,
603 		     TXMON_STATUS_INFO(tx_status_info, addr3),
604 		     QDF_MAC_ADDR_SIZE);
605 
606 	qdf_nbuf_set_pktlen(mpdu_nbuf, sizeof(*wh_addr3));
607 	dp_tx_mon_enqueue_mpdu_nbuf(pdev, tx_ppdu_info, num_users, mpdu_nbuf);
608 	TXMON_PPDU_HAL(tx_ppdu_info, is_used) = 1;
609 }
610 
611 /**
612  * dp_tx_mon_generate_4addr_qos_null_frm() - API to generate
613  * 4 address qos null frame
614  *
615  * @pdev: pdev Handle
616  * @tx_ppdu_info: pointer to tx ppdu info structure
617  *
618  * Return: void
619  */
620 static void
621 dp_tx_mon_generate_4addr_qos_null_frm(struct dp_pdev *pdev,
622 				      struct dp_tx_ppdu_info *tx_ppdu_info)
623 {
624 	/* allocate and populate 4 address qos null frame */
625 	/* enqueue 802.11 payload to per user mpdu_q */
626 	struct dp_mon_pdev *mon_pdev;
627 	struct dp_mon_pdev_be *mon_pdev_be;
628 	struct dp_pdev_tx_monitor_be *tx_mon_be;
629 	struct hal_tx_status_info *tx_status_info;
630 	struct ieee80211_qosframe_addr4 *wh_addr4 = NULL;
631 	qdf_nbuf_t mpdu_nbuf = NULL;
632 	uint16_t duration_le = 0;
633 	uint8_t num_users = 0;
634 	uint8_t frm_ctl;
635 
636 	/* sanity check */
637 	if (qdf_unlikely(!pdev))
638 		return;
639 
640 	mon_pdev = pdev->monitor_pdev;
641 	if (qdf_unlikely(!mon_pdev))
642 		return;
643 
644 	mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
645 	if (qdf_unlikely(!mon_pdev_be))
646 		return;
647 
648 	tx_mon_be = &mon_pdev_be->tx_monitor_be;
649 	tx_status_info = &tx_mon_be->data_status_info;
650 	/*
651 	 * for radiotap we allocate new skb,
652 	 * so we don't need reserver skb header
653 	 */
654 	mpdu_nbuf = qdf_nbuf_alloc(pdev->soc->osdev,
655 				   MAX_DUMMY_FRM_BODY, 0, 4, FALSE);
656 	if (!mpdu_nbuf)
657 		return;
658 
659 	wh_addr4 = (struct ieee80211_qosframe_addr4 *)qdf_nbuf_data(mpdu_nbuf);
660 	qdf_mem_zero(wh_addr4, sizeof(struct ieee80211_qosframe_addr4));
661 
662 	frm_ctl = (QDF_IEEE80211_FC0_VERSION_0 | QDF_IEEE80211_FC0_TYPE_DATA |
663 		   QDF_IEEE80211_FC0_SUBTYPE_QOS_NULL);
664 	TXMON_PPDU_COM(tx_ppdu_info, frame_control) = frm_ctl;
665 	TXMON_PPDU_COM(tx_ppdu_info, frame_control_info_valid) = 1;
666 	wh_addr4->i_fc[1] = 0;
667 	wh_addr4->i_fc[0] = frm_ctl;
668 
669 	duration_le = qdf_cpu_to_le16(TXMON_PPDU_COM(tx_ppdu_info, duration));
670 	wh_addr4->i_dur[1] = (duration_le & 0xFF00) >> 8;
671 	wh_addr4->i_dur[0] = (duration_le & 0xFF);
672 
673 	qdf_mem_copy(wh_addr4->i_addr1,
674 		     TXMON_STATUS_INFO(tx_status_info, addr1),
675 		     QDF_MAC_ADDR_SIZE);
676 	qdf_mem_copy(wh_addr4->i_addr2,
677 		     TXMON_STATUS_INFO(tx_status_info, addr2),
678 		     QDF_MAC_ADDR_SIZE);
679 	qdf_mem_copy(wh_addr4->i_addr3,
680 		     TXMON_STATUS_INFO(tx_status_info, addr3),
681 		     QDF_MAC_ADDR_SIZE);
682 	qdf_mem_copy(wh_addr4->i_addr4,
683 		     TXMON_STATUS_INFO(tx_status_info, addr4),
684 		     QDF_MAC_ADDR_SIZE);
685 
686 	qdf_nbuf_set_pktlen(mpdu_nbuf, sizeof(*wh_addr4));
687 	dp_tx_mon_enqueue_mpdu_nbuf(pdev, tx_ppdu_info, num_users, mpdu_nbuf);
688 	TXMON_PPDU_HAL(tx_ppdu_info, is_used) = 1;
689 }
690 
691 #define TXMON_BA_CTRL_SZ		2
692 #define TXMON_BA_INFO_SZ(bitmap_sz)	((4 * (bitmap_sz)) + 6)
693 #define TXMON_MU_BA_ACK_FRAME_SZ(bitmap_sz)		\
694 		(sizeof(struct ieee80211_ctlframe_addr2) +\
695 		 TXMON_BA_CTRL_SZ + (bitmap_sz))
696 
697 #define TXMON_BA_ACK_FRAME_SZ(bitmap_sz)		\
698 		(sizeof(struct ieee80211_ctlframe_addr2) +\
699 		 TXMON_BA_CTRL_SZ + TXMON_BA_INFO_SZ(bitmap_sz))
700 
701 /**
702  * dp_tx_mon_generate_mu_block_ack_frm() - API to generate MU block ack frame
703  * @pdev: pdev Handle
704  * @tx_ppdu_info: pointer to tx ppdu info structure
705  * @window_flag: frame generated window
706  *
707  * Return: void
708  */
709 static void
710 dp_tx_mon_generate_mu_block_ack_frm(struct dp_pdev *pdev,
711 				    struct dp_tx_ppdu_info *tx_ppdu_info,
712 				    uint8_t window_flag)
713 {
714 	/* allocate and populate MU block ack frame */
715 	/* enqueue 802.11 payload to per user mpdu_q */
716 	struct dp_mon_pdev *mon_pdev;
717 	struct dp_mon_pdev_be *mon_pdev_be;
718 	struct dp_pdev_tx_monitor_be *tx_mon_be;
719 	struct hal_tx_status_info *tx_status_info;
720 	struct ieee80211_ctlframe_addr2 *wh_addr2 = NULL;
721 	qdf_nbuf_t mpdu_nbuf = NULL;
722 	uint16_t ba_control = 0;
723 	uint8_t *frm = NULL;
724 	uint32_t ba_sz = 0;
725 	uint8_t num_users = TXMON_PPDU_HAL(tx_ppdu_info, num_users);
726 	uint8_t i = 0;
727 	uint8_t frm_ctl;
728 
729 	/* sanity check */
730 	if (qdf_unlikely(!pdev))
731 		return;
732 
733 	mon_pdev = pdev->monitor_pdev;
734 	if (qdf_unlikely(!mon_pdev))
735 		return;
736 
737 	mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
738 	if (qdf_unlikely(!mon_pdev_be))
739 		return;
740 
741 	tx_mon_be = &mon_pdev_be->tx_monitor_be;
742 	tx_status_info = &tx_mon_be->data_status_info;
743 	for (i = 0; i < num_users; i++)
744 		ba_sz += (4 << TXMON_BA_INFO_SZ(TXMON_PPDU_USR(tx_ppdu_info,
745 							       i,
746 							       ba_bitmap_sz)));
747 
748 	/*
749 	 * for multi sta block ack, do we need to increase the size
750 	 * or copy info on subsequent frame offset
751 	 *
752 	 * for radiotap we allocate new skb,
753 	 * so we don't need reserver skb header
754 	 */
755 	mpdu_nbuf = qdf_nbuf_alloc(pdev->soc->osdev,
756 				   TXMON_MU_BA_ACK_FRAME_SZ(ba_sz), 0, 4,
757 				   FALSE);
758 	if (!mpdu_nbuf) {
759 		/* TODO: update status and break */
760 		return;
761 	}
762 
763 	wh_addr2 = (struct ieee80211_ctlframe_addr2 *)qdf_nbuf_data(mpdu_nbuf);
764 	qdf_mem_zero(wh_addr2, DP_BA_ACK_FRAME_SIZE);
765 
766 	frm_ctl = (QDF_IEEE80211_FC0_VERSION_0 | QDF_IEEE80211_FC0_TYPE_CTL |
767 		   QDF_IEEE80211_FC0_SUBTYPE_BA);
768 	TXMON_PPDU_COM(tx_ppdu_info, frame_control) = frm_ctl;
769 	TXMON_PPDU_COM(tx_ppdu_info, frame_control_info_valid) = 1;
770 	wh_addr2->i_fc[1] = 0;
771 	wh_addr2->i_fc[0] = frm_ctl;
772 
773 	*(u_int16_t *)(&wh_addr2->i_aidordur) = qdf_cpu_to_le16(0x0000);
774 
775 	if (window_flag == RESPONSE_WINDOW) {
776 		qdf_mem_copy(wh_addr2->i_addr2,
777 			     TXMON_STATUS_INFO(tx_status_info, addr2),
778 			     QDF_MAC_ADDR_SIZE);
779 		if (num_users > 1)
780 			qdf_mem_set(wh_addr2->i_addr1, QDF_MAC_ADDR_SIZE, 0xFF);
781 		else
782 			qdf_mem_copy(wh_addr2->i_addr1,
783 				     TXMON_STATUS_INFO(tx_status_info, addr1),
784 				     QDF_MAC_ADDR_SIZE);
785 	} else {
786 		qdf_mem_copy(wh_addr2->i_addr2,
787 			     TXMON_STATUS_INFO(tx_status_info, addr1),
788 			     QDF_MAC_ADDR_SIZE);
789 		qdf_mem_copy(wh_addr2->i_addr1,
790 			     TXMON_STATUS_INFO(tx_status_info, addr2),
791 			     QDF_MAC_ADDR_SIZE);
792 	}
793 
794 	frm = (uint8_t *)&wh_addr2[1];
795 
796 	/* BA control */
797 	ba_control = 0x0016;
798 	*((uint16_t *)frm) = qdf_cpu_to_le16(ba_control);
799 	frm += 2;
800 
801 	for (i = 0; i < num_users; i++) {
802 		*((uint16_t *)frm) =
803 			qdf_cpu_to_le16((TXMON_PPDU_USR(tx_ppdu_info, i, tid) <<
804 					 DP_IEEE80211_BAR_CTL_TID_S) |
805 					(TXMON_PPDU_USR(tx_ppdu_info, i,
806 							aid) & 0x7FF));
807 		frm += 2;
808 		*((uint16_t *)frm) = qdf_cpu_to_le16(
809 				TXMON_PPDU_USR(tx_ppdu_info, i, start_seq));
810 		frm += 2;
811 		qdf_mem_copy(frm,
812 			     TXMON_PPDU_USR(tx_ppdu_info, i, ba_bitmap),
813 					    4 <<
814 					    TXMON_PPDU_USR(tx_ppdu_info,
815 							   i, ba_bitmap_sz));
816 		frm += 4 << TXMON_PPDU_USR(tx_ppdu_info, i, ba_bitmap_sz);
817 	}
818 
819 	qdf_nbuf_set_pktlen(mpdu_nbuf,
820 			    (frm - (uint8_t *)qdf_nbuf_data(mpdu_nbuf)));
821 
822 	/* always enqueue to first active user */
823 	dp_tx_mon_enqueue_mpdu_nbuf(pdev, tx_ppdu_info, 0, mpdu_nbuf);
824 	TXMON_PPDU_HAL(tx_ppdu_info, is_used) = 1;
825 	/* HE MU fields not required for Multi Sta Block ack frame */
826 	TXMON_PPDU_COM(tx_ppdu_info, he_mu_flags) = 0;
827 }
828 
829 /**
830  * dp_tx_mon_generate_block_ack_frm() - API to generate block ack frame
831  * @pdev: pdev Handle
832  * @tx_ppdu_info: pointer to tx ppdu info structure
833  * @window_flag: frame generated window
834  *
835  * Return: void
836  */
837 static void
838 dp_tx_mon_generate_block_ack_frm(struct dp_pdev *pdev,
839 				 struct dp_tx_ppdu_info *tx_ppdu_info,
840 				 uint8_t window_flag)
841 {
842 	/* allocate and populate block ack frame */
843 	/* enqueue 802.11 payload to per user mpdu_q */
844 	struct dp_mon_pdev *mon_pdev;
845 	struct dp_mon_pdev_be *mon_pdev_be;
846 	struct dp_pdev_tx_monitor_be *tx_mon_be;
847 	struct hal_tx_status_info *tx_status_info;
848 	struct ieee80211_ctlframe_addr2 *wh_addr2 = NULL;
849 	qdf_nbuf_t mpdu_nbuf = NULL;
850 	uint8_t *frm = NULL;
851 	uint8_t user_id = TXMON_PPDU(tx_ppdu_info, cur_usr_idx);
852 	uint32_t ba_bitmap_sz = TXMON_PPDU_USR(tx_ppdu_info,
853 					       user_id, ba_bitmap_sz);
854 	uint8_t frm_ctl;
855 
856 	/* sanity check */
857 	if (qdf_unlikely(!pdev))
858 		return;
859 
860 	mon_pdev = pdev->monitor_pdev;
861 	if (qdf_unlikely(!mon_pdev))
862 		return;
863 
864 	mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
865 	if (qdf_unlikely(!mon_pdev_be))
866 		return;
867 
868 	tx_mon_be = &mon_pdev_be->tx_monitor_be;
869 	tx_status_info = &tx_mon_be->data_status_info;
870 	/*
871 	 * for multi sta block ack, do we need to increase the size
872 	 * or copy info on subsequent frame offset
873 	 *
874 	 * for radiotap we allocate new skb,
875 	 * so we don't need reserver skb header
876 	 */
877 	mpdu_nbuf = qdf_nbuf_alloc(pdev->soc->osdev,
878 				   TXMON_BA_ACK_FRAME_SZ(ba_bitmap_sz),
879 				   0, 4, FALSE);
880 	if (!mpdu_nbuf) {
881 		/* TODO: update status and break */
882 		return;
883 	}
884 
885 	/*
886 	 * BA CONTROL
887 	 * fields required to construct block ack information
888 	 * B0 - BA ACK POLICY
889 	 *	0 - Normal ACK
890 	 *	1 - No ACK
891 	 * B1 - MULTI TID
892 	 * B2 - COMPRESSED BITMAP
893 	 *	B12
894 	 *	00 - Basic block ack
895 	 *	01 - Compressed block ack
896 	 *	10 - Reserved
897 	 *	11 - Multi tid block ack
898 	 * B3-B11 - Reserved
899 	 * B12-B15 - TID info
900 	 *
901 	 * BA INFORMATION
902 	 * Per sta tid info
903 	 *	AID: 11 bits
904 	 *	ACK type: 1 bit
905 	 *	TID: 4 bits
906 	 *
907 	 * BA SEQ CTRL
908 	 *
909 	 * BA bitmap
910 	 *
911 	 */
912 
913 	wh_addr2 = (struct ieee80211_ctlframe_addr2 *)qdf_nbuf_data(mpdu_nbuf);
914 	qdf_mem_zero(wh_addr2, DP_BA_ACK_FRAME_SIZE);
915 
916 	frm_ctl = (QDF_IEEE80211_FC0_VERSION_0 | QDF_IEEE80211_FC0_TYPE_CTL |
917 		   QDF_IEEE80211_FC0_SUBTYPE_BA);
918 	TXMON_PPDU_COM(tx_ppdu_info, frame_control) = frm_ctl;
919 	TXMON_PPDU_COM(tx_ppdu_info, frame_control_info_valid) = 1;
920 	wh_addr2->i_fc[1] = 0;
921 	wh_addr2->i_fc[0] = frm_ctl;
922 
923 	/* duration */
924 	*(u_int16_t *)(&wh_addr2->i_aidordur) = qdf_cpu_to_le16(0x0020);
925 
926 	if (window_flag) {
927 		qdf_mem_copy(wh_addr2->i_addr2,
928 			     TXMON_STATUS_INFO(tx_status_info, addr2),
929 			     QDF_MAC_ADDR_SIZE);
930 		qdf_mem_copy(wh_addr2->i_addr1,
931 			     TXMON_STATUS_INFO(tx_status_info, addr1),
932 			     QDF_MAC_ADDR_SIZE);
933 	} else {
934 		qdf_mem_copy(wh_addr2->i_addr2,
935 			     TXMON_STATUS_INFO(tx_status_info, addr1),
936 			     QDF_MAC_ADDR_SIZE);
937 		qdf_mem_copy(wh_addr2->i_addr1,
938 			     TXMON_STATUS_INFO(tx_status_info, addr2),
939 			     QDF_MAC_ADDR_SIZE);
940 	}
941 
942 	frm = (uint8_t *)&wh_addr2[1];
943 	/* BA control */
944 	*((uint16_t *)frm) = qdf_cpu_to_le16(TXMON_PPDU_USR(tx_ppdu_info,
945 							    user_id,
946 							    ba_control));
947 	frm += 2;
948 	*((uint16_t *)frm) = qdf_cpu_to_le16(TXMON_PPDU_USR(tx_ppdu_info,
949 							    user_id,
950 							    start_seq));
951 	frm += 2;
952 	qdf_mem_copy(frm,
953 		     TXMON_PPDU_USR(tx_ppdu_info, user_id, ba_bitmap),
954 		     4 << TXMON_PPDU_USR(tx_ppdu_info, user_id, ba_bitmap_sz));
955 	frm += (4 << TXMON_PPDU_USR(tx_ppdu_info, user_id, ba_bitmap_sz));
956 
957 	qdf_nbuf_set_pktlen(mpdu_nbuf,
958 			    (frm - (uint8_t *)qdf_nbuf_data(mpdu_nbuf)));
959 
960 	dp_tx_mon_enqueue_mpdu_nbuf(pdev, tx_ppdu_info, 0, mpdu_nbuf);
961 
962 	TXMON_PPDU_HAL(tx_ppdu_info, is_used) = 1;
963 }
964 
965 /**
966  * dp_tx_mon_alloc_mpdu() - API to allocate mpdu and add that current
967  * user index
968  *
969  * @pdev: pdev Handle
970  * @tx_ppdu_info: pointer to tx ppdu info structure
971  *
972  * Return: void
973  */
974 static void
975 dp_tx_mon_alloc_mpdu(struct dp_pdev *pdev, struct dp_tx_ppdu_info *tx_ppdu_info)
976 {
977 	qdf_nbuf_t mpdu_nbuf = NULL;
978 	qdf_nbuf_queue_t *usr_mpdu_q = NULL;
979 	uint32_t usr_idx = 0;
980 
981 	/*
982 	 * payload will be added as a frag to buffer
983 	 * and we allocate new skb for radiotap header
984 	 * we allocate a dummy buffer size
985 	 */
986 	mpdu_nbuf = qdf_nbuf_alloc(pdev->soc->osdev,
987 				   MAX_MONITOR_HEADER, MAX_MONITOR_HEADER,
988 				   4, FALSE);
989 	if (!mpdu_nbuf) {
990 		qdf_err("%s: %d No memory to allocate mpdu_nbuf!!!!!\n",
991 			__func__, __LINE__);
992 		return;
993 	}
994 
995 	usr_idx = TXMON_PPDU(tx_ppdu_info, cur_usr_idx);
996 	usr_mpdu_q = &TXMON_PPDU_USR(tx_ppdu_info, usr_idx, mpdu_q);
997 
998 	qdf_nbuf_queue_add(usr_mpdu_q, mpdu_nbuf);
999 }
1000 
1001 /**
1002  * dp_tx_mon_generate_data_frm() - API to generate data frame
1003  * @pdev: pdev Handle
1004  * @tx_ppdu_info: pointer to tx ppdu info structure
1005  * @take_ref:
1006  *
1007  * Return: void
1008  */
1009 static void
1010 dp_tx_mon_generate_data_frm(struct dp_pdev *pdev,
1011 			    struct dp_tx_ppdu_info *tx_ppdu_info,
1012 			    bool take_ref)
1013 {
1014 	struct dp_mon_pdev *mon_pdev;
1015 	struct dp_mon_pdev_be *mon_pdev_be;
1016 	struct dp_pdev_tx_monitor_be *tx_mon_be;
1017 	struct hal_tx_status_info *tx_status_info;
1018 	qdf_nbuf_t mpdu_nbuf = NULL;
1019 	qdf_nbuf_queue_t *usr_mpdu_q = NULL;
1020 	uint32_t usr_idx = 0;
1021 
1022 	/* sanity check */
1023 	if (qdf_unlikely(!pdev))
1024 		return;
1025 
1026 	mon_pdev = pdev->monitor_pdev;
1027 	if (qdf_unlikely(!mon_pdev))
1028 		return;
1029 
1030 	mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
1031 	if (qdf_unlikely(!mon_pdev_be))
1032 		return;
1033 
1034 	tx_mon_be = &mon_pdev_be->tx_monitor_be;
1035 
1036 	tx_status_info = &tx_mon_be->data_status_info;
1037 	usr_idx = TXMON_PPDU(tx_ppdu_info, cur_usr_idx);
1038 	usr_mpdu_q = &TXMON_PPDU_USR(tx_ppdu_info, usr_idx, mpdu_q);
1039 	mpdu_nbuf = qdf_nbuf_queue_last(usr_mpdu_q);
1040 
1041 	if (!mpdu_nbuf)
1042 		QDF_BUG(0);
1043 
1044 	tx_mon_be->stats.pkt_buf_processed++;
1045 
1046 	/* add function to either copy or add frag to frag_list */
1047 	qdf_nbuf_add_frag(pdev->soc->osdev,
1048 			  TXMON_STATUS_INFO(tx_status_info, buffer),
1049 			  mpdu_nbuf,
1050 			  TXMON_STATUS_INFO(tx_status_info, offset),
1051 			  TXMON_STATUS_INFO(tx_status_info, length),
1052 			  DP_MON_DATA_BUFFER_SIZE,
1053 			  take_ref, TXMON_NO_BUFFER_SZ);
1054 }
1055 
1056 /**
1057  * dp_tx_mon_generate_prot_frm() - API to generate protection frame
1058  * @pdev: pdev Handle
1059  * @tx_ppdu_info: pointer to tx ppdu info structure
1060  *
1061  * Return: void
1062  */
1063 static void
1064 dp_tx_mon_generate_prot_frm(struct dp_pdev *pdev,
1065 			    struct dp_tx_ppdu_info *tx_ppdu_info)
1066 {
1067 	struct dp_mon_pdev *mon_pdev;
1068 	struct dp_mon_pdev_be *mon_pdev_be;
1069 	struct dp_pdev_tx_monitor_be *tx_mon_be;
1070 	struct hal_tx_status_info *tx_status_info;
1071 
1072 	/* sanity check */
1073 	if (qdf_unlikely(!pdev))
1074 		return;
1075 
1076 	mon_pdev = pdev->monitor_pdev;
1077 	if (qdf_unlikely(!mon_pdev))
1078 		return;
1079 
1080 	mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
1081 	if (qdf_unlikely(!mon_pdev_be))
1082 		return;
1083 
1084 	tx_mon_be = &mon_pdev_be->tx_monitor_be;
1085 	tx_status_info = &tx_mon_be->prot_status_info;
1086 
1087 	/* update medium prot type from data */
1088 	TXMON_STATUS_INFO(tx_status_info, medium_prot_type) =
1089 		tx_mon_be->data_status_info.medium_prot_type;
1090 
1091 	switch (TXMON_STATUS_INFO(tx_status_info, medium_prot_type)) {
1092 	case TXMON_MEDIUM_NO_PROTECTION:
1093 	{
1094 		/* no protection frame - do nothing */
1095 		break;
1096 	}
1097 	case TXMON_MEDIUM_RTS_LEGACY:
1098 	case TXMON_MEDIUM_RTS_11AC_STATIC_BW:
1099 	case TXMON_MEDIUM_RTS_11AC_DYNAMIC_BW:
1100 	{
1101 		dp_tx_mon_generate_rts_frm(pdev, tx_ppdu_info,
1102 					   INITIATOR_WINDOW);
1103 		break;
1104 	}
1105 	case TXMON_MEDIUM_CTS2SELF:
1106 	{
1107 		dp_tx_mon_generate_cts2self_frm(pdev, tx_ppdu_info,
1108 						INITIATOR_WINDOW);
1109 		break;
1110 	}
1111 	case TXMON_MEDIUM_QOS_NULL_NO_ACK_3ADDR:
1112 	{
1113 		dp_tx_mon_generate_3addr_qos_null_frm(pdev, tx_ppdu_info);
1114 		break;
1115 	}
1116 	case TXMON_MEDIUM_QOS_NULL_NO_ACK_4ADDR:
1117 	{
1118 		dp_tx_mon_generate_4addr_qos_null_frm(pdev, tx_ppdu_info);
1119 		break;
1120 	}
1121 	}
1122 }
1123 
1124 /**
1125  * dp_tx_mon_generated_response_frm() - API to handle generated response frame
1126  * @pdev: pdev Handle
1127  * @tx_ppdu_info: pointer to tx ppdu info structure
1128  *
1129  * Return: QDF_STATUS
1130  */
1131 static QDF_STATUS
1132 dp_tx_mon_generated_response_frm(struct dp_pdev *pdev,
1133 				 struct dp_tx_ppdu_info *tx_ppdu_info)
1134 {
1135 	struct dp_mon_pdev *mon_pdev;
1136 	struct dp_mon_pdev_be *mon_pdev_be;
1137 	struct dp_pdev_tx_monitor_be *tx_mon_be;
1138 	struct hal_tx_status_info *tx_status_info;
1139 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1140 	uint8_t gen_response = 0;
1141 
1142 	/* sanity check */
1143 	if (qdf_unlikely(!pdev))
1144 		return QDF_STATUS_E_NOMEM;
1145 
1146 	mon_pdev = pdev->monitor_pdev;
1147 	if (qdf_unlikely(!mon_pdev))
1148 		return QDF_STATUS_E_NOMEM;
1149 
1150 	mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
1151 	if (qdf_unlikely(!mon_pdev_be))
1152 		return QDF_STATUS_E_NOMEM;
1153 
1154 	tx_mon_be = &mon_pdev_be->tx_monitor_be;
1155 
1156 	tx_status_info = &tx_mon_be->data_status_info;
1157 	gen_response = TXMON_STATUS_INFO(tx_status_info, generated_response);
1158 
1159 	switch (gen_response) {
1160 	case TXMON_GEN_RESP_SELFGEN_ACK:
1161 	{
1162 		dp_tx_mon_generate_ack_frm(pdev, tx_ppdu_info);
1163 		break;
1164 	}
1165 	case TXMON_GEN_RESP_SELFGEN_CTS:
1166 	{
1167 		dp_tx_mon_generate_cts2self_frm(pdev, tx_ppdu_info,
1168 						RESPONSE_WINDOW);
1169 		break;
1170 	}
1171 	case TXMON_GEN_RESP_SELFGEN_BA:
1172 	{
1173 		dp_tx_mon_generate_block_ack_frm(pdev, tx_ppdu_info,
1174 						 RESPONSE_WINDOW);
1175 		break;
1176 	}
1177 	case TXMON_GEN_RESP_SELFGEN_MBA:
1178 	{
1179 		dp_tx_mon_generate_mu_block_ack_frm(pdev, tx_ppdu_info,
1180 						    RESPONSE_WINDOW);
1181 		break;
1182 	}
1183 	case TXMON_GEN_RESP_SELFGEN_CBF:
1184 	{
1185 		break;
1186 	}
1187 	case TXMON_GEN_RESP_SELFGEN_TRIG:
1188 	{
1189 		break;
1190 	}
1191 	case TXMON_GEN_RESP_SELFGEN_NDP_LMR:
1192 	{
1193 		break;
1194 	}
1195 	};
1196 
1197 	return status;
1198 }
1199 
1200 /**
1201  * dp_tx_mon_update_ppdu_info_status() - API to update frame as information
1202  * is stored only for that processing
1203  *
1204  * @pdev: pdev Handle
1205  * @tx_data_ppdu_info: pointer to data tx ppdu info
1206  * @tx_prot_ppdu_info: pointer to protection tx ppdu info
1207  * @tx_tlv_hdr: pointer to tx_tlv_hdr
1208  * @status_frag: pointer to fragment
1209  * @tlv_status: tlv status return from hal api
1210  * @mon_desc_list_ref: tx monitor descriptor list reference
1211  *
1212  * Return: QDF_STATUS
1213  */
1214 static QDF_STATUS
1215 dp_tx_mon_update_ppdu_info_status(struct dp_pdev *pdev,
1216 				  struct dp_tx_ppdu_info *tx_data_ppdu_info,
1217 				  struct dp_tx_ppdu_info *tx_prot_ppdu_info,
1218 				  void *tx_tlv_hdr,
1219 				  qdf_frag_t status_frag,
1220 				  uint32_t tlv_status,
1221 				  struct dp_tx_mon_desc_list *mon_desc_list_ref)
1222 {
1223 	struct dp_mon_pdev *mon_pdev;
1224 	struct dp_mon_pdev_be *mon_pdev_be;
1225 	struct dp_pdev_tx_monitor_be *tx_mon_be;
1226 	struct hal_tx_status_info *tx_status_info;
1227 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1228 
1229 	/* sanity check */
1230 	if (qdf_unlikely(!pdev))
1231 		return QDF_STATUS_E_NOMEM;
1232 
1233 	mon_pdev = pdev->monitor_pdev;
1234 	if (qdf_unlikely(!mon_pdev))
1235 		return QDF_STATUS_E_NOMEM;
1236 
1237 	mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
1238 	if (qdf_unlikely(!mon_pdev_be))
1239 		return QDF_STATUS_E_NOMEM;
1240 
1241 	tx_mon_be = &mon_pdev_be->tx_monitor_be;
1242 
1243 	switch (tlv_status) {
1244 	case HAL_MON_TX_FES_SETUP:
1245 	{
1246 		/*
1247 		 * start of initiator window
1248 		 *
1249 		 * got number of user count from  fes setup tlv
1250 		 */
1251 		break;
1252 	}
1253 	case HAL_MON_RX_RESPONSE_REQUIRED_INFO:
1254 	{
1255 		break;
1256 	}
1257 	case HAL_MON_TX_FES_STATUS_START_PROT:
1258 	{
1259 		/* update tsft to local */
1260 		break;
1261 	}
1262 	case HAL_MON_TX_FES_STATUS_START_PPDU:
1263 	{
1264 		/* update tsft to local */
1265 		break;
1266 	}
1267 	case HAL_MON_TX_FES_STATUS_PROT:
1268 	{
1269 		TXMON_PPDU_HAL(tx_prot_ppdu_info, is_used) = 1;
1270 		TXMON_PPDU_COM(tx_prot_ppdu_info, ppdu_timestamp) =
1271 			TXMON_PPDU_COM(tx_prot_ppdu_info, ppdu_timestamp) << 1;
1272 
1273 		/* based on medium protection type we need to generate frame */
1274 		dp_tx_mon_generate_prot_frm(pdev, tx_prot_ppdu_info);
1275 		break;
1276 	}
1277 	case HAL_MON_RX_FRAME_BITMAP_ACK:
1278 	{
1279 		break;
1280 	}
1281 	case HAL_MON_RX_FRAME_BITMAP_BLOCK_ACK_256:
1282 	case HAL_MON_RX_FRAME_BITMAP_BLOCK_ACK_1K:
1283 	{
1284 		/*
1285 		 * this comes for each user
1286 		 * BlockAck is not same as ACK, single frame can hold
1287 		 * multiple BlockAck info
1288 		 */
1289 		tx_status_info = &tx_mon_be->data_status_info;
1290 
1291 		if (TXMON_PPDU_HAL(tx_data_ppdu_info, num_users))
1292 			dp_tx_mon_generate_block_ack_frm(pdev,
1293 							 tx_data_ppdu_info,
1294 							 INITIATOR_WINDOW);
1295 		else
1296 			dp_tx_mon_generate_mu_block_ack_frm(pdev,
1297 							    tx_data_ppdu_info,
1298 							    INITIATOR_WINDOW);
1299 
1300 		break;
1301 	}
1302 	case HAL_MON_TX_MPDU_START:
1303 	{
1304 		dp_tx_mon_alloc_mpdu(pdev, tx_data_ppdu_info);
1305 		TXMON_PPDU_HAL(tx_data_ppdu_info, is_used) = 1;
1306 		break;
1307 	}
1308 	case HAL_MON_TX_MSDU_START:
1309 	{
1310 		break;
1311 	}
1312 	case HAL_MON_TX_DATA:
1313 	{
1314 		TXMON_PPDU_HAL(tx_data_ppdu_info, is_used) = 1;
1315 		dp_tx_mon_generate_data_frm(pdev, tx_data_ppdu_info, true);
1316 		break;
1317 	}
1318 	case HAL_MON_TX_BUFFER_ADDR:
1319 	{
1320 		struct hal_mon_packet_info *packet_info = NULL;
1321 		struct dp_mon_desc *mon_desc = NULL;
1322 		qdf_frag_t packet_buffer = NULL;
1323 		uint32_t end_offset = 0;
1324 
1325 		tx_status_info = &tx_mon_be->data_status_info;
1326 		/* update buffer from packet info */
1327 		packet_info = &TXMON_PPDU_HAL(tx_data_ppdu_info, packet_info);
1328 		mon_desc = (struct dp_mon_desc *)(uintptr_t)packet_info->sw_cookie;
1329 
1330 		qdf_assert_always(mon_desc);
1331 
1332 		if (mon_desc->magic != DP_MON_DESC_MAGIC)
1333 			qdf_assert_always(0);
1334 
1335 		qdf_assert_always(mon_desc->buf_addr);
1336 		tx_mon_be->stats.pkt_buf_recv++;
1337 
1338 		if (!mon_desc->unmapped) {
1339 			qdf_mem_unmap_page(pdev->soc->osdev,
1340 					   (qdf_dma_addr_t)mon_desc->paddr,
1341 					   DP_MON_DATA_BUFFER_SIZE,
1342 					   QDF_DMA_FROM_DEVICE);
1343 			mon_desc->unmapped = 1;
1344 		}
1345 
1346 		packet_buffer = mon_desc->buf_addr;
1347 		mon_desc->buf_addr = NULL;
1348 
1349 		/* increment reap count */
1350 		mon_desc_list_ref->tx_mon_reap_cnt++;
1351 
1352 		/* add the mon_desc to free list */
1353 		dp_mon_add_to_free_desc_list(&mon_desc_list_ref->desc_list,
1354 					     &mon_desc_list_ref->tail,
1355 					     mon_desc);
1356 
1357 		TXMON_STATUS_INFO(tx_status_info, buffer) = packet_buffer;
1358 		TXMON_STATUS_INFO(tx_status_info, offset) = end_offset;
1359 		TXMON_STATUS_INFO(tx_status_info,
1360 				  length) = packet_info->dma_length;
1361 
1362 		TXMON_PPDU_HAL(tx_data_ppdu_info, is_used) = 1;
1363 		dp_tx_mon_generate_data_frm(pdev, tx_data_ppdu_info, false);
1364 		break;
1365 	}
1366 	case HAL_MON_TX_FES_STATUS_END:
1367 	{
1368 		break;
1369 	}
1370 	case HAL_MON_RESPONSE_END_STATUS_INFO:
1371 	{
1372 		dp_tx_mon_generated_response_frm(pdev, tx_data_ppdu_info);
1373 		break;
1374 	}
1375 	case HAL_MON_TX_FES_STATUS_START:
1376 	{
1377 		/* update the medium protection type */
1378 		break;
1379 	}
1380 	case HAL_MON_TX_QUEUE_EXTENSION:
1381 	{
1382 		/* No action for Queue Extension TLV */
1383 		break;
1384 	}
1385 	case HAL_MON_TX_FW2SW:
1386 	{
1387 		/* update the frequency */
1388 		tx_status_info = &tx_mon_be->data_status_info;
1389 
1390 		TXMON_PPDU_COM(tx_data_ppdu_info,
1391 			       chan_freq) = TXMON_STATUS_INFO(tx_status_info,
1392 							      freq);
1393 		TXMON_PPDU_COM(tx_prot_ppdu_info,
1394 			       chan_freq) = TXMON_STATUS_INFO(tx_status_info,
1395 							      freq);
1396 		break;
1397 	}
1398 	default:
1399 	{
1400 		/* return or break in default case */
1401 		break;
1402 	}
1403 	};
1404 
1405 	return status;
1406 }
1407 
1408 #ifdef MONITOR_TLV_RECORDING_ENABLE
1409 /**
1410  * dp_tx_mon_record_index_update() - update the indexes of dp_mon_tlv_logger
1411  *					to store next Tx TLV
1412  *
1413  * @mon_pdev_be: pointer to dp_mon_pdev_be
1414  *
1415  * Return: void
1416  */
1417 void dp_tx_mon_record_index_update(struct dp_mon_pdev_be *mon_pdev_be)
1418 {
1419 	struct dp_mon_tlv_logger *tlv_log = NULL;
1420 	struct dp_tx_mon_tlv_info *tlv_info = NULL;
1421 
1422 	tlv_log = mon_pdev_be->tx_tlv_log;
1423 	tlv_info = (struct dp_tx_mon_tlv_info *)tlv_log->buff;
1424 
1425 	(tlv_log->curr_ppdu_pos + 1 == MAX_NUM_PPDU_RECORD) ?
1426 		tlv_log->curr_ppdu_pos = 0 :
1427 			tlv_log->curr_ppdu_pos++;
1428 
1429 	tlv_log->wrap_flag = 0;
1430 	tlv_log->ppdu_start_idx = tlv_log->curr_ppdu_pos *
1431 		MAX_TLVS_PER_PPDU;
1432 	tlv_log->mpdu_idx = tlv_log->ppdu_start_idx +
1433 		MAX_PPDU_START_TLV_NUM;
1434 	tlv_log->ppdu_end_idx = tlv_log->mpdu_idx + MAX_MPDU_TLV_NUM;
1435 	tlv_log->max_ppdu_start_idx = tlv_log->ppdu_start_idx +
1436 		MAX_PPDU_START_TLV_NUM - 1;
1437 	tlv_log->max_mpdu_idx = tlv_log->mpdu_idx +
1438 		MAX_MPDU_TLV_NUM - 1;
1439 	tlv_log->max_ppdu_end_idx = tlv_log->ppdu_end_idx +
1440 		MAX_PPDU_END_TLV_NUM - 1;
1441 }
1442 
1443 /**
1444  * dp_tx_mon_record_tlv() - Store the contents of the tlv in buffer
1445  *
1446  * @mon_pdev_be: pointer to dp_mon_pdev_be
1447  * @data_ppdu_info: pointer to HAL Tx data ppdu info
1448  * @proto_ppdu_info: pointer to HAL Tx proto ppdu info
1449  *
1450  * Return: void
1451  */
1452 void dp_tx_mon_record_tlv(struct dp_mon_pdev_be *mon_pdev_be,
1453 			  struct hal_tx_ppdu_info *data_ppdu_info,
1454 			  struct hal_tx_ppdu_info *proto_ppdu_info)
1455 {
1456 	struct hal_tx_ppdu_info *ppdu_info = NULL;
1457 	struct dp_tx_mon_tlv_info *tlv_info = NULL;
1458 	struct dp_mon_tlv_logger *tlv_log = NULL;
1459 	uint16_t *ppdu_start_idx = NULL;
1460 	uint16_t *mpdu_idx = NULL;
1461 	uint16_t *ppdu_end_idx = NULL;
1462 	uint32_t tlv_tag;
1463 
1464 	if (!mon_pdev_be || !(mon_pdev_be->tx_tlv_log))
1465 		return;
1466 
1467 	tlv_log = mon_pdev_be->tx_tlv_log;
1468 	if (!tlv_log->tlv_logging_enable || !(tlv_log->buff))
1469 		return;
1470 
1471 	tlv_info = (struct dp_tx_mon_tlv_info *)tlv_log->buff;
1472 	ppdu_start_idx = &tlv_log->ppdu_start_idx;
1473 	mpdu_idx = &tlv_log->mpdu_idx;
1474 	ppdu_end_idx = &tlv_log->ppdu_end_idx;
1475 
1476 	ppdu_info = (data_ppdu_info->tx_tlv_info.is_data_ppdu_info) ?
1477 			data_ppdu_info : proto_ppdu_info;
1478 	tlv_tag = ppdu_info->tx_tlv_info.tlv_tag;
1479 
1480 	if (ppdu_info->tx_tlv_info.tlv_category == CATEGORY_PPDU_START) {
1481 		tlv_info[*ppdu_start_idx].tlv_tag = tlv_tag;
1482 		switch (tlv_tag) {
1483 		case WIFITX_FES_SETUP_E:
1484 		case WIFITXPCU_BUFFER_STATUS_E:
1485 		case WIFIPCU_PPDU_SETUP_INIT_E:
1486 		case WIFISCH_CRITICAL_TLV_REFERENCE_E:
1487 		case WIFITX_PEER_ENTRY_E:
1488 		case WIFITX_RAW_OR_NATIVE_FRAME_SETUP_E:
1489 		case WIFITX_QUEUE_EXTENSION_E:
1490 		case WIFITX_FES_SETUP_COMPLETE_E:
1491 		case WIFIFW2SW_MON_E:
1492 		case WIFISCHEDULER_END_E:
1493 		case WIFITQM_MPDU_GLOBAL_START_E:
1494 			;
1495 		}
1496 		if (*ppdu_start_idx < tlv_log->max_ppdu_start_idx)
1497 			(*ppdu_start_idx)++;
1498 	} else if (ppdu_info->tx_tlv_info.tlv_category == CATEGORY_MPDU) {
1499 		tlv_info[*mpdu_idx].tlv_tag = tlv_tag;
1500 		switch (tlv_tag) {
1501 		case WIFITX_MPDU_START_E:
1502 		case WIFITX_MSDU_START_E:
1503 		case WIFITX_DATA_E:
1504 		case WIFITX_MSDU_END_E:
1505 		case WIFITX_MPDU_END_E:
1506 			;
1507 		}
1508 		if (*mpdu_idx < tlv_log->max_mpdu_idx) {
1509 			(*mpdu_idx)++;
1510 		} else {
1511 			*mpdu_idx = *mpdu_idx - MAX_MPDU_TLV_NUM + 1;
1512 			tlv_log->wrap_flag ^= 1;
1513 		}
1514 	} else if (ppdu_info->tx_tlv_info.tlv_category == CATEGORY_PPDU_END) {
1515 		tlv_info[*ppdu_end_idx].tlv_tag = tlv_tag;
1516 		switch (tlv_tag) {
1517 		case WIFITX_LAST_MPDU_FETCHED_E:
1518 		case WIFITX_LAST_MPDU_END_E:
1519 		case WIFIPDG_TX_REQ_E:
1520 		case WIFITX_FES_STATUS_START_PPDU_E:
1521 		case WIFIPHYTX_PPDU_HEADER_INFO_REQUEST_E:
1522 		case WIFIMACTX_L_SIG_A_E:
1523 		case WIFITXPCU_PREAMBLE_DONE_E:
1524 		case WIFIMACTX_USER_DESC_COMMON_E:
1525 		case WIFIMACTX_SERVICE_E:
1526 		case WIFITXDMA_STOP_REQUEST_E:
1527 		case WIFITXPCU_USER_BUFFER_STATUS_E:
1528 		case WIFITX_FES_STATUS_USER_PPDU_E:
1529 		case WIFITX_MPDU_COUNT_TRANSFER_END_E:
1530 		case WIFIRX_START_PARAM_E:
1531 		case WIFITX_FES_STATUS_ACK_OR_BA_E:
1532 		case WIFITX_FES_STATUS_USER_RESPONSE_E:
1533 		case WIFITX_FES_STATUS_END_E:
1534 		case WIFITX_FES_STATUS_PROT_E:
1535 		case WIFIMACTX_PHY_DESC_E:
1536 		case WIFIMACTX_HE_SIG_A_SU_E:
1537 			;
1538 		}
1539 		if (*ppdu_end_idx < tlv_log->max_ppdu_end_idx)
1540 			(*ppdu_end_idx)++;
1541 	}
1542 }
1543 
1544 /**
1545  * dp_tx_mon_record_clear_buffer() - Clear the buffer to record next PPDU
1546  *
1547  * @mon_pdev_be : pointer to dp_mon_pdev_be
1548  *
1549  * Return
1550  */
1551 void dp_tx_mon_record_clear_buffer(struct dp_mon_pdev_be *mon_pdev_be)
1552 {
1553 	struct dp_mon_tlv_logger *tlv_log = NULL;
1554 	struct dp_tx_mon_tlv_info *tlv_info = NULL;
1555 
1556 	tlv_log = mon_pdev_be->tx_tlv_log;
1557 	tlv_info = (struct dp_tx_mon_tlv_info *)tlv_log->buff;
1558 	qdf_mem_zero(&tlv_info[tlv_log->ppdu_start_idx],
1559 		     MAX_TLVS_PER_PPDU *
1560 		     sizeof(struct dp_tx_mon_tlv_info));
1561 }
1562 #else
1563 
1564 static
1565 void dp_tx_mon_record_index_update(struct dp_mon_pdev_be *mon_pdev_be)
1566 {
1567 }
1568 
1569 static
1570 void dp_tx_mon_record_tlv(struct dp_mon_pdev_be *mon_pdev_be,
1571 			  struct hal_tx_ppdu_info *data_ppdu_info,
1572 			  struct hal_tx_ppdu_info *proto_ppdu_info)
1573 {
1574 }
1575 
1576 static
1577 void dp_tx_mon_record_clear_buffer(struct dp_mon_pdev_be *mon_pdev_be)
1578 {
1579 }
1580 #endif
1581 /**
1582  * dp_tx_mon_process_tlv_2_0() - API to parse PPDU worth information
1583  * @pdev: DP_PDEV handle
1584  * @mon_desc_list_ref: tx monitor descriptor list reference
1585  *
1586  * Return: status
1587  */
1588 static QDF_STATUS
1589 dp_tx_mon_process_tlv_2_0(struct dp_pdev *pdev,
1590 			  struct dp_tx_mon_desc_list *mon_desc_list_ref)
1591 {
1592 	struct dp_mon_pdev *mon_pdev;
1593 	struct dp_mon_pdev_be *mon_pdev_be;
1594 	struct dp_pdev_tx_monitor_be *tx_mon_be;
1595 	struct dp_tx_ppdu_info *tx_prot_ppdu_info = NULL;
1596 	struct dp_tx_ppdu_info *tx_data_ppdu_info = NULL;
1597 	struct hal_tx_status_info *tx_status_prot;
1598 	struct hal_tx_status_info *tx_status_data;
1599 	qdf_frag_t status_frag = NULL;
1600 	uint32_t end_offset = 0;
1601 	uint32_t tlv_status;
1602 	uint32_t status = QDF_STATUS_SUCCESS;
1603 	uint8_t *tx_tlv;
1604 	uint8_t *tx_tlv_start;
1605 	uint8_t num_users = 0;
1606 	uint8_t cur_frag_q_idx;
1607 	bool schedule_wrq = false;
1608 
1609 	/* sanity check */
1610 	if (qdf_unlikely(!pdev))
1611 		return QDF_STATUS_E_NOMEM;
1612 
1613 	mon_pdev = pdev->monitor_pdev;
1614 	if (qdf_unlikely(!mon_pdev))
1615 		return QDF_STATUS_E_NOMEM;
1616 
1617 	mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
1618 	if (qdf_unlikely(!mon_pdev_be))
1619 		return QDF_STATUS_E_NOMEM;
1620 
1621 	tx_mon_be = &mon_pdev_be->tx_monitor_be;
1622 	cur_frag_q_idx = tx_mon_be->cur_frag_q_idx;
1623 
1624 	tx_status_prot = &tx_mon_be->prot_status_info;
1625 	tx_status_data = &tx_mon_be->data_status_info;
1626 
1627 	tx_prot_ppdu_info = dp_tx_mon_get_ppdu_info(pdev, TX_PROT_PPDU_INFO,
1628 						    1, tx_mon_be->be_ppdu_id);
1629 
1630 	if (!tx_prot_ppdu_info) {
1631 		dp_mon_info("tx prot ppdu info alloc got failed!!");
1632 		return QDF_STATUS_E_NOMEM;
1633 	}
1634 
1635 	status_frag = tx_mon_be->frag_q_vec[cur_frag_q_idx].frag_buf;
1636 	end_offset = tx_mon_be->frag_q_vec[cur_frag_q_idx].end_offset;
1637 	tx_tlv = status_frag;
1638 	dp_mon_debug("last_frag_q_idx: %d status_frag:%pK",
1639 		     tx_mon_be->last_frag_q_idx, status_frag);
1640 
1641 	/* get number of user from tlv window */
1642 	tlv_status = hal_txmon_status_get_num_users(pdev->soc->hal_soc,
1643 						    tx_tlv, &num_users);
1644 	if (tlv_status == HAL_MON_TX_STATUS_PPDU_NOT_DONE || !num_users) {
1645 		dp_tx_mon_free_ppdu_info(tx_prot_ppdu_info, tx_mon_be);
1646 		tx_mon_be->tx_prot_ppdu_info = NULL;
1647 		dp_mon_err("window open with tlv_tag[0x%x] num_users[%d]!\n",
1648 			   hal_tx_status_get_tlv_tag(tx_tlv), num_users);
1649 		return QDF_STATUS_E_INVAL;
1650 	}
1651 
1652 	/* allocate tx_data_ppdu_info based on num_users */
1653 	tx_data_ppdu_info = dp_tx_mon_get_ppdu_info(pdev, TX_DATA_PPDU_INFO,
1654 						    num_users,
1655 						    tx_mon_be->be_ppdu_id);
1656 	if (!tx_data_ppdu_info) {
1657 		dp_tx_mon_free_ppdu_info(tx_prot_ppdu_info, tx_mon_be);
1658 		tx_mon_be->tx_prot_ppdu_info = NULL;
1659 		dp_mon_info("tx prot ppdu info alloc got failed!!");
1660 		return QDF_STATUS_E_NOMEM;
1661 	}
1662 
1663 	/* iterate status buffer queue */
1664 	while (tx_mon_be->cur_frag_q_idx < tx_mon_be->last_frag_q_idx) {
1665 		/* get status buffer from frag_q_vec */
1666 		status_frag = tx_mon_be->frag_q_vec[cur_frag_q_idx].frag_buf;
1667 		end_offset = tx_mon_be->frag_q_vec[cur_frag_q_idx].end_offset;
1668 		if (qdf_unlikely(!status_frag)) {
1669 			dp_mon_err("status frag is NULL\n");
1670 			QDF_BUG(0);
1671 		}
1672 
1673 		tx_tlv = status_frag;
1674 		tx_tlv_start = tx_tlv;
1675 
1676 		dp_tx_mon_record_clear_buffer(mon_pdev_be);
1677 		/*
1678 		 * parse each status buffer and populate the information to
1679 		 * dp_tx_ppdu_info
1680 		 */
1681 		do {
1682 			tlv_status = hal_txmon_status_parse_tlv(
1683 					pdev->soc->hal_soc,
1684 					&tx_data_ppdu_info->hal_txmon,
1685 					&tx_prot_ppdu_info->hal_txmon,
1686 					tx_status_data,
1687 					tx_status_prot,
1688 					tx_tlv, status_frag);
1689 
1690 			dp_tx_mon_record_tlv(mon_pdev_be,
1691 					     &tx_data_ppdu_info->hal_txmon,
1692 					     &tx_prot_ppdu_info->hal_txmon);
1693 
1694 			status =
1695 				dp_tx_mon_update_ppdu_info_status(
1696 							pdev,
1697 							tx_data_ppdu_info,
1698 							tx_prot_ppdu_info,
1699 							tx_tlv,
1700 							status_frag,
1701 							tlv_status,
1702 							mon_desc_list_ref);
1703 
1704 			/* need api definition for hal_tx_status_get_next_tlv */
1705 			tx_tlv = hal_tx_status_get_next_tlv(tx_tlv,
1706 						mon_pdev->is_tlv_hdr_64_bit);
1707 			if ((tx_tlv - tx_tlv_start) >= end_offset)
1708 				break;
1709 		} while ((tx_tlv - tx_tlv_start) < end_offset);
1710 
1711 		/*
1712 		 * free status buffer after parsing
1713 		 * is status_frag mapped to mpdu if so make sure
1714 		 */
1715 		tx_mon_be->stats.status_buf_free++;
1716 		qdf_frag_free(status_frag);
1717 		tx_mon_be->frag_q_vec[cur_frag_q_idx].frag_buf = NULL;
1718 		tx_mon_be->frag_q_vec[cur_frag_q_idx].end_offset = 0;
1719 		cur_frag_q_idx = ++tx_mon_be->cur_frag_q_idx;
1720 
1721 		dp_tx_mon_record_index_update(mon_pdev_be);
1722 	}
1723 
1724 	/* clear the unreleased frag array */
1725 	dp_tx_mon_status_queue_free(pdev, tx_mon_be, mon_desc_list_ref);
1726 
1727 	if (TXMON_PPDU_HAL(tx_prot_ppdu_info, is_used)) {
1728 		if (qdf_unlikely(!TXMON_PPDU_COM(tx_prot_ppdu_info,
1729 						 chan_num))) {
1730 			/* update channel number, if not fetched properly */
1731 			TXMON_PPDU_COM(tx_prot_ppdu_info,
1732 				       chan_num) = mon_pdev->mon_chan_num;
1733 		}
1734 
1735 		if (qdf_unlikely(!TXMON_PPDU_COM(tx_prot_ppdu_info,
1736 						 chan_freq))) {
1737 			/* update channel frequency, if not fetched properly */
1738 			TXMON_PPDU_COM(tx_prot_ppdu_info,
1739 				       chan_freq) = mon_pdev->mon_chan_freq;
1740 		}
1741 
1742 		/*
1743 		 * add dp_tx_ppdu_info to pdev queue
1744 		 * for post processing
1745 		 *
1746 		 * TODO: add a threshold check and drop the ppdu info
1747 		 */
1748 		qdf_spin_lock_bh(&tx_mon_be->tx_mon_list_lock);
1749 		tx_mon_be->last_prot_ppdu_info =
1750 					tx_mon_be->tx_prot_ppdu_info;
1751 		STAILQ_INSERT_TAIL(&tx_mon_be->tx_ppdu_info_queue,
1752 				   tx_prot_ppdu_info,
1753 				   tx_ppdu_info_queue_elem);
1754 		tx_mon_be->tx_ppdu_info_list_depth++;
1755 
1756 		tx_mon_be->tx_prot_ppdu_info = NULL;
1757 		qdf_spin_unlock_bh(&tx_mon_be->tx_mon_list_lock);
1758 		schedule_wrq = true;
1759 	} else {
1760 		dp_tx_mon_free_ppdu_info(tx_prot_ppdu_info, tx_mon_be);
1761 		tx_mon_be->tx_prot_ppdu_info = NULL;
1762 		tx_prot_ppdu_info = NULL;
1763 	}
1764 
1765 	if (TXMON_PPDU_HAL(tx_data_ppdu_info, is_used)) {
1766 		if (qdf_unlikely(!TXMON_PPDU_COM(tx_data_ppdu_info,
1767 						 chan_num))) {
1768 			/* update channel number, if not fetched properly */
1769 			TXMON_PPDU_COM(tx_data_ppdu_info,
1770 				       chan_num) = mon_pdev->mon_chan_num;
1771 		}
1772 
1773 		if (qdf_unlikely(!TXMON_PPDU_COM(tx_data_ppdu_info,
1774 						 chan_freq))) {
1775 			/* update channel frequency, if not fetched properly */
1776 			TXMON_PPDU_COM(tx_data_ppdu_info,
1777 				       chan_freq) = mon_pdev->mon_chan_freq;
1778 		}
1779 
1780 		/*
1781 		 * add dp_tx_ppdu_info to pdev queue
1782 		 * for post processing
1783 		 *
1784 		 * TODO: add a threshold check and drop the ppdu info
1785 		 */
1786 		qdf_spin_lock_bh(&tx_mon_be->tx_mon_list_lock);
1787 		tx_mon_be->last_data_ppdu_info =
1788 					tx_mon_be->tx_data_ppdu_info;
1789 		STAILQ_INSERT_TAIL(&tx_mon_be->tx_ppdu_info_queue,
1790 				   tx_data_ppdu_info,
1791 				   tx_ppdu_info_queue_elem);
1792 		tx_mon_be->tx_ppdu_info_list_depth++;
1793 
1794 		tx_mon_be->tx_data_ppdu_info = NULL;
1795 		qdf_spin_unlock_bh(&tx_mon_be->tx_mon_list_lock);
1796 		schedule_wrq = true;
1797 	} else {
1798 		dp_tx_mon_free_ppdu_info(tx_data_ppdu_info, tx_mon_be);
1799 		tx_mon_be->tx_data_ppdu_info = NULL;
1800 		tx_data_ppdu_info = NULL;
1801 	}
1802 
1803 	if (schedule_wrq)
1804 		qdf_queue_work(NULL, tx_mon_be->post_ppdu_workqueue,
1805 			       &tx_mon_be->post_ppdu_work);
1806 
1807 	return QDF_STATUS_SUCCESS;
1808 }
1809 
1810 void dp_tx_mon_update_end_reason(struct dp_mon_pdev *mon_pdev,
1811 				 int ppdu_id, int end_reason)
1812 {
1813 	struct dp_mon_pdev_be *mon_pdev_be;
1814 	struct dp_pdev_tx_monitor_be *tx_mon_be;
1815 
1816 	mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
1817 	if (qdf_unlikely(!mon_pdev_be))
1818 		return;
1819 
1820 	tx_mon_be = &mon_pdev_be->tx_monitor_be;
1821 
1822 	tx_mon_be->be_end_reason_bitmap |= (1 << end_reason);
1823 }
1824 
1825 QDF_STATUS
1826 dp_tx_mon_process_status_tlv(struct dp_soc *soc,
1827 			     struct dp_pdev *pdev,
1828 			     struct hal_mon_desc *mon_ring_desc,
1829 			     qdf_frag_t status_frag,
1830 			     uint32_t end_offset,
1831 			     struct dp_tx_mon_desc_list *mon_desc_list_ref)
1832 {
1833 	struct dp_mon_pdev *mon_pdev;
1834 	struct dp_mon_pdev_be *mon_pdev_be;
1835 	struct dp_pdev_tx_monitor_be *tx_mon_be = NULL;
1836 	uint8_t last_frag_q_idx = 0;
1837 
1838 	/* sanity check */
1839 	if (qdf_unlikely(!pdev))
1840 		goto free_status_buffer;
1841 
1842 	mon_pdev = pdev->monitor_pdev;
1843 	if (qdf_unlikely(!mon_pdev))
1844 		goto free_status_buffer;
1845 
1846 	mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
1847 	if (qdf_unlikely(!mon_pdev_be))
1848 		goto free_status_buffer;
1849 
1850 	tx_mon_be = &mon_pdev_be->tx_monitor_be;
1851 
1852 	if (qdf_unlikely(tx_mon_be->last_frag_q_idx >
1853 			 MAX_STATUS_BUFFER_IN_PPDU)) {
1854 		dp_mon_err("status frag queue for a ppdu[%d] exceed %d\n",
1855 			   tx_mon_be->be_ppdu_id,
1856 			   MAX_STATUS_BUFFER_IN_PPDU);
1857 		dp_tx_mon_status_queue_free(pdev, tx_mon_be, mon_desc_list_ref);
1858 		goto free_status_buffer;
1859 	}
1860 
1861 	if (tx_mon_be->mode == TX_MON_BE_DISABLE &&
1862 	    !dp_lite_mon_is_tx_enabled(mon_pdev)) {
1863 		dp_tx_mon_status_queue_free(pdev, tx_mon_be,
1864 					    mon_desc_list_ref);
1865 		goto free_status_buffer;
1866 	}
1867 
1868 	if (tx_mon_be->be_ppdu_id != mon_ring_desc->ppdu_id &&
1869 	    tx_mon_be->last_frag_q_idx) {
1870 		if (tx_mon_be->be_end_reason_bitmap &
1871 		    (1 << HAL_MON_FLUSH_DETECTED)) {
1872 			tx_mon_be->stats.ppdu_info_drop_flush++;
1873 			dp_tx_mon_status_queue_free(pdev, tx_mon_be,
1874 						    mon_desc_list_ref);
1875 		} else if (tx_mon_be->be_end_reason_bitmap &
1876 			   (1 << HAL_MON_PPDU_TRUNCATED)) {
1877 			tx_mon_be->stats.ppdu_info_drop_trunc++;
1878 			dp_tx_mon_status_queue_free(pdev, tx_mon_be,
1879 						    mon_desc_list_ref);
1880 		} else {
1881 			dp_mon_err("End of ppdu not seen PID:%d cur_pid:%d idx:%d",
1882 				   tx_mon_be->be_ppdu_id,
1883 				   mon_ring_desc->ppdu_id,
1884 				   tx_mon_be->last_frag_q_idx);
1885 			/* schedule ppdu worth information */
1886 			dp_tx_mon_status_queue_free(pdev, tx_mon_be,
1887 						    mon_desc_list_ref);
1888 		}
1889 
1890 		/* reset end reason bitmap */
1891 		tx_mon_be->be_end_reason_bitmap = 0;
1892 		tx_mon_be->last_frag_q_idx = 0;
1893 		tx_mon_be->cur_frag_q_idx = 0;
1894 	}
1895 
1896 	tx_mon_be->be_ppdu_id = mon_ring_desc->ppdu_id;
1897 	tx_mon_be->be_end_reason_bitmap |= (1 << mon_ring_desc->end_reason);
1898 
1899 	last_frag_q_idx = tx_mon_be->last_frag_q_idx;
1900 
1901 	tx_mon_be->frag_q_vec[last_frag_q_idx].frag_buf = status_frag;
1902 	tx_mon_be->frag_q_vec[last_frag_q_idx].end_offset = end_offset;
1903 	tx_mon_be->last_frag_q_idx++;
1904 
1905 	if (mon_ring_desc->end_reason == HAL_MON_END_OF_PPDU) {
1906 		/* drop processing of tlv, if ppdu info list exceed threshold */
1907 		if ((tx_mon_be->defer_ppdu_info_list_depth +
1908 		     tx_mon_be->tx_ppdu_info_list_depth) >
1909 		    MAX_PPDU_INFO_LIST_DEPTH) {
1910 			tx_mon_be->stats.ppdu_info_drop_th++;
1911 			dp_tx_mon_status_queue_free(pdev, tx_mon_be,
1912 						    mon_desc_list_ref);
1913 			return QDF_STATUS_E_PENDING;
1914 		}
1915 
1916 		if (dp_tx_mon_process_tlv_2_0(pdev,
1917 					      mon_desc_list_ref) !=
1918 		    QDF_STATUS_SUCCESS)
1919 			dp_tx_mon_status_queue_free(pdev, tx_mon_be,
1920 						    mon_desc_list_ref);
1921 	}
1922 
1923 	return QDF_STATUS_SUCCESS;
1924 
1925 free_status_buffer:
1926 	dp_tx_mon_status_free_packet_buf(pdev, status_frag, end_offset,
1927 					 mon_desc_list_ref);
1928 	if (qdf_likely(tx_mon_be))
1929 		tx_mon_be->stats.status_buf_free++;
1930 
1931 	qdf_frag_free(status_frag);
1932 
1933 	return QDF_STATUS_E_NOMEM;
1934 }
1935 
1936 #endif
1937 
1938 #ifdef WLAN_TX_MON_CORE_DEBUG
1939 QDF_STATUS
1940 dp_tx_mon_process_status_tlv(struct dp_soc *soc,
1941 			     struct dp_pdev *pdev,
1942 			     struct hal_mon_desc *mon_ring_desc,
1943 			     qdf_frag_t status_frag,
1944 			     uint32_t end_offset,
1945 			     struct dp_tx_mon_desc_list *mon_desc_list_ref)
1946 {
1947 	struct dp_mon_pdev *mon_pdev;
1948 	struct dp_mon_pdev_be *mon_pdev_be;
1949 	struct dp_pdev_tx_monitor_be *tx_mon_be;
1950 
1951 	/* sanity check */
1952 	if (qdf_unlikely(!pdev))
1953 		return QDF_STATUS_E_INVAL;
1954 
1955 	mon_pdev = pdev->monitor_pdev;
1956 	if (qdf_unlikely(!mon_pdev))
1957 		return QDF_STATUS_E_INVAL;
1958 
1959 	mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
1960 	if (qdf_unlikely(!mon_pdev_be))
1961 		return QDF_STATUS_E_INVAL;
1962 
1963 	tx_mon_be = &mon_pdev_be->tx_monitor_be;
1964 
1965 	dp_tx_mon_status_free_packet_buf(pdev, status_frag, end_offset,
1966 					 mon_desc_list_ref);
1967 	tx_mon_be->stats.status_buf_free++;
1968 	qdf_frag_free(status_frag);
1969 
1970 	return QDF_STATUS_E_INVAL;
1971 }
1972 
1973 void dp_tx_mon_update_end_reason(struct dp_mon_pdev *mon_pdev,
1974 				 int ppdu_id, int end_reason)
1975 {
1976 }
1977 #endif
1978 
1979 #if defined(WLAN_TX_PKT_CAPTURE_ENH_BE) && defined(WLAN_PKT_CAPTURE_TX_2_0) && \
1980 	defined(BE_PKTLOG_SUPPORT)
1981 QDF_STATUS
1982 dp_tx_process_pktlog_be(struct dp_soc *soc, struct dp_pdev *pdev,
1983 			qdf_frag_t status_frag, uint32_t end_offset)
1984 {
1985 	struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
1986 	qdf_nbuf_t nbuf = NULL;
1987 	enum WDI_EVENT pktlog_mode = WDI_NO_VAL;
1988 	int frag_bytes;
1989 
1990 	if (!mon_pdev->pktlog_hybrid_mode)
1991 		return QDF_STATUS_E_INVAL;
1992 
1993 	nbuf = qdf_nbuf_alloc(soc->osdev, MAX_DUMMY_FRM_BODY, 0, 4, FALSE);
1994 	if (!nbuf)
1995 		return QDF_STATUS_E_NOMEM;
1996 
1997 	qdf_nbuf_add_rx_frag(status_frag, nbuf, 0,
1998 			     (end_offset + 1),
1999 			     0, true);
2000 
2001 	if (mon_pdev->pktlog_hybrid_mode)
2002 		pktlog_mode = WDI_EVENT_HYBRID_TX;
2003 
2004 	frag_bytes = qdf_nbuf_get_frag_len(nbuf, 0);
2005 	if (pktlog_mode != WDI_NO_VAL) {
2006 		dp_wdi_event_handler(pktlog_mode, soc,
2007 				     nbuf, HTT_INVALID_PEER,
2008 				     WDI_NO_VAL, pdev->pdev_id);
2009 	}
2010 	qdf_nbuf_free(nbuf);
2011 
2012 	return QDF_STATUS_SUCCESS;
2013 }
2014 #endif
2015