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