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
dp_mon_filter_show_filter_1(struct htt_rx_ring_tlv_filter * tlv_filter)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
dp_mon_filter_show_filter_1(struct htt_rx_ring_tlv_filter * tlv_filter)69 void dp_mon_filter_show_filter_1(struct htt_rx_ring_tlv_filter *tlv_filter)
70 {
71 }
72 #endif
73
dp_mon_filter_show_filter(struct dp_mon_pdev * mon_pdev,enum dp_mon_filter_mode mode,struct dp_mon_filter * filter)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
dp_mon_set_fp_phy_err_filter(struct htt_rx_ring_tlv_filter * tlv_filter,struct dp_mon_filter * mon_filter)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
dp_mon_set_fp_phy_err_filter(struct htt_rx_ring_tlv_filter * tlv_filter,struct dp_mon_filter * mon_filter)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
dp_mon_filter_h2t_setup(struct dp_soc * soc,struct dp_pdev * pdev,enum dp_mon_filter_srng_type srng_type,struct dp_mon_filter * filter)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
dp_mon_skip_filter_config(struct dp_soc * soc)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
dp_update_num_mac_rings(struct dp_soc * soc,int * mon_mac_rings)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
dp_mon_ht2_rx_ring_cfg(struct dp_soc * soc,struct dp_pdev * pdev,enum dp_mon_filter_srng_type srng_type,struct htt_rx_ring_tlv_filter * tlv_filter)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
dp_mon_filter_setup_enhanced_stats(struct dp_pdev * pdev)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
dp_mon_filter_reset_enhanced_stats(struct dp_pdev * pdev)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
dp_mon_filter_setup_undecoded_metadata_mode(struct dp_pdev * pdev)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
dp_mon_filter_reset_undecoded_metadata_mode(struct dp_pdev * pdev)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
dp_mon_filter_setup_mcopy_mode(struct dp_pdev * pdev)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
dp_mon_filter_reset_mcopy_mode(struct dp_pdev * pdev)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)
dp_mon_filter_setup_smart_monitor(struct dp_pdev * pdev)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
dp_mon_filter_reset_smart_monitor(struct dp_pdev * pdev)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
dp_mon_filter_set_reset_mon_mac_filter(struct dp_pdev * pdev,bool val)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
dp_mon_filter_setup_rx_enh_capture(struct dp_pdev * pdev)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
dp_mon_filter_reset_rx_enh_capture(struct dp_pdev * pdev)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
dp_mon_filter_setup_mon_mode(struct dp_pdev * pdev)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
dp_mon_filter_setup_tx_mon_mode(struct dp_pdev * pdev)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
dp_mon_filter_reset_tx_mon_mode(struct dp_pdev * pdev)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
dp_mon_filter_reset_mon_mode(struct dp_pdev * pdev)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)
dp_rx_mon_hdr_length_set(uint32_t * msg_word,struct htt_rx_ring_tlv_filter * tlv_filter)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
dp_rx_mon_hdr_length_set(uint32_t * msg_word,struct htt_rx_ring_tlv_filter * tlv_filter)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
dp_mon_filter_setup_rx_pkt_log_full(struct dp_pdev * pdev)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
dp_mon_filter_reset_rx_pkt_log_full(struct dp_pdev * pdev)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
dp_mon_filter_setup_rx_pkt_log_lite(struct dp_pdev * pdev)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
dp_mon_filter_reset_rx_pkt_log_lite(struct dp_pdev * pdev)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
dp_mon_filter_setup_rx_pkt_log_cbf(struct dp_pdev * pdev)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
dp_mon_filter_reset_rx_pktlog_cbf(struct dp_pdev * pdev)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
dp_mon_filter_setup_pktlog_hybrid(struct dp_pdev * pdev)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
dp_mon_filter_reset_pktlog_hybrid(struct dp_pdev * pdev)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
dp_mon_filter_update(struct dp_pdev * pdev)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
dp_tx_mon_filter_update(struct dp_pdev * pdev)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
dp_mon_filters_reset(struct dp_pdev * pdev)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
dp_mon_filters_reset(struct dp_pdev * pdev)707 void dp_mon_filters_reset(struct dp_pdev *pdev)
708 {
709 }
710 #endif
711
712 void
dp_mon_filter_reset_mon_srng(struct dp_soc * soc,struct dp_pdev * pdev,enum dp_mon_filter_srng_type mon_srng_type)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
dp_mon_filter_adjust(struct dp_pdev * pdev,struct dp_mon_filter * filter)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
dp_mon_filter_set_mon_cmn(struct dp_pdev * pdev,struct dp_mon_filter * filter)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
dp_mon_filter_set_status_cmn(struct dp_mon_pdev * mon_pdev,struct dp_mon_filter * filter)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
dp_mon_filter_set_status_cbf(struct dp_pdev * pdev,struct dp_mon_filter * filter)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
dp_mon_filter_set_cbf_cmn(struct dp_pdev * pdev,struct dp_mon_filter * filter)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
dp_mon_filter_dealloc(struct dp_mon_pdev * mon_pdev)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
dp_mon_filter_alloc(struct dp_mon_pdev * mon_pdev)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
dp_mon_set_local_pkt_capture_running(struct dp_mon_pdev * mon_pdev,bool val)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
dp_mon_get_is_local_pkt_capture_running(struct cdp_soc_t * cdp_soc,uint8_t pdev_id)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
dp_mon_set_local_pkt_capture_rx_filter(struct dp_pdev * pdev,struct cdp_monitor_filter * src_filter)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
dp_mon_clear_local_pkt_capture_rx_filter(struct dp_pdev * pdev)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
dp_mon_reset_local_pkt_capture_rx_filter(struct dp_pdev * pdev)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
dp_mon_init_local_pkt_capture_queue(struct dp_mon_pdev * mon_pdev)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
dp_mon_free_local_pkt_capture_queue(struct dp_mon_pdev * mon_pdev)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
dp_mon_start_local_pkt_capture(struct cdp_soc_t * cdp_soc,uint8_t pdev_id,struct cdp_monitor_filter * filter)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
dp_mon_stop_local_pkt_capture(struct cdp_soc_t * cdp_soc,uint8_t pdev_id)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