net/ice/base: add accessors to get/set time reference
[dpdk.git] / drivers / event / octeontx2 / otx2_tim_evdev.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2019 Marvell International Ltd.
3  */
4
5 #include <rte_kvargs.h>
6 #include <rte_malloc.h>
7 #include <rte_mbuf_pool_ops.h>
8
9 #include "otx2_evdev.h"
10 #include "otx2_tim_evdev.h"
11
12 static struct rte_event_timer_adapter_ops otx2_tim_ops;
13
14 static inline int
15 tim_get_msix_offsets(void)
16 {
17         struct otx2_tim_evdev *dev = tim_priv_get();
18         struct otx2_mbox *mbox = dev->mbox;
19         struct msix_offset_rsp *msix_rsp;
20         int i, rc;
21
22         /* Get TIM MSIX vector offsets */
23         otx2_mbox_alloc_msg_msix_offset(mbox);
24         rc = otx2_mbox_process_msg(mbox, (void *)&msix_rsp);
25
26         for (i = 0; i < dev->nb_rings; i++)
27                 dev->tim_msixoff[i] = msix_rsp->timlf_msixoff[i];
28
29         return rc;
30 }
31
32 static void
33 tim_set_fp_ops(struct otx2_tim_ring *tim_ring)
34 {
35         uint8_t prod_flag = !tim_ring->prod_type_sp;
36
37         /* [DFB/FB] [SP][MP]*/
38         const rte_event_timer_arm_burst_t arm_burst[2][2][2] = {
39 #define FP(_name, _f3, _f2, _f1, flags)                                        \
40         [_f3][_f2][_f1] = otx2_tim_arm_burst_##_name,
41                 TIM_ARM_FASTPATH_MODES
42 #undef FP
43         };
44
45         const rte_event_timer_arm_tmo_tick_burst_t arm_tmo_burst[2][2] = {
46 #define FP(_name, _f2, _f1, flags)                                             \
47         [_f2][_f1] = otx2_tim_arm_tmo_tick_burst_##_name,
48                 TIM_ARM_TMO_FASTPATH_MODES
49 #undef FP
50         };
51
52         otx2_tim_ops.arm_burst =
53                 arm_burst[tim_ring->enable_stats][tim_ring->ena_dfb][prod_flag];
54         otx2_tim_ops.arm_tmo_tick_burst =
55                 arm_tmo_burst[tim_ring->enable_stats][tim_ring->ena_dfb];
56         otx2_tim_ops.cancel_burst = otx2_tim_timer_cancel_burst;
57 }
58
59 static void
60 otx2_tim_ring_info_get(const struct rte_event_timer_adapter *adptr,
61                        struct rte_event_timer_adapter_info *adptr_info)
62 {
63         struct otx2_tim_ring *tim_ring = adptr->data->adapter_priv;
64
65         adptr_info->max_tmo_ns = tim_ring->max_tout;
66         adptr_info->min_resolution_ns = tim_ring->ena_periodic ?
67                 tim_ring->max_tout : tim_ring->tck_nsec;
68         rte_memcpy(&adptr_info->conf, &adptr->data->conf,
69                    sizeof(struct rte_event_timer_adapter_conf));
70 }
71
72 static int
73 tim_chnk_pool_create(struct otx2_tim_ring *tim_ring,
74                      struct rte_event_timer_adapter_conf *rcfg)
75 {
76         unsigned int cache_sz = (tim_ring->nb_chunks / 1.5);
77         unsigned int mp_flags = 0;
78         char pool_name[25];
79         int rc;
80
81         cache_sz /= rte_lcore_count();
82         /* Create chunk pool. */
83         if (rcfg->flags & RTE_EVENT_TIMER_ADAPTER_F_SP_PUT) {
84                 mp_flags = MEMPOOL_F_SP_PUT | MEMPOOL_F_SC_GET;
85                 otx2_tim_dbg("Using single producer mode");
86                 tim_ring->prod_type_sp = true;
87         }
88
89         snprintf(pool_name, sizeof(pool_name), "otx2_tim_chunk_pool%d",
90                  tim_ring->ring_id);
91
92         if (cache_sz > RTE_MEMPOOL_CACHE_MAX_SIZE)
93                 cache_sz = RTE_MEMPOOL_CACHE_MAX_SIZE;
94
95         cache_sz = cache_sz != 0 ? cache_sz : 2;
96         tim_ring->nb_chunks += (cache_sz * rte_lcore_count());
97         if (!tim_ring->disable_npa) {
98                 tim_ring->chunk_pool = rte_mempool_create_empty(pool_name,
99                                 tim_ring->nb_chunks, tim_ring->chunk_sz,
100                                 cache_sz, 0, rte_socket_id(), mp_flags);
101
102                 if (tim_ring->chunk_pool == NULL) {
103                         otx2_err("Unable to create chunkpool.");
104                         return -ENOMEM;
105                 }
106
107                 rc = rte_mempool_set_ops_byname(tim_ring->chunk_pool,
108                                                 rte_mbuf_platform_mempool_ops(),
109                                                 NULL);
110                 if (rc < 0) {
111                         otx2_err("Unable to set chunkpool ops");
112                         goto free;
113                 }
114
115                 rc = rte_mempool_populate_default(tim_ring->chunk_pool);
116                 if (rc < 0) {
117                         otx2_err("Unable to set populate chunkpool.");
118                         goto free;
119                 }
120                 tim_ring->aura = npa_lf_aura_handle_to_aura(
121                                 tim_ring->chunk_pool->pool_id);
122                 tim_ring->ena_dfb = tim_ring->ena_periodic ? 1 : 0;
123         } else {
124                 tim_ring->chunk_pool = rte_mempool_create(pool_name,
125                                 tim_ring->nb_chunks, tim_ring->chunk_sz,
126                                 cache_sz, 0, NULL, NULL, NULL, NULL,
127                                 rte_socket_id(),
128                                 mp_flags);
129                 if (tim_ring->chunk_pool == NULL) {
130                         otx2_err("Unable to create chunkpool.");
131                         return -ENOMEM;
132                 }
133                 tim_ring->ena_dfb = 1;
134         }
135
136         return 0;
137
138 free:
139         rte_mempool_free(tim_ring->chunk_pool);
140         return rc;
141 }
142
143 static void
144 tim_err_desc(int rc)
145 {
146         switch (rc) {
147         case TIM_AF_NO_RINGS_LEFT:
148                 otx2_err("Unable to allocat new TIM ring.");
149                 break;
150         case TIM_AF_INVALID_NPA_PF_FUNC:
151                 otx2_err("Invalid NPA pf func.");
152                 break;
153         case TIM_AF_INVALID_SSO_PF_FUNC:
154                 otx2_err("Invalid SSO pf func.");
155                 break;
156         case TIM_AF_RING_STILL_RUNNING:
157                 otx2_tim_dbg("Ring busy.");
158                 break;
159         case TIM_AF_LF_INVALID:
160                 otx2_err("Invalid Ring id.");
161                 break;
162         case TIM_AF_CSIZE_NOT_ALIGNED:
163                 otx2_err("Chunk size specified needs to be multiple of 16.");
164                 break;
165         case TIM_AF_CSIZE_TOO_SMALL:
166                 otx2_err("Chunk size too small.");
167                 break;
168         case TIM_AF_CSIZE_TOO_BIG:
169                 otx2_err("Chunk size too big.");
170                 break;
171         case TIM_AF_INTERVAL_TOO_SMALL:
172                 otx2_err("Bucket traversal interval too small.");
173                 break;
174         case TIM_AF_INVALID_BIG_ENDIAN_VALUE:
175                 otx2_err("Invalid Big endian value.");
176                 break;
177         case TIM_AF_INVALID_CLOCK_SOURCE:
178                 otx2_err("Invalid Clock source specified.");
179                 break;
180         case TIM_AF_GPIO_CLK_SRC_NOT_ENABLED:
181                 otx2_err("GPIO clock source not enabled.");
182                 break;
183         case TIM_AF_INVALID_BSIZE:
184                 otx2_err("Invalid bucket size.");
185                 break;
186         case TIM_AF_INVALID_ENABLE_PERIODIC:
187                 otx2_err("Invalid bucket size.");
188                 break;
189         case TIM_AF_INVALID_ENABLE_DONTFREE:
190                 otx2_err("Invalid Don't free value.");
191                 break;
192         case TIM_AF_ENA_DONTFRE_NSET_PERIODIC:
193                 otx2_err("Don't free bit not set when periodic is enabled.");
194                 break;
195         case TIM_AF_RING_ALREADY_DISABLED:
196                 otx2_err("Ring already stopped");
197                 break;
198         default:
199                 otx2_err("Unknown Error.");
200         }
201 }
202
203 static int
204 otx2_tim_ring_create(struct rte_event_timer_adapter *adptr)
205 {
206         struct rte_event_timer_adapter_conf *rcfg = &adptr->data->conf;
207         struct otx2_tim_evdev *dev = tim_priv_get();
208         struct otx2_tim_ring *tim_ring;
209         struct tim_config_req *cfg_req;
210         struct tim_ring_req *free_req;
211         struct tim_lf_alloc_req *req;
212         struct tim_lf_alloc_rsp *rsp;
213         uint8_t is_periodic;
214         int i, rc;
215
216         if (dev == NULL)
217                 return -ENODEV;
218
219         if (adptr->data->id >= dev->nb_rings)
220                 return -ENODEV;
221
222         req = otx2_mbox_alloc_msg_tim_lf_alloc(dev->mbox);
223         req->npa_pf_func = otx2_npa_pf_func_get();
224         req->sso_pf_func = otx2_sso_pf_func_get();
225         req->ring = adptr->data->id;
226
227         rc = otx2_mbox_process_msg(dev->mbox, (void **)&rsp);
228         if (rc < 0) {
229                 tim_err_desc(rc);
230                 return -ENODEV;
231         }
232
233         if (NSEC2TICK(RTE_ALIGN_MUL_CEIL(rcfg->timer_tick_ns, 10),
234                       rsp->tenns_clk) < OTX2_TIM_MIN_TMO_TKS) {
235                 if (rcfg->flags & RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES)
236                         rcfg->timer_tick_ns = TICK2NSEC(OTX2_TIM_MIN_TMO_TKS,
237                                         rsp->tenns_clk);
238                 else {
239                         rc = -ERANGE;
240                         goto rng_mem_err;
241                 }
242         }
243
244         is_periodic = 0;
245         if (rcfg->flags & RTE_EVENT_TIMER_ADAPTER_F_PERIODIC) {
246                 if (rcfg->max_tmo_ns &&
247                     rcfg->max_tmo_ns != rcfg->timer_tick_ns) {
248                         rc = -ERANGE;
249                         goto rng_mem_err;
250                 }
251
252                 /* Use 2 buckets to avoid contention */
253                 rcfg->max_tmo_ns = rcfg->timer_tick_ns;
254                 rcfg->timer_tick_ns /= 2;
255                 is_periodic = 1;
256         }
257
258         tim_ring = rte_zmalloc("otx2_tim_prv", sizeof(struct otx2_tim_ring), 0);
259         if (tim_ring == NULL) {
260                 rc =  -ENOMEM;
261                 goto rng_mem_err;
262         }
263
264         adptr->data->adapter_priv = tim_ring;
265
266         tim_ring->tenns_clk_freq = rsp->tenns_clk;
267         tim_ring->clk_src = (int)rcfg->clk_src;
268         tim_ring->ring_id = adptr->data->id;
269         tim_ring->tck_nsec = RTE_ALIGN_MUL_CEIL(rcfg->timer_tick_ns, 10);
270         tim_ring->max_tout = is_periodic ?
271                 rcfg->timer_tick_ns * 2 : rcfg->max_tmo_ns;
272         tim_ring->nb_bkts = (tim_ring->max_tout / tim_ring->tck_nsec);
273         tim_ring->chunk_sz = dev->chunk_sz;
274         tim_ring->nb_timers = rcfg->nb_timers;
275         tim_ring->disable_npa = dev->disable_npa;
276         tim_ring->ena_periodic = is_periodic;
277         tim_ring->enable_stats = dev->enable_stats;
278
279         for (i = 0; i < dev->ring_ctl_cnt ; i++) {
280                 struct otx2_tim_ctl *ring_ctl = &dev->ring_ctl_data[i];
281
282                 if (ring_ctl->ring == tim_ring->ring_id) {
283                         tim_ring->chunk_sz = ring_ctl->chunk_slots ?
284                                 ((uint32_t)(ring_ctl->chunk_slots + 1) *
285                                  OTX2_TIM_CHUNK_ALIGNMENT) : tim_ring->chunk_sz;
286                         tim_ring->enable_stats = ring_ctl->enable_stats;
287                         tim_ring->disable_npa = ring_ctl->disable_npa;
288                 }
289         }
290
291         if (tim_ring->disable_npa) {
292                 tim_ring->nb_chunks =
293                         tim_ring->nb_timers /
294                         OTX2_TIM_NB_CHUNK_SLOTS(tim_ring->chunk_sz);
295                 tim_ring->nb_chunks = tim_ring->nb_chunks * tim_ring->nb_bkts;
296         } else {
297                 tim_ring->nb_chunks = tim_ring->nb_timers;
298         }
299         tim_ring->nb_chunk_slots = OTX2_TIM_NB_CHUNK_SLOTS(tim_ring->chunk_sz);
300         tim_ring->bkt = rte_zmalloc("otx2_tim_bucket", (tim_ring->nb_bkts) *
301                                     sizeof(struct otx2_tim_bkt),
302                                     RTE_CACHE_LINE_SIZE);
303         if (tim_ring->bkt == NULL)
304                 goto bkt_mem_err;
305
306         rc = tim_chnk_pool_create(tim_ring, rcfg);
307         if (rc < 0)
308                 goto chnk_mem_err;
309
310         cfg_req = otx2_mbox_alloc_msg_tim_config_ring(dev->mbox);
311
312         cfg_req->ring = tim_ring->ring_id;
313         cfg_req->bigendian = false;
314         cfg_req->clocksource = tim_ring->clk_src;
315         cfg_req->enableperiodic = tim_ring->ena_periodic;
316         cfg_req->enabledontfreebuffer = tim_ring->ena_dfb;
317         cfg_req->bucketsize = tim_ring->nb_bkts;
318         cfg_req->chunksize = tim_ring->chunk_sz;
319         cfg_req->interval = NSEC2TICK(tim_ring->tck_nsec,
320                                       tim_ring->tenns_clk_freq);
321
322         rc = otx2_mbox_process(dev->mbox);
323         if (rc < 0) {
324                 tim_err_desc(rc);
325                 goto chnk_mem_err;
326         }
327
328         tim_ring->base = dev->bar2 +
329                 (RVU_BLOCK_ADDR_TIM << 20 | tim_ring->ring_id << 12);
330
331         rc = tim_register_irq(tim_ring->ring_id);
332         if (rc < 0)
333                 goto chnk_mem_err;
334
335         otx2_write64((uint64_t)tim_ring->bkt,
336                      tim_ring->base + TIM_LF_RING_BASE);
337         otx2_write64(tim_ring->aura, tim_ring->base + TIM_LF_RING_AURA);
338
339         /* Set fastpath ops. */
340         tim_set_fp_ops(tim_ring);
341
342         /* Update SSO xae count. */
343         sso_updt_xae_cnt(sso_pmd_priv(dev->event_dev), (void *)tim_ring,
344                          RTE_EVENT_TYPE_TIMER);
345         sso_xae_reconfigure(dev->event_dev);
346
347         otx2_tim_dbg("Total memory used %"PRIu64"MB\n",
348                         (uint64_t)(((tim_ring->nb_chunks * tim_ring->chunk_sz)
349                         + (tim_ring->nb_bkts * sizeof(struct otx2_tim_bkt))) /
350                         BIT_ULL(20)));
351
352         return rc;
353
354 chnk_mem_err:
355         rte_free(tim_ring->bkt);
356 bkt_mem_err:
357         rte_free(tim_ring);
358 rng_mem_err:
359         free_req = otx2_mbox_alloc_msg_tim_lf_free(dev->mbox);
360         free_req->ring = adptr->data->id;
361         otx2_mbox_process(dev->mbox);
362         return rc;
363 }
364
365 static void
366 otx2_tim_calibrate_start_tsc(struct otx2_tim_ring *tim_ring)
367 {
368 #define OTX2_TIM_CALIB_ITER     1E6
369         uint32_t real_bkt, bucket;
370         int icount, ecount = 0;
371         uint64_t bkt_cyc;
372
373         for (icount = 0; icount < OTX2_TIM_CALIB_ITER; icount++) {
374                 real_bkt = otx2_read64(tim_ring->base + TIM_LF_RING_REL) >> 44;
375                 bkt_cyc = tim_cntvct();
376                 bucket = (bkt_cyc - tim_ring->ring_start_cyc) /
377                                                         tim_ring->tck_int;
378                 bucket = bucket % (tim_ring->nb_bkts);
379                 tim_ring->ring_start_cyc = bkt_cyc - (real_bkt *
380                                                         tim_ring->tck_int);
381                 if (bucket != real_bkt)
382                         ecount++;
383         }
384         tim_ring->last_updt_cyc = bkt_cyc;
385         otx2_tim_dbg("Bucket mispredict %3.2f distance %d\n",
386                      100 - (((double)(icount - ecount) / (double)icount) * 100),
387                      bucket - real_bkt);
388 }
389
390 static int
391 otx2_tim_ring_start(const struct rte_event_timer_adapter *adptr)
392 {
393         struct otx2_tim_ring *tim_ring = adptr->data->adapter_priv;
394         struct otx2_tim_evdev *dev = tim_priv_get();
395         struct tim_enable_rsp *rsp;
396         struct tim_ring_req *req;
397         int rc;
398
399         if (dev == NULL)
400                 return -ENODEV;
401
402         req = otx2_mbox_alloc_msg_tim_enable_ring(dev->mbox);
403         req->ring = tim_ring->ring_id;
404
405         rc = otx2_mbox_process_msg(dev->mbox, (void **)&rsp);
406         if (rc < 0) {
407                 tim_err_desc(rc);
408                 goto fail;
409         }
410         tim_ring->ring_start_cyc = rsp->timestarted;
411         tim_ring->tck_int = NSEC2TICK(tim_ring->tck_nsec, tim_cntfrq());
412         tim_ring->tot_int = tim_ring->tck_int * tim_ring->nb_bkts;
413         tim_ring->fast_div = rte_reciprocal_value_u64(tim_ring->tck_int);
414         tim_ring->fast_bkt = rte_reciprocal_value_u64(tim_ring->nb_bkts);
415
416         otx2_tim_calibrate_start_tsc(tim_ring);
417
418 fail:
419         return rc;
420 }
421
422 static int
423 otx2_tim_ring_stop(const struct rte_event_timer_adapter *adptr)
424 {
425         struct otx2_tim_ring *tim_ring = adptr->data->adapter_priv;
426         struct otx2_tim_evdev *dev = tim_priv_get();
427         struct tim_ring_req *req;
428         int rc;
429
430         if (dev == NULL)
431                 return -ENODEV;
432
433         req = otx2_mbox_alloc_msg_tim_disable_ring(dev->mbox);
434         req->ring = tim_ring->ring_id;
435
436         rc = otx2_mbox_process(dev->mbox);
437         if (rc < 0) {
438                 tim_err_desc(rc);
439                 rc = -EBUSY;
440         }
441
442         return rc;
443 }
444
445 static int
446 otx2_tim_ring_free(struct rte_event_timer_adapter *adptr)
447 {
448         struct otx2_tim_ring *tim_ring = adptr->data->adapter_priv;
449         struct otx2_tim_evdev *dev = tim_priv_get();
450         struct tim_ring_req *req;
451         int rc;
452
453         if (dev == NULL)
454                 return -ENODEV;
455
456         tim_unregister_irq(tim_ring->ring_id);
457
458         req = otx2_mbox_alloc_msg_tim_lf_free(dev->mbox);
459         req->ring = tim_ring->ring_id;
460
461         rc = otx2_mbox_process(dev->mbox);
462         if (rc < 0) {
463                 tim_err_desc(rc);
464                 return -EBUSY;
465         }
466
467         rte_free(tim_ring->bkt);
468         rte_mempool_free(tim_ring->chunk_pool);
469         rte_free(adptr->data->adapter_priv);
470
471         return 0;
472 }
473
474 static int
475 otx2_tim_stats_get(const struct rte_event_timer_adapter *adapter,
476                    struct rte_event_timer_adapter_stats *stats)
477 {
478         struct otx2_tim_ring *tim_ring = adapter->data->adapter_priv;
479         uint64_t bkt_cyc = tim_cntvct() - tim_ring->ring_start_cyc;
480
481         stats->evtim_exp_count = __atomic_load_n(&tim_ring->arm_cnt,
482                                                  __ATOMIC_RELAXED);
483         stats->ev_enq_count = stats->evtim_exp_count;
484         stats->adapter_tick_count = rte_reciprocal_divide_u64(bkt_cyc,
485                                 &tim_ring->fast_div);
486         return 0;
487 }
488
489 static int
490 otx2_tim_stats_reset(const struct rte_event_timer_adapter *adapter)
491 {
492         struct otx2_tim_ring *tim_ring = adapter->data->adapter_priv;
493
494         __atomic_store_n(&tim_ring->arm_cnt, 0, __ATOMIC_RELAXED);
495         return 0;
496 }
497
498 int
499 otx2_tim_caps_get(const struct rte_eventdev *evdev, uint64_t flags,
500                   uint32_t *caps,
501                   const struct rte_event_timer_adapter_ops **ops)
502 {
503         struct otx2_tim_evdev *dev = tim_priv_get();
504
505         RTE_SET_USED(flags);
506
507         if (dev == NULL)
508                 return -ENODEV;
509
510         otx2_tim_ops.init = otx2_tim_ring_create;
511         otx2_tim_ops.uninit = otx2_tim_ring_free;
512         otx2_tim_ops.start = otx2_tim_ring_start;
513         otx2_tim_ops.stop = otx2_tim_ring_stop;
514         otx2_tim_ops.get_info   = otx2_tim_ring_info_get;
515
516         if (dev->enable_stats) {
517                 otx2_tim_ops.stats_get   = otx2_tim_stats_get;
518                 otx2_tim_ops.stats_reset = otx2_tim_stats_reset;
519         }
520
521         /* Store evdev pointer for later use. */
522         dev->event_dev = (struct rte_eventdev *)(uintptr_t)evdev;
523         *caps = RTE_EVENT_TIMER_ADAPTER_CAP_INTERNAL_PORT |
524                 RTE_EVENT_TIMER_ADAPTER_CAP_PERIODIC;
525         *ops = &otx2_tim_ops;
526
527         return 0;
528 }
529
530 #define OTX2_TIM_DISABLE_NPA    "tim_disable_npa"
531 #define OTX2_TIM_CHNK_SLOTS     "tim_chnk_slots"
532 #define OTX2_TIM_STATS_ENA      "tim_stats_ena"
533 #define OTX2_TIM_RINGS_LMT      "tim_rings_lmt"
534 #define OTX2_TIM_RING_CTL       "tim_ring_ctl"
535
536 static void
537 tim_parse_ring_param(char *value, void *opaque)
538 {
539         struct otx2_tim_evdev *dev = opaque;
540         struct otx2_tim_ctl ring_ctl = {0};
541         char *tok = strtok(value, "-");
542         struct otx2_tim_ctl *old_ptr;
543         uint16_t *val;
544
545         val = (uint16_t *)&ring_ctl;
546
547         if (!strlen(value))
548                 return;
549
550         while (tok != NULL) {
551                 *val = atoi(tok);
552                 tok = strtok(NULL, "-");
553                 val++;
554         }
555
556         if (val != (&ring_ctl.enable_stats + 1)) {
557                 otx2_err(
558                 "Invalid ring param expected [ring-chunk_sz-disable_npa-enable_stats]");
559                 return;
560         }
561
562         dev->ring_ctl_cnt++;
563         old_ptr = dev->ring_ctl_data;
564         dev->ring_ctl_data = rte_realloc(dev->ring_ctl_data,
565                                          sizeof(struct otx2_tim_ctl) *
566                                          dev->ring_ctl_cnt, 0);
567         if (dev->ring_ctl_data == NULL) {
568                 dev->ring_ctl_data = old_ptr;
569                 dev->ring_ctl_cnt--;
570                 return;
571         }
572
573         dev->ring_ctl_data[dev->ring_ctl_cnt - 1] = ring_ctl;
574 }
575
576 static void
577 tim_parse_ring_ctl_list(const char *value, void *opaque)
578 {
579         char *s = strdup(value);
580         char *start = NULL;
581         char *end = NULL;
582         char *f = s;
583
584         while (*s) {
585                 if (*s == '[')
586                         start = s;
587                 else if (*s == ']')
588                         end = s;
589
590                 if (start && start < end) {
591                         *end = 0;
592                         tim_parse_ring_param(start + 1, opaque);
593                         start = end;
594                         s = end;
595                 }
596                 s++;
597         }
598
599         free(f);
600 }
601
602 static int
603 tim_parse_kvargs_dict(const char *key, const char *value, void *opaque)
604 {
605         RTE_SET_USED(key);
606
607         /* Dict format [ring-chunk_sz-disable_npa-enable_stats] use '-' as ','
608          * isn't allowed. 0 represents default.
609          */
610         tim_parse_ring_ctl_list(value, opaque);
611
612         return 0;
613 }
614
615 static void
616 tim_parse_devargs(struct rte_devargs *devargs, struct otx2_tim_evdev *dev)
617 {
618         struct rte_kvargs *kvlist;
619
620         if (devargs == NULL)
621                 return;
622
623         kvlist = rte_kvargs_parse(devargs->args, NULL);
624         if (kvlist == NULL)
625                 return;
626
627         rte_kvargs_process(kvlist, OTX2_TIM_DISABLE_NPA,
628                            &parse_kvargs_flag, &dev->disable_npa);
629         rte_kvargs_process(kvlist, OTX2_TIM_CHNK_SLOTS,
630                            &parse_kvargs_value, &dev->chunk_slots);
631         rte_kvargs_process(kvlist, OTX2_TIM_STATS_ENA, &parse_kvargs_flag,
632                            &dev->enable_stats);
633         rte_kvargs_process(kvlist, OTX2_TIM_RINGS_LMT, &parse_kvargs_value,
634                            &dev->min_ring_cnt);
635         rte_kvargs_process(kvlist, OTX2_TIM_RING_CTL,
636                            &tim_parse_kvargs_dict, &dev);
637
638         rte_kvargs_free(kvlist);
639 }
640
641 void
642 otx2_tim_init(struct rte_pci_device *pci_dev, struct otx2_dev *cmn_dev)
643 {
644         struct rsrc_attach_req *atch_req;
645         struct rsrc_detach_req *dtch_req;
646         struct free_rsrcs_rsp *rsrc_cnt;
647         const struct rte_memzone *mz;
648         struct otx2_tim_evdev *dev;
649         int rc;
650
651         if (rte_eal_process_type() != RTE_PROC_PRIMARY)
652                 return;
653
654         mz = rte_memzone_reserve(RTE_STR(OTX2_TIM_EVDEV_NAME),
655                                  sizeof(struct otx2_tim_evdev),
656                                  rte_socket_id(), 0);
657         if (mz == NULL) {
658                 otx2_tim_dbg("Unable to allocate memory for TIM Event device");
659                 return;
660         }
661
662         dev = mz->addr;
663         dev->pci_dev = pci_dev;
664         dev->mbox = cmn_dev->mbox;
665         dev->bar2 = cmn_dev->bar2;
666
667         tim_parse_devargs(pci_dev->device.devargs, dev);
668
669         otx2_mbox_alloc_msg_free_rsrc_cnt(dev->mbox);
670         rc = otx2_mbox_process_msg(dev->mbox, (void *)&rsrc_cnt);
671         if (rc < 0) {
672                 otx2_err("Unable to get free rsrc count.");
673                 goto mz_free;
674         }
675
676         dev->nb_rings = dev->min_ring_cnt ?
677                 RTE_MIN(dev->min_ring_cnt, rsrc_cnt->tim) : rsrc_cnt->tim;
678
679         if (!dev->nb_rings) {
680                 otx2_tim_dbg("No TIM Logical functions provisioned.");
681                 goto mz_free;
682         }
683
684         atch_req = otx2_mbox_alloc_msg_attach_resources(dev->mbox);
685         atch_req->modify = true;
686         atch_req->timlfs = dev->nb_rings;
687
688         rc = otx2_mbox_process(dev->mbox);
689         if (rc < 0) {
690                 otx2_err("Unable to attach TIM rings.");
691                 goto mz_free;
692         }
693
694         rc = tim_get_msix_offsets();
695         if (rc < 0) {
696                 otx2_err("Unable to get MSIX offsets for TIM.");
697                 goto detach;
698         }
699
700         if (dev->chunk_slots &&
701             dev->chunk_slots <= OTX2_TIM_MAX_CHUNK_SLOTS &&
702             dev->chunk_slots >= OTX2_TIM_MIN_CHUNK_SLOTS) {
703                 dev->chunk_sz = (dev->chunk_slots + 1) *
704                         OTX2_TIM_CHUNK_ALIGNMENT;
705         } else {
706                 dev->chunk_sz = OTX2_TIM_RING_DEF_CHUNK_SZ;
707         }
708
709         return;
710
711 detach:
712         dtch_req = otx2_mbox_alloc_msg_detach_resources(dev->mbox);
713         dtch_req->partial = true;
714         dtch_req->timlfs = true;
715
716         otx2_mbox_process(dev->mbox);
717 mz_free:
718         rte_memzone_free(mz);
719 }
720
721 void
722 otx2_tim_fini(void)
723 {
724         struct otx2_tim_evdev *dev = tim_priv_get();
725         struct rsrc_detach_req *dtch_req;
726
727         if (rte_eal_process_type() != RTE_PROC_PRIMARY)
728                 return;
729
730         dtch_req = otx2_mbox_alloc_msg_detach_resources(dev->mbox);
731         dtch_req->partial = true;
732         dtch_req->timlfs = true;
733
734         otx2_mbox_process(dev->mbox);
735         rte_memzone_free(rte_memzone_lookup(RTE_STR(OTX2_TIM_EVDEV_NAME)));
736 }