diff --git a/dp/inc/cdp_txrx_mon_struct.h b/dp/inc/cdp_txrx_mon_struct.h index f502f79052..ad2112cc5c 100644 --- a/dp/inc/cdp_txrx_mon_struct.h +++ b/dp/inc/cdp_txrx_mon_struct.h @@ -380,6 +380,7 @@ enum cdp_mon_phyrx_abort_reason_code { * @mon_rx_desc_invalid: rx_desc invalid count * @mpdu_ppdu_id_mismatch_drop: mpdu's ppdu id did not match destination * ring ppdu id + * @mpdu_decap_type_invalid: mpdu decap type invalid count * @rx_undecoded_count: Received undecoded frame count * @rx_undecoded_error: Rx undecoded errors * @rx_hdr_not_received: Rx HDR not received for MPDU @@ -425,6 +426,7 @@ struct cdp_pdev_mon_stats { uint32_t mon_rx_desc_invalid; uint32_t mon_nbuf_sanity_err; uint32_t mpdu_ppdu_id_mismatch_drop; + uint32_t mpdu_decap_type_invalid; #ifdef QCA_UNDECODED_METADATA_SUPPORT uint32_t rx_undecoded_count; uint32_t rx_undecoded_error[CDP_PHYRX_ERR_MAX]; diff --git a/dp/wifi3.0/monitor/2.0/dp_mon_2.0.h b/dp/wifi3.0/monitor/2.0/dp_mon_2.0.h index 7f1e214e75..81f685a9a7 100644 --- a/dp/wifi3.0/monitor/2.0/dp_mon_2.0.h +++ b/dp/wifi3.0/monitor/2.0/dp_mon_2.0.h @@ -37,6 +37,9 @@ #define DP_MON_MSDU_LOGGING 0 #define DP_MON_MPDU_LOGGING 1 +#define DP_MON_DECAP_FORMAT_INVALID 0xff +#define DP_MON_MIN_FRAGS_FOR_RESTITCH 2 + /* monitor frame filter modes */ enum dp_mon_frm_filter_mode { /* mode filter pass */ diff --git a/dp/wifi3.0/monitor/2.0/dp_rx_mon_2.0.c b/dp/wifi3.0/monitor/2.0/dp_rx_mon_2.0.c index 74836714bb..82f79da270 100644 --- a/dp/wifi3.0/monitor/2.0/dp_rx_mon_2.0.c +++ b/dp/wifi3.0/monitor/2.0/dp_rx_mon_2.0.c @@ -391,7 +391,7 @@ dp_rx_mon_process_ppdu_info(struct dp_pdev *pdev, status = dp_lite_mon_rx_mpdu_process(pdev, ppdu_info, mpdu, mpdu_idx, user); if (status != QDF_STATUS_SUCCESS) { - qdf_nbuf_free(mpdu); + dp_mon_free_parent_nbuf(mon_pdev, mpdu); continue; } } else { @@ -401,8 +401,12 @@ dp_rx_mon_process_ppdu_info(struct dp_pdev *pdev, continue; } - dp_rx_mon_handle_full_mon(pdev, - ppdu_info, mpdu); + status = dp_rx_mon_handle_full_mon(pdev, + ppdu_info, mpdu); + if (status != QDF_STATUS_SUCCESS) { + dp_mon_free_parent_nbuf(mon_pdev, mpdu); + continue; + } } else { dp_mon_free_parent_nbuf(mon_pdev, mpdu); continue; @@ -519,7 +523,7 @@ dp_rx_mon_add_ppdu_info_to_wq(struct dp_pdev *pdev, return QDF_STATUS_SUCCESS; } -void +QDF_STATUS dp_rx_mon_handle_full_mon(struct dp_pdev *pdev, struct hal_rx_ppdu_info *ppdu_info, qdf_nbuf_t mpdu) @@ -557,7 +561,13 @@ dp_rx_mon_handle_full_mon(struct dp_pdev *pdev, qdf_nbuf_trim_add_frag_size(mpdu, qdf_nbuf_get_nr_frags(mpdu) - 1, -HAL_RX_FCS_LEN, 0); - return; + return QDF_STATUS_SUCCESS; + } + + num_frags = qdf_nbuf_get_nr_frags(mpdu); + if (qdf_unlikely(num_frags < DP_MON_MIN_FRAGS_FOR_RESTITCH)) { + dp_mon_debug("not enough frags(%d) for restitch", num_frags); + return QDF_STATUS_E_FAILURE; } l2_hdr_offset = DP_RX_MON_NONRAW_L2_HDR_PAD_BYTE; @@ -824,6 +834,8 @@ dp_rx_mon_handle_full_mon(struct dp_pdev *pdev, msdu_cur = qdf_nbuf_queue_next(msdu_cur); } } + + return QDF_STATUS_SUCCESS; } /** @@ -978,6 +990,10 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev, } ppdu_info->mpdu_info[ppdu_info->user_id].mpdu_start_received = true; ppdu_info->mpdu_info[user_id].first_rx_hdr_rcvd = true; + /* initialize decap type to invalid, this will be set to appropriate + * value once the mpdu start tlv is received + */ + ppdu_info->mpdu_info[user_id].decap_type = DP_MON_DECAP_FORMAT_INVALID; } else { if (ppdu_info->mpdu_info[user_id].decap_type == HAL_HW_RX_DECAP_FORMAT_RAW) { @@ -1056,6 +1072,18 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev, return num_buf_reaped; } + if (mpdu_info->decap_type == DP_MON_DECAP_FORMAT_INVALID) { + /* decap type is invalid, drop the frame */ + mon_pdev->rx_mon_stats.mpdu_decap_type_invalid++; + DP_STATS_INC(mon_soc, frag_free, 1); + mon_pdev->rx_mon_stats.parent_buf_free++; + qdf_frag_free(addr); + qdf_nbuf_free(nbuf); + /* we have freed the nbuf mark the q entry null */ + ppdu_info->mpdu_q[user_id][mpdu_idx] = NULL; + return num_buf_reaped; + } + tmp_nbuf = qdf_get_nbuf_valid_frag(nbuf); if (!tmp_nbuf) { @@ -1132,6 +1160,8 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev, /* update msdu metadata at last buffer of msdu in MPDU */ nbuf = ppdu_info->mpdu_q[user_id][mpdu_idx]; if (!nbuf) { + /* reset msdu info for next msdu for same user */ + qdf_mem_zero(msdu_info, sizeof(*msdu_info)); dp_mon_err(" <%d> nbuf is NULL, return user: %d mpdu_idx: %d", __LINE__, user_id, mpdu_idx); break; } @@ -1157,7 +1187,7 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev, dp_rx_mon_pf_tag_to_buf_headroom_2_0(nbuf, ppdu_info, pdev, soc); /* reset msdu info for next msdu for same user */ - qdf_mem_zero(msdu_info, sizeof(msdu_info)); + qdf_mem_zero(msdu_info, sizeof(*msdu_info)); /* If flow classification is enabled, * update cce_metadata and fse_metadata @@ -1185,6 +1215,8 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev, mpdu_info = &ppdu_info->mpdu_info[user_id]; nbuf = ppdu_info->mpdu_q[user_id][mpdu_idx]; if (!nbuf) { + /* reset mpdu info for next mpdu for same user */ + qdf_mem_zero(mpdu_info, sizeof(*mpdu_info)); dp_mon_err(" <%d> nbuf is NULL, return user: %d mpdu_idx: %d", __LINE__, user_id, mpdu_idx); break; } @@ -1197,10 +1229,9 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev, mpdu_meta->full_pkt = mpdu_info->full_pkt; mpdu_meta->truncated = mpdu_info->truncated; - num_frags = qdf_nbuf_get_nr_frags(nbuf); ppdu_info->mpdu_q[user_id][mpdu_idx] = nbuf; - /* reset msdu info for next msdu for same user */ - qdf_mem_zero(mpdu_info, sizeof(mpdu_info)); + /* reset mpdu info for next mpdu for same user */ + qdf_mem_zero(mpdu_info, sizeof(*mpdu_info)); ppdu_info->mpdu_info[ppdu_info->user_id].mpdu_start_received = false; ppdu_info->mpdu_count[user_id]++; } diff --git a/dp/wifi3.0/monitor/2.0/dp_rx_mon_2.0.h b/dp/wifi3.0/monitor/2.0/dp_rx_mon_2.0.h index 9db8eb6c86..921027b7cb 100644 --- a/dp/wifi3.0/monitor/2.0/dp_rx_mon_2.0.h +++ b/dp/wifi3.0/monitor/2.0/dp_rx_mon_2.0.h @@ -171,8 +171,10 @@ static inline void dp_rx_mon_process_ppdu(void *context) * @pdev: DP pdev * @ppdu_info: PPDU info * @mpdu: mpdu buf + * + * Return: SUCCESS or Failure */ -void +QDF_STATUS dp_rx_mon_handle_full_mon(struct dp_pdev *pdev, struct hal_rx_ppdu_info *ppdu_info, qdf_nbuf_t mpdu); diff --git a/dp/wifi3.0/monitor/dp_mon.c b/dp/wifi3.0/monitor/dp_mon.c index 3ec57f466e..23a3946c3c 100644 --- a/dp/wifi3.0/monitor/dp_mon.c +++ b/dp/wifi3.0/monitor/dp_mon.c @@ -872,6 +872,8 @@ dp_print_pdev_rx_mon_stats(struct dp_pdev *pdev) rx_mon_stats->dest_ppdu_drop); DP_PRINT_STATS("mpdu_ppdu_id_mismatch_drop = %u", rx_mon_stats->mpdu_ppdu_id_mismatch_drop); + DP_PRINT_STATS("mpdu_decap_type_invalid = %u", + rx_mon_stats->mpdu_decap_type_invalid); stat_ring_ppdu_ids = (uint32_t *)qdf_mem_malloc(sizeof(uint32_t) * MAX_PPDU_ID_HIST); dest_ring_ppdu_ids =