xref: /wlan-dirver/qca-wifi-host-cmn/dp/wifi3.0/monitor/dp_mon_filter.c (revision e018c89988b0f4c4a85f63f5974121479123f922)
1 /*
2  * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 #include <dp_types.h>
20 #include <dp_htt.h>
21 #include <dp_internal.h>
22 #include <dp_rx_mon.h>
23 #include <dp_mon_filter.h>
24 #include <dp_mon.h>
25 
26 /*
27  * dp_mon_filter_mode_type_to_str
28  * Monitor Filter mode to string
29  */
30 int8_t *dp_mon_filter_mode_type_to_str[DP_MON_FILTER_MAX_MODE] = {
31 #ifdef QCA_ENHANCED_STATS_SUPPORT
32 	"DP MON FILTER ENHACHED STATS MODE",
33 #endif /* QCA_ENHANCED_STATS_SUPPORT */
34 #ifdef QCA_MCOPY_SUPPORT
35 	"DP MON FILTER MCOPY MODE",
36 #endif /* QCA_MCOPY_SUPPORT */
37 #if defined(ATH_SUPPORT_NAC_RSSI) || defined(ATH_SUPPORT_NAC)
38 	"DP MON FILTER SMART MONITOR MODE",
39 #endif /* ATH_SUPPORT_NAC_RSSI || ATH_SUPPORT_NAC */
40 	"DP_MON FILTER MONITOR MODE",
41 #ifdef WLAN_RX_PKT_CAPTURE_ENH
42 	"DP MON FILTER RX CAPTURE MODE",
43 #endif /* WLAN_RX_PKT_CAPTURE_ENH */
44 #ifdef WDI_EVENT_ENABLE
45 	"DP MON FILTER PKT LOG FULL MODE",
46 	"DP MON FILTER PKT LOG LITE MODE",
47 	"DP MON FILTER PKT LOG CBF MODE",
48 #ifdef BE_PKTLOG_SUPPORT
49 	"DP MON FILTER PKT LOG HYBRID MODE",
50 #endif
51 #endif /* WDI_EVENT_ENABLE */
52 #ifdef QCA_UNDECODED_METADATA_SUPPORT
53 	"DP MON FILTER RX UNDECODED METADATA CAPTURE MODE",
54 #endif
55 };
56 
57 #if defined(WLAN_PKT_CAPTURE_RX_2_0) || defined(CONFIG_WORD_BASED_TLV) || \
58 	defined(WLAN_FEATURE_LOCAL_PKT_CAPTURE)
59 static inline
60 void dp_mon_filter_show_filter_1(struct htt_rx_ring_tlv_filter *tlv_filter)
61 {
62 	DP_MON_FILTER_PRINT("rx_hdr_length: %d", tlv_filter->rx_hdr_length);
63 	DP_MON_FILTER_PRINT("mgmt_dma_length: %d", tlv_filter->mgmt_dma_length);
64 	DP_MON_FILTER_PRINT("ctrl_dma_length: %d", tlv_filter->ctrl_dma_length);
65 	DP_MON_FILTER_PRINT("data_dma_length: %d", tlv_filter->data_dma_length);
66 }
67 #else
68 static inline
69 void dp_mon_filter_show_filter_1(struct htt_rx_ring_tlv_filter *tlv_filter)
70 {
71 }
72 #endif
73 
74 void dp_mon_filter_show_filter(struct dp_mon_pdev *mon_pdev,
75 			       enum dp_mon_filter_mode mode,
76 			       struct dp_mon_filter *filter)
77 {
78 	struct htt_rx_ring_tlv_filter *tlv_filter = &filter->tlv_filter;
79 
80 	DP_MON_FILTER_PRINT("[%s]: Valid: %d",
81 			    dp_mon_filter_mode_type_to_str[mode],
82 			    filter->valid);
83 	dp_mon_filter_show_filter_1(tlv_filter);
84 	DP_MON_FILTER_PRINT("mpdu_start: %d", tlv_filter->mpdu_start);
85 	DP_MON_FILTER_PRINT("msdu_start: %d", tlv_filter->msdu_start);
86 	DP_MON_FILTER_PRINT("packet: %d", tlv_filter->packet);
87 	DP_MON_FILTER_PRINT("msdu_end: %d", tlv_filter->msdu_end);
88 	DP_MON_FILTER_PRINT("mpdu_end: %d", tlv_filter->mpdu_end);
89 	DP_MON_FILTER_PRINT("packet_header: %d",
90 			    tlv_filter->packet_header);
91 	DP_MON_FILTER_PRINT("attention: %d", tlv_filter->attention);
92 	DP_MON_FILTER_PRINT("ppdu_start: %d", tlv_filter->ppdu_start);
93 	DP_MON_FILTER_PRINT("ppdu_end: %d", tlv_filter->ppdu_end);
94 	DP_MON_FILTER_PRINT("ppdu_end_user_stats: %d",
95 			    tlv_filter->ppdu_end_user_stats);
96 	DP_MON_FILTER_PRINT("ppdu_end_user_stats_ext: %d",
97 			    tlv_filter->ppdu_end_user_stats_ext);
98 	DP_MON_FILTER_PRINT("ppdu_end_status_done: %d",
99 			    tlv_filter->ppdu_end_status_done);
100 	DP_MON_FILTER_PRINT("ppdu_start_user_info: %d",
101 			    tlv_filter->ppdu_start_user_info);
102 	DP_MON_FILTER_PRINT("header_per_msdu: %d", tlv_filter->header_per_msdu);
103 	DP_MON_FILTER_PRINT("enable_fp: %d", tlv_filter->enable_fp);
104 	DP_MON_FILTER_PRINT("enable_md: %d", tlv_filter->enable_md);
105 	DP_MON_FILTER_PRINT("enable_mo: %d", tlv_filter->enable_mo);
106 	DP_MON_FILTER_PRINT("fp_mgmt_filter: 0x%x", tlv_filter->fp_mgmt_filter);
107 	DP_MON_FILTER_PRINT("mo_mgmt_filter: 0x%x", tlv_filter->mo_mgmt_filter);
108 	DP_MON_FILTER_PRINT("fp_ctrl_filter: 0x%x", tlv_filter->fp_ctrl_filter);
109 	DP_MON_FILTER_PRINT("mo_ctrl_filter: 0x%x", tlv_filter->mo_ctrl_filter);
110 	DP_MON_FILTER_PRINT("fp_data_filter: 0x%x", tlv_filter->fp_data_filter);
111 	DP_MON_FILTER_PRINT("mo_data_filter: 0x%x", tlv_filter->mo_data_filter);
112 	DP_MON_FILTER_PRINT("md_data_filter: 0x%x", tlv_filter->md_data_filter);
113 	DP_MON_FILTER_PRINT("md_mgmt_filter: 0x%x", tlv_filter->md_mgmt_filter);
114 	DP_MON_FILTER_PRINT("md_ctrl_filter: 0x%x", tlv_filter->md_ctrl_filter);
115 #ifdef QCA_UNDECODED_METADATA_SUPPORT
116 	DP_MON_FILTER_PRINT("fp_phy_err: %d", tlv_filter->fp_phy_err);
117 	DP_MON_FILTER_PRINT("fp_phy_err_buf_src: %d",
118 			    tlv_filter->fp_phy_err_buf_src);
119 	DP_MON_FILTER_PRINT("fp_phy_err_buf_dest: %d",
120 			    tlv_filter->fp_phy_err_buf_dest);
121 	DP_MON_FILTER_PRINT("phy_err_mask: 0x%x", tlv_filter->phy_err_mask);
122 	DP_MON_FILTER_PRINT("phy_err_mask_cont: 0x%x",
123 			    tlv_filter->phy_err_mask_cont);
124 #endif
125 	DP_MON_FILTER_PRINT("mon_mac_filter: %d",
126 			    tlv_filter->enable_mon_mac_filter);
127 }
128 
129 #ifdef QCA_UNDECODED_METADATA_SUPPORT
130 static inline void
131 dp_mon_set_fp_phy_err_filter(struct htt_rx_ring_tlv_filter *tlv_filter,
132 			     struct dp_mon_filter *mon_filter)
133 {
134 	if (mon_filter->tlv_filter.phy_err_filter_valid) {
135 		tlv_filter->fp_phy_err =
136 			mon_filter->tlv_filter.fp_phy_err;
137 		tlv_filter->fp_phy_err_buf_src =
138 			mon_filter->tlv_filter.fp_phy_err_buf_src;
139 		tlv_filter->fp_phy_err_buf_dest =
140 			mon_filter->tlv_filter.fp_phy_err_buf_dest;
141 		tlv_filter->phy_err_mask =
142 			mon_filter->tlv_filter.phy_err_mask;
143 		tlv_filter->phy_err_mask_cont =
144 			mon_filter->tlv_filter.phy_err_mask_cont;
145 		tlv_filter->phy_err_filter_valid =
146 			mon_filter->tlv_filter.phy_err_filter_valid;
147 	}
148 }
149 #else
150 static inline void
151 dp_mon_set_fp_phy_err_filter(struct htt_rx_ring_tlv_filter *tlv_filter,
152 			     struct dp_mon_filter *mon_filter)
153 {
154 }
155 #endif
156 
157 void dp_mon_filter_h2t_setup(struct dp_soc *soc, struct dp_pdev *pdev,
158 			     enum dp_mon_filter_srng_type srng_type,
159 			     struct dp_mon_filter *filter)
160 {
161 	int32_t current_mode = 0;
162 	struct htt_rx_ring_tlv_filter *tlv_filter = &filter->tlv_filter;
163 	struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
164 
165 	/*
166 	 * Loop through all the modes.
167 	 */
168 	for (current_mode = 0; current_mode < DP_MON_FILTER_MAX_MODE;
169 						current_mode++) {
170 		struct dp_mon_filter *mon_filter =
171 			&mon_pdev->filter[current_mode][srng_type];
172 		uint32_t src_filter = 0, dst_filter = 0;
173 
174 		/*
175 		 * Check if the correct mode is enabled or not.
176 		 */
177 		if (!mon_filter->valid)
178 			continue;
179 
180 		filter->valid = true;
181 
182 		/*
183 		 * Set the super bit fields
184 		 */
185 		src_filter =
186 			DP_MON_FILTER_GET(&mon_filter->tlv_filter, FILTER_TLV);
187 		dst_filter = DP_MON_FILTER_GET(tlv_filter, FILTER_TLV);
188 		dst_filter |= src_filter;
189 		DP_MON_FILTER_SET(tlv_filter, FILTER_TLV, dst_filter);
190 
191 		/*
192 		 * Set the filter management filter.
193 		 */
194 		src_filter = DP_MON_FILTER_GET(&mon_filter->tlv_filter,
195 					       FILTER_FP_MGMT);
196 		dst_filter = DP_MON_FILTER_GET(tlv_filter, FILTER_FP_MGMT);
197 		dst_filter |= src_filter;
198 		DP_MON_FILTER_SET(tlv_filter, FILTER_FP_MGMT, dst_filter);
199 
200 		/*
201 		 * Set the monitor other management filter.
202 		 */
203 		src_filter = DP_MON_FILTER_GET(&mon_filter->tlv_filter,
204 					       FILTER_MO_MGMT);
205 		dst_filter = DP_MON_FILTER_GET(tlv_filter, FILTER_MO_MGMT);
206 		dst_filter |= src_filter;
207 		DP_MON_FILTER_SET(tlv_filter, FILTER_MO_MGMT, dst_filter);
208 
209 		/*
210 		 * Set the filter pass control filter.
211 		 */
212 		src_filter = DP_MON_FILTER_GET(&mon_filter->tlv_filter,
213 					       FILTER_FP_CTRL);
214 		dst_filter = DP_MON_FILTER_GET(tlv_filter, FILTER_FP_CTRL);
215 		dst_filter |= src_filter;
216 		DP_MON_FILTER_SET(tlv_filter, FILTER_FP_CTRL, dst_filter);
217 
218 		/*
219 		 * Set the monitor other control filter.
220 		 */
221 		src_filter = DP_MON_FILTER_GET(&mon_filter->tlv_filter,
222 					       FILTER_MO_CTRL);
223 		dst_filter = DP_MON_FILTER_GET(tlv_filter, FILTER_MO_CTRL);
224 		dst_filter |= src_filter;
225 		DP_MON_FILTER_SET(tlv_filter, FILTER_MO_CTRL, dst_filter);
226 
227 		/*
228 		 * Set the filter pass data filter.
229 		 */
230 		src_filter = DP_MON_FILTER_GET(&mon_filter->tlv_filter,
231 					       FILTER_FP_DATA);
232 		dst_filter = DP_MON_FILTER_GET(tlv_filter,
233 					       FILTER_FP_DATA);
234 		dst_filter |= src_filter;
235 		DP_MON_FILTER_SET(tlv_filter,
236 				  FILTER_FP_DATA, dst_filter);
237 
238 		/*
239 		 * Set the monitor other data filter.
240 		 */
241 		src_filter = DP_MON_FILTER_GET(&mon_filter->tlv_filter,
242 					       FILTER_MO_DATA);
243 		dst_filter = DP_MON_FILTER_GET(tlv_filter, FILTER_MO_DATA);
244 		dst_filter |= src_filter;
245 		DP_MON_FILTER_SET(tlv_filter, FILTER_MO_DATA, dst_filter);
246 
247 		/*
248 		 * Set the monitor direct data filter.
249 		 */
250 		src_filter = DP_MON_FILTER_GET(&mon_filter->tlv_filter,
251 					       FILTER_MD_DATA);
252 		dst_filter = DP_MON_FILTER_GET(tlv_filter,
253 					       FILTER_MD_DATA);
254 		dst_filter |= src_filter;
255 		DP_MON_FILTER_SET(tlv_filter,
256 				  FILTER_MD_DATA, dst_filter);
257 
258 		/*
259 		 * Set the monitor direct management filter.
260 		 */
261 		src_filter = DP_MON_FILTER_GET(&mon_filter->tlv_filter,
262 					       FILTER_MD_MGMT);
263 		dst_filter = DP_MON_FILTER_GET(tlv_filter, FILTER_MD_MGMT);
264 		dst_filter |= src_filter;
265 		DP_MON_FILTER_SET(tlv_filter, FILTER_MD_MGMT, dst_filter);
266 
267 		/*
268 		 * Set the monitor direct management filter.
269 		 */
270 		src_filter = DP_MON_FILTER_GET(&mon_filter->tlv_filter,
271 					       FILTER_MD_CTRL);
272 		dst_filter = DP_MON_FILTER_GET(tlv_filter, FILTER_MD_CTRL);
273 		dst_filter |= src_filter;
274 		DP_MON_FILTER_SET(tlv_filter, FILTER_MD_CTRL, dst_filter);
275 
276 		dp_mon_set_fp_phy_err_filter(tlv_filter, mon_filter);
277 		tlv_filter->enable_mon_mac_filter =
278 				mon_filter->tlv_filter.enable_mon_mac_filter;
279 		DP_RX_MON_FILTER_SET_RX_HDR_LEN(tlv_filter,
280 						mon_filter->tlv_filter);
281 	}
282 
283 	dp_mon_filter_show_filter(mon_pdev, 0, filter);
284 }
285 
286 /**
287  * dp_mon_skip_filter_config() - Check if filter config need to be skipped
288  * @soc: DP soc context
289  *
290  * Return: true if yes, false if not
291  */
292 static inline
293 bool dp_mon_skip_filter_config(struct dp_soc *soc)
294 {
295 	if (soc->cdp_soc.ol_ops->get_con_mode &&
296 	    soc->cdp_soc.ol_ops->get_con_mode() ==
297 	    QDF_GLOBAL_MISSION_MODE &&
298 	    !(QDF_MONITOR_FLAG_OTHER_BSS & soc->mon_flags))
299 		return true;
300 	else
301 		return false;
302 }
303 
304 /**
305  * dp_update_num_mac_rings() - Update number of MAC rings based on connection
306  *                             mode and DBS check
307  * @soc: DP soc context
308  * @mon_mac_rings: Pointer to variable for number of mac rings
309  *
310  * Return: None
311  */
312 static void
313 dp_update_num_mac_rings(struct dp_soc *soc, int *mon_mac_rings)
314 {
315 	if (soc->cdp_soc.ol_ops->get_con_mode &&
316 	    soc->cdp_soc.ol_ops->get_con_mode() ==
317 	    QDF_GLOBAL_MISSION_MODE &&
318 	    (QDF_MONITOR_FLAG_OTHER_BSS & soc->mon_flags)) {
319 		*mon_mac_rings = 1;
320 	} else {
321 		dp_update_num_mac_rings_for_dbs(soc, mon_mac_rings);
322 	}
323 }
324 
325 QDF_STATUS
326 dp_mon_ht2_rx_ring_cfg(struct dp_soc *soc,
327 		       struct dp_pdev *pdev,
328 		       enum dp_mon_filter_srng_type srng_type,
329 		       struct htt_rx_ring_tlv_filter *tlv_filter)
330 {
331 	int mac_id;
332 	int max_mac_rings = wlan_cfg_get_num_mac_rings(pdev->wlan_cfg_ctx);
333 	QDF_STATUS status = QDF_STATUS_SUCCESS;
334 	uint32_t target_type = hal_get_target_type(soc->hal_soc);
335 
336 	if (srng_type == DP_MON_FILTER_SRNG_TYPE_RXDMA_BUF &&
337 	    dp_mon_skip_filter_config(soc)) {
338 		dp_mon_filter_info("skip rxdma_buf filter cfg for lpc mode");
339 		return QDF_STATUS_SUCCESS;
340 	}
341 
342 	/*
343 	 * Overwrite the max_mac_rings for the status rings.
344 	 */
345 	if (srng_type == DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS)
346 		dp_update_num_mac_rings(soc, &max_mac_rings);
347 
348 	dp_mon_filter_info("%pK: srng type %d Max_mac_rings %d ",
349 			   soc, srng_type, max_mac_rings);
350 
351 	/*
352 	 * Loop through all MACs per radio and set the filter to the individual
353 	 * macs. For MCL
354 	 */
355 	for (mac_id = 0; mac_id < max_mac_rings; mac_id++) {
356 		int mac_for_pdev =
357 			dp_get_mac_id_for_pdev(mac_id, pdev->pdev_id);
358 		int lmac_id = dp_get_lmac_id_for_pdev_id(soc, mac_id, pdev->pdev_id);
359 		int hal_ring_type, ring_buf_size;
360 		hal_ring_handle_t hal_ring_hdl;
361 
362 		switch (srng_type) {
363 		case DP_MON_FILTER_SRNG_TYPE_RXDMA_BUF:
364 			if (target_type == TARGET_TYPE_QCN9160) {
365 				hal_ring_hdl =
366 				soc->rx_refill_buf_ring[lmac_id].hal_srng;
367 				ring_buf_size = RX_MONITOR_BUFFER_SIZE;
368 			} else {
369 				hal_ring_hdl =
370 					pdev->rx_mac_buf_ring[lmac_id].hal_srng;
371 				ring_buf_size = RX_DATA_BUFFER_SIZE;
372 			}
373 			hal_ring_type = RXDMA_BUF;
374 			break;
375 
376 		case DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS:
377 			/*
378 			 * If two back to back HTT msg sending happened in
379 			 * short time, the second HTT msg source SRNG HP
380 			 * writing has chance to fail, this has been confirmed
381 			 * by HST HW.
382 			 * for monitor mode, here is the last HTT msg for sending.
383 			 * if the 2nd HTT msg for monitor status ring sending failed,
384 			 * HW won't provide anything into 2nd monitor status ring.
385 			 * as a WAR, add some delay before 2nd HTT msg start sending,
386 			 * > 2us is required per HST HW, delay 100 us for safe.
387 			 */
388 			if (mac_id)
389 				qdf_udelay(100);
390 
391 			hal_ring_hdl =
392 				soc->rxdma_mon_status_ring[lmac_id].hal_srng;
393 			hal_ring_type = RXDMA_MONITOR_STATUS;
394 			ring_buf_size = RX_MON_STATUS_BUF_SIZE;
395 			break;
396 
397 		case DP_MON_FILTER_SRNG_TYPE_RXDMA_MON_BUF:
398 			hal_ring_hdl =
399 				soc->rxdma_mon_buf_ring[lmac_id].hal_srng;
400 			hal_ring_type = RXDMA_MONITOR_BUF;
401 			ring_buf_size = RX_MONITOR_BUFFER_SIZE;
402 			break;
403 
404 		case DP_MON_FILTER_SRNG_TYPE_RXMON_DEST:
405 			hal_ring_hdl =
406 				soc->rxdma_mon_dst_ring[lmac_id].hal_srng;
407 			hal_ring_type = RXDMA_MONITOR_DST;
408 			ring_buf_size = RX_MONITOR_BUFFER_SIZE;
409 			break;
410 		default:
411 			return QDF_STATUS_E_FAILURE;
412 		}
413 
414 		if (!hal_ring_hdl)
415 			continue;
416 
417 		status = htt_h2t_rx_ring_cfg(soc->htt_handle, mac_for_pdev,
418 					     hal_ring_hdl, hal_ring_type,
419 					     ring_buf_size,
420 					     tlv_filter);
421 		if (status != QDF_STATUS_SUCCESS)
422 			return status;
423 	}
424 
425 	return status;
426 }
427 
428 #ifdef QCA_ENHANCED_STATS_SUPPORT
429 void dp_mon_filter_setup_enhanced_stats(struct dp_pdev *pdev)
430 {
431 	struct dp_mon_ops *mon_ops = NULL;
432 
433 	mon_ops = dp_mon_ops_get(pdev->soc);
434 	if (mon_ops && mon_ops->mon_filter_setup_enhanced_stats)
435 		mon_ops->mon_filter_setup_enhanced_stats(pdev);
436 }
437 
438 void dp_mon_filter_reset_enhanced_stats(struct dp_pdev *pdev)
439 {
440 	struct dp_mon_ops *mon_ops = NULL;
441 
442 	mon_ops = dp_mon_ops_get(pdev->soc);
443 	if (mon_ops && mon_ops->mon_filter_reset_enhanced_stats)
444 		mon_ops->mon_filter_reset_enhanced_stats(pdev);
445 }
446 #endif /* QCA_ENHANCED_STATS_SUPPORT */
447 
448 #ifdef QCA_UNDECODED_METADATA_SUPPORT
449 void dp_mon_filter_setup_undecoded_metadata_mode(struct dp_pdev *pdev)
450 {
451 	struct dp_mon_ops *mon_ops = NULL;
452 
453 	mon_ops = dp_mon_ops_get(pdev->soc);
454 	if (mon_ops && mon_ops->mon_filter_setup_undecoded_metadata_capture)
455 		mon_ops->mon_filter_setup_undecoded_metadata_capture(pdev);
456 }
457 
458 void dp_mon_filter_reset_undecoded_metadata_mode(struct dp_pdev *pdev)
459 {
460 	struct dp_mon_ops *mon_ops = NULL;
461 
462 	mon_ops = dp_mon_ops_get(pdev->soc);
463 	if (mon_ops && mon_ops->mon_filter_reset_undecoded_metadata_capture)
464 		mon_ops->mon_filter_reset_undecoded_metadata_capture(pdev);
465 }
466 #endif /* QCA_UNDECODED_METADATA_SUPPORT */
467 
468 #ifdef QCA_MCOPY_SUPPORT
469 void dp_mon_filter_setup_mcopy_mode(struct dp_pdev *pdev)
470 {
471 	struct dp_mon_ops *mon_ops = NULL;
472 
473 	mon_ops = dp_mon_ops_get(pdev->soc);
474 	if (mon_ops && mon_ops->mon_filter_setup_mcopy_mode)
475 		mon_ops->mon_filter_setup_mcopy_mode(pdev);
476 }
477 
478 void dp_mon_filter_reset_mcopy_mode(struct dp_pdev *pdev)
479 {
480 	struct dp_mon_ops *mon_ops = NULL;
481 
482 	mon_ops = dp_mon_ops_get(pdev->soc);
483 	if (mon_ops && mon_ops->mon_filter_reset_mcopy_mode)
484 		mon_ops->mon_filter_reset_mcopy_mode(pdev);
485 }
486 #endif /* QCA_MCOPY_SUPPORT */
487 
488 #if defined(ATH_SUPPORT_NAC_RSSI) || defined(ATH_SUPPORT_NAC)
489 void dp_mon_filter_setup_smart_monitor(struct dp_pdev *pdev)
490 {
491 	struct dp_mon_ops *mon_ops = NULL;
492 
493 	mon_ops = dp_mon_ops_get(pdev->soc);
494 	if (mon_ops && mon_ops->mon_filter_setup_smart_monitor)
495 		mon_ops->mon_filter_setup_smart_monitor(pdev);
496 }
497 
498 void dp_mon_filter_reset_smart_monitor(struct dp_pdev *pdev)
499 {
500 	struct dp_mon_ops *mon_ops = NULL;
501 
502 	mon_ops = dp_mon_ops_get(pdev->soc);
503 	if (mon_ops && mon_ops->mon_filter_reset_smart_monitor)
504 		mon_ops->mon_filter_reset_smart_monitor(pdev);
505 }
506 #endif /* ATH_SUPPORT_NAC_RSSI || ATH_SUPPORT_NAC */
507 
508 void dp_mon_filter_set_reset_mon_mac_filter(struct dp_pdev *pdev, bool val)
509 {
510 	struct dp_mon_ops *mon_ops = NULL;
511 
512 	mon_ops = dp_mon_ops_get(pdev->soc);
513 	if (mon_ops && mon_ops->mon_filter_set_reset_mon_mac_filter)
514 		mon_ops->mon_filter_set_reset_mon_mac_filter(pdev, val);
515 }
516 
517 #ifdef WLAN_RX_PKT_CAPTURE_ENH
518 void dp_mon_filter_setup_rx_enh_capture(struct dp_pdev *pdev)
519 {
520 	struct dp_mon_ops *mon_ops = NULL;
521 
522 	mon_ops = dp_mon_ops_get(pdev->soc);
523 	if (mon_ops && mon_ops->mon_filter_setup_rx_enh_capture)
524 		mon_ops->mon_filter_setup_rx_enh_capture(pdev);
525 }
526 
527 void dp_mon_filter_reset_rx_enh_capture(struct dp_pdev *pdev)
528 {
529 	struct dp_mon_ops *mon_ops = NULL;
530 
531 	mon_ops = dp_mon_ops_get(pdev->soc);
532 	if (mon_ops && mon_ops->mon_filter_reset_rx_enh_capture)
533 		mon_ops->mon_filter_reset_rx_enh_capture(pdev);
534 }
535 #endif /* WLAN_RX_PKT_CAPTURE_ENH */
536 
537 void dp_mon_filter_setup_mon_mode(struct dp_pdev *pdev)
538 {
539 	struct dp_mon_ops *mon_ops = NULL;
540 
541 	mon_ops = dp_mon_ops_get(pdev->soc);
542 	if (mon_ops && mon_ops->mon_filter_setup_rx_mon_mode)
543 		mon_ops->mon_filter_setup_rx_mon_mode(pdev);
544 }
545 
546 void dp_mon_filter_setup_tx_mon_mode(struct dp_pdev *pdev)
547 {
548 	struct dp_mon_ops *mon_ops = NULL;
549 
550 	mon_ops = dp_mon_ops_get(pdev->soc);
551 	if (mon_ops && mon_ops->mon_filter_setup_tx_mon_mode)
552 		mon_ops->mon_filter_setup_tx_mon_mode(pdev);
553 }
554 
555 void dp_mon_filter_reset_tx_mon_mode(struct dp_pdev *pdev)
556 {
557 	struct dp_mon_ops *mon_ops = NULL;
558 
559 	mon_ops = dp_mon_ops_get(pdev->soc);
560 	if (mon_ops && mon_ops->mon_filter_reset_tx_mon_mode)
561 		mon_ops->mon_filter_reset_tx_mon_mode(pdev);
562 }
563 
564 void dp_mon_filter_reset_mon_mode(struct dp_pdev *pdev)
565 {
566 	struct dp_mon_ops *mon_ops = NULL;
567 
568 	mon_ops = dp_mon_ops_get(pdev->soc);
569 	if (mon_ops && mon_ops->mon_filter_reset_rx_mon_mode)
570 		mon_ops->mon_filter_reset_rx_mon_mode(pdev);
571 }
572 
573 #if defined(WLAN_PKT_CAPTURE_RX_2_0) || defined(CONFIG_WORD_BASED_TLV) || \
574 	defined(WLAN_FEATURE_LOCAL_PKT_CAPTURE)
575 void dp_rx_mon_hdr_length_set(uint32_t *msg_word,
576 			      struct htt_rx_ring_tlv_filter *tlv_filter)
577 {
578 	if (!msg_word || !tlv_filter)
579 		return;
580 
581 	HTT_RX_RING_SELECTION_CFG_RX_HDR_LEN_SET(*msg_word,
582 						 tlv_filter->rx_hdr_length);
583 }
584 #else
585 void dp_rx_mon_hdr_length_set(uint32_t *msg_word,
586 			      struct htt_rx_ring_tlv_filter *tlv_filter)
587 {
588 }
589 #endif
590 
591 #ifdef WDI_EVENT_ENABLE
592 void dp_mon_filter_setup_rx_pkt_log_full(struct dp_pdev *pdev)
593 {
594 	struct dp_mon_ops *mon_ops = NULL;
595 
596 	mon_ops = dp_mon_ops_get(pdev->soc);
597 	if (mon_ops && mon_ops->mon_filter_setup_rx_pkt_log_full)
598 		mon_ops->mon_filter_setup_rx_pkt_log_full(pdev);
599 }
600 
601 void dp_mon_filter_reset_rx_pkt_log_full(struct dp_pdev *pdev)
602 {
603 	struct dp_mon_ops *mon_ops = NULL;
604 
605 	mon_ops = dp_mon_ops_get(pdev->soc);
606 	if (mon_ops && mon_ops->mon_filter_reset_rx_pkt_log_full)
607 		mon_ops->mon_filter_reset_rx_pkt_log_full(pdev);
608 }
609 
610 void dp_mon_filter_setup_rx_pkt_log_lite(struct dp_pdev *pdev)
611 {
612 	struct dp_mon_ops *mon_ops = NULL;
613 
614 	mon_ops = dp_mon_ops_get(pdev->soc);
615 	if (mon_ops && mon_ops->mon_filter_setup_rx_pkt_log_lite)
616 		mon_ops->mon_filter_setup_rx_pkt_log_lite(pdev);
617 }
618 
619 void dp_mon_filter_reset_rx_pkt_log_lite(struct dp_pdev *pdev)
620 {
621 	struct dp_mon_ops *mon_ops = NULL;
622 
623 	mon_ops = dp_mon_ops_get(pdev->soc);
624 	if (mon_ops && mon_ops->mon_filter_reset_rx_pkt_log_lite)
625 		mon_ops->mon_filter_reset_rx_pkt_log_lite(pdev);
626 }
627 
628 void dp_mon_filter_setup_rx_pkt_log_cbf(struct dp_pdev *pdev)
629 {
630 	struct dp_mon_ops *mon_ops = NULL;
631 
632 	mon_ops = dp_mon_ops_get(pdev->soc);
633 	if (mon_ops && mon_ops->mon_filter_setup_rx_pkt_log_cbf)
634 		mon_ops->mon_filter_setup_rx_pkt_log_cbf(pdev);
635 }
636 
637 void dp_mon_filter_reset_rx_pktlog_cbf(struct dp_pdev *pdev)
638 {
639 	struct dp_mon_ops *mon_ops = NULL;
640 
641 	mon_ops = dp_mon_ops_get(pdev->soc);
642 	if (mon_ops && mon_ops->mon_filter_reset_rx_pkt_log_cbf)
643 		mon_ops->mon_filter_reset_rx_pkt_log_cbf(pdev);
644 }
645 
646 #ifdef BE_PKTLOG_SUPPORT
647 void dp_mon_filter_setup_pktlog_hybrid(struct dp_pdev *pdev)
648 {
649 	struct dp_mon_ops *mon_ops = NULL;
650 
651 	mon_ops = dp_mon_ops_get(pdev->soc);
652 	if (mon_ops && mon_ops->mon_filter_setup_pktlog_hybrid)
653 		mon_ops->mon_filter_setup_pktlog_hybrid(pdev);
654 }
655 
656 void dp_mon_filter_reset_pktlog_hybrid(struct dp_pdev *pdev)
657 {
658 	struct dp_mon_ops *mon_ops = NULL;
659 
660 	mon_ops = dp_mon_ops_get(pdev->soc);
661 	if (mon_ops && mon_ops->mon_filter_reset_pktlog_hybrid)
662 		mon_ops->mon_filter_reset_pktlog_hybrid(pdev);
663 }
664 #endif
665 #endif /* WDI_EVENT_ENABLE */
666 
667 QDF_STATUS dp_mon_filter_update(struct dp_pdev *pdev)
668 {
669 	struct dp_mon_ops *mon_ops = NULL;
670 
671 	mon_ops = dp_mon_ops_get(pdev->soc);
672 	if (!mon_ops) {
673 		dp_mon_filter_err("Rx mon filter update failed ops uninitialized");
674 		return QDF_STATUS_E_FAILURE;
675 	}
676 
677 	if (mon_ops && mon_ops->rx_mon_filter_update)
678 		mon_ops->rx_mon_filter_update(pdev);
679 
680 	return QDF_STATUS_SUCCESS;
681 }
682 
683 QDF_STATUS dp_tx_mon_filter_update(struct dp_pdev *pdev)
684 {
685 	struct dp_mon_ops *mon_ops = NULL;
686 
687 	mon_ops = dp_mon_ops_get(pdev->soc);
688 	if (!mon_ops) {
689 		dp_mon_filter_err("Tx mon filter update failed ops uninitialized");
690 		return QDF_STATUS_E_FAILURE;
691 	}
692 
693 	if (mon_ops && mon_ops->tx_mon_filter_update)
694 		mon_ops->tx_mon_filter_update(pdev);
695 
696 	return QDF_STATUS_SUCCESS;
697 }
698 
699 #ifdef QCA_ENHANCED_STATS_SUPPORT
700 void dp_mon_filters_reset(struct dp_pdev *pdev)
701 {
702 	dp_mon_filter_reset_enhanced_stats(pdev);
703 	dp_mon_filter_reset_mon_mode(pdev);
704 	dp_mon_filter_update(pdev);
705 }
706 #else
707 void dp_mon_filters_reset(struct dp_pdev *pdev)
708 {
709 }
710 #endif
711 
712 void
713 dp_mon_filter_reset_mon_srng(struct dp_soc *soc, struct dp_pdev *pdev,
714 			     enum dp_mon_filter_srng_type mon_srng_type)
715 {
716 	struct htt_rx_ring_tlv_filter tlv_filter = {0};
717 
718 	if (dp_mon_ht2_rx_ring_cfg(soc, pdev, mon_srng_type,
719 				   &tlv_filter) != QDF_STATUS_SUCCESS) {
720 		dp_mon_filter_err("%pK: Monitor destination ring filter setting failed",
721 				  soc);
722 	}
723 }
724 
725 /**
726  * dp_mon_filter_adjust() - adjust the mon filters per target basis
727  * @pdev: DP pdev handle
728  * @filter: DP mon filter
729  *
730  * Return: None
731  */
732 static inline
733 void dp_mon_filter_adjust(struct dp_pdev *pdev, struct dp_mon_filter *filter)
734 {
735 	struct dp_soc *soc = pdev->soc;
736 
737 	switch (hal_get_target_type(soc->hal_soc)) {
738 	case TARGET_TYPE_KIWI:
739 	case TARGET_TYPE_MANGO:
740 	case TARGET_TYPE_PEACH:
741 		filter->tlv_filter.msdu_start = 0;
742 		filter->tlv_filter.mpdu_end = 0;
743 		filter->tlv_filter.packet_header = 0;
744 		filter->tlv_filter.attention = 0;
745 		break;
746 	default:
747 		break;
748 	}
749 }
750 
751 void dp_mon_filter_set_mon_cmn(struct dp_pdev *pdev,
752 			       struct dp_mon_filter *filter)
753 {
754 	struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
755 
756 	filter->tlv_filter.mpdu_start = 1;
757 	filter->tlv_filter.msdu_start = 1;
758 	filter->tlv_filter.packet = 1;
759 	filter->tlv_filter.msdu_end = 1;
760 	filter->tlv_filter.mpdu_end = 1;
761 	filter->tlv_filter.packet_header = 1;
762 	filter->tlv_filter.attention = 1;
763 	filter->tlv_filter.ppdu_start = 0;
764 	filter->tlv_filter.ppdu_end = 0;
765 	filter->tlv_filter.ppdu_end_user_stats = 0;
766 	filter->tlv_filter.ppdu_end_user_stats_ext = 0;
767 	filter->tlv_filter.ppdu_end_status_done = 0;
768 	filter->tlv_filter.header_per_msdu = 1;
769 	filter->tlv_filter.enable_fp =
770 		(mon_pdev->mon_filter_mode & MON_FILTER_PASS) ? 1 : 0;
771 	filter->tlv_filter.enable_mo =
772 		(mon_pdev->mon_filter_mode & MON_FILTER_OTHER) ? 1 : 0;
773 
774 	filter->tlv_filter.fp_mgmt_filter = mon_pdev->fp_mgmt_filter;
775 	filter->tlv_filter.fp_ctrl_filter = mon_pdev->fp_ctrl_filter;
776 	filter->tlv_filter.fp_data_filter = mon_pdev->fp_data_filter;
777 	filter->tlv_filter.mo_mgmt_filter = mon_pdev->mo_mgmt_filter;
778 	filter->tlv_filter.mo_ctrl_filter = mon_pdev->mo_ctrl_filter;
779 	filter->tlv_filter.mo_data_filter = mon_pdev->mo_data_filter;
780 	filter->tlv_filter.offset_valid = false;
781 	dp_mon_filter_adjust(pdev, filter);
782 }
783 
784 void dp_mon_filter_set_status_cmn(struct dp_mon_pdev *mon_pdev,
785 				  struct dp_mon_filter *filter)
786 {
787 	filter->tlv_filter.mpdu_start = 1;
788 	filter->tlv_filter.msdu_start = 0;
789 	filter->tlv_filter.packet = 0;
790 	filter->tlv_filter.msdu_end = 0;
791 	filter->tlv_filter.mpdu_end = 0;
792 	filter->tlv_filter.attention = 0;
793 	filter->tlv_filter.ppdu_start = 1;
794 	filter->tlv_filter.ppdu_end = 1;
795 	filter->tlv_filter.ppdu_end_user_stats = 1;
796 	filter->tlv_filter.ppdu_end_user_stats_ext = 1;
797 	filter->tlv_filter.ppdu_end_status_done = 1;
798 	filter->tlv_filter.ppdu_start_user_info = 1;
799 	filter->tlv_filter.enable_fp = 1;
800 	filter->tlv_filter.enable_md = 0;
801 	filter->tlv_filter.fp_mgmt_filter = FILTER_MGMT_ALL;
802 	filter->tlv_filter.fp_ctrl_filter = FILTER_CTRL_ALL;
803 	filter->tlv_filter.fp_data_filter = FILTER_DATA_ALL;
804 	filter->tlv_filter.offset_valid = false;
805 
806 	if (mon_pdev->mon_filter_mode & MON_FILTER_OTHER) {
807 		filter->tlv_filter.enable_mo = 1;
808 		filter->tlv_filter.mo_mgmt_filter = FILTER_MGMT_ALL;
809 		filter->tlv_filter.mo_ctrl_filter = FILTER_CTRL_ALL;
810 		filter->tlv_filter.mo_data_filter = FILTER_DATA_ALL;
811 	} else {
812 		filter->tlv_filter.enable_mo = 0;
813 	}
814 }
815 
816 void dp_mon_filter_set_status_cbf(struct dp_pdev *pdev,
817 				  struct dp_mon_filter *filter)
818 {
819 	filter->tlv_filter.mpdu_start = 1;
820 	filter->tlv_filter.msdu_start = 0;
821 	filter->tlv_filter.packet = 0;
822 	filter->tlv_filter.msdu_end = 0;
823 	filter->tlv_filter.mpdu_end = 0;
824 	filter->tlv_filter.attention = 0;
825 	filter->tlv_filter.ppdu_start = 1;
826 	filter->tlv_filter.ppdu_end = 1;
827 	filter->tlv_filter.ppdu_end_user_stats = 1;
828 	filter->tlv_filter.ppdu_end_user_stats_ext = 1;
829 	filter->tlv_filter.ppdu_end_status_done = 1;
830 	filter->tlv_filter.ppdu_start_user_info = 1;
831 	filter->tlv_filter.enable_fp = 1;
832 	filter->tlv_filter.enable_md = 0;
833 	filter->tlv_filter.fp_mgmt_filter = FILTER_MGMT_ACT_NO_ACK;
834 	filter->tlv_filter.fp_ctrl_filter = 0;
835 	filter->tlv_filter.fp_data_filter = 0;
836 	filter->tlv_filter.offset_valid = false;
837 	filter->tlv_filter.enable_mo = 0;
838 }
839 
840 void dp_mon_filter_set_cbf_cmn(struct dp_pdev *pdev,
841 			       struct dp_mon_filter *filter)
842 {
843 	filter->tlv_filter.mpdu_start = 1;
844 	filter->tlv_filter.msdu_start = 1;
845 	filter->tlv_filter.packet = 1;
846 	filter->tlv_filter.msdu_end = 1;
847 	filter->tlv_filter.mpdu_end = 1;
848 	filter->tlv_filter.attention = 1;
849 	filter->tlv_filter.ppdu_start = 0;
850 	filter->tlv_filter.ppdu_end =  0;
851 	filter->tlv_filter.ppdu_end_user_stats = 0;
852 	filter->tlv_filter.ppdu_end_user_stats_ext = 0;
853 	filter->tlv_filter.ppdu_end_status_done = 0;
854 	filter->tlv_filter.ppdu_start_user_info = 0;
855 	filter->tlv_filter.enable_fp = 1;
856 	filter->tlv_filter.enable_md = 0;
857 	filter->tlv_filter.fp_mgmt_filter = FILTER_MGMT_ACT_NO_ACK;
858 	filter->tlv_filter.offset_valid = false;
859 	filter->tlv_filter.enable_mo = 0;
860 }
861 
862 void dp_mon_filter_dealloc(struct dp_mon_pdev *mon_pdev)
863 {
864 	enum dp_mon_filter_mode mode;
865 	struct dp_mon_filter **mon_filter = NULL;
866 
867 	if (!mon_pdev) {
868 		dp_mon_filter_err("Monitor pdev Context is null");
869 		return;
870 	}
871 
872 	mon_filter = mon_pdev->filter;
873 
874 	/*
875 	 * Check if the monitor filters are already allocated to the mon_pdev.
876 	 */
877 	if (!mon_filter) {
878 		dp_mon_filter_err("Found NULL memory for the Monitor filter");
879 		return;
880 	}
881 
882 	/*
883 	 * Iterate through the every mode and free the filter object.
884 	 */
885 	for (mode = 0; mode < DP_MON_FILTER_MAX_MODE; mode++) {
886 		if (!mon_filter[mode]) {
887 			continue;
888 		}
889 
890 		qdf_mem_free(mon_filter[mode]);
891 		mon_filter[mode] = NULL;
892 	}
893 
894 	qdf_mem_free(mon_filter);
895 	mon_pdev->filter = NULL;
896 }
897 
898 struct dp_mon_filter **dp_mon_filter_alloc(struct dp_mon_pdev *mon_pdev)
899 {
900 	struct dp_mon_filter **mon_filter = NULL;
901 	enum dp_mon_filter_mode mode;
902 
903 	if (!mon_pdev) {
904 		dp_mon_filter_err("pdev Context is null");
905 		return NULL;
906 	}
907 
908 	mon_filter = (struct dp_mon_filter **)qdf_mem_malloc(
909 			(sizeof(struct dp_mon_filter *) *
910 			 DP_MON_FILTER_MAX_MODE));
911 	if (!mon_filter) {
912 		dp_mon_filter_err("Monitor filter mem allocation failed");
913 		return NULL;
914 	}
915 
916 	qdf_mem_zero(mon_filter,
917 		     sizeof(struct dp_mon_filter *) * DP_MON_FILTER_MAX_MODE);
918 
919 	/*
920 	 * Allocate the memory for filters for different srngs for each modes.
921 	 */
922 	for (mode = 0; mode < DP_MON_FILTER_MAX_MODE; mode++) {
923 		mon_filter[mode] = qdf_mem_malloc(sizeof(struct dp_mon_filter) *
924 						  DP_MON_FILTER_SRNG_TYPE_MAX);
925 		/* Assign the mon_filter to the pdev->filter such
926 		 * that the dp_mon_filter_dealloc() can free up the filters. */
927 		if (!mon_filter[mode]) {
928 			mon_pdev->filter = mon_filter;
929 			goto fail;
930 		}
931 	}
932 
933 	return mon_filter;
934 fail:
935 	dp_mon_filter_dealloc(mon_pdev);
936 	return NULL;
937 }
938 
939 #ifdef WLAN_FEATURE_LOCAL_PKT_CAPTURE
940 QDF_STATUS dp_mon_set_local_pkt_capture_running(struct dp_mon_pdev *mon_pdev,
941 						bool val)
942 {
943 	if (!mon_pdev) {
944 		dp_mon_filter_err("Invalid monitor pdev");
945 		return QDF_STATUS_E_FAILURE;
946 	}
947 
948 	mon_pdev->is_local_pkt_capture_running = val;
949 	dp_mon_filter_debug("local_pkt_capture_running is set to %d", val);
950 	return QDF_STATUS_SUCCESS;
951 }
952 
953 bool dp_mon_get_is_local_pkt_capture_running(struct cdp_soc_t *cdp_soc,
954 					     uint8_t pdev_id)
955 {
956 	struct dp_soc *soc = (struct dp_soc *)cdp_soc;
957 	struct dp_pdev *pdev =
958 		dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
959 	struct dp_mon_pdev *mon_pdev;
960 
961 	if (!pdev || !pdev->monitor_pdev) {
962 		dp_mon_filter_err("Invalid pdev_id %u", pdev_id);
963 		return false;
964 	}
965 
966 	mon_pdev = pdev->monitor_pdev;
967 
968 	return mon_pdev->is_local_pkt_capture_running;
969 }
970 
971 static void
972 dp_mon_set_local_pkt_capture_rx_filter(struct dp_pdev *pdev,
973 				       struct cdp_monitor_filter *src_filter)
974 {
975 	struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
976 	enum dp_mon_filter_mode mode = DP_MON_FILTER_MONITOR_MODE;
977 	enum dp_mon_filter_srng_type srng_type;
978 	struct dp_mon_filter dst_filter = {0};
979 
980 	dst_filter.valid = true;
981 	dp_mon_filter_set_status_cmn(mon_pdev, &dst_filter);
982 
983 	dst_filter.tlv_filter.packet_header = 1;
984 	dst_filter.tlv_filter.header_per_msdu = 1;
985 	dst_filter.tlv_filter.rx_hdr_length = RX_HDR_DMA_LENGTH_256B;
986 	dst_filter.tlv_filter.fp_mgmt_filter = src_filter->fp_mgmt;
987 	dst_filter.tlv_filter.fp_ctrl_filter = src_filter->fp_ctrl;
988 	dst_filter.tlv_filter.fp_data_filter = src_filter->fp_data;
989 	dst_filter.tlv_filter.enable_fp = src_filter->mode;
990 	dst_filter.tlv_filter.enable_md = 0;
991 	dst_filter.tlv_filter.enable_mo = 0;
992 
993 	dp_mon_filter_show_filter(mon_pdev, mode, &dst_filter);
994 
995 	/* Store the above filter */
996 	srng_type = DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS;
997 	mon_pdev->filter[mode][srng_type] = dst_filter;
998 }
999 
1000 static void dp_mon_clear_local_pkt_capture_rx_filter(struct dp_pdev *pdev)
1001 {
1002 	struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
1003 	enum dp_mon_filter_mode mode = DP_MON_FILTER_MONITOR_MODE;
1004 	enum dp_mon_filter_srng_type srng_type =
1005 				DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS;
1006 	struct dp_mon_filter filter = {0};
1007 
1008 	mon_pdev->filter[mode][srng_type] = filter;
1009 }
1010 
1011 static void dp_mon_reset_local_pkt_capture_rx_filter(struct dp_pdev *pdev)
1012 {
1013 	struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
1014 	enum dp_mon_filter_mode mode = DP_MON_FILTER_MONITOR_MODE;
1015 	enum dp_mon_filter_srng_type srng_type =
1016 				DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS;
1017 	struct dp_mon_filter filter = {0};
1018 
1019 	filter.valid = true;
1020 	mon_pdev->filter[mode][srng_type] = filter;
1021 	dp_mon_pdev_filter_init(mon_pdev);
1022 }
1023 
1024 static inline void
1025 dp_mon_init_local_pkt_capture_queue(struct dp_mon_pdev *mon_pdev)
1026 {
1027 	qdf_spin_lock_bh(&mon_pdev->lpc_lock);
1028 	qdf_nbuf_queue_init(&mon_pdev->msdu_queue);
1029 	qdf_nbuf_queue_init(&mon_pdev->mpdu_queue);
1030 	mon_pdev->first_mpdu = true;
1031 	qdf_spin_unlock_bh(&mon_pdev->lpc_lock);
1032 }
1033 
1034 static inline void
1035 dp_mon_free_local_pkt_capture_queue(struct dp_mon_pdev *mon_pdev)
1036 {
1037 	qdf_spin_lock_bh(&mon_pdev->lpc_lock);
1038 	qdf_nbuf_queue_free(&mon_pdev->msdu_queue);
1039 	qdf_nbuf_queue_free(&mon_pdev->mpdu_queue);
1040 	qdf_spin_unlock_bh(&mon_pdev->lpc_lock);
1041 }
1042 
1043 QDF_STATUS dp_mon_start_local_pkt_capture(struct cdp_soc_t *cdp_soc,
1044 					  uint8_t pdev_id,
1045 					  struct cdp_monitor_filter *filter)
1046 {
1047 	bool local_pkt_capture_running;
1048 	struct dp_soc *soc = cdp_soc_t_to_dp_soc(cdp_soc);
1049 	struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
1050 	struct dp_mon_pdev *mon_pdev;
1051 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1052 
1053 	if (!pdev) {
1054 		dp_mon_filter_err("pdev Context is null");
1055 		return QDF_STATUS_E_INVAL;
1056 	}
1057 
1058 	mon_pdev = pdev->monitor_pdev;
1059 	local_pkt_capture_running =
1060 		dp_mon_get_is_local_pkt_capture_running(cdp_soc, pdev_id);
1061 	if (local_pkt_capture_running) {
1062 		dp_mon_filter_err("Can't start local pkt capture. Already running");
1063 		return QDF_STATUS_E_ALREADY;
1064 	}
1065 
1066 	mon_pdev->mon_filter_mode = filter->mode;
1067 	mon_pdev->fp_mgmt_filter = filter->fp_mgmt;
1068 	mon_pdev->fp_ctrl_filter = filter->fp_ctrl;
1069 	mon_pdev->fp_data_filter = filter->fp_data;
1070 
1071 	qdf_spin_lock_bh(&mon_pdev->mon_lock);
1072 	dp_mon_set_local_pkt_capture_rx_filter(pdev, filter);
1073 	status = dp_mon_filter_update(pdev);
1074 	if (QDF_IS_STATUS_ERROR(status)) {
1075 		dp_mon_clear_local_pkt_capture_rx_filter(pdev);
1076 		qdf_spin_unlock_bh(&mon_pdev->mon_lock);
1077 		dp_mon_filter_err("local pkt capture set rx filter failed");
1078 		return status;
1079 	}
1080 
1081 	dp_mon_filter_setup_tx_mon_mode(pdev);
1082 	status = dp_tx_mon_filter_update(pdev);
1083 	if (QDF_IS_STATUS_ERROR(status)) {
1084 		qdf_spin_unlock_bh(&mon_pdev->mon_lock);
1085 		dp_mon_filter_err("local pkt capture set tx filter failed");
1086 		return status;
1087 	}
1088 	qdf_spin_unlock_bh(&mon_pdev->mon_lock);
1089 
1090 	dp_mon_filter_debug("local pkt capture tx filter set");
1091 
1092 	dp_mon_init_local_pkt_capture_queue(mon_pdev);
1093 	dp_mon_set_local_pkt_capture_running(mon_pdev, true);
1094 	return status;
1095 }
1096 
1097 QDF_STATUS dp_mon_stop_local_pkt_capture(struct cdp_soc_t *cdp_soc,
1098 					 uint8_t pdev_id)
1099 {
1100 	bool local_pkt_capture_running;
1101 	struct dp_soc *soc = cdp_soc_t_to_dp_soc(cdp_soc);
1102 	struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
1103 	struct dp_mon_pdev *mon_pdev;
1104 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1105 
1106 	if (!pdev) {
1107 		dp_mon_filter_err("pdev Context is null");
1108 		return QDF_STATUS_E_INVAL;
1109 	}
1110 
1111 	mon_pdev = pdev->monitor_pdev;
1112 	local_pkt_capture_running =
1113 			dp_mon_get_is_local_pkt_capture_running(cdp_soc, pdev_id);
1114 	if (!local_pkt_capture_running) {
1115 		dp_mon_filter_err("Local pkt capture is not running");
1116 		return QDF_STATUS_SUCCESS;
1117 	}
1118 
1119 	dp_mon_set_local_pkt_capture_running(mon_pdev, false);
1120 	qdf_spin_lock_bh(&mon_pdev->mon_lock);
1121 	dp_mon_reset_local_pkt_capture_rx_filter(pdev);
1122 	status = dp_mon_filter_update(pdev);
1123 	if (QDF_IS_STATUS_ERROR(status)) {
1124 		dp_mon_filter_err("local pkt capture set rx filter failed");
1125 		qdf_spin_unlock_bh(&mon_pdev->mon_lock);
1126 		return status;
1127 	}
1128 	qdf_spin_unlock_bh(&mon_pdev->mon_lock);
1129 
1130 	qdf_spin_lock_bh(&mon_pdev->mon_lock);
1131 	dp_mon_filter_reset_tx_mon_mode(pdev);
1132 	dp_tx_mon_filter_update(pdev);
1133 	qdf_spin_unlock_bh(&mon_pdev->mon_lock);
1134 	dp_mon_filter_debug("local pkt capture stopped");
1135 
1136 	dp_mon_free_local_pkt_capture_queue(mon_pdev);
1137 
1138 	return QDF_STATUS_SUCCESS;
1139 }
1140 
1141 #endif /* WLAN_FEATURE_LOCAL_PKT_CAPTURE */
1142