diff --git a/dp/inc/cdp_txrx_mon_struct.h b/dp/inc/cdp_txrx_mon_struct.h index 3a7cb1803c..ad2112cc5c 100644 --- a/dp/inc/cdp_txrx_mon_struct.h +++ b/dp/inc/cdp_txrx_mon_struct.h @@ -390,6 +390,10 @@ enum cdp_mon_phyrx_abort_reason_code { * @mpdus_to_stack: Number of MPDUs delivered to stack * @status_buf_count: Number of status buffer received * @empty_desc_ppdu: Number of empty desc received + * @total_ppdu_info_enq: Number of PPDUs enqueued to wq + * @total_ppdu_info_drop: Number of PPDUs dropped + * @total_ppdu_info_alloc: Number of PPDU info allocated + * @total_ppdu_info_free: Number of PPDU info freeed */ struct cdp_pdev_mon_stats { #ifndef REMOVE_MON_DBG_STATS @@ -434,6 +438,10 @@ struct cdp_pdev_mon_stats { uint32_t mpdus_buf_to_stack; uint32_t status_buf_count; uint32_t empty_desc_ppdu; + uint32_t total_ppdu_info_enq; + uint32_t total_ppdu_info_drop; + uint32_t total_ppdu_info_alloc; + uint32_t total_ppdu_info_free; }; #ifdef QCA_SUPPORT_LITE_MONITOR diff --git a/dp/wifi3.0/monitor/1.0/dp_mon_1.0.c b/dp/wifi3.0/monitor/1.0/dp_mon_1.0.c index ecd656c5db..31aa727ee1 100644 --- a/dp/wifi3.0/monitor/1.0/dp_mon_1.0.c +++ b/dp/wifi3.0/monitor/1.0/dp_mon_1.0.c @@ -1220,6 +1220,7 @@ dp_mon_register_feature_ops_1_0(struct dp_soc *soc) mon_ops->mon_filter_reset_undecoded_metadata_capture = dp_mon_filter_reset_undecoded_metadata_capture_1_0; #endif + mon_ops->mon_rx_print_advanced_stats = NULL; } struct dp_mon_ops monitor_ops_1_0 = { diff --git a/dp/wifi3.0/monitor/2.0/dp_mon_2.0.c b/dp/wifi3.0/monitor/2.0/dp_mon_2.0.c index 7e2ba91766..0bcfe3e413 100644 --- a/dp/wifi3.0/monitor/2.0/dp_mon_2.0.c +++ b/dp/wifi3.0/monitor/2.0/dp_mon_2.0.c @@ -35,6 +35,65 @@ #if !defined(DISABLE_MON_CONFIG) +QDF_STATUS dp_rx_mon_ppdu_info_cache_create(struct dp_pdev *pdev) +{ + struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; + struct dp_mon_pdev_be *mon_pdev_be = + dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev); + uint16_t obj; + struct hal_rx_ppdu_info *ppdu_info = NULL; + + mon_pdev_be->ppdu_info_cache = + qdf_kmem_cache_create("rx_mon_ppdu_info_cache", + sizeof(struct hal_rx_ppdu_info)); + + if (!mon_pdev_be->ppdu_info_cache) { + dp_mon_err("cache creation failed pdev :%px", pdev); + return QDF_STATUS_E_NOMEM; + } + + TAILQ_INIT(&mon_pdev_be->rx_mon_free_queue); + for (obj = 0; obj < DP_RX_MON_WQ_THRESHOLD; obj++) { + ppdu_info = (struct hal_rx_ppdu_info *)qdf_kmem_cache_alloc(mon_pdev_be->ppdu_info_cache); + + if (ppdu_info) { + TAILQ_INSERT_TAIL(&mon_pdev_be->rx_mon_free_queue, + ppdu_info, + ppdu_free_list_elem); + mon_pdev_be->total_free_elem++; + } + } + qdf_spinlock_create(&mon_pdev_be->ppdu_info_lock); + + return QDF_STATUS_SUCCESS; +} + +void dp_rx_mon_ppdu_info_cache_destroy(struct dp_pdev *pdev) +{ + struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; + struct dp_mon_pdev_be *mon_pdev_be = + dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev); + struct hal_rx_ppdu_info *ppdu_info = NULL, *temp_ppdu_info = NULL; + + qdf_err(" total free element: %d", mon_pdev_be->total_free_elem); + qdf_spin_lock(&mon_pdev_be->ppdu_info_lock); + TAILQ_FOREACH_SAFE(ppdu_info, + &mon_pdev_be->rx_mon_free_queue, + ppdu_free_list_elem, + temp_ppdu_info) { + TAILQ_REMOVE(&mon_pdev_be->rx_mon_free_queue, + ppdu_info, ppdu_free_list_elem); + if (ppdu_info) { + mon_pdev_be->total_free_elem--; + qdf_err(" total free element: %d", mon_pdev_be->total_free_elem); + qdf_kmem_cache_free(mon_pdev_be->ppdu_info_cache, + ppdu_info); + } + } + qdf_spin_unlock(&mon_pdev_be->ppdu_info_lock); + qdf_kmem_cache_destroy(mon_pdev_be->ppdu_info_cache); +} + /** * dp_mon_pdev_ext_init_2_0() - Init pdev ext param * @@ -61,6 +120,7 @@ QDF_STATUS dp_mon_pdev_ext_init_2_0(struct dp_pdev *pdev) TAILQ_INIT(&mon_pdev_be->rx_mon_queue); qdf_spinlock_create(&mon_pdev_be->rx_mon_wq_lock); + qdf_err(" total free element: %d", mon_pdev_be->total_free_elem); return QDF_STATUS_SUCCESS; @@ -84,11 +144,12 @@ QDF_STATUS dp_mon_pdev_ext_deinit_2_0(struct dp_pdev *pdev) if (!mon_pdev_be->rx_mon_workqueue) return QDF_STATUS_E_FAILURE; - dp_rx_mon_drain_wq(pdev); + qdf_err(" total free element: %d", mon_pdev_be->total_free_elem); qdf_flush_workqueue(0, mon_pdev_be->rx_mon_workqueue); qdf_destroy_workqueue(0, mon_pdev_be->rx_mon_workqueue); qdf_flush_work(&mon_pdev_be->rx_mon_work); qdf_disable_work(&mon_pdev_be->rx_mon_work); + dp_rx_mon_drain_wq(pdev); mon_pdev_be->rx_mon_workqueue = NULL; qdf_spinlock_destroy(&mon_pdev_be->rx_mon_wq_lock); @@ -1389,6 +1450,8 @@ dp_mon_register_feature_ops_2_0(struct dp_soc *soc) dp_mon_filter_reset_undecoded_metadata_capture_2_0; #endif mon_ops->rx_enable_fpmo = dp_rx_mon_enable_fpmo; + mon_ops->mon_rx_print_advanced_stats = + dp_mon_rx_print_advanced_stats_2_0; } struct dp_mon_ops monitor_ops_2_0 = { @@ -1477,6 +1540,8 @@ struct dp_mon_ops monitor_ops_2_0 = { .mon_lite_mon_dealloc = dp_lite_mon_dealloc, .mon_lite_mon_vdev_delete = dp_lite_mon_vdev_delete, .mon_lite_mon_disable_rx = dp_lite_mon_disable_rx, + .mon_rx_ppdu_info_cache_create = dp_rx_mon_ppdu_info_cache_create, + .mon_rx_ppdu_info_cache_destroy = dp_rx_mon_ppdu_info_cache_destroy, }; struct cdp_mon_ops dp_ops_mon_2_0 = { 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 592bef2aac..4746e58488 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 @@ -142,9 +142,17 @@ struct dp_mon_desc_pool { * @rx_mon_workqueue: Rx mon workqueue * @rx_mon_work: Rx mon work * @rx_mon_queue: RxMON queue + * @rx_mon_free_queue: RxMON ppdu info free element queue + * @ppdu_info_lock: RxPPDU ppdu info queue lock * @rx_mon_queue_depth: RxMON queue depth * @desc_count: reaped status desc count * @status: reaped status buffer per ppdu + * @lite_mon_rx_config: rx litemon config + * @lite_mon_tx_config: tx litemon config + * @prev_rxmon_desc: prev destination desc + * @prev_rxmon_cookie: prev rxmon cookie + * @ppdu_info_cache: PPDU info cache + * @total_free_elem: total free element in queue */ struct dp_mon_pdev_be { struct dp_mon_pdev mon_pdev; @@ -158,6 +166,8 @@ struct dp_mon_pdev_be { qdf_work_t rx_mon_work; TAILQ_HEAD(, hal_rx_ppdu_info) rx_mon_queue; + TAILQ_HEAD(, hal_rx_ppdu_info) rx_mon_free_queue; + qdf_spinlock_t ppdu_info_lock; uint16_t rx_mon_queue_depth; uint16_t desc_count; struct dp_mon_desc *status[DP_MON_MAX_STATUS_BUF]; @@ -167,6 +177,8 @@ struct dp_mon_pdev_be { #endif void *prev_rxmon_desc; uint32_t prev_rxmon_cookie; + qdf_kmem_cache_t ppdu_info_cache; + uint32_t total_free_elem; }; /** 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 a525f5bbb8..4bdbf81da9 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 @@ -87,6 +87,54 @@ void dp_rx_mon_set_zero(qdf_nbuf_t nbuf) qdf_mem_zero(qdf_nbuf_head(nbuf), DP_RX_MON_TLV_ROOM); } +/** + * dp_rx_mon_get_ppdu_info() - Get PPDU info from freelist + * + * @mon_pdev: monitor pdev + * + * Return: ppdu_info + */ +static inline struct hal_rx_ppdu_info* +dp_rx_mon_get_ppdu_info(struct dp_mon_pdev *mon_pdev) +{ + struct dp_mon_pdev_be *mon_pdev_be = + dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev); + struct hal_rx_ppdu_info *ppdu_info, *temp_ppdu_info; + + qdf_spin_lock_bh(&mon_pdev_be->ppdu_info_lock); + TAILQ_FOREACH_SAFE(ppdu_info, + &mon_pdev_be->rx_mon_free_queue, + ppdu_list_elem, + temp_ppdu_info) { + TAILQ_REMOVE(&mon_pdev_be->rx_mon_free_queue, + ppdu_info, ppdu_free_list_elem); + + if (ppdu_info) { + mon_pdev_be->total_free_elem--; + break; + } + } + qdf_spin_unlock_bh(&mon_pdev_be->ppdu_info_lock); + + return ppdu_info; +} + +static inline void +__dp_rx_mon_free_ppdu_info(struct dp_mon_pdev *mon_pdev, + struct hal_rx_ppdu_info *ppdu_info) +{ + struct dp_mon_pdev_be *mon_pdev_be = + dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev); + + qdf_spin_lock_bh(&mon_pdev_be->ppdu_info_lock); + if (ppdu_info) { + TAILQ_INSERT_TAIL(&mon_pdev_be->rx_mon_free_queue, ppdu_info, + ppdu_free_list_elem); + mon_pdev_be->total_free_elem++; + } + qdf_spin_unlock_bh(&mon_pdev_be->ppdu_info_lock); +} + /** * dp_rx_mon_nbuf_add_rx_frag () - Add frag to SKB * @@ -337,13 +385,14 @@ dp_rx_mon_free_ppdu_info(struct dp_pdev *pdev, qdf_nbuf_t mpdu; for (mpdu_idx = 0; mpdu_idx < mpdu_count; mpdu_idx++) { - mpdu = (qdf_nbuf_t)ppdu_info->mpdu_q[user][mpdu_idx]; + mpdu = qdf_nbuf_queue_remove(&ppdu_info->mpdu_q[user]); if (!mpdu) continue; dp_mon_free_parent_nbuf(mon_pdev, mpdu); } } + __dp_rx_mon_free_ppdu_info(mon_pdev, ppdu_info); } void dp_rx_mon_drain_wq(struct dp_pdev *pdev) @@ -375,7 +424,7 @@ void dp_rx_mon_drain_wq(struct dp_pdev *pdev) TAILQ_REMOVE(&mon_pdev_be->rx_mon_queue, ppdu_info, ppdu_list_elem); - dp_rx_mon_free_ppdu_info(pdev, ppdu_info); + __dp_rx_mon_free_ppdu_info(mon_pdev, ppdu_info); } qdf_spin_unlock_bh(&mon_pdev_be->rx_mon_wq_lock); } @@ -439,7 +488,7 @@ dp_rx_mon_process_ppdu_info(struct dp_pdev *pdev, QDF_STATUS status; for (mpdu_idx = 0; mpdu_idx < mpdu_count; mpdu_idx++) { - mpdu = (qdf_nbuf_t)ppdu_info->mpdu_q[user][mpdu_idx]; + mpdu = qdf_nbuf_queue_remove(&ppdu_info->mpdu_q[user]); if (!mpdu) continue; @@ -535,7 +584,7 @@ void dp_rx_mon_process_ppdu(void *context) mon_pdev_be->rx_mon_queue_depth--; dp_rx_mon_process_ppdu_info(pdev, ppdu_info); - qdf_mem_free(ppdu_info); + __dp_rx_mon_free_ppdu_info(mon_pdev, ppdu_info); } qdf_spin_unlock_bh(&mon_pdev_be->rx_mon_wq_lock); } @@ -549,10 +598,11 @@ void dp_rx_mon_process_ppdu(void *context) * Return: SUCCESS or FAILIRE */ -QDF_STATUS -dp_rx_mon_add_ppdu_info_to_wq(struct dp_mon_pdev *mon_pdev, +static QDF_STATUS +dp_rx_mon_add_ppdu_info_to_wq(struct dp_pdev *pdev, struct hal_rx_ppdu_info *ppdu_info) { + struct dp_mon_pdev *mon_pdev = (struct dp_mon_pdev *)pdev->monitor_pdev; struct dp_mon_pdev_be *mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev); @@ -562,10 +612,16 @@ dp_rx_mon_add_ppdu_info_to_wq(struct dp_mon_pdev *mon_pdev, return QDF_STATUS_E_FAILURE; if (qdf_likely(ppdu_info)) { - qdf_spin_lock_bh(&mon_pdev_be->rx_mon_wq_lock); - TAILQ_INSERT_TAIL(&mon_pdev_be->rx_mon_queue, - ppdu_info, ppdu_list_elem); - mon_pdev_be->rx_mon_queue_depth++; + if (mon_pdev_be->rx_mon_queue_depth < DP_RX_MON_WQ_THRESHOLD) { + qdf_spin_lock_bh(&mon_pdev_be->rx_mon_wq_lock); + TAILQ_INSERT_TAIL(&mon_pdev_be->rx_mon_queue, + ppdu_info, ppdu_list_elem); + mon_pdev_be->rx_mon_queue_depth++; + mon_pdev->rx_mon_stats.total_ppdu_info_enq++; + } else { + mon_pdev->rx_mon_stats.total_ppdu_info_drop++; + dp_rx_mon_free_ppdu_info(pdev, ppdu_info); + } qdf_spin_unlock_bh(&mon_pdev_be->rx_mon_wq_lock); if (mon_pdev_be->rx_mon_queue_depth > DP_MON_QUEUE_DEPTH_MAX) { @@ -1041,7 +1097,7 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev, qdf_nbuf_set_next(nbuf, NULL); - ppdu_info->mpdu_q[user_id][mpdu_idx] = nbuf; + qdf_nbuf_queue_add(&ppdu_info->mpdu_q[user_id], nbuf); status = dp_rx_mon_nbuf_add_rx_frag(nbuf, status_frag, ppdu_info->hdr_len - DP_RX_MON_RX_HDR_OFFSET, @@ -1067,7 +1123,7 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev, !dp_lite_mon_is_level_msdu(mon_pdev)) break; - nbuf = ppdu_info->mpdu_q[user_id][mpdu_idx]; + nbuf = qdf_nbuf_queue_last(&ppdu_info->mpdu_q[user_id]); if (qdf_unlikely(!nbuf)) { dp_mon_debug("nbuf is NULL"); return num_buf_reaped; @@ -1095,6 +1151,7 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev, DP_MON_DATA_BUFFER_SIZE, true); } + ppdu_info->rx_hdr_rcvd[user_id] = true; } break; case HAL_TLV_STATUS_MON_BUF_ADDR: @@ -1125,9 +1182,8 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev, num_buf_reaped++; mon_pdev->rx_mon_stats.pkt_buf_count++; - nbuf = ppdu_info->mpdu_q[user_id][mpdu_idx]; - if (qdf_unlikely(!nbuf)) { + if (qdf_unlikely(!ppdu_info->rx_hdr_rcvd[user_id])) { /* WAR: RX_HDR is not received for this MPDU, drop this frame */ mon_pdev->rx_mon_stats.rx_hdr_not_received++; @@ -1136,15 +1192,17 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev, return num_buf_reaped; } + nbuf = qdf_nbuf_queue_last(&ppdu_info->mpdu_q[user_id]); + 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_queue_remove_last(&ppdu_info->mpdu_q[user_id]); 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; } @@ -1160,8 +1218,9 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev, DP_STATS_INC(mon_soc, frag_free, 1); mon_pdev->rx_mon_stats.parent_buf_free++; qdf_frag_free(addr); + /* remove this nbuf from queue */ + qdf_nbuf_queue_remove_last(&ppdu_info->mpdu_q[user_id]); qdf_nbuf_free(nbuf); - ppdu_info->mpdu_q[user_id][mpdu_idx] = NULL; return num_buf_reaped; } mon_pdev->rx_mon_stats.parent_buf_alloc++; @@ -1222,14 +1281,14 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev, struct hal_rx_mon_msdu_info *msdu_info = &ppdu_info->msdu[user_id]; struct hal_rx_mon_msdu_info *last_buf_info; /* update msdu metadata at last buffer of msdu in MPDU */ - nbuf = ppdu_info->mpdu_q[user_id][mpdu_idx]; - if (!nbuf) { + if (qdf_unlikely(!ppdu_info->rx_hdr_rcvd[user_id])) { /* reset msdu info for next msdu for same user */ qdf_mem_zero(msdu_info, sizeof(*msdu_info)); dp_mon_debug(" <%d> nbuf is NULL, return user: %d mpdu_idx: %d", __LINE__, user_id, mpdu_idx); break; } + nbuf = qdf_nbuf_queue_last(&ppdu_info->mpdu_q[user_id]); num_frags = qdf_nbuf_get_nr_frags(nbuf); if (ppdu_info->mpdu_info[user_id].decap_type == HAL_HW_RX_DECAP_FORMAT_RAW) { @@ -1263,12 +1322,11 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev, { struct hal_rx_mon_mpdu_info *mpdu_info, *mpdu_meta; - nbuf = ppdu_info->mpdu_q[user_id][mpdu_idx]; - if (!nbuf) { - dp_mon_debug(" <%d> nbuf is NULL, return user: %d mpdu_idx: %d", - __LINE__, user_id, mpdu_idx); + if (qdf_unlikely(!ppdu_info->rx_hdr_rcvd[user_id])) { + dp_mon_debug(" <%d> nbuf is NULL, return user: %d mpdu_idx: %d", __LINE__, user_id, mpdu_idx); break; } + nbuf = qdf_nbuf_queue_last(&ppdu_info->mpdu_q[user_id]); mpdu_meta = (struct hal_rx_mon_mpdu_info *)qdf_nbuf_data(nbuf); mpdu_info = &ppdu_info->mpdu_info[user_id]; mpdu_meta->decap_type = mpdu_info->decap_type; @@ -1279,14 +1337,14 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev, { struct hal_rx_mon_mpdu_info *mpdu_info, *mpdu_meta; mpdu_info = &ppdu_info->mpdu_info[user_id]; - nbuf = ppdu_info->mpdu_q[user_id][mpdu_idx]; - if (!nbuf) { + if (qdf_unlikely(!ppdu_info->rx_hdr_rcvd[user_id])) { /* reset mpdu info for next mpdu for same user */ qdf_mem_zero(mpdu_info, sizeof(*mpdu_info)); dp_mon_debug(" <%d> nbuf is NULL, return user: %d mpdu_idx: %d", __LINE__, user_id, mpdu_idx); break; } + nbuf = qdf_nbuf_queue_last(&ppdu_info->mpdu_q[user_id]); mpdu_meta = (struct hal_rx_mon_mpdu_info *)qdf_nbuf_data(nbuf); mpdu_meta->mpdu_length_err = mpdu_info->mpdu_length_err; mpdu_meta->fcs_err = mpdu_info->fcs_err; @@ -1296,11 +1354,11 @@ 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; - ppdu_info->mpdu_q[user_id][mpdu_idx] = nbuf; /* 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]++; + ppdu_info->rx_hdr_rcvd[user_id] = false; } break; } @@ -1324,7 +1382,7 @@ dp_rx_mon_process_status_tlv(struct dp_pdev *pdev) union dp_mon_desc_list_elem_t *desc_list = NULL; union dp_mon_desc_list_elem_t *tail = NULL; struct dp_mon_desc *mon_desc; - uint8_t idx; + uint8_t idx, user; void *buf; struct hal_rx_ppdu_info *ppdu_info; uint8_t *rx_tlv; @@ -1342,12 +1400,17 @@ dp_rx_mon_process_status_tlv(struct dp_pdev *pdev) return NULL; } - ppdu_info = &mon_pdev->ppdu_info; + ppdu_info = dp_rx_mon_get_ppdu_info(mon_pdev); if (!ppdu_info) { dp_mon_err("ppdu_info malloc failed pdev: %pK", pdev); + dp_rx_mon_flush_status_buf_queue(pdev); return NULL; } + mon_pdev->rx_mon_stats.total_ppdu_info_alloc++; + + for (user = 0; user < HAL_MAX_UL_MU_USERS; user++) + qdf_nbuf_queue_init(&ppdu_info->mpdu_q[user]); status_buf_count = mon_pdev_be->desc_count; for (idx = 0; idx < status_buf_count; idx++) { @@ -1592,7 +1655,11 @@ dp_rx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx, else if (dp_cfr_rcc_mode_status(pdev) && ppdu_info) dp_rx_handle_cfr(soc, pdev, ppdu_info); - dp_rx_mon_process_ppdu_info(pdev, ppdu_info); + status = dp_rx_mon_add_ppdu_info_to_wq(pdev, ppdu_info); + if (status != QDF_STATUS_SUCCESS) { + if (ppdu_info) + __dp_rx_mon_free_ppdu_info(mon_pdev, ppdu_info); + } work_done++; @@ -1810,4 +1877,48 @@ dp_rx_mon_populate_ppdu_info_2_0(struct hal_rx_ppdu_info *hal_ppdu_info, ppdu->punc_bw = NO_PUNCTURE; } #endif +void dp_mon_rx_print_advanced_stats_2_0(struct dp_soc *soc, + struct dp_pdev *pdev) +{ + struct cdp_pdev_mon_stats *rx_mon_stats; + struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; + struct dp_mon_soc *mon_soc = pdev->soc->monitor_soc; + struct dp_mon_pdev_be *mon_pdev_be = + dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev); + + rx_mon_stats = &mon_pdev->rx_mon_stats; + + DP_PRINT_STATS("total_ppdu_info_alloc = %d", + rx_mon_stats->total_ppdu_info_alloc); + DP_PRINT_STATS("total_ppdu_info_free = %d", + rx_mon_stats->total_ppdu_info_free); + DP_PRINT_STATS("total_ppdu_info_enq = %d", + rx_mon_stats->total_ppdu_info_enq); + DP_PRINT_STATS("total_ppdu_info_drop = %d", + rx_mon_stats->total_ppdu_info_drop); + DP_PRINT_STATS("rx_hdr_not_received = %d", + rx_mon_stats->rx_hdr_not_received); + DP_PRINT_STATS("parent_buf_alloc = %d", + rx_mon_stats->parent_buf_alloc); + DP_PRINT_STATS("parent_buf_free = %d", + rx_mon_stats->parent_buf_free); + DP_PRINT_STATS("mpdus_buf_to_stack = %d", + rx_mon_stats->mpdus_buf_to_stack); + DP_PRINT_STATS("frag_alloc = %d", + mon_soc->stats.frag_alloc); + DP_PRINT_STATS("frag_free = %d", + mon_soc->stats.frag_free); + DP_PRINT_STATS("status_buf_count = %d", + rx_mon_stats->status_buf_count); + DP_PRINT_STATS("pkt_buf_count = %d", + rx_mon_stats->pkt_buf_count); + DP_PRINT_STATS("rx_mon_queue_depth= %d", + mon_pdev_be->rx_mon_queue_depth); + DP_PRINT_STATS("empty_desc= %d", + mon_pdev->rx_mon_stats.empty_desc_ppdu); + DP_PRINT_STATS("mpdu_dropped_due_invalid_decap= %d", + mon_pdev->rx_mon_stats.mpdu_decap_type_invalid); + DP_PRINT_STATS("total_free_elem= %d", + mon_pdev_be->total_free_elem); +} #endif 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 6e3795a061..f7367863ba 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 @@ -49,6 +49,7 @@ + (DP_RX_MON_TLV_HDR_MARKER_LEN)\ + (DP_RX_MON_TLV_TOTAL_LEN)) +#define DP_RX_MON_WQ_THRESHOLD 128 /* * dp_rx_mon_buffers_alloc() - allocate rx monitor buffers * @soc: DP soc handle @@ -232,4 +233,14 @@ void dp_rx_mon_shift_pf_tag_in_headroom(qdf_nbuf_t nbuf, struct dp_soc *soc) { } #endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */ +/** + * dp_mon_rx_print_advanced_stats_2_0 () - print advanced monitor statistics + * + * @soc: DP soc handle + * @pdev: DP pdev handle + * + * Return: void + */ +void dp_mon_rx_print_advanced_stats_2_0(struct dp_soc *soc, + struct dp_pdev *pdev); #endif /* _DP_RX_MON_2_0_H_ */ diff --git a/dp/wifi3.0/monitor/dp_mon.c b/dp/wifi3.0/monitor/dp_mon.c index c27c907b73..045df03ed4 100644 --- a/dp/wifi3.0/monitor/dp_mon.c +++ b/dp/wifi3.0/monitor/dp_mon.c @@ -827,7 +827,6 @@ dp_print_pdev_rx_mon_stats(struct dp_pdev *pdev) uint32_t *dest_ring_ppdu_ids; int i, idx; struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; - struct dp_mon_soc *mon_soc = pdev->soc->monitor_soc; rx_mon_stats = &mon_pdev->rx_mon_stats; @@ -906,23 +905,8 @@ dp_print_pdev_rx_mon_stats(struct dp_pdev *pdev) DP_PRINT_STATS("mon_rx_dest_stuck = %d", rx_mon_stats->mon_rx_dest_stuck); - DP_PRINT_STATS("rx_hdr_not_received = %d", - rx_mon_stats->rx_hdr_not_received); - DP_PRINT_STATS("parent_buf_alloc = %d", - rx_mon_stats->parent_buf_alloc); - DP_PRINT_STATS("parent_buf_free = %d", - rx_mon_stats->parent_buf_free); - DP_PRINT_STATS("mpdus_buf_to_stack = %d", - rx_mon_stats->mpdus_buf_to_stack); - DP_PRINT_STATS("frag_alloc = %d", - mon_soc->stats.frag_alloc); - DP_PRINT_STATS("frag_free = %d", - mon_soc->stats.frag_free); - DP_PRINT_STATS("status_buf_count = %d", - rx_mon_stats->status_buf_count); - DP_PRINT_STATS("pkt_buf_count = %d", - rx_mon_stats->pkt_buf_count); dp_pdev_get_undecoded_capture_stats(mon_pdev, rx_mon_stats); + dp_mon_rx_print_advanced_stats(pdev->soc, pdev); } #ifdef QCA_SUPPORT_BPR @@ -5046,10 +5030,19 @@ QDF_STATUS dp_mon_pdev_attach(struct dp_pdev *pdev) } } + if (mon_ops->mon_rx_ppdu_info_cache_create) { + if (mon_ops->mon_rx_ppdu_info_cache_create(pdev)) { + dp_mon_err("%pK: dp_rx_pdev_mon_attach failed", pdev); + goto fail4; + } + } pdev->monitor_pdev = mon_pdev; dp_mon_pdev_per_target_config(pdev); return QDF_STATUS_SUCCESS; +fail4: + if (mon_ops->rx_mon_desc_pool_free) + mon_ops->rx_mon_desc_pool_free(pdev); fail3: if (mon_ops->mon_rings_free) mon_ops->mon_rings_free(pdev); @@ -5085,6 +5078,8 @@ QDF_STATUS dp_mon_pdev_detach(struct dp_pdev *pdev) return QDF_STATUS_E_FAILURE; } + if (mon_ops->mon_rx_ppdu_info_cache_destroy) + mon_ops->mon_rx_ppdu_info_cache_destroy(pdev); if (mon_ops->rx_mon_desc_pool_free) mon_ops->rx_mon_desc_pool_free(pdev); if (mon_ops->mon_rings_free) diff --git a/dp/wifi3.0/monitor/dp_mon.h b/dp/wifi3.0/monitor/dp_mon.h index b451a37c5a..eb45ada9ef 100644 --- a/dp/wifi3.0/monitor/dp_mon.h +++ b/dp/wifi3.0/monitor/dp_mon.h @@ -820,6 +820,11 @@ struct dp_mon_ops { void (*mon_lite_mon_vdev_delete)(struct dp_pdev *pdev, struct dp_vdev *vdev); void (*mon_lite_mon_disable_rx)(struct dp_pdev *pdev); + /* Print advanced monitor stats */ + void (*mon_rx_print_advanced_stats) + (struct dp_soc *soc, struct dp_pdev *pdev); + QDF_STATUS (*mon_rx_ppdu_info_cache_create)(struct dp_pdev *pdev); + void (*mon_rx_ppdu_info_cache_destroy)(struct dp_pdev *pdev); }; /** @@ -4257,6 +4262,7 @@ void dp_monitor_peer_telemetry_stats(struct dp_peer *peer, #endif /** +<<<<<<< HEAD * dp_monitor_is_tx_cap_enabled() - get tx-cature enabled/disabled * @peer: DP peer handle * @@ -4298,4 +4304,33 @@ qdf_size_t dp_mon_get_context_size_be(enum dp_context_type context_type) } } #endif + +/* + * dp_mon_rx_print_advanced_stats () - print advanced monitor stats + * + * @soc: DP soc handle + * @pdev: DP pdev handle + * + * Return: void + */ +static inline void +dp_mon_rx_print_advanced_stats(struct dp_soc *soc, + struct dp_pdev *pdev) +{ + struct dp_mon_soc *mon_soc = soc->monitor_soc; + struct dp_mon_ops *monitor_ops; + + if (!mon_soc) { + dp_mon_debug("mon soc is NULL"); + return; + } + + monitor_ops = mon_soc->mon_ops; + if (!monitor_ops || + !monitor_ops->mon_rx_print_advanced_stats) { + dp_mon_debug("callback not registered"); + return; + } + return monitor_ops->mon_rx_print_advanced_stats(soc, pdev); +} #endif /* _DP_MON_H_ */ diff --git a/hal/wifi3.0/hal_api_mon.h b/hal/wifi3.0/hal_api_mon.h index 61dda30556..ee700734d6 100644 --- a/hal/wifi3.0/hal_api_mon.h +++ b/hal/wifi3.0/hal_api_mon.h @@ -224,9 +224,9 @@ enum hal_eht_ppdu_sig_cmn_type { */ struct hal_mon_packet_info { uint64_t sw_cookie; - uint16_t dma_length; - bool msdu_continuation; - bool truncated; + uint32_t dma_length : 16, + msdu_continuation : 1, + truncated : 1; }; /* @@ -239,34 +239,34 @@ struct hal_mon_packet_info { * @first_msdu: first msdu * @decap_type: decap type * @last_msdu: last msdu - * @buffer_len: buffer len - * @frag_len: frag len - * @msdu_len: msdu len - * @msdu_index: msdu index - * @user_rssi: user rssi * @l3_header_padding: L3 padding header * @stbc: stbc enabled * @sgi: SGI value * @reception_type: reception type + * @msdu_index: msdu index + * @buffer_len: buffer len + * @frag_len: frag len + * @msdu_len: msdu len + * @user_rssi: user rssi */ struct hal_rx_mon_msdu_info { - uint8_t first_buffer; - uint8_t last_buffer; - uint8_t first_mpdu; - uint8_t mpdu_length_err; - uint8_t fcs_err; - uint8_t first_msdu; - uint8_t decap_type; - uint8_t last_msdu; - uint16_t buffer_len; - uint16_t frag_len; + uint32_t first_buffer : 1, + last_buffer : 1, + first_mpdu : 1, + mpdu_length_err : 1, + fcs_err : 1, + first_msdu : 1, + decap_type : 3, + last_msdu : 1, + l3_header_padding : 3, + stbc : 1, + sgi : 2, + reception_type : 3, + msdu_index : 4; + uint16_t buffer_len : 12; + uint16_t frag_len : 12; uint16_t msdu_len; - uint8_t msdu_index; - int8_t user_rssi; - uint8_t l3_header_padding; - uint8_t stbc; - uint8_t sgi; - uint8_t reception_type; + int16_t user_rssi; }; /* @@ -282,15 +282,15 @@ struct hal_rx_mon_msdu_info { * @truncated: truncated MPDU */ struct hal_rx_mon_mpdu_info { - uint8_t decap_type; - bool mpdu_length_err; - bool fcs_err; - bool overflow_err; - bool decrypt_err; - bool mpdu_start_received; - bool full_pkt; - bool first_rx_hdr_rcvd; - bool truncated; + uint32_t decap_type : 8, + mpdu_length_err : 1, + fcs_err : 1, + overflow_err : 1, + decrypt_err : 1, + mpdu_start_received : 1, + full_pkt : 1, + first_rx_hdr_rcvd : 1, + truncated : 1; }; /** @@ -628,12 +628,12 @@ enum { struct hal_rx_ppdu_common_info { uint32_t ppdu_id; uint64_t ppdu_timestamp; - uint32_t mpdu_cnt_fcs_ok; - uint32_t mpdu_cnt_fcs_err; + uint16_t mpdu_cnt_fcs_ok; + uint8_t mpdu_cnt_fcs_err; + uint8_t num_users; uint32_t mpdu_fcs_ok_bitmap[HAL_RX_NUM_WORDS_PER_PPDU_BITMAP]; uint32_t last_ppdu_id; - uint32_t mpdu_cnt; - uint8_t num_users; + uint16_t mpdu_cnt; }; /** @@ -643,7 +643,7 @@ struct hal_rx_ppdu_common_info { */ struct hal_rx_msdu_payload_info { uint8_t *first_msdu_payload; - uint32_t payload_len; + uint8_t payload_len; }; /** @@ -652,32 +652,32 @@ struct hal_rx_msdu_payload_info { * @frame_control: frame control from each MPDU * @to_ds_flag: flag indicate to_ds bit * @mac_addr2_valid: flag indicate if mac_addr2 is valid - * @mac_addr2: mac address2 in wh * @mcast_bcast: multicast/broadcast + * @mac_addr2: mac address2 in wh */ struct hal_rx_nac_info { - uint8_t fc_valid; - uint16_t frame_control; - uint8_t to_ds_flag; - uint8_t mac_addr2_valid; + uint32_t fc_valid : 1, + frame_control : 16, + to_ds_flag : 1, + mac_addr2_valid : 1, + mcast_bcast : 1; uint8_t mac_addr2[QDF_MAC_ADDR_SIZE]; - uint8_t mcast_bcast; }; /** * struct hal_rx_ppdu_msdu_info - struct for msdu info from HW TLVs + * @fse_metadata: cached FSE metadata value received in the MSDU END TLV * @cce_metadata: cached CCE metadata value received in the MSDU_END TLV * @is_flow_idx_timeout: flag to indicate if flow search timeout occurred * @is_flow_idx_invalid: flag to indicate if flow idx is valid or not - * @fse_metadata: cached FSE metadata value received in the MSDU END TLV * @flow_idx: flow idx matched in FSE received in the MSDU END TLV */ struct hal_rx_ppdu_msdu_info { - uint16_t cce_metadata; - bool is_flow_idx_timeout; - bool is_flow_idx_invalid; uint32_t fse_metadata; - uint32_t flow_idx; + uint32_t cce_metadata : 16, + is_flow_idx_timeout : 1, + is_flow_idx_invalid : 1; + uint32_t flow_idx : 20; }; #if defined(WLAN_CFR_ENABLE) && defined(WLAN_ENH_CFR_ENABLE) @@ -691,7 +691,7 @@ struct hal_rx_ppdu_msdu_info { */ struct hal_rx_ppdu_cfr_user_info { uint8_t peer_macaddr[QDF_MAC_ADDR_SIZE]; - uint32_t ast_index; + uint16_t ast_index; }; /** @@ -790,7 +790,6 @@ struct hal_rx_ppdu_cfr_info { uint8_t chan_capture_status; uint8_t rtt_che_buffer_pointer_high8; uint32_t rtt_che_buffer_pointer_low32; - struct hal_rx_ppdu_cfr_user_info cfr_user_info[HAL_MAX_UL_MU_USERS]; int16_t rtt_cfo_measurement; uint32_t agc_gain_info0; uint32_t agc_gain_info1; @@ -809,7 +808,7 @@ struct mon_rx_info { uint16_t qos_control; uint8_t mac_addr1_valid; uint8_t mac_addr1[QDF_MAC_ADDR_SIZE]; - uint32_t user_id; + uint16_t user_id; }; struct mon_rx_user_info { @@ -819,9 +818,9 @@ struct mon_rx_user_info { #ifdef QCA_SUPPORT_SCAN_SPCL_VAP_STATS struct hal_rx_frm_type_info { - uint32_t rx_mgmt_cnt; - uint32_t rx_ctrl_cnt; - uint32_t rx_data_cnt; + uint8_t rx_mgmt_cnt; + uint8_t rx_ctrl_cnt; + uint8_t rx_data_cnt; }; #else struct hal_rx_frm_type_info {}; @@ -1211,9 +1210,9 @@ struct hal_rx_ppdu_info { struct hal_rx_msdu_payload_info fcs_ok_msdu_info; struct hal_rx_nac_info nac_info; /* status ring PPDU start and end state */ - uint32_t rx_state; + uint8_t rx_state; /* MU user id for status ring TLV */ - uint32_t user_id; + uint8_t user_id; /* MPDU/MSDU truncated to 128 bytes header start addr in status skb */ unsigned char *data; /* MPDU/MSDU truncated to 128 bytes header real length */ @@ -1245,9 +1244,9 @@ struct hal_rx_ppdu_info { /* EHT SIG user info */ uint32_t eht_sig_user_info; /*per user mpdu count */ - uint16_t mpdu_count[HAL_MAX_UL_MU_USERS]; + uint8_t mpdu_count[HAL_MAX_UL_MU_USERS]; /*per user msdu count */ - uint16_t msdu_count[HAL_MAX_UL_MU_USERS]; + uint8_t msdu_count[HAL_MAX_UL_MU_USERS]; /* Placeholder to update per user last processed msdu’s info */ struct hal_rx_mon_msdu_info msdu[HAL_MAX_UL_MU_USERS]; /* Placeholder to update per user last processed mpdu’s info */ @@ -1256,10 +1255,14 @@ struct hal_rx_ppdu_info { struct hal_mon_packet_info packet_info; #ifdef QCA_MONITOR_2_0_SUPPORT /* per user per MPDU queue */ - qdf_nbuf_t mpdu_q[HAL_MAX_UL_MU_USERS][HAL_RX_MAX_MPDU]; + qdf_nbuf_queue_t mpdu_q[HAL_MAX_UL_MU_USERS]; #endif /* ppdu info list element */ TAILQ_ENTRY(hal_rx_ppdu_info) ppdu_list_elem; + /* ppdu info free list element */ + TAILQ_ENTRY(hal_rx_ppdu_info) ppdu_free_list_elem; + /* placeholder to track if RX_HDR is received */ + uint8_t rx_hdr_rcvd[HAL_MAX_UL_MU_USERS]; }; static inline uint32_t diff --git a/hal/wifi3.0/li/hal_li_generic_api.h b/hal/wifi3.0/li/hal_li_generic_api.h index 88d006856d..acd2acf5f6 100644 --- a/hal/wifi3.0/li/hal_li_generic_api.h +++ b/hal/wifi3.0/li/hal_li_generic_api.h @@ -661,9 +661,6 @@ hal_rx_status_get_tlv_info_generic_li(void *rx_tlv_hdr, void *ppduinfo, rx_tlv = (uint8_t *)rx_tlv_hdr + HAL_RX_TLV32_HDR_SIZE; - qdf_trace_hex_dump(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - rx_tlv, tlv_len); - switch (tlv_tag) { case WIFIRX_PPDU_START_E: { @@ -1750,9 +1747,6 @@ hal_rx_status_get_tlv_info_generic_li(void *rx_tlv_hdr, void *ppduinfo, __func__, tlv_tag, tlv_len, unhandled == true ? "unhandled" : ""); - qdf_trace_hex_dump(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - rx_tlv, tlv_len); - return HAL_TLV_STATUS_PPDU_NOT_DONE; }