ab595eb5803a7cc3436acb62d975dc3ea6760478
[dpdk.git] / drivers / common / cpt / cpt_ucode.h
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018 Cavium, Inc
3  */
4
5 #ifndef _CPT_UCODE_H_
6 #define _CPT_UCODE_H_
7 #include <stdbool.h>
8
9 #include "cpt_common.h"
10 #include "cpt_hw_types.h"
11 #include "cpt_mcode_defines.h"
12
13 /*
14  * This file defines functions that are interfaces to microcode spec.
15  *
16  */
17
18 static uint8_t zuc_d[32] = {
19         0x44, 0xD7, 0x26, 0xBC, 0x62, 0x6B, 0x13, 0x5E,
20         0x57, 0x89, 0x35, 0xE2, 0x71, 0x35, 0x09, 0xAF,
21         0x4D, 0x78, 0x2F, 0x13, 0x6B, 0xC4, 0x1A, 0xF1,
22         0x5E, 0x26, 0x3C, 0x4D, 0x78, 0x9A, 0x47, 0xAC
23 };
24
25 static __rte_always_inline void
26 gen_key_snow3g(const uint8_t *ck, uint32_t *keyx)
27 {
28         int i, base;
29
30         for (i = 0; i < 4; i++) {
31                 base = 4 * i;
32                 keyx[3 - i] = (ck[base] << 24) | (ck[base + 1] << 16) |
33                         (ck[base + 2] << 8) | (ck[base + 3]);
34                 keyx[3 - i] = rte_cpu_to_be_32(keyx[3 - i]);
35         }
36 }
37
38 static __rte_always_inline void
39 cpt_fc_salt_update(void *ctx,
40                    uint8_t *salt)
41 {
42         struct cpt_ctx *cpt_ctx = ctx;
43         memcpy(&cpt_ctx->fctx.enc.encr_iv, salt, 4);
44 }
45
46 static __rte_always_inline int
47 cpt_fc_ciph_validate_key_aes(uint16_t key_len)
48 {
49         switch (key_len) {
50         case CPT_BYTE_16:
51         case CPT_BYTE_24:
52         case CPT_BYTE_32:
53                 return 0;
54         default:
55                 return -1;
56         }
57 }
58
59 static __rte_always_inline int
60 cpt_fc_ciph_set_type(cipher_type_t type, struct cpt_ctx *ctx, uint16_t key_len)
61 {
62         int fc_type = 0;
63         switch (type) {
64         case PASSTHROUGH:
65                 fc_type = FC_GEN;
66                 break;
67         case DES3_CBC:
68         case DES3_ECB:
69                 fc_type = FC_GEN;
70                 break;
71         case AES_CBC:
72         case AES_ECB:
73         case AES_CFB:
74         case AES_CTR:
75         case AES_GCM:
76                 if (unlikely(cpt_fc_ciph_validate_key_aes(key_len) != 0))
77                         return -1;
78                 fc_type = FC_GEN;
79                 break;
80         case AES_XTS:
81                 key_len = key_len / 2;
82                 if (unlikely(key_len == CPT_BYTE_24)) {
83                         CPT_LOG_DP_ERR("Invalid AES key len for XTS");
84                         return -1;
85                 }
86                 if (unlikely(cpt_fc_ciph_validate_key_aes(key_len) != 0))
87                         return -1;
88                 fc_type = FC_GEN;
89                 break;
90         case ZUC_EEA3:
91         case SNOW3G_UEA2:
92                 if (unlikely(key_len != 16))
93                         return -1;
94                 /* No support for AEAD yet */
95                 if (unlikely(ctx->hash_type))
96                         return -1;
97                 fc_type = ZUC_SNOW3G;
98                 break;
99         case KASUMI_F8_CBC:
100         case KASUMI_F8_ECB:
101                 if (unlikely(key_len != 16))
102                         return -1;
103                 /* No support for AEAD yet */
104                 if (unlikely(ctx->hash_type))
105                         return -1;
106                 fc_type = KASUMI;
107                 break;
108         default:
109                 return -1;
110         }
111
112         ctx->fc_type = fc_type;
113         return 0;
114 }
115
116 static __rte_always_inline void
117 cpt_fc_ciph_set_key_passthrough(struct cpt_ctx *cpt_ctx, mc_fc_context_t *fctx)
118 {
119         cpt_ctx->enc_cipher = 0;
120         fctx->enc.enc_cipher = 0;
121 }
122
123 static __rte_always_inline void
124 cpt_fc_ciph_set_key_set_aes_key_type(mc_fc_context_t *fctx, uint16_t key_len)
125 {
126         mc_aes_type_t aes_key_type = 0;
127         switch (key_len) {
128         case CPT_BYTE_16:
129                 aes_key_type = AES_128_BIT;
130                 break;
131         case CPT_BYTE_24:
132                 aes_key_type = AES_192_BIT;
133                 break;
134         case CPT_BYTE_32:
135                 aes_key_type = AES_256_BIT;
136                 break;
137         default:
138                 /* This should not happen */
139                 CPT_LOG_DP_ERR("Invalid AES key len");
140                 return;
141         }
142         fctx->enc.aes_key = aes_key_type;
143 }
144
145 static __rte_always_inline void
146 cpt_fc_ciph_set_key_snow3g_uea2(struct cpt_ctx *cpt_ctx, const uint8_t *key,
147                 uint16_t key_len)
148 {
149         uint32_t keyx[4];
150         cpt_ctx->snow3g = 1;
151         gen_key_snow3g(key, keyx);
152         memcpy(cpt_ctx->zs_ctx.ci_key, keyx, key_len);
153         cpt_ctx->zsk_flags = 0;
154 }
155
156 static __rte_always_inline void
157 cpt_fc_ciph_set_key_zuc_eea3(struct cpt_ctx *cpt_ctx, const uint8_t *key,
158                 uint16_t key_len)
159 {
160         cpt_ctx->snow3g = 0;
161         memcpy(cpt_ctx->zs_ctx.ci_key, key, key_len);
162         memcpy(cpt_ctx->zs_ctx.zuc_const, zuc_d, 32);
163         cpt_ctx->zsk_flags = 0;
164 }
165
166 static __rte_always_inline void
167 cpt_fc_ciph_set_key_kasumi_f8_ecb(struct cpt_ctx *cpt_ctx, const uint8_t *key,
168                 uint16_t key_len)
169 {
170         cpt_ctx->k_ecb = 1;
171         memcpy(cpt_ctx->k_ctx.ci_key, key, key_len);
172         cpt_ctx->zsk_flags = 0;
173 }
174
175 static __rte_always_inline void
176 cpt_fc_ciph_set_key_kasumi_f8_cbc(struct cpt_ctx *cpt_ctx, const uint8_t *key,
177                 uint16_t key_len)
178 {
179         memcpy(cpt_ctx->k_ctx.ci_key, key, key_len);
180         cpt_ctx->zsk_flags = 0;
181 }
182
183 static __rte_always_inline int
184 cpt_fc_ciph_set_key(void *ctx, cipher_type_t type, const uint8_t *key,
185                     uint16_t key_len, uint8_t *salt)
186 {
187         struct cpt_ctx *cpt_ctx = ctx;
188         mc_fc_context_t *fctx = &cpt_ctx->fctx;
189         int ret;
190
191         ret = cpt_fc_ciph_set_type(type, cpt_ctx, key_len);
192         if (unlikely(ret))
193                 return -1;
194
195         if (cpt_ctx->fc_type == FC_GEN) {
196                 /*
197                  * We need to always say IV is from DPTR as user can
198                  * sometimes iverride IV per operation.
199                  */
200                 fctx->enc.iv_source = CPT_FROM_DPTR;
201
202                 if (cpt_ctx->auth_key_len > 64)
203                         return -1;
204         }
205
206         switch (type) {
207         case PASSTHROUGH:
208                 cpt_fc_ciph_set_key_passthrough(cpt_ctx, fctx);
209                 goto success;
210         case DES3_CBC:
211                 /* CPT performs DES using 3DES with the 8B DES-key
212                  * replicated 2 more times to match the 24B 3DES-key.
213                  * Eg. If org. key is "0x0a 0x0b", then new key is
214                  * "0x0a 0x0b 0x0a 0x0b 0x0a 0x0b"
215                  */
216                 if (key_len == 8) {
217                         /* Skipping the first 8B as it will be copied
218                          * in the regular code flow
219                          */
220                         memcpy(fctx->enc.encr_key+key_len, key, key_len);
221                         memcpy(fctx->enc.encr_key+2*key_len, key, key_len);
222                 }
223                 break;
224         case DES3_ECB:
225                 /* For DES3_ECB IV need to be from CTX. */
226                 fctx->enc.iv_source = CPT_FROM_CTX;
227                 break;
228         case AES_CBC:
229         case AES_ECB:
230         case AES_CFB:
231         case AES_CTR:
232                 cpt_fc_ciph_set_key_set_aes_key_type(fctx, key_len);
233                 break;
234         case AES_GCM:
235                 /* Even though iv source is from dptr,
236                  * aes_gcm salt is taken from ctx
237                  */
238                 if (salt) {
239                         memcpy(fctx->enc.encr_iv, salt, 4);
240                         /* Assuming it was just salt update
241                          * and nothing else
242                          */
243                         if (!key)
244                                 goto success;
245                 }
246                 cpt_fc_ciph_set_key_set_aes_key_type(fctx, key_len);
247                 break;
248         case AES_XTS:
249                 key_len = key_len / 2;
250                 cpt_fc_ciph_set_key_set_aes_key_type(fctx, key_len);
251
252                 /* Copy key2 for XTS into ipad */
253                 memset(fctx->hmac.ipad, 0, sizeof(fctx->hmac.ipad));
254                 memcpy(fctx->hmac.ipad, &key[key_len], key_len);
255                 break;
256         case SNOW3G_UEA2:
257                 cpt_fc_ciph_set_key_snow3g_uea2(cpt_ctx, key, key_len);
258                 goto success;
259         case ZUC_EEA3:
260                 cpt_fc_ciph_set_key_zuc_eea3(cpt_ctx, key, key_len);
261                 goto success;
262         case KASUMI_F8_ECB:
263                 cpt_fc_ciph_set_key_kasumi_f8_ecb(cpt_ctx, key, key_len);
264                 goto success;
265         case KASUMI_F8_CBC:
266                 cpt_fc_ciph_set_key_kasumi_f8_cbc(cpt_ctx, key, key_len);
267                 goto success;
268         default:
269                 return -1;
270         }
271
272         /* Only for FC_GEN case */
273
274         /* For GMAC auth, cipher must be NULL */
275         if (cpt_ctx->hash_type != GMAC_TYPE)
276                 fctx->enc.enc_cipher = type;
277
278         memcpy(fctx->enc.encr_key, key, key_len);
279
280 success:
281         cpt_ctx->enc_cipher = type;
282
283         return 0;
284 }
285
286 static __rte_always_inline uint32_t
287 fill_sg_comp(sg_comp_t *list,
288              uint32_t i,
289              phys_addr_t dma_addr,
290              uint32_t size)
291 {
292         sg_comp_t *to = &list[i>>2];
293
294         to->u.s.len[i%4] = rte_cpu_to_be_16(size);
295         to->ptr[i%4] = rte_cpu_to_be_64(dma_addr);
296         i++;
297         return i;
298 }
299
300 static __rte_always_inline uint32_t
301 fill_sg_comp_from_buf(sg_comp_t *list,
302                       uint32_t i,
303                       buf_ptr_t *from)
304 {
305         sg_comp_t *to = &list[i>>2];
306
307         to->u.s.len[i%4] = rte_cpu_to_be_16(from->size);
308         to->ptr[i%4] = rte_cpu_to_be_64(from->dma_addr);
309         i++;
310         return i;
311 }
312
313 static __rte_always_inline uint32_t
314 fill_sg_comp_from_buf_min(sg_comp_t *list,
315                           uint32_t i,
316                           buf_ptr_t *from,
317                           uint32_t *psize)
318 {
319         sg_comp_t *to = &list[i >> 2];
320         uint32_t size = *psize;
321         uint32_t e_len;
322
323         e_len = (size > from->size) ? from->size : size;
324         to->u.s.len[i % 4] = rte_cpu_to_be_16(e_len);
325         to->ptr[i % 4] = rte_cpu_to_be_64(from->dma_addr);
326         *psize -= e_len;
327         i++;
328         return i;
329 }
330
331 /*
332  * This fills the MC expected SGIO list
333  * from IOV given by user.
334  */
335 static __rte_always_inline uint32_t
336 fill_sg_comp_from_iov(sg_comp_t *list,
337                       uint32_t i,
338                       iov_ptr_t *from, uint32_t from_offset,
339                       uint32_t *psize, buf_ptr_t *extra_buf,
340                       uint32_t extra_offset)
341 {
342         int32_t j;
343         uint32_t extra_len = extra_buf ? extra_buf->size : 0;
344         uint32_t size = *psize;
345         buf_ptr_t *bufs;
346
347         bufs = from->bufs;
348         for (j = 0; (j < from->buf_cnt) && size; j++) {
349                 phys_addr_t e_dma_addr;
350                 uint32_t e_len;
351                 sg_comp_t *to = &list[i >> 2];
352
353                 if (unlikely(from_offset)) {
354                         if (from_offset >= bufs[j].size) {
355                                 from_offset -= bufs[j].size;
356                                 continue;
357                         }
358                         e_dma_addr = bufs[j].dma_addr + from_offset;
359                         e_len = (size > (bufs[j].size - from_offset)) ?
360                                 (bufs[j].size - from_offset) : size;
361                         from_offset = 0;
362                 } else {
363                         e_dma_addr = bufs[j].dma_addr;
364                         e_len = (size > bufs[j].size) ?
365                                 bufs[j].size : size;
366                 }
367
368                 to->u.s.len[i % 4] = rte_cpu_to_be_16(e_len);
369                 to->ptr[i % 4] = rte_cpu_to_be_64(e_dma_addr);
370
371                 if (extra_len && (e_len >= extra_offset)) {
372                         /* Break the data at given offset */
373                         uint32_t next_len = e_len - extra_offset;
374                         phys_addr_t next_dma = e_dma_addr + extra_offset;
375
376                         if (!extra_offset) {
377                                 i--;
378                         } else {
379                                 e_len = extra_offset;
380                                 size -= e_len;
381                                 to->u.s.len[i % 4] = rte_cpu_to_be_16(e_len);
382                         }
383
384                         extra_len = RTE_MIN(extra_len, size);
385                         /* Insert extra data ptr */
386                         if (extra_len) {
387                                 i++;
388                                 to = &list[i >> 2];
389                                 to->u.s.len[i % 4] =
390                                         rte_cpu_to_be_16(extra_len);
391                                 to->ptr[i % 4] =
392                                         rte_cpu_to_be_64(extra_buf->dma_addr);
393                                 size -= extra_len;
394                         }
395
396                         next_len = RTE_MIN(next_len, size);
397                         /* insert the rest of the data */
398                         if (next_len) {
399                                 i++;
400                                 to = &list[i >> 2];
401                                 to->u.s.len[i % 4] = rte_cpu_to_be_16(next_len);
402                                 to->ptr[i % 4] = rte_cpu_to_be_64(next_dma);
403                                 size -= next_len;
404                         }
405                         extra_len = 0;
406
407                 } else {
408                         size -= e_len;
409                 }
410                 if (extra_offset)
411                         extra_offset -= size;
412                 i++;
413         }
414
415         *psize = size;
416         return (uint32_t)i;
417 }
418
419 static __rte_always_inline void
420 cpt_digest_gen_prep(uint32_t flags,
421                     uint64_t d_lens,
422                     digest_params_t *params,
423                     void *op,
424                     void **prep_req)
425 {
426         struct cpt_request_info *req;
427         uint32_t size, i;
428         uint16_t data_len, mac_len, key_len;
429         auth_type_t hash_type;
430         buf_ptr_t *meta_p;
431         struct cpt_ctx *ctx;
432         sg_comp_t *gather_comp;
433         sg_comp_t *scatter_comp;
434         uint8_t *in_buffer;
435         uint32_t g_size_bytes, s_size_bytes;
436         uint64_t dptr_dma, rptr_dma;
437         vq_cmd_word0_t vq_cmd_w0;
438         vq_cmd_word3_t vq_cmd_w3;
439         void *c_vaddr, *m_vaddr;
440         uint64_t c_dma, m_dma;
441         opcode_info_t opcode;
442
443         ctx = params->ctx_buf.vaddr;
444         meta_p = &params->meta_buf;
445
446         m_vaddr = meta_p->vaddr;
447         m_dma = meta_p->dma_addr;
448
449         /*
450          * Save initial space that followed app data for completion code &
451          * alternate completion code to fall in same cache line as app data
452          */
453         m_vaddr = (uint8_t *)m_vaddr + COMPLETION_CODE_SIZE;
454         m_dma += COMPLETION_CODE_SIZE;
455         size = (uint8_t *)RTE_PTR_ALIGN((uint8_t *)m_vaddr, 16) -
456                 (uint8_t *)m_vaddr;
457         c_vaddr = (uint8_t *)m_vaddr + size;
458         c_dma = m_dma + size;
459         size += sizeof(cpt_res_s_t);
460
461         m_vaddr = (uint8_t *)m_vaddr + size;
462         m_dma += size;
463
464         req = m_vaddr;
465
466         size = sizeof(struct cpt_request_info);
467         m_vaddr = (uint8_t *)m_vaddr + size;
468         m_dma += size;
469
470         hash_type = ctx->hash_type;
471         mac_len = ctx->mac_len;
472         key_len = ctx->auth_key_len;
473         data_len = AUTH_DLEN(d_lens);
474
475         /*GP op header */
476         vq_cmd_w0.u64 = 0;
477         vq_cmd_w0.s.param2 = ((uint16_t)hash_type << 8);
478         if (ctx->hmac) {
479                 opcode.s.major = CPT_MAJOR_OP_HMAC | CPT_DMA_MODE;
480                 vq_cmd_w0.s.param1 = key_len;
481                 vq_cmd_w0.s.dlen = data_len + ROUNDUP8(key_len);
482         } else {
483                 opcode.s.major = CPT_MAJOR_OP_HASH | CPT_DMA_MODE;
484                 vq_cmd_w0.s.param1 = 0;
485                 vq_cmd_w0.s.dlen = data_len;
486         }
487
488         opcode.s.minor = 0;
489
490         /* Null auth only case enters the if */
491         if (unlikely(!hash_type && !ctx->enc_cipher)) {
492                 opcode.s.major = CPT_MAJOR_OP_MISC;
493                 /* Minor op is passthrough */
494                 opcode.s.minor = 0x03;
495                 /* Send out completion code only */
496                 vq_cmd_w0.s.param2 = 0x1;
497         }
498
499         vq_cmd_w0.s.opcode = opcode.flags;
500
501         /* DPTR has SG list */
502         in_buffer = m_vaddr;
503         dptr_dma = m_dma;
504
505         ((uint16_t *)in_buffer)[0] = 0;
506         ((uint16_t *)in_buffer)[1] = 0;
507
508         /* TODO Add error check if space will be sufficient */
509         gather_comp = (sg_comp_t *)((uint8_t *)m_vaddr + 8);
510
511         /*
512          * Input gather list
513          */
514
515         i = 0;
516
517         if (ctx->hmac) {
518                 uint64_t k_dma = params->ctx_buf.dma_addr +
519                         offsetof(struct cpt_ctx, auth_key);
520                 /* Key */
521                 i = fill_sg_comp(gather_comp, i, k_dma, ROUNDUP8(key_len));
522         }
523
524         /* input data */
525         size = data_len;
526         if (size) {
527                 i = fill_sg_comp_from_iov(gather_comp, i, params->src_iov,
528                                           0, &size, NULL, 0);
529                 if (unlikely(size)) {
530                         CPT_LOG_DP_DEBUG("Insufficient dst IOV size, short"
531                                          " by %dB", size);
532                         return;
533                 }
534         } else {
535                 /*
536                  * Looks like we need to support zero data
537                  * gather ptr in case of hash & hmac
538                  */
539                 i++;
540         }
541         ((uint16_t *)in_buffer)[2] = rte_cpu_to_be_16(i);
542         g_size_bytes = ((i + 3) / 4) * sizeof(sg_comp_t);
543
544         /*
545          * Output Gather list
546          */
547
548         i = 0;
549         scatter_comp = (sg_comp_t *)((uint8_t *)gather_comp + g_size_bytes);
550
551         if (flags & VALID_MAC_BUF) {
552                 if (unlikely(params->mac_buf.size < mac_len)) {
553                         CPT_LOG_DP_ERR("Insufficient MAC size");
554                         return;
555                 }
556
557                 size = mac_len;
558                 i = fill_sg_comp_from_buf_min(scatter_comp, i,
559                                               &params->mac_buf, &size);
560         } else {
561                 size = mac_len;
562                 i = fill_sg_comp_from_iov(scatter_comp, i,
563                                           params->src_iov, data_len,
564                                           &size, NULL, 0);
565                 if (unlikely(size)) {
566                         CPT_LOG_DP_ERR("Insufficient dst IOV size, short by"
567                                        " %dB", size);
568                         return;
569                 }
570         }
571
572         ((uint16_t *)in_buffer)[3] = rte_cpu_to_be_16(i);
573         s_size_bytes = ((i + 3) / 4) * sizeof(sg_comp_t);
574
575         size = g_size_bytes + s_size_bytes + SG_LIST_HDR_SIZE;
576
577         /* This is DPTR len incase of SG mode */
578         vq_cmd_w0.s.dlen = size;
579
580         m_vaddr = (uint8_t *)m_vaddr + size;
581         m_dma += size;
582
583         /* cpt alternate completion address saved earlier */
584         req->alternate_caddr = (uint64_t *)((uint8_t *)c_vaddr - 8);
585         *req->alternate_caddr = ~((uint64_t)COMPLETION_CODE_INIT);
586         rptr_dma = c_dma - 8;
587
588         req->ist.ei1 = dptr_dma;
589         req->ist.ei2 = rptr_dma;
590
591         /* vq command w3 */
592         vq_cmd_w3.u64 = 0;
593
594         /* 16 byte aligned cpt res address */
595         req->completion_addr = (uint64_t *)((uint8_t *)c_vaddr);
596         *req->completion_addr = COMPLETION_CODE_INIT;
597         req->comp_baddr  = c_dma;
598
599         /* Fill microcode part of instruction */
600         req->ist.ei0 = vq_cmd_w0.u64;
601         req->ist.ei3 = vq_cmd_w3.u64;
602
603         req->op = op;
604
605         *prep_req = req;
606         return;
607 }
608
609 static __rte_always_inline void
610 cpt_enc_hmac_prep(uint32_t flags,
611                   uint64_t d_offs,
612                   uint64_t d_lens,
613                   fc_params_t *fc_params,
614                   void *op,
615                   void **prep_req)
616 {
617         uint32_t iv_offset = 0;
618         int32_t inputlen, outputlen, enc_dlen, auth_dlen;
619         struct cpt_ctx *cpt_ctx;
620         uint32_t cipher_type, hash_type;
621         uint32_t mac_len, size;
622         uint8_t iv_len = 16;
623         struct cpt_request_info *req;
624         buf_ptr_t *meta_p, *aad_buf = NULL;
625         uint32_t encr_offset, auth_offset;
626         uint32_t encr_data_len, auth_data_len, aad_len = 0;
627         uint32_t passthrough_len = 0;
628         void *m_vaddr, *offset_vaddr;
629         uint64_t m_dma, offset_dma, ctx_dma;
630         vq_cmd_word0_t vq_cmd_w0;
631         vq_cmd_word3_t vq_cmd_w3;
632         void *c_vaddr;
633         uint64_t c_dma;
634         opcode_info_t opcode;
635
636         meta_p = &fc_params->meta_buf;
637         m_vaddr = meta_p->vaddr;
638         m_dma = meta_p->dma_addr;
639
640         encr_offset = ENCR_OFFSET(d_offs);
641         auth_offset = AUTH_OFFSET(d_offs);
642         encr_data_len = ENCR_DLEN(d_lens);
643         auth_data_len = AUTH_DLEN(d_lens);
644         if (unlikely(flags & VALID_AAD_BUF)) {
645                 /*
646                  * We dont support both aad
647                  * and auth data separately
648                  */
649                 auth_data_len = 0;
650                 auth_offset = 0;
651                 aad_len = fc_params->aad_buf.size;
652                 aad_buf = &fc_params->aad_buf;
653         }
654         cpt_ctx = fc_params->ctx_buf.vaddr;
655         cipher_type = cpt_ctx->enc_cipher;
656         hash_type = cpt_ctx->hash_type;
657         mac_len = cpt_ctx->mac_len;
658
659         /*
660          * Save initial space that followed app data for completion code &
661          * alternate completion code to fall in same cache line as app data
662          */
663         m_vaddr = (uint8_t *)m_vaddr + COMPLETION_CODE_SIZE;
664         m_dma += COMPLETION_CODE_SIZE;
665         size = (uint8_t *)RTE_PTR_ALIGN((uint8_t *)m_vaddr, 16) -
666                 (uint8_t *)m_vaddr;
667
668         c_vaddr = (uint8_t *)m_vaddr + size;
669         c_dma = m_dma + size;
670         size += sizeof(cpt_res_s_t);
671
672         m_vaddr = (uint8_t *)m_vaddr + size;
673         m_dma += size;
674
675         /* start cpt request info struct at 8 byte boundary */
676         size = (uint8_t *)RTE_PTR_ALIGN(m_vaddr, 8) -
677                 (uint8_t *)m_vaddr;
678
679         req = (struct cpt_request_info *)((uint8_t *)m_vaddr + size);
680
681         size += sizeof(struct cpt_request_info);
682         m_vaddr = (uint8_t *)m_vaddr + size;
683         m_dma += size;
684
685         if (unlikely(!(flags & VALID_IV_BUF))) {
686                 iv_len = 0;
687                 iv_offset = ENCR_IV_OFFSET(d_offs);
688         }
689
690         if (unlikely(flags & VALID_AAD_BUF)) {
691                 /*
692                  * When AAD is given, data above encr_offset is pass through
693                  * Since AAD is given as separate pointer and not as offset,
694                  * this is a special case as we need to fragment input data
695                  * into passthrough + encr_data and then insert AAD in between.
696                  */
697                 if (hash_type != GMAC_TYPE) {
698                         passthrough_len = encr_offset;
699                         auth_offset = passthrough_len + iv_len;
700                         encr_offset = passthrough_len + aad_len + iv_len;
701                         auth_data_len = aad_len + encr_data_len;
702                 } else {
703                         passthrough_len = 16 + aad_len;
704                         auth_offset = passthrough_len + iv_len;
705                         auth_data_len = aad_len;
706                 }
707         } else {
708                 encr_offset += iv_len;
709                 auth_offset += iv_len;
710         }
711
712         /* Encryption */
713         opcode.s.major = CPT_MAJOR_OP_FC;
714         opcode.s.minor = 0;
715
716         if (hash_type == GMAC_TYPE) {
717                 encr_offset = 0;
718                 encr_data_len = 0;
719         }
720
721         auth_dlen = auth_offset + auth_data_len;
722         enc_dlen = encr_data_len + encr_offset;
723         if (unlikely(encr_data_len & 0xf)) {
724                 if ((cipher_type == DES3_CBC) || (cipher_type == DES3_ECB))
725                         enc_dlen = ROUNDUP8(encr_data_len) + encr_offset;
726                 else if (likely((cipher_type == AES_CBC) ||
727                                 (cipher_type == AES_ECB)))
728                         enc_dlen = ROUNDUP16(encr_data_len) + encr_offset;
729         }
730
731         if (unlikely(auth_dlen > enc_dlen)) {
732                 inputlen = auth_dlen;
733                 outputlen = auth_dlen + mac_len;
734         } else {
735                 inputlen = enc_dlen;
736                 outputlen = enc_dlen + mac_len;
737         }
738
739         /* GP op header */
740         vq_cmd_w0.u64 = 0;
741         vq_cmd_w0.s.param1 = encr_data_len;
742         vq_cmd_w0.s.param2 = auth_data_len;
743         /*
744          * In 83XX since we have a limitation of
745          * IV & Offset control word not part of instruction
746          * and need to be part of Data Buffer, we check if
747          * head room is there and then only do the Direct mode processing
748          */
749         if (likely((flags & SINGLE_BUF_INPLACE) &&
750                    (flags & SINGLE_BUF_HEADTAILROOM))) {
751                 void *dm_vaddr = fc_params->bufs[0].vaddr;
752                 uint64_t dm_dma_addr = fc_params->bufs[0].dma_addr;
753                 /*
754                  * This flag indicates that there is 24 bytes head room and
755                  * 8 bytes tail room available, so that we get to do
756                  * DIRECT MODE with limitation
757                  */
758
759                 offset_vaddr = (uint8_t *)dm_vaddr - OFF_CTRL_LEN - iv_len;
760                 offset_dma = dm_dma_addr - OFF_CTRL_LEN - iv_len;
761
762                 /* DPTR */
763                 req->ist.ei1 = offset_dma;
764                 /* RPTR should just exclude offset control word */
765                 req->ist.ei2 = dm_dma_addr - iv_len;
766                 req->alternate_caddr = (uint64_t *)((uint8_t *)dm_vaddr
767                                                     + outputlen - iv_len);
768
769                 vq_cmd_w0.s.dlen = inputlen + OFF_CTRL_LEN;
770
771                 vq_cmd_w0.s.opcode = opcode.flags;
772
773                 if (likely(iv_len)) {
774                         uint64_t *dest = (uint64_t *)((uint8_t *)offset_vaddr
775                                                       + OFF_CTRL_LEN);
776                         uint64_t *src = fc_params->iv_buf;
777                         dest[0] = src[0];
778                         dest[1] = src[1];
779                 }
780
781                 *(uint64_t *)offset_vaddr =
782                         rte_cpu_to_be_64(((uint64_t)encr_offset << 16) |
783                                 ((uint64_t)iv_offset << 8) |
784                                 ((uint64_t)auth_offset));
785
786         } else {
787                 uint32_t i, g_size_bytes, s_size_bytes;
788                 uint64_t dptr_dma, rptr_dma;
789                 sg_comp_t *gather_comp;
790                 sg_comp_t *scatter_comp;
791                 uint8_t *in_buffer;
792
793                 /* This falls under strict SG mode */
794                 offset_vaddr = m_vaddr;
795                 offset_dma = m_dma;
796                 size = OFF_CTRL_LEN + iv_len;
797
798                 m_vaddr = (uint8_t *)m_vaddr + size;
799                 m_dma += size;
800
801                 opcode.s.major |= CPT_DMA_MODE;
802
803                 vq_cmd_w0.s.opcode = opcode.flags;
804
805                 if (likely(iv_len)) {
806                         uint64_t *dest = (uint64_t *)((uint8_t *)offset_vaddr
807                                                       + OFF_CTRL_LEN);
808                         uint64_t *src = fc_params->iv_buf;
809                         dest[0] = src[0];
810                         dest[1] = src[1];
811                 }
812
813                 *(uint64_t *)offset_vaddr =
814                         rte_cpu_to_be_64(((uint64_t)encr_offset << 16) |
815                                 ((uint64_t)iv_offset << 8) |
816                                 ((uint64_t)auth_offset));
817
818                 /* DPTR has SG list */
819                 in_buffer = m_vaddr;
820                 dptr_dma = m_dma;
821
822                 ((uint16_t *)in_buffer)[0] = 0;
823                 ((uint16_t *)in_buffer)[1] = 0;
824
825                 /* TODO Add error check if space will be sufficient */
826                 gather_comp = (sg_comp_t *)((uint8_t *)m_vaddr + 8);
827
828                 /*
829                  * Input Gather List
830                  */
831
832                 i = 0;
833
834                 /* Offset control word that includes iv */
835                 i = fill_sg_comp(gather_comp, i, offset_dma,
836                                  OFF_CTRL_LEN + iv_len);
837
838                 /* Add input data */
839                 size = inputlen - iv_len;
840                 if (likely(size)) {
841                         uint32_t aad_offset = aad_len ? passthrough_len : 0;
842
843                         if (unlikely(flags & SINGLE_BUF_INPLACE)) {
844                                 i = fill_sg_comp_from_buf_min(gather_comp, i,
845                                                               fc_params->bufs,
846                                                               &size);
847                         } else {
848                                 i = fill_sg_comp_from_iov(gather_comp, i,
849                                                           fc_params->src_iov,
850                                                           0, &size,
851                                                           aad_buf, aad_offset);
852                         }
853
854                         if (unlikely(size)) {
855                                 CPT_LOG_DP_ERR("Insufficient buffer space,"
856                                                " size %d needed", size);
857                                 return;
858                         }
859                 }
860                 ((uint16_t *)in_buffer)[2] = rte_cpu_to_be_16(i);
861                 g_size_bytes = ((i + 3) / 4) * sizeof(sg_comp_t);
862
863                 /*
864                  * Output Scatter list
865                  */
866                 i = 0;
867                 scatter_comp =
868                         (sg_comp_t *)((uint8_t *)gather_comp + g_size_bytes);
869
870                 /* Add IV */
871                 if (likely(iv_len)) {
872                         i = fill_sg_comp(scatter_comp, i,
873                                          offset_dma + OFF_CTRL_LEN,
874                                          iv_len);
875                 }
876
877                 /* output data or output data + digest*/
878                 if (unlikely(flags & VALID_MAC_BUF)) {
879                         size = outputlen - iv_len - mac_len;
880                         if (size) {
881                                 uint32_t aad_offset =
882                                         aad_len ? passthrough_len : 0;
883
884                                 if (unlikely(flags & SINGLE_BUF_INPLACE)) {
885                                         i = fill_sg_comp_from_buf_min(
886                                                         scatter_comp,
887                                                         i,
888                                                         fc_params->bufs,
889                                                         &size);
890                                 } else {
891                                         i = fill_sg_comp_from_iov(scatter_comp,
892                                                         i,
893                                                         fc_params->dst_iov,
894                                                         0,
895                                                         &size,
896                                                         aad_buf,
897                                                         aad_offset);
898                                 }
899                                 if (unlikely(size)) {
900                                         CPT_LOG_DP_ERR("Insufficient buffer"
901                                                        " space, size %d needed",
902                                                        size);
903                                         return;
904                                 }
905                         }
906                         /* mac_data */
907                         if (mac_len) {
908                                 i = fill_sg_comp_from_buf(scatter_comp, i,
909                                                           &fc_params->mac_buf);
910                         }
911                 } else {
912                         /* Output including mac */
913                         size = outputlen - iv_len;
914                         if (likely(size)) {
915                                 uint32_t aad_offset =
916                                         aad_len ? passthrough_len : 0;
917
918                                 if (unlikely(flags & SINGLE_BUF_INPLACE)) {
919                                         i = fill_sg_comp_from_buf_min(
920                                                         scatter_comp,
921                                                         i,
922                                                         fc_params->bufs,
923                                                         &size);
924                                 } else {
925                                         i = fill_sg_comp_from_iov(scatter_comp,
926                                                         i,
927                                                         fc_params->dst_iov,
928                                                         0,
929                                                         &size,
930                                                         aad_buf,
931                                                         aad_offset);
932                                 }
933                                 if (unlikely(size)) {
934                                         CPT_LOG_DP_ERR("Insufficient buffer"
935                                                        " space, size %d needed",
936                                                        size);
937                                         return;
938                                 }
939                         }
940                 }
941                 ((uint16_t *)in_buffer)[3] = rte_cpu_to_be_16(i);
942                 s_size_bytes = ((i + 3) / 4) * sizeof(sg_comp_t);
943
944                 size = g_size_bytes + s_size_bytes + SG_LIST_HDR_SIZE;
945
946                 /* This is DPTR len incase of SG mode */
947                 vq_cmd_w0.s.dlen = size;
948
949                 m_vaddr = (uint8_t *)m_vaddr + size;
950                 m_dma += size;
951
952                 /* cpt alternate completion address saved earlier */
953                 req->alternate_caddr = (uint64_t *)((uint8_t *)c_vaddr - 8);
954                 *req->alternate_caddr = ~((uint64_t)COMPLETION_CODE_INIT);
955                 rptr_dma = c_dma - 8;
956
957                 req->ist.ei1 = dptr_dma;
958                 req->ist.ei2 = rptr_dma;
959         }
960
961         ctx_dma = fc_params->ctx_buf.dma_addr +
962                 offsetof(struct cpt_ctx, fctx);
963         /* vq command w3 */
964         vq_cmd_w3.u64 = 0;
965         vq_cmd_w3.s.grp = 0;
966         vq_cmd_w3.s.cptr = ctx_dma;
967
968         /* 16 byte aligned cpt res address */
969         req->completion_addr = (uint64_t *)((uint8_t *)c_vaddr);
970         *req->completion_addr = COMPLETION_CODE_INIT;
971         req->comp_baddr  = c_dma;
972
973         /* Fill microcode part of instruction */
974         req->ist.ei0 = vq_cmd_w0.u64;
975         req->ist.ei3 = vq_cmd_w3.u64;
976
977         req->op  = op;
978
979         *prep_req = req;
980         return;
981 }
982
983 static __rte_always_inline void
984 cpt_dec_hmac_prep(uint32_t flags,
985                   uint64_t d_offs,
986                   uint64_t d_lens,
987                   fc_params_t *fc_params,
988                   void *op,
989                   void **prep_req)
990 {
991         uint32_t iv_offset = 0, size;
992         int32_t inputlen, outputlen, enc_dlen, auth_dlen;
993         struct cpt_ctx *cpt_ctx;
994         int32_t hash_type, mac_len;
995         uint8_t iv_len = 16;
996         struct cpt_request_info *req;
997         buf_ptr_t *meta_p, *aad_buf = NULL;
998         uint32_t encr_offset, auth_offset;
999         uint32_t encr_data_len, auth_data_len, aad_len = 0;
1000         uint32_t passthrough_len = 0;
1001         void *m_vaddr, *offset_vaddr;
1002         uint64_t m_dma, offset_dma, ctx_dma;
1003         opcode_info_t opcode;
1004         vq_cmd_word0_t vq_cmd_w0;
1005         vq_cmd_word3_t vq_cmd_w3;
1006         void *c_vaddr;
1007         uint64_t c_dma;
1008
1009         meta_p = &fc_params->meta_buf;
1010         m_vaddr = meta_p->vaddr;
1011         m_dma = meta_p->dma_addr;
1012
1013         encr_offset = ENCR_OFFSET(d_offs);
1014         auth_offset = AUTH_OFFSET(d_offs);
1015         encr_data_len = ENCR_DLEN(d_lens);
1016         auth_data_len = AUTH_DLEN(d_lens);
1017
1018         if (unlikely(flags & VALID_AAD_BUF)) {
1019                 /*
1020                  * We dont support both aad
1021                  * and auth data separately
1022                  */
1023                 auth_data_len = 0;
1024                 auth_offset = 0;
1025                 aad_len = fc_params->aad_buf.size;
1026                 aad_buf = &fc_params->aad_buf;
1027         }
1028
1029         cpt_ctx = fc_params->ctx_buf.vaddr;
1030         hash_type = cpt_ctx->hash_type;
1031         mac_len = cpt_ctx->mac_len;
1032
1033         if (unlikely(!(flags & VALID_IV_BUF))) {
1034                 iv_len = 0;
1035                 iv_offset = ENCR_IV_OFFSET(d_offs);
1036         }
1037
1038         if (unlikely(flags & VALID_AAD_BUF)) {
1039                 /*
1040                  * When AAD is given, data above encr_offset is pass through
1041                  * Since AAD is given as separate pointer and not as offset,
1042                  * this is a special case as we need to fragment input data
1043                  * into passthrough + encr_data and then insert AAD in between.
1044                  */
1045                 if (hash_type != GMAC_TYPE) {
1046                         passthrough_len = encr_offset;
1047                         auth_offset = passthrough_len + iv_len;
1048                         encr_offset = passthrough_len + aad_len + iv_len;
1049                         auth_data_len = aad_len + encr_data_len;
1050                 } else {
1051                         passthrough_len = 16 + aad_len;
1052                         auth_offset = passthrough_len + iv_len;
1053                         auth_data_len = aad_len;
1054                 }
1055         } else {
1056                 encr_offset += iv_len;
1057                 auth_offset += iv_len;
1058         }
1059
1060         /*
1061          * Save initial space that followed app data for completion code &
1062          * alternate completion code to fall in same cache line as app data
1063          */
1064         m_vaddr = (uint8_t *)m_vaddr + COMPLETION_CODE_SIZE;
1065         m_dma += COMPLETION_CODE_SIZE;
1066         size = (uint8_t *)RTE_PTR_ALIGN((uint8_t *)m_vaddr, 16) -
1067                (uint8_t *)m_vaddr;
1068         c_vaddr = (uint8_t *)m_vaddr + size;
1069         c_dma = m_dma + size;
1070         size += sizeof(cpt_res_s_t);
1071
1072         m_vaddr = (uint8_t *)m_vaddr + size;
1073         m_dma += size;
1074
1075         /* start cpt request info structure at 8 byte alignment */
1076         size = (uint8_t *)RTE_PTR_ALIGN(m_vaddr, 8) -
1077                 (uint8_t *)m_vaddr;
1078
1079         req = (struct cpt_request_info *)((uint8_t *)m_vaddr + size);
1080
1081         size += sizeof(struct cpt_request_info);
1082         m_vaddr = (uint8_t *)m_vaddr + size;
1083         m_dma += size;
1084
1085         /* Decryption */
1086         opcode.s.major = CPT_MAJOR_OP_FC;
1087         opcode.s.minor = 1;
1088
1089         if (hash_type == GMAC_TYPE) {
1090                 encr_offset = 0;
1091                 encr_data_len = 0;
1092         }
1093
1094         enc_dlen = encr_offset + encr_data_len;
1095         auth_dlen = auth_offset + auth_data_len;
1096
1097         if (auth_dlen > enc_dlen) {
1098                 inputlen = auth_dlen + mac_len;
1099                 outputlen = auth_dlen;
1100         } else {
1101                 inputlen = enc_dlen + mac_len;
1102                 outputlen = enc_dlen;
1103         }
1104
1105         vq_cmd_w0.u64 = 0;
1106         vq_cmd_w0.s.param1 = encr_data_len;
1107         vq_cmd_w0.s.param2 = auth_data_len;
1108
1109         /*
1110          * In 83XX since we have a limitation of
1111          * IV & Offset control word not part of instruction
1112          * and need to be part of Data Buffer, we check if
1113          * head room is there and then only do the Direct mode processing
1114          */
1115         if (likely((flags & SINGLE_BUF_INPLACE) &&
1116                    (flags & SINGLE_BUF_HEADTAILROOM))) {
1117                 void *dm_vaddr = fc_params->bufs[0].vaddr;
1118                 uint64_t dm_dma_addr = fc_params->bufs[0].dma_addr;
1119                 /*
1120                  * This flag indicates that there is 24 bytes head room and
1121                  * 8 bytes tail room available, so that we get to do
1122                  * DIRECT MODE with limitation
1123                  */
1124
1125                 offset_vaddr = (uint8_t *)dm_vaddr - OFF_CTRL_LEN - iv_len;
1126                 offset_dma = dm_dma_addr - OFF_CTRL_LEN - iv_len;
1127                 req->ist.ei1 = offset_dma;
1128
1129                 /* RPTR should just exclude offset control word */
1130                 req->ist.ei2 = dm_dma_addr - iv_len;
1131
1132                 req->alternate_caddr = (uint64_t *)((uint8_t *)dm_vaddr +
1133                                         outputlen - iv_len);
1134                 /* since this is decryption,
1135                  * don't touch the content of
1136                  * alternate ccode space as it contains
1137                  * hmac.
1138                  */
1139
1140                 vq_cmd_w0.s.dlen = inputlen + OFF_CTRL_LEN;
1141
1142                 vq_cmd_w0.s.opcode = opcode.flags;
1143
1144                 if (likely(iv_len)) {
1145                         uint64_t *dest = (uint64_t *)((uint8_t *)offset_vaddr +
1146                                                       OFF_CTRL_LEN);
1147                         uint64_t *src = fc_params->iv_buf;
1148                         dest[0] = src[0];
1149                         dest[1] = src[1];
1150                 }
1151
1152                 *(uint64_t *)offset_vaddr =
1153                         rte_cpu_to_be_64(((uint64_t)encr_offset << 16) |
1154                                 ((uint64_t)iv_offset << 8) |
1155                                 ((uint64_t)auth_offset));
1156
1157         } else {
1158                 uint64_t dptr_dma, rptr_dma;
1159                 uint32_t g_size_bytes, s_size_bytes;
1160                 sg_comp_t *gather_comp;
1161                 sg_comp_t *scatter_comp;
1162                 uint8_t *in_buffer;
1163                 uint8_t i = 0;
1164
1165                 /* This falls under strict SG mode */
1166                 offset_vaddr = m_vaddr;
1167                 offset_dma = m_dma;
1168                 size = OFF_CTRL_LEN + iv_len;
1169
1170                 m_vaddr = (uint8_t *)m_vaddr + size;
1171                 m_dma += size;
1172
1173                 opcode.s.major |= CPT_DMA_MODE;
1174
1175                 vq_cmd_w0.s.opcode = opcode.flags;
1176
1177                 if (likely(iv_len)) {
1178                         uint64_t *dest = (uint64_t *)((uint8_t *)offset_vaddr +
1179                                                       OFF_CTRL_LEN);
1180                         uint64_t *src = fc_params->iv_buf;
1181                         dest[0] = src[0];
1182                         dest[1] = src[1];
1183                 }
1184
1185                 *(uint64_t *)offset_vaddr =
1186                         rte_cpu_to_be_64(((uint64_t)encr_offset << 16) |
1187                                 ((uint64_t)iv_offset << 8) |
1188                                 ((uint64_t)auth_offset));
1189
1190                 /* DPTR has SG list */
1191                 in_buffer = m_vaddr;
1192                 dptr_dma = m_dma;
1193
1194                 ((uint16_t *)in_buffer)[0] = 0;
1195                 ((uint16_t *)in_buffer)[1] = 0;
1196
1197                 /* TODO Add error check if space will be sufficient */
1198                 gather_comp = (sg_comp_t *)((uint8_t *)m_vaddr + 8);
1199
1200                 /*
1201                  * Input Gather List
1202                  */
1203                 i = 0;
1204
1205                 /* Offset control word that includes iv */
1206                 i = fill_sg_comp(gather_comp, i, offset_dma,
1207                                  OFF_CTRL_LEN + iv_len);
1208
1209                 /* Add input data */
1210                 if (flags & VALID_MAC_BUF) {
1211                         size = inputlen - iv_len - mac_len;
1212                         if (size) {
1213                                 /* input data only */
1214                                 if (unlikely(flags & SINGLE_BUF_INPLACE)) {
1215                                         i = fill_sg_comp_from_buf_min(
1216                                                         gather_comp, i,
1217                                                         fc_params->bufs,
1218                                                         &size);
1219                                 } else {
1220                                         uint32_t aad_offset = aad_len ?
1221                                                 passthrough_len : 0;
1222
1223                                         i = fill_sg_comp_from_iov(gather_comp,
1224                                                         i,
1225                                                         fc_params->src_iov,
1226                                                         0, &size,
1227                                                         aad_buf,
1228                                                         aad_offset);
1229                                 }
1230                                 if (unlikely(size)) {
1231                                         CPT_LOG_DP_ERR("Insufficient buffer"
1232                                                        " space, size %d needed",
1233                                                        size);
1234                                         return;
1235                                 }
1236                         }
1237
1238                         /* mac data */
1239                         if (mac_len) {
1240                                 i = fill_sg_comp_from_buf(gather_comp, i,
1241                                                           &fc_params->mac_buf);
1242                         }
1243                 } else {
1244                         /* input data + mac */
1245                         size = inputlen - iv_len;
1246                         if (size) {
1247                                 if (unlikely(flags & SINGLE_BUF_INPLACE)) {
1248                                         i = fill_sg_comp_from_buf_min(
1249                                                         gather_comp, i,
1250                                                         fc_params->bufs,
1251                                                         &size);
1252                                 } else {
1253                                         uint32_t aad_offset = aad_len ?
1254                                                 passthrough_len : 0;
1255
1256                                         if (unlikely(!fc_params->src_iov)) {
1257                                                 CPT_LOG_DP_ERR("Bad input args");
1258                                                 return;
1259                                         }
1260
1261                                         i = fill_sg_comp_from_iov(
1262                                                         gather_comp, i,
1263                                                         fc_params->src_iov,
1264                                                         0, &size,
1265                                                         aad_buf,
1266                                                         aad_offset);
1267                                 }
1268
1269                                 if (unlikely(size)) {
1270                                         CPT_LOG_DP_ERR("Insufficient buffer"
1271                                                        " space, size %d needed",
1272                                                        size);
1273                                         return;
1274                                 }
1275                         }
1276                 }
1277                 ((uint16_t *)in_buffer)[2] = rte_cpu_to_be_16(i);
1278                 g_size_bytes = ((i + 3) / 4) * sizeof(sg_comp_t);
1279
1280                 /*
1281                  * Output Scatter List
1282                  */
1283
1284                 i = 0;
1285                 scatter_comp =
1286                         (sg_comp_t *)((uint8_t *)gather_comp + g_size_bytes);
1287
1288                 /* Add iv */
1289                 if (iv_len) {
1290                         i = fill_sg_comp(scatter_comp, i,
1291                                          offset_dma + OFF_CTRL_LEN,
1292                                          iv_len);
1293                 }
1294
1295                 /* Add output data */
1296                 size = outputlen - iv_len;
1297                 if (size) {
1298                         if (unlikely(flags & SINGLE_BUF_INPLACE)) {
1299                                 /* handle single buffer here */
1300                                 i = fill_sg_comp_from_buf_min(scatter_comp, i,
1301                                                               fc_params->bufs,
1302                                                               &size);
1303                         } else {
1304                                 uint32_t aad_offset = aad_len ?
1305                                         passthrough_len : 0;
1306
1307                                 if (unlikely(!fc_params->dst_iov)) {
1308                                         CPT_LOG_DP_ERR("Bad input args");
1309                                         return;
1310                                 }
1311
1312                                 i = fill_sg_comp_from_iov(scatter_comp, i,
1313                                                           fc_params->dst_iov, 0,
1314                                                           &size, aad_buf,
1315                                                           aad_offset);
1316                         }
1317
1318                         if (unlikely(size)) {
1319                                 CPT_LOG_DP_ERR("Insufficient buffer space,"
1320                                                " size %d needed", size);
1321                                 return;
1322                         }
1323                 }
1324
1325                 ((uint16_t *)in_buffer)[3] = rte_cpu_to_be_16(i);
1326                 s_size_bytes = ((i + 3) / 4) * sizeof(sg_comp_t);
1327
1328                 size = g_size_bytes + s_size_bytes + SG_LIST_HDR_SIZE;
1329
1330                 /* This is DPTR len incase of SG mode */
1331                 vq_cmd_w0.s.dlen = size;
1332
1333                 m_vaddr = (uint8_t *)m_vaddr + size;
1334                 m_dma += size;
1335
1336                 /* cpt alternate completion address saved earlier */
1337                 req->alternate_caddr = (uint64_t *)((uint8_t *)c_vaddr - 8);
1338                 *req->alternate_caddr = ~((uint64_t)COMPLETION_CODE_INIT);
1339                 rptr_dma = c_dma - 8;
1340                 size += COMPLETION_CODE_SIZE;
1341
1342                 req->ist.ei1 = dptr_dma;
1343                 req->ist.ei2 = rptr_dma;
1344         }
1345
1346         ctx_dma = fc_params->ctx_buf.dma_addr +
1347                 offsetof(struct cpt_ctx, fctx);
1348         /* vq command w3 */
1349         vq_cmd_w3.u64 = 0;
1350         vq_cmd_w3.s.grp = 0;
1351         vq_cmd_w3.s.cptr = ctx_dma;
1352
1353         /* 16 byte aligned cpt res address */
1354         req->completion_addr = (uint64_t *)((uint8_t *)c_vaddr);
1355         *req->completion_addr = COMPLETION_CODE_INIT;
1356         req->comp_baddr  = c_dma;
1357
1358         /* Fill microcode part of instruction */
1359         req->ist.ei0 = vq_cmd_w0.u64;
1360         req->ist.ei3 = vq_cmd_w3.u64;
1361
1362         req->op = op;
1363
1364         *prep_req = req;
1365         return;
1366 }
1367
1368 static __rte_always_inline void
1369 cpt_zuc_snow3g_enc_prep(uint32_t req_flags,
1370                         uint64_t d_offs,
1371                         uint64_t d_lens,
1372                         fc_params_t *params,
1373                         void *op,
1374                         void **prep_req)
1375 {
1376         uint32_t size;
1377         int32_t inputlen, outputlen;
1378         struct cpt_ctx *cpt_ctx;
1379         uint32_t mac_len = 0;
1380         uint8_t snow3g, j;
1381         struct cpt_request_info *req;
1382         buf_ptr_t *buf_p;
1383         uint32_t encr_offset = 0, auth_offset = 0;
1384         uint32_t encr_data_len = 0, auth_data_len = 0;
1385         int flags, iv_len = 16;
1386         void *m_vaddr, *c_vaddr;
1387         uint64_t m_dma, c_dma, offset_ctrl;
1388         uint64_t *offset_vaddr, offset_dma;
1389         uint32_t *iv_s, iv[4];
1390         vq_cmd_word0_t vq_cmd_w0;
1391         vq_cmd_word3_t vq_cmd_w3;
1392         opcode_info_t opcode;
1393
1394         buf_p = &params->meta_buf;
1395         m_vaddr = buf_p->vaddr;
1396         m_dma = buf_p->dma_addr;
1397
1398         cpt_ctx = params->ctx_buf.vaddr;
1399         flags = cpt_ctx->zsk_flags;
1400         mac_len = cpt_ctx->mac_len;
1401         snow3g = cpt_ctx->snow3g;
1402
1403         /*
1404          * Save initial space that followed app data for completion code &
1405          * alternate completion code to fall in same cache line as app data
1406          */
1407         m_vaddr = (uint8_t *)m_vaddr + COMPLETION_CODE_SIZE;
1408         m_dma += COMPLETION_CODE_SIZE;
1409         size = (uint8_t *)RTE_PTR_ALIGN((uint8_t *)m_vaddr, 16) -
1410                 (uint8_t *)m_vaddr;
1411
1412         c_vaddr = (uint8_t *)m_vaddr + size;
1413         c_dma = m_dma + size;
1414         size += sizeof(cpt_res_s_t);
1415
1416         m_vaddr = (uint8_t *)m_vaddr + size;
1417         m_dma += size;
1418
1419         /* Reserve memory for cpt request info */
1420         req = m_vaddr;
1421
1422         size = sizeof(struct cpt_request_info);
1423         m_vaddr = (uint8_t *)m_vaddr + size;
1424         m_dma += size;
1425
1426         opcode.s.major = CPT_MAJOR_OP_ZUC_SNOW3G;
1427
1428         /* indicates CPTR ctx, operation type, KEY & IV mode from DPTR */
1429
1430         opcode.s.minor = ((1 << 7) | (snow3g << 5) | (0 << 4) |
1431                           (0 << 3) | (flags & 0x7));
1432
1433         if (flags == 0x1) {
1434                 /*
1435                  * Microcode expects offsets in bytes
1436                  * TODO: Rounding off
1437                  */
1438                 auth_data_len = AUTH_DLEN(d_lens);
1439
1440                 /* EIA3 or UIA2 */
1441                 auth_offset = AUTH_OFFSET(d_offs);
1442                 auth_offset = auth_offset / 8;
1443
1444                 /* consider iv len */
1445                 auth_offset += iv_len;
1446
1447                 inputlen = auth_offset + (RTE_ALIGN(auth_data_len, 8) / 8);
1448                 outputlen = mac_len;
1449
1450                 offset_ctrl = rte_cpu_to_be_64((uint64_t)auth_offset);
1451
1452         } else {
1453                 /* EEA3 or UEA2 */
1454                 /*
1455                  * Microcode expects offsets in bytes
1456                  * TODO: Rounding off
1457                  */
1458                 encr_data_len = ENCR_DLEN(d_lens);
1459
1460                 encr_offset = ENCR_OFFSET(d_offs);
1461                 encr_offset = encr_offset / 8;
1462                 /* consider iv len */
1463                 encr_offset += iv_len;
1464
1465                 inputlen = encr_offset + (RTE_ALIGN(encr_data_len, 8) / 8);
1466                 outputlen = inputlen;
1467
1468                 /* iv offset is 0 */
1469                 offset_ctrl = rte_cpu_to_be_64((uint64_t)encr_offset << 16);
1470         }
1471
1472         /* IV */
1473         iv_s = (flags == 0x1) ? params->auth_iv_buf :
1474                 params->iv_buf;
1475
1476         if (snow3g) {
1477                 /*
1478                  * DPDK seems to provide it in form of IV3 IV2 IV1 IV0
1479                  * and BigEndian, MC needs it as IV0 IV1 IV2 IV3
1480                  */
1481
1482                 for (j = 0; j < 4; j++)
1483                         iv[j] = iv_s[3 - j];
1484         } else {
1485                 /* ZUC doesn't need a swap */
1486                 for (j = 0; j < 4; j++)
1487                         iv[j] = iv_s[j];
1488         }
1489
1490         /*
1491          * GP op header, lengths are expected in bits.
1492          */
1493         vq_cmd_w0.u64 = 0;
1494         vq_cmd_w0.s.param1 = encr_data_len;
1495         vq_cmd_w0.s.param2 = auth_data_len;
1496
1497         /*
1498          * In 83XX since we have a limitation of
1499          * IV & Offset control word not part of instruction
1500          * and need to be part of Data Buffer, we check if
1501          * head room is there and then only do the Direct mode processing
1502          */
1503         if (likely((req_flags & SINGLE_BUF_INPLACE) &&
1504                    (req_flags & SINGLE_BUF_HEADTAILROOM))) {
1505                 void *dm_vaddr = params->bufs[0].vaddr;
1506                 uint64_t dm_dma_addr = params->bufs[0].dma_addr;
1507                 /*
1508                  * This flag indicates that there is 24 bytes head room and
1509                  * 8 bytes tail room available, so that we get to do
1510                  * DIRECT MODE with limitation
1511                  */
1512
1513                 offset_vaddr = (uint64_t *)((uint8_t *)dm_vaddr -
1514                                             OFF_CTRL_LEN - iv_len);
1515                 offset_dma = dm_dma_addr - OFF_CTRL_LEN - iv_len;
1516
1517                 /* DPTR */
1518                 req->ist.ei1 = offset_dma;
1519                 /* RPTR should just exclude offset control word */
1520                 req->ist.ei2 = dm_dma_addr - iv_len;
1521                 req->alternate_caddr = (uint64_t *)((uint8_t *)dm_vaddr
1522                                                     + outputlen - iv_len);
1523
1524                 vq_cmd_w0.s.dlen = inputlen + OFF_CTRL_LEN;
1525
1526                 vq_cmd_w0.s.opcode = opcode.flags;
1527
1528                 if (likely(iv_len)) {
1529                         uint32_t *iv_d = (uint32_t *)((uint8_t *)offset_vaddr
1530                                                       + OFF_CTRL_LEN);
1531                         memcpy(iv_d, iv, 16);
1532                 }
1533
1534                 *offset_vaddr = offset_ctrl;
1535         } else {
1536                 uint32_t i, g_size_bytes, s_size_bytes;
1537                 uint64_t dptr_dma, rptr_dma;
1538                 sg_comp_t *gather_comp;
1539                 sg_comp_t *scatter_comp;
1540                 uint8_t *in_buffer;
1541                 uint32_t *iv_d;
1542
1543                 /* save space for iv */
1544                 offset_vaddr = m_vaddr;
1545                 offset_dma = m_dma;
1546
1547                 m_vaddr = (uint8_t *)m_vaddr + OFF_CTRL_LEN + iv_len;
1548                 m_dma += OFF_CTRL_LEN + iv_len;
1549
1550                 opcode.s.major |= CPT_DMA_MODE;
1551
1552                 vq_cmd_w0.s.opcode = opcode.flags;
1553
1554                 /* DPTR has SG list */
1555                 in_buffer = m_vaddr;
1556                 dptr_dma = m_dma;
1557
1558                 ((uint16_t *)in_buffer)[0] = 0;
1559                 ((uint16_t *)in_buffer)[1] = 0;
1560
1561                 /* TODO Add error check if space will be sufficient */
1562                 gather_comp = (sg_comp_t *)((uint8_t *)m_vaddr + 8);
1563
1564                 /*
1565                  * Input Gather List
1566                  */
1567                 i = 0;
1568
1569                 /* Offset control word followed by iv */
1570
1571                 i = fill_sg_comp(gather_comp, i, offset_dma,
1572                                  OFF_CTRL_LEN + iv_len);
1573
1574                 /* iv offset is 0 */
1575                 *offset_vaddr = offset_ctrl;
1576
1577                 iv_d = (uint32_t *)((uint8_t *)offset_vaddr + OFF_CTRL_LEN);
1578                 memcpy(iv_d, iv, 16);
1579
1580                 /* input data */
1581                 size = inputlen - iv_len;
1582                 if (size) {
1583                         i = fill_sg_comp_from_iov(gather_comp, i,
1584                                                   params->src_iov,
1585                                                   0, &size, NULL, 0);
1586                         if (unlikely(size)) {
1587                                 CPT_LOG_DP_ERR("Insufficient buffer space,"
1588                                                " size %d needed", size);
1589                                 return;
1590                         }
1591                 }
1592                 ((uint16_t *)in_buffer)[2] = rte_cpu_to_be_16(i);
1593                 g_size_bytes = ((i + 3) / 4) * sizeof(sg_comp_t);
1594
1595                 /*
1596                  * Output Scatter List
1597                  */
1598
1599                 i = 0;
1600                 scatter_comp =
1601                         (sg_comp_t *)((uint8_t *)gather_comp + g_size_bytes);
1602
1603                 if (flags == 0x1) {
1604                         /* IV in SLIST only for EEA3 & UEA2 */
1605                         iv_len = 0;
1606                 }
1607
1608                 if (iv_len) {
1609                         i = fill_sg_comp(scatter_comp, i,
1610                                          offset_dma + OFF_CTRL_LEN, iv_len);
1611                 }
1612
1613                 /* Add output data */
1614                 if (req_flags & VALID_MAC_BUF) {
1615                         size = outputlen - iv_len - mac_len;
1616                         if (size) {
1617                                 i = fill_sg_comp_from_iov(scatter_comp, i,
1618                                                           params->dst_iov, 0,
1619                                                           &size, NULL, 0);
1620
1621                                 if (unlikely(size)) {
1622                                         CPT_LOG_DP_ERR("Insufficient buffer space,"
1623                                                        " size %d needed", size);
1624                                         return;
1625                                 }
1626                         }
1627
1628                         /* mac data */
1629                         if (mac_len) {
1630                                 i = fill_sg_comp_from_buf(scatter_comp, i,
1631                                                           &params->mac_buf);
1632                         }
1633                 } else {
1634                         /* Output including mac */
1635                         size = outputlen - iv_len;
1636                         if (size) {
1637                                 i = fill_sg_comp_from_iov(scatter_comp, i,
1638                                                           params->dst_iov, 0,
1639                                                           &size, NULL, 0);
1640
1641                                 if (unlikely(size)) {
1642                                         CPT_LOG_DP_ERR("Insufficient buffer space,"
1643                                                        " size %d needed", size);
1644                                         return;
1645                                 }
1646                         }
1647                 }
1648                 ((uint16_t *)in_buffer)[3] = rte_cpu_to_be_16(i);
1649                 s_size_bytes = ((i + 3) / 4) * sizeof(sg_comp_t);
1650
1651                 size = g_size_bytes + s_size_bytes + SG_LIST_HDR_SIZE;
1652
1653                 /* This is DPTR len incase of SG mode */
1654                 vq_cmd_w0.s.dlen = size;
1655
1656                 m_vaddr = (uint8_t *)m_vaddr + size;
1657                 m_dma += size;
1658
1659                 /* cpt alternate completion address saved earlier */
1660                 req->alternate_caddr = (uint64_t *)((uint8_t *)c_vaddr - 8);
1661                 *req->alternate_caddr = ~((uint64_t)COMPLETION_CODE_INIT);
1662                 rptr_dma = c_dma - 8;
1663
1664                 req->ist.ei1 = dptr_dma;
1665                 req->ist.ei2 = rptr_dma;
1666         }
1667
1668         /* vq command w3 */
1669         vq_cmd_w3.u64 = 0;
1670         vq_cmd_w3.s.grp = 0;
1671         vq_cmd_w3.s.cptr = params->ctx_buf.dma_addr +
1672                 offsetof(struct cpt_ctx, zs_ctx);
1673
1674         /* 16 byte aligned cpt res address */
1675         req->completion_addr = (uint64_t *)((uint8_t *)c_vaddr);
1676         *req->completion_addr = COMPLETION_CODE_INIT;
1677         req->comp_baddr  = c_dma;
1678
1679         /* Fill microcode part of instruction */
1680         req->ist.ei0 = vq_cmd_w0.u64;
1681         req->ist.ei3 = vq_cmd_w3.u64;
1682
1683         req->op = op;
1684
1685         *prep_req = req;
1686         return;
1687 }
1688
1689 static __rte_always_inline void
1690 cpt_zuc_snow3g_dec_prep(uint32_t req_flags,
1691                         uint64_t d_offs,
1692                         uint64_t d_lens,
1693                         fc_params_t *params,
1694                         void *op,
1695                         void **prep_req)
1696 {
1697         uint32_t size;
1698         int32_t inputlen = 0, outputlen;
1699         struct cpt_ctx *cpt_ctx;
1700         uint8_t snow3g, iv_len = 16;
1701         struct cpt_request_info *req;
1702         buf_ptr_t *buf_p;
1703         uint32_t encr_offset;
1704         uint32_t encr_data_len;
1705         int flags;
1706         void *m_vaddr, *c_vaddr;
1707         uint64_t m_dma, c_dma;
1708         uint64_t *offset_vaddr, offset_dma;
1709         uint32_t *iv_s, iv[4], j;
1710         vq_cmd_word0_t vq_cmd_w0;
1711         vq_cmd_word3_t vq_cmd_w3;
1712         opcode_info_t opcode;
1713
1714         buf_p = &params->meta_buf;
1715         m_vaddr = buf_p->vaddr;
1716         m_dma = buf_p->dma_addr;
1717
1718         /*
1719          * Microcode expects offsets in bytes
1720          * TODO: Rounding off
1721          */
1722         encr_offset = ENCR_OFFSET(d_offs) / 8;
1723         encr_data_len = ENCR_DLEN(d_lens);
1724
1725         cpt_ctx = params->ctx_buf.vaddr;
1726         flags = cpt_ctx->zsk_flags;
1727         snow3g = cpt_ctx->snow3g;
1728         /*
1729          * Save initial space that followed app data for completion code &
1730          * alternate completion code to fall in same cache line as app data
1731          */
1732         m_vaddr = (uint8_t *)m_vaddr + COMPLETION_CODE_SIZE;
1733         m_dma += COMPLETION_CODE_SIZE;
1734         size = (uint8_t *)RTE_PTR_ALIGN((uint8_t *)m_vaddr, 16) -
1735                 (uint8_t *)m_vaddr;
1736
1737         c_vaddr = (uint8_t *)m_vaddr + size;
1738         c_dma = m_dma + size;
1739         size += sizeof(cpt_res_s_t);
1740
1741         m_vaddr = (uint8_t *)m_vaddr + size;
1742         m_dma += size;
1743
1744         /* Reserve memory for cpt request info */
1745         req = m_vaddr;
1746
1747         size = sizeof(struct cpt_request_info);
1748         m_vaddr = (uint8_t *)m_vaddr + size;
1749         m_dma += size;
1750
1751         opcode.s.major = CPT_MAJOR_OP_ZUC_SNOW3G;
1752
1753         /* indicates CPTR ctx, operation type, KEY & IV mode from DPTR */
1754
1755         opcode.s.minor = ((1 << 7) | (snow3g << 5) | (0 << 4) |
1756                           (0 << 3) | (flags & 0x7));
1757
1758         /* consider iv len */
1759         encr_offset += iv_len;
1760
1761         inputlen = encr_offset +
1762                 (RTE_ALIGN(encr_data_len, 8) / 8);
1763         outputlen = inputlen;
1764
1765         /* IV */
1766         iv_s = params->iv_buf;
1767         if (snow3g) {
1768                 /*
1769                  * DPDK seems to provide it in form of IV3 IV2 IV1 IV0
1770                  * and BigEndian, MC needs it as IV0 IV1 IV2 IV3
1771                  */
1772
1773                 for (j = 0; j < 4; j++)
1774                         iv[j] = iv_s[3 - j];
1775         } else {
1776                 /* ZUC doesn't need a swap */
1777                 for (j = 0; j < 4; j++)
1778                         iv[j] = iv_s[j];
1779         }
1780
1781         /*
1782          * GP op header, lengths are expected in bits.
1783          */
1784         vq_cmd_w0.u64 = 0;
1785         vq_cmd_w0.s.param1 = encr_data_len;
1786
1787         /*
1788          * In 83XX since we have a limitation of
1789          * IV & Offset control word not part of instruction
1790          * and need to be part of Data Buffer, we check if
1791          * head room is there and then only do the Direct mode processing
1792          */
1793         if (likely((req_flags & SINGLE_BUF_INPLACE) &&
1794                    (req_flags & SINGLE_BUF_HEADTAILROOM))) {
1795                 void *dm_vaddr = params->bufs[0].vaddr;
1796                 uint64_t dm_dma_addr = params->bufs[0].dma_addr;
1797                 /*
1798                  * This flag indicates that there is 24 bytes head room and
1799                  * 8 bytes tail room available, so that we get to do
1800                  * DIRECT MODE with limitation
1801                  */
1802
1803                 offset_vaddr = (uint64_t *)((uint8_t *)dm_vaddr -
1804                                             OFF_CTRL_LEN - iv_len);
1805                 offset_dma = dm_dma_addr - OFF_CTRL_LEN - iv_len;
1806
1807                 /* DPTR */
1808                 req->ist.ei1 = offset_dma;
1809                 /* RPTR should just exclude offset control word */
1810                 req->ist.ei2 = dm_dma_addr - iv_len;
1811                 req->alternate_caddr = (uint64_t *)((uint8_t *)dm_vaddr
1812                                                     + outputlen - iv_len);
1813
1814                 vq_cmd_w0.s.dlen = inputlen + OFF_CTRL_LEN;
1815
1816                 vq_cmd_w0.s.opcode = opcode.flags;
1817
1818                 if (likely(iv_len)) {
1819                         uint32_t *iv_d = (uint32_t *)((uint8_t *)offset_vaddr
1820                                                       + OFF_CTRL_LEN);
1821                         memcpy(iv_d, iv, 16);
1822                 }
1823
1824                 /* iv offset is 0 */
1825                 *offset_vaddr = rte_cpu_to_be_64((uint64_t)encr_offset << 16);
1826         } else {
1827                 uint32_t i, g_size_bytes, s_size_bytes;
1828                 uint64_t dptr_dma, rptr_dma;
1829                 sg_comp_t *gather_comp;
1830                 sg_comp_t *scatter_comp;
1831                 uint8_t *in_buffer;
1832                 uint32_t *iv_d;
1833
1834                 /* save space for offset and iv... */
1835                 offset_vaddr = m_vaddr;
1836                 offset_dma = m_dma;
1837
1838                 m_vaddr = (uint8_t *)m_vaddr + OFF_CTRL_LEN + iv_len;
1839                 m_dma += OFF_CTRL_LEN + iv_len;
1840
1841                 opcode.s.major |= CPT_DMA_MODE;
1842
1843                 vq_cmd_w0.s.opcode = opcode.flags;
1844
1845                 /* DPTR has SG list */
1846                 in_buffer = m_vaddr;
1847                 dptr_dma = m_dma;
1848
1849                 ((uint16_t *)in_buffer)[0] = 0;
1850                 ((uint16_t *)in_buffer)[1] = 0;
1851
1852                 /* TODO Add error check if space will be sufficient */
1853                 gather_comp = (sg_comp_t *)((uint8_t *)m_vaddr + 8);
1854
1855                 /*
1856                  * Input Gather List
1857                  */
1858                 i = 0;
1859
1860                 /* Offset control word */
1861
1862                 /* iv offset is 0 */
1863                 *offset_vaddr = rte_cpu_to_be_64((uint64_t)encr_offset << 16);
1864
1865                 i = fill_sg_comp(gather_comp, i, offset_dma,
1866                                  OFF_CTRL_LEN + iv_len);
1867
1868                 iv_d = (uint32_t *)((uint8_t *)offset_vaddr + OFF_CTRL_LEN);
1869                 memcpy(iv_d, iv, 16);
1870
1871                 /* Add input data */
1872                 size = inputlen - iv_len;
1873                 if (size) {
1874                         i = fill_sg_comp_from_iov(gather_comp, i,
1875                                                   params->src_iov,
1876                                                   0, &size, NULL, 0);
1877                         if (unlikely(size)) {
1878                                 CPT_LOG_DP_ERR("Insufficient buffer space,"
1879                                                " size %d needed", size);
1880                                 return;
1881                         }
1882                 }
1883                 ((uint16_t *)in_buffer)[2] = rte_cpu_to_be_16(i);
1884                 g_size_bytes = ((i + 3) / 4) * sizeof(sg_comp_t);
1885
1886                 /*
1887                  * Output Scatter List
1888                  */
1889
1890                 i = 0;
1891                 scatter_comp =
1892                         (sg_comp_t *)((uint8_t *)gather_comp + g_size_bytes);
1893
1894                 /* IV */
1895                 i = fill_sg_comp(scatter_comp, i,
1896                                  offset_dma + OFF_CTRL_LEN,
1897                                  iv_len);
1898
1899                 /* Add output data */
1900                 size = outputlen - iv_len;
1901                 if (size) {
1902                         i = fill_sg_comp_from_iov(scatter_comp, i,
1903                                                   params->dst_iov, 0,
1904                                                   &size, NULL, 0);
1905
1906                         if (unlikely(size)) {
1907                                 CPT_LOG_DP_ERR("Insufficient buffer space,"
1908                                                " size %d needed", size);
1909                                 return;
1910                         }
1911                 }
1912                 ((uint16_t *)in_buffer)[3] = rte_cpu_to_be_16(i);
1913                 s_size_bytes = ((i + 3) / 4) * sizeof(sg_comp_t);
1914
1915                 size = g_size_bytes + s_size_bytes + SG_LIST_HDR_SIZE;
1916
1917                 /* This is DPTR len incase of SG mode */
1918                 vq_cmd_w0.s.dlen = size;
1919
1920                 m_vaddr = (uint8_t *)m_vaddr + size;
1921                 m_dma += size;
1922
1923                 /* cpt alternate completion address saved earlier */
1924                 req->alternate_caddr = (uint64_t *)((uint8_t *)c_vaddr - 8);
1925                 *req->alternate_caddr = ~((uint64_t)COMPLETION_CODE_INIT);
1926                 rptr_dma = c_dma - 8;
1927
1928                 req->ist.ei1 = dptr_dma;
1929                 req->ist.ei2 = rptr_dma;
1930         }
1931
1932         /* vq command w3 */
1933         vq_cmd_w3.u64 = 0;
1934         vq_cmd_w3.s.grp = 0;
1935         vq_cmd_w3.s.cptr = params->ctx_buf.dma_addr +
1936                 offsetof(struct cpt_ctx, zs_ctx);
1937
1938         /* 16 byte aligned cpt res address */
1939         req->completion_addr = (uint64_t *)((uint8_t *)c_vaddr);
1940         *req->completion_addr = COMPLETION_CODE_INIT;
1941         req->comp_baddr  = c_dma;
1942
1943         /* Fill microcode part of instruction */
1944         req->ist.ei0 = vq_cmd_w0.u64;
1945         req->ist.ei3 = vq_cmd_w3.u64;
1946
1947         req->op = op;
1948
1949         *prep_req = req;
1950         return;
1951 }
1952
1953 static __rte_always_inline void
1954 cpt_kasumi_enc_prep(uint32_t req_flags,
1955                     uint64_t d_offs,
1956                     uint64_t d_lens,
1957                     fc_params_t *params,
1958                     void *op,
1959                     void **prep_req)
1960 {
1961         uint32_t size;
1962         int32_t inputlen = 0, outputlen = 0;
1963         struct cpt_ctx *cpt_ctx;
1964         uint32_t mac_len = 0;
1965         uint8_t i = 0;
1966         struct cpt_request_info *req;
1967         buf_ptr_t *buf_p;
1968         uint32_t encr_offset, auth_offset;
1969         uint32_t encr_data_len, auth_data_len;
1970         int flags;
1971         uint8_t *iv_s, *iv_d, iv_len = 8;
1972         uint8_t dir = 0;
1973         void *m_vaddr, *c_vaddr;
1974         uint64_t m_dma, c_dma;
1975         uint64_t *offset_vaddr, offset_dma;
1976         vq_cmd_word0_t vq_cmd_w0;
1977         vq_cmd_word3_t vq_cmd_w3;
1978         opcode_info_t opcode;
1979         uint8_t *in_buffer;
1980         uint32_t g_size_bytes, s_size_bytes;
1981         uint64_t dptr_dma, rptr_dma;
1982         sg_comp_t *gather_comp;
1983         sg_comp_t *scatter_comp;
1984
1985         buf_p = &params->meta_buf;
1986         m_vaddr = buf_p->vaddr;
1987         m_dma = buf_p->dma_addr;
1988
1989         encr_offset = ENCR_OFFSET(d_offs) / 8;
1990         auth_offset = AUTH_OFFSET(d_offs) / 8;
1991         encr_data_len = ENCR_DLEN(d_lens);
1992         auth_data_len = AUTH_DLEN(d_lens);
1993
1994         cpt_ctx = params->ctx_buf.vaddr;
1995         flags = cpt_ctx->zsk_flags;
1996         mac_len = cpt_ctx->mac_len;
1997
1998         if (flags == 0x0)
1999                 iv_s = params->iv_buf;
2000         else
2001                 iv_s = params->auth_iv_buf;
2002
2003         dir = iv_s[8] & 0x1;
2004
2005         /*
2006          * Save initial space that followed app data for completion code &
2007          * alternate completion code to fall in same cache line as app data
2008          */
2009         m_vaddr = (uint8_t *)m_vaddr + COMPLETION_CODE_SIZE;
2010         m_dma += COMPLETION_CODE_SIZE;
2011         size = (uint8_t *)RTE_PTR_ALIGN((uint8_t *)m_vaddr, 16) -
2012                 (uint8_t *)m_vaddr;
2013
2014         c_vaddr = (uint8_t *)m_vaddr + size;
2015         c_dma = m_dma + size;
2016         size += sizeof(cpt_res_s_t);
2017
2018         m_vaddr = (uint8_t *)m_vaddr + size;
2019         m_dma += size;
2020
2021         /* Reserve memory for cpt request info */
2022         req = m_vaddr;
2023
2024         size = sizeof(struct cpt_request_info);
2025         m_vaddr = (uint8_t *)m_vaddr + size;
2026         m_dma += size;
2027
2028         opcode.s.major = CPT_MAJOR_OP_KASUMI | CPT_DMA_MODE;
2029
2030         /* indicates ECB/CBC, direction, ctx from cptr, iv from dptr */
2031         opcode.s.minor = ((1 << 6) | (cpt_ctx->k_ecb << 5) |
2032                           (dir << 4) | (0 << 3) | (flags & 0x7));
2033
2034         /*
2035          * GP op header, lengths are expected in bits.
2036          */
2037         vq_cmd_w0.u64 = 0;
2038         vq_cmd_w0.s.param1 = encr_data_len;
2039         vq_cmd_w0.s.param2 = auth_data_len;
2040         vq_cmd_w0.s.opcode = opcode.flags;
2041
2042         /* consider iv len */
2043         if (flags == 0x0) {
2044                 encr_offset += iv_len;
2045                 auth_offset += iv_len;
2046         }
2047
2048         /* save space for offset ctrl and iv */
2049         offset_vaddr = m_vaddr;
2050         offset_dma = m_dma;
2051
2052         m_vaddr = (uint8_t *)m_vaddr + OFF_CTRL_LEN + iv_len;
2053         m_dma += OFF_CTRL_LEN + iv_len;
2054
2055         /* DPTR has SG list */
2056         in_buffer = m_vaddr;
2057         dptr_dma = m_dma;
2058
2059         ((uint16_t *)in_buffer)[0] = 0;
2060         ((uint16_t *)in_buffer)[1] = 0;
2061
2062         /* TODO Add error check if space will be sufficient */
2063         gather_comp = (sg_comp_t *)((uint8_t *)m_vaddr + 8);
2064
2065         /*
2066          * Input Gather List
2067          */
2068         i = 0;
2069
2070         /* Offset control word followed by iv */
2071
2072         if (flags == 0x0) {
2073                 inputlen = encr_offset + (RTE_ALIGN(encr_data_len, 8) / 8);
2074                 outputlen = inputlen;
2075                 /* iv offset is 0 */
2076                 *offset_vaddr = rte_cpu_to_be_64((uint64_t)encr_offset << 16);
2077         } else {
2078                 inputlen = auth_offset + (RTE_ALIGN(auth_data_len, 8) / 8);
2079                 outputlen = mac_len;
2080                 /* iv offset is 0 */
2081                 *offset_vaddr = rte_cpu_to_be_64((uint64_t)auth_offset);
2082         }
2083
2084         i = fill_sg_comp(gather_comp, i, offset_dma, OFF_CTRL_LEN + iv_len);
2085
2086         /* IV */
2087         iv_d = (uint8_t *)offset_vaddr + OFF_CTRL_LEN;
2088         memcpy(iv_d, iv_s, iv_len);
2089
2090         /* input data */
2091         size = inputlen - iv_len;
2092         if (size) {
2093                 i = fill_sg_comp_from_iov(gather_comp, i,
2094                                           params->src_iov, 0,
2095                                           &size, NULL, 0);
2096
2097                 if (unlikely(size)) {
2098                         CPT_LOG_DP_ERR("Insufficient buffer space,"
2099                                        " size %d needed", size);
2100                         return;
2101                 }
2102         }
2103         ((uint16_t *)in_buffer)[2] = rte_cpu_to_be_16(i);
2104         g_size_bytes = ((i + 3) / 4) * sizeof(sg_comp_t);
2105
2106         /*
2107          * Output Scatter List
2108          */
2109
2110         i = 0;
2111         scatter_comp = (sg_comp_t *)((uint8_t *)gather_comp + g_size_bytes);
2112
2113         if (flags == 0x1) {
2114                 /* IV in SLIST only for F8 */
2115                 iv_len = 0;
2116         }
2117
2118         /* IV */
2119         if (iv_len) {
2120                 i = fill_sg_comp(scatter_comp, i,
2121                                  offset_dma + OFF_CTRL_LEN,
2122                                  iv_len);
2123         }
2124
2125         /* Add output data */
2126         if (req_flags & VALID_MAC_BUF) {
2127                 size = outputlen - iv_len - mac_len;
2128                 if (size) {
2129                         i = fill_sg_comp_from_iov(scatter_comp, i,
2130                                                   params->dst_iov, 0,
2131                                                   &size, NULL, 0);
2132
2133                         if (unlikely(size)) {
2134                                 CPT_LOG_DP_ERR("Insufficient buffer space,"
2135                                                " size %d needed", size);
2136                                 return;
2137                         }
2138                 }
2139
2140                 /* mac data */
2141                 if (mac_len) {
2142                         i = fill_sg_comp_from_buf(scatter_comp, i,
2143                                                   &params->mac_buf);
2144                 }
2145         } else {
2146                 /* Output including mac */
2147                 size = outputlen - iv_len;
2148                 if (size) {
2149                         i = fill_sg_comp_from_iov(scatter_comp, i,
2150                                                   params->dst_iov, 0,
2151                                                   &size, NULL, 0);
2152
2153                         if (unlikely(size)) {
2154                                 CPT_LOG_DP_ERR("Insufficient buffer space,"
2155                                                " size %d needed", size);
2156                                 return;
2157                         }
2158                 }
2159         }
2160         ((uint16_t *)in_buffer)[3] = rte_cpu_to_be_16(i);
2161         s_size_bytes = ((i + 3) / 4) * sizeof(sg_comp_t);
2162
2163         size = g_size_bytes + s_size_bytes + SG_LIST_HDR_SIZE;
2164
2165         /* This is DPTR len incase of SG mode */
2166         vq_cmd_w0.s.dlen = size;
2167
2168         m_vaddr = (uint8_t *)m_vaddr + size;
2169         m_dma += size;
2170
2171         /* cpt alternate completion address saved earlier */
2172         req->alternate_caddr = (uint64_t *)((uint8_t *)c_vaddr - 8);
2173         *req->alternate_caddr = ~((uint64_t)COMPLETION_CODE_INIT);
2174         rptr_dma = c_dma - 8;
2175
2176         req->ist.ei1 = dptr_dma;
2177         req->ist.ei2 = rptr_dma;
2178
2179         /* vq command w3 */
2180         vq_cmd_w3.u64 = 0;
2181         vq_cmd_w3.s.grp = 0;
2182         vq_cmd_w3.s.cptr = params->ctx_buf.dma_addr +
2183                 offsetof(struct cpt_ctx, k_ctx);
2184
2185         /* 16 byte aligned cpt res address */
2186         req->completion_addr = (uint64_t *)((uint8_t *)c_vaddr);
2187         *req->completion_addr = COMPLETION_CODE_INIT;
2188         req->comp_baddr  = c_dma;
2189
2190         /* Fill microcode part of instruction */
2191         req->ist.ei0 = vq_cmd_w0.u64;
2192         req->ist.ei3 = vq_cmd_w3.u64;
2193
2194         req->op = op;
2195
2196         *prep_req = req;
2197         return;
2198 }
2199
2200 static __rte_always_inline void
2201 cpt_kasumi_dec_prep(uint64_t d_offs,
2202                     uint64_t d_lens,
2203                     fc_params_t *params,
2204                     void *op,
2205                     void **prep_req)
2206 {
2207         uint32_t size;
2208         int32_t inputlen = 0, outputlen;
2209         struct cpt_ctx *cpt_ctx;
2210         uint8_t i = 0, iv_len = 8;
2211         struct cpt_request_info *req;
2212         buf_ptr_t *buf_p;
2213         uint32_t encr_offset;
2214         uint32_t encr_data_len;
2215         int flags;
2216         uint8_t dir = 0;
2217         void *m_vaddr, *c_vaddr;
2218         uint64_t m_dma, c_dma;
2219         uint64_t *offset_vaddr, offset_dma;
2220         vq_cmd_word0_t vq_cmd_w0;
2221         vq_cmd_word3_t vq_cmd_w3;
2222         opcode_info_t opcode;
2223         uint8_t *in_buffer;
2224         uint32_t g_size_bytes, s_size_bytes;
2225         uint64_t dptr_dma, rptr_dma;
2226         sg_comp_t *gather_comp;
2227         sg_comp_t *scatter_comp;
2228
2229         buf_p = &params->meta_buf;
2230         m_vaddr = buf_p->vaddr;
2231         m_dma = buf_p->dma_addr;
2232
2233         encr_offset = ENCR_OFFSET(d_offs) / 8;
2234         encr_data_len = ENCR_DLEN(d_lens);
2235
2236         cpt_ctx = params->ctx_buf.vaddr;
2237         flags = cpt_ctx->zsk_flags;
2238         /*
2239          * Save initial space that followed app data for completion code &
2240          * alternate completion code to fall in same cache line as app data
2241          */
2242         m_vaddr = (uint8_t *)m_vaddr + COMPLETION_CODE_SIZE;
2243         m_dma += COMPLETION_CODE_SIZE;
2244         size = (uint8_t *)RTE_PTR_ALIGN((uint8_t *)m_vaddr, 16) -
2245                 (uint8_t *)m_vaddr;
2246
2247         c_vaddr = (uint8_t *)m_vaddr + size;
2248         c_dma = m_dma + size;
2249         size += sizeof(cpt_res_s_t);
2250
2251         m_vaddr = (uint8_t *)m_vaddr + size;
2252         m_dma += size;
2253
2254         /* Reserve memory for cpt request info */
2255         req = m_vaddr;
2256
2257         size = sizeof(struct cpt_request_info);
2258         m_vaddr = (uint8_t *)m_vaddr + size;
2259         m_dma += size;
2260
2261         opcode.s.major = CPT_MAJOR_OP_KASUMI | CPT_DMA_MODE;
2262
2263         /* indicates ECB/CBC, direction, ctx from cptr, iv from dptr */
2264         opcode.s.minor = ((1 << 6) | (cpt_ctx->k_ecb << 5) |
2265                           (dir << 4) | (0 << 3) | (flags & 0x7));
2266
2267         /*
2268          * GP op header, lengths are expected in bits.
2269          */
2270         vq_cmd_w0.u64 = 0;
2271         vq_cmd_w0.s.param1 = encr_data_len;
2272         vq_cmd_w0.s.opcode = opcode.flags;
2273
2274         /* consider iv len */
2275         encr_offset += iv_len;
2276
2277         inputlen = iv_len + (RTE_ALIGN(encr_data_len, 8) / 8);
2278         outputlen = inputlen;
2279
2280         /* save space for offset ctrl & iv */
2281         offset_vaddr = m_vaddr;
2282         offset_dma = m_dma;
2283
2284         m_vaddr = (uint8_t *)m_vaddr + OFF_CTRL_LEN + iv_len;
2285         m_dma += OFF_CTRL_LEN + iv_len;
2286
2287         /* DPTR has SG list */
2288         in_buffer = m_vaddr;
2289         dptr_dma = m_dma;
2290
2291         ((uint16_t *)in_buffer)[0] = 0;
2292         ((uint16_t *)in_buffer)[1] = 0;
2293
2294         /* TODO Add error check if space will be sufficient */
2295         gather_comp = (sg_comp_t *)((uint8_t *)m_vaddr + 8);
2296
2297         /*
2298          * Input Gather List
2299          */
2300         i = 0;
2301
2302         /* Offset control word followed by iv */
2303         *offset_vaddr = rte_cpu_to_be_64((uint64_t)encr_offset << 16);
2304
2305         i = fill_sg_comp(gather_comp, i, offset_dma, OFF_CTRL_LEN + iv_len);
2306
2307         /* IV */
2308         memcpy((uint8_t *)offset_vaddr + OFF_CTRL_LEN,
2309                params->iv_buf, iv_len);
2310
2311         /* Add input data */
2312         size = inputlen - iv_len;
2313         if (size) {
2314                 i = fill_sg_comp_from_iov(gather_comp, i,
2315                                           params->src_iov,
2316                                           0, &size, NULL, 0);
2317                 if (unlikely(size)) {
2318                         CPT_LOG_DP_ERR("Insufficient buffer space,"
2319                                        " size %d needed", size);
2320                         return;
2321                 }
2322         }
2323         ((uint16_t *)in_buffer)[2] = rte_cpu_to_be_16(i);
2324         g_size_bytes = ((i + 3) / 4) * sizeof(sg_comp_t);
2325
2326         /*
2327          * Output Scatter List
2328          */
2329
2330         i = 0;
2331         scatter_comp = (sg_comp_t *)((uint8_t *)gather_comp + g_size_bytes);
2332
2333         /* IV */
2334         i = fill_sg_comp(scatter_comp, i,
2335                          offset_dma + OFF_CTRL_LEN,
2336                          iv_len);
2337
2338         /* Add output data */
2339         size = outputlen - iv_len;
2340         if (size) {
2341                 i = fill_sg_comp_from_iov(scatter_comp, i,
2342                                           params->dst_iov, 0,
2343                                           &size, NULL, 0);
2344                 if (unlikely(size)) {
2345                         CPT_LOG_DP_ERR("Insufficient buffer space,"
2346                                        " size %d needed", size);
2347                         return;
2348                 }
2349         }
2350         ((uint16_t *)in_buffer)[3] = rte_cpu_to_be_16(i);
2351         s_size_bytes = ((i + 3) / 4) * sizeof(sg_comp_t);
2352
2353         size = g_size_bytes + s_size_bytes + SG_LIST_HDR_SIZE;
2354
2355         /* This is DPTR len incase of SG mode */
2356         vq_cmd_w0.s.dlen = size;
2357
2358         m_vaddr = (uint8_t *)m_vaddr + size;
2359         m_dma += size;
2360
2361         /* cpt alternate completion address saved earlier */
2362         req->alternate_caddr = (uint64_t *)((uint8_t *)c_vaddr - 8);
2363         *req->alternate_caddr = ~((uint64_t)COMPLETION_CODE_INIT);
2364         rptr_dma = c_dma - 8;
2365
2366         req->ist.ei1 = dptr_dma;
2367         req->ist.ei2 = rptr_dma;
2368
2369         /* vq command w3 */
2370         vq_cmd_w3.u64 = 0;
2371         vq_cmd_w3.s.grp = 0;
2372         vq_cmd_w3.s.cptr = params->ctx_buf.dma_addr +
2373                 offsetof(struct cpt_ctx, k_ctx);
2374
2375         /* 16 byte aligned cpt res address */
2376         req->completion_addr = (uint64_t *)((uint8_t *)c_vaddr);
2377         *req->completion_addr = COMPLETION_CODE_INIT;
2378         req->comp_baddr  = c_dma;
2379
2380         /* Fill microcode part of instruction */
2381         req->ist.ei0 = vq_cmd_w0.u64;
2382         req->ist.ei3 = vq_cmd_w3.u64;
2383
2384         req->op = op;
2385
2386         *prep_req = req;
2387         return;
2388 }
2389
2390 static __rte_always_inline void *
2391 cpt_fc_dec_hmac_prep(uint32_t flags,
2392                      uint64_t d_offs,
2393                      uint64_t d_lens,
2394                      fc_params_t *fc_params,
2395                      void *op)
2396 {
2397         struct cpt_ctx *ctx = fc_params->ctx_buf.vaddr;
2398         uint8_t fc_type;
2399         void *prep_req = NULL;
2400
2401         fc_type = ctx->fc_type;
2402
2403         if (likely(fc_type == FC_GEN)) {
2404                 cpt_dec_hmac_prep(flags, d_offs, d_lens, fc_params, op,
2405                                   &prep_req);
2406         } else if (fc_type == ZUC_SNOW3G) {
2407                 cpt_zuc_snow3g_dec_prep(flags, d_offs, d_lens, fc_params, op,
2408                                         &prep_req);
2409         } else if (fc_type == KASUMI) {
2410                 cpt_kasumi_dec_prep(d_offs, d_lens, fc_params, op, &prep_req);
2411         }
2412
2413         /*
2414          * For AUTH_ONLY case,
2415          * MC only supports digest generation and verification
2416          * should be done in software by memcmp()
2417          */
2418
2419         return prep_req;
2420 }
2421
2422 static __rte_always_inline void *__rte_hot
2423 cpt_fc_enc_hmac_prep(uint32_t flags, uint64_t d_offs, uint64_t d_lens,
2424                      fc_params_t *fc_params, void *op)
2425 {
2426         struct cpt_ctx *ctx = fc_params->ctx_buf.vaddr;
2427         uint8_t fc_type;
2428         void *prep_req = NULL;
2429
2430         fc_type = ctx->fc_type;
2431
2432         /* Common api for rest of the ops */
2433         if (likely(fc_type == FC_GEN)) {
2434                 cpt_enc_hmac_prep(flags, d_offs, d_lens, fc_params, op,
2435                                   &prep_req);
2436         } else if (fc_type == ZUC_SNOW3G) {
2437                 cpt_zuc_snow3g_enc_prep(flags, d_offs, d_lens, fc_params, op,
2438                                         &prep_req);
2439         } else if (fc_type == KASUMI) {
2440                 cpt_kasumi_enc_prep(flags, d_offs, d_lens, fc_params, op,
2441                                     &prep_req);
2442         } else if (fc_type == HASH_HMAC) {
2443                 cpt_digest_gen_prep(flags, d_lens, fc_params, op, &prep_req);
2444         }
2445
2446         return prep_req;
2447 }
2448
2449 static __rte_always_inline int
2450 cpt_fc_auth_set_key(void *ctx, auth_type_t type, const uint8_t *key,
2451                     uint16_t key_len, uint16_t mac_len)
2452 {
2453         struct cpt_ctx *cpt_ctx = ctx;
2454         mc_fc_context_t *fctx = &cpt_ctx->fctx;
2455
2456         if ((type >= ZUC_EIA3) && (type <= KASUMI_F9_ECB)) {
2457                 uint32_t keyx[4];
2458
2459                 if (key_len != 16)
2460                         return -1;
2461                 /* No support for AEAD yet */
2462                 if (cpt_ctx->enc_cipher)
2463                         return -1;
2464                 /* For ZUC/SNOW3G/Kasumi */
2465                 switch (type) {
2466                 case SNOW3G_UIA2:
2467                         cpt_ctx->snow3g = 1;
2468                         gen_key_snow3g(key, keyx);
2469                         memcpy(cpt_ctx->zs_ctx.ci_key, keyx, key_len);
2470                         cpt_ctx->fc_type = ZUC_SNOW3G;
2471                         cpt_ctx->zsk_flags = 0x1;
2472                         break;
2473                 case ZUC_EIA3:
2474                         cpt_ctx->snow3g = 0;
2475                         memcpy(cpt_ctx->zs_ctx.ci_key, key, key_len);
2476                         memcpy(cpt_ctx->zs_ctx.zuc_const, zuc_d, 32);
2477                         cpt_ctx->fc_type = ZUC_SNOW3G;
2478                         cpt_ctx->zsk_flags = 0x1;
2479                         break;
2480                 case KASUMI_F9_ECB:
2481                         /* Kasumi ECB mode */
2482                         cpt_ctx->k_ecb = 1;
2483                         memcpy(cpt_ctx->k_ctx.ci_key, key, key_len);
2484                         cpt_ctx->fc_type = KASUMI;
2485                         cpt_ctx->zsk_flags = 0x1;
2486                         break;
2487                 case KASUMI_F9_CBC:
2488                         memcpy(cpt_ctx->k_ctx.ci_key, key, key_len);
2489                         cpt_ctx->fc_type = KASUMI;
2490                         cpt_ctx->zsk_flags = 0x1;
2491                         break;
2492                 default:
2493                         return -1;
2494                 }
2495                 cpt_ctx->mac_len = 4;
2496                 cpt_ctx->hash_type = type;
2497                 return 0;
2498         }
2499
2500         if (!(cpt_ctx->fc_type == FC_GEN && !type)) {
2501                 if (!cpt_ctx->fc_type || !cpt_ctx->enc_cipher)
2502                         cpt_ctx->fc_type = HASH_HMAC;
2503         }
2504
2505         if (cpt_ctx->fc_type == FC_GEN && key_len > 64)
2506                 return -1;
2507
2508         /* For GMAC auth, cipher must be NULL */
2509         if (type == GMAC_TYPE)
2510                 fctx->enc.enc_cipher = 0;
2511
2512         fctx->enc.hash_type = cpt_ctx->hash_type = type;
2513         fctx->enc.mac_len = cpt_ctx->mac_len = mac_len;
2514
2515         if (key_len) {
2516                 cpt_ctx->hmac = 1;
2517                 memset(cpt_ctx->auth_key, 0, sizeof(cpt_ctx->auth_key));
2518                 memcpy(cpt_ctx->auth_key, key, key_len);
2519                 cpt_ctx->auth_key_len = key_len;
2520                 memset(fctx->hmac.ipad, 0, sizeof(fctx->hmac.ipad));
2521                 memset(fctx->hmac.opad, 0, sizeof(fctx->hmac.opad));
2522
2523                 if (key_len <= 64)
2524                         memcpy(fctx->hmac.opad, key, key_len);
2525                 fctx->enc.auth_input_type = 1;
2526         }
2527         return 0;
2528 }
2529
2530 static __rte_always_inline int
2531 fill_sess_aead(struct rte_crypto_sym_xform *xform,
2532                  struct cpt_sess_misc *sess)
2533 {
2534         struct rte_crypto_aead_xform *aead_form;
2535         cipher_type_t enc_type = 0; /* NULL Cipher type */
2536         auth_type_t auth_type = 0; /* NULL Auth type */
2537         uint32_t cipher_key_len = 0;
2538         uint8_t aes_gcm = 0;
2539         aead_form = &xform->aead;
2540         void *ctx = SESS_PRIV(sess);
2541
2542         if (aead_form->op == RTE_CRYPTO_AEAD_OP_ENCRYPT &&
2543            aead_form->algo == RTE_CRYPTO_AEAD_AES_GCM) {
2544                 sess->cpt_op |= CPT_OP_CIPHER_ENCRYPT;
2545                 sess->cpt_op |= CPT_OP_AUTH_GENERATE;
2546         } else if (aead_form->op == RTE_CRYPTO_AEAD_OP_DECRYPT &&
2547                 aead_form->algo == RTE_CRYPTO_AEAD_AES_GCM) {
2548                 sess->cpt_op |= CPT_OP_CIPHER_DECRYPT;
2549                 sess->cpt_op |= CPT_OP_AUTH_VERIFY;
2550         } else {
2551                 CPT_LOG_DP_ERR("Unknown cipher operation\n");
2552                 return -1;
2553         }
2554         switch (aead_form->algo) {
2555         case RTE_CRYPTO_AEAD_AES_GCM:
2556                 enc_type = AES_GCM;
2557                 cipher_key_len = 16;
2558                 aes_gcm = 1;
2559                 break;
2560         case RTE_CRYPTO_AEAD_AES_CCM:
2561                 CPT_LOG_DP_ERR("Crypto: Unsupported cipher algo %u",
2562                                aead_form->algo);
2563                 return -1;
2564         default:
2565                 CPT_LOG_DP_ERR("Crypto: Undefined cipher algo %u specified",
2566                                aead_form->algo);
2567                 return -1;
2568         }
2569         if (aead_form->key.length < cipher_key_len) {
2570                 CPT_LOG_DP_ERR("Invalid cipher params keylen %lu",
2571                                (unsigned int long)aead_form->key.length);
2572                 return -1;
2573         }
2574         sess->zsk_flag = 0;
2575         sess->aes_gcm = aes_gcm;
2576         sess->mac_len = aead_form->digest_length;
2577         sess->iv_offset = aead_form->iv.offset;
2578         sess->iv_length = aead_form->iv.length;
2579         sess->aad_length = aead_form->aad_length;
2580
2581         if (unlikely(cpt_fc_ciph_set_key(ctx, enc_type, aead_form->key.data,
2582                         aead_form->key.length, NULL)))
2583                 return -1;
2584
2585         if (unlikely(cpt_fc_auth_set_key(ctx, auth_type, NULL, 0,
2586                         aead_form->digest_length)))
2587                 return -1;
2588
2589         return 0;
2590 }
2591
2592 static __rte_always_inline int
2593 fill_sess_cipher(struct rte_crypto_sym_xform *xform,
2594                  struct cpt_sess_misc *sess)
2595 {
2596         struct rte_crypto_cipher_xform *c_form;
2597         cipher_type_t enc_type = 0; /* NULL Cipher type */
2598         uint32_t cipher_key_len = 0;
2599         uint8_t zsk_flag = 0, aes_ctr = 0, is_null = 0;
2600
2601         c_form = &xform->cipher;
2602
2603         if (c_form->op == RTE_CRYPTO_CIPHER_OP_ENCRYPT)
2604                 sess->cpt_op |= CPT_OP_CIPHER_ENCRYPT;
2605         else if (c_form->op == RTE_CRYPTO_CIPHER_OP_DECRYPT)
2606                 sess->cpt_op |= CPT_OP_CIPHER_DECRYPT;
2607         else {
2608                 CPT_LOG_DP_ERR("Unknown cipher operation\n");
2609                 return -1;
2610         }
2611
2612         switch (c_form->algo) {
2613         case RTE_CRYPTO_CIPHER_AES_CBC:
2614                 enc_type = AES_CBC;
2615                 cipher_key_len = 16;
2616                 break;
2617         case RTE_CRYPTO_CIPHER_3DES_CBC:
2618                 enc_type = DES3_CBC;
2619                 cipher_key_len = 24;
2620                 break;
2621         case RTE_CRYPTO_CIPHER_DES_CBC:
2622                 /* DES is implemented using 3DES in hardware */
2623                 enc_type = DES3_CBC;
2624                 cipher_key_len = 8;
2625                 break;
2626         case RTE_CRYPTO_CIPHER_AES_CTR:
2627                 enc_type = AES_CTR;
2628                 cipher_key_len = 16;
2629                 aes_ctr = 1;
2630                 break;
2631         case RTE_CRYPTO_CIPHER_NULL:
2632                 enc_type = 0;
2633                 is_null = 1;
2634                 break;
2635         case RTE_CRYPTO_CIPHER_KASUMI_F8:
2636                 enc_type = KASUMI_F8_ECB;
2637                 cipher_key_len = 16;
2638                 zsk_flag = K_F8;
2639                 break;
2640         case RTE_CRYPTO_CIPHER_SNOW3G_UEA2:
2641                 enc_type = SNOW3G_UEA2;
2642                 cipher_key_len = 16;
2643                 zsk_flag = ZS_EA;
2644                 break;
2645         case RTE_CRYPTO_CIPHER_ZUC_EEA3:
2646                 enc_type = ZUC_EEA3;
2647                 cipher_key_len = 16;
2648                 zsk_flag = ZS_EA;
2649                 break;
2650         case RTE_CRYPTO_CIPHER_AES_XTS:
2651                 enc_type = AES_XTS;
2652                 cipher_key_len = 16;
2653                 break;
2654         case RTE_CRYPTO_CIPHER_3DES_ECB:
2655                 enc_type = DES3_ECB;
2656                 cipher_key_len = 24;
2657                 break;
2658         case RTE_CRYPTO_CIPHER_AES_ECB:
2659                 enc_type = AES_ECB;
2660                 cipher_key_len = 16;
2661                 break;
2662         case RTE_CRYPTO_CIPHER_3DES_CTR:
2663         case RTE_CRYPTO_CIPHER_AES_F8:
2664         case RTE_CRYPTO_CIPHER_ARC4:
2665                 CPT_LOG_DP_ERR("Crypto: Unsupported cipher algo %u",
2666                                c_form->algo);
2667                 return -1;
2668         default:
2669                 CPT_LOG_DP_ERR("Crypto: Undefined cipher algo %u specified",
2670                                c_form->algo);
2671                 return -1;
2672         }
2673
2674         if (c_form->key.length < cipher_key_len) {
2675                 CPT_LOG_DP_ERR("Invalid cipher params keylen %lu",
2676                                (unsigned long) c_form->key.length);
2677                 return -1;
2678         }
2679
2680         sess->zsk_flag = zsk_flag;
2681         sess->aes_gcm = 0;
2682         sess->aes_ctr = aes_ctr;
2683         sess->iv_offset = c_form->iv.offset;
2684         sess->iv_length = c_form->iv.length;
2685         sess->is_null = is_null;
2686
2687         if (unlikely(cpt_fc_ciph_set_key(SESS_PRIV(sess), enc_type,
2688                         c_form->key.data, c_form->key.length, NULL)))
2689                 return -1;
2690
2691         return 0;
2692 }
2693
2694 static __rte_always_inline int
2695 fill_sess_auth(struct rte_crypto_sym_xform *xform,
2696                struct cpt_sess_misc *sess)
2697 {
2698         struct rte_crypto_auth_xform *a_form;
2699         auth_type_t auth_type = 0; /* NULL Auth type */
2700         uint8_t zsk_flag = 0, aes_gcm = 0, is_null = 0;
2701
2702         a_form = &xform->auth;
2703
2704         if (a_form->op == RTE_CRYPTO_AUTH_OP_VERIFY)
2705                 sess->cpt_op |= CPT_OP_AUTH_VERIFY;
2706         else if (a_form->op == RTE_CRYPTO_AUTH_OP_GENERATE)
2707                 sess->cpt_op |= CPT_OP_AUTH_GENERATE;
2708         else {
2709                 CPT_LOG_DP_ERR("Unknown auth operation");
2710                 return -1;
2711         }
2712
2713         switch (a_form->algo) {
2714         case RTE_CRYPTO_AUTH_SHA1_HMAC:
2715                 /* Fall through */
2716         case RTE_CRYPTO_AUTH_SHA1:
2717                 auth_type = SHA1_TYPE;
2718                 break;
2719         case RTE_CRYPTO_AUTH_SHA256_HMAC:
2720         case RTE_CRYPTO_AUTH_SHA256:
2721                 auth_type = SHA2_SHA256;
2722                 break;
2723         case RTE_CRYPTO_AUTH_SHA512_HMAC:
2724         case RTE_CRYPTO_AUTH_SHA512:
2725                 auth_type = SHA2_SHA512;
2726                 break;
2727         case RTE_CRYPTO_AUTH_AES_GMAC:
2728                 auth_type = GMAC_TYPE;
2729                 aes_gcm = 1;
2730                 break;
2731         case RTE_CRYPTO_AUTH_SHA224_HMAC:
2732         case RTE_CRYPTO_AUTH_SHA224:
2733                 auth_type = SHA2_SHA224;
2734                 break;
2735         case RTE_CRYPTO_AUTH_SHA384_HMAC:
2736         case RTE_CRYPTO_AUTH_SHA384:
2737                 auth_type = SHA2_SHA384;
2738                 break;
2739         case RTE_CRYPTO_AUTH_MD5_HMAC:
2740         case RTE_CRYPTO_AUTH_MD5:
2741                 auth_type = MD5_TYPE;
2742                 break;
2743         case RTE_CRYPTO_AUTH_KASUMI_F9:
2744                 auth_type = KASUMI_F9_ECB;
2745                 /*
2746                  * Indicate that direction needs to be taken out
2747                  * from end of src
2748                  */
2749                 zsk_flag = K_F9;
2750                 break;
2751         case RTE_CRYPTO_AUTH_SNOW3G_UIA2:
2752                 auth_type = SNOW3G_UIA2;
2753                 zsk_flag = ZS_IA;
2754                 break;
2755         case RTE_CRYPTO_AUTH_ZUC_EIA3:
2756                 auth_type = ZUC_EIA3;
2757                 zsk_flag = ZS_IA;
2758                 break;
2759         case RTE_CRYPTO_AUTH_NULL:
2760                 auth_type = 0;
2761                 is_null = 1;
2762                 break;
2763         case RTE_CRYPTO_AUTH_AES_XCBC_MAC:
2764         case RTE_CRYPTO_AUTH_AES_CMAC:
2765         case RTE_CRYPTO_AUTH_AES_CBC_MAC:
2766                 CPT_LOG_DP_ERR("Crypto: Unsupported hash algo %u",
2767                                a_form->algo);
2768                 return -1;
2769         default:
2770                 CPT_LOG_DP_ERR("Crypto: Undefined Hash algo %u specified",
2771                                a_form->algo);
2772                 return -1;
2773         }
2774
2775         sess->zsk_flag = zsk_flag;
2776         sess->aes_gcm = aes_gcm;
2777         sess->mac_len = a_form->digest_length;
2778         sess->is_null = is_null;
2779         if (zsk_flag) {
2780                 sess->auth_iv_offset = a_form->iv.offset;
2781                 sess->auth_iv_length = a_form->iv.length;
2782         }
2783         if (unlikely(cpt_fc_auth_set_key(SESS_PRIV(sess), auth_type,
2784                         a_form->key.data, a_form->key.length,
2785                         a_form->digest_length)))
2786                 return -1;
2787
2788         return 0;
2789 }
2790
2791 static __rte_always_inline int
2792 fill_sess_gmac(struct rte_crypto_sym_xform *xform,
2793                  struct cpt_sess_misc *sess)
2794 {
2795         struct rte_crypto_auth_xform *a_form;
2796         cipher_type_t enc_type = 0; /* NULL Cipher type */
2797         auth_type_t auth_type = 0; /* NULL Auth type */
2798         void *ctx = SESS_PRIV(sess);
2799
2800         a_form = &xform->auth;
2801
2802         if (a_form->op == RTE_CRYPTO_AUTH_OP_GENERATE)
2803                 sess->cpt_op |= CPT_OP_ENCODE;
2804         else if (a_form->op == RTE_CRYPTO_AUTH_OP_VERIFY)
2805                 sess->cpt_op |= CPT_OP_DECODE;
2806         else {
2807                 CPT_LOG_DP_ERR("Unknown auth operation");
2808                 return -1;
2809         }
2810
2811         switch (a_form->algo) {
2812         case RTE_CRYPTO_AUTH_AES_GMAC:
2813                 enc_type = AES_GCM;
2814                 auth_type = GMAC_TYPE;
2815                 break;
2816         default:
2817                 CPT_LOG_DP_ERR("Crypto: Undefined cipher algo %u specified",
2818                                a_form->algo);
2819                 return -1;
2820         }
2821
2822         sess->zsk_flag = 0;
2823         sess->aes_gcm = 0;
2824         sess->is_gmac = 1;
2825         sess->iv_offset = a_form->iv.offset;
2826         sess->iv_length = a_form->iv.length;
2827         sess->mac_len = a_form->digest_length;
2828
2829         if (unlikely(cpt_fc_ciph_set_key(ctx, enc_type, a_form->key.data,
2830                         a_form->key.length, NULL)))
2831                 return -1;
2832
2833         if (unlikely(cpt_fc_auth_set_key(ctx, auth_type, NULL, 0,
2834                         a_form->digest_length)))
2835                 return -1;
2836
2837         return 0;
2838 }
2839
2840 static __rte_always_inline void *
2841 alloc_op_meta(struct rte_mbuf *m_src,
2842               buf_ptr_t *buf,
2843               int32_t len,
2844               struct rte_mempool *cpt_meta_pool)
2845 {
2846         uint8_t *mdata;
2847
2848 #ifndef CPT_ALWAYS_USE_SEPARATE_BUF
2849         if (likely(m_src && (m_src->nb_segs == 1))) {
2850                 int32_t tailroom;
2851                 phys_addr_t mphys;
2852
2853                 /* Check if tailroom is sufficient to hold meta data */
2854                 tailroom = rte_pktmbuf_tailroom(m_src);
2855                 if (likely(tailroom > len + 8)) {
2856                         mdata = (uint8_t *)m_src->buf_addr + m_src->buf_len;
2857                         mphys = m_src->buf_physaddr + m_src->buf_len;
2858                         mdata -= len;
2859                         mphys -= len;
2860                         buf->vaddr = mdata;
2861                         buf->dma_addr = mphys;
2862                         buf->size = len;
2863                         /* Indicate that this is a mbuf allocated mdata */
2864                         mdata = (uint8_t *)((uint64_t)mdata | 1ull);
2865                         return mdata;
2866                 }
2867         }
2868 #else
2869         RTE_SET_USED(m_src);
2870 #endif
2871
2872         if (unlikely(rte_mempool_get(cpt_meta_pool, (void **)&mdata) < 0))
2873                 return NULL;
2874
2875         buf->vaddr = mdata;
2876         buf->dma_addr = rte_mempool_virt2iova(mdata);
2877         buf->size = len;
2878
2879         return mdata;
2880 }
2881
2882 /**
2883  * cpt_free_metabuf - free metabuf to mempool.
2884  * @param instance: pointer to instance.
2885  * @param objp: pointer to the metabuf.
2886  */
2887 static __rte_always_inline void
2888 free_op_meta(void *mdata, struct rte_mempool *cpt_meta_pool)
2889 {
2890         bool nofree = ((uintptr_t)mdata & 1ull);
2891
2892         if (likely(nofree))
2893                 return;
2894         rte_mempool_put(cpt_meta_pool, mdata);
2895 }
2896
2897 static __rte_always_inline uint32_t
2898 prepare_iov_from_pkt(struct rte_mbuf *pkt,
2899                      iov_ptr_t *iovec, uint32_t start_offset)
2900 {
2901         uint16_t index = 0;
2902         void *seg_data = NULL;
2903         phys_addr_t seg_phys;
2904         int32_t seg_size = 0;
2905
2906         if (!pkt) {
2907                 iovec->buf_cnt = 0;
2908                 return 0;
2909         }
2910
2911         if (!start_offset) {
2912                 seg_data = rte_pktmbuf_mtod(pkt, void *);
2913                 seg_phys = rte_pktmbuf_mtophys(pkt);
2914                 seg_size = pkt->data_len;
2915         } else {
2916                 while (start_offset >= pkt->data_len) {
2917                         start_offset -= pkt->data_len;
2918                         pkt = pkt->next;
2919                 }
2920
2921                 seg_data = rte_pktmbuf_mtod_offset(pkt, void *, start_offset);
2922                 seg_phys = rte_pktmbuf_mtophys_offset(pkt, start_offset);
2923                 seg_size = pkt->data_len - start_offset;
2924                 if (!seg_size)
2925                         return 1;
2926         }
2927
2928         /* first seg */
2929         iovec->bufs[index].vaddr = seg_data;
2930         iovec->bufs[index].dma_addr = seg_phys;
2931         iovec->bufs[index].size = seg_size;
2932         index++;
2933         pkt = pkt->next;
2934
2935         while (unlikely(pkt != NULL)) {
2936                 seg_data = rte_pktmbuf_mtod(pkt, void *);
2937                 seg_phys = rte_pktmbuf_mtophys(pkt);
2938                 seg_size = pkt->data_len;
2939                 if (!seg_size)
2940                         break;
2941
2942                 iovec->bufs[index].vaddr = seg_data;
2943                 iovec->bufs[index].dma_addr = seg_phys;
2944                 iovec->bufs[index].size = seg_size;
2945
2946                 index++;
2947
2948                 pkt = pkt->next;
2949         }
2950
2951         iovec->buf_cnt = index;
2952         return 0;
2953 }
2954
2955 static __rte_always_inline uint32_t
2956 prepare_iov_from_pkt_inplace(struct rte_mbuf *pkt,
2957                              fc_params_t *param,
2958                              uint32_t *flags)
2959 {
2960         uint16_t index = 0;
2961         void *seg_data = NULL;
2962         phys_addr_t seg_phys;
2963         uint32_t seg_size = 0;
2964         iov_ptr_t *iovec;
2965
2966         seg_data = rte_pktmbuf_mtod(pkt, void *);
2967         seg_phys = rte_pktmbuf_mtophys(pkt);
2968         seg_size = pkt->data_len;
2969
2970         /* first seg */
2971         if (likely(!pkt->next)) {
2972                 uint32_t headroom, tailroom;
2973
2974                 *flags |= SINGLE_BUF_INPLACE;
2975                 headroom = rte_pktmbuf_headroom(pkt);
2976                 tailroom = rte_pktmbuf_tailroom(pkt);
2977                 if (likely((headroom >= 24) &&
2978                     (tailroom >= 8))) {
2979                         /* In 83XX this is prerequivisit for Direct mode */
2980                         *flags |= SINGLE_BUF_HEADTAILROOM;
2981                 }
2982                 param->bufs[0].vaddr = seg_data;
2983                 param->bufs[0].dma_addr = seg_phys;
2984                 param->bufs[0].size = seg_size;
2985                 return 0;
2986         }
2987         iovec = param->src_iov;
2988         iovec->bufs[index].vaddr = seg_data;
2989         iovec->bufs[index].dma_addr = seg_phys;
2990         iovec->bufs[index].size = seg_size;
2991         index++;
2992         pkt = pkt->next;
2993
2994         while (unlikely(pkt != NULL)) {
2995                 seg_data = rte_pktmbuf_mtod(pkt, void *);
2996                 seg_phys = rte_pktmbuf_mtophys(pkt);
2997                 seg_size = pkt->data_len;
2998
2999                 if (!seg_size)
3000                         break;
3001
3002                 iovec->bufs[index].vaddr = seg_data;
3003                 iovec->bufs[index].dma_addr = seg_phys;
3004                 iovec->bufs[index].size = seg_size;
3005
3006                 index++;
3007
3008                 pkt = pkt->next;
3009         }
3010
3011         iovec->buf_cnt = index;
3012         return 0;
3013 }
3014
3015 static __rte_always_inline int
3016 fill_fc_params(struct rte_crypto_op *cop,
3017                struct cpt_sess_misc *sess_misc,
3018                struct cpt_qp_meta_info *m_info,
3019                void **mdata_ptr,
3020                void **prep_req)
3021 {
3022         uint32_t space = 0;
3023         struct rte_crypto_sym_op *sym_op = cop->sym;
3024         void *mdata = NULL;
3025         uintptr_t *op;
3026         uint32_t mc_hash_off;
3027         uint32_t flags = 0;
3028         uint64_t d_offs, d_lens;
3029         struct rte_mbuf *m_src, *m_dst;
3030         uint8_t cpt_op = sess_misc->cpt_op;
3031 #ifdef CPT_ALWAYS_USE_SG_MODE
3032         uint8_t inplace = 0;
3033 #else
3034         uint8_t inplace = 1;
3035 #endif
3036         fc_params_t fc_params;
3037         char src[SRC_IOV_SIZE];
3038         char dst[SRC_IOV_SIZE];
3039         uint32_t iv_buf[4];
3040         int ret;
3041
3042         if (likely(sess_misc->iv_length)) {
3043                 flags |= VALID_IV_BUF;
3044                 fc_params.iv_buf = rte_crypto_op_ctod_offset(cop,
3045                                    uint8_t *, sess_misc->iv_offset);
3046                 if (sess_misc->aes_ctr &&
3047                     unlikely(sess_misc->iv_length != 16)) {
3048                         memcpy((uint8_t *)iv_buf,
3049                                 rte_crypto_op_ctod_offset(cop,
3050                                 uint8_t *, sess_misc->iv_offset), 12);
3051                         iv_buf[3] = rte_cpu_to_be_32(0x1);
3052                         fc_params.iv_buf = iv_buf;
3053                 }
3054         }
3055
3056         if (sess_misc->zsk_flag) {
3057                 fc_params.auth_iv_buf = rte_crypto_op_ctod_offset(cop,
3058                                         uint8_t *,
3059                                         sess_misc->auth_iv_offset);
3060                 if (sess_misc->zsk_flag != ZS_EA)
3061                         inplace = 0;
3062         }
3063         m_src = sym_op->m_src;
3064         m_dst = sym_op->m_dst;
3065
3066         if (sess_misc->aes_gcm) {
3067                 uint8_t *salt;
3068                 uint8_t *aad_data;
3069                 uint16_t aad_len;
3070
3071                 d_offs = sym_op->aead.data.offset;
3072                 d_lens = sym_op->aead.data.length;
3073                 mc_hash_off = sym_op->aead.data.offset +
3074                               sym_op->aead.data.length;
3075
3076                 aad_data = sym_op->aead.aad.data;
3077                 aad_len = sess_misc->aad_length;
3078                 if (likely((aad_data + aad_len) ==
3079                            rte_pktmbuf_mtod_offset(m_src,
3080                                 uint8_t *,
3081                                 sym_op->aead.data.offset))) {
3082                         d_offs = (d_offs - aad_len) | (d_offs << 16);
3083                         d_lens = (d_lens + aad_len) | (d_lens << 32);
3084                 } else {
3085                         fc_params.aad_buf.vaddr = sym_op->aead.aad.data;
3086                         fc_params.aad_buf.dma_addr = sym_op->aead.aad.phys_addr;
3087                         fc_params.aad_buf.size = aad_len;
3088                         flags |= VALID_AAD_BUF;
3089                         inplace = 0;
3090                         d_offs = d_offs << 16;
3091                         d_lens = d_lens << 32;
3092                 }
3093
3094                 salt = fc_params.iv_buf;
3095                 if (unlikely(*(uint32_t *)salt != sess_misc->salt)) {
3096                         cpt_fc_salt_update(SESS_PRIV(sess_misc), salt);
3097                         sess_misc->salt = *(uint32_t *)salt;
3098                 }
3099                 fc_params.iv_buf = salt + 4;
3100                 if (likely(sess_misc->mac_len)) {
3101                         struct rte_mbuf *m = (cpt_op & CPT_OP_ENCODE) ? m_dst :
3102                                              m_src;
3103
3104                         if (!m)
3105                                 m = m_src;
3106
3107                         /* hmac immediately following data is best case */
3108                         if (unlikely(rte_pktmbuf_mtod(m, uint8_t *) +
3109                             mc_hash_off !=
3110                             (uint8_t *)sym_op->aead.digest.data)) {
3111                                 flags |= VALID_MAC_BUF;
3112                                 fc_params.mac_buf.size = sess_misc->mac_len;
3113                                 fc_params.mac_buf.vaddr =
3114                                   sym_op->aead.digest.data;
3115                                 fc_params.mac_buf.dma_addr =
3116                                  sym_op->aead.digest.phys_addr;
3117                                 inplace = 0;
3118                         }
3119                 }
3120         } else {
3121                 d_offs = sym_op->cipher.data.offset;
3122                 d_lens = sym_op->cipher.data.length;
3123                 mc_hash_off = sym_op->cipher.data.offset +
3124                               sym_op->cipher.data.length;
3125                 d_offs = (d_offs << 16) | sym_op->auth.data.offset;
3126                 d_lens = (d_lens << 32) | sym_op->auth.data.length;
3127
3128                 if (mc_hash_off < (sym_op->auth.data.offset +
3129                                    sym_op->auth.data.length)){
3130                         mc_hash_off = (sym_op->auth.data.offset +
3131                                        sym_op->auth.data.length);
3132                 }
3133                 /* for gmac, salt should be updated like in gcm */
3134                 if (unlikely(sess_misc->is_gmac)) {
3135                         uint8_t *salt;
3136                         salt = fc_params.iv_buf;
3137                         if (unlikely(*(uint32_t *)salt != sess_misc->salt)) {
3138                                 cpt_fc_salt_update(SESS_PRIV(sess_misc), salt);
3139                                 sess_misc->salt = *(uint32_t *)salt;
3140                         }
3141                         fc_params.iv_buf = salt + 4;
3142                 }
3143                 if (likely(sess_misc->mac_len)) {
3144                         struct rte_mbuf *m;
3145
3146                         m = (cpt_op & CPT_OP_ENCODE) ? m_dst : m_src;
3147                         if (!m)
3148                                 m = m_src;
3149
3150                         /* hmac immediately following data is best case */
3151                         if (unlikely(rte_pktmbuf_mtod(m, uint8_t *) +
3152                             mc_hash_off !=
3153                              (uint8_t *)sym_op->auth.digest.data)) {
3154                                 flags |= VALID_MAC_BUF;
3155                                 fc_params.mac_buf.size =
3156                                         sess_misc->mac_len;
3157                                 fc_params.mac_buf.vaddr =
3158                                         sym_op->auth.digest.data;
3159                                 fc_params.mac_buf.dma_addr =
3160                                 sym_op->auth.digest.phys_addr;
3161                                 inplace = 0;
3162                         }
3163                 }
3164         }
3165         fc_params.ctx_buf.vaddr = SESS_PRIV(sess_misc);
3166         fc_params.ctx_buf.dma_addr = sess_misc->ctx_dma_addr;
3167
3168         if (unlikely(sess_misc->is_null || sess_misc->cpt_op == CPT_OP_DECODE))
3169                 inplace = 0;
3170
3171         if (likely(!m_dst && inplace)) {
3172                 /* Case of single buffer without AAD buf or
3173                  * separate mac buf in place and
3174                  * not air crypto
3175                  */
3176                 fc_params.dst_iov = fc_params.src_iov = (void *)src;
3177
3178                 if (unlikely(prepare_iov_from_pkt_inplace(m_src,
3179                                                           &fc_params,
3180                                                           &flags))) {
3181                         CPT_LOG_DP_ERR("Prepare inplace src iov failed");
3182                         ret = -EINVAL;
3183                         goto err_exit;
3184                 }
3185
3186         } else {
3187                 /* Out of place processing */
3188                 fc_params.src_iov = (void *)src;
3189                 fc_params.dst_iov = (void *)dst;
3190
3191                 /* Store SG I/O in the api for reuse */
3192                 if (prepare_iov_from_pkt(m_src, fc_params.src_iov, 0)) {
3193                         CPT_LOG_DP_ERR("Prepare src iov failed");
3194                         ret = -EINVAL;
3195                         goto err_exit;
3196                 }
3197
3198                 if (unlikely(m_dst != NULL)) {
3199                         uint32_t pkt_len;
3200
3201                         /* Try to make room as much as src has */
3202                         pkt_len = rte_pktmbuf_pkt_len(m_dst);
3203
3204                         if (unlikely(pkt_len < rte_pktmbuf_pkt_len(m_src))) {
3205                                 pkt_len = rte_pktmbuf_pkt_len(m_src) - pkt_len;
3206                                 if (!rte_pktmbuf_append(m_dst, pkt_len)) {
3207                                         CPT_LOG_DP_ERR("Not enough space in "
3208                                                        "m_dst %p, need %u"
3209                                                        " more",
3210                                                        m_dst, pkt_len);
3211                                         ret = -EINVAL;
3212                                         goto err_exit;
3213                                 }
3214                         }
3215
3216                         if (prepare_iov_from_pkt(m_dst, fc_params.dst_iov, 0)) {
3217                                 CPT_LOG_DP_ERR("Prepare dst iov failed for "
3218                                                "m_dst %p", m_dst);
3219                                 ret = -EINVAL;
3220                                 goto err_exit;
3221                         }
3222                 } else {
3223                         fc_params.dst_iov = (void *)src;
3224                 }
3225         }
3226
3227         if (likely(flags & SINGLE_BUF_HEADTAILROOM))
3228                 mdata = alloc_op_meta(m_src, &fc_params.meta_buf,
3229                                       m_info->lb_mlen, m_info->pool);
3230         else
3231                 mdata = alloc_op_meta(NULL, &fc_params.meta_buf,
3232                                       m_info->sg_mlen, m_info->pool);
3233
3234         if (unlikely(mdata == NULL)) {
3235                 CPT_LOG_DP_ERR("Error allocating meta buffer for request");
3236                 ret = -ENOMEM;
3237                 goto err_exit;
3238         }
3239
3240         op = (uintptr_t *)((uintptr_t)mdata & (uintptr_t)~1ull);
3241         op[0] = (uintptr_t)mdata;
3242         op[1] = (uintptr_t)cop;
3243         op[2] = op[3] = 0; /* Used to indicate auth verify */
3244         space += 4 * sizeof(uint64_t);
3245
3246         fc_params.meta_buf.vaddr = (uint8_t *)op + space;
3247         fc_params.meta_buf.dma_addr += space;
3248         fc_params.meta_buf.size -= space;
3249
3250         /* Finally prepare the instruction */
3251         if (cpt_op & CPT_OP_ENCODE)
3252                 *prep_req = cpt_fc_enc_hmac_prep(flags, d_offs, d_lens,
3253                                                  &fc_params, op);
3254         else
3255                 *prep_req = cpt_fc_dec_hmac_prep(flags, d_offs, d_lens,
3256                                                  &fc_params, op);
3257
3258         if (unlikely(*prep_req == NULL)) {
3259                 CPT_LOG_DP_ERR("Preparing request failed due to bad input arg");
3260                 ret = -EINVAL;
3261                 goto free_mdata_and_exit;
3262         }
3263
3264         *mdata_ptr = mdata;
3265
3266         return 0;
3267
3268 free_mdata_and_exit:
3269         free_op_meta(mdata, m_info->pool);
3270 err_exit:
3271         return ret;
3272 }
3273
3274 static __rte_always_inline void
3275 compl_auth_verify(struct rte_crypto_op *op,
3276                       uint8_t *gen_mac,
3277                       uint64_t mac_len)
3278 {
3279         uint8_t *mac;
3280         struct rte_crypto_sym_op *sym_op = op->sym;
3281
3282         if (sym_op->auth.digest.data)
3283                 mac = sym_op->auth.digest.data;
3284         else
3285                 mac = rte_pktmbuf_mtod_offset(sym_op->m_src,
3286                                               uint8_t *,
3287                                               sym_op->auth.data.length +
3288                                               sym_op->auth.data.offset);
3289         if (!mac) {
3290                 op->status = RTE_CRYPTO_OP_STATUS_ERROR;
3291                 return;
3292         }
3293
3294         if (memcmp(mac, gen_mac, mac_len))
3295                 op->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
3296         else
3297                 op->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
3298 }
3299
3300 static __rte_always_inline void
3301 find_kasumif9_direction_and_length(uint8_t *src,
3302                                    uint32_t counter_num_bytes,
3303                                    uint32_t *addr_length_in_bits,
3304                                    uint8_t *addr_direction)
3305 {
3306         uint8_t found = 0;
3307         uint32_t pos;
3308         uint8_t last_byte;
3309         while (!found && counter_num_bytes > 0) {
3310                 counter_num_bytes--;
3311                 if (src[counter_num_bytes] == 0x00)
3312                         continue;
3313                 pos = rte_bsf32(src[counter_num_bytes]);
3314                 if (pos == 7) {
3315                         if (likely(counter_num_bytes > 0)) {
3316                                 last_byte = src[counter_num_bytes - 1];
3317                                 *addr_direction  =  last_byte & 0x1;
3318                                 *addr_length_in_bits = counter_num_bytes * 8
3319                                                         - 1;
3320                         }
3321                 } else {
3322                         last_byte = src[counter_num_bytes];
3323                         *addr_direction = (last_byte >> (pos + 1)) & 0x1;
3324                         *addr_length_in_bits = counter_num_bytes * 8
3325                                                 + (8 - (pos + 2));
3326                 }
3327                 found = 1;
3328         }
3329 }
3330
3331 /*
3332  * This handles all auth only except AES_GMAC
3333  */
3334 static __rte_always_inline int
3335 fill_digest_params(struct rte_crypto_op *cop,
3336                    struct cpt_sess_misc *sess,
3337                    struct cpt_qp_meta_info *m_info,
3338                    void **mdata_ptr,
3339                    void **prep_req)
3340 {
3341         uint32_t space = 0;
3342         struct rte_crypto_sym_op *sym_op = cop->sym;
3343         void *mdata;
3344         phys_addr_t mphys;
3345         uint64_t *op;
3346         uint32_t auth_range_off;
3347         uint32_t flags = 0;
3348         uint64_t d_offs = 0, d_lens;
3349         struct rte_mbuf *m_src, *m_dst;
3350         uint16_t auth_op = sess->cpt_op & CPT_OP_AUTH_MASK;
3351         uint16_t mac_len = sess->mac_len;
3352         fc_params_t params;
3353         char src[SRC_IOV_SIZE];
3354         uint8_t iv_buf[16];
3355         int ret;
3356
3357         memset(&params, 0, sizeof(fc_params_t));
3358
3359         m_src = sym_op->m_src;
3360
3361         /* For just digest lets force mempool alloc */
3362         mdata = alloc_op_meta(NULL, &params.meta_buf, m_info->sg_mlen,
3363                               m_info->pool);
3364         if (mdata == NULL) {
3365                 ret = -ENOMEM;
3366                 goto err_exit;
3367         }
3368
3369         mphys = params.meta_buf.dma_addr;
3370
3371         op = mdata;
3372         op[0] = (uintptr_t)mdata;
3373         op[1] = (uintptr_t)cop;
3374         op[2] = op[3] = 0; /* Used to indicate auth verify */
3375         space += 4 * sizeof(uint64_t);
3376
3377         auth_range_off = sym_op->auth.data.offset;
3378
3379         flags = VALID_MAC_BUF;
3380         params.src_iov = (void *)src;
3381         if (unlikely(sess->zsk_flag)) {
3382                 /*
3383                  * Since for Zuc, Kasumi, Snow3g offsets are in bits
3384                  * we will send pass through even for auth only case,
3385                  * let MC handle it
3386                  */
3387                 d_offs = auth_range_off;
3388                 auth_range_off = 0;
3389                 params.auth_iv_buf = rte_crypto_op_ctod_offset(cop,
3390                                         uint8_t *, sess->auth_iv_offset);
3391                 if (sess->zsk_flag == K_F9) {
3392                         uint32_t length_in_bits, num_bytes;
3393                         uint8_t *src, direction = 0;
3394
3395                         memcpy(iv_buf, rte_pktmbuf_mtod(cop->sym->m_src,
3396                                                         uint8_t *), 8);
3397                         /*
3398                          * This is kasumi f9, take direction from
3399                          * source buffer
3400                          */
3401                         length_in_bits = cop->sym->auth.data.length;
3402                         num_bytes = (length_in_bits >> 3);
3403                         src = rte_pktmbuf_mtod(cop->sym->m_src, uint8_t *);
3404                         find_kasumif9_direction_and_length(src,
3405                                                 num_bytes,
3406                                                 &length_in_bits,
3407                                                 &direction);
3408                         length_in_bits -= 64;
3409                         cop->sym->auth.data.offset += 64;
3410                         d_offs = cop->sym->auth.data.offset;
3411                         auth_range_off = d_offs / 8;
3412                         cop->sym->auth.data.length = length_in_bits;
3413
3414                         /* Store it at end of auth iv */
3415                         iv_buf[8] = direction;
3416                         params.auth_iv_buf = iv_buf;
3417                 }
3418         }
3419
3420         d_lens = sym_op->auth.data.length;
3421
3422         params.ctx_buf.vaddr = SESS_PRIV(sess);
3423         params.ctx_buf.dma_addr = sess->ctx_dma_addr;
3424
3425         if (auth_op == CPT_OP_AUTH_GENERATE) {
3426                 if (sym_op->auth.digest.data) {
3427                         /*
3428                          * Digest to be generated
3429                          * in separate buffer
3430                          */
3431                         params.mac_buf.size =
3432                                 sess->mac_len;
3433                         params.mac_buf.vaddr =
3434                                 sym_op->auth.digest.data;
3435                         params.mac_buf.dma_addr =
3436                                 sym_op->auth.digest.phys_addr;
3437                 } else {
3438                         uint32_t off = sym_op->auth.data.offset +
3439                                 sym_op->auth.data.length;
3440                         int32_t dlen, space;
3441
3442                         m_dst = sym_op->m_dst ?
3443                                 sym_op->m_dst : sym_op->m_src;
3444                         dlen = rte_pktmbuf_pkt_len(m_dst);
3445
3446                         space = off + mac_len - dlen;
3447                         if (space > 0)
3448                                 if (!rte_pktmbuf_append(m_dst, space)) {
3449                                         CPT_LOG_DP_ERR("Failed to extend "
3450                                                        "mbuf by %uB", space);
3451                                         ret = -EINVAL;
3452                                         goto free_mdata_and_exit;
3453                                 }
3454
3455                         params.mac_buf.vaddr =
3456                                 rte_pktmbuf_mtod_offset(m_dst, void *, off);
3457                         params.mac_buf.dma_addr =
3458                                 rte_pktmbuf_mtophys_offset(m_dst, off);
3459                         params.mac_buf.size = mac_len;
3460                 }
3461         } else {
3462                 /* Need space for storing generated mac */
3463                 params.mac_buf.vaddr = (uint8_t *)mdata + space;
3464                 params.mac_buf.dma_addr = mphys + space;
3465                 params.mac_buf.size = mac_len;
3466                 space += RTE_ALIGN_CEIL(mac_len, 8);
3467                 op[2] = (uintptr_t)params.mac_buf.vaddr;
3468                 op[3] = mac_len;
3469         }
3470
3471         params.meta_buf.vaddr = (uint8_t *)mdata + space;
3472         params.meta_buf.dma_addr = mphys + space;
3473         params.meta_buf.size -= space;
3474
3475         /* Out of place processing */
3476         params.src_iov = (void *)src;
3477
3478         /*Store SG I/O in the api for reuse */
3479         if (prepare_iov_from_pkt(m_src, params.src_iov, auth_range_off)) {
3480                 CPT_LOG_DP_ERR("Prepare src iov failed");
3481                 ret = -EINVAL;
3482                 goto free_mdata_and_exit;
3483         }
3484
3485         *prep_req = cpt_fc_enc_hmac_prep(flags, d_offs, d_lens, &params, op);
3486         if (unlikely(*prep_req == NULL)) {
3487                 ret = -EINVAL;
3488                 goto free_mdata_and_exit;
3489         }
3490
3491         *mdata_ptr = mdata;
3492
3493         return 0;
3494
3495 free_mdata_and_exit:
3496         free_op_meta(mdata, m_info->pool);
3497 err_exit:
3498         return ret;
3499 }
3500
3501 #endif /*_CPT_UCODE_H_ */