crypto/nitrox: support AES-GCM
[dpdk.git] / drivers / crypto / nitrox / nitrox_sym_reqmgr.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2019 Marvell International Ltd.
3  */
4
5 #include <rte_crypto.h>
6 #include <rte_cryptodev.h>
7 #include <rte_cycles.h>
8 #include <rte_errno.h>
9
10 #include "nitrox_sym_reqmgr.h"
11 #include "nitrox_logs.h"
12
13 #define MAX_SGBUF_CNT 16
14 #define MAX_SGCOMP_CNT 5
15 /* SLC_STORE_INFO */
16 #define MIN_UDD_LEN 16
17 /* PKT_IN_HDR + SLC_STORE_INFO */
18 #define FDATA_SIZE 32
19 /* Base destination port for the solicited requests */
20 #define SOLICIT_BASE_DPORT 256
21 #define PENDING_SIG 0xFFFFFFFFFFFFFFFFUL
22 #define CMD_TIMEOUT 2
23
24 struct gphdr {
25         uint16_t param0;
26         uint16_t param1;
27         uint16_t param2;
28         uint16_t param3;
29 };
30
31 union pkt_instr_hdr {
32         uint64_t value;
33         struct {
34 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
35                 uint64_t raz_48_63 : 16;
36                 uint64_t g : 1;
37                 uint64_t gsz : 7;
38                 uint64_t ihi : 1;
39                 uint64_t ssz : 7;
40                 uint64_t raz_30_31 : 2;
41                 uint64_t fsz : 6;
42                 uint64_t raz_16_23 : 8;
43                 uint64_t tlen : 16;
44 #else
45                 uint64_t tlen : 16;
46                 uint64_t raz_16_23 : 8;
47                 uint64_t fsz : 6;
48                 uint64_t raz_30_31 : 2;
49                 uint64_t ssz : 7;
50                 uint64_t ihi : 1;
51                 uint64_t gsz : 7;
52                 uint64_t g : 1;
53                 uint64_t raz_48_63 : 16;
54 #endif
55         } s;
56 };
57
58 union pkt_hdr {
59         uint64_t value[2];
60         struct {
61 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
62                 uint64_t opcode : 8;
63                 uint64_t arg : 8;
64                 uint64_t ctxc : 2;
65                 uint64_t unca : 1;
66                 uint64_t raz_44 : 1;
67                 uint64_t info : 3;
68                 uint64_t destport : 9;
69                 uint64_t unc : 8;
70                 uint64_t raz_19_23 : 5;
71                 uint64_t grp : 3;
72                 uint64_t raz_15 : 1;
73                 uint64_t ctxl : 7;
74                 uint64_t uddl : 8;
75 #else
76                 uint64_t uddl : 8;
77                 uint64_t ctxl : 7;
78                 uint64_t raz_15 : 1;
79                 uint64_t grp : 3;
80                 uint64_t raz_19_23 : 5;
81                 uint64_t unc : 8;
82                 uint64_t destport : 9;
83                 uint64_t info : 3;
84                 uint64_t raz_44 : 1;
85                 uint64_t unca : 1;
86                 uint64_t ctxc : 2;
87                 uint64_t arg : 8;
88                 uint64_t opcode : 8;
89 #endif
90                 uint64_t ctxp;
91         } s;
92 };
93
94 union slc_store_info {
95         uint64_t value[2];
96         struct {
97 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
98                 uint64_t raz_39_63 : 25;
99                 uint64_t ssz : 7;
100                 uint64_t raz_0_31 : 32;
101 #else
102                 uint64_t raz_0_31 : 32;
103                 uint64_t ssz : 7;
104                 uint64_t raz_39_63 : 25;
105 #endif
106                 uint64_t rptr;
107         } s;
108 };
109
110 struct nps_pkt_instr {
111         uint64_t dptr0;
112         union pkt_instr_hdr ih;
113         union pkt_hdr irh;
114         union slc_store_info slc;
115         uint64_t fdata[2];
116 };
117
118 struct resp_hdr {
119         uint64_t orh;
120         uint64_t completion;
121 };
122
123 struct nitrox_sglist {
124         uint16_t len;
125         uint16_t raz0;
126         uint32_t raz1;
127         rte_iova_t iova;
128         void *virt;
129 };
130
131 struct nitrox_sgcomp {
132         uint16_t len[4];
133         uint64_t iova[4];
134 };
135
136 struct nitrox_sgtable {
137         uint8_t map_bufs_cnt;
138         uint8_t nr_sgcomp;
139         uint16_t total_bytes;
140
141         struct nitrox_sglist sglist[MAX_SGBUF_CNT];
142         struct nitrox_sgcomp sgcomp[MAX_SGCOMP_CNT];
143 };
144
145 struct iv {
146         uint8_t *virt;
147         rte_iova_t iova;
148         uint16_t len;
149 };
150
151 struct nitrox_softreq {
152         struct nitrox_crypto_ctx *ctx;
153         struct rte_crypto_op *op;
154         struct gphdr gph;
155         struct nps_pkt_instr instr;
156         struct resp_hdr resp;
157         struct nitrox_sgtable in;
158         struct nitrox_sgtable out;
159         struct iv iv;
160         uint64_t timeout;
161         rte_iova_t dptr;
162         rte_iova_t rptr;
163         rte_iova_t iova;
164 };
165
166 static void
167 softreq_init(struct nitrox_softreq *sr, rte_iova_t iova)
168 {
169         memset(sr, 0, sizeof(*sr));
170         sr->iova = iova;
171 }
172
173 /*
174  * 64-Byte Instruction Format
175  *
176  *  ----------------------
177  *  |      DPTR0         | 8 bytes
178  *  ----------------------
179  *  |  PKT_IN_INSTR_HDR  | 8 bytes
180  *  ----------------------
181  *  |    PKT_IN_HDR      | 16 bytes
182  *  ----------------------
183  *  |    SLC_INFO        | 16 bytes
184  *  ----------------------
185  *  |   Front data       | 16 bytes
186  *  ----------------------
187  */
188 static void
189 create_se_instr(struct nitrox_softreq *sr, uint8_t qno)
190 {
191         struct nitrox_crypto_ctx *ctx = sr->ctx;
192         rte_iova_t ctx_handle;
193
194         /* fill the packet instruction */
195         /* word 0 */
196         sr->instr.dptr0 = rte_cpu_to_be_64(sr->dptr);
197
198         /* word 1 */
199         sr->instr.ih.value = 0;
200         sr->instr.ih.s.g = 1;
201         sr->instr.ih.s.gsz = sr->in.map_bufs_cnt;
202         sr->instr.ih.s.ssz = sr->out.map_bufs_cnt;
203         sr->instr.ih.s.fsz = FDATA_SIZE + sizeof(struct gphdr);
204         sr->instr.ih.s.tlen = sr->instr.ih.s.fsz + sr->in.total_bytes;
205         sr->instr.ih.value = rte_cpu_to_be_64(sr->instr.ih.value);
206
207         /* word 2 */
208         sr->instr.irh.value[0] = 0;
209         sr->instr.irh.s.uddl = MIN_UDD_LEN;
210         /* context length in 64-bit words */
211         sr->instr.irh.s.ctxl = RTE_ALIGN_MUL_CEIL(sizeof(ctx->fctx), 8) / 8;
212         /* offset from solicit base port 256 */
213         sr->instr.irh.s.destport = SOLICIT_BASE_DPORT + qno;
214         /* Invalid context cache */
215         sr->instr.irh.s.ctxc = 0x3;
216         sr->instr.irh.s.arg = ctx->req_op;
217         sr->instr.irh.s.opcode = ctx->opcode;
218         sr->instr.irh.value[0] = rte_cpu_to_be_64(sr->instr.irh.value[0]);
219
220         /* word 3 */
221         ctx_handle = ctx->iova + offsetof(struct nitrox_crypto_ctx, fctx);
222         sr->instr.irh.s.ctxp = rte_cpu_to_be_64(ctx_handle);
223
224         /* word 4 */
225         sr->instr.slc.value[0] = 0;
226         sr->instr.slc.s.ssz = sr->out.map_bufs_cnt;
227         sr->instr.slc.value[0] = rte_cpu_to_be_64(sr->instr.slc.value[0]);
228
229         /* word 5 */
230         sr->instr.slc.s.rptr = rte_cpu_to_be_64(sr->rptr);
231         /*
232          * No conversion for front data,
233          * It goes into payload
234          * put GP Header in front data
235          */
236         memcpy(&sr->instr.fdata[0], &sr->gph, sizeof(sr->instr.fdata[0]));
237         sr->instr.fdata[1] = 0;
238 }
239
240 static void
241 softreq_copy_iv(struct nitrox_softreq *sr, uint8_t salt_size)
242 {
243         uint16_t offset = sr->ctx->iv.offset + salt_size;
244
245         sr->iv.virt = rte_crypto_op_ctod_offset(sr->op, uint8_t *, offset);
246         sr->iv.iova = rte_crypto_op_ctophys_offset(sr->op, offset);
247         sr->iv.len = sr->ctx->iv.length - salt_size;
248 }
249
250 static int
251 extract_cipher_auth_digest(struct nitrox_softreq *sr,
252                            struct nitrox_sglist *digest)
253 {
254         struct rte_crypto_op *op = sr->op;
255         struct rte_mbuf *mdst = op->sym->m_dst ? op->sym->m_dst :
256                                         op->sym->m_src;
257
258         if (sr->ctx->req_op == NITROX_OP_DECRYPT &&
259             unlikely(!op->sym->auth.digest.data))
260                 return -EINVAL;
261
262         digest->len = sr->ctx->digest_length;
263         if (op->sym->auth.digest.data) {
264                 digest->iova = op->sym->auth.digest.phys_addr;
265                 digest->virt = op->sym->auth.digest.data;
266                 return 0;
267         }
268
269         if (unlikely(rte_pktmbuf_data_len(mdst) < op->sym->auth.data.offset +
270                op->sym->auth.data.length + digest->len))
271                 return -EINVAL;
272
273         digest->iova = rte_pktmbuf_iova_offset(mdst,
274                                         op->sym->auth.data.offset +
275                                         op->sym->auth.data.length);
276         digest->virt = rte_pktmbuf_mtod_offset(mdst, uint8_t *,
277                                         op->sym->auth.data.offset +
278                                         op->sym->auth.data.length);
279         return 0;
280 }
281
282 static void
283 fill_sglist(struct nitrox_sgtable *sgtbl, uint16_t len, rte_iova_t iova,
284             void *virt)
285 {
286         struct nitrox_sglist *sglist = sgtbl->sglist;
287         uint8_t cnt = sgtbl->map_bufs_cnt;
288
289         if (unlikely(!len))
290                 return;
291
292         sglist[cnt].len = len;
293         sglist[cnt].iova = iova;
294         sglist[cnt].virt = virt;
295         sgtbl->total_bytes += len;
296         cnt++;
297         sgtbl->map_bufs_cnt = cnt;
298 }
299
300 static int
301 create_sglist_from_mbuf(struct nitrox_sgtable *sgtbl, struct rte_mbuf *mbuf,
302                         uint32_t off, int datalen)
303 {
304         struct nitrox_sglist *sglist = sgtbl->sglist;
305         uint8_t cnt = sgtbl->map_bufs_cnt;
306         struct rte_mbuf *m;
307         int mlen;
308
309         if (unlikely(datalen <= 0))
310                 return 0;
311
312         for (m = mbuf; m && off > rte_pktmbuf_data_len(m); m = m->next)
313                 off -= rte_pktmbuf_data_len(m);
314
315         if (unlikely(!m))
316                 return -EIO;
317
318         mlen = rte_pktmbuf_data_len(m) - off;
319         if (datalen <= mlen)
320                 mlen = datalen;
321         sglist[cnt].len = mlen;
322         sglist[cnt].iova = rte_pktmbuf_iova_offset(m, off);
323         sglist[cnt].virt = rte_pktmbuf_mtod_offset(m, uint8_t *, off);
324         sgtbl->total_bytes += mlen;
325         cnt++;
326         datalen -= mlen;
327         for (m = m->next; m && datalen; m = m->next) {
328                 mlen = rte_pktmbuf_data_len(m) < datalen ?
329                         rte_pktmbuf_data_len(m) : datalen;
330                 sglist[cnt].len = mlen;
331                 sglist[cnt].iova = rte_pktmbuf_iova(m);
332                 sglist[cnt].virt = rte_pktmbuf_mtod(m, uint8_t *);
333                 sgtbl->total_bytes += mlen;
334                 cnt++;
335                 datalen -= mlen;
336         }
337
338         RTE_VERIFY(cnt <= MAX_SGBUF_CNT);
339         sgtbl->map_bufs_cnt = cnt;
340         return 0;
341 }
342
343 static int
344 create_cipher_auth_sglist(struct nitrox_softreq *sr,
345                           struct nitrox_sgtable *sgtbl, struct rte_mbuf *mbuf)
346 {
347         struct rte_crypto_op *op = sr->op;
348         int auth_only_len;
349         int err;
350
351         fill_sglist(sgtbl, sr->iv.len, sr->iv.iova, sr->iv.virt);
352         auth_only_len = op->sym->auth.data.length - op->sym->cipher.data.length;
353         if (unlikely(auth_only_len < 0))
354                 return -EINVAL;
355
356         if (unlikely(
357                 op->sym->cipher.data.offset + op->sym->cipher.data.length !=
358                 op->sym->auth.data.offset + op->sym->auth.data.length)) {
359                 NITROX_LOG(ERR, "Auth only data after cipher data not supported\n");
360                 return -ENOTSUP;
361         }
362
363         err = create_sglist_from_mbuf(sgtbl, mbuf, op->sym->auth.data.offset,
364                                       auth_only_len);
365         if (unlikely(err))
366                 return err;
367
368         err = create_sglist_from_mbuf(sgtbl, mbuf, op->sym->cipher.data.offset,
369                                       op->sym->cipher.data.length);
370         if (unlikely(err))
371                 return err;
372
373         return 0;
374 }
375
376 static int
377 create_combined_sglist(struct nitrox_softreq *sr, struct nitrox_sgtable *sgtbl,
378                        struct rte_mbuf *mbuf)
379 {
380         struct rte_crypto_op *op = sr->op;
381
382         fill_sglist(sgtbl, sr->iv.len, sr->iv.iova, sr->iv.virt);
383         fill_sglist(sgtbl, sr->ctx->aad_length, op->sym->aead.aad.phys_addr,
384                     op->sym->aead.aad.data);
385         return create_sglist_from_mbuf(sgtbl, mbuf, op->sym->cipher.data.offset,
386                                        op->sym->cipher.data.length);
387 }
388
389 static int
390 create_aead_sglist(struct nitrox_softreq *sr, struct nitrox_sgtable *sgtbl,
391                    struct rte_mbuf *mbuf)
392 {
393         int err;
394
395         switch (sr->ctx->nitrox_chain) {
396         case NITROX_CHAIN_CIPHER_AUTH:
397         case NITROX_CHAIN_AUTH_CIPHER:
398                 err = create_cipher_auth_sglist(sr, sgtbl, mbuf);
399                 break;
400         case NITROX_CHAIN_COMBINED:
401                 err = create_combined_sglist(sr, sgtbl, mbuf);
402                 break;
403         default:
404                 err = -EINVAL;
405                 break;
406         }
407
408         return err;
409 }
410
411 static void
412 create_sgcomp(struct nitrox_sgtable *sgtbl)
413 {
414         int i, j, nr_sgcomp;
415         struct nitrox_sgcomp *sgcomp = sgtbl->sgcomp;
416         struct nitrox_sglist *sglist = sgtbl->sglist;
417
418         nr_sgcomp = RTE_ALIGN_MUL_CEIL(sgtbl->map_bufs_cnt, 4) / 4;
419         sgtbl->nr_sgcomp = nr_sgcomp;
420         for (i = 0; i < nr_sgcomp; i++, sgcomp++) {
421                 for (j = 0; j < 4; j++, sglist++) {
422                         sgcomp->len[j] = rte_cpu_to_be_16(sglist->len);
423                         sgcomp->iova[j] = rte_cpu_to_be_64(sglist->iova);
424                 }
425         }
426 }
427
428 static int
429 create_aead_inbuf(struct nitrox_softreq *sr, struct nitrox_sglist *digest)
430 {
431         int err;
432         struct nitrox_crypto_ctx *ctx = sr->ctx;
433
434         err = create_aead_sglist(sr, &sr->in, sr->op->sym->m_src);
435         if (unlikely(err))
436                 return err;
437
438         if (ctx->req_op == NITROX_OP_DECRYPT)
439                 fill_sglist(&sr->in, digest->len, digest->iova, digest->virt);
440
441         create_sgcomp(&sr->in);
442         sr->dptr = sr->iova + offsetof(struct nitrox_softreq, in.sgcomp);
443         return 0;
444 }
445
446 static int
447 create_aead_oop_outbuf(struct nitrox_softreq *sr, struct nitrox_sglist *digest)
448 {
449         int err;
450         struct nitrox_crypto_ctx *ctx = sr->ctx;
451
452         err = create_aead_sglist(sr, &sr->out, sr->op->sym->m_dst);
453         if (unlikely(err))
454                 return err;
455
456         if (ctx->req_op == NITROX_OP_ENCRYPT)
457                 fill_sglist(&sr->out, digest->len, digest->iova, digest->virt);
458
459         return 0;
460 }
461
462 static void
463 create_aead_inplace_outbuf(struct nitrox_softreq *sr,
464                            struct nitrox_sglist *digest)
465 {
466         int i, cnt;
467         struct nitrox_crypto_ctx *ctx = sr->ctx;
468
469         cnt = sr->out.map_bufs_cnt;
470         for (i = 0; i < sr->in.map_bufs_cnt; i++, cnt++) {
471                 sr->out.sglist[cnt].len = sr->in.sglist[i].len;
472                 sr->out.sglist[cnt].iova = sr->in.sglist[i].iova;
473                 sr->out.sglist[cnt].virt = sr->in.sglist[i].virt;
474         }
475
476         sr->out.map_bufs_cnt = cnt;
477         if (ctx->req_op == NITROX_OP_ENCRYPT) {
478                 fill_sglist(&sr->out, digest->len, digest->iova,
479                             digest->virt);
480         } else if (ctx->req_op == NITROX_OP_DECRYPT) {
481                 sr->out.map_bufs_cnt--;
482         }
483 }
484
485 static int
486 create_aead_outbuf(struct nitrox_softreq *sr, struct nitrox_sglist *digest)
487 {
488         struct rte_crypto_op *op = sr->op;
489         int cnt = 0;
490
491         sr->resp.orh = PENDING_SIG;
492         sr->out.sglist[cnt].len = sizeof(sr->resp.orh);
493         sr->out.sglist[cnt].iova = sr->iova + offsetof(struct nitrox_softreq,
494                                                        resp.orh);
495         sr->out.sglist[cnt].virt = &sr->resp.orh;
496         cnt++;
497         sr->out.map_bufs_cnt = cnt;
498         if (op->sym->m_dst) {
499                 int err;
500
501                 err = create_aead_oop_outbuf(sr, digest);
502                 if (unlikely(err))
503                         return err;
504         } else {
505                 create_aead_inplace_outbuf(sr, digest);
506         }
507
508         cnt = sr->out.map_bufs_cnt;
509         sr->resp.completion = PENDING_SIG;
510         sr->out.sglist[cnt].len = sizeof(sr->resp.completion);
511         sr->out.sglist[cnt].iova = sr->iova + offsetof(struct nitrox_softreq,
512                                                      resp.completion);
513         sr->out.sglist[cnt].virt = &sr->resp.completion;
514         cnt++;
515         RTE_VERIFY(cnt <= MAX_SGBUF_CNT);
516         sr->out.map_bufs_cnt = cnt;
517
518         create_sgcomp(&sr->out);
519         sr->rptr = sr->iova + offsetof(struct nitrox_softreq, out.sgcomp);
520         return 0;
521 }
522
523 static void
524 create_aead_gph(uint32_t cryptlen, uint16_t ivlen, uint32_t authlen,
525                 struct gphdr *gph)
526 {
527         int auth_only_len;
528         union {
529                 struct {
530 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
531                         uint16_t iv_offset : 8;
532                         uint16_t auth_offset    : 8;
533 #else
534                         uint16_t auth_offset    : 8;
535                         uint16_t iv_offset : 8;
536 #endif
537                 };
538                 uint16_t value;
539         } param3;
540
541         gph->param0 = rte_cpu_to_be_16(cryptlen);
542         gph->param1 = rte_cpu_to_be_16(authlen);
543
544         auth_only_len = authlen - cryptlen;
545         gph->param2 = rte_cpu_to_be_16(ivlen + auth_only_len);
546
547         param3.iv_offset = 0;
548         param3.auth_offset = ivlen;
549         gph->param3 = rte_cpu_to_be_16(param3.value);
550 }
551
552 static int
553 process_cipher_auth_data(struct nitrox_softreq *sr)
554 {
555         struct rte_crypto_op *op = sr->op;
556         int err;
557         struct nitrox_sglist digest;
558
559         softreq_copy_iv(sr, 0);
560         err = extract_cipher_auth_digest(sr, &digest);
561         if (unlikely(err))
562                 return err;
563
564         err = create_aead_inbuf(sr, &digest);
565         if (unlikely(err))
566                 return err;
567
568         err = create_aead_outbuf(sr, &digest);
569         if (unlikely(err))
570                 return err;
571
572         create_aead_gph(op->sym->cipher.data.length, sr->iv.len,
573                         op->sym->auth.data.length, &sr->gph);
574         return 0;
575 }
576
577 static int
578 softreq_copy_salt(struct nitrox_softreq *sr)
579 {
580         struct nitrox_crypto_ctx *ctx = sr->ctx;
581         uint8_t *addr;
582
583         if (unlikely(ctx->iv.length < AES_GCM_SALT_SIZE)) {
584                 NITROX_LOG(ERR, "Invalid IV length %d\n", ctx->iv.length);
585                 return -EINVAL;
586         }
587
588         addr = rte_crypto_op_ctod_offset(sr->op, uint8_t *, ctx->iv.offset);
589         if (!memcmp(ctx->salt, addr, AES_GCM_SALT_SIZE))
590                 return 0;
591
592         memcpy(ctx->salt, addr, AES_GCM_SALT_SIZE);
593         memcpy(ctx->fctx.crypto.iv, addr, AES_GCM_SALT_SIZE);
594         return 0;
595 }
596
597 static int
598 extract_combined_digest(struct nitrox_softreq *sr, struct nitrox_sglist *digest)
599 {
600         struct rte_crypto_op *op = sr->op;
601         struct rte_mbuf *mdst = op->sym->m_dst ? op->sym->m_dst :
602                 op->sym->m_src;
603
604         digest->len = sr->ctx->digest_length;
605         if (op->sym->aead.digest.data) {
606                 digest->iova = op->sym->aead.digest.phys_addr;
607                 digest->virt = op->sym->aead.digest.data;
608
609                 return 0;
610         }
611
612         if (unlikely(rte_pktmbuf_data_len(mdst) < op->sym->aead.data.offset +
613                op->sym->aead.data.length + digest->len))
614                 return -EINVAL;
615
616         digest->iova = rte_pktmbuf_iova_offset(mdst,
617                                         op->sym->aead.data.offset +
618                                         op->sym->aead.data.length);
619         digest->virt = rte_pktmbuf_mtod_offset(mdst, uint8_t *,
620                                         op->sym->aead.data.offset +
621                                         op->sym->aead.data.length);
622
623         return 0;
624 }
625
626 static int
627 process_combined_data(struct nitrox_softreq *sr)
628 {
629         int err;
630         struct nitrox_sglist digest;
631         struct rte_crypto_op *op = sr->op;
632
633         err = softreq_copy_salt(sr);
634         if (unlikely(err))
635                 return err;
636
637         softreq_copy_iv(sr, AES_GCM_SALT_SIZE);
638         err = extract_combined_digest(sr, &digest);
639         if (unlikely(err))
640                 return err;
641
642         err = create_aead_inbuf(sr, &digest);
643         if (unlikely(err))
644                 return err;
645
646         err = create_aead_outbuf(sr, &digest);
647         if (unlikely(err))
648                 return err;
649
650         create_aead_gph(op->sym->aead.data.length, sr->iv.len,
651                         op->sym->aead.data.length + sr->ctx->aad_length,
652                         &sr->gph);
653
654         return 0;
655 }
656
657 static int
658 process_softreq(struct nitrox_softreq *sr)
659 {
660         struct nitrox_crypto_ctx *ctx = sr->ctx;
661         int err = 0;
662
663         switch (ctx->nitrox_chain) {
664         case NITROX_CHAIN_CIPHER_AUTH:
665         case NITROX_CHAIN_AUTH_CIPHER:
666                 err = process_cipher_auth_data(sr);
667                 break;
668         case NITROX_CHAIN_COMBINED:
669                 err = process_combined_data(sr);
670                 break;
671         default:
672                 err = -EINVAL;
673                 break;
674         }
675
676         return err;
677 }
678
679 int
680 nitrox_process_se_req(uint16_t qno, struct rte_crypto_op *op,
681                       struct nitrox_crypto_ctx *ctx,
682                       struct nitrox_softreq *sr)
683 {
684         int err;
685
686         softreq_init(sr, sr->iova);
687         sr->ctx = ctx;
688         sr->op = op;
689         err = process_softreq(sr);
690         if (unlikely(err))
691                 return err;
692
693         create_se_instr(sr, qno);
694         sr->timeout = rte_get_timer_cycles() + CMD_TIMEOUT * rte_get_timer_hz();
695         return 0;
696 }
697
698 int
699 nitrox_check_se_req(struct nitrox_softreq *sr, struct rte_crypto_op **op)
700 {
701         uint64_t cc;
702         uint64_t orh;
703         int err;
704
705         cc = *(volatile uint64_t *)(&sr->resp.completion);
706         orh = *(volatile uint64_t *)(&sr->resp.orh);
707         if (cc != PENDING_SIG)
708                 err = orh & 0xff;
709         else if ((orh != PENDING_SIG) && (orh & 0xff))
710                 err = orh & 0xff;
711         else if (rte_get_timer_cycles() >= sr->timeout)
712                 err = 0xff;
713         else
714                 return -EAGAIN;
715
716         if (unlikely(err))
717                 NITROX_LOG(ERR, "Request err 0x%x, orh 0x%"PRIx64"\n", err,
718                            sr->resp.orh);
719
720         *op = sr->op;
721         return err;
722 }
723
724 void *
725 nitrox_sym_instr_addr(struct nitrox_softreq *sr)
726 {
727         return &sr->instr;
728 }
729
730 static void
731 req_pool_obj_init(__rte_unused struct rte_mempool *mp,
732                   __rte_unused void *opaque, void *obj,
733                   __rte_unused unsigned int obj_idx)
734 {
735         softreq_init(obj, rte_mempool_virt2iova(obj));
736 }
737
738 struct rte_mempool *
739 nitrox_sym_req_pool_create(struct rte_cryptodev *cdev, uint32_t nobjs,
740                            uint16_t qp_id, int socket_id)
741 {
742         char softreq_pool_name[RTE_RING_NAMESIZE];
743         struct rte_mempool *mp;
744
745         snprintf(softreq_pool_name, RTE_RING_NAMESIZE, "%s_sr_%d",
746                  cdev->data->name, qp_id);
747         mp = rte_mempool_create(softreq_pool_name,
748                                 RTE_ALIGN_MUL_CEIL(nobjs, 64),
749                                 sizeof(struct nitrox_softreq),
750                                 64, 0, NULL, NULL, req_pool_obj_init, NULL,
751                                 socket_id, 0);
752         if (unlikely(!mp))
753                 NITROX_LOG(ERR, "Failed to create req pool, qid %d, err %d\n",
754                            qp_id, rte_errno);
755
756         return mp;
757 }
758
759 void
760 nitrox_sym_req_pool_free(struct rte_mempool *mp)
761 {
762         rte_mempool_free(mp);
763 }