qcacmn: add NAPI schedule latency and poll time histogram support
Add support for NAPI schedule latency and poll time histogram stats for WCN6450. Change-Id: If982ebe4e3cfa80f47c6d2fe9d4cb9dfa318481d CRs-Fixed: 3485287
This commit is contained in:

committed by
Rahul Choudhary

parent
ad4dd18f1b
commit
9d3b562c0c
@@ -311,6 +311,23 @@ struct qca_napi_stat {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*Number of buckets for latency*/
|
||||||
|
#define HIF_SCHED_LATENCY_BUCKETS 8
|
||||||
|
|
||||||
|
/*Buckets for latency between 0 to 2 ms*/
|
||||||
|
#define HIF_SCHED_LATENCY_BUCKET_0_2 2
|
||||||
|
/*Buckets for latency between 3 to 10 ms*/
|
||||||
|
#define HIF_SCHED_LATENCY_BUCKET_3_10 10
|
||||||
|
/*Buckets for latency between 11 to 20 ms*/
|
||||||
|
#define HIF_SCHED_LATENCY_BUCKET_11_20 20
|
||||||
|
/*Buckets for latency between 21 to 50 ms*/
|
||||||
|
#define HIF_SCHED_LATENCY_BUCKET_21_50 50
|
||||||
|
/*Buckets for latency between 50 to 100 ms*/
|
||||||
|
#define HIF_SCHED_LATENCY_BUCKET_51_100 100
|
||||||
|
/*Buckets for latency between 100 to 250 ms*/
|
||||||
|
#define HIF_SCHED_LATENCY_BUCKET_101_250 250
|
||||||
|
/*Buckets for latency between 250 to 500 ms*/
|
||||||
|
#define HIF_SCHED_LATENCY_BUCKET_251_500 500
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct qca_napi_info - per NAPI instance data structure
|
* struct qca_napi_info - per NAPI instance data structure
|
||||||
@@ -327,6 +344,9 @@ struct qca_napi_stat {
|
|||||||
* @rx_thread_napi:
|
* @rx_thread_napi:
|
||||||
* @rx_thread_netdev:
|
* @rx_thread_netdev:
|
||||||
* @lro_ctx:
|
* @lro_ctx:
|
||||||
|
* @poll_start_time: napi poll service start time
|
||||||
|
* @sched_latency_stats: napi schedule latency stats
|
||||||
|
* @tstamp: napi schedule start timestamp
|
||||||
*
|
*
|
||||||
* This data structure holds stuff per NAPI instance.
|
* This data structure holds stuff per NAPI instance.
|
||||||
* Note that, in the current implementation, though scale is
|
* Note that, in the current implementation, though scale is
|
||||||
@@ -350,6 +370,13 @@ struct qca_napi_info {
|
|||||||
struct net_device rx_thread_netdev;
|
struct net_device rx_thread_netdev;
|
||||||
#endif /* RECEIVE_OFFLOAD */
|
#endif /* RECEIVE_OFFLOAD */
|
||||||
qdf_lro_ctx_t lro_ctx;
|
qdf_lro_ctx_t lro_ctx;
|
||||||
|
#ifdef WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT
|
||||||
|
unsigned long long poll_start_time;
|
||||||
|
#endif
|
||||||
|
#ifdef HIF_LATENCY_PROFILE_ENABLE
|
||||||
|
uint64_t sched_latency_stats[HIF_SCHED_LATENCY_BUCKETS];
|
||||||
|
uint64_t tstamp;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
enum qca_napi_tput_state {
|
enum qca_napi_tput_state {
|
||||||
|
@@ -23,23 +23,6 @@
|
|||||||
#include <hif.h>
|
#include <hif.h>
|
||||||
#include <hif_irq_affinity.h>
|
#include <hif_irq_affinity.h>
|
||||||
#include <linux/cpumask.h>
|
#include <linux/cpumask.h>
|
||||||
/*Number of buckets for latency*/
|
|
||||||
#define HIF_SCHED_LATENCY_BUCKETS 8
|
|
||||||
|
|
||||||
/*Buckets for latency between 0 to 2 ms*/
|
|
||||||
#define HIF_SCHED_LATENCY_BUCKET_0_2 2
|
|
||||||
/*Buckets for latency between 3 to 10 ms*/
|
|
||||||
#define HIF_SCHED_LATENCY_BUCKET_3_10 10
|
|
||||||
/*Buckets for latency between 11 to 20 ms*/
|
|
||||||
#define HIF_SCHED_LATENCY_BUCKET_11_20 20
|
|
||||||
/*Buckets for latency between 21 to 50 ms*/
|
|
||||||
#define HIF_SCHED_LATENCY_BUCKET_21_50 50
|
|
||||||
/*Buckets for latency between 50 to 100 ms*/
|
|
||||||
#define HIF_SCHED_LATENCY_BUCKET_51_100 100
|
|
||||||
/*Buckets for latency between 100 to 250 ms*/
|
|
||||||
#define HIF_SCHED_LATENCY_BUCKET_101_250 250
|
|
||||||
/*Buckets for latency between 250 to 500 ms*/
|
|
||||||
#define HIF_SCHED_LATENCY_BUCKET_251_500 500
|
|
||||||
|
|
||||||
#ifndef IRQ_DISABLED_MAX_DURATION_NS
|
#ifndef IRQ_DISABLED_MAX_DURATION_NS
|
||||||
#define IRQ_DISABLED_MAX_DURATION_NS 100000000
|
#define IRQ_DISABLED_MAX_DURATION_NS 100000000
|
||||||
|
@@ -749,6 +749,136 @@ inline void hif_napi_enable_irq(struct hif_opaque_softc *hif, int id)
|
|||||||
hif_irq_enable(scn, NAPI_ID2PIPE(id));
|
hif_irq_enable(scn, NAPI_ID2PIPE(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HIF_LATENCY_PROFILE_ENABLE
|
||||||
|
/*
|
||||||
|
* hif_napi_latency_profile_start() - update the schedule start timestamp
|
||||||
|
*
|
||||||
|
* @scn: HIF context
|
||||||
|
* ce_id: Copyengine id
|
||||||
|
*
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
|
static inline void hif_napi_latency_profile_start(struct hif_softc *scn,
|
||||||
|
int ce_id)
|
||||||
|
{
|
||||||
|
struct qca_napi_info *napii;
|
||||||
|
|
||||||
|
napii = scn->napi_data.napis[ce_id];
|
||||||
|
if (napii)
|
||||||
|
napii->tstamp = qdf_ktime_to_ms(qdf_ktime_get());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* hif_napi_latency_profile_measure() - calculate the NAPI schedule latency
|
||||||
|
* and update histogram
|
||||||
|
*
|
||||||
|
* @napi_info: pointer to qca_napi_info for the napi instance
|
||||||
|
*
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
|
static void hif_napi_latency_profile_measure(struct qca_napi_info *napi_info)
|
||||||
|
{
|
||||||
|
int64_t cur_tstamp;
|
||||||
|
int64_t time_elapsed;
|
||||||
|
|
||||||
|
cur_tstamp = qdf_ktime_to_ms(qdf_ktime_get());
|
||||||
|
|
||||||
|
if (cur_tstamp > napi_info->tstamp)
|
||||||
|
time_elapsed = (cur_tstamp - napi_info->tstamp);
|
||||||
|
else
|
||||||
|
time_elapsed = ~0x0 - (napi_info->tstamp - cur_tstamp);
|
||||||
|
|
||||||
|
napi_info->tstamp = cur_tstamp;
|
||||||
|
|
||||||
|
if (time_elapsed <= HIF_SCHED_LATENCY_BUCKET_0_2)
|
||||||
|
napi_info->sched_latency_stats[0]++;
|
||||||
|
else if (time_elapsed <= HIF_SCHED_LATENCY_BUCKET_3_10)
|
||||||
|
napi_info->sched_latency_stats[1]++;
|
||||||
|
else if (time_elapsed <= HIF_SCHED_LATENCY_BUCKET_11_20)
|
||||||
|
napi_info->sched_latency_stats[2]++;
|
||||||
|
else if (time_elapsed <= HIF_SCHED_LATENCY_BUCKET_21_50)
|
||||||
|
napi_info->sched_latency_stats[3]++;
|
||||||
|
else if (time_elapsed <= HIF_SCHED_LATENCY_BUCKET_51_100)
|
||||||
|
napi_info->sched_latency_stats[4]++;
|
||||||
|
else if (time_elapsed <= HIF_SCHED_LATENCY_BUCKET_101_250)
|
||||||
|
napi_info->sched_latency_stats[5]++;
|
||||||
|
else if (time_elapsed <= HIF_SCHED_LATENCY_BUCKET_251_500)
|
||||||
|
napi_info->sched_latency_stats[6]++;
|
||||||
|
else
|
||||||
|
napi_info->sched_latency_stats[7]++;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static inline void
|
||||||
|
hif_napi_latency_profile_start(struct hif_softc *scn, int ce_id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
hif_napi_latency_profile_measure(struct qca_napi_info *napi_info)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT
|
||||||
|
/**
|
||||||
|
* hif_napi_update_service_start_time() - Update NAPI poll start time
|
||||||
|
*
|
||||||
|
* @napi_info: per NAPI instance data structure
|
||||||
|
*
|
||||||
|
* The function is called at the beginning of a NAPI poll to record the poll
|
||||||
|
* start time.
|
||||||
|
*
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
hif_napi_update_service_start_time(struct qca_napi_info *napi_info)
|
||||||
|
{
|
||||||
|
napi_info->poll_start_time = qdf_time_sched_clock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hif_napi_fill_poll_time_histogram() - fills poll time histogram for a NAPI
|
||||||
|
*
|
||||||
|
* @napi_info: per NAPI instance data structure
|
||||||
|
*
|
||||||
|
* The function is called at the end of a NAPI poll to calculate poll time
|
||||||
|
* buckets.
|
||||||
|
*
|
||||||
|
* Return: void
|
||||||
|
*/
|
||||||
|
static void hif_napi_fill_poll_time_histogram(struct qca_napi_info *napi_info)
|
||||||
|
{
|
||||||
|
struct qca_napi_stat *napi_stat;
|
||||||
|
unsigned long long poll_time_ns;
|
||||||
|
uint32_t poll_time_us;
|
||||||
|
uint32_t bucket_size_us = 500;
|
||||||
|
uint32_t bucket;
|
||||||
|
uint32_t cpu_id = qdf_get_cpu();
|
||||||
|
|
||||||
|
poll_time_ns = qdf_time_sched_clock() - napi_info->poll_start_time;
|
||||||
|
poll_time_us = qdf_do_div(poll_time_ns, 1000);
|
||||||
|
|
||||||
|
napi_stat = &napi_info->stats[cpu_id];
|
||||||
|
if (poll_time_ns > napi_info->stats[cpu_id].napi_max_poll_time)
|
||||||
|
napi_info->stats[cpu_id].napi_max_poll_time = poll_time_ns;
|
||||||
|
|
||||||
|
bucket = poll_time_us / bucket_size_us;
|
||||||
|
if (bucket >= QCA_NAPI_NUM_BUCKETS)
|
||||||
|
bucket = QCA_NAPI_NUM_BUCKETS - 1;
|
||||||
|
|
||||||
|
++napi_stat->poll_time_buckets[bucket];
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static inline void
|
||||||
|
hif_napi_update_service_start_time(struct qca_napi_info *napi_info)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
hif_napi_fill_poll_time_histogram(struct qca_napi_info *napi_info)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hif_napi_schedule() - schedules napi, updates stats
|
* hif_napi_schedule() - schedules napi, updates stats
|
||||||
@@ -780,6 +910,7 @@ bool hif_napi_schedule(struct hif_opaque_softc *hif_ctx, int ce_id)
|
|||||||
NULL, NULL, 0, 0);
|
NULL, NULL, 0, 0);
|
||||||
napii->stats[cpu].napi_schedules++;
|
napii->stats[cpu].napi_schedules++;
|
||||||
NAPI_DEBUG("scheduling napi %d (ce:%d)", napii->id, ce_id);
|
NAPI_DEBUG("scheduling napi %d (ce:%d)", napii->id, ce_id);
|
||||||
|
hif_napi_latency_profile_start(scn, ce_id);
|
||||||
napi_schedule(&(napii->napi));
|
napi_schedule(&(napii->napi));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -896,6 +1027,9 @@ int hif_napi_poll(struct hif_opaque_softc *hif_ctx,
|
|||||||
napi_info = (struct qca_napi_info *)
|
napi_info = (struct qca_napi_info *)
|
||||||
container_of(napi, struct qca_napi_info, napi);
|
container_of(napi, struct qca_napi_info, napi);
|
||||||
|
|
||||||
|
hif_napi_update_service_start_time(napi_info);
|
||||||
|
hif_napi_latency_profile_measure(napi_info);
|
||||||
|
|
||||||
NAPI_DEBUG("%s -->(napi(%d, irq=%d), budget=%d)",
|
NAPI_DEBUG("%s -->(napi(%d, irq=%d), budget=%d)",
|
||||||
__func__, napi_info->id, napi_info->irq, budget);
|
__func__, napi_info->id, napi_info->irq, budget);
|
||||||
|
|
||||||
@@ -979,6 +1113,8 @@ int hif_napi_poll(struct hif_opaque_softc *hif_ctx,
|
|||||||
hif_record_ce_desc_event(hif, NAPI_ID2PIPE(napi_info->id),
|
hif_record_ce_desc_event(hif, NAPI_ID2PIPE(napi_info->id),
|
||||||
NAPI_POLL_EXIT, NULL, NULL, normalized, 0);
|
NAPI_POLL_EXIT, NULL, NULL, normalized, 0);
|
||||||
|
|
||||||
|
hif_napi_fill_poll_time_histogram(napi_info);
|
||||||
|
|
||||||
NAPI_DEBUG("%s <--[normalized=%d]", __func__, normalized);
|
NAPI_DEBUG("%s <--[normalized=%d]", __func__, normalized);
|
||||||
return normalized;
|
return normalized;
|
||||||
out:
|
out:
|
||||||
|
Reference in New Issue
Block a user