1 /*
2  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2023 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 
18 #include "qdf_types.h"
19 #include "hal_be_hw_headers.h"
20 #include "dp_types.h"
21 #include "hal_be_tx.h"
22 #include "hal_api.h"
23 #include "qdf_trace.h"
24 #include "hal_be_api_mon.h"
25 #include "dp_internal.h"
26 #include "qdf_mem.h"   /* qdf_mem_malloc,free */
27 #include "dp_mon.h"
28 #include <dp_mon_2.0.h>
29 #include <dp_tx_mon_2.0.h>
30 #include <dp_be.h>
31 #include <hal_be_api_mon.h>
32 #include <dp_mon_filter_2.0.h>
33 #include "dp_ratetable.h"
34 #ifdef QCA_SUPPORT_LITE_MONITOR
35 #include "dp_lite_mon.h"
36 #endif
37 
38 #define MAX_TX_MONITOR_STUCK 50
39 
40 #ifdef TXMON_DEBUG
41 /*
42  * dp_tx_mon_debug_statu() - API to display tx monitor status
43  * @tx_mon_be - pointer to dp_pdev_tx_monitor_be
44  * @work_done - tx monitor work done
45  *
46  * Return: void
47  */
48 static inline void
dp_tx_mon_debug_status(struct dp_pdev_tx_monitor_be * tx_mon_be,uint32_t work_done)49 dp_tx_mon_debug_status(struct dp_pdev_tx_monitor_be *tx_mon_be,
50 		       uint32_t work_done)
51 {
52 	if (tx_mon_be->mode && !work_done)
53 		tx_mon_be->stats.tx_mon_stuck++;
54 	else if (tx_mon_be->mode && work_done)
55 		tx_mon_be->stats.tx_mon_stuck = 0;
56 
57 	if (tx_mon_be->stats.tx_mon_stuck > MAX_TX_MONITOR_STUCK) {
58 		dp_mon_warn("Tx monitor block got stuck!!!!!");
59 		tx_mon_be->stats.tx_mon_stuck = 0;
60 		tx_mon_be->stats.total_tx_mon_stuck++;
61 	}
62 
63 	dp_mon_debug_rl("tx_ppdu_info[%u :D %u] STATUS[R %llu: F %llu] PKT_BUF[R %llu: F %llu : P %llu : S %llu]",
64 			tx_mon_be->tx_ppdu_info_list_depth,
65 			tx_mon_be->defer_ppdu_info_list_depth,
66 			tx_mon_be->stats.status_buf_recv,
67 			tx_mon_be->stats.status_buf_free,
68 			tx_mon_be->stats.pkt_buf_recv,
69 			tx_mon_be->stats.pkt_buf_free,
70 			tx_mon_be->stats.pkt_buf_processed,
71 			tx_mon_be->stats.pkt_buf_to_stack);
72 }
73 
74 #else
75 /*
76  * dp_tx_mon_debug_statu() - API to display tx monitor status
77  * @tx_mon_be - pointer to dp_pdev_tx_monitor_be
78  * @work_done - tx monitor work done
79  *
80  * Return: void
81  */
82 static inline void
dp_tx_mon_debug_status(struct dp_pdev_tx_monitor_be * tx_mon_be,uint32_t work_done)83 dp_tx_mon_debug_status(struct dp_pdev_tx_monitor_be *tx_mon_be,
84 		       uint32_t work_done)
85 {
86 	if (tx_mon_be->mode && !work_done)
87 		tx_mon_be->stats.tx_mon_stuck++;
88 	else if (tx_mon_be->mode && work_done)
89 		tx_mon_be->stats.tx_mon_stuck = 0;
90 
91 	if (tx_mon_be->stats.tx_mon_stuck > MAX_TX_MONITOR_STUCK) {
92 		dp_mon_warn("Tx monitor block got stuck!!!!!");
93 		tx_mon_be->stats.tx_mon_stuck = 0;
94 		tx_mon_be->stats.total_tx_mon_stuck++;
95 	}
96 }
97 #endif
98 
99 static inline uint32_t
dp_tx_mon_srng_process_2_0(struct dp_soc * soc,struct dp_intr * int_ctx,uint32_t mac_id,uint32_t quota)100 dp_tx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx,
101 			   uint32_t mac_id, uint32_t quota)
102 {
103 	struct dp_pdev *pdev = dp_get_pdev_for_lmac_id(soc, mac_id);
104 	void *tx_mon_dst_ring_desc;
105 	hal_soc_handle_t hal_soc;
106 	void *mon_dst_srng;
107 	struct dp_mon_pdev *mon_pdev;
108 	struct dp_mon_pdev_be *mon_pdev_be;
109 	uint32_t work_done = 0;
110 	struct dp_mon_soc *mon_soc = soc->monitor_soc;
111 	struct dp_mon_soc_be *mon_soc_be = dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
112 	struct dp_pdev_tx_monitor_be *tx_mon_be = NULL;
113 	struct dp_mon_desc_pool *tx_mon_desc_pool = &mon_soc_be->tx_desc_mon;
114 	struct dp_tx_mon_desc_list mon_desc_list;
115 	uint32_t replenish_cnt = 0;
116 
117 	if (!pdev) {
118 		dp_mon_err("%pK: pdev is null for mac_id = %d", soc, mac_id);
119 		return work_done;
120 	}
121 
122 	mon_pdev = pdev->monitor_pdev;
123 	mon_dst_srng = mon_soc_be->tx_mon_dst_ring[mac_id].hal_srng;
124 
125 	if (!mon_dst_srng || !hal_srng_initialized(mon_dst_srng)) {
126 		dp_mon_err("%pK: : HAL Monitor Destination Ring Init Failed -- %pK",
127 			   soc, mon_dst_srng);
128 		return work_done;
129 	}
130 
131 	mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
132 	if (qdf_unlikely(!mon_pdev_be))
133 		return work_done;
134 
135 	tx_mon_be = &mon_pdev_be->tx_monitor_be;
136 	hal_soc = soc->hal_soc;
137 
138 	qdf_assert((hal_soc && pdev));
139 
140 	qdf_spin_lock_bh(&mon_pdev->mon_lock);
141 	mon_desc_list.desc_list = NULL;
142 	mon_desc_list.tail = NULL;
143 	mon_desc_list.tx_mon_reap_cnt = 0;
144 
145 	if (qdf_unlikely(dp_srng_access_start(int_ctx, soc, mon_dst_srng))) {
146 		dp_mon_err("%s %d : HAL Mon Dest Ring access Failed -- %pK",
147 			   __func__, __LINE__, mon_dst_srng);
148 		qdf_spin_unlock_bh(&mon_pdev->mon_lock);
149 		return work_done;
150 	}
151 
152 	while (qdf_likely((tx_mon_dst_ring_desc =
153 		(void *)hal_srng_dst_peek(hal_soc, mon_dst_srng))
154 				&& quota--)) {
155 		struct hal_mon_desc hal_mon_tx_desc = {0};
156 		struct dp_mon_desc *mon_desc = NULL;
157 		qdf_frag_t status_frag = NULL;
158 		uint32_t end_offset = 0;
159 
160 		hal_be_get_mon_dest_status(soc->hal_soc,
161 					   tx_mon_dst_ring_desc,
162 					   &hal_mon_tx_desc);
163 
164 		if (hal_mon_tx_desc.empty_descriptor) {
165 			/* update stats counter */
166 			dp_mon_debug("P_ID:%d INIT:%d E_DESC:%d R_ID:%d L_CNT:%d  DROP[PPDU:%d MPDU:%d TLV:%d] E_O_PPDU:%d",
167 				    hal_mon_tx_desc.ppdu_id,
168 				    hal_mon_tx_desc.initiator,
169 				    hal_mon_tx_desc.empty_descriptor,
170 				    hal_mon_tx_desc.ring_id,
171 				    hal_mon_tx_desc.looping_count,
172 				    hal_mon_tx_desc.ppdu_drop_count,
173 				    hal_mon_tx_desc.mpdu_drop_count,
174 				    hal_mon_tx_desc.tlv_drop_count,
175 				    hal_mon_tx_desc.end_of_ppdu_dropped);
176 
177 			tx_mon_be->stats.ppdu_drop_cnt +=
178 				hal_mon_tx_desc.ppdu_drop_count;
179 			tx_mon_be->stats.mpdu_drop_cnt +=
180 				hal_mon_tx_desc.mpdu_drop_count;
181 			tx_mon_be->stats.tlv_drop_cnt +=
182 				hal_mon_tx_desc.tlv_drop_count;
183 			work_done++;
184 			hal_srng_dst_get_next(hal_soc, mon_dst_srng);
185 			continue;
186 		}
187 
188 		dp_mon_debug("P_ID:%d INIT:%d E_DESC:%d R_ID:%d L_CNT:%d BUF_ADDR: 0x%llx E_OFF: %d E_REA: %d",
189 			    hal_mon_tx_desc.ppdu_id,
190 			    hal_mon_tx_desc.initiator,
191 			    hal_mon_tx_desc.empty_descriptor,
192 			    hal_mon_tx_desc.ring_id,
193 			    hal_mon_tx_desc.looping_count,
194 			    hal_mon_tx_desc.buf_addr,
195 			    hal_mon_tx_desc.end_offset,
196 			    hal_mon_tx_desc.end_reason);
197 
198 		mon_desc = (struct dp_mon_desc *)(uintptr_t)(hal_mon_tx_desc.buf_addr);
199 		qdf_assert_always(mon_desc);
200 
201 		if (!mon_desc->unmapped) {
202 			qdf_mem_unmap_page(soc->osdev, mon_desc->paddr,
203 					   DP_MON_DATA_BUFFER_SIZE,
204 					   QDF_DMA_FROM_DEVICE);
205 			mon_desc->unmapped = 1;
206 		}
207 
208 		if (mon_desc->magic != DP_MON_DESC_MAGIC) {
209 			dp_mon_err("Invalid monitor descriptor");
210 			qdf_assert_always(0);
211 		}
212 
213 		end_offset = hal_mon_tx_desc.end_offset;
214 
215 		status_frag = (qdf_frag_t)(mon_desc->buf_addr);
216 		mon_desc->buf_addr = NULL;
217 		/* increment reap count */
218 		++mon_desc_list.tx_mon_reap_cnt;
219 
220 		/* add the mon_desc to free list */
221 		dp_mon_add_to_free_desc_list(&mon_desc_list.desc_list,
222 					     &mon_desc_list.tail, mon_desc);
223 
224 
225 		if (qdf_unlikely(!status_frag)) {
226 			dp_mon_debug("P_ID:%d INIT:%d E_DESC:%d R_ID:%d L_CNT:%d BUF_ADDR: 0x%llx E_OFF: %d E_REA: %d",
227 				     hal_mon_tx_desc.ppdu_id,
228 				     hal_mon_tx_desc.initiator,
229 				     hal_mon_tx_desc.empty_descriptor,
230 				     hal_mon_tx_desc.ring_id,
231 				     hal_mon_tx_desc.looping_count,
232 				     hal_mon_tx_desc.buf_addr,
233 				     hal_mon_tx_desc.end_offset,
234 				     hal_mon_tx_desc.end_reason);
235 
236 			work_done++;
237 			hal_srng_dst_get_next(hal_soc, mon_dst_srng);
238 			continue;
239 		}
240 
241 		tx_mon_be->stats.status_buf_recv++;
242 
243 		if ((hal_mon_tx_desc.end_reason == HAL_MON_FLUSH_DETECTED) ||
244 		    (hal_mon_tx_desc.end_reason == HAL_MON_PPDU_TRUNCATED)) {
245 			tx_mon_be->be_ppdu_id = hal_mon_tx_desc.ppdu_id;
246 
247 			dp_tx_mon_update_end_reason(mon_pdev,
248 						    hal_mon_tx_desc.ppdu_id,
249 						    hal_mon_tx_desc.end_reason);
250 			/* check and free packet buffer from status buffer */
251 			dp_tx_mon_status_free_packet_buf(pdev, status_frag,
252 							 end_offset,
253 							 &mon_desc_list);
254 
255 			tx_mon_be->stats.status_buf_free++;
256 			qdf_frag_free(status_frag);
257 
258 			work_done++;
259 			hal_srng_dst_get_next(hal_soc, mon_dst_srng);
260 			continue;
261 		}
262 
263 		dp_tx_process_pktlog_be(soc, pdev,
264 					status_frag,
265 					end_offset);
266 
267 		dp_tx_mon_process_status_tlv(soc, pdev,
268 					     &hal_mon_tx_desc,
269 					     status_frag,
270 					     end_offset,
271 					     &mon_desc_list);
272 
273 		work_done++;
274 		hal_srng_dst_get_next(hal_soc, mon_dst_srng);
275 	}
276 	dp_srng_access_end(int_ctx, soc, mon_dst_srng);
277 
278 	if (mon_desc_list.tx_mon_reap_cnt) {
279 		dp_mon_buffers_replenish(soc, &mon_soc_be->tx_mon_buf_ring,
280 					 tx_mon_desc_pool,
281 					 mon_desc_list.tx_mon_reap_cnt,
282 					 &mon_desc_list.desc_list,
283 					 &mon_desc_list.tail,
284 					 &replenish_cnt);
285 	}
286 	qdf_spin_unlock_bh(&mon_pdev->mon_lock);
287 	dp_mon_debug("mac_id: %d, work_done:%d tx_monitor_reap_cnt:%d",
288 		     mac_id, work_done, mon_desc_list.tx_mon_reap_cnt);
289 
290 	tx_mon_be->stats.total_tx_mon_reap_cnt += mon_desc_list.tx_mon_reap_cnt;
291 	tx_mon_be->stats.totat_tx_mon_replenish_cnt += replenish_cnt;
292 	dp_tx_mon_debug_status(tx_mon_be, work_done);
293 
294 	return work_done;
295 }
296 
297 uint32_t
dp_tx_mon_process_2_0(struct dp_soc * soc,struct dp_intr * int_ctx,uint32_t mac_id,uint32_t quota)298 dp_tx_mon_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx,
299 		      uint32_t mac_id, uint32_t quota)
300 {
301 	uint32_t work_done;
302 
303 	work_done = dp_tx_mon_srng_process_2_0(soc, int_ctx, mac_id, quota);
304 
305 	return work_done;
306 }
307 
308 void
dp_tx_mon_print_ring_stat_2_0(struct dp_pdev * pdev)309 dp_tx_mon_print_ring_stat_2_0(struct dp_pdev *pdev)
310 {
311 	struct dp_soc *soc = pdev->soc;
312 	struct dp_mon_soc *mon_soc = soc->monitor_soc;
313 	struct dp_mon_soc_be *mon_soc_be =
314 		dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
315 	int lmac_id;
316 
317 	lmac_id = dp_get_lmac_id_for_pdev_id(soc, 0, pdev->pdev_id);
318 	dp_print_ring_stat_from_hal(soc, &mon_soc_be->tx_mon_buf_ring,
319 				    TX_MONITOR_BUF);
320 	dp_print_ring_stat_from_hal(soc, &mon_soc_be->tx_mon_dst_ring[lmac_id],
321 				    TX_MONITOR_DST);
322 }
323 
324 void
dp_tx_mon_buf_desc_pool_deinit(struct dp_soc * soc)325 dp_tx_mon_buf_desc_pool_deinit(struct dp_soc *soc)
326 {
327 	struct dp_mon_soc *mon_soc = soc->monitor_soc;
328 	struct dp_mon_soc_be *mon_soc_be =
329 		dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
330 
331 	dp_mon_desc_pool_deinit(&mon_soc_be->tx_desc_mon);
332 }
333 
334 QDF_STATUS
dp_tx_mon_buf_desc_pool_init(struct dp_soc * soc)335 dp_tx_mon_buf_desc_pool_init(struct dp_soc *soc)
336 {
337 	struct dp_mon_soc *mon_soc = soc->monitor_soc;
338 	struct dp_mon_soc_be *mon_soc_be =
339 		dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
340 	uint32_t num_entries;
341 
342 	num_entries =
343 		wlan_cfg_get_dp_soc_tx_mon_buf_ring_size(soc->wlan_cfg_ctx);
344 
345 	return dp_mon_desc_pool_init(&mon_soc_be->tx_desc_mon, num_entries);
346 }
347 
dp_tx_mon_buf_desc_pool_free(struct dp_soc * soc)348 void dp_tx_mon_buf_desc_pool_free(struct dp_soc *soc)
349 {
350 	struct dp_mon_soc *mon_soc = soc->monitor_soc;
351 	struct dp_mon_soc_be *mon_soc_be =
352 		dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
353 
354 	if (mon_soc_be)
355 		dp_mon_desc_pool_free(soc, &mon_soc_be->tx_desc_mon,
356 				      DP_MON_TX_DESC_POOL_TYPE);
357 }
358 
dp_tx_mon_soc_init_2_0(struct dp_soc * soc)359 QDF_STATUS dp_tx_mon_soc_init_2_0(struct dp_soc *soc)
360 {
361 	struct dp_mon_soc *mon_soc = soc->monitor_soc;
362 	struct dp_mon_soc_be *mon_soc_be =
363 		dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
364 
365 	if (dp_srng_init(soc, &mon_soc_be->tx_mon_buf_ring,
366 			 TX_MONITOR_BUF, 0, 0)) {
367 		dp_mon_err("%pK: " RNG_ERR "tx_mon_buf_ring", soc);
368 		goto fail;
369 	}
370 
371 	if (dp_tx_mon_buf_desc_pool_init(soc)) {
372 		dp_mon_err("%pK: " RNG_ERR "tx mon desc pool init", soc);
373 		goto fail;
374 	}
375 
376 	return QDF_STATUS_SUCCESS;
377 fail:
378 	return QDF_STATUS_E_FAILURE;
379 }
380 
dp_tx_mon_soc_deinit_2_0(struct dp_soc * soc,uint32_t lmac_id)381 void dp_tx_mon_soc_deinit_2_0(struct dp_soc *soc, uint32_t lmac_id)
382 {
383 	struct dp_mon_soc *mon_soc = soc->monitor_soc;
384 	struct dp_mon_soc_be *mon_soc_be =
385 		dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
386 
387 	dp_tx_mon_buffers_free(soc);
388 	dp_tx_mon_buf_desc_pool_deinit(soc);
389 	dp_srng_deinit(soc, &mon_soc_be->tx_mon_buf_ring, TX_MONITOR_BUF, 0);
390 }
391 
392 QDF_STATUS
dp_tx_mon_buf_desc_pool_alloc(struct dp_soc * soc)393 dp_tx_mon_buf_desc_pool_alloc(struct dp_soc *soc)
394 {
395 	struct dp_mon_desc_pool *tx_mon_desc_pool;
396 	int entries;
397 	struct wlan_cfg_dp_soc_ctxt *soc_cfg_ctx;
398 	struct dp_mon_soc *mon_soc = soc->monitor_soc;
399 	struct dp_mon_soc_be *mon_soc_be =
400 		dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
401 
402 	soc_cfg_ctx = soc->wlan_cfg_ctx;
403 
404 	entries = wlan_cfg_get_dp_soc_tx_mon_buf_ring_size(soc_cfg_ctx);
405 
406 
407 	tx_mon_desc_pool = &mon_soc_be->tx_desc_mon;
408 
409 	qdf_print("%s:%d tx mon buf desc pool entries: %d", __func__, __LINE__, entries);
410 	return dp_mon_desc_pool_alloc(soc, DP_MON_TX_DESC_POOL_TYPE,
411 				      entries, tx_mon_desc_pool);
412 }
413 
414 void
dp_tx_mon_buffers_free(struct dp_soc * soc)415 dp_tx_mon_buffers_free(struct dp_soc *soc)
416 {
417 	struct dp_mon_desc_pool *tx_mon_desc_pool;
418 	struct dp_mon_soc *mon_soc = soc->monitor_soc;
419 	struct dp_mon_soc_be *mon_soc_be =
420 		dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
421 
422 	tx_mon_desc_pool = &mon_soc_be->tx_desc_mon;
423 
424 	dp_mon_pool_frag_unmap_and_free(soc, tx_mon_desc_pool);
425 }
426 
427 QDF_STATUS
dp_tx_mon_buffers_alloc(struct dp_soc * soc,uint32_t size)428 dp_tx_mon_buffers_alloc(struct dp_soc *soc, uint32_t size)
429 {
430 	struct dp_srng *mon_buf_ring;
431 	struct dp_mon_desc_pool *tx_mon_desc_pool;
432 	union dp_mon_desc_list_elem_t *desc_list = NULL;
433 	union dp_mon_desc_list_elem_t *tail = NULL;
434 	struct dp_mon_soc *mon_soc = soc->monitor_soc;
435 	struct dp_mon_soc_be *mon_soc_be =
436 		dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
437 
438 	mon_buf_ring = &mon_soc_be->tx_mon_buf_ring;
439 
440 	tx_mon_desc_pool = &mon_soc_be->tx_desc_mon;
441 
442 	return dp_mon_buffers_replenish(soc, mon_buf_ring,
443 					tx_mon_desc_pool,
444 					size,
445 					&desc_list, &tail, NULL);
446 }
447 
448 #ifdef WLAN_TX_PKT_CAPTURE_ENH_BE
449 
450 /*
451  * dp_tx_mon_nbuf_get_num_frag() - get total number of fragments
452  * @buf: Network buf instance
453  *
454  * Return: number of fragments
455  */
456 static inline
dp_tx_mon_nbuf_get_num_frag(qdf_nbuf_t nbuf)457 uint32_t dp_tx_mon_nbuf_get_num_frag(qdf_nbuf_t nbuf)
458 {
459 	uint32_t num_frag = 0;
460 
461 	if (qdf_unlikely(!nbuf))
462 		return num_frag;
463 
464 	num_frag = qdf_nbuf_get_nr_frags_in_fraglist(nbuf);
465 
466 	return num_frag;
467 }
468 
469 /*
470  * dp_tx_mon_free_usr_mpduq() - API to free user mpduq
471  * @tx_ppdu_info - pointer to tx_ppdu_info
472  * @usr_idx - user index
473  * @tx_mon_be - pointer to tx capture be
474  *
475  * Return: void
476  */
dp_tx_mon_free_usr_mpduq(struct dp_tx_ppdu_info * tx_ppdu_info,uint8_t usr_idx,struct dp_pdev_tx_monitor_be * tx_mon_be)477 void dp_tx_mon_free_usr_mpduq(struct dp_tx_ppdu_info *tx_ppdu_info,
478 			      uint8_t usr_idx,
479 			      struct dp_pdev_tx_monitor_be *tx_mon_be)
480 {
481 	qdf_nbuf_queue_t *mpdu_q;
482 	uint32_t num_frag = 0;
483 	qdf_nbuf_t buf = NULL;
484 
485 	if (qdf_unlikely(!tx_ppdu_info))
486 		return;
487 
488 	mpdu_q = &TXMON_PPDU_USR(tx_ppdu_info, usr_idx, mpdu_q);
489 
490 	while ((buf = qdf_nbuf_queue_remove(mpdu_q)) != NULL) {
491 		num_frag += dp_tx_mon_nbuf_get_num_frag(buf);
492 		qdf_nbuf_free(buf);
493 	}
494 	tx_mon_be->stats.pkt_buf_free += num_frag;
495 }
496 
497 /*
498  * dp_tx_mon_free_ppdu_info() - API to free dp_tx_ppdu_info
499  * @tx_ppdu_info - pointer to tx_ppdu_info
500  * @tx_mon_be - pointer to tx capture be
501  *
502  * Return: void
503  */
dp_tx_mon_free_ppdu_info(struct dp_tx_ppdu_info * tx_ppdu_info,struct dp_pdev_tx_monitor_be * tx_mon_be)504 void dp_tx_mon_free_ppdu_info(struct dp_tx_ppdu_info *tx_ppdu_info,
505 			      struct dp_pdev_tx_monitor_be *tx_mon_be)
506 {
507 	uint32_t user = 0;
508 
509 	for (; user < TXMON_PPDU_HAL(tx_ppdu_info, num_users); user++) {
510 		qdf_nbuf_queue_t *mpdu_q;
511 		uint32_t num_frag = 0;
512 		qdf_nbuf_t buf = NULL;
513 
514 		mpdu_q = &TXMON_PPDU_USR(tx_ppdu_info, user, mpdu_q);
515 
516 		while ((buf = qdf_nbuf_queue_remove(mpdu_q)) != NULL) {
517 			num_frag += dp_tx_mon_nbuf_get_num_frag(buf);
518 			qdf_nbuf_free(buf);
519 		}
520 		tx_mon_be->stats.pkt_buf_free += num_frag;
521 	}
522 
523 	TXMON_PPDU_HAL(tx_ppdu_info, is_used) = 0;
524 	qdf_mem_free(tx_ppdu_info);
525 }
526 
527 /*
528  * dp_tx_mon_get_ppdu_info() - API to allocate dp_tx_ppdu_info
529  * @pdev - pdev handle
530  * @type - type of ppdu_info data or protection
531  * @num_user - number user in a ppdu_info
532  * @ppdu_id - ppdu_id number
533  *
534  * Return: pointer to dp_tx_ppdu_info
535  */
dp_tx_mon_get_ppdu_info(struct dp_pdev * pdev,enum tx_ppdu_info_type type,uint8_t num_user,uint32_t ppdu_id)536 struct dp_tx_ppdu_info *dp_tx_mon_get_ppdu_info(struct dp_pdev *pdev,
537 						enum tx_ppdu_info_type type,
538 						uint8_t num_user,
539 						uint32_t ppdu_id)
540 {
541 	struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
542 	struct dp_mon_pdev_be *mon_pdev_be =
543 			dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
544 	struct dp_pdev_tx_monitor_be *tx_mon_be =
545 			&mon_pdev_be->tx_monitor_be;
546 	struct dp_tx_ppdu_info *tx_ppdu_info;
547 	size_t sz_ppdu_info = 0;
548 	uint8_t i;
549 
550 	/* allocate new tx_ppdu_info */
551 	sz_ppdu_info = (sizeof(struct dp_tx_ppdu_info) +
552 			(sizeof(struct mon_rx_user_status) * num_user));
553 
554 	tx_ppdu_info = (struct dp_tx_ppdu_info *)qdf_mem_malloc(sz_ppdu_info);
555 	if (!tx_ppdu_info) {
556 		dp_mon_err("allocation of tx_ppdu_info type[%d] failed!!!",
557 			   type);
558 		return NULL;
559 	}
560 
561 	TXMON_PPDU_HAL(tx_ppdu_info, is_used) = 0;
562 	TXMON_PPDU_HAL(tx_ppdu_info, num_users) = num_user;
563 	TXMON_PPDU_HAL(tx_ppdu_info, ppdu_id) = ppdu_id;
564 	TXMON_PPDU(tx_ppdu_info, ppdu_id) = ppdu_id;
565 
566 	for (i = 0; i < num_user; i++) {
567 		qdf_nbuf_queue_t *mpdu_q;
568 
569 		mpdu_q = &TXMON_PPDU_USR(tx_ppdu_info, i, mpdu_q);
570 		qdf_nbuf_queue_init(mpdu_q);
571 	}
572 
573 	/* assign tx_ppdu_info to monitor pdev for reference */
574 	if (type == TX_PROT_PPDU_INFO) {
575 		qdf_mem_zero(&tx_mon_be->prot_status_info, sizeof(struct hal_tx_status_info));
576 		tx_mon_be->tx_prot_ppdu_info = tx_ppdu_info;
577 		TXMON_PPDU_HAL(tx_ppdu_info, is_data) = 0;
578 	} else {
579 		qdf_mem_zero(&tx_mon_be->data_status_info, sizeof(struct hal_tx_status_info));
580 		tx_mon_be->tx_data_ppdu_info = tx_ppdu_info;
581 		TXMON_PPDU_HAL(tx_ppdu_info, is_data) = 1;
582 	}
583 
584 	return tx_ppdu_info;
585 }
586 
587 /*
588  * dp_print_pdev_tx_monitor_stats_2_0: print tx capture stats
589  * @pdev: DP PDEV handle
590  *
591  * return: void
592  */
dp_print_pdev_tx_monitor_stats_2_0(struct dp_pdev * pdev)593 void dp_print_pdev_tx_monitor_stats_2_0(struct dp_pdev *pdev)
594 {
595 	struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
596 	struct dp_mon_pdev_be *mon_pdev_be =
597 			dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
598 	struct dp_pdev_tx_monitor_be *tx_mon_be =
599 			&mon_pdev_be->tx_monitor_be;
600 	struct dp_tx_monitor_drop_stats stats = {0};
601 
602 	qdf_mem_copy(&stats, &tx_mon_be->stats,
603 		     sizeof(struct dp_tx_monitor_drop_stats));
604 
605 	/* TX monitor stats needed for beryllium */
606 	DP_PRINT_STATS("\n\tTX Capture BE stats mode[%d]:", tx_mon_be->mode);
607 	DP_PRINT_STATS("\tbuffer pending : %u", tx_mon_be->last_frag_q_idx);
608 	DP_PRINT_STATS("\treplenish count: %llu",
609 		       stats.totat_tx_mon_replenish_cnt);
610 	DP_PRINT_STATS("\treap count     : %llu", stats.total_tx_mon_reap_cnt);
611 	DP_PRINT_STATS("\tmonitor stuck  : %u", stats.total_tx_mon_stuck);
612 	DP_PRINT_STATS("\tStatus buffer");
613 	DP_PRINT_STATS("\t\treceived  : %llu", stats.status_buf_recv);
614 	DP_PRINT_STATS("\t\tfree      : %llu", stats.status_buf_free);
615 	DP_PRINT_STATS("\tPacket buffer");
616 	DP_PRINT_STATS("\t\treceived  : %llu", stats.pkt_buf_recv);
617 	DP_PRINT_STATS("\t\tfree      : %llu", stats.pkt_buf_free);
618 	DP_PRINT_STATS("\t\tprocessed : %llu", stats.pkt_buf_processed);
619 	DP_PRINT_STATS("\t\tto stack  : %llu", stats.pkt_buf_to_stack);
620 	DP_PRINT_STATS("\tppdu info");
621 	DP_PRINT_STATS("\t\tthreshold : %llu", stats.ppdu_info_drop_th);
622 	DP_PRINT_STATS("\t\tflush     : %llu", stats.ppdu_info_drop_flush);
623 	DP_PRINT_STATS("\t\ttruncated : %llu", stats.ppdu_info_drop_trunc);
624 	DP_PRINT_STATS("\tDrop stats");
625 	DP_PRINT_STATS("\t\tppdu drop : %llu", stats.ppdu_drop_cnt);
626 	DP_PRINT_STATS("\t\tmpdu drop : %llu", stats.mpdu_drop_cnt);
627 	DP_PRINT_STATS("\t\ttlv drop : %llu", stats.tlv_drop_cnt);
628 }
629 
630 #ifdef QCA_SUPPORT_LITE_MONITOR
dp_lite_mon_free_tx_peers(struct dp_pdev * pdev)631 static void dp_lite_mon_free_tx_peers(struct dp_pdev *pdev)
632 {
633 	struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
634 	struct dp_mon_pdev_be *mon_pdev_be =
635 			dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
636 	struct dp_lite_mon_tx_config *lite_mon_tx_config;
637 
638 	lite_mon_tx_config = mon_pdev_be->lite_mon_tx_config;
639 	qdf_spin_lock_bh(&lite_mon_tx_config->lite_mon_tx_lock);
640 	dp_lite_mon_free_peers(pdev, &lite_mon_tx_config->tx_config);
641 	qdf_spin_unlock_bh(&lite_mon_tx_config->lite_mon_tx_lock);
642 }
643 #else
dp_lite_mon_free_tx_peers(struct dp_pdev * pdev)644 static void dp_lite_mon_free_tx_peers(struct dp_pdev *pdev)
645 {
646 }
647 #endif
648 
649 /*
650  * dp_config_enh_tx_monitor_2_0()- API to enable/disable enhanced tx capture
651  * @pdev_handle: DP_PDEV handle
652  * @val: user provided value
653  *
654  * Return: QDF_STATUS
655  */
656 QDF_STATUS
dp_config_enh_tx_monitor_2_0(struct dp_pdev * pdev,uint8_t val)657 dp_config_enh_tx_monitor_2_0(struct dp_pdev *pdev, uint8_t val)
658 {
659 	struct wlan_cfg_dp_soc_ctxt *soc_cfg_ctx;
660 	struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
661 	struct dp_mon_pdev_be *mon_pdev_be =
662 			dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
663 	struct dp_pdev_tx_monitor_be *tx_mon_be =
664 			&mon_pdev_be->tx_monitor_be;
665 	struct dp_soc *soc = pdev->soc;
666 	uint16_t num_of_buffers;
667 	QDF_STATUS status;
668 
669 	soc_cfg_ctx = soc->wlan_cfg_ctx;
670 	switch (val) {
671 	case TX_MON_BE_DISABLE:
672 	{
673 		tx_mon_be->mode = TX_MON_BE_DISABLE;
674 		mon_pdev_be->tx_mon_mode = 0;
675 		mon_pdev_be->tx_mon_filter_length = DMA_LENGTH_64B;
676 		/* Free any peers that were added for tx peer filtering */
677 		dp_lite_mon_free_tx_peers(pdev);
678 		break;
679 	}
680 	case TX_MON_BE_FULL_CAPTURE:
681 	{
682 		num_of_buffers = wlan_cfg_get_dp_soc_tx_mon_buf_ring_size(soc_cfg_ctx);
683 		status = dp_vdev_set_monitor_mode_buf_rings_tx_2_0(pdev,
684 								   num_of_buffers);
685 		if (status != QDF_STATUS_SUCCESS) {
686 			dp_mon_err("Tx monitor buffer allocation failed");
687 			return status;
688 		}
689 		qdf_mem_zero(&tx_mon_be->stats,
690 			     sizeof(struct dp_tx_monitor_drop_stats));
691 		tx_mon_be->last_tsft = 0;
692 		tx_mon_be->last_ppdu_timestamp = 0;
693 		tx_mon_be->mode = TX_MON_BE_FULL_CAPTURE;
694 		mon_pdev_be->tx_mon_mode = 1;
695 		mon_pdev_be->tx_mon_filter_length = DEFAULT_DMA_LENGTH;
696 		break;
697 	}
698 	case TX_MON_BE_PEER_FILTER:
699 	{
700 		status = dp_vdev_set_monitor_mode_buf_rings_tx_2_0(pdev,
701 								   DP_MON_RING_FILL_LEVEL_DEFAULT);
702 		if (status != QDF_STATUS_SUCCESS) {
703 			dp_mon_err("Tx monitor buffer allocation failed");
704 			return status;
705 		}
706 		tx_mon_be->mode = TX_MON_BE_PEER_FILTER;
707 		mon_pdev_be->tx_mon_mode = 2;
708 		mon_pdev_be->tx_mon_filter_length = DMA_LENGTH_256B;
709 		break;
710 	}
711 	default:
712 	{
713 		return QDF_STATUS_E_INVAL;
714 	}
715 	}
716 
717 	dp_mon_info("Tx monitor mode:%d mon_mode_flag:%d config_length:%d",
718 		    tx_mon_be->mode, mon_pdev_be->tx_mon_mode,
719 		    mon_pdev_be->tx_mon_filter_length);
720 
721 	dp_mon_filter_setup_tx_mon_mode(pdev);
722 	dp_tx_mon_filter_update(pdev);
723 
724 	return QDF_STATUS_SUCCESS;
725 }
726 
727 /*
728  * dp_peer_set_tx_capture_enabled_2_0() -  add tx monitor peer filter
729  * @pdev: Datapath PDEV handle
730  * @peer: Datapath PEER handle
731  * @is_tx_pkt_cap_enable: flag for tx capture enable/disable
732  * @peer_mac: peer mac address
733  *
734  * Return: status
735  */
dp_peer_set_tx_capture_enabled_2_0(struct dp_pdev * pdev_handle,struct dp_peer * peer_handle,uint8_t is_tx_pkt_cap_enable,uint8_t * peer_mac)736 QDF_STATUS dp_peer_set_tx_capture_enabled_2_0(struct dp_pdev *pdev_handle,
737 					      struct dp_peer *peer_handle,
738 					      uint8_t is_tx_pkt_cap_enable,
739 					      uint8_t *peer_mac)
740 {
741 	return QDF_STATUS_SUCCESS;
742 }
743 
744 #ifdef QCA_SUPPORT_LITE_MONITOR
dp_fill_lite_mon_vdev(struct cdp_tx_indication_info * tx_cap_info,struct dp_mon_pdev_be * mon_pdev_be)745 static void dp_fill_lite_mon_vdev(struct cdp_tx_indication_info *tx_cap_info,
746 				  struct dp_mon_pdev_be *mon_pdev_be)
747 {
748 	struct dp_lite_mon_config *config;
749 	struct dp_vdev *lite_mon_vdev;
750 
751 	config = &mon_pdev_be->lite_mon_tx_config->tx_config;
752 	lite_mon_vdev = config->lite_mon_vdev;
753 
754 	if (lite_mon_vdev)
755 		tx_cap_info->osif_vdev = lite_mon_vdev->osif_vdev;
756 }
757 
758 /**
759  * dp_lite_mon_filter_ppdu() - Filter frames at ppdu level
760  * @mpdu_count: mpdu count in the nbuf queue
761  * @level: Lite monitor filter level
762  *
763  * Return: QDF_STATUS
764  */
765 static inline QDF_STATUS
dp_lite_mon_filter_ppdu(uint8_t mpdu_count,uint8_t level)766 dp_lite_mon_filter_ppdu(uint8_t mpdu_count, uint8_t level)
767 {
768 	if (level == CDP_LITE_MON_LEVEL_PPDU && mpdu_count > 1)
769 		return QDF_STATUS_E_CANCELED;
770 
771 	return QDF_STATUS_SUCCESS;
772 }
773 
774 /**
775  * dp_lite_mon_filter_peer() - filter frames with peer
776  * @config: Lite monitor configuration
777  * @wh: Pointer to ieee80211_frame
778  *
779  * Return: QDF_STATUS
780  */
781 static inline QDF_STATUS
dp_lite_mon_filter_peer(struct dp_lite_mon_tx_config * config,struct ieee80211_frame_min_one * wh)782 dp_lite_mon_filter_peer(struct dp_lite_mon_tx_config *config,
783 			struct ieee80211_frame_min_one *wh)
784 {
785 	struct dp_lite_mon_peer *peer;
786 
787 	/* Return here if sw peer filtering is not required or if peer count
788 	 * is zero
789 	 */
790 	if (!config->sw_peer_filtering || !config->tx_config.peer_count)
791 		return QDF_STATUS_SUCCESS;
792 
793 	TAILQ_FOREACH(peer, &config->tx_config.peer_list, peer_list_elem) {
794 		if (!qdf_mem_cmp(&peer->peer_mac.raw[0],
795 				 &wh->i_addr1[0], QDF_MAC_ADDR_SIZE)) {
796 			return QDF_STATUS_SUCCESS;
797 		}
798 	}
799 
800 	return QDF_STATUS_E_ABORTED;
801 }
802 
803 /**
804  * dp_lite_mon_filter_subtype() - filter frames with subtype
805  * @config: Lite monitor configuration
806  * @wh: Pointer to ieee80211_frame
807  *
808  * Return: QDF_STATUS
809  */
810 static inline QDF_STATUS
dp_lite_mon_filter_subtype(struct dp_lite_mon_tx_config * config,struct ieee80211_frame_min_one * wh)811 dp_lite_mon_filter_subtype(struct dp_lite_mon_tx_config *config,
812 			   struct ieee80211_frame_min_one *wh)
813 {
814 	uint16_t mgmt_filter, ctrl_filter, data_filter, type, subtype;
815 	uint8_t is_mcast = 0;
816 
817 	/* Return here if subtype filtering is not required */
818 	if (!config->subtype_filtering)
819 		return QDF_STATUS_SUCCESS;
820 
821 	mgmt_filter = config->tx_config.mgmt_filter[DP_MON_FRM_FILTER_MODE_FP];
822 	ctrl_filter = config->tx_config.ctrl_filter[DP_MON_FRM_FILTER_MODE_FP];
823 	data_filter = config->tx_config.data_filter[DP_MON_FRM_FILTER_MODE_FP];
824 
825 	type = (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK);
826 	subtype = ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) >>
827 		IEEE80211_FC0_SUBTYPE_SHIFT);
828 
829 	switch (type) {
830 	case QDF_IEEE80211_FC0_TYPE_MGT:
831 		if (mgmt_filter >> subtype & 0x1)
832 			return QDF_STATUS_SUCCESS;
833 		else
834 			return QDF_STATUS_E_ABORTED;
835 	case QDF_IEEE80211_FC0_TYPE_CTL:
836 		if (ctrl_filter >> subtype & 0x1)
837 			return QDF_STATUS_SUCCESS;
838 		else
839 			return QDF_STATUS_E_ABORTED;
840 	case QDF_IEEE80211_FC0_TYPE_DATA:
841 		is_mcast = DP_FRAME_IS_MULTICAST(wh->i_addr1);
842 		if ((is_mcast && (data_filter & FILTER_DATA_MCAST)) ||
843 		    (!is_mcast && (data_filter & FILTER_DATA_UCAST)))
844 			return QDF_STATUS_SUCCESS;
845 		return QDF_STATUS_E_ABORTED;
846 	default:
847 		return QDF_STATUS_E_INVAL;
848 	}
849 }
850 
851 /**
852  * dp_lite_mon_filter_peer_subtype() - filter frames with subtype and peer
853  * @config: Lite monitor configuration
854  * @buf: Pointer to nbuf
855  *
856  * Return: QDF_STATUS
857  */
858 static inline QDF_STATUS
dp_lite_mon_filter_peer_subtype(struct dp_lite_mon_tx_config * config,qdf_nbuf_t buf)859 dp_lite_mon_filter_peer_subtype(struct dp_lite_mon_tx_config *config,
860 				qdf_nbuf_t buf)
861 {
862 	struct ieee80211_frame_min_one *wh;
863 	qdf_nbuf_t nbuf;
864 	QDF_STATUS ret;
865 
866 	/* Return here if subtype and peer filtering is not required */
867 	if (!config->subtype_filtering && !config->sw_peer_filtering &&
868 	    !config->tx_config.peer_count)
869 		return QDF_STATUS_SUCCESS;
870 
871 	if (dp_tx_mon_nbuf_get_num_frag(buf)) {
872 		wh = (struct ieee80211_frame_min_one *)qdf_nbuf_get_frag_addr(buf, 0);
873 	} else {
874 		nbuf = qdf_nbuf_get_ext_list(buf);
875 		if (nbuf)
876 			wh = (struct ieee80211_frame_min_one *)qdf_nbuf_data(nbuf);
877 		else
878 			return QDF_STATUS_E_INVAL;
879 	}
880 
881 	ret = dp_lite_mon_filter_subtype(config, wh);
882 	if (ret)
883 		return ret;
884 
885 	ret = dp_lite_mon_filter_peer(config, wh);
886 	if (ret)
887 		return ret;
888 
889 	return QDF_STATUS_SUCCESS;
890 }
891 
892 /**
893  * dp_tx_lite_mon_filtering() - Additional filtering for lite monitor
894  * @pdev: Pointer to physical device
895  * @tx_ppdu_info: pointer to dp_tx_ppdu_info structure
896  * @buf: qdf nbuf structure of buffer
897  * @mpdu_count: mpdu count in the nbuf queue
898  *
899  * Return: QDF_STATUS
900  */
901 static inline QDF_STATUS
dp_tx_lite_mon_filtering(struct dp_pdev * pdev,struct dp_tx_ppdu_info * tx_ppdu_info,qdf_nbuf_t buf,int mpdu_count)902 dp_tx_lite_mon_filtering(struct dp_pdev *pdev,
903 			 struct dp_tx_ppdu_info *tx_ppdu_info,
904 			 qdf_nbuf_t buf, int mpdu_count)
905 {
906 	struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
907 	struct dp_mon_pdev_be *mon_pdev_be =
908 		dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
909 	struct dp_lite_mon_tx_config *config =
910 		mon_pdev_be->lite_mon_tx_config;
911 	QDF_STATUS ret;
912 
913 	if (!dp_lite_mon_is_tx_enabled(mon_pdev) &&
914 	    !config->tx_config.peer_count)
915 		return QDF_STATUS_SUCCESS;
916 
917 	/* PPDU level filtering */
918 	ret = dp_lite_mon_filter_ppdu(mpdu_count, config->tx_config.level);
919 	if (ret)
920 		return ret;
921 
922 	/* Subtype and peer filtering */
923 	ret = dp_lite_mon_filter_peer_subtype(config, buf);
924 	if (ret)
925 		return ret;
926 
927 	return QDF_STATUS_SUCCESS;
928 }
929 
930 #else
dp_fill_lite_mon_vdev(struct cdp_tx_indication_info * tx_cap_info,struct dp_mon_pdev_be * mon_pdev_be)931 static void dp_fill_lite_mon_vdev(struct cdp_tx_indication_info *tx_cap_info,
932 				  struct dp_mon_pdev_be *mon_pdev_be)
933 {
934 }
935 
936 /**
937  * dp_tx_lite_mon_filtering() - Additional filtering for lite monitor
938  * @pdev: Pointer to physical device
939  * @tx_ppdu_info: pointer to dp_tx_ppdu_info structure
940  * @buf: qdf nbuf structure of buffer
941  * @mpdu_count: mpdu count in the nbuf queue
942  *
943  * Return: QDF_STATUS
944  */
945 static inline QDF_STATUS
dp_tx_lite_mon_filtering(struct dp_pdev * pdev,struct dp_tx_ppdu_info * tx_ppdu_info,qdf_nbuf_t buf,int mpdu_count)946 dp_tx_lite_mon_filtering(struct dp_pdev *pdev,
947 			 struct dp_tx_ppdu_info *tx_ppdu_info,
948 			 qdf_nbuf_t buf, int mpdu_count)
949 {
950 	return QDF_STATUS_SUCCESS;
951 }
952 #endif
953 
954 #ifdef WLAN_FEATURE_LOCAL_PKT_CAPTURE
955 /**
956  * dp_tx_mon_lpc_type_filtering() - Additional filtering for lpc
957  * @pdev: Pointer to physical device
958  * @tx_ppdu_info: pointer to dp_tx_ppdu_info structure
959  * @buf: qdf nbuf structure of buffer
960  *
961  * Return: QDF_STATUS
962  */
963 static inline QDF_STATUS
dp_tx_mon_lpc_type_filtering(struct dp_pdev * pdev,struct dp_tx_ppdu_info * tx_ppdu_info,qdf_nbuf_t buf)964 dp_tx_mon_lpc_type_filtering(struct dp_pdev *pdev,
965 			     struct dp_tx_ppdu_info *tx_ppdu_info,
966 			     qdf_nbuf_t buf)
967 {
968 	struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
969 	qdf_nbuf_t nbuf;
970 	struct ieee80211_frame_min_one *wh;
971 	uint16_t mgmt_filter, ctrl_filter, data_filter, type;
972 
973 	if (qdf_unlikely(!IS_LOCAL_PKT_CAPTURE_RUNNING(mon_pdev,
974 			is_local_pkt_capture_running)))
975 		return QDF_STATUS_E_ABORTED;
976 
977 	if (dp_tx_mon_nbuf_get_num_frag(buf)) {
978 		wh = (struct ieee80211_frame_min_one *)qdf_nbuf_get_frag_addr(buf, 0);
979 	} else {
980 		nbuf = qdf_nbuf_get_ext_list(buf);
981 		if (nbuf)
982 			wh = (struct ieee80211_frame_min_one *)qdf_nbuf_data(nbuf);
983 		else
984 			return QDF_STATUS_E_ABORTED;
985 	}
986 
987 	mgmt_filter = mon_pdev->fp_mgmt_filter;
988 	ctrl_filter = mon_pdev->fp_ctrl_filter;
989 	data_filter = mon_pdev->fp_data_filter;
990 
991 	type = (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK);
992 
993 	switch (type) {
994 	case QDF_IEEE80211_FC0_TYPE_MGT:
995 		return mgmt_filter ? QDF_STATUS_SUCCESS : QDF_STATUS_E_ABORTED;
996 	case QDF_IEEE80211_FC0_TYPE_CTL:
997 		return ctrl_filter ? QDF_STATUS_SUCCESS : QDF_STATUS_E_ABORTED;
998 	case QDF_IEEE80211_FC0_TYPE_DATA:
999 		return data_filter ? QDF_STATUS_SUCCESS : QDF_STATUS_E_ABORTED;
1000 	default:
1001 		return QDF_STATUS_E_ABORTED;
1002 	}
1003 
1004 	return QDF_STATUS_SUCCESS;
1005 }
1006 
1007 static int
dp_tx_handle_local_pkt_capture(struct dp_pdev * pdev,qdf_nbuf_t nbuf)1008 dp_tx_handle_local_pkt_capture(struct dp_pdev *pdev, qdf_nbuf_t nbuf)
1009 {
1010 	struct dp_mon_vdev *mon_vdev;
1011 	struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
1012 
1013 	if (!mon_pdev->mvdev) {
1014 		dp_mon_err("Monitor vdev is NULL !!");
1015 		return 1;
1016 	}
1017 
1018 	mon_vdev = mon_pdev->mvdev->monitor_vdev;
1019 
1020 	if (mon_vdev && mon_vdev->osif_rx_mon)
1021 		mon_vdev->osif_rx_mon(mon_pdev->mvdev->osif_vdev, nbuf, NULL);
1022 
1023 	return 0;
1024 }
1025 #else
1026 static int
dp_tx_handle_local_pkt_capture(struct dp_pdev * pdev,qdf_nbuf_t nbuf)1027 dp_tx_handle_local_pkt_capture(struct dp_pdev *pdev, qdf_nbuf_t nbuf)
1028 {
1029 	return 0;
1030 }
1031 
1032 static inline QDF_STATUS
dp_tx_mon_lpc_type_filtering(struct dp_pdev * pdev,struct dp_tx_ppdu_info * tx_ppdu_info,qdf_nbuf_t buf)1033 dp_tx_mon_lpc_type_filtering(struct dp_pdev *pdev,
1034 			     struct dp_tx_ppdu_info *tx_ppdu_info,
1035 			     qdf_nbuf_t buf)
1036 {
1037 	return QDF_STATUS_SUCCESS;
1038 }
1039 
1040 #endif
1041 
1042 /**
1043  * dp_tx_mon_send_to_stack() - API to send to stack
1044  * @pdev: pdev Handle
1045  * @mpdu: pointer to mpdu
1046  * @num_frag: number of frag in mpdu
1047  * @ppdu_id: ppdu id of the mpdu
1048  *
1049  * Return: void
1050  */
1051 static void
dp_tx_mon_send_to_stack(struct dp_pdev * pdev,qdf_nbuf_t mpdu,uint32_t num_frag,uint32_t ppdu_id)1052 dp_tx_mon_send_to_stack(struct dp_pdev *pdev, qdf_nbuf_t mpdu,
1053 			uint32_t num_frag, uint32_t ppdu_id)
1054 {
1055 	struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
1056 	struct dp_mon_pdev_be *mon_pdev_be =
1057 			dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
1058 	struct dp_pdev_tx_monitor_be *tx_mon_be =
1059 			&mon_pdev_be->tx_monitor_be;
1060 	struct cdp_tx_indication_info tx_capture_info = {0};
1061 
1062 	tx_mon_be->stats.pkt_buf_to_stack += num_frag;
1063 
1064 	tx_capture_info.radiotap_done = 1;
1065 	tx_capture_info.mpdu_nbuf = mpdu;
1066 	tx_capture_info.mpdu_info.ppdu_id = ppdu_id;
1067 
1068 	if (qdf_unlikely(IS_LOCAL_PKT_CAPTURE_RUNNING(mon_pdev,
1069 			is_local_pkt_capture_running))) {
1070 		int ret = dp_tx_handle_local_pkt_capture(pdev, mpdu);
1071 
1072 		/*
1073 		 * On error, free the memory here,
1074 		 * otherwise it will be freed by the network stack
1075 		 */
1076 		if (ret)
1077 			qdf_nbuf_free(mpdu);
1078 		return;
1079 	} else if (!dp_lite_mon_is_tx_enabled(mon_pdev)) {
1080 		dp_wdi_event_handler(WDI_EVENT_TX_PKT_CAPTURE,
1081 				     pdev->soc,
1082 				     &tx_capture_info,
1083 				     HTT_INVALID_PEER,
1084 				     WDI_NO_VAL,
1085 				     pdev->pdev_id);
1086 	} else {
1087 		dp_fill_lite_mon_vdev(&tx_capture_info, mon_pdev_be);
1088 		dp_wdi_event_handler(WDI_EVENT_LITE_MON_TX,
1089 				     pdev->soc,
1090 				     &tx_capture_info,
1091 				     HTT_INVALID_PEER,
1092 				     WDI_NO_VAL,
1093 				     pdev->pdev_id);
1094 	}
1095 	if (tx_capture_info.mpdu_nbuf)
1096 		qdf_nbuf_free(tx_capture_info.mpdu_nbuf);
1097 }
1098 
1099 /**
1100  * dp_tx_mon_send_per_usr_mpdu() - API to send per usr mpdu to stack
1101  * @pdev: pdev Handle
1102  * @ppdu_info: pointer to dp_tx_ppdu_info
1103  * @user_idx: current user index
1104  *
1105  * Return: void
1106  */
1107 static void
dp_tx_mon_send_per_usr_mpdu(struct dp_pdev * pdev,struct dp_tx_ppdu_info * ppdu_info,uint8_t user_idx)1108 dp_tx_mon_send_per_usr_mpdu(struct dp_pdev *pdev,
1109 			    struct dp_tx_ppdu_info *ppdu_info,
1110 			    uint8_t user_idx)
1111 {
1112 	qdf_nbuf_queue_t *usr_mpdu_q = NULL;
1113 	qdf_nbuf_t buf = NULL;
1114 	uint8_t mpdu_count = 0;
1115 
1116 	usr_mpdu_q = &TXMON_PPDU_USR(ppdu_info, user_idx, mpdu_q);
1117 
1118 	while ((buf = qdf_nbuf_queue_remove(usr_mpdu_q)) != NULL) {
1119 		uint32_t num_frag = dp_tx_mon_nbuf_get_num_frag(buf);
1120 
1121 		ppdu_info->hal_txmon.rx_status.rx_user_status =
1122 				&ppdu_info->hal_txmon.rx_user_status[user_idx];
1123 
1124 		if (dp_tx_lite_mon_filtering(pdev, ppdu_info, buf,
1125 					     ++mpdu_count) ||
1126 		    dp_tx_mon_lpc_type_filtering(pdev, ppdu_info, buf)) {
1127 			qdf_nbuf_free(buf);
1128 			continue;
1129 		}
1130 
1131 		qdf_nbuf_update_radiotap(&ppdu_info->hal_txmon.rx_status,
1132 					 buf, qdf_nbuf_headroom(buf));
1133 
1134 		dp_tx_mon_send_to_stack(pdev, buf, num_frag,
1135 					TXMON_PPDU(ppdu_info, ppdu_id));
1136 	}
1137 }
1138 
1139 #define PHY_MEDIUM_MHZ	960
1140 #define PHY_TIMESTAMP_WRAP (0xFFFFFFFF / PHY_MEDIUM_MHZ)
1141 
1142 /**
1143  * dp_populate_tsft_from_phy_timestamp() - API to get tsft from phy timestamp
1144  * @pdev: pdev Handle
1145  * @ppdu_info: ppdi_info Handle
1146  *
1147  * Return: QDF_STATUS
1148  */
1149 static QDF_STATUS
dp_populate_tsft_from_phy_timestamp(struct dp_pdev * pdev,struct dp_tx_ppdu_info * ppdu_info)1150 dp_populate_tsft_from_phy_timestamp(struct dp_pdev *pdev,
1151 				    struct dp_tx_ppdu_info *ppdu_info)
1152 {
1153 	struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
1154 	struct dp_mon_pdev_be *mon_pdev_be =
1155 			dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
1156 	struct dp_pdev_tx_monitor_be *tx_mon_be =
1157 			&mon_pdev_be->tx_monitor_be;
1158 	uint64_t tsft = 0;
1159 	uint32_t ppdu_timestamp = 0;
1160 
1161 	tsft = TXMON_PPDU_COM(ppdu_info, tsft);
1162 	ppdu_timestamp = TXMON_PPDU_COM(ppdu_info, ppdu_timestamp);
1163 
1164 	if (tsft && ppdu_timestamp) {
1165 		/* update tsft and ppdu timestamp */
1166 		tx_mon_be->last_tsft = tsft;
1167 		tx_mon_be->last_ppdu_timestamp = ppdu_timestamp;
1168 	} else if (!tx_mon_be->last_ppdu_timestamp || !tx_mon_be->last_tsft) {
1169 		return QDF_STATUS_E_EMPTY;
1170 	}
1171 
1172 	if (!tsft && ppdu_timestamp) {
1173 		/* response window */
1174 		uint32_t cur_usec = ppdu_timestamp / PHY_MEDIUM_MHZ;
1175 		uint32_t last_usec = (tx_mon_be->last_ppdu_timestamp /
1176 				      PHY_MEDIUM_MHZ);
1177 		uint32_t diff = 0;
1178 
1179 		if (last_usec < cur_usec) {
1180 			diff = cur_usec - last_usec;
1181 			tsft = tx_mon_be->last_tsft + diff;
1182 		} else {
1183 			diff = (PHY_TIMESTAMP_WRAP - last_usec) + cur_usec;
1184 			tsft = tx_mon_be->last_tsft + diff;
1185 		}
1186 		TXMON_PPDU_COM(ppdu_info, tsft) = tsft;
1187 		/* update tsft and ppdu timestamp */
1188 		tx_mon_be->last_tsft = tsft;
1189 		tx_mon_be->last_ppdu_timestamp = ppdu_timestamp;
1190 	}
1191 
1192 	if (!TXMON_PPDU_COM(ppdu_info, tsft) &&
1193 	    !TXMON_PPDU_COM(ppdu_info, ppdu_timestamp))
1194 		return QDF_STATUS_E_EMPTY;
1195 
1196 	return QDF_STATUS_SUCCESS;
1197 }
1198 
1199 /**
1200  * dp_tx_mon_update_channel_freq() - API to update channel frequency and number
1201  * @pdev: pdev Handle
1202  * @soc: soc Handle
1203  * @freq: Frequency
1204  *
1205  * Return: void
1206  */
1207 static inline void
dp_tx_mon_update_channel_freq(struct dp_pdev * pdev,struct dp_soc * soc,uint16_t freq)1208 dp_tx_mon_update_channel_freq(struct dp_pdev *pdev, struct dp_soc *soc,
1209 			      uint16_t freq)
1210 {
1211 	if (soc && soc->cdp_soc.ol_ops->freq_to_channel) {
1212 		uint8_t c_num;
1213 
1214 		c_num = soc->cdp_soc.ol_ops->freq_to_channel(soc->ctrl_psoc,
1215 							     pdev->pdev_id,
1216 							     freq);
1217 		pdev->operating_channel.num = c_num;
1218 	}
1219 
1220 	if (soc && soc->cdp_soc.ol_ops->freq_to_band) {
1221 		uint8_t band;
1222 
1223 		band = soc->cdp_soc.ol_ops->freq_to_band(soc->ctrl_psoc,
1224 							 pdev->pdev_id,
1225 							 freq);
1226 		pdev->operating_channel.band = band;
1227 	}
1228 }
1229 
1230 /**
1231  * dp_tx_mon_update_radiotap() - API to update radiotap information
1232  * @pdev: pdev Handle
1233  * @ppdu_info: pointer to dp_tx_ppdu_info
1234  *
1235  * Return: void
1236  */
1237 static void
dp_tx_mon_update_radiotap(struct dp_pdev * pdev,struct dp_tx_ppdu_info * ppdu_info)1238 dp_tx_mon_update_radiotap(struct dp_pdev *pdev,
1239 			  struct dp_tx_ppdu_info *ppdu_info)
1240 {
1241 	uint32_t usr_idx = 0;
1242 	uint32_t num_users = 0;
1243 
1244 	num_users = TXMON_PPDU_HAL(ppdu_info, num_users);
1245 
1246 	if (qdf_unlikely(TXMON_PPDU_COM(ppdu_info, chan_freq) == 0 &&
1247 			 TXMON_PPDU_COM(ppdu_info, chan_num) == 0)) {
1248 		TXMON_PPDU_COM(ppdu_info, chan_freq) =
1249 				pdev->operating_channel.freq;
1250 		TXMON_PPDU_COM(ppdu_info, chan_num) =
1251 				pdev->operating_channel.num;
1252 	} else if (TXMON_PPDU_COM(ppdu_info, chan_freq) != 0 &&
1253 		   TXMON_PPDU_COM(ppdu_info, chan_num) == 0) {
1254 		uint16_t freq = TXMON_PPDU_COM(ppdu_info, chan_freq);
1255 
1256 		if (qdf_unlikely(pdev->operating_channel.freq != freq)) {
1257 			dp_tx_mon_update_channel_freq(pdev, pdev->soc, freq);
1258 			pdev->operating_channel.freq = freq;
1259 		}
1260 		TXMON_PPDU_COM(ppdu_info,
1261 			       chan_num) = pdev->operating_channel.num;
1262 	}
1263 
1264 	if (QDF_STATUS_SUCCESS !=
1265 	    dp_populate_tsft_from_phy_timestamp(pdev, ppdu_info))
1266 		return;
1267 
1268 	/* update mlo timestamp */
1269 	TXMON_PPDU_COM(ppdu_info, tsft) =
1270 			(TXMON_PPDU_COM(ppdu_info, tsft) +
1271 			 pdev->timestamp.mlo_offset_lo_us +
1272 			 ((uint64_t)pdev->timestamp.mlo_offset_hi_us << 32));
1273 
1274 	for (usr_idx = 0; usr_idx < num_users; usr_idx++) {
1275 		qdf_nbuf_queue_t *mpdu_q = NULL;
1276 
1277 		/* set AMPDU flag if number mpdu is more than 1 */
1278 		mpdu_q = &TXMON_PPDU_USR(ppdu_info, usr_idx, mpdu_q);
1279 		if (mpdu_q && (qdf_nbuf_queue_len(mpdu_q) > 1)) {
1280 			TXMON_PPDU_COM(ppdu_info,
1281 				       rs_flags) |= IEEE80211_AMPDU_FLAG;
1282 			TXMON_PPDU_USR(ppdu_info, usr_idx, is_ampdu) = 1;
1283 		}
1284 
1285 		if (qdf_unlikely(!TXMON_PPDU_COM(ppdu_info, rate))) {
1286 			uint32_t rate = 0;
1287 			uint32_t rix = 0;
1288 			uint16_t ratecode = 0;
1289 
1290 			rate = dp_getrateindex(TXMON_PPDU_COM(ppdu_info, sgi),
1291 					       TXMON_PPDU_USR(ppdu_info,
1292 							      usr_idx, mcs),
1293 					       TXMON_PPDU_COM(ppdu_info, nss),
1294 					       TXMON_PPDU_COM(ppdu_info,
1295 							      preamble_type),
1296 					       TXMON_PPDU_COM(ppdu_info, bw),
1297 					       0,
1298 					       &rix, &ratecode);
1299 
1300 			/* update rate */
1301 			TXMON_PPDU_COM(ppdu_info, rate) = rate;
1302 		}
1303 
1304 		dp_tx_mon_send_per_usr_mpdu(pdev, ppdu_info, usr_idx);
1305 	}
1306 }
1307 
1308 /**
1309  * dp_tx_mon_ppdu_process - Deferred PPDU stats handler
1310  * @context: Opaque work context (PDEV)
1311  *
1312  * Return: none
1313  */
dp_tx_mon_ppdu_process(void * context)1314 static void dp_tx_mon_ppdu_process(void *context)
1315 {
1316 	struct dp_pdev *pdev = (struct dp_pdev *)context;
1317 	struct dp_mon_pdev *mon_pdev;
1318 	struct dp_mon_pdev_be *mon_pdev_be;
1319 	struct dp_tx_ppdu_info *defer_ppdu_info = NULL;
1320 	struct dp_tx_ppdu_info *defer_ppdu_info_next = NULL;
1321 	struct dp_pdev_tx_monitor_be *tx_mon_be;
1322 
1323 	/* sanity check */
1324 	if (qdf_unlikely(!pdev))
1325 		return;
1326 
1327 	mon_pdev = pdev->monitor_pdev;
1328 
1329 	if (qdf_unlikely(!mon_pdev))
1330 		return;
1331 
1332 	mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
1333 	if (qdf_unlikely(!mon_pdev_be))
1334 		return;
1335 
1336 	tx_mon_be = &mon_pdev_be->tx_monitor_be;
1337 	if (qdf_unlikely(TX_MON_BE_DISABLE == tx_mon_be->mode &&
1338 			 !dp_lite_mon_is_tx_enabled(mon_pdev)))
1339 		return;
1340 
1341 	/* take lock here */
1342 	qdf_spin_lock_bh(&tx_mon_be->tx_mon_list_lock);
1343 	STAILQ_CONCAT(&tx_mon_be->defer_tx_ppdu_info_queue,
1344 		      &tx_mon_be->tx_ppdu_info_queue);
1345 	tx_mon_be->defer_ppdu_info_list_depth +=
1346 		tx_mon_be->tx_ppdu_info_list_depth;
1347 	tx_mon_be->tx_ppdu_info_list_depth = 0;
1348 	qdf_spin_unlock_bh(&tx_mon_be->tx_mon_list_lock);
1349 
1350 	STAILQ_FOREACH_SAFE(defer_ppdu_info,
1351 			    &tx_mon_be->defer_tx_ppdu_info_queue,
1352 			    tx_ppdu_info_queue_elem, defer_ppdu_info_next) {
1353 		/* remove dp_tx_ppdu_info from the list */
1354 		STAILQ_REMOVE(&tx_mon_be->defer_tx_ppdu_info_queue,
1355 			      defer_ppdu_info,
1356 			      dp_tx_ppdu_info,
1357 			      tx_ppdu_info_queue_elem);
1358 		tx_mon_be->defer_ppdu_info_list_depth--;
1359 
1360 		dp_tx_mon_update_radiotap(pdev, defer_ppdu_info);
1361 
1362 		/* free the ppdu_info */
1363 		dp_tx_mon_free_ppdu_info(defer_ppdu_info, tx_mon_be);
1364 		defer_ppdu_info = NULL;
1365 	}
1366 }
1367 
dp_tx_ppdu_stats_attach_2_0(struct dp_pdev * pdev)1368 void dp_tx_ppdu_stats_attach_2_0(struct dp_pdev *pdev)
1369 {
1370 	struct dp_mon_pdev *mon_pdev;
1371 	struct dp_mon_pdev_be *mon_pdev_be;
1372 	struct dp_pdev_tx_monitor_be *tx_mon_be;
1373 
1374 	if (qdf_unlikely(!pdev))
1375 		return;
1376 
1377 	mon_pdev = pdev->monitor_pdev;
1378 
1379 	if (qdf_unlikely(!mon_pdev))
1380 		return;
1381 
1382 	mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
1383 	if (qdf_unlikely(!mon_pdev_be))
1384 		return;
1385 
1386 	tx_mon_be = &mon_pdev_be->tx_monitor_be;
1387 
1388 	STAILQ_INIT(&tx_mon_be->tx_ppdu_info_queue);
1389 	tx_mon_be->tx_ppdu_info_list_depth = 0;
1390 
1391 	STAILQ_INIT(&tx_mon_be->defer_tx_ppdu_info_queue);
1392 	tx_mon_be->defer_ppdu_info_list_depth = 0;
1393 
1394 	qdf_spinlock_create(&tx_mon_be->tx_mon_list_lock);
1395 	/* Work queue setup for TX MONITOR post handling */
1396 	qdf_create_work(0, &tx_mon_be->post_ppdu_work,
1397 			dp_tx_mon_ppdu_process, pdev);
1398 
1399 	tx_mon_be->post_ppdu_workqueue =
1400 			qdf_alloc_unbound_workqueue("tx_mon_ppdu_work_queue");
1401 }
1402 
dp_tx_ppdu_stats_detach_2_0(struct dp_pdev * pdev)1403 void dp_tx_ppdu_stats_detach_2_0(struct dp_pdev *pdev)
1404 {
1405 	struct dp_mon_pdev *mon_pdev;
1406 	struct dp_mon_pdev_be *mon_pdev_be;
1407 	struct dp_pdev_tx_monitor_be *tx_mon_be;
1408 	struct dp_tx_ppdu_info *tx_ppdu_info = NULL;
1409 	struct dp_tx_ppdu_info *tx_ppdu_info_next = NULL;
1410 
1411 	if (qdf_unlikely(!pdev))
1412 		return;
1413 
1414 	mon_pdev = pdev->monitor_pdev;
1415 
1416 	if (qdf_unlikely(!mon_pdev))
1417 		return;
1418 
1419 	mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
1420 	if (qdf_unlikely(!mon_pdev_be))
1421 		return;
1422 
1423 	tx_mon_be = &mon_pdev_be->tx_monitor_be;
1424 	/* TODO: disable tx_monitor, to avoid further packet from HW */
1425 	dp_monitor_config_enh_tx_capture(pdev, TX_MON_BE_DISABLE);
1426 
1427 	/* flush workqueue */
1428 	qdf_flush_workqueue(0, tx_mon_be->post_ppdu_workqueue);
1429 	qdf_destroy_workqueue(0, tx_mon_be->post_ppdu_workqueue);
1430 
1431 	/*
1432 	 * TODO: iterate both tx_ppdu_info and defer_ppdu_info_list
1433 	 * free the tx_ppdu_info and decrement depth
1434 	 */
1435 	qdf_spin_lock_bh(&tx_mon_be->tx_mon_list_lock);
1436 	STAILQ_FOREACH_SAFE(tx_ppdu_info,
1437 			    &tx_mon_be->tx_ppdu_info_queue,
1438 			    tx_ppdu_info_queue_elem, tx_ppdu_info_next) {
1439 		/* remove dp_tx_ppdu_info from the list */
1440 		STAILQ_REMOVE(&tx_mon_be->tx_ppdu_info_queue, tx_ppdu_info,
1441 			      dp_tx_ppdu_info, tx_ppdu_info_queue_elem);
1442 		/* decrement list length */
1443 		tx_mon_be->tx_ppdu_info_list_depth--;
1444 		/* free tx_ppdu_info */
1445 		dp_tx_mon_free_ppdu_info(tx_ppdu_info, tx_mon_be);
1446 	}
1447 	qdf_spin_unlock_bh(&tx_mon_be->tx_mon_list_lock);
1448 
1449 	qdf_spin_lock_bh(&tx_mon_be->tx_mon_list_lock);
1450 	STAILQ_FOREACH_SAFE(tx_ppdu_info,
1451 			    &tx_mon_be->defer_tx_ppdu_info_queue,
1452 			    tx_ppdu_info_queue_elem, tx_ppdu_info_next) {
1453 		/* remove dp_tx_ppdu_info from the list */
1454 		STAILQ_REMOVE(&tx_mon_be->defer_tx_ppdu_info_queue,
1455 			      tx_ppdu_info,
1456 			      dp_tx_ppdu_info, tx_ppdu_info_queue_elem);
1457 		/* decrement list length */
1458 		tx_mon_be->defer_ppdu_info_list_depth--;
1459 		/* free tx_ppdu_info */
1460 		dp_tx_mon_free_ppdu_info(tx_ppdu_info, tx_mon_be);
1461 	}
1462 	qdf_spin_unlock_bh(&tx_mon_be->tx_mon_list_lock);
1463 
1464 	qdf_spinlock_destroy(&tx_mon_be->tx_mon_list_lock);
1465 }
1466 #endif /* WLAN_TX_PKT_CAPTURE_ENH_BE */
1467 
1468 #if (defined(WIFI_MONITOR_SUPPORT) && defined(WLAN_TX_MON_CORE_DEBUG))
1469 /*
1470  * dp_config_enh_tx_core_monitor_2_0()- API to validate core framework
1471  * @pdev_handle: DP_PDEV handle
1472  * @val: user provided value
1473  *
1474  * Return: QDF_STATUS
1475  */
1476 QDF_STATUS
dp_config_enh_tx_core_monitor_2_0(struct dp_pdev * pdev,uint8_t val)1477 dp_config_enh_tx_core_monitor_2_0(struct dp_pdev *pdev, uint8_t val)
1478 {
1479 	struct wlan_cfg_dp_soc_ctxt *soc_cfg_ctx;
1480 	struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
1481 	struct dp_mon_pdev_be *mon_pdev_be =
1482 			dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
1483 	struct dp_pdev_tx_monitor_be *tx_mon_be =
1484 			&mon_pdev_be->tx_monitor_be;
1485 	struct dp_soc *soc = pdev->soc;
1486 	uint16_t num_of_buffers;
1487 	QDF_STATUS status;
1488 
1489 	soc_cfg_ctx = soc->wlan_cfg_ctx;
1490 	switch (val) {
1491 	case TX_MON_BE_FRM_WRK_DISABLE:
1492 	{
1493 		tx_mon_be->mode = val;
1494 		mon_pdev_be->tx_mon_mode = 0;
1495 		mon_pdev_be->tx_mon_filter_length = DMA_LENGTH_64B;
1496 		break;
1497 	}
1498 	case TX_MON_BE_FRM_WRK_FULL_CAPTURE:
1499 	{
1500 		num_of_buffers = wlan_cfg_get_dp_soc_tx_mon_buf_ring_size(soc_cfg_ctx);
1501 		status = dp_vdev_set_monitor_mode_buf_rings_tx_2_0(pdev,
1502 								   num_of_buffers);
1503 		if (status != QDF_STATUS_SUCCESS) {
1504 			dp_mon_err("Tx monitor buffer allocation failed");
1505 			return status;
1506 		}
1507 		tx_mon_be->mode = val;
1508 		qdf_mem_zero(&tx_mon_be->stats,
1509 			     sizeof(struct dp_tx_monitor_drop_stats));
1510 		tx_mon_be->mode = val;
1511 		mon_pdev_be->tx_mon_mode = 1;
1512 		mon_pdev_be->tx_mon_filter_length = DEFAULT_DMA_LENGTH;
1513 		break;
1514 	}
1515 	case TX_MON_BE_FRM_WRK_128B_CAPTURE:
1516 	{
1517 		status = dp_vdev_set_monitor_mode_buf_rings_tx_2_0(pdev,
1518 								   DP_MON_RING_FILL_LEVEL_DEFAULT);
1519 		if (status != QDF_STATUS_SUCCESS) {
1520 			dp_mon_err("Tx monitor buffer allocation failed");
1521 			return status;
1522 		}
1523 		tx_mon_be->mode = val;
1524 		mon_pdev_be->tx_mon_mode = 1;
1525 		mon_pdev_be->tx_mon_filter_length = DMA_LENGTH_128B;
1526 		break;
1527 	}
1528 	default:
1529 	{
1530 		return QDF_STATUS_E_INVAL;
1531 	}
1532 	}
1533 
1534 	dp_mon_debug("Tx monitor mode:%d mon_mode_flag:%d config_length:%d",
1535 		    tx_mon_be->mode, mon_pdev_be->tx_mon_mode,
1536 		    mon_pdev_be->tx_mon_filter_length);
1537 
1538 	/* send HTT msg to configure TLV based on mode */
1539 	dp_mon_filter_setup_tx_mon_mode(pdev);
1540 	dp_tx_mon_filter_update(pdev);
1541 
1542 	return QDF_STATUS_SUCCESS;
1543 }
1544 #endif
1545 
1546 #ifdef WLAN_PKT_CAPTURE_TX_2_0
dp_tx_mon_pdev_htt_srng_setup_2_0(struct dp_soc * soc,struct dp_pdev * pdev,int mac_id,int mac_for_pdev)1547 QDF_STATUS dp_tx_mon_pdev_htt_srng_setup_2_0(struct dp_soc *soc,
1548 					     struct dp_pdev *pdev,
1549 					     int mac_id,
1550 					     int mac_for_pdev)
1551 {
1552 	struct dp_mon_soc *mon_soc = soc->monitor_soc;
1553 	struct dp_mon_soc_be *mon_soc_be = dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
1554 
1555 	return htt_srng_setup(soc->htt_handle, mac_for_pdev,
1556 			      mon_soc_be->tx_mon_dst_ring[mac_id].hal_srng,
1557 			      TX_MONITOR_DST);
1558 }
1559 
dp_tx_mon_soc_htt_srng_setup_2_0(struct dp_soc * soc,int mac_id)1560 QDF_STATUS dp_tx_mon_soc_htt_srng_setup_2_0(struct dp_soc *soc,
1561 					    int mac_id)
1562 {
1563 	struct dp_mon_soc *mon_soc = soc->monitor_soc;
1564 	struct dp_mon_soc_be *mon_soc_be = dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
1565 
1566 	hal_set_low_threshold(mon_soc_be->tx_mon_buf_ring.hal_srng, 0);
1567 	return htt_srng_setup(soc->htt_handle, mac_id,
1568 				mon_soc_be->tx_mon_buf_ring.hal_srng,
1569 				TX_MONITOR_BUF);
1570 }
1571 
dp_tx_mon_pdev_rings_alloc_2_0(struct dp_pdev * pdev,uint32_t lmac_id)1572 QDF_STATUS dp_tx_mon_pdev_rings_alloc_2_0(struct dp_pdev *pdev, uint32_t lmac_id)
1573 {
1574 	struct dp_soc *soc = pdev->soc;
1575 	int entries;
1576 	struct wlan_cfg_dp_pdev_ctxt *pdev_cfg_ctx;
1577 	struct dp_mon_soc *mon_soc = soc->monitor_soc;
1578 	struct dp_mon_soc_be *mon_soc_be = dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
1579 
1580 	pdev_cfg_ctx = pdev->wlan_cfg_ctx;
1581 	entries = wlan_cfg_get_dma_tx_mon_dest_ring_size(pdev_cfg_ctx);
1582 
1583 	return dp_srng_alloc(soc, &mon_soc_be->tx_mon_dst_ring[lmac_id],
1584 				  TX_MONITOR_DST, entries, 0);
1585 }
1586 
dp_tx_mon_pdev_rings_free_2_0(struct dp_pdev * pdev,uint32_t lmac_id)1587 void dp_tx_mon_pdev_rings_free_2_0(struct dp_pdev *pdev, uint32_t lmac_id)
1588 {
1589 	struct dp_soc *soc = pdev->soc;
1590 	struct dp_mon_soc *mon_soc = soc->monitor_soc;
1591 	struct dp_mon_soc_be *mon_soc_be = dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
1592 
1593 	dp_srng_free(soc, &mon_soc_be->tx_mon_dst_ring[lmac_id]);
1594 }
1595 
dp_tx_mon_pdev_rings_init_2_0(struct dp_pdev * pdev,uint32_t lmac_id)1596 QDF_STATUS dp_tx_mon_pdev_rings_init_2_0(struct dp_pdev *pdev, uint32_t lmac_id)
1597 {
1598 	struct dp_soc *soc = pdev->soc;
1599 	struct dp_mon_soc *mon_soc = soc->monitor_soc;
1600 	struct dp_mon_soc_be *mon_soc_be = dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
1601 
1602 	return dp_srng_init(soc, &mon_soc_be->tx_mon_dst_ring[lmac_id],
1603 				 TX_MONITOR_DST, pdev->pdev_id, lmac_id);
1604 }
1605 
dp_tx_mon_pdev_rings_deinit_2_0(struct dp_pdev * pdev,uint32_t lmac_id)1606 void dp_tx_mon_pdev_rings_deinit_2_0(struct dp_pdev *pdev, uint32_t lmac_id)
1607 {
1608 	struct dp_soc *soc = pdev->soc;
1609 	struct dp_mon_soc *mon_soc = soc->monitor_soc;
1610 	struct dp_mon_soc_be *mon_soc_be =
1611 			dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
1612 
1613 	dp_srng_deinit(soc, &mon_soc_be->tx_mon_dst_ring[lmac_id],
1614 		       TX_MONITOR_DST, pdev->pdev_id);
1615 }
1616 
dp_tx_mon_soc_attach_2_0(struct dp_soc * soc,uint32_t lmac_id)1617 QDF_STATUS dp_tx_mon_soc_attach_2_0(struct dp_soc *soc, uint32_t lmac_id)
1618 {
1619 	int entries;
1620 	struct wlan_cfg_dp_soc_ctxt *soc_cfg_ctx = soc->wlan_cfg_ctx;
1621 	struct dp_mon_soc *mon_soc = soc->monitor_soc;
1622 	struct dp_mon_soc_be *mon_soc_be =
1623 		dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
1624 
1625 	entries = wlan_cfg_get_dp_soc_tx_mon_buf_ring_size(soc_cfg_ctx);
1626 	qdf_print("%s:%d tx mon buf entries: %d", __func__, __LINE__, entries);
1627 
1628 	return dp_srng_alloc(soc, &mon_soc_be->tx_mon_buf_ring,
1629 			  TX_MONITOR_BUF, entries, 0);
1630 }
1631 
dp_tx_mon_soc_detach_2_0(struct dp_soc * soc,uint32_t lmac_id)1632 QDF_STATUS dp_tx_mon_soc_detach_2_0(struct dp_soc *soc, uint32_t lmac_id)
1633 {
1634 	struct dp_mon_soc *mon_soc = soc->monitor_soc;
1635 	struct dp_mon_soc_be *mon_soc_be =
1636 			dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
1637 
1638 	if (!mon_soc_be) {
1639 		dp_mon_err("DP MON SOC NULL");
1640 		return QDF_STATUS_E_FAILURE;
1641 	}
1642 
1643 	dp_tx_mon_buf_desc_pool_free(soc);
1644 	dp_srng_free(soc, &mon_soc_be->tx_mon_buf_ring);
1645 	return QDF_STATUS_SUCCESS;
1646 }
1647 
1648 #endif
1649