net/ice: fix Tx threshold setup
[dpdk.git] / drivers / event / octeontx / timvf_evdev.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2017 Cavium, Inc
3  */
4
5 #include "timvf_evdev.h"
6
7 int otx_logtype_timvf;
8
9 RTE_INIT(otx_timvf_init_log)
10 {
11         otx_logtype_timvf = rte_log_register("pmd.event.octeontx.timer");
12         if (otx_logtype_timvf >= 0)
13                 rte_log_set_level(otx_logtype_timvf, RTE_LOG_NOTICE);
14 }
15
16 struct __rte_packed timvf_mbox_dev_info {
17         uint64_t ring_active[4];
18         uint64_t clk_freq;
19 };
20
21 /* Response messages */
22 enum {
23         MBOX_RET_SUCCESS,
24         MBOX_RET_INVALID,
25         MBOX_RET_INTERNAL_ERR,
26 };
27
28 static int
29 timvf_mbox_dev_info_get(struct timvf_mbox_dev_info *info)
30 {
31         struct octeontx_mbox_hdr hdr = {0};
32         uint16_t len = sizeof(struct timvf_mbox_dev_info);
33
34         hdr.coproc = TIM_COPROC;
35         hdr.msg = TIM_GET_DEV_INFO;
36         hdr.vfid = 0; /* TIM DEV is always 0. TIM RING ID changes. */
37
38         memset(info, 0, len);
39         return octeontx_mbox_send(&hdr, NULL, 0, info, len);
40 }
41
42 static void
43 timvf_ring_info_get(const struct rte_event_timer_adapter *adptr,
44                 struct rte_event_timer_adapter_info *adptr_info)
45 {
46         struct timvf_ring *timr = adptr->data->adapter_priv;
47         adptr_info->max_tmo_ns = timr->max_tout;
48         adptr_info->min_resolution_ns = timr->tck_nsec;
49         rte_memcpy(&adptr_info->conf, &adptr->data->conf,
50                         sizeof(struct rte_event_timer_adapter_conf));
51 }
52
53 static int
54 timvf_ring_conf_set(struct timvf_ctrl_reg *rctl, uint8_t ring_id)
55 {
56         struct octeontx_mbox_hdr hdr = {0};
57         uint16_t len = sizeof(struct timvf_ctrl_reg);
58         int ret;
59
60         hdr.coproc = TIM_COPROC;
61         hdr.msg = TIM_SET_RING_INFO;
62         hdr.vfid = ring_id;
63
64         ret = octeontx_mbox_send(&hdr, rctl, len, NULL, 0);
65         if (ret < 0 || hdr.res_code != MBOX_RET_SUCCESS)
66                 return -EACCES;
67         return 0;
68 }
69
70 static int
71 timvf_get_start_cyc(uint64_t *now, uint8_t ring_id)
72 {
73         struct octeontx_mbox_hdr hdr = {0};
74
75         hdr.coproc = TIM_COPROC;
76         hdr.msg = TIM_RING_START_CYC_GET;
77         hdr.vfid = ring_id;
78         *now = 0;
79         return octeontx_mbox_send(&hdr, NULL, 0, now, sizeof(uint64_t));
80 }
81
82 static int
83 optimize_bucket_parameters(struct timvf_ring *timr)
84 {
85         uint32_t hbkts;
86         uint32_t lbkts;
87         uint64_t tck_nsec;
88
89         hbkts = rte_align32pow2(timr->nb_bkts);
90         tck_nsec = RTE_ALIGN_MUL_CEIL(timr->max_tout / (hbkts - 1), 10);
91
92         if ((tck_nsec < 1000 || hbkts > TIM_MAX_BUCKETS))
93                 hbkts = 0;
94
95         lbkts = rte_align32prevpow2(timr->nb_bkts);
96         tck_nsec = RTE_ALIGN_MUL_CEIL((timr->max_tout / (lbkts - 1)), 10);
97
98         if ((tck_nsec < 1000 || hbkts > TIM_MAX_BUCKETS))
99                 lbkts = 0;
100
101         if (!hbkts && !lbkts)
102                 return 0;
103
104         if (!hbkts) {
105                 timr->nb_bkts = lbkts;
106                 goto end;
107         } else if (!lbkts) {
108                 timr->nb_bkts = hbkts;
109                 goto end;
110         }
111
112         timr->nb_bkts = (hbkts - timr->nb_bkts) <
113                 (timr->nb_bkts - lbkts) ? hbkts : lbkts;
114 end:
115         timr->get_target_bkt = bkt_and;
116         timr->tck_nsec = RTE_ALIGN_MUL_CEIL((timr->max_tout /
117                                 (timr->nb_bkts - 1)), 10);
118         return 1;
119 }
120
121 static int
122 timvf_ring_start(const struct rte_event_timer_adapter *adptr)
123 {
124         int ret;
125         uint8_t use_fpa = 0;
126         uint64_t interval;
127         uintptr_t pool;
128         struct timvf_ctrl_reg rctrl;
129         struct timvf_mbox_dev_info dinfo;
130         struct timvf_ring *timr = adptr->data->adapter_priv;
131
132         ret = timvf_mbox_dev_info_get(&dinfo);
133         if (ret < 0 || ret != sizeof(struct timvf_mbox_dev_info))
134                 return -EINVAL;
135
136         /* Calculate the interval cycles according to clock source. */
137         switch (timr->clk_src) {
138         case TIM_CLK_SRC_SCLK:
139                 interval = NSEC2CLK(timr->tck_nsec, dinfo.clk_freq);
140                 break;
141         case TIM_CLK_SRC_GPIO:
142                 /* GPIO doesn't work on tck_nsec. */
143                 interval = 0;
144                 break;
145         case TIM_CLK_SRC_GTI:
146                 interval = NSEC2CLK(timr->tck_nsec, dinfo.clk_freq);
147                 break;
148         case TIM_CLK_SRC_PTP:
149                 interval = NSEC2CLK(timr->tck_nsec, dinfo.clk_freq);
150                 break;
151         default:
152                 timvf_log_err("Unsupported clock source configured %d",
153                                 timr->clk_src);
154                 return -EINVAL;
155         }
156
157         if (!strcmp(rte_mbuf_best_mempool_ops(), "octeontx_fpavf"))
158                 use_fpa = 1;
159
160         /*CTRL0 register.*/
161         rctrl.rctrl0 = interval;
162
163         /*CTRL1 register.*/
164         rctrl.rctrl1 =  (uint64_t)(timr->clk_src) << 51 |
165                 1ull << 48 /* LOCK_EN (Enable hw bucket lock mechanism) */ |
166                 1ull << 47 /* ENA */ |
167                 1ull << 44 /* ENA_LDWB */ |
168                 (timr->nb_bkts - 1);
169
170         rctrl.rctrl2 = (uint64_t)(TIM_CHUNK_SIZE / 16) << 40;
171
172         if (use_fpa) {
173                 pool = (uintptr_t)((struct rte_mempool *)
174                                 timr->chunk_pool)->pool_id;
175                 ret = octeontx_fpa_bufpool_gaura(pool);
176                 if (ret < 0) {
177                         timvf_log_dbg("Unable to get gaura id");
178                         ret = -ENOMEM;
179                         goto error;
180                 }
181                 timvf_write64((uint64_t)ret,
182                                 (uint8_t *)timr->vbar0 + TIM_VRING_AURA);
183         } else {
184                 rctrl.rctrl1 |= 1ull << 43 /* ENA_DFB (Enable don't free) */;
185         }
186
187         timvf_write64((uintptr_t)timr->bkt,
188                         (uint8_t *)timr->vbar0 + TIM_VRING_BASE);
189         timvf_set_chunk_refill(timr, use_fpa);
190         if (timvf_ring_conf_set(&rctrl, timr->tim_ring_id)) {
191                 ret = -EACCES;
192                 goto error;
193         }
194
195         if (timvf_get_start_cyc(&timr->ring_start_cyc,
196                                 timr->tim_ring_id) < 0) {
197                 ret = -EACCES;
198                 goto error;
199         }
200         timr->tck_int = NSEC2CLK(timr->tck_nsec, rte_get_timer_hz());
201         timr->fast_div = rte_reciprocal_value_u64(timr->tck_int);
202         timvf_log_info("nb_bkts %d min_ns %"PRIu64" min_cyc %"PRIu64""
203                         " maxtmo %"PRIu64"\n",
204                         timr->nb_bkts, timr->tck_nsec, interval,
205                         timr->max_tout);
206
207         return 0;
208 error:
209         rte_free(timr->bkt);
210         rte_mempool_free(timr->chunk_pool);
211         return ret;
212 }
213
214 static int
215 timvf_ring_stop(const struct rte_event_timer_adapter *adptr)
216 {
217         struct timvf_ring *timr = adptr->data->adapter_priv;
218         struct timvf_ctrl_reg rctrl = {0};
219         rctrl.rctrl0 = timvf_read64((uint8_t *)timr->vbar0 + TIM_VRING_CTL0);
220         rctrl.rctrl1 = timvf_read64((uint8_t *)timr->vbar0 + TIM_VRING_CTL1);
221         rctrl.rctrl1 &= ~(1ull << 47); /* Disable */
222         rctrl.rctrl2 = timvf_read64((uint8_t *)timr->vbar0 + TIM_VRING_CTL2);
223
224         if (timvf_ring_conf_set(&rctrl, timr->tim_ring_id))
225                 return -EACCES;
226         return 0;
227 }
228
229 static int
230 timvf_ring_create(struct rte_event_timer_adapter *adptr)
231 {
232         char pool_name[25];
233         int ret;
234         uint64_t nb_timers;
235         struct rte_event_timer_adapter_conf *rcfg = &adptr->data->conf;
236         struct timvf_ring *timr;
237         struct timvf_info tinfo;
238         const char *mempool_ops;
239         unsigned int mp_flags = 0;
240
241         if (timvf_info(&tinfo) < 0)
242                 return -ENODEV;
243
244         if (adptr->data->id >= tinfo.total_timvfs)
245                 return -ENODEV;
246
247         timr = rte_zmalloc("octeontx_timvf_priv",
248                         sizeof(struct timvf_ring), 0);
249         if (timr == NULL)
250                 return -ENOMEM;
251
252         adptr->data->adapter_priv = timr;
253         /* Check config parameters. */
254         if ((rcfg->clk_src != RTE_EVENT_TIMER_ADAPTER_CPU_CLK) &&
255                         (!rcfg->timer_tick_ns ||
256                          rcfg->timer_tick_ns < TIM_MIN_INTERVAL)) {
257                 timvf_log_err("Too low timer ticks");
258                 goto cfg_err;
259         }
260
261         timr->clk_src = (int) rcfg->clk_src;
262         timr->tim_ring_id = adptr->data->id;
263         timr->tck_nsec = RTE_ALIGN_MUL_CEIL(rcfg->timer_tick_ns, 10);
264         timr->max_tout = rcfg->max_tmo_ns;
265         timr->nb_bkts = (timr->max_tout / timr->tck_nsec);
266         timr->vbar0 = timvf_bar(timr->tim_ring_id, 0);
267         timr->bkt_pos = (uint8_t *)timr->vbar0 + TIM_VRING_REL;
268         nb_timers = rcfg->nb_timers;
269         timr->get_target_bkt = bkt_mod;
270
271         timr->nb_chunks = nb_timers / nb_chunk_slots;
272
273         /* Try to optimize the bucket parameters. */
274         if ((rcfg->flags & RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES)
275                         && !rte_is_power_of_2(timr->nb_bkts)) {
276                 if (optimize_bucket_parameters(timr)) {
277                         timvf_log_info("Optimized configured values");
278                         timvf_log_dbg("nb_bkts  : %"PRIu32"", timr->nb_bkts);
279                         timvf_log_dbg("tck_nsec : %"PRIu64"", timr->tck_nsec);
280                 } else
281                         timvf_log_info("Failed to Optimize configured values");
282         }
283
284         if (rcfg->flags & RTE_EVENT_TIMER_ADAPTER_F_SP_PUT) {
285                 mp_flags = MEMPOOL_F_SP_PUT | MEMPOOL_F_SC_GET;
286                 timvf_log_info("Using single producer mode");
287         }
288
289         timr->bkt = rte_zmalloc("octeontx_timvf_bucket",
290                         (timr->nb_bkts) * sizeof(struct tim_mem_bucket),
291                         0);
292         if (timr->bkt == NULL)
293                 goto mem_err;
294
295         snprintf(pool_name, sizeof(pool_name), "timvf_chunk_pool%d",
296                         timr->tim_ring_id);
297         timr->chunk_pool = (void *)rte_mempool_create_empty(pool_name,
298                         timr->nb_chunks, TIM_CHUNK_SIZE, 0, 0, rte_socket_id(),
299                         mp_flags);
300
301         if (!timr->chunk_pool) {
302                 rte_free(timr->bkt);
303                 timvf_log_err("Unable to create chunkpool.");
304                 return -ENOMEM;
305         }
306
307         mempool_ops = rte_mbuf_best_mempool_ops();
308         ret = rte_mempool_set_ops_byname(timr->chunk_pool,
309                         mempool_ops, NULL);
310
311         if (ret != 0) {
312                 timvf_log_err("Unable to set chunkpool ops.");
313                 goto mem_err;
314         }
315
316         ret = rte_mempool_populate_default(timr->chunk_pool);
317         if (ret < 0) {
318                 timvf_log_err("Unable to set populate chunkpool.");
319                 goto mem_err;
320         }
321         timvf_write64(0, (uint8_t *)timr->vbar0 + TIM_VRING_BASE);
322         timvf_write64(0, (uint8_t *)timr->vbar0 + TIM_VF_NRSPERR_INT);
323         timvf_write64(0, (uint8_t *)timr->vbar0 + TIM_VF_NRSPERR_INT_W1S);
324         timvf_write64(0x7, (uint8_t *)timr->vbar0 + TIM_VF_NRSPERR_ENA_W1C);
325         timvf_write64(0x7, (uint8_t *)timr->vbar0 + TIM_VF_NRSPERR_ENA_W1S);
326
327         return 0;
328 mem_err:
329         rte_free(timr);
330         return -ENOMEM;
331 cfg_err:
332         rte_free(timr);
333         return -EINVAL;
334 }
335
336 static int
337 timvf_ring_free(struct rte_event_timer_adapter *adptr)
338 {
339         struct timvf_ring *timr = adptr->data->adapter_priv;
340         rte_mempool_free(timr->chunk_pool);
341         rte_free(timr->bkt);
342         rte_free(adptr->data->adapter_priv);
343         return 0;
344 }
345
346 static int
347 timvf_stats_get(const struct rte_event_timer_adapter *adapter,
348                 struct rte_event_timer_adapter_stats *stats)
349 {
350         struct timvf_ring *timr = adapter->data->adapter_priv;
351         uint64_t bkt_cyc = rte_rdtsc() - timr->ring_start_cyc;
352
353         stats->evtim_exp_count = timr->tim_arm_cnt;
354         stats->ev_enq_count = timr->tim_arm_cnt;
355         stats->adapter_tick_count = rte_reciprocal_divide_u64(bkt_cyc,
356                                 &timr->fast_div);
357         return 0;
358 }
359
360 static int
361 timvf_stats_reset(const struct rte_event_timer_adapter *adapter)
362 {
363         struct timvf_ring *timr = adapter->data->adapter_priv;
364
365         timr->tim_arm_cnt = 0;
366         return 0;
367 }
368
369 static struct rte_event_timer_adapter_ops timvf_ops = {
370         .init           = timvf_ring_create,
371         .uninit         = timvf_ring_free,
372         .start          = timvf_ring_start,
373         .stop           = timvf_ring_stop,
374         .get_info       = timvf_ring_info_get,
375 };
376
377 int
378 timvf_timer_adapter_caps_get(const struct rte_eventdev *dev, uint64_t flags,
379                 uint32_t *caps, const struct rte_event_timer_adapter_ops **ops,
380                 uint8_t enable_stats)
381 {
382         RTE_SET_USED(dev);
383
384         if (enable_stats) {
385                 timvf_ops.stats_get   = timvf_stats_get;
386                 timvf_ops.stats_reset = timvf_stats_reset;
387         }
388
389         if (flags & RTE_EVENT_TIMER_ADAPTER_F_SP_PUT)
390                 timvf_ops.arm_burst = enable_stats ?
391                         timvf_timer_arm_burst_sp_stats :
392                         timvf_timer_arm_burst_sp;
393         else
394                 timvf_ops.arm_burst = enable_stats ?
395                         timvf_timer_arm_burst_mp_stats :
396                         timvf_timer_arm_burst_mp;
397
398         timvf_ops.arm_tmo_tick_burst = enable_stats ?
399                 timvf_timer_arm_tmo_brst_stats :
400                 timvf_timer_arm_tmo_brst;
401         timvf_ops.cancel_burst = timvf_timer_cancel_burst;
402         *caps = RTE_EVENT_TIMER_ADAPTER_CAP_INTERNAL_PORT;
403         *ops = &timvf_ops;
404         return 0;
405 }