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