-/*
- * SPDX-License-Identifier: BSD-3-Clause
+/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2017 Cavium, Inc
*/
+#include "ssovf_evdev.h"
#include "timvf_evdev.h"
-int otx_logtype_timvf;
+RTE_LOG_REGISTER_SUFFIX(otx_logtype_timvf, timer, NOTICE);
-RTE_INIT(otx_timvf_init_log);
-static void
-otx_timvf_init_log(void)
-{
- otx_logtype_timvf = rte_log_register("pmd.event.octeontx.timer");
- if (otx_logtype_timvf >= 0)
- rte_log_set_level(otx_logtype_timvf, RTE_LOG_NOTICE);
-}
+static struct rte_eventdev *event_dev;
struct __rte_packed timvf_mbox_dev_info {
uint64_t ring_active[4];
return octeontx_mbox_send(&hdr, NULL, 0, now, sizeof(uint64_t));
}
+static int
+optimize_bucket_parameters(struct timvf_ring *timr)
+{
+ uint32_t hbkts;
+ uint32_t lbkts;
+ uint64_t tck_nsec;
+
+ hbkts = rte_align32pow2(timr->nb_bkts);
+ tck_nsec = RTE_ALIGN_MUL_CEIL(timr->max_tout / (hbkts - 1), 10);
+
+ if ((tck_nsec < 1000 || hbkts > TIM_MAX_BUCKETS))
+ hbkts = 0;
+
+ lbkts = rte_align32prevpow2(timr->nb_bkts);
+ tck_nsec = RTE_ALIGN_MUL_CEIL((timr->max_tout / (lbkts - 1)), 10);
+
+ if ((tck_nsec < 1000 || hbkts > TIM_MAX_BUCKETS))
+ lbkts = 0;
+
+ if (!hbkts && !lbkts)
+ return 0;
+
+ if (!hbkts) {
+ timr->nb_bkts = lbkts;
+ goto end;
+ } else if (!lbkts) {
+ timr->nb_bkts = hbkts;
+ goto end;
+ }
+
+ timr->nb_bkts = (hbkts - timr->nb_bkts) <
+ (timr->nb_bkts - lbkts) ? hbkts : lbkts;
+end:
+ timr->get_target_bkt = bkt_and;
+ timr->tck_nsec = RTE_ALIGN_MUL_CEIL((timr->max_tout /
+ (timr->nb_bkts - 1)), 10);
+ return 1;
+}
+
static int
timvf_ring_start(const struct rte_event_timer_adapter *adptr)
{
int ret;
+ uint8_t use_fpa = 0;
uint64_t interval;
+ uintptr_t pool;
struct timvf_ctrl_reg rctrl;
struct timvf_mbox_dev_info dinfo;
struct timvf_ring *timr = adptr->data->adapter_priv;
return -EINVAL;
}
+ if (!strcmp(rte_mbuf_best_mempool_ops(), "octeontx_fpavf"))
+ use_fpa = 1;
+
/*CTRL0 register.*/
rctrl.rctrl0 = interval;
rctrl.rctrl2 = (uint64_t)(TIM_CHUNK_SIZE / 16) << 40;
+ if (use_fpa) {
+ pool = (uintptr_t)((struct rte_mempool *)
+ timr->chunk_pool)->pool_id;
+ ret = octeontx_fpa_bufpool_gaura(pool);
+ if (ret < 0) {
+ timvf_log_dbg("Unable to get gaura id");
+ ret = -ENOMEM;
+ goto error;
+ }
+ timvf_write64((uint64_t)ret,
+ (uint8_t *)timr->vbar0 + TIM_VRING_AURA);
+ } else {
+ rctrl.rctrl1 |= 1ull << 43 /* ENA_DFB (Enable don't free) */;
+ }
+
timvf_write64((uintptr_t)timr->bkt,
(uint8_t *)timr->vbar0 + TIM_VRING_BASE);
- timvf_set_chunk_refill(timr);
+ timvf_set_chunk_refill(timr, use_fpa);
if (timvf_ring_conf_set(&rctrl, timr->tim_ring_id)) {
ret = -EACCES;
goto error;
static int
timvf_ring_create(struct rte_event_timer_adapter *adptr)
{
- char pool_name[25];
- int ret;
- uint64_t nb_timers;
struct rte_event_timer_adapter_conf *rcfg = &adptr->data->conf;
+ uint16_t free_idx = UINT16_MAX;
+ unsigned int mp_flags = 0;
+ struct ssovf_evdev *edev;
struct timvf_ring *timr;
- struct timvf_info tinfo;
const char *mempool_ops;
- unsigned int mp_flags = 0;
-
- if (timvf_info(&tinfo) < 0)
- return -ENODEV;
+ uint8_t tim_ring_id;
+ char pool_name[25];
+ int i, ret;
- if (adptr->data->id >= tinfo.total_timvfs)
+ tim_ring_id = timvf_get_ring();
+ if (tim_ring_id == UINT8_MAX)
return -ENODEV;
+ edev = ssovf_pmd_priv(event_dev);
timr = rte_zmalloc("octeontx_timvf_priv",
sizeof(struct timvf_ring), 0);
if (timr == NULL)
}
timr->clk_src = (int) rcfg->clk_src;
- timr->tim_ring_id = adptr->data->id;
- timr->tck_nsec = rcfg->timer_tick_ns;
+ timr->tim_ring_id = tim_ring_id;
+ timr->tck_nsec = RTE_ALIGN_MUL_CEIL(rcfg->timer_tick_ns, 10);
timr->max_tout = rcfg->max_tmo_ns;
timr->nb_bkts = (timr->max_tout / timr->tck_nsec);
timr->vbar0 = timvf_bar(timr->tim_ring_id, 0);
timr->bkt_pos = (uint8_t *)timr->vbar0 + TIM_VRING_REL;
- nb_timers = rcfg->nb_timers;
+ timr->nb_timers = rcfg->nb_timers;
timr->get_target_bkt = bkt_mod;
- timr->nb_chunks = nb_timers / nb_chunk_slots;
+ if (edev->available_events < timr->nb_timers) {
+ timvf_log_err(
+ "Max available events %"PRIu32" requested timer events %"PRIu64"",
+ edev->available_events, timr->nb_timers);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < edev->tim_ring_cnt; i++) {
+ if (edev->tim_ring_ids[i] == UINT16_MAX)
+ free_idx = i;
+ }
+
+ if (free_idx == UINT16_MAX) {
+ void *old_ptr;
+
+ edev->tim_ring_cnt++;
+ old_ptr = edev->tim_ring_ids;
+ edev->tim_ring_ids =
+ rte_realloc(edev->tim_ring_ids,
+ sizeof(uint16_t) * edev->tim_ring_cnt, 0);
+ if (edev->tim_ring_ids == NULL) {
+ edev->tim_ring_ids = old_ptr;
+ edev->tim_ring_cnt--;
+ return -ENOMEM;
+ }
+
+ edev->available_events -= timr->nb_timers;
+ } else {
+ edev->tim_ring_ids[free_idx] = tim_ring_id;
+ edev->available_events -= timr->nb_timers;
+ }
+
+ timr->nb_chunks = timr->nb_timers / nb_chunk_slots;
+
+ /* Try to optimize the bucket parameters. */
+ if ((rcfg->flags & RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES)
+ && !rte_is_power_of_2(timr->nb_bkts)) {
+ if (optimize_bucket_parameters(timr)) {
+ timvf_log_info("Optimized configured values");
+ timvf_log_dbg("nb_bkts : %"PRIu32"", timr->nb_bkts);
+ timvf_log_dbg("tck_nsec : %"PRIu64"", timr->tck_nsec);
+ } else
+ timvf_log_info("Failed to Optimize configured values");
+ }
if (rcfg->flags & RTE_EVENT_TIMER_ADAPTER_F_SP_PUT) {
- mp_flags = MEMPOOL_F_SP_PUT | MEMPOOL_F_SC_GET;
+ mp_flags = RTE_MEMPOOL_F_SP_PUT | RTE_MEMPOOL_F_SC_GET;
timvf_log_info("Using single producer mode");
}
if (timr->bkt == NULL)
goto mem_err;
- snprintf(pool_name, 30, "timvf_chunk_pool%d", timr->tim_ring_id);
+ snprintf(pool_name, sizeof(pool_name), "timvf_chunk_pool%d",
+ timr->tim_ring_id);
timr->chunk_pool = (void *)rte_mempool_create_empty(pool_name,
timr->nb_chunks, TIM_CHUNK_SIZE, 0, 0, rte_socket_id(),
mp_flags);
timvf_ring_free(struct rte_event_timer_adapter *adptr)
{
struct timvf_ring *timr = adptr->data->adapter_priv;
+ struct ssovf_evdev *edev;
+ int i;
+
+ edev = ssovf_pmd_priv(event_dev);
+ for (i = 0; i < edev->tim_ring_cnt; i++) {
+ if (edev->tim_ring_ids[i] == timr->tim_ring_id) {
+ edev->available_events += timr->nb_timers;
+ edev->tim_ring_ids[i] = UINT16_MAX;
+ break;
+ }
+ }
+
rte_mempool_free(timr->chunk_pool);
rte_free(timr->bkt);
+ timvf_release_ring(timr->tim_ring_id);
rte_free(adptr->data->adapter_priv);
return 0;
}
return 0;
}
-static struct rte_event_timer_adapter_ops timvf_ops = {
- .init = timvf_ring_create,
- .uninit = timvf_ring_free,
- .start = timvf_ring_start,
- .stop = timvf_ring_stop,
- .get_info = timvf_ring_info_get,
+static struct event_timer_adapter_ops timvf_ops = {
+ .init = timvf_ring_create,
+ .uninit = timvf_ring_free,
+ .start = timvf_ring_start,
+ .stop = timvf_ring_stop,
+ .get_info = timvf_ring_info_get,
};
int
timvf_timer_adapter_caps_get(const struct rte_eventdev *dev, uint64_t flags,
- uint32_t *caps, const struct rte_event_timer_adapter_ops **ops,
- uint8_t enable_stats)
+ uint32_t *caps,
+ const struct event_timer_adapter_ops **ops,
+ uint8_t enable_stats)
{
RTE_SET_USED(dev);
timvf_timer_arm_burst_mp_stats :
timvf_timer_arm_burst_mp;
+ timvf_ops.arm_tmo_tick_burst = enable_stats ?
+ timvf_timer_arm_tmo_brst_stats :
+ timvf_timer_arm_tmo_brst;
timvf_ops.cancel_burst = timvf_timer_cancel_burst;
*caps = RTE_EVENT_TIMER_ADAPTER_CAP_INTERNAL_PORT;
*ops = &timvf_ops;
return 0;
}
+
+void
+timvf_set_eventdevice(struct rte_eventdev *dev)
+{
+ event_dev = dev;
+}