162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Copyright (c) 2016-2017 HiSilicon Limited. */
362306a36Sopenharmony_ci#include <linux/crypto.h>
462306a36Sopenharmony_ci#include <linux/dma-mapping.h>
562306a36Sopenharmony_ci#include <linux/dmapool.h>
662306a36Sopenharmony_ci#include <linux/module.h>
762306a36Sopenharmony_ci#include <linux/mutex.h>
862306a36Sopenharmony_ci#include <linux/slab.h>
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <crypto/aes.h>
1162306a36Sopenharmony_ci#include <crypto/algapi.h>
1262306a36Sopenharmony_ci#include <crypto/internal/des.h>
1362306a36Sopenharmony_ci#include <crypto/skcipher.h>
1462306a36Sopenharmony_ci#include <crypto/xts.h>
1562306a36Sopenharmony_ci#include <crypto/internal/skcipher.h>
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include "sec_drv.h"
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#define SEC_MAX_CIPHER_KEY		64
2062306a36Sopenharmony_ci#define SEC_REQ_LIMIT SZ_32M
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_cistruct sec_c_alg_cfg {
2362306a36Sopenharmony_ci	unsigned c_alg		: 3;
2462306a36Sopenharmony_ci	unsigned c_mode		: 3;
2562306a36Sopenharmony_ci	unsigned key_len	: 2;
2662306a36Sopenharmony_ci	unsigned c_width	: 2;
2762306a36Sopenharmony_ci};
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_cistatic const struct sec_c_alg_cfg sec_c_alg_cfgs[] =  {
3062306a36Sopenharmony_ci	[SEC_C_DES_ECB_64] = {
3162306a36Sopenharmony_ci		.c_alg = SEC_C_ALG_DES,
3262306a36Sopenharmony_ci		.c_mode = SEC_C_MODE_ECB,
3362306a36Sopenharmony_ci		.key_len = SEC_KEY_LEN_DES,
3462306a36Sopenharmony_ci	},
3562306a36Sopenharmony_ci	[SEC_C_DES_CBC_64] = {
3662306a36Sopenharmony_ci		.c_alg = SEC_C_ALG_DES,
3762306a36Sopenharmony_ci		.c_mode = SEC_C_MODE_CBC,
3862306a36Sopenharmony_ci		.key_len = SEC_KEY_LEN_DES,
3962306a36Sopenharmony_ci	},
4062306a36Sopenharmony_ci	[SEC_C_3DES_ECB_192_3KEY] = {
4162306a36Sopenharmony_ci		.c_alg = SEC_C_ALG_3DES,
4262306a36Sopenharmony_ci		.c_mode = SEC_C_MODE_ECB,
4362306a36Sopenharmony_ci		.key_len = SEC_KEY_LEN_3DES_3_KEY,
4462306a36Sopenharmony_ci	},
4562306a36Sopenharmony_ci	[SEC_C_3DES_ECB_192_2KEY] = {
4662306a36Sopenharmony_ci		.c_alg = SEC_C_ALG_3DES,
4762306a36Sopenharmony_ci		.c_mode = SEC_C_MODE_ECB,
4862306a36Sopenharmony_ci		.key_len = SEC_KEY_LEN_3DES_2_KEY,
4962306a36Sopenharmony_ci	},
5062306a36Sopenharmony_ci	[SEC_C_3DES_CBC_192_3KEY] = {
5162306a36Sopenharmony_ci		.c_alg = SEC_C_ALG_3DES,
5262306a36Sopenharmony_ci		.c_mode = SEC_C_MODE_CBC,
5362306a36Sopenharmony_ci		.key_len = SEC_KEY_LEN_3DES_3_KEY,
5462306a36Sopenharmony_ci	},
5562306a36Sopenharmony_ci	[SEC_C_3DES_CBC_192_2KEY] = {
5662306a36Sopenharmony_ci		.c_alg = SEC_C_ALG_3DES,
5762306a36Sopenharmony_ci		.c_mode = SEC_C_MODE_CBC,
5862306a36Sopenharmony_ci		.key_len = SEC_KEY_LEN_3DES_2_KEY,
5962306a36Sopenharmony_ci	},
6062306a36Sopenharmony_ci	[SEC_C_AES_ECB_128] = {
6162306a36Sopenharmony_ci		.c_alg = SEC_C_ALG_AES,
6262306a36Sopenharmony_ci		.c_mode = SEC_C_MODE_ECB,
6362306a36Sopenharmony_ci		.key_len = SEC_KEY_LEN_AES_128,
6462306a36Sopenharmony_ci	},
6562306a36Sopenharmony_ci	[SEC_C_AES_ECB_192] = {
6662306a36Sopenharmony_ci		.c_alg = SEC_C_ALG_AES,
6762306a36Sopenharmony_ci		.c_mode = SEC_C_MODE_ECB,
6862306a36Sopenharmony_ci		.key_len = SEC_KEY_LEN_AES_192,
6962306a36Sopenharmony_ci	},
7062306a36Sopenharmony_ci	[SEC_C_AES_ECB_256] = {
7162306a36Sopenharmony_ci		.c_alg = SEC_C_ALG_AES,
7262306a36Sopenharmony_ci		.c_mode = SEC_C_MODE_ECB,
7362306a36Sopenharmony_ci		.key_len = SEC_KEY_LEN_AES_256,
7462306a36Sopenharmony_ci	},
7562306a36Sopenharmony_ci	[SEC_C_AES_CBC_128] = {
7662306a36Sopenharmony_ci		.c_alg = SEC_C_ALG_AES,
7762306a36Sopenharmony_ci		.c_mode = SEC_C_MODE_CBC,
7862306a36Sopenharmony_ci		.key_len = SEC_KEY_LEN_AES_128,
7962306a36Sopenharmony_ci	},
8062306a36Sopenharmony_ci	[SEC_C_AES_CBC_192] = {
8162306a36Sopenharmony_ci		.c_alg = SEC_C_ALG_AES,
8262306a36Sopenharmony_ci		.c_mode = SEC_C_MODE_CBC,
8362306a36Sopenharmony_ci		.key_len = SEC_KEY_LEN_AES_192,
8462306a36Sopenharmony_ci	},
8562306a36Sopenharmony_ci	[SEC_C_AES_CBC_256] = {
8662306a36Sopenharmony_ci		.c_alg = SEC_C_ALG_AES,
8762306a36Sopenharmony_ci		.c_mode = SEC_C_MODE_CBC,
8862306a36Sopenharmony_ci		.key_len = SEC_KEY_LEN_AES_256,
8962306a36Sopenharmony_ci	},
9062306a36Sopenharmony_ci	[SEC_C_AES_CTR_128] = {
9162306a36Sopenharmony_ci		.c_alg = SEC_C_ALG_AES,
9262306a36Sopenharmony_ci		.c_mode = SEC_C_MODE_CTR,
9362306a36Sopenharmony_ci		.key_len = SEC_KEY_LEN_AES_128,
9462306a36Sopenharmony_ci	},
9562306a36Sopenharmony_ci	[SEC_C_AES_CTR_192] = {
9662306a36Sopenharmony_ci		.c_alg = SEC_C_ALG_AES,
9762306a36Sopenharmony_ci		.c_mode = SEC_C_MODE_CTR,
9862306a36Sopenharmony_ci		.key_len = SEC_KEY_LEN_AES_192,
9962306a36Sopenharmony_ci	},
10062306a36Sopenharmony_ci	[SEC_C_AES_CTR_256] = {
10162306a36Sopenharmony_ci		.c_alg = SEC_C_ALG_AES,
10262306a36Sopenharmony_ci		.c_mode = SEC_C_MODE_CTR,
10362306a36Sopenharmony_ci		.key_len = SEC_KEY_LEN_AES_256,
10462306a36Sopenharmony_ci	},
10562306a36Sopenharmony_ci	[SEC_C_AES_XTS_128] = {
10662306a36Sopenharmony_ci		.c_alg = SEC_C_ALG_AES,
10762306a36Sopenharmony_ci		.c_mode = SEC_C_MODE_XTS,
10862306a36Sopenharmony_ci		.key_len = SEC_KEY_LEN_AES_128,
10962306a36Sopenharmony_ci	},
11062306a36Sopenharmony_ci	[SEC_C_AES_XTS_256] = {
11162306a36Sopenharmony_ci		.c_alg = SEC_C_ALG_AES,
11262306a36Sopenharmony_ci		.c_mode = SEC_C_MODE_XTS,
11362306a36Sopenharmony_ci		.key_len = SEC_KEY_LEN_AES_256,
11462306a36Sopenharmony_ci	},
11562306a36Sopenharmony_ci	[SEC_C_NULL] = {
11662306a36Sopenharmony_ci	},
11762306a36Sopenharmony_ci};
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci/*
12062306a36Sopenharmony_ci * Mutex used to ensure safe operation of reference count of
12162306a36Sopenharmony_ci * alg providers
12262306a36Sopenharmony_ci */
12362306a36Sopenharmony_cistatic DEFINE_MUTEX(algs_lock);
12462306a36Sopenharmony_cistatic unsigned int active_devs;
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_cistatic void sec_alg_skcipher_init_template(struct sec_alg_tfm_ctx *ctx,
12762306a36Sopenharmony_ci					   struct sec_bd_info *req,
12862306a36Sopenharmony_ci					   enum sec_cipher_alg alg)
12962306a36Sopenharmony_ci{
13062306a36Sopenharmony_ci	const struct sec_c_alg_cfg *cfg = &sec_c_alg_cfgs[alg];
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	memset(req, 0, sizeof(*req));
13362306a36Sopenharmony_ci	req->w0 |= cfg->c_mode << SEC_BD_W0_C_MODE_S;
13462306a36Sopenharmony_ci	req->w1 |= cfg->c_alg << SEC_BD_W1_C_ALG_S;
13562306a36Sopenharmony_ci	req->w3 |= cfg->key_len << SEC_BD_W3_C_KEY_LEN_S;
13662306a36Sopenharmony_ci	req->w0 |= cfg->c_width << SEC_BD_W0_C_WIDTH_S;
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	req->cipher_key_addr_lo = lower_32_bits(ctx->pkey);
13962306a36Sopenharmony_ci	req->cipher_key_addr_hi = upper_32_bits(ctx->pkey);
14062306a36Sopenharmony_ci}
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_cistatic void sec_alg_skcipher_init_context(struct crypto_skcipher *atfm,
14362306a36Sopenharmony_ci					  const u8 *key,
14462306a36Sopenharmony_ci					  unsigned int keylen,
14562306a36Sopenharmony_ci					  enum sec_cipher_alg alg)
14662306a36Sopenharmony_ci{
14762306a36Sopenharmony_ci	struct crypto_tfm *tfm = crypto_skcipher_tfm(atfm);
14862306a36Sopenharmony_ci	struct sec_alg_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	ctx->cipher_alg = alg;
15162306a36Sopenharmony_ci	memcpy(ctx->key, key, keylen);
15262306a36Sopenharmony_ci	sec_alg_skcipher_init_template(ctx, &ctx->req_template,
15362306a36Sopenharmony_ci				       ctx->cipher_alg);
15462306a36Sopenharmony_ci}
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_cistatic void sec_free_hw_sgl(struct sec_hw_sgl *hw_sgl,
15762306a36Sopenharmony_ci			    dma_addr_t psec_sgl, struct sec_dev_info *info)
15862306a36Sopenharmony_ci{
15962306a36Sopenharmony_ci	struct sec_hw_sgl *sgl_current, *sgl_next;
16062306a36Sopenharmony_ci	dma_addr_t sgl_next_dma;
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	sgl_current = hw_sgl;
16362306a36Sopenharmony_ci	while (sgl_current) {
16462306a36Sopenharmony_ci		sgl_next = sgl_current->next;
16562306a36Sopenharmony_ci		sgl_next_dma = sgl_current->next_sgl;
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci		dma_pool_free(info->hw_sgl_pool, sgl_current, psec_sgl);
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci		sgl_current = sgl_next;
17062306a36Sopenharmony_ci		psec_sgl = sgl_next_dma;
17162306a36Sopenharmony_ci	}
17262306a36Sopenharmony_ci}
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_cistatic int sec_alloc_and_fill_hw_sgl(struct sec_hw_sgl **sec_sgl,
17562306a36Sopenharmony_ci				     dma_addr_t *psec_sgl,
17662306a36Sopenharmony_ci				     struct scatterlist *sgl,
17762306a36Sopenharmony_ci				     int count,
17862306a36Sopenharmony_ci				     struct sec_dev_info *info,
17962306a36Sopenharmony_ci				     gfp_t gfp)
18062306a36Sopenharmony_ci{
18162306a36Sopenharmony_ci	struct sec_hw_sgl *sgl_current = NULL;
18262306a36Sopenharmony_ci	struct sec_hw_sgl *sgl_next;
18362306a36Sopenharmony_ci	dma_addr_t sgl_next_dma;
18462306a36Sopenharmony_ci	struct scatterlist *sg;
18562306a36Sopenharmony_ci	int ret, sge_index, i;
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	if (!count)
18862306a36Sopenharmony_ci		return -EINVAL;
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci	for_each_sg(sgl, sg, count, i) {
19162306a36Sopenharmony_ci		sge_index = i % SEC_MAX_SGE_NUM;
19262306a36Sopenharmony_ci		if (sge_index == 0) {
19362306a36Sopenharmony_ci			sgl_next = dma_pool_zalloc(info->hw_sgl_pool,
19462306a36Sopenharmony_ci						   gfp, &sgl_next_dma);
19562306a36Sopenharmony_ci			if (!sgl_next) {
19662306a36Sopenharmony_ci				ret = -ENOMEM;
19762306a36Sopenharmony_ci				goto err_free_hw_sgls;
19862306a36Sopenharmony_ci			}
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci			if (!sgl_current) { /* First one */
20162306a36Sopenharmony_ci				*psec_sgl = sgl_next_dma;
20262306a36Sopenharmony_ci				*sec_sgl = sgl_next;
20362306a36Sopenharmony_ci			} else { /* Chained */
20462306a36Sopenharmony_ci				sgl_current->entry_sum_in_sgl = SEC_MAX_SGE_NUM;
20562306a36Sopenharmony_ci				sgl_current->next_sgl = sgl_next_dma;
20662306a36Sopenharmony_ci				sgl_current->next = sgl_next;
20762306a36Sopenharmony_ci			}
20862306a36Sopenharmony_ci			sgl_current = sgl_next;
20962306a36Sopenharmony_ci		}
21062306a36Sopenharmony_ci		sgl_current->sge_entries[sge_index].buf = sg_dma_address(sg);
21162306a36Sopenharmony_ci		sgl_current->sge_entries[sge_index].len = sg_dma_len(sg);
21262306a36Sopenharmony_ci		sgl_current->data_bytes_in_sgl += sg_dma_len(sg);
21362306a36Sopenharmony_ci	}
21462306a36Sopenharmony_ci	sgl_current->entry_sum_in_sgl = count % SEC_MAX_SGE_NUM;
21562306a36Sopenharmony_ci	sgl_current->next_sgl = 0;
21662306a36Sopenharmony_ci	(*sec_sgl)->entry_sum_in_chain = count;
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	return 0;
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_cierr_free_hw_sgls:
22162306a36Sopenharmony_ci	sec_free_hw_sgl(*sec_sgl, *psec_sgl, info);
22262306a36Sopenharmony_ci	*psec_sgl = 0;
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	return ret;
22562306a36Sopenharmony_ci}
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_cistatic int sec_alg_skcipher_setkey(struct crypto_skcipher *tfm,
22862306a36Sopenharmony_ci				   const u8 *key, unsigned int keylen,
22962306a36Sopenharmony_ci				   enum sec_cipher_alg alg)
23062306a36Sopenharmony_ci{
23162306a36Sopenharmony_ci	struct sec_alg_tfm_ctx *ctx = crypto_skcipher_ctx(tfm);
23262306a36Sopenharmony_ci	struct device *dev = ctx->queue->dev_info->dev;
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci	mutex_lock(&ctx->lock);
23562306a36Sopenharmony_ci	if (ctx->key) {
23662306a36Sopenharmony_ci		/* rekeying */
23762306a36Sopenharmony_ci		memset(ctx->key, 0, SEC_MAX_CIPHER_KEY);
23862306a36Sopenharmony_ci	} else {
23962306a36Sopenharmony_ci		/* new key */
24062306a36Sopenharmony_ci		ctx->key = dma_alloc_coherent(dev, SEC_MAX_CIPHER_KEY,
24162306a36Sopenharmony_ci					      &ctx->pkey, GFP_KERNEL);
24262306a36Sopenharmony_ci		if (!ctx->key) {
24362306a36Sopenharmony_ci			mutex_unlock(&ctx->lock);
24462306a36Sopenharmony_ci			return -ENOMEM;
24562306a36Sopenharmony_ci		}
24662306a36Sopenharmony_ci	}
24762306a36Sopenharmony_ci	mutex_unlock(&ctx->lock);
24862306a36Sopenharmony_ci	sec_alg_skcipher_init_context(tfm, key, keylen, alg);
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	return 0;
25162306a36Sopenharmony_ci}
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_cistatic int sec_alg_skcipher_setkey_aes_ecb(struct crypto_skcipher *tfm,
25462306a36Sopenharmony_ci					   const u8 *key, unsigned int keylen)
25562306a36Sopenharmony_ci{
25662306a36Sopenharmony_ci	enum sec_cipher_alg alg;
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	switch (keylen) {
25962306a36Sopenharmony_ci	case AES_KEYSIZE_128:
26062306a36Sopenharmony_ci		alg = SEC_C_AES_ECB_128;
26162306a36Sopenharmony_ci		break;
26262306a36Sopenharmony_ci	case AES_KEYSIZE_192:
26362306a36Sopenharmony_ci		alg = SEC_C_AES_ECB_192;
26462306a36Sopenharmony_ci		break;
26562306a36Sopenharmony_ci	case AES_KEYSIZE_256:
26662306a36Sopenharmony_ci		alg = SEC_C_AES_ECB_256;
26762306a36Sopenharmony_ci		break;
26862306a36Sopenharmony_ci	default:
26962306a36Sopenharmony_ci		return -EINVAL;
27062306a36Sopenharmony_ci	}
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	return sec_alg_skcipher_setkey(tfm, key, keylen, alg);
27362306a36Sopenharmony_ci}
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_cistatic int sec_alg_skcipher_setkey_aes_cbc(struct crypto_skcipher *tfm,
27662306a36Sopenharmony_ci					   const u8 *key, unsigned int keylen)
27762306a36Sopenharmony_ci{
27862306a36Sopenharmony_ci	enum sec_cipher_alg alg;
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	switch (keylen) {
28162306a36Sopenharmony_ci	case AES_KEYSIZE_128:
28262306a36Sopenharmony_ci		alg = SEC_C_AES_CBC_128;
28362306a36Sopenharmony_ci		break;
28462306a36Sopenharmony_ci	case AES_KEYSIZE_192:
28562306a36Sopenharmony_ci		alg = SEC_C_AES_CBC_192;
28662306a36Sopenharmony_ci		break;
28762306a36Sopenharmony_ci	case AES_KEYSIZE_256:
28862306a36Sopenharmony_ci		alg = SEC_C_AES_CBC_256;
28962306a36Sopenharmony_ci		break;
29062306a36Sopenharmony_ci	default:
29162306a36Sopenharmony_ci		return -EINVAL;
29262306a36Sopenharmony_ci	}
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	return sec_alg_skcipher_setkey(tfm, key, keylen, alg);
29562306a36Sopenharmony_ci}
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_cistatic int sec_alg_skcipher_setkey_aes_ctr(struct crypto_skcipher *tfm,
29862306a36Sopenharmony_ci					   const u8 *key, unsigned int keylen)
29962306a36Sopenharmony_ci{
30062306a36Sopenharmony_ci	enum sec_cipher_alg alg;
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	switch (keylen) {
30362306a36Sopenharmony_ci	case AES_KEYSIZE_128:
30462306a36Sopenharmony_ci		alg = SEC_C_AES_CTR_128;
30562306a36Sopenharmony_ci		break;
30662306a36Sopenharmony_ci	case AES_KEYSIZE_192:
30762306a36Sopenharmony_ci		alg = SEC_C_AES_CTR_192;
30862306a36Sopenharmony_ci		break;
30962306a36Sopenharmony_ci	case AES_KEYSIZE_256:
31062306a36Sopenharmony_ci		alg = SEC_C_AES_CTR_256;
31162306a36Sopenharmony_ci		break;
31262306a36Sopenharmony_ci	default:
31362306a36Sopenharmony_ci		return -EINVAL;
31462306a36Sopenharmony_ci	}
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci	return sec_alg_skcipher_setkey(tfm, key, keylen, alg);
31762306a36Sopenharmony_ci}
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_cistatic int sec_alg_skcipher_setkey_aes_xts(struct crypto_skcipher *tfm,
32062306a36Sopenharmony_ci					   const u8 *key, unsigned int keylen)
32162306a36Sopenharmony_ci{
32262306a36Sopenharmony_ci	enum sec_cipher_alg alg;
32362306a36Sopenharmony_ci	int ret;
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	ret = xts_verify_key(tfm, key, keylen);
32662306a36Sopenharmony_ci	if (ret)
32762306a36Sopenharmony_ci		return ret;
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	switch (keylen) {
33062306a36Sopenharmony_ci	case AES_KEYSIZE_128 * 2:
33162306a36Sopenharmony_ci		alg = SEC_C_AES_XTS_128;
33262306a36Sopenharmony_ci		break;
33362306a36Sopenharmony_ci	case AES_KEYSIZE_256 * 2:
33462306a36Sopenharmony_ci		alg = SEC_C_AES_XTS_256;
33562306a36Sopenharmony_ci		break;
33662306a36Sopenharmony_ci	default:
33762306a36Sopenharmony_ci		return -EINVAL;
33862306a36Sopenharmony_ci	}
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	return sec_alg_skcipher_setkey(tfm, key, keylen, alg);
34162306a36Sopenharmony_ci}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_cistatic int sec_alg_skcipher_setkey_des_ecb(struct crypto_skcipher *tfm,
34462306a36Sopenharmony_ci					   const u8 *key, unsigned int keylen)
34562306a36Sopenharmony_ci{
34662306a36Sopenharmony_ci	return verify_skcipher_des_key(tfm, key) ?:
34762306a36Sopenharmony_ci	       sec_alg_skcipher_setkey(tfm, key, keylen, SEC_C_DES_ECB_64);
34862306a36Sopenharmony_ci}
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_cistatic int sec_alg_skcipher_setkey_des_cbc(struct crypto_skcipher *tfm,
35162306a36Sopenharmony_ci					   const u8 *key, unsigned int keylen)
35262306a36Sopenharmony_ci{
35362306a36Sopenharmony_ci	return verify_skcipher_des_key(tfm, key) ?:
35462306a36Sopenharmony_ci	       sec_alg_skcipher_setkey(tfm, key, keylen, SEC_C_DES_CBC_64);
35562306a36Sopenharmony_ci}
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_cistatic int sec_alg_skcipher_setkey_3des_ecb(struct crypto_skcipher *tfm,
35862306a36Sopenharmony_ci					    const u8 *key, unsigned int keylen)
35962306a36Sopenharmony_ci{
36062306a36Sopenharmony_ci	return verify_skcipher_des3_key(tfm, key) ?:
36162306a36Sopenharmony_ci	       sec_alg_skcipher_setkey(tfm, key, keylen,
36262306a36Sopenharmony_ci				       SEC_C_3DES_ECB_192_3KEY);
36362306a36Sopenharmony_ci}
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_cistatic int sec_alg_skcipher_setkey_3des_cbc(struct crypto_skcipher *tfm,
36662306a36Sopenharmony_ci					    const u8 *key, unsigned int keylen)
36762306a36Sopenharmony_ci{
36862306a36Sopenharmony_ci	return verify_skcipher_des3_key(tfm, key) ?:
36962306a36Sopenharmony_ci	       sec_alg_skcipher_setkey(tfm, key, keylen,
37062306a36Sopenharmony_ci				       SEC_C_3DES_CBC_192_3KEY);
37162306a36Sopenharmony_ci}
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_cistatic void sec_alg_free_el(struct sec_request_el *el,
37462306a36Sopenharmony_ci			    struct sec_dev_info *info)
37562306a36Sopenharmony_ci{
37662306a36Sopenharmony_ci	sec_free_hw_sgl(el->out, el->dma_out, info);
37762306a36Sopenharmony_ci	sec_free_hw_sgl(el->in, el->dma_in, info);
37862306a36Sopenharmony_ci	kfree(el->sgl_in);
37962306a36Sopenharmony_ci	kfree(el->sgl_out);
38062306a36Sopenharmony_ci	kfree(el);
38162306a36Sopenharmony_ci}
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci/* queuelock must be held */
38462306a36Sopenharmony_cistatic int sec_send_request(struct sec_request *sec_req, struct sec_queue *queue)
38562306a36Sopenharmony_ci{
38662306a36Sopenharmony_ci	struct sec_request_el *el, *temp;
38762306a36Sopenharmony_ci	int ret = 0;
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_ci	mutex_lock(&sec_req->lock);
39062306a36Sopenharmony_ci	list_for_each_entry_safe(el, temp, &sec_req->elements, head) {
39162306a36Sopenharmony_ci		/*
39262306a36Sopenharmony_ci		 * Add to hardware queue only under following circumstances
39362306a36Sopenharmony_ci		 * 1) Software and hardware queue empty so no chain dependencies
39462306a36Sopenharmony_ci		 * 2) No dependencies as new IV - (check software queue empty
39562306a36Sopenharmony_ci		 *    to maintain order)
39662306a36Sopenharmony_ci		 * 3) No dependencies because the mode does no chaining.
39762306a36Sopenharmony_ci		 *
39862306a36Sopenharmony_ci		 * In other cases first insert onto the software queue which
39962306a36Sopenharmony_ci		 * is then emptied as requests complete
40062306a36Sopenharmony_ci		 */
40162306a36Sopenharmony_ci		if (!queue->havesoftqueue ||
40262306a36Sopenharmony_ci		    (kfifo_is_empty(&queue->softqueue) &&
40362306a36Sopenharmony_ci		     sec_queue_empty(queue))) {
40462306a36Sopenharmony_ci			ret = sec_queue_send(queue, &el->req, sec_req);
40562306a36Sopenharmony_ci			if (ret == -EAGAIN) {
40662306a36Sopenharmony_ci				/* Wait unti we can send then try again */
40762306a36Sopenharmony_ci				/* DEAD if here - should not happen */
40862306a36Sopenharmony_ci				ret = -EBUSY;
40962306a36Sopenharmony_ci				goto err_unlock;
41062306a36Sopenharmony_ci			}
41162306a36Sopenharmony_ci		} else {
41262306a36Sopenharmony_ci			kfifo_put(&queue->softqueue, el);
41362306a36Sopenharmony_ci		}
41462306a36Sopenharmony_ci	}
41562306a36Sopenharmony_cierr_unlock:
41662306a36Sopenharmony_ci	mutex_unlock(&sec_req->lock);
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci	return ret;
41962306a36Sopenharmony_ci}
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_cistatic void sec_skcipher_alg_callback(struct sec_bd_info *sec_resp,
42262306a36Sopenharmony_ci				      struct crypto_async_request *req_base)
42362306a36Sopenharmony_ci{
42462306a36Sopenharmony_ci	struct skcipher_request *skreq = container_of(req_base,
42562306a36Sopenharmony_ci						      struct skcipher_request,
42662306a36Sopenharmony_ci						      base);
42762306a36Sopenharmony_ci	struct sec_request *sec_req = skcipher_request_ctx(skreq);
42862306a36Sopenharmony_ci	struct sec_request *backlog_req;
42962306a36Sopenharmony_ci	struct sec_request_el *sec_req_el, *nextrequest;
43062306a36Sopenharmony_ci	struct sec_alg_tfm_ctx *ctx = sec_req->tfm_ctx;
43162306a36Sopenharmony_ci	struct crypto_skcipher *atfm = crypto_skcipher_reqtfm(skreq);
43262306a36Sopenharmony_ci	struct device *dev = ctx->queue->dev_info->dev;
43362306a36Sopenharmony_ci	int icv_or_skey_en, ret;
43462306a36Sopenharmony_ci	bool done;
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	sec_req_el = list_first_entry(&sec_req->elements, struct sec_request_el,
43762306a36Sopenharmony_ci				      head);
43862306a36Sopenharmony_ci	icv_or_skey_en = (sec_resp->w0 & SEC_BD_W0_ICV_OR_SKEY_EN_M) >>
43962306a36Sopenharmony_ci		SEC_BD_W0_ICV_OR_SKEY_EN_S;
44062306a36Sopenharmony_ci	if (sec_resp->w1 & SEC_BD_W1_BD_INVALID || icv_or_skey_en == 3) {
44162306a36Sopenharmony_ci		dev_err(dev, "Got an invalid answer %lu %d\n",
44262306a36Sopenharmony_ci			sec_resp->w1 & SEC_BD_W1_BD_INVALID,
44362306a36Sopenharmony_ci			icv_or_skey_en);
44462306a36Sopenharmony_ci		sec_req->err = -EINVAL;
44562306a36Sopenharmony_ci		/*
44662306a36Sopenharmony_ci		 * We need to muddle on to avoid getting stuck with elements
44762306a36Sopenharmony_ci		 * on the queue. Error will be reported so requester so
44862306a36Sopenharmony_ci		 * it should be able to handle appropriately.
44962306a36Sopenharmony_ci		 */
45062306a36Sopenharmony_ci	}
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci	spin_lock_bh(&ctx->queue->queuelock);
45362306a36Sopenharmony_ci	/* Put the IV in place for chained cases */
45462306a36Sopenharmony_ci	switch (ctx->cipher_alg) {
45562306a36Sopenharmony_ci	case SEC_C_AES_CBC_128:
45662306a36Sopenharmony_ci	case SEC_C_AES_CBC_192:
45762306a36Sopenharmony_ci	case SEC_C_AES_CBC_256:
45862306a36Sopenharmony_ci		if (sec_req_el->req.w0 & SEC_BD_W0_DE)
45962306a36Sopenharmony_ci			sg_pcopy_to_buffer(sec_req_el->sgl_out,
46062306a36Sopenharmony_ci					   sg_nents(sec_req_el->sgl_out),
46162306a36Sopenharmony_ci					   skreq->iv,
46262306a36Sopenharmony_ci					   crypto_skcipher_ivsize(atfm),
46362306a36Sopenharmony_ci					   sec_req_el->el_length -
46462306a36Sopenharmony_ci					   crypto_skcipher_ivsize(atfm));
46562306a36Sopenharmony_ci		else
46662306a36Sopenharmony_ci			sg_pcopy_to_buffer(sec_req_el->sgl_in,
46762306a36Sopenharmony_ci					   sg_nents(sec_req_el->sgl_in),
46862306a36Sopenharmony_ci					   skreq->iv,
46962306a36Sopenharmony_ci					   crypto_skcipher_ivsize(atfm),
47062306a36Sopenharmony_ci					   sec_req_el->el_length -
47162306a36Sopenharmony_ci					   crypto_skcipher_ivsize(atfm));
47262306a36Sopenharmony_ci		/* No need to sync to the device as coherent DMA */
47362306a36Sopenharmony_ci		break;
47462306a36Sopenharmony_ci	case SEC_C_AES_CTR_128:
47562306a36Sopenharmony_ci	case SEC_C_AES_CTR_192:
47662306a36Sopenharmony_ci	case SEC_C_AES_CTR_256:
47762306a36Sopenharmony_ci		crypto_inc(skreq->iv, 16);
47862306a36Sopenharmony_ci		break;
47962306a36Sopenharmony_ci	default:
48062306a36Sopenharmony_ci		/* Do not update */
48162306a36Sopenharmony_ci		break;
48262306a36Sopenharmony_ci	}
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci	if (ctx->queue->havesoftqueue &&
48562306a36Sopenharmony_ci	    !kfifo_is_empty(&ctx->queue->softqueue) &&
48662306a36Sopenharmony_ci	    sec_queue_empty(ctx->queue)) {
48762306a36Sopenharmony_ci		ret = kfifo_get(&ctx->queue->softqueue, &nextrequest);
48862306a36Sopenharmony_ci		if (ret <= 0)
48962306a36Sopenharmony_ci			dev_err(dev,
49062306a36Sopenharmony_ci				"Error getting next element from kfifo %d\n",
49162306a36Sopenharmony_ci				ret);
49262306a36Sopenharmony_ci		else
49362306a36Sopenharmony_ci			/* We know there is space so this cannot fail */
49462306a36Sopenharmony_ci			sec_queue_send(ctx->queue, &nextrequest->req,
49562306a36Sopenharmony_ci				       nextrequest->sec_req);
49662306a36Sopenharmony_ci	} else if (!list_empty(&ctx->backlog)) {
49762306a36Sopenharmony_ci		/* Need to verify there is room first */
49862306a36Sopenharmony_ci		backlog_req = list_first_entry(&ctx->backlog,
49962306a36Sopenharmony_ci					       typeof(*backlog_req),
50062306a36Sopenharmony_ci					       backlog_head);
50162306a36Sopenharmony_ci		if (sec_queue_can_enqueue(ctx->queue,
50262306a36Sopenharmony_ci		    backlog_req->num_elements) ||
50362306a36Sopenharmony_ci		    (ctx->queue->havesoftqueue &&
50462306a36Sopenharmony_ci		     kfifo_avail(&ctx->queue->softqueue) >
50562306a36Sopenharmony_ci		     backlog_req->num_elements)) {
50662306a36Sopenharmony_ci			sec_send_request(backlog_req, ctx->queue);
50762306a36Sopenharmony_ci			crypto_request_complete(backlog_req->req_base,
50862306a36Sopenharmony_ci						-EINPROGRESS);
50962306a36Sopenharmony_ci			list_del(&backlog_req->backlog_head);
51062306a36Sopenharmony_ci		}
51162306a36Sopenharmony_ci	}
51262306a36Sopenharmony_ci	spin_unlock_bh(&ctx->queue->queuelock);
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ci	mutex_lock(&sec_req->lock);
51562306a36Sopenharmony_ci	list_del(&sec_req_el->head);
51662306a36Sopenharmony_ci	mutex_unlock(&sec_req->lock);
51762306a36Sopenharmony_ci	sec_alg_free_el(sec_req_el, ctx->queue->dev_info);
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci	/*
52062306a36Sopenharmony_ci	 * Request is done.
52162306a36Sopenharmony_ci	 * The dance is needed as the lock is freed in the completion
52262306a36Sopenharmony_ci	 */
52362306a36Sopenharmony_ci	mutex_lock(&sec_req->lock);
52462306a36Sopenharmony_ci	done = list_empty(&sec_req->elements);
52562306a36Sopenharmony_ci	mutex_unlock(&sec_req->lock);
52662306a36Sopenharmony_ci	if (done) {
52762306a36Sopenharmony_ci		if (crypto_skcipher_ivsize(atfm)) {
52862306a36Sopenharmony_ci			dma_unmap_single(dev, sec_req->dma_iv,
52962306a36Sopenharmony_ci					 crypto_skcipher_ivsize(atfm),
53062306a36Sopenharmony_ci					 DMA_TO_DEVICE);
53162306a36Sopenharmony_ci		}
53262306a36Sopenharmony_ci		dma_unmap_sg(dev, skreq->src, sec_req->len_in,
53362306a36Sopenharmony_ci			     DMA_BIDIRECTIONAL);
53462306a36Sopenharmony_ci		if (skreq->src != skreq->dst)
53562306a36Sopenharmony_ci			dma_unmap_sg(dev, skreq->dst, sec_req->len_out,
53662306a36Sopenharmony_ci				     DMA_BIDIRECTIONAL);
53762306a36Sopenharmony_ci		skcipher_request_complete(skreq, sec_req->err);
53862306a36Sopenharmony_ci	}
53962306a36Sopenharmony_ci}
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_civoid sec_alg_callback(struct sec_bd_info *resp, void *shadow)
54262306a36Sopenharmony_ci{
54362306a36Sopenharmony_ci	struct sec_request *sec_req = shadow;
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci	sec_req->cb(resp, sec_req->req_base);
54662306a36Sopenharmony_ci}
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_cistatic int sec_alg_alloc_and_calc_split_sizes(int length, size_t **split_sizes,
54962306a36Sopenharmony_ci					      int *steps, gfp_t gfp)
55062306a36Sopenharmony_ci{
55162306a36Sopenharmony_ci	size_t *sizes;
55262306a36Sopenharmony_ci	int i;
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci	/* Split into suitable sized blocks */
55562306a36Sopenharmony_ci	*steps = roundup(length, SEC_REQ_LIMIT) / SEC_REQ_LIMIT;
55662306a36Sopenharmony_ci	sizes = kcalloc(*steps, sizeof(*sizes), gfp);
55762306a36Sopenharmony_ci	if (!sizes)
55862306a36Sopenharmony_ci		return -ENOMEM;
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ci	for (i = 0; i < *steps - 1; i++)
56162306a36Sopenharmony_ci		sizes[i] = SEC_REQ_LIMIT;
56262306a36Sopenharmony_ci	sizes[*steps - 1] = length - SEC_REQ_LIMIT * (*steps - 1);
56362306a36Sopenharmony_ci	*split_sizes = sizes;
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci	return 0;
56662306a36Sopenharmony_ci}
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_cistatic int sec_map_and_split_sg(struct scatterlist *sgl, size_t *split_sizes,
56962306a36Sopenharmony_ci				int steps, struct scatterlist ***splits,
57062306a36Sopenharmony_ci				int **splits_nents,
57162306a36Sopenharmony_ci				int sgl_len_in,
57262306a36Sopenharmony_ci				struct device *dev, gfp_t gfp)
57362306a36Sopenharmony_ci{
57462306a36Sopenharmony_ci	int ret, count;
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci	count = dma_map_sg(dev, sgl, sgl_len_in, DMA_BIDIRECTIONAL);
57762306a36Sopenharmony_ci	if (!count)
57862306a36Sopenharmony_ci		return -EINVAL;
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci	*splits = kcalloc(steps, sizeof(struct scatterlist *), gfp);
58162306a36Sopenharmony_ci	if (!*splits) {
58262306a36Sopenharmony_ci		ret = -ENOMEM;
58362306a36Sopenharmony_ci		goto err_unmap_sg;
58462306a36Sopenharmony_ci	}
58562306a36Sopenharmony_ci	*splits_nents = kcalloc(steps, sizeof(int), gfp);
58662306a36Sopenharmony_ci	if (!*splits_nents) {
58762306a36Sopenharmony_ci		ret = -ENOMEM;
58862306a36Sopenharmony_ci		goto err_free_splits;
58962306a36Sopenharmony_ci	}
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	/* output the scatter list before and after this */
59262306a36Sopenharmony_ci	ret = sg_split(sgl, count, 0, steps, split_sizes,
59362306a36Sopenharmony_ci		       *splits, *splits_nents, gfp);
59462306a36Sopenharmony_ci	if (ret) {
59562306a36Sopenharmony_ci		ret = -ENOMEM;
59662306a36Sopenharmony_ci		goto err_free_splits_nents;
59762306a36Sopenharmony_ci	}
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci	return 0;
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_cierr_free_splits_nents:
60262306a36Sopenharmony_ci	kfree(*splits_nents);
60362306a36Sopenharmony_cierr_free_splits:
60462306a36Sopenharmony_ci	kfree(*splits);
60562306a36Sopenharmony_cierr_unmap_sg:
60662306a36Sopenharmony_ci	dma_unmap_sg(dev, sgl, sgl_len_in, DMA_BIDIRECTIONAL);
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci	return ret;
60962306a36Sopenharmony_ci}
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_ci/*
61262306a36Sopenharmony_ci * Reverses the sec_map_and_split_sg call for messages not yet added to
61362306a36Sopenharmony_ci * the queues.
61462306a36Sopenharmony_ci */
61562306a36Sopenharmony_cistatic void sec_unmap_sg_on_err(struct scatterlist *sgl, int steps,
61662306a36Sopenharmony_ci				struct scatterlist **splits, int *splits_nents,
61762306a36Sopenharmony_ci				int sgl_len_in, struct device *dev)
61862306a36Sopenharmony_ci{
61962306a36Sopenharmony_ci	int i;
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_ci	for (i = 0; i < steps; i++)
62262306a36Sopenharmony_ci		kfree(splits[i]);
62362306a36Sopenharmony_ci	kfree(splits_nents);
62462306a36Sopenharmony_ci	kfree(splits);
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci	dma_unmap_sg(dev, sgl, sgl_len_in, DMA_BIDIRECTIONAL);
62762306a36Sopenharmony_ci}
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_cistatic struct sec_request_el
63062306a36Sopenharmony_ci*sec_alg_alloc_and_fill_el(struct sec_bd_info *template, int encrypt,
63162306a36Sopenharmony_ci			   int el_size, bool different_dest,
63262306a36Sopenharmony_ci			   struct scatterlist *sgl_in, int n_ents_in,
63362306a36Sopenharmony_ci			   struct scatterlist *sgl_out, int n_ents_out,
63462306a36Sopenharmony_ci			   struct sec_dev_info *info, gfp_t gfp)
63562306a36Sopenharmony_ci{
63662306a36Sopenharmony_ci	struct sec_request_el *el;
63762306a36Sopenharmony_ci	struct sec_bd_info *req;
63862306a36Sopenharmony_ci	int ret;
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci	el = kzalloc(sizeof(*el), gfp);
64162306a36Sopenharmony_ci	if (!el)
64262306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
64362306a36Sopenharmony_ci	el->el_length = el_size;
64462306a36Sopenharmony_ci	req = &el->req;
64562306a36Sopenharmony_ci	memcpy(req, template, sizeof(*req));
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci	req->w0 &= ~SEC_BD_W0_CIPHER_M;
64862306a36Sopenharmony_ci	if (encrypt)
64962306a36Sopenharmony_ci		req->w0 |= SEC_CIPHER_ENCRYPT << SEC_BD_W0_CIPHER_S;
65062306a36Sopenharmony_ci	else
65162306a36Sopenharmony_ci		req->w0 |= SEC_CIPHER_DECRYPT << SEC_BD_W0_CIPHER_S;
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci	req->w0 &= ~SEC_BD_W0_C_GRAN_SIZE_19_16_M;
65462306a36Sopenharmony_ci	req->w0 |= ((el_size >> 16) << SEC_BD_W0_C_GRAN_SIZE_19_16_S) &
65562306a36Sopenharmony_ci		SEC_BD_W0_C_GRAN_SIZE_19_16_M;
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci	req->w0 &= ~SEC_BD_W0_C_GRAN_SIZE_21_20_M;
65862306a36Sopenharmony_ci	req->w0 |= ((el_size >> 20) << SEC_BD_W0_C_GRAN_SIZE_21_20_S) &
65962306a36Sopenharmony_ci		SEC_BD_W0_C_GRAN_SIZE_21_20_M;
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci	/* Writing whole u32 so no need to take care of masking */
66262306a36Sopenharmony_ci	req->w2 = ((1 << SEC_BD_W2_GRAN_NUM_S) & SEC_BD_W2_GRAN_NUM_M) |
66362306a36Sopenharmony_ci		((el_size << SEC_BD_W2_C_GRAN_SIZE_15_0_S) &
66462306a36Sopenharmony_ci		 SEC_BD_W2_C_GRAN_SIZE_15_0_M);
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci	req->w3 &= ~SEC_BD_W3_CIPHER_LEN_OFFSET_M;
66762306a36Sopenharmony_ci	req->w1 |= SEC_BD_W1_ADDR_TYPE;
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci	el->sgl_in = sgl_in;
67062306a36Sopenharmony_ci
67162306a36Sopenharmony_ci	ret = sec_alloc_and_fill_hw_sgl(&el->in, &el->dma_in, el->sgl_in,
67262306a36Sopenharmony_ci					n_ents_in, info, gfp);
67362306a36Sopenharmony_ci	if (ret)
67462306a36Sopenharmony_ci		goto err_free_el;
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci	req->data_addr_lo = lower_32_bits(el->dma_in);
67762306a36Sopenharmony_ci	req->data_addr_hi = upper_32_bits(el->dma_in);
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_ci	if (different_dest) {
68062306a36Sopenharmony_ci		el->sgl_out = sgl_out;
68162306a36Sopenharmony_ci		ret = sec_alloc_and_fill_hw_sgl(&el->out, &el->dma_out,
68262306a36Sopenharmony_ci						el->sgl_out,
68362306a36Sopenharmony_ci						n_ents_out, info, gfp);
68462306a36Sopenharmony_ci		if (ret)
68562306a36Sopenharmony_ci			goto err_free_hw_sgl_in;
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_ci		req->w0 |= SEC_BD_W0_DE;
68862306a36Sopenharmony_ci		req->cipher_destin_addr_lo = lower_32_bits(el->dma_out);
68962306a36Sopenharmony_ci		req->cipher_destin_addr_hi = upper_32_bits(el->dma_out);
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_ci	} else {
69262306a36Sopenharmony_ci		req->w0 &= ~SEC_BD_W0_DE;
69362306a36Sopenharmony_ci		req->cipher_destin_addr_lo = lower_32_bits(el->dma_in);
69462306a36Sopenharmony_ci		req->cipher_destin_addr_hi = upper_32_bits(el->dma_in);
69562306a36Sopenharmony_ci	}
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_ci	return el;
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_cierr_free_hw_sgl_in:
70062306a36Sopenharmony_ci	sec_free_hw_sgl(el->in, el->dma_in, info);
70162306a36Sopenharmony_cierr_free_el:
70262306a36Sopenharmony_ci	kfree(el);
70362306a36Sopenharmony_ci
70462306a36Sopenharmony_ci	return ERR_PTR(ret);
70562306a36Sopenharmony_ci}
70662306a36Sopenharmony_ci
70762306a36Sopenharmony_cistatic int sec_alg_skcipher_crypto(struct skcipher_request *skreq,
70862306a36Sopenharmony_ci				   bool encrypt)
70962306a36Sopenharmony_ci{
71062306a36Sopenharmony_ci	struct crypto_skcipher *atfm = crypto_skcipher_reqtfm(skreq);
71162306a36Sopenharmony_ci	struct crypto_tfm *tfm = crypto_skcipher_tfm(atfm);
71262306a36Sopenharmony_ci	struct sec_alg_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
71362306a36Sopenharmony_ci	struct sec_queue *queue = ctx->queue;
71462306a36Sopenharmony_ci	struct sec_request *sec_req = skcipher_request_ctx(skreq);
71562306a36Sopenharmony_ci	struct sec_dev_info *info = queue->dev_info;
71662306a36Sopenharmony_ci	int i, ret, steps;
71762306a36Sopenharmony_ci	size_t *split_sizes;
71862306a36Sopenharmony_ci	struct scatterlist **splits_in;
71962306a36Sopenharmony_ci	struct scatterlist **splits_out = NULL;
72062306a36Sopenharmony_ci	int *splits_in_nents;
72162306a36Sopenharmony_ci	int *splits_out_nents = NULL;
72262306a36Sopenharmony_ci	struct sec_request_el *el, *temp;
72362306a36Sopenharmony_ci	bool split = skreq->src != skreq->dst;
72462306a36Sopenharmony_ci	gfp_t gfp = skreq->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : GFP_ATOMIC;
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_ci	mutex_init(&sec_req->lock);
72762306a36Sopenharmony_ci	sec_req->req_base = &skreq->base;
72862306a36Sopenharmony_ci	sec_req->err = 0;
72962306a36Sopenharmony_ci	/* SGL mapping out here to allow us to break it up as necessary */
73062306a36Sopenharmony_ci	sec_req->len_in = sg_nents(skreq->src);
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci	ret = sec_alg_alloc_and_calc_split_sizes(skreq->cryptlen, &split_sizes,
73362306a36Sopenharmony_ci						 &steps, gfp);
73462306a36Sopenharmony_ci	if (ret)
73562306a36Sopenharmony_ci		return ret;
73662306a36Sopenharmony_ci	sec_req->num_elements = steps;
73762306a36Sopenharmony_ci	ret = sec_map_and_split_sg(skreq->src, split_sizes, steps, &splits_in,
73862306a36Sopenharmony_ci				   &splits_in_nents, sec_req->len_in,
73962306a36Sopenharmony_ci				   info->dev, gfp);
74062306a36Sopenharmony_ci	if (ret)
74162306a36Sopenharmony_ci		goto err_free_split_sizes;
74262306a36Sopenharmony_ci
74362306a36Sopenharmony_ci	if (split) {
74462306a36Sopenharmony_ci		sec_req->len_out = sg_nents(skreq->dst);
74562306a36Sopenharmony_ci		ret = sec_map_and_split_sg(skreq->dst, split_sizes, steps,
74662306a36Sopenharmony_ci					   &splits_out, &splits_out_nents,
74762306a36Sopenharmony_ci					   sec_req->len_out, info->dev, gfp);
74862306a36Sopenharmony_ci		if (ret)
74962306a36Sopenharmony_ci			goto err_unmap_in_sg;
75062306a36Sopenharmony_ci	}
75162306a36Sopenharmony_ci	/* Shared info stored in seq_req - applies to all BDs */
75262306a36Sopenharmony_ci	sec_req->tfm_ctx = ctx;
75362306a36Sopenharmony_ci	sec_req->cb = sec_skcipher_alg_callback;
75462306a36Sopenharmony_ci	INIT_LIST_HEAD(&sec_req->elements);
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ci	/*
75762306a36Sopenharmony_ci	 * Future optimization.
75862306a36Sopenharmony_ci	 * In the chaining case we can't use a dma pool bounce buffer
75962306a36Sopenharmony_ci	 * but in the case where we know there is no chaining we can
76062306a36Sopenharmony_ci	 */
76162306a36Sopenharmony_ci	if (crypto_skcipher_ivsize(atfm)) {
76262306a36Sopenharmony_ci		sec_req->dma_iv = dma_map_single(info->dev, skreq->iv,
76362306a36Sopenharmony_ci						 crypto_skcipher_ivsize(atfm),
76462306a36Sopenharmony_ci						 DMA_TO_DEVICE);
76562306a36Sopenharmony_ci		if (dma_mapping_error(info->dev, sec_req->dma_iv)) {
76662306a36Sopenharmony_ci			ret = -ENOMEM;
76762306a36Sopenharmony_ci			goto err_unmap_out_sg;
76862306a36Sopenharmony_ci		}
76962306a36Sopenharmony_ci	}
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci	/* Set them all up then queue - cleaner error handling. */
77262306a36Sopenharmony_ci	for (i = 0; i < steps; i++) {
77362306a36Sopenharmony_ci		el = sec_alg_alloc_and_fill_el(&ctx->req_template,
77462306a36Sopenharmony_ci					       encrypt ? 1 : 0,
77562306a36Sopenharmony_ci					       split_sizes[i],
77662306a36Sopenharmony_ci					       skreq->src != skreq->dst,
77762306a36Sopenharmony_ci					       splits_in[i], splits_in_nents[i],
77862306a36Sopenharmony_ci					       split ? splits_out[i] : NULL,
77962306a36Sopenharmony_ci					       split ? splits_out_nents[i] : 0,
78062306a36Sopenharmony_ci					       info, gfp);
78162306a36Sopenharmony_ci		if (IS_ERR(el)) {
78262306a36Sopenharmony_ci			ret = PTR_ERR(el);
78362306a36Sopenharmony_ci			goto err_free_elements;
78462306a36Sopenharmony_ci		}
78562306a36Sopenharmony_ci		el->req.cipher_iv_addr_lo = lower_32_bits(sec_req->dma_iv);
78662306a36Sopenharmony_ci		el->req.cipher_iv_addr_hi = upper_32_bits(sec_req->dma_iv);
78762306a36Sopenharmony_ci		el->sec_req = sec_req;
78862306a36Sopenharmony_ci		list_add_tail(&el->head, &sec_req->elements);
78962306a36Sopenharmony_ci	}
79062306a36Sopenharmony_ci
79162306a36Sopenharmony_ci	/*
79262306a36Sopenharmony_ci	 * Only attempt to queue if the whole lot can fit in the queue -
79362306a36Sopenharmony_ci	 * we can't successfully cleanup after a partial queing so this
79462306a36Sopenharmony_ci	 * must succeed or fail atomically.
79562306a36Sopenharmony_ci	 *
79662306a36Sopenharmony_ci	 * Big hammer test of both software and hardware queues - could be
79762306a36Sopenharmony_ci	 * more refined but this is unlikely to happen so no need.
79862306a36Sopenharmony_ci	 */
79962306a36Sopenharmony_ci
80062306a36Sopenharmony_ci	/* Grab a big lock for a long time to avoid concurrency issues */
80162306a36Sopenharmony_ci	spin_lock_bh(&queue->queuelock);
80262306a36Sopenharmony_ci
80362306a36Sopenharmony_ci	/*
80462306a36Sopenharmony_ci	 * Can go on to queue if we have space in either:
80562306a36Sopenharmony_ci	 * 1) The hardware queue and no software queue
80662306a36Sopenharmony_ci	 * 2) The software queue
80762306a36Sopenharmony_ci	 * AND there is nothing in the backlog.  If there is backlog we
80862306a36Sopenharmony_ci	 * have to only queue to the backlog queue and return busy.
80962306a36Sopenharmony_ci	 */
81062306a36Sopenharmony_ci	if ((!sec_queue_can_enqueue(queue, steps) &&
81162306a36Sopenharmony_ci	     (!queue->havesoftqueue ||
81262306a36Sopenharmony_ci	      kfifo_avail(&queue->softqueue) > steps)) ||
81362306a36Sopenharmony_ci	    !list_empty(&ctx->backlog)) {
81462306a36Sopenharmony_ci		ret = -EBUSY;
81562306a36Sopenharmony_ci		if ((skreq->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) {
81662306a36Sopenharmony_ci			list_add_tail(&sec_req->backlog_head, &ctx->backlog);
81762306a36Sopenharmony_ci			spin_unlock_bh(&queue->queuelock);
81862306a36Sopenharmony_ci			goto out;
81962306a36Sopenharmony_ci		}
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_ci		spin_unlock_bh(&queue->queuelock);
82262306a36Sopenharmony_ci		goto err_free_elements;
82362306a36Sopenharmony_ci	}
82462306a36Sopenharmony_ci	ret = sec_send_request(sec_req, queue);
82562306a36Sopenharmony_ci	spin_unlock_bh(&queue->queuelock);
82662306a36Sopenharmony_ci	if (ret)
82762306a36Sopenharmony_ci		goto err_free_elements;
82862306a36Sopenharmony_ci
82962306a36Sopenharmony_ci	ret = -EINPROGRESS;
83062306a36Sopenharmony_ciout:
83162306a36Sopenharmony_ci	/* Cleanup - all elements in pointer arrays have been copied */
83262306a36Sopenharmony_ci	kfree(splits_in_nents);
83362306a36Sopenharmony_ci	kfree(splits_in);
83462306a36Sopenharmony_ci	kfree(splits_out_nents);
83562306a36Sopenharmony_ci	kfree(splits_out);
83662306a36Sopenharmony_ci	kfree(split_sizes);
83762306a36Sopenharmony_ci	return ret;
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_cierr_free_elements:
84062306a36Sopenharmony_ci	list_for_each_entry_safe(el, temp, &sec_req->elements, head) {
84162306a36Sopenharmony_ci		list_del(&el->head);
84262306a36Sopenharmony_ci		sec_alg_free_el(el, info);
84362306a36Sopenharmony_ci	}
84462306a36Sopenharmony_ci	if (crypto_skcipher_ivsize(atfm))
84562306a36Sopenharmony_ci		dma_unmap_single(info->dev, sec_req->dma_iv,
84662306a36Sopenharmony_ci				 crypto_skcipher_ivsize(atfm),
84762306a36Sopenharmony_ci				 DMA_BIDIRECTIONAL);
84862306a36Sopenharmony_cierr_unmap_out_sg:
84962306a36Sopenharmony_ci	if (split)
85062306a36Sopenharmony_ci		sec_unmap_sg_on_err(skreq->dst, steps, splits_out,
85162306a36Sopenharmony_ci				    splits_out_nents, sec_req->len_out,
85262306a36Sopenharmony_ci				    info->dev);
85362306a36Sopenharmony_cierr_unmap_in_sg:
85462306a36Sopenharmony_ci	sec_unmap_sg_on_err(skreq->src, steps, splits_in, splits_in_nents,
85562306a36Sopenharmony_ci			    sec_req->len_in, info->dev);
85662306a36Sopenharmony_cierr_free_split_sizes:
85762306a36Sopenharmony_ci	kfree(split_sizes);
85862306a36Sopenharmony_ci
85962306a36Sopenharmony_ci	return ret;
86062306a36Sopenharmony_ci}
86162306a36Sopenharmony_ci
86262306a36Sopenharmony_cistatic int sec_alg_skcipher_encrypt(struct skcipher_request *req)
86362306a36Sopenharmony_ci{
86462306a36Sopenharmony_ci	return sec_alg_skcipher_crypto(req, true);
86562306a36Sopenharmony_ci}
86662306a36Sopenharmony_ci
86762306a36Sopenharmony_cistatic int sec_alg_skcipher_decrypt(struct skcipher_request *req)
86862306a36Sopenharmony_ci{
86962306a36Sopenharmony_ci	return sec_alg_skcipher_crypto(req, false);
87062306a36Sopenharmony_ci}
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_cistatic int sec_alg_skcipher_init(struct crypto_skcipher *tfm)
87362306a36Sopenharmony_ci{
87462306a36Sopenharmony_ci	struct sec_alg_tfm_ctx *ctx = crypto_skcipher_ctx(tfm);
87562306a36Sopenharmony_ci
87662306a36Sopenharmony_ci	mutex_init(&ctx->lock);
87762306a36Sopenharmony_ci	INIT_LIST_HEAD(&ctx->backlog);
87862306a36Sopenharmony_ci	crypto_skcipher_set_reqsize(tfm, sizeof(struct sec_request));
87962306a36Sopenharmony_ci
88062306a36Sopenharmony_ci	ctx->queue = sec_queue_alloc_start_safe();
88162306a36Sopenharmony_ci	if (IS_ERR(ctx->queue))
88262306a36Sopenharmony_ci		return PTR_ERR(ctx->queue);
88362306a36Sopenharmony_ci
88462306a36Sopenharmony_ci	spin_lock_init(&ctx->queue->queuelock);
88562306a36Sopenharmony_ci	ctx->queue->havesoftqueue = false;
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_ci	return 0;
88862306a36Sopenharmony_ci}
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_cistatic void sec_alg_skcipher_exit(struct crypto_skcipher *tfm)
89162306a36Sopenharmony_ci{
89262306a36Sopenharmony_ci	struct sec_alg_tfm_ctx *ctx = crypto_skcipher_ctx(tfm);
89362306a36Sopenharmony_ci	struct device *dev = ctx->queue->dev_info->dev;
89462306a36Sopenharmony_ci
89562306a36Sopenharmony_ci	if (ctx->key) {
89662306a36Sopenharmony_ci		memzero_explicit(ctx->key, SEC_MAX_CIPHER_KEY);
89762306a36Sopenharmony_ci		dma_free_coherent(dev, SEC_MAX_CIPHER_KEY, ctx->key,
89862306a36Sopenharmony_ci				  ctx->pkey);
89962306a36Sopenharmony_ci	}
90062306a36Sopenharmony_ci	sec_queue_stop_release(ctx->queue);
90162306a36Sopenharmony_ci}
90262306a36Sopenharmony_ci
90362306a36Sopenharmony_cistatic int sec_alg_skcipher_init_with_queue(struct crypto_skcipher *tfm)
90462306a36Sopenharmony_ci{
90562306a36Sopenharmony_ci	struct sec_alg_tfm_ctx *ctx = crypto_skcipher_ctx(tfm);
90662306a36Sopenharmony_ci	int ret;
90762306a36Sopenharmony_ci
90862306a36Sopenharmony_ci	ret = sec_alg_skcipher_init(tfm);
90962306a36Sopenharmony_ci	if (ret)
91062306a36Sopenharmony_ci		return ret;
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci	INIT_KFIFO(ctx->queue->softqueue);
91362306a36Sopenharmony_ci	ret = kfifo_alloc(&ctx->queue->softqueue, 512, GFP_KERNEL);
91462306a36Sopenharmony_ci	if (ret) {
91562306a36Sopenharmony_ci		sec_alg_skcipher_exit(tfm);
91662306a36Sopenharmony_ci		return ret;
91762306a36Sopenharmony_ci	}
91862306a36Sopenharmony_ci	ctx->queue->havesoftqueue = true;
91962306a36Sopenharmony_ci
92062306a36Sopenharmony_ci	return 0;
92162306a36Sopenharmony_ci}
92262306a36Sopenharmony_ci
92362306a36Sopenharmony_cistatic void sec_alg_skcipher_exit_with_queue(struct crypto_skcipher *tfm)
92462306a36Sopenharmony_ci{
92562306a36Sopenharmony_ci	struct sec_alg_tfm_ctx *ctx = crypto_skcipher_ctx(tfm);
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_ci	kfifo_free(&ctx->queue->softqueue);
92862306a36Sopenharmony_ci	sec_alg_skcipher_exit(tfm);
92962306a36Sopenharmony_ci}
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_cistatic struct skcipher_alg sec_algs[] = {
93262306a36Sopenharmony_ci	{
93362306a36Sopenharmony_ci		.base = {
93462306a36Sopenharmony_ci			.cra_name = "ecb(aes)",
93562306a36Sopenharmony_ci			.cra_driver_name = "hisi_sec_aes_ecb",
93662306a36Sopenharmony_ci			.cra_priority = 4001,
93762306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_ASYNC |
93862306a36Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY,
93962306a36Sopenharmony_ci			.cra_blocksize = AES_BLOCK_SIZE,
94062306a36Sopenharmony_ci			.cra_ctxsize = sizeof(struct sec_alg_tfm_ctx),
94162306a36Sopenharmony_ci			.cra_alignmask = 0,
94262306a36Sopenharmony_ci			.cra_module = THIS_MODULE,
94362306a36Sopenharmony_ci		},
94462306a36Sopenharmony_ci		.init = sec_alg_skcipher_init,
94562306a36Sopenharmony_ci		.exit = sec_alg_skcipher_exit,
94662306a36Sopenharmony_ci		.setkey = sec_alg_skcipher_setkey_aes_ecb,
94762306a36Sopenharmony_ci		.decrypt = sec_alg_skcipher_decrypt,
94862306a36Sopenharmony_ci		.encrypt = sec_alg_skcipher_encrypt,
94962306a36Sopenharmony_ci		.min_keysize = AES_MIN_KEY_SIZE,
95062306a36Sopenharmony_ci		.max_keysize = AES_MAX_KEY_SIZE,
95162306a36Sopenharmony_ci		.ivsize = 0,
95262306a36Sopenharmony_ci	}, {
95362306a36Sopenharmony_ci		.base = {
95462306a36Sopenharmony_ci			.cra_name = "cbc(aes)",
95562306a36Sopenharmony_ci			.cra_driver_name = "hisi_sec_aes_cbc",
95662306a36Sopenharmony_ci			.cra_priority = 4001,
95762306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_ASYNC |
95862306a36Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY,
95962306a36Sopenharmony_ci			.cra_blocksize = AES_BLOCK_SIZE,
96062306a36Sopenharmony_ci			.cra_ctxsize = sizeof(struct sec_alg_tfm_ctx),
96162306a36Sopenharmony_ci			.cra_alignmask = 0,
96262306a36Sopenharmony_ci			.cra_module = THIS_MODULE,
96362306a36Sopenharmony_ci		},
96462306a36Sopenharmony_ci		.init = sec_alg_skcipher_init_with_queue,
96562306a36Sopenharmony_ci		.exit = sec_alg_skcipher_exit_with_queue,
96662306a36Sopenharmony_ci		.setkey = sec_alg_skcipher_setkey_aes_cbc,
96762306a36Sopenharmony_ci		.decrypt = sec_alg_skcipher_decrypt,
96862306a36Sopenharmony_ci		.encrypt = sec_alg_skcipher_encrypt,
96962306a36Sopenharmony_ci		.min_keysize = AES_MIN_KEY_SIZE,
97062306a36Sopenharmony_ci		.max_keysize = AES_MAX_KEY_SIZE,
97162306a36Sopenharmony_ci		.ivsize = AES_BLOCK_SIZE,
97262306a36Sopenharmony_ci	}, {
97362306a36Sopenharmony_ci		.base = {
97462306a36Sopenharmony_ci			.cra_name = "ctr(aes)",
97562306a36Sopenharmony_ci			.cra_driver_name = "hisi_sec_aes_ctr",
97662306a36Sopenharmony_ci			.cra_priority = 4001,
97762306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_ASYNC |
97862306a36Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY,
97962306a36Sopenharmony_ci			.cra_blocksize = AES_BLOCK_SIZE,
98062306a36Sopenharmony_ci			.cra_ctxsize = sizeof(struct sec_alg_tfm_ctx),
98162306a36Sopenharmony_ci			.cra_alignmask = 0,
98262306a36Sopenharmony_ci			.cra_module = THIS_MODULE,
98362306a36Sopenharmony_ci		},
98462306a36Sopenharmony_ci		.init = sec_alg_skcipher_init_with_queue,
98562306a36Sopenharmony_ci		.exit = sec_alg_skcipher_exit_with_queue,
98662306a36Sopenharmony_ci		.setkey = sec_alg_skcipher_setkey_aes_ctr,
98762306a36Sopenharmony_ci		.decrypt = sec_alg_skcipher_decrypt,
98862306a36Sopenharmony_ci		.encrypt = sec_alg_skcipher_encrypt,
98962306a36Sopenharmony_ci		.min_keysize = AES_MIN_KEY_SIZE,
99062306a36Sopenharmony_ci		.max_keysize = AES_MAX_KEY_SIZE,
99162306a36Sopenharmony_ci		.ivsize = AES_BLOCK_SIZE,
99262306a36Sopenharmony_ci	}, {
99362306a36Sopenharmony_ci		.base = {
99462306a36Sopenharmony_ci			.cra_name = "xts(aes)",
99562306a36Sopenharmony_ci			.cra_driver_name = "hisi_sec_aes_xts",
99662306a36Sopenharmony_ci			.cra_priority = 4001,
99762306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_ASYNC |
99862306a36Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY,
99962306a36Sopenharmony_ci			.cra_blocksize = AES_BLOCK_SIZE,
100062306a36Sopenharmony_ci			.cra_ctxsize = sizeof(struct sec_alg_tfm_ctx),
100162306a36Sopenharmony_ci			.cra_alignmask = 0,
100262306a36Sopenharmony_ci			.cra_module = THIS_MODULE,
100362306a36Sopenharmony_ci		},
100462306a36Sopenharmony_ci		.init = sec_alg_skcipher_init,
100562306a36Sopenharmony_ci		.exit = sec_alg_skcipher_exit,
100662306a36Sopenharmony_ci		.setkey = sec_alg_skcipher_setkey_aes_xts,
100762306a36Sopenharmony_ci		.decrypt = sec_alg_skcipher_decrypt,
100862306a36Sopenharmony_ci		.encrypt = sec_alg_skcipher_encrypt,
100962306a36Sopenharmony_ci		.min_keysize = 2 * AES_MIN_KEY_SIZE,
101062306a36Sopenharmony_ci		.max_keysize = 2 * AES_MAX_KEY_SIZE,
101162306a36Sopenharmony_ci		.ivsize = AES_BLOCK_SIZE,
101262306a36Sopenharmony_ci	}, {
101362306a36Sopenharmony_ci	/* Unable to find any test vectors so untested */
101462306a36Sopenharmony_ci		.base = {
101562306a36Sopenharmony_ci			.cra_name = "ecb(des)",
101662306a36Sopenharmony_ci			.cra_driver_name = "hisi_sec_des_ecb",
101762306a36Sopenharmony_ci			.cra_priority = 4001,
101862306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_ASYNC |
101962306a36Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY,
102062306a36Sopenharmony_ci			.cra_blocksize = DES_BLOCK_SIZE,
102162306a36Sopenharmony_ci			.cra_ctxsize = sizeof(struct sec_alg_tfm_ctx),
102262306a36Sopenharmony_ci			.cra_alignmask = 0,
102362306a36Sopenharmony_ci			.cra_module = THIS_MODULE,
102462306a36Sopenharmony_ci		},
102562306a36Sopenharmony_ci		.init = sec_alg_skcipher_init,
102662306a36Sopenharmony_ci		.exit = sec_alg_skcipher_exit,
102762306a36Sopenharmony_ci		.setkey = sec_alg_skcipher_setkey_des_ecb,
102862306a36Sopenharmony_ci		.decrypt = sec_alg_skcipher_decrypt,
102962306a36Sopenharmony_ci		.encrypt = sec_alg_skcipher_encrypt,
103062306a36Sopenharmony_ci		.min_keysize = DES_KEY_SIZE,
103162306a36Sopenharmony_ci		.max_keysize = DES_KEY_SIZE,
103262306a36Sopenharmony_ci		.ivsize = 0,
103362306a36Sopenharmony_ci	}, {
103462306a36Sopenharmony_ci		.base = {
103562306a36Sopenharmony_ci			.cra_name = "cbc(des)",
103662306a36Sopenharmony_ci			.cra_driver_name = "hisi_sec_des_cbc",
103762306a36Sopenharmony_ci			.cra_priority = 4001,
103862306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_ASYNC |
103962306a36Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY,
104062306a36Sopenharmony_ci			.cra_blocksize = DES_BLOCK_SIZE,
104162306a36Sopenharmony_ci			.cra_ctxsize = sizeof(struct sec_alg_tfm_ctx),
104262306a36Sopenharmony_ci			.cra_alignmask = 0,
104362306a36Sopenharmony_ci			.cra_module = THIS_MODULE,
104462306a36Sopenharmony_ci		},
104562306a36Sopenharmony_ci		.init = sec_alg_skcipher_init_with_queue,
104662306a36Sopenharmony_ci		.exit = sec_alg_skcipher_exit_with_queue,
104762306a36Sopenharmony_ci		.setkey = sec_alg_skcipher_setkey_des_cbc,
104862306a36Sopenharmony_ci		.decrypt = sec_alg_skcipher_decrypt,
104962306a36Sopenharmony_ci		.encrypt = sec_alg_skcipher_encrypt,
105062306a36Sopenharmony_ci		.min_keysize = DES_KEY_SIZE,
105162306a36Sopenharmony_ci		.max_keysize = DES_KEY_SIZE,
105262306a36Sopenharmony_ci		.ivsize = DES_BLOCK_SIZE,
105362306a36Sopenharmony_ci	}, {
105462306a36Sopenharmony_ci		.base = {
105562306a36Sopenharmony_ci			.cra_name = "cbc(des3_ede)",
105662306a36Sopenharmony_ci			.cra_driver_name = "hisi_sec_3des_cbc",
105762306a36Sopenharmony_ci			.cra_priority = 4001,
105862306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_ASYNC |
105962306a36Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY,
106062306a36Sopenharmony_ci			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
106162306a36Sopenharmony_ci			.cra_ctxsize = sizeof(struct sec_alg_tfm_ctx),
106262306a36Sopenharmony_ci			.cra_alignmask = 0,
106362306a36Sopenharmony_ci			.cra_module = THIS_MODULE,
106462306a36Sopenharmony_ci		},
106562306a36Sopenharmony_ci		.init = sec_alg_skcipher_init_with_queue,
106662306a36Sopenharmony_ci		.exit = sec_alg_skcipher_exit_with_queue,
106762306a36Sopenharmony_ci		.setkey = sec_alg_skcipher_setkey_3des_cbc,
106862306a36Sopenharmony_ci		.decrypt = sec_alg_skcipher_decrypt,
106962306a36Sopenharmony_ci		.encrypt = sec_alg_skcipher_encrypt,
107062306a36Sopenharmony_ci		.min_keysize = DES3_EDE_KEY_SIZE,
107162306a36Sopenharmony_ci		.max_keysize = DES3_EDE_KEY_SIZE,
107262306a36Sopenharmony_ci		.ivsize = DES3_EDE_BLOCK_SIZE,
107362306a36Sopenharmony_ci	}, {
107462306a36Sopenharmony_ci		.base = {
107562306a36Sopenharmony_ci			.cra_name = "ecb(des3_ede)",
107662306a36Sopenharmony_ci			.cra_driver_name = "hisi_sec_3des_ecb",
107762306a36Sopenharmony_ci			.cra_priority = 4001,
107862306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_ASYNC |
107962306a36Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY,
108062306a36Sopenharmony_ci			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
108162306a36Sopenharmony_ci			.cra_ctxsize = sizeof(struct sec_alg_tfm_ctx),
108262306a36Sopenharmony_ci			.cra_alignmask = 0,
108362306a36Sopenharmony_ci			.cra_module = THIS_MODULE,
108462306a36Sopenharmony_ci		},
108562306a36Sopenharmony_ci		.init = sec_alg_skcipher_init,
108662306a36Sopenharmony_ci		.exit = sec_alg_skcipher_exit,
108762306a36Sopenharmony_ci		.setkey = sec_alg_skcipher_setkey_3des_ecb,
108862306a36Sopenharmony_ci		.decrypt = sec_alg_skcipher_decrypt,
108962306a36Sopenharmony_ci		.encrypt = sec_alg_skcipher_encrypt,
109062306a36Sopenharmony_ci		.min_keysize = DES3_EDE_KEY_SIZE,
109162306a36Sopenharmony_ci		.max_keysize = DES3_EDE_KEY_SIZE,
109262306a36Sopenharmony_ci		.ivsize = 0,
109362306a36Sopenharmony_ci	}
109462306a36Sopenharmony_ci};
109562306a36Sopenharmony_ci
109662306a36Sopenharmony_ciint sec_algs_register(void)
109762306a36Sopenharmony_ci{
109862306a36Sopenharmony_ci	int ret = 0;
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci	mutex_lock(&algs_lock);
110162306a36Sopenharmony_ci	if (++active_devs != 1)
110262306a36Sopenharmony_ci		goto unlock;
110362306a36Sopenharmony_ci
110462306a36Sopenharmony_ci	ret = crypto_register_skciphers(sec_algs, ARRAY_SIZE(sec_algs));
110562306a36Sopenharmony_ci	if (ret)
110662306a36Sopenharmony_ci		--active_devs;
110762306a36Sopenharmony_ciunlock:
110862306a36Sopenharmony_ci	mutex_unlock(&algs_lock);
110962306a36Sopenharmony_ci
111062306a36Sopenharmony_ci	return ret;
111162306a36Sopenharmony_ci}
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_civoid sec_algs_unregister(void)
111462306a36Sopenharmony_ci{
111562306a36Sopenharmony_ci	mutex_lock(&algs_lock);
111662306a36Sopenharmony_ci	if (--active_devs != 0)
111762306a36Sopenharmony_ci		goto unlock;
111862306a36Sopenharmony_ci	crypto_unregister_skciphers(sec_algs, ARRAY_SIZE(sec_algs));
111962306a36Sopenharmony_ci
112062306a36Sopenharmony_ciunlock:
112162306a36Sopenharmony_ci	mutex_unlock(&algs_lock);
112262306a36Sopenharmony_ci}
1123