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