[][openwrt][mt7988][crypto][Add look-aside mode]

[Description]
Add look-aside mode. Similar to the upstream driver, register the
algorithm with the Linux crypto subsystem to provide encryption and
decryption algorithms for use by other modules.

The construction of transform records, command descriptors,
tokens, and packets is implemented through the APIs provided by the DDK.

All suportted algorithms can check src/init.c, there is a list for all
supported algo. However, the IPSec throught put is only 300 Mbps for
AES-CBC-HMAC-SHA1 while the upstream driver is 1000 Mbps. Still need to
enhance performance.

[Release-log]
N/A


Change-Id: I15d2550cb3190c47a79da82c8654dea6647bd101
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/8838386
diff --git a/feed/kernel/crypto-eip/src/ddk-wrapper.c b/feed/kernel/crypto-eip/src/ddk-wrapper.c
index 1fb1e3d..c07b2de 100644
--- a/feed/kernel/crypto-eip/src/ddk-wrapper.c
+++ b/feed/kernel/crypto-eip/src/ddk-wrapper.c
@@ -20,7 +20,61 @@
 #include "crypto-eip/crypto-eip.h"
 #include "crypto-eip/ddk-wrapper.h"
 #include "crypto-eip/internal.h"
-#include "crypto-eip/crypto-eip197-inline-ddk.h"
+
+LIST_HEAD(result_list);
+
+void crypto_free_sa(void *sa_pointer)
+{
+	DMABuf_Handle_t SAHandle = {0};
+
+	SAHandle.p = sa_pointer;
+	PEC_SA_UnRegister(PEC_INTERFACE_ID, SAHandle, DMABuf_NULLHandle,
+				DMABuf_NULLHandle);
+	DMABuf_Release(SAHandle);
+}
+
+void crypto_free_token(void *token)
+{
+	DMABuf_Handle_t TokenHandle = {0};
+
+	TokenHandle.p = token;
+	DMABuf_Release(TokenHandle);
+}
+
+/* TODO: to be remove*/
+void crypto_free_pkt(void *pkt)
+{
+	DMABuf_Handle_t PktHandle = {0};
+
+	PktHandle.p = pkt;
+	DMABuf_Release(PktHandle);
+}
+
+void crypto_free_sglist(void *sglist)
+{
+	PEC_Status_t res;
+	unsigned int count;
+	unsigned int size;
+	DMABuf_Handle_t SGListHandle = {0};
+	DMABuf_Handle_t ParticleHandle = {0};
+	int i;
+	uint8_t *Particle_p;
+
+	SGListHandle.p = sglist;
+	res = PEC_SGList_GetCapacity(SGListHandle, &count);
+	if (res != PEC_STATUS_OK)
+		return;
+	for (i = 0; i < count; i++) {
+		PEC_SGList_Read(SGListHandle,
+						i,
+						&ParticleHandle,
+						&size,
+						&Particle_p);
+		DMABuf_Particle_Release(ParticleHandle);
+	}
+
+	PEC_SGList_Destroy(SGListHandle);
+}
 
 static bool crypto_iotoken_create(IOToken_Input_Dscr_t * const dscr_p,
 				  void * const ext_p, u32 *data_p,
@@ -28,75 +82,1610 @@
 {
 	int IOTokenRc;
 
+	dscr_p->InPacket_ByteCount = pec_cmd_dscr->SrcPkt_ByteCount;
+	dscr_p->Ext_p = ext_p;
+
+	IOTokenRc = IOToken_Create(dscr_p, data_p);
+	if (IOTokenRc < 0) {
+		CRYPTO_ERR("IOToken_Create error %d\n", IOTokenRc);
+		return false;
+	}
+
+	pec_cmd_dscr->InputToken_p = data_p;
+
+	return true;
+}
+
+unsigned int crypto_pe_busy_get_one(IOToken_Output_Dscr_t *const OutTokenDscr_p,
+			       u32 *OutTokenData_p,
+			       PEC_ResultDescriptor_t *RD_p)
+{
+	int LoopCounter = MTK_EIP197_INLINE_NOF_TRIES;
+	int IOToken_Rc;
+	PEC_Status_t pecres;
+
+	ZEROINIT(*OutTokenDscr_p);
+	ZEROINIT(*RD_p);
+
+	/* Link data structures */
+	RD_p->OutputToken_p = OutTokenData_p;
+
+	while (LoopCounter > 0) {
+		/* Try to get the processed packet from the driver */
+		unsigned int Counter = 0;
+
+		pecres = PEC_Packet_Get(PEC_INTERFACE_ID, RD_p, 1, &Counter);
+		if (pecres != PEC_STATUS_OK) {
+			/* IO error */
+			CRYPTO_ERR("PEC_Packet_Get error %d\n", pecres);
+			return 0;
+		}
+
+		if (Counter) {
+			IOToken_Rc = IOToken_Parse(OutTokenData_p, OutTokenDscr_p);
+			if (IOToken_Rc < 0) {
+				/* IO error */
+				CRYPTO_ERR("IOToken_Parse error %d\n", IOToken_Rc);
+				return 0;
+			}
+
+			if (OutTokenDscr_p->ErrorCode != 0) {
+				/* Packet process error */
+				CRYPTO_ERR("Result descriptor error 0x%x\n",
+					OutTokenDscr_p->ErrorCode);
+				return 0;
+			}
+
+			/* packet received */
+			return Counter;
+		}
+
+		/* Wait for MTK_EIP197_PKT_GET_TIMEOUT_MS milliseconds */
+		udelay(MTK_EIP197_PKT_GET_TIMEOUT_MS);
+		LoopCounter--;
+	}
+
+	/* IO error (timeout, not result packet received) */
+	return 0;
+}
+
+unsigned int crypto_pe_get_one(IOToken_Output_Dscr_t *const OutTokenDscr_p,
+			       u32 *OutTokenData_p,
+			       PEC_ResultDescriptor_t *RD_p)
+{
+	int IOToken_Rc;
+	unsigned int Counter = 0;
+	PEC_Status_t pecres;
+
+	ZEROINIT(*OutTokenDscr_p);
+	ZEROINIT(*RD_p);
+
+	RD_p->OutputToken_p = OutTokenData_p;
+
+	/* Try to get the processed packet from the driver */
+	pecres = PEC_Packet_Get(PEC_INTERFACE_ID, RD_p, 1, &Counter);
+	if (pecres != PEC_STATUS_OK) {
+		/* IO error */
+		CRYPTO_ERR("PEC_Packet_Get error %d\n", pecres);
+		return 0;
+	}
+
+	if (Counter) {
+		IOToken_Rc = IOToken_Parse(OutTokenData_p, OutTokenDscr_p);
+		if (IOToken_Rc < 0) {
+			/* IO error */
+			CRYPTO_ERR("IOToken_Parse error %d\n", IOToken_Rc);
+			return 0;
+		}
+		if (OutTokenDscr_p->ErrorCode != 0) {
+			/* Packet process error */
+			CRYPTO_ERR("Result descriptor error 0x%x\n",
+				OutTokenDscr_p->ErrorCode);
+			return 0;
+		}
+		/* packet received */
+		return Counter;
+	}
+
+	/* IO error (timeout, not result packet received) */
+	return 0;
+}
+
+SABuilder_Crypto_Mode_t lookaside_match_alg_mode(enum mtk_crypto_cipher_mode mode)
+{
+	switch (mode) {
+	case MTK_CRYPTO_MODE_CBC:
+		return SAB_CRYPTO_MODE_CBC;
+	case MTK_CRYPTO_MODE_ECB:
+		return SAB_CRYPTO_MODE_ECB;
+	case MTK_CRYPTO_MODE_OFB:
+		return SAB_CRYPTO_MODE_OFB;
+	case MTK_CRYPTO_MODE_CFB:
+		return SAB_CRYPTO_MODE_CFB;
+	case MTK_CRYPTO_MODE_CTR:
+		return SAB_CRYPTO_MODE_CTR;
+	case MTK_CRYPTO_MODE_GCM:
+		return SAB_CRYPTO_MODE_GCM;
+	case MTK_CRYPTO_MODE_GMAC:
+		return SAB_CRYPTO_MODE_GMAC;
+	case MTK_CRYPTO_MODE_CCM:
+		return SAB_CRYPTO_MODE_CCM;
+	default:
+		return SAB_CRYPTO_MODE_BASIC;
+	}
+}
+
+SABuilder_Crypto_t lookaside_match_alg_name(enum mtk_crypto_alg alg)
+{
+	switch (alg) {
+	case MTK_CRYPTO_AES:
+		return SAB_CRYPTO_AES;
+	case MTK_CRYPTO_DES:
+		return SAB_CRYPTO_DES;
+	case MTK_CRYPTO_3DES:
+		return SAB_CRYPTO_3DES;
+	default:
+		return SAB_CRYPTO_NULL;
+	}
+}
+
+SABuilder_Auth_t aead_hash_match(enum mtk_crypto_alg alg)
+{
+	switch (alg) {
+	case MTK_CRYPTO_ALG_SHA1:
+		return SAB_AUTH_HMAC_SHA1;
+	case MTK_CRYPTO_ALG_SHA224:
+		return SAB_AUTH_HMAC_SHA2_224;
+	case MTK_CRYPTO_ALG_SHA256:
+		return SAB_AUTH_HMAC_SHA2_256;
+	case MTK_CRYPTO_ALG_SHA384:
+		return SAB_AUTH_HMAC_SHA2_384;
+	case MTK_CRYPTO_ALG_SHA512:
+		return SAB_AUTH_HMAC_SHA2_512;
+	case MTK_CRYPTO_ALG_MD5:
+		return SAB_AUTH_HMAC_MD5;
+	case MTK_CRYPTO_ALG_GCM:
+		return SAB_AUTH_AES_GCM;
+	case MTK_CRYPTO_ALG_GMAC:
+		return SAB_AUTH_AES_GMAC;
+	case MTK_CRYPTO_ALG_CCM:
+		return SAB_AUTH_AES_CCM;
+	default:
+		return SAB_AUTH_NULL;
+	}
+}
+
+void mtk_crypto_interrupt_handler(void)
+{
+	struct mtk_crypto_result *rd;
+	struct mtk_crypto_context *ctx;
+	IOToken_Output_Dscr_t OutTokenDscr;
+	PEC_ResultDescriptor_t Res;
+	uint32_t OutputToken[IOTOKEN_OUT_WORD_COUNT];
+	int ret = 0;
+
+	while (true) {
+		if (list_empty(&result_list))
+			return;
+		rd = list_first_entry(&result_list, struct mtk_crypto_result, list);
+
+		if (crypto_pe_get_one(&OutTokenDscr, OutputToken, &Res) < 1) {
+			PEC_NotifyFunction_t CBFunc;
+
+			CBFunc = mtk_crypto_interrupt_handler;
+			if (OutTokenDscr.ErrorCode == 0) {
+				PEC_ResultNotify_Request(PEC_INTERFACE_ID, CBFunc, 1);
+				return;
+			} else if (OutTokenDscr.ErrorCode & BIT(9)) {
+				ret = -EBADMSG;
+			} else if (OutTokenDscr.ErrorCode == 0x4003) {
+				ret = 0;
+			} else
+				ret = 1;
+
+			CRYPTO_ERR("error from crypto_pe_get_one: %d\n", ret);
+		}
+
+		ctx = crypto_tfm_ctx(rd->async->tfm);
+		ret = ctx->handle_result(rd, ret);
+
+		spin_lock_bh(&add_lock);
+		list_del(&rd->list);
+		spin_unlock_bh(&add_lock);
+		kfree(rd);
+	}
+}
+
+int crypto_aead_cipher(struct crypto_async_request *async, struct mtk_crypto_cipher_req *mtk_req,
+		       struct scatterlist *src, struct scatterlist *dst, unsigned int cryptlen,
+		       unsigned int assoclen, unsigned int digestsize, u8 *iv, unsigned int ivsize)
+{
+	struct mtk_crypto_cipher_ctx *ctx = crypto_tfm_ctx(async->tfm);
+	struct mtk_crypto_result *result;
+	struct scatterlist *sg;
+	unsigned int totlen_src;
+	unsigned int totlen_dst;
+	unsigned int src_pkt =  cryptlen + assoclen;
+	unsigned int pass_assoc = 0;
+	int pass_id;
+	int rc;
+	int i;
+	SABuilder_Params_t params;
+	SABuilder_Params_Basic_t ProtocolParams;
+	unsigned int SAWords = 0;
+
+	DMABuf_Status_t DMAStatus;
+	DMABuf_Properties_t DMAProperties = {0, 0, 0, 0};
+	DMABuf_HostAddress_t SAHostAddress;
+	DMABuf_HostAddress_t TokenHostAddress;
+	DMABuf_HostAddress_t PktHostAddress;
+
+	DMABuf_Handle_t SAHandle = {0};
+	DMABuf_Handle_t TokenHandle = {0};
+	DMABuf_Handle_t SrcSGListHandle = {0};
+	DMABuf_Handle_t DstSGListHandle = {0};
+
+	unsigned int TCRWords = 0;
+	void *TCRData = 0;
+	unsigned int TokenWords = 0;
+	unsigned int TokenHeaderWord;
+	unsigned int TokenMaxWords = 0;
+
+	TokenBuilder_Params_t TokenParams;
+	PEC_CommandDescriptor_t Cmd;
+	PEC_NotifyFunction_t CBFunc;
+	unsigned int count;
+
+	IOToken_Input_Dscr_t InTokenDscr;
+	IOToken_Output_Dscr_t OutTokenDscr;
+	uint32_t InputToken[IOTOKEN_IN_WORD_COUNT];
+	void *InTokenDscrExt_p = NULL;
+	uint8_t gcm_iv[16] = {0};
+	uint8_t *aad = NULL;
+
+#ifdef CRYPTO_IOTOKEN_EXT
+	IOToken_Input_Dscr_Ext_t InTokenDscrExt;
+
+	ZEROINIT(InTokenDscrExt);
+	InTokenDscrExt_p = &InTokenDscrExt;
+#endif
+	ZEROINIT(InTokenDscr);
+	ZEROINIT(OutTokenDscr);
+
+	/* Init SA */
+	if (mtk_req->direction == MTK_CRYPTO_ENCRYPT) {
+		totlen_src = cryptlen + assoclen;
+		totlen_dst = totlen_src + digestsize;
+		rc = SABuilder_Init_Basic(&params, &ProtocolParams, SAB_DIRECTION_OUTBOUND);
+	} else {
+		totlen_src = cryptlen + assoclen;
+		totlen_dst = totlen_src - digestsize;
+		rc = SABuilder_Init_Basic(&params, &ProtocolParams, SAB_DIRECTION_INBOUND);
+	}
+	if (rc) {
+		CRYPTO_ERR("SABuilder_Init_Basic failed: %d\n", rc);
+		goto error_exit;
+	}
+
+	/* Build SA */
+	params.CryptoAlgo = lookaside_match_alg_name(ctx->alg);
+	params.CryptoMode = lookaside_match_alg_mode(ctx->mode);
+	params.KeyByteCount = ctx->key_len;
+	params.Key_p = (uint8_t *) ctx->key;
+	if (params.CryptoMode == SAB_CRYPTO_MODE_GCM && ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP) {
+		params.Nonce_p = (uint8_t *) &ctx->nonce;
+		params.IVSrc = SAB_IV_SRC_TOKEN;
+		params.flags |= SAB_FLAG_COPY_IV;
+		memcpy(gcm_iv, &ctx->nonce, 4);
+		memcpy(gcm_iv + 4, iv, ivsize);
+		gcm_iv[15] = 1;
+	} else if (params.CryptoMode == SAB_CRYPTO_MODE_GMAC) {
+		params.Nonce_p = (uint8_t *) &ctx->nonce;
+		params.IVSrc = SAB_IV_SRC_TOKEN;
+		memcpy(gcm_iv, &ctx->nonce, 4);
+		memcpy(gcm_iv + 4, iv, ivsize);
+		gcm_iv[15] = 1;
+	} else if (params.CryptoMode == SAB_CRYPTO_MODE_GCM) {
+		params.IVSrc = SAB_IV_SRC_TOKEN;
+		memcpy(gcm_iv, iv, ivsize);
+		gcm_iv[15] = 1;
+	} else if (params.CryptoMode == SAB_CRYPTO_MODE_CCM) {
+		params.IVSrc = SAB_IV_SRC_SA;
+		params.Nonce_p = (uint8_t *) &ctx->nonce + 1;
+		params.IV_p = iv;
+	} else {
+		params.IVSrc = SAB_IV_SRC_SA;
+		params.IV_p = iv;
+	}
+
+	if (params.CryptoMode == SAB_CRYPTO_MODE_CTR)
+		params.Nonce_p = (uint8_t *) &ctx->nonce;
+
+	params.AuthAlgo = aead_hash_match(ctx->hash_alg);
+	params.AuthKey1_p = (uint8_t *) ctx->ipad;
+	params.AuthKey2_p = (uint8_t *) ctx->opad;
+
+	ProtocolParams.ICVByteCount = digestsize;
+
+	rc = SABuilder_GetSizes(&params, &SAWords, NULL, NULL);
+	if (rc) {
+		CRYPTO_ERR("SA not created because of size errors: %d\n", rc);
+		goto error_remove_sg;
+	}
+
+	DMAProperties.fCached = true;
+	DMAProperties.Alignment = MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT;
+	DMAProperties.Bank = MTK_EIP197_INLINE_BANK_TRANSFORM;
+	DMAProperties.Size = MAX(4*SAWords, 256);
+
+	DMAStatus = DMABuf_Alloc(DMAProperties, &SAHostAddress, &SAHandle);
+	if (DMAStatus != DMABUF_STATUS_OK) {
+		rc = 1;
+		CRYPTO_ERR("Allocation of SA failed: %d\n", DMAStatus);
+		goto error_remove_sg;
+	}
+
+	rc = SABuilder_BuildSA(&params, (u32 *)SAHostAddress.p, NULL, NULL);
+	if (rc) {
+		CRYPTO_ERR("SA not created because of errors: %d\n", rc);
+		goto error_remove_sg;
+	}
+
+	/* Check dst buffer has enough size */
+	mtk_req->nr_src = sg_nents_for_len(src, totlen_src);
+	mtk_req->nr_dst = sg_nents_for_len(dst, totlen_dst);
+
+	if (src == dst) {
+		mtk_req->nr_src = max(mtk_req->nr_src, mtk_req->nr_dst);
+		mtk_req->nr_dst = mtk_req->nr_src;
+		if (unlikely((totlen_src || totlen_dst) && (mtk_req->nr_src <= 0))) {
+			CRYPTO_ERR("In-place buffer not large enough\n");
+			return -EINVAL;
+		}
+		dma_map_sg(crypto_dev, src, mtk_req->nr_src, DMA_BIDIRECTIONAL);
+	} else {
+		if (unlikely(totlen_src && (mtk_req->nr_src <= 0))) {
+			CRYPTO_ERR("Source buffer not large enough\n");
+			return -EINVAL;
+		}
+		dma_map_sg(crypto_dev, src, mtk_req->nr_src, DMA_TO_DEVICE);
+
+		if (unlikely(totlen_dst && (mtk_req->nr_dst <= 0))) {
+			CRYPTO_ERR("Dest buffer not large enough\n");
+			dma_unmap_sg(crypto_dev, src, mtk_req->nr_src, DMA_TO_DEVICE);
+			return -EINVAL;
+		}
+		dma_map_sg(crypto_dev, dst, mtk_req->nr_dst, DMA_FROM_DEVICE);
+	}
+
+	if (params.CryptoMode == SAB_CRYPTO_MODE_CCM ||
+		(params.CryptoMode == SAB_CRYPTO_MODE_GCM &&
+		 ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP)) {
+
+		aad = kmalloc(assoclen, GFP_KERNEL);
+		if (!aad)
+			goto error_remove_sg;
+		sg_copy_to_buffer(src, mtk_req->nr_src, aad, assoclen);
+		src_pkt -= assoclen;
+		pass_assoc = assoclen;
+	}
+
+	/* Assign sg list */
+	rc = PEC_SGList_Create(MAX(mtk_req->nr_src, 1), &SrcSGListHandle);
+	if (rc != PEC_STATUS_OK) {
+		CRYPTO_ERR("PEC_SGList_Create src failed with rc = %d\n", rc);
+		goto error_remove_sg;
+	}
+
+	pass_id = 0;
+	DMAProperties.fCached = true;
+	DMAProperties.Alignment = MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT;
+	DMAProperties.Bank = MTK_EIP197_INLINE_BANK_PACKET;
+	for_each_sg(src, sg, mtk_req->nr_src, i) {
+		int len = sg_dma_len(sg);
+		DMABuf_Handle_t sg_handle;
+		DMABuf_HostAddress_t host;
+
+		if (totlen_src < len)
+			len = totlen_src;
+
+		if (pass_assoc) {
+			if (pass_assoc >= len) {
+				pass_assoc -= len;
+				pass_id++;
+				continue;
+			}
+			DMAProperties.Size = MAX(len - pass_assoc, 1);
+			rc = DMABuf_Particle_Alloc(DMAProperties, sg_dma_address(sg) + pass_assoc,
+							&host, &sg_handle);
+			if (rc != DMABUF_STATUS_OK) {
+				CRYPTO_ERR("DMABuf_Particle_Alloc failed rc = %d\n", rc);
+				goto error_remove_sg;
+			}
+			rc = PEC_SGList_Write(SrcSGListHandle, i - pass_id, sg_handle,
+						len - pass_assoc);
+			if (rc != PEC_STATUS_OK)
+				pr_notice("PEC_SGList_Write failed rc = %d\n", rc);
+			pass_assoc = 0;
+		} else {
+			DMAProperties.Size = MAX(len, 1);
+			rc = DMABuf_Particle_Alloc(DMAProperties, sg_dma_address(sg),
+							&host, &sg_handle);
+			if (rc != DMABUF_STATUS_OK) {
+				CRYPTO_ERR("DMABuf_Particle_Alloc failed rc = %d\n", rc);
+				goto error_remove_sg;
+			}
+
+			rc = PEC_SGList_Write(SrcSGListHandle, i - pass_id, sg_handle, len);
+			if (rc != PEC_STATUS_OK)
+				pr_notice("PEC_SGList_Write failed rc = %d\n", rc);
+		}
+
+		totlen_src -= len;
+		if (!totlen_src)
+			break;
+	}
+
+	/* Alloc sg list for result */
+	rc = PEC_SGList_Create(MAX(mtk_req->nr_dst, 1), &DstSGListHandle);
+	if (rc != PEC_STATUS_OK) {
+		CRYPTO_ERR("PEC_SGList_Create dst failed with rc = %d\n", rc);
+		goto error_remove_sg;
+	}
+
+	for_each_sg(dst, sg, mtk_req->nr_dst, i) {
+		int len = sg_dma_len(sg);
+		DMABuf_Handle_t sg_handle;
+		DMABuf_HostAddress_t host;
+
+		if (len > totlen_dst)
+			len = totlen_dst;
+
+		DMAProperties.Size = MAX(len, 1);
+		rc = DMABuf_Particle_Alloc(DMAProperties, sg_dma_address(sg), &host, &sg_handle);
+		if (rc != DMABUF_STATUS_OK) {
+			CRYPTO_ERR("DMABuf_Particle_Alloc failed rc = %d\n", rc);
+			goto error_remove_sg;
+		}
+		rc = PEC_SGList_Write(DstSGListHandle, i, sg_handle, len);
+		if (rc != PEC_STATUS_OK)
+			pr_notice("PEC_SGList_Write failed rc = %d\n", rc);
+
+		if (unlikely(!len))
+			break;
+		totlen_dst -= len;
+	}
+
+	/* Build Token */
+	rc = TokenBuilder_GetContextSize(&params, &TCRWords);
+	if (rc) {
+		CRYPTO_ERR("TokenBuilder_GetContextSize returned errors: %d\n", rc);
+		goto error_remove_sg;
+	}
+
+	TCRData = kmalloc(4 * TCRWords, GFP_KERNEL);
+	if (!TCRData) {
+		rc = 1;
+		CRYPTO_ERR("Allocation of TCR failed\n");
+		goto error_remove_sg;
+	}
+
+	rc = TokenBuilder_BuildContext(&params, TCRData);
+	if (rc) {
+		CRYPTO_ERR("TokenBuilder_BuildContext failed: %d\n", rc);
+		goto error_remove_sg;
+	}
+
+	rc = TokenBuilder_GetSize(TCRData, &TokenMaxWords);
+	if (rc) {
+		CRYPTO_ERR("TokenBuilder_GetSize failed: %d\n", rc);
+		goto error_remove_sg;
+	}
+
+	DMAProperties.fCached = true;
+	DMAProperties.Alignment = MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT;
+	DMAProperties.Bank = MTK_EIP197_INLINE_BANK_TOKEN;
+	DMAProperties.Size = 4*TokenMaxWords;
+
+	DMAStatus = DMABuf_Alloc(DMAProperties, &TokenHostAddress, &TokenHandle);
+	if (DMAStatus != DMABUF_STATUS_OK) {
+		rc = 1;
+		CRYPTO_ERR("Allocation of token builder failed: %d\n", DMAStatus);
+		goto error_remove_sg;
+	}
+
+	rc = PEC_SA_Register(PEC_INTERFACE_ID, SAHandle, DMABuf_NULLHandle,
+				DMABuf_NULLHandle);
+	if (rc != PEC_STATUS_OK) {
+		CRYPTO_ERR("PEC_SA_Register failed: %d\n", rc);
+		goto error_remove_sg;
+	}
+
+	ZEROINIT(TokenParams);
+
+	if (params.CryptoMode == SAB_CRYPTO_MODE_GCM || params.CryptoMode == SAB_CRYPTO_MODE_GMAC)
+		TokenParams.IV_p = gcm_iv;
+
+	if ((params.CryptoMode == SAB_CRYPTO_MODE_GCM && ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP) ||
+	     params.CryptoMode == SAB_CRYPTO_MODE_CCM) {
+		TokenParams.AdditionalValue = assoclen - ivsize;
+		TokenParams.AAD_p = aad;
+	} else if (params.CryptoMode != SAB_CRYPTO_MODE_GMAC)
+		TokenParams.AdditionalValue = assoclen;
+
+
+	PktHostAddress.p = kmalloc(sizeof(uint8_t), GFP_KERNEL);
+	rc = TokenBuilder_BuildToken(TCRData, (uint8_t *)PktHostAddress.p, src_pkt,
+					&TokenParams, (uint32_t *)TokenHostAddress.p,
+					&TokenWords, &TokenHeaderWord);
+	kfree(PktHostAddress.p);
+	if (rc != TKB_STATUS_OK) {
+		CRYPTO_ERR("Token builder failed: %d\n", rc);
+		goto error_exit_unregister;
+	}
+
+	ZEROINIT(Cmd);
+	Cmd.Token_Handle = TokenHandle;
+	Cmd.Token_WordCount = TokenWords;
+	Cmd.SrcPkt_Handle = SrcSGListHandle;
+	Cmd.SrcPkt_ByteCount = src_pkt;
+	Cmd.DstPkt_Handle = DstSGListHandle;
+	Cmd.SA_Handle1 = SAHandle;
+	Cmd.SA_Handle2 = DMABuf_NULLHandle;
+
+	#if defined(CRYPTO_IOTOKEN_EXT)
+	InTokenDscrExt.HW_Services = IOTOKEN_CMD_PKT_LAC;
+#endif
+	InTokenDscr.TknHdrWordInit = TokenHeaderWord;
+
+	if (!crypto_iotoken_create(&InTokenDscr,
+				   InTokenDscrExt_p,
+				   InputToken,
+				   &Cmd)) {
+		rc = 1;
+		goto error_exit_unregister;
+	}
+
+	rc = PEC_Packet_Put(PEC_INTERFACE_ID, &Cmd, 1, &count);
+	if (rc != PEC_STATUS_OK && count != 1)
+		goto error_exit_unregister;
+
+	result = kmalloc(sizeof(struct mtk_crypto_result), GFP_KERNEL);
+	if (!result) {
+		rc = 1;
+		CRYPTO_ERR("No memory for result\n");
+		goto error_exit_unregister;
+	}
+	INIT_LIST_HEAD(&result->list);
+	result->eip.sa = SAHandle.p;
+	result->eip.token = TokenHandle.p;
+	result->eip.token_context = TCRData;
+	result->eip.pkt_handle = SrcSGListHandle.p;
+	result->async = async;
+	result->dst = DstSGListHandle.p;
+
+	spin_lock_bh(&add_lock);
+	list_add_tail(&result->list, &result_list);
+	spin_unlock_bh(&add_lock);
+	CBFunc = mtk_crypto_interrupt_handler;
+	rc = PEC_ResultNotify_Request(PEC_INTERFACE_ID, CBFunc, 1);
+	if (rc != PEC_STATUS_OK) {
+		CRYPTO_ERR("PEC_ResultNotify_Request failed with rc = %d\n", rc);
+		goto error_exit_unregister;
+	}
+
+	return rc;
+
+error_exit_unregister:
+	PEC_SA_UnRegister(PEC_INTERFACE_ID, SAHandle, DMABuf_NULLHandle,
+				DMABuf_NULLHandle);
+error_remove_sg:
+	if (src == dst) {
+		dma_unmap_sg(crypto_dev, src, mtk_req->nr_src, DMA_BIDIRECTIONAL);
+	} else {
+		dma_unmap_sg(crypto_dev, src, mtk_req->nr_src, DMA_TO_DEVICE);
+		dma_unmap_sg(crypto_dev, dst, mtk_req->nr_dst, DMA_FROM_DEVICE);
+	}
+
+	if (aad != NULL)
+		kfree(aad);
+
+	crypto_free_sglist(SrcSGListHandle.p);
+	crypto_free_sglist(DstSGListHandle.p);
+
+error_exit:
+	DMABuf_Release(SAHandle);
+	DMABuf_Release(TokenHandle);
+
+	if (TCRData != NULL)
+		kfree(TCRData);
+
+	return rc;
+}
+
+int crypto_basic_cipher(struct crypto_async_request *async, struct mtk_crypto_cipher_req *mtk_req,
+			struct scatterlist *src, struct scatterlist *dst, unsigned int cryptlen,
+			unsigned int assoclen, unsigned int digestsize, u8 *iv, unsigned int ivsize)
+{
+	struct mtk_crypto_cipher_ctx *ctx = crypto_tfm_ctx(async->tfm);
+	struct skcipher_request *areq = skcipher_request_cast(async);
+	struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(areq);
+	struct mtk_crypto_result *result;
+	struct scatterlist *sg;
+	unsigned int totlen_src = cryptlen + assoclen;
+	unsigned int totlen_dst = totlen_src;
+	unsigned int blksize = crypto_skcipher_blocksize(skcipher);
+	int rc;
+	int i;
+	SABuilder_Params_t params;
+	SABuilder_Params_Basic_t ProtocolParams;
+	unsigned int SAWords = 0;
+
+	DMABuf_Status_t DMAStatus;
+	DMABuf_Properties_t DMAProperties = {0, 0, 0, 0};
+	DMABuf_HostAddress_t SAHostAddress;
+	DMABuf_HostAddress_t TokenHostAddress;
+	DMABuf_HostAddress_t PktHostAddress;
+
+	DMABuf_Handle_t SAHandle = {0};
+	DMABuf_Handle_t TokenHandle = {0};
+	DMABuf_Handle_t SrcSGListHandle = {0};
+	DMABuf_Handle_t DstSGListHandle = {0};
+
+	unsigned int TCRWords = 0;
+	void *TCRData = 0;
+	unsigned int TokenWords = 0;
+	unsigned int TokenHeaderWord;
+	unsigned int TokenMaxWords = 0;
+
+	TokenBuilder_Params_t TokenParams;
+	PEC_CommandDescriptor_t Cmd;
+	unsigned int count;
+
+	IOToken_Input_Dscr_t InTokenDscr;
+	IOToken_Output_Dscr_t OutTokenDscr;
+	uint32_t InputToken[IOTOKEN_IN_WORD_COUNT];
+	void *InTokenDscrExt_p = NULL;
+	PEC_NotifyFunction_t CBFunc;
+
+#ifdef CRYPTO_IOTOKEN_EXT
+	IOToken_Input_Dscr_Ext_t InTokenDscrExt;
+
+	ZEROINIT(InTokenDscrExt);
+	InTokenDscrExt_p = &InTokenDscrExt;
+#endif
+	ZEROINIT(InTokenDscr);
+	ZEROINIT(OutTokenDscr);
+
+	/* If the data is not aligned with block size, return invalid */
+	if (!IS_ALIGNED(cryptlen, blksize))
+		return -EINVAL;
+
+	/* Init SA */
+	if (mtk_req->direction == MTK_CRYPTO_ENCRYPT)
+		rc = SABuilder_Init_Basic(&params, &ProtocolParams, SAB_DIRECTION_OUTBOUND);
+	else
+		rc = SABuilder_Init_Basic(&params, &ProtocolParams, SAB_DIRECTION_INBOUND);
+	if (rc) {
+		CRYPTO_ERR("SABuilder_Init_Basic failed: %d\n", rc);
+		goto error_exit;
+	}
+
+	/* Build SA */
+	params.CryptoAlgo = lookaside_match_alg_name(ctx->alg);
+	params.CryptoMode = lookaside_match_alg_mode(ctx->mode);
+	params.KeyByteCount = ctx->key_len;
+	params.Key_p = (uint8_t *) ctx->key;
+	params.IVSrc = SAB_IV_SRC_SA;
+	if (params.CryptoMode == SAB_CRYPTO_MODE_CTR)
+		params.Nonce_p = (uint8_t *) &ctx->nonce;
+	params.IV_p = iv;
+
+	rc = SABuilder_GetSizes(&params, &SAWords, NULL, NULL);
+	if (rc) {
+		CRYPTO_ERR("SA not created because of size errors: %d\n", rc);
+		goto error_exit;
+	}
+
+	DMAProperties.fCached = true;
+	DMAProperties.Alignment = MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT;
+	DMAProperties.Bank = MTK_EIP197_INLINE_BANK_TRANSFORM;
+	DMAProperties.Size = MAX(4*SAWords, 256);
+
+	DMAStatus = DMABuf_Alloc(DMAProperties, &SAHostAddress, &SAHandle);
+	if (DMAStatus != DMABUF_STATUS_OK) {
+		rc = 1;
+		CRYPTO_ERR("Allocation of SA failed: %d\n", DMAStatus);
+		goto error_exit;
+	}
+
+	rc = SABuilder_BuildSA(&params, (u32 *)SAHostAddress.p, NULL, NULL);
+	if (rc) {
+		CRYPTO_ERR("SA not created because of errors: %d\n", rc);
+		goto error_exit;
+	}
+
+	/* Build Token */
+	rc = TokenBuilder_GetContextSize(&params, &TCRWords);
+	if (rc) {
+		CRYPTO_ERR("TokenBuilder_GetContextSize returned errors: %d\n", rc);
+		goto error_exit;
+	}
+
+	TCRData = kmalloc(4 * TCRWords, GFP_KERNEL);
+	if (!TCRData) {
+		rc = 1;
+		CRYPTO_ERR("Allocation of TCR failed\n");
+		goto error_exit;
+	}
+
+	rc = TokenBuilder_BuildContext(&params, TCRData);
+	if (rc) {
+		CRYPTO_ERR("TokenBuilder_BuildContext failed: %d\n", rc);
+		goto error_exit;
+	}
+
+	rc = TokenBuilder_GetSize(TCRData, &TokenMaxWords);
+	if (rc) {
+		CRYPTO_ERR("TokenBuilder_GetSize failed: %d\n", rc);
+		goto error_exit;
+	}
+
+	DMAProperties.fCached = true;
+	DMAProperties.Alignment = MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT;
+	DMAProperties.Bank = MTK_EIP197_INLINE_BANK_TOKEN;
+	DMAProperties.Size = 4*TokenMaxWords;
+
+	DMAStatus = DMABuf_Alloc(DMAProperties, &TokenHostAddress, &TokenHandle);
+	if (DMAStatus != DMABUF_STATUS_OK) {
+		rc = 1;
+		CRYPTO_ERR("Allocation of token builder failed: %d\n", DMAStatus);
+		goto error_exit;
+	}
+
+	rc = PEC_SA_Register(PEC_INTERFACE_ID, SAHandle, DMABuf_NULLHandle,
+				DMABuf_NULLHandle);
+	if (rc != PEC_STATUS_OK) {
+		CRYPTO_ERR("PEC_SA_Register failed: %d\n", rc);
+		goto error_exit;
+	}
+
+	/* Check buffer has enough size for output */
+	mtk_req->nr_src = sg_nents_for_len(src, totlen_src);
+	mtk_req->nr_dst = sg_nents_for_len(dst, totlen_dst);
+
+	if (src == dst) {
+		mtk_req->nr_src = max(mtk_req->nr_src, mtk_req->nr_dst);
+		mtk_req->nr_dst = mtk_req->nr_src;
+		if (unlikely((totlen_src || totlen_dst) && (mtk_req->nr_src <= 0))) {
+			CRYPTO_ERR("In-place buffer not large enough\n");
+			return -EINVAL;
+		}
+		dma_map_sg(crypto_dev, src, mtk_req->nr_src, DMA_BIDIRECTIONAL);
+	} else {
+		if (unlikely(totlen_src && (mtk_req->nr_src <= 0))) {
+			CRYPTO_ERR("Source buffer not large enough\n");
+			return -EINVAL;
+		}
+		dma_map_sg(crypto_dev, src, mtk_req->nr_src, DMA_TO_DEVICE);
+
+		if (unlikely(totlen_dst && (mtk_req->nr_dst <= 0))) {
+			CRYPTO_ERR("Dest buffer not large enough\n");
+			dma_unmap_sg(crypto_dev, src, mtk_req->nr_src, DMA_TO_DEVICE);
+			return -EINVAL;
+		}
+		dma_map_sg(crypto_dev, dst, mtk_req->nr_dst, DMA_FROM_DEVICE);
+	}
+
+	rc = PEC_SGList_Create(MAX(mtk_req->nr_src, 1), &SrcSGListHandle);
+	if (rc != PEC_STATUS_OK) {
+		CRYPTO_ERR("PEC_SGList_Create src failed with rc = %d\n", rc);
+		goto error_remove_sg;
+	}
+
+	DMAProperties.fCached = true;
+	DMAProperties.Alignment = MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT;
+	DMAProperties.Bank = MTK_EIP197_INLINE_BANK_PACKET;
+	for_each_sg(src, sg, mtk_req->nr_src, i) {
+		int len = sg_dma_len(sg);
+		DMABuf_Handle_t sg_handle;
+		DMABuf_HostAddress_t host;
+
+		if (totlen_src < len)
+			len = totlen_src;
+
+		DMAProperties.Size = MAX(len, 1);
+		rc = DMABuf_Particle_Alloc(DMAProperties, sg_dma_address(sg), &host, &sg_handle);
+		if (rc != DMABUF_STATUS_OK) {
+			CRYPTO_ERR("DMABuf_Particle_Alloc failed rc = %d\n", rc);
+			goto error_remove_sg;
+		}
+		rc = PEC_SGList_Write(SrcSGListHandle, i, sg_handle, len);
+		if (rc != PEC_STATUS_OK)
+			pr_notice("PEC_SGList_Write failed rc = %d\n", rc);
+
+		totlen_src -= len;
+		if (!totlen_src)
+			break;
+	}
+
+	rc = PEC_SGList_Create(MAX(mtk_req->nr_dst, 1), &DstSGListHandle);
+	if (rc != PEC_STATUS_OK) {
+		CRYPTO_ERR("PEC_SGList_Create dst failed with rc = %d\n", rc);
+		goto error_remove_sg;
+	}
+
+	for_each_sg(dst, sg, mtk_req->nr_dst, i) {
+		int len = sg_dma_len(sg);
+		DMABuf_Handle_t sg_handle;
+		DMABuf_HostAddress_t host;
+
+		if (len > totlen_dst)
+			len = totlen_dst;
+
+		DMAProperties.Size = MAX(len, 1);
+		rc = DMABuf_Particle_Alloc(DMAProperties, sg_dma_address(sg), &host, &sg_handle);
+		if (rc != DMABUF_STATUS_OK) {
+			CRYPTO_ERR("DMABuf_Particle_Alloc failed rc = %d\n", rc);
+			goto error_remove_sg;
+		}
+		rc = PEC_SGList_Write(DstSGListHandle, i, sg_handle, len);
+
+		if (unlikely(!len))
+			break;
+		totlen_dst -= len;
+	}
+
+	if (params.CryptoMode == SAB_CRYPTO_MODE_CBC &&
+			mtk_req->direction == MTK_CRYPTO_DECRYPT)
+		sg_pcopy_to_buffer(src, mtk_req->nr_src, iv, ivsize, cryptlen - ivsize);
+
+	PktHostAddress.p = kmalloc(sizeof(uint8_t), GFP_KERNEL);
+	ZEROINIT(TokenParams);
+	rc = TokenBuilder_BuildToken(TCRData, (uint8_t *)PktHostAddress.p, cryptlen,
+					&TokenParams, (uint32_t *)TokenHostAddress.p,
+					&TokenWords, &TokenHeaderWord);
+	kfree(PktHostAddress.p);
+	if (rc != TKB_STATUS_OK) {
+		CRYPTO_ERR("Token builder failed: %d\n", rc);
+		goto error_remove_sg;
+	}
+
+	ZEROINIT(Cmd);
+	Cmd.Token_Handle = TokenHandle;
+	Cmd.Token_WordCount = TokenWords;
+	Cmd.SrcPkt_Handle = SrcSGListHandle;
+	Cmd.SrcPkt_ByteCount = cryptlen;
+	Cmd.DstPkt_Handle = DstSGListHandle;
+	Cmd.SA_Handle1 = SAHandle;
+	Cmd.SA_Handle2 = DMABuf_NULLHandle;
+
+#if defined(CRYPTO_IOTOKEN_EXT)
+	InTokenDscrExt.HW_Services = IOTOKEN_CMD_PKT_LAC;
+#endif
+	InTokenDscr.TknHdrWordInit = TokenHeaderWord;
+
+	if (!crypto_iotoken_create(&InTokenDscr,
+				   InTokenDscrExt_p,
+				   InputToken,
+				   &Cmd)) {
+		rc = 1;
+		goto error_remove_sg;
+	}
+
+	rc = PEC_Packet_Put(PEC_INTERFACE_ID, &Cmd, 1, &count);
+	if (rc != PEC_STATUS_OK && count != 1) {
+		rc = 1;
+		CRYPTO_ERR("PEC_Packet_Put error: %d\n", rc);
+		goto error_remove_sg;
+	}
+
+	result = kmalloc(sizeof(struct mtk_crypto_result), GFP_KERNEL);
+	if (!result) {
+		rc = 1;
+		CRYPTO_ERR("No memory for result\n");
+		goto error_remove_sg;
+	}
+	INIT_LIST_HEAD(&result->list);
+	result->eip.sa = SAHandle.p;
+	result->eip.token = TokenHandle.p;
+	result->eip.token_context = TCRData;
+	result->eip.pkt_handle = SrcSGListHandle.p;
+	result->async = async;
+	result->dst = DstSGListHandle.p;
+
+	spin_lock_bh(&add_lock);
+	list_add_tail(&result->list, &result_list);
+	spin_unlock_bh(&add_lock);
+	CBFunc = mtk_crypto_interrupt_handler;
+	rc = PEC_ResultNotify_Request(PEC_INTERFACE_ID, CBFunc, 1);
+	if (rc != PEC_STATUS_OK) {
+		CRYPTO_ERR("PEC_ResultNotify_Request failed with rc = %d\n", rc);
+		goto error_remove_sg;
+	}
+	return 0;
+
+error_remove_sg:
+	if (src == dst) {
+		dma_unmap_sg(crypto_dev, src, mtk_req->nr_src, DMA_BIDIRECTIONAL);
+	} else {
+		dma_unmap_sg(crypto_dev, src, mtk_req->nr_src, DMA_TO_DEVICE);
+		dma_unmap_sg(crypto_dev, dst, mtk_req->nr_dst, DMA_FROM_DEVICE);
+	}
+
+	crypto_free_sglist(SrcSGListHandle.p);
+	crypto_free_sglist(DstSGListHandle.p);
+
+	PEC_SA_UnRegister(PEC_INTERFACE_ID, SAHandle, DMABuf_NULLHandle,
+				DMABuf_NULLHandle);
+
+error_exit:
+	DMABuf_Release(SAHandle);
+	DMABuf_Release(TokenHandle);
+
+	if (TCRData != NULL)
+		kfree(TCRData);
+
+	return rc;
+}
+
+SABuilder_Auth_t lookaside_match_hash(enum mtk_crypto_alg alg)
+{
+	switch (alg) {
+	case MTK_CRYPTO_ALG_SHA1:
+		return SAB_AUTH_HASH_SHA1;
+	case MTK_CRYPTO_ALG_SHA224:
+		return SAB_AUTH_HASH_SHA2_224;
+	case MTK_CRYPTO_ALG_SHA256:
+		return SAB_AUTH_HASH_SHA2_256;
+	case MTK_CRYPTO_ALG_SHA384:
+		return SAB_AUTH_HASH_SHA2_384;
+	case MTK_CRYPTO_ALG_SHA512:
+		return SAB_AUTH_HASH_SHA2_512;
+	case MTK_CRYPTO_ALG_MD5:
+		return SAB_AUTH_HASH_MD5;
+	case MTK_CRYPTO_ALG_XCBC:
+		return SAB_AUTH_AES_XCBC_MAC;
+	case MTK_CRYPTO_ALG_CMAC_128:
+		return SAB_AUTH_AES_CMAC_128;
+	case MTK_CRYPTO_ALG_CMAC_192:
+		return SAB_AUTH_AES_CMAC_192;
+	case MTK_CRYPTO_ALG_CMAC_256:
+		return SAB_AUTH_AES_CMAC_256;
+	default:
+		return SAB_AUTH_NULL;
+	}
+}
+
+int crypto_ahash_token_req(struct crypto_async_request *async, struct mtk_crypto_ahash_req *mtk_req,
+				uint8_t *Input_p, unsigned int InputByteCount, bool finish)
+{
+	struct mtk_crypto_result *result;
+
+	DMABuf_Properties_t DMAProperties = {0, 0, 0, 0};
+	DMABuf_HostAddress_t TokenHostAddress;
+	DMABuf_HostAddress_t PktHostAddress;
+	DMABuf_Status_t DMAStatus;
+
+	DMABuf_Handle_t TokenHandle = {0};
+	DMABuf_Handle_t PktHandle = {0};
+	DMABuf_Handle_t SAHandle = {0};
+
+	unsigned int TokenMaxWords = 0;
+	unsigned int TokenHeaderWord;
+	unsigned int TokenWords = 0;
+	void *TCRData = 0;
+
+	TokenBuilder_Params_t TokenParams;
+	PEC_CommandDescriptor_t Cmd;
+	PEC_NotifyFunction_t CBFunc;
+
+	unsigned int count;
+	int rc;
+
+	u32 InputToken[IOTOKEN_IN_WORD_COUNT];
+	IOToken_Output_Dscr_t OutTokenDscr;
+	IOToken_Input_Dscr_t InTokenDscr;
+	void *InTokenDscrExt_p = NULL;
+
+#ifdef CRYPTO_IOTOKEN_EXT
+	IOToken_Input_Dscr_Ext_t InTokenDscrExt;
+
+	ZEROINIT(InTokenDscrExt);
+	InTokenDscrExt_p = &InTokenDscrExt;
+#endif
+	ZEROINIT(InTokenDscr);
+	ZEROINIT(OutTokenDscr);
+
+	TCRData = mtk_req->token_context;
+	rc = TokenBuilder_GetSize(TCRData, &TokenMaxWords);
+	if (rc) {
+		CRYPTO_ERR("TokenBuilder_GetSize failed: %d\n", rc);
+		goto error_exit;
+	}
+
+	DMAProperties.fCached = true;
+	DMAProperties.Alignment = MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT;
+	DMAProperties.Bank = MTK_EIP197_INLINE_BANK_TOKEN;
+	DMAProperties.Size = 4*TokenMaxWords;
+
+	DMAStatus = DMABuf_Alloc(DMAProperties, &TokenHostAddress, &TokenHandle);
+	if (DMAStatus != DMABUF_STATUS_OK) {
+		rc = 1;
+		CRYPTO_ERR("Allocation of token builder failed: %d\n", DMAStatus);
+		goto error_exit;
+	}
+
+	DMAProperties.fCached = true;
+	DMAProperties.Alignment = MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT;
+	DMAProperties.Bank = MTK_EIP197_INLINE_BANK_PACKET;
+	DMAProperties.Size = MAX(InputByteCount, mtk_req->digest_sz);
+
+	DMAStatus = DMABuf_Alloc(DMAProperties, &PktHostAddress, &PktHandle);
+	if (DMAStatus != DMABUF_STATUS_OK) {
+		rc = 1;
+		CRYPTO_ERR("Allocation of source packet buffer failed: %d\n",
+			   DMAStatus);
+		goto error_exit;
+	}
+	memcpy(PktHostAddress.p, Input_p, InputByteCount);
+
+	ZEROINIT(TokenParams);
+	TokenParams.PacketFlags |= TKB_PACKET_FLAG_HASHAPPEND;
+	if (finish)
+		TokenParams.PacketFlags |= TKB_PACKET_FLAG_HASHFINAL;
+
+	rc = TokenBuilder_BuildToken(TCRData, (u8 *) PktHostAddress.p,
+				     InputByteCount, &TokenParams,
+				     (u32 *) TokenHostAddress.p,
+				     &TokenWords, &TokenHeaderWord);
+	if (rc != TKB_STATUS_OK) {
+		CRYPTO_ERR("Token builder failed: %d\n", rc);
+		goto error_exit_unregister;
+	}
+
+	SAHandle.p = mtk_req->sa_pointer;
+	ZEROINIT(Cmd);
+	Cmd.Token_Handle = TokenHandle;
+	Cmd.Token_WordCount = TokenWords;
+	Cmd.SrcPkt_Handle = PktHandle;
+	Cmd.SrcPkt_ByteCount = InputByteCount;
+	Cmd.DstPkt_Handle = PktHandle;
+	Cmd.SA_Handle1 = SAHandle;
+	Cmd.SA_Handle2 = DMABuf_NULLHandle;
+
+#if defined(CRYPTO_IOTOKEN_EXT)
+	InTokenDscrExt.HW_Services  = IOTOKEN_CMD_PKT_LAC;
+#endif
+	InTokenDscr.TknHdrWordInit = TokenHeaderWord;
+
+	if (!crypto_iotoken_create(&InTokenDscr,
+				   InTokenDscrExt_p,
+				   InputToken,
+				   &Cmd)) {
+		rc = 1;
+		goto error_exit_unregister;
+	}
+
+	rc = PEC_Packet_Put(PEC_INTERFACE_ID, &Cmd, 1, &count);
+	if (rc != PEC_STATUS_OK && count != 1) {
+		rc = 1;
+		CRYPTO_ERR("PEC_Packet_Put error: %d\n", rc);
+		goto error_exit_unregister;
+	}
+
+	result = kmalloc(sizeof(struct mtk_crypto_result), GFP_KERNEL);
+	if (!result) {
+		rc = 1;
+		CRYPTO_ERR("No memory for result\n");
+		goto error_exit_unregister;
+	}
+	INIT_LIST_HEAD(&result->list);
+	result->eip.token = TokenHandle.p;
+	result->eip.pkt_handle = PktHandle.p;
+	result->async = async;
+	result->dst = PktHostAddress.p;
+
+	spin_lock_bh(&add_lock);
+	list_add_tail(&result->list, &result_list);
+	spin_unlock_bh(&add_lock);
+	CBFunc = mtk_crypto_interrupt_handler;
+	rc = PEC_ResultNotify_Request(PEC_INTERFACE_ID, CBFunc, 1);
+
+	return rc;
+
+error_exit_unregister:
+	PEC_SA_UnRegister(PEC_INTERFACE_ID, SAHandle, DMABuf_NULLHandle,
+				DMABuf_NULLHandle);
+
+error_exit:
+	DMABuf_Release(SAHandle);
+	DMABuf_Release(TokenHandle);
+	DMABuf_Release(PktHandle);
+
+	if (TCRData != NULL)
+		kfree(TCRData);
+
+	return rc;
+}
+
+int crypto_ahash_aes_cbc(struct crypto_async_request *async, struct mtk_crypto_ahash_req *mtk_req,
+				uint8_t *Input_p, unsigned int InputByteCount)
+{
+	struct mtk_crypto_ahash_ctx *ctx = crypto_tfm_ctx(async->tfm);
+	struct mtk_crypto_result *result;
+	SABuilder_Params_Basic_t ProtocolParams;
+	SABuilder_Params_t params;
+	unsigned int SAWords = 0;
+	int rc;
+
+	DMABuf_Properties_t DMAProperties = {0, 0, 0, 0};
+	DMABuf_HostAddress_t TokenHostAddress;
+	DMABuf_HostAddress_t PktHostAddress;
+	DMABuf_HostAddress_t SAHostAddress;
+	DMABuf_Status_t DMAStatus;
+
+	DMABuf_Handle_t TokenHandle = {0};
+	DMABuf_Handle_t PktHandle = {0};
+	DMABuf_Handle_t SAHandle = {0};
+
+	unsigned int TokenMaxWords = 0;
+	unsigned int TokenHeaderWord;
+	unsigned int TokenWords = 0;
+	unsigned int TCRWords = 0;
+	void *TCRData = 0;
+
+	TokenBuilder_Params_t TokenParams;
+	PEC_CommandDescriptor_t Cmd;
+	PEC_NotifyFunction_t CBFunc;
+
+	unsigned int count;
+	int i;
+
+	u32 InputToken[IOTOKEN_IN_WORD_COUNT];
+	IOToken_Output_Dscr_t OutTokenDscr;
+	IOToken_Input_Dscr_t InTokenDscr;
+	void *InTokenDscrExt_p = NULL;
+
+#ifdef CRYPTO_IOTOKEN_EXT
+	IOToken_Input_Dscr_Ext_t InTokenDscrExt;
+
+	ZEROINIT(InTokenDscrExt);
+	InTokenDscrExt_p = &InTokenDscrExt;
+#endif
+	ZEROINIT(InTokenDscr);
+	ZEROINIT(OutTokenDscr);
+
+	if (!IS_ALIGNED(InputByteCount, 16)) {
+		pr_notice("not aligned: %d\n", InputByteCount);
+		return -EINVAL;
+	}
+	rc = SABuilder_Init_Basic(&params, &ProtocolParams, SAB_DIRECTION_OUTBOUND);
+	if (rc) {
+		CRYPTO_ERR("SABuilder_Init_Basic failed: %d\n", rc);
+		goto error_exit;
+	}
+
+	params.CryptoAlgo = SAB_CRYPTO_AES;
+	params.CryptoMode = SAB_CRYPTO_MODE_CBC;
+	params.KeyByteCount = ctx->key_sz - 2 * AES_BLOCK_SIZE;
+	params.Key_p = (uint8_t *) ctx->ipad + 2 * AES_BLOCK_SIZE;
+	params.IVSrc = SAB_IV_SRC_SA;
+	params.IV_p = (uint8_t *) mtk_req->state;
+
+	if (ctx->alg == MTK_CRYPTO_ALG_XCBC) {
+		for (i = 0; i < params.KeyByteCount; i = i + 4) {
+			swap(params.Key_p[i], params.Key_p[i+3]);
+			swap(params.Key_p[i+1], params.Key_p[i+2]);
+		}
+	}
+
+	rc = SABuilder_GetSizes(&params, &SAWords, NULL, NULL);
+	if (rc) {
+		CRYPTO_ERR("SA not created because of size errors: %d\n", rc);
+		goto error_exit;
+	}
+
+	DMAProperties.fCached = true;
+	DMAProperties.Alignment = MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT;
+	DMAProperties.Bank = MTK_EIP197_INLINE_BANK_TRANSFORM;
+	DMAProperties.Size = MAX(4*SAWords, 256);
+
+	DMAStatus = DMABuf_Alloc(DMAProperties, &SAHostAddress, &SAHandle);
+	if (DMAStatus != DMABUF_STATUS_OK) {
+		rc = 1;
+		CRYPTO_ERR("Allocation of SA failed: %d\n", DMAStatus);
+		goto error_exit;
+	}
+
+	rc = SABuilder_BuildSA(&params, (u32 *)SAHostAddress.p, NULL, NULL);
+	if (rc) {
+		CRYPTO_ERR("SA not created because of errors: %d\n", rc);
+		goto error_exit;
+	}
+
+	rc = TokenBuilder_GetContextSize(&params, &TCRWords);
+	if (rc) {
+		CRYPTO_ERR("TokenBuilder_GetContextSize returned errors: %d\n", rc);
+		goto error_exit;
+	}
+
+	TCRData = kmalloc(4 * TCRWords, GFP_KERNEL);
+	if (!TCRData) {
+		rc = 1;
+		CRYPTO_ERR("Allocation of TCR failed\n");
+		goto error_exit;
+	}
+
+	rc = TokenBuilder_BuildContext(&params, TCRData);
+	if (rc) {
+		CRYPTO_ERR("TokenBuilder_BuildContext failed: %d\n", rc);
+		goto error_exit;
+	}
+
+	rc = TokenBuilder_GetSize(TCRData, &TokenMaxWords);
+	if (rc) {
+		CRYPTO_ERR("TokenBuilder_GetSize failed: %d\n", rc);
+		goto error_exit;
+	}
+
+	DMAProperties.fCached = true;
+	DMAProperties.Alignment = MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT;
+	DMAProperties.Bank = MTK_EIP197_INLINE_BANK_TOKEN;
+	DMAProperties.Size = 4*TokenMaxWords;
+
+	DMAStatus = DMABuf_Alloc(DMAProperties, &TokenHostAddress, &TokenHandle);
+	if (DMAStatus != DMABUF_STATUS_OK) {
+		rc = 1;
+		CRYPTO_ERR("Allocation of token builder failed: %d\n", DMAStatus);
+		goto error_exit;
+	}
+
+	DMAProperties.fCached = true;
+	DMAProperties.Alignment = MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT;
+	DMAProperties.Bank = MTK_EIP197_INLINE_BANK_PACKET;
+	DMAProperties.Size = MAX(InputByteCount, 1);
+
+	DMAStatus = DMABuf_Alloc(DMAProperties, &PktHostAddress, &PktHandle);
+	if (DMAStatus != DMABUF_STATUS_OK) {
+		rc = 1;
+		CRYPTO_ERR("Allocation of source packet buffer failed: %d\n", DMAStatus);
+		goto error_exit;
+	}
+
+	rc = PEC_SA_Register(PEC_INTERFACE_ID, SAHandle, DMABuf_NULLHandle,
+				DMABuf_NULLHandle);
+	if (rc != PEC_STATUS_OK) {
+		CRYPTO_ERR("PEC_SA_Register failed: %d\n", rc);
+		goto error_exit;
+	}
+
+	memcpy(PktHostAddress.p, Input_p, InputByteCount);
+
+	ZEROINIT(TokenParams);
+	rc = TokenBuilder_BuildToken(TCRData, (uint8_t *) PktHostAddress.p, InputByteCount,
+					&TokenParams, (uint32_t *) TokenHostAddress.p,
+					&TokenWords, &TokenHeaderWord);
+	if (rc != TKB_STATUS_OK) {
+		CRYPTO_ERR("Token builder failed: %d\n", rc);
+		goto error_exit_unregister;
+	}
+
+	ZEROINIT(Cmd);
+	Cmd.Token_Handle = TokenHandle;
+	Cmd.Token_WordCount = TokenWords;
+	Cmd.SrcPkt_Handle = PktHandle;
+	Cmd.SrcPkt_ByteCount = InputByteCount;
+	Cmd.DstPkt_Handle = PktHandle;
+	Cmd.SA_Handle1 = SAHandle;
+	Cmd.SA_Handle2 = DMABuf_NULLHandle;
+
+#if defined(CRYPTO_IOTOKEN_EXT)
+	InTokenDscrExt.HW_Services = IOTOKEN_CMD_PKT_LAC;
+#endif
+	InTokenDscr.TknHdrWordInit = TokenHeaderWord;
+
-	dscr_p->InPacket_ByteCount = pec_cmd_dscr->SrcPkt_ByteCount;
-	dscr_p->Ext_p = ext_p;
+	if (!crypto_iotoken_create(&InTokenDscr,
+				   InTokenDscrExt_p,
+				   InputToken,
+				   &Cmd)) {
+		rc = 1;
+		goto error_exit_unregister;
+	}
 
-	IOTokenRc = IOToken_Create(dscr_p, data_p);
-	if (IOTokenRc < 0) {
-		CRYPTO_ERR("IOToken_Create error %d\n", IOTokenRc);
-		return false;
+	rc = PEC_Packet_Put(PEC_INTERFACE_ID, &Cmd, 1, &count);
+	if (rc != PEC_STATUS_OK && count != 1) {
+		rc = 1;
+		CRYPTO_ERR("PEC_Packet_Put error: %d\n", rc);
+		goto error_exit_unregister;
 	}
 
-	pec_cmd_dscr->InputToken_p = data_p;
+	result = kmalloc(sizeof(struct mtk_crypto_result), GFP_KERNEL);
+	if (!result) {
+		rc = 1;
+		CRYPTO_ERR("No memory for result\n");
+		goto error_exit_unregister;
+	}
+	INIT_LIST_HEAD(&result->list);
+	result->eip.sa = SAHandle.p;
+	result->eip.token = TokenHandle.p;
+	result->eip.token_context = TCRData;
+	result->eip.pkt_handle = PktHandle.p;
+	result->async = async;
+	result->dst = PktHostAddress.p;
+	result->size = InputByteCount;
 
-	return true;
+	spin_lock_bh(&add_lock);
+	list_add_tail(&result->list, &result_list);
+	spin_unlock_bh(&add_lock);
+
+	CBFunc = mtk_crypto_interrupt_handler;
+	rc = PEC_ResultNotify_Request(PEC_INTERFACE_ID, CBFunc, 1);
+	if (rc != PEC_STATUS_OK) {
+		CRYPTO_ERR("PEC_ResultNotify_Request failed with rc = %d\n", rc);
+		goto error_exit_unregister;
+	}
+	return 0;
+
+error_exit_unregister:
+	PEC_SA_UnRegister(PEC_INTERFACE_ID, SAHandle, DMABuf_NULLHandle,
+				DMABuf_NULLHandle);
+
+error_exit:
+	DMABuf_Release(SAHandle);
+	DMABuf_Release(TokenHandle);
+	DMABuf_Release(PktHandle);
+
+	if (TCRData != NULL)
+		kfree(TCRData);
+
+	return rc;
 }
 
-unsigned int crypto_pe_get_one(IOToken_Output_Dscr_t *const OutTokenDscr_p,
-			       u32 *OutTokenData_p,
-			       PEC_ResultDescriptor_t *RD_p)
+int crypto_first_ahash_req(struct crypto_async_request *async,
+			   struct mtk_crypto_ahash_req *mtk_req, uint8_t *Input_p,
+			   unsigned int InputByteCount, bool finish)
 {
-	int LoopCounter = MTK_EIP197_INLINE_NOF_TRIES;
-	int IOToken_Rc;
-	PEC_Status_t pecres;
+	struct mtk_crypto_ahash_ctx *ctx = crypto_tfm_ctx(async->tfm);
+	struct mtk_crypto_result *result;
+	SABuilder_Params_Basic_t ProtocolParams;
+	SABuilder_Params_t params;
+	unsigned int SAWords = 0;
+	static uint8_t DummyAuthKey[64];
+	int rc;
 
-	ZEROINIT(*OutTokenDscr_p);
-	ZEROINIT(*RD_p);
+	DMABuf_Properties_t DMAProperties = {0, 0, 0, 0};
+	DMABuf_HostAddress_t TokenHostAddress;
+	DMABuf_HostAddress_t PktHostAddress;
+	DMABuf_HostAddress_t SAHostAddress;
+	DMABuf_Status_t DMAStatus;
 
-	/* Link data structures */
-	RD_p->OutputToken_p = OutTokenData_p;
+	DMABuf_Handle_t TokenHandle = {0};
+	DMABuf_Handle_t PktHandle = {0};
+	DMABuf_Handle_t SAHandle = {0};
 
-	while (LoopCounter > 0) {
-		/* Try to get the processed packet from the driver */
-		unsigned int Counter = 0;
+	unsigned int TokenMaxWords = 0;
+	unsigned int TokenHeaderWord;
+	unsigned int TokenWords = 0;
+	unsigned int TCRWords = 0;
+	void *TCRData = 0;
 
-		pecres = PEC_Packet_Get(PEC_INTERFACE_ID, RD_p, 1, &Counter);
-		if (pecres != PEC_STATUS_OK) {
-			/* IO error */
-			CRYPTO_ERR("PEC_Packet_Get error %d\n", pecres);
-			return 0;
-		}
+	TokenBuilder_Params_t TokenParams;
+	PEC_CommandDescriptor_t Cmd;
+	PEC_NotifyFunction_t CBFunc;
 
-		if (Counter) {
-			IOToken_Rc = IOToken_Parse(OutTokenData_p, OutTokenDscr_p);
-			if (IOToken_Rc < 0) {
-				/* IO error */
-				CRYPTO_ERR("IOToken_Parse error %d\n", IOToken_Rc);
-				return 0;
-			}
+	unsigned int count;
+	int i;
 
-			if (OutTokenDscr_p->ErrorCode != 0) {
-				/* Packet process error */
-				CRYPTO_ERR("Result descriptor error 0x%x\n",
-					OutTokenDscr_p->ErrorCode);
-				return 0;
-			}
+	u32 InputToken[IOTOKEN_IN_WORD_COUNT];
+	IOToken_Output_Dscr_t OutTokenDscr;
+	IOToken_Input_Dscr_t InTokenDscr;
+	void *InTokenDscrExt_p = NULL;
 
-			/* packet received */
-			return Counter;
+#ifdef CRYPTO_IOTOKEN_EXT
+	IOToken_Input_Dscr_Ext_t InTokenDscrExt;
+
+	ZEROINIT(InTokenDscrExt);
+	InTokenDscrExt_p = &InTokenDscrExt;
+#endif
+	ZEROINIT(InTokenDscr);
+	ZEROINIT(OutTokenDscr);
+
+	rc = SABuilder_Init_Basic(&params, &ProtocolParams, SAB_DIRECTION_OUTBOUND);
+	if (rc) {
+		CRYPTO_ERR("SABuilder_Init_Basic failed: %d\n", rc);
+		goto error_exit;
+	}
+
+	params.IV_p = (uint8_t *) ctx->ipad;
+	params.AuthAlgo = lookaside_match_hash(ctx->alg);
+	params.AuthKey1_p = DummyAuthKey;
+	if (params.AuthAlgo == SAB_AUTH_AES_XCBC_MAC) {
+		params.AuthKey1_p = (uint8_t *) ctx->ipad + 2 * AES_BLOCK_SIZE;
+		params.AuthKey2_p = (uint8_t *) ctx->ipad;
+		params.AuthKey3_p = (uint8_t *) ctx->ipad + AES_BLOCK_SIZE;
+
+		for (i = 0; i < AES_BLOCK_SIZE; i = i + 4) {
+			swap(params.AuthKey1_p[i], params.AuthKey1_p[i+3]);
+			swap(params.AuthKey1_p[i+1], params.AuthKey1_p[i+2]);
+
+			swap(params.AuthKey2_p[i], params.AuthKey2_p[i+3]);
+			swap(params.AuthKey2_p[i+1], params.AuthKey2_p[i+2]);
+
+			swap(params.AuthKey3_p[i], params.AuthKey3_p[i+3]);
+			swap(params.AuthKey3_p[i+1], params.AuthKey3_p[i+2]);
 		}
+	}
 
-		/* Wait for MTK_EIP197_PKT_GET_TIMEOUT_MS milliseconds */
-		udelay(MTK_EIP197_PKT_GET_TIMEOUT_MS * 1000);
-		LoopCounter--;
+	if (!finish)
+		params.flags |= SAB_FLAG_HASH_SAVE | SAB_FLAG_HASH_INTERMEDIATE;
+
+	params.flags |= SAB_FLAG_SUPPRESS_PAYLOAD;
+	ProtocolParams.ICVByteCount = mtk_req->digest_sz;
+
+	rc = SABuilder_GetSizes(&params, &SAWords, NULL, NULL);
+	if (rc) {
+		CRYPTO_ERR("SA not created because of size errors: %d\n", rc);
+		goto error_exit;
+	}
+
+	DMAProperties.fCached = true;
+	DMAProperties.Alignment = MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT;
+	DMAProperties.Bank = MTK_EIP197_INLINE_BANK_TRANSFORM;
+	DMAProperties.Size = MAX(4*SAWords, 256);
+
+	DMAStatus = DMABuf_Alloc(DMAProperties, &SAHostAddress, &SAHandle);
+	if (DMAStatus != DMABUF_STATUS_OK) {
+		rc = 1;
+		CRYPTO_ERR("Allocation of SA failed: %d\n", DMAStatus);
+		goto error_exit;
 	}
 
-	CRYPTO_ERR("Timeout when reading packet\n");
+	rc = SABuilder_BuildSA(&params, (u32 *)SAHostAddress.p, NULL, NULL);
+	if (rc) {
+		CRYPTO_ERR("SA not created because of errors: %d\n", rc);
+		goto error_exit;
+	}
 
-	/* IO error (timeout, not result packet received) */
-	return 0;
-}
+	rc = TokenBuilder_GetContextSize(&params, &TCRWords);
+	if (rc) {
+		CRYPTO_ERR("TokenBuilder_GetContextSize returned errors: %d\n", rc);
+		goto error_exit;
+	}
+
+	TCRData = kmalloc(4 * TCRWords, GFP_KERNEL);
+	if (!TCRData) {
+		rc = 1;
+		CRYPTO_ERR("Allocation of TCR failed\n");
+		goto error_exit;
+	}
+
+	rc = TokenBuilder_BuildContext(&params, TCRData);
+	if (rc) {
+		CRYPTO_ERR("TokenBuilder_BuildContext failed: %d\n", rc);
+		goto error_exit;
+	}
+	mtk_req->token_context = TCRData;
+
+	rc = TokenBuilder_GetSize(TCRData, &TokenMaxWords);
+	if (rc) {
+		CRYPTO_ERR("TokenBuilder_GetSize failed: %d\n", rc);
+		goto error_exit;
+	}
+
+	DMAProperties.fCached = true;
+	DMAProperties.Alignment = MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT;
+	DMAProperties.Bank = MTK_EIP197_INLINE_BANK_TOKEN;
+	DMAProperties.Size = 4*TokenMaxWords;
+
+	DMAStatus = DMABuf_Alloc(DMAProperties, &TokenHostAddress, &TokenHandle);
+	if (DMAStatus != DMABUF_STATUS_OK) {
+		rc = 1;
+		CRYPTO_ERR("Allocation of token builder failed: %d\n", DMAStatus);
+		goto error_exit;
+	}
+
+	DMAProperties.fCached = true;
+	DMAProperties.Alignment = MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT;
+	DMAProperties.Bank = MTK_EIP197_INLINE_BANK_PACKET;
+	DMAProperties.Size = MAX(InputByteCount, mtk_req->digest_sz);
+
+	DMAStatus = DMABuf_Alloc(DMAProperties, &PktHostAddress, &PktHandle);
+	if (DMAStatus != DMABUF_STATUS_OK) {
+		rc = 1;
+		CRYPTO_ERR("Allocation of source packet buffer failed: %d\n",
+			   DMAStatus);
+		goto error_exit;
+	}
 
+	rc = PEC_SA_Register(PEC_INTERFACE_ID, SAHandle, DMABuf_NULLHandle,
+				DMABuf_NULLHandle);
+	if (rc != PEC_STATUS_OK) {
+		CRYPTO_ERR("PEC_SA_Register failed: %d\n", rc);
+		goto error_exit;
+	}
+	memcpy(PktHostAddress.p, Input_p, InputByteCount);
+
+	ZEROINIT(TokenParams);
+	TokenParams.PacketFlags |= (TKB_PACKET_FLAG_HASHFIRST
+				    | TKB_PACKET_FLAG_HASHAPPEND);
+	if (finish)
+		TokenParams.PacketFlags |= TKB_PACKET_FLAG_HASHFINAL;
+
+	rc = TokenBuilder_BuildToken(TCRData, (u8 *) PktHostAddress.p,
+				     InputByteCount, &TokenParams,
+				     (u32 *) TokenHostAddress.p,
+				     &TokenWords, &TokenHeaderWord);
+	if (rc != TKB_STATUS_OK) {
+		CRYPTO_ERR("Token builder failed: %d\n", rc);
+		goto error_exit_unregister;
+	}
+
+	ZEROINIT(Cmd);
+	Cmd.Token_Handle = TokenHandle;
+	Cmd.Token_WordCount = TokenWords;
+	Cmd.SrcPkt_Handle = PktHandle;
+	Cmd.SrcPkt_ByteCount = InputByteCount;
+	Cmd.DstPkt_Handle = PktHandle;
+	Cmd.SA_Handle1 = SAHandle;
+	Cmd.SA_Handle2 = DMABuf_NULLHandle;
+
+	mtk_req->sa_pointer = SAHandle.p;
+
+#if defined(CRYPTO_IOTOKEN_EXT)
+	InTokenDscrExt.HW_Services  = IOTOKEN_CMD_PKT_LAC;
+#endif
+	InTokenDscr.TknHdrWordInit = TokenHeaderWord;
+
+	if (!crypto_iotoken_create(&InTokenDscr,
+				   InTokenDscrExt_p,
+				   InputToken,
+				   &Cmd)) {
+		rc = 1;
+		goto error_exit_unregister;
+	}
+
+	rc = PEC_Packet_Put(PEC_INTERFACE_ID, &Cmd, 1, &count);
+	if (rc != PEC_STATUS_OK && count != 1) {
+		rc = 1;
+		CRYPTO_ERR("PEC_Packet_Put error: %d\n", rc);
+		goto error_exit_unregister;
+	}
+
+	result = kmalloc(sizeof(struct mtk_crypto_result), GFP_KERNEL);
+	if (!result) {
+		rc = 1;
+		CRYPTO_ERR("No memory for result\n");
+		goto error_exit_unregister;
+	}
+	INIT_LIST_HEAD(&result->list);
+	result->eip.token = TokenHandle.p;
+	result->eip.pkt_handle = PktHandle.p;
+	result->async = async;
+	result->dst = PktHostAddress.p;
+
+	spin_lock_bh(&add_lock);
+	list_add_tail(&result->list, &result_list);
+	spin_unlock_bh(&add_lock);
+	CBFunc = mtk_crypto_interrupt_handler;
+	rc = PEC_ResultNotify_Request(PEC_INTERFACE_ID, CBFunc, 1);
+
+	return rc;
+
+error_exit_unregister:
+	PEC_SA_UnRegister(PEC_INTERFACE_ID, SAHandle, DMABuf_NULLHandle,
+				DMABuf_NULLHandle);
+
+error_exit:
+	DMABuf_Release(SAHandle);
+	DMABuf_Release(TokenHandle);
+	DMABuf_Release(PktHandle);
+
+	if (TCRData != NULL)
+		kfree(TCRData);
+
+	return rc;
+}
 
 bool crypto_basic_hash(SABuilder_Auth_t HashAlgo, uint8_t *Input_p,
 				unsigned int InputByteCount, uint8_t *Output_p,
@@ -265,7 +1854,6 @@
 	Cmd.SA_Handle1 = SAHandle;
 	Cmd.SA_Handle2 = DMABuf_NULLHandle;
 
-
 #if defined(CRYPTO_IOTOKEN_EXT)
 	InTokenDscrExt.HW_Services  = IOTOKEN_CMD_PKT_LAC;
 #endif
@@ -286,9 +1874,9 @@
 		goto error_exit_unregister;
 	}
 
-	if (crypto_pe_get_one(&OutTokenDscr, OutputToken, &Res) < 1) {
+	if (crypto_pe_busy_get_one(&OutTokenDscr, OutputToken, &Res) < 1) {
 		rc = 1;
-		CRYPTO_ERR("error from crypto_pe_get_one\n");
+		CRYPTO_ERR("error from crypto_pe_busy_get_one\n");
 		goto error_exit_unregister;
 	}
 	memcpy(Output_p, PktHostAddress.p, OutputByteCount);