qcacmn: Add support to enable tx hw latency stats at run time

This feature can be enabled runtime using sysfs interface.
Support is added to dump and clear the histogram stats.

The lower delay regions has to be more granular to indicate any
medium related issues for time sensitive XR applications.

Change-Id: I0a44a54d12d92ce016de349810cb2bedebaf9a58
CRs-Fixed: 2981006
This commit is contained in:
Yeshwanth Sriram Guntuka
2021-11-15 21:41:57 +05:30
zatwierdzone przez Madan Koyyalamudi
rodzic 3de51ff2c5
commit df666b7116
13 zmienionych plików z 515 dodań i 103 usunięć

Wyświetl plik

@@ -3854,6 +3854,28 @@ static inline void dp_tx_update_peer_delay_stats(struct dp_txrx_peer *txrx_peer,
}
#endif
#ifdef HW_TX_DELAY_STATS_ENABLE
static inline
void dp_update_tx_delay_stats(struct dp_vdev *vdev, uint32_t delay, uint8_t tid,
uint8_t mode, uint8_t ring_id)
{
struct cdp_tid_tx_stats *tstats =
&vdev->stats.tid_tx_stats[ring_id][tid];
dp_update_delay_stats(tstats, NULL, delay, tid, mode, ring_id);
}
#else
static inline
void dp_update_tx_delay_stats(struct dp_vdev *vdev, uint32_t delay, uint8_t tid,
uint8_t mode, uint8_t ring_id)
{
struct cdp_tid_tx_stats *tstats =
&vdev->pdev->stats.tid_stats.tid_tx_stats[ring_id][tid];
dp_update_delay_stats(tstats, NULL, delay, tid, mode, ring_id);
}
#endif
/**
* dp_tx_compute_delay() - Compute and fill in all timestamps
* to pass in correct fields
@@ -3870,28 +3892,38 @@ void dp_tx_compute_delay(struct dp_vdev *vdev, struct dp_tx_desc_s *tx_desc,
int64_t current_timestamp, timestamp_ingress, timestamp_hw_enqueue;
uint32_t sw_enqueue_delay, fwhw_transmit_delay, interframe_delay;
if (qdf_likely(!vdev->pdev->delay_stats_flag))
if (qdf_likely(!vdev->pdev->delay_stats_flag) &&
qdf_likely(!dp_is_vdev_tx_delay_stats_enabled(vdev)))
return;
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);
/*
* Delay between packet enqueued to HW and Tx completion
*/
dp_update_tx_delay_stats(vdev, fwhw_transmit_delay, tid,
CDP_DELAY_STATS_FW_HW_TRANSMIT, ring_id);
/*
* For MCL, only enqueue to completion delay is required
* so return if the vdev flag is enabled.
*/
if (dp_is_vdev_tx_delay_stats_enabled(vdev))
return;
timestamp_ingress = qdf_nbuf_get_timestamp(tx_desc->nbuf);
sw_enqueue_delay = (uint32_t)(timestamp_hw_enqueue - timestamp_ingress);
interframe_delay = (uint32_t)(timestamp_ingress -
vdev->prev_tx_enq_tstamp);
/*
* Delay in software enqueue
*/
dp_update_delay_stats(vdev->pdev, sw_enqueue_delay, tid,
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, ring_id);
dp_update_tx_delay_stats(vdev, sw_enqueue_delay, tid,
CDP_DELAY_STATS_SW_ENQ, ring_id);
/*
* Update interframe delay stats calculated at hardstart receive point.
@@ -3900,8 +3932,8 @@ void dp_tx_compute_delay(struct dp_vdev *vdev, struct dp_tx_desc_s *tx_desc,
* On the other side, this will help in avoiding extra per packet check
* of !vdev->prev_tx_enq_tstamp.
*/
dp_update_delay_stats(vdev->pdev, interframe_delay, tid,
CDP_DELAY_STATS_TX_INTERFRAME, ring_id);
dp_update_tx_delay_stats(vdev, interframe_delay, tid,
CDP_DELAY_STATS_TX_INTERFRAME, ring_id);
vdev->prev_tx_enq_tstamp = timestamp_ingress;
}
@@ -4034,7 +4066,8 @@ dp_tx_update_peer_stats(struct dp_tx_desc_s *tx_desc,
length = qdf_nbuf_len(tx_desc->nbuf);
DP_PEER_STATS_FLAT_INC_PKT(txrx_peer, comp_pkt, 1, length);
if (qdf_unlikely(pdev->delay_stats_flag))
if (qdf_unlikely(pdev->delay_stats_flag) ||
qdf_unlikely(dp_is_vdev_tx_delay_stats_enabled(txrx_peer->vdev)))
dp_tx_compute_delay(txrx_peer->vdev, tx_desc, tid, ring_id);
if (ts->status < CDP_MAX_TX_TQM_STATUS) {