162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Marvell OcteonTX CPT driver
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (C) 2019 Marvell International Ltd.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * This program is free software; you can redistribute it and/or modify
762306a36Sopenharmony_ci * it under the terms of the GNU General Public License version 2 as
862306a36Sopenharmony_ci * published by the Free Software Foundation.
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <crypto/aes.h>
1262306a36Sopenharmony_ci#include <crypto/authenc.h>
1362306a36Sopenharmony_ci#include <crypto/cryptd.h>
1462306a36Sopenharmony_ci#include <crypto/des.h>
1562306a36Sopenharmony_ci#include <crypto/internal/aead.h>
1662306a36Sopenharmony_ci#include <crypto/sha1.h>
1762306a36Sopenharmony_ci#include <crypto/sha2.h>
1862306a36Sopenharmony_ci#include <crypto/xts.h>
1962306a36Sopenharmony_ci#include <crypto/scatterwalk.h>
2062306a36Sopenharmony_ci#include <linux/rtnetlink.h>
2162306a36Sopenharmony_ci#include <linux/sort.h>
2262306a36Sopenharmony_ci#include <linux/module.h>
2362306a36Sopenharmony_ci#include "otx_cptvf.h"
2462306a36Sopenharmony_ci#include "otx_cptvf_algs.h"
2562306a36Sopenharmony_ci#include "otx_cptvf_reqmgr.h"
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#define CPT_MAX_VF_NUM	64
2862306a36Sopenharmony_ci/* Size of salt in AES GCM mode */
2962306a36Sopenharmony_ci#define AES_GCM_SALT_SIZE	4
3062306a36Sopenharmony_ci/* Size of IV in AES GCM mode */
3162306a36Sopenharmony_ci#define AES_GCM_IV_SIZE		8
3262306a36Sopenharmony_ci/* Size of ICV (Integrity Check Value) in AES GCM mode */
3362306a36Sopenharmony_ci#define AES_GCM_ICV_SIZE	16
3462306a36Sopenharmony_ci/* Offset of IV in AES GCM mode */
3562306a36Sopenharmony_ci#define AES_GCM_IV_OFFSET	8
3662306a36Sopenharmony_ci#define CONTROL_WORD_LEN	8
3762306a36Sopenharmony_ci#define KEY2_OFFSET		48
3862306a36Sopenharmony_ci#define DMA_MODE_FLAG(dma_mode) \
3962306a36Sopenharmony_ci	(((dma_mode) == OTX_CPT_DMA_GATHER_SCATTER) ? (1 << 7) : 0)
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci/* Truncated SHA digest size */
4262306a36Sopenharmony_ci#define SHA1_TRUNC_DIGEST_SIZE		12
4362306a36Sopenharmony_ci#define SHA256_TRUNC_DIGEST_SIZE	16
4462306a36Sopenharmony_ci#define SHA384_TRUNC_DIGEST_SIZE	24
4562306a36Sopenharmony_ci#define SHA512_TRUNC_DIGEST_SIZE	32
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cistatic DEFINE_MUTEX(mutex);
4862306a36Sopenharmony_cistatic int is_crypto_registered;
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cistruct cpt_device_desc {
5162306a36Sopenharmony_ci	enum otx_cptpf_type pf_type;
5262306a36Sopenharmony_ci	struct pci_dev *dev;
5362306a36Sopenharmony_ci	int num_queues;
5462306a36Sopenharmony_ci};
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_cistruct cpt_device_table {
5762306a36Sopenharmony_ci	atomic_t count;
5862306a36Sopenharmony_ci	struct cpt_device_desc desc[CPT_MAX_VF_NUM];
5962306a36Sopenharmony_ci};
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_cistatic struct cpt_device_table se_devices = {
6262306a36Sopenharmony_ci	.count = ATOMIC_INIT(0)
6362306a36Sopenharmony_ci};
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cistatic struct cpt_device_table ae_devices = {
6662306a36Sopenharmony_ci	.count = ATOMIC_INIT(0)
6762306a36Sopenharmony_ci};
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_cistatic inline int get_se_device(struct pci_dev **pdev, int *cpu_num)
7062306a36Sopenharmony_ci{
7162306a36Sopenharmony_ci	int count, ret = 0;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	count = atomic_read(&se_devices.count);
7462306a36Sopenharmony_ci	if (count < 1)
7562306a36Sopenharmony_ci		return -ENODEV;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	*cpu_num = get_cpu();
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	if (se_devices.desc[0].pf_type == OTX_CPT_SE) {
8062306a36Sopenharmony_ci		/*
8162306a36Sopenharmony_ci		 * On OcteonTX platform there is one CPT instruction queue bound
8262306a36Sopenharmony_ci		 * to each VF. We get maximum performance if one CPT queue
8362306a36Sopenharmony_ci		 * is available for each cpu otherwise CPT queues need to be
8462306a36Sopenharmony_ci		 * shared between cpus.
8562306a36Sopenharmony_ci		 */
8662306a36Sopenharmony_ci		if (*cpu_num >= count)
8762306a36Sopenharmony_ci			*cpu_num %= count;
8862306a36Sopenharmony_ci		*pdev = se_devices.desc[*cpu_num].dev;
8962306a36Sopenharmony_ci	} else {
9062306a36Sopenharmony_ci		pr_err("Unknown PF type %d\n", se_devices.desc[0].pf_type);
9162306a36Sopenharmony_ci		ret = -EINVAL;
9262306a36Sopenharmony_ci	}
9362306a36Sopenharmony_ci	put_cpu();
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	return ret;
9662306a36Sopenharmony_ci}
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_cistatic inline int validate_hmac_cipher_null(struct otx_cpt_req_info *cpt_req)
9962306a36Sopenharmony_ci{
10062306a36Sopenharmony_ci	struct otx_cpt_req_ctx *rctx;
10162306a36Sopenharmony_ci	struct aead_request *req;
10262306a36Sopenharmony_ci	struct crypto_aead *tfm;
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	req = container_of(cpt_req->areq, struct aead_request, base);
10562306a36Sopenharmony_ci	tfm = crypto_aead_reqtfm(req);
10662306a36Sopenharmony_ci	rctx = aead_request_ctx_dma(req);
10762306a36Sopenharmony_ci	if (memcmp(rctx->fctx.hmac.s.hmac_calc,
10862306a36Sopenharmony_ci		   rctx->fctx.hmac.s.hmac_recv,
10962306a36Sopenharmony_ci		   crypto_aead_authsize(tfm)) != 0)
11062306a36Sopenharmony_ci		return -EBADMSG;
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	return 0;
11362306a36Sopenharmony_ci}
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_cistatic void otx_cpt_aead_callback(int status, void *arg1, void *arg2)
11662306a36Sopenharmony_ci{
11762306a36Sopenharmony_ci	struct otx_cpt_info_buffer *cpt_info = arg2;
11862306a36Sopenharmony_ci	struct crypto_async_request *areq = arg1;
11962306a36Sopenharmony_ci	struct otx_cpt_req_info *cpt_req;
12062306a36Sopenharmony_ci	struct pci_dev *pdev;
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	if (!cpt_info)
12362306a36Sopenharmony_ci		goto complete;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	cpt_req = cpt_info->req;
12662306a36Sopenharmony_ci	if (!status) {
12762306a36Sopenharmony_ci		/*
12862306a36Sopenharmony_ci		 * When selected cipher is NULL we need to manually
12962306a36Sopenharmony_ci		 * verify whether calculated hmac value matches
13062306a36Sopenharmony_ci		 * received hmac value
13162306a36Sopenharmony_ci		 */
13262306a36Sopenharmony_ci		if (cpt_req->req_type == OTX_CPT_AEAD_ENC_DEC_NULL_REQ &&
13362306a36Sopenharmony_ci		    !cpt_req->is_enc)
13462306a36Sopenharmony_ci			status = validate_hmac_cipher_null(cpt_req);
13562306a36Sopenharmony_ci	}
13662306a36Sopenharmony_ci	pdev = cpt_info->pdev;
13762306a36Sopenharmony_ci	do_request_cleanup(pdev, cpt_info);
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_cicomplete:
14062306a36Sopenharmony_ci	if (areq)
14162306a36Sopenharmony_ci		crypto_request_complete(areq, status);
14262306a36Sopenharmony_ci}
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_cistatic void output_iv_copyback(struct crypto_async_request *areq)
14562306a36Sopenharmony_ci{
14662306a36Sopenharmony_ci	struct otx_cpt_req_info *req_info;
14762306a36Sopenharmony_ci	struct skcipher_request *sreq;
14862306a36Sopenharmony_ci	struct crypto_skcipher *stfm;
14962306a36Sopenharmony_ci	struct otx_cpt_req_ctx *rctx;
15062306a36Sopenharmony_ci	struct otx_cpt_enc_ctx *ctx;
15162306a36Sopenharmony_ci	u32 start, ivsize;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	sreq = container_of(areq, struct skcipher_request, base);
15462306a36Sopenharmony_ci	stfm = crypto_skcipher_reqtfm(sreq);
15562306a36Sopenharmony_ci	ctx = crypto_skcipher_ctx(stfm);
15662306a36Sopenharmony_ci	if (ctx->cipher_type == OTX_CPT_AES_CBC ||
15762306a36Sopenharmony_ci	    ctx->cipher_type == OTX_CPT_DES3_CBC) {
15862306a36Sopenharmony_ci		rctx = skcipher_request_ctx_dma(sreq);
15962306a36Sopenharmony_ci		req_info = &rctx->cpt_req;
16062306a36Sopenharmony_ci		ivsize = crypto_skcipher_ivsize(stfm);
16162306a36Sopenharmony_ci		start = sreq->cryptlen - ivsize;
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci		if (req_info->is_enc) {
16462306a36Sopenharmony_ci			scatterwalk_map_and_copy(sreq->iv, sreq->dst, start,
16562306a36Sopenharmony_ci						 ivsize, 0);
16662306a36Sopenharmony_ci		} else {
16762306a36Sopenharmony_ci			if (sreq->src != sreq->dst) {
16862306a36Sopenharmony_ci				scatterwalk_map_and_copy(sreq->iv, sreq->src,
16962306a36Sopenharmony_ci							 start, ivsize, 0);
17062306a36Sopenharmony_ci			} else {
17162306a36Sopenharmony_ci				memcpy(sreq->iv, req_info->iv_out, ivsize);
17262306a36Sopenharmony_ci				kfree(req_info->iv_out);
17362306a36Sopenharmony_ci			}
17462306a36Sopenharmony_ci		}
17562306a36Sopenharmony_ci	}
17662306a36Sopenharmony_ci}
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_cistatic void otx_cpt_skcipher_callback(int status, void *arg1, void *arg2)
17962306a36Sopenharmony_ci{
18062306a36Sopenharmony_ci	struct otx_cpt_info_buffer *cpt_info = arg2;
18162306a36Sopenharmony_ci	struct crypto_async_request *areq = arg1;
18262306a36Sopenharmony_ci	struct pci_dev *pdev;
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	if (areq) {
18562306a36Sopenharmony_ci		if (!status)
18662306a36Sopenharmony_ci			output_iv_copyback(areq);
18762306a36Sopenharmony_ci		if (cpt_info) {
18862306a36Sopenharmony_ci			pdev = cpt_info->pdev;
18962306a36Sopenharmony_ci			do_request_cleanup(pdev, cpt_info);
19062306a36Sopenharmony_ci		}
19162306a36Sopenharmony_ci		crypto_request_complete(areq, status);
19262306a36Sopenharmony_ci	}
19362306a36Sopenharmony_ci}
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_cistatic inline void update_input_data(struct otx_cpt_req_info *req_info,
19662306a36Sopenharmony_ci				     struct scatterlist *inp_sg,
19762306a36Sopenharmony_ci				     u32 nbytes, u32 *argcnt)
19862306a36Sopenharmony_ci{
19962306a36Sopenharmony_ci	req_info->req.dlen += nbytes;
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	while (nbytes) {
20262306a36Sopenharmony_ci		u32 len = min(nbytes, inp_sg->length);
20362306a36Sopenharmony_ci		u8 *ptr = sg_virt(inp_sg);
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci		req_info->in[*argcnt].vptr = (void *)ptr;
20662306a36Sopenharmony_ci		req_info->in[*argcnt].size = len;
20762306a36Sopenharmony_ci		nbytes -= len;
20862306a36Sopenharmony_ci		++(*argcnt);
20962306a36Sopenharmony_ci		inp_sg = sg_next(inp_sg);
21062306a36Sopenharmony_ci	}
21162306a36Sopenharmony_ci}
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_cistatic inline void update_output_data(struct otx_cpt_req_info *req_info,
21462306a36Sopenharmony_ci				      struct scatterlist *outp_sg,
21562306a36Sopenharmony_ci				      u32 offset, u32 nbytes, u32 *argcnt)
21662306a36Sopenharmony_ci{
21762306a36Sopenharmony_ci	req_info->rlen += nbytes;
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	while (nbytes) {
22062306a36Sopenharmony_ci		u32 len = min(nbytes, outp_sg->length - offset);
22162306a36Sopenharmony_ci		u8 *ptr = sg_virt(outp_sg);
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci		req_info->out[*argcnt].vptr = (void *) (ptr + offset);
22462306a36Sopenharmony_ci		req_info->out[*argcnt].size = len;
22562306a36Sopenharmony_ci		nbytes -= len;
22662306a36Sopenharmony_ci		++(*argcnt);
22762306a36Sopenharmony_ci		offset = 0;
22862306a36Sopenharmony_ci		outp_sg = sg_next(outp_sg);
22962306a36Sopenharmony_ci	}
23062306a36Sopenharmony_ci}
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_cistatic inline u32 create_ctx_hdr(struct skcipher_request *req, u32 enc,
23362306a36Sopenharmony_ci				 u32 *argcnt)
23462306a36Sopenharmony_ci{
23562306a36Sopenharmony_ci	struct crypto_skcipher *stfm = crypto_skcipher_reqtfm(req);
23662306a36Sopenharmony_ci	struct otx_cpt_req_ctx *rctx = skcipher_request_ctx_dma(req);
23762306a36Sopenharmony_ci	struct otx_cpt_req_info *req_info = &rctx->cpt_req;
23862306a36Sopenharmony_ci	struct crypto_tfm *tfm = crypto_skcipher_tfm(stfm);
23962306a36Sopenharmony_ci	struct otx_cpt_enc_ctx *ctx = crypto_tfm_ctx(tfm);
24062306a36Sopenharmony_ci	struct otx_cpt_fc_ctx *fctx = &rctx->fctx;
24162306a36Sopenharmony_ci	int ivsize = crypto_skcipher_ivsize(stfm);
24262306a36Sopenharmony_ci	u32 start = req->cryptlen - ivsize;
24362306a36Sopenharmony_ci	gfp_t flags;
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci	flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
24662306a36Sopenharmony_ci			GFP_KERNEL : GFP_ATOMIC;
24762306a36Sopenharmony_ci	req_info->ctrl.s.dma_mode = OTX_CPT_DMA_GATHER_SCATTER;
24862306a36Sopenharmony_ci	req_info->ctrl.s.se_req = OTX_CPT_SE_CORE_REQ;
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	req_info->req.opcode.s.major = OTX_CPT_MAJOR_OP_FC |
25162306a36Sopenharmony_ci				DMA_MODE_FLAG(OTX_CPT_DMA_GATHER_SCATTER);
25262306a36Sopenharmony_ci	if (enc) {
25362306a36Sopenharmony_ci		req_info->req.opcode.s.minor = 2;
25462306a36Sopenharmony_ci	} else {
25562306a36Sopenharmony_ci		req_info->req.opcode.s.minor = 3;
25662306a36Sopenharmony_ci		if ((ctx->cipher_type == OTX_CPT_AES_CBC ||
25762306a36Sopenharmony_ci		    ctx->cipher_type == OTX_CPT_DES3_CBC) &&
25862306a36Sopenharmony_ci		    req->src == req->dst) {
25962306a36Sopenharmony_ci			req_info->iv_out = kmalloc(ivsize, flags);
26062306a36Sopenharmony_ci			if (!req_info->iv_out)
26162306a36Sopenharmony_ci				return -ENOMEM;
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci			scatterwalk_map_and_copy(req_info->iv_out, req->src,
26462306a36Sopenharmony_ci						 start, ivsize, 0);
26562306a36Sopenharmony_ci		}
26662306a36Sopenharmony_ci	}
26762306a36Sopenharmony_ci	/* Encryption data length */
26862306a36Sopenharmony_ci	req_info->req.param1 = req->cryptlen;
26962306a36Sopenharmony_ci	/* Authentication data length */
27062306a36Sopenharmony_ci	req_info->req.param2 = 0;
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	fctx->enc.enc_ctrl.e.enc_cipher = ctx->cipher_type;
27362306a36Sopenharmony_ci	fctx->enc.enc_ctrl.e.aes_key = ctx->key_type;
27462306a36Sopenharmony_ci	fctx->enc.enc_ctrl.e.iv_source = OTX_CPT_FROM_CPTR;
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	if (ctx->cipher_type == OTX_CPT_AES_XTS)
27762306a36Sopenharmony_ci		memcpy(fctx->enc.encr_key, ctx->enc_key, ctx->key_len * 2);
27862306a36Sopenharmony_ci	else
27962306a36Sopenharmony_ci		memcpy(fctx->enc.encr_key, ctx->enc_key, ctx->key_len);
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	memcpy(fctx->enc.encr_iv, req->iv, crypto_skcipher_ivsize(stfm));
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci	fctx->enc.enc_ctrl.flags = cpu_to_be64(fctx->enc.enc_ctrl.cflags);
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	/*
28662306a36Sopenharmony_ci	 * Storing  Packet Data Information in offset
28762306a36Sopenharmony_ci	 * Control Word First 8 bytes
28862306a36Sopenharmony_ci	 */
28962306a36Sopenharmony_ci	req_info->in[*argcnt].vptr = (u8 *)&rctx->ctrl_word;
29062306a36Sopenharmony_ci	req_info->in[*argcnt].size = CONTROL_WORD_LEN;
29162306a36Sopenharmony_ci	req_info->req.dlen += CONTROL_WORD_LEN;
29262306a36Sopenharmony_ci	++(*argcnt);
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	req_info->in[*argcnt].vptr = (u8 *)fctx;
29562306a36Sopenharmony_ci	req_info->in[*argcnt].size = sizeof(struct otx_cpt_fc_ctx);
29662306a36Sopenharmony_ci	req_info->req.dlen += sizeof(struct otx_cpt_fc_ctx);
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci	++(*argcnt);
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	return 0;
30162306a36Sopenharmony_ci}
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_cistatic inline u32 create_input_list(struct skcipher_request *req, u32 enc,
30462306a36Sopenharmony_ci				    u32 enc_iv_len)
30562306a36Sopenharmony_ci{
30662306a36Sopenharmony_ci	struct otx_cpt_req_ctx *rctx = skcipher_request_ctx_dma(req);
30762306a36Sopenharmony_ci	struct otx_cpt_req_info *req_info = &rctx->cpt_req;
30862306a36Sopenharmony_ci	u32 argcnt =  0;
30962306a36Sopenharmony_ci	int ret;
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci	ret = create_ctx_hdr(req, enc, &argcnt);
31262306a36Sopenharmony_ci	if (ret)
31362306a36Sopenharmony_ci		return ret;
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	update_input_data(req_info, req->src, req->cryptlen, &argcnt);
31662306a36Sopenharmony_ci	req_info->incnt = argcnt;
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	return 0;
31962306a36Sopenharmony_ci}
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_cistatic inline void create_output_list(struct skcipher_request *req,
32262306a36Sopenharmony_ci				      u32 enc_iv_len)
32362306a36Sopenharmony_ci{
32462306a36Sopenharmony_ci	struct otx_cpt_req_ctx *rctx = skcipher_request_ctx_dma(req);
32562306a36Sopenharmony_ci	struct otx_cpt_req_info *req_info = &rctx->cpt_req;
32662306a36Sopenharmony_ci	u32 argcnt = 0;
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci	/*
32962306a36Sopenharmony_ci	 * OUTPUT Buffer Processing
33062306a36Sopenharmony_ci	 * AES encryption/decryption output would be
33162306a36Sopenharmony_ci	 * received in the following format
33262306a36Sopenharmony_ci	 *
33362306a36Sopenharmony_ci	 * ------IV--------|------ENCRYPTED/DECRYPTED DATA-----|
33462306a36Sopenharmony_ci	 * [ 16 Bytes/     [   Request Enc/Dec/ DATA Len AES CBC ]
33562306a36Sopenharmony_ci	 */
33662306a36Sopenharmony_ci	update_output_data(req_info, req->dst, 0, req->cryptlen, &argcnt);
33762306a36Sopenharmony_ci	req_info->outcnt = argcnt;
33862306a36Sopenharmony_ci}
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_cistatic inline int cpt_enc_dec(struct skcipher_request *req, u32 enc)
34162306a36Sopenharmony_ci{
34262306a36Sopenharmony_ci	struct crypto_skcipher *stfm = crypto_skcipher_reqtfm(req);
34362306a36Sopenharmony_ci	struct otx_cpt_req_ctx *rctx = skcipher_request_ctx_dma(req);
34462306a36Sopenharmony_ci	struct otx_cpt_req_info *req_info = &rctx->cpt_req;
34562306a36Sopenharmony_ci	u32 enc_iv_len = crypto_skcipher_ivsize(stfm);
34662306a36Sopenharmony_ci	struct pci_dev *pdev;
34762306a36Sopenharmony_ci	int status, cpu_num;
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	/* Validate that request doesn't exceed maximum CPT supported size */
35062306a36Sopenharmony_ci	if (req->cryptlen > OTX_CPT_MAX_REQ_SIZE)
35162306a36Sopenharmony_ci		return -E2BIG;
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci	/* Clear control words */
35462306a36Sopenharmony_ci	rctx->ctrl_word.flags = 0;
35562306a36Sopenharmony_ci	rctx->fctx.enc.enc_ctrl.flags = 0;
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	status = create_input_list(req, enc, enc_iv_len);
35862306a36Sopenharmony_ci	if (status)
35962306a36Sopenharmony_ci		return status;
36062306a36Sopenharmony_ci	create_output_list(req, enc_iv_len);
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci	status = get_se_device(&pdev, &cpu_num);
36362306a36Sopenharmony_ci	if (status)
36462306a36Sopenharmony_ci		return status;
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci	req_info->callback = (void *)otx_cpt_skcipher_callback;
36762306a36Sopenharmony_ci	req_info->areq = &req->base;
36862306a36Sopenharmony_ci	req_info->req_type = OTX_CPT_ENC_DEC_REQ;
36962306a36Sopenharmony_ci	req_info->is_enc = enc;
37062306a36Sopenharmony_ci	req_info->is_trunc_hmac = false;
37162306a36Sopenharmony_ci	req_info->ctrl.s.grp = 0;
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci	/*
37462306a36Sopenharmony_ci	 * We perform an asynchronous send and once
37562306a36Sopenharmony_ci	 * the request is completed the driver would
37662306a36Sopenharmony_ci	 * intimate through registered call back functions
37762306a36Sopenharmony_ci	 */
37862306a36Sopenharmony_ci	status = otx_cpt_do_request(pdev, req_info, cpu_num);
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	return status;
38162306a36Sopenharmony_ci}
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_cistatic int otx_cpt_skcipher_encrypt(struct skcipher_request *req)
38462306a36Sopenharmony_ci{
38562306a36Sopenharmony_ci	return cpt_enc_dec(req, true);
38662306a36Sopenharmony_ci}
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_cistatic int otx_cpt_skcipher_decrypt(struct skcipher_request *req)
38962306a36Sopenharmony_ci{
39062306a36Sopenharmony_ci	return cpt_enc_dec(req, false);
39162306a36Sopenharmony_ci}
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_cistatic int otx_cpt_skcipher_xts_setkey(struct crypto_skcipher *tfm,
39462306a36Sopenharmony_ci				       const u8 *key, u32 keylen)
39562306a36Sopenharmony_ci{
39662306a36Sopenharmony_ci	struct otx_cpt_enc_ctx *ctx = crypto_skcipher_ctx(tfm);
39762306a36Sopenharmony_ci	const u8 *key2 = key + (keylen / 2);
39862306a36Sopenharmony_ci	const u8 *key1 = key;
39962306a36Sopenharmony_ci	int ret;
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	ret = xts_verify_key(tfm, key, keylen);
40262306a36Sopenharmony_ci	if (ret)
40362306a36Sopenharmony_ci		return ret;
40462306a36Sopenharmony_ci	ctx->key_len = keylen;
40562306a36Sopenharmony_ci	memcpy(ctx->enc_key, key1, keylen / 2);
40662306a36Sopenharmony_ci	memcpy(ctx->enc_key + KEY2_OFFSET, key2, keylen / 2);
40762306a36Sopenharmony_ci	ctx->cipher_type = OTX_CPT_AES_XTS;
40862306a36Sopenharmony_ci	switch (ctx->key_len) {
40962306a36Sopenharmony_ci	case 2 * AES_KEYSIZE_128:
41062306a36Sopenharmony_ci		ctx->key_type = OTX_CPT_AES_128_BIT;
41162306a36Sopenharmony_ci		break;
41262306a36Sopenharmony_ci	case 2 * AES_KEYSIZE_256:
41362306a36Sopenharmony_ci		ctx->key_type = OTX_CPT_AES_256_BIT;
41462306a36Sopenharmony_ci		break;
41562306a36Sopenharmony_ci	default:
41662306a36Sopenharmony_ci		return -EINVAL;
41762306a36Sopenharmony_ci	}
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci	return 0;
42062306a36Sopenharmony_ci}
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_cistatic int cpt_des_setkey(struct crypto_skcipher *tfm, const u8 *key,
42362306a36Sopenharmony_ci			  u32 keylen, u8 cipher_type)
42462306a36Sopenharmony_ci{
42562306a36Sopenharmony_ci	struct otx_cpt_enc_ctx *ctx = crypto_skcipher_ctx(tfm);
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci	if (keylen != DES3_EDE_KEY_SIZE)
42862306a36Sopenharmony_ci		return -EINVAL;
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci	ctx->key_len = keylen;
43162306a36Sopenharmony_ci	ctx->cipher_type = cipher_type;
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci	memcpy(ctx->enc_key, key, keylen);
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci	return 0;
43662306a36Sopenharmony_ci}
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_cistatic int cpt_aes_setkey(struct crypto_skcipher *tfm, const u8 *key,
43962306a36Sopenharmony_ci			  u32 keylen, u8 cipher_type)
44062306a36Sopenharmony_ci{
44162306a36Sopenharmony_ci	struct otx_cpt_enc_ctx *ctx = crypto_skcipher_ctx(tfm);
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci	switch (keylen) {
44462306a36Sopenharmony_ci	case AES_KEYSIZE_128:
44562306a36Sopenharmony_ci		ctx->key_type = OTX_CPT_AES_128_BIT;
44662306a36Sopenharmony_ci		break;
44762306a36Sopenharmony_ci	case AES_KEYSIZE_192:
44862306a36Sopenharmony_ci		ctx->key_type = OTX_CPT_AES_192_BIT;
44962306a36Sopenharmony_ci		break;
45062306a36Sopenharmony_ci	case AES_KEYSIZE_256:
45162306a36Sopenharmony_ci		ctx->key_type = OTX_CPT_AES_256_BIT;
45262306a36Sopenharmony_ci		break;
45362306a36Sopenharmony_ci	default:
45462306a36Sopenharmony_ci		return -EINVAL;
45562306a36Sopenharmony_ci	}
45662306a36Sopenharmony_ci	ctx->key_len = keylen;
45762306a36Sopenharmony_ci	ctx->cipher_type = cipher_type;
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci	memcpy(ctx->enc_key, key, keylen);
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci	return 0;
46262306a36Sopenharmony_ci}
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_cistatic int otx_cpt_skcipher_cbc_aes_setkey(struct crypto_skcipher *tfm,
46562306a36Sopenharmony_ci					   const u8 *key, u32 keylen)
46662306a36Sopenharmony_ci{
46762306a36Sopenharmony_ci	return cpt_aes_setkey(tfm, key, keylen, OTX_CPT_AES_CBC);
46862306a36Sopenharmony_ci}
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_cistatic int otx_cpt_skcipher_ecb_aes_setkey(struct crypto_skcipher *tfm,
47162306a36Sopenharmony_ci					   const u8 *key, u32 keylen)
47262306a36Sopenharmony_ci{
47362306a36Sopenharmony_ci	return cpt_aes_setkey(tfm, key, keylen, OTX_CPT_AES_ECB);
47462306a36Sopenharmony_ci}
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_cistatic int otx_cpt_skcipher_cfb_aes_setkey(struct crypto_skcipher *tfm,
47762306a36Sopenharmony_ci					   const u8 *key, u32 keylen)
47862306a36Sopenharmony_ci{
47962306a36Sopenharmony_ci	return cpt_aes_setkey(tfm, key, keylen, OTX_CPT_AES_CFB);
48062306a36Sopenharmony_ci}
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_cistatic int otx_cpt_skcipher_cbc_des3_setkey(struct crypto_skcipher *tfm,
48362306a36Sopenharmony_ci					    const u8 *key, u32 keylen)
48462306a36Sopenharmony_ci{
48562306a36Sopenharmony_ci	return cpt_des_setkey(tfm, key, keylen, OTX_CPT_DES3_CBC);
48662306a36Sopenharmony_ci}
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_cistatic int otx_cpt_skcipher_ecb_des3_setkey(struct crypto_skcipher *tfm,
48962306a36Sopenharmony_ci					    const u8 *key, u32 keylen)
49062306a36Sopenharmony_ci{
49162306a36Sopenharmony_ci	return cpt_des_setkey(tfm, key, keylen, OTX_CPT_DES3_ECB);
49262306a36Sopenharmony_ci}
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_cistatic int otx_cpt_enc_dec_init(struct crypto_skcipher *tfm)
49562306a36Sopenharmony_ci{
49662306a36Sopenharmony_ci	struct otx_cpt_enc_ctx *ctx = crypto_skcipher_ctx(tfm);
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ci	memset(ctx, 0, sizeof(*ctx));
49962306a36Sopenharmony_ci	/*
50062306a36Sopenharmony_ci	 * Additional memory for skcipher_request is
50162306a36Sopenharmony_ci	 * allocated since the cryptd daemon uses
50262306a36Sopenharmony_ci	 * this memory for request_ctx information
50362306a36Sopenharmony_ci	 */
50462306a36Sopenharmony_ci	crypto_skcipher_set_reqsize_dma(
50562306a36Sopenharmony_ci		tfm, sizeof(struct otx_cpt_req_ctx) +
50662306a36Sopenharmony_ci		     sizeof(struct skcipher_request));
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci	return 0;
50962306a36Sopenharmony_ci}
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_cistatic int cpt_aead_init(struct crypto_aead *tfm, u8 cipher_type, u8 mac_type)
51262306a36Sopenharmony_ci{
51362306a36Sopenharmony_ci	struct otx_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(tfm);
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	ctx->cipher_type = cipher_type;
51662306a36Sopenharmony_ci	ctx->mac_type = mac_type;
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci	/*
51962306a36Sopenharmony_ci	 * When selected cipher is NULL we use HMAC opcode instead of
52062306a36Sopenharmony_ci	 * FLEXICRYPTO opcode therefore we don't need to use HASH algorithms
52162306a36Sopenharmony_ci	 * for calculating ipad and opad
52262306a36Sopenharmony_ci	 */
52362306a36Sopenharmony_ci	if (ctx->cipher_type != OTX_CPT_CIPHER_NULL) {
52462306a36Sopenharmony_ci		switch (ctx->mac_type) {
52562306a36Sopenharmony_ci		case OTX_CPT_SHA1:
52662306a36Sopenharmony_ci			ctx->hashalg = crypto_alloc_shash("sha1", 0,
52762306a36Sopenharmony_ci							  CRYPTO_ALG_ASYNC);
52862306a36Sopenharmony_ci			if (IS_ERR(ctx->hashalg))
52962306a36Sopenharmony_ci				return PTR_ERR(ctx->hashalg);
53062306a36Sopenharmony_ci			break;
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci		case OTX_CPT_SHA256:
53362306a36Sopenharmony_ci			ctx->hashalg = crypto_alloc_shash("sha256", 0,
53462306a36Sopenharmony_ci							  CRYPTO_ALG_ASYNC);
53562306a36Sopenharmony_ci			if (IS_ERR(ctx->hashalg))
53662306a36Sopenharmony_ci				return PTR_ERR(ctx->hashalg);
53762306a36Sopenharmony_ci			break;
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci		case OTX_CPT_SHA384:
54062306a36Sopenharmony_ci			ctx->hashalg = crypto_alloc_shash("sha384", 0,
54162306a36Sopenharmony_ci							  CRYPTO_ALG_ASYNC);
54262306a36Sopenharmony_ci			if (IS_ERR(ctx->hashalg))
54362306a36Sopenharmony_ci				return PTR_ERR(ctx->hashalg);
54462306a36Sopenharmony_ci			break;
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci		case OTX_CPT_SHA512:
54762306a36Sopenharmony_ci			ctx->hashalg = crypto_alloc_shash("sha512", 0,
54862306a36Sopenharmony_ci							  CRYPTO_ALG_ASYNC);
54962306a36Sopenharmony_ci			if (IS_ERR(ctx->hashalg))
55062306a36Sopenharmony_ci				return PTR_ERR(ctx->hashalg);
55162306a36Sopenharmony_ci			break;
55262306a36Sopenharmony_ci		}
55362306a36Sopenharmony_ci	}
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci	crypto_aead_set_reqsize_dma(tfm, sizeof(struct otx_cpt_req_ctx));
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci	return 0;
55862306a36Sopenharmony_ci}
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_cistatic int otx_cpt_aead_cbc_aes_sha1_init(struct crypto_aead *tfm)
56162306a36Sopenharmony_ci{
56262306a36Sopenharmony_ci	return cpt_aead_init(tfm, OTX_CPT_AES_CBC, OTX_CPT_SHA1);
56362306a36Sopenharmony_ci}
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_cistatic int otx_cpt_aead_cbc_aes_sha256_init(struct crypto_aead *tfm)
56662306a36Sopenharmony_ci{
56762306a36Sopenharmony_ci	return cpt_aead_init(tfm, OTX_CPT_AES_CBC, OTX_CPT_SHA256);
56862306a36Sopenharmony_ci}
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_cistatic int otx_cpt_aead_cbc_aes_sha384_init(struct crypto_aead *tfm)
57162306a36Sopenharmony_ci{
57262306a36Sopenharmony_ci	return cpt_aead_init(tfm, OTX_CPT_AES_CBC, OTX_CPT_SHA384);
57362306a36Sopenharmony_ci}
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_cistatic int otx_cpt_aead_cbc_aes_sha512_init(struct crypto_aead *tfm)
57662306a36Sopenharmony_ci{
57762306a36Sopenharmony_ci	return cpt_aead_init(tfm, OTX_CPT_AES_CBC, OTX_CPT_SHA512);
57862306a36Sopenharmony_ci}
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_cistatic int otx_cpt_aead_ecb_null_sha1_init(struct crypto_aead *tfm)
58162306a36Sopenharmony_ci{
58262306a36Sopenharmony_ci	return cpt_aead_init(tfm, OTX_CPT_CIPHER_NULL, OTX_CPT_SHA1);
58362306a36Sopenharmony_ci}
58462306a36Sopenharmony_ci
58562306a36Sopenharmony_cistatic int otx_cpt_aead_ecb_null_sha256_init(struct crypto_aead *tfm)
58662306a36Sopenharmony_ci{
58762306a36Sopenharmony_ci	return cpt_aead_init(tfm, OTX_CPT_CIPHER_NULL, OTX_CPT_SHA256);
58862306a36Sopenharmony_ci}
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_cistatic int otx_cpt_aead_ecb_null_sha384_init(struct crypto_aead *tfm)
59162306a36Sopenharmony_ci{
59262306a36Sopenharmony_ci	return cpt_aead_init(tfm, OTX_CPT_CIPHER_NULL, OTX_CPT_SHA384);
59362306a36Sopenharmony_ci}
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_cistatic int otx_cpt_aead_ecb_null_sha512_init(struct crypto_aead *tfm)
59662306a36Sopenharmony_ci{
59762306a36Sopenharmony_ci	return cpt_aead_init(tfm, OTX_CPT_CIPHER_NULL, OTX_CPT_SHA512);
59862306a36Sopenharmony_ci}
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_cistatic int otx_cpt_aead_gcm_aes_init(struct crypto_aead *tfm)
60162306a36Sopenharmony_ci{
60262306a36Sopenharmony_ci	return cpt_aead_init(tfm, OTX_CPT_AES_GCM, OTX_CPT_MAC_NULL);
60362306a36Sopenharmony_ci}
60462306a36Sopenharmony_ci
60562306a36Sopenharmony_cistatic void otx_cpt_aead_exit(struct crypto_aead *tfm)
60662306a36Sopenharmony_ci{
60762306a36Sopenharmony_ci	struct otx_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(tfm);
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci	kfree(ctx->ipad);
61062306a36Sopenharmony_ci	kfree(ctx->opad);
61162306a36Sopenharmony_ci	if (ctx->hashalg)
61262306a36Sopenharmony_ci		crypto_free_shash(ctx->hashalg);
61362306a36Sopenharmony_ci	kfree(ctx->sdesc);
61462306a36Sopenharmony_ci}
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ci/*
61762306a36Sopenharmony_ci * This is the Integrity Check Value validation (aka the authentication tag
61862306a36Sopenharmony_ci * length)
61962306a36Sopenharmony_ci */
62062306a36Sopenharmony_cistatic int otx_cpt_aead_set_authsize(struct crypto_aead *tfm,
62162306a36Sopenharmony_ci				     unsigned int authsize)
62262306a36Sopenharmony_ci{
62362306a36Sopenharmony_ci	struct otx_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(tfm);
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_ci	switch (ctx->mac_type) {
62662306a36Sopenharmony_ci	case OTX_CPT_SHA1:
62762306a36Sopenharmony_ci		if (authsize != SHA1_DIGEST_SIZE &&
62862306a36Sopenharmony_ci		    authsize != SHA1_TRUNC_DIGEST_SIZE)
62962306a36Sopenharmony_ci			return -EINVAL;
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_ci		if (authsize == SHA1_TRUNC_DIGEST_SIZE)
63262306a36Sopenharmony_ci			ctx->is_trunc_hmac = true;
63362306a36Sopenharmony_ci		break;
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci	case OTX_CPT_SHA256:
63662306a36Sopenharmony_ci		if (authsize != SHA256_DIGEST_SIZE &&
63762306a36Sopenharmony_ci		    authsize != SHA256_TRUNC_DIGEST_SIZE)
63862306a36Sopenharmony_ci			return -EINVAL;
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci		if (authsize == SHA256_TRUNC_DIGEST_SIZE)
64162306a36Sopenharmony_ci			ctx->is_trunc_hmac = true;
64262306a36Sopenharmony_ci		break;
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	case OTX_CPT_SHA384:
64562306a36Sopenharmony_ci		if (authsize != SHA384_DIGEST_SIZE &&
64662306a36Sopenharmony_ci		    authsize != SHA384_TRUNC_DIGEST_SIZE)
64762306a36Sopenharmony_ci			return -EINVAL;
64862306a36Sopenharmony_ci
64962306a36Sopenharmony_ci		if (authsize == SHA384_TRUNC_DIGEST_SIZE)
65062306a36Sopenharmony_ci			ctx->is_trunc_hmac = true;
65162306a36Sopenharmony_ci		break;
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci	case OTX_CPT_SHA512:
65462306a36Sopenharmony_ci		if (authsize != SHA512_DIGEST_SIZE &&
65562306a36Sopenharmony_ci		    authsize != SHA512_TRUNC_DIGEST_SIZE)
65662306a36Sopenharmony_ci			return -EINVAL;
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_ci		if (authsize == SHA512_TRUNC_DIGEST_SIZE)
65962306a36Sopenharmony_ci			ctx->is_trunc_hmac = true;
66062306a36Sopenharmony_ci		break;
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_ci	case OTX_CPT_MAC_NULL:
66362306a36Sopenharmony_ci		if (ctx->cipher_type == OTX_CPT_AES_GCM) {
66462306a36Sopenharmony_ci			if (authsize != AES_GCM_ICV_SIZE)
66562306a36Sopenharmony_ci				return -EINVAL;
66662306a36Sopenharmony_ci		} else
66762306a36Sopenharmony_ci			return -EINVAL;
66862306a36Sopenharmony_ci		break;
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_ci	default:
67162306a36Sopenharmony_ci		return -EINVAL;
67262306a36Sopenharmony_ci	}
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_ci	tfm->authsize = authsize;
67562306a36Sopenharmony_ci	return 0;
67662306a36Sopenharmony_ci}
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_cistatic struct otx_cpt_sdesc *alloc_sdesc(struct crypto_shash *alg)
67962306a36Sopenharmony_ci{
68062306a36Sopenharmony_ci	struct otx_cpt_sdesc *sdesc;
68162306a36Sopenharmony_ci	int size;
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_ci	size = sizeof(struct shash_desc) + crypto_shash_descsize(alg);
68462306a36Sopenharmony_ci	sdesc = kmalloc(size, GFP_KERNEL);
68562306a36Sopenharmony_ci	if (!sdesc)
68662306a36Sopenharmony_ci		return NULL;
68762306a36Sopenharmony_ci
68862306a36Sopenharmony_ci	sdesc->shash.tfm = alg;
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_ci	return sdesc;
69162306a36Sopenharmony_ci}
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_cistatic inline void swap_data32(void *buf, u32 len)
69462306a36Sopenharmony_ci{
69562306a36Sopenharmony_ci	cpu_to_be32_array(buf, buf, len / 4);
69662306a36Sopenharmony_ci}
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_cistatic inline void swap_data64(void *buf, u32 len)
69962306a36Sopenharmony_ci{
70062306a36Sopenharmony_ci	__be64 *dst = buf;
70162306a36Sopenharmony_ci	u64 *src = buf;
70262306a36Sopenharmony_ci	int i = 0;
70362306a36Sopenharmony_ci
70462306a36Sopenharmony_ci	for (i = 0 ; i < len / 8; i++, src++, dst++)
70562306a36Sopenharmony_ci		*dst = cpu_to_be64p(src);
70662306a36Sopenharmony_ci}
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_cistatic int copy_pad(u8 mac_type, u8 *out_pad, u8 *in_pad)
70962306a36Sopenharmony_ci{
71062306a36Sopenharmony_ci	struct sha512_state *sha512;
71162306a36Sopenharmony_ci	struct sha256_state *sha256;
71262306a36Sopenharmony_ci	struct sha1_state *sha1;
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_ci	switch (mac_type) {
71562306a36Sopenharmony_ci	case OTX_CPT_SHA1:
71662306a36Sopenharmony_ci		sha1 = (struct sha1_state *) in_pad;
71762306a36Sopenharmony_ci		swap_data32(sha1->state, SHA1_DIGEST_SIZE);
71862306a36Sopenharmony_ci		memcpy(out_pad, &sha1->state, SHA1_DIGEST_SIZE);
71962306a36Sopenharmony_ci		break;
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_ci	case OTX_CPT_SHA256:
72262306a36Sopenharmony_ci		sha256 = (struct sha256_state *) in_pad;
72362306a36Sopenharmony_ci		swap_data32(sha256->state, SHA256_DIGEST_SIZE);
72462306a36Sopenharmony_ci		memcpy(out_pad, &sha256->state, SHA256_DIGEST_SIZE);
72562306a36Sopenharmony_ci		break;
72662306a36Sopenharmony_ci
72762306a36Sopenharmony_ci	case OTX_CPT_SHA384:
72862306a36Sopenharmony_ci	case OTX_CPT_SHA512:
72962306a36Sopenharmony_ci		sha512 = (struct sha512_state *) in_pad;
73062306a36Sopenharmony_ci		swap_data64(sha512->state, SHA512_DIGEST_SIZE);
73162306a36Sopenharmony_ci		memcpy(out_pad, &sha512->state, SHA512_DIGEST_SIZE);
73262306a36Sopenharmony_ci		break;
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_ci	default:
73562306a36Sopenharmony_ci		return -EINVAL;
73662306a36Sopenharmony_ci	}
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci	return 0;
73962306a36Sopenharmony_ci}
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_cistatic int aead_hmac_init(struct crypto_aead *cipher)
74262306a36Sopenharmony_ci{
74362306a36Sopenharmony_ci	struct otx_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(cipher);
74462306a36Sopenharmony_ci	int state_size = crypto_shash_statesize(ctx->hashalg);
74562306a36Sopenharmony_ci	int ds = crypto_shash_digestsize(ctx->hashalg);
74662306a36Sopenharmony_ci	int bs = crypto_shash_blocksize(ctx->hashalg);
74762306a36Sopenharmony_ci	int authkeylen = ctx->auth_key_len;
74862306a36Sopenharmony_ci	u8 *ipad = NULL, *opad = NULL;
74962306a36Sopenharmony_ci	int ret = 0, icount = 0;
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci	ctx->sdesc = alloc_sdesc(ctx->hashalg);
75262306a36Sopenharmony_ci	if (!ctx->sdesc)
75362306a36Sopenharmony_ci		return -ENOMEM;
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_ci	ctx->ipad = kzalloc(bs, GFP_KERNEL);
75662306a36Sopenharmony_ci	if (!ctx->ipad) {
75762306a36Sopenharmony_ci		ret = -ENOMEM;
75862306a36Sopenharmony_ci		goto calc_fail;
75962306a36Sopenharmony_ci	}
76062306a36Sopenharmony_ci
76162306a36Sopenharmony_ci	ctx->opad = kzalloc(bs, GFP_KERNEL);
76262306a36Sopenharmony_ci	if (!ctx->opad) {
76362306a36Sopenharmony_ci		ret = -ENOMEM;
76462306a36Sopenharmony_ci		goto calc_fail;
76562306a36Sopenharmony_ci	}
76662306a36Sopenharmony_ci
76762306a36Sopenharmony_ci	ipad = kzalloc(state_size, GFP_KERNEL);
76862306a36Sopenharmony_ci	if (!ipad) {
76962306a36Sopenharmony_ci		ret = -ENOMEM;
77062306a36Sopenharmony_ci		goto calc_fail;
77162306a36Sopenharmony_ci	}
77262306a36Sopenharmony_ci
77362306a36Sopenharmony_ci	opad = kzalloc(state_size, GFP_KERNEL);
77462306a36Sopenharmony_ci	if (!opad) {
77562306a36Sopenharmony_ci		ret = -ENOMEM;
77662306a36Sopenharmony_ci		goto calc_fail;
77762306a36Sopenharmony_ci	}
77862306a36Sopenharmony_ci
77962306a36Sopenharmony_ci	if (authkeylen > bs) {
78062306a36Sopenharmony_ci		ret = crypto_shash_digest(&ctx->sdesc->shash, ctx->key,
78162306a36Sopenharmony_ci					  authkeylen, ipad);
78262306a36Sopenharmony_ci		if (ret)
78362306a36Sopenharmony_ci			goto calc_fail;
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_ci		authkeylen = ds;
78662306a36Sopenharmony_ci	} else {
78762306a36Sopenharmony_ci		memcpy(ipad, ctx->key, authkeylen);
78862306a36Sopenharmony_ci	}
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_ci	memset(ipad + authkeylen, 0, bs - authkeylen);
79162306a36Sopenharmony_ci	memcpy(opad, ipad, bs);
79262306a36Sopenharmony_ci
79362306a36Sopenharmony_ci	for (icount = 0; icount < bs; icount++) {
79462306a36Sopenharmony_ci		ipad[icount] ^= 0x36;
79562306a36Sopenharmony_ci		opad[icount] ^= 0x5c;
79662306a36Sopenharmony_ci	}
79762306a36Sopenharmony_ci
79862306a36Sopenharmony_ci	/*
79962306a36Sopenharmony_ci	 * Partial Hash calculated from the software
80062306a36Sopenharmony_ci	 * algorithm is retrieved for IPAD & OPAD
80162306a36Sopenharmony_ci	 */
80262306a36Sopenharmony_ci
80362306a36Sopenharmony_ci	/* IPAD Calculation */
80462306a36Sopenharmony_ci	crypto_shash_init(&ctx->sdesc->shash);
80562306a36Sopenharmony_ci	crypto_shash_update(&ctx->sdesc->shash, ipad, bs);
80662306a36Sopenharmony_ci	crypto_shash_export(&ctx->sdesc->shash, ipad);
80762306a36Sopenharmony_ci	ret = copy_pad(ctx->mac_type, ctx->ipad, ipad);
80862306a36Sopenharmony_ci	if (ret)
80962306a36Sopenharmony_ci		goto calc_fail;
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_ci	/* OPAD Calculation */
81262306a36Sopenharmony_ci	crypto_shash_init(&ctx->sdesc->shash);
81362306a36Sopenharmony_ci	crypto_shash_update(&ctx->sdesc->shash, opad, bs);
81462306a36Sopenharmony_ci	crypto_shash_export(&ctx->sdesc->shash, opad);
81562306a36Sopenharmony_ci	ret = copy_pad(ctx->mac_type, ctx->opad, opad);
81662306a36Sopenharmony_ci	if (ret)
81762306a36Sopenharmony_ci		goto calc_fail;
81862306a36Sopenharmony_ci
81962306a36Sopenharmony_ci	kfree(ipad);
82062306a36Sopenharmony_ci	kfree(opad);
82162306a36Sopenharmony_ci
82262306a36Sopenharmony_ci	return 0;
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_cicalc_fail:
82562306a36Sopenharmony_ci	kfree(ctx->ipad);
82662306a36Sopenharmony_ci	ctx->ipad = NULL;
82762306a36Sopenharmony_ci	kfree(ctx->opad);
82862306a36Sopenharmony_ci	ctx->opad = NULL;
82962306a36Sopenharmony_ci	kfree(ipad);
83062306a36Sopenharmony_ci	kfree(opad);
83162306a36Sopenharmony_ci	kfree(ctx->sdesc);
83262306a36Sopenharmony_ci	ctx->sdesc = NULL;
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci	return ret;
83562306a36Sopenharmony_ci}
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_cistatic int otx_cpt_aead_cbc_aes_sha_setkey(struct crypto_aead *cipher,
83862306a36Sopenharmony_ci					   const unsigned char *key,
83962306a36Sopenharmony_ci					   unsigned int keylen)
84062306a36Sopenharmony_ci{
84162306a36Sopenharmony_ci	struct otx_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(cipher);
84262306a36Sopenharmony_ci	struct crypto_authenc_key_param *param;
84362306a36Sopenharmony_ci	int enckeylen = 0, authkeylen = 0;
84462306a36Sopenharmony_ci	struct rtattr *rta = (void *)key;
84562306a36Sopenharmony_ci	int status = -EINVAL;
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_ci	if (!RTA_OK(rta, keylen))
84862306a36Sopenharmony_ci		goto badkey;
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_ci	if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
85162306a36Sopenharmony_ci		goto badkey;
85262306a36Sopenharmony_ci
85362306a36Sopenharmony_ci	if (RTA_PAYLOAD(rta) < sizeof(*param))
85462306a36Sopenharmony_ci		goto badkey;
85562306a36Sopenharmony_ci
85662306a36Sopenharmony_ci	param = RTA_DATA(rta);
85762306a36Sopenharmony_ci	enckeylen = be32_to_cpu(param->enckeylen);
85862306a36Sopenharmony_ci	key += RTA_ALIGN(rta->rta_len);
85962306a36Sopenharmony_ci	keylen -= RTA_ALIGN(rta->rta_len);
86062306a36Sopenharmony_ci	if (keylen < enckeylen)
86162306a36Sopenharmony_ci		goto badkey;
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_ci	if (keylen > OTX_CPT_MAX_KEY_SIZE)
86462306a36Sopenharmony_ci		goto badkey;
86562306a36Sopenharmony_ci
86662306a36Sopenharmony_ci	authkeylen = keylen - enckeylen;
86762306a36Sopenharmony_ci	memcpy(ctx->key, key, keylen);
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_ci	switch (enckeylen) {
87062306a36Sopenharmony_ci	case AES_KEYSIZE_128:
87162306a36Sopenharmony_ci		ctx->key_type = OTX_CPT_AES_128_BIT;
87262306a36Sopenharmony_ci		break;
87362306a36Sopenharmony_ci	case AES_KEYSIZE_192:
87462306a36Sopenharmony_ci		ctx->key_type = OTX_CPT_AES_192_BIT;
87562306a36Sopenharmony_ci		break;
87662306a36Sopenharmony_ci	case AES_KEYSIZE_256:
87762306a36Sopenharmony_ci		ctx->key_type = OTX_CPT_AES_256_BIT;
87862306a36Sopenharmony_ci		break;
87962306a36Sopenharmony_ci	default:
88062306a36Sopenharmony_ci		/* Invalid key length */
88162306a36Sopenharmony_ci		goto badkey;
88262306a36Sopenharmony_ci	}
88362306a36Sopenharmony_ci
88462306a36Sopenharmony_ci	ctx->enc_key_len = enckeylen;
88562306a36Sopenharmony_ci	ctx->auth_key_len = authkeylen;
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_ci	status = aead_hmac_init(cipher);
88862306a36Sopenharmony_ci	if (status)
88962306a36Sopenharmony_ci		goto badkey;
89062306a36Sopenharmony_ci
89162306a36Sopenharmony_ci	return 0;
89262306a36Sopenharmony_cibadkey:
89362306a36Sopenharmony_ci	return status;
89462306a36Sopenharmony_ci}
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_cistatic int otx_cpt_aead_ecb_null_sha_setkey(struct crypto_aead *cipher,
89762306a36Sopenharmony_ci					    const unsigned char *key,
89862306a36Sopenharmony_ci					    unsigned int keylen)
89962306a36Sopenharmony_ci{
90062306a36Sopenharmony_ci	struct otx_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(cipher);
90162306a36Sopenharmony_ci	struct crypto_authenc_key_param *param;
90262306a36Sopenharmony_ci	struct rtattr *rta = (void *)key;
90362306a36Sopenharmony_ci	int enckeylen = 0;
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci	if (!RTA_OK(rta, keylen))
90662306a36Sopenharmony_ci		goto badkey;
90762306a36Sopenharmony_ci
90862306a36Sopenharmony_ci	if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
90962306a36Sopenharmony_ci		goto badkey;
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_ci	if (RTA_PAYLOAD(rta) < sizeof(*param))
91262306a36Sopenharmony_ci		goto badkey;
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_ci	param = RTA_DATA(rta);
91562306a36Sopenharmony_ci	enckeylen = be32_to_cpu(param->enckeylen);
91662306a36Sopenharmony_ci	key += RTA_ALIGN(rta->rta_len);
91762306a36Sopenharmony_ci	keylen -= RTA_ALIGN(rta->rta_len);
91862306a36Sopenharmony_ci	if (enckeylen != 0)
91962306a36Sopenharmony_ci		goto badkey;
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_ci	if (keylen > OTX_CPT_MAX_KEY_SIZE)
92262306a36Sopenharmony_ci		goto badkey;
92362306a36Sopenharmony_ci
92462306a36Sopenharmony_ci	memcpy(ctx->key, key, keylen);
92562306a36Sopenharmony_ci	ctx->enc_key_len = enckeylen;
92662306a36Sopenharmony_ci	ctx->auth_key_len = keylen;
92762306a36Sopenharmony_ci	return 0;
92862306a36Sopenharmony_cibadkey:
92962306a36Sopenharmony_ci	return -EINVAL;
93062306a36Sopenharmony_ci}
93162306a36Sopenharmony_ci
93262306a36Sopenharmony_cistatic int otx_cpt_aead_gcm_aes_setkey(struct crypto_aead *cipher,
93362306a36Sopenharmony_ci				       const unsigned char *key,
93462306a36Sopenharmony_ci				       unsigned int keylen)
93562306a36Sopenharmony_ci{
93662306a36Sopenharmony_ci	struct otx_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(cipher);
93762306a36Sopenharmony_ci
93862306a36Sopenharmony_ci	/*
93962306a36Sopenharmony_ci	 * For aes gcm we expect to get encryption key (16, 24, 32 bytes)
94062306a36Sopenharmony_ci	 * and salt (4 bytes)
94162306a36Sopenharmony_ci	 */
94262306a36Sopenharmony_ci	switch (keylen) {
94362306a36Sopenharmony_ci	case AES_KEYSIZE_128 + AES_GCM_SALT_SIZE:
94462306a36Sopenharmony_ci		ctx->key_type = OTX_CPT_AES_128_BIT;
94562306a36Sopenharmony_ci		ctx->enc_key_len = AES_KEYSIZE_128;
94662306a36Sopenharmony_ci		break;
94762306a36Sopenharmony_ci	case AES_KEYSIZE_192 + AES_GCM_SALT_SIZE:
94862306a36Sopenharmony_ci		ctx->key_type = OTX_CPT_AES_192_BIT;
94962306a36Sopenharmony_ci		ctx->enc_key_len = AES_KEYSIZE_192;
95062306a36Sopenharmony_ci		break;
95162306a36Sopenharmony_ci	case AES_KEYSIZE_256 + AES_GCM_SALT_SIZE:
95262306a36Sopenharmony_ci		ctx->key_type = OTX_CPT_AES_256_BIT;
95362306a36Sopenharmony_ci		ctx->enc_key_len = AES_KEYSIZE_256;
95462306a36Sopenharmony_ci		break;
95562306a36Sopenharmony_ci	default:
95662306a36Sopenharmony_ci		/* Invalid key and salt length */
95762306a36Sopenharmony_ci		return -EINVAL;
95862306a36Sopenharmony_ci	}
95962306a36Sopenharmony_ci
96062306a36Sopenharmony_ci	/* Store encryption key and salt */
96162306a36Sopenharmony_ci	memcpy(ctx->key, key, keylen);
96262306a36Sopenharmony_ci
96362306a36Sopenharmony_ci	return 0;
96462306a36Sopenharmony_ci}
96562306a36Sopenharmony_ci
96662306a36Sopenharmony_cistatic inline u32 create_aead_ctx_hdr(struct aead_request *req, u32 enc,
96762306a36Sopenharmony_ci				      u32 *argcnt)
96862306a36Sopenharmony_ci{
96962306a36Sopenharmony_ci	struct otx_cpt_req_ctx *rctx = aead_request_ctx_dma(req);
97062306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
97162306a36Sopenharmony_ci	struct otx_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(tfm);
97262306a36Sopenharmony_ci	struct otx_cpt_req_info *req_info = &rctx->cpt_req;
97362306a36Sopenharmony_ci	struct otx_cpt_fc_ctx *fctx = &rctx->fctx;
97462306a36Sopenharmony_ci	int mac_len = crypto_aead_authsize(tfm);
97562306a36Sopenharmony_ci	int ds;
97662306a36Sopenharmony_ci
97762306a36Sopenharmony_ci	rctx->ctrl_word.e.enc_data_offset = req->assoclen;
97862306a36Sopenharmony_ci
97962306a36Sopenharmony_ci	switch (ctx->cipher_type) {
98062306a36Sopenharmony_ci	case OTX_CPT_AES_CBC:
98162306a36Sopenharmony_ci		fctx->enc.enc_ctrl.e.iv_source = OTX_CPT_FROM_CPTR;
98262306a36Sopenharmony_ci		/* Copy encryption key to context */
98362306a36Sopenharmony_ci		memcpy(fctx->enc.encr_key, ctx->key + ctx->auth_key_len,
98462306a36Sopenharmony_ci		       ctx->enc_key_len);
98562306a36Sopenharmony_ci		/* Copy IV to context */
98662306a36Sopenharmony_ci		memcpy(fctx->enc.encr_iv, req->iv, crypto_aead_ivsize(tfm));
98762306a36Sopenharmony_ci
98862306a36Sopenharmony_ci		ds = crypto_shash_digestsize(ctx->hashalg);
98962306a36Sopenharmony_ci		if (ctx->mac_type == OTX_CPT_SHA384)
99062306a36Sopenharmony_ci			ds = SHA512_DIGEST_SIZE;
99162306a36Sopenharmony_ci		if (ctx->ipad)
99262306a36Sopenharmony_ci			memcpy(fctx->hmac.e.ipad, ctx->ipad, ds);
99362306a36Sopenharmony_ci		if (ctx->opad)
99462306a36Sopenharmony_ci			memcpy(fctx->hmac.e.opad, ctx->opad, ds);
99562306a36Sopenharmony_ci		break;
99662306a36Sopenharmony_ci
99762306a36Sopenharmony_ci	case OTX_CPT_AES_GCM:
99862306a36Sopenharmony_ci		fctx->enc.enc_ctrl.e.iv_source = OTX_CPT_FROM_DPTR;
99962306a36Sopenharmony_ci		/* Copy encryption key to context */
100062306a36Sopenharmony_ci		memcpy(fctx->enc.encr_key, ctx->key, ctx->enc_key_len);
100162306a36Sopenharmony_ci		/* Copy salt to context */
100262306a36Sopenharmony_ci		memcpy(fctx->enc.encr_iv, ctx->key + ctx->enc_key_len,
100362306a36Sopenharmony_ci		       AES_GCM_SALT_SIZE);
100462306a36Sopenharmony_ci
100562306a36Sopenharmony_ci		rctx->ctrl_word.e.iv_offset = req->assoclen - AES_GCM_IV_OFFSET;
100662306a36Sopenharmony_ci		break;
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_ci	default:
100962306a36Sopenharmony_ci		/* Unknown cipher type */
101062306a36Sopenharmony_ci		return -EINVAL;
101162306a36Sopenharmony_ci	}
101262306a36Sopenharmony_ci	rctx->ctrl_word.flags = cpu_to_be64(rctx->ctrl_word.cflags);
101362306a36Sopenharmony_ci
101462306a36Sopenharmony_ci	req_info->ctrl.s.dma_mode = OTX_CPT_DMA_GATHER_SCATTER;
101562306a36Sopenharmony_ci	req_info->ctrl.s.se_req = OTX_CPT_SE_CORE_REQ;
101662306a36Sopenharmony_ci	req_info->req.opcode.s.major = OTX_CPT_MAJOR_OP_FC |
101762306a36Sopenharmony_ci				 DMA_MODE_FLAG(OTX_CPT_DMA_GATHER_SCATTER);
101862306a36Sopenharmony_ci	if (enc) {
101962306a36Sopenharmony_ci		req_info->req.opcode.s.minor = 2;
102062306a36Sopenharmony_ci		req_info->req.param1 = req->cryptlen;
102162306a36Sopenharmony_ci		req_info->req.param2 = req->cryptlen + req->assoclen;
102262306a36Sopenharmony_ci	} else {
102362306a36Sopenharmony_ci		req_info->req.opcode.s.minor = 3;
102462306a36Sopenharmony_ci		req_info->req.param1 = req->cryptlen - mac_len;
102562306a36Sopenharmony_ci		req_info->req.param2 = req->cryptlen + req->assoclen - mac_len;
102662306a36Sopenharmony_ci	}
102762306a36Sopenharmony_ci
102862306a36Sopenharmony_ci	fctx->enc.enc_ctrl.e.enc_cipher = ctx->cipher_type;
102962306a36Sopenharmony_ci	fctx->enc.enc_ctrl.e.aes_key = ctx->key_type;
103062306a36Sopenharmony_ci	fctx->enc.enc_ctrl.e.mac_type = ctx->mac_type;
103162306a36Sopenharmony_ci	fctx->enc.enc_ctrl.e.mac_len = mac_len;
103262306a36Sopenharmony_ci	fctx->enc.enc_ctrl.flags = cpu_to_be64(fctx->enc.enc_ctrl.cflags);
103362306a36Sopenharmony_ci
103462306a36Sopenharmony_ci	/*
103562306a36Sopenharmony_ci	 * Storing Packet Data Information in offset
103662306a36Sopenharmony_ci	 * Control Word First 8 bytes
103762306a36Sopenharmony_ci	 */
103862306a36Sopenharmony_ci	req_info->in[*argcnt].vptr = (u8 *)&rctx->ctrl_word;
103962306a36Sopenharmony_ci	req_info->in[*argcnt].size = CONTROL_WORD_LEN;
104062306a36Sopenharmony_ci	req_info->req.dlen += CONTROL_WORD_LEN;
104162306a36Sopenharmony_ci	++(*argcnt);
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_ci	req_info->in[*argcnt].vptr = (u8 *)fctx;
104462306a36Sopenharmony_ci	req_info->in[*argcnt].size = sizeof(struct otx_cpt_fc_ctx);
104562306a36Sopenharmony_ci	req_info->req.dlen += sizeof(struct otx_cpt_fc_ctx);
104662306a36Sopenharmony_ci	++(*argcnt);
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_ci	return 0;
104962306a36Sopenharmony_ci}
105062306a36Sopenharmony_ci
105162306a36Sopenharmony_cistatic inline u32 create_hmac_ctx_hdr(struct aead_request *req, u32 *argcnt,
105262306a36Sopenharmony_ci				      u32 enc)
105362306a36Sopenharmony_ci{
105462306a36Sopenharmony_ci	struct otx_cpt_req_ctx *rctx = aead_request_ctx_dma(req);
105562306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
105662306a36Sopenharmony_ci	struct otx_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(tfm);
105762306a36Sopenharmony_ci	struct otx_cpt_req_info *req_info = &rctx->cpt_req;
105862306a36Sopenharmony_ci
105962306a36Sopenharmony_ci	req_info->ctrl.s.dma_mode = OTX_CPT_DMA_GATHER_SCATTER;
106062306a36Sopenharmony_ci	req_info->ctrl.s.se_req = OTX_CPT_SE_CORE_REQ;
106162306a36Sopenharmony_ci	req_info->req.opcode.s.major = OTX_CPT_MAJOR_OP_HMAC |
106262306a36Sopenharmony_ci				 DMA_MODE_FLAG(OTX_CPT_DMA_GATHER_SCATTER);
106362306a36Sopenharmony_ci	req_info->is_trunc_hmac = ctx->is_trunc_hmac;
106462306a36Sopenharmony_ci
106562306a36Sopenharmony_ci	req_info->req.opcode.s.minor = 0;
106662306a36Sopenharmony_ci	req_info->req.param1 = ctx->auth_key_len;
106762306a36Sopenharmony_ci	req_info->req.param2 = ctx->mac_type << 8;
106862306a36Sopenharmony_ci
106962306a36Sopenharmony_ci	/* Add authentication key */
107062306a36Sopenharmony_ci	req_info->in[*argcnt].vptr = ctx->key;
107162306a36Sopenharmony_ci	req_info->in[*argcnt].size = round_up(ctx->auth_key_len, 8);
107262306a36Sopenharmony_ci	req_info->req.dlen += round_up(ctx->auth_key_len, 8);
107362306a36Sopenharmony_ci	++(*argcnt);
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ci	return 0;
107662306a36Sopenharmony_ci}
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_cistatic inline u32 create_aead_input_list(struct aead_request *req, u32 enc)
107962306a36Sopenharmony_ci{
108062306a36Sopenharmony_ci	struct otx_cpt_req_ctx *rctx = aead_request_ctx_dma(req);
108162306a36Sopenharmony_ci	struct otx_cpt_req_info *req_info = &rctx->cpt_req;
108262306a36Sopenharmony_ci	u32 inputlen =  req->cryptlen + req->assoclen;
108362306a36Sopenharmony_ci	u32 status, argcnt = 0;
108462306a36Sopenharmony_ci
108562306a36Sopenharmony_ci	status = create_aead_ctx_hdr(req, enc, &argcnt);
108662306a36Sopenharmony_ci	if (status)
108762306a36Sopenharmony_ci		return status;
108862306a36Sopenharmony_ci	update_input_data(req_info, req->src, inputlen, &argcnt);
108962306a36Sopenharmony_ci	req_info->incnt = argcnt;
109062306a36Sopenharmony_ci
109162306a36Sopenharmony_ci	return 0;
109262306a36Sopenharmony_ci}
109362306a36Sopenharmony_ci
109462306a36Sopenharmony_cistatic inline u32 create_aead_output_list(struct aead_request *req, u32 enc,
109562306a36Sopenharmony_ci					  u32 mac_len)
109662306a36Sopenharmony_ci{
109762306a36Sopenharmony_ci	struct otx_cpt_req_ctx *rctx = aead_request_ctx_dma(req);
109862306a36Sopenharmony_ci	struct otx_cpt_req_info *req_info =  &rctx->cpt_req;
109962306a36Sopenharmony_ci	u32 argcnt = 0, outputlen = 0;
110062306a36Sopenharmony_ci
110162306a36Sopenharmony_ci	if (enc)
110262306a36Sopenharmony_ci		outputlen = req->cryptlen +  req->assoclen + mac_len;
110362306a36Sopenharmony_ci	else
110462306a36Sopenharmony_ci		outputlen = req->cryptlen + req->assoclen - mac_len;
110562306a36Sopenharmony_ci
110662306a36Sopenharmony_ci	update_output_data(req_info, req->dst, 0, outputlen, &argcnt);
110762306a36Sopenharmony_ci	req_info->outcnt = argcnt;
110862306a36Sopenharmony_ci
110962306a36Sopenharmony_ci	return 0;
111062306a36Sopenharmony_ci}
111162306a36Sopenharmony_ci
111262306a36Sopenharmony_cistatic inline u32 create_aead_null_input_list(struct aead_request *req,
111362306a36Sopenharmony_ci					      u32 enc, u32 mac_len)
111462306a36Sopenharmony_ci{
111562306a36Sopenharmony_ci	struct otx_cpt_req_ctx *rctx = aead_request_ctx_dma(req);
111662306a36Sopenharmony_ci	struct otx_cpt_req_info *req_info = &rctx->cpt_req;
111762306a36Sopenharmony_ci	u32 inputlen, argcnt = 0;
111862306a36Sopenharmony_ci
111962306a36Sopenharmony_ci	if (enc)
112062306a36Sopenharmony_ci		inputlen =  req->cryptlen + req->assoclen;
112162306a36Sopenharmony_ci	else
112262306a36Sopenharmony_ci		inputlen =  req->cryptlen + req->assoclen - mac_len;
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_ci	create_hmac_ctx_hdr(req, &argcnt, enc);
112562306a36Sopenharmony_ci	update_input_data(req_info, req->src, inputlen, &argcnt);
112662306a36Sopenharmony_ci	req_info->incnt = argcnt;
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_ci	return 0;
112962306a36Sopenharmony_ci}
113062306a36Sopenharmony_ci
113162306a36Sopenharmony_cistatic inline u32 create_aead_null_output_list(struct aead_request *req,
113262306a36Sopenharmony_ci					       u32 enc, u32 mac_len)
113362306a36Sopenharmony_ci{
113462306a36Sopenharmony_ci	struct otx_cpt_req_ctx *rctx = aead_request_ctx_dma(req);
113562306a36Sopenharmony_ci	struct otx_cpt_req_info *req_info =  &rctx->cpt_req;
113662306a36Sopenharmony_ci	struct scatterlist *dst;
113762306a36Sopenharmony_ci	u8 *ptr = NULL;
113862306a36Sopenharmony_ci	int argcnt = 0, status, offset;
113962306a36Sopenharmony_ci	u32 inputlen;
114062306a36Sopenharmony_ci
114162306a36Sopenharmony_ci	if (enc)
114262306a36Sopenharmony_ci		inputlen =  req->cryptlen + req->assoclen;
114362306a36Sopenharmony_ci	else
114462306a36Sopenharmony_ci		inputlen =  req->cryptlen + req->assoclen - mac_len;
114562306a36Sopenharmony_ci
114662306a36Sopenharmony_ci	/*
114762306a36Sopenharmony_ci	 * If source and destination are different
114862306a36Sopenharmony_ci	 * then copy payload to destination
114962306a36Sopenharmony_ci	 */
115062306a36Sopenharmony_ci	if (req->src != req->dst) {
115162306a36Sopenharmony_ci
115262306a36Sopenharmony_ci		ptr = kmalloc(inputlen, (req_info->areq->flags &
115362306a36Sopenharmony_ci					 CRYPTO_TFM_REQ_MAY_SLEEP) ?
115462306a36Sopenharmony_ci					 GFP_KERNEL : GFP_ATOMIC);
115562306a36Sopenharmony_ci		if (!ptr) {
115662306a36Sopenharmony_ci			status = -ENOMEM;
115762306a36Sopenharmony_ci			goto error;
115862306a36Sopenharmony_ci		}
115962306a36Sopenharmony_ci
116062306a36Sopenharmony_ci		status = sg_copy_to_buffer(req->src, sg_nents(req->src), ptr,
116162306a36Sopenharmony_ci					   inputlen);
116262306a36Sopenharmony_ci		if (status != inputlen) {
116362306a36Sopenharmony_ci			status = -EINVAL;
116462306a36Sopenharmony_ci			goto error_free;
116562306a36Sopenharmony_ci		}
116662306a36Sopenharmony_ci		status = sg_copy_from_buffer(req->dst, sg_nents(req->dst), ptr,
116762306a36Sopenharmony_ci					     inputlen);
116862306a36Sopenharmony_ci		if (status != inputlen) {
116962306a36Sopenharmony_ci			status = -EINVAL;
117062306a36Sopenharmony_ci			goto error_free;
117162306a36Sopenharmony_ci		}
117262306a36Sopenharmony_ci		kfree(ptr);
117362306a36Sopenharmony_ci	}
117462306a36Sopenharmony_ci
117562306a36Sopenharmony_ci	if (enc) {
117662306a36Sopenharmony_ci		/*
117762306a36Sopenharmony_ci		 * In an encryption scenario hmac needs
117862306a36Sopenharmony_ci		 * to be appended after payload
117962306a36Sopenharmony_ci		 */
118062306a36Sopenharmony_ci		dst = req->dst;
118162306a36Sopenharmony_ci		offset = inputlen;
118262306a36Sopenharmony_ci		while (offset >= dst->length) {
118362306a36Sopenharmony_ci			offset -= dst->length;
118462306a36Sopenharmony_ci			dst = sg_next(dst);
118562306a36Sopenharmony_ci			if (!dst) {
118662306a36Sopenharmony_ci				status = -ENOENT;
118762306a36Sopenharmony_ci				goto error;
118862306a36Sopenharmony_ci			}
118962306a36Sopenharmony_ci		}
119062306a36Sopenharmony_ci
119162306a36Sopenharmony_ci		update_output_data(req_info, dst, offset, mac_len, &argcnt);
119262306a36Sopenharmony_ci	} else {
119362306a36Sopenharmony_ci		/*
119462306a36Sopenharmony_ci		 * In a decryption scenario calculated hmac for received
119562306a36Sopenharmony_ci		 * payload needs to be compare with hmac received
119662306a36Sopenharmony_ci		 */
119762306a36Sopenharmony_ci		status = sg_copy_buffer(req->src, sg_nents(req->src),
119862306a36Sopenharmony_ci					rctx->fctx.hmac.s.hmac_recv, mac_len,
119962306a36Sopenharmony_ci					inputlen, true);
120062306a36Sopenharmony_ci		if (status != mac_len) {
120162306a36Sopenharmony_ci			status = -EINVAL;
120262306a36Sopenharmony_ci			goto error;
120362306a36Sopenharmony_ci		}
120462306a36Sopenharmony_ci
120562306a36Sopenharmony_ci		req_info->out[argcnt].vptr = rctx->fctx.hmac.s.hmac_calc;
120662306a36Sopenharmony_ci		req_info->out[argcnt].size = mac_len;
120762306a36Sopenharmony_ci		argcnt++;
120862306a36Sopenharmony_ci	}
120962306a36Sopenharmony_ci
121062306a36Sopenharmony_ci	req_info->outcnt = argcnt;
121162306a36Sopenharmony_ci	return 0;
121262306a36Sopenharmony_ci
121362306a36Sopenharmony_cierror_free:
121462306a36Sopenharmony_ci	kfree(ptr);
121562306a36Sopenharmony_cierror:
121662306a36Sopenharmony_ci	return status;
121762306a36Sopenharmony_ci}
121862306a36Sopenharmony_ci
121962306a36Sopenharmony_cistatic u32 cpt_aead_enc_dec(struct aead_request *req, u8 reg_type, u8 enc)
122062306a36Sopenharmony_ci{
122162306a36Sopenharmony_ci	struct otx_cpt_req_ctx *rctx = aead_request_ctx_dma(req);
122262306a36Sopenharmony_ci	struct otx_cpt_req_info *req_info = &rctx->cpt_req;
122362306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
122462306a36Sopenharmony_ci	struct pci_dev *pdev;
122562306a36Sopenharmony_ci	u32 status, cpu_num;
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_ci	/* Clear control words */
122862306a36Sopenharmony_ci	rctx->ctrl_word.flags = 0;
122962306a36Sopenharmony_ci	rctx->fctx.enc.enc_ctrl.flags = 0;
123062306a36Sopenharmony_ci
123162306a36Sopenharmony_ci	req_info->callback = otx_cpt_aead_callback;
123262306a36Sopenharmony_ci	req_info->areq = &req->base;
123362306a36Sopenharmony_ci	req_info->req_type = reg_type;
123462306a36Sopenharmony_ci	req_info->is_enc = enc;
123562306a36Sopenharmony_ci	req_info->is_trunc_hmac = false;
123662306a36Sopenharmony_ci
123762306a36Sopenharmony_ci	switch (reg_type) {
123862306a36Sopenharmony_ci	case OTX_CPT_AEAD_ENC_DEC_REQ:
123962306a36Sopenharmony_ci		status = create_aead_input_list(req, enc);
124062306a36Sopenharmony_ci		if (status)
124162306a36Sopenharmony_ci			return status;
124262306a36Sopenharmony_ci		status = create_aead_output_list(req, enc,
124362306a36Sopenharmony_ci						 crypto_aead_authsize(tfm));
124462306a36Sopenharmony_ci		if (status)
124562306a36Sopenharmony_ci			return status;
124662306a36Sopenharmony_ci		break;
124762306a36Sopenharmony_ci
124862306a36Sopenharmony_ci	case OTX_CPT_AEAD_ENC_DEC_NULL_REQ:
124962306a36Sopenharmony_ci		status = create_aead_null_input_list(req, enc,
125062306a36Sopenharmony_ci						     crypto_aead_authsize(tfm));
125162306a36Sopenharmony_ci		if (status)
125262306a36Sopenharmony_ci			return status;
125362306a36Sopenharmony_ci		status = create_aead_null_output_list(req, enc,
125462306a36Sopenharmony_ci						crypto_aead_authsize(tfm));
125562306a36Sopenharmony_ci		if (status)
125662306a36Sopenharmony_ci			return status;
125762306a36Sopenharmony_ci		break;
125862306a36Sopenharmony_ci
125962306a36Sopenharmony_ci	default:
126062306a36Sopenharmony_ci		return -EINVAL;
126162306a36Sopenharmony_ci	}
126262306a36Sopenharmony_ci
126362306a36Sopenharmony_ci	/* Validate that request doesn't exceed maximum CPT supported size */
126462306a36Sopenharmony_ci	if (req_info->req.param1 > OTX_CPT_MAX_REQ_SIZE ||
126562306a36Sopenharmony_ci	    req_info->req.param2 > OTX_CPT_MAX_REQ_SIZE)
126662306a36Sopenharmony_ci		return -E2BIG;
126762306a36Sopenharmony_ci
126862306a36Sopenharmony_ci	status = get_se_device(&pdev, &cpu_num);
126962306a36Sopenharmony_ci	if (status)
127062306a36Sopenharmony_ci		return status;
127162306a36Sopenharmony_ci
127262306a36Sopenharmony_ci	req_info->ctrl.s.grp = 0;
127362306a36Sopenharmony_ci
127462306a36Sopenharmony_ci	status = otx_cpt_do_request(pdev, req_info, cpu_num);
127562306a36Sopenharmony_ci	/*
127662306a36Sopenharmony_ci	 * We perform an asynchronous send and once
127762306a36Sopenharmony_ci	 * the request is completed the driver would
127862306a36Sopenharmony_ci	 * intimate through registered call back functions
127962306a36Sopenharmony_ci	 */
128062306a36Sopenharmony_ci	return status;
128162306a36Sopenharmony_ci}
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_cistatic int otx_cpt_aead_encrypt(struct aead_request *req)
128462306a36Sopenharmony_ci{
128562306a36Sopenharmony_ci	return cpt_aead_enc_dec(req, OTX_CPT_AEAD_ENC_DEC_REQ, true);
128662306a36Sopenharmony_ci}
128762306a36Sopenharmony_ci
128862306a36Sopenharmony_cistatic int otx_cpt_aead_decrypt(struct aead_request *req)
128962306a36Sopenharmony_ci{
129062306a36Sopenharmony_ci	return cpt_aead_enc_dec(req, OTX_CPT_AEAD_ENC_DEC_REQ, false);
129162306a36Sopenharmony_ci}
129262306a36Sopenharmony_ci
129362306a36Sopenharmony_cistatic int otx_cpt_aead_null_encrypt(struct aead_request *req)
129462306a36Sopenharmony_ci{
129562306a36Sopenharmony_ci	return cpt_aead_enc_dec(req, OTX_CPT_AEAD_ENC_DEC_NULL_REQ, true);
129662306a36Sopenharmony_ci}
129762306a36Sopenharmony_ci
129862306a36Sopenharmony_cistatic int otx_cpt_aead_null_decrypt(struct aead_request *req)
129962306a36Sopenharmony_ci{
130062306a36Sopenharmony_ci	return cpt_aead_enc_dec(req, OTX_CPT_AEAD_ENC_DEC_NULL_REQ, false);
130162306a36Sopenharmony_ci}
130262306a36Sopenharmony_ci
130362306a36Sopenharmony_cistatic struct skcipher_alg otx_cpt_skciphers[] = { {
130462306a36Sopenharmony_ci	.base.cra_name = "xts(aes)",
130562306a36Sopenharmony_ci	.base.cra_driver_name = "cpt_xts_aes",
130662306a36Sopenharmony_ci	.base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY,
130762306a36Sopenharmony_ci	.base.cra_blocksize = AES_BLOCK_SIZE,
130862306a36Sopenharmony_ci	.base.cra_ctxsize = sizeof(struct otx_cpt_enc_ctx),
130962306a36Sopenharmony_ci	.base.cra_alignmask = 7,
131062306a36Sopenharmony_ci	.base.cra_priority = 4001,
131162306a36Sopenharmony_ci	.base.cra_module = THIS_MODULE,
131262306a36Sopenharmony_ci
131362306a36Sopenharmony_ci	.init = otx_cpt_enc_dec_init,
131462306a36Sopenharmony_ci	.ivsize = AES_BLOCK_SIZE,
131562306a36Sopenharmony_ci	.min_keysize = 2 * AES_MIN_KEY_SIZE,
131662306a36Sopenharmony_ci	.max_keysize = 2 * AES_MAX_KEY_SIZE,
131762306a36Sopenharmony_ci	.setkey = otx_cpt_skcipher_xts_setkey,
131862306a36Sopenharmony_ci	.encrypt = otx_cpt_skcipher_encrypt,
131962306a36Sopenharmony_ci	.decrypt = otx_cpt_skcipher_decrypt,
132062306a36Sopenharmony_ci}, {
132162306a36Sopenharmony_ci	.base.cra_name = "cbc(aes)",
132262306a36Sopenharmony_ci	.base.cra_driver_name = "cpt_cbc_aes",
132362306a36Sopenharmony_ci	.base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY,
132462306a36Sopenharmony_ci	.base.cra_blocksize = AES_BLOCK_SIZE,
132562306a36Sopenharmony_ci	.base.cra_ctxsize = sizeof(struct otx_cpt_enc_ctx),
132662306a36Sopenharmony_ci	.base.cra_alignmask = 7,
132762306a36Sopenharmony_ci	.base.cra_priority = 4001,
132862306a36Sopenharmony_ci	.base.cra_module = THIS_MODULE,
132962306a36Sopenharmony_ci
133062306a36Sopenharmony_ci	.init = otx_cpt_enc_dec_init,
133162306a36Sopenharmony_ci	.ivsize = AES_BLOCK_SIZE,
133262306a36Sopenharmony_ci	.min_keysize = AES_MIN_KEY_SIZE,
133362306a36Sopenharmony_ci	.max_keysize = AES_MAX_KEY_SIZE,
133462306a36Sopenharmony_ci	.setkey = otx_cpt_skcipher_cbc_aes_setkey,
133562306a36Sopenharmony_ci	.encrypt = otx_cpt_skcipher_encrypt,
133662306a36Sopenharmony_ci	.decrypt = otx_cpt_skcipher_decrypt,
133762306a36Sopenharmony_ci}, {
133862306a36Sopenharmony_ci	.base.cra_name = "ecb(aes)",
133962306a36Sopenharmony_ci	.base.cra_driver_name = "cpt_ecb_aes",
134062306a36Sopenharmony_ci	.base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY,
134162306a36Sopenharmony_ci	.base.cra_blocksize = AES_BLOCK_SIZE,
134262306a36Sopenharmony_ci	.base.cra_ctxsize = sizeof(struct otx_cpt_enc_ctx),
134362306a36Sopenharmony_ci	.base.cra_alignmask = 7,
134462306a36Sopenharmony_ci	.base.cra_priority = 4001,
134562306a36Sopenharmony_ci	.base.cra_module = THIS_MODULE,
134662306a36Sopenharmony_ci
134762306a36Sopenharmony_ci	.init = otx_cpt_enc_dec_init,
134862306a36Sopenharmony_ci	.ivsize = 0,
134962306a36Sopenharmony_ci	.min_keysize = AES_MIN_KEY_SIZE,
135062306a36Sopenharmony_ci	.max_keysize = AES_MAX_KEY_SIZE,
135162306a36Sopenharmony_ci	.setkey = otx_cpt_skcipher_ecb_aes_setkey,
135262306a36Sopenharmony_ci	.encrypt = otx_cpt_skcipher_encrypt,
135362306a36Sopenharmony_ci	.decrypt = otx_cpt_skcipher_decrypt,
135462306a36Sopenharmony_ci}, {
135562306a36Sopenharmony_ci	.base.cra_name = "cfb(aes)",
135662306a36Sopenharmony_ci	.base.cra_driver_name = "cpt_cfb_aes",
135762306a36Sopenharmony_ci	.base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY,
135862306a36Sopenharmony_ci	.base.cra_blocksize = AES_BLOCK_SIZE,
135962306a36Sopenharmony_ci	.base.cra_ctxsize = sizeof(struct otx_cpt_enc_ctx),
136062306a36Sopenharmony_ci	.base.cra_alignmask = 7,
136162306a36Sopenharmony_ci	.base.cra_priority = 4001,
136262306a36Sopenharmony_ci	.base.cra_module = THIS_MODULE,
136362306a36Sopenharmony_ci
136462306a36Sopenharmony_ci	.init = otx_cpt_enc_dec_init,
136562306a36Sopenharmony_ci	.ivsize = AES_BLOCK_SIZE,
136662306a36Sopenharmony_ci	.min_keysize = AES_MIN_KEY_SIZE,
136762306a36Sopenharmony_ci	.max_keysize = AES_MAX_KEY_SIZE,
136862306a36Sopenharmony_ci	.setkey = otx_cpt_skcipher_cfb_aes_setkey,
136962306a36Sopenharmony_ci	.encrypt = otx_cpt_skcipher_encrypt,
137062306a36Sopenharmony_ci	.decrypt = otx_cpt_skcipher_decrypt,
137162306a36Sopenharmony_ci}, {
137262306a36Sopenharmony_ci	.base.cra_name = "cbc(des3_ede)",
137362306a36Sopenharmony_ci	.base.cra_driver_name = "cpt_cbc_des3_ede",
137462306a36Sopenharmony_ci	.base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY,
137562306a36Sopenharmony_ci	.base.cra_blocksize = DES3_EDE_BLOCK_SIZE,
137662306a36Sopenharmony_ci	.base.cra_ctxsize = sizeof(struct otx_cpt_des3_ctx),
137762306a36Sopenharmony_ci	.base.cra_alignmask = 7,
137862306a36Sopenharmony_ci	.base.cra_priority = 4001,
137962306a36Sopenharmony_ci	.base.cra_module = THIS_MODULE,
138062306a36Sopenharmony_ci
138162306a36Sopenharmony_ci	.init = otx_cpt_enc_dec_init,
138262306a36Sopenharmony_ci	.min_keysize = DES3_EDE_KEY_SIZE,
138362306a36Sopenharmony_ci	.max_keysize = DES3_EDE_KEY_SIZE,
138462306a36Sopenharmony_ci	.ivsize = DES_BLOCK_SIZE,
138562306a36Sopenharmony_ci	.setkey = otx_cpt_skcipher_cbc_des3_setkey,
138662306a36Sopenharmony_ci	.encrypt = otx_cpt_skcipher_encrypt,
138762306a36Sopenharmony_ci	.decrypt = otx_cpt_skcipher_decrypt,
138862306a36Sopenharmony_ci}, {
138962306a36Sopenharmony_ci	.base.cra_name = "ecb(des3_ede)",
139062306a36Sopenharmony_ci	.base.cra_driver_name = "cpt_ecb_des3_ede",
139162306a36Sopenharmony_ci	.base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY,
139262306a36Sopenharmony_ci	.base.cra_blocksize = DES3_EDE_BLOCK_SIZE,
139362306a36Sopenharmony_ci	.base.cra_ctxsize = sizeof(struct otx_cpt_des3_ctx),
139462306a36Sopenharmony_ci	.base.cra_alignmask = 7,
139562306a36Sopenharmony_ci	.base.cra_priority = 4001,
139662306a36Sopenharmony_ci	.base.cra_module = THIS_MODULE,
139762306a36Sopenharmony_ci
139862306a36Sopenharmony_ci	.init = otx_cpt_enc_dec_init,
139962306a36Sopenharmony_ci	.min_keysize = DES3_EDE_KEY_SIZE,
140062306a36Sopenharmony_ci	.max_keysize = DES3_EDE_KEY_SIZE,
140162306a36Sopenharmony_ci	.ivsize = 0,
140262306a36Sopenharmony_ci	.setkey = otx_cpt_skcipher_ecb_des3_setkey,
140362306a36Sopenharmony_ci	.encrypt = otx_cpt_skcipher_encrypt,
140462306a36Sopenharmony_ci	.decrypt = otx_cpt_skcipher_decrypt,
140562306a36Sopenharmony_ci} };
140662306a36Sopenharmony_ci
140762306a36Sopenharmony_cistatic struct aead_alg otx_cpt_aeads[] = { {
140862306a36Sopenharmony_ci	.base = {
140962306a36Sopenharmony_ci		.cra_name = "authenc(hmac(sha1),cbc(aes))",
141062306a36Sopenharmony_ci		.cra_driver_name = "cpt_hmac_sha1_cbc_aes",
141162306a36Sopenharmony_ci		.cra_blocksize = AES_BLOCK_SIZE,
141262306a36Sopenharmony_ci		.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY,
141362306a36Sopenharmony_ci		.cra_ctxsize = sizeof(struct otx_cpt_aead_ctx) + CRYPTO_DMA_PADDING,
141462306a36Sopenharmony_ci		.cra_priority = 4001,
141562306a36Sopenharmony_ci		.cra_alignmask = 0,
141662306a36Sopenharmony_ci		.cra_module = THIS_MODULE,
141762306a36Sopenharmony_ci	},
141862306a36Sopenharmony_ci	.init = otx_cpt_aead_cbc_aes_sha1_init,
141962306a36Sopenharmony_ci	.exit = otx_cpt_aead_exit,
142062306a36Sopenharmony_ci	.setkey = otx_cpt_aead_cbc_aes_sha_setkey,
142162306a36Sopenharmony_ci	.setauthsize = otx_cpt_aead_set_authsize,
142262306a36Sopenharmony_ci	.encrypt = otx_cpt_aead_encrypt,
142362306a36Sopenharmony_ci	.decrypt = otx_cpt_aead_decrypt,
142462306a36Sopenharmony_ci	.ivsize = AES_BLOCK_SIZE,
142562306a36Sopenharmony_ci	.maxauthsize = SHA1_DIGEST_SIZE,
142662306a36Sopenharmony_ci}, {
142762306a36Sopenharmony_ci	.base = {
142862306a36Sopenharmony_ci		.cra_name = "authenc(hmac(sha256),cbc(aes))",
142962306a36Sopenharmony_ci		.cra_driver_name = "cpt_hmac_sha256_cbc_aes",
143062306a36Sopenharmony_ci		.cra_blocksize = AES_BLOCK_SIZE,
143162306a36Sopenharmony_ci		.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY,
143262306a36Sopenharmony_ci		.cra_ctxsize = sizeof(struct otx_cpt_aead_ctx) + CRYPTO_DMA_PADDING,
143362306a36Sopenharmony_ci		.cra_priority = 4001,
143462306a36Sopenharmony_ci		.cra_alignmask = 0,
143562306a36Sopenharmony_ci		.cra_module = THIS_MODULE,
143662306a36Sopenharmony_ci	},
143762306a36Sopenharmony_ci	.init = otx_cpt_aead_cbc_aes_sha256_init,
143862306a36Sopenharmony_ci	.exit = otx_cpt_aead_exit,
143962306a36Sopenharmony_ci	.setkey = otx_cpt_aead_cbc_aes_sha_setkey,
144062306a36Sopenharmony_ci	.setauthsize = otx_cpt_aead_set_authsize,
144162306a36Sopenharmony_ci	.encrypt = otx_cpt_aead_encrypt,
144262306a36Sopenharmony_ci	.decrypt = otx_cpt_aead_decrypt,
144362306a36Sopenharmony_ci	.ivsize = AES_BLOCK_SIZE,
144462306a36Sopenharmony_ci	.maxauthsize = SHA256_DIGEST_SIZE,
144562306a36Sopenharmony_ci}, {
144662306a36Sopenharmony_ci	.base = {
144762306a36Sopenharmony_ci		.cra_name = "authenc(hmac(sha384),cbc(aes))",
144862306a36Sopenharmony_ci		.cra_driver_name = "cpt_hmac_sha384_cbc_aes",
144962306a36Sopenharmony_ci		.cra_blocksize = AES_BLOCK_SIZE,
145062306a36Sopenharmony_ci		.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY,
145162306a36Sopenharmony_ci		.cra_ctxsize = sizeof(struct otx_cpt_aead_ctx) + CRYPTO_DMA_PADDING,
145262306a36Sopenharmony_ci		.cra_priority = 4001,
145362306a36Sopenharmony_ci		.cra_alignmask = 0,
145462306a36Sopenharmony_ci		.cra_module = THIS_MODULE,
145562306a36Sopenharmony_ci	},
145662306a36Sopenharmony_ci	.init = otx_cpt_aead_cbc_aes_sha384_init,
145762306a36Sopenharmony_ci	.exit = otx_cpt_aead_exit,
145862306a36Sopenharmony_ci	.setkey = otx_cpt_aead_cbc_aes_sha_setkey,
145962306a36Sopenharmony_ci	.setauthsize = otx_cpt_aead_set_authsize,
146062306a36Sopenharmony_ci	.encrypt = otx_cpt_aead_encrypt,
146162306a36Sopenharmony_ci	.decrypt = otx_cpt_aead_decrypt,
146262306a36Sopenharmony_ci	.ivsize = AES_BLOCK_SIZE,
146362306a36Sopenharmony_ci	.maxauthsize = SHA384_DIGEST_SIZE,
146462306a36Sopenharmony_ci}, {
146562306a36Sopenharmony_ci	.base = {
146662306a36Sopenharmony_ci		.cra_name = "authenc(hmac(sha512),cbc(aes))",
146762306a36Sopenharmony_ci		.cra_driver_name = "cpt_hmac_sha512_cbc_aes",
146862306a36Sopenharmony_ci		.cra_blocksize = AES_BLOCK_SIZE,
146962306a36Sopenharmony_ci		.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY,
147062306a36Sopenharmony_ci		.cra_ctxsize = sizeof(struct otx_cpt_aead_ctx) + CRYPTO_DMA_PADDING,
147162306a36Sopenharmony_ci		.cra_priority = 4001,
147262306a36Sopenharmony_ci		.cra_alignmask = 0,
147362306a36Sopenharmony_ci		.cra_module = THIS_MODULE,
147462306a36Sopenharmony_ci	},
147562306a36Sopenharmony_ci	.init = otx_cpt_aead_cbc_aes_sha512_init,
147662306a36Sopenharmony_ci	.exit = otx_cpt_aead_exit,
147762306a36Sopenharmony_ci	.setkey = otx_cpt_aead_cbc_aes_sha_setkey,
147862306a36Sopenharmony_ci	.setauthsize = otx_cpt_aead_set_authsize,
147962306a36Sopenharmony_ci	.encrypt = otx_cpt_aead_encrypt,
148062306a36Sopenharmony_ci	.decrypt = otx_cpt_aead_decrypt,
148162306a36Sopenharmony_ci	.ivsize = AES_BLOCK_SIZE,
148262306a36Sopenharmony_ci	.maxauthsize = SHA512_DIGEST_SIZE,
148362306a36Sopenharmony_ci}, {
148462306a36Sopenharmony_ci	.base = {
148562306a36Sopenharmony_ci		.cra_name = "authenc(hmac(sha1),ecb(cipher_null))",
148662306a36Sopenharmony_ci		.cra_driver_name = "cpt_hmac_sha1_ecb_null",
148762306a36Sopenharmony_ci		.cra_blocksize = 1,
148862306a36Sopenharmony_ci		.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY,
148962306a36Sopenharmony_ci		.cra_ctxsize = sizeof(struct otx_cpt_aead_ctx) + CRYPTO_DMA_PADDING,
149062306a36Sopenharmony_ci		.cra_priority = 4001,
149162306a36Sopenharmony_ci		.cra_alignmask = 0,
149262306a36Sopenharmony_ci		.cra_module = THIS_MODULE,
149362306a36Sopenharmony_ci	},
149462306a36Sopenharmony_ci	.init = otx_cpt_aead_ecb_null_sha1_init,
149562306a36Sopenharmony_ci	.exit = otx_cpt_aead_exit,
149662306a36Sopenharmony_ci	.setkey = otx_cpt_aead_ecb_null_sha_setkey,
149762306a36Sopenharmony_ci	.setauthsize = otx_cpt_aead_set_authsize,
149862306a36Sopenharmony_ci	.encrypt = otx_cpt_aead_null_encrypt,
149962306a36Sopenharmony_ci	.decrypt = otx_cpt_aead_null_decrypt,
150062306a36Sopenharmony_ci	.ivsize = 0,
150162306a36Sopenharmony_ci	.maxauthsize = SHA1_DIGEST_SIZE,
150262306a36Sopenharmony_ci}, {
150362306a36Sopenharmony_ci	.base = {
150462306a36Sopenharmony_ci		.cra_name = "authenc(hmac(sha256),ecb(cipher_null))",
150562306a36Sopenharmony_ci		.cra_driver_name = "cpt_hmac_sha256_ecb_null",
150662306a36Sopenharmony_ci		.cra_blocksize = 1,
150762306a36Sopenharmony_ci		.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY,
150862306a36Sopenharmony_ci		.cra_ctxsize = sizeof(struct otx_cpt_aead_ctx) + CRYPTO_DMA_PADDING,
150962306a36Sopenharmony_ci		.cra_priority = 4001,
151062306a36Sopenharmony_ci		.cra_alignmask = 0,
151162306a36Sopenharmony_ci		.cra_module = THIS_MODULE,
151262306a36Sopenharmony_ci	},
151362306a36Sopenharmony_ci	.init = otx_cpt_aead_ecb_null_sha256_init,
151462306a36Sopenharmony_ci	.exit = otx_cpt_aead_exit,
151562306a36Sopenharmony_ci	.setkey = otx_cpt_aead_ecb_null_sha_setkey,
151662306a36Sopenharmony_ci	.setauthsize = otx_cpt_aead_set_authsize,
151762306a36Sopenharmony_ci	.encrypt = otx_cpt_aead_null_encrypt,
151862306a36Sopenharmony_ci	.decrypt = otx_cpt_aead_null_decrypt,
151962306a36Sopenharmony_ci	.ivsize = 0,
152062306a36Sopenharmony_ci	.maxauthsize = SHA256_DIGEST_SIZE,
152162306a36Sopenharmony_ci}, {
152262306a36Sopenharmony_ci	.base = {
152362306a36Sopenharmony_ci		.cra_name = "authenc(hmac(sha384),ecb(cipher_null))",
152462306a36Sopenharmony_ci		.cra_driver_name = "cpt_hmac_sha384_ecb_null",
152562306a36Sopenharmony_ci		.cra_blocksize = 1,
152662306a36Sopenharmony_ci		.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY,
152762306a36Sopenharmony_ci		.cra_ctxsize = sizeof(struct otx_cpt_aead_ctx) + CRYPTO_DMA_PADDING,
152862306a36Sopenharmony_ci		.cra_priority = 4001,
152962306a36Sopenharmony_ci		.cra_alignmask = 0,
153062306a36Sopenharmony_ci		.cra_module = THIS_MODULE,
153162306a36Sopenharmony_ci	},
153262306a36Sopenharmony_ci	.init = otx_cpt_aead_ecb_null_sha384_init,
153362306a36Sopenharmony_ci	.exit = otx_cpt_aead_exit,
153462306a36Sopenharmony_ci	.setkey = otx_cpt_aead_ecb_null_sha_setkey,
153562306a36Sopenharmony_ci	.setauthsize = otx_cpt_aead_set_authsize,
153662306a36Sopenharmony_ci	.encrypt = otx_cpt_aead_null_encrypt,
153762306a36Sopenharmony_ci	.decrypt = otx_cpt_aead_null_decrypt,
153862306a36Sopenharmony_ci	.ivsize = 0,
153962306a36Sopenharmony_ci	.maxauthsize = SHA384_DIGEST_SIZE,
154062306a36Sopenharmony_ci}, {
154162306a36Sopenharmony_ci	.base = {
154262306a36Sopenharmony_ci		.cra_name = "authenc(hmac(sha512),ecb(cipher_null))",
154362306a36Sopenharmony_ci		.cra_driver_name = "cpt_hmac_sha512_ecb_null",
154462306a36Sopenharmony_ci		.cra_blocksize = 1,
154562306a36Sopenharmony_ci		.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY,
154662306a36Sopenharmony_ci		.cra_ctxsize = sizeof(struct otx_cpt_aead_ctx) + CRYPTO_DMA_PADDING,
154762306a36Sopenharmony_ci		.cra_priority = 4001,
154862306a36Sopenharmony_ci		.cra_alignmask = 0,
154962306a36Sopenharmony_ci		.cra_module = THIS_MODULE,
155062306a36Sopenharmony_ci	},
155162306a36Sopenharmony_ci	.init = otx_cpt_aead_ecb_null_sha512_init,
155262306a36Sopenharmony_ci	.exit = otx_cpt_aead_exit,
155362306a36Sopenharmony_ci	.setkey = otx_cpt_aead_ecb_null_sha_setkey,
155462306a36Sopenharmony_ci	.setauthsize = otx_cpt_aead_set_authsize,
155562306a36Sopenharmony_ci	.encrypt = otx_cpt_aead_null_encrypt,
155662306a36Sopenharmony_ci	.decrypt = otx_cpt_aead_null_decrypt,
155762306a36Sopenharmony_ci	.ivsize = 0,
155862306a36Sopenharmony_ci	.maxauthsize = SHA512_DIGEST_SIZE,
155962306a36Sopenharmony_ci}, {
156062306a36Sopenharmony_ci	.base = {
156162306a36Sopenharmony_ci		.cra_name = "rfc4106(gcm(aes))",
156262306a36Sopenharmony_ci		.cra_driver_name = "cpt_rfc4106_gcm_aes",
156362306a36Sopenharmony_ci		.cra_blocksize = 1,
156462306a36Sopenharmony_ci		.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY,
156562306a36Sopenharmony_ci		.cra_ctxsize = sizeof(struct otx_cpt_aead_ctx) + CRYPTO_DMA_PADDING,
156662306a36Sopenharmony_ci		.cra_priority = 4001,
156762306a36Sopenharmony_ci		.cra_alignmask = 0,
156862306a36Sopenharmony_ci		.cra_module = THIS_MODULE,
156962306a36Sopenharmony_ci	},
157062306a36Sopenharmony_ci	.init = otx_cpt_aead_gcm_aes_init,
157162306a36Sopenharmony_ci	.exit = otx_cpt_aead_exit,
157262306a36Sopenharmony_ci	.setkey = otx_cpt_aead_gcm_aes_setkey,
157362306a36Sopenharmony_ci	.setauthsize = otx_cpt_aead_set_authsize,
157462306a36Sopenharmony_ci	.encrypt = otx_cpt_aead_encrypt,
157562306a36Sopenharmony_ci	.decrypt = otx_cpt_aead_decrypt,
157662306a36Sopenharmony_ci	.ivsize = AES_GCM_IV_SIZE,
157762306a36Sopenharmony_ci	.maxauthsize = AES_GCM_ICV_SIZE,
157862306a36Sopenharmony_ci} };
157962306a36Sopenharmony_ci
158062306a36Sopenharmony_cistatic inline int is_any_alg_used(void)
158162306a36Sopenharmony_ci{
158262306a36Sopenharmony_ci	int i;
158362306a36Sopenharmony_ci
158462306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(otx_cpt_skciphers); i++)
158562306a36Sopenharmony_ci		if (refcount_read(&otx_cpt_skciphers[i].base.cra_refcnt) != 1)
158662306a36Sopenharmony_ci			return true;
158762306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(otx_cpt_aeads); i++)
158862306a36Sopenharmony_ci		if (refcount_read(&otx_cpt_aeads[i].base.cra_refcnt) != 1)
158962306a36Sopenharmony_ci			return true;
159062306a36Sopenharmony_ci	return false;
159162306a36Sopenharmony_ci}
159262306a36Sopenharmony_ci
159362306a36Sopenharmony_cistatic inline int cpt_register_algs(void)
159462306a36Sopenharmony_ci{
159562306a36Sopenharmony_ci	int i, err = 0;
159662306a36Sopenharmony_ci
159762306a36Sopenharmony_ci	if (!IS_ENABLED(CONFIG_DM_CRYPT)) {
159862306a36Sopenharmony_ci		for (i = 0; i < ARRAY_SIZE(otx_cpt_skciphers); i++)
159962306a36Sopenharmony_ci			otx_cpt_skciphers[i].base.cra_flags &= ~CRYPTO_ALG_DEAD;
160062306a36Sopenharmony_ci
160162306a36Sopenharmony_ci		err = crypto_register_skciphers(otx_cpt_skciphers,
160262306a36Sopenharmony_ci						ARRAY_SIZE(otx_cpt_skciphers));
160362306a36Sopenharmony_ci		if (err)
160462306a36Sopenharmony_ci			return err;
160562306a36Sopenharmony_ci	}
160662306a36Sopenharmony_ci
160762306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(otx_cpt_aeads); i++)
160862306a36Sopenharmony_ci		otx_cpt_aeads[i].base.cra_flags &= ~CRYPTO_ALG_DEAD;
160962306a36Sopenharmony_ci
161062306a36Sopenharmony_ci	err = crypto_register_aeads(otx_cpt_aeads, ARRAY_SIZE(otx_cpt_aeads));
161162306a36Sopenharmony_ci	if (err) {
161262306a36Sopenharmony_ci		crypto_unregister_skciphers(otx_cpt_skciphers,
161362306a36Sopenharmony_ci					    ARRAY_SIZE(otx_cpt_skciphers));
161462306a36Sopenharmony_ci		return err;
161562306a36Sopenharmony_ci	}
161662306a36Sopenharmony_ci
161762306a36Sopenharmony_ci	return 0;
161862306a36Sopenharmony_ci}
161962306a36Sopenharmony_ci
162062306a36Sopenharmony_cistatic inline void cpt_unregister_algs(void)
162162306a36Sopenharmony_ci{
162262306a36Sopenharmony_ci	crypto_unregister_skciphers(otx_cpt_skciphers,
162362306a36Sopenharmony_ci				    ARRAY_SIZE(otx_cpt_skciphers));
162462306a36Sopenharmony_ci	crypto_unregister_aeads(otx_cpt_aeads, ARRAY_SIZE(otx_cpt_aeads));
162562306a36Sopenharmony_ci}
162662306a36Sopenharmony_ci
162762306a36Sopenharmony_cistatic int compare_func(const void *lptr, const void *rptr)
162862306a36Sopenharmony_ci{
162962306a36Sopenharmony_ci	struct cpt_device_desc *ldesc = (struct cpt_device_desc *) lptr;
163062306a36Sopenharmony_ci	struct cpt_device_desc *rdesc = (struct cpt_device_desc *) rptr;
163162306a36Sopenharmony_ci
163262306a36Sopenharmony_ci	if (ldesc->dev->devfn < rdesc->dev->devfn)
163362306a36Sopenharmony_ci		return -1;
163462306a36Sopenharmony_ci	if (ldesc->dev->devfn > rdesc->dev->devfn)
163562306a36Sopenharmony_ci		return 1;
163662306a36Sopenharmony_ci	return 0;
163762306a36Sopenharmony_ci}
163862306a36Sopenharmony_ci
163962306a36Sopenharmony_cistatic void swap_func(void *lptr, void *rptr, int size)
164062306a36Sopenharmony_ci{
164162306a36Sopenharmony_ci	struct cpt_device_desc *ldesc = (struct cpt_device_desc *) lptr;
164262306a36Sopenharmony_ci	struct cpt_device_desc *rdesc = (struct cpt_device_desc *) rptr;
164362306a36Sopenharmony_ci
164462306a36Sopenharmony_ci	swap(*ldesc, *rdesc);
164562306a36Sopenharmony_ci}
164662306a36Sopenharmony_ci
164762306a36Sopenharmony_ciint otx_cpt_crypto_init(struct pci_dev *pdev, struct module *mod,
164862306a36Sopenharmony_ci			enum otx_cptpf_type pf_type,
164962306a36Sopenharmony_ci			enum otx_cptvf_type engine_type,
165062306a36Sopenharmony_ci			int num_queues, int num_devices)
165162306a36Sopenharmony_ci{
165262306a36Sopenharmony_ci	int ret = 0;
165362306a36Sopenharmony_ci	int count;
165462306a36Sopenharmony_ci
165562306a36Sopenharmony_ci	mutex_lock(&mutex);
165662306a36Sopenharmony_ci	switch (engine_type) {
165762306a36Sopenharmony_ci	case OTX_CPT_SE_TYPES:
165862306a36Sopenharmony_ci		count = atomic_read(&se_devices.count);
165962306a36Sopenharmony_ci		if (count >= CPT_MAX_VF_NUM) {
166062306a36Sopenharmony_ci			dev_err(&pdev->dev, "No space to add a new device\n");
166162306a36Sopenharmony_ci			ret = -ENOSPC;
166262306a36Sopenharmony_ci			goto err;
166362306a36Sopenharmony_ci		}
166462306a36Sopenharmony_ci		se_devices.desc[count].pf_type = pf_type;
166562306a36Sopenharmony_ci		se_devices.desc[count].num_queues = num_queues;
166662306a36Sopenharmony_ci		se_devices.desc[count++].dev = pdev;
166762306a36Sopenharmony_ci		atomic_inc(&se_devices.count);
166862306a36Sopenharmony_ci
166962306a36Sopenharmony_ci		if (atomic_read(&se_devices.count) == num_devices &&
167062306a36Sopenharmony_ci		    is_crypto_registered == false) {
167162306a36Sopenharmony_ci			if (cpt_register_algs()) {
167262306a36Sopenharmony_ci				dev_err(&pdev->dev,
167362306a36Sopenharmony_ci				   "Error in registering crypto algorithms\n");
167462306a36Sopenharmony_ci				ret =  -EINVAL;
167562306a36Sopenharmony_ci				goto err;
167662306a36Sopenharmony_ci			}
167762306a36Sopenharmony_ci			try_module_get(mod);
167862306a36Sopenharmony_ci			is_crypto_registered = true;
167962306a36Sopenharmony_ci		}
168062306a36Sopenharmony_ci		sort(se_devices.desc, count, sizeof(struct cpt_device_desc),
168162306a36Sopenharmony_ci		     compare_func, swap_func);
168262306a36Sopenharmony_ci		break;
168362306a36Sopenharmony_ci
168462306a36Sopenharmony_ci	case OTX_CPT_AE_TYPES:
168562306a36Sopenharmony_ci		count = atomic_read(&ae_devices.count);
168662306a36Sopenharmony_ci		if (count >= CPT_MAX_VF_NUM) {
168762306a36Sopenharmony_ci			dev_err(&pdev->dev, "No space to a add new device\n");
168862306a36Sopenharmony_ci			ret = -ENOSPC;
168962306a36Sopenharmony_ci			goto err;
169062306a36Sopenharmony_ci		}
169162306a36Sopenharmony_ci		ae_devices.desc[count].pf_type = pf_type;
169262306a36Sopenharmony_ci		ae_devices.desc[count].num_queues = num_queues;
169362306a36Sopenharmony_ci		ae_devices.desc[count++].dev = pdev;
169462306a36Sopenharmony_ci		atomic_inc(&ae_devices.count);
169562306a36Sopenharmony_ci		sort(ae_devices.desc, count, sizeof(struct cpt_device_desc),
169662306a36Sopenharmony_ci		     compare_func, swap_func);
169762306a36Sopenharmony_ci		break;
169862306a36Sopenharmony_ci
169962306a36Sopenharmony_ci	default:
170062306a36Sopenharmony_ci		dev_err(&pdev->dev, "Unknown VF type %d\n", engine_type);
170162306a36Sopenharmony_ci		ret = BAD_OTX_CPTVF_TYPE;
170262306a36Sopenharmony_ci	}
170362306a36Sopenharmony_cierr:
170462306a36Sopenharmony_ci	mutex_unlock(&mutex);
170562306a36Sopenharmony_ci	return ret;
170662306a36Sopenharmony_ci}
170762306a36Sopenharmony_ci
170862306a36Sopenharmony_civoid otx_cpt_crypto_exit(struct pci_dev *pdev, struct module *mod,
170962306a36Sopenharmony_ci			 enum otx_cptvf_type engine_type)
171062306a36Sopenharmony_ci{
171162306a36Sopenharmony_ci	struct cpt_device_table *dev_tbl;
171262306a36Sopenharmony_ci	bool dev_found = false;
171362306a36Sopenharmony_ci	int i, j, count;
171462306a36Sopenharmony_ci
171562306a36Sopenharmony_ci	mutex_lock(&mutex);
171662306a36Sopenharmony_ci
171762306a36Sopenharmony_ci	dev_tbl = (engine_type == OTX_CPT_AE_TYPES) ? &ae_devices : &se_devices;
171862306a36Sopenharmony_ci	count = atomic_read(&dev_tbl->count);
171962306a36Sopenharmony_ci	for (i = 0; i < count; i++)
172062306a36Sopenharmony_ci		if (pdev == dev_tbl->desc[i].dev) {
172162306a36Sopenharmony_ci			for (j = i; j < count-1; j++)
172262306a36Sopenharmony_ci				dev_tbl->desc[j] = dev_tbl->desc[j+1];
172362306a36Sopenharmony_ci			dev_found = true;
172462306a36Sopenharmony_ci			break;
172562306a36Sopenharmony_ci		}
172662306a36Sopenharmony_ci
172762306a36Sopenharmony_ci	if (!dev_found) {
172862306a36Sopenharmony_ci		dev_err(&pdev->dev, "%s device not found\n", __func__);
172962306a36Sopenharmony_ci		goto exit;
173062306a36Sopenharmony_ci	}
173162306a36Sopenharmony_ci
173262306a36Sopenharmony_ci	if (engine_type != OTX_CPT_AE_TYPES) {
173362306a36Sopenharmony_ci		if (atomic_dec_and_test(&se_devices.count) &&
173462306a36Sopenharmony_ci		    !is_any_alg_used()) {
173562306a36Sopenharmony_ci			cpt_unregister_algs();
173662306a36Sopenharmony_ci			module_put(mod);
173762306a36Sopenharmony_ci			is_crypto_registered = false;
173862306a36Sopenharmony_ci		}
173962306a36Sopenharmony_ci	} else
174062306a36Sopenharmony_ci		atomic_dec(&ae_devices.count);
174162306a36Sopenharmony_ciexit:
174262306a36Sopenharmony_ci	mutex_unlock(&mutex);
174362306a36Sopenharmony_ci}
1744