From 7d3197b9a52186861371d6973414cd95ad70dbb5 Mon Sep 17 00:00:00 2001 From: nobelj Date: Thu, 23 Jun 2022 01:27:01 -0700 Subject: [PATCH] qcacmn: tx monitor populate stats information add tx monitor stats information. Change-Id: Iffc55c2a4fa5351140daeffac3a50dd6867f6ea1 CRs-Fixed: 3230286 --- dp/wifi3.0/monitor/2.0/dp_mon_2.0.c | 11 +- dp/wifi3.0/monitor/2.0/dp_mon_2.0.h | 4 +- dp/wifi3.0/monitor/2.0/dp_rx_mon_2.0.c | 8 +- dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.c | 170 +++++++++++++++++- dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.h | 43 ++++- dp/wifi3.0/monitor/2.0/dp_tx_mon_status_2.0.c | 28 ++- dp/wifi3.0/monitor/dp_mon.h | 1 + qdf/inc/qdf_nbuf.h | 5 + qdf/linux/src/i_qdf_nbuf.h | 19 ++ 9 files changed, 266 insertions(+), 23 deletions(-) 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 6bcfe42379..be18b616d1 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 @@ -223,7 +223,8 @@ dp_mon_buffers_replenish(struct dp_soc *dp_soc, struct dp_mon_desc_pool *mon_desc_pool, uint32_t num_req_buffers, union dp_mon_desc_list_elem_t **desc_list, - union dp_mon_desc_list_elem_t **tail) + union dp_mon_desc_list_elem_t **tail, + uint32_t *replenish_cnt_ref) { uint32_t num_alloc_desc; uint16_t num_desc_to_free = 0; @@ -321,6 +322,8 @@ dp_mon_buffers_replenish(struct dp_soc *dp_soc, } hal_srng_access_end(dp_soc->hal_soc, mon_srng); + if (replenish_cnt_ref) + *replenish_cnt_ref += count; free_desc: /* @@ -812,7 +815,8 @@ QDF_STATUS dp_tx_mon_refill_buf_ring_2_0(struct dp_intr *int_ctx) if (num_entries_avail) dp_mon_buffers_replenish(soc, tx_mon_buf_ring, &mon_soc_be->tx_desc_mon, - num_entries_avail, &desc_list, &tail); + num_entries_avail, &desc_list, &tail, + NULL); return QDF_STATUS_SUCCESS; } @@ -844,7 +848,8 @@ QDF_STATUS dp_rx_mon_refill_buf_ring_2_0(struct dp_intr *int_ctx) if (num_entries_avail) dp_mon_buffers_replenish(soc, rx_mon_buf_ring, &mon_soc_be->rx_desc_mon, - num_entries_avail, &desc_list, &tail); + num_entries_avail, &desc_list, &tail, + NULL); return QDF_STATUS_SUCCESS; } 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 ee4e3c1540..af5520844a 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 @@ -264,6 +264,7 @@ void dp_mon_pool_frag_unmap_and_free(struct dp_soc *dp_soc, * or NULL during dp rx initialization or out of buffer * interrupt. * @tail: tail of descs list + * @relenish_cnt_ref: pointer to update replenish_cnt * * Return: return success or failure */ @@ -272,7 +273,8 @@ QDF_STATUS dp_mon_buffers_replenish(struct dp_soc *dp_soc, struct dp_mon_desc_pool *mon_desc_pool, uint32_t num_req_buffers, union dp_mon_desc_list_elem_t **desc_list, - union dp_mon_desc_list_elem_t **tail); + union dp_mon_desc_list_elem_t **tail, + uint32_t *replenish_cnt_ref); /** * dp_mon_filter_show_tx_filter_be() - Show the set filters 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 027317b0a6..51bf67aaf5 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 @@ -845,7 +845,7 @@ dp_rx_mon_flush_status_buf_queue(struct dp_pdev *pdev) dp_mon_buffers_replenish(soc, &soc->rxdma_mon_buf_ring[0], rx_mon_desc_pool, work_done, - &desc_list, &tail); + &desc_list, &tail, NULL); } } @@ -878,7 +878,7 @@ dp_rx_mon_handle_flush_n_trucated_ppdu(struct dp_soc *soc, dp_mon_buffers_replenish(soc, &soc->rxdma_mon_buf_ring[0], rx_mon_desc_pool, work_done, - &desc_list, &tail); + &desc_list, &tail, NULL); } uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev, @@ -1296,7 +1296,7 @@ dp_rx_mon_process_status_tlv(struct dp_pdev *pdev) dp_mon_buffers_replenish(soc, &soc->rxdma_mon_buf_ring[0], rx_mon_desc_pool, work_done, - &desc_list, &tail); + &desc_list, &tail, NULL); } ppdu_info->rx_status.tsft = ppdu_info->rx_status.tsft + @@ -1589,7 +1589,7 @@ dp_rx_mon_buffers_alloc(struct dp_soc *soc, uint32_t size) return dp_mon_buffers_replenish(soc, mon_buf_ring, rx_mon_desc_pool, size, - &desc_list, &tail); + &desc_list, &tail, NULL); } #ifdef QCA_ENHANCED_STATS_SUPPORT diff --git a/dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.c b/dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.c index 1ad5171c55..664866bb04 100644 --- a/dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.c +++ b/dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.c @@ -33,6 +33,67 @@ #include "dp_ratetable.h" #endif +#define MAX_TX_MONITOR_STUCK 50 + +#ifdef TXMON_DEBUG +/* + * dp_tx_mon_debug_statu() - API to display tx monitor status + * @tx_mon_be - pointer to dp_pdev_tx_monitor_be + * @work_done - tx monitor work done + * + * Return: void + */ +static inline void +dp_tx_mon_debug_status(struct dp_pdev_tx_monitor_be *tx_mon_be, + uint32_t work_done) +{ + if (tx_mon_be->mode && !work_done) + tx_mon_be->stats.tx_mon_stuck++; + else if (tx_mon_be->mode && work_done) + tx_mon_be->stats.tx_mon_stuck = 0; + + if (tx_mon_be->stats.tx_mon_stuck > MAX_TX_MONITOR_STUCK) { + dp_mon_warn("Tx monitor block got stuck!!!!!"); + tx_mon_be->stats.tx_mon_stuck = 0; + tx_mon_be->stats.total_tx_mon_stuck++; + } + + dp_mon_debug_rl("tx_ppdu_info[%u :D %u] STATUS[R %llu: F %llu] PKT_BUF[R %llu: F %llu : P %llu : S %llu]", + tx_mon_be->tx_ppdu_info_list_depth, + tx_mon_be->defer_ppdu_info_list_depth, + tx_mon_be->stats.status_buf_recv, + tx_mon_be->stats.status_buf_free, + tx_mon_be->stats.pkt_buf_recv, + tx_mon_be->stats.pkt_buf_free, + tx_mon_be->stats.pkt_buf_processed, + tx_mon_be->stats.pkt_buf_to_stack); +} + +#else +/* + * dp_tx_mon_debug_statu() - API to display tx monitor status + * @tx_mon_be - pointer to dp_pdev_tx_monitor_be + * @work_done - tx monitor work done + * + * Return: void + */ +static inline void +dp_tx_mon_debug_status(struct dp_pdev_tx_monitor_be *tx_mon_be, + uint32_t work_done) +{ + if (tx_mon_be->mode && !work_done) + tx_mon_be->stats.tx_mon_stuck++; + else if (tx_mon_be->mode && work_done) + tx_mon_be->stats.tx_mon_stuck = 0; + + if (tx_mon_be->stats.tx_mon_stuck > MAX_TX_MONITOR_STUCK) { + dp_mon_warn("Tx monitor block got stuck!!!!!"); + tx_mon_be->stats.tx_mon_stuck = 0; + tx_mon_be->stats.total_tx_mon_stuck++; + } +} +#endif + static inline uint32_t dp_tx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx, uint32_t mac_id, uint32_t quota) @@ -49,6 +110,7 @@ dp_tx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx, struct dp_pdev_tx_monitor_be *tx_mon_be = NULL; struct dp_mon_desc_pool *tx_mon_desc_pool = &mon_soc_be->tx_desc_mon; struct dp_tx_mon_desc_list mon_desc_list; + uint32_t replenish_cnt = 0; if (!pdev) { dp_mon_err("%pK: pdev is null for mac_id = %d", soc, mac_id); @@ -110,6 +172,12 @@ dp_tx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx, hal_mon_tx_desc.tlv_drop_count, hal_mon_tx_desc.end_of_ppdu_dropped); + tx_mon_be->stats.ppdu_drop_cnt += + hal_mon_tx_desc.ppdu_drop_count; + tx_mon_be->stats.mpdu_drop_cnt += + hal_mon_tx_desc.mpdu_drop_count; + tx_mon_be->stats.tlv_drop_cnt += + hal_mon_tx_desc.tlv_drop_count; work_done++; hal_srng_dst_get_next(hal_soc, mon_dst_srng); continue; @@ -168,9 +236,12 @@ dp_tx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx, continue; } + tx_mon_be->stats.status_buf_recv++; + if ((hal_mon_tx_desc.end_reason == HAL_MON_FLUSH_DETECTED) || (hal_mon_tx_desc.end_reason == HAL_MON_PPDU_TRUNCATED)) { tx_mon_be->be_ppdu_id = hal_mon_tx_desc.ppdu_id; + dp_tx_mon_update_end_reason(mon_pdev, hal_mon_tx_desc.ppdu_id, hal_mon_tx_desc.end_reason); @@ -178,6 +249,8 @@ dp_tx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx, dp_tx_mon_status_free_packet_buf(pdev, status_frag, end_offset, &mon_desc_list); + + tx_mon_be->stats.status_buf_free++; qdf_frag_free(status_frag); work_done++; @@ -201,12 +274,17 @@ dp_tx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx, tx_mon_desc_pool, mon_desc_list.tx_mon_reap_cnt, &mon_desc_list.desc_list, - &mon_desc_list.tail); + &mon_desc_list.tail, + &replenish_cnt); } qdf_spin_unlock_bh(&mon_pdev->mon_lock); dp_mon_debug("mac_id: %d, work_done:%d tx_monitor_reap_cnt:%d", mac_id, work_done, mon_desc_list.tx_mon_reap_cnt); + tx_mon_be->stats.total_tx_mon_reap_cnt += mon_desc_list.tx_mon_reap_cnt; + tx_mon_be->stats.totat_tx_mon_replenish_cnt += replenish_cnt; + dp_tx_mon_debug_status(tx_mon_be, work_done); + return work_done; } @@ -309,11 +387,30 @@ dp_tx_mon_buffers_alloc(struct dp_soc *soc, uint32_t size) return dp_mon_buffers_replenish(soc, mon_buf_ring, tx_mon_desc_pool, size, - &desc_list, &tail); + &desc_list, &tail, NULL); } #ifdef WLAN_TX_PKT_CAPTURE_ENH_BE +/* + * dp_tx_mon_nbuf_get_num_frag() - get total number of fragments + * @buf: Network buf instance + * + * Return: number of fragments + */ +static inline +uint32_t dp_tx_mon_nbuf_get_num_frag(qdf_nbuf_t nbuf) +{ + uint32_t num_frag = 0; + + if (qdf_unlikely(!nbuf)) + return num_frag; + + num_frag = qdf_nbuf_get_nr_frags_in_fraglist(nbuf); + + return num_frag; +} + /* * dp_tx_mon_free_usr_mpduq() - API to free user mpduq * @tx_ppdu_info - pointer to tx_ppdu_info @@ -327,12 +424,19 @@ void dp_tx_mon_free_usr_mpduq(struct dp_tx_ppdu_info *tx_ppdu_info, struct dp_pdev_tx_monitor_be *tx_mon_be) { qdf_nbuf_queue_t *mpdu_q; + uint32_t num_frag = 0; + qdf_nbuf_t buf = NULL; if (qdf_unlikely(!tx_ppdu_info)) return; mpdu_q = &TXMON_PPDU_USR(tx_ppdu_info, usr_idx, mpdu_q); - qdf_nbuf_queue_free(mpdu_q); + + while ((buf = qdf_nbuf_queue_remove(mpdu_q)) != NULL) { + num_frag += dp_tx_mon_nbuf_get_num_frag(buf); + qdf_nbuf_free(buf); + } + tx_mon_be->stats.pkt_buf_free += num_frag; } /* @@ -349,9 +453,16 @@ void dp_tx_mon_free_ppdu_info(struct dp_tx_ppdu_info *tx_ppdu_info, for (; user < TXMON_PPDU_HAL(tx_ppdu_info, num_users); user++) { qdf_nbuf_queue_t *mpdu_q; + uint32_t num_frag = 0; + qdf_nbuf_t buf = NULL; mpdu_q = &TXMON_PPDU_USR(tx_ppdu_info, user, mpdu_q); - qdf_nbuf_queue_free(mpdu_q); + + while ((buf = qdf_nbuf_queue_remove(mpdu_q)) != NULL) { + num_frag += dp_tx_mon_nbuf_get_num_frag(buf); + qdf_nbuf_free(buf); + } + tx_mon_be->stats.pkt_buf_free += num_frag; } TXMON_PPDU_HAL(tx_ppdu_info, is_used) = 0; @@ -424,7 +535,39 @@ struct dp_tx_ppdu_info *dp_tx_mon_get_ppdu_info(struct dp_pdev *pdev, */ void dp_print_pdev_tx_monitor_stats_2_0(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 dp_pdev_tx_monitor_be *tx_mon_be = + &mon_pdev_be->tx_monitor_be; + struct dp_tx_monitor_drop_stats stats = {0}; + + qdf_mem_copy(&stats, &tx_mon_be->stats, + sizeof(struct dp_tx_monitor_drop_stats)); + /* TX monitor stats needed for beryllium */ + DP_PRINT_STATS("\n\tTX Capture BE stats mode[%d]:", tx_mon_be->mode); + DP_PRINT_STATS("\tbuffer pending : %u", tx_mon_be->last_frag_q_idx); + DP_PRINT_STATS("\treplenish count: %llu", + stats.totat_tx_mon_replenish_cnt); + DP_PRINT_STATS("\treap count : %llu", stats.total_tx_mon_reap_cnt); + DP_PRINT_STATS("\tmonitor stuck : %u", stats.total_tx_mon_stuck); + DP_PRINT_STATS("\tStatus buffer"); + DP_PRINT_STATS("\t\treceived : %llu", stats.status_buf_recv); + DP_PRINT_STATS("\t\tfree : %llu", stats.status_buf_free); + DP_PRINT_STATS("\tPacket buffer"); + DP_PRINT_STATS("\t\treceived : %llu", stats.pkt_buf_recv); + DP_PRINT_STATS("\t\tfree : %llu", stats.pkt_buf_free); + DP_PRINT_STATS("\t\tprocessed : %llu", stats.pkt_buf_processed); + DP_PRINT_STATS("\t\tto stack : %llu", stats.pkt_buf_to_stack); + DP_PRINT_STATS("\tppdu info"); + DP_PRINT_STATS("\t\tthreshold : %llu", stats.ppdu_info_drop_th); + DP_PRINT_STATS("\t\tflush : %llu", stats.ppdu_info_drop_flush); + DP_PRINT_STATS("\t\ttruncated : %llu", stats.ppdu_info_drop_trunc); + DP_PRINT_STATS("\tDrop stats"); + DP_PRINT_STATS("\t\tppdu drop : %llu", stats.ppdu_drop_cnt); + DP_PRINT_STATS("\t\tmpdu drop : %llu", stats.mpdu_drop_cnt); + DP_PRINT_STATS("\t\ttlv drop : %llu", stats.tlv_drop_cnt); } /* @@ -455,6 +598,8 @@ dp_config_enh_tx_monitor_2_0(struct dp_pdev *pdev, uint8_t val) case TX_MON_BE_FULL_CAPTURE: { /* TODO: send HTT msg to configure TLV based on mode */ + qdf_mem_zero(&tx_mon_be->stats, + sizeof(struct dp_tx_monitor_drop_stats)); tx_mon_be->mode = TX_MON_BE_FULL_CAPTURE; mon_pdev_be->tx_mon_mode = 1; mon_pdev_be->tx_mon_filter_length = DEFAULT_DMA_LENGTH; @@ -464,7 +609,7 @@ dp_config_enh_tx_monitor_2_0(struct dp_pdev *pdev, uint8_t val) { /* TODO: send HTT msg to configure TLV based on mode */ tx_mon_be->mode = TX_MON_BE_PEER_FILTER; - mon_pdev_be->tx_mon_mode = 1; + mon_pdev_be->tx_mon_mode = 2; mon_pdev_be->tx_mon_filter_length = DMA_LENGTH_256B; break; } @@ -526,17 +671,23 @@ static void dp_fill_lite_mon_vdev(struct cdp_tx_indication_info *tx_cap_info, * dp_tx_mon_send_to_stack() - API to send to stack * @pdev: pdev Handle * @mpdu: pointer to mpdu + * @num_frag: number of frag in mpdu * * Return: void */ static void -dp_tx_mon_send_to_stack(struct dp_pdev *pdev, qdf_nbuf_t mpdu) +dp_tx_mon_send_to_stack(struct dp_pdev *pdev, qdf_nbuf_t mpdu, + uint32_t num_frag) { 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 dp_pdev_tx_monitor_be *tx_mon_be = + &mon_pdev_be->tx_monitor_be; struct cdp_tx_indication_info tx_capture_info = {0}; + tx_mon_be->stats.pkt_buf_to_stack += num_frag; + tx_capture_info.radiotap_done = 1; tx_capture_info.mpdu_nbuf = mpdu; if (!dp_lite_mon_is_tx_enabled(mon_pdev)) { @@ -578,13 +729,15 @@ dp_tx_mon_send_per_usr_mpdu(struct dp_pdev *pdev, usr_mpdu_q = &TXMON_PPDU_USR(ppdu_info, user_idx, mpdu_q); while ((buf = qdf_nbuf_queue_remove(usr_mpdu_q)) != NULL) { + uint32_t num_frag = dp_tx_mon_nbuf_get_num_frag(buf); + ppdu_info->hal_txmon.rx_status.rx_user_status = &ppdu_info->hal_txmon.rx_user_status[user_idx]; qdf_nbuf_update_radiotap(&ppdu_info->hal_txmon.rx_status, buf, qdf_nbuf_headroom(buf)); - dp_tx_mon_send_to_stack(pdev, buf); + dp_tx_mon_send_to_stack(pdev, buf, num_frag); } } @@ -846,6 +999,9 @@ dp_config_enh_tx_core_monitor_2_0(struct dp_pdev *pdev, uint8_t val) case TX_MON_BE_FRM_WRK_FULL_CAPTURE: { tx_mon_be->mode = val; + qdf_mem_zero(&tx_mon_be->stats, + sizeof(struct dp_tx_monitor_drop_stats)); + tx_mon_be->mode = val; mon_pdev_be->tx_mon_mode = 1; mon_pdev_be->tx_mon_filter_length = DEFAULT_DMA_LENGTH; break; diff --git a/dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.h b/dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.h index 5739d69241..0ef9b81740 100644 --- a/dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.h +++ b/dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.h @@ -358,11 +358,41 @@ struct dp_tx_ppdu_info { * @ppdu_drop_cnt: ppdu drop counter * @mpdu_drop_cnt: mpdu drop counter * @tlv_drop_cnt: tlv drop counter + * @pkt_buf_recv: tx monitor packet buffer received + * @pkt_buf_free: tx monitor packet buffer free + * @pkt_buf_processed: tx monitor packet buffer processed + * @pkt_buf_to_stack: tx monitor packet buffer send to stack + * @status_buf_recv: tx monitor status buffer received + * @status_buf_free: tx monitor status buffer free + * @totat_tx_mon_replenish_cnt: tx monitor replenish count + * @total_tx_mon_reap_cnt: tx monitor reap count + * @tx_mon_stuck: tx monitor stuck count + * @total_tx_mon_stuck: tx monitor stuck count + * @ppdu_info_drop_th: count ppdu info been dropped due threshold reached + * @ppdu_info_drop_flush: count ppdu info been dropped due to flush detected + * @ppdu_info_drop_trunc: count ppdu info been dropped due to truncated */ struct dp_tx_monitor_drop_stats { uint64_t ppdu_drop_cnt; uint64_t mpdu_drop_cnt; uint64_t tlv_drop_cnt; + + uint64_t pkt_buf_recv; + uint64_t pkt_buf_free; + uint64_t pkt_buf_processed; + uint64_t pkt_buf_to_stack; + + uint64_t status_buf_recv; + uint64_t status_buf_free; + + uint64_t totat_tx_mon_replenish_cnt; + uint64_t total_tx_mon_reap_cnt; + uint8_t tx_mon_stuck; + uint32_t total_tx_mon_stuck; + + uint64_t ppdu_info_drop_th; + uint64_t ppdu_info_drop_flush; + uint64_t ppdu_info_drop_trunc; }; /** @@ -419,12 +449,13 @@ enum dp_tx_monitor_framework_mode { * dp_pdev_tx_monitor_be - info to store tx capture information in pdev * @be_ppdu_id: current ppdu id * @mode: tx monitor core framework current mode - * @tx_stats: tx monitor drop stats for that mac + * @stats: tx monitor drop stats for that mac + * */ struct dp_pdev_tx_monitor_be { uint32_t be_ppdu_id; uint32_t mode; - struct dp_tx_monitor_drop_stats tx_stats; + struct dp_tx_monitor_drop_stats stats; }; /** @@ -458,7 +489,7 @@ struct dp_txmon_frag_vec { * @tx_ppdu_info_list: ppdu info list to hold ppdu * @defer_ppdu_info_list_depth: defer ppdu list depth counter * @defer_ppdu_info_list: defer ppdu info list to hold defer ppdu - * @tx_stats: tx monitor drop stats for that mac + * @stats: tx monitor drop stats for that mac * @tx_prot_ppdu_info: tx monitor protection ppdu info * @tx_data_ppdu_info: tx monitor data ppdu info * @last_prot_ppdu_info: last tx monitor protection ppdu info @@ -487,7 +518,7 @@ struct dp_pdev_tx_monitor_be { STAILQ_HEAD(, dp_tx_ppdu_info) defer_tx_ppdu_info_queue; - struct dp_tx_monitor_drop_stats tx_stats; + struct dp_tx_monitor_drop_stats stats; struct dp_tx_ppdu_info *tx_prot_ppdu_info; struct dp_tx_ppdu_info *tx_data_ppdu_info; @@ -530,7 +561,7 @@ void dp_tx_mon_ppdu_info_free(struct dp_tx_ppdu_info *tx_ppdu_info); */ void dp_tx_mon_free_usr_mpduq(struct dp_tx_ppdu_info *tx_ppdu_info, uint8_t usr_idx, - struct dp_pdev_tx_monitor_be *tx_cap_be); + struct dp_pdev_tx_monitor_be *tx_mon_be); /* * dp_tx_mon_free_ppdu_info() - API to free dp_tx_ppdu_info @@ -540,7 +571,7 @@ void dp_tx_mon_free_usr_mpduq(struct dp_tx_ppdu_info *tx_ppdu_info, * Return: void */ void dp_tx_mon_free_ppdu_info(struct dp_tx_ppdu_info *tx_ppdu_info, - struct dp_pdev_tx_monitor_be *tx_cap_be); + struct dp_pdev_tx_monitor_be *tx_mon_be); /* * dp_tx_mon_get_ppdu_info() - API to allocate dp_tx_ppdu_info diff --git a/dp/wifi3.0/monitor/2.0/dp_tx_mon_status_2.0.c b/dp/wifi3.0/monitor/2.0/dp_tx_mon_status_2.0.c index 3f02f26e12..8873278557 100644 --- a/dp/wifi3.0/monitor/2.0/dp_tx_mon_status_2.0.c +++ b/dp/wifi3.0/monitor/2.0/dp_tx_mon_status_2.0.c @@ -26,6 +26,8 @@ #include #include +#define MAX_PPDU_INFO_LIST_DEPTH 64 + /** * dp_tx_mon_status_free_packet_buf() - API to free packet buffer * @pdev: pdev Handle @@ -103,6 +105,9 @@ dp_tx_mon_status_free_packet_buf(struct dp_pdev *pdev, &mon_desc_list_ref->tail, mon_desc); + tx_mon_be->stats.pkt_buf_recv++; + tx_mon_be->stats.pkt_buf_free++; + /* free buffer, mapped to descriptor */ qdf_frag_free(packet_buffer); } @@ -140,6 +145,7 @@ dp_tx_mon_status_queue_free(struct dp_pdev *pdev, end_offset = tx_mon_be->frag_q_vec[i].end_offset; dp_tx_mon_status_free_packet_buf(pdev, status_frag, end_offset, mon_desc_list_ref); + tx_mon_be->stats.status_buf_free++; qdf_frag_free(status_frag); tx_mon_be->frag_q_vec[i].frag_buf = NULL; tx_mon_be->frag_q_vec[i].end_offset = 0; @@ -946,6 +952,8 @@ dp_tx_mon_generate_data_frm(struct dp_pdev *pdev, if (!mpdu_nbuf) QDF_BUG(0); + tx_mon_be->stats.pkt_buf_processed++; + /* add function to either copy or add frag to frag_list */ qdf_nbuf_add_frag(pdev->soc->osdev, TXMON_STATUS_INFO(tx_status_info, buffer), @@ -1320,6 +1328,7 @@ dp_tx_mon_update_ppdu_info_status(struct dp_pdev *pdev, qdf_assert_always(0); qdf_assert_always(mon_desc->buf_addr); + tx_mon_be->stats.pkt_buf_recv++; if (!mon_desc->unmapped) { qdf_mem_unmap_page(pdev->soc->osdev, @@ -1401,10 +1410,10 @@ dp_tx_mon_process_tlv_2_0(struct dp_pdev *pdev, struct hal_tx_status_info *tx_status_data; qdf_frag_t status_frag = NULL; uint32_t end_offset = 0; - uint8_t *tx_tlv; - uint8_t *tx_tlv_start; uint32_t tlv_status; uint32_t status = QDF_STATUS_SUCCESS; + uint8_t *tx_tlv; + uint8_t *tx_tlv_start; uint8_t num_users = 0; uint8_t cur_frag_q_idx; bool schedule_wrq = false; @@ -1513,6 +1522,7 @@ dp_tx_mon_process_tlv_2_0(struct dp_pdev *pdev, * free status buffer after parsing * is status_frag mapped to mpdu if so make sure */ + tx_mon_be->stats.status_buf_free++; qdf_frag_free(status_frag); tx_mon_be->frag_q_vec[cur_frag_q_idx].frag_buf = NULL; tx_mon_be->frag_q_vec[cur_frag_q_idx].end_offset = 0; @@ -1689,10 +1699,12 @@ dp_tx_mon_process_status_tlv(struct dp_soc *soc, tx_mon_be->last_frag_q_idx) { if (tx_mon_be->be_end_reason_bitmap & (1 << HAL_MON_FLUSH_DETECTED)) { + tx_mon_be->stats.ppdu_info_drop_flush++; dp_tx_mon_status_queue_free(pdev, tx_mon_be, mon_desc_list_ref); } else if (tx_mon_be->be_end_reason_bitmap & (1 << HAL_MON_PPDU_TRUNCATED)) { + tx_mon_be->stats.ppdu_info_drop_trunc++; dp_tx_mon_status_queue_free(pdev, tx_mon_be, mon_desc_list_ref); } else { @@ -1721,6 +1733,16 @@ dp_tx_mon_process_status_tlv(struct dp_soc *soc, tx_mon_be->last_frag_q_idx++; if (mon_ring_desc->end_reason == HAL_MON_END_OF_PPDU) { + /* drop processing of tlv, if ppdu info list exceed threshold */ + if ((tx_mon_be->defer_ppdu_info_list_depth + + tx_mon_be->tx_ppdu_info_list_depth) > + MAX_PPDU_INFO_LIST_DEPTH) { + tx_mon_be->stats.ppdu_info_drop_th++; + dp_tx_mon_status_queue_free(pdev, tx_mon_be, + mon_desc_list_ref); + return QDF_STATUS_E_PENDING; + } + if (dp_tx_mon_process_tlv_2_0(pdev, mon_desc_list_ref) != QDF_STATUS_SUCCESS) @@ -1733,6 +1755,7 @@ dp_tx_mon_process_status_tlv(struct dp_soc *soc, free_status_buffer: dp_tx_mon_status_free_packet_buf(pdev, status_frag, end_offset, mon_desc_list_ref); + tx_mon_be->stats.status_buf_free++; qdf_frag_free(status_frag); return QDF_STATUS_E_NOMEM; @@ -1781,6 +1804,7 @@ dp_tx_mon_process_status_tlv(struct dp_soc *soc, dp_tx_mon_status_free_packet_buf(pdev, status_frag, end_offset, mon_desc_list_ref); + tx_mon_be->stats.status_buf_free++; qdf_frag_free(status_frag); return QDF_STATUS_E_INVAL; diff --git a/dp/wifi3.0/monitor/dp_mon.h b/dp/wifi3.0/monitor/dp_mon.h index 436c250528..0265ce9d76 100644 --- a/dp/wifi3.0/monitor/dp_mon.h +++ b/dp/wifi3.0/monitor/dp_mon.h @@ -57,6 +57,7 @@ #define dp_mon_debug(params...) QDF_TRACE_DEBUG(QDF_MODULE_ID_MON, params) #define dp_mon_warn(params...) QDF_TRACE_WARN(QDF_MODULE_ID_MON, params) +#define dp_mon_warn_rl(params...) QDF_TRACE_WARN_RL(QDF_MODULE_ID_MON, params) #define dp_mon_debug_rl(params...) QDF_TRACE_DEBUG_RL(QDF_MODULE_ID_MON, params) #define dp_mon_info_rl(params...) \ __QDF_TRACE_RL(QDF_TRACE_LEVEL_INFO_HIGH, QDF_MODULE_ID_MON, ## params) diff --git a/qdf/inc/qdf_nbuf.h b/qdf/inc/qdf_nbuf.h index e60b54d8d3..86ede1daf5 100644 --- a/qdf/inc/qdf_nbuf.h +++ b/qdf/inc/qdf_nbuf.h @@ -4202,6 +4202,11 @@ static inline uint32_t qdf_nbuf_get_nr_frags(qdf_nbuf_t nbuf) return __qdf_nbuf_get_nr_frags(nbuf); } +static inline uint32_t qdf_nbuf_get_nr_frags_in_fraglist(qdf_nbuf_t nbuf) +{ + return __qdf_nbuf_get_nr_frags_in_fraglist(nbuf); +} + static inline qdf_size_t qdf_nbuf_headlen(qdf_nbuf_t buf) { return __qdf_nbuf_headlen(buf); diff --git a/qdf/linux/src/i_qdf_nbuf.h b/qdf/linux/src/i_qdf_nbuf.h index 16b9155421..6b42523d23 100644 --- a/qdf/linux/src/i_qdf_nbuf.h +++ b/qdf/linux/src/i_qdf_nbuf.h @@ -1094,6 +1094,25 @@ static inline size_t __qdf_nbuf_get_nr_frags(struct sk_buff *skb) return skb_shinfo(skb)->nr_frags; } +/** + * __qdf_nbuf_get_nr_frags_in_fraglist() - return the number of fragments + * @skb: sk buff + * + * This API returns a total number of fragments from the fraglist + * Return: total number of fragments + */ +static inline uint32_t __qdf_nbuf_get_nr_frags_in_fraglist(struct sk_buff *skb) +{ + uint32_t num_frag = 0; + struct sk_buff *list = NULL; + + num_frag = skb_shinfo(skb)->nr_frags; + skb_walk_frags(skb, list) + num_frag += skb_shinfo(list)->nr_frags; + + return num_frag; +} + /* * qdf_nbuf_pool_delete() implementation - do nothing in linux */