diff --git a/dp/inc/cdp_txrx_cmn_struct.h b/dp/inc/cdp_txrx_cmn_struct.h index ff14d2904a..975e4ebfab 100644 --- a/dp/inc/cdp_txrx_cmn_struct.h +++ b/dp/inc/cdp_txrx_cmn_struct.h @@ -820,6 +820,8 @@ struct cdp_soc_t { * @CDP_CONFIG_IGMPMLD_TID: Configurable TID value when igmmld_override is set * @CDP_CONFIG_ARP_DBG_CONF: Enable ARP debug * @CDP_CONFIG_CAPTURE_LATENCY: Capture time latency + * @CDP_INGRESS_STATS: Accumulate ingress statistics + * @CDP_OSIF_DROP: Accumulate drops in OSIF layer */ enum cdp_pdev_param_type { CDP_CONFIG_DEBUG_SNIFFER, @@ -830,6 +832,8 @@ enum cdp_pdev_param_type { CDP_CONFIG_IGMPMLD_TID, CDP_CONFIG_ARP_DBG_CONF, CDP_CONFIG_CAPTURE_LATENCY, + CDP_INGRESS_STATS, + CDP_OSIF_DROP, }; /* diff --git a/dp/inc/cdp_txrx_stats_struct.h b/dp/inc/cdp_txrx_stats_struct.h index 51a4e580c9..bfcf219c06 100644 --- a/dp/inc/cdp_txrx_stats_struct.h +++ b/dp/inc/cdp_txrx_stats_struct.h @@ -106,6 +106,7 @@ * HTT_PPDU_STATS_MAX_TAG declared in FW */ #define CDP_PPDU_STATS_MAX_TAG 14 +#define CDP_MAX_DATA_TIDS 9 #ifdef CONFIG_MCL #define CDP_WDI_NUM_EVENTS WDI_NUM_EVENTS @@ -164,6 +165,141 @@ struct cdp_tidq_stats { uint32_t stats[TIDQ_STATS_MAX]; }; +/* + * cdp_delay_stats_mode: Different types of delay statistics + * + * @CDP_DELAY_STATS_SW_ENQ: Stack to hw enqueue delay + * @CDP_DELAY_STATS_INTERFRAME: Interframe delay at radio entry point + * @CDP_DELAY_STATS_FW_HW_TRANSMIT: Hw enqueue to tx completion delay + * @CDP_DELAY_STATS_REAP_STACK: Delay in ring reap to indicating network stack + * @CDP_DELAY_STATS_RX_INTERFRAME: Rx inteframe delay + * @CDP_DELAY_STATS_MODE_MAX: Maximum delay mode + */ +enum cdp_delay_stats_mode { + CDP_DELAY_STATS_SW_ENQ, + CDP_DELAY_STATS_INTERFRAME, + CDP_DELAY_STATS_FW_HW_TRANSMIT, + CDP_DELAY_STATS_REAP_STACK, + CDP_DELAY_STATS_RX_INTERFRAME, + CDP_DELAY_STATS_MODE_MAX, +}; + +/* + * cdp_delay_bucket_index + * Index to be used for all delay stats + */ +enum cdp_delay_bucket_index { + CDP_DELAY_BUCKET_1, + CDP_DELAY_BUCKET_2, + CDP_DELAY_BUCKET_3, + CDP_DELAY_BUCKET_4, + CDP_DELAY_BUCKET_5, + CDP_DELAY_BUCKET_6, + CDP_DELAY_BUCKET_7, + CDP_DELAY_BUCKET_8, + CDP_DELAY_BUCKET_9, + CDP_DELAY_BUCKET_10, + CDP_DELAY_BUCKET_11, + CDP_DELAY_BUCKET_12, + CDP_DELAY_BUCKET_MAX, +}; + +/* + * struct cdp_tx_host_drop - packet drop due to following reasons. + */ +enum cdp_tx_sw_drop { + TX_DESC_ERR, + TX_HAL_RING_ACCESS_ERR, + TX_DMA_MAP_ERR, + TX_HW_ENQUEUE, + TX_SW_ENQUEUE, + TX_MAX_DROP, +}; + +/* + * struct cdp_rx_host_drop - packet drop due to following reasons. + */ +enum cdp_rx_sw_drop { + INTRABSS_DROP, + MSDU_DONE_FAILURE, + INVALID_PEER_VDEV, + POLICY_CHECK_DROP, + MEC_DROP, + NAWDS_MCAST_DROP, + MESH_FILTER_DROP, + ENQUEUE_DROP, + RX_MAX_DROP, +}; + +/* + * struct cdp_delay_stats + * @delay_bucket: division of buckets as per latency + * @min_delay: minimum delay + * @max_delay: maximum delay + * @avg_delay: average delay + */ +struct cdp_delay_stats { + uint64_t delay_bucket[CDP_DELAY_BUCKET_MAX]; + uint32_t min_delay; + uint32_t max_delay; + uint32_t avg_delay; +}; + +/* + * struct cdp_tid_tx_stats + * @swq_delay: delay between wifi driver entry point and enqueue to HW in tx + * @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 + * @swdrop_cnt: software drop in tx path + */ +struct cdp_tid_tx_stats { + struct cdp_delay_stats swq_delay; + 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]; +}; + +/* + * struct cdp_tid_tx_stats + * @to_stack_delay: Time taken between ring reap to indication to network stack + * @intfrm_delay: Interframe rx delay + * @delivered_cnt: Total packets indicated to stack + * @intrabss_cnt: Rx total intraBSS frames + * @msdu_cnt: number of msdu received from HW + * @mcast_msdu_cnt: Num Mcast Msdus received from HW in Rx + * @bcast_msdu_cnt: Num Bcast Msdus received from HW in Rx + * @fail_cnt: Rx deliver drop counters + */ +struct cdp_tid_rx_stats { + struct cdp_delay_stats to_stack_delay; + struct cdp_delay_stats intfrm_delay; + uint64_t delivered_to_stack; + uint64_t intrabss_cnt; + uint64_t msdu_cnt; + uint64_t mcast_msdu_cnt; + uint64_t bcast_msdu_cnt; + uint64_t fail_cnt[RX_MAX_DROP]; +}; + +/* + * struct cdp_tid_stats + * @ingress_stack: Total packets received from linux stack + * @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_pkt_info - packet info * @num: no of packets * @bytes: total no of bytes @@ -1065,6 +1201,7 @@ struct cdp_pdev_stats { /* Received wdi messages from fw */ uint32_t wdi_event[CDP_WDI_NUM_EVENTS]; + struct cdp_tid_stats tid_stats; }; #ifndef BIG_ENDIAN_HOST diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 9e2af36acb..81264ed100 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -7760,6 +7760,36 @@ dp_set_bpr_enable(struct cdp_pdev *pdev_handle, int val) return QDF_STATUS_SUCCESS; } +/* + * dp_pdev_tid_stats_ingress_inc + * @pdev: pdev handle + * @val: increase in value + * + * Return: void + */ +static void +dp_pdev_tid_stats_ingress_inc(struct cdp_pdev *pdev, uint32_t val) +{ + struct dp_pdev *dp_pdev = (struct dp_pdev *)pdev; + + dp_pdev->stats.tid_stats.ingress_stack += val; +} + +/* + * dp_pdev_tid_stats_osif_drop + * @pdev: pdev handle + * @val: increase in value + * + * Return: void + */ +static void +dp_pdev_tid_stats_osif_drop(struct cdp_pdev *pdev, uint32_t val) +{ + struct dp_pdev *dp_pdev = (struct dp_pdev *)pdev; + + dp_pdev->stats.tid_stats.osif_drop += val; +} + /* * dp_config_debug_sniffer()- API to enable/disable debug sniffer * @pdev_handle: DP_PDEV handle @@ -8006,6 +8036,12 @@ static QDF_STATUS dp_set_pdev_param(struct cdp_pdev *pdev_handle, else pdev->latency_capture_enable = false; break; + case CDP_INGRESS_STATS: + dp_pdev_tid_stats_ingress_inc(pdev_handle, val); + break; + case CDP_OSIF_DROP: + dp_pdev_tid_stats_osif_drop(pdev_handle, val); + break; default: return QDF_STATUS_E_INVAL; } diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index 449975fc8c..5fb2919165 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -428,6 +428,9 @@ dp_rx_intrabss_fwd(struct dp_soc *soc, struct dp_peer *da_peer; struct dp_ast_entry *ast_entry; qdf_nbuf_t nbuf_copy; + uint8_t tid = qdf_nbuf_get_priority(nbuf); + struct cdp_tid_rx_stats *tid_stats = + &ta_peer->vdev->pdev->stats.tid_stats.tid_rx_stats[tid]; /* check if the destination peer is available in peer table * and also check if the source peer and destination peer @@ -480,6 +483,7 @@ dp_rx_intrabss_fwd(struct dp_soc *soc, * failed and we want to continue with * next nbuf. */ + tid_stats->fail_cnt[INTRABSS_DROP]++; return true; } } @@ -490,7 +494,8 @@ dp_rx_intrabss_fwd(struct dp_soc *soc, return true; } else { DP_STATS_INC_PKT(ta_peer, rx.intra_bss.fail, 1, - len); + len); + tid_stats->fail_cnt[INTRABSS_DROP]++; return false; } } @@ -513,9 +518,11 @@ dp_rx_intrabss_fwd(struct dp_soc *soc, if (dp_tx_send(ta_peer->vdev, nbuf_copy)) { DP_STATS_INC_PKT(ta_peer, rx.intra_bss.fail, 1, len); + tid_stats->fail_cnt[INTRABSS_DROP]++; qdf_nbuf_free(nbuf_copy); } else { DP_STATS_INC_PKT(ta_peer, rx.intra_bss.pkts, 1, len); + tid_stats->intrabss_cnt++; } } /* return false as we have to still send the original pkt @@ -1094,6 +1101,8 @@ static inline void dp_rx_deliver_to_stack(struct dp_vdev *vdev, qdf_nbuf_t nbuf_head, qdf_nbuf_t nbuf_tail) { + struct cdp_tid_rx_stats *stats = NULL; + uint8_t tid = 0; /* * highly unlikely to have a vdev without a registered rx * callback function. if so let us free the nbuf_list. @@ -1103,6 +1112,10 @@ static inline void dp_rx_deliver_to_stack(struct dp_vdev *vdev, do { nbuf = nbuf_head; nbuf_head = nbuf_head->next; + tid = qdf_nbuf_get_priority(nbuf); + stats = &vdev->pdev->stats.tid_stats.tid_rx_stats[tid]; + stats->fail_cnt[INVALID_PEER_VDEV]++; + stats->delivered_to_stack--; qdf_nbuf_free(nbuf); } while (nbuf_head); @@ -1401,6 +1414,7 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, uint32_t rx_bufs_reaped[MAX_PDEV_CNT] = { 0 }; uint8_t mac_id = 0; struct dp_pdev *pdev; + struct dp_pdev *rx_pdev; struct dp_srng *dp_rxdma_srng; struct rx_desc_pool *rx_desc_pool; struct dp_soc *soc = int_ctx->soc; @@ -1412,6 +1426,7 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, qdf_nbuf_t deliver_list_tail = NULL; int32_t tid = 0; uint32_t dst_num_valid = 0; + struct cdp_tid_rx_stats *tid_stats; DP_HIST_INIT(); /* Debug -- Remove later */ @@ -1593,19 +1608,34 @@ done: while (nbuf) { next = nbuf->next; rx_tlv_hdr = qdf_nbuf_data(nbuf); + /* Get TID from first msdu per MPDU, save to skb->priority */ + if (qdf_nbuf_is_rx_chfrag_start(nbuf)) + tid = hal_rx_mpdu_start_tid_get(soc->hal_soc, + rx_tlv_hdr); + DP_RX_TID_SAVE(nbuf, tid); /* * Check if DMA completed -- msdu_done is the last bit * to be written */ + rx_pdev = soc->pdev_list[rx_desc->pool_id]; + tid_stats = &rx_pdev->stats.tid_stats.tid_rx_stats[tid]; if (qdf_unlikely(!hal_rx_attn_msdu_done_get(rx_tlv_hdr))) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - FL("MSDU DONE failure")); + FL("MSDU DONE failure")); hal_rx_dump_pkt_tlvs(hal_soc, rx_tlv_hdr, - QDF_TRACE_LEVEL_INFO); + QDF_TRACE_LEVEL_INFO); + tid_stats->fail_cnt[MSDU_DONE_FAILURE]++; qdf_assert(0); } + tid_stats->msdu_cnt++; + if (qdf_unlikely(hal_rx_msdu_end_da_is_mcbc_get(rx_tlv_hdr))) { + tid_stats->mcast_msdu_cnt++; + if (qdf_nbuf_is_bcast_pkt(nbuf)) + tid_stats->bcast_msdu_cnt++; + } + peer_mdata = hal_rx_mpdu_peer_meta_data_get(rx_tlv_hdr); peer_id = DP_PEER_METADATA_PEER_ID_GET(peer_mdata); peer = dp_peer_find_by_id(soc, peer_id); @@ -1632,12 +1662,14 @@ done: } else { DP_STATS_INC_PKT(soc, rx.err.rx_invalid_peer, 1, qdf_nbuf_len(nbuf)); + tid_stats->fail_cnt[INVALID_PEER_VDEV]++; qdf_nbuf_free(nbuf); nbuf = next; continue; } if (qdf_unlikely(vdev == NULL)) { + tid_stats->fail_cnt[INVALID_PEER_VDEV]++; qdf_nbuf_free(nbuf); nbuf = next; DP_STATS_INC(soc, rx.err.invalid_vdev, 1); @@ -1701,6 +1733,7 @@ done: QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("Policy Check Drop pkt")); + tid_stats->fail_cnt[POLICY_CHECK_DROP]++; /* Drop & free packet */ qdf_nbuf_free(nbuf); /* Statistics */ @@ -1713,6 +1746,7 @@ done: QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("received pkt with same src MAC")); + tid_stats->fail_cnt[MEC_DROP]++; DP_STATS_INC_PKT(peer, rx.mec_drop, 1, msdu_len); /* Drop & free packet */ @@ -1726,6 +1760,7 @@ done: if (qdf_unlikely(peer && (peer->nawds_enabled == true) && (hal_rx_msdu_end_da_is_mcbc_get(rx_tlv_hdr)) && (hal_rx_get_mpdu_mac_ad4_valid(rx_tlv_hdr) == false))) { + tid_stats->fail_cnt[NAWDS_MCAST_DROP]++; DP_STATS_INC(peer, rx.nawds_mcast_drop, 1); qdf_nbuf_free(nbuf); nbuf = next; @@ -1750,14 +1785,14 @@ done: dp_rx_msdu_stats_update(soc, nbuf, rx_tlv_hdr, peer, ring_id); if (qdf_unlikely(vdev->mesh_vdev)) { - if (dp_rx_filter_mesh_packets(vdev, nbuf, - rx_tlv_hdr) + if (dp_rx_filter_mesh_packets(vdev, nbuf, rx_tlv_hdr) == QDF_STATUS_SUCCESS) { QDF_TRACE(QDF_MODULE_ID_DP, - QDF_TRACE_LEVEL_INFO_MED, - FL("mesh pkt filtered")); - DP_STATS_INC(vdev->pdev, dropped.mesh_filter, - 1); + QDF_TRACE_LEVEL_INFO_MED, + FL("mesh pkt filtered")); + tid_stats->fail_cnt[MESH_FILTER_DROP]++; + DP_STATS_INC(vdev->pdev, dropped.mesh_filter, + 1); qdf_nbuf_free(nbuf); nbuf = next; @@ -1812,6 +1847,7 @@ done: nbuf)) { nbuf = next; dp_peer_unref_del_find_by_id(peer); + tid_stats->intrabss_cnt++; continue; /* Get next desc */ } } @@ -1819,18 +1855,13 @@ done: dp_rx_fill_gro_info(soc, rx_tlv_hdr, nbuf); qdf_nbuf_cb_update_peer_local_id(nbuf, peer->local_id); - /* Get TID from first msdu per MPDU, save to skb->priority */ - if (qdf_nbuf_is_rx_chfrag_start(nbuf)) - tid = hal_rx_mpdu_start_tid_get(soc->hal_soc, - rx_tlv_hdr); - DP_RX_TID_SAVE(nbuf, tid); - DP_RX_LIST_APPEND(deliver_list_head, deliver_list_tail, nbuf); DP_STATS_INC_PKT(peer, rx.to_stack, 1, qdf_nbuf_len(nbuf)); + tid_stats->delivered_to_stack++; nbuf = next; dp_peer_unref_del_find_by_id(peer); } diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index e615ffd486..fc7bd45e94 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/dp/wifi3.0/dp_tx.c @@ -1157,19 +1157,16 @@ static bool dp_cce_classify(struct dp_vdev *vdev, qdf_nbuf_t nbuf) } /** - * dp_tx_classify_tid() - Obtain TID to be used for this frame + * dp_tx_get_tid() - Obtain TID to be used for this frame * @vdev: DP vdev handle * @nbuf: skb * * Extract the DSCP or PCP information from frame and map into TID value. - * Software based TID classification is required when more than 2 DSCP-TID - * mapping tables are needed. - * Hardware supports 2 DSCP-TID mapping tables * * Return: void */ -static void dp_tx_classify_tid(struct dp_vdev *vdev, qdf_nbuf_t nbuf, - struct dp_tx_msdu_info_s *msdu_info) +static void dp_tx_get_tid(struct dp_vdev *vdev, qdf_nbuf_t nbuf, + struct dp_tx_msdu_info_s *msdu_info) { uint8_t tos = 0, dscp_tid_override = 0; uint8_t *hdr_ptr, *L3datap; @@ -1181,14 +1178,6 @@ static void dp_tx_classify_tid(struct dp_vdev *vdev, qdf_nbuf_t nbuf, struct dp_pdev *pdev = (struct dp_pdev *)vdev->pdev; DP_TX_TID_OVERRIDE(msdu_info, nbuf); - - if (pdev->soc && vdev->dscp_tid_map_id < pdev->soc->num_hw_dscp_tid_map) - return; - - /* for mesh packets don't do any classification */ - if (qdf_unlikely(vdev->mesh_vdev)) - return; - if (qdf_likely(vdev->tx_encap_type != htt_cmn_pkt_type_raw)) { eh = (qdf_ether_header_t *)nbuf->data; hdr_ptr = eh->ether_dhost; @@ -1286,9 +1275,41 @@ static void dp_tx_classify_tid(struct dp_vdev *vdev, qdf_nbuf_t nbuf, tos = (tos >> DP_IP_DSCP_SHIFT) & DP_IP_DSCP_MASK; msdu_info->tid = pdev->dscp_tid_map[vdev->dscp_tid_map_id][tos]; } + + if (msdu_info->tid >= CDP_MAX_DATA_TIDS) + msdu_info->tid = CDP_MAX_DATA_TIDS - 1; + return; } +/** + * dp_tx_classify_tid() - Obtain TID to be used for this frame + * @vdev: DP vdev handle + * @nbuf: skb + * + * Software based TID classification is required when more than 2 DSCP-TID + * mapping tables are needed. + * Hardware supports 2 DSCP-TID mapping tables for HKv1 and 48 for HKv2. + * + * Return: void + */ +static void dp_tx_classify_tid(struct dp_vdev *vdev, qdf_nbuf_t nbuf, + struct dp_tx_msdu_info_s *msdu_info) +{ + struct dp_pdev *pdev = (struct dp_pdev *)vdev->pdev; + + DP_TX_TID_OVERRIDE(msdu_info, nbuf); + + if (pdev->soc && vdev->dscp_tid_map_id < pdev->soc->num_hw_dscp_tid_map) + return; + + /* for mesh packets don't do any classification */ + if (qdf_unlikely(vdev->mesh_vdev)) + return; + + dp_tx_get_tid(vdev, nbuf, msdu_info); +} + #ifdef FEATURE_WLAN_TDLS /** * dp_tx_update_tdls_flags() - Update descriptor flags for TDLS frame @@ -1364,6 +1385,7 @@ static qdf_nbuf_t dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf, void *hal_srng = soc->tcl_data_ring[tx_q->ring_id].hal_srng; uint16_t htt_tcl_metadata = 0; uint8_t tid = msdu_info->tid; + struct cdp_tid_tx_stats *tid_stats = NULL; /* Setup Tx descriptor for an MSDU, and MSDU extension descriptor */ tx_desc = dp_tx_prepare_desc_single(vdev, nbuf, tx_q->desc_pool_id, @@ -1372,6 +1394,9 @@ static qdf_nbuf_t dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf, QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, "%s Tx_desc prepare Fail vdev %pK queue %d", __func__, 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->swdrop_cnt[TX_DESC_ERR]++; return nbuf; } @@ -1389,6 +1414,9 @@ static qdf_nbuf_t dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf, QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "%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->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); qdf_nbuf_unmap(vdev->osdev, nbuf, QDF_DMA_TO_DEVICE); @@ -1419,6 +1447,9 @@ static qdf_nbuf_t dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf, QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, "%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->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); goto fail_return; @@ -1466,11 +1497,15 @@ qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf, struct dp_tx_queue *tx_q = &msdu_info->tx_queue; void *hal_srng = soc->tcl_data_ring[tx_q->ring_id].hal_srng; + struct cdp_tid_tx_stats *tid_stats = NULL; if (qdf_unlikely(hal_srng_access_start(soc->hal_soc, hal_srng))) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "%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->swdrop_cnt[TX_HAL_RING_ACCESS_ERR]++; DP_STATS_INC(vdev, tx_i.dropped.ring_full, 1); return nbuf; } @@ -1531,9 +1566,13 @@ qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf, if (status != QDF_STATUS_SUCCESS) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "%s Tx_hw_enqueue Fail tx_desc %pK queue %d", - __func__, tx_desc, tx_q->ring_id); + "%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->swdrop_cnt[TX_HW_ENQUEUE]++; if (tx_desc->flags & DP_TX_DESC_FLAG_ME) dp_tx_me_free_buf(pdev, tx_desc->me_buffer); @@ -2640,10 +2679,16 @@ dp_tx_update_peer_stats(struct dp_peer *peer, struct dp_pdev *pdev = peer->vdev->pdev; struct dp_soc *soc = NULL; uint8_t mcs, pkt_type; + uint8_t tid = ts->tid; + struct cdp_tid_tx_stats *tid_stats; if (!pdev) return; + if (qdf_unlikely(tid >= CDP_MAX_DATA_TIDS)) + tid = CDP_MAX_DATA_TIDS - 1; + + tid_stats = &pdev->stats.tid_stats.tid_tx_stats[tid]; soc = pdev->soc; mcs = ts->mcs; @@ -2655,6 +2700,7 @@ dp_tx_update_peer_stats(struct dp_peer *peer, } DP_STATS_INC_PKT(peer, tx.comp_pkt, 1, length); + tid_stats->complete_cnt++; DP_STATS_INCC(peer, tx.dropped.age_out, 1, (ts->status == HAL_TX_TQM_RR_REM_CMD_AGED)); @@ -2677,8 +2723,12 @@ dp_tx_update_peer_stats(struct dp_peer *peer, (ts->status == HAL_TX_TQM_RR_FW_REASON3)); if (ts->status != HAL_TX_TQM_RR_FRAME_ACKED) { + tid_stats->comp_fail_cnt++; return; } + + tid_stats->success_cnt++; + DP_STATS_INCC(peer, tx.ofdma, 1, ts->ofdma); DP_STATS_INCC(peer, tx.amsdu_cnt, 1, ts->msdu_part_of_amsdu); @@ -3077,6 +3127,7 @@ void dp_tx_process_htt_completion(struct dp_tx_desc_s *tx_desc, uint8_t *status) struct hal_tx_completion_status ts = {0}; uint32_t *htt_desc = (uint32_t *)status; struct dp_peer *peer; + struct cdp_tid_tx_stats *tid_stats = NULL; qdf_assert(tx_desc->pdev); @@ -3091,6 +3142,7 @@ void dp_tx_process_htt_completion(struct dp_tx_desc_s *tx_desc, uint8_t *status) case HTT_TX_FW2WBM_TX_STATUS_DROP: case HTT_TX_FW2WBM_TX_STATUS_TTL: { + uint8_t tid; if (HTT_TX_WBM_COMPLETION_V2_VALID_GET(htt_desc[2])) { ts.peer_id = HTT_TX_WBM_COMPLETION_V2_SW_PEER_ID_GET( @@ -3111,9 +3163,19 @@ void dp_tx_process_htt_completion(struct dp_tx_desc_s *tx_desc, uint8_t *status) ts.first_msdu = 1; ts.last_msdu = 1; + tid = ts.tid; + if (qdf_unlikely(tid >= CDP_MAX_DATA_TIDS)) + tid = CDP_MAX_DATA_TIDS - 1; - if (tx_status != HTT_TX_FW2WBM_TX_STATUS_OK) + tid_stats = &pdev->stats.tid_stats.tid_tx_stats[tid]; + + tid_stats->complete_cnt++; + 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++; + } else { + tid_stats->success_cnt++; + } peer = dp_peer_find_by_id(soc, ts.peer_id); diff --git a/dp/wifi3.0/dp_tx.h b/dp/wifi3.0/dp_tx.h index b1050defbd..04d9ed5e0b 100644 --- a/dp/wifi3.0/dp_tx.h +++ b/dp/wifi3.0/dp_tx.h @@ -223,12 +223,8 @@ void dp_iterate_update_peer_list(void *pdev_hdl); #define DP_TX_TID_OVERRIDE(_msdu_info, _nbuf) #endif -#ifdef ATH_RX_PRI_SAVE #define DP_RX_TID_SAVE(_nbuf, _tid) \ (qdf_nbuf_set_priority(_nbuf, _tid)) -#else -#define DP_RX_TID_SAVE(_nbuf, _tid) -#endif /* TODO TX_FEATURE_NOT_YET */ static inline void dp_tx_comp_process_exception(struct dp_tx_desc_s *tx_desc)