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_rx.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 <qdf_flex_mem.h>
28 #include "qdf_nbuf_frag.h"
29 #include "dp_mon.h"
30 #include <dp_rx_mon.h>
31 #include <dp_mon_2.0.h>
32 #include <dp_rx_mon.h>
33 #include <dp_rx_mon_2.0.h>
34 #include <dp_rx.h>
35 #include <dp_be.h>
36 #include <hal_be_api_mon.h>
37 #ifdef QCA_SUPPORT_LITE_MONITOR
38 #include "dp_lite_mon.h"
39 #endif
40
41 #define F_MASK 0xFFFF
42 #define TEST_MASK 0xCBF
43
44 #ifdef MONITOR_TLV_RECORDING_ENABLE
45 /**
46 * dp_mon_record_index_update() - update the indexes of dp_mon_tlv_logger
47 * to store next tlv
48 *
49 * @mon_pdev_be: pointer to dp_mon_pdev_be
50 *
51 * Return
52 */
53 void
dp_mon_record_index_update(struct dp_mon_pdev_be * mon_pdev_be)54 dp_mon_record_index_update(struct dp_mon_pdev_be *mon_pdev_be)
55 {
56 struct dp_mon_tlv_logger *tlv_log = NULL;
57 struct dp_mon_tlv_info *tlv_info = NULL;
58
59 if (!mon_pdev_be || !(mon_pdev_be->rx_tlv_log))
60 return;
61
62 tlv_log = mon_pdev_be->rx_tlv_log;
63 if (!tlv_log->tlv_logging_enable || !(tlv_log->buff))
64 return;
65
66 tlv_info = (struct dp_mon_tlv_info *)tlv_log->buff;
67
68 (tlv_log->curr_ppdu_pos + 1 == MAX_NUM_PPDU_RECORD) ?
69 tlv_log->curr_ppdu_pos = 0 :
70 tlv_log->curr_ppdu_pos++;
71
72 tlv_log->wrap_flag = 0;
73 tlv_log->ppdu_start_idx = tlv_log->curr_ppdu_pos *
74 MAX_TLVS_PER_PPDU;
75 tlv_log->mpdu_idx = tlv_log->ppdu_start_idx +
76 MAX_PPDU_START_TLV_NUM;
77 tlv_log->ppdu_end_idx = tlv_log->mpdu_idx + MAX_MPDU_TLV_NUM;
78 tlv_log->max_ppdu_start_idx = tlv_log->ppdu_start_idx +
79 MAX_PPDU_START_TLV_NUM - 1;
80 tlv_log->max_mpdu_idx = tlv_log->mpdu_idx +
81 MAX_MPDU_TLV_NUM - 1;
82 tlv_log->max_ppdu_end_idx = tlv_log->ppdu_end_idx +
83 MAX_PPDU_END_TLV_NUM - 1;
84 }
85
86 /**
87 * dp_mon_record_tlv() - Store the contents of the tlv in buffer
88 *
89 * @mon_pdev_be: pointe to dp_mon_pdev_be
90 * @ppdu_info: struct hal_rx_ppdu_info
91 *
92 * Return
93 */
94 void
dp_mon_record_tlv(struct dp_mon_pdev_be * mon_pdev_be,struct hal_rx_ppdu_info * ppdu_info)95 dp_mon_record_tlv(struct dp_mon_pdev_be *mon_pdev_be,
96 struct hal_rx_ppdu_info *ppdu_info)
97 {
98 struct dp_mon_tlv_logger *tlv_log = NULL;
99 struct dp_mon_tlv_info *tlv_info = NULL;
100 uint32_t tlv_tag;
101 uint16_t *ppdu_start_idx = NULL;
102 uint16_t *mpdu_idx = NULL;
103 uint16_t *ppdu_end_idx = NULL;
104
105 if (!mon_pdev_be || !(mon_pdev_be->rx_tlv_log))
106 return;
107
108 tlv_log = mon_pdev_be->rx_tlv_log;
109 if (!tlv_log->tlv_logging_enable || !(tlv_log->buff))
110 return;
111
112 tlv_info = (struct dp_mon_tlv_info *)tlv_log->buff;
113 ppdu_start_idx = &tlv_log->ppdu_start_idx;
114 mpdu_idx = &tlv_log->mpdu_idx;
115 ppdu_end_idx = &tlv_log->ppdu_end_idx;
116
117 tlv_tag = ppdu_info->rx_tlv_info.tlv_tag;
118 if (ppdu_info->rx_tlv_info.tlv_category == CATEGORY_PPDU_START) {
119 tlv_info[*ppdu_start_idx].tlv_tag = tlv_tag;
120 switch (tlv_tag) {
121 case WIFIRX_PPDU_START_E:
122 tlv_info[*ppdu_start_idx].
123 data.ppdu_start.ppdu_id =
124 ppdu_info->com_info.ppdu_id;
125 break;
126 case WIFIRX_PPDU_START_USER_INFO_E:
127 tlv_info[*ppdu_start_idx].
128 data.ppdu_start_user_info.user_id =
129 ppdu_info->user_id;
130 tlv_info[*ppdu_start_idx].
131 data.ppdu_start_user_info.rate_mcs =
132 ppdu_info->rx_status.mcs;
133 tlv_info[*ppdu_start_idx].
134 data.ppdu_start_user_info.nss =
135 ppdu_info->rx_status.nss;
136 tlv_info[*ppdu_start_idx].
137 data.ppdu_start_user_info.reception_type =
138 ppdu_info->rx_status.reception_type;
139 tlv_info[*ppdu_start_idx].
140 data.ppdu_start_user_info.sgi =
141 ppdu_info->rx_status.sgi;
142 break;
143 }
144 if (*ppdu_start_idx < tlv_log->max_ppdu_start_idx)
145 (*ppdu_start_idx)++;
146 } else if (ppdu_info->rx_tlv_info.tlv_category == CATEGORY_MPDU) {
147 tlv_info[*mpdu_idx].tlv_tag = tlv_tag;
148 switch (tlv_tag) {
149 case WIFIRX_MPDU_START_E:
150 tlv_info[*mpdu_idx].
151 data.mpdu_start.user_id =
152 ppdu_info->user_id;
153 tlv_info[*mpdu_idx].
154 data.mpdu_start.wrap_flag =
155 tlv_log->wrap_flag;
156 break;
157 case WIFIRX_MPDU_END_E:
158 tlv_info[*mpdu_idx].
159 data.mpdu_end.user_id =
160 ppdu_info->user_id;
161 tlv_info[*mpdu_idx].
162 data.mpdu_end.fcs_err =
163 ppdu_info->fcs_err;
164 tlv_info[*mpdu_idx].
165 data.mpdu_end.wrap_flag =
166 tlv_log->wrap_flag;
167 break;
168 case WIFIRX_HEADER_E:
169 tlv_info[*mpdu_idx].
170 data.header.wrap_flag =
171 tlv_log->wrap_flag;
172 break;
173 case WIFIRX_MSDU_END_E:
174 tlv_info[*mpdu_idx].
175 data.msdu_end.user_id =
176 ppdu_info->user_id;
177 tlv_info[*mpdu_idx].
178 data.msdu_end.wrap_flag =
179 tlv_log->wrap_flag;
180 break;
181 case WIFIMON_BUFFER_ADDR_E:
182 tlv_info[*mpdu_idx].
183 data.mon_buffer_addr.dma_length =
184 ppdu_info->packet_info.dma_length;
185 tlv_info[*mpdu_idx].
186 data.mon_buffer_addr.truncation =
187 ppdu_info->packet_info.truncated;
188 tlv_info[*mpdu_idx].
189 data.mon_buffer_addr.continuation =
190 ppdu_info->packet_info.msdu_continuation;
191 tlv_info[*mpdu_idx].
192 data.mon_buffer_addr.wrap_flag =
193 tlv_log->wrap_flag;
194 break;
195 }
196 if (*mpdu_idx < tlv_log->max_mpdu_idx) {
197 (*mpdu_idx)++;
198 } else {
199 *mpdu_idx = *mpdu_idx - MAX_MPDU_TLV_NUM + 1;
200 tlv_log->wrap_flag ^= 1;
201 }
202 } else if (ppdu_info->rx_tlv_info.tlv_category == CATEGORY_PPDU_END) {
203 tlv_info[*ppdu_end_idx].tlv_tag = tlv_tag;
204 switch (tlv_tag) {
205 case WIFIRX_USER_PPDU_END_E:
206 break;
207 case WIFIRX_PPDU_END_E:
208 break;
209 case WIFIPHYRX_RSSI_LEGACY_E:
210 break;
211 case WIFIPHYRX_L_SIG_B_E:
212 break;
213 case WIFIPHYRX_COMMON_USER_INFO_E:
214 break;
215 case WIFIPHYRX_DATA_DONE_E:
216 break;
217 case WIFIPHYRX_PKT_END_PART1_E:
218 break;
219 case WIFIPHYRX_PKT_END_E:
220 break;
221 case WIFIRXPCU_PPDU_END_INFO_E:
222 break;
223 case WIFIRX_PPDU_END_USER_STATS_E:
224 break;
225 case WIFIRX_PPDU_END_STATUS_DONE_E:
226 break;
227 }
228 if (*ppdu_end_idx < tlv_log->max_ppdu_end_idx)
229 (*ppdu_end_idx)++;
230 }
231 }
232
233 /**
234 * dp_mon_record_clear_buffer() - Clear the buffer to record next PPDU
235 *
236 * @mon_pdev_be: pointer to dp_mon_pdev_be
237 *
238 * Return
239 */
240 void
dp_mon_record_clear_buffer(struct dp_mon_pdev_be * mon_pdev_be)241 dp_mon_record_clear_buffer(struct dp_mon_pdev_be *mon_pdev_be)
242 {
243 struct dp_mon_tlv_logger *tlv_log = NULL;
244 struct dp_mon_tlv_info *tlv_info = NULL;
245
246 if (!mon_pdev_be || !(mon_pdev_be->rx_tlv_log))
247 return;
248
249 tlv_log = mon_pdev_be->rx_tlv_log;
250 if (!tlv_log->tlv_logging_enable || !(tlv_log->buff))
251 return;
252
253 tlv_info = (struct dp_mon_tlv_info *)tlv_log->buff;
254 qdf_mem_zero(&tlv_info[tlv_log->ppdu_start_idx],
255 MAX_TLVS_PER_PPDU * sizeof(struct dp_mon_tlv_info));
256 }
257 #else
258 void
dp_mon_record_index_update(struct dp_mon_pdev_be * mon_pdev_be)259 dp_mon_record_index_update(struct dp_mon_pdev_be *mon_pdev_be)
260 {
261 }
262
263 void
dp_mon_record_tlv(struct dp_mon_pdev_be * mon_pdev_be,struct hal_rx_ppdu_info * ppdu_info)264 dp_mon_record_tlv(struct dp_mon_pdev_be *mon_pdev_be,
265 struct hal_rx_ppdu_info *ppdu_info)
266 {
267 }
268
269 void
dp_mon_record_clear_buffer(struct dp_mon_pdev_be * mon_pdev_be)270 dp_mon_record_clear_buffer(struct dp_mon_pdev_be *mon_pdev_be)
271 {
272 }
273
274 #endif
275
276 /**
277 * dp_rx_mon_update_drop_cnt() - Update drop statistics
278 *
279 * @mon_pdev: monitor pdev
280 * @hal_mon_rx_desc: HAL monitor desc
281 *
282 * Return: void
283 */
284 static inline void
dp_rx_mon_update_drop_cnt(struct dp_mon_pdev * mon_pdev,struct hal_mon_desc * hal_mon_rx_desc)285 dp_rx_mon_update_drop_cnt(struct dp_mon_pdev *mon_pdev,
286 struct hal_mon_desc *hal_mon_rx_desc)
287 {
288 mon_pdev->rx_mon_stats.empty_desc_ppdu++;
289 mon_pdev->rx_mon_stats.ppdu_drop_cnt +=
290 hal_mon_rx_desc->ppdu_drop_count;
291 mon_pdev->rx_mon_stats.mpdu_drop_cnt +=
292 hal_mon_rx_desc->mpdu_drop_count;
293 if (hal_mon_rx_desc->end_of_ppdu_dropped)
294 mon_pdev->rx_mon_stats.end_of_ppdu_drop_cnt++;
295 mon_pdev->rx_mon_stats.tlv_drop_cnt +=
296 hal_mon_rx_desc->tlv_drop_count;
297 }
298
299 #ifdef QCA_MONITOR_2_0_PKT_SUPPORT
300 #if defined(WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG) &&\
301 defined(WLAN_SUPPORT_RX_TAG_STATISTICS)
302 /** dp_mon_rx_update_rx_protocol_tag_stats() - Update mon protocols's
303 * statistics
304 * @pdev: pdev handle
305 * @protocol_index: Protocol index for which the stats should be incremented
306 * @ring_index: REO ring number from which this tag was received.
307 *
308 * Return: void
309 */
dp_mon_rx_update_rx_protocol_tag_stats(struct dp_pdev * pdev,uint16_t protocol_index)310 static void dp_mon_rx_update_rx_protocol_tag_stats(struct dp_pdev *pdev,
311 uint16_t protocol_index)
312 {
313 pdev->mon_proto_tag_stats[protocol_index].tag_ctr++;
314 }
315
316 #ifdef QCA_TEST_MON_PF_TAGS_STATS
317
318 static
dp_rx_mon_print_tag_buf(uint8_t * buf,uint16_t room)319 void dp_rx_mon_print_tag_buf(uint8_t *buf, uint16_t room)
320 {
321 print_hex_dump(KERN_ERR, "TLV BUFFER: ", DUMP_PREFIX_NONE,
322 32, 2, buf, room, false);
323 }
324
325 #else
326 static
dp_rx_mon_print_tag_buf(uint8_t * buf,uint16_t room)327 void dp_rx_mon_print_tag_buf(uint8_t *buf, uint16_t room)
328 {
329 }
330 #endif
331
332 void
dp_rx_mon_shift_pf_tag_in_headroom(qdf_nbuf_t nbuf,struct dp_soc * soc,struct hal_rx_ppdu_info * ppdu_info)333 dp_rx_mon_shift_pf_tag_in_headroom(qdf_nbuf_t nbuf, struct dp_soc *soc,
334 struct hal_rx_ppdu_info *ppdu_info)
335 {
336 uint32_t room = 0;
337 uint16_t msdu_count = 0;
338 uint16_t *dp = NULL;
339 uint16_t *hp = NULL;
340 uint16_t tlv_data_len, total_tlv_len;
341 uint32_t bytes = 0;
342
343 if (qdf_unlikely(!soc)) {
344 dp_mon_err("Soc[%pK] Null. Can't update pftag to nbuf headroom",
345 soc);
346 return;
347 }
348
349 if (!wlan_cfg_is_rx_mon_protocol_flow_tag_enabled(soc->wlan_cfg_ctx))
350 return;
351
352 if (qdf_unlikely(!nbuf))
353 return;
354
355 /* Headroom must be have enough space for tlv to be added*/
356 if (qdf_unlikely(qdf_nbuf_headroom(nbuf) < DP_RX_MON_TLV_ROOM)) {
357 dp_mon_err("Headroom[%d] < DP_RX_MON_TLV_ROOM[%d]",
358 qdf_nbuf_headroom(nbuf), DP_RX_MON_TLV_ROOM);
359 return;
360 }
361
362 hp = (uint16_t *)qdf_nbuf_head(nbuf);
363 msdu_count = *hp;
364
365 if (qdf_unlikely(!msdu_count))
366 return;
367
368 dp_mon_debug("msdu_count: %d", msdu_count);
369
370 room = DP_RX_MON_PF_TAG_LEN_PER_FRAG * msdu_count;
371 tlv_data_len = DP_RX_MON_TLV_MSDU_CNT + (room);
372 total_tlv_len = DP_RX_MON_TLV_HDR_LEN + tlv_data_len;
373
374 //1. store space for MARKER
375 dp = (uint16_t *)qdf_nbuf_push_head(nbuf, sizeof(uint16_t));
376 if (qdf_likely(dp)) {
377 *(uint16_t *)dp = DP_RX_MON_TLV_HDR_MARKER;
378 bytes += sizeof(uint16_t);
379 }
380
381 //2. store space for total size
382 dp = (uint16_t *)qdf_nbuf_push_head(nbuf, sizeof(uint16_t));
383 if (qdf_likely(dp)) {
384 *(uint16_t *)dp = total_tlv_len;
385 bytes += sizeof(uint16_t);
386 }
387
388 //create TLV
389 bytes += dp_mon_rx_add_tlv(DP_RX_MON_TLV_PF_ID, tlv_data_len, hp, nbuf);
390
391 dp_rx_mon_print_tag_buf(qdf_nbuf_data(nbuf), total_tlv_len);
392
393 qdf_nbuf_pull_head(nbuf, bytes);
394
395 }
396
397 void
dp_rx_mon_pf_tag_to_buf_headroom_2_0(void * nbuf,struct hal_rx_ppdu_info * ppdu_info,struct dp_pdev * pdev,struct dp_soc * soc)398 dp_rx_mon_pf_tag_to_buf_headroom_2_0(void *nbuf,
399 struct hal_rx_ppdu_info *ppdu_info,
400 struct dp_pdev *pdev, struct dp_soc *soc)
401 {
402 uint8_t *nbuf_head = NULL;
403 uint8_t user_id;
404 struct hal_rx_mon_msdu_info *msdu_info;
405 uint16_t flow_id;
406 uint16_t cce_metadata;
407 uint16_t protocol_tag = 0;
408 uint32_t flow_tag;
409 uint8_t invalid_cce = 0, invalid_fse = 0;
410
411 if (qdf_unlikely(!soc)) {
412 dp_mon_err("Soc[%pK] Null. Can't update pftag to nbuf headroom",
413 soc);
414 return;
415 }
416
417 if (!wlan_cfg_is_rx_mon_protocol_flow_tag_enabled(soc->wlan_cfg_ctx))
418 return;
419
420 if (qdf_unlikely(!nbuf))
421 return;
422
423 /* Headroom must be have enough space for tlv to be added*/
424 if (qdf_unlikely(qdf_nbuf_headroom(nbuf) < DP_RX_MON_TLV_ROOM)) {
425 dp_mon_err("Headroom[%d] < DP_RX_MON_TLV_ROOM[%d]",
426 qdf_nbuf_headroom(nbuf), DP_RX_MON_TLV_ROOM);
427 return;
428 }
429
430 user_id = ppdu_info->user_id;
431 if (qdf_unlikely(user_id >= HAL_MAX_UL_MU_USERS)) {
432 dp_mon_debug("Invalid user_id user_id: %d pdev: %pK", user_id, pdev);
433 return;
434 }
435
436 msdu_info = &ppdu_info->msdu[user_id];
437 flow_id = ppdu_info->rx_msdu_info[user_id].flow_idx;
438 cce_metadata = ppdu_info->rx_msdu_info[user_id].cce_metadata -
439 RX_PROTOCOL_TAG_START_OFFSET;
440
441 flow_tag = ppdu_info->rx_msdu_info[user_id].fse_metadata & F_MASK;
442
443 if (qdf_unlikely((cce_metadata > RX_PROTOCOL_TAG_MAX - 1) ||
444 (cce_metadata > 0 && cce_metadata < 4))) {
445 dp_mon_debug("Invalid user_id cce_metadata: %d pdev: %pK", cce_metadata, pdev);
446 invalid_cce = 1;
447 protocol_tag = cce_metadata;
448 } else {
449 protocol_tag = pdev->rx_proto_tag_map[cce_metadata].tag;
450 dp_mon_rx_update_rx_protocol_tag_stats(pdev, cce_metadata);
451 }
452
453 if (flow_tag > 0) {
454 dp_mon_rx_update_rx_flow_tag_stats(pdev, flow_id);
455 } else {
456 dp_mon_debug("Invalid flow_tag: %d pdev: %pK ", flow_tag, pdev);
457 invalid_fse = 1;
458 }
459
460 if (invalid_cce && invalid_fse)
461 return;
462
463 if (msdu_info->msdu_index >= DP_RX_MON_MAX_MSDU) {
464 dp_mon_err("msdu_index causes overflow in headroom");
465 return;
466 }
467
468 dp_mon_debug("protocol_tag: %d, cce_metadata: %d, flow_tag: %d",
469 protocol_tag, cce_metadata, flow_tag);
470
471 dp_mon_debug("msdu_index: %d", msdu_info->msdu_index);
472
473
474 nbuf_head = qdf_nbuf_head(nbuf);
475
476 *((uint16_t *)nbuf_head) = msdu_info->msdu_index + 1;
477 nbuf_head += DP_RX_MON_TLV_MSDU_CNT;
478
479 nbuf_head += ((msdu_info->msdu_index) * DP_RX_MON_PF_TAG_SIZE);
480 if (!invalid_cce)
481 *((uint16_t *)nbuf_head) = protocol_tag;
482 nbuf_head += sizeof(uint16_t);
483 if (!invalid_fse)
484 *((uint16_t *)nbuf_head) = flow_tag;
485 }
486
487 #else
488 static inline void
dp_mon_rx_update_rx_protocol_tag_stats(struct dp_pdev * pdev,uint16_t protocol_index)489 dp_mon_rx_update_rx_protocol_tag_stats(struct dp_pdev *pdev,
490 uint16_t protocol_index)
491 {
492 }
493
494 static inline
dp_rx_mon_shift_pf_tag_in_headroom(qdf_nbuf_t nbuf,struct dp_soc * soc,struct hal_rx_ppdu_info * ppdu_info)495 void dp_rx_mon_shift_pf_tag_in_headroom(qdf_nbuf_t nbuf, struct dp_soc *soc,
496 struct hal_rx_ppdu_info *ppdu_info)
497 {
498 }
499
500 static inline
dp_rx_mon_pf_tag_to_buf_headroom_2_0(void * nbuf,struct hal_rx_ppdu_info * ppdu_info,struct dp_pdev * pdev,struct dp_soc * soc)501 void dp_rx_mon_pf_tag_to_buf_headroom_2_0(void *nbuf,
502 struct hal_rx_ppdu_info *ppdu_info,
503 struct dp_pdev *pdev,
504 struct dp_soc *soc)
505 {
506 }
507
508 #endif
509
510 #ifdef QCA_KMEM_CACHE_SUPPORT
dp_rx_mon_ppdu_info_cache_create(struct dp_pdev * pdev)511 QDF_STATUS dp_rx_mon_ppdu_info_cache_create(struct dp_pdev *pdev)
512 {
513 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
514 struct dp_mon_pdev_be *mon_pdev_be =
515 dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
516 uint16_t obj;
517 struct hal_rx_ppdu_info *ppdu_info = NULL;
518
519 mon_pdev_be->ppdu_info_cache =
520 qdf_kmem_cache_create("rx_mon_ppdu_info_cache",
521 sizeof(struct hal_rx_ppdu_info));
522
523 if (!mon_pdev_be->ppdu_info_cache) {
524 dp_mon_err("cache creation failed pdev :%px", pdev);
525 return QDF_STATUS_E_NOMEM;
526 }
527
528 TAILQ_INIT(&mon_pdev_be->rx_mon_free_queue);
529 for (obj = 0; obj < DP_RX_MON_WQ_THRESHOLD; obj++) {
530 ppdu_info = (struct hal_rx_ppdu_info *)qdf_kmem_cache_alloc(mon_pdev_be->ppdu_info_cache);
531
532 if (ppdu_info) {
533 qdf_mem_zero(ppdu_info, sizeof(struct hal_rx_ppdu_info));
534 TAILQ_INSERT_TAIL(&mon_pdev_be->rx_mon_free_queue,
535 ppdu_info,
536 ppdu_free_list_elem);
537 mon_pdev_be->total_free_elem++;
538 }
539 }
540 qdf_spinlock_create(&mon_pdev_be->ppdu_info_lock);
541
542 return QDF_STATUS_SUCCESS;
543 }
544
dp_rx_mon_ppdu_info_cache_destroy(struct dp_pdev * pdev)545 void dp_rx_mon_ppdu_info_cache_destroy(struct dp_pdev *pdev)
546 {
547 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
548 struct dp_mon_pdev_be *mon_pdev_be =
549 dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
550 struct hal_rx_ppdu_info *ppdu_info = NULL, *temp_ppdu_info = NULL;
551
552 qdf_spin_lock(&mon_pdev_be->ppdu_info_lock);
553 TAILQ_FOREACH_SAFE(ppdu_info,
554 &mon_pdev_be->rx_mon_free_queue,
555 ppdu_free_list_elem,
556 temp_ppdu_info) {
557 TAILQ_REMOVE(&mon_pdev_be->rx_mon_free_queue,
558 ppdu_info, ppdu_free_list_elem);
559 if (ppdu_info) {
560 mon_pdev_be->total_free_elem--;
561 qdf_kmem_cache_free(mon_pdev_be->ppdu_info_cache,
562 ppdu_info);
563 }
564 }
565 qdf_spin_unlock(&mon_pdev_be->ppdu_info_lock);
566 dp_mon_debug(" total free element: %d", mon_pdev_be->total_free_elem);
567 qdf_kmem_cache_destroy(mon_pdev_be->ppdu_info_cache);
568 }
569 #endif
570
dp_rx_mon_init_wq_sm(struct dp_pdev * pdev)571 static QDF_STATUS dp_rx_mon_init_wq_sm(struct dp_pdev *pdev)
572 {
573 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
574 struct dp_mon_pdev_be *mon_pdev_be =
575 dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
576
577 qdf_create_work(0, &mon_pdev_be->rx_mon_work,
578 dp_rx_mon_process_ppdu, pdev);
579 mon_pdev_be->rx_mon_workqueue =
580 qdf_alloc_unbound_workqueue("rx_mon_work_queue");
581
582 if (!mon_pdev_be->rx_mon_workqueue) {
583 dp_mon_err("failed to create rxmon wq mon_pdev: %pK", mon_pdev);
584 goto fail;
585 }
586 TAILQ_INIT(&mon_pdev_be->rx_mon_queue);
587
588 qdf_spinlock_create(&mon_pdev_be->rx_mon_wq_lock);
589 return QDF_STATUS_SUCCESS;
590
591 fail:
592 return QDF_STATUS_E_FAILURE;
593 }
594
dp_rx_mon_deinit_wq_sm(struct dp_pdev * pdev)595 static QDF_STATUS dp_rx_mon_deinit_wq_sm(struct dp_pdev *pdev)
596 {
597 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
598 struct dp_mon_pdev_be *mon_pdev_be =
599 dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
600
601 if (!mon_pdev_be->rx_mon_workqueue)
602 return QDF_STATUS_E_FAILURE;
603
604 qdf_err(" total free element: %d", mon_pdev_be->total_free_elem);
605 qdf_flush_workqueue(0, mon_pdev_be->rx_mon_workqueue);
606 qdf_destroy_workqueue(0, mon_pdev_be->rx_mon_workqueue);
607 qdf_flush_work(&mon_pdev_be->rx_mon_work);
608 qdf_disable_work(&mon_pdev_be->rx_mon_work);
609 dp_rx_mon_drain_wq(pdev);
610 mon_pdev_be->rx_mon_workqueue = NULL;
611 qdf_spinlock_destroy(&mon_pdev_be->rx_mon_wq_lock);
612
613 return QDF_STATUS_SUCCESS;
614 }
615
616 static
dp_rx_mon_set_zero(qdf_nbuf_t nbuf)617 void dp_rx_mon_set_zero(qdf_nbuf_t nbuf)
618 {
619 qdf_mem_zero(qdf_nbuf_head(nbuf), DP_RX_MON_TLV_ROOM);
620 }
621
622 /**
623 * dp_rx_mon_nbuf_add_rx_frag() - Add frag to SKB
624 *
625 * @nbuf: SKB to which frag is going to be added
626 * @frag: frag to be added to SKB
627 * @frag_len: frag length
628 * @offset: frag offset
629 * @buf_size: buffer size
630 * @frag_ref: take frag ref
631 *
632 * Return: QDF_STATUS
633 */
634 static inline QDF_STATUS
dp_rx_mon_nbuf_add_rx_frag(qdf_nbuf_t nbuf,qdf_frag_t * frag,uint16_t frag_len,uint16_t offset,uint16_t buf_size,bool frag_ref)635 dp_rx_mon_nbuf_add_rx_frag(qdf_nbuf_t nbuf, qdf_frag_t *frag,
636 uint16_t frag_len, uint16_t offset,
637 uint16_t buf_size, bool frag_ref)
638 {
639 uint8_t num_frags;
640
641 num_frags = qdf_nbuf_get_nr_frags(nbuf);
642 if (num_frags < QDF_NBUF_MAX_FRAGS) {
643 qdf_nbuf_add_rx_frag(frag, nbuf,
644 offset,
645 frag_len,
646 buf_size,
647 frag_ref);
648 return QDF_STATUS_SUCCESS;
649 }
650 return QDF_STATUS_E_FAILURE;
651 }
652
653 /**
654 * dp_rx_mon_handle_mpdu_end() - Process MPDU_END TLV
655 *
656 * @ppdu_info: PPDU info
657 *
658 * Return: void
659 */
660 static inline void
dp_rx_mon_handle_mpdu_end(struct hal_rx_ppdu_info * ppdu_info)661 dp_rx_mon_handle_mpdu_end(struct hal_rx_ppdu_info *ppdu_info)
662 {
663 struct hal_rx_mon_mpdu_info *mpdu_info, *mpdu_meta;
664 qdf_nbuf_t nbuf;
665 uint8_t user_id = ppdu_info->user_id;
666 uint8_t mpdu_idx = ppdu_info->mpdu_count[user_id];
667
668 mpdu_info = &ppdu_info->mpdu_info[user_id];
669 if (qdf_unlikely(!ppdu_info->rx_hdr_rcvd[user_id])) {
670 /* reset mpdu info for next mpdu for same user */
671 qdf_mem_zero(mpdu_info, sizeof(*mpdu_info));
672 dp_mon_debug(" <%d> nbuf is NULL, return user: %d mpdu_idx: %d",
673 __LINE__, user_id, mpdu_idx);
674 return;
675 }
676 nbuf = qdf_nbuf_queue_last(&ppdu_info->mpdu_q[user_id]);
677 if (qdf_unlikely(!nbuf)) {
678 dp_mon_debug("nbuf is NULL");
679 return;
680 }
681 mpdu_meta = (struct hal_rx_mon_mpdu_info *)qdf_nbuf_data(nbuf);
682 mpdu_meta->mpdu_length_err = mpdu_info->mpdu_length_err;
683 mpdu_meta->fcs_err = mpdu_info->fcs_err;
684 mpdu_meta->overflow_err = mpdu_info->overflow_err;
685 mpdu_meta->decrypt_err = mpdu_info->decrypt_err;
686 mpdu_meta->full_pkt = mpdu_info->full_pkt;
687 mpdu_meta->truncated = mpdu_info->truncated;
688
689 /* reset mpdu info for next mpdu for same user */
690 qdf_mem_zero(mpdu_info, sizeof(*mpdu_info));
691 ppdu_info->mpdu_info[ppdu_info->user_id].mpdu_start_received = false;
692 ppdu_info->mpdu_count[user_id]++;
693 }
694
695 /**
696 * dp_rx_mon_handle_mpdu_start() - Process MPDU_START TLV
697 *
698 * @ppdu_info: PPDU info
699 *
700 * Return: void
701 */
702 static inline void
dp_rx_mon_handle_mpdu_start(struct hal_rx_ppdu_info * ppdu_info)703 dp_rx_mon_handle_mpdu_start(struct hal_rx_ppdu_info *ppdu_info)
704 {
705 struct hal_rx_mon_mpdu_info *mpdu_info, *mpdu_meta;
706 qdf_nbuf_t nbuf;
707 uint8_t user_id = ppdu_info->user_id;
708 uint8_t mpdu_idx = ppdu_info->mpdu_count[user_id];
709
710 if (qdf_unlikely(!ppdu_info->rx_hdr_rcvd[user_id])) {
711 dp_mon_debug(" <%d> nbuf is NULL, return user: %d mpdu_idx: %d", __LINE__, user_id, mpdu_idx);
712 return;
713 }
714 nbuf = qdf_nbuf_queue_last(&ppdu_info->mpdu_q[user_id]);
715 if (qdf_unlikely(!nbuf)) {
716 dp_mon_debug("nbuf is NULL");
717 return;
718 }
719 mpdu_meta = (struct hal_rx_mon_mpdu_info *)qdf_nbuf_data(nbuf);
720 mpdu_info = &ppdu_info->mpdu_info[user_id];
721 mpdu_meta->decap_type = mpdu_info->decap_type;
722 ppdu_info->mpdu_info[ppdu_info->user_id].mpdu_start_received = true;
723 }
724
725 /**
726 * dp_rx_mon_handle_msdu_end() - Process MSDU_END TLV
727 *
728 * @pdev: DP Pdev
729 * @ppdu_info: PPDU info
730 *
731 * Return: void
732 */
733 static inline void
dp_rx_mon_handle_msdu_end(struct dp_pdev * pdev,struct hal_rx_ppdu_info * ppdu_info)734 dp_rx_mon_handle_msdu_end(struct dp_pdev *pdev,
735 struct hal_rx_ppdu_info *ppdu_info)
736 {
737 qdf_nbuf_t nbuf;
738 qdf_frag_t addr;
739 uint16_t num_frags;
740 struct hal_rx_mon_msdu_info *msdu_info;
741 struct hal_rx_mon_msdu_info *last_buf_info;
742 uint8_t user_id = ppdu_info->user_id;
743 uint8_t mpdu_idx = ppdu_info->mpdu_count[user_id];
744
745 msdu_info = &ppdu_info->msdu[user_id];
746 /* update msdu metadata at last buffer of msdu in MPDU */
747 if (qdf_unlikely(!ppdu_info->rx_hdr_rcvd[user_id])) {
748 /* reset msdu info for next msdu for same user */
749 qdf_mem_zero(msdu_info, sizeof(*msdu_info));
750 dp_mon_debug(" <%d> nbuf is NULL, return user: %d mpdu_idx: %d",
751 __LINE__, user_id, mpdu_idx);
752 return;
753 }
754 nbuf = qdf_nbuf_queue_last(&ppdu_info->mpdu_q[user_id]);
755 if (qdf_unlikely(!nbuf)) {
756 dp_mon_debug("nbuf is NULL");
757 return;
758 }
759 num_frags = qdf_nbuf_get_nr_frags(nbuf);
760 if (ppdu_info->mpdu_info[user_id].decap_type ==
761 HAL_HW_RX_DECAP_FORMAT_RAW) {
762 return;
763 }
764 /* This points to last buffer of MSDU . update metadata here */
765 addr = qdf_nbuf_get_frag_addr(nbuf, num_frags - 1) -
766 DP_RX_MON_PACKET_OFFSET;
767 last_buf_info = addr;
768
769 last_buf_info->first_msdu = msdu_info->first_msdu;
770 last_buf_info->last_msdu = msdu_info->last_msdu;
771 last_buf_info->decap_type = msdu_info->decap_type;
772 last_buf_info->msdu_index = msdu_info->msdu_index;
773 last_buf_info->user_rssi = msdu_info->user_rssi;
774 last_buf_info->reception_type = msdu_info->reception_type;
775 last_buf_info->msdu_len = msdu_info->msdu_len;
776
777 /* If flow classification is enabled,
778 * update protocol and flow tag to buf headroom
779 */
780 dp_rx_mon_pf_tag_to_buf_headroom_2_0(nbuf, ppdu_info, pdev, pdev->soc);
781
782 /* reset msdu info for next msdu for same user */
783 qdf_mem_zero(msdu_info, sizeof(*msdu_info));
784 }
785
786 /**
787 * dp_rx_mon_handle_mon_buf_addr() - Process MON BUF ADDR TLV
788 *
789 * @pdev: DP Pdev
790 * @ppdu_info: PPDU info
791 * @desc_list: desc list head
792 * @tail: desc list tail
793 *
794 * Return: number of buffers reaped
795 */
796 static inline uint16_t
dp_rx_mon_handle_mon_buf_addr(struct dp_pdev * pdev,struct hal_rx_ppdu_info * ppdu_info,union dp_mon_desc_list_elem_t ** desc_list,union dp_mon_desc_list_elem_t ** tail)797 dp_rx_mon_handle_mon_buf_addr(struct dp_pdev *pdev,
798 struct hal_rx_ppdu_info *ppdu_info,
799 union dp_mon_desc_list_elem_t **desc_list,
800 union dp_mon_desc_list_elem_t **tail)
801 {
802 struct dp_soc *soc = pdev->soc;
803 struct dp_mon_soc *mon_soc = soc->monitor_soc;
804 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
805 struct dp_mon_pdev_be *mon_pdev_be =
806 dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
807 struct hal_rx_mon_msdu_info *buf_info;
808 struct hal_mon_packet_info *packet_info = &ppdu_info->packet_info;
809 struct dp_mon_desc *mon_desc = (struct dp_mon_desc *)(uintptr_t)ppdu_info->packet_info.sw_cookie;
810 unsigned long long desc = ppdu_info->packet_info.sw_cookie;
811 struct hal_rx_mon_mpdu_info *mpdu_info;
812 qdf_nbuf_t nbuf, tmp_nbuf;
813 qdf_frag_t addr;
814 uint16_t frag_idx = 0;
815 uint16_t num_buf_reaped = 0;
816 uint8_t user_id = ppdu_info->user_id;
817 bool rx_hdr_valid = true;
818 uint32_t cookie_2;
819
820 if (!mon_pdev->monitor_configured &&
821 !dp_lite_mon_is_rx_enabled(mon_pdev)) {
822 return num_buf_reaped;
823 }
824
825 if (qdf_unlikely(user_id >= HAL_MAX_UL_MU_USERS ||
826 ppdu_info->hdr_len > DP_RX_MON_MAX_RX_HEADER_LEN))
827 rx_hdr_valid = false;
828
829 cookie_2 = DP_MON_GET_COOKIE(desc);
830 mon_desc = DP_MON_GET_DESC(desc);
831 qdf_assert_always(mon_desc);
832
833 if (mon_desc->cookie_2 != cookie_2) {
834 mon_pdev->rx_mon_stats.dup_mon_sw_desc++;
835 qdf_err("duplicate cookie found mon_desc:%pK", mon_desc);
836 qdf_assert_always(0);
837 }
838
839 if (mon_desc->magic != DP_MON_DESC_MAGIC)
840 qdf_assert_always(0);
841
842 /* WAR: sometimes duplicate pkt desc are received
843 * from HW this check gracefully handles
844 * such cases.
845 */
846 if ((mon_desc == mon_pdev_be->prev_rxmon_pkt_desc) &&
847 (mon_desc->cookie == mon_pdev_be->prev_rxmon_pkt_cookie)) {
848 dp_mon_err("duplicate pkt desc found mon_pdev: %pK mon_desc: %pK cookie: %d",
849 mon_pdev, mon_desc,
850 mon_desc->cookie);
851 mon_pdev->rx_mon_stats.dup_mon_buf_cnt++;
852 return num_buf_reaped;
853 }
854 mon_pdev_be->prev_rxmon_pkt_desc = mon_desc;
855 mon_pdev_be->prev_rxmon_pkt_cookie = mon_desc->cookie;
856
857 addr = mon_desc->buf_addr;
858 qdf_assert_always(addr);
859
860 if (!mon_desc->unmapped) {
861 qdf_mem_unmap_page(soc->osdev,
862 (qdf_dma_addr_t)mon_desc->paddr,
863 DP_MON_DATA_BUFFER_SIZE,
864 QDF_DMA_FROM_DEVICE);
865 mon_desc->unmapped = 1;
866 }
867 dp_mon_add_to_free_desc_list(desc_list, tail, mon_desc);
868 num_buf_reaped++;
869
870 mon_pdev->rx_mon_stats.pkt_buf_count++;
871
872 /* if rx hdr is not valid free pkt buffer and return */
873 if (qdf_unlikely(!rx_hdr_valid)) {
874 DP_STATS_INC(mon_soc, frag_free, 1);
875 qdf_frag_free(addr);
876 return num_buf_reaped;
877 }
878
879 if (qdf_unlikely(!ppdu_info->rx_hdr_rcvd[user_id])) {
880 /* WAR: RX_HDR is not received for this MPDU, drop this frame */
881 mon_pdev->rx_mon_stats.rx_hdr_not_received++;
882 DP_STATS_INC(mon_soc, frag_free, 1);
883 qdf_frag_free(addr);
884 return num_buf_reaped;
885 }
886
887 if (packet_info->dma_length >
888 (DP_MON_DATA_BUFFER_SIZE - DP_RX_MON_PACKET_OFFSET)) {
889 /* WAR: Invalid DMA length is received for this MPDU */
890 mon_pdev->rx_mon_stats.invalid_dma_length++;
891 DP_STATS_INC(mon_soc, frag_free, 1);
892 qdf_frag_free(addr);
893 return num_buf_reaped;
894 }
895
896 nbuf = qdf_nbuf_queue_last(&ppdu_info->mpdu_q[user_id]);
897 if (qdf_unlikely(!nbuf)) {
898 dp_mon_debug("nbuf is NULL");
899 DP_STATS_INC(mon_soc, frag_free, 1);
900 DP_STATS_INC(mon_soc, empty_queue, 1);
901 qdf_frag_free(addr);
902 return num_buf_reaped;
903 }
904
905 mpdu_info = &ppdu_info->mpdu_info[user_id];
906 if (mpdu_info->decap_type == DP_MON_DECAP_FORMAT_INVALID) {
907 /* decap type is invalid, drop the frame */
908 mon_pdev->rx_mon_stats.mpdu_decap_type_invalid++;
909 DP_STATS_INC(mon_soc, frag_free, 1);
910 mon_pdev->rx_mon_stats.parent_buf_free++;
911 qdf_frag_free(addr);
912 qdf_nbuf_queue_remove_last(&ppdu_info->mpdu_q[user_id]);
913 qdf_nbuf_free(nbuf);
914 /* if invalid decap type handling is disabled, assert */
915 if (soc->wlan_cfg_ctx->is_handle_invalid_decap_type_disabled) {
916 dp_mon_err("Decap type invalid");
917 qdf_assert_always(0);
918 }
919 ppdu_info->rx_hdr_rcvd[user_id] = false;
920 return num_buf_reaped;
921 }
922
923 tmp_nbuf = qdf_get_nbuf_valid_frag(nbuf);
924
925 if (!tmp_nbuf) {
926 tmp_nbuf = qdf_nbuf_alloc(pdev->soc->osdev,
927 DP_RX_MON_MAX_MONITOR_HEADER,
928 DP_RX_MON_MAX_MONITOR_HEADER,
929 4, FALSE);
930 if (qdf_unlikely(!tmp_nbuf)) {
931 dp_mon_err("nbuf is NULL");
932 DP_STATS_INC(mon_soc, frag_free, 1);
933 mon_pdev->rx_mon_stats.parent_buf_free++;
934 qdf_frag_free(addr);
935 /* remove this nbuf from queue */
936 qdf_nbuf_queue_remove_last(&ppdu_info->mpdu_q[user_id]);
937 qdf_nbuf_free(nbuf);
938 return num_buf_reaped;
939 }
940 mon_pdev->rx_mon_stats.parent_buf_alloc++;
941 dp_rx_mon_append_nbuf(nbuf, tmp_nbuf);
942 }
943 mpdu_info->full_pkt = true;
944
945 if (mpdu_info->decap_type == HAL_HW_RX_DECAP_FORMAT_RAW) {
946 if (mpdu_info->first_rx_hdr_rcvd) {
947 qdf_nbuf_remove_frag(nbuf, frag_idx, DP_MON_DATA_BUFFER_SIZE);
948 dp_rx_mon_nbuf_add_rx_frag(nbuf, addr,
949 packet_info->dma_length,
950 DP_RX_MON_PACKET_OFFSET,
951 DP_MON_DATA_BUFFER_SIZE,
952 false);
953 DP_STATS_INC(mon_soc, frag_free, 1);
954 mpdu_info->first_rx_hdr_rcvd = false;
955 } else {
956 dp_rx_mon_nbuf_add_rx_frag(tmp_nbuf, addr,
957 packet_info->dma_length,
958 DP_RX_MON_PACKET_OFFSET,
959 DP_MON_DATA_BUFFER_SIZE,
960 false);
961 DP_STATS_INC(mon_soc, frag_free, 1);
962 }
963 } else {
964 dp_rx_mon_nbuf_add_rx_frag(tmp_nbuf, addr,
965 packet_info->dma_length,
966 DP_RX_MON_PACKET_OFFSET,
967 DP_MON_DATA_BUFFER_SIZE,
968 false);
969 DP_STATS_INC(mon_soc, frag_free, 1);
970 buf_info = addr;
971
972 if (!ppdu_info->msdu[user_id].first_buffer) {
973 buf_info->first_buffer = true;
974 ppdu_info->msdu[user_id].first_buffer = true;
975 } else {
976 buf_info->first_buffer = false;
977 }
978
979 if (packet_info->msdu_continuation)
980 buf_info->last_buffer = false;
981 else
982 buf_info->last_buffer = true;
983
984 buf_info->frag_len = packet_info->dma_length;
985 }
986 if (qdf_unlikely(packet_info->truncated))
987 mpdu_info->truncated = true;
988
989 return num_buf_reaped;
990 }
991
992 /**
993 * dp_rx_mon_handle_rx_hdr() - Process RX_HDR TLV
994 *
995 * @pdev: DP pdev
996 * @ppdu_info: PPDU info
997 * @status_frag: Status frag
998 *
999 * Return: void
1000 */
1001 static inline void
dp_rx_mon_handle_rx_hdr(struct dp_pdev * pdev,struct hal_rx_ppdu_info * ppdu_info,void * status_frag)1002 dp_rx_mon_handle_rx_hdr(struct dp_pdev *pdev,
1003 struct hal_rx_ppdu_info *ppdu_info,
1004 void *status_frag)
1005 {
1006 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
1007 qdf_nbuf_t nbuf, tmp_nbuf;
1008 uint8_t user_id = ppdu_info->user_id;
1009 QDF_STATUS status;
1010
1011 /* If this is first RX_HEADER for MPDU, allocate skb
1012 * else add frag to already allocated skb
1013 */
1014
1015 if (!ppdu_info->mpdu_info[user_id].mpdu_start_received) {
1016 nbuf = qdf_nbuf_alloc(pdev->soc->osdev,
1017 DP_RX_MON_TLV_ROOM +
1018 DP_RX_MON_MAX_RADIO_TAP_HDR,
1019 DP_RX_MON_TLV_ROOM +
1020 DP_RX_MON_MAX_RADIO_TAP_HDR,
1021 4, FALSE);
1022
1023 /**
1024 * Set *head_msdu->next as NULL as all msdus are
1025 * mapped via nr frags
1026 **/
1027 if (qdf_unlikely(!nbuf)) {
1028 dp_mon_debug("malloc failed pdev: %pK ", pdev);
1029 return;
1030 }
1031
1032 mon_pdev->rx_mon_stats.parent_buf_alloc++;
1033
1034 dp_rx_mon_set_zero(nbuf);
1035
1036 qdf_nbuf_set_next(nbuf, NULL);
1037
1038 qdf_nbuf_queue_add(&ppdu_info->mpdu_q[user_id], nbuf);
1039
1040 status = dp_rx_mon_nbuf_add_rx_frag(nbuf, status_frag,
1041 ppdu_info->hdr_len - DP_RX_MON_RX_HDR_OFFSET,
1042 ppdu_info->data - (unsigned char *)status_frag + 4,
1043 DP_MON_DATA_BUFFER_SIZE, true);
1044 if (qdf_unlikely(status != QDF_STATUS_SUCCESS)) {
1045 dp_mon_err("num_frags exceeding MAX frags");
1046 return;
1047 }
1048 ppdu_info->mpdu_info[ppdu_info->user_id].mpdu_start_received = true;
1049 ppdu_info->mpdu_info[user_id].first_rx_hdr_rcvd = true;
1050 /* initialize decap type to invalid, this will be set to appropriate
1051 * value once the mpdu start tlv is received
1052 */
1053 ppdu_info->mpdu_info[user_id].decap_type = DP_MON_DECAP_FORMAT_INVALID;
1054 } else {
1055 if (ppdu_info->mpdu_info[user_id].decap_type ==
1056 HAL_HW_RX_DECAP_FORMAT_RAW) {
1057 return;
1058 }
1059
1060 if (dp_lite_mon_is_rx_enabled(mon_pdev) &&
1061 !dp_lite_mon_is_level_msdu(mon_pdev))
1062 return;
1063
1064 nbuf = qdf_nbuf_queue_last(&ppdu_info->mpdu_q[user_id]);
1065 if (qdf_unlikely(!nbuf)) {
1066 dp_mon_debug("nbuf is NULL");
1067 return;
1068 }
1069
1070 tmp_nbuf = qdf_get_nbuf_valid_frag(nbuf);
1071
1072 if (!tmp_nbuf) {
1073 tmp_nbuf = qdf_nbuf_alloc(pdev->soc->osdev,
1074 DP_RX_MON_MAX_MONITOR_HEADER,
1075 DP_RX_MON_MAX_MONITOR_HEADER,
1076 4, FALSE);
1077 if (qdf_unlikely(!tmp_nbuf)) {
1078 dp_mon_err("nbuf is NULL");
1079 qdf_assert_always(0);
1080 }
1081 mon_pdev->rx_mon_stats.parent_buf_alloc++;
1082 dp_rx_mon_append_nbuf(nbuf, tmp_nbuf);
1083 }
1084 dp_rx_mon_nbuf_add_rx_frag(tmp_nbuf, status_frag,
1085 ppdu_info->hdr_len - DP_RX_MON_RX_HDR_OFFSET,
1086 ppdu_info->data - (unsigned char *)status_frag + 4,
1087 DP_MON_DATA_BUFFER_SIZE,
1088 true);
1089 }
1090 ppdu_info->rx_hdr_rcvd[user_id] = true;
1091 }
1092
1093 /**
1094 * dp_rx_mon_free_mpdu_queue() - Free MPDU queue
1095 * @mon_pdev: monitor pdev
1096 * @ppdu_info: PPDU info
1097 *
1098 * Return: Void
1099 */
1100
dp_rx_mon_free_mpdu_queue(struct dp_mon_pdev * mon_pdev,struct hal_rx_ppdu_info * ppdu_info)1101 static void dp_rx_mon_free_mpdu_queue(struct dp_mon_pdev *mon_pdev,
1102 struct hal_rx_ppdu_info *ppdu_info)
1103 {
1104 uint8_t user;
1105 qdf_nbuf_t mpdu;
1106
1107 for (user = 0; user < HAL_MAX_UL_MU_USERS; user++) {
1108 if (!qdf_nbuf_is_queue_empty(&ppdu_info->mpdu_q[user])) {
1109 while ((mpdu = qdf_nbuf_queue_remove(&ppdu_info->mpdu_q[user])) != NULL)
1110 dp_mon_free_parent_nbuf(mon_pdev, mpdu);
1111 }
1112 }
1113 }
1114
1115 #ifdef QCA_KMEM_CACHE_SUPPORT
1116 /**
1117 * dp_rx_mon_get_ppdu_info() - Get PPDU info from freelist
1118 *
1119 * @mon_pdev: monitor pdev
1120 *
1121 * Return: ppdu_info
1122 */
1123 struct hal_rx_ppdu_info*
dp_rx_mon_get_ppdu_info(struct dp_mon_pdev * mon_pdev)1124 dp_rx_mon_get_ppdu_info(struct dp_mon_pdev *mon_pdev)
1125 {
1126 struct dp_mon_pdev_be *mon_pdev_be =
1127 dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
1128 struct hal_rx_ppdu_info *ppdu_info, *temp_ppdu_info;
1129
1130 qdf_spin_lock_bh(&mon_pdev_be->ppdu_info_lock);
1131 TAILQ_FOREACH_SAFE(ppdu_info,
1132 &mon_pdev_be->rx_mon_free_queue,
1133 ppdu_free_list_elem,
1134 temp_ppdu_info) {
1135 TAILQ_REMOVE(&mon_pdev_be->rx_mon_free_queue,
1136 ppdu_info, ppdu_free_list_elem);
1137
1138 if (ppdu_info) {
1139 mon_pdev_be->total_free_elem--;
1140 break;
1141 }
1142 }
1143 qdf_spin_unlock_bh(&mon_pdev_be->ppdu_info_lock);
1144
1145 return ppdu_info;
1146 }
1147
1148 void
__dp_rx_mon_free_ppdu_info(struct dp_mon_pdev * mon_pdev,struct hal_rx_ppdu_info * ppdu_info)1149 __dp_rx_mon_free_ppdu_info(struct dp_mon_pdev *mon_pdev,
1150 struct hal_rx_ppdu_info *ppdu_info)
1151 {
1152 struct dp_mon_pdev_be *mon_pdev_be =
1153 dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
1154
1155 qdf_spin_lock_bh(&mon_pdev_be->ppdu_info_lock);
1156 if (ppdu_info) {
1157 qdf_mem_zero(ppdu_info, sizeof(struct hal_rx_ppdu_info));
1158 TAILQ_INSERT_TAIL(&mon_pdev_be->rx_mon_free_queue, ppdu_info,
1159 ppdu_free_list_elem);
1160 mon_pdev_be->total_free_elem++;
1161 }
1162 qdf_spin_unlock_bh(&mon_pdev_be->ppdu_info_lock);
1163 }
1164
1165 /**
1166 * dp_rx_mon_free_ppdu_info() - Free PPDU info
1167 * @pdev: DP pdev
1168 * @ppdu_info: PPDU info
1169 *
1170 * Return: Void
1171 */
1172 void
dp_rx_mon_free_ppdu_info(struct dp_pdev * pdev,struct hal_rx_ppdu_info * ppdu_info)1173 dp_rx_mon_free_ppdu_info(struct dp_pdev *pdev,
1174 struct hal_rx_ppdu_info *ppdu_info)
1175 {
1176 struct dp_mon_pdev *mon_pdev;
1177
1178 mon_pdev = (struct dp_mon_pdev *)pdev->monitor_pdev;
1179 dp_rx_mon_free_mpdu_queue(mon_pdev, ppdu_info);
1180 __dp_rx_mon_free_ppdu_info(mon_pdev, ppdu_info);
1181 }
1182 #endif
1183
1184 /**
1185 * dp_mon_free_parent_nbuf() - Free parent SKB
1186 *
1187 * @mon_pdev: monitor pdev
1188 * @nbuf: SKB to be freed
1189 *
1190 * Return: void
1191 */
dp_mon_free_parent_nbuf(struct dp_mon_pdev * mon_pdev,qdf_nbuf_t nbuf)1192 void dp_mon_free_parent_nbuf(struct dp_mon_pdev *mon_pdev,
1193 qdf_nbuf_t nbuf)
1194 {
1195 mon_pdev->rx_mon_stats.parent_buf_free++;
1196 qdf_nbuf_free(nbuf);
1197 }
1198
dp_rx_mon_drain_wq(struct dp_pdev * pdev)1199 void dp_rx_mon_drain_wq(struct dp_pdev *pdev)
1200 {
1201 struct dp_mon_pdev *mon_pdev;
1202 struct hal_rx_ppdu_info *ppdu_info = NULL;
1203 struct hal_rx_ppdu_info *temp_ppdu_info = NULL;
1204 struct dp_mon_pdev_be *mon_pdev_be;
1205
1206 if (qdf_unlikely(!pdev)) {
1207 dp_mon_debug("Pdev is NULL");
1208 return;
1209 }
1210
1211 mon_pdev = (struct dp_mon_pdev *)pdev->monitor_pdev;
1212 if (qdf_unlikely(!mon_pdev)) {
1213 dp_mon_debug("monitor pdev is NULL");
1214 return;
1215 }
1216
1217 mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
1218
1219 qdf_spin_lock_bh(&mon_pdev_be->rx_mon_wq_lock);
1220 TAILQ_FOREACH_SAFE(ppdu_info,
1221 &mon_pdev_be->rx_mon_queue,
1222 ppdu_list_elem,
1223 temp_ppdu_info) {
1224 mon_pdev_be->rx_mon_queue_depth--;
1225 TAILQ_REMOVE(&mon_pdev_be->rx_mon_queue,
1226 ppdu_info, ppdu_list_elem);
1227
1228 dp_rx_mon_free_ppdu_info(pdev, ppdu_info);
1229 }
1230 qdf_spin_unlock_bh(&mon_pdev_be->rx_mon_wq_lock);
1231 }
1232
1233 /**
1234 * dp_rx_mon_deliver_mpdu() - Deliver MPDU to osif layer
1235 *
1236 * @mon_pdev: monitor pdev
1237 * @mpdu: MPDU nbuf
1238 * @rx_status: monitor status
1239 *
1240 * Return: QDF_STATUS
1241 */
1242 static QDF_STATUS
dp_rx_mon_deliver_mpdu(struct dp_mon_pdev * mon_pdev,qdf_nbuf_t mpdu,struct mon_rx_status * rx_status)1243 dp_rx_mon_deliver_mpdu(struct dp_mon_pdev *mon_pdev,
1244 qdf_nbuf_t mpdu,
1245 struct mon_rx_status *rx_status)
1246 {
1247 qdf_nbuf_t nbuf;
1248
1249 if (mon_pdev->mvdev && mon_pdev->mvdev->monitor_vdev->osif_rx_mon) {
1250 mon_pdev->rx_mon_stats.mpdus_buf_to_stack++;
1251 nbuf = qdf_nbuf_get_ext_list(mpdu);
1252
1253 while (nbuf) {
1254 mon_pdev->rx_mon_stats.mpdus_buf_to_stack++;
1255 nbuf = nbuf->next;
1256 }
1257 mon_pdev->mvdev->monitor_vdev->osif_rx_mon(mon_pdev->mvdev->osif_vdev,
1258 mpdu,
1259 rx_status);
1260 } else {
1261 return QDF_STATUS_E_FAILURE;
1262 }
1263
1264 return QDF_STATUS_SUCCESS;
1265 }
1266
1267 /**
1268 * dp_rx_mon_process_ppdu_info() - Process PPDU info
1269 * @pdev: DP pdev
1270 * @ppdu_info: PPDU info
1271 *
1272 * Return: Void
1273 */
1274 static void
dp_rx_mon_process_ppdu_info(struct dp_pdev * pdev,struct hal_rx_ppdu_info * ppdu_info)1275 dp_rx_mon_process_ppdu_info(struct dp_pdev *pdev,
1276 struct hal_rx_ppdu_info *ppdu_info)
1277 {
1278 struct dp_mon_pdev *mon_pdev = (struct dp_mon_pdev *)pdev->monitor_pdev;
1279 uint8_t user;
1280 qdf_nbuf_t mpdu;
1281
1282 if (!ppdu_info)
1283 return;
1284
1285 for (user = 0; user < ppdu_info->com_info.num_users; user++) {
1286 uint16_t mpdu_count;
1287 uint16_t mpdu_idx;
1288 struct hal_rx_mon_mpdu_info *mpdu_meta;
1289 QDF_STATUS status;
1290
1291 if (user >= HAL_MAX_UL_MU_USERS) {
1292 dp_mon_err("num user exceeds max limit");
1293 return;
1294 }
1295
1296 mpdu_count = ppdu_info->mpdu_count[user];
1297 ppdu_info->rx_status.rx_user_status =
1298 &ppdu_info->rx_user_status[user];
1299 for (mpdu_idx = 0; mpdu_idx < mpdu_count; mpdu_idx++) {
1300 mpdu = qdf_nbuf_queue_remove(&ppdu_info->mpdu_q[user]);
1301
1302 if (!mpdu)
1303 continue;
1304
1305 mpdu_meta = (struct hal_rx_mon_mpdu_info *)qdf_nbuf_data(mpdu);
1306
1307 ppdu_info->rx_status.rs_fcs_err = mpdu_meta->fcs_err;
1308 if (dp_lite_mon_is_rx_enabled(mon_pdev)) {
1309 status = dp_lite_mon_rx_mpdu_process(pdev, ppdu_info,
1310 mpdu, mpdu_idx, user);
1311 if (status != QDF_STATUS_SUCCESS) {
1312 dp_mon_free_parent_nbuf(mon_pdev, mpdu);
1313 continue;
1314 }
1315 } else {
1316 if (mpdu_meta->full_pkt) {
1317 if (qdf_unlikely(mpdu_meta->truncated)) {
1318 dp_mon_free_parent_nbuf(mon_pdev, mpdu);
1319 continue;
1320 }
1321
1322 status = dp_rx_mon_handle_full_mon(pdev,
1323 ppdu_info, mpdu);
1324 if (status != QDF_STATUS_SUCCESS) {
1325 dp_mon_free_parent_nbuf(mon_pdev, mpdu);
1326 continue;
1327 }
1328 } else {
1329 dp_mon_free_parent_nbuf(mon_pdev, mpdu);
1330 continue;
1331 }
1332
1333 /* reset mpdu metadata and apply radiotap header over MPDU */
1334 qdf_mem_zero(mpdu_meta, sizeof(struct hal_rx_mon_mpdu_info));
1335 if (!qdf_nbuf_update_radiotap(&ppdu_info->rx_status,
1336 mpdu,
1337 qdf_nbuf_headroom(mpdu))) {
1338 dp_mon_err("failed to update radiotap pdev: %pK",
1339 pdev);
1340 }
1341
1342 dp_rx_mon_shift_pf_tag_in_headroom(mpdu,
1343 pdev->soc,
1344 ppdu_info);
1345
1346 dp_rx_mon_process_dest_pktlog(pdev->soc,
1347 pdev->pdev_id,
1348 mpdu);
1349 /* Deliver MPDU to osif layer */
1350 status = dp_rx_mon_deliver_mpdu(mon_pdev,
1351 mpdu,
1352 &ppdu_info->rx_status);
1353 if (status != QDF_STATUS_SUCCESS)
1354 dp_mon_free_parent_nbuf(mon_pdev, mpdu);
1355 }
1356 ppdu_info->rx_status.rs_fcs_err = false;
1357 }
1358 }
1359
1360 dp_rx_mon_free_mpdu_queue(mon_pdev, ppdu_info);
1361 }
1362
1363 /**
1364 * dp_rx_mon_process_ppdu()- Deferred monitor processing
1365 * This workqueue API handles:
1366 * a. Full monitor
1367 * b. Lite monitor
1368 *
1369 * @context: Opaque work context
1370 *
1371 * Return: none
1372 */
dp_rx_mon_process_ppdu(void * context)1373 void dp_rx_mon_process_ppdu(void *context)
1374 {
1375 struct dp_pdev *pdev = (struct dp_pdev *)context;
1376 struct dp_mon_pdev *mon_pdev;
1377 struct hal_rx_ppdu_info *ppdu_info = NULL;
1378 struct hal_rx_ppdu_info *temp_ppdu_info = NULL;
1379 struct dp_mon_pdev_be *mon_pdev_be;
1380
1381 if (qdf_unlikely(!pdev)) {
1382 dp_mon_debug("Pdev is NULL");
1383 return;
1384 }
1385
1386 mon_pdev = (struct dp_mon_pdev *)pdev->monitor_pdev;
1387 if (qdf_unlikely(!mon_pdev)) {
1388 dp_mon_debug("monitor pdev is NULL");
1389 return;
1390 }
1391
1392 mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
1393
1394 qdf_spin_lock_bh(&mon_pdev_be->rx_mon_wq_lock);
1395 TAILQ_FOREACH_SAFE(ppdu_info,
1396 &mon_pdev_be->rx_mon_queue,
1397 ppdu_list_elem, temp_ppdu_info) {
1398 TAILQ_REMOVE(&mon_pdev_be->rx_mon_queue,
1399 ppdu_info, ppdu_list_elem);
1400
1401 mon_pdev_be->rx_mon_queue_depth--;
1402 dp_rx_mon_process_ppdu_info(pdev, ppdu_info);
1403 __dp_rx_mon_free_ppdu_info(mon_pdev, ppdu_info);
1404 }
1405 qdf_spin_unlock_bh(&mon_pdev_be->rx_mon_wq_lock);
1406 }
1407
1408 /**
1409 * dp_rx_mon_add_ppdu_info_to_wq() - Add PPDU info to workqueue
1410 *
1411 * @pdev: monitor pdev
1412 * @ppdu_info: ppdu info to be added to workqueue
1413 *
1414 * Return: SUCCESS or FAILIRE
1415 */
1416
1417 static QDF_STATUS
dp_rx_mon_add_ppdu_info_to_wq(struct dp_pdev * pdev,struct hal_rx_ppdu_info * ppdu_info)1418 dp_rx_mon_add_ppdu_info_to_wq(struct dp_pdev *pdev,
1419 struct hal_rx_ppdu_info *ppdu_info)
1420 {
1421 struct dp_mon_pdev *mon_pdev = (struct dp_mon_pdev *)pdev->monitor_pdev;
1422 struct dp_mon_pdev_be *mon_pdev_be =
1423 dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
1424
1425 /* Full monitor or lite monitor mode is not enabled, return */
1426 if (!mon_pdev->monitor_configured &&
1427 !dp_lite_mon_is_rx_enabled(mon_pdev))
1428 return QDF_STATUS_E_FAILURE;
1429
1430 if (qdf_likely(ppdu_info)) {
1431 if (mon_pdev_be->rx_mon_queue_depth < DP_RX_MON_WQ_THRESHOLD) {
1432 qdf_spin_lock_bh(&mon_pdev_be->rx_mon_wq_lock);
1433 TAILQ_INSERT_TAIL(&mon_pdev_be->rx_mon_queue,
1434 ppdu_info, ppdu_list_elem);
1435 mon_pdev_be->rx_mon_queue_depth++;
1436 mon_pdev->rx_mon_stats.total_ppdu_info_enq++;
1437 } else {
1438 mon_pdev->rx_mon_stats.total_ppdu_info_drop++;
1439 dp_rx_mon_free_ppdu_info(pdev, ppdu_info);
1440 }
1441 qdf_spin_unlock_bh(&mon_pdev_be->rx_mon_wq_lock);
1442
1443 if (mon_pdev_be->rx_mon_queue_depth > DP_MON_QUEUE_DEPTH_MAX) {
1444 qdf_queue_work(0, mon_pdev_be->rx_mon_workqueue,
1445 &mon_pdev_be->rx_mon_work);
1446 }
1447 }
1448 return QDF_STATUS_SUCCESS;
1449 }
1450
1451 QDF_STATUS
dp_rx_mon_handle_full_mon(struct dp_pdev * pdev,struct hal_rx_ppdu_info * ppdu_info,qdf_nbuf_t mpdu)1452 dp_rx_mon_handle_full_mon(struct dp_pdev *pdev,
1453 struct hal_rx_ppdu_info *ppdu_info,
1454 qdf_nbuf_t mpdu)
1455 {
1456 uint32_t wifi_hdr_len, sec_hdr_len, msdu_llc_len,
1457 mpdu_buf_len, decap_hdr_pull_bytes, dir,
1458 is_amsdu, amsdu_pad, frag_size, tot_msdu_len;
1459 struct hal_rx_mon_mpdu_info *mpdu_meta;
1460 struct hal_rx_mon_msdu_info *msdu_meta;
1461 char *hdr_desc;
1462 uint8_t num_frags, frag_iter, l2_hdr_offset;
1463 struct ieee80211_frame *wh;
1464 struct ieee80211_qoscntl *qos;
1465 uint32_t hdr_frag_size, frag_page_offset, pad_byte_pholder;
1466 qdf_nbuf_t head_msdu, msdu_cur;
1467 void *frag_addr;
1468 bool prev_msdu_end_received = false;
1469 bool is_nbuf_head = true;
1470
1471 /***************************************************************************
1472 *********************** Non-raw packet ************************************
1473 ---------------------------------------------------------------------------
1474 | | frag-0 | frag-1 | frag - 2 | frag - 3 | frag - 4 | frag - 5 |
1475 | skb | rx_hdr-1 | rx_msdu-1 | rx_hdr-2 | rx_msdu-2 | rx_hdr-3 | rx-msdu-3 |
1476 ---------------------------------------------------------------------------
1477 **************************************************************************/
1478
1479 if (!mpdu) {
1480 dp_mon_debug("nbuf is NULL, return");
1481 return QDF_STATUS_E_FAILURE;
1482 }
1483
1484 head_msdu = mpdu;
1485
1486 mpdu_meta = (struct hal_rx_mon_mpdu_info *)qdf_nbuf_data(mpdu);
1487
1488 if (mpdu_meta->decap_type == HAL_HW_RX_DECAP_FORMAT_RAW) {
1489 if (qdf_unlikely(ppdu_info->rx_status.rs_fcs_err)) {
1490 hdr_desc = qdf_nbuf_get_frag_addr(mpdu, 0);
1491 wh = (struct ieee80211_frame *)hdr_desc;
1492 if ((wh->i_fc[0] & QDF_IEEE80211_FC0_VERSION_MASK) !=
1493 QDF_IEEE80211_FC0_VERSION_0) {
1494 DP_STATS_INC(pdev, dropped.mon_ver_err, 1);
1495 return QDF_STATUS_E_FAILURE;
1496 }
1497 }
1498 qdf_nbuf_trim_add_frag_size(mpdu,
1499 qdf_nbuf_get_nr_frags(mpdu) - 1,
1500 -HAL_RX_FCS_LEN, 0);
1501 return QDF_STATUS_SUCCESS;
1502 }
1503
1504 num_frags = qdf_nbuf_get_nr_frags(mpdu);
1505 if (qdf_unlikely(num_frags < DP_MON_MIN_FRAGS_FOR_RESTITCH)) {
1506 dp_mon_debug("not enough frags(%d) for restitch", num_frags);
1507 return QDF_STATUS_E_FAILURE;
1508 }
1509
1510 l2_hdr_offset = DP_RX_MON_NONRAW_L2_HDR_PAD_BYTE;
1511
1512 /* hdr_desc points to 80211 hdr */
1513 hdr_desc = qdf_nbuf_get_frag_addr(mpdu, 0);
1514
1515 /* Calculate Base header size */
1516 wifi_hdr_len = sizeof(struct ieee80211_frame);
1517 wh = (struct ieee80211_frame *)hdr_desc;
1518
1519 dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
1520
1521 if (dir == IEEE80211_FC1_DIR_DSTODS)
1522 wifi_hdr_len += 6;
1523
1524 is_amsdu = 0;
1525 if (wh->i_fc[0] & QDF_IEEE80211_FC0_SUBTYPE_QOS) {
1526 qos = (struct ieee80211_qoscntl *)
1527 (hdr_desc + wifi_hdr_len);
1528 wifi_hdr_len += 2;
1529
1530 is_amsdu = (qos->i_qos[0] & IEEE80211_QOS_AMSDU);
1531 }
1532
1533 /*Calculate security header length based on 'Protected'
1534 * and 'EXT_IV' flag
1535 */
1536 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1537 char *iv = (char *)wh + wifi_hdr_len;
1538
1539 if (iv[3] & KEY_EXTIV)
1540 sec_hdr_len = 8;
1541 else
1542 sec_hdr_len = 4;
1543 } else {
1544 sec_hdr_len = 0;
1545 }
1546 wifi_hdr_len += sec_hdr_len;
1547
1548 /* MSDU related stuff LLC - AMSDU subframe header etc */
1549 msdu_llc_len = is_amsdu ? (DP_RX_MON_DECAP_HDR_SIZE +
1550 DP_RX_MON_LLC_SIZE +
1551 DP_RX_MON_SNAP_SIZE) :
1552 (DP_RX_MON_LLC_SIZE + DP_RX_MON_SNAP_SIZE);
1553
1554 mpdu_buf_len = wifi_hdr_len + msdu_llc_len;
1555
1556 /* "Decap" header to remove from MSDU buffer */
1557 decap_hdr_pull_bytes = DP_RX_MON_DECAP_HDR_SIZE;
1558
1559 amsdu_pad = 0;
1560 tot_msdu_len = 0;
1561 tot_msdu_len = 0;
1562
1563 /*
1564 * Update protocol and flow tag for MSDU
1565 * update frag index in ctx_idx field.
1566 * Reset head pointer data of nbuf before updating.
1567 */
1568 QDF_NBUF_CB_RX_CTX_ID(mpdu) = 0;
1569
1570 /* Construct destination address */
1571 hdr_frag_size = qdf_nbuf_get_frag_size_by_idx(mpdu, 0);
1572
1573 /* Adjust page frag offset to point to 802.11 header */
1574 if (hdr_frag_size > mpdu_buf_len)
1575 qdf_nbuf_trim_add_frag_size(head_msdu, 0, -(hdr_frag_size - mpdu_buf_len), 0);
1576
1577 msdu_meta = (struct hal_rx_mon_msdu_info *)(((void *)qdf_nbuf_get_frag_addr(mpdu, 1)) - DP_RX_MON_PACKET_OFFSET);
1578
1579 frag_size = qdf_nbuf_get_frag_size_by_idx(head_msdu, 1);
1580 pad_byte_pholder =
1581 RX_MONITOR_BUFFER_SIZE - (frag_size + DP_RX_MON_PACKET_OFFSET);
1582
1583 /* Adjust page frag offset to appropriate after decap header */
1584 frag_page_offset =
1585 decap_hdr_pull_bytes + l2_hdr_offset;
1586 qdf_nbuf_move_frag_page_offset(head_msdu, 1, frag_page_offset);
1587 frag_size = frag_size - frag_page_offset;
1588
1589 if (msdu_meta->first_buffer && msdu_meta->last_buffer) {
1590 /* MSDU with single buffer */
1591 amsdu_pad = frag_size & 0x3;
1592 amsdu_pad = amsdu_pad ? (4 - amsdu_pad) : 0;
1593 if (amsdu_pad && (amsdu_pad <= pad_byte_pholder)) {
1594 char *frag_addr_temp;
1595
1596 qdf_nbuf_trim_add_frag_size(mpdu, 1, amsdu_pad, 0);
1597 frag_addr_temp =
1598 (char *)qdf_nbuf_get_frag_addr(mpdu, 1);
1599 frag_addr_temp = (frag_addr_temp +
1600 qdf_nbuf_get_frag_size_by_idx(mpdu, 1)) -
1601 amsdu_pad;
1602 qdf_mem_zero(frag_addr_temp, amsdu_pad);
1603 amsdu_pad = 0;
1604 }
1605 } else {
1606 tot_msdu_len = frag_size;
1607 amsdu_pad = 0;
1608 }
1609
1610 pad_byte_pholder = 0;
1611 for (msdu_cur = mpdu; msdu_cur;) {
1612 /* frag_iter will start from 0 for second skb onwards */
1613 if (msdu_cur == mpdu)
1614 frag_iter = 2;
1615 else
1616 frag_iter = 0;
1617
1618 num_frags = qdf_nbuf_get_nr_frags(msdu_cur);
1619
1620 for (; frag_iter < num_frags; frag_iter++) {
1621 /* Construct destination address
1622 * ----------------------------------------------------------
1623 * | | L2_HDR_PAD | Decap HDR | Payload | Pad |
1624 * | | (First buffer) | | |
1625 * | | / / |
1626 * | >Frag address points here / / |
1627 * | \ / / |
1628 * | \ This bytes needs to / / |
1629 * | \ removed to frame pkt/ / |
1630 * | ---------------------- / |
1631 * | | / Add |
1632 * | | / amsdu pad |
1633 * | LLC HDR will be added here <-| | Byte for |
1634 * | | | | last frame |
1635 * | >Dest addr will point | | if space |
1636 * | somewhere in this area | | available |
1637 * | And amsdu_pad will be created if | | |
1638 * | dint get added in last buffer | | |
1639 * | (First Buffer) | | |
1640 * ----------------------------------------------------------
1641 */
1642 /* If previous msdu end has received, modify next frag's offset to point to LLC */
1643 if (prev_msdu_end_received) {
1644 hdr_frag_size = qdf_nbuf_get_frag_size_by_idx(msdu_cur, frag_iter);
1645 /* Adjust page frag offset to point to llc/snap header */
1646 if (hdr_frag_size > msdu_llc_len)
1647 qdf_nbuf_trim_add_frag_size(msdu_cur, frag_iter, -(hdr_frag_size - msdu_llc_len), 0);
1648 prev_msdu_end_received = false;
1649 continue;
1650 }
1651
1652 frag_addr =
1653 qdf_nbuf_get_frag_addr(msdu_cur, frag_iter) -
1654 DP_RX_MON_PACKET_OFFSET;
1655 msdu_meta = (struct hal_rx_mon_msdu_info *)frag_addr;
1656
1657 /*
1658 * Update protocol and flow tag for MSDU
1659 * update frag index in ctx_idx field
1660 */
1661 QDF_NBUF_CB_RX_CTX_ID(msdu_cur) = frag_iter;
1662
1663 frag_size = qdf_nbuf_get_frag_size_by_idx(msdu_cur,
1664 frag_iter);
1665
1666 /* If Middle buffer, dont add any header */
1667 if ((!msdu_meta->first_buffer) &&
1668 (!msdu_meta->last_buffer)) {
1669 tot_msdu_len += frag_size;
1670 amsdu_pad = 0;
1671 pad_byte_pholder = 0;
1672 continue;
1673 }
1674
1675 /* Calculate if current buffer has placeholder
1676 * to accommodate amsdu pad byte
1677 */
1678 pad_byte_pholder =
1679 RX_MONITOR_BUFFER_SIZE - (frag_size + DP_RX_MON_PACKET_OFFSET);
1680 /*
1681 * We will come here only only three condition:
1682 * 1. Msdu with single Buffer
1683 * 2. First buffer in case MSDU is spread in multiple
1684 * buffer
1685 * 3. Last buffer in case MSDU is spread in multiple
1686 * buffer
1687 *
1688 * First buffER | Last buffer
1689 * Case 1: 1 | 1
1690 * Case 2: 1 | 0
1691 * Case 3: 0 | 1
1692 *
1693 * In 3rd case only l2_hdr_padding byte will be Zero and
1694 * in other case, It will be 2 Bytes.
1695 */
1696 if (msdu_meta->first_buffer)
1697 l2_hdr_offset =
1698 DP_RX_MON_NONRAW_L2_HDR_PAD_BYTE;
1699 else
1700 l2_hdr_offset = DP_RX_MON_RAW_L2_HDR_PAD_BYTE;
1701
1702 if (msdu_meta->first_buffer) {
1703 /* Adjust page frag offset to point to 802.11 header */
1704 hdr_frag_size = qdf_nbuf_get_frag_size_by_idx(msdu_cur, frag_iter-1);
1705 if (hdr_frag_size > (msdu_llc_len + amsdu_pad))
1706 qdf_nbuf_trim_add_frag_size(msdu_cur, frag_iter - 1, -(hdr_frag_size - (msdu_llc_len + amsdu_pad)), 0);
1707
1708 /* Adjust page frag offset to appropriate after decap header */
1709 frag_page_offset =
1710 (decap_hdr_pull_bytes + l2_hdr_offset);
1711 if (frag_size > (decap_hdr_pull_bytes + l2_hdr_offset)) {
1712 qdf_nbuf_move_frag_page_offset(msdu_cur, frag_iter, frag_page_offset);
1713 frag_size = frag_size - (l2_hdr_offset + decap_hdr_pull_bytes);
1714 }
1715
1716
1717 /*
1718 * Calculate new page offset and create hole
1719 * if amsdu_pad required.
1720 */
1721 tot_msdu_len = frag_size;
1722 /*
1723 * No amsdu padding required for first frame of
1724 * continuation buffer
1725 */
1726 if (!msdu_meta->last_buffer) {
1727 amsdu_pad = 0;
1728 continue;
1729 }
1730 } else {
1731 tot_msdu_len += frag_size;
1732 }
1733
1734 /* Will reach to this place in only two case:
1735 * 1. Single buffer MSDU
1736 * 2. Last buffer of MSDU in case of multiple buf MSDU
1737 */
1738
1739 /* This flag is used to identify msdu boundary */
1740 prev_msdu_end_received = true;
1741 /* Check size of buffer if amsdu padding required */
1742 amsdu_pad = tot_msdu_len & 0x3;
1743 amsdu_pad = amsdu_pad ? (4 - amsdu_pad) : 0;
1744
1745 /* Create placeholder if current buffer can
1746 * accommodate padding.
1747 */
1748 if (amsdu_pad && (amsdu_pad <= pad_byte_pholder)) {
1749 char *frag_addr_temp;
1750
1751 qdf_nbuf_trim_add_frag_size(msdu_cur,
1752 frag_iter,
1753 amsdu_pad, 0);
1754 frag_addr_temp = (char *)qdf_nbuf_get_frag_addr(msdu_cur,
1755 frag_iter);
1756 frag_addr_temp = (frag_addr_temp +
1757 qdf_nbuf_get_frag_size_by_idx(msdu_cur, frag_iter)) -
1758 amsdu_pad;
1759 qdf_mem_zero(frag_addr_temp, amsdu_pad);
1760 amsdu_pad = 0;
1761 }
1762
1763 /* reset tot_msdu_len */
1764 tot_msdu_len = 0;
1765 }
1766 if (is_nbuf_head) {
1767 msdu_cur = qdf_nbuf_get_ext_list(msdu_cur);
1768 is_nbuf_head = false;
1769 } else {
1770 msdu_cur = qdf_nbuf_queue_next(msdu_cur);
1771 }
1772 }
1773
1774 return QDF_STATUS_SUCCESS;
1775 }
1776
1777 static inline int
dp_rx_mon_flush_packet_tlv(struct dp_pdev * pdev,void * buf,uint16_t end_offset,union dp_mon_desc_list_elem_t ** desc_list,union dp_mon_desc_list_elem_t ** tail)1778 dp_rx_mon_flush_packet_tlv(struct dp_pdev *pdev, void *buf, uint16_t end_offset,
1779 union dp_mon_desc_list_elem_t **desc_list,
1780 union dp_mon_desc_list_elem_t **tail)
1781 {
1782 struct dp_soc *soc = pdev->soc;
1783 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
1784 struct dp_mon_pdev_be *mon_pdev_be =
1785 dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
1786 struct dp_mon_soc *mon_soc = soc->monitor_soc;
1787 uint16_t work_done = 0;
1788 qdf_frag_t addr;
1789 uint8_t *rx_tlv;
1790 uint8_t *rx_tlv_start;
1791 uint16_t tlv_status = HAL_TLV_STATUS_BUF_DONE;
1792 struct hal_rx_ppdu_info *ppdu_info;
1793 uint32_t cookie_2;
1794
1795 if (!buf)
1796 return work_done;
1797
1798 ppdu_info = &mon_pdev->ppdu_info;
1799 if (!ppdu_info) {
1800 dp_mon_debug("ppdu_info malloc failed pdev: %pK", pdev);
1801 return work_done;
1802 }
1803 qdf_mem_zero(ppdu_info, sizeof(struct hal_rx_ppdu_info));
1804 rx_tlv = buf;
1805 rx_tlv_start = buf;
1806
1807 do {
1808 tlv_status = hal_rx_status_get_tlv_info(rx_tlv,
1809 ppdu_info,
1810 pdev->soc->hal_soc,
1811 buf);
1812
1813 if (tlv_status == HAL_TLV_STATUS_MON_BUF_ADDR) {
1814 struct dp_mon_desc *mon_desc;
1815 unsigned long long desc = ppdu_info->packet_info.sw_cookie;
1816
1817 cookie_2 = DP_MON_GET_COOKIE(desc);
1818 mon_desc = DP_MON_GET_DESC(desc);
1819
1820 qdf_assert_always(mon_desc);
1821
1822 if (mon_desc->cookie_2 != cookie_2) {
1823 mon_pdev->rx_mon_stats.dup_mon_sw_desc++;
1824 qdf_err("duplicate cookie found mon_desc:%pK", mon_desc);
1825 qdf_assert_always(0);
1826 }
1827
1828 /* WAR: sometimes duplicate pkt desc are received
1829 * from HW, this check gracefully handles
1830 * such cases.
1831 */
1832 if ((mon_desc == mon_pdev_be->prev_rxmon_pkt_desc) &&
1833 (mon_desc->cookie ==
1834 mon_pdev_be->prev_rxmon_pkt_cookie)) {
1835 dp_mon_err("duplicate pkt desc found mon_pdev: %pK mon_desc: %pK cookie: %d",
1836 mon_pdev, mon_desc,
1837 mon_desc->cookie);
1838 mon_pdev->rx_mon_stats.dup_mon_buf_cnt++;
1839 goto end;
1840 }
1841 mon_pdev_be->prev_rxmon_pkt_desc = mon_desc;
1842 mon_pdev_be->prev_rxmon_pkt_cookie = mon_desc->cookie;
1843
1844 addr = mon_desc->buf_addr;
1845
1846 if (!mon_desc->unmapped) {
1847 qdf_mem_unmap_page(soc->osdev,
1848 (qdf_dma_addr_t)mon_desc->paddr,
1849 DP_MON_DATA_BUFFER_SIZE,
1850 QDF_DMA_FROM_DEVICE);
1851 mon_desc->unmapped = 1;
1852 }
1853 dp_mon_add_to_free_desc_list(desc_list, tail, mon_desc);
1854 work_done++;
1855
1856 if (addr) {
1857 qdf_frag_free(addr);
1858 DP_STATS_INC(mon_soc, frag_free, 1);
1859 }
1860 }
1861
1862 end:
1863 rx_tlv = hal_rx_status_get_next_tlv(rx_tlv, 1);
1864
1865 if ((rx_tlv - rx_tlv_start) >= (end_offset + 1))
1866 break;
1867
1868 } while ((tlv_status == HAL_TLV_STATUS_PPDU_NOT_DONE) ||
1869 (tlv_status == HAL_TLV_STATUS_HEADER) ||
1870 (tlv_status == HAL_TLV_STATUS_MPDU_END) ||
1871 (tlv_status == HAL_TLV_STATUS_MSDU_END) ||
1872 (tlv_status == HAL_TLV_STATUS_MON_BUF_ADDR) ||
1873 (tlv_status == HAL_TLV_STATUS_MPDU_START));
1874
1875 return work_done;
1876 }
1877
1878 #endif
1879
1880 /**
1881 * dp_rx_mon_flush_status_buf_queue() - Flush status buffer queue
1882 *
1883 * @pdev: DP pdev handle
1884 *
1885 *Return: void
1886 */
1887 static inline void
dp_rx_mon_flush_status_buf_queue(struct dp_pdev * pdev)1888 dp_rx_mon_flush_status_buf_queue(struct dp_pdev *pdev)
1889 {
1890 struct dp_soc *soc = pdev->soc;
1891 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
1892 struct dp_mon_pdev_be *mon_pdev_be =
1893 dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
1894 union dp_mon_desc_list_elem_t *desc_list = NULL;
1895 union dp_mon_desc_list_elem_t *tail = NULL;
1896 struct dp_mon_desc *mon_desc;
1897 uint16_t idx;
1898 void *buf;
1899 struct dp_mon_soc *mon_soc = soc->monitor_soc;
1900 struct dp_mon_soc_be *mon_soc_be = dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
1901 struct dp_mon_desc_pool *rx_mon_desc_pool = &mon_soc_be->rx_desc_mon;
1902 uint16_t work_done = 0;
1903 uint16_t status_buf_count;
1904 uint16_t end_offset = 0;
1905
1906 if (!mon_pdev_be->desc_count) {
1907 dp_mon_info("no of status buffer count is zero: %pK", pdev);
1908 return;
1909 }
1910
1911 status_buf_count = mon_pdev_be->desc_count;
1912 for (idx = 0; idx < status_buf_count; idx++) {
1913 mon_desc = mon_pdev_be->status[idx];
1914 if (!mon_desc) {
1915 qdf_assert_always(0);
1916 return;
1917 }
1918
1919 buf = mon_desc->buf_addr;
1920 end_offset = mon_desc->end_offset;
1921
1922 dp_mon_add_to_free_desc_list(&desc_list, &tail, mon_desc);
1923 work_done++;
1924
1925 work_done += dp_rx_mon_flush_packet_tlv(pdev, buf, end_offset,
1926 &desc_list, &tail);
1927
1928 /* set status buffer pointer to NULL */
1929 mon_pdev_be->status[idx] = NULL;
1930 mon_pdev_be->desc_count--;
1931
1932 qdf_frag_free(buf);
1933 DP_STATS_INC(mon_soc, frag_free, 1);
1934 }
1935
1936 if (work_done) {
1937 mon_pdev->rx_mon_stats.mon_rx_bufs_replenished_dest +=
1938 work_done;
1939 if (desc_list)
1940 dp_mon_add_desc_list_to_free_list(soc,
1941 &desc_list, &tail,
1942 rx_mon_desc_pool);
1943 }
1944 }
1945
1946 /**
1947 * dp_rx_mon_handle_flush_n_trucated_ppdu() - Handle flush and truncated ppdu
1948 *
1949 * @soc: DP soc handle
1950 * @pdev: pdev handle
1951 * @mon_desc: mon sw desc
1952 */
1953 static inline void
dp_rx_mon_handle_flush_n_trucated_ppdu(struct dp_soc * soc,struct dp_pdev * pdev,struct dp_mon_desc * mon_desc)1954 dp_rx_mon_handle_flush_n_trucated_ppdu(struct dp_soc *soc,
1955 struct dp_pdev *pdev,
1956 struct dp_mon_desc *mon_desc)
1957 {
1958 union dp_mon_desc_list_elem_t *desc_list = NULL;
1959 union dp_mon_desc_list_elem_t *tail = NULL;
1960 struct dp_mon_soc *mon_soc = soc->monitor_soc;
1961 struct dp_mon_soc_be *mon_soc_be =
1962 dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
1963 struct dp_mon_desc_pool *rx_mon_desc_pool = &mon_soc_be->rx_desc_mon;
1964 uint16_t work_done;
1965 void *buf;
1966 uint16_t end_offset = 0;
1967
1968 /* Flush status buffers in queue */
1969 dp_rx_mon_flush_status_buf_queue(pdev);
1970 buf = mon_desc->buf_addr;
1971 end_offset = mon_desc->end_offset;
1972 dp_mon_add_to_free_desc_list(&desc_list, &tail, mon_desc);
1973 work_done = 1;
1974 work_done += dp_rx_mon_flush_packet_tlv(pdev, buf, end_offset,
1975 &desc_list, &tail);
1976 if (buf) {
1977 qdf_frag_free(buf);
1978 DP_STATS_INC(mon_soc, frag_free, 1);
1979 }
1980
1981 if (desc_list)
1982 dp_mon_add_desc_list_to_free_list(soc, &desc_list, &tail,
1983 rx_mon_desc_pool);
1984 }
1985
dp_rx_mon_append_nbuf(qdf_nbuf_t nbuf,qdf_nbuf_t tmp_nbuf)1986 void dp_rx_mon_append_nbuf(qdf_nbuf_t nbuf, qdf_nbuf_t tmp_nbuf)
1987 {
1988 qdf_nbuf_t last_nbuf;
1989
1990 /*
1991 * If nbuf does not have fraglist, then append tmp_nbuf as fraglist,
1992 * else append tmp_nbuf as next of last_nbuf present in nbuf fraglist.
1993 */
1994 if (!qdf_nbuf_has_fraglist(nbuf))
1995 qdf_nbuf_append_ext_list(nbuf, tmp_nbuf,
1996 qdf_nbuf_len(tmp_nbuf));
1997 else {
1998 last_nbuf = qdf_nbuf_get_last_frag_list_nbuf(nbuf);
1999
2000 if (qdf_likely(last_nbuf))
2001 qdf_nbuf_set_next(last_nbuf, tmp_nbuf);
2002 }
2003 }
2004
2005 static
dp_rx_mon_process_tlv_status(struct dp_pdev * pdev,struct hal_rx_ppdu_info * ppdu_info,void * status_frag,uint16_t tlv_status,union dp_mon_desc_list_elem_t ** desc_list,union dp_mon_desc_list_elem_t ** tail)2006 uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev,
2007 struct hal_rx_ppdu_info *ppdu_info,
2008 void *status_frag,
2009 uint16_t tlv_status,
2010 union dp_mon_desc_list_elem_t **desc_list,
2011 union dp_mon_desc_list_elem_t **tail)
2012 {
2013 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
2014 uint8_t user_id = ppdu_info->user_id;
2015 uint8_t num_buf_reaped = 0;
2016 bool rx_hdr_valid = true;
2017
2018 if (!mon_pdev->monitor_configured &&
2019 !dp_lite_mon_is_rx_enabled(mon_pdev)) {
2020 return num_buf_reaped;
2021 }
2022
2023 /* If user id or rx header len is invalid drop this
2024 * mpdu. However we have to honor buffer address TLV
2025 * for this mpdu to free any associated packet buffer
2026 */
2027 if (qdf_unlikely(user_id >= HAL_MAX_UL_MU_USERS ||
2028 ppdu_info->hdr_len > DP_RX_MON_MAX_RX_HEADER_LEN))
2029 rx_hdr_valid = false;
2030
2031 switch (tlv_status) {
2032 case HAL_TLV_STATUS_HEADER: {
2033 if (qdf_unlikely(!rx_hdr_valid)) {
2034 dp_mon_debug("rx hdr invalid userid: %d, len: %d ",
2035 user_id, ppdu_info->hdr_len);
2036 mon_pdev->rx_mon_stats.rx_hdr_invalid_cnt++;
2037 return num_buf_reaped;
2038 }
2039 dp_rx_mon_handle_rx_hdr(pdev, ppdu_info, status_frag);
2040 }
2041 break;
2042 case HAL_TLV_STATUS_MON_BUF_ADDR:
2043 {
2044 num_buf_reaped = dp_rx_mon_handle_mon_buf_addr(pdev, ppdu_info, desc_list, tail);
2045 }
2046 break;
2047 case HAL_TLV_STATUS_MSDU_END:
2048 {
2049 if (qdf_unlikely(!rx_hdr_valid))
2050 break;
2051
2052 dp_rx_mon_handle_msdu_end(pdev, ppdu_info);
2053 }
2054 break;
2055 case HAL_TLV_STATUS_MPDU_START:
2056 {
2057 if (qdf_unlikely(!rx_hdr_valid))
2058 break;
2059
2060 dp_rx_mon_handle_mpdu_start(ppdu_info);
2061 break;
2062 }
2063 case HAL_TLV_STATUS_MPDU_END:
2064 {
2065 if (qdf_unlikely(!rx_hdr_valid))
2066 break;
2067
2068 dp_rx_mon_handle_mpdu_end(ppdu_info);
2069 }
2070 break;
2071 case HAL_TLV_STATUS_MON_DROP:
2072 {
2073 mon_pdev->rx_mon_stats.ppdu_drop_cnt +=
2074 ppdu_info->drop_cnt.ppdu_drop_cnt;
2075 mon_pdev->rx_mon_stats.mpdu_drop_cnt +=
2076 ppdu_info->drop_cnt.mpdu_drop_cnt;
2077 mon_pdev->rx_mon_stats.end_of_ppdu_drop_cnt +=
2078 ppdu_info->drop_cnt.end_of_ppdu_drop_cnt;
2079 mon_pdev->rx_mon_stats.tlv_drop_cnt +=
2080 ppdu_info->drop_cnt.tlv_drop_cnt;
2081 }
2082 break;
2083 }
2084 return num_buf_reaped;
2085 }
2086
2087 /**
2088 * dp_rx_mon_process_status_tlv() - Handle mon status process TLV
2089 *
2090 * @pdev: DP pdev handle
2091 *
2092 * Return
2093 */
2094 static inline struct hal_rx_ppdu_info *
dp_rx_mon_process_status_tlv(struct dp_pdev * pdev)2095 dp_rx_mon_process_status_tlv(struct dp_pdev *pdev)
2096 {
2097 struct dp_soc *soc = pdev->soc;
2098 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
2099 struct dp_mon_pdev_be *mon_pdev_be =
2100 dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
2101 union dp_mon_desc_list_elem_t *desc_list = NULL;
2102 union dp_mon_desc_list_elem_t *tail = NULL;
2103 struct dp_mon_desc *mon_desc;
2104 uint16_t idx;
2105 void *buf;
2106 struct hal_rx_ppdu_info *ppdu_info;
2107 uint8_t *rx_tlv;
2108 uint8_t *rx_tlv_start;
2109 uint16_t end_offset = 0;
2110 uint16_t tlv_status = HAL_TLV_STATUS_BUF_DONE;
2111 struct dp_mon_soc *mon_soc = soc->monitor_soc;
2112 struct dp_mon_soc_be *mon_soc_be = dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
2113 struct dp_mon_desc_pool *rx_mon_desc_pool = &mon_soc_be->rx_desc_mon;
2114 uint16_t work_done = 0;
2115 uint16_t status_buf_count;
2116
2117 if (!mon_pdev_be->desc_count) {
2118 dp_mon_err("no of status buffer count is zero: %pK", pdev);
2119 return NULL;
2120 }
2121
2122 ppdu_info = dp_rx_mon_get_ppdu_info(mon_pdev);
2123
2124 if (!ppdu_info) {
2125 dp_mon_debug("ppdu_info malloc failed pdev: %pK", pdev);
2126 dp_rx_mon_flush_status_buf_queue(pdev);
2127 return NULL;
2128 }
2129
2130 mon_pdev->rx_mon_stats.total_ppdu_info_alloc++;
2131
2132 status_buf_count = mon_pdev_be->desc_count;
2133 for (idx = 0; idx < status_buf_count; idx++) {
2134 mon_desc = mon_pdev_be->status[idx];
2135 if (!mon_desc) {
2136 return NULL;
2137 }
2138
2139 buf = mon_desc->buf_addr;
2140 end_offset = mon_desc->end_offset;
2141
2142 dp_mon_add_to_free_desc_list(&desc_list, &tail, mon_desc);
2143 work_done++;
2144
2145 rx_tlv = buf;
2146 rx_tlv_start = buf;
2147
2148 dp_mon_record_clear_buffer(mon_pdev_be);
2149
2150 do {
2151 tlv_status = hal_rx_status_get_tlv_info(rx_tlv,
2152 ppdu_info,
2153 pdev->soc->hal_soc,
2154 buf);
2155 dp_mon_record_tlv(mon_pdev_be, ppdu_info);
2156 work_done += dp_rx_mon_process_tlv_status(pdev,
2157 ppdu_info,
2158 buf,
2159 tlv_status,
2160 &desc_list,
2161 &tail);
2162 rx_tlv = hal_rx_status_get_next_tlv(rx_tlv, 1);
2163
2164 /* HW provides end_offset (how many bytes HW DMA'ed)
2165 * as part of descriptor, use this as delimiter for
2166 * status buffer
2167 */
2168 if ((rx_tlv - rx_tlv_start) >= (end_offset + 1))
2169 break;
2170
2171 } while ((tlv_status == HAL_TLV_STATUS_PPDU_NOT_DONE) ||
2172 (tlv_status == HAL_TLV_STATUS_HEADER) ||
2173 (tlv_status == HAL_TLV_STATUS_MPDU_END) ||
2174 (tlv_status == HAL_TLV_STATUS_MSDU_END) ||
2175 (tlv_status == HAL_TLV_STATUS_MON_BUF_ADDR) ||
2176 (tlv_status == HAL_TLV_STATUS_MPDU_START));
2177
2178 /* set status buffer pointer to NULL */
2179 mon_pdev_be->status[idx] = NULL;
2180 mon_pdev_be->desc_count--;
2181
2182 qdf_frag_free(buf);
2183 DP_STATS_INC(mon_soc, frag_free, 1);
2184 mon_pdev->rx_mon_stats.status_buf_count++;
2185 dp_mon_record_index_update(mon_pdev_be);
2186 }
2187
2188 dp_mon_rx_stats_update_rssi_dbm_params(mon_pdev, ppdu_info);
2189 if (work_done) {
2190 mon_pdev->rx_mon_stats.mon_rx_bufs_replenished_dest +=
2191 work_done;
2192 if (desc_list)
2193 dp_mon_add_desc_list_to_free_list(soc,
2194 &desc_list, &tail,
2195 rx_mon_desc_pool);
2196 }
2197
2198 ppdu_info->rx_status.tsft = ppdu_info->rx_status.tsft +
2199 pdev->timestamp.mlo_offset_lo_us +
2200 ((uint64_t)pdev->timestamp.mlo_offset_hi_us
2201 << 32);
2202
2203 return ppdu_info;
2204 }
2205
2206 /**
2207 * dp_mon_pdev_flush_desc() - Flush status and packet desc during deinit
2208 *
2209 * @pdev: DP pdev handle
2210 *
2211 * Return
2212 */
dp_mon_pdev_flush_desc(struct dp_pdev * pdev)2213 static QDF_STATUS dp_mon_pdev_flush_desc(struct dp_pdev *pdev)
2214 {
2215 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
2216 struct dp_mon_pdev_be *mon_pdev_be;
2217
2218 if (qdf_unlikely(!mon_pdev)) {
2219 dp_mon_debug("monitor pdev is NULL");
2220 return QDF_STATUS_E_FAILURE;
2221 }
2222
2223 mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
2224
2225 qdf_spin_lock_bh(&mon_pdev->mon_lock);
2226
2227 if (mon_pdev_be->desc_count) {
2228 mon_pdev->rx_mon_stats.pending_desc_count +=
2229 mon_pdev_be->desc_count;
2230 dp_rx_mon_flush_status_buf_queue(pdev);
2231 }
2232
2233 qdf_spin_unlock_bh(&mon_pdev->mon_lock);
2234
2235 return QDF_STATUS_SUCCESS;
2236 }
2237
2238 #ifdef WLAN_FEATURE_11BE_MLO
2239 #define DP_PEER_ID_MASK 0x3FFF
2240 /**
2241 * dp_rx_mon_update_peer_id() - Update sw_peer_id with link peer_id
2242 *
2243 * @pdev: DP pdev handle
2244 * @ppdu_info: HAL PPDU Info buffer
2245 *
2246 * Return: none
2247 */
2248 static inline
dp_rx_mon_update_peer_id(struct dp_pdev * pdev,struct hal_rx_ppdu_info * ppdu_info)2249 void dp_rx_mon_update_peer_id(struct dp_pdev *pdev,
2250 struct hal_rx_ppdu_info *ppdu_info)
2251 {
2252 uint32_t i;
2253 uint16_t peer_id;
2254 struct dp_soc *soc = pdev->soc;
2255 uint32_t num_users = ppdu_info->com_info.num_users;
2256
2257 for (i = 0; i < num_users; i++) {
2258 peer_id = ppdu_info->rx_user_status[i].sw_peer_id;
2259 if (peer_id == HTT_INVALID_PEER)
2260 continue;
2261 /*
2262 +---------------------------------------------------------------------+
2263 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
2264 +---------------------------------------------------------------------+
2265 | CHIP ID | ML | PEER ID |
2266 +---------------------------------------------------------------------+
2267 */
2268 peer_id &= DP_PEER_ID_MASK;
2269 peer_id = dp_get_link_peer_id_by_lmac_id(soc, peer_id,
2270 pdev->lmac_id);
2271 ppdu_info->rx_user_status[i].sw_peer_id = peer_id;
2272 }
2273 }
2274 #else
2275 static inline
dp_rx_mon_update_peer_id(struct dp_pdev * pdev,struct hal_rx_ppdu_info * ppdu_info)2276 void dp_rx_mon_update_peer_id(struct dp_pdev *pdev,
2277 struct hal_rx_ppdu_info *ppdu_info)
2278 {
2279 }
2280 #endif
2281
2282 /*
2283 * HAL_RX_PKT_TYPE_11A 0 -> CDP_PKT_TYPE_OFDM
2284 * HAL_RX_PKT_TYPE_11B 1 -> CDP_PKT_TYPE_CCK
2285 * HAL_RX_PKT_TYPE_11N 2 -> CDP_PKT_TYPE_HT
2286 * HAL_RX_PKT_TYPE_11AC 3 -> CDP_PKT_TYPE_VHT
2287 * HAL_RX_PKT_TYPE_11AX 4 -> CDP_PKT_TYPE_HE
2288 * HAL_RX_PKT_TYPE_11BE 6 -> CDP_PKT_TYPE_EHT
2289 */
2290
2291 static uint32_t const cdp_preamble_type_map[] = {
2292 CDP_PKT_TYPE_OFDM,
2293 CDP_PKT_TYPE_CCK,
2294 CDP_PKT_TYPE_HT,
2295 CDP_PKT_TYPE_VHT,
2296 CDP_PKT_TYPE_HE,
2297 CDP_PKT_TYPE_NO_SUP,
2298 #ifdef WLAN_FEATURE_11BE
2299 CDP_PKT_TYPE_EHT,
2300 #endif
2301 CDP_PKT_TYPE_MAX,
2302 };
2303
2304 /*
2305 * HAL_RX_RECEPTION_TYPE_SU -> CDP_RX_TYPE_SU
2306 * HAL_RX_RECEPTION_TYPE_MU_MIMO -> CDP_RX_TYPE_MU_MIMO
2307 * HAL_RX_RECEPTION_TYPE_OFDMA -> CDP_RX_TYPE_MU_OFDMA
2308 * HAL_RX_RECEPTION_TYPE_MU_OFDMA -> CDP_RX_TYPE_MU_OFDMA_MIMO
2309 */
2310 static uint32_t const cdp_reception_type_map[] = {
2311 CDP_RX_TYPE_SU,
2312 CDP_RX_TYPE_MU_MIMO,
2313 CDP_RX_TYPE_MU_OFDMA,
2314 CDP_RX_TYPE_MU_OFDMA_MIMO,
2315 };
2316
2317 static uint32_t const cdp_mu_dl_up_map[] = {
2318 CDP_MU_TYPE_DL,
2319 CDP_MU_TYPE_UL,
2320 };
2321
2322 static inline void
dp_rx_mu_stats_update(struct hal_rx_ppdu_info * ppdu_info,struct cdp_pdev_mon_stats * rx_mon_sts,uint32_t preamble_type,uint32_t recept_type,uint32_t mu_dl_ul,uint32_t i)2323 dp_rx_mu_stats_update(
2324 struct hal_rx_ppdu_info *ppdu_info,
2325 struct cdp_pdev_mon_stats *rx_mon_sts,
2326 uint32_t preamble_type,
2327 uint32_t recept_type,
2328 uint32_t mu_dl_ul,
2329 uint32_t i
2330 )
2331 {
2332 struct mon_rx_user_status *rx_user_status;
2333
2334 rx_user_status = &ppdu_info->rx_user_status[i];
2335 rx_mon_sts->mpdu_cnt_fcs_ok[preamble_type][recept_type][mu_dl_ul][i]
2336 += rx_user_status->mpdu_cnt_fcs_ok;
2337 rx_mon_sts->mpdu_cnt_fcs_err[preamble_type][recept_type][mu_dl_ul][i]
2338 += rx_user_status->mpdu_cnt_fcs_err;
2339 }
2340
2341 static inline void
dp_rx_he_ppdu_stats_update(struct cdp_pdev_mon_stats * stats,struct hal_rx_u_sig_info * u_sig)2342 dp_rx_he_ppdu_stats_update(
2343 struct cdp_pdev_mon_stats *stats,
2344 struct hal_rx_u_sig_info *u_sig
2345 )
2346 {
2347 stats->ppdu_eht_type_mode[u_sig->ppdu_type_comp_mode][u_sig->ul_dl]++;
2348 }
2349
2350 static inline void
dp_rx_he_ppdu_stats(struct dp_pdev * pdev,struct hal_rx_ppdu_info * ppdu_info)2351 dp_rx_he_ppdu_stats(struct dp_pdev *pdev, struct hal_rx_ppdu_info *ppdu_info)
2352 {
2353 struct dp_mon_pdev *mon_pdev;
2354 struct cdp_pdev_mon_stats *rx_mon_stats;
2355
2356 mon_pdev = pdev->monitor_pdev;
2357 rx_mon_stats = &mon_pdev->rx_mon_stats;
2358
2359 if (ppdu_info->u_sig_info.ppdu_type_comp_mode < CDP_EHT_TYPE_MODE_MAX &&
2360 ppdu_info->u_sig_info.ul_dl < CDP_MU_TYPE_MAX)
2361 dp_rx_he_ppdu_stats_update(
2362 rx_mon_stats,
2363 &ppdu_info->u_sig_info);
2364 else
2365 qdf_assert(0);
2366 }
2367
2368 static inline void
dp_rx_mu_stats(struct dp_pdev * pdev,struct hal_rx_ppdu_info * ppdu_info)2369 dp_rx_mu_stats(struct dp_pdev *pdev, struct hal_rx_ppdu_info *ppdu_info)
2370 {
2371 struct dp_mon_pdev *mon_pdev;
2372 struct cdp_pdev_mon_stats *rx_mon_stats;
2373 struct mon_rx_status *rx_status;
2374 uint32_t preamble_type, reception_type, mu_dl_ul, num_users, i;
2375
2376 mon_pdev = pdev->monitor_pdev;
2377 rx_mon_stats = &mon_pdev->rx_mon_stats;
2378 rx_status = &ppdu_info->rx_status;
2379
2380 num_users = ppdu_info->com_info.num_users;
2381
2382 if (rx_status->preamble_type < CDP_PKT_TYPE_MAX)
2383 preamble_type = cdp_preamble_type_map[rx_status->preamble_type];
2384 else
2385 preamble_type = CDP_PKT_TYPE_NO_SUP;
2386
2387 reception_type = cdp_reception_type_map[rx_status->reception_type];
2388 mu_dl_ul = cdp_mu_dl_up_map[rx_status->mu_dl_ul];
2389
2390 for (i = 0; i < num_users; i++) {
2391 if (i >= CDP_MU_SNIF_USER_MAX)
2392 return;
2393
2394 dp_rx_mu_stats_update(ppdu_info, rx_mon_stats, preamble_type,
2395 reception_type, mu_dl_ul, i);
2396 }
2397
2398 if (rx_status->eht_flags)
2399 dp_rx_he_ppdu_stats(pdev, ppdu_info);
2400 }
2401
2402 static inline uint32_t
dp_rx_mon_srng_process_2_0(struct dp_soc * soc,struct dp_intr * int_ctx,uint32_t mac_id,uint32_t quota)2403 dp_rx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx,
2404 uint32_t mac_id, uint32_t quota)
2405 {
2406 struct dp_pdev *pdev = dp_get_pdev_for_lmac_id(soc, mac_id);
2407 struct dp_mon_pdev *mon_pdev;
2408 struct dp_mon_pdev_be *mon_pdev_be;
2409 struct dp_mon_soc *mon_soc = soc->monitor_soc;
2410 struct dp_mon_soc_be *mon_soc_be = dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
2411 struct dp_mon_desc_pool *rx_mon_desc_pool = &mon_soc_be->rx_desc_mon;
2412 hal_soc_handle_t hal_soc = soc->hal_soc;
2413 void *rx_mon_dst_ring_desc;
2414 void *mon_dst_srng;
2415 uint32_t work_done = 0;
2416 struct hal_rx_ppdu_info *ppdu_info = NULL;
2417 QDF_STATUS status;
2418 uint32_t cookie_2;
2419 if (!pdev || !hal_soc) {
2420 dp_mon_err("%pK: pdev or hal_soc is null, mac_id = %d",
2421 soc, mac_id);
2422 return work_done;
2423 }
2424
2425 mon_pdev = pdev->monitor_pdev;
2426 mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
2427 mon_dst_srng = soc->rxdma_mon_dst_ring[mac_id].hal_srng;
2428
2429 if (!mon_dst_srng || !hal_srng_initialized(mon_dst_srng)) {
2430 dp_mon_err("%pK: : HAL Monitor Destination Ring Init Failed -- %pK",
2431 soc, mon_dst_srng);
2432 return work_done;
2433 }
2434
2435 qdf_spin_lock_bh(&mon_pdev->mon_lock);
2436
2437 if (qdf_unlikely(dp_rx_srng_access_start(int_ctx, soc, mon_dst_srng))) {
2438 dp_mon_err("%s %d : HAL Mon Dest Ring access Failed -- %pK",
2439 __func__, __LINE__, mon_dst_srng);
2440 qdf_spin_unlock_bh(&mon_pdev->mon_lock);
2441 return work_done;
2442 }
2443
2444 while (qdf_likely((rx_mon_dst_ring_desc =
2445 (void *)hal_srng_dst_peek(hal_soc, mon_dst_srng))
2446 && quota--)) {
2447 struct hal_mon_desc hal_mon_rx_desc = {0};
2448 struct dp_mon_desc *mon_desc;
2449 unsigned long long desc;
2450 hal_be_get_mon_dest_status(soc->hal_soc,
2451 rx_mon_dst_ring_desc,
2452 &hal_mon_rx_desc);
2453 /* If it's empty descriptor, skip processing
2454 * and process next hW desc
2455 */
2456 if (hal_mon_rx_desc.empty_descriptor == 1) {
2457 dp_mon_debug("empty descriptor found mon_pdev: %pK",
2458 mon_pdev);
2459 rx_mon_dst_ring_desc =
2460 hal_srng_dst_get_next(hal_soc, mon_dst_srng);
2461 dp_rx_mon_update_drop_cnt(mon_pdev, &hal_mon_rx_desc);
2462 continue;
2463 }
2464 desc = hal_mon_rx_desc.buf_addr;
2465 cookie_2 = DP_MON_GET_COOKIE(desc);
2466 mon_desc = DP_MON_GET_DESC(desc);
2467
2468 qdf_assert_always(mon_desc);
2469
2470 if (mon_desc->cookie_2 != cookie_2) {
2471 mon_pdev->rx_mon_stats.dup_mon_sw_desc++;
2472 qdf_err("duplicate cookie found mon_desc:%pK", mon_desc);
2473 qdf_assert_always(0);
2474 }
2475
2476 if ((mon_desc == mon_pdev_be->prev_rxmon_desc) &&
2477 (mon_desc->cookie == mon_pdev_be->prev_rxmon_cookie)) {
2478 dp_mon_err("duplicate descritout found mon_pdev: %pK mon_desc: %pK cookie: %d",
2479 mon_pdev, mon_desc, mon_desc->cookie);
2480 mon_pdev->rx_mon_stats.dup_mon_buf_cnt++;
2481 hal_srng_dst_get_next(hal_soc, mon_dst_srng);
2482 continue;
2483 }
2484 mon_pdev_be->prev_rxmon_desc = mon_desc;
2485 mon_pdev_be->prev_rxmon_cookie = mon_desc->cookie;
2486
2487 if (!mon_desc->unmapped) {
2488 qdf_mem_unmap_page(soc->osdev, mon_desc->paddr,
2489 rx_mon_desc_pool->buf_size,
2490 QDF_DMA_FROM_DEVICE);
2491 mon_desc->unmapped = 1;
2492 }
2493 mon_desc->end_offset = hal_mon_rx_desc.end_offset;
2494
2495 /* Flush and truncated status buffers content
2496 * need to discarded
2497 */
2498 if (hal_mon_rx_desc.end_reason == HAL_MON_FLUSH_DETECTED ||
2499 hal_mon_rx_desc.end_reason == HAL_MON_PPDU_TRUNCATED) {
2500 dp_mon_debug("end_resaon: %d mon_pdev: %pK",
2501 hal_mon_rx_desc.end_reason, mon_pdev);
2502 mon_pdev->rx_mon_stats.status_ppdu_drop++;
2503 dp_rx_mon_handle_flush_n_trucated_ppdu(soc,
2504 pdev,
2505 mon_desc);
2506 rx_mon_dst_ring_desc = hal_srng_dst_get_next(hal_soc,
2507 mon_dst_srng);
2508 continue;
2509 }
2510 if (mon_pdev_be->desc_count >= DP_MON_MAX_STATUS_BUF)
2511 qdf_assert_always(0);
2512
2513 mon_pdev_be->status[mon_pdev_be->desc_count++] = mon_desc;
2514
2515 rx_mon_dst_ring_desc = hal_srng_dst_get_next(hal_soc, mon_dst_srng);
2516
2517 dp_rx_process_pktlog_be(soc, pdev, ppdu_info,
2518 mon_desc->buf_addr,
2519 hal_mon_rx_desc.end_offset);
2520
2521 if (hal_mon_rx_desc.end_reason == HAL_MON_STATUS_BUFFER_FULL)
2522 continue;
2523
2524 mon_pdev->rx_mon_stats.status_ppdu_done++;
2525
2526 ppdu_info = dp_rx_mon_process_status_tlv(pdev);
2527
2528 if (ppdu_info) {
2529 mon_pdev->rx_mon_stats.start_user_info_cnt +=
2530 ppdu_info->start_user_info_cnt;
2531 ppdu_info->start_user_info_cnt = 0;
2532
2533 mon_pdev->rx_mon_stats.end_user_stats_cnt +=
2534 ppdu_info->end_user_stats_cnt;
2535 ppdu_info->end_user_stats_cnt = 0;
2536
2537 dp_rx_mon_update_peer_id(pdev, ppdu_info);
2538 dp_rx_mu_stats(pdev, ppdu_info);
2539 }
2540
2541 /* Call enhanced stats update API */
2542 if (mon_pdev->enhanced_stats_en && ppdu_info)
2543 dp_rx_handle_ppdu_stats(soc, pdev, ppdu_info);
2544 else if (dp_cfr_rcc_mode_status(pdev) && ppdu_info)
2545 dp_rx_handle_cfr(soc, pdev, ppdu_info);
2546
2547 dp_rx_mon_update_user_ctrl_frame_stats(pdev, ppdu_info);
2548
2549 status = dp_rx_mon_add_ppdu_info_to_wq(pdev, ppdu_info);
2550 if (status != QDF_STATUS_SUCCESS) {
2551 if (ppdu_info)
2552 dp_rx_mon_free_ppdu_info(pdev, ppdu_info);
2553 }
2554
2555 work_done++;
2556
2557 /* desc_count should be zero after PPDU status processing */
2558 if (mon_pdev_be->desc_count > 0)
2559 qdf_assert_always(0);
2560
2561 mon_pdev_be->desc_count = 0;
2562 }
2563 dp_rx_srng_access_end(int_ctx, soc, mon_dst_srng);
2564
2565 qdf_spin_unlock_bh(&mon_pdev->mon_lock);
2566 dp_mon_info("mac_id: %d, work_done:%d", mac_id, work_done);
2567 return work_done;
2568 }
2569
2570 uint32_t
dp_rx_mon_process_2_0(struct dp_soc * soc,struct dp_intr * int_ctx,uint32_t mac_id,uint32_t quota)2571 dp_rx_mon_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx,
2572 uint32_t mac_id, uint32_t quota)
2573 {
2574 uint32_t work_done;
2575
2576 work_done = dp_rx_mon_srng_process_2_0(soc, int_ctx, mac_id, quota);
2577
2578 return work_done;
2579 }
2580
2581 /**
2582 * dp_mon_pdev_ext_init_2_0() - Init pdev ext param
2583 *
2584 * @pdev: DP pdev handle
2585 *
2586 * Return: QDF_STATUS_SUCCESS: Success
2587 * QDF_STATUS_E_FAILURE: failure
2588 */
dp_mon_pdev_ext_init_2_0(struct dp_pdev * pdev)2589 QDF_STATUS dp_mon_pdev_ext_init_2_0(struct dp_pdev *pdev)
2590 {
2591 return dp_rx_mon_init_wq_sm(pdev);
2592 }
2593
2594 /**
2595 * dp_mon_pdev_ext_deinit_2_0() - denit pdev ext param
2596 *
2597 * @pdev: DP pdev handle
2598 *
2599 * Return: QDF_STATUS_SUCCESS
2600 */
dp_mon_pdev_ext_deinit_2_0(struct dp_pdev * pdev)2601 QDF_STATUS dp_mon_pdev_ext_deinit_2_0(struct dp_pdev *pdev)
2602 {
2603 dp_mon_pdev_flush_desc(pdev);
2604
2605 return dp_rx_mon_deinit_wq_sm(pdev);
2606 }
2607
2608 #ifdef QCA_ENHANCED_STATS_SUPPORT
2609 void
dp_rx_mon_populate_ppdu_usr_info_2_0(struct mon_rx_user_status * rx_user_status,struct cdp_rx_stats_ppdu_user * ppdu_user)2610 dp_rx_mon_populate_ppdu_usr_info_2_0(struct mon_rx_user_status *rx_user_status,
2611 struct cdp_rx_stats_ppdu_user *ppdu_user)
2612 {
2613 ppdu_user->mpdu_retries = rx_user_status->retry_mpdu;
2614 }
2615
2616 #ifdef WLAN_FEATURE_11BE
dp_rx_mon_stats_update_2_0(struct dp_mon_peer * mon_peer,struct cdp_rx_indication_ppdu * ppdu,struct cdp_rx_stats_ppdu_user * ppdu_user)2617 void dp_rx_mon_stats_update_2_0(struct dp_mon_peer *mon_peer,
2618 struct cdp_rx_indication_ppdu *ppdu,
2619 struct cdp_rx_stats_ppdu_user *ppdu_user)
2620 {
2621 uint8_t mcs, preamble, ppdu_type, punc_mode, res_mcs;
2622 uint32_t num_msdu;
2623
2624 preamble = ppdu->u.preamble;
2625 ppdu_type = ppdu->u.ppdu_type;
2626 num_msdu = ppdu_user->num_msdu;
2627 punc_mode = ppdu->punc_bw;
2628
2629 if (ppdu_type == HAL_RX_TYPE_SU)
2630 mcs = ppdu->u.mcs;
2631 else
2632 mcs = ppdu_user->mcs;
2633
2634 DP_STATS_INC(mon_peer, rx.mpdu_retry_cnt, ppdu_user->mpdu_retries);
2635 DP_STATS_INC(mon_peer, rx.punc_bw[punc_mode], num_msdu);
2636
2637 if (preamble == DOT11_BE) {
2638 res_mcs = (mcs < MAX_MCS_11BE) ? mcs : (MAX_MCS - 1);
2639
2640 DP_STATS_INC(mon_peer,
2641 rx.pkt_type[preamble].mcs_count[res_mcs], num_msdu);
2642 DP_STATS_INCC(mon_peer,
2643 rx.su_be_ppdu_cnt.mcs_count[res_mcs], 1,
2644 (ppdu_type == HAL_RX_TYPE_SU));
2645 DP_STATS_INCC(mon_peer,
2646 rx.mu_be_ppdu_cnt[TXRX_TYPE_MU_OFDMA].mcs_count[res_mcs],
2647 1, (ppdu_type == HAL_RX_TYPE_MU_OFDMA));
2648 DP_STATS_INCC(mon_peer,
2649 rx.mu_be_ppdu_cnt[TXRX_TYPE_MU_MIMO].mcs_count[res_mcs],
2650 1, (ppdu_type == HAL_RX_TYPE_MU_MIMO));
2651 }
2652 }
2653
2654 void
dp_rx_mon_populate_ppdu_info_2_0(struct hal_rx_ppdu_info * hal_ppdu_info,struct cdp_rx_indication_ppdu * ppdu)2655 dp_rx_mon_populate_ppdu_info_2_0(struct hal_rx_ppdu_info *hal_ppdu_info,
2656 struct cdp_rx_indication_ppdu *ppdu)
2657 {
2658 uint16_t puncture_pattern;
2659 enum cdp_punctured_modes punc_mode;
2660
2661 /* Align bw value as per host data structures */
2662 if (hal_ppdu_info->rx_status.bw == HAL_FULL_RX_BW_320)
2663 ppdu->u.bw = CMN_BW_320MHZ;
2664 else
2665 ppdu->u.bw = hal_ppdu_info->rx_status.bw;
2666 if (hal_ppdu_info->rx_status.preamble_type == HAL_RX_PKT_TYPE_11BE) {
2667 /* Align preamble value as per host data structures */
2668 ppdu->u.preamble = DOT11_BE;
2669 ppdu->u.stbc = hal_ppdu_info->rx_status.is_stbc;
2670 ppdu->u.dcm = hal_ppdu_info->rx_status.dcm;
2671 } else {
2672 ppdu->u.preamble = hal_ppdu_info->rx_status.preamble_type;
2673 }
2674
2675 puncture_pattern = hal_ppdu_info->rx_status.punctured_pattern;
2676 punc_mode = dp_mon_get_puncture_type(puncture_pattern,
2677 ppdu->u.bw);
2678 ppdu->punc_bw = punc_mode;
2679 }
2680 #else
dp_rx_mon_stats_update_2_0(struct dp_mon_peer * mon_peer,struct cdp_rx_indication_ppdu * ppdu,struct cdp_rx_stats_ppdu_user * ppdu_user)2681 void dp_rx_mon_stats_update_2_0(struct dp_mon_peer *mon_peer,
2682 struct cdp_rx_indication_ppdu *ppdu,
2683 struct cdp_rx_stats_ppdu_user *ppdu_user)
2684 {
2685 DP_STATS_INC(mon_peer, rx.mpdu_retry_cnt, ppdu_user->mpdu_retries);
2686 }
2687
2688 void
dp_rx_mon_populate_ppdu_info_2_0(struct hal_rx_ppdu_info * hal_ppdu_info,struct cdp_rx_indication_ppdu * ppdu)2689 dp_rx_mon_populate_ppdu_info_2_0(struct hal_rx_ppdu_info *hal_ppdu_info,
2690 struct cdp_rx_indication_ppdu *ppdu)
2691 {
2692 ppdu->punc_bw = NO_PUNCTURE;
2693 }
2694 #endif
dp_mon_rx_print_advanced_stats_2_0(struct dp_soc * soc,struct dp_pdev * pdev)2695 void dp_mon_rx_print_advanced_stats_2_0(struct dp_soc *soc,
2696 struct dp_pdev *pdev)
2697 {
2698 struct cdp_pdev_mon_stats *rx_mon_stats;
2699 struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
2700 struct dp_mon_soc *mon_soc = pdev->soc->monitor_soc;
2701 struct dp_mon_pdev_be *mon_pdev_be =
2702 dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
2703
2704 rx_mon_stats = &mon_pdev->rx_mon_stats;
2705
2706 DP_PRINT_STATS("total_ppdu_info_alloc = %d",
2707 rx_mon_stats->total_ppdu_info_alloc);
2708 DP_PRINT_STATS("total_ppdu_info_free = %d",
2709 rx_mon_stats->total_ppdu_info_free);
2710 DP_PRINT_STATS("total_ppdu_info_enq = %d",
2711 rx_mon_stats->total_ppdu_info_enq);
2712 DP_PRINT_STATS("total_ppdu_info_drop = %d",
2713 rx_mon_stats->total_ppdu_info_drop);
2714 DP_PRINT_STATS("rx_hdr_not_received = %d",
2715 rx_mon_stats->rx_hdr_not_received);
2716 DP_PRINT_STATS("parent_buf_alloc = %d",
2717 rx_mon_stats->parent_buf_alloc);
2718 DP_PRINT_STATS("parent_buf_free = %d",
2719 rx_mon_stats->parent_buf_free);
2720 DP_PRINT_STATS("mpdus_buf_to_stack = %d",
2721 rx_mon_stats->mpdus_buf_to_stack);
2722 DP_PRINT_STATS("frag_alloc = %d",
2723 mon_soc->stats.frag_alloc);
2724 DP_PRINT_STATS("total frag_free = %d",
2725 mon_soc->stats.frag_free);
2726 DP_PRINT_STATS("frag_free due to empty queue= %d",
2727 mon_soc->stats.empty_queue);
2728 DP_PRINT_STATS("status_buf_count = %d",
2729 rx_mon_stats->status_buf_count);
2730 DP_PRINT_STATS("pkt_buf_count = %d",
2731 rx_mon_stats->pkt_buf_count);
2732 DP_PRINT_STATS("rx_mon_queue_depth= %d",
2733 mon_pdev_be->rx_mon_queue_depth);
2734 DP_PRINT_STATS("empty_desc= %d",
2735 mon_pdev->rx_mon_stats.empty_desc_ppdu);
2736 DP_PRINT_STATS("mpdu_dropped_due_invalid_decap= %d",
2737 mon_pdev->rx_mon_stats.mpdu_decap_type_invalid);
2738 DP_PRINT_STATS("total_free_elem= %d",
2739 mon_pdev_be->total_free_elem);
2740 DP_PRINT_STATS("ppdu_drop_cnt= %d",
2741 mon_pdev->rx_mon_stats.ppdu_drop_cnt);
2742 DP_PRINT_STATS("mpdu_drop_cnt= %d",
2743 mon_pdev->rx_mon_stats.mpdu_drop_cnt);
2744 DP_PRINT_STATS("end_of_ppdu_drop_cnt= %d",
2745 mon_pdev->rx_mon_stats.end_of_ppdu_drop_cnt);
2746 DP_PRINT_STATS("tlv_drop_cnt= %d",
2747 mon_pdev->rx_mon_stats.tlv_drop_cnt);
2748 DP_PRINT_STATS("rx_hdr_invalid_cnt = %d",
2749 rx_mon_stats->rx_hdr_invalid_cnt);
2750 DP_PRINT_STATS("invalid_dma_length Received = %d",
2751 rx_mon_stats->invalid_dma_length);
2752 DP_PRINT_STATS("pending_desc_count= %d",
2753 mon_pdev->rx_mon_stats.pending_desc_count);
2754 }
2755 #endif
2756
2757 #ifdef WLAN_PKT_CAPTURE_RX_2_0
2758 void
dp_rx_mon_buf_desc_pool_deinit(struct dp_soc * soc)2759 dp_rx_mon_buf_desc_pool_deinit(struct dp_soc *soc)
2760 {
2761 struct dp_mon_soc *mon_soc = soc->monitor_soc;
2762 struct dp_mon_soc_be *mon_soc_be = dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
2763
2764 /* Drain page frag cachce before pool deinit */
2765 qdf_frag_cache_drain(&mon_soc_be->rx_desc_mon.pf_cache);
2766 dp_mon_desc_pool_deinit(&mon_soc_be->rx_desc_mon);
2767 }
2768
2769 QDF_STATUS
dp_rx_mon_buf_desc_pool_init(struct dp_soc * soc)2770 dp_rx_mon_buf_desc_pool_init(struct dp_soc *soc)
2771 {
2772 struct dp_mon_soc *mon_soc = soc->monitor_soc;
2773 struct dp_mon_soc_be *mon_soc_be = dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
2774 uint32_t num_entries;
2775
2776 num_entries =
2777 wlan_cfg_get_dp_soc_rx_mon_buf_ring_size(soc->wlan_cfg_ctx);
2778 return dp_mon_desc_pool_init(&mon_soc_be->rx_desc_mon, num_entries);
2779 }
2780
dp_rx_mon_buf_desc_pool_free(struct dp_soc * soc)2781 void dp_rx_mon_buf_desc_pool_free(struct dp_soc *soc)
2782 {
2783 struct dp_mon_soc *mon_soc = soc->monitor_soc;
2784 struct dp_mon_soc_be *mon_soc_be = dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
2785
2786 if (mon_soc)
2787 dp_mon_desc_pool_free(soc, &mon_soc_be->rx_desc_mon,
2788 DP_MON_RX_DESC_POOL_TYPE);
2789 }
2790
dp_rx_mon_soc_detach_2_0(struct dp_soc * soc,int lmac_id)2791 void dp_rx_mon_soc_detach_2_0(struct dp_soc *soc, int lmac_id)
2792 {
2793 dp_rx_mon_buf_desc_pool_free(soc);
2794 dp_srng_free(soc, &soc->rxdma_mon_buf_ring[lmac_id]);
2795 }
2796
dp_rx_mon_soc_deinit_2_0(struct dp_soc * soc,uint32_t lmac_id)2797 void dp_rx_mon_soc_deinit_2_0(struct dp_soc *soc, uint32_t lmac_id)
2798 {
2799 dp_rx_mon_buffers_free(soc);
2800 dp_rx_mon_buf_desc_pool_deinit(soc);
2801 dp_srng_deinit(soc, &soc->rxdma_mon_buf_ring[lmac_id],
2802 RXDMA_MONITOR_BUF, 0);
2803 }
2804
2805 QDF_STATUS
dp_rx_mon_buf_desc_pool_alloc(struct dp_soc * soc)2806 dp_rx_mon_buf_desc_pool_alloc(struct dp_soc *soc)
2807 {
2808 struct dp_srng *mon_buf_ring;
2809 struct dp_mon_desc_pool *rx_mon_desc_pool;
2810 struct dp_mon_soc *mon_soc = soc->monitor_soc;
2811 struct dp_mon_soc_be *mon_soc_be = dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
2812 int entries;
2813 struct wlan_cfg_dp_soc_ctxt *soc_cfg_ctx;
2814
2815 soc_cfg_ctx = soc->wlan_cfg_ctx;
2816
2817 entries = wlan_cfg_get_dp_soc_rx_mon_buf_ring_size(soc_cfg_ctx);
2818 mon_buf_ring = &soc->rxdma_mon_buf_ring[0];
2819
2820 rx_mon_desc_pool = &mon_soc_be->rx_desc_mon;
2821
2822 qdf_print("%s:%d rx mon buf desc pool entries: %d", __func__, __LINE__, entries);
2823 return dp_mon_desc_pool_alloc(soc, DP_MON_RX_DESC_POOL_TYPE,
2824 entries, rx_mon_desc_pool);
2825 }
2826
2827 void
dp_rx_mon_buffers_free(struct dp_soc * soc)2828 dp_rx_mon_buffers_free(struct dp_soc *soc)
2829 {
2830 struct dp_mon_desc_pool *rx_mon_desc_pool;
2831 struct dp_mon_soc *mon_soc = soc->monitor_soc;
2832 struct dp_mon_soc_be *mon_soc_be = dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
2833
2834 rx_mon_desc_pool = &mon_soc_be->rx_desc_mon;
2835
2836 dp_mon_pool_frag_unmap_and_free(soc, rx_mon_desc_pool);
2837 }
2838
2839 QDF_STATUS
dp_rx_mon_buffers_alloc(struct dp_soc * soc,uint32_t size)2840 dp_rx_mon_buffers_alloc(struct dp_soc *soc, uint32_t size)
2841 {
2842 struct dp_srng *mon_buf_ring;
2843 struct dp_mon_desc_pool *rx_mon_desc_pool;
2844 union dp_mon_desc_list_elem_t *desc_list = NULL;
2845 union dp_mon_desc_list_elem_t *tail = NULL;
2846 struct dp_mon_soc *mon_soc = soc->monitor_soc;
2847 struct dp_mon_soc_be *mon_soc_be = dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
2848
2849 mon_buf_ring = &soc->rxdma_mon_buf_ring[0];
2850
2851 rx_mon_desc_pool = &mon_soc_be->rx_desc_mon;
2852
2853 return dp_mon_buffers_replenish(soc, mon_buf_ring,
2854 rx_mon_desc_pool,
2855 size,
2856 &desc_list, &tail, NULL);
2857 }
2858
dp_rx_mon_soc_init_2_0(struct dp_soc * soc)2859 QDF_STATUS dp_rx_mon_soc_init_2_0(struct dp_soc *soc)
2860 {
2861 if (dp_srng_init(soc, &soc->rxdma_mon_buf_ring[0],
2862 RXDMA_MONITOR_BUF, 0, 0)) {
2863 dp_mon_err("%pK: " RNG_ERR "rx_mon_buf_ring", soc);
2864 goto fail;
2865 }
2866
2867 if (dp_rx_mon_buf_desc_pool_init(soc)) {
2868 dp_mon_err("%pK: " RNG_ERR "rx mon desc pool init", soc);
2869 goto fail;
2870 }
2871
2872 /* monitor buffers for src */
2873 if (dp_rx_mon_buffers_alloc(soc, DP_MON_RING_FILL_LEVEL_DEFAULT)) {
2874 dp_mon_err("%pK: Rx mon buffers allocation failed", soc);
2875 goto fail;
2876 }
2877
2878 return QDF_STATUS_SUCCESS;
2879 fail:
2880 return QDF_STATUS_E_FAILURE;
2881 }
2882
dp_rx_mon_pdev_htt_srng_setup_2_0(struct dp_soc * soc,struct dp_pdev * pdev,int mac_id,int mac_for_pdev)2883 QDF_STATUS dp_rx_mon_pdev_htt_srng_setup_2_0(struct dp_soc *soc,
2884 struct dp_pdev *pdev,
2885 int mac_id,
2886 int mac_for_pdev)
2887 {
2888 return htt_srng_setup(soc->htt_handle, mac_for_pdev,
2889 soc->rxdma_mon_dst_ring[mac_id].hal_srng,
2890 RXDMA_MONITOR_DST);
2891 }
2892
dp_rx_mon_soc_htt_srng_setup_2_0(struct dp_soc * soc,int mac_id)2893 QDF_STATUS dp_rx_mon_soc_htt_srng_setup_2_0(struct dp_soc *soc,
2894 int mac_id)
2895 {
2896 hal_set_low_threshold(soc->rxdma_mon_buf_ring[0].hal_srng,
2897 MON_BUF_MIN_ENTRIES << 2);
2898 return htt_srng_setup(soc->htt_handle, 0,
2899 soc->rxdma_mon_buf_ring[0].hal_srng,
2900 RXDMA_MONITOR_BUF);
2901 }
2902
dp_rx_mon_pdev_rings_alloc_2_0(struct dp_pdev * pdev,int lmac_id)2903 QDF_STATUS dp_rx_mon_pdev_rings_alloc_2_0(struct dp_pdev *pdev, int lmac_id)
2904 {
2905 struct dp_soc *soc = pdev->soc;
2906 int entries;
2907 struct wlan_cfg_dp_pdev_ctxt *pdev_cfg_ctx;
2908
2909 pdev_cfg_ctx = pdev->wlan_cfg_ctx;
2910 entries = wlan_cfg_get_dma_rx_mon_dest_ring_size(pdev_cfg_ctx);
2911
2912 return dp_srng_alloc(soc, &soc->rxdma_mon_dst_ring[lmac_id],
2913 RXDMA_MONITOR_DST, entries, 0);
2914 }
2915
dp_rx_mon_pdev_rings_free_2_0(struct dp_pdev * pdev,int lmac_id)2916 void dp_rx_mon_pdev_rings_free_2_0(struct dp_pdev *pdev, int lmac_id)
2917 {
2918 struct dp_soc *soc = pdev->soc;
2919
2920 dp_srng_free(soc, &soc->rxdma_mon_dst_ring[lmac_id]);
2921 }
2922
dp_rx_mon_pdev_rings_init_2_0(struct dp_pdev * pdev,int lmac_id)2923 QDF_STATUS dp_rx_mon_pdev_rings_init_2_0(struct dp_pdev *pdev, int lmac_id)
2924 {
2925 struct dp_soc *soc = pdev->soc;
2926
2927 return dp_srng_init(soc, &soc->rxdma_mon_dst_ring[lmac_id],
2928 RXDMA_MONITOR_DST, pdev->pdev_id, lmac_id);
2929 }
2930
dp_rx_mon_pdev_rings_deinit_2_0(struct dp_pdev * pdev,int lmac_id)2931 void dp_rx_mon_pdev_rings_deinit_2_0(struct dp_pdev *pdev, int lmac_id)
2932 {
2933 struct dp_soc *soc = pdev->soc;
2934
2935 dp_srng_deinit(soc, &soc->rxdma_mon_dst_ring[lmac_id],
2936 RXDMA_MONITOR_DST, pdev->pdev_id);
2937 }
2938
dp_rx_mon_soc_attach_2_0(struct dp_soc * soc,int lmac_id)2939 QDF_STATUS dp_rx_mon_soc_attach_2_0(struct dp_soc *soc, int lmac_id)
2940 {
2941 int entries;
2942 struct wlan_cfg_dp_soc_ctxt *soc_cfg_ctx = soc->wlan_cfg_ctx;
2943
2944 entries = wlan_cfg_get_dp_soc_rx_mon_buf_ring_size(soc_cfg_ctx);
2945 qdf_print("%s:%d rx mon buf entries: %d", __func__, __LINE__, entries);
2946
2947 return dp_srng_alloc(soc, &soc->rxdma_mon_buf_ring[lmac_id],
2948 RXDMA_MONITOR_BUF, entries, 0);
2949 }
2950
2951 #endif /* WLAN_PKT_CAPTURE_RX_2_0 */
2952