From: Shijith Thotton <sthotton@marvell.com>
To: <dev@dpdk.org>
Cc: Shijith Thotton <sthotton@marvell.com>, <jerinj@marvell.com>,
"Pavan Nikhilesh" <pbhagavatula@marvell.com>,
Nithin Dabilpuram <ndabilpuram@marvell.com>,
Kiran Kumar K <kirankumark@marvell.com>,
"Sunil Kumar Kori" <skori@marvell.com>,
Satha Rao <skoteshwar@marvell.com>
Subject: [dpdk-dev] [PATCH v2] drivers: add external clock support for cnxk timer
Date: Wed, 15 Sep 2021 21:33:27 +0530 [thread overview]
Message-ID: <abba6d4e9e332734b767596ac5a8bc482b68d6ac.1631721608.git.sthotton@marvell.com> (raw)
In-Reply-To: <ee6a527b0e824a34cbebbf0865a5bdc172d5207e.1627483481.git.sthotton@marvell.com>
To configure tim with external clock, requested resolution should be
adjusted based on core and external clock frequency for accuracy.
tim_ext_clk is the devarg used to pass external clock frequency.
E.g. -a 0002:0e:00.0,tim_ext_clk=122880000
Signed-off-by: Shijith Thotton <sthotton@marvell.com>
Signed-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com>
---
Depends-on: series-18039 ("eal: add macro to swap two numbers")
v2:
- Fixed devargs parsing and rebased.
doc/guides/eventdevs/cnxk.rst | 9 ++
drivers/common/cnxk/roc_platform.h | 1 +
drivers/common/cnxk/roc_tim.h | 2 +
drivers/event/cnxk/cnxk_eventdev.h | 9 ++
drivers/event/cnxk/cnxk_tim_evdev.c | 124 ++++++++++++++++++++++++++--
drivers/event/cnxk/cnxk_tim_evdev.h | 6 +-
6 files changed, 142 insertions(+), 9 deletions(-)
diff --git a/doc/guides/eventdevs/cnxk.rst b/doc/guides/eventdevs/cnxk.rst
index 53560d3830..238b71f81f 100644
--- a/doc/guides/eventdevs/cnxk.rst
+++ b/doc/guides/eventdevs/cnxk.rst
@@ -164,6 +164,15 @@ Runtime Config Options
-a 0002:0e:00.0,tim_ring_ctl=[2-1023-1-0]
+- ``TIM external clock frequency``
+
+ The ``tim_ext_clk`` devagrs can be used to pass external clock frequency when
+ external clock source is selected.
+
+ For Example::
+
+ -a 0002:0e:00.0,tim_ext_clk=122880000
+
Debugging Options
-----------------
diff --git a/drivers/common/cnxk/roc_platform.h b/drivers/common/cnxk/roc_platform.h
index 285b24b82d..7e73972b80 100644
--- a/drivers/common/cnxk/roc_platform.h
+++ b/drivers/common/cnxk/roc_platform.h
@@ -43,6 +43,7 @@
#define PLT_MAX RTE_MAX
#define PLT_DIM RTE_DIM
#define PLT_SET_USED RTE_SET_USED
+#define PLT_SWAP RTE_SWAP
#define PLT_STATIC_ASSERT(s) _Static_assert(s, #s)
#define PLT_ALIGN RTE_ALIGN
#define PLT_ALIGN_MUL_CEIL RTE_ALIGN_MUL_CEIL
diff --git a/drivers/common/cnxk/roc_tim.h b/drivers/common/cnxk/roc_tim.h
index 159b021a31..205113f24f 100644
--- a/drivers/common/cnxk/roc_tim.h
+++ b/drivers/common/cnxk/roc_tim.h
@@ -10,6 +10,8 @@ enum roc_tim_clk_src {
ROC_TIM_CLK_SRC_GPIO,
ROC_TIM_CLK_SRC_GTI,
ROC_TIM_CLK_SRC_PTP,
+ ROC_TIM_CLK_SRC_SYNCE,
+ ROC_TIM_CLK_SRC_BTS,
ROC_TIM_CLK_SRC_INVALID,
};
diff --git a/drivers/event/cnxk/cnxk_eventdev.h b/drivers/event/cnxk/cnxk_eventdev.h
index fc49b88d6f..7c3fcbe6f8 100644
--- a/drivers/event/cnxk/cnxk_eventdev.h
+++ b/drivers/event/cnxk/cnxk_eventdev.h
@@ -200,6 +200,15 @@ parse_kvargs_value(const char *key, const char *value, void *opaque)
return 0;
}
+static inline int
+parse_kvargs_long(const char *key, const char *value, void *opaque)
+{
+ RTE_SET_USED(key);
+
+ *(uint64_t *)opaque = (uint64_t)atol(value);
+ return 0;
+}
+
static inline struct cnxk_sso_evdev *
cnxk_sso_pmd_priv(const struct rte_eventdev *event_dev)
{
diff --git a/drivers/event/cnxk/cnxk_tim_evdev.c b/drivers/event/cnxk/cnxk_tim_evdev.c
index c3e9dc508c..5b117da1b1 100644
--- a/drivers/event/cnxk/cnxk_tim_evdev.c
+++ b/drivers/event/cnxk/cnxk_tim_evdev.c
@@ -2,6 +2,8 @@
* Copyright(C) 2021 Marvell.
*/
+#include <math.h>
+
#include "cnxk_eventdev.h"
#include "cnxk_tim_evdev.h"
@@ -115,12 +117,88 @@ 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] % cnxk_tim_min_resolution_ns(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)
+{
+#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];
+ uint64_t m_tck = cnxk_tim_min_tmo_ticks(cnxk_tim_cntfrq());
+ 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)
{
struct rte_event_timer_adapter_conf *rcfg = &adptr->data->conf;
struct cnxk_tim_evdev *dev = cnxk_tim_priv_get();
struct cnxk_tim_ring *tim_ring;
+ uint64_t interval;
int i, rc;
if (dev == NULL)
@@ -153,11 +231,35 @@ cnxk_tim_ring_create(struct rte_event_timer_adapter *adptr)
goto tim_hw_free;
}
}
+
tim_ring->ring_id = adptr->data->id;
tim_ring->clk_src = (int)rcfg->clk_src;
- tim_ring->tck_nsec = RTE_ALIGN_MUL_CEIL(
- rcfg->timer_tick_ns,
- cnxk_tim_min_resolution_ns(cnxk_tim_cntfrq()));
+ if (rcfg->clk_src == RTE_EVENT_TIMER_ADAPTER_CPU_CLK) {
+ rcfg->timer_tick_ns = RTE_ALIGN_MUL_CEIL(
+ rcfg->timer_tick_ns,
+ cnxk_tim_min_resolution_ns(cnxk_tim_cntfrq()));
+ } else { /* External clock */
+ uint64_t req_ns, req_tck;
+ double tck_ns;
+
+ if (dev->ext_clk_frq == 0) {
+ rc = -ENODEV;
+ goto tim_hw_free;
+ }
+
+ req_ns = rcfg->timer_tick_ns;
+ tck_ns = NSECPERSEC / dev->ext_clk_frq;
+ req_tck = round(rcfg->timer_tick_ns / tck_ns);
+ tim_adjust_resolution(&req_ns, &req_tck, tck_ns,
+ cnxk_tim_cntfrq(), rcfg->max_tmo_ns);
+ if ((rcfg->timer_tick_ns != req_ns) &&
+ !(rcfg->flags & RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES)) {
+ rc = -ERANGE;
+ goto tim_hw_free;
+ }
+ rcfg->timer_tick_ns = ceil(req_tck * tck_ns);
+ }
+ tim_ring->tck_nsec = rcfg->timer_tick_ns;
tim_ring->max_tout = rcfg->max_tmo_ns;
tim_ring->nb_bkts = (tim_ring->max_tout / tim_ring->tck_nsec);
tim_ring->nb_timers = rcfg->nb_timers;
@@ -201,11 +303,15 @@ cnxk_tim_ring_create(struct rte_event_timer_adapter *adptr)
if (rc < 0)
goto tim_bkt_free;
- rc = roc_tim_lf_config(
- &dev->tim, tim_ring->ring_id,
- cnxk_tim_convert_clk_src(tim_ring->clk_src), 0, 0,
- tim_ring->nb_bkts, tim_ring->chunk_sz,
- NSEC2TICK(tim_ring->tck_nsec, cnxk_tim_cntfrq()));
+ if (rcfg->clk_src == RTE_EVENT_TIMER_ADAPTER_CPU_CLK)
+ interval = NSEC2TICK(tim_ring->tck_nsec, cnxk_tim_cntfrq());
+ else
+ interval = NSEC2TICK(tim_ring->tck_nsec, dev->ext_clk_frq);
+
+ rc = roc_tim_lf_config(&dev->tim, tim_ring->ring_id,
+ cnxk_tim_convert_clk_src(tim_ring->clk_src), 0,
+ 0, tim_ring->nb_bkts, tim_ring->chunk_sz,
+ interval);
if (rc < 0) {
plt_err("Failed to configure timer ring");
goto tim_chnk_free;
@@ -480,6 +586,8 @@ cnxk_tim_parse_devargs(struct rte_devargs *devargs, struct cnxk_tim_evdev *dev)
&dev->enable_stats);
rte_kvargs_process(kvlist, CNXK_TIM_RINGS_LMT, &parse_kvargs_value,
&dev->min_ring_cnt);
+ rte_kvargs_process(kvlist, CNXK_TIM_EXT_CLK, &parse_kvargs_long,
+ &dev->ext_clk_frq);
rte_kvargs_process(kvlist, CNXK_TIM_RING_CTL,
&cnxk_tim_parse_kvargs_dict, &dev);
diff --git a/drivers/event/cnxk/cnxk_tim_evdev.h b/drivers/event/cnxk/cnxk_tim_evdev.h
index 9a23952a91..6fc86c88d7 100644
--- a/drivers/event/cnxk/cnxk_tim_evdev.h
+++ b/drivers/event/cnxk/cnxk_tim_evdev.h
@@ -40,6 +40,7 @@
#define CNXK_TIM_STATS_ENA "tim_stats_ena"
#define CNXK_TIM_RINGS_LMT "tim_rings_lmt"
#define CNXK_TIM_RING_CTL "tim_ring_ctl"
+#define CNXK_TIM_EXT_CLK "tim_ext_clk"
#define CNXK_TIM_SP 0x1
#define CNXK_TIM_MP 0x2
@@ -95,6 +96,7 @@ struct cnxk_tim_evdev {
uint32_t min_ring_cnt;
uint8_t enable_stats;
uint16_t ring_ctl_cnt;
+ uint64_t ext_clk_frq;
struct cnxk_tim_ctl *ring_ctl_data;
};
@@ -188,7 +190,9 @@ cnxk_tim_convert_clk_src(enum cnxk_tim_clk_src clk_src)
switch (clk_src) {
case RTE_EVENT_TIMER_ADAPTER_CPU_CLK:
return roc_model_runtime_is_cn9k() ? ROC_TIM_CLK_SRC_10NS :
- ROC_TIM_CLK_SRC_GTI;
+ ROC_TIM_CLK_SRC_GTI;
+ case RTE_EVENT_TIMER_ADAPTER_EXT_CLK0:
+ return ROC_TIM_CLK_SRC_GPIO;
default:
return ROC_TIM_CLK_SRC_INVALID;
}
--
2.25.1
next prev parent reply other threads:[~2021-09-15 16:05 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-07-28 15:24 [dpdk-dev] [PATCH] " Shijith Thotton
2021-09-15 16:03 ` Shijith Thotton [this message]
2021-09-23 21:30 ` [dpdk-dev] [PATCH v3 1/2] event/cnxk: update min interval calculation pbhagavatula
2021-09-23 21:30 ` [dpdk-dev] [PATCH v3 2/2] event/cnxk: add external clock support for timer pbhagavatula
2021-10-09 8:04 ` [dpdk-dev] [PATCH v4 1/2] event/cnxk: update min interval calculation pbhagavatula
2021-10-09 8:04 ` [dpdk-dev] [PATCH v4 2/2] event/cnxk: add external clock support for timer pbhagavatula
2021-10-14 11:51 ` [dpdk-dev] [PATCH v4 1/2] event/cnxk: update min interval calculation Jerin Jacob
2021-12-13 11:13 ` [PATCH v5 " pbhagavatula
2021-12-13 11:13 ` [PATCH v5 2/2] event/cnxk: add external clock support for timer pbhagavatula
2022-01-21 10:18 ` [PATCH v5 1/2] event/cnxk: update min interval calculation Jerin Jacob
2022-01-25 9:54 ` Ray Kinsella
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=abba6d4e9e332734b767596ac5a8bc482b68d6ac.1631721608.git.sthotton@marvell.com \
--to=sthotton@marvell.com \
--cc=dev@dpdk.org \
--cc=jerinj@marvell.com \
--cc=kirankumark@marvell.com \
--cc=ndabilpuram@marvell.com \
--cc=pbhagavatula@marvell.com \
--cc=skori@marvell.com \
--cc=skoteshwar@marvell.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).