qcacmn: Implement delay VOW stats for hawkeye
Delay counters per TID have been implemented for following types: 1. Linux stack to hw enqueue delay 2. HW enqueue delay to tx completion delay 3. TX interframe delay 4. RX interframe delay 5. RX frame delay from ring reap to networking stack Change-Id: I836596cbd878a43955c18b4981cb5b7b43d4df5e
Este cometimento está contido em:

cometido por
nshrivas

ascendente
17e1cb5cf4
cometimento
a331e6e55f
@@ -4444,6 +4444,8 @@ static struct cdp_vdev *dp_vdev_attach_wifi3(struct cdp_pdev *txrx_pdev,
|
||||
vdev->dscp_tid_map_id = 0;
|
||||
vdev->mcast_enhancement_en = 0;
|
||||
vdev->raw_mode_war = wlan_cfg_get_raw_mode_war(soc->wlan_cfg_ctx);
|
||||
vdev->prev_tx_enq_tstamp = 0;
|
||||
vdev->prev_rx_deliver_tstamp = 0;
|
||||
|
||||
qdf_spin_lock_bh(&pdev->vdev_list_lock);
|
||||
/* add this vdev into the pdev's list */
|
||||
@@ -6050,6 +6052,20 @@ uint8_t dp_get_pdev_id_frm_pdev(struct cdp_pdev *pdev_handle)
|
||||
return pdev->pdev_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* dp_get_delay_stats_flag() - get delay stats flag
|
||||
* @pdev_handle: Datapath PDEV handle
|
||||
*
|
||||
* Return: 0 if flag is disabled else 1
|
||||
*/
|
||||
static
|
||||
bool dp_get_delay_stats_flag(struct cdp_pdev *pdev_handle)
|
||||
{
|
||||
struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle;
|
||||
|
||||
return pdev->delay_stats_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* dp_pdev_set_chan_noise_floor() - set channel noise floor
|
||||
* @pdev_handle: Datapath PDEV handle
|
||||
@@ -8158,12 +8174,33 @@ static QDF_STATUS dp_set_pdev_param(struct cdp_pdev *pdev_handle,
|
||||
case CDP_OSIF_DROP:
|
||||
dp_pdev_tid_stats_osif_drop(pdev_handle, val);
|
||||
break;
|
||||
case CDP_CONFIG_DELAY_STATS:
|
||||
if (val == 1)
|
||||
pdev->delay_stats_flag = true;
|
||||
else
|
||||
pdev->delay_stats_flag = false;
|
||||
break;
|
||||
default:
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* dp_calculate_delay_stats: function to get rx delay stats
|
||||
* @vdev_handle: DP vdev handle
|
||||
* @nbuf: skb
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static void dp_calculate_delay_stats(struct cdp_vdev *vdev_handle,
|
||||
qdf_nbuf_t nbuf)
|
||||
{
|
||||
struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle;
|
||||
|
||||
dp_rx_compute_delay(vdev, nbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* dp_get_vdev_param: function to get parameters from vdev
|
||||
* @param: parameter type to get value
|
||||
@@ -9360,7 +9397,7 @@ static struct cdp_cmn_ops dp_ops_cmn = {
|
||||
.txrx_stats_request = dp_txrx_stats_request,
|
||||
.txrx_set_monitor_mode = dp_vdev_set_monitor_mode,
|
||||
.txrx_get_pdev_id_frm_pdev = dp_get_pdev_id_frm_pdev,
|
||||
.txrx_get_vow_config_frm_pdev = NULL,
|
||||
.txrx_get_vow_config_frm_pdev = dp_get_delay_stats_flag,
|
||||
.txrx_pdev_set_chan_noise_floor = dp_pdev_set_chan_noise_floor,
|
||||
.txrx_set_nac = dp_set_nac,
|
||||
.txrx_get_tx_pending = dp_get_tx_pending,
|
||||
@@ -9424,6 +9461,7 @@ static struct cdp_ctrl_ops dp_ops_ctrl = {
|
||||
.set_key = dp_set_michael_key,
|
||||
.txrx_get_vdev_param = dp_get_vdev_param,
|
||||
.enable_peer_based_pktlog = dp_enable_peer_based_pktlog,
|
||||
.calculate_delay_stats = dp_calculate_delay_stats,
|
||||
};
|
||||
|
||||
static struct cdp_me_ops dp_ops_me = {
|
||||
@@ -10246,3 +10284,153 @@ int dp_set_pktlog_wifi3(struct dp_pdev *pdev, uint32_t event,
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* dp_bucket_index() - Return index from array
|
||||
*
|
||||
* @delay: delay measured
|
||||
* @array: array used to index corresponding delay
|
||||
*
|
||||
* Return: index
|
||||
*/
|
||||
static uint8_t dp_bucket_index(uint32_t delay, uint16_t *array)
|
||||
{
|
||||
uint8_t i = CDP_DELAY_BUCKET_1;
|
||||
|
||||
for (; i < CDP_DELAY_BUCKET_MAX; i++) {
|
||||
if (delay < array[i] && delay > array[i + 1])
|
||||
return i;
|
||||
}
|
||||
|
||||
return (CDP_DELAY_BUCKET_MAX - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* dp_fill_delay_buckets() - Fill delay statistics bucket for each
|
||||
* type of delay
|
||||
*
|
||||
* @pdev: pdev handle
|
||||
* @delay: delay in ms
|
||||
* @t: tid value
|
||||
* @mode: type of tx delay mode
|
||||
* 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 delay_index = 0;
|
||||
struct cdp_tid_tx_stats *tstats =
|
||||
&pdev->stats.tid_stats.tid_tx_stats[tid];
|
||||
struct cdp_tid_rx_stats *rstats =
|
||||
&pdev->stats.tid_stats.tid_rx_stats[tid];
|
||||
/*
|
||||
* cdp_fw_to_hw_delay_range
|
||||
* Fw to hw delay ranges in milliseconds
|
||||
*/
|
||||
uint16_t cdp_fw_to_hw_delay[CDP_DELAY_BUCKET_MAX] = {
|
||||
10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 250, 500};
|
||||
|
||||
/*
|
||||
* cdp_sw_enq_delay_range
|
||||
* Software enqueue delay ranges in milliseconds
|
||||
*/
|
||||
uint16_t cdp_sw_enq_delay[CDP_DELAY_BUCKET_MAX] = {
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
|
||||
|
||||
/*
|
||||
* cdp_intfrm_delay_range
|
||||
* Interframe delay ranges in milliseconds
|
||||
*/
|
||||
uint16_t cdp_intfrm_delay[CDP_DELAY_BUCKET_MAX] = {
|
||||
5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60};
|
||||
|
||||
/*
|
||||
* Update delay stats in proper bucket
|
||||
*/
|
||||
switch (mode) {
|
||||
/* Software Enqueue delay ranges */
|
||||
case CDP_DELAY_STATS_SW_ENQ:
|
||||
|
||||
delay_index = dp_bucket_index(delay, cdp_sw_enq_delay);
|
||||
tstats->swq_delay.delay_bucket[delay_index]++;
|
||||
return &tstats->swq_delay;
|
||||
|
||||
/* Tx Completion delay ranges */
|
||||
case CDP_DELAY_STATS_FW_HW_TRANSMIT:
|
||||
|
||||
delay_index = dp_bucket_index(delay, cdp_fw_to_hw_delay);
|
||||
tstats->hwtx_delay.delay_bucket[delay_index]++;
|
||||
return &tstats->hwtx_delay;
|
||||
|
||||
/* Interframe tx delay ranges */
|
||||
case CDP_DELAY_STATS_TX_INTERFRAME:
|
||||
|
||||
delay_index = dp_bucket_index(delay, cdp_intfrm_delay);
|
||||
tstats->intfrm_delay.delay_bucket[delay_index]++;
|
||||
return &tstats->intfrm_delay;
|
||||
|
||||
/* Interframe rx delay ranges */
|
||||
case CDP_DELAY_STATS_RX_INTERFRAME:
|
||||
|
||||
delay_index = dp_bucket_index(delay, cdp_intfrm_delay);
|
||||
rstats->intfrm_delay.delay_bucket[delay_index]++;
|
||||
return &rstats->intfrm_delay;
|
||||
|
||||
/* Ring reap to indication to network stack */
|
||||
case CDP_DELAY_STATS_REAP_STACK:
|
||||
|
||||
delay_index = dp_bucket_index(delay, cdp_intfrm_delay);
|
||||
rstats->to_stack_delay.delay_bucket[delay_index]++;
|
||||
return &rstats->intfrm_delay;
|
||||
default:
|
||||
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
|
||||
"%s Incorrect delay mode: %d", __func__, mode);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* Return: none
|
||||
*/
|
||||
void dp_update_delay_stats(struct dp_pdev *pdev, uint32_t delay,
|
||||
uint8_t tid, uint8_t mode)
|
||||
{
|
||||
struct cdp_delay_stats *dstats = NULL;
|
||||
|
||||
/*
|
||||
* 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);
|
||||
if (qdf_unlikely(!dstats))
|
||||
return;
|
||||
|
||||
if (delay != 0) {
|
||||
/*
|
||||
* Compute minimum,average and maximum
|
||||
* delay
|
||||
*/
|
||||
if (delay < dstats->min_delay)
|
||||
dstats->min_delay = delay;
|
||||
|
||||
if (delay > dstats->max_delay)
|
||||
dstats->max_delay = delay;
|
||||
|
||||
/*
|
||||
* Average over delay measured till now
|
||||
*/
|
||||
if (!dstats->avg_delay)
|
||||
dstats->avg_delay = delay;
|
||||
else
|
||||
dstats->avg_delay = ((delay + dstats->avg_delay) / 2);
|
||||
}
|
||||
}
|
||||
|
Criar uma nova questão referindo esta
Bloquear um utilizador