diff --git a/dp/inc/cdp_txrx_cmn_struct.h b/dp/inc/cdp_txrx_cmn_struct.h index 55af6e0983..807574665b 100644 --- a/dp/inc/cdp_txrx_cmn_struct.h +++ b/dp/inc/cdp_txrx_cmn_struct.h @@ -1165,6 +1165,7 @@ typedef union cdp_config_param_t { bool cdp_psoc_param_en_rate_stats; int cdp_psoc_param_en_nss_cfg; int cdp_psoc_param_preferred_hw_mode; + bool cdp_psoc_param_pext_stats; } cdp_config_param_type; /** @@ -1267,11 +1268,13 @@ enum cdp_vdev_param_type { * @CDP_ENABLE_RATE_STATS: set rate stats enable/disable * @CDP_SET_NSS_CFG: set nss cfg * @CDP_SET_PREFERRED_HW_MODE: set preferred hw mode + * @CDP_CFG_PEER_EXT_STATS: Peer extended stats mode. */ enum cdp_psoc_param_type { CDP_ENABLE_RATE_STATS, CDP_SET_NSS_CFG, CDP_SET_PREFERRED_HW_MODE, + CDP_CFG_PEER_EXT_STATS, }; #define TXRX_FW_STATS_TXSTATS 1 diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index cd8e5b5fa9..806e97ba07 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -8013,6 +8013,34 @@ static QDF_STATUS dp_set_pdev_param(struct cdp_soc_t *cdp_soc, uint8_t pdev_id, return QDF_STATUS_SUCCESS; } +#ifdef QCA_PEER_EXT_STATS +static void dp_rx_update_peer_delay_stats(struct dp_soc *soc, + qdf_nbuf_t nbuf) +{ + struct dp_peer *peer = NULL; + uint16_t peer_id, ring_id; + uint8_t tid = qdf_nbuf_get_tid_val(nbuf); + struct cdp_peer_ext_stats *pext_stats = NULL; + + peer_id = QDF_NBUF_CB_RX_PEER_ID(nbuf); + if (peer_id > soc->max_peers) + return; + + peer = dp_peer_find_by_id(soc, peer_id); + if (qdf_unlikely(!peer) || qdf_unlikely(!peer->pext_stats)) + return; + + pext_stats = peer->pext_stats; + ring_id = QDF_NBUF_CB_RX_CTX_ID(nbuf); + dp_rx_compute_tid_delay(&pext_stats->delay_stats[tid][ring_id], nbuf); +} +#else +static inline void dp_rx_update_peer_delay_stats(struct dp_soc *soc, + qdf_nbuf_t nbuf) +{ +} +#endif + /* * dp_calculate_delay_stats: function to get rx delay stats * @cdp_soc: DP soc handle @@ -8025,14 +8053,23 @@ static QDF_STATUS dp_calculate_delay_stats(struct cdp_soc_t *cdp_soc, uint8_t vdev_id, qdf_nbuf_t nbuf) { + struct dp_soc *soc = (struct dp_soc *)cdp_soc; struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)cdp_soc, vdev_id); - if (vdev) { + + if (!vdev) + return QDF_STATUS_SUCCESS; + + if (vdev->pdev->delay_stats_flag) { dp_rx_compute_delay(vdev, nbuf); - return QDF_STATUS_E_FAILURE; + return QDF_STATUS_SUCCESS; } + /* + * Update the per peer delay stats + */ + dp_rx_update_peer_delay_stats(soc, nbuf); return QDF_STATUS_SUCCESS; } @@ -8255,6 +8292,21 @@ static QDF_STATUS dp_get_psoc_param(struct cdp_soc_t *cdp_soc, enum cdp_psoc_param_type param, cdp_config_param_type *val) { + struct dp_soc *soc = (struct dp_soc *)cdp_soc; + + if (!soc) + return QDF_STATUS_E_FAILURE; + + switch (param) { + case CDP_CFG_PEER_EXT_STATS: + val->cdp_psoc_param_pext_stats = + wlan_cfg_is_peer_ext_stats_enabled(soc->wlan_cfg_ctx); + break; + default: + dp_warn("Invalid param"); + break; + } + return QDF_STATUS_SUCCESS; } diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index 149f6fed8b..71bf680d79 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -32,6 +32,7 @@ #ifdef FEATURE_WDS #include "dp_txrx_wds.h" #endif +#include "dp_hist.h" #ifdef ATH_RX_PRI_SAVE #define DP_RX_TID_SAVE(_nbuf, _tid) \ @@ -1189,6 +1190,24 @@ qdf_nbuf_t dp_rx_sg_create(qdf_nbuf_t nbuf) return parent; } +#ifdef QCA_PEER_EXT_STATS +/* + * dp_rx_compute_tid_delay - Computer per TID delay stats + * @peer: DP soc context + * @nbuf: NBuffer + * + * Return: Void + */ +void dp_rx_compute_tid_delay(struct cdp_delay_tid_stats *stats, + qdf_nbuf_t nbuf) +{ + struct cdp_delay_rx_stats *rx_delay = &stats->rx_delay; + uint32_t to_stack = qdf_nbuf_get_timedelta_ms(nbuf); + + dp_hist_update_stats(&rx_delay->to_stack_delay, to_stack); +} +#endif /* QCA_PEER_EXT_STATS */ + /** * dp_rx_compute_delay() - Compute and fill in all timestamps * to pass in correct fields @@ -2283,7 +2302,9 @@ done: rx_pdev = vdev->pdev; DP_RX_TID_SAVE(nbuf, tid); - if (qdf_unlikely(rx_pdev->delay_stats_flag)) + if (qdf_unlikely(rx_pdev->delay_stats_flag) || + qdf_unlikely(wlan_cfg_is_peer_ext_stats_enabled( + soc->wlan_cfg_ctx))) qdf_nbuf_set_timestamp(nbuf); ring_id = QDF_NBUF_CB_RX_CTX_ID(nbuf); diff --git a/dp/wifi3.0/dp_rx.h b/dp/wifi3.0/dp_rx.h index 6747a86d0f..b09e23bedf 100644 --- a/dp/wifi3.0/dp_rx.h +++ b/dp/wifi3.0/dp_rx.h @@ -1233,6 +1233,12 @@ void dp_rx_dump_info_and_assert(struct dp_soc *soc, struct dp_rx_desc *rx_desc); void dp_rx_compute_delay(struct dp_vdev *vdev, qdf_nbuf_t nbuf); + +#ifdef QCA_PEER_EXT_STATS +void dp_rx_compute_tid_delay(struct cdp_delay_tid_stats *stats, + qdf_nbuf_t nbuf); +#endif /* QCA_PEER_EXT_STATS */ + #ifdef RX_DESC_DEBUG_CHECK /** * dp_rx_desc_check_magic() - check the magic value in dp_rx_desc diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index 58ad9eb244..7bca13caf2 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/dp/wifi3.0/dp_tx.c @@ -40,6 +40,7 @@ #ifdef ATH_SUPPORT_IQUE #include "dp_txrx_me.h" #endif +#include "dp_hist.h" /* TODO Add support in TSO */ @@ -1225,8 +1226,10 @@ static QDF_STATUS dp_tx_hw_enqueue(struct dp_soc *soc, struct dp_vdev *vdev, if (tx_desc->flags & DP_TX_DESC_FLAG_MESH) hal_tx_desc_set_mesh_en(soc->hal_soc, hal_tx_desc_cached, 1); - if (qdf_unlikely(vdev->pdev->delay_stats_flag)) - tx_desc->timestamp = qdf_ktime_to_ms(qdf_ktime_get()); + if (qdf_unlikely(vdev->pdev->delay_stats_flag) || + qdf_unlikely(wlan_cfg_is_peer_ext_stats_enabled( + soc->wlan_cfg_ctx))) + tx_desc->timestamp = qdf_ktime_to_ms(qdf_ktime_real_get()); dp_verbose_debug("length:%d , type = %d, dma_addr %llx, offset %d desc id %u", tx_desc->length, type, (uint64_t)tx_desc->dma_addr, @@ -2986,6 +2989,84 @@ void dp_tx_comp_fill_tx_completion_stats(struct dp_tx_desc_s *tx_desc, #endif +#ifdef QCA_PEER_EXT_STATS +/* + * dp_tx_compute_tid_delay() - Compute per TID delay + * @stats: Per TID delay stats + * @tx_desc: Software Tx descriptor + * + * Compute the software enqueue and hw enqueue delays and + * update the respective histograms + * + * Return: void + */ +static void dp_tx_compute_tid_delay(struct cdp_delay_tid_stats *stats, + struct dp_tx_desc_s *tx_desc) +{ + struct cdp_delay_tx_stats *tx_delay = &stats->tx_delay; + int64_t current_timestamp, timestamp_ingress, timestamp_hw_enqueue; + uint32_t sw_enqueue_delay, fwhw_transmit_delay; + + current_timestamp = qdf_ktime_to_ms(qdf_ktime_real_get()); + timestamp_ingress = qdf_nbuf_get_timestamp(tx_desc->nbuf); + timestamp_hw_enqueue = tx_desc->timestamp; + sw_enqueue_delay = (uint32_t)(timestamp_hw_enqueue - timestamp_ingress); + fwhw_transmit_delay = (uint32_t)(current_timestamp - + timestamp_hw_enqueue); + + /* + * Update the Tx software enqueue delay and HW enque-Completion delay. + */ + dp_hist_update_stats(&tx_delay->tx_swq_delay, sw_enqueue_delay); + dp_hist_update_stats(&tx_delay->hwtx_delay, fwhw_transmit_delay); +} + +/* + * dp_tx_update_peer_ext_stats() - Update the peer extended stats + * @peer: DP peer context + * @tx_desc: Tx software descriptor + * @tid: Transmission ID + * @ring_id: Rx CPU context ID/CPU_ID + * + * Update the peer extended stats. These are enhanced other + * delay stats per msdu level. + * + * Return: void + */ +static void dp_tx_update_peer_ext_stats(struct dp_peer *peer, + struct dp_tx_desc_s *tx_desc, + uint8_t tid, uint8_t ring_id) +{ + struct dp_pdev *pdev = peer->vdev->pdev; + struct dp_soc *soc = NULL; + struct cdp_peer_ext_stats *pext_stats = NULL; + + soc = pdev->soc; + if (qdf_likely(!wlan_cfg_is_peer_ext_stats_enabled(soc->wlan_cfg_ctx))) + return; + + pext_stats = peer->pext_stats; + + qdf_assert(pext_stats); + qdf_assert(ring < CDP_MAX_TXRX_CTX); + + /* + * For non-TID packets use the TID 9 + */ + if (qdf_unlikely(tid >= CDP_MAX_DATA_TIDS)) + tid = CDP_MAX_DATA_TIDS - 1; + + dp_tx_compute_tid_delay(&pext_stats->delay_stats[tid][ring_id], + tx_desc); +} +#else +static inline void dp_tx_update_peer_ext_stats(struct dp_peer *peer, + struct dp_tx_desc_s *tx_desc, + uint8_t tid, uint8_t ring_id) +{ +} +#endif + /** * dp_tx_compute_delay() - Compute and fill in all timestamps * to pass in correct fields @@ -3006,7 +3087,7 @@ static void dp_tx_compute_delay(struct dp_vdev *vdev, if (qdf_likely(!vdev->pdev->delay_stats_flag)) return; - current_timestamp = qdf_ktime_to_ms(qdf_ktime_get()); + current_timestamp = qdf_ktime_to_ms(qdf_ktime_real_get()); timestamp_ingress = qdf_nbuf_get_timestamp(tx_desc->nbuf); timestamp_hw_enqueue = tx_desc->timestamp; sw_enqueue_delay = (uint32_t)(timestamp_hw_enqueue - timestamp_ingress); @@ -3356,7 +3437,7 @@ dp_tx_comp_process_desc(struct dp_soc *soc, * scatter gather packets */ if (qdf_unlikely(!!desc->pdev->latency_capture_enable)) { - time_latency = (qdf_ktime_to_ms(qdf_ktime_get()) - + time_latency = (qdf_ktime_to_ms(qdf_ktime_real_get()) - desc->timestamp); } if (!(desc->msdu_ext_desc)) { @@ -3531,6 +3612,7 @@ void dp_tx_comp_process_tx_status(struct dp_soc *soc, } dp_tx_update_peer_stats(tx_desc, ts, peer, ring_id); + dp_tx_update_peer_ext_stats(peer, tx_desc, ts->tid, ring_id); #ifdef QCA_SUPPORT_RDK_STATS if (soc->wlanstats_enabled) @@ -3723,7 +3805,6 @@ void dp_tx_process_htt_completion(struct dp_tx_desc_s *tx_desc, uint8_t *status, } peer = dp_peer_find_by_id(soc, ts.peer_id); - if (qdf_likely(peer)) dp_peer_unref_del_find_by_id(peer);