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