569b7f6da241559572e9c26b48c67b1cb7a5e903
[dpdk.git] / drivers / common / cnxk / roc_nix_inl.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4
5 #include "roc_api.h"
6 #include "roc_priv.h"
7
8 uint32_t soft_exp_consumer_cnt;
9
10 PLT_STATIC_ASSERT(ROC_NIX_INL_ONF_IPSEC_INB_SA_SZ ==
11                   1UL << ROC_NIX_INL_ONF_IPSEC_INB_SA_SZ_LOG2);
12 PLT_STATIC_ASSERT(ROC_NIX_INL_ONF_IPSEC_INB_SA_SZ == 512);
13 PLT_STATIC_ASSERT(ROC_NIX_INL_ONF_IPSEC_OUTB_SA_SZ ==
14                   1UL << ROC_NIX_INL_ONF_IPSEC_OUTB_SA_SZ_LOG2);
15 PLT_STATIC_ASSERT(ROC_NIX_INL_OT_IPSEC_INB_SA_SZ ==
16                   1UL << ROC_NIX_INL_OT_IPSEC_INB_SA_SZ_LOG2);
17 PLT_STATIC_ASSERT(ROC_NIX_INL_OT_IPSEC_INB_SA_SZ == 1024);
18 PLT_STATIC_ASSERT(ROC_NIX_INL_OT_IPSEC_OUTB_SA_SZ ==
19                   1UL << ROC_NIX_INL_OT_IPSEC_OUTB_SA_SZ_LOG2);
20
21 static int
22 nix_inl_inb_sa_tbl_setup(struct roc_nix *roc_nix)
23 {
24         uint32_t ipsec_in_min_spi = roc_nix->ipsec_in_min_spi;
25         uint32_t ipsec_in_max_spi = roc_nix->ipsec_in_max_spi;
26         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
27         struct roc_nix_ipsec_cfg cfg;
28         uint64_t max_sa, i;
29         size_t inb_sa_sz;
30         void *sa;
31         int rc;
32
33         max_sa = plt_align32pow2(ipsec_in_max_spi - ipsec_in_min_spi + 1);
34
35         /* CN9K SA size is different */
36         if (roc_model_is_cn9k())
37                 inb_sa_sz = ROC_NIX_INL_ONF_IPSEC_INB_SA_SZ;
38         else
39                 inb_sa_sz = ROC_NIX_INL_OT_IPSEC_INB_SA_SZ;
40
41         /* Alloc contiguous memory for Inbound SA's */
42         nix->inb_sa_sz = inb_sa_sz;
43         nix->inb_spi_mask = max_sa - 1;
44         nix->inb_sa_base = plt_zmalloc(inb_sa_sz * max_sa,
45                                        ROC_NIX_INL_SA_BASE_ALIGN);
46         if (!nix->inb_sa_base) {
47                 plt_err("Failed to allocate memory for Inbound SA");
48                 return -ENOMEM;
49         }
50         if (roc_model_is_cn10k()) {
51                 for (i = 0; i < max_sa; i++) {
52                         sa = ((uint8_t *)nix->inb_sa_base) + (i * inb_sa_sz);
53                         roc_ot_ipsec_inb_sa_init(sa, true);
54                 }
55         }
56
57         memset(&cfg, 0, sizeof(cfg));
58         cfg.sa_size = inb_sa_sz;
59         cfg.iova = (uintptr_t)nix->inb_sa_base;
60         cfg.max_sa = max_sa;
61         cfg.tt = SSO_TT_ORDERED;
62
63         /* Setup device specific inb SA table */
64         rc = roc_nix_lf_inl_ipsec_cfg(roc_nix, &cfg, true);
65         if (rc) {
66                 plt_err("Failed to setup NIX Inbound SA conf, rc=%d", rc);
67                 goto free_mem;
68         }
69
70         return 0;
71 free_mem:
72         plt_free(nix->inb_sa_base);
73         nix->inb_sa_base = NULL;
74         return rc;
75 }
76
77 static int
78 nix_inl_sa_tbl_release(struct roc_nix *roc_nix)
79 {
80         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
81         int rc;
82
83         rc = roc_nix_lf_inl_ipsec_cfg(roc_nix, NULL, false);
84         if (rc) {
85                 plt_err("Failed to disable Inbound inline ipsec, rc=%d", rc);
86                 return rc;
87         }
88
89         plt_free(nix->inb_sa_base);
90         nix->inb_sa_base = NULL;
91         return 0;
92 }
93
94 struct roc_cpt_lf *
95 roc_nix_inl_outb_lf_base_get(struct roc_nix *roc_nix)
96 {
97         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
98
99         /* NIX Inline config needs to be done */
100         if (!nix->inl_outb_ena || !nix->cpt_lf_base)
101                 return NULL;
102
103         return (struct roc_cpt_lf *)nix->cpt_lf_base;
104 }
105
106 uintptr_t
107 roc_nix_inl_outb_sa_base_get(struct roc_nix *roc_nix)
108 {
109         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
110
111         return (uintptr_t)nix->outb_sa_base;
112 }
113
114 uintptr_t
115 roc_nix_inl_inb_sa_base_get(struct roc_nix *roc_nix, bool inb_inl_dev)
116 {
117         struct idev_cfg *idev = idev_get_cfg();
118         struct nix_inl_dev *inl_dev;
119         struct nix *nix = NULL;
120
121         if (idev == NULL)
122                 return 0;
123
124         if (!inb_inl_dev && roc_nix == NULL)
125                 return -EINVAL;
126
127         if (roc_nix) {
128                 nix = roc_nix_to_nix_priv(roc_nix);
129                 if (!nix->inl_inb_ena)
130                         return 0;
131         }
132
133         if (inb_inl_dev) {
134                 inl_dev = idev->nix_inl_dev;
135                 /* Return inline dev sa base */
136                 if (inl_dev)
137                         return (uintptr_t)inl_dev->inb_sa_base;
138                 return 0;
139         }
140
141         return (uintptr_t)nix->inb_sa_base;
142 }
143
144 uint32_t
145 roc_nix_inl_inb_spi_range(struct roc_nix *roc_nix, bool inb_inl_dev,
146                           uint32_t *min_spi, uint32_t *max_spi)
147 {
148         struct idev_cfg *idev = idev_get_cfg();
149         uint32_t min = 0, max = 0, mask = 0;
150         struct nix_inl_dev *inl_dev;
151         struct nix *nix = NULL;
152
153         if (idev == NULL)
154                 return 0;
155
156         if (!inb_inl_dev && roc_nix == NULL)
157                 return -EINVAL;
158
159         inl_dev = idev->nix_inl_dev;
160         if (inb_inl_dev) {
161                 if (inl_dev == NULL)
162                         goto exit;
163                 min = inl_dev->ipsec_in_min_spi;
164                 max = inl_dev->ipsec_in_max_spi;
165                 mask = inl_dev->inb_spi_mask;
166         } else {
167                 nix = roc_nix_to_nix_priv(roc_nix);
168                 if (!nix->inl_inb_ena)
169                         goto exit;
170                 min = roc_nix->ipsec_in_min_spi;
171                 max = roc_nix->ipsec_in_max_spi;
172                 mask = nix->inb_spi_mask;
173         }
174 exit:
175         if (min_spi)
176                 *min_spi = min;
177         if (max_spi)
178                 *max_spi = max;
179         return mask;
180 }
181
182 uint32_t
183 roc_nix_inl_inb_sa_sz(struct roc_nix *roc_nix, bool inl_dev_sa)
184 {
185         struct idev_cfg *idev = idev_get_cfg();
186         struct nix_inl_dev *inl_dev;
187         struct nix *nix;
188
189         if (idev == NULL)
190                 return 0;
191
192         if (!inl_dev_sa && roc_nix == NULL)
193                 return -EINVAL;
194
195         if (roc_nix) {
196                 nix = roc_nix_to_nix_priv(roc_nix);
197                 if (!inl_dev_sa)
198                         return nix->inb_sa_sz;
199         }
200
201         if (inl_dev_sa) {
202                 inl_dev = idev->nix_inl_dev;
203                 if (inl_dev)
204                         return inl_dev->inb_sa_sz;
205         }
206
207         return 0;
208 }
209
210 uintptr_t
211 roc_nix_inl_inb_sa_get(struct roc_nix *roc_nix, bool inb_inl_dev, uint32_t spi)
212 {
213         uint32_t max_spi, min_spi, mask;
214         uintptr_t sa_base;
215         uint64_t sz;
216
217         sa_base = roc_nix_inl_inb_sa_base_get(roc_nix, inb_inl_dev);
218         /* Check if SA base exists */
219         if (!sa_base)
220                 return 0;
221
222         /* Check if SPI is in range */
223         mask = roc_nix_inl_inb_spi_range(roc_nix, inb_inl_dev, &min_spi,
224                                          &max_spi);
225         if (spi > max_spi || spi < min_spi)
226                 plt_warn("Inbound SA SPI %u not in range (%u..%u)", spi,
227                          min_spi, max_spi);
228
229         /* Get SA size */
230         sz = roc_nix_inl_inb_sa_sz(roc_nix, inb_inl_dev);
231         if (!sz)
232                 return 0;
233
234         /* Basic logic of SPI->SA for now */
235         return (sa_base + ((spi & mask) * sz));
236 }
237
238 int
239 roc_nix_reassembly_configure(uint32_t max_wait_time, uint16_t max_frags)
240 {
241         struct idev_cfg *idev = idev_get_cfg();
242         struct roc_cpt *roc_cpt;
243         struct roc_cpt_rxc_time_cfg cfg;
244
245         PLT_SET_USED(max_frags);
246         roc_cpt = idev->cpt;
247         if (!roc_cpt) {
248                 plt_err("Cannot support inline inbound, cryptodev not probed");
249                 return -ENOTSUP;
250         }
251
252         cfg.step = (max_wait_time * 1000 / ROC_NIX_INL_REAS_ACTIVE_LIMIT);
253         cfg.zombie_limit = ROC_NIX_INL_REAS_ZOMBIE_LIMIT;
254         cfg.zombie_thres = ROC_NIX_INL_REAS_ZOMBIE_THRESHOLD;
255         cfg.active_limit = ROC_NIX_INL_REAS_ACTIVE_LIMIT;
256         cfg.active_thres = ROC_NIX_INL_REAS_ACTIVE_THRESHOLD;
257
258         return roc_cpt_rxc_time_cfg(roc_cpt, &cfg);
259 }
260
261 int
262 roc_nix_inl_inb_init(struct roc_nix *roc_nix)
263 {
264         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
265         struct idev_cfg *idev = idev_get_cfg();
266         struct roc_cpt *roc_cpt;
267         uint16_t param1;
268         int rc;
269
270         if (idev == NULL)
271                 return -ENOTSUP;
272
273         /* Unless we have another mechanism to trigger
274          * onetime Inline config in CPTPF, we cannot
275          * support without CPT being probed.
276          */
277         roc_cpt = idev->cpt;
278         if (!roc_cpt) {
279                 plt_err("Cannot support inline inbound, cryptodev not probed");
280                 return -ENOTSUP;
281         }
282
283         if (roc_model_is_cn9k()) {
284                 param1 = ROC_ONF_IPSEC_INB_MAX_L2_SZ;
285         } else {
286                 union roc_ot_ipsec_inb_param1 u;
287
288                 u.u16 = 0;
289                 u.s.esp_trailer_disable = 1;
290                 param1 = u.u16;
291         }
292
293         /* Do onetime Inbound Inline config in CPTPF */
294         rc = roc_cpt_inline_ipsec_inb_cfg(roc_cpt, param1, 0);
295         if (rc && rc != -EEXIST) {
296                 plt_err("Failed to setup inbound lf, rc=%d", rc);
297                 return rc;
298         }
299
300         /* Setup Inbound SA table */
301         rc = nix_inl_inb_sa_tbl_setup(roc_nix);
302         if (rc)
303                 return rc;
304
305         nix->inl_inb_ena = true;
306         return 0;
307 }
308
309 int
310 roc_nix_inl_inb_fini(struct roc_nix *roc_nix)
311 {
312         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
313
314         if (!nix->inl_inb_ena)
315                 return 0;
316
317         nix->inl_inb_ena = false;
318
319         /* Flush Inbound CTX cache entries */
320         roc_nix_cpt_ctx_cache_sync(roc_nix);
321
322         /* Disable Inbound SA */
323         return nix_inl_sa_tbl_release(roc_nix);
324 }
325
326 int
327 roc_nix_inl_outb_init(struct roc_nix *roc_nix)
328 {
329         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
330         struct idev_cfg *idev = idev_get_cfg();
331         struct roc_cpt_lf *lf_base, *lf;
332         struct dev *dev = &nix->dev;
333         struct msix_offset_rsp *rsp;
334         struct nix_inl_dev *inl_dev;
335         size_t sa_sz, ring_sz;
336         uint16_t sso_pffunc;
337         uint8_t eng_grpmask;
338         uint64_t blkaddr, i;
339         uint64_t *ring_base;
340         uint16_t nb_lf;
341         void *sa_base;
342         int j, rc;
343         void *sa;
344
345         if (idev == NULL)
346                 return -ENOTSUP;
347
348         nb_lf = roc_nix->outb_nb_crypto_qs;
349         blkaddr = nix->is_nix1 ? RVU_BLOCK_ADDR_CPT1 : RVU_BLOCK_ADDR_CPT0;
350
351         /* Retrieve inline device if present */
352         inl_dev = idev->nix_inl_dev;
353         sso_pffunc = inl_dev ? inl_dev->dev.pf_func : idev_sso_pffunc_get();
354         /* Use sso_pffunc if explicitly requested */
355         if (roc_nix->ipsec_out_sso_pffunc)
356                 sso_pffunc = idev_sso_pffunc_get();
357
358         if (!sso_pffunc) {
359                 plt_err("Failed to setup inline outb, need either "
360                         "inline device or sso device");
361                 return -ENOTSUP;
362         }
363
364         /* Attach CPT LF for outbound */
365         rc = cpt_lfs_attach(dev, blkaddr, true, nb_lf);
366         if (rc) {
367                 plt_err("Failed to attach CPT LF for inline outb, rc=%d", rc);
368                 return rc;
369         }
370
371         /* Alloc CPT LF */
372         eng_grpmask = (1ULL << ROC_CPT_DFLT_ENG_GRP_SE |
373                        1ULL << ROC_CPT_DFLT_ENG_GRP_SE_IE |
374                        1ULL << ROC_CPT_DFLT_ENG_GRP_AE);
375         rc = cpt_lfs_alloc(dev, eng_grpmask, blkaddr,
376                            !roc_nix->ipsec_out_sso_pffunc);
377         if (rc) {
378                 plt_err("Failed to alloc CPT LF resources, rc=%d", rc);
379                 goto lf_detach;
380         }
381
382         /* Get msix offsets */
383         rc = cpt_get_msix_offset(dev, &rsp);
384         if (rc) {
385                 plt_err("Failed to get CPT LF msix offset, rc=%d", rc);
386                 goto lf_free;
387         }
388
389         mbox_memcpy(nix->cpt_msixoff,
390                     nix->is_nix1 ? rsp->cpt1_lf_msixoff : rsp->cptlf_msixoff,
391                     sizeof(nix->cpt_msixoff));
392
393         /* Alloc required num of cpt lfs */
394         lf_base = plt_zmalloc(nb_lf * sizeof(struct roc_cpt_lf), 0);
395         if (!lf_base) {
396                 plt_err("Failed to alloc cpt lf memory");
397                 rc = -ENOMEM;
398                 goto lf_free;
399         }
400
401         /* Initialize CPT LF's */
402         for (i = 0; i < nb_lf; i++) {
403                 lf = &lf_base[i];
404
405                 lf->lf_id = i;
406                 lf->nb_desc = roc_nix->outb_nb_desc;
407                 lf->dev = &nix->dev;
408                 lf->msixoff = nix->cpt_msixoff[i];
409                 lf->pci_dev = nix->pci_dev;
410
411                 /* Setup CPT LF instruction queue */
412                 rc = cpt_lf_init(lf);
413                 if (rc) {
414                         plt_err("Failed to initialize CPT LF, rc=%d", rc);
415                         goto lf_fini;
416                 }
417
418                 /* Associate this CPT LF with NIX PFFUNC */
419                 rc = cpt_lf_outb_cfg(dev, sso_pffunc, nix->dev.pf_func, i,
420                                      true);
421                 if (rc) {
422                         plt_err("Failed to setup CPT LF->(NIX,SSO) link, rc=%d",
423                                 rc);
424                         goto lf_fini;
425                 }
426
427                 /* Enable IQ */
428                 roc_cpt_iq_enable(lf);
429         }
430
431         if (!roc_nix->ipsec_out_max_sa)
432                 goto skip_sa_alloc;
433
434         /* CN9K SA size is different */
435         if (roc_model_is_cn9k())
436                 sa_sz = ROC_NIX_INL_ONF_IPSEC_OUTB_SA_SZ;
437         else
438                 sa_sz = ROC_NIX_INL_OT_IPSEC_OUTB_SA_SZ;
439         /* Alloc contiguous memory of outbound SA */
440         sa_base = plt_zmalloc(sa_sz * roc_nix->ipsec_out_max_sa,
441                               ROC_NIX_INL_SA_BASE_ALIGN);
442         if (!sa_base) {
443                 plt_err("Outbound SA base alloc failed");
444                 goto lf_fini;
445         }
446         if (roc_model_is_cn10k()) {
447                 for (i = 0; i < roc_nix->ipsec_out_max_sa; i++) {
448                         sa = ((uint8_t *)sa_base) + (i * sa_sz);
449                         roc_ot_ipsec_outb_sa_init(sa);
450                 }
451         }
452         nix->outb_sa_base = sa_base;
453         nix->outb_sa_sz = sa_sz;
454
455 skip_sa_alloc:
456
457         nix->cpt_lf_base = lf_base;
458         nix->nb_cpt_lf = nb_lf;
459         nix->outb_err_sso_pffunc = sso_pffunc;
460         nix->inl_outb_ena = true;
461         nix->outb_se_ring_cnt =
462                 roc_nix->ipsec_out_max_sa / ROC_IPSEC_ERR_RING_MAX_ENTRY + 1;
463         nix->outb_se_ring_base =
464                 roc_nix->port_id * ROC_NIX_SOFT_EXP_PER_PORT_MAX_RINGS;
465
466         if (inl_dev == NULL) {
467                 nix->outb_se_ring_cnt = 0;
468                 return 0;
469         }
470
471         /* Allocate memory to be used as a ring buffer to poll for
472          * soft expiry event from ucode
473          */
474         ring_sz = (ROC_IPSEC_ERR_RING_MAX_ENTRY + 1) * sizeof(uint64_t);
475         ring_base = inl_dev->sa_soft_exp_ring;
476         for (i = 0; i < nix->outb_se_ring_cnt; i++) {
477                 ring_base[nix->outb_se_ring_base + i] =
478                         PLT_U64_CAST(plt_zmalloc(ring_sz, 0));
479                 if (!ring_base[nix->outb_se_ring_base + i]) {
480                         plt_err("Couldn't allocate memory for soft exp ring");
481                         while (i--)
482                                 plt_free(PLT_PTR_CAST(
483                                         ring_base[nix->outb_se_ring_base + i]));
484                         rc = -ENOMEM;
485                         goto lf_fini;
486                 }
487         }
488
489         return 0;
490
491 lf_fini:
492         for (j = i - 1; j >= 0; j--)
493                 cpt_lf_fini(&lf_base[j]);
494         plt_free(lf_base);
495 lf_free:
496         rc |= cpt_lfs_free(dev);
497 lf_detach:
498         rc |= cpt_lfs_detach(dev);
499         return rc;
500 }
501
502 int
503 roc_nix_inl_outb_fini(struct roc_nix *roc_nix)
504 {
505         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
506         struct roc_cpt_lf *lf_base = nix->cpt_lf_base;
507         struct idev_cfg *idev = idev_get_cfg();
508         struct dev *dev = &nix->dev;
509         struct nix_inl_dev *inl_dev;
510         uint64_t *ring_base;
511         int i, rc, ret = 0;
512
513         if (!nix->inl_outb_ena)
514                 return 0;
515
516         nix->inl_outb_ena = false;
517
518         /* Cleanup CPT LF instruction queue */
519         for (i = 0; i < nix->nb_cpt_lf; i++)
520                 cpt_lf_fini(&lf_base[i]);
521
522         /* Free LF resources */
523         rc = cpt_lfs_free(dev);
524         if (rc)
525                 plt_err("Failed to free CPT LF resources, rc=%d", rc);
526         ret |= rc;
527
528         /* Detach LF */
529         rc = cpt_lfs_detach(dev);
530         if (rc)
531                 plt_err("Failed to detach CPT LF, rc=%d", rc);
532
533         /* Free LF memory */
534         plt_free(lf_base);
535         nix->cpt_lf_base = NULL;
536         nix->nb_cpt_lf = 0;
537
538         /* Free outbound SA base */
539         plt_free(nix->outb_sa_base);
540         nix->outb_sa_base = NULL;
541
542         if (idev && idev->nix_inl_dev) {
543                 inl_dev = idev->nix_inl_dev;
544                 ring_base = inl_dev->sa_soft_exp_ring;
545
546                 for (i = 0; i < ROC_NIX_INL_MAX_SOFT_EXP_RNGS; i++) {
547                         if (ring_base[i])
548                                 plt_free(PLT_PTR_CAST(ring_base[i]));
549                 }
550         }
551
552         ret |= rc;
553         return ret;
554 }
555
556 bool
557 roc_nix_inl_dev_is_probed(void)
558 {
559         struct idev_cfg *idev = idev_get_cfg();
560
561         if (idev == NULL)
562                 return 0;
563
564         return !!idev->nix_inl_dev;
565 }
566
567 bool
568 roc_nix_inl_inb_is_enabled(struct roc_nix *roc_nix)
569 {
570         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
571
572         return nix->inl_inb_ena;
573 }
574
575 bool
576 roc_nix_inl_outb_is_enabled(struct roc_nix *roc_nix)
577 {
578         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
579
580         return nix->inl_outb_ena;
581 }
582
583 int
584 roc_nix_inl_dev_rq_get(struct roc_nix_rq *rq)
585 {
586         struct idev_cfg *idev = idev_get_cfg();
587         struct nix_inl_dev *inl_dev;
588         struct roc_nix_rq *inl_rq;
589         struct dev *dev;
590         int rc;
591
592         if (idev == NULL)
593                 return 0;
594
595         inl_dev = idev->nix_inl_dev;
596         /* Nothing to do if no inline device */
597         if (!inl_dev)
598                 return 0;
599
600         /* Just take reference if already inited */
601         if (inl_dev->rq_refs) {
602                 inl_dev->rq_refs++;
603                 rq->inl_dev_ref = true;
604                 return 0;
605         }
606
607         dev = &inl_dev->dev;
608         inl_rq = &inl_dev->rq;
609         memset(inl_rq, 0, sizeof(struct roc_nix_rq));
610
611         /* Take RQ pool attributes from the first ethdev RQ */
612         inl_rq->qid = 0;
613         inl_rq->aura_handle = rq->aura_handle;
614         inl_rq->first_skip = rq->first_skip;
615         inl_rq->later_skip = rq->later_skip;
616         inl_rq->lpb_size = rq->lpb_size;
617         inl_rq->lpb_drop_ena = true;
618         inl_rq->spb_ena = rq->spb_ena;
619         inl_rq->spb_aura_handle = rq->spb_aura_handle;
620         inl_rq->spb_size = rq->spb_size;
621         inl_rq->spb_drop_ena = !!rq->spb_ena;
622
623         if (!roc_model_is_cn9k()) {
624                 uint64_t aura_limit =
625                         roc_npa_aura_op_limit_get(inl_rq->aura_handle);
626                 uint64_t aura_shift = plt_log2_u32(aura_limit);
627                 uint64_t aura_drop, drop_pc;
628
629                 if (aura_shift < 8)
630                         aura_shift = 0;
631                 else
632                         aura_shift = aura_shift - 8;
633
634                 /* Set first pass RQ to drop after part of buffers are in
635                  * use to avoid metabuf alloc failure. This is needed as long
636                  * as we cannot use different aura.
637                  */
638                 drop_pc = inl_dev->lpb_drop_pc;
639                 aura_drop = ((aura_limit * drop_pc) / 100) >> aura_shift;
640                 roc_npa_aura_drop_set(inl_rq->aura_handle, aura_drop, true);
641         }
642
643         if (inl_rq->spb_ena) {
644                 uint64_t aura_limit =
645                         roc_npa_aura_op_limit_get(inl_rq->spb_aura_handle);
646                 uint64_t aura_shift = plt_log2_u32(aura_limit);
647                 uint64_t aura_drop, drop_pc;
648
649                 if (aura_shift < 8)
650                         aura_shift = 0;
651                 else
652                         aura_shift = aura_shift - 8;
653
654                 /* Set first pass RQ to drop after part of buffers are in
655                  * use to avoid metabuf alloc failure. This is needed as long
656                  * as we cannot use different aura.
657                  */
658                 drop_pc = inl_dev->spb_drop_pc;
659                 aura_drop = ((aura_limit * drop_pc) / 100) >> aura_shift;
660                 roc_npa_aura_drop_set(inl_rq->spb_aura_handle, aura_drop, true);
661         }
662
663         /* Enable IPSec */
664         inl_rq->ipsech_ena = true;
665
666         inl_rq->flow_tag_width = 20;
667         /* Special tag mask */
668         inl_rq->tag_mask = rq->tag_mask;
669         inl_rq->tt = SSO_TT_ORDERED;
670         inl_rq->hwgrp = 0;
671         inl_rq->wqe_skip = inl_dev->wqe_skip;
672         inl_rq->sso_ena = true;
673
674         /* Prepare and send RQ init mbox */
675         if (roc_model_is_cn9k())
676                 rc = nix_rq_cn9k_cfg(dev, inl_rq, inl_dev->qints, false, true);
677         else
678                 rc = nix_rq_cfg(dev, inl_rq, inl_dev->qints, false, true);
679         if (rc) {
680                 plt_err("Failed to prepare aq_enq msg, rc=%d", rc);
681                 return rc;
682         }
683
684         rc = mbox_process(dev->mbox);
685         if (rc) {
686                 plt_err("Failed to send aq_enq msg, rc=%d", rc);
687                 return rc;
688         }
689
690         inl_dev->rq_refs++;
691         rq->inl_dev_ref = true;
692         return 0;
693 }
694
695 int
696 roc_nix_inl_dev_rq_put(struct roc_nix_rq *rq)
697 {
698         struct idev_cfg *idev = idev_get_cfg();
699         struct nix_inl_dev *inl_dev;
700         struct roc_nix_rq *inl_rq;
701         struct dev *dev;
702         int rc;
703
704         if (idev == NULL)
705                 return 0;
706
707         if (!rq->inl_dev_ref)
708                 return 0;
709
710         inl_dev = idev->nix_inl_dev;
711         /* Inline device should be there if we have ref */
712         if (!inl_dev) {
713                 plt_err("Failed to find inline device with refs");
714                 return -EFAULT;
715         }
716
717         rq->inl_dev_ref = false;
718         inl_dev->rq_refs--;
719         if (inl_dev->rq_refs)
720                 return 0;
721
722         dev = &inl_dev->dev;
723         inl_rq = &inl_dev->rq;
724         /* There are no more references, disable RQ */
725         rc = nix_rq_ena_dis(dev, inl_rq, false);
726         if (rc)
727                 plt_err("Failed to disable inline device rq, rc=%d", rc);
728
729         roc_npa_aura_drop_set(inl_rq->aura_handle, 0, false);
730         if (inl_rq->spb_ena)
731                 roc_npa_aura_drop_set(inl_rq->spb_aura_handle, 0, false);
732
733         /* Flush NIX LF for CN10K */
734         nix_rq_vwqe_flush(rq, inl_dev->vwqe_interval);
735
736         return rc;
737 }
738
739 uint64_t
740 roc_nix_inl_dev_rq_limit_get(void)
741 {
742         struct idev_cfg *idev = idev_get_cfg();
743         struct nix_inl_dev *inl_dev;
744         struct roc_nix_rq *inl_rq;
745
746         if (!idev || !idev->nix_inl_dev)
747                 return 0;
748
749         inl_dev = idev->nix_inl_dev;
750         if (!inl_dev->rq_refs)
751                 return 0;
752
753         inl_rq = &inl_dev->rq;
754
755         return roc_npa_aura_op_limit_get(inl_rq->aura_handle);
756 }
757
758 void
759 roc_nix_inb_mode_set(struct roc_nix *roc_nix, bool use_inl_dev)
760 {
761         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
762
763         /* Info used by NPC flow rule add */
764         nix->inb_inl_dev = use_inl_dev;
765 }
766
767 int
768 roc_nix_inl_outb_soft_exp_poll_switch(struct roc_nix *roc_nix, bool poll)
769 {
770         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
771         struct idev_cfg *idev = idev_get_cfg();
772         struct nix_inl_dev *inl_dev;
773         uint16_t ring_idx, i;
774
775         if (!idev || !idev->nix_inl_dev)
776                 return 0;
777
778         inl_dev = idev->nix_inl_dev;
779
780         for (i = 0; i < nix->outb_se_ring_cnt; i++) {
781                 ring_idx = nix->outb_se_ring_base + i;
782
783                 if (poll)
784                         plt_bitmap_set(inl_dev->soft_exp_ring_bmap, ring_idx);
785                 else
786                         plt_bitmap_clear(inl_dev->soft_exp_ring_bmap, ring_idx);
787         }
788
789         if (poll)
790                 soft_exp_consumer_cnt++;
791         else
792                 soft_exp_consumer_cnt--;
793
794         return 0;
795 }
796
797 bool
798 roc_nix_inb_is_with_inl_dev(struct roc_nix *roc_nix)
799 {
800         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
801
802         return nix->inb_inl_dev;
803 }
804
805 struct roc_nix_rq *
806 roc_nix_inl_dev_rq(void)
807 {
808         struct idev_cfg *idev = idev_get_cfg();
809         struct nix_inl_dev *inl_dev;
810
811         if (idev != NULL) {
812                 inl_dev = idev->nix_inl_dev;
813                 if (inl_dev != NULL && inl_dev->rq_refs)
814                         return &inl_dev->rq;
815         }
816
817         return NULL;
818 }
819
820 uint16_t __roc_api
821 roc_nix_inl_outb_sso_pffunc_get(struct roc_nix *roc_nix)
822 {
823         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
824
825         return nix->outb_err_sso_pffunc;
826 }
827
828 int
829 roc_nix_inl_cb_register(roc_nix_inl_sso_work_cb_t cb, void *args)
830 {
831         struct idev_cfg *idev = idev_get_cfg();
832         struct nix_inl_dev *inl_dev;
833
834         if (idev == NULL)
835                 return -EIO;
836
837         inl_dev = idev->nix_inl_dev;
838         if (!inl_dev)
839                 return -EIO;
840
841         /* Be silent if registration called with same cb and args */
842         if (inl_dev->work_cb == cb && inl_dev->cb_args == args)
843                 return 0;
844
845         /* Don't allow registration again if registered with different cb */
846         if (inl_dev->work_cb)
847                 return -EBUSY;
848
849         inl_dev->work_cb = cb;
850         inl_dev->cb_args = args;
851         return 0;
852 }
853
854 int
855 roc_nix_inl_cb_unregister(roc_nix_inl_sso_work_cb_t cb, void *args)
856 {
857         struct idev_cfg *idev = idev_get_cfg();
858         struct nix_inl_dev *inl_dev;
859
860         if (idev == NULL)
861                 return -ENOENT;
862
863         inl_dev = idev->nix_inl_dev;
864         if (!inl_dev)
865                 return -ENOENT;
866
867         if (inl_dev->work_cb != cb || inl_dev->cb_args != args)
868                 return -EINVAL;
869
870         inl_dev->work_cb = NULL;
871         inl_dev->cb_args = NULL;
872         return 0;
873 }
874
875 int
876 roc_nix_inl_inb_tag_update(struct roc_nix *roc_nix, uint32_t tag_const,
877                            uint8_t tt)
878 {
879         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
880         struct roc_nix_ipsec_cfg cfg;
881
882         /* Be silent if inline inbound not enabled */
883         if (!nix->inl_inb_ena)
884                 return 0;
885
886         memset(&cfg, 0, sizeof(cfg));
887         cfg.sa_size = nix->inb_sa_sz;
888         cfg.iova = (uintptr_t)nix->inb_sa_base;
889         cfg.max_sa = nix->inb_spi_mask + 1;
890         cfg.tt = tt;
891         cfg.tag_const = tag_const;
892
893         return roc_nix_lf_inl_ipsec_cfg(roc_nix, &cfg, true);
894 }
895
896 int
897 roc_nix_inl_sa_sync(struct roc_nix *roc_nix, void *sa, bool inb,
898                     enum roc_nix_inl_sa_sync_op op)
899 {
900         struct idev_cfg *idev = idev_get_cfg();
901         struct nix_inl_dev *inl_dev = NULL;
902         struct roc_cpt_lf *outb_lf = NULL;
903         union cpt_lf_ctx_reload reload;
904         union cpt_lf_ctx_flush flush;
905         bool get_inl_lf = true;
906         uintptr_t rbase;
907         struct nix *nix;
908
909         /* Nothing much to do on cn9k */
910         if (roc_model_is_cn9k()) {
911                 plt_atomic_thread_fence(__ATOMIC_ACQ_REL);
912                 return 0;
913         }
914
915         if (idev)
916                 inl_dev = idev->nix_inl_dev;
917
918         if (!inl_dev && roc_nix == NULL)
919                 return -EINVAL;
920
921         if (roc_nix) {
922                 nix = roc_nix_to_nix_priv(roc_nix);
923                 outb_lf = nix->cpt_lf_base;
924                 if (inb && !nix->inb_inl_dev)
925                         get_inl_lf = false;
926         }
927
928         if (inb && get_inl_lf) {
929                 outb_lf = NULL;
930                 if (inl_dev && inl_dev->attach_cptlf)
931                         outb_lf = &inl_dev->cpt_lf;
932         }
933
934         if (outb_lf) {
935                 rbase = outb_lf->rbase;
936
937                 flush.u = 0;
938                 reload.u = 0;
939                 switch (op) {
940                 case ROC_NIX_INL_SA_OP_FLUSH_INVAL:
941                         flush.s.inval = 1;
942                         /* fall through */
943                 case ROC_NIX_INL_SA_OP_FLUSH:
944                         flush.s.cptr = ((uintptr_t)sa) >> 7;
945                         plt_write64(flush.u, rbase + CPT_LF_CTX_FLUSH);
946                         break;
947                 case ROC_NIX_INL_SA_OP_RELOAD:
948                         reload.s.cptr = ((uintptr_t)sa) >> 7;
949                         plt_write64(reload.u, rbase + CPT_LF_CTX_RELOAD);
950                         break;
951                 default:
952                         return -EINVAL;
953                 }
954                 return 0;
955         }
956         plt_err("Could not get CPT LF for SA sync");
957         return -ENOTSUP;
958 }
959
960 int
961 roc_nix_inl_ctx_write(struct roc_nix *roc_nix, void *sa_dptr, void *sa_cptr,
962                       bool inb, uint16_t sa_len)
963 {
964         struct idev_cfg *idev = idev_get_cfg();
965         struct nix_inl_dev *inl_dev = NULL;
966         struct roc_cpt_lf *outb_lf = NULL;
967         union cpt_lf_ctx_flush flush;
968         bool get_inl_lf = true;
969         uintptr_t rbase;
970         struct nix *nix;
971         int rc;
972
973         /* Nothing much to do on cn9k */
974         if (roc_model_is_cn9k()) {
975                 plt_atomic_thread_fence(__ATOMIC_ACQ_REL);
976                 return 0;
977         }
978
979         if (idev)
980                 inl_dev = idev->nix_inl_dev;
981
982         if (!inl_dev && roc_nix == NULL)
983                 return -EINVAL;
984
985         if (roc_nix) {
986                 nix = roc_nix_to_nix_priv(roc_nix);
987                 outb_lf = nix->cpt_lf_base;
988
989                 if (inb && !nix->inb_inl_dev)
990                         get_inl_lf = false;
991         }
992
993         if (inb && get_inl_lf) {
994                 outb_lf = NULL;
995                 if (inl_dev && inl_dev->attach_cptlf)
996                         outb_lf = &inl_dev->cpt_lf;
997         }
998
999         if (outb_lf) {
1000                 rbase = outb_lf->rbase;
1001                 flush.u = 0;
1002
1003                 rc = roc_cpt_ctx_write(outb_lf, sa_dptr, sa_cptr, sa_len);
1004                 if (rc)
1005                         return rc;
1006                 /* Trigger CTX flush to write dirty data back to DRAM */
1007                 flush.s.cptr = ((uintptr_t)sa_cptr) >> 7;
1008                 plt_write64(flush.u, rbase + CPT_LF_CTX_FLUSH);
1009
1010                 return 0;
1011         }
1012         plt_nix_dbg("Could not get CPT LF for CTX write");
1013         return -ENOTSUP;
1014 }
1015
1016 void
1017 roc_nix_inl_dev_lock(void)
1018 {
1019         struct idev_cfg *idev = idev_get_cfg();
1020
1021         if (idev != NULL)
1022                 plt_spinlock_lock(&idev->nix_inl_dev_lock);
1023 }
1024
1025 void
1026 roc_nix_inl_dev_unlock(void)
1027 {
1028         struct idev_cfg *idev = idev_get_cfg();
1029
1030         if (idev != NULL)
1031                 plt_spinlock_unlock(&idev->nix_inl_dev_lock);
1032 }