18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/* Copyright (C) 2012-2019 ARM Limited (or its affiliates). */
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#include <crypto/internal/aead.h>
58c2ecf20Sopenharmony_ci#include <crypto/authenc.h>
68c2ecf20Sopenharmony_ci#include <crypto/scatterwalk.h>
78c2ecf20Sopenharmony_ci#include <linux/dmapool.h>
88c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h>
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include "cc_buffer_mgr.h"
118c2ecf20Sopenharmony_ci#include "cc_lli_defs.h"
128c2ecf20Sopenharmony_ci#include "cc_cipher.h"
138c2ecf20Sopenharmony_ci#include "cc_hash.h"
148c2ecf20Sopenharmony_ci#include "cc_aead.h"
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ciunion buffer_array_entry {
178c2ecf20Sopenharmony_ci	struct scatterlist *sgl;
188c2ecf20Sopenharmony_ci	dma_addr_t buffer_dma;
198c2ecf20Sopenharmony_ci};
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_cistruct buffer_array {
228c2ecf20Sopenharmony_ci	unsigned int num_of_buffers;
238c2ecf20Sopenharmony_ci	union buffer_array_entry entry[MAX_NUM_OF_BUFFERS_IN_MLLI];
248c2ecf20Sopenharmony_ci	unsigned int offset[MAX_NUM_OF_BUFFERS_IN_MLLI];
258c2ecf20Sopenharmony_ci	int nents[MAX_NUM_OF_BUFFERS_IN_MLLI];
268c2ecf20Sopenharmony_ci	int total_data_len[MAX_NUM_OF_BUFFERS_IN_MLLI];
278c2ecf20Sopenharmony_ci	bool is_last[MAX_NUM_OF_BUFFERS_IN_MLLI];
288c2ecf20Sopenharmony_ci	u32 *mlli_nents[MAX_NUM_OF_BUFFERS_IN_MLLI];
298c2ecf20Sopenharmony_ci};
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_cistatic inline char *cc_dma_buf_type(enum cc_req_dma_buf_type type)
328c2ecf20Sopenharmony_ci{
338c2ecf20Sopenharmony_ci	switch (type) {
348c2ecf20Sopenharmony_ci	case CC_DMA_BUF_NULL:
358c2ecf20Sopenharmony_ci		return "BUF_NULL";
368c2ecf20Sopenharmony_ci	case CC_DMA_BUF_DLLI:
378c2ecf20Sopenharmony_ci		return "BUF_DLLI";
388c2ecf20Sopenharmony_ci	case CC_DMA_BUF_MLLI:
398c2ecf20Sopenharmony_ci		return "BUF_MLLI";
408c2ecf20Sopenharmony_ci	default:
418c2ecf20Sopenharmony_ci		return "BUF_INVALID";
428c2ecf20Sopenharmony_ci	}
438c2ecf20Sopenharmony_ci}
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci/**
468c2ecf20Sopenharmony_ci * cc_copy_mac() - Copy MAC to temporary location
478c2ecf20Sopenharmony_ci *
488c2ecf20Sopenharmony_ci * @dev: device object
498c2ecf20Sopenharmony_ci * @req: aead request object
508c2ecf20Sopenharmony_ci * @dir: [IN] copy from/to sgl
518c2ecf20Sopenharmony_ci */
528c2ecf20Sopenharmony_cistatic void cc_copy_mac(struct device *dev, struct aead_request *req,
538c2ecf20Sopenharmony_ci			enum cc_sg_cpy_direct dir)
548c2ecf20Sopenharmony_ci{
558c2ecf20Sopenharmony_ci	struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
568c2ecf20Sopenharmony_ci	u32 skip = req->assoclen + req->cryptlen;
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	cc_copy_sg_portion(dev, areq_ctx->backup_mac, req->src,
598c2ecf20Sopenharmony_ci			   (skip - areq_ctx->req_authsize), skip, dir);
608c2ecf20Sopenharmony_ci}
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci/**
638c2ecf20Sopenharmony_ci * cc_get_sgl_nents() - Get scatterlist number of entries.
648c2ecf20Sopenharmony_ci *
658c2ecf20Sopenharmony_ci * @dev: Device object
668c2ecf20Sopenharmony_ci * @sg_list: SG list
678c2ecf20Sopenharmony_ci * @nbytes: [IN] Total SGL data bytes.
688c2ecf20Sopenharmony_ci * @lbytes: [OUT] Returns the amount of bytes at the last entry
698c2ecf20Sopenharmony_ci *
708c2ecf20Sopenharmony_ci * Return:
718c2ecf20Sopenharmony_ci * Number of entries in the scatterlist
728c2ecf20Sopenharmony_ci */
738c2ecf20Sopenharmony_cistatic unsigned int cc_get_sgl_nents(struct device *dev,
748c2ecf20Sopenharmony_ci				     struct scatterlist *sg_list,
758c2ecf20Sopenharmony_ci				     unsigned int nbytes, u32 *lbytes)
768c2ecf20Sopenharmony_ci{
778c2ecf20Sopenharmony_ci	unsigned int nents = 0;
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	*lbytes = 0;
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	while (nbytes && sg_list) {
828c2ecf20Sopenharmony_ci		nents++;
838c2ecf20Sopenharmony_ci		/* get the number of bytes in the last entry */
848c2ecf20Sopenharmony_ci		*lbytes = nbytes;
858c2ecf20Sopenharmony_ci		nbytes -= (sg_list->length > nbytes) ?
868c2ecf20Sopenharmony_ci				nbytes : sg_list->length;
878c2ecf20Sopenharmony_ci		sg_list = sg_next(sg_list);
888c2ecf20Sopenharmony_ci	}
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	dev_dbg(dev, "nents %d last bytes %d\n", nents, *lbytes);
918c2ecf20Sopenharmony_ci	return nents;
928c2ecf20Sopenharmony_ci}
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci/**
958c2ecf20Sopenharmony_ci * cc_copy_sg_portion() - Copy scatter list data,
968c2ecf20Sopenharmony_ci * from to_skip to end, to dest and vice versa
978c2ecf20Sopenharmony_ci *
988c2ecf20Sopenharmony_ci * @dev: Device object
998c2ecf20Sopenharmony_ci * @dest: Buffer to copy to/from
1008c2ecf20Sopenharmony_ci * @sg: SG list
1018c2ecf20Sopenharmony_ci * @to_skip: Number of bytes to skip before copying
1028c2ecf20Sopenharmony_ci * @end: Offset of last byte to copy
1038c2ecf20Sopenharmony_ci * @direct: Transfer direction (true == from SG list to buffer, false == from
1048c2ecf20Sopenharmony_ci *          buffer to SG list)
1058c2ecf20Sopenharmony_ci */
1068c2ecf20Sopenharmony_civoid cc_copy_sg_portion(struct device *dev, u8 *dest, struct scatterlist *sg,
1078c2ecf20Sopenharmony_ci			u32 to_skip, u32 end, enum cc_sg_cpy_direct direct)
1088c2ecf20Sopenharmony_ci{
1098c2ecf20Sopenharmony_ci	u32 nents;
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	nents = sg_nents_for_len(sg, end);
1128c2ecf20Sopenharmony_ci	sg_copy_buffer(sg, nents, dest, (end - to_skip + 1), to_skip,
1138c2ecf20Sopenharmony_ci		       (direct == CC_SG_TO_BUF));
1148c2ecf20Sopenharmony_ci}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_cistatic int cc_render_buff_to_mlli(struct device *dev, dma_addr_t buff_dma,
1178c2ecf20Sopenharmony_ci				  u32 buff_size, u32 *curr_nents,
1188c2ecf20Sopenharmony_ci				  u32 **mlli_entry_pp)
1198c2ecf20Sopenharmony_ci{
1208c2ecf20Sopenharmony_ci	u32 *mlli_entry_p = *mlli_entry_pp;
1218c2ecf20Sopenharmony_ci	u32 new_nents;
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	/* Verify there is no memory overflow*/
1248c2ecf20Sopenharmony_ci	new_nents = (*curr_nents + buff_size / CC_MAX_MLLI_ENTRY_SIZE + 1);
1258c2ecf20Sopenharmony_ci	if (new_nents > MAX_NUM_OF_TOTAL_MLLI_ENTRIES) {
1268c2ecf20Sopenharmony_ci		dev_err(dev, "Too many mlli entries. current %d max %d\n",
1278c2ecf20Sopenharmony_ci			new_nents, MAX_NUM_OF_TOTAL_MLLI_ENTRIES);
1288c2ecf20Sopenharmony_ci		return -ENOMEM;
1298c2ecf20Sopenharmony_ci	}
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	/*handle buffer longer than 64 kbytes */
1328c2ecf20Sopenharmony_ci	while (buff_size > CC_MAX_MLLI_ENTRY_SIZE) {
1338c2ecf20Sopenharmony_ci		cc_lli_set_addr(mlli_entry_p, buff_dma);
1348c2ecf20Sopenharmony_ci		cc_lli_set_size(mlli_entry_p, CC_MAX_MLLI_ENTRY_SIZE);
1358c2ecf20Sopenharmony_ci		dev_dbg(dev, "entry[%d]: single_buff=0x%08X size=%08X\n",
1368c2ecf20Sopenharmony_ci			*curr_nents, mlli_entry_p[LLI_WORD0_OFFSET],
1378c2ecf20Sopenharmony_ci			mlli_entry_p[LLI_WORD1_OFFSET]);
1388c2ecf20Sopenharmony_ci		buff_dma += CC_MAX_MLLI_ENTRY_SIZE;
1398c2ecf20Sopenharmony_ci		buff_size -= CC_MAX_MLLI_ENTRY_SIZE;
1408c2ecf20Sopenharmony_ci		mlli_entry_p = mlli_entry_p + 2;
1418c2ecf20Sopenharmony_ci		(*curr_nents)++;
1428c2ecf20Sopenharmony_ci	}
1438c2ecf20Sopenharmony_ci	/*Last entry */
1448c2ecf20Sopenharmony_ci	cc_lli_set_addr(mlli_entry_p, buff_dma);
1458c2ecf20Sopenharmony_ci	cc_lli_set_size(mlli_entry_p, buff_size);
1468c2ecf20Sopenharmony_ci	dev_dbg(dev, "entry[%d]: single_buff=0x%08X size=%08X\n",
1478c2ecf20Sopenharmony_ci		*curr_nents, mlli_entry_p[LLI_WORD0_OFFSET],
1488c2ecf20Sopenharmony_ci		mlli_entry_p[LLI_WORD1_OFFSET]);
1498c2ecf20Sopenharmony_ci	mlli_entry_p = mlli_entry_p + 2;
1508c2ecf20Sopenharmony_ci	*mlli_entry_pp = mlli_entry_p;
1518c2ecf20Sopenharmony_ci	(*curr_nents)++;
1528c2ecf20Sopenharmony_ci	return 0;
1538c2ecf20Sopenharmony_ci}
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_cistatic int cc_render_sg_to_mlli(struct device *dev, struct scatterlist *sgl,
1568c2ecf20Sopenharmony_ci				u32 sgl_data_len, u32 sgl_offset,
1578c2ecf20Sopenharmony_ci				u32 *curr_nents, u32 **mlli_entry_pp)
1588c2ecf20Sopenharmony_ci{
1598c2ecf20Sopenharmony_ci	struct scatterlist *curr_sgl = sgl;
1608c2ecf20Sopenharmony_ci	u32 *mlli_entry_p = *mlli_entry_pp;
1618c2ecf20Sopenharmony_ci	s32 rc = 0;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	for ( ; (curr_sgl && sgl_data_len);
1648c2ecf20Sopenharmony_ci	      curr_sgl = sg_next(curr_sgl)) {
1658c2ecf20Sopenharmony_ci		u32 entry_data_len =
1668c2ecf20Sopenharmony_ci			(sgl_data_len > sg_dma_len(curr_sgl) - sgl_offset) ?
1678c2ecf20Sopenharmony_ci				sg_dma_len(curr_sgl) - sgl_offset :
1688c2ecf20Sopenharmony_ci				sgl_data_len;
1698c2ecf20Sopenharmony_ci		sgl_data_len -= entry_data_len;
1708c2ecf20Sopenharmony_ci		rc = cc_render_buff_to_mlli(dev, sg_dma_address(curr_sgl) +
1718c2ecf20Sopenharmony_ci					    sgl_offset, entry_data_len,
1728c2ecf20Sopenharmony_ci					    curr_nents, &mlli_entry_p);
1738c2ecf20Sopenharmony_ci		if (rc)
1748c2ecf20Sopenharmony_ci			return rc;
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci		sgl_offset = 0;
1778c2ecf20Sopenharmony_ci	}
1788c2ecf20Sopenharmony_ci	*mlli_entry_pp = mlli_entry_p;
1798c2ecf20Sopenharmony_ci	return 0;
1808c2ecf20Sopenharmony_ci}
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_cistatic int cc_generate_mlli(struct device *dev, struct buffer_array *sg_data,
1838c2ecf20Sopenharmony_ci			    struct mlli_params *mlli_params, gfp_t flags)
1848c2ecf20Sopenharmony_ci{
1858c2ecf20Sopenharmony_ci	u32 *mlli_p;
1868c2ecf20Sopenharmony_ci	u32 total_nents = 0, prev_total_nents = 0;
1878c2ecf20Sopenharmony_ci	int rc = 0, i;
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	dev_dbg(dev, "NUM of SG's = %d\n", sg_data->num_of_buffers);
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	/* Allocate memory from the pointed pool */
1928c2ecf20Sopenharmony_ci	mlli_params->mlli_virt_addr =
1938c2ecf20Sopenharmony_ci		dma_pool_alloc(mlli_params->curr_pool, flags,
1948c2ecf20Sopenharmony_ci			       &mlli_params->mlli_dma_addr);
1958c2ecf20Sopenharmony_ci	if (!mlli_params->mlli_virt_addr) {
1968c2ecf20Sopenharmony_ci		dev_err(dev, "dma_pool_alloc() failed\n");
1978c2ecf20Sopenharmony_ci		rc = -ENOMEM;
1988c2ecf20Sopenharmony_ci		goto build_mlli_exit;
1998c2ecf20Sopenharmony_ci	}
2008c2ecf20Sopenharmony_ci	/* Point to start of MLLI */
2018c2ecf20Sopenharmony_ci	mlli_p = mlli_params->mlli_virt_addr;
2028c2ecf20Sopenharmony_ci	/* go over all SG's and link it to one MLLI table */
2038c2ecf20Sopenharmony_ci	for (i = 0; i < sg_data->num_of_buffers; i++) {
2048c2ecf20Sopenharmony_ci		union buffer_array_entry *entry = &sg_data->entry[i];
2058c2ecf20Sopenharmony_ci		u32 tot_len = sg_data->total_data_len[i];
2068c2ecf20Sopenharmony_ci		u32 offset = sg_data->offset[i];
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci		rc = cc_render_sg_to_mlli(dev, entry->sgl, tot_len, offset,
2098c2ecf20Sopenharmony_ci					  &total_nents, &mlli_p);
2108c2ecf20Sopenharmony_ci		if (rc)
2118c2ecf20Sopenharmony_ci			return rc;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci		/* set last bit in the current table */
2148c2ecf20Sopenharmony_ci		if (sg_data->mlli_nents[i]) {
2158c2ecf20Sopenharmony_ci			/*Calculate the current MLLI table length for the
2168c2ecf20Sopenharmony_ci			 *length field in the descriptor
2178c2ecf20Sopenharmony_ci			 */
2188c2ecf20Sopenharmony_ci			*sg_data->mlli_nents[i] +=
2198c2ecf20Sopenharmony_ci				(total_nents - prev_total_nents);
2208c2ecf20Sopenharmony_ci			prev_total_nents = total_nents;
2218c2ecf20Sopenharmony_ci		}
2228c2ecf20Sopenharmony_ci	}
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	/* Set MLLI size for the bypass operation */
2258c2ecf20Sopenharmony_ci	mlli_params->mlli_len = (total_nents * LLI_ENTRY_BYTE_SIZE);
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	dev_dbg(dev, "MLLI params: virt_addr=%pK dma_addr=%pad mlli_len=0x%X\n",
2288c2ecf20Sopenharmony_ci		mlli_params->mlli_virt_addr, &mlli_params->mlli_dma_addr,
2298c2ecf20Sopenharmony_ci		mlli_params->mlli_len);
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_cibuild_mlli_exit:
2328c2ecf20Sopenharmony_ci	return rc;
2338c2ecf20Sopenharmony_ci}
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_cistatic void cc_add_sg_entry(struct device *dev, struct buffer_array *sgl_data,
2368c2ecf20Sopenharmony_ci			    unsigned int nents, struct scatterlist *sgl,
2378c2ecf20Sopenharmony_ci			    unsigned int data_len, unsigned int data_offset,
2388c2ecf20Sopenharmony_ci			    bool is_last_table, u32 *mlli_nents)
2398c2ecf20Sopenharmony_ci{
2408c2ecf20Sopenharmony_ci	unsigned int index = sgl_data->num_of_buffers;
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	dev_dbg(dev, "index=%u nents=%u sgl=%pK data_len=0x%08X is_last=%d\n",
2438c2ecf20Sopenharmony_ci		index, nents, sgl, data_len, is_last_table);
2448c2ecf20Sopenharmony_ci	sgl_data->nents[index] = nents;
2458c2ecf20Sopenharmony_ci	sgl_data->entry[index].sgl = sgl;
2468c2ecf20Sopenharmony_ci	sgl_data->offset[index] = data_offset;
2478c2ecf20Sopenharmony_ci	sgl_data->total_data_len[index] = data_len;
2488c2ecf20Sopenharmony_ci	sgl_data->is_last[index] = is_last_table;
2498c2ecf20Sopenharmony_ci	sgl_data->mlli_nents[index] = mlli_nents;
2508c2ecf20Sopenharmony_ci	if (sgl_data->mlli_nents[index])
2518c2ecf20Sopenharmony_ci		*sgl_data->mlli_nents[index] = 0;
2528c2ecf20Sopenharmony_ci	sgl_data->num_of_buffers++;
2538c2ecf20Sopenharmony_ci}
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_cistatic int cc_map_sg(struct device *dev, struct scatterlist *sg,
2568c2ecf20Sopenharmony_ci		     unsigned int nbytes, int direction, u32 *nents,
2578c2ecf20Sopenharmony_ci		     u32 max_sg_nents, u32 *lbytes, u32 *mapped_nents)
2588c2ecf20Sopenharmony_ci{
2598c2ecf20Sopenharmony_ci	int ret = 0;
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	if (!nbytes) {
2628c2ecf20Sopenharmony_ci		*mapped_nents = 0;
2638c2ecf20Sopenharmony_ci		*lbytes = 0;
2648c2ecf20Sopenharmony_ci		*nents = 0;
2658c2ecf20Sopenharmony_ci		return 0;
2668c2ecf20Sopenharmony_ci	}
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	*nents = cc_get_sgl_nents(dev, sg, nbytes, lbytes);
2698c2ecf20Sopenharmony_ci	if (*nents > max_sg_nents) {
2708c2ecf20Sopenharmony_ci		*nents = 0;
2718c2ecf20Sopenharmony_ci		dev_err(dev, "Too many fragments. current %d max %d\n",
2728c2ecf20Sopenharmony_ci			*nents, max_sg_nents);
2738c2ecf20Sopenharmony_ci		return -ENOMEM;
2748c2ecf20Sopenharmony_ci	}
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	ret = dma_map_sg(dev, sg, *nents, direction);
2778c2ecf20Sopenharmony_ci	if (dma_mapping_error(dev, ret)) {
2788c2ecf20Sopenharmony_ci		*nents = 0;
2798c2ecf20Sopenharmony_ci		dev_err(dev, "dma_map_sg() sg buffer failed %d\n", ret);
2808c2ecf20Sopenharmony_ci		return -ENOMEM;
2818c2ecf20Sopenharmony_ci	}
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci	*mapped_nents = ret;
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	return 0;
2868c2ecf20Sopenharmony_ci}
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_cistatic int
2898c2ecf20Sopenharmony_cicc_set_aead_conf_buf(struct device *dev, struct aead_req_ctx *areq_ctx,
2908c2ecf20Sopenharmony_ci		     u8 *config_data, struct buffer_array *sg_data,
2918c2ecf20Sopenharmony_ci		     unsigned int assoclen)
2928c2ecf20Sopenharmony_ci{
2938c2ecf20Sopenharmony_ci	dev_dbg(dev, " handle additional data config set to DLLI\n");
2948c2ecf20Sopenharmony_ci	/* create sg for the current buffer */
2958c2ecf20Sopenharmony_ci	sg_init_one(&areq_ctx->ccm_adata_sg, config_data,
2968c2ecf20Sopenharmony_ci		    AES_BLOCK_SIZE + areq_ctx->ccm_hdr_size);
2978c2ecf20Sopenharmony_ci	if (dma_map_sg(dev, &areq_ctx->ccm_adata_sg, 1, DMA_TO_DEVICE) != 1) {
2988c2ecf20Sopenharmony_ci		dev_err(dev, "dma_map_sg() config buffer failed\n");
2998c2ecf20Sopenharmony_ci		return -ENOMEM;
3008c2ecf20Sopenharmony_ci	}
3018c2ecf20Sopenharmony_ci	dev_dbg(dev, "Mapped curr_buff: dma_address=%pad page=%p addr=%pK offset=%u length=%u\n",
3028c2ecf20Sopenharmony_ci		&sg_dma_address(&areq_ctx->ccm_adata_sg),
3038c2ecf20Sopenharmony_ci		sg_page(&areq_ctx->ccm_adata_sg),
3048c2ecf20Sopenharmony_ci		sg_virt(&areq_ctx->ccm_adata_sg),
3058c2ecf20Sopenharmony_ci		areq_ctx->ccm_adata_sg.offset, areq_ctx->ccm_adata_sg.length);
3068c2ecf20Sopenharmony_ci	/* prepare for case of MLLI */
3078c2ecf20Sopenharmony_ci	if (assoclen > 0) {
3088c2ecf20Sopenharmony_ci		cc_add_sg_entry(dev, sg_data, 1, &areq_ctx->ccm_adata_sg,
3098c2ecf20Sopenharmony_ci				(AES_BLOCK_SIZE + areq_ctx->ccm_hdr_size),
3108c2ecf20Sopenharmony_ci				0, false, NULL);
3118c2ecf20Sopenharmony_ci	}
3128c2ecf20Sopenharmony_ci	return 0;
3138c2ecf20Sopenharmony_ci}
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_cistatic int cc_set_hash_buf(struct device *dev, struct ahash_req_ctx *areq_ctx,
3168c2ecf20Sopenharmony_ci			   u8 *curr_buff, u32 curr_buff_cnt,
3178c2ecf20Sopenharmony_ci			   struct buffer_array *sg_data)
3188c2ecf20Sopenharmony_ci{
3198c2ecf20Sopenharmony_ci	dev_dbg(dev, " handle curr buff %x set to   DLLI\n", curr_buff_cnt);
3208c2ecf20Sopenharmony_ci	/* create sg for the current buffer */
3218c2ecf20Sopenharmony_ci	sg_init_one(areq_ctx->buff_sg, curr_buff, curr_buff_cnt);
3228c2ecf20Sopenharmony_ci	if (dma_map_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE) != 1) {
3238c2ecf20Sopenharmony_ci		dev_err(dev, "dma_map_sg() src buffer failed\n");
3248c2ecf20Sopenharmony_ci		return -ENOMEM;
3258c2ecf20Sopenharmony_ci	}
3268c2ecf20Sopenharmony_ci	dev_dbg(dev, "Mapped curr_buff: dma_address=%pad page=%p addr=%pK offset=%u length=%u\n",
3278c2ecf20Sopenharmony_ci		&sg_dma_address(areq_ctx->buff_sg), sg_page(areq_ctx->buff_sg),
3288c2ecf20Sopenharmony_ci		sg_virt(areq_ctx->buff_sg), areq_ctx->buff_sg->offset,
3298c2ecf20Sopenharmony_ci		areq_ctx->buff_sg->length);
3308c2ecf20Sopenharmony_ci	areq_ctx->data_dma_buf_type = CC_DMA_BUF_DLLI;
3318c2ecf20Sopenharmony_ci	areq_ctx->curr_sg = areq_ctx->buff_sg;
3328c2ecf20Sopenharmony_ci	areq_ctx->in_nents = 0;
3338c2ecf20Sopenharmony_ci	/* prepare for case of MLLI */
3348c2ecf20Sopenharmony_ci	cc_add_sg_entry(dev, sg_data, 1, areq_ctx->buff_sg, curr_buff_cnt, 0,
3358c2ecf20Sopenharmony_ci			false, NULL);
3368c2ecf20Sopenharmony_ci	return 0;
3378c2ecf20Sopenharmony_ci}
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_civoid cc_unmap_cipher_request(struct device *dev, void *ctx,
3408c2ecf20Sopenharmony_ci				unsigned int ivsize, struct scatterlist *src,
3418c2ecf20Sopenharmony_ci				struct scatterlist *dst)
3428c2ecf20Sopenharmony_ci{
3438c2ecf20Sopenharmony_ci	struct cipher_req_ctx *req_ctx = (struct cipher_req_ctx *)ctx;
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci	if (req_ctx->gen_ctx.iv_dma_addr) {
3468c2ecf20Sopenharmony_ci		dev_dbg(dev, "Unmapped iv: iv_dma_addr=%pad iv_size=%u\n",
3478c2ecf20Sopenharmony_ci			&req_ctx->gen_ctx.iv_dma_addr, ivsize);
3488c2ecf20Sopenharmony_ci		dma_unmap_single(dev, req_ctx->gen_ctx.iv_dma_addr,
3498c2ecf20Sopenharmony_ci				 ivsize, DMA_BIDIRECTIONAL);
3508c2ecf20Sopenharmony_ci	}
3518c2ecf20Sopenharmony_ci	/* Release pool */
3528c2ecf20Sopenharmony_ci	if (req_ctx->dma_buf_type == CC_DMA_BUF_MLLI &&
3538c2ecf20Sopenharmony_ci	    req_ctx->mlli_params.mlli_virt_addr) {
3548c2ecf20Sopenharmony_ci		dma_pool_free(req_ctx->mlli_params.curr_pool,
3558c2ecf20Sopenharmony_ci			      req_ctx->mlli_params.mlli_virt_addr,
3568c2ecf20Sopenharmony_ci			      req_ctx->mlli_params.mlli_dma_addr);
3578c2ecf20Sopenharmony_ci	}
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci	if (src != dst) {
3608c2ecf20Sopenharmony_ci		dma_unmap_sg(dev, src, req_ctx->in_nents, DMA_TO_DEVICE);
3618c2ecf20Sopenharmony_ci		dma_unmap_sg(dev, dst, req_ctx->out_nents, DMA_FROM_DEVICE);
3628c2ecf20Sopenharmony_ci		dev_dbg(dev, "Unmapped req->dst=%pK\n", sg_virt(dst));
3638c2ecf20Sopenharmony_ci		dev_dbg(dev, "Unmapped req->src=%pK\n", sg_virt(src));
3648c2ecf20Sopenharmony_ci	} else {
3658c2ecf20Sopenharmony_ci		dma_unmap_sg(dev, src, req_ctx->in_nents, DMA_BIDIRECTIONAL);
3668c2ecf20Sopenharmony_ci		dev_dbg(dev, "Unmapped req->src=%pK\n", sg_virt(src));
3678c2ecf20Sopenharmony_ci	}
3688c2ecf20Sopenharmony_ci}
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ciint cc_map_cipher_request(struct cc_drvdata *drvdata, void *ctx,
3718c2ecf20Sopenharmony_ci			  unsigned int ivsize, unsigned int nbytes,
3728c2ecf20Sopenharmony_ci			  void *info, struct scatterlist *src,
3738c2ecf20Sopenharmony_ci			  struct scatterlist *dst, gfp_t flags)
3748c2ecf20Sopenharmony_ci{
3758c2ecf20Sopenharmony_ci	struct cipher_req_ctx *req_ctx = (struct cipher_req_ctx *)ctx;
3768c2ecf20Sopenharmony_ci	struct mlli_params *mlli_params = &req_ctx->mlli_params;
3778c2ecf20Sopenharmony_ci	struct device *dev = drvdata_to_dev(drvdata);
3788c2ecf20Sopenharmony_ci	struct buffer_array sg_data;
3798c2ecf20Sopenharmony_ci	u32 dummy = 0;
3808c2ecf20Sopenharmony_ci	int rc = 0;
3818c2ecf20Sopenharmony_ci	u32 mapped_nents = 0;
3828c2ecf20Sopenharmony_ci	int src_direction = (src != dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL);
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci	req_ctx->dma_buf_type = CC_DMA_BUF_DLLI;
3858c2ecf20Sopenharmony_ci	mlli_params->curr_pool = NULL;
3868c2ecf20Sopenharmony_ci	sg_data.num_of_buffers = 0;
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci	/* Map IV buffer */
3898c2ecf20Sopenharmony_ci	if (ivsize) {
3908c2ecf20Sopenharmony_ci		dump_byte_array("iv", info, ivsize);
3918c2ecf20Sopenharmony_ci		req_ctx->gen_ctx.iv_dma_addr =
3928c2ecf20Sopenharmony_ci			dma_map_single(dev, info, ivsize, DMA_BIDIRECTIONAL);
3938c2ecf20Sopenharmony_ci		if (dma_mapping_error(dev, req_ctx->gen_ctx.iv_dma_addr)) {
3948c2ecf20Sopenharmony_ci			dev_err(dev, "Mapping iv %u B at va=%pK for DMA failed\n",
3958c2ecf20Sopenharmony_ci				ivsize, info);
3968c2ecf20Sopenharmony_ci			return -ENOMEM;
3978c2ecf20Sopenharmony_ci		}
3988c2ecf20Sopenharmony_ci		dev_dbg(dev, "Mapped iv %u B at va=%pK to dma=%pad\n",
3998c2ecf20Sopenharmony_ci			ivsize, info, &req_ctx->gen_ctx.iv_dma_addr);
4008c2ecf20Sopenharmony_ci	} else {
4018c2ecf20Sopenharmony_ci		req_ctx->gen_ctx.iv_dma_addr = 0;
4028c2ecf20Sopenharmony_ci	}
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci	/* Map the src SGL */
4058c2ecf20Sopenharmony_ci	rc = cc_map_sg(dev, src, nbytes, src_direction, &req_ctx->in_nents,
4068c2ecf20Sopenharmony_ci		       LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy, &mapped_nents);
4078c2ecf20Sopenharmony_ci	if (rc)
4088c2ecf20Sopenharmony_ci		goto cipher_exit;
4098c2ecf20Sopenharmony_ci	if (mapped_nents > 1)
4108c2ecf20Sopenharmony_ci		req_ctx->dma_buf_type = CC_DMA_BUF_MLLI;
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci	if (src == dst) {
4138c2ecf20Sopenharmony_ci		/* Handle inplace operation */
4148c2ecf20Sopenharmony_ci		if (req_ctx->dma_buf_type == CC_DMA_BUF_MLLI) {
4158c2ecf20Sopenharmony_ci			req_ctx->out_nents = 0;
4168c2ecf20Sopenharmony_ci			cc_add_sg_entry(dev, &sg_data, req_ctx->in_nents, src,
4178c2ecf20Sopenharmony_ci					nbytes, 0, true,
4188c2ecf20Sopenharmony_ci					&req_ctx->in_mlli_nents);
4198c2ecf20Sopenharmony_ci		}
4208c2ecf20Sopenharmony_ci	} else {
4218c2ecf20Sopenharmony_ci		/* Map the dst sg */
4228c2ecf20Sopenharmony_ci		rc = cc_map_sg(dev, dst, nbytes, DMA_FROM_DEVICE,
4238c2ecf20Sopenharmony_ci			       &req_ctx->out_nents, LLI_MAX_NUM_OF_DATA_ENTRIES,
4248c2ecf20Sopenharmony_ci			       &dummy, &mapped_nents);
4258c2ecf20Sopenharmony_ci		if (rc)
4268c2ecf20Sopenharmony_ci			goto cipher_exit;
4278c2ecf20Sopenharmony_ci		if (mapped_nents > 1)
4288c2ecf20Sopenharmony_ci			req_ctx->dma_buf_type = CC_DMA_BUF_MLLI;
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ci		if (req_ctx->dma_buf_type == CC_DMA_BUF_MLLI) {
4318c2ecf20Sopenharmony_ci			cc_add_sg_entry(dev, &sg_data, req_ctx->in_nents, src,
4328c2ecf20Sopenharmony_ci					nbytes, 0, true,
4338c2ecf20Sopenharmony_ci					&req_ctx->in_mlli_nents);
4348c2ecf20Sopenharmony_ci			cc_add_sg_entry(dev, &sg_data, req_ctx->out_nents, dst,
4358c2ecf20Sopenharmony_ci					nbytes, 0, true,
4368c2ecf20Sopenharmony_ci					&req_ctx->out_mlli_nents);
4378c2ecf20Sopenharmony_ci		}
4388c2ecf20Sopenharmony_ci	}
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci	if (req_ctx->dma_buf_type == CC_DMA_BUF_MLLI) {
4418c2ecf20Sopenharmony_ci		mlli_params->curr_pool = drvdata->mlli_buffs_pool;
4428c2ecf20Sopenharmony_ci		rc = cc_generate_mlli(dev, &sg_data, mlli_params, flags);
4438c2ecf20Sopenharmony_ci		if (rc)
4448c2ecf20Sopenharmony_ci			goto cipher_exit;
4458c2ecf20Sopenharmony_ci	}
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci	dev_dbg(dev, "areq_ctx->dma_buf_type = %s\n",
4488c2ecf20Sopenharmony_ci		cc_dma_buf_type(req_ctx->dma_buf_type));
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci	return 0;
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_cicipher_exit:
4538c2ecf20Sopenharmony_ci	cc_unmap_cipher_request(dev, req_ctx, ivsize, src, dst);
4548c2ecf20Sopenharmony_ci	return rc;
4558c2ecf20Sopenharmony_ci}
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_civoid cc_unmap_aead_request(struct device *dev, struct aead_request *req)
4588c2ecf20Sopenharmony_ci{
4598c2ecf20Sopenharmony_ci	struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
4608c2ecf20Sopenharmony_ci	unsigned int hw_iv_size = areq_ctx->hw_iv_size;
4618c2ecf20Sopenharmony_ci	struct cc_drvdata *drvdata = dev_get_drvdata(dev);
4628c2ecf20Sopenharmony_ci	int src_direction = (req->src != req->dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL);
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	if (areq_ctx->mac_buf_dma_addr) {
4658c2ecf20Sopenharmony_ci		dma_unmap_single(dev, areq_ctx->mac_buf_dma_addr,
4668c2ecf20Sopenharmony_ci				 MAX_MAC_SIZE, DMA_BIDIRECTIONAL);
4678c2ecf20Sopenharmony_ci	}
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	if (areq_ctx->cipher_mode == DRV_CIPHER_GCTR) {
4708c2ecf20Sopenharmony_ci		if (areq_ctx->hkey_dma_addr) {
4718c2ecf20Sopenharmony_ci			dma_unmap_single(dev, areq_ctx->hkey_dma_addr,
4728c2ecf20Sopenharmony_ci					 AES_BLOCK_SIZE, DMA_BIDIRECTIONAL);
4738c2ecf20Sopenharmony_ci		}
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci		if (areq_ctx->gcm_block_len_dma_addr) {
4768c2ecf20Sopenharmony_ci			dma_unmap_single(dev, areq_ctx->gcm_block_len_dma_addr,
4778c2ecf20Sopenharmony_ci					 AES_BLOCK_SIZE, DMA_TO_DEVICE);
4788c2ecf20Sopenharmony_ci		}
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci		if (areq_ctx->gcm_iv_inc1_dma_addr) {
4818c2ecf20Sopenharmony_ci			dma_unmap_single(dev, areq_ctx->gcm_iv_inc1_dma_addr,
4828c2ecf20Sopenharmony_ci					 AES_BLOCK_SIZE, DMA_TO_DEVICE);
4838c2ecf20Sopenharmony_ci		}
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci		if (areq_ctx->gcm_iv_inc2_dma_addr) {
4868c2ecf20Sopenharmony_ci			dma_unmap_single(dev, areq_ctx->gcm_iv_inc2_dma_addr,
4878c2ecf20Sopenharmony_ci					 AES_BLOCK_SIZE, DMA_TO_DEVICE);
4888c2ecf20Sopenharmony_ci		}
4898c2ecf20Sopenharmony_ci	}
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_ci	if (areq_ctx->ccm_hdr_size != ccm_header_size_null) {
4928c2ecf20Sopenharmony_ci		if (areq_ctx->ccm_iv0_dma_addr) {
4938c2ecf20Sopenharmony_ci			dma_unmap_single(dev, areq_ctx->ccm_iv0_dma_addr,
4948c2ecf20Sopenharmony_ci					 AES_BLOCK_SIZE, DMA_TO_DEVICE);
4958c2ecf20Sopenharmony_ci		}
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci		dma_unmap_sg(dev, &areq_ctx->ccm_adata_sg, 1, DMA_TO_DEVICE);
4988c2ecf20Sopenharmony_ci	}
4998c2ecf20Sopenharmony_ci	if (areq_ctx->gen_ctx.iv_dma_addr) {
5008c2ecf20Sopenharmony_ci		dma_unmap_single(dev, areq_ctx->gen_ctx.iv_dma_addr,
5018c2ecf20Sopenharmony_ci				 hw_iv_size, DMA_BIDIRECTIONAL);
5028c2ecf20Sopenharmony_ci		kfree_sensitive(areq_ctx->gen_ctx.iv);
5038c2ecf20Sopenharmony_ci	}
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci	/* Release pool */
5068c2ecf20Sopenharmony_ci	if ((areq_ctx->assoc_buff_type == CC_DMA_BUF_MLLI ||
5078c2ecf20Sopenharmony_ci	     areq_ctx->data_buff_type == CC_DMA_BUF_MLLI) &&
5088c2ecf20Sopenharmony_ci	    (areq_ctx->mlli_params.mlli_virt_addr)) {
5098c2ecf20Sopenharmony_ci		dev_dbg(dev, "free MLLI buffer: dma=%pad virt=%pK\n",
5108c2ecf20Sopenharmony_ci			&areq_ctx->mlli_params.mlli_dma_addr,
5118c2ecf20Sopenharmony_ci			areq_ctx->mlli_params.mlli_virt_addr);
5128c2ecf20Sopenharmony_ci		dma_pool_free(areq_ctx->mlli_params.curr_pool,
5138c2ecf20Sopenharmony_ci			      areq_ctx->mlli_params.mlli_virt_addr,
5148c2ecf20Sopenharmony_ci			      areq_ctx->mlli_params.mlli_dma_addr);
5158c2ecf20Sopenharmony_ci	}
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci	dev_dbg(dev, "Unmapping src sgl: req->src=%pK areq_ctx->src.nents=%u areq_ctx->assoc.nents=%u assoclen:%u cryptlen=%u\n",
5188c2ecf20Sopenharmony_ci		sg_virt(req->src), areq_ctx->src.nents, areq_ctx->assoc.nents,
5198c2ecf20Sopenharmony_ci		areq_ctx->assoclen, req->cryptlen);
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci	dma_unmap_sg(dev, req->src, areq_ctx->src.mapped_nents, src_direction);
5228c2ecf20Sopenharmony_ci	if (req->src != req->dst) {
5238c2ecf20Sopenharmony_ci		dev_dbg(dev, "Unmapping dst sgl: req->dst=%pK\n",
5248c2ecf20Sopenharmony_ci			sg_virt(req->dst));
5258c2ecf20Sopenharmony_ci		dma_unmap_sg(dev, req->dst, areq_ctx->dst.mapped_nents, DMA_FROM_DEVICE);
5268c2ecf20Sopenharmony_ci	}
5278c2ecf20Sopenharmony_ci	if (drvdata->coherent &&
5288c2ecf20Sopenharmony_ci	    areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT &&
5298c2ecf20Sopenharmony_ci	    req->src == req->dst) {
5308c2ecf20Sopenharmony_ci		/* copy back mac from temporary location to deal with possible
5318c2ecf20Sopenharmony_ci		 * data memory overriding that caused by cache coherence
5328c2ecf20Sopenharmony_ci		 * problem.
5338c2ecf20Sopenharmony_ci		 */
5348c2ecf20Sopenharmony_ci		cc_copy_mac(dev, req, CC_SG_FROM_BUF);
5358c2ecf20Sopenharmony_ci	}
5368c2ecf20Sopenharmony_ci}
5378c2ecf20Sopenharmony_ci
5388c2ecf20Sopenharmony_cistatic bool cc_is_icv_frag(unsigned int sgl_nents, unsigned int authsize,
5398c2ecf20Sopenharmony_ci			   u32 last_entry_data_size)
5408c2ecf20Sopenharmony_ci{
5418c2ecf20Sopenharmony_ci	return ((sgl_nents > 1) && (last_entry_data_size < authsize));
5428c2ecf20Sopenharmony_ci}
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_cistatic int cc_aead_chain_iv(struct cc_drvdata *drvdata,
5458c2ecf20Sopenharmony_ci			    struct aead_request *req,
5468c2ecf20Sopenharmony_ci			    struct buffer_array *sg_data,
5478c2ecf20Sopenharmony_ci			    bool is_last, bool do_chain)
5488c2ecf20Sopenharmony_ci{
5498c2ecf20Sopenharmony_ci	struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
5508c2ecf20Sopenharmony_ci	unsigned int hw_iv_size = areq_ctx->hw_iv_size;
5518c2ecf20Sopenharmony_ci	struct device *dev = drvdata_to_dev(drvdata);
5528c2ecf20Sopenharmony_ci	gfp_t flags = cc_gfp_flags(&req->base);
5538c2ecf20Sopenharmony_ci	int rc = 0;
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci	if (!req->iv) {
5568c2ecf20Sopenharmony_ci		areq_ctx->gen_ctx.iv_dma_addr = 0;
5578c2ecf20Sopenharmony_ci		areq_ctx->gen_ctx.iv = NULL;
5588c2ecf20Sopenharmony_ci		goto chain_iv_exit;
5598c2ecf20Sopenharmony_ci	}
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci	areq_ctx->gen_ctx.iv = kmemdup(req->iv, hw_iv_size, flags);
5628c2ecf20Sopenharmony_ci	if (!areq_ctx->gen_ctx.iv)
5638c2ecf20Sopenharmony_ci		return -ENOMEM;
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci	areq_ctx->gen_ctx.iv_dma_addr =
5668c2ecf20Sopenharmony_ci		dma_map_single(dev, areq_ctx->gen_ctx.iv, hw_iv_size,
5678c2ecf20Sopenharmony_ci			       DMA_BIDIRECTIONAL);
5688c2ecf20Sopenharmony_ci	if (dma_mapping_error(dev, areq_ctx->gen_ctx.iv_dma_addr)) {
5698c2ecf20Sopenharmony_ci		dev_err(dev, "Mapping iv %u B at va=%pK for DMA failed\n",
5708c2ecf20Sopenharmony_ci			hw_iv_size, req->iv);
5718c2ecf20Sopenharmony_ci		kfree_sensitive(areq_ctx->gen_ctx.iv);
5728c2ecf20Sopenharmony_ci		areq_ctx->gen_ctx.iv = NULL;
5738c2ecf20Sopenharmony_ci		rc = -ENOMEM;
5748c2ecf20Sopenharmony_ci		goto chain_iv_exit;
5758c2ecf20Sopenharmony_ci	}
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci	dev_dbg(dev, "Mapped iv %u B at va=%pK to dma=%pad\n",
5788c2ecf20Sopenharmony_ci		hw_iv_size, req->iv, &areq_ctx->gen_ctx.iv_dma_addr);
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_cichain_iv_exit:
5818c2ecf20Sopenharmony_ci	return rc;
5828c2ecf20Sopenharmony_ci}
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_cistatic int cc_aead_chain_assoc(struct cc_drvdata *drvdata,
5858c2ecf20Sopenharmony_ci			       struct aead_request *req,
5868c2ecf20Sopenharmony_ci			       struct buffer_array *sg_data,
5878c2ecf20Sopenharmony_ci			       bool is_last, bool do_chain)
5888c2ecf20Sopenharmony_ci{
5898c2ecf20Sopenharmony_ci	struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
5908c2ecf20Sopenharmony_ci	int rc = 0;
5918c2ecf20Sopenharmony_ci	int mapped_nents = 0;
5928c2ecf20Sopenharmony_ci	struct device *dev = drvdata_to_dev(drvdata);
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_ci	if (!sg_data) {
5958c2ecf20Sopenharmony_ci		rc = -EINVAL;
5968c2ecf20Sopenharmony_ci		goto chain_assoc_exit;
5978c2ecf20Sopenharmony_ci	}
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	if (areq_ctx->assoclen == 0) {
6008c2ecf20Sopenharmony_ci		areq_ctx->assoc_buff_type = CC_DMA_BUF_NULL;
6018c2ecf20Sopenharmony_ci		areq_ctx->assoc.nents = 0;
6028c2ecf20Sopenharmony_ci		areq_ctx->assoc.mlli_nents = 0;
6038c2ecf20Sopenharmony_ci		dev_dbg(dev, "Chain assoc of length 0: buff_type=%s nents=%u\n",
6048c2ecf20Sopenharmony_ci			cc_dma_buf_type(areq_ctx->assoc_buff_type),
6058c2ecf20Sopenharmony_ci			areq_ctx->assoc.nents);
6068c2ecf20Sopenharmony_ci		goto chain_assoc_exit;
6078c2ecf20Sopenharmony_ci	}
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci	mapped_nents = sg_nents_for_len(req->src, areq_ctx->assoclen);
6108c2ecf20Sopenharmony_ci	if (mapped_nents < 0)
6118c2ecf20Sopenharmony_ci		return mapped_nents;
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_ci	if (mapped_nents > LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES) {
6148c2ecf20Sopenharmony_ci		dev_err(dev, "Too many fragments. current %d max %d\n",
6158c2ecf20Sopenharmony_ci			mapped_nents, LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES);
6168c2ecf20Sopenharmony_ci		return -ENOMEM;
6178c2ecf20Sopenharmony_ci	}
6188c2ecf20Sopenharmony_ci	areq_ctx->assoc.nents = mapped_nents;
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci	/* in CCM case we have additional entry for
6218c2ecf20Sopenharmony_ci	 * ccm header configurations
6228c2ecf20Sopenharmony_ci	 */
6238c2ecf20Sopenharmony_ci	if (areq_ctx->ccm_hdr_size != ccm_header_size_null) {
6248c2ecf20Sopenharmony_ci		if ((mapped_nents + 1) > LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES) {
6258c2ecf20Sopenharmony_ci			dev_err(dev, "CCM case.Too many fragments. Current %d max %d\n",
6268c2ecf20Sopenharmony_ci				(areq_ctx->assoc.nents + 1),
6278c2ecf20Sopenharmony_ci				LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES);
6288c2ecf20Sopenharmony_ci			rc = -ENOMEM;
6298c2ecf20Sopenharmony_ci			goto chain_assoc_exit;
6308c2ecf20Sopenharmony_ci		}
6318c2ecf20Sopenharmony_ci	}
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	if (mapped_nents == 1 && areq_ctx->ccm_hdr_size == ccm_header_size_null)
6348c2ecf20Sopenharmony_ci		areq_ctx->assoc_buff_type = CC_DMA_BUF_DLLI;
6358c2ecf20Sopenharmony_ci	else
6368c2ecf20Sopenharmony_ci		areq_ctx->assoc_buff_type = CC_DMA_BUF_MLLI;
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci	if (do_chain || areq_ctx->assoc_buff_type == CC_DMA_BUF_MLLI) {
6398c2ecf20Sopenharmony_ci		dev_dbg(dev, "Chain assoc: buff_type=%s nents=%u\n",
6408c2ecf20Sopenharmony_ci			cc_dma_buf_type(areq_ctx->assoc_buff_type),
6418c2ecf20Sopenharmony_ci			areq_ctx->assoc.nents);
6428c2ecf20Sopenharmony_ci		cc_add_sg_entry(dev, sg_data, areq_ctx->assoc.nents, req->src,
6438c2ecf20Sopenharmony_ci				areq_ctx->assoclen, 0, is_last,
6448c2ecf20Sopenharmony_ci				&areq_ctx->assoc.mlli_nents);
6458c2ecf20Sopenharmony_ci		areq_ctx->assoc_buff_type = CC_DMA_BUF_MLLI;
6468c2ecf20Sopenharmony_ci	}
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_cichain_assoc_exit:
6498c2ecf20Sopenharmony_ci	return rc;
6508c2ecf20Sopenharmony_ci}
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_cistatic void cc_prepare_aead_data_dlli(struct aead_request *req,
6538c2ecf20Sopenharmony_ci				      u32 *src_last_bytes, u32 *dst_last_bytes)
6548c2ecf20Sopenharmony_ci{
6558c2ecf20Sopenharmony_ci	struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
6568c2ecf20Sopenharmony_ci	enum drv_crypto_direction direct = areq_ctx->gen_ctx.op_type;
6578c2ecf20Sopenharmony_ci	unsigned int authsize = areq_ctx->req_authsize;
6588c2ecf20Sopenharmony_ci	struct scatterlist *sg;
6598c2ecf20Sopenharmony_ci	ssize_t offset;
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ci	areq_ctx->is_icv_fragmented = false;
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_ci	if ((req->src == req->dst) || direct == DRV_CRYPTO_DIRECTION_DECRYPT) {
6648c2ecf20Sopenharmony_ci		sg = areq_ctx->src_sgl;
6658c2ecf20Sopenharmony_ci		offset = *src_last_bytes - authsize;
6668c2ecf20Sopenharmony_ci	} else {
6678c2ecf20Sopenharmony_ci		sg = areq_ctx->dst_sgl;
6688c2ecf20Sopenharmony_ci		offset = *dst_last_bytes - authsize;
6698c2ecf20Sopenharmony_ci	}
6708c2ecf20Sopenharmony_ci
6718c2ecf20Sopenharmony_ci	areq_ctx->icv_dma_addr = sg_dma_address(sg) + offset;
6728c2ecf20Sopenharmony_ci	areq_ctx->icv_virt_addr = sg_virt(sg) + offset;
6738c2ecf20Sopenharmony_ci}
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_cistatic void cc_prepare_aead_data_mlli(struct cc_drvdata *drvdata,
6768c2ecf20Sopenharmony_ci				      struct aead_request *req,
6778c2ecf20Sopenharmony_ci				      struct buffer_array *sg_data,
6788c2ecf20Sopenharmony_ci				      u32 *src_last_bytes, u32 *dst_last_bytes,
6798c2ecf20Sopenharmony_ci				      bool is_last_table)
6808c2ecf20Sopenharmony_ci{
6818c2ecf20Sopenharmony_ci	struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
6828c2ecf20Sopenharmony_ci	enum drv_crypto_direction direct = areq_ctx->gen_ctx.op_type;
6838c2ecf20Sopenharmony_ci	unsigned int authsize = areq_ctx->req_authsize;
6848c2ecf20Sopenharmony_ci	struct device *dev = drvdata_to_dev(drvdata);
6858c2ecf20Sopenharmony_ci	struct scatterlist *sg;
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_ci	if (req->src == req->dst) {
6888c2ecf20Sopenharmony_ci		/*INPLACE*/
6898c2ecf20Sopenharmony_ci		cc_add_sg_entry(dev, sg_data, areq_ctx->src.nents,
6908c2ecf20Sopenharmony_ci				areq_ctx->src_sgl, areq_ctx->cryptlen,
6918c2ecf20Sopenharmony_ci				areq_ctx->src_offset, is_last_table,
6928c2ecf20Sopenharmony_ci				&areq_ctx->src.mlli_nents);
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_ci		areq_ctx->is_icv_fragmented =
6958c2ecf20Sopenharmony_ci			cc_is_icv_frag(areq_ctx->src.nents, authsize,
6968c2ecf20Sopenharmony_ci				       *src_last_bytes);
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ci		if (areq_ctx->is_icv_fragmented) {
6998c2ecf20Sopenharmony_ci			/* Backup happens only when ICV is fragmented, ICV
7008c2ecf20Sopenharmony_ci			 * verification is made by CPU compare in order to
7018c2ecf20Sopenharmony_ci			 * simplify MAC verification upon request completion
7028c2ecf20Sopenharmony_ci			 */
7038c2ecf20Sopenharmony_ci			if (direct == DRV_CRYPTO_DIRECTION_DECRYPT) {
7048c2ecf20Sopenharmony_ci				/* In coherent platforms (e.g. ACP)
7058c2ecf20Sopenharmony_ci				 * already copying ICV for any
7068c2ecf20Sopenharmony_ci				 * INPLACE-DECRYPT operation, hence
7078c2ecf20Sopenharmony_ci				 * we must neglect this code.
7088c2ecf20Sopenharmony_ci				 */
7098c2ecf20Sopenharmony_ci				if (!drvdata->coherent)
7108c2ecf20Sopenharmony_ci					cc_copy_mac(dev, req, CC_SG_TO_BUF);
7118c2ecf20Sopenharmony_ci
7128c2ecf20Sopenharmony_ci				areq_ctx->icv_virt_addr = areq_ctx->backup_mac;
7138c2ecf20Sopenharmony_ci			} else {
7148c2ecf20Sopenharmony_ci				areq_ctx->icv_virt_addr = areq_ctx->mac_buf;
7158c2ecf20Sopenharmony_ci				areq_ctx->icv_dma_addr =
7168c2ecf20Sopenharmony_ci					areq_ctx->mac_buf_dma_addr;
7178c2ecf20Sopenharmony_ci			}
7188c2ecf20Sopenharmony_ci		} else { /* Contig. ICV */
7198c2ecf20Sopenharmony_ci			sg = &areq_ctx->src_sgl[areq_ctx->src.nents - 1];
7208c2ecf20Sopenharmony_ci			/*Should hanlde if the sg is not contig.*/
7218c2ecf20Sopenharmony_ci			areq_ctx->icv_dma_addr = sg_dma_address(sg) +
7228c2ecf20Sopenharmony_ci				(*src_last_bytes - authsize);
7238c2ecf20Sopenharmony_ci			areq_ctx->icv_virt_addr = sg_virt(sg) +
7248c2ecf20Sopenharmony_ci				(*src_last_bytes - authsize);
7258c2ecf20Sopenharmony_ci		}
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci	} else if (direct == DRV_CRYPTO_DIRECTION_DECRYPT) {
7288c2ecf20Sopenharmony_ci		/*NON-INPLACE and DECRYPT*/
7298c2ecf20Sopenharmony_ci		cc_add_sg_entry(dev, sg_data, areq_ctx->src.nents,
7308c2ecf20Sopenharmony_ci				areq_ctx->src_sgl, areq_ctx->cryptlen,
7318c2ecf20Sopenharmony_ci				areq_ctx->src_offset, is_last_table,
7328c2ecf20Sopenharmony_ci				&areq_ctx->src.mlli_nents);
7338c2ecf20Sopenharmony_ci		cc_add_sg_entry(dev, sg_data, areq_ctx->dst.nents,
7348c2ecf20Sopenharmony_ci				areq_ctx->dst_sgl, areq_ctx->cryptlen,
7358c2ecf20Sopenharmony_ci				areq_ctx->dst_offset, is_last_table,
7368c2ecf20Sopenharmony_ci				&areq_ctx->dst.mlli_nents);
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci		areq_ctx->is_icv_fragmented =
7398c2ecf20Sopenharmony_ci			cc_is_icv_frag(areq_ctx->src.nents, authsize,
7408c2ecf20Sopenharmony_ci				       *src_last_bytes);
7418c2ecf20Sopenharmony_ci		/* Backup happens only when ICV is fragmented, ICV
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_ci		 * verification is made by CPU compare in order to simplify
7448c2ecf20Sopenharmony_ci		 * MAC verification upon request completion
7458c2ecf20Sopenharmony_ci		 */
7468c2ecf20Sopenharmony_ci		if (areq_ctx->is_icv_fragmented) {
7478c2ecf20Sopenharmony_ci			cc_copy_mac(dev, req, CC_SG_TO_BUF);
7488c2ecf20Sopenharmony_ci			areq_ctx->icv_virt_addr = areq_ctx->backup_mac;
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci		} else { /* Contig. ICV */
7518c2ecf20Sopenharmony_ci			sg = &areq_ctx->src_sgl[areq_ctx->src.nents - 1];
7528c2ecf20Sopenharmony_ci			/*Should hanlde if the sg is not contig.*/
7538c2ecf20Sopenharmony_ci			areq_ctx->icv_dma_addr = sg_dma_address(sg) +
7548c2ecf20Sopenharmony_ci				(*src_last_bytes - authsize);
7558c2ecf20Sopenharmony_ci			areq_ctx->icv_virt_addr = sg_virt(sg) +
7568c2ecf20Sopenharmony_ci				(*src_last_bytes - authsize);
7578c2ecf20Sopenharmony_ci		}
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_ci	} else {
7608c2ecf20Sopenharmony_ci		/*NON-INPLACE and ENCRYPT*/
7618c2ecf20Sopenharmony_ci		cc_add_sg_entry(dev, sg_data, areq_ctx->dst.nents,
7628c2ecf20Sopenharmony_ci				areq_ctx->dst_sgl, areq_ctx->cryptlen,
7638c2ecf20Sopenharmony_ci				areq_ctx->dst_offset, is_last_table,
7648c2ecf20Sopenharmony_ci				&areq_ctx->dst.mlli_nents);
7658c2ecf20Sopenharmony_ci		cc_add_sg_entry(dev, sg_data, areq_ctx->src.nents,
7668c2ecf20Sopenharmony_ci				areq_ctx->src_sgl, areq_ctx->cryptlen,
7678c2ecf20Sopenharmony_ci				areq_ctx->src_offset, is_last_table,
7688c2ecf20Sopenharmony_ci				&areq_ctx->src.mlli_nents);
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_ci		areq_ctx->is_icv_fragmented =
7718c2ecf20Sopenharmony_ci			cc_is_icv_frag(areq_ctx->dst.nents, authsize,
7728c2ecf20Sopenharmony_ci				       *dst_last_bytes);
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_ci		if (!areq_ctx->is_icv_fragmented) {
7758c2ecf20Sopenharmony_ci			sg = &areq_ctx->dst_sgl[areq_ctx->dst.nents - 1];
7768c2ecf20Sopenharmony_ci			/* Contig. ICV */
7778c2ecf20Sopenharmony_ci			areq_ctx->icv_dma_addr = sg_dma_address(sg) +
7788c2ecf20Sopenharmony_ci				(*dst_last_bytes - authsize);
7798c2ecf20Sopenharmony_ci			areq_ctx->icv_virt_addr = sg_virt(sg) +
7808c2ecf20Sopenharmony_ci				(*dst_last_bytes - authsize);
7818c2ecf20Sopenharmony_ci		} else {
7828c2ecf20Sopenharmony_ci			areq_ctx->icv_dma_addr = areq_ctx->mac_buf_dma_addr;
7838c2ecf20Sopenharmony_ci			areq_ctx->icv_virt_addr = areq_ctx->mac_buf;
7848c2ecf20Sopenharmony_ci		}
7858c2ecf20Sopenharmony_ci	}
7868c2ecf20Sopenharmony_ci}
7878c2ecf20Sopenharmony_ci
7888c2ecf20Sopenharmony_cistatic int cc_aead_chain_data(struct cc_drvdata *drvdata,
7898c2ecf20Sopenharmony_ci			      struct aead_request *req,
7908c2ecf20Sopenharmony_ci			      struct buffer_array *sg_data,
7918c2ecf20Sopenharmony_ci			      bool is_last_table, bool do_chain)
7928c2ecf20Sopenharmony_ci{
7938c2ecf20Sopenharmony_ci	struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
7948c2ecf20Sopenharmony_ci	struct device *dev = drvdata_to_dev(drvdata);
7958c2ecf20Sopenharmony_ci	enum drv_crypto_direction direct = areq_ctx->gen_ctx.op_type;
7968c2ecf20Sopenharmony_ci	unsigned int authsize = areq_ctx->req_authsize;
7978c2ecf20Sopenharmony_ci	unsigned int src_last_bytes = 0, dst_last_bytes = 0;
7988c2ecf20Sopenharmony_ci	int rc = 0;
7998c2ecf20Sopenharmony_ci	u32 src_mapped_nents = 0, dst_mapped_nents = 0;
8008c2ecf20Sopenharmony_ci	u32 offset = 0;
8018c2ecf20Sopenharmony_ci	/* non-inplace mode */
8028c2ecf20Sopenharmony_ci	unsigned int size_for_map = req->assoclen + req->cryptlen;
8038c2ecf20Sopenharmony_ci	u32 sg_index = 0;
8048c2ecf20Sopenharmony_ci	u32 size_to_skip = req->assoclen;
8058c2ecf20Sopenharmony_ci	struct scatterlist *sgl;
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_ci	offset = size_to_skip;
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci	if (!sg_data)
8108c2ecf20Sopenharmony_ci		return -EINVAL;
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_ci	areq_ctx->src_sgl = req->src;
8138c2ecf20Sopenharmony_ci	areq_ctx->dst_sgl = req->dst;
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_ci	size_for_map += (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ?
8168c2ecf20Sopenharmony_ci			authsize : 0;
8178c2ecf20Sopenharmony_ci	src_mapped_nents = cc_get_sgl_nents(dev, req->src, size_for_map,
8188c2ecf20Sopenharmony_ci					    &src_last_bytes);
8198c2ecf20Sopenharmony_ci	sg_index = areq_ctx->src_sgl->length;
8208c2ecf20Sopenharmony_ci	//check where the data starts
8218c2ecf20Sopenharmony_ci	while (src_mapped_nents && (sg_index <= size_to_skip)) {
8228c2ecf20Sopenharmony_ci		src_mapped_nents--;
8238c2ecf20Sopenharmony_ci		offset -= areq_ctx->src_sgl->length;
8248c2ecf20Sopenharmony_ci		sgl = sg_next(areq_ctx->src_sgl);
8258c2ecf20Sopenharmony_ci		if (!sgl)
8268c2ecf20Sopenharmony_ci			break;
8278c2ecf20Sopenharmony_ci		areq_ctx->src_sgl = sgl;
8288c2ecf20Sopenharmony_ci		sg_index += areq_ctx->src_sgl->length;
8298c2ecf20Sopenharmony_ci	}
8308c2ecf20Sopenharmony_ci	if (src_mapped_nents > LLI_MAX_NUM_OF_DATA_ENTRIES) {
8318c2ecf20Sopenharmony_ci		dev_err(dev, "Too many fragments. current %d max %d\n",
8328c2ecf20Sopenharmony_ci			src_mapped_nents, LLI_MAX_NUM_OF_DATA_ENTRIES);
8338c2ecf20Sopenharmony_ci		return -ENOMEM;
8348c2ecf20Sopenharmony_ci	}
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci	areq_ctx->src.nents = src_mapped_nents;
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci	areq_ctx->src_offset = offset;
8398c2ecf20Sopenharmony_ci
8408c2ecf20Sopenharmony_ci	if (req->src != req->dst) {
8418c2ecf20Sopenharmony_ci		size_for_map = req->assoclen + req->cryptlen;
8428c2ecf20Sopenharmony_ci
8438c2ecf20Sopenharmony_ci		if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT)
8448c2ecf20Sopenharmony_ci			size_for_map += authsize;
8458c2ecf20Sopenharmony_ci		else
8468c2ecf20Sopenharmony_ci			size_for_map -= authsize;
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_ci		rc = cc_map_sg(dev, req->dst, size_for_map, DMA_FROM_DEVICE,
8498c2ecf20Sopenharmony_ci			       &areq_ctx->dst.mapped_nents,
8508c2ecf20Sopenharmony_ci			       LLI_MAX_NUM_OF_DATA_ENTRIES, &dst_last_bytes,
8518c2ecf20Sopenharmony_ci			       &dst_mapped_nents);
8528c2ecf20Sopenharmony_ci		if (rc)
8538c2ecf20Sopenharmony_ci			goto chain_data_exit;
8548c2ecf20Sopenharmony_ci	}
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_ci	dst_mapped_nents = cc_get_sgl_nents(dev, req->dst, size_for_map,
8578c2ecf20Sopenharmony_ci					    &dst_last_bytes);
8588c2ecf20Sopenharmony_ci	sg_index = areq_ctx->dst_sgl->length;
8598c2ecf20Sopenharmony_ci	offset = size_to_skip;
8608c2ecf20Sopenharmony_ci
8618c2ecf20Sopenharmony_ci	//check where the data starts
8628c2ecf20Sopenharmony_ci	while (dst_mapped_nents && sg_index <= size_to_skip) {
8638c2ecf20Sopenharmony_ci		dst_mapped_nents--;
8648c2ecf20Sopenharmony_ci		offset -= areq_ctx->dst_sgl->length;
8658c2ecf20Sopenharmony_ci		sgl = sg_next(areq_ctx->dst_sgl);
8668c2ecf20Sopenharmony_ci		if (!sgl)
8678c2ecf20Sopenharmony_ci			break;
8688c2ecf20Sopenharmony_ci		areq_ctx->dst_sgl = sgl;
8698c2ecf20Sopenharmony_ci		sg_index += areq_ctx->dst_sgl->length;
8708c2ecf20Sopenharmony_ci	}
8718c2ecf20Sopenharmony_ci	if (dst_mapped_nents > LLI_MAX_NUM_OF_DATA_ENTRIES) {
8728c2ecf20Sopenharmony_ci		dev_err(dev, "Too many fragments. current %d max %d\n",
8738c2ecf20Sopenharmony_ci			dst_mapped_nents, LLI_MAX_NUM_OF_DATA_ENTRIES);
8748c2ecf20Sopenharmony_ci		return -ENOMEM;
8758c2ecf20Sopenharmony_ci	}
8768c2ecf20Sopenharmony_ci	areq_ctx->dst.nents = dst_mapped_nents;
8778c2ecf20Sopenharmony_ci	areq_ctx->dst_offset = offset;
8788c2ecf20Sopenharmony_ci	if (src_mapped_nents > 1 ||
8798c2ecf20Sopenharmony_ci	    dst_mapped_nents  > 1 ||
8808c2ecf20Sopenharmony_ci	    do_chain) {
8818c2ecf20Sopenharmony_ci		areq_ctx->data_buff_type = CC_DMA_BUF_MLLI;
8828c2ecf20Sopenharmony_ci		cc_prepare_aead_data_mlli(drvdata, req, sg_data,
8838c2ecf20Sopenharmony_ci					  &src_last_bytes, &dst_last_bytes,
8848c2ecf20Sopenharmony_ci					  is_last_table);
8858c2ecf20Sopenharmony_ci	} else {
8868c2ecf20Sopenharmony_ci		areq_ctx->data_buff_type = CC_DMA_BUF_DLLI;
8878c2ecf20Sopenharmony_ci		cc_prepare_aead_data_dlli(req, &src_last_bytes,
8888c2ecf20Sopenharmony_ci					  &dst_last_bytes);
8898c2ecf20Sopenharmony_ci	}
8908c2ecf20Sopenharmony_ci
8918c2ecf20Sopenharmony_cichain_data_exit:
8928c2ecf20Sopenharmony_ci	return rc;
8938c2ecf20Sopenharmony_ci}
8948c2ecf20Sopenharmony_ci
8958c2ecf20Sopenharmony_cistatic void cc_update_aead_mlli_nents(struct cc_drvdata *drvdata,
8968c2ecf20Sopenharmony_ci				      struct aead_request *req)
8978c2ecf20Sopenharmony_ci{
8988c2ecf20Sopenharmony_ci	struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
8998c2ecf20Sopenharmony_ci	u32 curr_mlli_size = 0;
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_ci	if (areq_ctx->assoc_buff_type == CC_DMA_BUF_MLLI) {
9028c2ecf20Sopenharmony_ci		areq_ctx->assoc.sram_addr = drvdata->mlli_sram_addr;
9038c2ecf20Sopenharmony_ci		curr_mlli_size = areq_ctx->assoc.mlli_nents *
9048c2ecf20Sopenharmony_ci						LLI_ENTRY_BYTE_SIZE;
9058c2ecf20Sopenharmony_ci	}
9068c2ecf20Sopenharmony_ci
9078c2ecf20Sopenharmony_ci	if (areq_ctx->data_buff_type == CC_DMA_BUF_MLLI) {
9088c2ecf20Sopenharmony_ci		/*Inplace case dst nents equal to src nents*/
9098c2ecf20Sopenharmony_ci		if (req->src == req->dst) {
9108c2ecf20Sopenharmony_ci			areq_ctx->dst.mlli_nents = areq_ctx->src.mlli_nents;
9118c2ecf20Sopenharmony_ci			areq_ctx->src.sram_addr = drvdata->mlli_sram_addr +
9128c2ecf20Sopenharmony_ci								curr_mlli_size;
9138c2ecf20Sopenharmony_ci			areq_ctx->dst.sram_addr = areq_ctx->src.sram_addr;
9148c2ecf20Sopenharmony_ci			if (!areq_ctx->is_single_pass)
9158c2ecf20Sopenharmony_ci				areq_ctx->assoc.mlli_nents +=
9168c2ecf20Sopenharmony_ci					areq_ctx->src.mlli_nents;
9178c2ecf20Sopenharmony_ci		} else {
9188c2ecf20Sopenharmony_ci			if (areq_ctx->gen_ctx.op_type ==
9198c2ecf20Sopenharmony_ci					DRV_CRYPTO_DIRECTION_DECRYPT) {
9208c2ecf20Sopenharmony_ci				areq_ctx->src.sram_addr =
9218c2ecf20Sopenharmony_ci						drvdata->mlli_sram_addr +
9228c2ecf20Sopenharmony_ci								curr_mlli_size;
9238c2ecf20Sopenharmony_ci				areq_ctx->dst.sram_addr =
9248c2ecf20Sopenharmony_ci						areq_ctx->src.sram_addr +
9258c2ecf20Sopenharmony_ci						areq_ctx->src.mlli_nents *
9268c2ecf20Sopenharmony_ci						LLI_ENTRY_BYTE_SIZE;
9278c2ecf20Sopenharmony_ci				if (!areq_ctx->is_single_pass)
9288c2ecf20Sopenharmony_ci					areq_ctx->assoc.mlli_nents +=
9298c2ecf20Sopenharmony_ci						areq_ctx->src.mlli_nents;
9308c2ecf20Sopenharmony_ci			} else {
9318c2ecf20Sopenharmony_ci				areq_ctx->dst.sram_addr =
9328c2ecf20Sopenharmony_ci						drvdata->mlli_sram_addr +
9338c2ecf20Sopenharmony_ci								curr_mlli_size;
9348c2ecf20Sopenharmony_ci				areq_ctx->src.sram_addr =
9358c2ecf20Sopenharmony_ci						areq_ctx->dst.sram_addr +
9368c2ecf20Sopenharmony_ci						areq_ctx->dst.mlli_nents *
9378c2ecf20Sopenharmony_ci						LLI_ENTRY_BYTE_SIZE;
9388c2ecf20Sopenharmony_ci				if (!areq_ctx->is_single_pass)
9398c2ecf20Sopenharmony_ci					areq_ctx->assoc.mlli_nents +=
9408c2ecf20Sopenharmony_ci						areq_ctx->dst.mlli_nents;
9418c2ecf20Sopenharmony_ci			}
9428c2ecf20Sopenharmony_ci		}
9438c2ecf20Sopenharmony_ci	}
9448c2ecf20Sopenharmony_ci}
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_ciint cc_map_aead_request(struct cc_drvdata *drvdata, struct aead_request *req)
9478c2ecf20Sopenharmony_ci{
9488c2ecf20Sopenharmony_ci	struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
9498c2ecf20Sopenharmony_ci	struct mlli_params *mlli_params = &areq_ctx->mlli_params;
9508c2ecf20Sopenharmony_ci	struct device *dev = drvdata_to_dev(drvdata);
9518c2ecf20Sopenharmony_ci	struct buffer_array sg_data;
9528c2ecf20Sopenharmony_ci	unsigned int authsize = areq_ctx->req_authsize;
9538c2ecf20Sopenharmony_ci	int rc = 0;
9548c2ecf20Sopenharmony_ci	dma_addr_t dma_addr;
9558c2ecf20Sopenharmony_ci	u32 mapped_nents = 0;
9568c2ecf20Sopenharmony_ci	u32 dummy = 0; /*used for the assoc data fragments */
9578c2ecf20Sopenharmony_ci	u32 size_to_map;
9588c2ecf20Sopenharmony_ci	gfp_t flags = cc_gfp_flags(&req->base);
9598c2ecf20Sopenharmony_ci
9608c2ecf20Sopenharmony_ci	mlli_params->curr_pool = NULL;
9618c2ecf20Sopenharmony_ci	sg_data.num_of_buffers = 0;
9628c2ecf20Sopenharmony_ci
9638c2ecf20Sopenharmony_ci	/* copy mac to a temporary location to deal with possible
9648c2ecf20Sopenharmony_ci	 * data memory overriding that caused by cache coherence problem.
9658c2ecf20Sopenharmony_ci	 */
9668c2ecf20Sopenharmony_ci	if (drvdata->coherent &&
9678c2ecf20Sopenharmony_ci	    areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT &&
9688c2ecf20Sopenharmony_ci	    req->src == req->dst)
9698c2ecf20Sopenharmony_ci		cc_copy_mac(dev, req, CC_SG_TO_BUF);
9708c2ecf20Sopenharmony_ci
9718c2ecf20Sopenharmony_ci	/* cacluate the size for cipher remove ICV in decrypt*/
9728c2ecf20Sopenharmony_ci	areq_ctx->cryptlen = (areq_ctx->gen_ctx.op_type ==
9738c2ecf20Sopenharmony_ci				 DRV_CRYPTO_DIRECTION_ENCRYPT) ?
9748c2ecf20Sopenharmony_ci				req->cryptlen :
9758c2ecf20Sopenharmony_ci				(req->cryptlen - authsize);
9768c2ecf20Sopenharmony_ci
9778c2ecf20Sopenharmony_ci	dma_addr = dma_map_single(dev, areq_ctx->mac_buf, MAX_MAC_SIZE,
9788c2ecf20Sopenharmony_ci				  DMA_BIDIRECTIONAL);
9798c2ecf20Sopenharmony_ci	if (dma_mapping_error(dev, dma_addr)) {
9808c2ecf20Sopenharmony_ci		dev_err(dev, "Mapping mac_buf %u B at va=%pK for DMA failed\n",
9818c2ecf20Sopenharmony_ci			MAX_MAC_SIZE, areq_ctx->mac_buf);
9828c2ecf20Sopenharmony_ci		rc = -ENOMEM;
9838c2ecf20Sopenharmony_ci		goto aead_map_failure;
9848c2ecf20Sopenharmony_ci	}
9858c2ecf20Sopenharmony_ci	areq_ctx->mac_buf_dma_addr = dma_addr;
9868c2ecf20Sopenharmony_ci
9878c2ecf20Sopenharmony_ci	if (areq_ctx->ccm_hdr_size != ccm_header_size_null) {
9888c2ecf20Sopenharmony_ci		void *addr = areq_ctx->ccm_config + CCM_CTR_COUNT_0_OFFSET;
9898c2ecf20Sopenharmony_ci
9908c2ecf20Sopenharmony_ci		dma_addr = dma_map_single(dev, addr, AES_BLOCK_SIZE,
9918c2ecf20Sopenharmony_ci					  DMA_TO_DEVICE);
9928c2ecf20Sopenharmony_ci
9938c2ecf20Sopenharmony_ci		if (dma_mapping_error(dev, dma_addr)) {
9948c2ecf20Sopenharmony_ci			dev_err(dev, "Mapping mac_buf %u B at va=%pK for DMA failed\n",
9958c2ecf20Sopenharmony_ci				AES_BLOCK_SIZE, addr);
9968c2ecf20Sopenharmony_ci			areq_ctx->ccm_iv0_dma_addr = 0;
9978c2ecf20Sopenharmony_ci			rc = -ENOMEM;
9988c2ecf20Sopenharmony_ci			goto aead_map_failure;
9998c2ecf20Sopenharmony_ci		}
10008c2ecf20Sopenharmony_ci		areq_ctx->ccm_iv0_dma_addr = dma_addr;
10018c2ecf20Sopenharmony_ci
10028c2ecf20Sopenharmony_ci		rc = cc_set_aead_conf_buf(dev, areq_ctx, areq_ctx->ccm_config,
10038c2ecf20Sopenharmony_ci					  &sg_data, areq_ctx->assoclen);
10048c2ecf20Sopenharmony_ci		if (rc)
10058c2ecf20Sopenharmony_ci			goto aead_map_failure;
10068c2ecf20Sopenharmony_ci	}
10078c2ecf20Sopenharmony_ci
10088c2ecf20Sopenharmony_ci	if (areq_ctx->cipher_mode == DRV_CIPHER_GCTR) {
10098c2ecf20Sopenharmony_ci		dma_addr = dma_map_single(dev, areq_ctx->hkey, AES_BLOCK_SIZE,
10108c2ecf20Sopenharmony_ci					  DMA_BIDIRECTIONAL);
10118c2ecf20Sopenharmony_ci		if (dma_mapping_error(dev, dma_addr)) {
10128c2ecf20Sopenharmony_ci			dev_err(dev, "Mapping hkey %u B at va=%pK for DMA failed\n",
10138c2ecf20Sopenharmony_ci				AES_BLOCK_SIZE, areq_ctx->hkey);
10148c2ecf20Sopenharmony_ci			rc = -ENOMEM;
10158c2ecf20Sopenharmony_ci			goto aead_map_failure;
10168c2ecf20Sopenharmony_ci		}
10178c2ecf20Sopenharmony_ci		areq_ctx->hkey_dma_addr = dma_addr;
10188c2ecf20Sopenharmony_ci
10198c2ecf20Sopenharmony_ci		dma_addr = dma_map_single(dev, &areq_ctx->gcm_len_block,
10208c2ecf20Sopenharmony_ci					  AES_BLOCK_SIZE, DMA_TO_DEVICE);
10218c2ecf20Sopenharmony_ci		if (dma_mapping_error(dev, dma_addr)) {
10228c2ecf20Sopenharmony_ci			dev_err(dev, "Mapping gcm_len_block %u B at va=%pK for DMA failed\n",
10238c2ecf20Sopenharmony_ci				AES_BLOCK_SIZE, &areq_ctx->gcm_len_block);
10248c2ecf20Sopenharmony_ci			rc = -ENOMEM;
10258c2ecf20Sopenharmony_ci			goto aead_map_failure;
10268c2ecf20Sopenharmony_ci		}
10278c2ecf20Sopenharmony_ci		areq_ctx->gcm_block_len_dma_addr = dma_addr;
10288c2ecf20Sopenharmony_ci
10298c2ecf20Sopenharmony_ci		dma_addr = dma_map_single(dev, areq_ctx->gcm_iv_inc1,
10308c2ecf20Sopenharmony_ci					  AES_BLOCK_SIZE, DMA_TO_DEVICE);
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_ci		if (dma_mapping_error(dev, dma_addr)) {
10338c2ecf20Sopenharmony_ci			dev_err(dev, "Mapping gcm_iv_inc1 %u B at va=%pK for DMA failed\n",
10348c2ecf20Sopenharmony_ci				AES_BLOCK_SIZE, (areq_ctx->gcm_iv_inc1));
10358c2ecf20Sopenharmony_ci			areq_ctx->gcm_iv_inc1_dma_addr = 0;
10368c2ecf20Sopenharmony_ci			rc = -ENOMEM;
10378c2ecf20Sopenharmony_ci			goto aead_map_failure;
10388c2ecf20Sopenharmony_ci		}
10398c2ecf20Sopenharmony_ci		areq_ctx->gcm_iv_inc1_dma_addr = dma_addr;
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ci		dma_addr = dma_map_single(dev, areq_ctx->gcm_iv_inc2,
10428c2ecf20Sopenharmony_ci					  AES_BLOCK_SIZE, DMA_TO_DEVICE);
10438c2ecf20Sopenharmony_ci
10448c2ecf20Sopenharmony_ci		if (dma_mapping_error(dev, dma_addr)) {
10458c2ecf20Sopenharmony_ci			dev_err(dev, "Mapping gcm_iv_inc2 %u B at va=%pK for DMA failed\n",
10468c2ecf20Sopenharmony_ci				AES_BLOCK_SIZE, (areq_ctx->gcm_iv_inc2));
10478c2ecf20Sopenharmony_ci			areq_ctx->gcm_iv_inc2_dma_addr = 0;
10488c2ecf20Sopenharmony_ci			rc = -ENOMEM;
10498c2ecf20Sopenharmony_ci			goto aead_map_failure;
10508c2ecf20Sopenharmony_ci		}
10518c2ecf20Sopenharmony_ci		areq_ctx->gcm_iv_inc2_dma_addr = dma_addr;
10528c2ecf20Sopenharmony_ci	}
10538c2ecf20Sopenharmony_ci
10548c2ecf20Sopenharmony_ci	size_to_map = req->cryptlen + req->assoclen;
10558c2ecf20Sopenharmony_ci	/* If we do in-place encryption, we also need the auth tag */
10568c2ecf20Sopenharmony_ci	if ((areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_ENCRYPT) &&
10578c2ecf20Sopenharmony_ci	   (req->src == req->dst)) {
10588c2ecf20Sopenharmony_ci		size_to_map += authsize;
10598c2ecf20Sopenharmony_ci	}
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_ci	rc = cc_map_sg(dev, req->src, size_to_map,
10628c2ecf20Sopenharmony_ci		       (req->src != req->dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL),
10638c2ecf20Sopenharmony_ci		       &areq_ctx->src.mapped_nents,
10648c2ecf20Sopenharmony_ci		       (LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES +
10658c2ecf20Sopenharmony_ci			LLI_MAX_NUM_OF_DATA_ENTRIES),
10668c2ecf20Sopenharmony_ci		       &dummy, &mapped_nents);
10678c2ecf20Sopenharmony_ci	if (rc)
10688c2ecf20Sopenharmony_ci		goto aead_map_failure;
10698c2ecf20Sopenharmony_ci
10708c2ecf20Sopenharmony_ci	if (areq_ctx->is_single_pass) {
10718c2ecf20Sopenharmony_ci		/*
10728c2ecf20Sopenharmony_ci		 * Create MLLI table for:
10738c2ecf20Sopenharmony_ci		 *   (1) Assoc. data
10748c2ecf20Sopenharmony_ci		 *   (2) Src/Dst SGLs
10758c2ecf20Sopenharmony_ci		 *   Note: IV is contg. buffer (not an SGL)
10768c2ecf20Sopenharmony_ci		 */
10778c2ecf20Sopenharmony_ci		rc = cc_aead_chain_assoc(drvdata, req, &sg_data, true, false);
10788c2ecf20Sopenharmony_ci		if (rc)
10798c2ecf20Sopenharmony_ci			goto aead_map_failure;
10808c2ecf20Sopenharmony_ci		rc = cc_aead_chain_iv(drvdata, req, &sg_data, true, false);
10818c2ecf20Sopenharmony_ci		if (rc)
10828c2ecf20Sopenharmony_ci			goto aead_map_failure;
10838c2ecf20Sopenharmony_ci		rc = cc_aead_chain_data(drvdata, req, &sg_data, true, false);
10848c2ecf20Sopenharmony_ci		if (rc)
10858c2ecf20Sopenharmony_ci			goto aead_map_failure;
10868c2ecf20Sopenharmony_ci	} else { /* DOUBLE-PASS flow */
10878c2ecf20Sopenharmony_ci		/*
10888c2ecf20Sopenharmony_ci		 * Prepare MLLI table(s) in this order:
10898c2ecf20Sopenharmony_ci		 *
10908c2ecf20Sopenharmony_ci		 * If ENCRYPT/DECRYPT (inplace):
10918c2ecf20Sopenharmony_ci		 *   (1) MLLI table for assoc
10928c2ecf20Sopenharmony_ci		 *   (2) IV entry (chained right after end of assoc)
10938c2ecf20Sopenharmony_ci		 *   (3) MLLI for src/dst (inplace operation)
10948c2ecf20Sopenharmony_ci		 *
10958c2ecf20Sopenharmony_ci		 * If ENCRYPT (non-inplace)
10968c2ecf20Sopenharmony_ci		 *   (1) MLLI table for assoc
10978c2ecf20Sopenharmony_ci		 *   (2) IV entry (chained right after end of assoc)
10988c2ecf20Sopenharmony_ci		 *   (3) MLLI for dst
10998c2ecf20Sopenharmony_ci		 *   (4) MLLI for src
11008c2ecf20Sopenharmony_ci		 *
11018c2ecf20Sopenharmony_ci		 * If DECRYPT (non-inplace)
11028c2ecf20Sopenharmony_ci		 *   (1) MLLI table for assoc
11038c2ecf20Sopenharmony_ci		 *   (2) IV entry (chained right after end of assoc)
11048c2ecf20Sopenharmony_ci		 *   (3) MLLI for src
11058c2ecf20Sopenharmony_ci		 *   (4) MLLI for dst
11068c2ecf20Sopenharmony_ci		 */
11078c2ecf20Sopenharmony_ci		rc = cc_aead_chain_assoc(drvdata, req, &sg_data, false, true);
11088c2ecf20Sopenharmony_ci		if (rc)
11098c2ecf20Sopenharmony_ci			goto aead_map_failure;
11108c2ecf20Sopenharmony_ci		rc = cc_aead_chain_iv(drvdata, req, &sg_data, false, true);
11118c2ecf20Sopenharmony_ci		if (rc)
11128c2ecf20Sopenharmony_ci			goto aead_map_failure;
11138c2ecf20Sopenharmony_ci		rc = cc_aead_chain_data(drvdata, req, &sg_data, true, true);
11148c2ecf20Sopenharmony_ci		if (rc)
11158c2ecf20Sopenharmony_ci			goto aead_map_failure;
11168c2ecf20Sopenharmony_ci	}
11178c2ecf20Sopenharmony_ci
11188c2ecf20Sopenharmony_ci	/* Mlli support -start building the MLLI according to the above
11198c2ecf20Sopenharmony_ci	 * results
11208c2ecf20Sopenharmony_ci	 */
11218c2ecf20Sopenharmony_ci	if (areq_ctx->assoc_buff_type == CC_DMA_BUF_MLLI ||
11228c2ecf20Sopenharmony_ci	    areq_ctx->data_buff_type == CC_DMA_BUF_MLLI) {
11238c2ecf20Sopenharmony_ci		mlli_params->curr_pool = drvdata->mlli_buffs_pool;
11248c2ecf20Sopenharmony_ci		rc = cc_generate_mlli(dev, &sg_data, mlli_params, flags);
11258c2ecf20Sopenharmony_ci		if (rc)
11268c2ecf20Sopenharmony_ci			goto aead_map_failure;
11278c2ecf20Sopenharmony_ci
11288c2ecf20Sopenharmony_ci		cc_update_aead_mlli_nents(drvdata, req);
11298c2ecf20Sopenharmony_ci		dev_dbg(dev, "assoc params mn %d\n",
11308c2ecf20Sopenharmony_ci			areq_ctx->assoc.mlli_nents);
11318c2ecf20Sopenharmony_ci		dev_dbg(dev, "src params mn %d\n", areq_ctx->src.mlli_nents);
11328c2ecf20Sopenharmony_ci		dev_dbg(dev, "dst params mn %d\n", areq_ctx->dst.mlli_nents);
11338c2ecf20Sopenharmony_ci	}
11348c2ecf20Sopenharmony_ci	return 0;
11358c2ecf20Sopenharmony_ci
11368c2ecf20Sopenharmony_ciaead_map_failure:
11378c2ecf20Sopenharmony_ci	cc_unmap_aead_request(dev, req);
11388c2ecf20Sopenharmony_ci	return rc;
11398c2ecf20Sopenharmony_ci}
11408c2ecf20Sopenharmony_ci
11418c2ecf20Sopenharmony_ciint cc_map_hash_request_final(struct cc_drvdata *drvdata, void *ctx,
11428c2ecf20Sopenharmony_ci			      struct scatterlist *src, unsigned int nbytes,
11438c2ecf20Sopenharmony_ci			      bool do_update, gfp_t flags)
11448c2ecf20Sopenharmony_ci{
11458c2ecf20Sopenharmony_ci	struct ahash_req_ctx *areq_ctx = (struct ahash_req_ctx *)ctx;
11468c2ecf20Sopenharmony_ci	struct device *dev = drvdata_to_dev(drvdata);
11478c2ecf20Sopenharmony_ci	u8 *curr_buff = cc_hash_buf(areq_ctx);
11488c2ecf20Sopenharmony_ci	u32 *curr_buff_cnt = cc_hash_buf_cnt(areq_ctx);
11498c2ecf20Sopenharmony_ci	struct mlli_params *mlli_params = &areq_ctx->mlli_params;
11508c2ecf20Sopenharmony_ci	struct buffer_array sg_data;
11518c2ecf20Sopenharmony_ci	int rc = 0;
11528c2ecf20Sopenharmony_ci	u32 dummy = 0;
11538c2ecf20Sopenharmony_ci	u32 mapped_nents = 0;
11548c2ecf20Sopenharmony_ci
11558c2ecf20Sopenharmony_ci	dev_dbg(dev, "final params : curr_buff=%pK curr_buff_cnt=0x%X nbytes = 0x%X src=%pK curr_index=%u\n",
11568c2ecf20Sopenharmony_ci		curr_buff, *curr_buff_cnt, nbytes, src, areq_ctx->buff_index);
11578c2ecf20Sopenharmony_ci	/* Init the type of the dma buffer */
11588c2ecf20Sopenharmony_ci	areq_ctx->data_dma_buf_type = CC_DMA_BUF_NULL;
11598c2ecf20Sopenharmony_ci	mlli_params->curr_pool = NULL;
11608c2ecf20Sopenharmony_ci	sg_data.num_of_buffers = 0;
11618c2ecf20Sopenharmony_ci	areq_ctx->in_nents = 0;
11628c2ecf20Sopenharmony_ci
11638c2ecf20Sopenharmony_ci	if (nbytes == 0 && *curr_buff_cnt == 0) {
11648c2ecf20Sopenharmony_ci		/* nothing to do */
11658c2ecf20Sopenharmony_ci		return 0;
11668c2ecf20Sopenharmony_ci	}
11678c2ecf20Sopenharmony_ci
11688c2ecf20Sopenharmony_ci	/* map the previous buffer */
11698c2ecf20Sopenharmony_ci	if (*curr_buff_cnt) {
11708c2ecf20Sopenharmony_ci		rc = cc_set_hash_buf(dev, areq_ctx, curr_buff, *curr_buff_cnt,
11718c2ecf20Sopenharmony_ci				     &sg_data);
11728c2ecf20Sopenharmony_ci		if (rc)
11738c2ecf20Sopenharmony_ci			return rc;
11748c2ecf20Sopenharmony_ci	}
11758c2ecf20Sopenharmony_ci
11768c2ecf20Sopenharmony_ci	if (src && nbytes > 0 && do_update) {
11778c2ecf20Sopenharmony_ci		rc = cc_map_sg(dev, src, nbytes, DMA_TO_DEVICE,
11788c2ecf20Sopenharmony_ci			       &areq_ctx->in_nents, LLI_MAX_NUM_OF_DATA_ENTRIES,
11798c2ecf20Sopenharmony_ci			       &dummy, &mapped_nents);
11808c2ecf20Sopenharmony_ci		if (rc)
11818c2ecf20Sopenharmony_ci			goto unmap_curr_buff;
11828c2ecf20Sopenharmony_ci		if (src && mapped_nents == 1 &&
11838c2ecf20Sopenharmony_ci		    areq_ctx->data_dma_buf_type == CC_DMA_BUF_NULL) {
11848c2ecf20Sopenharmony_ci			memcpy(areq_ctx->buff_sg, src,
11858c2ecf20Sopenharmony_ci			       sizeof(struct scatterlist));
11868c2ecf20Sopenharmony_ci			areq_ctx->buff_sg->length = nbytes;
11878c2ecf20Sopenharmony_ci			areq_ctx->curr_sg = areq_ctx->buff_sg;
11888c2ecf20Sopenharmony_ci			areq_ctx->data_dma_buf_type = CC_DMA_BUF_DLLI;
11898c2ecf20Sopenharmony_ci		} else {
11908c2ecf20Sopenharmony_ci			areq_ctx->data_dma_buf_type = CC_DMA_BUF_MLLI;
11918c2ecf20Sopenharmony_ci		}
11928c2ecf20Sopenharmony_ci	}
11938c2ecf20Sopenharmony_ci
11948c2ecf20Sopenharmony_ci	/*build mlli */
11958c2ecf20Sopenharmony_ci	if (areq_ctx->data_dma_buf_type == CC_DMA_BUF_MLLI) {
11968c2ecf20Sopenharmony_ci		mlli_params->curr_pool = drvdata->mlli_buffs_pool;
11978c2ecf20Sopenharmony_ci		/* add the src data to the sg_data */
11988c2ecf20Sopenharmony_ci		cc_add_sg_entry(dev, &sg_data, areq_ctx->in_nents, src, nbytes,
11998c2ecf20Sopenharmony_ci				0, true, &areq_ctx->mlli_nents);
12008c2ecf20Sopenharmony_ci		rc = cc_generate_mlli(dev, &sg_data, mlli_params, flags);
12018c2ecf20Sopenharmony_ci		if (rc)
12028c2ecf20Sopenharmony_ci			goto fail_unmap_din;
12038c2ecf20Sopenharmony_ci	}
12048c2ecf20Sopenharmony_ci	/* change the buffer index for the unmap function */
12058c2ecf20Sopenharmony_ci	areq_ctx->buff_index = (areq_ctx->buff_index ^ 1);
12068c2ecf20Sopenharmony_ci	dev_dbg(dev, "areq_ctx->data_dma_buf_type = %s\n",
12078c2ecf20Sopenharmony_ci		cc_dma_buf_type(areq_ctx->data_dma_buf_type));
12088c2ecf20Sopenharmony_ci	return 0;
12098c2ecf20Sopenharmony_ci
12108c2ecf20Sopenharmony_cifail_unmap_din:
12118c2ecf20Sopenharmony_ci	dma_unmap_sg(dev, src, areq_ctx->in_nents, DMA_TO_DEVICE);
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_ciunmap_curr_buff:
12148c2ecf20Sopenharmony_ci	if (*curr_buff_cnt)
12158c2ecf20Sopenharmony_ci		dma_unmap_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE);
12168c2ecf20Sopenharmony_ci
12178c2ecf20Sopenharmony_ci	return rc;
12188c2ecf20Sopenharmony_ci}
12198c2ecf20Sopenharmony_ci
12208c2ecf20Sopenharmony_ciint cc_map_hash_request_update(struct cc_drvdata *drvdata, void *ctx,
12218c2ecf20Sopenharmony_ci			       struct scatterlist *src, unsigned int nbytes,
12228c2ecf20Sopenharmony_ci			       unsigned int block_size, gfp_t flags)
12238c2ecf20Sopenharmony_ci{
12248c2ecf20Sopenharmony_ci	struct ahash_req_ctx *areq_ctx = (struct ahash_req_ctx *)ctx;
12258c2ecf20Sopenharmony_ci	struct device *dev = drvdata_to_dev(drvdata);
12268c2ecf20Sopenharmony_ci	u8 *curr_buff = cc_hash_buf(areq_ctx);
12278c2ecf20Sopenharmony_ci	u32 *curr_buff_cnt = cc_hash_buf_cnt(areq_ctx);
12288c2ecf20Sopenharmony_ci	u8 *next_buff = cc_next_buf(areq_ctx);
12298c2ecf20Sopenharmony_ci	u32 *next_buff_cnt = cc_next_buf_cnt(areq_ctx);
12308c2ecf20Sopenharmony_ci	struct mlli_params *mlli_params = &areq_ctx->mlli_params;
12318c2ecf20Sopenharmony_ci	unsigned int update_data_len;
12328c2ecf20Sopenharmony_ci	u32 total_in_len = nbytes + *curr_buff_cnt;
12338c2ecf20Sopenharmony_ci	struct buffer_array sg_data;
12348c2ecf20Sopenharmony_ci	unsigned int swap_index = 0;
12358c2ecf20Sopenharmony_ci	int rc = 0;
12368c2ecf20Sopenharmony_ci	u32 dummy = 0;
12378c2ecf20Sopenharmony_ci	u32 mapped_nents = 0;
12388c2ecf20Sopenharmony_ci
12398c2ecf20Sopenharmony_ci	dev_dbg(dev, " update params : curr_buff=%pK curr_buff_cnt=0x%X nbytes=0x%X src=%pK curr_index=%u\n",
12408c2ecf20Sopenharmony_ci		curr_buff, *curr_buff_cnt, nbytes, src, areq_ctx->buff_index);
12418c2ecf20Sopenharmony_ci	/* Init the type of the dma buffer */
12428c2ecf20Sopenharmony_ci	areq_ctx->data_dma_buf_type = CC_DMA_BUF_NULL;
12438c2ecf20Sopenharmony_ci	mlli_params->curr_pool = NULL;
12448c2ecf20Sopenharmony_ci	areq_ctx->curr_sg = NULL;
12458c2ecf20Sopenharmony_ci	sg_data.num_of_buffers = 0;
12468c2ecf20Sopenharmony_ci	areq_ctx->in_nents = 0;
12478c2ecf20Sopenharmony_ci
12488c2ecf20Sopenharmony_ci	if (total_in_len < block_size) {
12498c2ecf20Sopenharmony_ci		dev_dbg(dev, " less than one block: curr_buff=%pK *curr_buff_cnt=0x%X copy_to=%pK\n",
12508c2ecf20Sopenharmony_ci			curr_buff, *curr_buff_cnt, &curr_buff[*curr_buff_cnt]);
12518c2ecf20Sopenharmony_ci		areq_ctx->in_nents = sg_nents_for_len(src, nbytes);
12528c2ecf20Sopenharmony_ci		sg_copy_to_buffer(src, areq_ctx->in_nents,
12538c2ecf20Sopenharmony_ci				  &curr_buff[*curr_buff_cnt], nbytes);
12548c2ecf20Sopenharmony_ci		*curr_buff_cnt += nbytes;
12558c2ecf20Sopenharmony_ci		return 1;
12568c2ecf20Sopenharmony_ci	}
12578c2ecf20Sopenharmony_ci
12588c2ecf20Sopenharmony_ci	/* Calculate the residue size*/
12598c2ecf20Sopenharmony_ci	*next_buff_cnt = total_in_len & (block_size - 1);
12608c2ecf20Sopenharmony_ci	/* update data len */
12618c2ecf20Sopenharmony_ci	update_data_len = total_in_len - *next_buff_cnt;
12628c2ecf20Sopenharmony_ci
12638c2ecf20Sopenharmony_ci	dev_dbg(dev, " temp length : *next_buff_cnt=0x%X update_data_len=0x%X\n",
12648c2ecf20Sopenharmony_ci		*next_buff_cnt, update_data_len);
12658c2ecf20Sopenharmony_ci
12668c2ecf20Sopenharmony_ci	/* Copy the new residue to next buffer */
12678c2ecf20Sopenharmony_ci	if (*next_buff_cnt) {
12688c2ecf20Sopenharmony_ci		dev_dbg(dev, " handle residue: next buff %pK skip data %u residue %u\n",
12698c2ecf20Sopenharmony_ci			next_buff, (update_data_len - *curr_buff_cnt),
12708c2ecf20Sopenharmony_ci			*next_buff_cnt);
12718c2ecf20Sopenharmony_ci		cc_copy_sg_portion(dev, next_buff, src,
12728c2ecf20Sopenharmony_ci				   (update_data_len - *curr_buff_cnt),
12738c2ecf20Sopenharmony_ci				   nbytes, CC_SG_TO_BUF);
12748c2ecf20Sopenharmony_ci		/* change the buffer index for next operation */
12758c2ecf20Sopenharmony_ci		swap_index = 1;
12768c2ecf20Sopenharmony_ci	}
12778c2ecf20Sopenharmony_ci
12788c2ecf20Sopenharmony_ci	if (*curr_buff_cnt) {
12798c2ecf20Sopenharmony_ci		rc = cc_set_hash_buf(dev, areq_ctx, curr_buff, *curr_buff_cnt,
12808c2ecf20Sopenharmony_ci				     &sg_data);
12818c2ecf20Sopenharmony_ci		if (rc)
12828c2ecf20Sopenharmony_ci			return rc;
12838c2ecf20Sopenharmony_ci		/* change the buffer index for next operation */
12848c2ecf20Sopenharmony_ci		swap_index = 1;
12858c2ecf20Sopenharmony_ci	}
12868c2ecf20Sopenharmony_ci
12878c2ecf20Sopenharmony_ci	if (update_data_len > *curr_buff_cnt) {
12888c2ecf20Sopenharmony_ci		rc = cc_map_sg(dev, src, (update_data_len - *curr_buff_cnt),
12898c2ecf20Sopenharmony_ci			       DMA_TO_DEVICE, &areq_ctx->in_nents,
12908c2ecf20Sopenharmony_ci			       LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy,
12918c2ecf20Sopenharmony_ci			       &mapped_nents);
12928c2ecf20Sopenharmony_ci		if (rc)
12938c2ecf20Sopenharmony_ci			goto unmap_curr_buff;
12948c2ecf20Sopenharmony_ci		if (mapped_nents == 1 &&
12958c2ecf20Sopenharmony_ci		    areq_ctx->data_dma_buf_type == CC_DMA_BUF_NULL) {
12968c2ecf20Sopenharmony_ci			/* only one entry in the SG and no previous data */
12978c2ecf20Sopenharmony_ci			memcpy(areq_ctx->buff_sg, src,
12988c2ecf20Sopenharmony_ci			       sizeof(struct scatterlist));
12998c2ecf20Sopenharmony_ci			areq_ctx->buff_sg->length = update_data_len;
13008c2ecf20Sopenharmony_ci			areq_ctx->data_dma_buf_type = CC_DMA_BUF_DLLI;
13018c2ecf20Sopenharmony_ci			areq_ctx->curr_sg = areq_ctx->buff_sg;
13028c2ecf20Sopenharmony_ci		} else {
13038c2ecf20Sopenharmony_ci			areq_ctx->data_dma_buf_type = CC_DMA_BUF_MLLI;
13048c2ecf20Sopenharmony_ci		}
13058c2ecf20Sopenharmony_ci	}
13068c2ecf20Sopenharmony_ci
13078c2ecf20Sopenharmony_ci	if (areq_ctx->data_dma_buf_type == CC_DMA_BUF_MLLI) {
13088c2ecf20Sopenharmony_ci		mlli_params->curr_pool = drvdata->mlli_buffs_pool;
13098c2ecf20Sopenharmony_ci		/* add the src data to the sg_data */
13108c2ecf20Sopenharmony_ci		cc_add_sg_entry(dev, &sg_data, areq_ctx->in_nents, src,
13118c2ecf20Sopenharmony_ci				(update_data_len - *curr_buff_cnt), 0, true,
13128c2ecf20Sopenharmony_ci				&areq_ctx->mlli_nents);
13138c2ecf20Sopenharmony_ci		rc = cc_generate_mlli(dev, &sg_data, mlli_params, flags);
13148c2ecf20Sopenharmony_ci		if (rc)
13158c2ecf20Sopenharmony_ci			goto fail_unmap_din;
13168c2ecf20Sopenharmony_ci	}
13178c2ecf20Sopenharmony_ci	areq_ctx->buff_index = (areq_ctx->buff_index ^ swap_index);
13188c2ecf20Sopenharmony_ci
13198c2ecf20Sopenharmony_ci	return 0;
13208c2ecf20Sopenharmony_ci
13218c2ecf20Sopenharmony_cifail_unmap_din:
13228c2ecf20Sopenharmony_ci	dma_unmap_sg(dev, src, areq_ctx->in_nents, DMA_TO_DEVICE);
13238c2ecf20Sopenharmony_ci
13248c2ecf20Sopenharmony_ciunmap_curr_buff:
13258c2ecf20Sopenharmony_ci	if (*curr_buff_cnt)
13268c2ecf20Sopenharmony_ci		dma_unmap_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE);
13278c2ecf20Sopenharmony_ci
13288c2ecf20Sopenharmony_ci	return rc;
13298c2ecf20Sopenharmony_ci}
13308c2ecf20Sopenharmony_ci
13318c2ecf20Sopenharmony_civoid cc_unmap_hash_request(struct device *dev, void *ctx,
13328c2ecf20Sopenharmony_ci			   struct scatterlist *src, bool do_revert)
13338c2ecf20Sopenharmony_ci{
13348c2ecf20Sopenharmony_ci	struct ahash_req_ctx *areq_ctx = (struct ahash_req_ctx *)ctx;
13358c2ecf20Sopenharmony_ci	u32 *prev_len = cc_next_buf_cnt(areq_ctx);
13368c2ecf20Sopenharmony_ci
13378c2ecf20Sopenharmony_ci	/*In case a pool was set, a table was
13388c2ecf20Sopenharmony_ci	 *allocated and should be released
13398c2ecf20Sopenharmony_ci	 */
13408c2ecf20Sopenharmony_ci	if (areq_ctx->mlli_params.curr_pool) {
13418c2ecf20Sopenharmony_ci		dev_dbg(dev, "free MLLI buffer: dma=%pad virt=%pK\n",
13428c2ecf20Sopenharmony_ci			&areq_ctx->mlli_params.mlli_dma_addr,
13438c2ecf20Sopenharmony_ci			areq_ctx->mlli_params.mlli_virt_addr);
13448c2ecf20Sopenharmony_ci		dma_pool_free(areq_ctx->mlli_params.curr_pool,
13458c2ecf20Sopenharmony_ci			      areq_ctx->mlli_params.mlli_virt_addr,
13468c2ecf20Sopenharmony_ci			      areq_ctx->mlli_params.mlli_dma_addr);
13478c2ecf20Sopenharmony_ci	}
13488c2ecf20Sopenharmony_ci
13498c2ecf20Sopenharmony_ci	if (src && areq_ctx->in_nents) {
13508c2ecf20Sopenharmony_ci		dev_dbg(dev, "Unmapped sg src: virt=%pK dma=%pad len=0x%X\n",
13518c2ecf20Sopenharmony_ci			sg_virt(src), &sg_dma_address(src), sg_dma_len(src));
13528c2ecf20Sopenharmony_ci		dma_unmap_sg(dev, src,
13538c2ecf20Sopenharmony_ci			     areq_ctx->in_nents, DMA_TO_DEVICE);
13548c2ecf20Sopenharmony_ci	}
13558c2ecf20Sopenharmony_ci
13568c2ecf20Sopenharmony_ci	if (*prev_len) {
13578c2ecf20Sopenharmony_ci		dev_dbg(dev, "Unmapped buffer: areq_ctx->buff_sg=%pK dma=%pad len 0x%X\n",
13588c2ecf20Sopenharmony_ci			sg_virt(areq_ctx->buff_sg),
13598c2ecf20Sopenharmony_ci			&sg_dma_address(areq_ctx->buff_sg),
13608c2ecf20Sopenharmony_ci			sg_dma_len(areq_ctx->buff_sg));
13618c2ecf20Sopenharmony_ci		dma_unmap_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE);
13628c2ecf20Sopenharmony_ci		if (!do_revert) {
13638c2ecf20Sopenharmony_ci			/* clean the previous data length for update
13648c2ecf20Sopenharmony_ci			 * operation
13658c2ecf20Sopenharmony_ci			 */
13668c2ecf20Sopenharmony_ci			*prev_len = 0;
13678c2ecf20Sopenharmony_ci		} else {
13688c2ecf20Sopenharmony_ci			areq_ctx->buff_index ^= 1;
13698c2ecf20Sopenharmony_ci		}
13708c2ecf20Sopenharmony_ci	}
13718c2ecf20Sopenharmony_ci}
13728c2ecf20Sopenharmony_ci
13738c2ecf20Sopenharmony_ciint cc_buffer_mgr_init(struct cc_drvdata *drvdata)
13748c2ecf20Sopenharmony_ci{
13758c2ecf20Sopenharmony_ci	struct device *dev = drvdata_to_dev(drvdata);
13768c2ecf20Sopenharmony_ci
13778c2ecf20Sopenharmony_ci	drvdata->mlli_buffs_pool =
13788c2ecf20Sopenharmony_ci		dma_pool_create("dx_single_mlli_tables", dev,
13798c2ecf20Sopenharmony_ci				MAX_NUM_OF_TOTAL_MLLI_ENTRIES *
13808c2ecf20Sopenharmony_ci				LLI_ENTRY_BYTE_SIZE,
13818c2ecf20Sopenharmony_ci				MLLI_TABLE_MIN_ALIGNMENT, 0);
13828c2ecf20Sopenharmony_ci
13838c2ecf20Sopenharmony_ci	if (!drvdata->mlli_buffs_pool)
13848c2ecf20Sopenharmony_ci		return -ENOMEM;
13858c2ecf20Sopenharmony_ci
13868c2ecf20Sopenharmony_ci	return 0;
13878c2ecf20Sopenharmony_ci}
13888c2ecf20Sopenharmony_ci
13898c2ecf20Sopenharmony_ciint cc_buffer_mgr_fini(struct cc_drvdata *drvdata)
13908c2ecf20Sopenharmony_ci{
13918c2ecf20Sopenharmony_ci	dma_pool_destroy(drvdata->mlli_buffs_pool);
13928c2ecf20Sopenharmony_ci	return 0;
13938c2ecf20Sopenharmony_ci}
1394