diff --git a/dp/inc/cdp_txrx_stats_struct.h b/dp/inc/cdp_txrx_stats_struct.h index a6c1a13177..3183349866 100644 --- a/dp/inc/cdp_txrx_stats_struct.h +++ b/dp/inc/cdp_txrx_stats_struct.h @@ -71,7 +71,8 @@ #define WME_AC_VO 3 /* voice */ #define WME_AC_MAX 4 /* MAX AC Value */ -#define CDP_MAX_RX_RINGS 4 +#define CDP_MAX_RX_RINGS 4 /* max rx rings */ +#define CDP_MAX_TX_COMP_RINGS 3 /* max tx completion rings */ /* TID level VoW stats macros * to add and get stats @@ -291,8 +292,7 @@ struct cdp_delay_stats { * @hwtx_delay: delay between wifi driver exit (enqueue to HW) and tx completion * @intfrm_delay: interframe delay * @success_cnt: total successful transmit count - * @complete_cnt: total transmit count - * @fwdrop_cnt: firmware drop found in tx completion path + * @comp_fail_cnt: firmware drop found in tx completion path * @swdrop_cnt: software drop in tx path */ struct cdp_tid_tx_stats { @@ -300,7 +300,6 @@ struct cdp_tid_tx_stats { struct cdp_delay_stats hwtx_delay; struct cdp_delay_stats intfrm_delay; uint64_t success_cnt; - uint64_t complete_cnt; uint64_t comp_fail_cnt; uint64_t swdrop_cnt[TX_MAX_DROP]; }; @@ -330,14 +329,17 @@ struct cdp_tid_rx_stats { /* * struct cdp_tid_stats * @ingress_stack: Total packets received from linux stack + * @osif_drop: drops in osif layer * @tid_tx_stats: transmit counters per tid * @tid_rx_stats: receive counters per tid */ struct cdp_tid_stats { uint64_t ingress_stack; uint64_t osif_drop; - struct cdp_tid_tx_stats tid_tx_stats[CDP_MAX_DATA_TIDS]; - struct cdp_tid_rx_stats tid_rx_stats[CDP_MAX_DATA_TIDS]; + struct cdp_tid_tx_stats tid_tx_stats[CDP_MAX_TX_COMP_RINGS] + [CDP_MAX_DATA_TIDS]; + struct cdp_tid_rx_stats tid_rx_stats[CDP_MAX_RX_RINGS] + [CDP_MAX_DATA_TIDS]; }; /* struct cdp_pkt_info - packet info diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index 5454598703..e90e018874 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -858,8 +858,19 @@ uint32_t dp_pdev_tid_stats_display(void *pdev_handle, enum _ol_ath_param_t param, uint32_t value, void *buff); #endif +/** + * dp_update_delay_stats() - Update delay statistics in structure + * and fill min, max and avg delay + * @pdev: pdev handle + * @delay: delay in ms + * @tid: tid value + * @mode: type of tx delay mode + * @ring id: ring number + * + * Return: none + */ void dp_update_delay_stats(struct dp_pdev *pdev, uint32_t delay, - uint8_t tid, uint8_t mode); + uint8_t tid, uint8_t mode, uint8_t ring_id); /** * dp_print_ring_stats(): Print tail and head pointer diff --git a/dp/wifi3.0/dp_ipa.c b/dp/wifi3.0/dp_ipa.c index 3729dc18b9..78b04bb6bc 100644 --- a/dp/wifi3.0/dp_ipa.c +++ b/dp/wifi3.0/dp_ipa.c @@ -1619,29 +1619,22 @@ static qdf_nbuf_t dp_ipa_intrabss_send(struct dp_pdev *pdev, struct dp_vdev *vdev, qdf_nbuf_t nbuf) { - struct cdp_tid_rx_stats *tid_stats; struct dp_peer *vdev_peer; uint16_t len; - uint8_t tid; vdev_peer = vdev->vap_bss_peer; if (qdf_unlikely(!vdev_peer)) return nbuf; - tid = qdf_nbuf_get_priority(nbuf); - tid_stats = &pdev->stats.tid_stats.tid_rx_stats[tid]; - qdf_mem_zero(nbuf->cb, sizeof(nbuf->cb)); len = qdf_nbuf_len(nbuf); if (dp_tx_send(vdev, nbuf)) { DP_STATS_INC_PKT(vdev_peer, rx.intra_bss.fail, 1, len); - tid_stats->fail_cnt[INTRABSS_DROP]++; return nbuf; } DP_STATS_INC_PKT(vdev_peer, rx.intra_bss.pkts, 1, len); - tid_stats->intrabss_cnt++; return NULL; } diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index b0de4f25ed..0f910d5dd8 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -1394,7 +1394,7 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget) work_done = dp_tx_comp_handler(int_ctx, soc, soc->tx_comp_ring[ring].hal_srng, - remaining_quota); + ring, remaining_quota); if (work_done) { intr_stats->num_tx_ring_masks[ring]++; @@ -9635,19 +9635,20 @@ static uint8_t dp_bucket_index(uint32_t delay, uint16_t *array) * * @pdev: pdev handle * @delay: delay in ms - * @t: tid value + * @tid: tid value * @mode: type of tx delay mode + * @ring_id: ring number * Return: pointer to cdp_delay_stats structure */ static struct cdp_delay_stats * dp_fill_delay_buckets(struct dp_pdev *pdev, uint32_t delay, - uint8_t tid, uint8_t mode) + uint8_t tid, uint8_t mode, uint8_t ring_id) { uint8_t delay_index = 0; struct cdp_tid_tx_stats *tstats = - &pdev->stats.tid_stats.tid_tx_stats[tid]; + &pdev->stats.tid_stats.tid_tx_stats[ring_id][tid]; struct cdp_tid_rx_stats *rstats = - &pdev->stats.tid_stats.tid_rx_stats[tid]; + &pdev->stats.tid_stats.tid_rx_stats[ring_id][tid]; /* * cdp_fw_to_hw_delay_range * Fw to hw delay ranges in milliseconds @@ -9723,10 +9724,11 @@ dp_fill_delay_buckets(struct dp_pdev *pdev, uint32_t delay, * @delay: delay in ms * @tid: tid value * @mode: type of tx delay mode + * @ring id: ring number * Return: none */ void dp_update_delay_stats(struct dp_pdev *pdev, uint32_t delay, - uint8_t tid, uint8_t mode) + uint8_t tid, uint8_t mode, uint8_t ring_id) { struct cdp_delay_stats *dstats = NULL; @@ -9734,7 +9736,7 @@ void dp_update_delay_stats(struct dp_pdev *pdev, uint32_t delay, * Delay ranges are different for different delay modes * Get the correct index to update delay bucket */ - dstats = dp_fill_delay_buckets(pdev, delay, tid, mode); + dstats = dp_fill_delay_buckets(pdev, delay, tid, mode, ring_id); if (qdf_unlikely(!dstats)) return; diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index 9d9b5c7e9f..6e2fa97497 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -393,8 +393,9 @@ dp_rx_intrabss_fwd(struct dp_soc *soc, struct dp_ast_entry *ast_entry; qdf_nbuf_t nbuf_copy; uint8_t tid = qdf_nbuf_get_tid_val(nbuf); - struct cdp_tid_rx_stats *tid_stats = - &ta_peer->vdev->pdev->stats.tid_stats.tid_rx_stats[tid]; + uint8_t ring_id = QDF_NBUF_CB_RX_CTX_ID(nbuf); + struct cdp_tid_rx_stats *tid_stats = &ta_peer->vdev->pdev->stats. + tid_stats.tid_rx_stats[ring_id][tid]; /* check if the destination peer is available in peer table * and also check if the source peer and destination peer @@ -1078,6 +1079,7 @@ qdf_nbuf_t dp_rx_sg_create(qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr) */ void dp_rx_compute_delay(struct dp_vdev *vdev, qdf_nbuf_t nbuf) { + uint8_t ring_id = QDF_NBUF_CB_RX_CTX_ID(nbuf); int64_t current_ts = qdf_ktime_to_ms(qdf_ktime_get()); uint32_t to_stack = qdf_nbuf_get_timedelta_ms(nbuf); uint8_t tid = qdf_nbuf_get_tid_val(nbuf); @@ -1085,7 +1087,7 @@ void dp_rx_compute_delay(struct dp_vdev *vdev, qdf_nbuf_t nbuf) (uint32_t)(current_ts - vdev->prev_rx_deliver_tstamp); dp_update_delay_stats(vdev->pdev, to_stack, tid, - CDP_DELAY_STATS_REAP_STACK); + CDP_DELAY_STATS_REAP_STACK, ring_id); /* * Update interframe delay stats calculated at deliver_data_ol point. * Value of vdev->prev_rx_deliver_tstamp will be 0 for 1st frame, so @@ -1094,7 +1096,7 @@ void dp_rx_compute_delay(struct dp_vdev *vdev, qdf_nbuf_t nbuf) * of vdev->prev_rx_deliver_tstamp. */ dp_update_delay_stats(vdev->pdev, interframe_delay, tid, - CDP_DELAY_STATS_RX_INTERFRAME); + CDP_DELAY_STATS_RX_INTERFRAME, ring_id); vdev->prev_rx_deliver_tstamp = current_ts; } @@ -1109,15 +1111,16 @@ static inline int dp_rx_drop_nbuf_list(struct dp_pdev *pdev, qdf_nbuf_t buf_list) { struct cdp_tid_rx_stats *stats = NULL; - uint8_t tid = 0; + uint8_t tid = 0, ring_id = 0; int num_dropped = 0; qdf_nbuf_t buf, next_buf; buf = buf_list; while (buf) { + ring_id = QDF_NBUF_CB_RX_CTX_ID(buf); next_buf = qdf_nbuf_queue_next(buf); tid = qdf_nbuf_get_tid_val(buf); - stats = &pdev->stats.tid_stats.tid_rx_stats[tid]; + stats = &pdev->stats.tid_stats.tid_rx_stats[ring_id][tid]; stats->fail_cnt[INVALID_PEER_VDEV]++; stats->delivered_to_stack--; qdf_nbuf_free(buf); @@ -1816,7 +1819,8 @@ done: if (qdf_unlikely(rx_pdev->delay_stats_flag)) qdf_nbuf_set_timestamp(nbuf); - tid_stats = &rx_pdev->stats.tid_stats.tid_rx_stats[tid]; + tid_stats = &rx_pdev->stats.tid_stats. + tid_rx_stats[ring_id][tid]; if (qdf_unlikely(!hal_rx_attn_msdu_done_get(rx_tlv_hdr))) { dp_err("MSDU DONE failure"); DP_STATS_INC(soc, rx.err.msdu_done_fail, 1); diff --git a/dp/wifi3.0/dp_stats.c b/dp/wifi3.0/dp_stats.c index cbe1acc2ee..b7dfb03d4a 100644 --- a/dp/wifi3.0/dp_stats.c +++ b/dp/wifi3.0/dp_stats.c @@ -186,6 +186,9 @@ const char *intfrm_delay_bucket[CDP_DELAY_BUCKET_MAX + 1] = { #include "dp_tx_capture.h" #endif +#define TID_COUNTER_STATS 1 /* Success/drop stats type */ +#define TID_DELAY_STATS 2 /* Delay stats type */ + /* * dp_print_stats_string_tlv: display htt_stats_string_tlv * @tag_buf: buffer containing the tlv htt_stats_string_tlv @@ -4030,79 +4033,174 @@ static inline const char *dp_vow_str_intfrm_delay(uint8_t index) return intfrm_delay_bucket[index]; } +/** + * dp_accumulate_delay_stats() - Update delay stats members + * @total: Update stats total structure + * @per_ring: per ring structures from where stats need to be accumulated + * + * Return: void + */ +static void +dp_accumulate_delay_stats(struct cdp_delay_stats *total, + struct cdp_delay_stats *per_ring) +{ + uint8_t index; + + for (index = 0; index < CDP_DELAY_BUCKET_MAX; index++) + total->delay_bucket[index] += per_ring->delay_bucket[index]; + total->min_delay = QDF_MIN(total->min_delay, per_ring->min_delay); + total->max_delay = QDF_MAX(total->max_delay, per_ring->max_delay); + total->avg_delay = (total->avg_delay + per_ring->avg_delay) / 2; +} + +/** + * dp_accumulate_tid_stats() - Accumulate TID stats from each ring + * @pdev: pdev handle + * @tid: traffic ID + * @total_tx: fill this tx structure to get stats from all wbm rings + * @total_rx: fill this rx structure to get stats from all reo rings + * @type: delay stats or regular frame counters + * + * Return: void + */ +static void +dp_accumulate_tid_stats(struct dp_pdev *pdev, uint8_t tid, + struct cdp_tid_tx_stats *total_tx, + struct cdp_tid_rx_stats *total_rx, uint8_t type) +{ + uint8_t ring_id = 0, drop = 0; + struct cdp_tid_stats *tid_stats = &pdev->stats.tid_stats; + struct cdp_tid_tx_stats *per_ring_tx = NULL; + struct cdp_tid_rx_stats *per_ring_rx = NULL; + + if (wlan_cfg_get_dp_soc_nss_cfg(pdev->soc->wlan_cfg_ctx)) { + qdf_mem_copy(total_tx, &tid_stats->tid_tx_stats[0][tid], + sizeof(struct cdp_tid_tx_stats)); + qdf_mem_copy(total_rx, &tid_stats->tid_rx_stats[0][tid], + sizeof(struct cdp_tid_rx_stats)); + return; + } else { + qdf_mem_zero(total_tx, sizeof(struct cdp_tid_tx_stats)); + qdf_mem_zero(total_rx, sizeof(struct cdp_tid_rx_stats)); + } + + switch (type) { + case TID_COUNTER_STATS: + { + for (ring_id = 0; ring_id < CDP_MAX_TX_COMP_RINGS; ring_id++) { + per_ring_tx = &tid_stats->tid_tx_stats[ring_id][tid]; + total_tx->success_cnt += per_ring_tx->success_cnt; + total_tx->comp_fail_cnt += per_ring_tx->comp_fail_cnt; + for (drop = 0; drop < TX_MAX_DROP; drop++) + total_tx->swdrop_cnt[drop] += + per_ring_tx->swdrop_cnt[drop]; + } + for (ring_id = 0; ring_id < CDP_MAX_RX_RINGS; ring_id++) { + per_ring_rx = &tid_stats->tid_rx_stats[ring_id][tid]; + total_rx->delivered_to_stack += + per_ring_rx->delivered_to_stack; + total_rx->intrabss_cnt += per_ring_rx->intrabss_cnt; + total_rx->msdu_cnt += per_ring_rx->msdu_cnt; + total_rx->mcast_msdu_cnt += per_ring_rx->mcast_msdu_cnt; + total_rx->bcast_msdu_cnt += per_ring_rx->bcast_msdu_cnt; + for (drop = 0; drop < RX_MAX_DROP; drop++) + total_rx->fail_cnt[drop] += + per_ring_rx->fail_cnt[drop]; + } + break; + } + + case TID_DELAY_STATS: + { + for (ring_id = 0; ring_id < CDP_MAX_TX_COMP_RINGS; ring_id++) { + per_ring_tx = &tid_stats->tid_tx_stats[ring_id][tid]; + dp_accumulate_delay_stats(&total_tx->swq_delay, + &per_ring_tx->swq_delay); + dp_accumulate_delay_stats(&total_tx->hwtx_delay, + &per_ring_tx->hwtx_delay); + dp_accumulate_delay_stats(&total_tx->intfrm_delay, + &per_ring_tx->intfrm_delay); + } + for (ring_id = 0; ring_id < CDP_MAX_RX_RINGS; ring_id++) { + per_ring_rx = &tid_stats->tid_rx_stats[ring_id][tid]; + dp_accumulate_delay_stats(&total_rx->intfrm_delay, + &per_ring_rx->intfrm_delay); + dp_accumulate_delay_stats(&total_rx->to_stack_delay, + &per_ring_rx->to_stack_delay); + } + break; + } + + default: + qdf_err("Invalid stats type"); + break; + } +} + void dp_pdev_print_tid_stats(struct dp_pdev *pdev) { - struct cdp_tid_stats *tid_stats; - struct cdp_tid_tx_stats *txstats; - struct cdp_tid_rx_stats *rxstats; - struct dp_soc *soc = pdev->soc; + struct cdp_tid_tx_stats total_tx; + struct cdp_tid_rx_stats total_rx; uint8_t tid; - if (!soc) - return; - tid = 0; - rxstats = NULL; - txstats = NULL; - tid_stats = &pdev->stats.tid_stats; - DP_PRINT_STATS("Packets received in hardstart: %llu ", - tid_stats->ingress_stack); + pdev->stats.tid_stats.ingress_stack); DP_PRINT_STATS("Packets dropped in osif layer: %llu ", - tid_stats->osif_drop); + pdev->stats.tid_stats.osif_drop); DP_PRINT_STATS("Per TID Video Stats:\n"); for (tid = 0; tid < CDP_MAX_DATA_TIDS; tid++) { - txstats = &tid_stats->tid_tx_stats[tid]; - rxstats = &tid_stats->tid_rx_stats[tid]; + dp_accumulate_tid_stats(pdev, tid, &total_tx, &total_rx, + TID_COUNTER_STATS); DP_PRINT_STATS("----TID: %d----", tid); - DP_PRINT_STATS("Tx Success Count: %llu", txstats->success_cnt); - DP_PRINT_STATS("Tx Complete Count: %llu", - txstats->complete_cnt); + DP_PRINT_STATS("Tx Success Count: %llu", total_tx.success_cnt); DP_PRINT_STATS("Tx Firmware Drop Count: %llu", - txstats->comp_fail_cnt); + total_tx.comp_fail_cnt); DP_PRINT_STATS("Tx Hardware Drop Count: %llu", - txstats->swdrop_cnt[TX_HW_ENQUEUE]); + total_tx.swdrop_cnt[TX_HW_ENQUEUE]); DP_PRINT_STATS("Tx Software Drop Count: %llu", - txstats->swdrop_cnt[TX_SW_ENQUEUE]); + total_tx.swdrop_cnt[TX_SW_ENQUEUE]); DP_PRINT_STATS("Tx Descriptor Error Count: %llu", - txstats->swdrop_cnt[TX_DESC_ERR]); + total_tx.swdrop_cnt[TX_DESC_ERR]); DP_PRINT_STATS("Tx HAL Ring Error Count: %llu", - txstats->swdrop_cnt[TX_HAL_RING_ACCESS_ERR]); + total_tx.swdrop_cnt[TX_HAL_RING_ACCESS_ERR]); DP_PRINT_STATS("Tx Dma Map Error Count: %llu", - txstats->swdrop_cnt[TX_DMA_MAP_ERR]); + total_tx.swdrop_cnt[TX_DMA_MAP_ERR]); DP_PRINT_STATS("Rx Delievered Count: %llu", - rxstats->delivered_to_stack); + total_rx.delivered_to_stack); DP_PRINT_STATS("Rx Software Enqueue Drop Count: %llu", - rxstats->fail_cnt[ENQUEUE_DROP]); + total_rx.fail_cnt[ENQUEUE_DROP]); DP_PRINT_STATS("Rx Intrabss Drop Count: %llu", - rxstats->fail_cnt[INTRABSS_DROP]); + total_rx.fail_cnt[INTRABSS_DROP]); DP_PRINT_STATS("Rx Msdu Done Failure Count: %llu", - rxstats->fail_cnt[MSDU_DONE_FAILURE]); + total_rx.fail_cnt[MSDU_DONE_FAILURE]); DP_PRINT_STATS("Rx Invalid Peer Count: %llu", - rxstats->fail_cnt[INVALID_PEER_VDEV]); + total_rx.fail_cnt[INVALID_PEER_VDEV]); DP_PRINT_STATS("Rx Policy Check Drop Count: %llu", - rxstats->fail_cnt[POLICY_CHECK_DROP]); + total_rx.fail_cnt[POLICY_CHECK_DROP]); DP_PRINT_STATS("Rx Mec Drop Count: %llu", - rxstats->fail_cnt[MEC_DROP]); + total_rx.fail_cnt[MEC_DROP]); DP_PRINT_STATS("Rx Nawds Mcast Drop Count: %llu", - rxstats->fail_cnt[NAWDS_MCAST_DROP]); + total_rx.fail_cnt[NAWDS_MCAST_DROP]); DP_PRINT_STATS("Rx Mesh Filter Drop Count: %llu", - rxstats->fail_cnt[MESH_FILTER_DROP]); + total_rx.fail_cnt[MESH_FILTER_DROP]); DP_PRINT_STATS("Rx Intra Bss Deliver Count: %llu", - rxstats->intrabss_cnt); - DP_PRINT_STATS("Rx MSDU Count: %llu", rxstats->msdu_cnt); + total_rx.intrabss_cnt); + DP_PRINT_STATS("Rx MSDU Count: %llu", total_rx.msdu_cnt); DP_PRINT_STATS("Rx Multicast MSDU Count: %llu", - rxstats->mcast_msdu_cnt); + total_rx.mcast_msdu_cnt); DP_PRINT_STATS("Rx Broadcast MSDU Count: %llu\n", - rxstats->bcast_msdu_cnt); + total_rx.bcast_msdu_cnt); } } void dp_pdev_print_delay_stats(struct dp_pdev *pdev) { struct dp_soc *soc = pdev->soc; - struct cdp_tid_tx_stats *txstats = NULL; - struct cdp_tid_rx_stats *rxstats; + struct cdp_tid_tx_stats total_tx; + struct cdp_tid_rx_stats total_rx; + struct cdp_tid_stats *tid_stats; + uint8_t tid, index; uint64_t count = 0; @@ -4111,17 +4209,17 @@ void dp_pdev_print_delay_stats(struct dp_pdev *pdev) tid = 0; index = 0; - rxstats = NULL; + tid_stats = &pdev->stats.tid_stats; DP_PRINT_STATS("Per TID Delay Non-Zero Stats:\n"); for (tid = 0; tid < CDP_MAX_DATA_TIDS; tid++) { + dp_accumulate_tid_stats(pdev, tid, &total_tx, &total_rx, + TID_DELAY_STATS); DP_PRINT_STATS("----TID: %d----", tid); - txstats = &pdev->stats.tid_stats.tid_tx_stats[tid]; - rxstats = &pdev->stats.tid_stats.tid_rx_stats[tid]; DP_PRINT_STATS("Software Enqueue Delay:"); for (index = 0; index < CDP_DELAY_BUCKET_MAX; index++) { - count = txstats->swq_delay.delay_bucket[index]; + count = total_tx.swq_delay.delay_bucket[index]; if (count) { DP_PRINT_STATS("%s: Packets = %llu", dp_vow_str_sw_enq_delay(index), @@ -4129,52 +4227,52 @@ void dp_pdev_print_delay_stats(struct dp_pdev *pdev) } } - DP_PRINT_STATS("Min = %u", txstats->swq_delay.min_delay); - DP_PRINT_STATS("Max = %u", txstats->swq_delay.max_delay); - DP_PRINT_STATS("Avg = %u\n", txstats->swq_delay.avg_delay); + DP_PRINT_STATS("Min = %u", total_tx.swq_delay.min_delay); + DP_PRINT_STATS("Max = %u", total_tx.swq_delay.max_delay); + DP_PRINT_STATS("Avg = %u\n", total_tx.swq_delay.avg_delay); DP_PRINT_STATS("Hardware Transmission Delay:"); for (index = 0; index < CDP_DELAY_BUCKET_MAX; index++) { - count = txstats->hwtx_delay.delay_bucket[index]; + count = total_tx.hwtx_delay.delay_bucket[index]; if (count) { DP_PRINT_STATS("%s: Packets = %llu", dp_vow_str_fw_to_hw_delay(index), count); } } - DP_PRINT_STATS("Min = %u", txstats->hwtx_delay.min_delay); - DP_PRINT_STATS("Max = %u", txstats->hwtx_delay.max_delay); - DP_PRINT_STATS("Avg = %u\n", txstats->hwtx_delay.avg_delay); + DP_PRINT_STATS("Min = %u", total_tx.hwtx_delay.min_delay); + DP_PRINT_STATS("Max = %u", total_tx.hwtx_delay.max_delay); + DP_PRINT_STATS("Avg = %u\n", total_tx.hwtx_delay.avg_delay); DP_PRINT_STATS("Tx Interframe Delay:"); for (index = 0; index < CDP_DELAY_BUCKET_MAX; index++) { - count = txstats->intfrm_delay.delay_bucket[index]; + count = total_tx.intfrm_delay.delay_bucket[index]; if (count) { DP_PRINT_STATS("%s: Packets = %llu", dp_vow_str_intfrm_delay(index), count); } } - DP_PRINT_STATS("Min = %u", txstats->intfrm_delay.min_delay); - DP_PRINT_STATS("Max = %u", txstats->intfrm_delay.max_delay); - DP_PRINT_STATS("Avg = %u\n", txstats->intfrm_delay.avg_delay); + DP_PRINT_STATS("Min = %u", total_tx.intfrm_delay.min_delay); + DP_PRINT_STATS("Max = %u", total_tx.intfrm_delay.max_delay); + DP_PRINT_STATS("Avg = %u\n", total_tx.intfrm_delay.avg_delay); DP_PRINT_STATS("Rx Interframe Delay:"); for (index = 0; index < CDP_DELAY_BUCKET_MAX; index++) { - count = rxstats->intfrm_delay.delay_bucket[index]; + count = total_rx.intfrm_delay.delay_bucket[index]; if (count) { DP_PRINT_STATS("%s: Packets = %llu", dp_vow_str_intfrm_delay(index), count); } } - DP_PRINT_STATS("Min = %u", rxstats->intfrm_delay.min_delay); - DP_PRINT_STATS("Max = %u", rxstats->intfrm_delay.max_delay); - DP_PRINT_STATS("Avg = %u\n", rxstats->intfrm_delay.avg_delay); + DP_PRINT_STATS("Min = %u", total_rx.intfrm_delay.min_delay); + DP_PRINT_STATS("Max = %u", total_rx.intfrm_delay.max_delay); + DP_PRINT_STATS("Avg = %u\n", total_rx.intfrm_delay.avg_delay); DP_PRINT_STATS("Rx Reap to Stack Delay:"); for (index = 0; index < CDP_DELAY_BUCKET_MAX; index++) { - count = rxstats->to_stack_delay.delay_bucket[index]; + count = total_rx.to_stack_delay.delay_bucket[index]; if (count) { DP_PRINT_STATS("%s: Packets = %llu", dp_vow_str_intfrm_delay(index), @@ -4182,9 +4280,9 @@ void dp_pdev_print_delay_stats(struct dp_pdev *pdev) } } - DP_PRINT_STATS("Min = %u", rxstats->to_stack_delay.min_delay); - DP_PRINT_STATS("Max = %u", rxstats->to_stack_delay.max_delay); - DP_PRINT_STATS("Avg = %u\n", rxstats->to_stack_delay.avg_delay); + DP_PRINT_STATS("Min = %u", total_rx.to_stack_delay.min_delay); + DP_PRINT_STATS("Max = %u", total_rx.to_stack_delay.max_delay); + DP_PRINT_STATS("Avg = %u\n", total_rx.to_stack_delay.avg_delay); } } #endif diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index 68edd1b578..7e1f09e56c 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/dp/wifi3.0/dp_tx.c @@ -1455,7 +1455,8 @@ static qdf_nbuf_t dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf, dp_err_rl("Tx_desc prepare Fail vdev %pK queue %d", vdev, tx_q->desc_pool_id); dp_tx_get_tid(vdev, nbuf, msdu_info); - tid_stats = &pdev->stats.tid_stats.tid_tx_stats[msdu_info->tid]; + tid_stats = &pdev->stats.tid_stats. + tid_tx_stats[tx_q->ring_id][msdu_info->tid]; tid_stats->swdrop_cnt[TX_DESC_ERR]++; return nbuf; } @@ -1475,7 +1476,8 @@ static qdf_nbuf_t dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf, "%s %d : HAL RING Access Failed -- %pK", __func__, __LINE__, hal_srng); dp_tx_get_tid(vdev, nbuf, msdu_info); - tid_stats = &pdev->stats.tid_stats.tid_tx_stats[msdu_info->tid]; + tid_stats = &pdev->stats.tid_stats. + tid_tx_stats[tx_q->ring_id][tid]; tid_stats->swdrop_cnt[TX_HAL_RING_ACCESS_ERR]++; DP_STATS_INC(vdev, tx_i.dropped.ring_full, 1); dp_tx_desc_release(tx_desc, tx_q->desc_pool_id); @@ -1508,7 +1510,8 @@ static qdf_nbuf_t dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf, "%s Tx_hw_enqueue Fail tx_desc %pK queue %d", __func__, tx_desc, tx_q->ring_id); dp_tx_get_tid(vdev, nbuf, msdu_info); - tid_stats = &pdev->stats.tid_stats.tid_tx_stats[msdu_info->tid]; + tid_stats = &pdev->stats.tid_stats. + tid_tx_stats[tx_q->ring_id][tid]; tid_stats->swdrop_cnt[TX_HW_ENQUEUE]++; dp_tx_desc_release(tx_desc, tx_q->desc_pool_id); qdf_nbuf_unmap(vdev->osdev, nbuf, QDF_DMA_TO_DEVICE); @@ -1564,7 +1567,8 @@ qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf, "%s %d : HAL RING Access Failed -- %pK", __func__, __LINE__, hal_srng); dp_tx_get_tid(vdev, nbuf, msdu_info); - tid_stats = &pdev->stats.tid_stats.tid_tx_stats[msdu_info->tid]; + tid_stats = &pdev->stats.tid_stats. + tid_tx_stats[tx_q->ring_id][msdu_info->tid]; tid_stats->swdrop_cnt[TX_HAL_RING_ACCESS_ERR]++; DP_STATS_INC(vdev, tx_i.dropped.ring_full, 1); return nbuf; @@ -1631,7 +1635,7 @@ qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf, dp_tx_get_tid(vdev, nbuf, msdu_info); tid_stats = &pdev->stats.tid_stats. - tid_tx_stats[msdu_info->tid]; + tid_tx_stats[tx_q->ring_id][msdu_info->tid]; tid_stats->swdrop_cnt[TX_HW_ENQUEUE]++; if (tx_desc->flags & DP_TX_DESC_FLAG_ME) dp_tx_me_free_buf(pdev, tx_desc->me_buffer); @@ -2665,10 +2669,12 @@ void dp_tx_comp_fill_tx_completion_stats(struct dp_tx_desc_s *tx_desc, * @vdev: pdev handle * @tx_desc: tx descriptor * @tid: tid value + * @ring_id: TCL or WBM ring number for transmit path * Return: none */ static void dp_tx_compute_delay(struct dp_vdev *vdev, - struct dp_tx_desc_s *tx_desc, uint8_t tid) + struct dp_tx_desc_s *tx_desc, + uint8_t tid, uint8_t ring_id) { int64_t current_timestamp, timestamp_ingress, timestamp_hw_enqueue; uint32_t sw_enqueue_delay, fwhw_transmit_delay, interframe_delay; @@ -2689,12 +2695,12 @@ static void dp_tx_compute_delay(struct dp_vdev *vdev, * Delay in software enqueue */ dp_update_delay_stats(vdev->pdev, sw_enqueue_delay, tid, - CDP_DELAY_STATS_SW_ENQ); + CDP_DELAY_STATS_SW_ENQ, ring_id); /* * Delay between packet enqueued to HW and Tx completion */ dp_update_delay_stats(vdev->pdev, fwhw_transmit_delay, tid, - CDP_DELAY_STATS_FW_HW_TRANSMIT); + CDP_DELAY_STATS_FW_HW_TRANSMIT, ring_id); /* * Update interframe delay stats calculated at hardstart receive point. @@ -2704,22 +2710,25 @@ static void dp_tx_compute_delay(struct dp_vdev *vdev, * of !vdev->prev_tx_enq_tstamp. */ dp_update_delay_stats(vdev->pdev, interframe_delay, tid, - CDP_DELAY_STATS_TX_INTERFRAME); + CDP_DELAY_STATS_TX_INTERFRAME, ring_id); vdev->prev_tx_enq_tstamp = timestamp_ingress; } /** * dp_tx_update_peer_stats() - Update peer stats from Tx completion indications + * per wbm ring + * * @tx_desc: software descriptor head pointer * @ts: Tx completion status * @peer: peer handle + * @ring_id: ring number * * Return: None */ static inline void dp_tx_update_peer_stats(struct dp_tx_desc_s *tx_desc, struct hal_tx_completion_status *ts, - struct dp_peer *peer) + struct dp_peer *peer, uint8_t ring_id) { struct dp_pdev *pdev = peer->vdev->pdev; struct dp_soc *soc = NULL; @@ -2734,7 +2743,7 @@ dp_tx_update_peer_stats(struct dp_tx_desc_s *tx_desc, if (qdf_unlikely(tid >= CDP_MAX_DATA_TIDS)) tid = CDP_MAX_DATA_TIDS - 1; - tid_stats = &pdev->stats.tid_stats.tid_tx_stats[tid]; + tid_stats = &pdev->stats.tid_stats.tid_tx_stats[ring_id][tid]; soc = pdev->soc; mcs = ts->mcs; @@ -2749,8 +2758,7 @@ dp_tx_update_peer_stats(struct dp_tx_desc_s *tx_desc, DP_STATS_INC_PKT(peer, tx.comp_pkt, 1, length); if (qdf_unlikely(pdev->delay_stats_flag)) - dp_tx_compute_delay(peer->vdev, tx_desc, tid); - tid_stats->complete_cnt++; + dp_tx_compute_delay(peer->vdev, tx_desc, tid, ring_id); DP_STATS_INCC(peer, tx.dropped.age_out, 1, (ts->status == HAL_TX_TQM_RR_REM_CMD_AGED)); @@ -3023,13 +3031,14 @@ dp_tx_comp_process_desc(struct dp_soc *soc, * @tx_desc: software descriptor head pointer * @ts: Tx completion status * @peer: peer handle + * @ring_id: ring number * * Return: none */ static inline void dp_tx_comp_process_tx_status(struct dp_tx_desc_s *tx_desc, struct hal_tx_completion_status *ts, - struct dp_peer *peer) + struct dp_peer *peer, uint8_t ring_id) { uint32_t length; qdf_ether_header_t *eh; @@ -3119,7 +3128,7 @@ void dp_tx_comp_process_tx_status(struct dp_tx_desc_s *tx_desc, } } - dp_tx_update_peer_stats(tx_desc, ts, peer); + dp_tx_update_peer_stats(tx_desc, ts, peer, ring_id); #ifdef QCA_SUPPORT_RDK_STATS if (soc->wlanstats_enabled) @@ -3135,6 +3144,7 @@ out: * dp_tx_comp_process_desc_list() - Tx complete software descriptor handler * @soc: core txrx main context * @comp_head: software descriptor head pointer + * @ring_id: ring number * * This function will process batch of descriptors reaped by dp_tx_comp_handler * and release the software descriptors after processing is complete @@ -3143,7 +3153,7 @@ out: */ static void dp_tx_comp_process_desc_list(struct dp_soc *soc, - struct dp_tx_desc_s *comp_head) + struct dp_tx_desc_s *comp_head, uint8_t ring_id) { struct dp_tx_desc_s *desc; struct dp_tx_desc_s *next; @@ -3156,7 +3166,7 @@ dp_tx_comp_process_desc_list(struct dp_soc *soc, while (desc) { hal_tx_comp_get_status(&desc->comp, &ts, soc->hal_soc); peer = dp_peer_find_by_id(soc, ts.peer_id); - dp_tx_comp_process_tx_status(desc, &ts, peer); + dp_tx_comp_process_tx_status(desc, &ts, peer, ring_id); netbuf = desc->nbuf; /* check tx complete notification */ @@ -3180,13 +3190,15 @@ dp_tx_comp_process_desc_list(struct dp_soc *soc, * dp_tx_process_htt_completion() - Tx HTT Completion Indication Handler * @tx_desc: software descriptor head pointer * @status : Tx completion status from HTT descriptor + * @ring_id: ring number * * This function will process HTT Tx indication messages from Target * * Return: none */ static -void dp_tx_process_htt_completion(struct dp_tx_desc_s *tx_desc, uint8_t *status) +void dp_tx_process_htt_completion(struct dp_tx_desc_s *tx_desc, uint8_t *status, + uint8_t ring_id) { uint8_t tx_status; struct dp_pdev *pdev; @@ -3238,11 +3250,10 @@ void dp_tx_process_htt_completion(struct dp_tx_desc_s *tx_desc, uint8_t *status) if (qdf_unlikely(tid >= CDP_MAX_DATA_TIDS)) tid = CDP_MAX_DATA_TIDS - 1; - tid_stats = &pdev->stats.tid_stats.tid_tx_stats[tid]; + tid_stats = &pdev->stats.tid_stats.tid_tx_stats[ring_id][tid]; if (qdf_unlikely(pdev->delay_stats_flag)) - dp_tx_compute_delay(vdev, tx_desc, tid); - tid_stats->complete_cnt++; + dp_tx_compute_delay(vdev, tx_desc, tid, ring_id); if (qdf_unlikely(tx_status != HTT_TX_FW2WBM_TX_STATUS_OK)) { ts.status = HAL_TX_TQM_RR_REM_CMD_REM; tid_stats->comp_fail_cnt++; @@ -3255,7 +3266,7 @@ void dp_tx_process_htt_completion(struct dp_tx_desc_s *tx_desc, uint8_t *status) if (qdf_likely(peer)) dp_peer_unref_del_find_by_id(peer); - dp_tx_comp_process_tx_status(tx_desc, &ts, peer); + dp_tx_comp_process_tx_status(tx_desc, &ts, peer, ring_id); dp_tx_comp_process_desc(soc, tx_desc, &ts, peer); dp_tx_desc_release(tx_desc, tx_desc->pool_id); @@ -3318,7 +3329,7 @@ static inline bool dp_tx_comp_enable_eol_data_check(struct dp_soc *soc) #endif uint32_t dp_tx_comp_handler(struct dp_intr *int_ctx, struct dp_soc *soc, - void *hal_srng, uint32_t quota) + void *hal_srng, uint8_t ring_id, uint32_t quota) { void *tx_comp_hal_desc; uint8_t buffer_src; @@ -3400,7 +3411,7 @@ more_data: hal_tx_comp_get_htt_desc(tx_comp_hal_desc, htt_tx_status); dp_tx_process_htt_completion(tx_desc, - htt_tx_status); + htt_tx_status, ring_id); } else { /* Pool id is not matching. Error */ if (tx_desc->pool_id != pool_id) { @@ -3460,7 +3471,7 @@ more_data: /* Process the reaped descriptors */ if (head_desc) - dp_tx_comp_process_desc_list(soc, head_desc); + dp_tx_comp_process_desc_list(soc, head_desc, ring_id); if (dp_tx_comp_enable_eol_data_check(soc)) { if (!force_break && diff --git a/dp/wifi3.0/dp_tx.h b/dp/wifi3.0/dp_tx.h index c449ead9d2..92e5ccde99 100644 --- a/dp/wifi3.0/dp_tx.h +++ b/dp/wifi3.0/dp_tx.h @@ -185,6 +185,7 @@ qdf_nbuf_t dp_tx_non_std(struct cdp_vdev *vdev_handle, * dp_tx_comp_handler() - Tx completion handler * @int_ctx: pointer to DP interrupt context * @soc: core txrx main context + * @hal_srng: Opaque HAL SRNG pointer * @ring_id: completion ring id * @quota: No. of packets/descriptors that can be serviced in one loop * @@ -195,7 +196,7 @@ qdf_nbuf_t dp_tx_non_std(struct cdp_vdev *vdev_handle, * Return: Number of TX completions processed */ uint32_t dp_tx_comp_handler(struct dp_intr *int_ctx, struct dp_soc *soc, - void *hal_srng, uint32_t quota); + void *hal_srng, uint8_t ring_id, uint32_t quota); QDF_STATUS dp_tx_prepare_send_me(struct dp_vdev *vdev, qdf_nbuf_t nbuf);