event/cnxk: disable timer resolution estimation
Disable timer resolution estimation, read TIM LF clock registers to get the current running clock counter as estimating causes time drift. Signed-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com>
This commit is contained in:
parent
4b5ffa6a05
commit
a6d13f59e6
@ -31,6 +31,12 @@
|
||||
#define TIM_LF_INT_VEC_NRSPERR_INT (0x0ull)
|
||||
#define TIM_LF_INT_VEC_RAS_INT (0x1ull)
|
||||
#define TIM_LF_RING_AURA (0x0)
|
||||
#define TIM_LF_FR_RN_GPIOS (0x020)
|
||||
#define TIM_LF_FR_RN_GTI (0x030)
|
||||
#define TIM_LF_FR_RN_PTP (0x040)
|
||||
#define TIM_LF_FR_RN_TENNS (0x050)
|
||||
#define TIM_LF_FR_RN_SYNCE (0x060)
|
||||
#define TIM_LF_FR_RN_BTS (0x070)
|
||||
#define TIM_LF_RING_BASE (0x130)
|
||||
#define TIM_LF_NRSPERR_INT (0x200)
|
||||
#define TIM_LF_NRSPERR_INT_W1S (0x208)
|
||||
|
@ -120,80 +120,6 @@ cnxk_tim_ring_info_get(const struct rte_event_timer_adapter *adptr,
|
||||
sizeof(struct rte_event_timer_adapter_conf));
|
||||
}
|
||||
|
||||
static inline void
|
||||
sort_multi_array(double ref_arr[], uint64_t arr1[], uint64_t arr2[],
|
||||
uint64_t arr3[], uint8_t sz)
|
||||
{
|
||||
int x;
|
||||
|
||||
for (x = 0; x < sz - 1; x++) {
|
||||
if (ref_arr[x] > ref_arr[x + 1]) {
|
||||
PLT_SWAP(ref_arr[x], ref_arr[x + 1]);
|
||||
PLT_SWAP(arr1[x], arr1[x + 1]);
|
||||
PLT_SWAP(arr2[x], arr2[x + 1]);
|
||||
PLT_SWAP(arr3[x], arr3[x + 1]);
|
||||
x = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
populate_sample(uint64_t tck[], uint64_t ns[], double diff[], uint64_t dst[],
|
||||
uint64_t req_tck, uint64_t clk_freq, double tck_ns, uint8_t sz,
|
||||
bool mov_fwd)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sz; i++) {
|
||||
tck[i] = i ? tck[i - 1] : req_tck;
|
||||
do {
|
||||
mov_fwd ? tck[i]++ : tck[i]--;
|
||||
ns[i] = round((double)tck[i] * tck_ns);
|
||||
if (round((double)tck[i] * tck_ns) >
|
||||
((double)tck[i] * tck_ns))
|
||||
continue;
|
||||
} while (ns[i] % (uint64_t)cnxk_tim_ns_per_tck(clk_freq));
|
||||
diff[i] = PLT_MAX((double)ns[i], (double)tck[i] * tck_ns) -
|
||||
PLT_MIN((double)ns[i], (double)tck[i] * tck_ns);
|
||||
dst[i] = mov_fwd ? tck[i] - req_tck : req_tck - tck[i];
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tim_adjust_resolution(uint64_t *req_ns, uint64_t *req_tck, double tck_ns,
|
||||
uint64_t clk_freq, uint64_t max_tmo, uint64_t m_tck)
|
||||
{
|
||||
#define MAX_SAMPLES 5
|
||||
double rmax_diff[MAX_SAMPLES], rmin_diff[MAX_SAMPLES];
|
||||
uint64_t min_tck[MAX_SAMPLES], max_tck[MAX_SAMPLES];
|
||||
uint64_t min_dst[MAX_SAMPLES], max_dst[MAX_SAMPLES];
|
||||
uint64_t min_ns[MAX_SAMPLES], max_ns[MAX_SAMPLES];
|
||||
int i;
|
||||
|
||||
populate_sample(max_tck, max_ns, rmax_diff, max_dst, *req_tck, clk_freq,
|
||||
tck_ns, MAX_SAMPLES, true);
|
||||
sort_multi_array(rmax_diff, max_dst, max_tck, max_ns, MAX_SAMPLES);
|
||||
|
||||
populate_sample(min_tck, min_ns, rmin_diff, min_dst, *req_tck, clk_freq,
|
||||
tck_ns, MAX_SAMPLES, false);
|
||||
sort_multi_array(rmin_diff, min_dst, min_tck, min_ns, MAX_SAMPLES);
|
||||
|
||||
for (i = 0; i < MAX_SAMPLES; i++) {
|
||||
if (min_dst[i] < max_dst[i] && min_tck[i] > m_tck &&
|
||||
(max_tmo / min_ns[i]) <=
|
||||
(TIM_MAX_BUCKET_SIZE - TIM_MIN_BUCKET_SIZE)) {
|
||||
*req_tck = min_tck[i];
|
||||
*req_ns = min_ns[i];
|
||||
break;
|
||||
} else if ((max_tmo / max_ns[i]) <
|
||||
(TIM_MAX_BUCKET_SIZE - TIM_MIN_BUCKET_SIZE)) {
|
||||
*req_tck = max_tck[i];
|
||||
*req_ns = max_ns[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
cnxk_tim_ring_create(struct rte_event_timer_adapter *adptr)
|
||||
{
|
||||
@ -264,27 +190,7 @@ cnxk_tim_ring_create(struct rte_event_timer_adapter *adptr)
|
||||
goto tim_hw_free;
|
||||
}
|
||||
|
||||
tim_ring->tck_nsec =
|
||||
round(RTE_ALIGN_MUL_NEAR((long double)rcfg->timer_tick_ns,
|
||||
cnxk_tim_ns_per_tck(clk_freq)));
|
||||
if (log10(clk_freq) - floor(log10(clk_freq)) != 0.0) {
|
||||
uint64_t req_ns, req_tck;
|
||||
double tck_ns;
|
||||
|
||||
req_ns = tim_ring->tck_nsec;
|
||||
tck_ns = NSECPERSEC / clk_freq;
|
||||
req_tck = round(rcfg->timer_tick_ns / tck_ns);
|
||||
tim_adjust_resolution(&req_ns, &req_tck, tck_ns, clk_freq,
|
||||
rcfg->max_tmo_ns, min_intvl_cyc);
|
||||
if ((tim_ring->tck_nsec != req_ns) &&
|
||||
!(rcfg->flags & RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES)) {
|
||||
rc = -ERANGE;
|
||||
goto tim_hw_free;
|
||||
}
|
||||
tim_ring->tck_nsec = ceil(req_tck * tck_ns);
|
||||
}
|
||||
|
||||
tim_ring->tck_int = round((long double)tim_ring->tck_nsec /
|
||||
tim_ring->tck_int = round((double)rcfg->timer_tick_ns /
|
||||
cnxk_tim_ns_per_tck(clk_freq));
|
||||
tim_ring->tck_nsec =
|
||||
ceil(tim_ring->tck_int * cnxk_tim_ns_per_tck(clk_freq));
|
||||
@ -297,6 +203,13 @@ cnxk_tim_ring_create(struct rte_event_timer_adapter *adptr)
|
||||
tim_ring->chunk_sz = dev->chunk_sz;
|
||||
tim_ring->disable_npa = dev->disable_npa;
|
||||
tim_ring->enable_stats = dev->enable_stats;
|
||||
tim_ring->base = roc_tim_lf_base_get(&dev->tim, tim_ring->ring_id);
|
||||
tim_ring->tbase = cnxk_tim_get_tick_base(clk_src, tim_ring->base);
|
||||
|
||||
if (roc_model_is_cn9k() && (tim_ring->clk_src == ROC_TIM_CLK_SRC_GTI))
|
||||
tim_ring->tick_fn = cnxk_tim_cntvct;
|
||||
else
|
||||
tim_ring->tick_fn = cnxk_tim_tick_read;
|
||||
|
||||
for (i = 0; i < dev->ring_ctl_cnt; i++) {
|
||||
struct cnxk_tim_ctl *ring_ctl = &dev->ring_ctl_data[i];
|
||||
@ -343,7 +256,6 @@ cnxk_tim_ring_create(struct rte_event_timer_adapter *adptr)
|
||||
goto tim_chnk_free;
|
||||
}
|
||||
|
||||
tim_ring->base = roc_tim_lf_base_get(&dev->tim, tim_ring->ring_id);
|
||||
plt_write64((uint64_t)tim_ring->bkt, tim_ring->base + TIM_LF_RING_BASE);
|
||||
plt_write64(tim_ring->aura, tim_ring->base + TIM_LF_RING_AURA);
|
||||
|
||||
@ -393,31 +305,6 @@ cnxk_tim_ring_free(struct rte_event_timer_adapter *adptr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
cnxk_tim_calibrate_start_tsc(struct cnxk_tim_ring *tim_ring)
|
||||
{
|
||||
#define CNXK_TIM_CALIB_ITER 1E6
|
||||
uint32_t real_bkt, bucket;
|
||||
int icount, ecount = 0;
|
||||
uint64_t bkt_cyc;
|
||||
|
||||
for (icount = 0; icount < CNXK_TIM_CALIB_ITER; icount++) {
|
||||
real_bkt = plt_read64(tim_ring->base + TIM_LF_RING_REL) >> 44;
|
||||
bkt_cyc = cnxk_tim_cntvct();
|
||||
bucket = (bkt_cyc - tim_ring->ring_start_cyc) /
|
||||
tim_ring->tck_int;
|
||||
bucket = bucket % (tim_ring->nb_bkts);
|
||||
tim_ring->ring_start_cyc =
|
||||
bkt_cyc - (real_bkt * tim_ring->tck_int);
|
||||
if (bucket != real_bkt)
|
||||
ecount++;
|
||||
}
|
||||
tim_ring->last_updt_cyc = bkt_cyc;
|
||||
plt_tim_dbg("Bucket mispredict %3.2f distance %d\n",
|
||||
100 - (((double)(icount - ecount) / (double)icount) * 100),
|
||||
bucket - real_bkt);
|
||||
}
|
||||
|
||||
static int
|
||||
cnxk_tim_ring_start(const struct rte_event_timer_adapter *adptr)
|
||||
{
|
||||
@ -433,12 +320,16 @@ cnxk_tim_ring_start(const struct rte_event_timer_adapter *adptr)
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
tim_ring->tot_int = tim_ring->tck_int * tim_ring->nb_bkts;
|
||||
tim_ring->fast_div = rte_reciprocal_value_u64(tim_ring->tck_int);
|
||||
tim_ring->fast_bkt = rte_reciprocal_value_u64(tim_ring->nb_bkts);
|
||||
|
||||
cnxk_tim_calibrate_start_tsc(tim_ring);
|
||||
if (roc_model_is_cn9k() && (tim_ring->clk_src == ROC_TIM_CLK_SRC_GTI)) {
|
||||
uint64_t start_diff;
|
||||
|
||||
start_diff = cnxk_tim_cntvct(tim_ring->tbase) -
|
||||
cnxk_tim_tick_read(tim_ring->tbase);
|
||||
tim_ring->ring_start_cyc += start_diff;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -464,7 +355,8 @@ cnxk_tim_stats_get(const struct rte_event_timer_adapter *adapter,
|
||||
struct rte_event_timer_adapter_stats *stats)
|
||||
{
|
||||
struct cnxk_tim_ring *tim_ring = adapter->data->adapter_priv;
|
||||
uint64_t bkt_cyc = cnxk_tim_cntvct() - tim_ring->ring_start_cyc;
|
||||
uint64_t bkt_cyc =
|
||||
tim_ring->tick_fn(tim_ring->tbase) - tim_ring->ring_start_cyc;
|
||||
|
||||
stats->evtim_exp_count =
|
||||
__atomic_load_n(&tim_ring->arm_cnt, __ATOMIC_RELAXED);
|
||||
|
@ -24,14 +24,14 @@
|
||||
|
||||
#define CNXK_TIM_EVDEV_NAME cnxk_tim_eventdev
|
||||
#define CNXK_TIM_MAX_BUCKETS (0xFFFFF)
|
||||
#define CNXK_TIM_RING_DEF_CHUNK_SZ (4096)
|
||||
#define CNXK_TIM_RING_DEF_CHUNK_SZ (256)
|
||||
#define CNXK_TIM_CHUNK_ALIGNMENT (16)
|
||||
#define CNXK_TIM_MAX_BURST \
|
||||
(RTE_CACHE_LINE_SIZE / CNXK_TIM_CHUNK_ALIGNMENT)
|
||||
#define CNXK_TIM_NB_CHUNK_SLOTS(sz) (((sz) / CNXK_TIM_CHUNK_ALIGNMENT) - 1)
|
||||
#define CNXK_TIM_MIN_CHUNK_SLOTS (0x1)
|
||||
#define CNXK_TIM_MAX_CHUNK_SLOTS (0x1FFE)
|
||||
#define CNXK_TIM_MAX_POOL_CACHE_SZ (128)
|
||||
#define CNXK_TIM_MAX_POOL_CACHE_SZ (16)
|
||||
|
||||
#define CN9K_TIM_MIN_TMO_TKS (256)
|
||||
|
||||
@ -122,18 +122,18 @@ struct cnxk_tim_bkt {
|
||||
};
|
||||
|
||||
struct cnxk_tim_ring {
|
||||
uintptr_t base;
|
||||
uint16_t nb_chunk_slots;
|
||||
uint32_t nb_bkts;
|
||||
uint64_t last_updt_cyc;
|
||||
uintptr_t tbase;
|
||||
uint64_t (*tick_fn)(uint64_t tbase);
|
||||
uint64_t ring_start_cyc;
|
||||
uint64_t tck_int;
|
||||
uint64_t tot_int;
|
||||
struct cnxk_tim_bkt *bkt;
|
||||
struct rte_mempool *chunk_pool;
|
||||
struct rte_reciprocal_u64 fast_div;
|
||||
struct rte_reciprocal_u64 fast_bkt;
|
||||
uint64_t tck_int;
|
||||
uint64_t arm_cnt;
|
||||
uintptr_t base;
|
||||
uint8_t prod_type_sp;
|
||||
uint8_t enable_stats;
|
||||
uint8_t disable_npa;
|
||||
@ -166,19 +166,19 @@ cnxk_tim_priv_get(void)
|
||||
return mz->addr;
|
||||
}
|
||||
|
||||
static inline long double
|
||||
static inline double
|
||||
cnxk_tim_ns_per_tck(uint64_t freq)
|
||||
{
|
||||
return (long double)NSECPERSEC / freq;
|
||||
return (double)NSECPERSEC / freq;
|
||||
}
|
||||
|
||||
#ifdef RTE_ARCH_ARM64
|
||||
static inline uint64_t
|
||||
cnxk_tim_cntvct(void)
|
||||
cnxk_tim_cntvct(uint64_t base __rte_unused)
|
||||
{
|
||||
uint64_t tsc;
|
||||
|
||||
asm volatile("mrs %0, cntvct_el0" : "=r"(tsc));
|
||||
asm volatile("mrs %0, CNTVCT_EL0" : "=r"(tsc)::"memory");
|
||||
return tsc;
|
||||
}
|
||||
|
||||
@ -192,7 +192,7 @@ cnxk_tim_cntfrq(void)
|
||||
}
|
||||
#else
|
||||
static inline uint64_t
|
||||
cnxk_tim_cntvct(void)
|
||||
cnxk_tim_cntvct(uint64_t base __rte_unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -204,6 +204,12 @@ cnxk_tim_cntfrq(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline uint64_t
|
||||
cnxk_tim_tick_read(uint64_t tick_base)
|
||||
{
|
||||
return plt_read64(tick_base);
|
||||
}
|
||||
|
||||
static inline enum roc_tim_clk_src
|
||||
cnxk_tim_convert_clk_src(enum rte_event_timer_adapter_clk_src clk_src)
|
||||
{
|
||||
@ -224,6 +230,27 @@ cnxk_tim_convert_clk_src(enum rte_event_timer_adapter_clk_src clk_src)
|
||||
}
|
||||
}
|
||||
|
||||
static inline uintptr_t
|
||||
cnxk_tim_get_tick_base(enum roc_tim_clk_src clk_src, uintptr_t base)
|
||||
{
|
||||
switch (clk_src) {
|
||||
case ROC_TIM_CLK_SRC_GTI:
|
||||
return base + TIM_LF_FR_RN_GTI;
|
||||
case ROC_TIM_CLK_SRC_GPIO:
|
||||
return base + TIM_LF_FR_RN_GPIOS;
|
||||
case ROC_TIM_CLK_SRC_10NS:
|
||||
return base + TIM_LF_FR_RN_TENNS;
|
||||
case ROC_TIM_CLK_SRC_PTP:
|
||||
return base + TIM_LF_FR_RN_PTP;
|
||||
case ROC_TIM_CLK_SRC_SYNCE:
|
||||
return base + TIM_LF_FR_RN_SYNCE;
|
||||
case ROC_TIM_CLK_SRC_BTS:
|
||||
return base + TIM_LF_FR_RN_BTS;
|
||||
default:
|
||||
return ROC_TIM_CLK_SRC_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int
|
||||
cnxk_tim_get_clk_freq(struct cnxk_tim_evdev *dev, enum roc_tim_clk_src clk_src,
|
||||
uint64_t *freq)
|
||||
|
@ -39,22 +39,6 @@ cnxk_tim_format_event(const struct rte_event_timer *const tim,
|
||||
entry->wqe = tim->ev.u64;
|
||||
}
|
||||
|
||||
static inline void
|
||||
cnxk_tim_sync_start_cyc(struct cnxk_tim_ring *tim_ring)
|
||||
{
|
||||
uint64_t cur_cyc = cnxk_tim_cntvct();
|
||||
uint32_t real_bkt;
|
||||
|
||||
if (cur_cyc - tim_ring->last_updt_cyc > tim_ring->tot_int) {
|
||||
real_bkt = plt_read64(tim_ring->base + TIM_LF_RING_REL) >> 44;
|
||||
cur_cyc = cnxk_tim_cntvct();
|
||||
|
||||
tim_ring->ring_start_cyc =
|
||||
cur_cyc - (real_bkt * tim_ring->tck_int);
|
||||
tim_ring->last_updt_cyc = cur_cyc;
|
||||
}
|
||||
}
|
||||
|
||||
static __rte_always_inline uint16_t
|
||||
cnxk_tim_timer_arm_burst(const struct rte_event_timer_adapter *adptr,
|
||||
struct rte_event_timer **tim, const uint16_t nb_timers,
|
||||
@ -65,7 +49,6 @@ cnxk_tim_timer_arm_burst(const struct rte_event_timer_adapter *adptr,
|
||||
uint16_t index;
|
||||
int ret = 0;
|
||||
|
||||
cnxk_tim_sync_start_cyc(tim_ring);
|
||||
for (index = 0; index < nb_timers; index++) {
|
||||
if (cnxk_tim_arm_checks(tim_ring, tim[index]))
|
||||
break;
|
||||
@ -127,7 +110,6 @@ cnxk_tim_timer_arm_tmo_brst(const struct rte_event_timer_adapter *adptr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
cnxk_tim_sync_start_cyc(tim_ring);
|
||||
while (arr_idx < nb_timers) {
|
||||
for (idx = 0; idx < CNXK_TIM_MAX_BURST && (arr_idx < nb_timers);
|
||||
idx++, arr_idx++) {
|
||||
|
@ -131,7 +131,8 @@ cnxk_tim_get_target_bucket(struct cnxk_tim_ring *const tim_ring,
|
||||
const uint32_t rel_bkt, struct cnxk_tim_bkt **bkt,
|
||||
struct cnxk_tim_bkt **mirr_bkt)
|
||||
{
|
||||
const uint64_t bkt_cyc = cnxk_tim_cntvct() - tim_ring->ring_start_cyc;
|
||||
const uint64_t bkt_cyc =
|
||||
tim_ring->tick_fn(tim_ring->tbase) - tim_ring->ring_start_cyc;
|
||||
uint64_t bucket =
|
||||
rte_reciprocal_divide_u64(bkt_cyc, &tim_ring->fast_div) +
|
||||
rel_bkt;
|
||||
|
Loading…
Reference in New Issue
Block a user