18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * This file is part of the Chelsio T6 Crypto driver for Linux.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright (c) 2003-2016 Chelsio Communications, Inc. All rights reserved.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two
78c2ecf20Sopenharmony_ci * licenses.  You may choose to be licensed under the terms of the GNU
88c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file
98c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the
108c2ecf20Sopenharmony_ci * OpenIB.org BSD license below:
118c2ecf20Sopenharmony_ci *
128c2ecf20Sopenharmony_ci *     Redistribution and use in source and binary forms, with or
138c2ecf20Sopenharmony_ci *     without modification, are permitted provided that the following
148c2ecf20Sopenharmony_ci *     conditions are met:
158c2ecf20Sopenharmony_ci *
168c2ecf20Sopenharmony_ci *      - Redistributions of source code must retain the above
178c2ecf20Sopenharmony_ci *        copyright notice, this list of conditions and the following
188c2ecf20Sopenharmony_ci *        disclaimer.
198c2ecf20Sopenharmony_ci *
208c2ecf20Sopenharmony_ci *      - Redistributions in binary form must reproduce the above
218c2ecf20Sopenharmony_ci *        copyright notice, this list of conditions and the following
228c2ecf20Sopenharmony_ci *        disclaimer in the documentation and/or other materials
238c2ecf20Sopenharmony_ci *        provided with the distribution.
248c2ecf20Sopenharmony_ci *
258c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
268c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
278c2ecf20Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
288c2ecf20Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
298c2ecf20Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
308c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
318c2ecf20Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
328c2ecf20Sopenharmony_ci * SOFTWARE.
338c2ecf20Sopenharmony_ci *
348c2ecf20Sopenharmony_ci * Written and Maintained by:
358c2ecf20Sopenharmony_ci *	Manoj Malviya (manojmalviya@chelsio.com)
368c2ecf20Sopenharmony_ci *	Atul Gupta (atul.gupta@chelsio.com)
378c2ecf20Sopenharmony_ci *	Jitendra Lulla (jlulla@chelsio.com)
388c2ecf20Sopenharmony_ci *	Yeshaswi M R Gowda (yeshaswi@chelsio.com)
398c2ecf20Sopenharmony_ci *	Harsh Jain (harsh@chelsio.com)
408c2ecf20Sopenharmony_ci */
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci#define pr_fmt(fmt) "chcr:" fmt
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci#include <linux/kernel.h>
458c2ecf20Sopenharmony_ci#include <linux/module.h>
468c2ecf20Sopenharmony_ci#include <linux/crypto.h>
478c2ecf20Sopenharmony_ci#include <linux/skbuff.h>
488c2ecf20Sopenharmony_ci#include <linux/rtnetlink.h>
498c2ecf20Sopenharmony_ci#include <linux/highmem.h>
508c2ecf20Sopenharmony_ci#include <linux/scatterlist.h>
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci#include <crypto/aes.h>
538c2ecf20Sopenharmony_ci#include <crypto/algapi.h>
548c2ecf20Sopenharmony_ci#include <crypto/hash.h>
558c2ecf20Sopenharmony_ci#include <crypto/gcm.h>
568c2ecf20Sopenharmony_ci#include <crypto/sha.h>
578c2ecf20Sopenharmony_ci#include <crypto/authenc.h>
588c2ecf20Sopenharmony_ci#include <crypto/ctr.h>
598c2ecf20Sopenharmony_ci#include <crypto/gf128mul.h>
608c2ecf20Sopenharmony_ci#include <crypto/internal/aead.h>
618c2ecf20Sopenharmony_ci#include <crypto/null.h>
628c2ecf20Sopenharmony_ci#include <crypto/internal/skcipher.h>
638c2ecf20Sopenharmony_ci#include <crypto/aead.h>
648c2ecf20Sopenharmony_ci#include <crypto/scatterwalk.h>
658c2ecf20Sopenharmony_ci#include <crypto/internal/hash.h>
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci#include "t4fw_api.h"
688c2ecf20Sopenharmony_ci#include "t4_msg.h"
698c2ecf20Sopenharmony_ci#include "chcr_core.h"
708c2ecf20Sopenharmony_ci#include "chcr_algo.h"
718c2ecf20Sopenharmony_ci#include "chcr_crypto.h"
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci#define IV AES_BLOCK_SIZE
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_cistatic unsigned int sgl_ent_len[] = {
768c2ecf20Sopenharmony_ci	0, 0, 16, 24, 40, 48, 64, 72, 88,
778c2ecf20Sopenharmony_ci	96, 112, 120, 136, 144, 160, 168, 184,
788c2ecf20Sopenharmony_ci	192, 208, 216, 232, 240, 256, 264, 280,
798c2ecf20Sopenharmony_ci	288, 304, 312, 328, 336, 352, 360, 376
808c2ecf20Sopenharmony_ci};
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_cistatic unsigned int dsgl_ent_len[] = {
838c2ecf20Sopenharmony_ci	0, 32, 32, 48, 48, 64, 64, 80, 80,
848c2ecf20Sopenharmony_ci	112, 112, 128, 128, 144, 144, 160, 160,
858c2ecf20Sopenharmony_ci	192, 192, 208, 208, 224, 224, 240, 240,
868c2ecf20Sopenharmony_ci	272, 272, 288, 288, 304, 304, 320, 320
878c2ecf20Sopenharmony_ci};
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_cistatic u32 round_constant[11] = {
908c2ecf20Sopenharmony_ci	0x01000000, 0x02000000, 0x04000000, 0x08000000,
918c2ecf20Sopenharmony_ci	0x10000000, 0x20000000, 0x40000000, 0x80000000,
928c2ecf20Sopenharmony_ci	0x1B000000, 0x36000000, 0x6C000000
938c2ecf20Sopenharmony_ci};
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_cistatic int chcr_handle_cipher_resp(struct skcipher_request *req,
968c2ecf20Sopenharmony_ci				   unsigned char *input, int err);
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_cistatic inline  struct chcr_aead_ctx *AEAD_CTX(struct chcr_context *ctx)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	return ctx->crypto_ctx->aeadctx;
1018c2ecf20Sopenharmony_ci}
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_cistatic inline struct ablk_ctx *ABLK_CTX(struct chcr_context *ctx)
1048c2ecf20Sopenharmony_ci{
1058c2ecf20Sopenharmony_ci	return ctx->crypto_ctx->ablkctx;
1068c2ecf20Sopenharmony_ci}
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_cistatic inline struct hmac_ctx *HMAC_CTX(struct chcr_context *ctx)
1098c2ecf20Sopenharmony_ci{
1108c2ecf20Sopenharmony_ci	return ctx->crypto_ctx->hmacctx;
1118c2ecf20Sopenharmony_ci}
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_cistatic inline struct chcr_gcm_ctx *GCM_CTX(struct chcr_aead_ctx *gctx)
1148c2ecf20Sopenharmony_ci{
1158c2ecf20Sopenharmony_ci	return gctx->ctx->gcm;
1168c2ecf20Sopenharmony_ci}
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_cistatic inline struct chcr_authenc_ctx *AUTHENC_CTX(struct chcr_aead_ctx *gctx)
1198c2ecf20Sopenharmony_ci{
1208c2ecf20Sopenharmony_ci	return gctx->ctx->authenc;
1218c2ecf20Sopenharmony_ci}
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_cistatic inline struct uld_ctx *ULD_CTX(struct chcr_context *ctx)
1248c2ecf20Sopenharmony_ci{
1258c2ecf20Sopenharmony_ci	return container_of(ctx->dev, struct uld_ctx, dev);
1268c2ecf20Sopenharmony_ci}
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_cistatic inline int is_ofld_imm(const struct sk_buff *skb)
1298c2ecf20Sopenharmony_ci{
1308c2ecf20Sopenharmony_ci	return (skb->len <= SGE_MAX_WR_LEN);
1318c2ecf20Sopenharmony_ci}
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_cistatic inline void chcr_init_hctx_per_wr(struct chcr_ahash_req_ctx *reqctx)
1348c2ecf20Sopenharmony_ci{
1358c2ecf20Sopenharmony_ci	memset(&reqctx->hctx_wr, 0, sizeof(struct chcr_hctx_per_wr));
1368c2ecf20Sopenharmony_ci}
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_cistatic int sg_nents_xlen(struct scatterlist *sg, unsigned int reqlen,
1398c2ecf20Sopenharmony_ci			 unsigned int entlen,
1408c2ecf20Sopenharmony_ci			 unsigned int skip)
1418c2ecf20Sopenharmony_ci{
1428c2ecf20Sopenharmony_ci	int nents = 0;
1438c2ecf20Sopenharmony_ci	unsigned int less;
1448c2ecf20Sopenharmony_ci	unsigned int skip_len = 0;
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	while (sg && skip) {
1478c2ecf20Sopenharmony_ci		if (sg_dma_len(sg) <= skip) {
1488c2ecf20Sopenharmony_ci			skip -= sg_dma_len(sg);
1498c2ecf20Sopenharmony_ci			skip_len = 0;
1508c2ecf20Sopenharmony_ci			sg = sg_next(sg);
1518c2ecf20Sopenharmony_ci		} else {
1528c2ecf20Sopenharmony_ci			skip_len = skip;
1538c2ecf20Sopenharmony_ci			skip = 0;
1548c2ecf20Sopenharmony_ci		}
1558c2ecf20Sopenharmony_ci	}
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	while (sg && reqlen) {
1588c2ecf20Sopenharmony_ci		less = min(reqlen, sg_dma_len(sg) - skip_len);
1598c2ecf20Sopenharmony_ci		nents += DIV_ROUND_UP(less, entlen);
1608c2ecf20Sopenharmony_ci		reqlen -= less;
1618c2ecf20Sopenharmony_ci		skip_len = 0;
1628c2ecf20Sopenharmony_ci		sg = sg_next(sg);
1638c2ecf20Sopenharmony_ci	}
1648c2ecf20Sopenharmony_ci	return nents;
1658c2ecf20Sopenharmony_ci}
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_cistatic inline int get_aead_subtype(struct crypto_aead *aead)
1688c2ecf20Sopenharmony_ci{
1698c2ecf20Sopenharmony_ci	struct aead_alg *alg = crypto_aead_alg(aead);
1708c2ecf20Sopenharmony_ci	struct chcr_alg_template *chcr_crypto_alg =
1718c2ecf20Sopenharmony_ci		container_of(alg, struct chcr_alg_template, alg.aead);
1728c2ecf20Sopenharmony_ci	return chcr_crypto_alg->type & CRYPTO_ALG_SUB_TYPE_MASK;
1738c2ecf20Sopenharmony_ci}
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_civoid chcr_verify_tag(struct aead_request *req, u8 *input, int *err)
1768c2ecf20Sopenharmony_ci{
1778c2ecf20Sopenharmony_ci	u8 temp[SHA512_DIGEST_SIZE];
1788c2ecf20Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
1798c2ecf20Sopenharmony_ci	int authsize = crypto_aead_authsize(tfm);
1808c2ecf20Sopenharmony_ci	struct cpl_fw6_pld *fw6_pld;
1818c2ecf20Sopenharmony_ci	int cmp = 0;
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	fw6_pld = (struct cpl_fw6_pld *)input;
1848c2ecf20Sopenharmony_ci	if ((get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106) ||
1858c2ecf20Sopenharmony_ci	    (get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_GCM)) {
1868c2ecf20Sopenharmony_ci		cmp = crypto_memneq(&fw6_pld->data[2], (fw6_pld + 1), authsize);
1878c2ecf20Sopenharmony_ci	} else {
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci		sg_pcopy_to_buffer(req->src, sg_nents(req->src), temp,
1908c2ecf20Sopenharmony_ci				authsize, req->assoclen +
1918c2ecf20Sopenharmony_ci				req->cryptlen - authsize);
1928c2ecf20Sopenharmony_ci		cmp = crypto_memneq(temp, (fw6_pld + 1), authsize);
1938c2ecf20Sopenharmony_ci	}
1948c2ecf20Sopenharmony_ci	if (cmp)
1958c2ecf20Sopenharmony_ci		*err = -EBADMSG;
1968c2ecf20Sopenharmony_ci	else
1978c2ecf20Sopenharmony_ci		*err = 0;
1988c2ecf20Sopenharmony_ci}
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_cistatic int chcr_inc_wrcount(struct chcr_dev *dev)
2018c2ecf20Sopenharmony_ci{
2028c2ecf20Sopenharmony_ci	if (dev->state == CHCR_DETACH)
2038c2ecf20Sopenharmony_ci		return 1;
2048c2ecf20Sopenharmony_ci	atomic_inc(&dev->inflight);
2058c2ecf20Sopenharmony_ci	return 0;
2068c2ecf20Sopenharmony_ci}
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_cistatic inline void chcr_dec_wrcount(struct chcr_dev *dev)
2098c2ecf20Sopenharmony_ci{
2108c2ecf20Sopenharmony_ci	atomic_dec(&dev->inflight);
2118c2ecf20Sopenharmony_ci}
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_cistatic inline int chcr_handle_aead_resp(struct aead_request *req,
2148c2ecf20Sopenharmony_ci					 unsigned char *input,
2158c2ecf20Sopenharmony_ci					 int err)
2168c2ecf20Sopenharmony_ci{
2178c2ecf20Sopenharmony_ci	struct chcr_aead_reqctx *reqctx = aead_request_ctx(req);
2188c2ecf20Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
2198c2ecf20Sopenharmony_ci	struct chcr_dev *dev = a_ctx(tfm)->dev;
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	chcr_aead_common_exit(req);
2228c2ecf20Sopenharmony_ci	if (reqctx->verify == VERIFY_SW) {
2238c2ecf20Sopenharmony_ci		chcr_verify_tag(req, input, &err);
2248c2ecf20Sopenharmony_ci		reqctx->verify = VERIFY_HW;
2258c2ecf20Sopenharmony_ci	}
2268c2ecf20Sopenharmony_ci	chcr_dec_wrcount(dev);
2278c2ecf20Sopenharmony_ci	req->base.complete(&req->base, err);
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	return err;
2308c2ecf20Sopenharmony_ci}
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_cistatic void get_aes_decrypt_key(unsigned char *dec_key,
2338c2ecf20Sopenharmony_ci				       const unsigned char *key,
2348c2ecf20Sopenharmony_ci				       unsigned int keylength)
2358c2ecf20Sopenharmony_ci{
2368c2ecf20Sopenharmony_ci	u32 temp;
2378c2ecf20Sopenharmony_ci	u32 w_ring[MAX_NK];
2388c2ecf20Sopenharmony_ci	int i, j, k;
2398c2ecf20Sopenharmony_ci	u8  nr, nk;
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	switch (keylength) {
2428c2ecf20Sopenharmony_ci	case AES_KEYLENGTH_128BIT:
2438c2ecf20Sopenharmony_ci		nk = KEYLENGTH_4BYTES;
2448c2ecf20Sopenharmony_ci		nr = NUMBER_OF_ROUNDS_10;
2458c2ecf20Sopenharmony_ci		break;
2468c2ecf20Sopenharmony_ci	case AES_KEYLENGTH_192BIT:
2478c2ecf20Sopenharmony_ci		nk = KEYLENGTH_6BYTES;
2488c2ecf20Sopenharmony_ci		nr = NUMBER_OF_ROUNDS_12;
2498c2ecf20Sopenharmony_ci		break;
2508c2ecf20Sopenharmony_ci	case AES_KEYLENGTH_256BIT:
2518c2ecf20Sopenharmony_ci		nk = KEYLENGTH_8BYTES;
2528c2ecf20Sopenharmony_ci		nr = NUMBER_OF_ROUNDS_14;
2538c2ecf20Sopenharmony_ci		break;
2548c2ecf20Sopenharmony_ci	default:
2558c2ecf20Sopenharmony_ci		return;
2568c2ecf20Sopenharmony_ci	}
2578c2ecf20Sopenharmony_ci	for (i = 0; i < nk; i++)
2588c2ecf20Sopenharmony_ci		w_ring[i] = get_unaligned_be32(&key[i * 4]);
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci	i = 0;
2618c2ecf20Sopenharmony_ci	temp = w_ring[nk - 1];
2628c2ecf20Sopenharmony_ci	while (i + nk < (nr + 1) * 4) {
2638c2ecf20Sopenharmony_ci		if (!(i % nk)) {
2648c2ecf20Sopenharmony_ci			/* RotWord(temp) */
2658c2ecf20Sopenharmony_ci			temp = (temp << 8) | (temp >> 24);
2668c2ecf20Sopenharmony_ci			temp = aes_ks_subword(temp);
2678c2ecf20Sopenharmony_ci			temp ^= round_constant[i / nk];
2688c2ecf20Sopenharmony_ci		} else if (nk == 8 && (i % 4 == 0)) {
2698c2ecf20Sopenharmony_ci			temp = aes_ks_subword(temp);
2708c2ecf20Sopenharmony_ci		}
2718c2ecf20Sopenharmony_ci		w_ring[i % nk] ^= temp;
2728c2ecf20Sopenharmony_ci		temp = w_ring[i % nk];
2738c2ecf20Sopenharmony_ci		i++;
2748c2ecf20Sopenharmony_ci	}
2758c2ecf20Sopenharmony_ci	i--;
2768c2ecf20Sopenharmony_ci	for (k = 0, j = i % nk; k < nk; k++) {
2778c2ecf20Sopenharmony_ci		put_unaligned_be32(w_ring[j], &dec_key[k * 4]);
2788c2ecf20Sopenharmony_ci		j--;
2798c2ecf20Sopenharmony_ci		if (j < 0)
2808c2ecf20Sopenharmony_ci			j += nk;
2818c2ecf20Sopenharmony_ci	}
2828c2ecf20Sopenharmony_ci}
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_cistatic struct crypto_shash *chcr_alloc_shash(unsigned int ds)
2858c2ecf20Sopenharmony_ci{
2868c2ecf20Sopenharmony_ci	struct crypto_shash *base_hash = ERR_PTR(-EINVAL);
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	switch (ds) {
2898c2ecf20Sopenharmony_ci	case SHA1_DIGEST_SIZE:
2908c2ecf20Sopenharmony_ci		base_hash = crypto_alloc_shash("sha1", 0, 0);
2918c2ecf20Sopenharmony_ci		break;
2928c2ecf20Sopenharmony_ci	case SHA224_DIGEST_SIZE:
2938c2ecf20Sopenharmony_ci		base_hash = crypto_alloc_shash("sha224", 0, 0);
2948c2ecf20Sopenharmony_ci		break;
2958c2ecf20Sopenharmony_ci	case SHA256_DIGEST_SIZE:
2968c2ecf20Sopenharmony_ci		base_hash = crypto_alloc_shash("sha256", 0, 0);
2978c2ecf20Sopenharmony_ci		break;
2988c2ecf20Sopenharmony_ci	case SHA384_DIGEST_SIZE:
2998c2ecf20Sopenharmony_ci		base_hash = crypto_alloc_shash("sha384", 0, 0);
3008c2ecf20Sopenharmony_ci		break;
3018c2ecf20Sopenharmony_ci	case SHA512_DIGEST_SIZE:
3028c2ecf20Sopenharmony_ci		base_hash = crypto_alloc_shash("sha512", 0, 0);
3038c2ecf20Sopenharmony_ci		break;
3048c2ecf20Sopenharmony_ci	}
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci	return base_hash;
3078c2ecf20Sopenharmony_ci}
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_cistatic int chcr_compute_partial_hash(struct shash_desc *desc,
3108c2ecf20Sopenharmony_ci				     char *iopad, char *result_hash,
3118c2ecf20Sopenharmony_ci				     int digest_size)
3128c2ecf20Sopenharmony_ci{
3138c2ecf20Sopenharmony_ci	struct sha1_state sha1_st;
3148c2ecf20Sopenharmony_ci	struct sha256_state sha256_st;
3158c2ecf20Sopenharmony_ci	struct sha512_state sha512_st;
3168c2ecf20Sopenharmony_ci	int error;
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	if (digest_size == SHA1_DIGEST_SIZE) {
3198c2ecf20Sopenharmony_ci		error = crypto_shash_init(desc) ?:
3208c2ecf20Sopenharmony_ci			crypto_shash_update(desc, iopad, SHA1_BLOCK_SIZE) ?:
3218c2ecf20Sopenharmony_ci			crypto_shash_export(desc, (void *)&sha1_st);
3228c2ecf20Sopenharmony_ci		memcpy(result_hash, sha1_st.state, SHA1_DIGEST_SIZE);
3238c2ecf20Sopenharmony_ci	} else if (digest_size == SHA224_DIGEST_SIZE) {
3248c2ecf20Sopenharmony_ci		error = crypto_shash_init(desc) ?:
3258c2ecf20Sopenharmony_ci			crypto_shash_update(desc, iopad, SHA256_BLOCK_SIZE) ?:
3268c2ecf20Sopenharmony_ci			crypto_shash_export(desc, (void *)&sha256_st);
3278c2ecf20Sopenharmony_ci		memcpy(result_hash, sha256_st.state, SHA256_DIGEST_SIZE);
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	} else if (digest_size == SHA256_DIGEST_SIZE) {
3308c2ecf20Sopenharmony_ci		error = crypto_shash_init(desc) ?:
3318c2ecf20Sopenharmony_ci			crypto_shash_update(desc, iopad, SHA256_BLOCK_SIZE) ?:
3328c2ecf20Sopenharmony_ci			crypto_shash_export(desc, (void *)&sha256_st);
3338c2ecf20Sopenharmony_ci		memcpy(result_hash, sha256_st.state, SHA256_DIGEST_SIZE);
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci	} else if (digest_size == SHA384_DIGEST_SIZE) {
3368c2ecf20Sopenharmony_ci		error = crypto_shash_init(desc) ?:
3378c2ecf20Sopenharmony_ci			crypto_shash_update(desc, iopad, SHA512_BLOCK_SIZE) ?:
3388c2ecf20Sopenharmony_ci			crypto_shash_export(desc, (void *)&sha512_st);
3398c2ecf20Sopenharmony_ci		memcpy(result_hash, sha512_st.state, SHA512_DIGEST_SIZE);
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	} else if (digest_size == SHA512_DIGEST_SIZE) {
3428c2ecf20Sopenharmony_ci		error = crypto_shash_init(desc) ?:
3438c2ecf20Sopenharmony_ci			crypto_shash_update(desc, iopad, SHA512_BLOCK_SIZE) ?:
3448c2ecf20Sopenharmony_ci			crypto_shash_export(desc, (void *)&sha512_st);
3458c2ecf20Sopenharmony_ci		memcpy(result_hash, sha512_st.state, SHA512_DIGEST_SIZE);
3468c2ecf20Sopenharmony_ci	} else {
3478c2ecf20Sopenharmony_ci		error = -EINVAL;
3488c2ecf20Sopenharmony_ci		pr_err("Unknown digest size %d\n", digest_size);
3498c2ecf20Sopenharmony_ci	}
3508c2ecf20Sopenharmony_ci	return error;
3518c2ecf20Sopenharmony_ci}
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_cistatic void chcr_change_order(char *buf, int ds)
3548c2ecf20Sopenharmony_ci{
3558c2ecf20Sopenharmony_ci	int i;
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci	if (ds == SHA512_DIGEST_SIZE) {
3588c2ecf20Sopenharmony_ci		for (i = 0; i < (ds / sizeof(u64)); i++)
3598c2ecf20Sopenharmony_ci			*((__be64 *)buf + i) =
3608c2ecf20Sopenharmony_ci				cpu_to_be64(*((u64 *)buf + i));
3618c2ecf20Sopenharmony_ci	} else {
3628c2ecf20Sopenharmony_ci		for (i = 0; i < (ds / sizeof(u32)); i++)
3638c2ecf20Sopenharmony_ci			*((__be32 *)buf + i) =
3648c2ecf20Sopenharmony_ci				cpu_to_be32(*((u32 *)buf + i));
3658c2ecf20Sopenharmony_ci	}
3668c2ecf20Sopenharmony_ci}
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_cistatic inline int is_hmac(struct crypto_tfm *tfm)
3698c2ecf20Sopenharmony_ci{
3708c2ecf20Sopenharmony_ci	struct crypto_alg *alg = tfm->__crt_alg;
3718c2ecf20Sopenharmony_ci	struct chcr_alg_template *chcr_crypto_alg =
3728c2ecf20Sopenharmony_ci		container_of(__crypto_ahash_alg(alg), struct chcr_alg_template,
3738c2ecf20Sopenharmony_ci			     alg.hash);
3748c2ecf20Sopenharmony_ci	if (chcr_crypto_alg->type == CRYPTO_ALG_TYPE_HMAC)
3758c2ecf20Sopenharmony_ci		return 1;
3768c2ecf20Sopenharmony_ci	return 0;
3778c2ecf20Sopenharmony_ci}
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_cistatic inline void dsgl_walk_init(struct dsgl_walk *walk,
3808c2ecf20Sopenharmony_ci				   struct cpl_rx_phys_dsgl *dsgl)
3818c2ecf20Sopenharmony_ci{
3828c2ecf20Sopenharmony_ci	walk->dsgl = dsgl;
3838c2ecf20Sopenharmony_ci	walk->nents = 0;
3848c2ecf20Sopenharmony_ci	walk->to = (struct phys_sge_pairs *)(dsgl + 1);
3858c2ecf20Sopenharmony_ci}
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_cistatic inline void dsgl_walk_end(struct dsgl_walk *walk, unsigned short qid,
3888c2ecf20Sopenharmony_ci				 int pci_chan_id)
3898c2ecf20Sopenharmony_ci{
3908c2ecf20Sopenharmony_ci	struct cpl_rx_phys_dsgl *phys_cpl;
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	phys_cpl = walk->dsgl;
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	phys_cpl->op_to_tid = htonl(CPL_RX_PHYS_DSGL_OPCODE_V(CPL_RX_PHYS_DSGL)
3958c2ecf20Sopenharmony_ci				    | CPL_RX_PHYS_DSGL_ISRDMA_V(0));
3968c2ecf20Sopenharmony_ci	phys_cpl->pcirlxorder_to_noofsgentr =
3978c2ecf20Sopenharmony_ci		htonl(CPL_RX_PHYS_DSGL_PCIRLXORDER_V(0) |
3988c2ecf20Sopenharmony_ci		      CPL_RX_PHYS_DSGL_PCINOSNOOP_V(0) |
3998c2ecf20Sopenharmony_ci		      CPL_RX_PHYS_DSGL_PCITPHNTENB_V(0) |
4008c2ecf20Sopenharmony_ci		      CPL_RX_PHYS_DSGL_PCITPHNT_V(0) |
4018c2ecf20Sopenharmony_ci		      CPL_RX_PHYS_DSGL_DCAID_V(0) |
4028c2ecf20Sopenharmony_ci		      CPL_RX_PHYS_DSGL_NOOFSGENTR_V(walk->nents));
4038c2ecf20Sopenharmony_ci	phys_cpl->rss_hdr_int.opcode = CPL_RX_PHYS_ADDR;
4048c2ecf20Sopenharmony_ci	phys_cpl->rss_hdr_int.qid = htons(qid);
4058c2ecf20Sopenharmony_ci	phys_cpl->rss_hdr_int.hash_val = 0;
4068c2ecf20Sopenharmony_ci	phys_cpl->rss_hdr_int.channel = pci_chan_id;
4078c2ecf20Sopenharmony_ci}
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_cistatic inline void dsgl_walk_add_page(struct dsgl_walk *walk,
4108c2ecf20Sopenharmony_ci					size_t size,
4118c2ecf20Sopenharmony_ci					dma_addr_t addr)
4128c2ecf20Sopenharmony_ci{
4138c2ecf20Sopenharmony_ci	int j;
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	if (!size)
4168c2ecf20Sopenharmony_ci		return;
4178c2ecf20Sopenharmony_ci	j = walk->nents;
4188c2ecf20Sopenharmony_ci	walk->to->len[j % 8] = htons(size);
4198c2ecf20Sopenharmony_ci	walk->to->addr[j % 8] = cpu_to_be64(addr);
4208c2ecf20Sopenharmony_ci	j++;
4218c2ecf20Sopenharmony_ci	if ((j % 8) == 0)
4228c2ecf20Sopenharmony_ci		walk->to++;
4238c2ecf20Sopenharmony_ci	walk->nents = j;
4248c2ecf20Sopenharmony_ci}
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_cistatic void  dsgl_walk_add_sg(struct dsgl_walk *walk,
4278c2ecf20Sopenharmony_ci			   struct scatterlist *sg,
4288c2ecf20Sopenharmony_ci			      unsigned int slen,
4298c2ecf20Sopenharmony_ci			      unsigned int skip)
4308c2ecf20Sopenharmony_ci{
4318c2ecf20Sopenharmony_ci	int skip_len = 0;
4328c2ecf20Sopenharmony_ci	unsigned int left_size = slen, len = 0;
4338c2ecf20Sopenharmony_ci	unsigned int j = walk->nents;
4348c2ecf20Sopenharmony_ci	int offset, ent_len;
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	if (!slen)
4378c2ecf20Sopenharmony_ci		return;
4388c2ecf20Sopenharmony_ci	while (sg && skip) {
4398c2ecf20Sopenharmony_ci		if (sg_dma_len(sg) <= skip) {
4408c2ecf20Sopenharmony_ci			skip -= sg_dma_len(sg);
4418c2ecf20Sopenharmony_ci			skip_len = 0;
4428c2ecf20Sopenharmony_ci			sg = sg_next(sg);
4438c2ecf20Sopenharmony_ci		} else {
4448c2ecf20Sopenharmony_ci			skip_len = skip;
4458c2ecf20Sopenharmony_ci			skip = 0;
4468c2ecf20Sopenharmony_ci		}
4478c2ecf20Sopenharmony_ci	}
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ci	while (left_size && sg) {
4508c2ecf20Sopenharmony_ci		len = min_t(u32, left_size, sg_dma_len(sg) - skip_len);
4518c2ecf20Sopenharmony_ci		offset = 0;
4528c2ecf20Sopenharmony_ci		while (len) {
4538c2ecf20Sopenharmony_ci			ent_len =  min_t(u32, len, CHCR_DST_SG_SIZE);
4548c2ecf20Sopenharmony_ci			walk->to->len[j % 8] = htons(ent_len);
4558c2ecf20Sopenharmony_ci			walk->to->addr[j % 8] = cpu_to_be64(sg_dma_address(sg) +
4568c2ecf20Sopenharmony_ci						      offset + skip_len);
4578c2ecf20Sopenharmony_ci			offset += ent_len;
4588c2ecf20Sopenharmony_ci			len -= ent_len;
4598c2ecf20Sopenharmony_ci			j++;
4608c2ecf20Sopenharmony_ci			if ((j % 8) == 0)
4618c2ecf20Sopenharmony_ci				walk->to++;
4628c2ecf20Sopenharmony_ci		}
4638c2ecf20Sopenharmony_ci		walk->last_sg = sg;
4648c2ecf20Sopenharmony_ci		walk->last_sg_len = min_t(u32, left_size, sg_dma_len(sg) -
4658c2ecf20Sopenharmony_ci					  skip_len) + skip_len;
4668c2ecf20Sopenharmony_ci		left_size -= min_t(u32, left_size, sg_dma_len(sg) - skip_len);
4678c2ecf20Sopenharmony_ci		skip_len = 0;
4688c2ecf20Sopenharmony_ci		sg = sg_next(sg);
4698c2ecf20Sopenharmony_ci	}
4708c2ecf20Sopenharmony_ci	walk->nents = j;
4718c2ecf20Sopenharmony_ci}
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_cistatic inline void ulptx_walk_init(struct ulptx_walk *walk,
4748c2ecf20Sopenharmony_ci				   struct ulptx_sgl *ulp)
4758c2ecf20Sopenharmony_ci{
4768c2ecf20Sopenharmony_ci	walk->sgl = ulp;
4778c2ecf20Sopenharmony_ci	walk->nents = 0;
4788c2ecf20Sopenharmony_ci	walk->pair_idx = 0;
4798c2ecf20Sopenharmony_ci	walk->pair = ulp->sge;
4808c2ecf20Sopenharmony_ci	walk->last_sg = NULL;
4818c2ecf20Sopenharmony_ci	walk->last_sg_len = 0;
4828c2ecf20Sopenharmony_ci}
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_cistatic inline void ulptx_walk_end(struct ulptx_walk *walk)
4858c2ecf20Sopenharmony_ci{
4868c2ecf20Sopenharmony_ci	walk->sgl->cmd_nsge = htonl(ULPTX_CMD_V(ULP_TX_SC_DSGL) |
4878c2ecf20Sopenharmony_ci			      ULPTX_NSGE_V(walk->nents));
4888c2ecf20Sopenharmony_ci}
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_cistatic inline void ulptx_walk_add_page(struct ulptx_walk *walk,
4928c2ecf20Sopenharmony_ci					size_t size,
4938c2ecf20Sopenharmony_ci					dma_addr_t addr)
4948c2ecf20Sopenharmony_ci{
4958c2ecf20Sopenharmony_ci	if (!size)
4968c2ecf20Sopenharmony_ci		return;
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	if (walk->nents == 0) {
4998c2ecf20Sopenharmony_ci		walk->sgl->len0 = cpu_to_be32(size);
5008c2ecf20Sopenharmony_ci		walk->sgl->addr0 = cpu_to_be64(addr);
5018c2ecf20Sopenharmony_ci	} else {
5028c2ecf20Sopenharmony_ci		walk->pair->addr[walk->pair_idx] = cpu_to_be64(addr);
5038c2ecf20Sopenharmony_ci		walk->pair->len[walk->pair_idx] = cpu_to_be32(size);
5048c2ecf20Sopenharmony_ci		walk->pair_idx = !walk->pair_idx;
5058c2ecf20Sopenharmony_ci		if (!walk->pair_idx)
5068c2ecf20Sopenharmony_ci			walk->pair++;
5078c2ecf20Sopenharmony_ci	}
5088c2ecf20Sopenharmony_ci	walk->nents++;
5098c2ecf20Sopenharmony_ci}
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_cistatic void  ulptx_walk_add_sg(struct ulptx_walk *walk,
5128c2ecf20Sopenharmony_ci					struct scatterlist *sg,
5138c2ecf20Sopenharmony_ci			       unsigned int len,
5148c2ecf20Sopenharmony_ci			       unsigned int skip)
5158c2ecf20Sopenharmony_ci{
5168c2ecf20Sopenharmony_ci	int small;
5178c2ecf20Sopenharmony_ci	int skip_len = 0;
5188c2ecf20Sopenharmony_ci	unsigned int sgmin;
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci	if (!len)
5218c2ecf20Sopenharmony_ci		return;
5228c2ecf20Sopenharmony_ci	while (sg && skip) {
5238c2ecf20Sopenharmony_ci		if (sg_dma_len(sg) <= skip) {
5248c2ecf20Sopenharmony_ci			skip -= sg_dma_len(sg);
5258c2ecf20Sopenharmony_ci			skip_len = 0;
5268c2ecf20Sopenharmony_ci			sg = sg_next(sg);
5278c2ecf20Sopenharmony_ci		} else {
5288c2ecf20Sopenharmony_ci			skip_len = skip;
5298c2ecf20Sopenharmony_ci			skip = 0;
5308c2ecf20Sopenharmony_ci		}
5318c2ecf20Sopenharmony_ci	}
5328c2ecf20Sopenharmony_ci	WARN(!sg, "SG should not be null here\n");
5338c2ecf20Sopenharmony_ci	if (sg && (walk->nents == 0)) {
5348c2ecf20Sopenharmony_ci		small = min_t(unsigned int, sg_dma_len(sg) - skip_len, len);
5358c2ecf20Sopenharmony_ci		sgmin = min_t(unsigned int, small, CHCR_SRC_SG_SIZE);
5368c2ecf20Sopenharmony_ci		walk->sgl->len0 = cpu_to_be32(sgmin);
5378c2ecf20Sopenharmony_ci		walk->sgl->addr0 = cpu_to_be64(sg_dma_address(sg) + skip_len);
5388c2ecf20Sopenharmony_ci		walk->nents++;
5398c2ecf20Sopenharmony_ci		len -= sgmin;
5408c2ecf20Sopenharmony_ci		walk->last_sg = sg;
5418c2ecf20Sopenharmony_ci		walk->last_sg_len = sgmin + skip_len;
5428c2ecf20Sopenharmony_ci		skip_len += sgmin;
5438c2ecf20Sopenharmony_ci		if (sg_dma_len(sg) == skip_len) {
5448c2ecf20Sopenharmony_ci			sg = sg_next(sg);
5458c2ecf20Sopenharmony_ci			skip_len = 0;
5468c2ecf20Sopenharmony_ci		}
5478c2ecf20Sopenharmony_ci	}
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	while (sg && len) {
5508c2ecf20Sopenharmony_ci		small = min(sg_dma_len(sg) - skip_len, len);
5518c2ecf20Sopenharmony_ci		sgmin = min_t(unsigned int, small, CHCR_SRC_SG_SIZE);
5528c2ecf20Sopenharmony_ci		walk->pair->len[walk->pair_idx] = cpu_to_be32(sgmin);
5538c2ecf20Sopenharmony_ci		walk->pair->addr[walk->pair_idx] =
5548c2ecf20Sopenharmony_ci			cpu_to_be64(sg_dma_address(sg) + skip_len);
5558c2ecf20Sopenharmony_ci		walk->pair_idx = !walk->pair_idx;
5568c2ecf20Sopenharmony_ci		walk->nents++;
5578c2ecf20Sopenharmony_ci		if (!walk->pair_idx)
5588c2ecf20Sopenharmony_ci			walk->pair++;
5598c2ecf20Sopenharmony_ci		len -= sgmin;
5608c2ecf20Sopenharmony_ci		skip_len += sgmin;
5618c2ecf20Sopenharmony_ci		walk->last_sg = sg;
5628c2ecf20Sopenharmony_ci		walk->last_sg_len = skip_len;
5638c2ecf20Sopenharmony_ci		if (sg_dma_len(sg) == skip_len) {
5648c2ecf20Sopenharmony_ci			sg = sg_next(sg);
5658c2ecf20Sopenharmony_ci			skip_len = 0;
5668c2ecf20Sopenharmony_ci		}
5678c2ecf20Sopenharmony_ci	}
5688c2ecf20Sopenharmony_ci}
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_cistatic inline int get_cryptoalg_subtype(struct crypto_skcipher *tfm)
5718c2ecf20Sopenharmony_ci{
5728c2ecf20Sopenharmony_ci	struct skcipher_alg *alg = crypto_skcipher_alg(tfm);
5738c2ecf20Sopenharmony_ci	struct chcr_alg_template *chcr_crypto_alg =
5748c2ecf20Sopenharmony_ci		container_of(alg, struct chcr_alg_template, alg.skcipher);
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_ci	return chcr_crypto_alg->type & CRYPTO_ALG_SUB_TYPE_MASK;
5778c2ecf20Sopenharmony_ci}
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_cistatic int cxgb4_is_crypto_q_full(struct net_device *dev, unsigned int idx)
5808c2ecf20Sopenharmony_ci{
5818c2ecf20Sopenharmony_ci	struct adapter *adap = netdev2adap(dev);
5828c2ecf20Sopenharmony_ci	struct sge_uld_txq_info *txq_info =
5838c2ecf20Sopenharmony_ci		adap->sge.uld_txq_info[CXGB4_TX_CRYPTO];
5848c2ecf20Sopenharmony_ci	struct sge_uld_txq *txq;
5858c2ecf20Sopenharmony_ci	int ret = 0;
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_ci	local_bh_disable();
5888c2ecf20Sopenharmony_ci	txq = &txq_info->uldtxq[idx];
5898c2ecf20Sopenharmony_ci	spin_lock(&txq->sendq.lock);
5908c2ecf20Sopenharmony_ci	if (txq->full)
5918c2ecf20Sopenharmony_ci		ret = -1;
5928c2ecf20Sopenharmony_ci	spin_unlock(&txq->sendq.lock);
5938c2ecf20Sopenharmony_ci	local_bh_enable();
5948c2ecf20Sopenharmony_ci	return ret;
5958c2ecf20Sopenharmony_ci}
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_cistatic int generate_copy_rrkey(struct ablk_ctx *ablkctx,
5988c2ecf20Sopenharmony_ci			       struct _key_ctx *key_ctx)
5998c2ecf20Sopenharmony_ci{
6008c2ecf20Sopenharmony_ci	if (ablkctx->ciph_mode == CHCR_SCMD_CIPHER_MODE_AES_CBC) {
6018c2ecf20Sopenharmony_ci		memcpy(key_ctx->key, ablkctx->rrkey, ablkctx->enckey_len);
6028c2ecf20Sopenharmony_ci	} else {
6038c2ecf20Sopenharmony_ci		memcpy(key_ctx->key,
6048c2ecf20Sopenharmony_ci		       ablkctx->key + (ablkctx->enckey_len >> 1),
6058c2ecf20Sopenharmony_ci		       ablkctx->enckey_len >> 1);
6068c2ecf20Sopenharmony_ci		memcpy(key_ctx->key + (ablkctx->enckey_len >> 1),
6078c2ecf20Sopenharmony_ci		       ablkctx->rrkey, ablkctx->enckey_len >> 1);
6088c2ecf20Sopenharmony_ci	}
6098c2ecf20Sopenharmony_ci	return 0;
6108c2ecf20Sopenharmony_ci}
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_cistatic int chcr_hash_ent_in_wr(struct scatterlist *src,
6138c2ecf20Sopenharmony_ci			     unsigned int minsg,
6148c2ecf20Sopenharmony_ci			     unsigned int space,
6158c2ecf20Sopenharmony_ci			     unsigned int srcskip)
6168c2ecf20Sopenharmony_ci{
6178c2ecf20Sopenharmony_ci	int srclen = 0;
6188c2ecf20Sopenharmony_ci	int srcsg = minsg;
6198c2ecf20Sopenharmony_ci	int soffset = 0, sless;
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	if (sg_dma_len(src) == srcskip) {
6228c2ecf20Sopenharmony_ci		src = sg_next(src);
6238c2ecf20Sopenharmony_ci		srcskip = 0;
6248c2ecf20Sopenharmony_ci	}
6258c2ecf20Sopenharmony_ci	while (src && space > (sgl_ent_len[srcsg + 1])) {
6268c2ecf20Sopenharmony_ci		sless = min_t(unsigned int, sg_dma_len(src) - soffset -	srcskip,
6278c2ecf20Sopenharmony_ci							CHCR_SRC_SG_SIZE);
6288c2ecf20Sopenharmony_ci		srclen += sless;
6298c2ecf20Sopenharmony_ci		soffset += sless;
6308c2ecf20Sopenharmony_ci		srcsg++;
6318c2ecf20Sopenharmony_ci		if (sg_dma_len(src) == (soffset + srcskip)) {
6328c2ecf20Sopenharmony_ci			src = sg_next(src);
6338c2ecf20Sopenharmony_ci			soffset = 0;
6348c2ecf20Sopenharmony_ci			srcskip = 0;
6358c2ecf20Sopenharmony_ci		}
6368c2ecf20Sopenharmony_ci	}
6378c2ecf20Sopenharmony_ci	return srclen;
6388c2ecf20Sopenharmony_ci}
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_cistatic int chcr_sg_ent_in_wr(struct scatterlist *src,
6418c2ecf20Sopenharmony_ci			     struct scatterlist *dst,
6428c2ecf20Sopenharmony_ci			     unsigned int minsg,
6438c2ecf20Sopenharmony_ci			     unsigned int space,
6448c2ecf20Sopenharmony_ci			     unsigned int srcskip,
6458c2ecf20Sopenharmony_ci			     unsigned int dstskip)
6468c2ecf20Sopenharmony_ci{
6478c2ecf20Sopenharmony_ci	int srclen = 0, dstlen = 0;
6488c2ecf20Sopenharmony_ci	int srcsg = minsg, dstsg = minsg;
6498c2ecf20Sopenharmony_ci	int offset = 0, soffset = 0, less, sless = 0;
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci	if (sg_dma_len(src) == srcskip) {
6528c2ecf20Sopenharmony_ci		src = sg_next(src);
6538c2ecf20Sopenharmony_ci		srcskip = 0;
6548c2ecf20Sopenharmony_ci	}
6558c2ecf20Sopenharmony_ci	if (sg_dma_len(dst) == dstskip) {
6568c2ecf20Sopenharmony_ci		dst = sg_next(dst);
6578c2ecf20Sopenharmony_ci		dstskip = 0;
6588c2ecf20Sopenharmony_ci	}
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_ci	while (src && dst &&
6618c2ecf20Sopenharmony_ci	       space > (sgl_ent_len[srcsg + 1] + dsgl_ent_len[dstsg])) {
6628c2ecf20Sopenharmony_ci		sless = min_t(unsigned int, sg_dma_len(src) - srcskip - soffset,
6638c2ecf20Sopenharmony_ci				CHCR_SRC_SG_SIZE);
6648c2ecf20Sopenharmony_ci		srclen += sless;
6658c2ecf20Sopenharmony_ci		srcsg++;
6668c2ecf20Sopenharmony_ci		offset = 0;
6678c2ecf20Sopenharmony_ci		while (dst && ((dstsg + 1) <= MAX_DSGL_ENT) &&
6688c2ecf20Sopenharmony_ci		       space > (sgl_ent_len[srcsg] + dsgl_ent_len[dstsg + 1])) {
6698c2ecf20Sopenharmony_ci			if (srclen <= dstlen)
6708c2ecf20Sopenharmony_ci				break;
6718c2ecf20Sopenharmony_ci			less = min_t(unsigned int, sg_dma_len(dst) - offset -
6728c2ecf20Sopenharmony_ci				     dstskip, CHCR_DST_SG_SIZE);
6738c2ecf20Sopenharmony_ci			dstlen += less;
6748c2ecf20Sopenharmony_ci			offset += less;
6758c2ecf20Sopenharmony_ci			if ((offset + dstskip) == sg_dma_len(dst)) {
6768c2ecf20Sopenharmony_ci				dst = sg_next(dst);
6778c2ecf20Sopenharmony_ci				offset = 0;
6788c2ecf20Sopenharmony_ci			}
6798c2ecf20Sopenharmony_ci			dstsg++;
6808c2ecf20Sopenharmony_ci			dstskip = 0;
6818c2ecf20Sopenharmony_ci		}
6828c2ecf20Sopenharmony_ci		soffset += sless;
6838c2ecf20Sopenharmony_ci		if ((soffset + srcskip) == sg_dma_len(src)) {
6848c2ecf20Sopenharmony_ci			src = sg_next(src);
6858c2ecf20Sopenharmony_ci			srcskip = 0;
6868c2ecf20Sopenharmony_ci			soffset = 0;
6878c2ecf20Sopenharmony_ci		}
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci	}
6908c2ecf20Sopenharmony_ci	return min(srclen, dstlen);
6918c2ecf20Sopenharmony_ci}
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_cistatic int chcr_cipher_fallback(struct crypto_skcipher *cipher,
6948c2ecf20Sopenharmony_ci				struct skcipher_request *req,
6958c2ecf20Sopenharmony_ci				u8 *iv,
6968c2ecf20Sopenharmony_ci				unsigned short op_type)
6978c2ecf20Sopenharmony_ci{
6988c2ecf20Sopenharmony_ci	struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req);
6998c2ecf20Sopenharmony_ci	int err;
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ci	skcipher_request_set_tfm(&reqctx->fallback_req, cipher);
7028c2ecf20Sopenharmony_ci	skcipher_request_set_callback(&reqctx->fallback_req, req->base.flags,
7038c2ecf20Sopenharmony_ci				      req->base.complete, req->base.data);
7048c2ecf20Sopenharmony_ci	skcipher_request_set_crypt(&reqctx->fallback_req, req->src, req->dst,
7058c2ecf20Sopenharmony_ci				   req->cryptlen, iv);
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_ci	err = op_type ? crypto_skcipher_decrypt(&reqctx->fallback_req) :
7088c2ecf20Sopenharmony_ci			crypto_skcipher_encrypt(&reqctx->fallback_req);
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci	return err;
7118c2ecf20Sopenharmony_ci
7128c2ecf20Sopenharmony_ci}
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_cistatic inline int get_qidxs(struct crypto_async_request *req,
7158c2ecf20Sopenharmony_ci			    unsigned int *txqidx, unsigned int *rxqidx)
7168c2ecf20Sopenharmony_ci{
7178c2ecf20Sopenharmony_ci	struct crypto_tfm *tfm = req->tfm;
7188c2ecf20Sopenharmony_ci	int ret = 0;
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_ci	switch (tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
7218c2ecf20Sopenharmony_ci	case CRYPTO_ALG_TYPE_AEAD:
7228c2ecf20Sopenharmony_ci	{
7238c2ecf20Sopenharmony_ci		struct aead_request *aead_req =
7248c2ecf20Sopenharmony_ci			container_of(req, struct aead_request, base);
7258c2ecf20Sopenharmony_ci		struct chcr_aead_reqctx *reqctx = aead_request_ctx(aead_req);
7268c2ecf20Sopenharmony_ci		*txqidx = reqctx->txqidx;
7278c2ecf20Sopenharmony_ci		*rxqidx = reqctx->rxqidx;
7288c2ecf20Sopenharmony_ci		break;
7298c2ecf20Sopenharmony_ci	}
7308c2ecf20Sopenharmony_ci	case CRYPTO_ALG_TYPE_SKCIPHER:
7318c2ecf20Sopenharmony_ci	{
7328c2ecf20Sopenharmony_ci		struct skcipher_request *sk_req =
7338c2ecf20Sopenharmony_ci			container_of(req, struct skcipher_request, base);
7348c2ecf20Sopenharmony_ci		struct chcr_skcipher_req_ctx *reqctx =
7358c2ecf20Sopenharmony_ci			skcipher_request_ctx(sk_req);
7368c2ecf20Sopenharmony_ci		*txqidx = reqctx->txqidx;
7378c2ecf20Sopenharmony_ci		*rxqidx = reqctx->rxqidx;
7388c2ecf20Sopenharmony_ci		break;
7398c2ecf20Sopenharmony_ci	}
7408c2ecf20Sopenharmony_ci	case CRYPTO_ALG_TYPE_AHASH:
7418c2ecf20Sopenharmony_ci	{
7428c2ecf20Sopenharmony_ci		struct ahash_request *ahash_req =
7438c2ecf20Sopenharmony_ci			container_of(req, struct ahash_request, base);
7448c2ecf20Sopenharmony_ci		struct chcr_ahash_req_ctx *reqctx =
7458c2ecf20Sopenharmony_ci			ahash_request_ctx(ahash_req);
7468c2ecf20Sopenharmony_ci		*txqidx = reqctx->txqidx;
7478c2ecf20Sopenharmony_ci		*rxqidx = reqctx->rxqidx;
7488c2ecf20Sopenharmony_ci		break;
7498c2ecf20Sopenharmony_ci	}
7508c2ecf20Sopenharmony_ci	default:
7518c2ecf20Sopenharmony_ci		ret = -EINVAL;
7528c2ecf20Sopenharmony_ci		/* should never get here */
7538c2ecf20Sopenharmony_ci		BUG();
7548c2ecf20Sopenharmony_ci		break;
7558c2ecf20Sopenharmony_ci	}
7568c2ecf20Sopenharmony_ci	return ret;
7578c2ecf20Sopenharmony_ci}
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_cistatic inline void create_wreq(struct chcr_context *ctx,
7608c2ecf20Sopenharmony_ci			       struct chcr_wr *chcr_req,
7618c2ecf20Sopenharmony_ci			       struct crypto_async_request *req,
7628c2ecf20Sopenharmony_ci			       unsigned int imm,
7638c2ecf20Sopenharmony_ci			       int hash_sz,
7648c2ecf20Sopenharmony_ci			       unsigned int len16,
7658c2ecf20Sopenharmony_ci			       unsigned int sc_len,
7668c2ecf20Sopenharmony_ci			       unsigned int lcb)
7678c2ecf20Sopenharmony_ci{
7688c2ecf20Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(ctx);
7698c2ecf20Sopenharmony_ci	unsigned int tx_channel_id, rx_channel_id;
7708c2ecf20Sopenharmony_ci	unsigned int txqidx = 0, rxqidx = 0;
7718c2ecf20Sopenharmony_ci	unsigned int qid, fid, portno;
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci	get_qidxs(req, &txqidx, &rxqidx);
7748c2ecf20Sopenharmony_ci	qid = u_ctx->lldi.rxq_ids[rxqidx];
7758c2ecf20Sopenharmony_ci	fid = u_ctx->lldi.rxq_ids[0];
7768c2ecf20Sopenharmony_ci	portno = rxqidx / ctx->rxq_perchan;
7778c2ecf20Sopenharmony_ci	tx_channel_id = txqidx / ctx->txq_perchan;
7788c2ecf20Sopenharmony_ci	rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[portno]);
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_ci
7818c2ecf20Sopenharmony_ci	chcr_req->wreq.op_to_cctx_size = FILL_WR_OP_CCTX_SIZE;
7828c2ecf20Sopenharmony_ci	chcr_req->wreq.pld_size_hash_size =
7838c2ecf20Sopenharmony_ci		htonl(FW_CRYPTO_LOOKASIDE_WR_HASH_SIZE_V(hash_sz));
7848c2ecf20Sopenharmony_ci	chcr_req->wreq.len16_pkd =
7858c2ecf20Sopenharmony_ci		htonl(FW_CRYPTO_LOOKASIDE_WR_LEN16_V(DIV_ROUND_UP(len16, 16)));
7868c2ecf20Sopenharmony_ci	chcr_req->wreq.cookie = cpu_to_be64((uintptr_t)req);
7878c2ecf20Sopenharmony_ci	chcr_req->wreq.rx_chid_to_rx_q_id = FILL_WR_RX_Q_ID(rx_channel_id, qid,
7888c2ecf20Sopenharmony_ci							    !!lcb, txqidx);
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci	chcr_req->ulptx.cmd_dest = FILL_ULPTX_CMD_DEST(tx_channel_id, fid);
7918c2ecf20Sopenharmony_ci	chcr_req->ulptx.len = htonl((DIV_ROUND_UP(len16, 16) -
7928c2ecf20Sopenharmony_ci				((sizeof(chcr_req->wreq)) >> 4)));
7938c2ecf20Sopenharmony_ci	chcr_req->sc_imm.cmd_more = FILL_CMD_MORE(!imm);
7948c2ecf20Sopenharmony_ci	chcr_req->sc_imm.len = cpu_to_be32(sizeof(struct cpl_tx_sec_pdu) +
7958c2ecf20Sopenharmony_ci					   sizeof(chcr_req->key_ctx) + sc_len);
7968c2ecf20Sopenharmony_ci}
7978c2ecf20Sopenharmony_ci
7988c2ecf20Sopenharmony_ci/**
7998c2ecf20Sopenharmony_ci *	create_cipher_wr - form the WR for cipher operations
8008c2ecf20Sopenharmony_ci *	@req: cipher req.
8018c2ecf20Sopenharmony_ci *	@ctx: crypto driver context of the request.
8028c2ecf20Sopenharmony_ci *	@qid: ingress qid where response of this WR should be received.
8038c2ecf20Sopenharmony_ci *	@op_type:	encryption or decryption
8048c2ecf20Sopenharmony_ci */
8058c2ecf20Sopenharmony_cistatic struct sk_buff *create_cipher_wr(struct cipher_wr_param *wrparam)
8068c2ecf20Sopenharmony_ci{
8078c2ecf20Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(wrparam->req);
8088c2ecf20Sopenharmony_ci	struct chcr_context *ctx = c_ctx(tfm);
8098c2ecf20Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(ctx);
8108c2ecf20Sopenharmony_ci	struct ablk_ctx *ablkctx = ABLK_CTX(ctx);
8118c2ecf20Sopenharmony_ci	struct sk_buff *skb = NULL;
8128c2ecf20Sopenharmony_ci	struct chcr_wr *chcr_req;
8138c2ecf20Sopenharmony_ci	struct cpl_rx_phys_dsgl *phys_cpl;
8148c2ecf20Sopenharmony_ci	struct ulptx_sgl *ulptx;
8158c2ecf20Sopenharmony_ci	struct chcr_skcipher_req_ctx *reqctx =
8168c2ecf20Sopenharmony_ci		skcipher_request_ctx(wrparam->req);
8178c2ecf20Sopenharmony_ci	unsigned int temp = 0, transhdr_len, dst_size;
8188c2ecf20Sopenharmony_ci	int error;
8198c2ecf20Sopenharmony_ci	int nents;
8208c2ecf20Sopenharmony_ci	unsigned int kctx_len;
8218c2ecf20Sopenharmony_ci	gfp_t flags = wrparam->req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ?
8228c2ecf20Sopenharmony_ci			GFP_KERNEL : GFP_ATOMIC;
8238c2ecf20Sopenharmony_ci	struct adapter *adap = padap(ctx->dev);
8248c2ecf20Sopenharmony_ci	unsigned int rx_channel_id = reqctx->rxqidx / ctx->rxq_perchan;
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_ci	rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]);
8278c2ecf20Sopenharmony_ci	nents = sg_nents_xlen(reqctx->dstsg,  wrparam->bytes, CHCR_DST_SG_SIZE,
8288c2ecf20Sopenharmony_ci			      reqctx->dst_ofst);
8298c2ecf20Sopenharmony_ci	dst_size = get_space_for_phys_dsgl(nents);
8308c2ecf20Sopenharmony_ci	kctx_len = roundup(ablkctx->enckey_len, 16);
8318c2ecf20Sopenharmony_ci	transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, dst_size);
8328c2ecf20Sopenharmony_ci	nents = sg_nents_xlen(reqctx->srcsg, wrparam->bytes,
8338c2ecf20Sopenharmony_ci				  CHCR_SRC_SG_SIZE, reqctx->src_ofst);
8348c2ecf20Sopenharmony_ci	temp = reqctx->imm ? roundup(wrparam->bytes, 16) :
8358c2ecf20Sopenharmony_ci				     (sgl_len(nents) * 8);
8368c2ecf20Sopenharmony_ci	transhdr_len += temp;
8378c2ecf20Sopenharmony_ci	transhdr_len = roundup(transhdr_len, 16);
8388c2ecf20Sopenharmony_ci	skb = alloc_skb(SGE_MAX_WR_LEN, flags);
8398c2ecf20Sopenharmony_ci	if (!skb) {
8408c2ecf20Sopenharmony_ci		error = -ENOMEM;
8418c2ecf20Sopenharmony_ci		goto err;
8428c2ecf20Sopenharmony_ci	}
8438c2ecf20Sopenharmony_ci	chcr_req = __skb_put_zero(skb, transhdr_len);
8448c2ecf20Sopenharmony_ci	chcr_req->sec_cpl.op_ivinsrtofst =
8458c2ecf20Sopenharmony_ci			FILL_SEC_CPL_OP_IVINSR(rx_channel_id, 2, 1);
8468c2ecf20Sopenharmony_ci
8478c2ecf20Sopenharmony_ci	chcr_req->sec_cpl.pldlen = htonl(IV + wrparam->bytes);
8488c2ecf20Sopenharmony_ci	chcr_req->sec_cpl.aadstart_cipherstop_hi =
8498c2ecf20Sopenharmony_ci			FILL_SEC_CPL_CIPHERSTOP_HI(0, 0, IV + 1, 0);
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci	chcr_req->sec_cpl.cipherstop_lo_authinsert =
8528c2ecf20Sopenharmony_ci			FILL_SEC_CPL_AUTHINSERT(0, 0, 0, 0);
8538c2ecf20Sopenharmony_ci	chcr_req->sec_cpl.seqno_numivs = FILL_SEC_CPL_SCMD0_SEQNO(reqctx->op, 0,
8548c2ecf20Sopenharmony_ci							 ablkctx->ciph_mode,
8558c2ecf20Sopenharmony_ci							 0, 0, IV >> 1);
8568c2ecf20Sopenharmony_ci	chcr_req->sec_cpl.ivgen_hdrlen = FILL_SEC_CPL_IVGEN_HDRLEN(0, 0, 0,
8578c2ecf20Sopenharmony_ci							  0, 1, dst_size);
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_ci	chcr_req->key_ctx.ctx_hdr = ablkctx->key_ctx_hdr;
8608c2ecf20Sopenharmony_ci	if ((reqctx->op == CHCR_DECRYPT_OP) &&
8618c2ecf20Sopenharmony_ci	    (!(get_cryptoalg_subtype(tfm) ==
8628c2ecf20Sopenharmony_ci	       CRYPTO_ALG_SUB_TYPE_CTR)) &&
8638c2ecf20Sopenharmony_ci	    (!(get_cryptoalg_subtype(tfm) ==
8648c2ecf20Sopenharmony_ci	       CRYPTO_ALG_SUB_TYPE_CTR_RFC3686))) {
8658c2ecf20Sopenharmony_ci		generate_copy_rrkey(ablkctx, &chcr_req->key_ctx);
8668c2ecf20Sopenharmony_ci	} else {
8678c2ecf20Sopenharmony_ci		if ((ablkctx->ciph_mode == CHCR_SCMD_CIPHER_MODE_AES_CBC) ||
8688c2ecf20Sopenharmony_ci		    (ablkctx->ciph_mode == CHCR_SCMD_CIPHER_MODE_AES_CTR)) {
8698c2ecf20Sopenharmony_ci			memcpy(chcr_req->key_ctx.key, ablkctx->key,
8708c2ecf20Sopenharmony_ci			       ablkctx->enckey_len);
8718c2ecf20Sopenharmony_ci		} else {
8728c2ecf20Sopenharmony_ci			memcpy(chcr_req->key_ctx.key, ablkctx->key +
8738c2ecf20Sopenharmony_ci			       (ablkctx->enckey_len >> 1),
8748c2ecf20Sopenharmony_ci			       ablkctx->enckey_len >> 1);
8758c2ecf20Sopenharmony_ci			memcpy(chcr_req->key_ctx.key +
8768c2ecf20Sopenharmony_ci			       (ablkctx->enckey_len >> 1),
8778c2ecf20Sopenharmony_ci			       ablkctx->key,
8788c2ecf20Sopenharmony_ci			       ablkctx->enckey_len >> 1);
8798c2ecf20Sopenharmony_ci		}
8808c2ecf20Sopenharmony_ci	}
8818c2ecf20Sopenharmony_ci	phys_cpl = (struct cpl_rx_phys_dsgl *)((u8 *)(chcr_req + 1) + kctx_len);
8828c2ecf20Sopenharmony_ci	ulptx = (struct ulptx_sgl *)((u8 *)(phys_cpl + 1) + dst_size);
8838c2ecf20Sopenharmony_ci	chcr_add_cipher_src_ent(wrparam->req, ulptx, wrparam);
8848c2ecf20Sopenharmony_ci	chcr_add_cipher_dst_ent(wrparam->req, phys_cpl, wrparam, wrparam->qid);
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_ci	atomic_inc(&adap->chcr_stats.cipher_rqst);
8878c2ecf20Sopenharmony_ci	temp = sizeof(struct cpl_rx_phys_dsgl) + dst_size + kctx_len + IV
8888c2ecf20Sopenharmony_ci		+ (reqctx->imm ? (wrparam->bytes) : 0);
8898c2ecf20Sopenharmony_ci	create_wreq(c_ctx(tfm), chcr_req, &(wrparam->req->base), reqctx->imm, 0,
8908c2ecf20Sopenharmony_ci		    transhdr_len, temp,
8918c2ecf20Sopenharmony_ci			ablkctx->ciph_mode == CHCR_SCMD_CIPHER_MODE_AES_CBC);
8928c2ecf20Sopenharmony_ci	reqctx->skb = skb;
8938c2ecf20Sopenharmony_ci
8948c2ecf20Sopenharmony_ci	if (reqctx->op && (ablkctx->ciph_mode ==
8958c2ecf20Sopenharmony_ci			   CHCR_SCMD_CIPHER_MODE_AES_CBC))
8968c2ecf20Sopenharmony_ci		sg_pcopy_to_buffer(wrparam->req->src,
8978c2ecf20Sopenharmony_ci			sg_nents(wrparam->req->src), wrparam->req->iv, 16,
8988c2ecf20Sopenharmony_ci			reqctx->processed + wrparam->bytes - AES_BLOCK_SIZE);
8998c2ecf20Sopenharmony_ci
9008c2ecf20Sopenharmony_ci	return skb;
9018c2ecf20Sopenharmony_cierr:
9028c2ecf20Sopenharmony_ci	return ERR_PTR(error);
9038c2ecf20Sopenharmony_ci}
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_cistatic inline int chcr_keyctx_ck_size(unsigned int keylen)
9068c2ecf20Sopenharmony_ci{
9078c2ecf20Sopenharmony_ci	int ck_size = 0;
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_ci	if (keylen == AES_KEYSIZE_128)
9108c2ecf20Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128;
9118c2ecf20Sopenharmony_ci	else if (keylen == AES_KEYSIZE_192)
9128c2ecf20Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_192;
9138c2ecf20Sopenharmony_ci	else if (keylen == AES_KEYSIZE_256)
9148c2ecf20Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256;
9158c2ecf20Sopenharmony_ci	else
9168c2ecf20Sopenharmony_ci		ck_size = 0;
9178c2ecf20Sopenharmony_ci
9188c2ecf20Sopenharmony_ci	return ck_size;
9198c2ecf20Sopenharmony_ci}
9208c2ecf20Sopenharmony_cistatic int chcr_cipher_fallback_setkey(struct crypto_skcipher *cipher,
9218c2ecf20Sopenharmony_ci				       const u8 *key,
9228c2ecf20Sopenharmony_ci				       unsigned int keylen)
9238c2ecf20Sopenharmony_ci{
9248c2ecf20Sopenharmony_ci	struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(cipher));
9258c2ecf20Sopenharmony_ci
9268c2ecf20Sopenharmony_ci	crypto_skcipher_clear_flags(ablkctx->sw_cipher,
9278c2ecf20Sopenharmony_ci				CRYPTO_TFM_REQ_MASK);
9288c2ecf20Sopenharmony_ci	crypto_skcipher_set_flags(ablkctx->sw_cipher,
9298c2ecf20Sopenharmony_ci				cipher->base.crt_flags & CRYPTO_TFM_REQ_MASK);
9308c2ecf20Sopenharmony_ci	return crypto_skcipher_setkey(ablkctx->sw_cipher, key, keylen);
9318c2ecf20Sopenharmony_ci}
9328c2ecf20Sopenharmony_ci
9338c2ecf20Sopenharmony_cistatic int chcr_aes_cbc_setkey(struct crypto_skcipher *cipher,
9348c2ecf20Sopenharmony_ci			       const u8 *key,
9358c2ecf20Sopenharmony_ci			       unsigned int keylen)
9368c2ecf20Sopenharmony_ci{
9378c2ecf20Sopenharmony_ci	struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(cipher));
9388c2ecf20Sopenharmony_ci	unsigned int ck_size, context_size;
9398c2ecf20Sopenharmony_ci	u16 alignment = 0;
9408c2ecf20Sopenharmony_ci	int err;
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ci	err = chcr_cipher_fallback_setkey(cipher, key, keylen);
9438c2ecf20Sopenharmony_ci	if (err)
9448c2ecf20Sopenharmony_ci		goto badkey_err;
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_ci	ck_size = chcr_keyctx_ck_size(keylen);
9478c2ecf20Sopenharmony_ci	alignment = ck_size == CHCR_KEYCTX_CIPHER_KEY_SIZE_192 ? 8 : 0;
9488c2ecf20Sopenharmony_ci	memcpy(ablkctx->key, key, keylen);
9498c2ecf20Sopenharmony_ci	ablkctx->enckey_len = keylen;
9508c2ecf20Sopenharmony_ci	get_aes_decrypt_key(ablkctx->rrkey, ablkctx->key, keylen << 3);
9518c2ecf20Sopenharmony_ci	context_size = (KEY_CONTEXT_HDR_SALT_AND_PAD +
9528c2ecf20Sopenharmony_ci			keylen + alignment) >> 4;
9538c2ecf20Sopenharmony_ci
9548c2ecf20Sopenharmony_ci	ablkctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, CHCR_KEYCTX_NO_KEY,
9558c2ecf20Sopenharmony_ci						0, 0, context_size);
9568c2ecf20Sopenharmony_ci	ablkctx->ciph_mode = CHCR_SCMD_CIPHER_MODE_AES_CBC;
9578c2ecf20Sopenharmony_ci	return 0;
9588c2ecf20Sopenharmony_cibadkey_err:
9598c2ecf20Sopenharmony_ci	ablkctx->enckey_len = 0;
9608c2ecf20Sopenharmony_ci
9618c2ecf20Sopenharmony_ci	return err;
9628c2ecf20Sopenharmony_ci}
9638c2ecf20Sopenharmony_ci
9648c2ecf20Sopenharmony_cistatic int chcr_aes_ctr_setkey(struct crypto_skcipher *cipher,
9658c2ecf20Sopenharmony_ci				   const u8 *key,
9668c2ecf20Sopenharmony_ci				   unsigned int keylen)
9678c2ecf20Sopenharmony_ci{
9688c2ecf20Sopenharmony_ci	struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(cipher));
9698c2ecf20Sopenharmony_ci	unsigned int ck_size, context_size;
9708c2ecf20Sopenharmony_ci	u16 alignment = 0;
9718c2ecf20Sopenharmony_ci	int err;
9728c2ecf20Sopenharmony_ci
9738c2ecf20Sopenharmony_ci	err = chcr_cipher_fallback_setkey(cipher, key, keylen);
9748c2ecf20Sopenharmony_ci	if (err)
9758c2ecf20Sopenharmony_ci		goto badkey_err;
9768c2ecf20Sopenharmony_ci	ck_size = chcr_keyctx_ck_size(keylen);
9778c2ecf20Sopenharmony_ci	alignment = (ck_size == CHCR_KEYCTX_CIPHER_KEY_SIZE_192) ? 8 : 0;
9788c2ecf20Sopenharmony_ci	memcpy(ablkctx->key, key, keylen);
9798c2ecf20Sopenharmony_ci	ablkctx->enckey_len = keylen;
9808c2ecf20Sopenharmony_ci	context_size = (KEY_CONTEXT_HDR_SALT_AND_PAD +
9818c2ecf20Sopenharmony_ci			keylen + alignment) >> 4;
9828c2ecf20Sopenharmony_ci
9838c2ecf20Sopenharmony_ci	ablkctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, CHCR_KEYCTX_NO_KEY,
9848c2ecf20Sopenharmony_ci						0, 0, context_size);
9858c2ecf20Sopenharmony_ci	ablkctx->ciph_mode = CHCR_SCMD_CIPHER_MODE_AES_CTR;
9868c2ecf20Sopenharmony_ci
9878c2ecf20Sopenharmony_ci	return 0;
9888c2ecf20Sopenharmony_cibadkey_err:
9898c2ecf20Sopenharmony_ci	ablkctx->enckey_len = 0;
9908c2ecf20Sopenharmony_ci
9918c2ecf20Sopenharmony_ci	return err;
9928c2ecf20Sopenharmony_ci}
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_cistatic int chcr_aes_rfc3686_setkey(struct crypto_skcipher *cipher,
9958c2ecf20Sopenharmony_ci				   const u8 *key,
9968c2ecf20Sopenharmony_ci				   unsigned int keylen)
9978c2ecf20Sopenharmony_ci{
9988c2ecf20Sopenharmony_ci	struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(cipher));
9998c2ecf20Sopenharmony_ci	unsigned int ck_size, context_size;
10008c2ecf20Sopenharmony_ci	u16 alignment = 0;
10018c2ecf20Sopenharmony_ci	int err;
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_ci	if (keylen < CTR_RFC3686_NONCE_SIZE)
10048c2ecf20Sopenharmony_ci		return -EINVAL;
10058c2ecf20Sopenharmony_ci	memcpy(ablkctx->nonce, key + (keylen - CTR_RFC3686_NONCE_SIZE),
10068c2ecf20Sopenharmony_ci	       CTR_RFC3686_NONCE_SIZE);
10078c2ecf20Sopenharmony_ci
10088c2ecf20Sopenharmony_ci	keylen -= CTR_RFC3686_NONCE_SIZE;
10098c2ecf20Sopenharmony_ci	err = chcr_cipher_fallback_setkey(cipher, key, keylen);
10108c2ecf20Sopenharmony_ci	if (err)
10118c2ecf20Sopenharmony_ci		goto badkey_err;
10128c2ecf20Sopenharmony_ci
10138c2ecf20Sopenharmony_ci	ck_size = chcr_keyctx_ck_size(keylen);
10148c2ecf20Sopenharmony_ci	alignment = (ck_size == CHCR_KEYCTX_CIPHER_KEY_SIZE_192) ? 8 : 0;
10158c2ecf20Sopenharmony_ci	memcpy(ablkctx->key, key, keylen);
10168c2ecf20Sopenharmony_ci	ablkctx->enckey_len = keylen;
10178c2ecf20Sopenharmony_ci	context_size = (KEY_CONTEXT_HDR_SALT_AND_PAD +
10188c2ecf20Sopenharmony_ci			keylen + alignment) >> 4;
10198c2ecf20Sopenharmony_ci
10208c2ecf20Sopenharmony_ci	ablkctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, CHCR_KEYCTX_NO_KEY,
10218c2ecf20Sopenharmony_ci						0, 0, context_size);
10228c2ecf20Sopenharmony_ci	ablkctx->ciph_mode = CHCR_SCMD_CIPHER_MODE_AES_CTR;
10238c2ecf20Sopenharmony_ci
10248c2ecf20Sopenharmony_ci	return 0;
10258c2ecf20Sopenharmony_cibadkey_err:
10268c2ecf20Sopenharmony_ci	ablkctx->enckey_len = 0;
10278c2ecf20Sopenharmony_ci
10288c2ecf20Sopenharmony_ci	return err;
10298c2ecf20Sopenharmony_ci}
10308c2ecf20Sopenharmony_cistatic void ctr_add_iv(u8 *dstiv, u8 *srciv, u32 add)
10318c2ecf20Sopenharmony_ci{
10328c2ecf20Sopenharmony_ci	unsigned int size = AES_BLOCK_SIZE;
10338c2ecf20Sopenharmony_ci	__be32 *b = (__be32 *)(dstiv + size);
10348c2ecf20Sopenharmony_ci	u32 c, prev;
10358c2ecf20Sopenharmony_ci
10368c2ecf20Sopenharmony_ci	memcpy(dstiv, srciv, AES_BLOCK_SIZE);
10378c2ecf20Sopenharmony_ci	for (; size >= 4; size -= 4) {
10388c2ecf20Sopenharmony_ci		prev = be32_to_cpu(*--b);
10398c2ecf20Sopenharmony_ci		c = prev + add;
10408c2ecf20Sopenharmony_ci		*b = cpu_to_be32(c);
10418c2ecf20Sopenharmony_ci		if (prev < c)
10428c2ecf20Sopenharmony_ci			break;
10438c2ecf20Sopenharmony_ci		add = 1;
10448c2ecf20Sopenharmony_ci	}
10458c2ecf20Sopenharmony_ci
10468c2ecf20Sopenharmony_ci}
10478c2ecf20Sopenharmony_ci
10488c2ecf20Sopenharmony_cistatic unsigned int adjust_ctr_overflow(u8 *iv, u32 bytes)
10498c2ecf20Sopenharmony_ci{
10508c2ecf20Sopenharmony_ci	__be32 *b = (__be32 *)(iv + AES_BLOCK_SIZE);
10518c2ecf20Sopenharmony_ci	u64 c;
10528c2ecf20Sopenharmony_ci	u32 temp = be32_to_cpu(*--b);
10538c2ecf20Sopenharmony_ci
10548c2ecf20Sopenharmony_ci	temp = ~temp;
10558c2ecf20Sopenharmony_ci	c = (u64)temp +  1; // No of block can processed without overflow
10568c2ecf20Sopenharmony_ci	if ((bytes / AES_BLOCK_SIZE) >= c)
10578c2ecf20Sopenharmony_ci		bytes = c * AES_BLOCK_SIZE;
10588c2ecf20Sopenharmony_ci	return bytes;
10598c2ecf20Sopenharmony_ci}
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_cistatic int chcr_update_tweak(struct skcipher_request *req, u8 *iv,
10628c2ecf20Sopenharmony_ci			     u32 isfinal)
10638c2ecf20Sopenharmony_ci{
10648c2ecf20Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
10658c2ecf20Sopenharmony_ci	struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(tfm));
10668c2ecf20Sopenharmony_ci	struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req);
10678c2ecf20Sopenharmony_ci	struct crypto_aes_ctx aes;
10688c2ecf20Sopenharmony_ci	int ret, i;
10698c2ecf20Sopenharmony_ci	u8 *key;
10708c2ecf20Sopenharmony_ci	unsigned int keylen;
10718c2ecf20Sopenharmony_ci	int round = reqctx->last_req_len / AES_BLOCK_SIZE;
10728c2ecf20Sopenharmony_ci	int round8 = round / 8;
10738c2ecf20Sopenharmony_ci
10748c2ecf20Sopenharmony_ci	memcpy(iv, reqctx->iv, AES_BLOCK_SIZE);
10758c2ecf20Sopenharmony_ci
10768c2ecf20Sopenharmony_ci	keylen = ablkctx->enckey_len / 2;
10778c2ecf20Sopenharmony_ci	key = ablkctx->key + keylen;
10788c2ecf20Sopenharmony_ci	/* For a 192 bit key remove the padded zeroes which was
10798c2ecf20Sopenharmony_ci	 * added in chcr_xts_setkey
10808c2ecf20Sopenharmony_ci	 */
10818c2ecf20Sopenharmony_ci	if (KEY_CONTEXT_CK_SIZE_G(ntohl(ablkctx->key_ctx_hdr))
10828c2ecf20Sopenharmony_ci			== CHCR_KEYCTX_CIPHER_KEY_SIZE_192)
10838c2ecf20Sopenharmony_ci		ret = aes_expandkey(&aes, key, keylen - 8);
10848c2ecf20Sopenharmony_ci	else
10858c2ecf20Sopenharmony_ci		ret = aes_expandkey(&aes, key, keylen);
10868c2ecf20Sopenharmony_ci	if (ret)
10878c2ecf20Sopenharmony_ci		return ret;
10888c2ecf20Sopenharmony_ci	aes_encrypt(&aes, iv, iv);
10898c2ecf20Sopenharmony_ci	for (i = 0; i < round8; i++)
10908c2ecf20Sopenharmony_ci		gf128mul_x8_ble((le128 *)iv, (le128 *)iv);
10918c2ecf20Sopenharmony_ci
10928c2ecf20Sopenharmony_ci	for (i = 0; i < (round % 8); i++)
10938c2ecf20Sopenharmony_ci		gf128mul_x_ble((le128 *)iv, (le128 *)iv);
10948c2ecf20Sopenharmony_ci
10958c2ecf20Sopenharmony_ci	if (!isfinal)
10968c2ecf20Sopenharmony_ci		aes_decrypt(&aes, iv, iv);
10978c2ecf20Sopenharmony_ci
10988c2ecf20Sopenharmony_ci	memzero_explicit(&aes, sizeof(aes));
10998c2ecf20Sopenharmony_ci	return 0;
11008c2ecf20Sopenharmony_ci}
11018c2ecf20Sopenharmony_ci
11028c2ecf20Sopenharmony_cistatic int chcr_update_cipher_iv(struct skcipher_request *req,
11038c2ecf20Sopenharmony_ci				   struct cpl_fw6_pld *fw6_pld, u8 *iv)
11048c2ecf20Sopenharmony_ci{
11058c2ecf20Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
11068c2ecf20Sopenharmony_ci	struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req);
11078c2ecf20Sopenharmony_ci	int subtype = get_cryptoalg_subtype(tfm);
11088c2ecf20Sopenharmony_ci	int ret = 0;
11098c2ecf20Sopenharmony_ci
11108c2ecf20Sopenharmony_ci	if (subtype == CRYPTO_ALG_SUB_TYPE_CTR)
11118c2ecf20Sopenharmony_ci		ctr_add_iv(iv, req->iv, (reqctx->processed /
11128c2ecf20Sopenharmony_ci			   AES_BLOCK_SIZE));
11138c2ecf20Sopenharmony_ci	else if (subtype == CRYPTO_ALG_SUB_TYPE_CTR_RFC3686)
11148c2ecf20Sopenharmony_ci		*(__be32 *)(reqctx->iv + CTR_RFC3686_NONCE_SIZE +
11158c2ecf20Sopenharmony_ci			CTR_RFC3686_IV_SIZE) = cpu_to_be32((reqctx->processed /
11168c2ecf20Sopenharmony_ci						AES_BLOCK_SIZE) + 1);
11178c2ecf20Sopenharmony_ci	else if (subtype == CRYPTO_ALG_SUB_TYPE_XTS)
11188c2ecf20Sopenharmony_ci		ret = chcr_update_tweak(req, iv, 0);
11198c2ecf20Sopenharmony_ci	else if (subtype == CRYPTO_ALG_SUB_TYPE_CBC) {
11208c2ecf20Sopenharmony_ci		if (reqctx->op)
11218c2ecf20Sopenharmony_ci			/*Updated before sending last WR*/
11228c2ecf20Sopenharmony_ci			memcpy(iv, req->iv, AES_BLOCK_SIZE);
11238c2ecf20Sopenharmony_ci		else
11248c2ecf20Sopenharmony_ci			memcpy(iv, &fw6_pld->data[2], AES_BLOCK_SIZE);
11258c2ecf20Sopenharmony_ci	}
11268c2ecf20Sopenharmony_ci
11278c2ecf20Sopenharmony_ci	return ret;
11288c2ecf20Sopenharmony_ci
11298c2ecf20Sopenharmony_ci}
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_ci/* We need separate function for final iv because in rfc3686  Initial counter
11328c2ecf20Sopenharmony_ci * starts from 1 and buffer size of iv is 8 byte only which remains constant
11338c2ecf20Sopenharmony_ci * for subsequent update requests
11348c2ecf20Sopenharmony_ci */
11358c2ecf20Sopenharmony_ci
11368c2ecf20Sopenharmony_cistatic int chcr_final_cipher_iv(struct skcipher_request *req,
11378c2ecf20Sopenharmony_ci				   struct cpl_fw6_pld *fw6_pld, u8 *iv)
11388c2ecf20Sopenharmony_ci{
11398c2ecf20Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
11408c2ecf20Sopenharmony_ci	struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req);
11418c2ecf20Sopenharmony_ci	int subtype = get_cryptoalg_subtype(tfm);
11428c2ecf20Sopenharmony_ci	int ret = 0;
11438c2ecf20Sopenharmony_ci
11448c2ecf20Sopenharmony_ci	if (subtype == CRYPTO_ALG_SUB_TYPE_CTR)
11458c2ecf20Sopenharmony_ci		ctr_add_iv(iv, req->iv, DIV_ROUND_UP(reqctx->processed,
11468c2ecf20Sopenharmony_ci						       AES_BLOCK_SIZE));
11478c2ecf20Sopenharmony_ci	else if (subtype == CRYPTO_ALG_SUB_TYPE_XTS) {
11488c2ecf20Sopenharmony_ci		if (!reqctx->partial_req)
11498c2ecf20Sopenharmony_ci			memcpy(iv, reqctx->iv, AES_BLOCK_SIZE);
11508c2ecf20Sopenharmony_ci		else
11518c2ecf20Sopenharmony_ci			ret = chcr_update_tweak(req, iv, 1);
11528c2ecf20Sopenharmony_ci	}
11538c2ecf20Sopenharmony_ci	else if (subtype == CRYPTO_ALG_SUB_TYPE_CBC) {
11548c2ecf20Sopenharmony_ci		/*Already updated for Decrypt*/
11558c2ecf20Sopenharmony_ci		if (!reqctx->op)
11568c2ecf20Sopenharmony_ci			memcpy(iv, &fw6_pld->data[2], AES_BLOCK_SIZE);
11578c2ecf20Sopenharmony_ci
11588c2ecf20Sopenharmony_ci	}
11598c2ecf20Sopenharmony_ci	return ret;
11608c2ecf20Sopenharmony_ci
11618c2ecf20Sopenharmony_ci}
11628c2ecf20Sopenharmony_ci
11638c2ecf20Sopenharmony_cistatic int chcr_handle_cipher_resp(struct skcipher_request *req,
11648c2ecf20Sopenharmony_ci				   unsigned char *input, int err)
11658c2ecf20Sopenharmony_ci{
11668c2ecf20Sopenharmony_ci	struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req);
11678c2ecf20Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
11688c2ecf20Sopenharmony_ci	struct cpl_fw6_pld *fw6_pld = (struct cpl_fw6_pld *)input;
11698c2ecf20Sopenharmony_ci	struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(tfm));
11708c2ecf20Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(c_ctx(tfm));
11718c2ecf20Sopenharmony_ci	struct chcr_dev *dev = c_ctx(tfm)->dev;
11728c2ecf20Sopenharmony_ci	struct chcr_context *ctx = c_ctx(tfm);
11738c2ecf20Sopenharmony_ci	struct adapter *adap = padap(ctx->dev);
11748c2ecf20Sopenharmony_ci	struct cipher_wr_param wrparam;
11758c2ecf20Sopenharmony_ci	struct sk_buff *skb;
11768c2ecf20Sopenharmony_ci	int bytes;
11778c2ecf20Sopenharmony_ci
11788c2ecf20Sopenharmony_ci	if (err)
11798c2ecf20Sopenharmony_ci		goto unmap;
11808c2ecf20Sopenharmony_ci	if (req->cryptlen == reqctx->processed) {
11818c2ecf20Sopenharmony_ci		chcr_cipher_dma_unmap(&ULD_CTX(c_ctx(tfm))->lldi.pdev->dev,
11828c2ecf20Sopenharmony_ci				      req);
11838c2ecf20Sopenharmony_ci		err = chcr_final_cipher_iv(req, fw6_pld, req->iv);
11848c2ecf20Sopenharmony_ci		goto complete;
11858c2ecf20Sopenharmony_ci	}
11868c2ecf20Sopenharmony_ci
11878c2ecf20Sopenharmony_ci	if (!reqctx->imm) {
11888c2ecf20Sopenharmony_ci		bytes = chcr_sg_ent_in_wr(reqctx->srcsg, reqctx->dstsg, 0,
11898c2ecf20Sopenharmony_ci					  CIP_SPACE_LEFT(ablkctx->enckey_len),
11908c2ecf20Sopenharmony_ci					  reqctx->src_ofst, reqctx->dst_ofst);
11918c2ecf20Sopenharmony_ci		if ((bytes + reqctx->processed) >= req->cryptlen)
11928c2ecf20Sopenharmony_ci			bytes  = req->cryptlen - reqctx->processed;
11938c2ecf20Sopenharmony_ci		else
11948c2ecf20Sopenharmony_ci			bytes = rounddown(bytes, 16);
11958c2ecf20Sopenharmony_ci	} else {
11968c2ecf20Sopenharmony_ci		/*CTR mode counter overfloa*/
11978c2ecf20Sopenharmony_ci		bytes  = req->cryptlen - reqctx->processed;
11988c2ecf20Sopenharmony_ci	}
11998c2ecf20Sopenharmony_ci	err = chcr_update_cipher_iv(req, fw6_pld, reqctx->iv);
12008c2ecf20Sopenharmony_ci	if (err)
12018c2ecf20Sopenharmony_ci		goto unmap;
12028c2ecf20Sopenharmony_ci
12038c2ecf20Sopenharmony_ci	if (unlikely(bytes == 0)) {
12048c2ecf20Sopenharmony_ci		chcr_cipher_dma_unmap(&ULD_CTX(c_ctx(tfm))->lldi.pdev->dev,
12058c2ecf20Sopenharmony_ci				      req);
12068c2ecf20Sopenharmony_ci		memcpy(req->iv, reqctx->init_iv, IV);
12078c2ecf20Sopenharmony_ci		atomic_inc(&adap->chcr_stats.fallback);
12088c2ecf20Sopenharmony_ci		err = chcr_cipher_fallback(ablkctx->sw_cipher, req, req->iv,
12098c2ecf20Sopenharmony_ci					   reqctx->op);
12108c2ecf20Sopenharmony_ci		goto complete;
12118c2ecf20Sopenharmony_ci	}
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_ci	if (get_cryptoalg_subtype(tfm) ==
12148c2ecf20Sopenharmony_ci	    CRYPTO_ALG_SUB_TYPE_CTR)
12158c2ecf20Sopenharmony_ci		bytes = adjust_ctr_overflow(reqctx->iv, bytes);
12168c2ecf20Sopenharmony_ci	wrparam.qid = u_ctx->lldi.rxq_ids[reqctx->rxqidx];
12178c2ecf20Sopenharmony_ci	wrparam.req = req;
12188c2ecf20Sopenharmony_ci	wrparam.bytes = bytes;
12198c2ecf20Sopenharmony_ci	skb = create_cipher_wr(&wrparam);
12208c2ecf20Sopenharmony_ci	if (IS_ERR(skb)) {
12218c2ecf20Sopenharmony_ci		pr_err("%s : Failed to form WR. No memory\n", __func__);
12228c2ecf20Sopenharmony_ci		err = PTR_ERR(skb);
12238c2ecf20Sopenharmony_ci		goto unmap;
12248c2ecf20Sopenharmony_ci	}
12258c2ecf20Sopenharmony_ci	skb->dev = u_ctx->lldi.ports[0];
12268c2ecf20Sopenharmony_ci	set_wr_txq(skb, CPL_PRIORITY_DATA, reqctx->txqidx);
12278c2ecf20Sopenharmony_ci	chcr_send_wr(skb);
12288c2ecf20Sopenharmony_ci	reqctx->last_req_len = bytes;
12298c2ecf20Sopenharmony_ci	reqctx->processed += bytes;
12308c2ecf20Sopenharmony_ci	if (get_cryptoalg_subtype(tfm) ==
12318c2ecf20Sopenharmony_ci		CRYPTO_ALG_SUB_TYPE_CBC && req->base.flags ==
12328c2ecf20Sopenharmony_ci			CRYPTO_TFM_REQ_MAY_SLEEP ) {
12338c2ecf20Sopenharmony_ci		complete(&ctx->cbc_aes_aio_done);
12348c2ecf20Sopenharmony_ci	}
12358c2ecf20Sopenharmony_ci	return 0;
12368c2ecf20Sopenharmony_ciunmap:
12378c2ecf20Sopenharmony_ci	chcr_cipher_dma_unmap(&ULD_CTX(c_ctx(tfm))->lldi.pdev->dev, req);
12388c2ecf20Sopenharmony_cicomplete:
12398c2ecf20Sopenharmony_ci	if (get_cryptoalg_subtype(tfm) ==
12408c2ecf20Sopenharmony_ci		CRYPTO_ALG_SUB_TYPE_CBC && req->base.flags ==
12418c2ecf20Sopenharmony_ci			CRYPTO_TFM_REQ_MAY_SLEEP ) {
12428c2ecf20Sopenharmony_ci		complete(&ctx->cbc_aes_aio_done);
12438c2ecf20Sopenharmony_ci	}
12448c2ecf20Sopenharmony_ci	chcr_dec_wrcount(dev);
12458c2ecf20Sopenharmony_ci	req->base.complete(&req->base, err);
12468c2ecf20Sopenharmony_ci	return err;
12478c2ecf20Sopenharmony_ci}
12488c2ecf20Sopenharmony_ci
12498c2ecf20Sopenharmony_cistatic int process_cipher(struct skcipher_request *req,
12508c2ecf20Sopenharmony_ci				  unsigned short qid,
12518c2ecf20Sopenharmony_ci				  struct sk_buff **skb,
12528c2ecf20Sopenharmony_ci				  unsigned short op_type)
12538c2ecf20Sopenharmony_ci{
12548c2ecf20Sopenharmony_ci	struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req);
12558c2ecf20Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
12568c2ecf20Sopenharmony_ci	unsigned int ivsize = crypto_skcipher_ivsize(tfm);
12578c2ecf20Sopenharmony_ci	struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(tfm));
12588c2ecf20Sopenharmony_ci	struct adapter *adap = padap(c_ctx(tfm)->dev);
12598c2ecf20Sopenharmony_ci	struct	cipher_wr_param wrparam;
12608c2ecf20Sopenharmony_ci	int bytes, err = -EINVAL;
12618c2ecf20Sopenharmony_ci	int subtype;
12628c2ecf20Sopenharmony_ci
12638c2ecf20Sopenharmony_ci	reqctx->processed = 0;
12648c2ecf20Sopenharmony_ci	reqctx->partial_req = 0;
12658c2ecf20Sopenharmony_ci	if (!req->iv)
12668c2ecf20Sopenharmony_ci		goto error;
12678c2ecf20Sopenharmony_ci	subtype = get_cryptoalg_subtype(tfm);
12688c2ecf20Sopenharmony_ci	if ((ablkctx->enckey_len == 0) || (ivsize > AES_BLOCK_SIZE) ||
12698c2ecf20Sopenharmony_ci	    (req->cryptlen == 0) ||
12708c2ecf20Sopenharmony_ci	    (req->cryptlen % crypto_skcipher_blocksize(tfm))) {
12718c2ecf20Sopenharmony_ci		if (req->cryptlen == 0 && subtype != CRYPTO_ALG_SUB_TYPE_XTS)
12728c2ecf20Sopenharmony_ci			goto fallback;
12738c2ecf20Sopenharmony_ci		else if (req->cryptlen % crypto_skcipher_blocksize(tfm) &&
12748c2ecf20Sopenharmony_ci			 subtype == CRYPTO_ALG_SUB_TYPE_XTS)
12758c2ecf20Sopenharmony_ci			goto fallback;
12768c2ecf20Sopenharmony_ci		pr_err("AES: Invalid value of Key Len %d nbytes %d IV Len %d\n",
12778c2ecf20Sopenharmony_ci		       ablkctx->enckey_len, req->cryptlen, ivsize);
12788c2ecf20Sopenharmony_ci		goto error;
12798c2ecf20Sopenharmony_ci	}
12808c2ecf20Sopenharmony_ci
12818c2ecf20Sopenharmony_ci	err = chcr_cipher_dma_map(&ULD_CTX(c_ctx(tfm))->lldi.pdev->dev, req);
12828c2ecf20Sopenharmony_ci	if (err)
12838c2ecf20Sopenharmony_ci		goto error;
12848c2ecf20Sopenharmony_ci	if (req->cryptlen < (SGE_MAX_WR_LEN - (sizeof(struct chcr_wr) +
12858c2ecf20Sopenharmony_ci					    AES_MIN_KEY_SIZE +
12868c2ecf20Sopenharmony_ci					    sizeof(struct cpl_rx_phys_dsgl) +
12878c2ecf20Sopenharmony_ci					/*Min dsgl size*/
12888c2ecf20Sopenharmony_ci					    32))) {
12898c2ecf20Sopenharmony_ci		/* Can be sent as Imm*/
12908c2ecf20Sopenharmony_ci		unsigned int dnents = 0, transhdr_len, phys_dsgl, kctx_len;
12918c2ecf20Sopenharmony_ci
12928c2ecf20Sopenharmony_ci		dnents = sg_nents_xlen(req->dst, req->cryptlen,
12938c2ecf20Sopenharmony_ci				       CHCR_DST_SG_SIZE, 0);
12948c2ecf20Sopenharmony_ci		phys_dsgl = get_space_for_phys_dsgl(dnents);
12958c2ecf20Sopenharmony_ci		kctx_len = roundup(ablkctx->enckey_len, 16);
12968c2ecf20Sopenharmony_ci		transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, phys_dsgl);
12978c2ecf20Sopenharmony_ci		reqctx->imm = (transhdr_len + IV + req->cryptlen) <=
12988c2ecf20Sopenharmony_ci			SGE_MAX_WR_LEN;
12998c2ecf20Sopenharmony_ci		bytes = IV + req->cryptlen;
13008c2ecf20Sopenharmony_ci
13018c2ecf20Sopenharmony_ci	} else {
13028c2ecf20Sopenharmony_ci		reqctx->imm = 0;
13038c2ecf20Sopenharmony_ci	}
13048c2ecf20Sopenharmony_ci
13058c2ecf20Sopenharmony_ci	if (!reqctx->imm) {
13068c2ecf20Sopenharmony_ci		bytes = chcr_sg_ent_in_wr(req->src, req->dst, 0,
13078c2ecf20Sopenharmony_ci					  CIP_SPACE_LEFT(ablkctx->enckey_len),
13088c2ecf20Sopenharmony_ci					  0, 0);
13098c2ecf20Sopenharmony_ci		if ((bytes + reqctx->processed) >= req->cryptlen)
13108c2ecf20Sopenharmony_ci			bytes  = req->cryptlen - reqctx->processed;
13118c2ecf20Sopenharmony_ci		else
13128c2ecf20Sopenharmony_ci			bytes = rounddown(bytes, 16);
13138c2ecf20Sopenharmony_ci	} else {
13148c2ecf20Sopenharmony_ci		bytes = req->cryptlen;
13158c2ecf20Sopenharmony_ci	}
13168c2ecf20Sopenharmony_ci	if (subtype == CRYPTO_ALG_SUB_TYPE_CTR) {
13178c2ecf20Sopenharmony_ci		bytes = adjust_ctr_overflow(req->iv, bytes);
13188c2ecf20Sopenharmony_ci	}
13198c2ecf20Sopenharmony_ci	if (subtype == CRYPTO_ALG_SUB_TYPE_CTR_RFC3686) {
13208c2ecf20Sopenharmony_ci		memcpy(reqctx->iv, ablkctx->nonce, CTR_RFC3686_NONCE_SIZE);
13218c2ecf20Sopenharmony_ci		memcpy(reqctx->iv + CTR_RFC3686_NONCE_SIZE, req->iv,
13228c2ecf20Sopenharmony_ci				CTR_RFC3686_IV_SIZE);
13238c2ecf20Sopenharmony_ci
13248c2ecf20Sopenharmony_ci		/* initialize counter portion of counter block */
13258c2ecf20Sopenharmony_ci		*(__be32 *)(reqctx->iv + CTR_RFC3686_NONCE_SIZE +
13268c2ecf20Sopenharmony_ci			CTR_RFC3686_IV_SIZE) = cpu_to_be32(1);
13278c2ecf20Sopenharmony_ci		memcpy(reqctx->init_iv, reqctx->iv, IV);
13288c2ecf20Sopenharmony_ci
13298c2ecf20Sopenharmony_ci	} else {
13308c2ecf20Sopenharmony_ci
13318c2ecf20Sopenharmony_ci		memcpy(reqctx->iv, req->iv, IV);
13328c2ecf20Sopenharmony_ci		memcpy(reqctx->init_iv, req->iv, IV);
13338c2ecf20Sopenharmony_ci	}
13348c2ecf20Sopenharmony_ci	if (unlikely(bytes == 0)) {
13358c2ecf20Sopenharmony_ci		chcr_cipher_dma_unmap(&ULD_CTX(c_ctx(tfm))->lldi.pdev->dev,
13368c2ecf20Sopenharmony_ci				      req);
13378c2ecf20Sopenharmony_cifallback:       atomic_inc(&adap->chcr_stats.fallback);
13388c2ecf20Sopenharmony_ci		err = chcr_cipher_fallback(ablkctx->sw_cipher, req,
13398c2ecf20Sopenharmony_ci					   subtype ==
13408c2ecf20Sopenharmony_ci					   CRYPTO_ALG_SUB_TYPE_CTR_RFC3686 ?
13418c2ecf20Sopenharmony_ci					   reqctx->iv : req->iv,
13428c2ecf20Sopenharmony_ci					   op_type);
13438c2ecf20Sopenharmony_ci		goto error;
13448c2ecf20Sopenharmony_ci	}
13458c2ecf20Sopenharmony_ci	reqctx->op = op_type;
13468c2ecf20Sopenharmony_ci	reqctx->srcsg = req->src;
13478c2ecf20Sopenharmony_ci	reqctx->dstsg = req->dst;
13488c2ecf20Sopenharmony_ci	reqctx->src_ofst = 0;
13498c2ecf20Sopenharmony_ci	reqctx->dst_ofst = 0;
13508c2ecf20Sopenharmony_ci	wrparam.qid = qid;
13518c2ecf20Sopenharmony_ci	wrparam.req = req;
13528c2ecf20Sopenharmony_ci	wrparam.bytes = bytes;
13538c2ecf20Sopenharmony_ci	*skb = create_cipher_wr(&wrparam);
13548c2ecf20Sopenharmony_ci	if (IS_ERR(*skb)) {
13558c2ecf20Sopenharmony_ci		err = PTR_ERR(*skb);
13568c2ecf20Sopenharmony_ci		goto unmap;
13578c2ecf20Sopenharmony_ci	}
13588c2ecf20Sopenharmony_ci	reqctx->processed = bytes;
13598c2ecf20Sopenharmony_ci	reqctx->last_req_len = bytes;
13608c2ecf20Sopenharmony_ci	reqctx->partial_req = !!(req->cryptlen - reqctx->processed);
13618c2ecf20Sopenharmony_ci
13628c2ecf20Sopenharmony_ci	return 0;
13638c2ecf20Sopenharmony_ciunmap:
13648c2ecf20Sopenharmony_ci	chcr_cipher_dma_unmap(&ULD_CTX(c_ctx(tfm))->lldi.pdev->dev, req);
13658c2ecf20Sopenharmony_cierror:
13668c2ecf20Sopenharmony_ci	return err;
13678c2ecf20Sopenharmony_ci}
13688c2ecf20Sopenharmony_ci
13698c2ecf20Sopenharmony_cistatic int chcr_aes_encrypt(struct skcipher_request *req)
13708c2ecf20Sopenharmony_ci{
13718c2ecf20Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
13728c2ecf20Sopenharmony_ci	struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req);
13738c2ecf20Sopenharmony_ci	struct chcr_dev *dev = c_ctx(tfm)->dev;
13748c2ecf20Sopenharmony_ci	struct sk_buff *skb = NULL;
13758c2ecf20Sopenharmony_ci	int err;
13768c2ecf20Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(c_ctx(tfm));
13778c2ecf20Sopenharmony_ci	struct chcr_context *ctx = c_ctx(tfm);
13788c2ecf20Sopenharmony_ci	unsigned int cpu;
13798c2ecf20Sopenharmony_ci
13808c2ecf20Sopenharmony_ci	cpu = get_cpu();
13818c2ecf20Sopenharmony_ci	reqctx->txqidx = cpu % ctx->ntxq;
13828c2ecf20Sopenharmony_ci	reqctx->rxqidx = cpu % ctx->nrxq;
13838c2ecf20Sopenharmony_ci	put_cpu();
13848c2ecf20Sopenharmony_ci
13858c2ecf20Sopenharmony_ci	err = chcr_inc_wrcount(dev);
13868c2ecf20Sopenharmony_ci	if (err)
13878c2ecf20Sopenharmony_ci		return -ENXIO;
13888c2ecf20Sopenharmony_ci	if (unlikely(cxgb4_is_crypto_q_full(u_ctx->lldi.ports[0],
13898c2ecf20Sopenharmony_ci						reqctx->txqidx) &&
13908c2ecf20Sopenharmony_ci		(!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)))) {
13918c2ecf20Sopenharmony_ci			err = -ENOSPC;
13928c2ecf20Sopenharmony_ci			goto error;
13938c2ecf20Sopenharmony_ci	}
13948c2ecf20Sopenharmony_ci
13958c2ecf20Sopenharmony_ci	err = process_cipher(req, u_ctx->lldi.rxq_ids[reqctx->rxqidx],
13968c2ecf20Sopenharmony_ci			     &skb, CHCR_ENCRYPT_OP);
13978c2ecf20Sopenharmony_ci	if (err || !skb)
13988c2ecf20Sopenharmony_ci		return  err;
13998c2ecf20Sopenharmony_ci	skb->dev = u_ctx->lldi.ports[0];
14008c2ecf20Sopenharmony_ci	set_wr_txq(skb, CPL_PRIORITY_DATA, reqctx->txqidx);
14018c2ecf20Sopenharmony_ci	chcr_send_wr(skb);
14028c2ecf20Sopenharmony_ci	if (get_cryptoalg_subtype(tfm) ==
14038c2ecf20Sopenharmony_ci		CRYPTO_ALG_SUB_TYPE_CBC && req->base.flags ==
14048c2ecf20Sopenharmony_ci			CRYPTO_TFM_REQ_MAY_SLEEP ) {
14058c2ecf20Sopenharmony_ci			reqctx->partial_req = 1;
14068c2ecf20Sopenharmony_ci			wait_for_completion(&ctx->cbc_aes_aio_done);
14078c2ecf20Sopenharmony_ci        }
14088c2ecf20Sopenharmony_ci	return -EINPROGRESS;
14098c2ecf20Sopenharmony_cierror:
14108c2ecf20Sopenharmony_ci	chcr_dec_wrcount(dev);
14118c2ecf20Sopenharmony_ci	return err;
14128c2ecf20Sopenharmony_ci}
14138c2ecf20Sopenharmony_ci
14148c2ecf20Sopenharmony_cistatic int chcr_aes_decrypt(struct skcipher_request *req)
14158c2ecf20Sopenharmony_ci{
14168c2ecf20Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
14178c2ecf20Sopenharmony_ci	struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req);
14188c2ecf20Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(c_ctx(tfm));
14198c2ecf20Sopenharmony_ci	struct chcr_dev *dev = c_ctx(tfm)->dev;
14208c2ecf20Sopenharmony_ci	struct sk_buff *skb = NULL;
14218c2ecf20Sopenharmony_ci	int err;
14228c2ecf20Sopenharmony_ci	struct chcr_context *ctx = c_ctx(tfm);
14238c2ecf20Sopenharmony_ci	unsigned int cpu;
14248c2ecf20Sopenharmony_ci
14258c2ecf20Sopenharmony_ci	cpu = get_cpu();
14268c2ecf20Sopenharmony_ci	reqctx->txqidx = cpu % ctx->ntxq;
14278c2ecf20Sopenharmony_ci	reqctx->rxqidx = cpu % ctx->nrxq;
14288c2ecf20Sopenharmony_ci	put_cpu();
14298c2ecf20Sopenharmony_ci
14308c2ecf20Sopenharmony_ci	err = chcr_inc_wrcount(dev);
14318c2ecf20Sopenharmony_ci	if (err)
14328c2ecf20Sopenharmony_ci		return -ENXIO;
14338c2ecf20Sopenharmony_ci
14348c2ecf20Sopenharmony_ci	if (unlikely(cxgb4_is_crypto_q_full(u_ctx->lldi.ports[0],
14358c2ecf20Sopenharmony_ci						reqctx->txqidx) &&
14368c2ecf20Sopenharmony_ci		(!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG))))
14378c2ecf20Sopenharmony_ci			return -ENOSPC;
14388c2ecf20Sopenharmony_ci	err = process_cipher(req, u_ctx->lldi.rxq_ids[reqctx->rxqidx],
14398c2ecf20Sopenharmony_ci			     &skb, CHCR_DECRYPT_OP);
14408c2ecf20Sopenharmony_ci	if (err || !skb)
14418c2ecf20Sopenharmony_ci		return err;
14428c2ecf20Sopenharmony_ci	skb->dev = u_ctx->lldi.ports[0];
14438c2ecf20Sopenharmony_ci	set_wr_txq(skb, CPL_PRIORITY_DATA, reqctx->txqidx);
14448c2ecf20Sopenharmony_ci	chcr_send_wr(skb);
14458c2ecf20Sopenharmony_ci	return -EINPROGRESS;
14468c2ecf20Sopenharmony_ci}
14478c2ecf20Sopenharmony_cistatic int chcr_device_init(struct chcr_context *ctx)
14488c2ecf20Sopenharmony_ci{
14498c2ecf20Sopenharmony_ci	struct uld_ctx *u_ctx = NULL;
14508c2ecf20Sopenharmony_ci	int txq_perchan, ntxq;
14518c2ecf20Sopenharmony_ci	int err = 0, rxq_perchan;
14528c2ecf20Sopenharmony_ci
14538c2ecf20Sopenharmony_ci	if (!ctx->dev) {
14548c2ecf20Sopenharmony_ci		u_ctx = assign_chcr_device();
14558c2ecf20Sopenharmony_ci		if (!u_ctx) {
14568c2ecf20Sopenharmony_ci			err = -ENXIO;
14578c2ecf20Sopenharmony_ci			pr_err("chcr device assignment fails\n");
14588c2ecf20Sopenharmony_ci			goto out;
14598c2ecf20Sopenharmony_ci		}
14608c2ecf20Sopenharmony_ci		ctx->dev = &u_ctx->dev;
14618c2ecf20Sopenharmony_ci		ntxq = u_ctx->lldi.ntxq;
14628c2ecf20Sopenharmony_ci		rxq_perchan = u_ctx->lldi.nrxq / u_ctx->lldi.nchan;
14638c2ecf20Sopenharmony_ci		txq_perchan = ntxq / u_ctx->lldi.nchan;
14648c2ecf20Sopenharmony_ci		ctx->ntxq = ntxq;
14658c2ecf20Sopenharmony_ci		ctx->nrxq = u_ctx->lldi.nrxq;
14668c2ecf20Sopenharmony_ci		ctx->rxq_perchan = rxq_perchan;
14678c2ecf20Sopenharmony_ci		ctx->txq_perchan = txq_perchan;
14688c2ecf20Sopenharmony_ci	}
14698c2ecf20Sopenharmony_ciout:
14708c2ecf20Sopenharmony_ci	return err;
14718c2ecf20Sopenharmony_ci}
14728c2ecf20Sopenharmony_ci
14738c2ecf20Sopenharmony_cistatic int chcr_init_tfm(struct crypto_skcipher *tfm)
14748c2ecf20Sopenharmony_ci{
14758c2ecf20Sopenharmony_ci	struct skcipher_alg *alg = crypto_skcipher_alg(tfm);
14768c2ecf20Sopenharmony_ci	struct chcr_context *ctx = crypto_skcipher_ctx(tfm);
14778c2ecf20Sopenharmony_ci	struct ablk_ctx *ablkctx = ABLK_CTX(ctx);
14788c2ecf20Sopenharmony_ci
14798c2ecf20Sopenharmony_ci	ablkctx->sw_cipher = crypto_alloc_skcipher(alg->base.cra_name, 0,
14808c2ecf20Sopenharmony_ci				CRYPTO_ALG_NEED_FALLBACK);
14818c2ecf20Sopenharmony_ci	if (IS_ERR(ablkctx->sw_cipher)) {
14828c2ecf20Sopenharmony_ci		pr_err("failed to allocate fallback for %s\n", alg->base.cra_name);
14838c2ecf20Sopenharmony_ci		return PTR_ERR(ablkctx->sw_cipher);
14848c2ecf20Sopenharmony_ci	}
14858c2ecf20Sopenharmony_ci	init_completion(&ctx->cbc_aes_aio_done);
14868c2ecf20Sopenharmony_ci	crypto_skcipher_set_reqsize(tfm, sizeof(struct chcr_skcipher_req_ctx) +
14878c2ecf20Sopenharmony_ci					 crypto_skcipher_reqsize(ablkctx->sw_cipher));
14888c2ecf20Sopenharmony_ci
14898c2ecf20Sopenharmony_ci	return chcr_device_init(ctx);
14908c2ecf20Sopenharmony_ci}
14918c2ecf20Sopenharmony_ci
14928c2ecf20Sopenharmony_cistatic int chcr_rfc3686_init(struct crypto_skcipher *tfm)
14938c2ecf20Sopenharmony_ci{
14948c2ecf20Sopenharmony_ci	struct skcipher_alg *alg = crypto_skcipher_alg(tfm);
14958c2ecf20Sopenharmony_ci	struct chcr_context *ctx = crypto_skcipher_ctx(tfm);
14968c2ecf20Sopenharmony_ci	struct ablk_ctx *ablkctx = ABLK_CTX(ctx);
14978c2ecf20Sopenharmony_ci
14988c2ecf20Sopenharmony_ci	/*RFC3686 initialises IV counter value to 1, rfc3686(ctr(aes))
14998c2ecf20Sopenharmony_ci	 * cannot be used as fallback in chcr_handle_cipher_response
15008c2ecf20Sopenharmony_ci	 */
15018c2ecf20Sopenharmony_ci	ablkctx->sw_cipher = crypto_alloc_skcipher("ctr(aes)", 0,
15028c2ecf20Sopenharmony_ci				CRYPTO_ALG_NEED_FALLBACK);
15038c2ecf20Sopenharmony_ci	if (IS_ERR(ablkctx->sw_cipher)) {
15048c2ecf20Sopenharmony_ci		pr_err("failed to allocate fallback for %s\n", alg->base.cra_name);
15058c2ecf20Sopenharmony_ci		return PTR_ERR(ablkctx->sw_cipher);
15068c2ecf20Sopenharmony_ci	}
15078c2ecf20Sopenharmony_ci	crypto_skcipher_set_reqsize(tfm, sizeof(struct chcr_skcipher_req_ctx) +
15088c2ecf20Sopenharmony_ci				    crypto_skcipher_reqsize(ablkctx->sw_cipher));
15098c2ecf20Sopenharmony_ci	return chcr_device_init(ctx);
15108c2ecf20Sopenharmony_ci}
15118c2ecf20Sopenharmony_ci
15128c2ecf20Sopenharmony_ci
15138c2ecf20Sopenharmony_cistatic void chcr_exit_tfm(struct crypto_skcipher *tfm)
15148c2ecf20Sopenharmony_ci{
15158c2ecf20Sopenharmony_ci	struct chcr_context *ctx = crypto_skcipher_ctx(tfm);
15168c2ecf20Sopenharmony_ci	struct ablk_ctx *ablkctx = ABLK_CTX(ctx);
15178c2ecf20Sopenharmony_ci
15188c2ecf20Sopenharmony_ci	crypto_free_skcipher(ablkctx->sw_cipher);
15198c2ecf20Sopenharmony_ci}
15208c2ecf20Sopenharmony_ci
15218c2ecf20Sopenharmony_cistatic int get_alg_config(struct algo_param *params,
15228c2ecf20Sopenharmony_ci			  unsigned int auth_size)
15238c2ecf20Sopenharmony_ci{
15248c2ecf20Sopenharmony_ci	switch (auth_size) {
15258c2ecf20Sopenharmony_ci	case SHA1_DIGEST_SIZE:
15268c2ecf20Sopenharmony_ci		params->mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_160;
15278c2ecf20Sopenharmony_ci		params->auth_mode = CHCR_SCMD_AUTH_MODE_SHA1;
15288c2ecf20Sopenharmony_ci		params->result_size = SHA1_DIGEST_SIZE;
15298c2ecf20Sopenharmony_ci		break;
15308c2ecf20Sopenharmony_ci	case SHA224_DIGEST_SIZE:
15318c2ecf20Sopenharmony_ci		params->mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_256;
15328c2ecf20Sopenharmony_ci		params->auth_mode = CHCR_SCMD_AUTH_MODE_SHA224;
15338c2ecf20Sopenharmony_ci		params->result_size = SHA256_DIGEST_SIZE;
15348c2ecf20Sopenharmony_ci		break;
15358c2ecf20Sopenharmony_ci	case SHA256_DIGEST_SIZE:
15368c2ecf20Sopenharmony_ci		params->mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_256;
15378c2ecf20Sopenharmony_ci		params->auth_mode = CHCR_SCMD_AUTH_MODE_SHA256;
15388c2ecf20Sopenharmony_ci		params->result_size = SHA256_DIGEST_SIZE;
15398c2ecf20Sopenharmony_ci		break;
15408c2ecf20Sopenharmony_ci	case SHA384_DIGEST_SIZE:
15418c2ecf20Sopenharmony_ci		params->mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_512;
15428c2ecf20Sopenharmony_ci		params->auth_mode = CHCR_SCMD_AUTH_MODE_SHA512_384;
15438c2ecf20Sopenharmony_ci		params->result_size = SHA512_DIGEST_SIZE;
15448c2ecf20Sopenharmony_ci		break;
15458c2ecf20Sopenharmony_ci	case SHA512_DIGEST_SIZE:
15468c2ecf20Sopenharmony_ci		params->mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_512;
15478c2ecf20Sopenharmony_ci		params->auth_mode = CHCR_SCMD_AUTH_MODE_SHA512_512;
15488c2ecf20Sopenharmony_ci		params->result_size = SHA512_DIGEST_SIZE;
15498c2ecf20Sopenharmony_ci		break;
15508c2ecf20Sopenharmony_ci	default:
15518c2ecf20Sopenharmony_ci		pr_err("ERROR, unsupported digest size\n");
15528c2ecf20Sopenharmony_ci		return -EINVAL;
15538c2ecf20Sopenharmony_ci	}
15548c2ecf20Sopenharmony_ci	return 0;
15558c2ecf20Sopenharmony_ci}
15568c2ecf20Sopenharmony_ci
15578c2ecf20Sopenharmony_cistatic inline void chcr_free_shash(struct crypto_shash *base_hash)
15588c2ecf20Sopenharmony_ci{
15598c2ecf20Sopenharmony_ci		crypto_free_shash(base_hash);
15608c2ecf20Sopenharmony_ci}
15618c2ecf20Sopenharmony_ci
15628c2ecf20Sopenharmony_ci/**
15638c2ecf20Sopenharmony_ci *	create_hash_wr - Create hash work request
15648c2ecf20Sopenharmony_ci *	@req - Cipher req base
15658c2ecf20Sopenharmony_ci */
15668c2ecf20Sopenharmony_cistatic struct sk_buff *create_hash_wr(struct ahash_request *req,
15678c2ecf20Sopenharmony_ci				      struct hash_wr_param *param)
15688c2ecf20Sopenharmony_ci{
15698c2ecf20Sopenharmony_ci	struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req);
15708c2ecf20Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
15718c2ecf20Sopenharmony_ci	struct chcr_context *ctx = h_ctx(tfm);
15728c2ecf20Sopenharmony_ci	struct hmac_ctx *hmacctx = HMAC_CTX(ctx);
15738c2ecf20Sopenharmony_ci	struct sk_buff *skb = NULL;
15748c2ecf20Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(ctx);
15758c2ecf20Sopenharmony_ci	struct chcr_wr *chcr_req;
15768c2ecf20Sopenharmony_ci	struct ulptx_sgl *ulptx;
15778c2ecf20Sopenharmony_ci	unsigned int nents = 0, transhdr_len;
15788c2ecf20Sopenharmony_ci	unsigned int temp = 0;
15798c2ecf20Sopenharmony_ci	gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
15808c2ecf20Sopenharmony_ci		GFP_ATOMIC;
15818c2ecf20Sopenharmony_ci	struct adapter *adap = padap(h_ctx(tfm)->dev);
15828c2ecf20Sopenharmony_ci	int error = 0;
15838c2ecf20Sopenharmony_ci	unsigned int rx_channel_id = req_ctx->rxqidx / ctx->rxq_perchan;
15848c2ecf20Sopenharmony_ci
15858c2ecf20Sopenharmony_ci	rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]);
15868c2ecf20Sopenharmony_ci	transhdr_len = HASH_TRANSHDR_SIZE(param->kctx_len);
15878c2ecf20Sopenharmony_ci	req_ctx->hctx_wr.imm = (transhdr_len + param->bfr_len +
15888c2ecf20Sopenharmony_ci				param->sg_len) <= SGE_MAX_WR_LEN;
15898c2ecf20Sopenharmony_ci	nents = sg_nents_xlen(req_ctx->hctx_wr.srcsg, param->sg_len,
15908c2ecf20Sopenharmony_ci		      CHCR_SRC_SG_SIZE, req_ctx->hctx_wr.src_ofst);
15918c2ecf20Sopenharmony_ci	nents += param->bfr_len ? 1 : 0;
15928c2ecf20Sopenharmony_ci	transhdr_len += req_ctx->hctx_wr.imm ? roundup(param->bfr_len +
15938c2ecf20Sopenharmony_ci				param->sg_len, 16) : (sgl_len(nents) * 8);
15948c2ecf20Sopenharmony_ci	transhdr_len = roundup(transhdr_len, 16);
15958c2ecf20Sopenharmony_ci
15968c2ecf20Sopenharmony_ci	skb = alloc_skb(transhdr_len, flags);
15978c2ecf20Sopenharmony_ci	if (!skb)
15988c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
15998c2ecf20Sopenharmony_ci	chcr_req = __skb_put_zero(skb, transhdr_len);
16008c2ecf20Sopenharmony_ci
16018c2ecf20Sopenharmony_ci	chcr_req->sec_cpl.op_ivinsrtofst =
16028c2ecf20Sopenharmony_ci		FILL_SEC_CPL_OP_IVINSR(rx_channel_id, 2, 0);
16038c2ecf20Sopenharmony_ci
16048c2ecf20Sopenharmony_ci	chcr_req->sec_cpl.pldlen = htonl(param->bfr_len + param->sg_len);
16058c2ecf20Sopenharmony_ci
16068c2ecf20Sopenharmony_ci	chcr_req->sec_cpl.aadstart_cipherstop_hi =
16078c2ecf20Sopenharmony_ci		FILL_SEC_CPL_CIPHERSTOP_HI(0, 0, 0, 0);
16088c2ecf20Sopenharmony_ci	chcr_req->sec_cpl.cipherstop_lo_authinsert =
16098c2ecf20Sopenharmony_ci		FILL_SEC_CPL_AUTHINSERT(0, 1, 0, 0);
16108c2ecf20Sopenharmony_ci	chcr_req->sec_cpl.seqno_numivs =
16118c2ecf20Sopenharmony_ci		FILL_SEC_CPL_SCMD0_SEQNO(0, 0, 0, param->alg_prm.auth_mode,
16128c2ecf20Sopenharmony_ci					 param->opad_needed, 0);
16138c2ecf20Sopenharmony_ci
16148c2ecf20Sopenharmony_ci	chcr_req->sec_cpl.ivgen_hdrlen =
16158c2ecf20Sopenharmony_ci		FILL_SEC_CPL_IVGEN_HDRLEN(param->last, param->more, 0, 1, 0, 0);
16168c2ecf20Sopenharmony_ci
16178c2ecf20Sopenharmony_ci	memcpy(chcr_req->key_ctx.key, req_ctx->partial_hash,
16188c2ecf20Sopenharmony_ci	       param->alg_prm.result_size);
16198c2ecf20Sopenharmony_ci
16208c2ecf20Sopenharmony_ci	if (param->opad_needed)
16218c2ecf20Sopenharmony_ci		memcpy(chcr_req->key_ctx.key +
16228c2ecf20Sopenharmony_ci		       ((param->alg_prm.result_size <= 32) ? 32 :
16238c2ecf20Sopenharmony_ci			CHCR_HASH_MAX_DIGEST_SIZE),
16248c2ecf20Sopenharmony_ci		       hmacctx->opad, param->alg_prm.result_size);
16258c2ecf20Sopenharmony_ci
16268c2ecf20Sopenharmony_ci	chcr_req->key_ctx.ctx_hdr = FILL_KEY_CTX_HDR(CHCR_KEYCTX_NO_KEY,
16278c2ecf20Sopenharmony_ci					    param->alg_prm.mk_size, 0,
16288c2ecf20Sopenharmony_ci					    param->opad_needed,
16298c2ecf20Sopenharmony_ci					    ((param->kctx_len +
16308c2ecf20Sopenharmony_ci					     sizeof(chcr_req->key_ctx)) >> 4));
16318c2ecf20Sopenharmony_ci	chcr_req->sec_cpl.scmd1 = cpu_to_be64((u64)param->scmd1);
16328c2ecf20Sopenharmony_ci	ulptx = (struct ulptx_sgl *)((u8 *)(chcr_req + 1) + param->kctx_len +
16338c2ecf20Sopenharmony_ci				     DUMMY_BYTES);
16348c2ecf20Sopenharmony_ci	if (param->bfr_len != 0) {
16358c2ecf20Sopenharmony_ci		req_ctx->hctx_wr.dma_addr =
16368c2ecf20Sopenharmony_ci			dma_map_single(&u_ctx->lldi.pdev->dev, req_ctx->reqbfr,
16378c2ecf20Sopenharmony_ci				       param->bfr_len, DMA_TO_DEVICE);
16388c2ecf20Sopenharmony_ci		if (dma_mapping_error(&u_ctx->lldi.pdev->dev,
16398c2ecf20Sopenharmony_ci				       req_ctx->hctx_wr. dma_addr)) {
16408c2ecf20Sopenharmony_ci			error = -ENOMEM;
16418c2ecf20Sopenharmony_ci			goto err;
16428c2ecf20Sopenharmony_ci		}
16438c2ecf20Sopenharmony_ci		req_ctx->hctx_wr.dma_len = param->bfr_len;
16448c2ecf20Sopenharmony_ci	} else {
16458c2ecf20Sopenharmony_ci		req_ctx->hctx_wr.dma_addr = 0;
16468c2ecf20Sopenharmony_ci	}
16478c2ecf20Sopenharmony_ci	chcr_add_hash_src_ent(req, ulptx, param);
16488c2ecf20Sopenharmony_ci	/* Request upto max wr size */
16498c2ecf20Sopenharmony_ci	temp = param->kctx_len + DUMMY_BYTES + (req_ctx->hctx_wr.imm ?
16508c2ecf20Sopenharmony_ci				(param->sg_len + param->bfr_len) : 0);
16518c2ecf20Sopenharmony_ci	atomic_inc(&adap->chcr_stats.digest_rqst);
16528c2ecf20Sopenharmony_ci	create_wreq(h_ctx(tfm), chcr_req, &req->base, req_ctx->hctx_wr.imm,
16538c2ecf20Sopenharmony_ci		    param->hash_size, transhdr_len,
16548c2ecf20Sopenharmony_ci		    temp,  0);
16558c2ecf20Sopenharmony_ci	req_ctx->hctx_wr.skb = skb;
16568c2ecf20Sopenharmony_ci	return skb;
16578c2ecf20Sopenharmony_cierr:
16588c2ecf20Sopenharmony_ci	kfree_skb(skb);
16598c2ecf20Sopenharmony_ci	return  ERR_PTR(error);
16608c2ecf20Sopenharmony_ci}
16618c2ecf20Sopenharmony_ci
16628c2ecf20Sopenharmony_cistatic int chcr_ahash_update(struct ahash_request *req)
16638c2ecf20Sopenharmony_ci{
16648c2ecf20Sopenharmony_ci	struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req);
16658c2ecf20Sopenharmony_ci	struct crypto_ahash *rtfm = crypto_ahash_reqtfm(req);
16668c2ecf20Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(h_ctx(rtfm));
16678c2ecf20Sopenharmony_ci	struct chcr_context *ctx = h_ctx(rtfm);
16688c2ecf20Sopenharmony_ci	struct chcr_dev *dev = h_ctx(rtfm)->dev;
16698c2ecf20Sopenharmony_ci	struct sk_buff *skb;
16708c2ecf20Sopenharmony_ci	u8 remainder = 0, bs;
16718c2ecf20Sopenharmony_ci	unsigned int nbytes = req->nbytes;
16728c2ecf20Sopenharmony_ci	struct hash_wr_param params;
16738c2ecf20Sopenharmony_ci	int error;
16748c2ecf20Sopenharmony_ci	unsigned int cpu;
16758c2ecf20Sopenharmony_ci
16768c2ecf20Sopenharmony_ci	cpu = get_cpu();
16778c2ecf20Sopenharmony_ci	req_ctx->txqidx = cpu % ctx->ntxq;
16788c2ecf20Sopenharmony_ci	req_ctx->rxqidx = cpu % ctx->nrxq;
16798c2ecf20Sopenharmony_ci	put_cpu();
16808c2ecf20Sopenharmony_ci
16818c2ecf20Sopenharmony_ci	bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(rtfm));
16828c2ecf20Sopenharmony_ci
16838c2ecf20Sopenharmony_ci	if (nbytes + req_ctx->reqlen >= bs) {
16848c2ecf20Sopenharmony_ci		remainder = (nbytes + req_ctx->reqlen) % bs;
16858c2ecf20Sopenharmony_ci		nbytes = nbytes + req_ctx->reqlen - remainder;
16868c2ecf20Sopenharmony_ci	} else {
16878c2ecf20Sopenharmony_ci		sg_pcopy_to_buffer(req->src, sg_nents(req->src), req_ctx->reqbfr
16888c2ecf20Sopenharmony_ci				   + req_ctx->reqlen, nbytes, 0);
16898c2ecf20Sopenharmony_ci		req_ctx->reqlen += nbytes;
16908c2ecf20Sopenharmony_ci		return 0;
16918c2ecf20Sopenharmony_ci	}
16928c2ecf20Sopenharmony_ci	error = chcr_inc_wrcount(dev);
16938c2ecf20Sopenharmony_ci	if (error)
16948c2ecf20Sopenharmony_ci		return -ENXIO;
16958c2ecf20Sopenharmony_ci	/* Detach state for CHCR means lldi or padap is freed. Increasing
16968c2ecf20Sopenharmony_ci	 * inflight count for dev guarantees that lldi and padap is valid
16978c2ecf20Sopenharmony_ci	 */
16988c2ecf20Sopenharmony_ci	if (unlikely(cxgb4_is_crypto_q_full(u_ctx->lldi.ports[0],
16998c2ecf20Sopenharmony_ci						req_ctx->txqidx) &&
17008c2ecf20Sopenharmony_ci		(!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)))) {
17018c2ecf20Sopenharmony_ci			error = -ENOSPC;
17028c2ecf20Sopenharmony_ci			goto err;
17038c2ecf20Sopenharmony_ci	}
17048c2ecf20Sopenharmony_ci
17058c2ecf20Sopenharmony_ci	chcr_init_hctx_per_wr(req_ctx);
17068c2ecf20Sopenharmony_ci	error = chcr_hash_dma_map(&u_ctx->lldi.pdev->dev, req);
17078c2ecf20Sopenharmony_ci	if (error) {
17088c2ecf20Sopenharmony_ci		error = -ENOMEM;
17098c2ecf20Sopenharmony_ci		goto err;
17108c2ecf20Sopenharmony_ci	}
17118c2ecf20Sopenharmony_ci	get_alg_config(&params.alg_prm, crypto_ahash_digestsize(rtfm));
17128c2ecf20Sopenharmony_ci	params.kctx_len = roundup(params.alg_prm.result_size, 16);
17138c2ecf20Sopenharmony_ci	params.sg_len = chcr_hash_ent_in_wr(req->src, !!req_ctx->reqlen,
17148c2ecf20Sopenharmony_ci				     HASH_SPACE_LEFT(params.kctx_len), 0);
17158c2ecf20Sopenharmony_ci	if (params.sg_len > req->nbytes)
17168c2ecf20Sopenharmony_ci		params.sg_len = req->nbytes;
17178c2ecf20Sopenharmony_ci	params.sg_len = rounddown(params.sg_len + req_ctx->reqlen, bs) -
17188c2ecf20Sopenharmony_ci			req_ctx->reqlen;
17198c2ecf20Sopenharmony_ci	params.opad_needed = 0;
17208c2ecf20Sopenharmony_ci	params.more = 1;
17218c2ecf20Sopenharmony_ci	params.last = 0;
17228c2ecf20Sopenharmony_ci	params.bfr_len = req_ctx->reqlen;
17238c2ecf20Sopenharmony_ci	params.scmd1 = 0;
17248c2ecf20Sopenharmony_ci	req_ctx->hctx_wr.srcsg = req->src;
17258c2ecf20Sopenharmony_ci
17268c2ecf20Sopenharmony_ci	params.hash_size = params.alg_prm.result_size;
17278c2ecf20Sopenharmony_ci	req_ctx->data_len += params.sg_len + params.bfr_len;
17288c2ecf20Sopenharmony_ci	skb = create_hash_wr(req, &params);
17298c2ecf20Sopenharmony_ci	if (IS_ERR(skb)) {
17308c2ecf20Sopenharmony_ci		error = PTR_ERR(skb);
17318c2ecf20Sopenharmony_ci		goto unmap;
17328c2ecf20Sopenharmony_ci	}
17338c2ecf20Sopenharmony_ci
17348c2ecf20Sopenharmony_ci	req_ctx->hctx_wr.processed += params.sg_len;
17358c2ecf20Sopenharmony_ci	if (remainder) {
17368c2ecf20Sopenharmony_ci		/* Swap buffers */
17378c2ecf20Sopenharmony_ci		swap(req_ctx->reqbfr, req_ctx->skbfr);
17388c2ecf20Sopenharmony_ci		sg_pcopy_to_buffer(req->src, sg_nents(req->src),
17398c2ecf20Sopenharmony_ci				   req_ctx->reqbfr, remainder, req->nbytes -
17408c2ecf20Sopenharmony_ci				   remainder);
17418c2ecf20Sopenharmony_ci	}
17428c2ecf20Sopenharmony_ci	req_ctx->reqlen = remainder;
17438c2ecf20Sopenharmony_ci	skb->dev = u_ctx->lldi.ports[0];
17448c2ecf20Sopenharmony_ci	set_wr_txq(skb, CPL_PRIORITY_DATA, req_ctx->txqidx);
17458c2ecf20Sopenharmony_ci	chcr_send_wr(skb);
17468c2ecf20Sopenharmony_ci	return -EINPROGRESS;
17478c2ecf20Sopenharmony_ciunmap:
17488c2ecf20Sopenharmony_ci	chcr_hash_dma_unmap(&u_ctx->lldi.pdev->dev, req);
17498c2ecf20Sopenharmony_cierr:
17508c2ecf20Sopenharmony_ci	chcr_dec_wrcount(dev);
17518c2ecf20Sopenharmony_ci	return error;
17528c2ecf20Sopenharmony_ci}
17538c2ecf20Sopenharmony_ci
17548c2ecf20Sopenharmony_cistatic void create_last_hash_block(char *bfr_ptr, unsigned int bs, u64 scmd1)
17558c2ecf20Sopenharmony_ci{
17568c2ecf20Sopenharmony_ci	memset(bfr_ptr, 0, bs);
17578c2ecf20Sopenharmony_ci	*bfr_ptr = 0x80;
17588c2ecf20Sopenharmony_ci	if (bs == 64)
17598c2ecf20Sopenharmony_ci		*(__be64 *)(bfr_ptr + 56) = cpu_to_be64(scmd1  << 3);
17608c2ecf20Sopenharmony_ci	else
17618c2ecf20Sopenharmony_ci		*(__be64 *)(bfr_ptr + 120) =  cpu_to_be64(scmd1  << 3);
17628c2ecf20Sopenharmony_ci}
17638c2ecf20Sopenharmony_ci
17648c2ecf20Sopenharmony_cistatic int chcr_ahash_final(struct ahash_request *req)
17658c2ecf20Sopenharmony_ci{
17668c2ecf20Sopenharmony_ci	struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req);
17678c2ecf20Sopenharmony_ci	struct crypto_ahash *rtfm = crypto_ahash_reqtfm(req);
17688c2ecf20Sopenharmony_ci	struct chcr_dev *dev = h_ctx(rtfm)->dev;
17698c2ecf20Sopenharmony_ci	struct hash_wr_param params;
17708c2ecf20Sopenharmony_ci	struct sk_buff *skb;
17718c2ecf20Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(h_ctx(rtfm));
17728c2ecf20Sopenharmony_ci	struct chcr_context *ctx = h_ctx(rtfm);
17738c2ecf20Sopenharmony_ci	u8 bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(rtfm));
17748c2ecf20Sopenharmony_ci	int error;
17758c2ecf20Sopenharmony_ci	unsigned int cpu;
17768c2ecf20Sopenharmony_ci
17778c2ecf20Sopenharmony_ci	cpu = get_cpu();
17788c2ecf20Sopenharmony_ci	req_ctx->txqidx = cpu % ctx->ntxq;
17798c2ecf20Sopenharmony_ci	req_ctx->rxqidx = cpu % ctx->nrxq;
17808c2ecf20Sopenharmony_ci	put_cpu();
17818c2ecf20Sopenharmony_ci
17828c2ecf20Sopenharmony_ci	error = chcr_inc_wrcount(dev);
17838c2ecf20Sopenharmony_ci	if (error)
17848c2ecf20Sopenharmony_ci		return -ENXIO;
17858c2ecf20Sopenharmony_ci
17868c2ecf20Sopenharmony_ci	chcr_init_hctx_per_wr(req_ctx);
17878c2ecf20Sopenharmony_ci	if (is_hmac(crypto_ahash_tfm(rtfm)))
17888c2ecf20Sopenharmony_ci		params.opad_needed = 1;
17898c2ecf20Sopenharmony_ci	else
17908c2ecf20Sopenharmony_ci		params.opad_needed = 0;
17918c2ecf20Sopenharmony_ci	params.sg_len = 0;
17928c2ecf20Sopenharmony_ci	req_ctx->hctx_wr.isfinal = 1;
17938c2ecf20Sopenharmony_ci	get_alg_config(&params.alg_prm, crypto_ahash_digestsize(rtfm));
17948c2ecf20Sopenharmony_ci	params.kctx_len = roundup(params.alg_prm.result_size, 16);
17958c2ecf20Sopenharmony_ci	if (is_hmac(crypto_ahash_tfm(rtfm))) {
17968c2ecf20Sopenharmony_ci		params.opad_needed = 1;
17978c2ecf20Sopenharmony_ci		params.kctx_len *= 2;
17988c2ecf20Sopenharmony_ci	} else {
17998c2ecf20Sopenharmony_ci		params.opad_needed = 0;
18008c2ecf20Sopenharmony_ci	}
18018c2ecf20Sopenharmony_ci
18028c2ecf20Sopenharmony_ci	req_ctx->hctx_wr.result = 1;
18038c2ecf20Sopenharmony_ci	params.bfr_len = req_ctx->reqlen;
18048c2ecf20Sopenharmony_ci	req_ctx->data_len += params.bfr_len + params.sg_len;
18058c2ecf20Sopenharmony_ci	req_ctx->hctx_wr.srcsg = req->src;
18068c2ecf20Sopenharmony_ci	if (req_ctx->reqlen == 0) {
18078c2ecf20Sopenharmony_ci		create_last_hash_block(req_ctx->reqbfr, bs, req_ctx->data_len);
18088c2ecf20Sopenharmony_ci		params.last = 0;
18098c2ecf20Sopenharmony_ci		params.more = 1;
18108c2ecf20Sopenharmony_ci		params.scmd1 = 0;
18118c2ecf20Sopenharmony_ci		params.bfr_len = bs;
18128c2ecf20Sopenharmony_ci
18138c2ecf20Sopenharmony_ci	} else {
18148c2ecf20Sopenharmony_ci		params.scmd1 = req_ctx->data_len;
18158c2ecf20Sopenharmony_ci		params.last = 1;
18168c2ecf20Sopenharmony_ci		params.more = 0;
18178c2ecf20Sopenharmony_ci	}
18188c2ecf20Sopenharmony_ci	params.hash_size = crypto_ahash_digestsize(rtfm);
18198c2ecf20Sopenharmony_ci	skb = create_hash_wr(req, &params);
18208c2ecf20Sopenharmony_ci	if (IS_ERR(skb)) {
18218c2ecf20Sopenharmony_ci		error = PTR_ERR(skb);
18228c2ecf20Sopenharmony_ci		goto err;
18238c2ecf20Sopenharmony_ci	}
18248c2ecf20Sopenharmony_ci	req_ctx->reqlen = 0;
18258c2ecf20Sopenharmony_ci	skb->dev = u_ctx->lldi.ports[0];
18268c2ecf20Sopenharmony_ci	set_wr_txq(skb, CPL_PRIORITY_DATA, req_ctx->txqidx);
18278c2ecf20Sopenharmony_ci	chcr_send_wr(skb);
18288c2ecf20Sopenharmony_ci	return -EINPROGRESS;
18298c2ecf20Sopenharmony_cierr:
18308c2ecf20Sopenharmony_ci	chcr_dec_wrcount(dev);
18318c2ecf20Sopenharmony_ci	return error;
18328c2ecf20Sopenharmony_ci}
18338c2ecf20Sopenharmony_ci
18348c2ecf20Sopenharmony_cistatic int chcr_ahash_finup(struct ahash_request *req)
18358c2ecf20Sopenharmony_ci{
18368c2ecf20Sopenharmony_ci	struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req);
18378c2ecf20Sopenharmony_ci	struct crypto_ahash *rtfm = crypto_ahash_reqtfm(req);
18388c2ecf20Sopenharmony_ci	struct chcr_dev *dev = h_ctx(rtfm)->dev;
18398c2ecf20Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(h_ctx(rtfm));
18408c2ecf20Sopenharmony_ci	struct chcr_context *ctx = h_ctx(rtfm);
18418c2ecf20Sopenharmony_ci	struct sk_buff *skb;
18428c2ecf20Sopenharmony_ci	struct hash_wr_param params;
18438c2ecf20Sopenharmony_ci	u8  bs;
18448c2ecf20Sopenharmony_ci	int error;
18458c2ecf20Sopenharmony_ci	unsigned int cpu;
18468c2ecf20Sopenharmony_ci
18478c2ecf20Sopenharmony_ci	cpu = get_cpu();
18488c2ecf20Sopenharmony_ci	req_ctx->txqidx = cpu % ctx->ntxq;
18498c2ecf20Sopenharmony_ci	req_ctx->rxqidx = cpu % ctx->nrxq;
18508c2ecf20Sopenharmony_ci	put_cpu();
18518c2ecf20Sopenharmony_ci
18528c2ecf20Sopenharmony_ci	bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(rtfm));
18538c2ecf20Sopenharmony_ci	error = chcr_inc_wrcount(dev);
18548c2ecf20Sopenharmony_ci	if (error)
18558c2ecf20Sopenharmony_ci		return -ENXIO;
18568c2ecf20Sopenharmony_ci
18578c2ecf20Sopenharmony_ci	if (unlikely(cxgb4_is_crypto_q_full(u_ctx->lldi.ports[0],
18588c2ecf20Sopenharmony_ci						req_ctx->txqidx) &&
18598c2ecf20Sopenharmony_ci		(!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)))) {
18608c2ecf20Sopenharmony_ci			error = -ENOSPC;
18618c2ecf20Sopenharmony_ci			goto err;
18628c2ecf20Sopenharmony_ci	}
18638c2ecf20Sopenharmony_ci	chcr_init_hctx_per_wr(req_ctx);
18648c2ecf20Sopenharmony_ci	error = chcr_hash_dma_map(&u_ctx->lldi.pdev->dev, req);
18658c2ecf20Sopenharmony_ci	if (error) {
18668c2ecf20Sopenharmony_ci		error = -ENOMEM;
18678c2ecf20Sopenharmony_ci		goto err;
18688c2ecf20Sopenharmony_ci	}
18698c2ecf20Sopenharmony_ci
18708c2ecf20Sopenharmony_ci	get_alg_config(&params.alg_prm, crypto_ahash_digestsize(rtfm));
18718c2ecf20Sopenharmony_ci	params.kctx_len = roundup(params.alg_prm.result_size, 16);
18728c2ecf20Sopenharmony_ci	if (is_hmac(crypto_ahash_tfm(rtfm))) {
18738c2ecf20Sopenharmony_ci		params.kctx_len *= 2;
18748c2ecf20Sopenharmony_ci		params.opad_needed = 1;
18758c2ecf20Sopenharmony_ci	} else {
18768c2ecf20Sopenharmony_ci		params.opad_needed = 0;
18778c2ecf20Sopenharmony_ci	}
18788c2ecf20Sopenharmony_ci
18798c2ecf20Sopenharmony_ci	params.sg_len = chcr_hash_ent_in_wr(req->src, !!req_ctx->reqlen,
18808c2ecf20Sopenharmony_ci				    HASH_SPACE_LEFT(params.kctx_len), 0);
18818c2ecf20Sopenharmony_ci	if (params.sg_len < req->nbytes) {
18828c2ecf20Sopenharmony_ci		if (is_hmac(crypto_ahash_tfm(rtfm))) {
18838c2ecf20Sopenharmony_ci			params.kctx_len /= 2;
18848c2ecf20Sopenharmony_ci			params.opad_needed = 0;
18858c2ecf20Sopenharmony_ci		}
18868c2ecf20Sopenharmony_ci		params.last = 0;
18878c2ecf20Sopenharmony_ci		params.more = 1;
18888c2ecf20Sopenharmony_ci		params.sg_len = rounddown(params.sg_len + req_ctx->reqlen, bs)
18898c2ecf20Sopenharmony_ci					- req_ctx->reqlen;
18908c2ecf20Sopenharmony_ci		params.hash_size = params.alg_prm.result_size;
18918c2ecf20Sopenharmony_ci		params.scmd1 = 0;
18928c2ecf20Sopenharmony_ci	} else {
18938c2ecf20Sopenharmony_ci		params.last = 1;
18948c2ecf20Sopenharmony_ci		params.more = 0;
18958c2ecf20Sopenharmony_ci		params.sg_len = req->nbytes;
18968c2ecf20Sopenharmony_ci		params.hash_size = crypto_ahash_digestsize(rtfm);
18978c2ecf20Sopenharmony_ci		params.scmd1 = req_ctx->data_len + req_ctx->reqlen +
18988c2ecf20Sopenharmony_ci				params.sg_len;
18998c2ecf20Sopenharmony_ci	}
19008c2ecf20Sopenharmony_ci	params.bfr_len = req_ctx->reqlen;
19018c2ecf20Sopenharmony_ci	req_ctx->data_len += params.bfr_len + params.sg_len;
19028c2ecf20Sopenharmony_ci	req_ctx->hctx_wr.result = 1;
19038c2ecf20Sopenharmony_ci	req_ctx->hctx_wr.srcsg = req->src;
19048c2ecf20Sopenharmony_ci	if ((req_ctx->reqlen + req->nbytes) == 0) {
19058c2ecf20Sopenharmony_ci		create_last_hash_block(req_ctx->reqbfr, bs, req_ctx->data_len);
19068c2ecf20Sopenharmony_ci		params.last = 0;
19078c2ecf20Sopenharmony_ci		params.more = 1;
19088c2ecf20Sopenharmony_ci		params.scmd1 = 0;
19098c2ecf20Sopenharmony_ci		params.bfr_len = bs;
19108c2ecf20Sopenharmony_ci	}
19118c2ecf20Sopenharmony_ci	skb = create_hash_wr(req, &params);
19128c2ecf20Sopenharmony_ci	if (IS_ERR(skb)) {
19138c2ecf20Sopenharmony_ci		error = PTR_ERR(skb);
19148c2ecf20Sopenharmony_ci		goto unmap;
19158c2ecf20Sopenharmony_ci	}
19168c2ecf20Sopenharmony_ci	req_ctx->reqlen = 0;
19178c2ecf20Sopenharmony_ci	req_ctx->hctx_wr.processed += params.sg_len;
19188c2ecf20Sopenharmony_ci	skb->dev = u_ctx->lldi.ports[0];
19198c2ecf20Sopenharmony_ci	set_wr_txq(skb, CPL_PRIORITY_DATA, req_ctx->txqidx);
19208c2ecf20Sopenharmony_ci	chcr_send_wr(skb);
19218c2ecf20Sopenharmony_ci	return -EINPROGRESS;
19228c2ecf20Sopenharmony_ciunmap:
19238c2ecf20Sopenharmony_ci	chcr_hash_dma_unmap(&u_ctx->lldi.pdev->dev, req);
19248c2ecf20Sopenharmony_cierr:
19258c2ecf20Sopenharmony_ci	chcr_dec_wrcount(dev);
19268c2ecf20Sopenharmony_ci	return error;
19278c2ecf20Sopenharmony_ci}
19288c2ecf20Sopenharmony_ci
19298c2ecf20Sopenharmony_cistatic int chcr_ahash_digest(struct ahash_request *req)
19308c2ecf20Sopenharmony_ci{
19318c2ecf20Sopenharmony_ci	struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req);
19328c2ecf20Sopenharmony_ci	struct crypto_ahash *rtfm = crypto_ahash_reqtfm(req);
19338c2ecf20Sopenharmony_ci	struct chcr_dev *dev = h_ctx(rtfm)->dev;
19348c2ecf20Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(h_ctx(rtfm));
19358c2ecf20Sopenharmony_ci	struct chcr_context *ctx = h_ctx(rtfm);
19368c2ecf20Sopenharmony_ci	struct sk_buff *skb;
19378c2ecf20Sopenharmony_ci	struct hash_wr_param params;
19388c2ecf20Sopenharmony_ci	u8  bs;
19398c2ecf20Sopenharmony_ci	int error;
19408c2ecf20Sopenharmony_ci	unsigned int cpu;
19418c2ecf20Sopenharmony_ci
19428c2ecf20Sopenharmony_ci	cpu = get_cpu();
19438c2ecf20Sopenharmony_ci	req_ctx->txqidx = cpu % ctx->ntxq;
19448c2ecf20Sopenharmony_ci	req_ctx->rxqidx = cpu % ctx->nrxq;
19458c2ecf20Sopenharmony_ci	put_cpu();
19468c2ecf20Sopenharmony_ci
19478c2ecf20Sopenharmony_ci	rtfm->init(req);
19488c2ecf20Sopenharmony_ci	bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(rtfm));
19498c2ecf20Sopenharmony_ci	error = chcr_inc_wrcount(dev);
19508c2ecf20Sopenharmony_ci	if (error)
19518c2ecf20Sopenharmony_ci		return -ENXIO;
19528c2ecf20Sopenharmony_ci
19538c2ecf20Sopenharmony_ci	if (unlikely(cxgb4_is_crypto_q_full(u_ctx->lldi.ports[0],
19548c2ecf20Sopenharmony_ci						req_ctx->txqidx) &&
19558c2ecf20Sopenharmony_ci		(!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)))) {
19568c2ecf20Sopenharmony_ci			error = -ENOSPC;
19578c2ecf20Sopenharmony_ci			goto err;
19588c2ecf20Sopenharmony_ci	}
19598c2ecf20Sopenharmony_ci
19608c2ecf20Sopenharmony_ci	chcr_init_hctx_per_wr(req_ctx);
19618c2ecf20Sopenharmony_ci	error = chcr_hash_dma_map(&u_ctx->lldi.pdev->dev, req);
19628c2ecf20Sopenharmony_ci	if (error) {
19638c2ecf20Sopenharmony_ci		error = -ENOMEM;
19648c2ecf20Sopenharmony_ci		goto err;
19658c2ecf20Sopenharmony_ci	}
19668c2ecf20Sopenharmony_ci
19678c2ecf20Sopenharmony_ci	get_alg_config(&params.alg_prm, crypto_ahash_digestsize(rtfm));
19688c2ecf20Sopenharmony_ci	params.kctx_len = roundup(params.alg_prm.result_size, 16);
19698c2ecf20Sopenharmony_ci	if (is_hmac(crypto_ahash_tfm(rtfm))) {
19708c2ecf20Sopenharmony_ci		params.kctx_len *= 2;
19718c2ecf20Sopenharmony_ci		params.opad_needed = 1;
19728c2ecf20Sopenharmony_ci	} else {
19738c2ecf20Sopenharmony_ci		params.opad_needed = 0;
19748c2ecf20Sopenharmony_ci	}
19758c2ecf20Sopenharmony_ci	params.sg_len = chcr_hash_ent_in_wr(req->src, !!req_ctx->reqlen,
19768c2ecf20Sopenharmony_ci				HASH_SPACE_LEFT(params.kctx_len), 0);
19778c2ecf20Sopenharmony_ci	if (params.sg_len < req->nbytes) {
19788c2ecf20Sopenharmony_ci		if (is_hmac(crypto_ahash_tfm(rtfm))) {
19798c2ecf20Sopenharmony_ci			params.kctx_len /= 2;
19808c2ecf20Sopenharmony_ci			params.opad_needed = 0;
19818c2ecf20Sopenharmony_ci		}
19828c2ecf20Sopenharmony_ci		params.last = 0;
19838c2ecf20Sopenharmony_ci		params.more = 1;
19848c2ecf20Sopenharmony_ci		params.scmd1 = 0;
19858c2ecf20Sopenharmony_ci		params.sg_len = rounddown(params.sg_len, bs);
19868c2ecf20Sopenharmony_ci		params.hash_size = params.alg_prm.result_size;
19878c2ecf20Sopenharmony_ci	} else {
19888c2ecf20Sopenharmony_ci		params.sg_len = req->nbytes;
19898c2ecf20Sopenharmony_ci		params.hash_size = crypto_ahash_digestsize(rtfm);
19908c2ecf20Sopenharmony_ci		params.last = 1;
19918c2ecf20Sopenharmony_ci		params.more = 0;
19928c2ecf20Sopenharmony_ci		params.scmd1 = req->nbytes + req_ctx->data_len;
19938c2ecf20Sopenharmony_ci
19948c2ecf20Sopenharmony_ci	}
19958c2ecf20Sopenharmony_ci	params.bfr_len = 0;
19968c2ecf20Sopenharmony_ci	req_ctx->hctx_wr.result = 1;
19978c2ecf20Sopenharmony_ci	req_ctx->hctx_wr.srcsg = req->src;
19988c2ecf20Sopenharmony_ci	req_ctx->data_len += params.bfr_len + params.sg_len;
19998c2ecf20Sopenharmony_ci
20008c2ecf20Sopenharmony_ci	if (req->nbytes == 0) {
20018c2ecf20Sopenharmony_ci		create_last_hash_block(req_ctx->reqbfr, bs, req_ctx->data_len);
20028c2ecf20Sopenharmony_ci		params.more = 1;
20038c2ecf20Sopenharmony_ci		params.bfr_len = bs;
20048c2ecf20Sopenharmony_ci	}
20058c2ecf20Sopenharmony_ci
20068c2ecf20Sopenharmony_ci	skb = create_hash_wr(req, &params);
20078c2ecf20Sopenharmony_ci	if (IS_ERR(skb)) {
20088c2ecf20Sopenharmony_ci		error = PTR_ERR(skb);
20098c2ecf20Sopenharmony_ci		goto unmap;
20108c2ecf20Sopenharmony_ci	}
20118c2ecf20Sopenharmony_ci	req_ctx->hctx_wr.processed += params.sg_len;
20128c2ecf20Sopenharmony_ci	skb->dev = u_ctx->lldi.ports[0];
20138c2ecf20Sopenharmony_ci	set_wr_txq(skb, CPL_PRIORITY_DATA, req_ctx->txqidx);
20148c2ecf20Sopenharmony_ci	chcr_send_wr(skb);
20158c2ecf20Sopenharmony_ci	return -EINPROGRESS;
20168c2ecf20Sopenharmony_ciunmap:
20178c2ecf20Sopenharmony_ci	chcr_hash_dma_unmap(&u_ctx->lldi.pdev->dev, req);
20188c2ecf20Sopenharmony_cierr:
20198c2ecf20Sopenharmony_ci	chcr_dec_wrcount(dev);
20208c2ecf20Sopenharmony_ci	return error;
20218c2ecf20Sopenharmony_ci}
20228c2ecf20Sopenharmony_ci
20238c2ecf20Sopenharmony_cistatic int chcr_ahash_continue(struct ahash_request *req)
20248c2ecf20Sopenharmony_ci{
20258c2ecf20Sopenharmony_ci	struct chcr_ahash_req_ctx *reqctx = ahash_request_ctx(req);
20268c2ecf20Sopenharmony_ci	struct chcr_hctx_per_wr *hctx_wr = &reqctx->hctx_wr;
20278c2ecf20Sopenharmony_ci	struct crypto_ahash *rtfm = crypto_ahash_reqtfm(req);
20288c2ecf20Sopenharmony_ci	struct chcr_context *ctx = h_ctx(rtfm);
20298c2ecf20Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(ctx);
20308c2ecf20Sopenharmony_ci	struct sk_buff *skb;
20318c2ecf20Sopenharmony_ci	struct hash_wr_param params;
20328c2ecf20Sopenharmony_ci	u8  bs;
20338c2ecf20Sopenharmony_ci	int error;
20348c2ecf20Sopenharmony_ci	unsigned int cpu;
20358c2ecf20Sopenharmony_ci
20368c2ecf20Sopenharmony_ci	cpu = get_cpu();
20378c2ecf20Sopenharmony_ci	reqctx->txqidx = cpu % ctx->ntxq;
20388c2ecf20Sopenharmony_ci	reqctx->rxqidx = cpu % ctx->nrxq;
20398c2ecf20Sopenharmony_ci	put_cpu();
20408c2ecf20Sopenharmony_ci
20418c2ecf20Sopenharmony_ci	bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(rtfm));
20428c2ecf20Sopenharmony_ci	get_alg_config(&params.alg_prm, crypto_ahash_digestsize(rtfm));
20438c2ecf20Sopenharmony_ci	params.kctx_len = roundup(params.alg_prm.result_size, 16);
20448c2ecf20Sopenharmony_ci	if (is_hmac(crypto_ahash_tfm(rtfm))) {
20458c2ecf20Sopenharmony_ci		params.kctx_len *= 2;
20468c2ecf20Sopenharmony_ci		params.opad_needed = 1;
20478c2ecf20Sopenharmony_ci	} else {
20488c2ecf20Sopenharmony_ci		params.opad_needed = 0;
20498c2ecf20Sopenharmony_ci	}
20508c2ecf20Sopenharmony_ci	params.sg_len = chcr_hash_ent_in_wr(hctx_wr->srcsg, 0,
20518c2ecf20Sopenharmony_ci					    HASH_SPACE_LEFT(params.kctx_len),
20528c2ecf20Sopenharmony_ci					    hctx_wr->src_ofst);
20538c2ecf20Sopenharmony_ci	if ((params.sg_len + hctx_wr->processed) > req->nbytes)
20548c2ecf20Sopenharmony_ci		params.sg_len = req->nbytes - hctx_wr->processed;
20558c2ecf20Sopenharmony_ci	if (!hctx_wr->result ||
20568c2ecf20Sopenharmony_ci	    ((params.sg_len + hctx_wr->processed) < req->nbytes)) {
20578c2ecf20Sopenharmony_ci		if (is_hmac(crypto_ahash_tfm(rtfm))) {
20588c2ecf20Sopenharmony_ci			params.kctx_len /= 2;
20598c2ecf20Sopenharmony_ci			params.opad_needed = 0;
20608c2ecf20Sopenharmony_ci		}
20618c2ecf20Sopenharmony_ci		params.last = 0;
20628c2ecf20Sopenharmony_ci		params.more = 1;
20638c2ecf20Sopenharmony_ci		params.sg_len = rounddown(params.sg_len, bs);
20648c2ecf20Sopenharmony_ci		params.hash_size = params.alg_prm.result_size;
20658c2ecf20Sopenharmony_ci		params.scmd1 = 0;
20668c2ecf20Sopenharmony_ci	} else {
20678c2ecf20Sopenharmony_ci		params.last = 1;
20688c2ecf20Sopenharmony_ci		params.more = 0;
20698c2ecf20Sopenharmony_ci		params.hash_size = crypto_ahash_digestsize(rtfm);
20708c2ecf20Sopenharmony_ci		params.scmd1 = reqctx->data_len + params.sg_len;
20718c2ecf20Sopenharmony_ci	}
20728c2ecf20Sopenharmony_ci	params.bfr_len = 0;
20738c2ecf20Sopenharmony_ci	reqctx->data_len += params.sg_len;
20748c2ecf20Sopenharmony_ci	skb = create_hash_wr(req, &params);
20758c2ecf20Sopenharmony_ci	if (IS_ERR(skb)) {
20768c2ecf20Sopenharmony_ci		error = PTR_ERR(skb);
20778c2ecf20Sopenharmony_ci		goto err;
20788c2ecf20Sopenharmony_ci	}
20798c2ecf20Sopenharmony_ci	hctx_wr->processed += params.sg_len;
20808c2ecf20Sopenharmony_ci	skb->dev = u_ctx->lldi.ports[0];
20818c2ecf20Sopenharmony_ci	set_wr_txq(skb, CPL_PRIORITY_DATA, reqctx->txqidx);
20828c2ecf20Sopenharmony_ci	chcr_send_wr(skb);
20838c2ecf20Sopenharmony_ci	return 0;
20848c2ecf20Sopenharmony_cierr:
20858c2ecf20Sopenharmony_ci	return error;
20868c2ecf20Sopenharmony_ci}
20878c2ecf20Sopenharmony_ci
20888c2ecf20Sopenharmony_cistatic inline void chcr_handle_ahash_resp(struct ahash_request *req,
20898c2ecf20Sopenharmony_ci					  unsigned char *input,
20908c2ecf20Sopenharmony_ci					  int err)
20918c2ecf20Sopenharmony_ci{
20928c2ecf20Sopenharmony_ci	struct chcr_ahash_req_ctx *reqctx = ahash_request_ctx(req);
20938c2ecf20Sopenharmony_ci	struct chcr_hctx_per_wr *hctx_wr = &reqctx->hctx_wr;
20948c2ecf20Sopenharmony_ci	int digestsize, updated_digestsize;
20958c2ecf20Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
20968c2ecf20Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(h_ctx(tfm));
20978c2ecf20Sopenharmony_ci	struct chcr_dev *dev = h_ctx(tfm)->dev;
20988c2ecf20Sopenharmony_ci
20998c2ecf20Sopenharmony_ci	if (input == NULL)
21008c2ecf20Sopenharmony_ci		goto out;
21018c2ecf20Sopenharmony_ci	digestsize = crypto_ahash_digestsize(crypto_ahash_reqtfm(req));
21028c2ecf20Sopenharmony_ci	updated_digestsize = digestsize;
21038c2ecf20Sopenharmony_ci	if (digestsize == SHA224_DIGEST_SIZE)
21048c2ecf20Sopenharmony_ci		updated_digestsize = SHA256_DIGEST_SIZE;
21058c2ecf20Sopenharmony_ci	else if (digestsize == SHA384_DIGEST_SIZE)
21068c2ecf20Sopenharmony_ci		updated_digestsize = SHA512_DIGEST_SIZE;
21078c2ecf20Sopenharmony_ci
21088c2ecf20Sopenharmony_ci	if (hctx_wr->dma_addr) {
21098c2ecf20Sopenharmony_ci		dma_unmap_single(&u_ctx->lldi.pdev->dev, hctx_wr->dma_addr,
21108c2ecf20Sopenharmony_ci				 hctx_wr->dma_len, DMA_TO_DEVICE);
21118c2ecf20Sopenharmony_ci		hctx_wr->dma_addr = 0;
21128c2ecf20Sopenharmony_ci	}
21138c2ecf20Sopenharmony_ci	if (hctx_wr->isfinal || ((hctx_wr->processed + reqctx->reqlen) ==
21148c2ecf20Sopenharmony_ci				 req->nbytes)) {
21158c2ecf20Sopenharmony_ci		if (hctx_wr->result == 1) {
21168c2ecf20Sopenharmony_ci			hctx_wr->result = 0;
21178c2ecf20Sopenharmony_ci			memcpy(req->result, input + sizeof(struct cpl_fw6_pld),
21188c2ecf20Sopenharmony_ci			       digestsize);
21198c2ecf20Sopenharmony_ci		} else {
21208c2ecf20Sopenharmony_ci			memcpy(reqctx->partial_hash,
21218c2ecf20Sopenharmony_ci			       input + sizeof(struct cpl_fw6_pld),
21228c2ecf20Sopenharmony_ci			       updated_digestsize);
21238c2ecf20Sopenharmony_ci
21248c2ecf20Sopenharmony_ci		}
21258c2ecf20Sopenharmony_ci		goto unmap;
21268c2ecf20Sopenharmony_ci	}
21278c2ecf20Sopenharmony_ci	memcpy(reqctx->partial_hash, input + sizeof(struct cpl_fw6_pld),
21288c2ecf20Sopenharmony_ci	       updated_digestsize);
21298c2ecf20Sopenharmony_ci
21308c2ecf20Sopenharmony_ci	err = chcr_ahash_continue(req);
21318c2ecf20Sopenharmony_ci	if (err)
21328c2ecf20Sopenharmony_ci		goto unmap;
21338c2ecf20Sopenharmony_ci	return;
21348c2ecf20Sopenharmony_ciunmap:
21358c2ecf20Sopenharmony_ci	if (hctx_wr->is_sg_map)
21368c2ecf20Sopenharmony_ci		chcr_hash_dma_unmap(&u_ctx->lldi.pdev->dev, req);
21378c2ecf20Sopenharmony_ci
21388c2ecf20Sopenharmony_ci
21398c2ecf20Sopenharmony_ciout:
21408c2ecf20Sopenharmony_ci	chcr_dec_wrcount(dev);
21418c2ecf20Sopenharmony_ci	req->base.complete(&req->base, err);
21428c2ecf20Sopenharmony_ci}
21438c2ecf20Sopenharmony_ci
21448c2ecf20Sopenharmony_ci/*
21458c2ecf20Sopenharmony_ci *	chcr_handle_resp - Unmap the DMA buffers associated with the request
21468c2ecf20Sopenharmony_ci *	@req: crypto request
21478c2ecf20Sopenharmony_ci */
21488c2ecf20Sopenharmony_ciint chcr_handle_resp(struct crypto_async_request *req, unsigned char *input,
21498c2ecf20Sopenharmony_ci			 int err)
21508c2ecf20Sopenharmony_ci{
21518c2ecf20Sopenharmony_ci	struct crypto_tfm *tfm = req->tfm;
21528c2ecf20Sopenharmony_ci	struct chcr_context *ctx = crypto_tfm_ctx(tfm);
21538c2ecf20Sopenharmony_ci	struct adapter *adap = padap(ctx->dev);
21548c2ecf20Sopenharmony_ci
21558c2ecf20Sopenharmony_ci	switch (tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
21568c2ecf20Sopenharmony_ci	case CRYPTO_ALG_TYPE_AEAD:
21578c2ecf20Sopenharmony_ci		err = chcr_handle_aead_resp(aead_request_cast(req), input, err);
21588c2ecf20Sopenharmony_ci		break;
21598c2ecf20Sopenharmony_ci
21608c2ecf20Sopenharmony_ci	case CRYPTO_ALG_TYPE_SKCIPHER:
21618c2ecf20Sopenharmony_ci		 chcr_handle_cipher_resp(skcipher_request_cast(req),
21628c2ecf20Sopenharmony_ci					       input, err);
21638c2ecf20Sopenharmony_ci		break;
21648c2ecf20Sopenharmony_ci	case CRYPTO_ALG_TYPE_AHASH:
21658c2ecf20Sopenharmony_ci		chcr_handle_ahash_resp(ahash_request_cast(req), input, err);
21668c2ecf20Sopenharmony_ci		}
21678c2ecf20Sopenharmony_ci	atomic_inc(&adap->chcr_stats.complete);
21688c2ecf20Sopenharmony_ci	return err;
21698c2ecf20Sopenharmony_ci}
21708c2ecf20Sopenharmony_cistatic int chcr_ahash_export(struct ahash_request *areq, void *out)
21718c2ecf20Sopenharmony_ci{
21728c2ecf20Sopenharmony_ci	struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
21738c2ecf20Sopenharmony_ci	struct chcr_ahash_req_ctx *state = out;
21748c2ecf20Sopenharmony_ci
21758c2ecf20Sopenharmony_ci	state->reqlen = req_ctx->reqlen;
21768c2ecf20Sopenharmony_ci	state->data_len = req_ctx->data_len;
21778c2ecf20Sopenharmony_ci	memcpy(state->bfr1, req_ctx->reqbfr, req_ctx->reqlen);
21788c2ecf20Sopenharmony_ci	memcpy(state->partial_hash, req_ctx->partial_hash,
21798c2ecf20Sopenharmony_ci	       CHCR_HASH_MAX_DIGEST_SIZE);
21808c2ecf20Sopenharmony_ci	chcr_init_hctx_per_wr(state);
21818c2ecf20Sopenharmony_ci	return 0;
21828c2ecf20Sopenharmony_ci}
21838c2ecf20Sopenharmony_ci
21848c2ecf20Sopenharmony_cistatic int chcr_ahash_import(struct ahash_request *areq, const void *in)
21858c2ecf20Sopenharmony_ci{
21868c2ecf20Sopenharmony_ci	struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
21878c2ecf20Sopenharmony_ci	struct chcr_ahash_req_ctx *state = (struct chcr_ahash_req_ctx *)in;
21888c2ecf20Sopenharmony_ci
21898c2ecf20Sopenharmony_ci	req_ctx->reqlen = state->reqlen;
21908c2ecf20Sopenharmony_ci	req_ctx->data_len = state->data_len;
21918c2ecf20Sopenharmony_ci	req_ctx->reqbfr = req_ctx->bfr1;
21928c2ecf20Sopenharmony_ci	req_ctx->skbfr = req_ctx->bfr2;
21938c2ecf20Sopenharmony_ci	memcpy(req_ctx->bfr1, state->bfr1, CHCR_HASH_MAX_BLOCK_SIZE_128);
21948c2ecf20Sopenharmony_ci	memcpy(req_ctx->partial_hash, state->partial_hash,
21958c2ecf20Sopenharmony_ci	       CHCR_HASH_MAX_DIGEST_SIZE);
21968c2ecf20Sopenharmony_ci	chcr_init_hctx_per_wr(req_ctx);
21978c2ecf20Sopenharmony_ci	return 0;
21988c2ecf20Sopenharmony_ci}
21998c2ecf20Sopenharmony_ci
22008c2ecf20Sopenharmony_cistatic int chcr_ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
22018c2ecf20Sopenharmony_ci			     unsigned int keylen)
22028c2ecf20Sopenharmony_ci{
22038c2ecf20Sopenharmony_ci	struct hmac_ctx *hmacctx = HMAC_CTX(h_ctx(tfm));
22048c2ecf20Sopenharmony_ci	unsigned int digestsize = crypto_ahash_digestsize(tfm);
22058c2ecf20Sopenharmony_ci	unsigned int bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
22068c2ecf20Sopenharmony_ci	unsigned int i, err = 0, updated_digestsize;
22078c2ecf20Sopenharmony_ci
22088c2ecf20Sopenharmony_ci	SHASH_DESC_ON_STACK(shash, hmacctx->base_hash);
22098c2ecf20Sopenharmony_ci
22108c2ecf20Sopenharmony_ci	/* use the key to calculate the ipad and opad. ipad will sent with the
22118c2ecf20Sopenharmony_ci	 * first request's data. opad will be sent with the final hash result
22128c2ecf20Sopenharmony_ci	 * ipad in hmacctx->ipad and opad in hmacctx->opad location
22138c2ecf20Sopenharmony_ci	 */
22148c2ecf20Sopenharmony_ci	shash->tfm = hmacctx->base_hash;
22158c2ecf20Sopenharmony_ci	if (keylen > bs) {
22168c2ecf20Sopenharmony_ci		err = crypto_shash_digest(shash, key, keylen,
22178c2ecf20Sopenharmony_ci					  hmacctx->ipad);
22188c2ecf20Sopenharmony_ci		if (err)
22198c2ecf20Sopenharmony_ci			goto out;
22208c2ecf20Sopenharmony_ci		keylen = digestsize;
22218c2ecf20Sopenharmony_ci	} else {
22228c2ecf20Sopenharmony_ci		memcpy(hmacctx->ipad, key, keylen);
22238c2ecf20Sopenharmony_ci	}
22248c2ecf20Sopenharmony_ci	memset(hmacctx->ipad + keylen, 0, bs - keylen);
22258c2ecf20Sopenharmony_ci	memcpy(hmacctx->opad, hmacctx->ipad, bs);
22268c2ecf20Sopenharmony_ci
22278c2ecf20Sopenharmony_ci	for (i = 0; i < bs / sizeof(int); i++) {
22288c2ecf20Sopenharmony_ci		*((unsigned int *)(&hmacctx->ipad) + i) ^= IPAD_DATA;
22298c2ecf20Sopenharmony_ci		*((unsigned int *)(&hmacctx->opad) + i) ^= OPAD_DATA;
22308c2ecf20Sopenharmony_ci	}
22318c2ecf20Sopenharmony_ci
22328c2ecf20Sopenharmony_ci	updated_digestsize = digestsize;
22338c2ecf20Sopenharmony_ci	if (digestsize == SHA224_DIGEST_SIZE)
22348c2ecf20Sopenharmony_ci		updated_digestsize = SHA256_DIGEST_SIZE;
22358c2ecf20Sopenharmony_ci	else if (digestsize == SHA384_DIGEST_SIZE)
22368c2ecf20Sopenharmony_ci		updated_digestsize = SHA512_DIGEST_SIZE;
22378c2ecf20Sopenharmony_ci	err = chcr_compute_partial_hash(shash, hmacctx->ipad,
22388c2ecf20Sopenharmony_ci					hmacctx->ipad, digestsize);
22398c2ecf20Sopenharmony_ci	if (err)
22408c2ecf20Sopenharmony_ci		goto out;
22418c2ecf20Sopenharmony_ci	chcr_change_order(hmacctx->ipad, updated_digestsize);
22428c2ecf20Sopenharmony_ci
22438c2ecf20Sopenharmony_ci	err = chcr_compute_partial_hash(shash, hmacctx->opad,
22448c2ecf20Sopenharmony_ci					hmacctx->opad, digestsize);
22458c2ecf20Sopenharmony_ci	if (err)
22468c2ecf20Sopenharmony_ci		goto out;
22478c2ecf20Sopenharmony_ci	chcr_change_order(hmacctx->opad, updated_digestsize);
22488c2ecf20Sopenharmony_ciout:
22498c2ecf20Sopenharmony_ci	return err;
22508c2ecf20Sopenharmony_ci}
22518c2ecf20Sopenharmony_ci
22528c2ecf20Sopenharmony_cistatic int chcr_aes_xts_setkey(struct crypto_skcipher *cipher, const u8 *key,
22538c2ecf20Sopenharmony_ci			       unsigned int key_len)
22548c2ecf20Sopenharmony_ci{
22558c2ecf20Sopenharmony_ci	struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(cipher));
22568c2ecf20Sopenharmony_ci	unsigned short context_size = 0;
22578c2ecf20Sopenharmony_ci	int err;
22588c2ecf20Sopenharmony_ci
22598c2ecf20Sopenharmony_ci	err = chcr_cipher_fallback_setkey(cipher, key, key_len);
22608c2ecf20Sopenharmony_ci	if (err)
22618c2ecf20Sopenharmony_ci		goto badkey_err;
22628c2ecf20Sopenharmony_ci
22638c2ecf20Sopenharmony_ci	memcpy(ablkctx->key, key, key_len);
22648c2ecf20Sopenharmony_ci	ablkctx->enckey_len = key_len;
22658c2ecf20Sopenharmony_ci	get_aes_decrypt_key(ablkctx->rrkey, ablkctx->key, key_len << 2);
22668c2ecf20Sopenharmony_ci	context_size = (KEY_CONTEXT_HDR_SALT_AND_PAD + key_len) >> 4;
22678c2ecf20Sopenharmony_ci	/* Both keys for xts must be aligned to 16 byte boundary
22688c2ecf20Sopenharmony_ci	 * by padding with zeros. So for 24 byte keys padding 8 zeroes.
22698c2ecf20Sopenharmony_ci	 */
22708c2ecf20Sopenharmony_ci	if (key_len == 48) {
22718c2ecf20Sopenharmony_ci		context_size = (KEY_CONTEXT_HDR_SALT_AND_PAD + key_len
22728c2ecf20Sopenharmony_ci				+ 16) >> 4;
22738c2ecf20Sopenharmony_ci		memmove(ablkctx->key + 32, ablkctx->key + 24, 24);
22748c2ecf20Sopenharmony_ci		memset(ablkctx->key + 24, 0, 8);
22758c2ecf20Sopenharmony_ci		memset(ablkctx->key + 56, 0, 8);
22768c2ecf20Sopenharmony_ci		ablkctx->enckey_len = 64;
22778c2ecf20Sopenharmony_ci		ablkctx->key_ctx_hdr =
22788c2ecf20Sopenharmony_ci			FILL_KEY_CTX_HDR(CHCR_KEYCTX_CIPHER_KEY_SIZE_192,
22798c2ecf20Sopenharmony_ci					 CHCR_KEYCTX_NO_KEY, 1,
22808c2ecf20Sopenharmony_ci					 0, context_size);
22818c2ecf20Sopenharmony_ci	} else {
22828c2ecf20Sopenharmony_ci		ablkctx->key_ctx_hdr =
22838c2ecf20Sopenharmony_ci		FILL_KEY_CTX_HDR((key_len == AES_KEYSIZE_256) ?
22848c2ecf20Sopenharmony_ci				 CHCR_KEYCTX_CIPHER_KEY_SIZE_128 :
22858c2ecf20Sopenharmony_ci				 CHCR_KEYCTX_CIPHER_KEY_SIZE_256,
22868c2ecf20Sopenharmony_ci				 CHCR_KEYCTX_NO_KEY, 1,
22878c2ecf20Sopenharmony_ci				 0, context_size);
22888c2ecf20Sopenharmony_ci	}
22898c2ecf20Sopenharmony_ci	ablkctx->ciph_mode = CHCR_SCMD_CIPHER_MODE_AES_XTS;
22908c2ecf20Sopenharmony_ci	return 0;
22918c2ecf20Sopenharmony_cibadkey_err:
22928c2ecf20Sopenharmony_ci	ablkctx->enckey_len = 0;
22938c2ecf20Sopenharmony_ci
22948c2ecf20Sopenharmony_ci	return err;
22958c2ecf20Sopenharmony_ci}
22968c2ecf20Sopenharmony_ci
22978c2ecf20Sopenharmony_cistatic int chcr_sha_init(struct ahash_request *areq)
22988c2ecf20Sopenharmony_ci{
22998c2ecf20Sopenharmony_ci	struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
23008c2ecf20Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
23018c2ecf20Sopenharmony_ci	int digestsize =  crypto_ahash_digestsize(tfm);
23028c2ecf20Sopenharmony_ci
23038c2ecf20Sopenharmony_ci	req_ctx->data_len = 0;
23048c2ecf20Sopenharmony_ci	req_ctx->reqlen = 0;
23058c2ecf20Sopenharmony_ci	req_ctx->reqbfr = req_ctx->bfr1;
23068c2ecf20Sopenharmony_ci	req_ctx->skbfr = req_ctx->bfr2;
23078c2ecf20Sopenharmony_ci	copy_hash_init_values(req_ctx->partial_hash, digestsize);
23088c2ecf20Sopenharmony_ci
23098c2ecf20Sopenharmony_ci	return 0;
23108c2ecf20Sopenharmony_ci}
23118c2ecf20Sopenharmony_ci
23128c2ecf20Sopenharmony_cistatic int chcr_sha_cra_init(struct crypto_tfm *tfm)
23138c2ecf20Sopenharmony_ci{
23148c2ecf20Sopenharmony_ci	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
23158c2ecf20Sopenharmony_ci				 sizeof(struct chcr_ahash_req_ctx));
23168c2ecf20Sopenharmony_ci	return chcr_device_init(crypto_tfm_ctx(tfm));
23178c2ecf20Sopenharmony_ci}
23188c2ecf20Sopenharmony_ci
23198c2ecf20Sopenharmony_cistatic int chcr_hmac_init(struct ahash_request *areq)
23208c2ecf20Sopenharmony_ci{
23218c2ecf20Sopenharmony_ci	struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
23228c2ecf20Sopenharmony_ci	struct crypto_ahash *rtfm = crypto_ahash_reqtfm(areq);
23238c2ecf20Sopenharmony_ci	struct hmac_ctx *hmacctx = HMAC_CTX(h_ctx(rtfm));
23248c2ecf20Sopenharmony_ci	unsigned int digestsize = crypto_ahash_digestsize(rtfm);
23258c2ecf20Sopenharmony_ci	unsigned int bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(rtfm));
23268c2ecf20Sopenharmony_ci
23278c2ecf20Sopenharmony_ci	chcr_sha_init(areq);
23288c2ecf20Sopenharmony_ci	req_ctx->data_len = bs;
23298c2ecf20Sopenharmony_ci	if (is_hmac(crypto_ahash_tfm(rtfm))) {
23308c2ecf20Sopenharmony_ci		if (digestsize == SHA224_DIGEST_SIZE)
23318c2ecf20Sopenharmony_ci			memcpy(req_ctx->partial_hash, hmacctx->ipad,
23328c2ecf20Sopenharmony_ci			       SHA256_DIGEST_SIZE);
23338c2ecf20Sopenharmony_ci		else if (digestsize == SHA384_DIGEST_SIZE)
23348c2ecf20Sopenharmony_ci			memcpy(req_ctx->partial_hash, hmacctx->ipad,
23358c2ecf20Sopenharmony_ci			       SHA512_DIGEST_SIZE);
23368c2ecf20Sopenharmony_ci		else
23378c2ecf20Sopenharmony_ci			memcpy(req_ctx->partial_hash, hmacctx->ipad,
23388c2ecf20Sopenharmony_ci			       digestsize);
23398c2ecf20Sopenharmony_ci	}
23408c2ecf20Sopenharmony_ci	return 0;
23418c2ecf20Sopenharmony_ci}
23428c2ecf20Sopenharmony_ci
23438c2ecf20Sopenharmony_cistatic int chcr_hmac_cra_init(struct crypto_tfm *tfm)
23448c2ecf20Sopenharmony_ci{
23458c2ecf20Sopenharmony_ci	struct chcr_context *ctx = crypto_tfm_ctx(tfm);
23468c2ecf20Sopenharmony_ci	struct hmac_ctx *hmacctx = HMAC_CTX(ctx);
23478c2ecf20Sopenharmony_ci	unsigned int digestsize =
23488c2ecf20Sopenharmony_ci		crypto_ahash_digestsize(__crypto_ahash_cast(tfm));
23498c2ecf20Sopenharmony_ci
23508c2ecf20Sopenharmony_ci	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
23518c2ecf20Sopenharmony_ci				 sizeof(struct chcr_ahash_req_ctx));
23528c2ecf20Sopenharmony_ci	hmacctx->base_hash = chcr_alloc_shash(digestsize);
23538c2ecf20Sopenharmony_ci	if (IS_ERR(hmacctx->base_hash))
23548c2ecf20Sopenharmony_ci		return PTR_ERR(hmacctx->base_hash);
23558c2ecf20Sopenharmony_ci	return chcr_device_init(crypto_tfm_ctx(tfm));
23568c2ecf20Sopenharmony_ci}
23578c2ecf20Sopenharmony_ci
23588c2ecf20Sopenharmony_cistatic void chcr_hmac_cra_exit(struct crypto_tfm *tfm)
23598c2ecf20Sopenharmony_ci{
23608c2ecf20Sopenharmony_ci	struct chcr_context *ctx = crypto_tfm_ctx(tfm);
23618c2ecf20Sopenharmony_ci	struct hmac_ctx *hmacctx = HMAC_CTX(ctx);
23628c2ecf20Sopenharmony_ci
23638c2ecf20Sopenharmony_ci	if (hmacctx->base_hash) {
23648c2ecf20Sopenharmony_ci		chcr_free_shash(hmacctx->base_hash);
23658c2ecf20Sopenharmony_ci		hmacctx->base_hash = NULL;
23668c2ecf20Sopenharmony_ci	}
23678c2ecf20Sopenharmony_ci}
23688c2ecf20Sopenharmony_ci
23698c2ecf20Sopenharmony_ciinline void chcr_aead_common_exit(struct aead_request *req)
23708c2ecf20Sopenharmony_ci{
23718c2ecf20Sopenharmony_ci	struct chcr_aead_reqctx  *reqctx = aead_request_ctx(req);
23728c2ecf20Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
23738c2ecf20Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(a_ctx(tfm));
23748c2ecf20Sopenharmony_ci
23758c2ecf20Sopenharmony_ci	chcr_aead_dma_unmap(&u_ctx->lldi.pdev->dev, req, reqctx->op);
23768c2ecf20Sopenharmony_ci}
23778c2ecf20Sopenharmony_ci
23788c2ecf20Sopenharmony_cistatic int chcr_aead_common_init(struct aead_request *req)
23798c2ecf20Sopenharmony_ci{
23808c2ecf20Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
23818c2ecf20Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm));
23828c2ecf20Sopenharmony_ci	struct chcr_aead_reqctx  *reqctx = aead_request_ctx(req);
23838c2ecf20Sopenharmony_ci	unsigned int authsize = crypto_aead_authsize(tfm);
23848c2ecf20Sopenharmony_ci	int error = -EINVAL;
23858c2ecf20Sopenharmony_ci
23868c2ecf20Sopenharmony_ci	/* validate key size */
23878c2ecf20Sopenharmony_ci	if (aeadctx->enckey_len == 0)
23888c2ecf20Sopenharmony_ci		goto err;
23898c2ecf20Sopenharmony_ci	if (reqctx->op && req->cryptlen < authsize)
23908c2ecf20Sopenharmony_ci		goto err;
23918c2ecf20Sopenharmony_ci	if (reqctx->b0_len)
23928c2ecf20Sopenharmony_ci		reqctx->scratch_pad = reqctx->iv + IV;
23938c2ecf20Sopenharmony_ci	else
23948c2ecf20Sopenharmony_ci		reqctx->scratch_pad = NULL;
23958c2ecf20Sopenharmony_ci
23968c2ecf20Sopenharmony_ci	error = chcr_aead_dma_map(&ULD_CTX(a_ctx(tfm))->lldi.pdev->dev, req,
23978c2ecf20Sopenharmony_ci				  reqctx->op);
23988c2ecf20Sopenharmony_ci	if (error) {
23998c2ecf20Sopenharmony_ci		error = -ENOMEM;
24008c2ecf20Sopenharmony_ci		goto err;
24018c2ecf20Sopenharmony_ci	}
24028c2ecf20Sopenharmony_ci
24038c2ecf20Sopenharmony_ci	return 0;
24048c2ecf20Sopenharmony_cierr:
24058c2ecf20Sopenharmony_ci	return error;
24068c2ecf20Sopenharmony_ci}
24078c2ecf20Sopenharmony_ci
24088c2ecf20Sopenharmony_cistatic int chcr_aead_need_fallback(struct aead_request *req, int dst_nents,
24098c2ecf20Sopenharmony_ci				   int aadmax, int wrlen,
24108c2ecf20Sopenharmony_ci				   unsigned short op_type)
24118c2ecf20Sopenharmony_ci{
24128c2ecf20Sopenharmony_ci	unsigned int authsize = crypto_aead_authsize(crypto_aead_reqtfm(req));
24138c2ecf20Sopenharmony_ci
24148c2ecf20Sopenharmony_ci	if (((req->cryptlen - (op_type ? authsize : 0)) == 0) ||
24158c2ecf20Sopenharmony_ci	    dst_nents > MAX_DSGL_ENT ||
24168c2ecf20Sopenharmony_ci	    (req->assoclen > aadmax) ||
24178c2ecf20Sopenharmony_ci	    (wrlen > SGE_MAX_WR_LEN))
24188c2ecf20Sopenharmony_ci		return 1;
24198c2ecf20Sopenharmony_ci	return 0;
24208c2ecf20Sopenharmony_ci}
24218c2ecf20Sopenharmony_ci
24228c2ecf20Sopenharmony_cistatic int chcr_aead_fallback(struct aead_request *req, unsigned short op_type)
24238c2ecf20Sopenharmony_ci{
24248c2ecf20Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
24258c2ecf20Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm));
24268c2ecf20Sopenharmony_ci	struct aead_request *subreq = aead_request_ctx(req);
24278c2ecf20Sopenharmony_ci
24288c2ecf20Sopenharmony_ci	aead_request_set_tfm(subreq, aeadctx->sw_cipher);
24298c2ecf20Sopenharmony_ci	aead_request_set_callback(subreq, req->base.flags,
24308c2ecf20Sopenharmony_ci				  req->base.complete, req->base.data);
24318c2ecf20Sopenharmony_ci	aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
24328c2ecf20Sopenharmony_ci				 req->iv);
24338c2ecf20Sopenharmony_ci	aead_request_set_ad(subreq, req->assoclen);
24348c2ecf20Sopenharmony_ci	return op_type ? crypto_aead_decrypt(subreq) :
24358c2ecf20Sopenharmony_ci		crypto_aead_encrypt(subreq);
24368c2ecf20Sopenharmony_ci}
24378c2ecf20Sopenharmony_ci
24388c2ecf20Sopenharmony_cistatic struct sk_buff *create_authenc_wr(struct aead_request *req,
24398c2ecf20Sopenharmony_ci					 unsigned short qid,
24408c2ecf20Sopenharmony_ci					 int size)
24418c2ecf20Sopenharmony_ci{
24428c2ecf20Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
24438c2ecf20Sopenharmony_ci	struct chcr_context *ctx = a_ctx(tfm);
24448c2ecf20Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(ctx);
24458c2ecf20Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(ctx);
24468c2ecf20Sopenharmony_ci	struct chcr_authenc_ctx *actx = AUTHENC_CTX(aeadctx);
24478c2ecf20Sopenharmony_ci	struct chcr_aead_reqctx *reqctx = aead_request_ctx(req);
24488c2ecf20Sopenharmony_ci	struct sk_buff *skb = NULL;
24498c2ecf20Sopenharmony_ci	struct chcr_wr *chcr_req;
24508c2ecf20Sopenharmony_ci	struct cpl_rx_phys_dsgl *phys_cpl;
24518c2ecf20Sopenharmony_ci	struct ulptx_sgl *ulptx;
24528c2ecf20Sopenharmony_ci	unsigned int transhdr_len;
24538c2ecf20Sopenharmony_ci	unsigned int dst_size = 0, temp, subtype = get_aead_subtype(tfm);
24548c2ecf20Sopenharmony_ci	unsigned int   kctx_len = 0, dnents, snents;
24558c2ecf20Sopenharmony_ci	unsigned int  authsize = crypto_aead_authsize(tfm);
24568c2ecf20Sopenharmony_ci	int error = -EINVAL;
24578c2ecf20Sopenharmony_ci	u8 *ivptr;
24588c2ecf20Sopenharmony_ci	int null = 0;
24598c2ecf20Sopenharmony_ci	gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
24608c2ecf20Sopenharmony_ci		GFP_ATOMIC;
24618c2ecf20Sopenharmony_ci	struct adapter *adap = padap(ctx->dev);
24628c2ecf20Sopenharmony_ci	unsigned int rx_channel_id = reqctx->rxqidx / ctx->rxq_perchan;
24638c2ecf20Sopenharmony_ci
24648c2ecf20Sopenharmony_ci	rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]);
24658c2ecf20Sopenharmony_ci	if (req->cryptlen == 0)
24668c2ecf20Sopenharmony_ci		return NULL;
24678c2ecf20Sopenharmony_ci
24688c2ecf20Sopenharmony_ci	reqctx->b0_len = 0;
24698c2ecf20Sopenharmony_ci	error = chcr_aead_common_init(req);
24708c2ecf20Sopenharmony_ci	if (error)
24718c2ecf20Sopenharmony_ci		return ERR_PTR(error);
24728c2ecf20Sopenharmony_ci
24738c2ecf20Sopenharmony_ci	if (subtype == CRYPTO_ALG_SUB_TYPE_CBC_NULL ||
24748c2ecf20Sopenharmony_ci		subtype == CRYPTO_ALG_SUB_TYPE_CTR_NULL) {
24758c2ecf20Sopenharmony_ci		null = 1;
24768c2ecf20Sopenharmony_ci	}
24778c2ecf20Sopenharmony_ci	dnents = sg_nents_xlen(req->dst, req->assoclen + req->cryptlen +
24788c2ecf20Sopenharmony_ci		(reqctx->op ? -authsize : authsize), CHCR_DST_SG_SIZE, 0);
24798c2ecf20Sopenharmony_ci	dnents += MIN_AUTH_SG; // For IV
24808c2ecf20Sopenharmony_ci	snents = sg_nents_xlen(req->src, req->assoclen + req->cryptlen,
24818c2ecf20Sopenharmony_ci			       CHCR_SRC_SG_SIZE, 0);
24828c2ecf20Sopenharmony_ci	dst_size = get_space_for_phys_dsgl(dnents);
24838c2ecf20Sopenharmony_ci	kctx_len = (KEY_CONTEXT_CTX_LEN_G(ntohl(aeadctx->key_ctx_hdr)) << 4)
24848c2ecf20Sopenharmony_ci		- sizeof(chcr_req->key_ctx);
24858c2ecf20Sopenharmony_ci	transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, dst_size);
24868c2ecf20Sopenharmony_ci	reqctx->imm = (transhdr_len + req->assoclen + req->cryptlen) <
24878c2ecf20Sopenharmony_ci			SGE_MAX_WR_LEN;
24888c2ecf20Sopenharmony_ci	temp = reqctx->imm ? roundup(req->assoclen + req->cryptlen, 16)
24898c2ecf20Sopenharmony_ci			: (sgl_len(snents) * 8);
24908c2ecf20Sopenharmony_ci	transhdr_len += temp;
24918c2ecf20Sopenharmony_ci	transhdr_len = roundup(transhdr_len, 16);
24928c2ecf20Sopenharmony_ci
24938c2ecf20Sopenharmony_ci	if (chcr_aead_need_fallback(req, dnents, T6_MAX_AAD_SIZE,
24948c2ecf20Sopenharmony_ci				    transhdr_len, reqctx->op)) {
24958c2ecf20Sopenharmony_ci		atomic_inc(&adap->chcr_stats.fallback);
24968c2ecf20Sopenharmony_ci		chcr_aead_common_exit(req);
24978c2ecf20Sopenharmony_ci		return ERR_PTR(chcr_aead_fallback(req, reqctx->op));
24988c2ecf20Sopenharmony_ci	}
24998c2ecf20Sopenharmony_ci	skb = alloc_skb(transhdr_len, flags);
25008c2ecf20Sopenharmony_ci	if (!skb) {
25018c2ecf20Sopenharmony_ci		error = -ENOMEM;
25028c2ecf20Sopenharmony_ci		goto err;
25038c2ecf20Sopenharmony_ci	}
25048c2ecf20Sopenharmony_ci
25058c2ecf20Sopenharmony_ci	chcr_req = __skb_put_zero(skb, transhdr_len);
25068c2ecf20Sopenharmony_ci
25078c2ecf20Sopenharmony_ci	temp  = (reqctx->op == CHCR_ENCRYPT_OP) ? 0 : authsize;
25088c2ecf20Sopenharmony_ci
25098c2ecf20Sopenharmony_ci	/*
25108c2ecf20Sopenharmony_ci	 * Input order	is AAD,IV and Payload. where IV should be included as
25118c2ecf20Sopenharmony_ci	 * the part of authdata. All other fields should be filled according
25128c2ecf20Sopenharmony_ci	 * to the hardware spec
25138c2ecf20Sopenharmony_ci	 */
25148c2ecf20Sopenharmony_ci	chcr_req->sec_cpl.op_ivinsrtofst =
25158c2ecf20Sopenharmony_ci				FILL_SEC_CPL_OP_IVINSR(rx_channel_id, 2, 1);
25168c2ecf20Sopenharmony_ci	chcr_req->sec_cpl.pldlen = htonl(req->assoclen + IV + req->cryptlen);
25178c2ecf20Sopenharmony_ci	chcr_req->sec_cpl.aadstart_cipherstop_hi = FILL_SEC_CPL_CIPHERSTOP_HI(
25188c2ecf20Sopenharmony_ci					null ? 0 : 1 + IV,
25198c2ecf20Sopenharmony_ci					null ? 0 : IV + req->assoclen,
25208c2ecf20Sopenharmony_ci					req->assoclen + IV + 1,
25218c2ecf20Sopenharmony_ci					(temp & 0x1F0) >> 4);
25228c2ecf20Sopenharmony_ci	chcr_req->sec_cpl.cipherstop_lo_authinsert = FILL_SEC_CPL_AUTHINSERT(
25238c2ecf20Sopenharmony_ci					temp & 0xF,
25248c2ecf20Sopenharmony_ci					null ? 0 : req->assoclen + IV + 1,
25258c2ecf20Sopenharmony_ci					temp, temp);
25268c2ecf20Sopenharmony_ci	if (subtype == CRYPTO_ALG_SUB_TYPE_CTR_NULL ||
25278c2ecf20Sopenharmony_ci	    subtype == CRYPTO_ALG_SUB_TYPE_CTR_SHA)
25288c2ecf20Sopenharmony_ci		temp = CHCR_SCMD_CIPHER_MODE_AES_CTR;
25298c2ecf20Sopenharmony_ci	else
25308c2ecf20Sopenharmony_ci		temp = CHCR_SCMD_CIPHER_MODE_AES_CBC;
25318c2ecf20Sopenharmony_ci	chcr_req->sec_cpl.seqno_numivs = FILL_SEC_CPL_SCMD0_SEQNO(reqctx->op,
25328c2ecf20Sopenharmony_ci					(reqctx->op == CHCR_ENCRYPT_OP) ? 1 : 0,
25338c2ecf20Sopenharmony_ci					temp,
25348c2ecf20Sopenharmony_ci					actx->auth_mode, aeadctx->hmac_ctrl,
25358c2ecf20Sopenharmony_ci					IV >> 1);
25368c2ecf20Sopenharmony_ci	chcr_req->sec_cpl.ivgen_hdrlen =  FILL_SEC_CPL_IVGEN_HDRLEN(0, 0, 1,
25378c2ecf20Sopenharmony_ci					 0, 0, dst_size);
25388c2ecf20Sopenharmony_ci
25398c2ecf20Sopenharmony_ci	chcr_req->key_ctx.ctx_hdr = aeadctx->key_ctx_hdr;
25408c2ecf20Sopenharmony_ci	if (reqctx->op == CHCR_ENCRYPT_OP ||
25418c2ecf20Sopenharmony_ci		subtype == CRYPTO_ALG_SUB_TYPE_CTR_SHA ||
25428c2ecf20Sopenharmony_ci		subtype == CRYPTO_ALG_SUB_TYPE_CTR_NULL)
25438c2ecf20Sopenharmony_ci		memcpy(chcr_req->key_ctx.key, aeadctx->key,
25448c2ecf20Sopenharmony_ci		       aeadctx->enckey_len);
25458c2ecf20Sopenharmony_ci	else
25468c2ecf20Sopenharmony_ci		memcpy(chcr_req->key_ctx.key, actx->dec_rrkey,
25478c2ecf20Sopenharmony_ci		       aeadctx->enckey_len);
25488c2ecf20Sopenharmony_ci
25498c2ecf20Sopenharmony_ci	memcpy(chcr_req->key_ctx.key + roundup(aeadctx->enckey_len, 16),
25508c2ecf20Sopenharmony_ci	       actx->h_iopad, kctx_len - roundup(aeadctx->enckey_len, 16));
25518c2ecf20Sopenharmony_ci	phys_cpl = (struct cpl_rx_phys_dsgl *)((u8 *)(chcr_req + 1) + kctx_len);
25528c2ecf20Sopenharmony_ci	ivptr = (u8 *)(phys_cpl + 1) + dst_size;
25538c2ecf20Sopenharmony_ci	ulptx = (struct ulptx_sgl *)(ivptr + IV);
25548c2ecf20Sopenharmony_ci	if (subtype == CRYPTO_ALG_SUB_TYPE_CTR_SHA ||
25558c2ecf20Sopenharmony_ci	    subtype == CRYPTO_ALG_SUB_TYPE_CTR_NULL) {
25568c2ecf20Sopenharmony_ci		memcpy(ivptr, aeadctx->nonce, CTR_RFC3686_NONCE_SIZE);
25578c2ecf20Sopenharmony_ci		memcpy(ivptr + CTR_RFC3686_NONCE_SIZE, req->iv,
25588c2ecf20Sopenharmony_ci				CTR_RFC3686_IV_SIZE);
25598c2ecf20Sopenharmony_ci		*(__be32 *)(ivptr + CTR_RFC3686_NONCE_SIZE +
25608c2ecf20Sopenharmony_ci			CTR_RFC3686_IV_SIZE) = cpu_to_be32(1);
25618c2ecf20Sopenharmony_ci	} else {
25628c2ecf20Sopenharmony_ci		memcpy(ivptr, req->iv, IV);
25638c2ecf20Sopenharmony_ci	}
25648c2ecf20Sopenharmony_ci	chcr_add_aead_dst_ent(req, phys_cpl, qid);
25658c2ecf20Sopenharmony_ci	chcr_add_aead_src_ent(req, ulptx);
25668c2ecf20Sopenharmony_ci	atomic_inc(&adap->chcr_stats.cipher_rqst);
25678c2ecf20Sopenharmony_ci	temp = sizeof(struct cpl_rx_phys_dsgl) + dst_size + IV +
25688c2ecf20Sopenharmony_ci		kctx_len + (reqctx->imm ? (req->assoclen + req->cryptlen) : 0);
25698c2ecf20Sopenharmony_ci	create_wreq(a_ctx(tfm), chcr_req, &req->base, reqctx->imm, size,
25708c2ecf20Sopenharmony_ci		   transhdr_len, temp, 0);
25718c2ecf20Sopenharmony_ci	reqctx->skb = skb;
25728c2ecf20Sopenharmony_ci
25738c2ecf20Sopenharmony_ci	return skb;
25748c2ecf20Sopenharmony_cierr:
25758c2ecf20Sopenharmony_ci	chcr_aead_common_exit(req);
25768c2ecf20Sopenharmony_ci
25778c2ecf20Sopenharmony_ci	return ERR_PTR(error);
25788c2ecf20Sopenharmony_ci}
25798c2ecf20Sopenharmony_ci
25808c2ecf20Sopenharmony_ciint chcr_aead_dma_map(struct device *dev,
25818c2ecf20Sopenharmony_ci		      struct aead_request *req,
25828c2ecf20Sopenharmony_ci		      unsigned short op_type)
25838c2ecf20Sopenharmony_ci{
25848c2ecf20Sopenharmony_ci	int error;
25858c2ecf20Sopenharmony_ci	struct chcr_aead_reqctx  *reqctx = aead_request_ctx(req);
25868c2ecf20Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
25878c2ecf20Sopenharmony_ci	unsigned int authsize = crypto_aead_authsize(tfm);
25888c2ecf20Sopenharmony_ci	int src_len, dst_len;
25898c2ecf20Sopenharmony_ci
25908c2ecf20Sopenharmony_ci	/* calculate and handle src and dst sg length separately
25918c2ecf20Sopenharmony_ci	 * for inplace and out-of place operations
25928c2ecf20Sopenharmony_ci	 */
25938c2ecf20Sopenharmony_ci	if (req->src == req->dst) {
25948c2ecf20Sopenharmony_ci		src_len = req->assoclen + req->cryptlen + (op_type ?
25958c2ecf20Sopenharmony_ci							0 : authsize);
25968c2ecf20Sopenharmony_ci		dst_len = src_len;
25978c2ecf20Sopenharmony_ci	} else {
25988c2ecf20Sopenharmony_ci		src_len = req->assoclen + req->cryptlen;
25998c2ecf20Sopenharmony_ci		dst_len = req->assoclen + req->cryptlen + (op_type ?
26008c2ecf20Sopenharmony_ci							-authsize : authsize);
26018c2ecf20Sopenharmony_ci	}
26028c2ecf20Sopenharmony_ci
26038c2ecf20Sopenharmony_ci	if (!req->cryptlen || !src_len || !dst_len)
26048c2ecf20Sopenharmony_ci		return 0;
26058c2ecf20Sopenharmony_ci	reqctx->iv_dma = dma_map_single(dev, reqctx->iv, (IV + reqctx->b0_len),
26068c2ecf20Sopenharmony_ci					DMA_BIDIRECTIONAL);
26078c2ecf20Sopenharmony_ci	if (dma_mapping_error(dev, reqctx->iv_dma))
26088c2ecf20Sopenharmony_ci		return -ENOMEM;
26098c2ecf20Sopenharmony_ci	if (reqctx->b0_len)
26108c2ecf20Sopenharmony_ci		reqctx->b0_dma = reqctx->iv_dma + IV;
26118c2ecf20Sopenharmony_ci	else
26128c2ecf20Sopenharmony_ci		reqctx->b0_dma = 0;
26138c2ecf20Sopenharmony_ci	if (req->src == req->dst) {
26148c2ecf20Sopenharmony_ci		error = dma_map_sg(dev, req->src,
26158c2ecf20Sopenharmony_ci				sg_nents_for_len(req->src, src_len),
26168c2ecf20Sopenharmony_ci					DMA_BIDIRECTIONAL);
26178c2ecf20Sopenharmony_ci		if (!error)
26188c2ecf20Sopenharmony_ci			goto err;
26198c2ecf20Sopenharmony_ci	} else {
26208c2ecf20Sopenharmony_ci		error = dma_map_sg(dev, req->src,
26218c2ecf20Sopenharmony_ci				   sg_nents_for_len(req->src, src_len),
26228c2ecf20Sopenharmony_ci				   DMA_TO_DEVICE);
26238c2ecf20Sopenharmony_ci		if (!error)
26248c2ecf20Sopenharmony_ci			goto err;
26258c2ecf20Sopenharmony_ci		error = dma_map_sg(dev, req->dst,
26268c2ecf20Sopenharmony_ci				   sg_nents_for_len(req->dst, dst_len),
26278c2ecf20Sopenharmony_ci				   DMA_FROM_DEVICE);
26288c2ecf20Sopenharmony_ci		if (!error) {
26298c2ecf20Sopenharmony_ci			dma_unmap_sg(dev, req->src,
26308c2ecf20Sopenharmony_ci				     sg_nents_for_len(req->src, src_len),
26318c2ecf20Sopenharmony_ci				     DMA_TO_DEVICE);
26328c2ecf20Sopenharmony_ci			goto err;
26338c2ecf20Sopenharmony_ci		}
26348c2ecf20Sopenharmony_ci	}
26358c2ecf20Sopenharmony_ci
26368c2ecf20Sopenharmony_ci	return 0;
26378c2ecf20Sopenharmony_cierr:
26388c2ecf20Sopenharmony_ci	dma_unmap_single(dev, reqctx->iv_dma, IV, DMA_BIDIRECTIONAL);
26398c2ecf20Sopenharmony_ci	return -ENOMEM;
26408c2ecf20Sopenharmony_ci}
26418c2ecf20Sopenharmony_ci
26428c2ecf20Sopenharmony_civoid chcr_aead_dma_unmap(struct device *dev,
26438c2ecf20Sopenharmony_ci			 struct aead_request *req,
26448c2ecf20Sopenharmony_ci			 unsigned short op_type)
26458c2ecf20Sopenharmony_ci{
26468c2ecf20Sopenharmony_ci	struct chcr_aead_reqctx  *reqctx = aead_request_ctx(req);
26478c2ecf20Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
26488c2ecf20Sopenharmony_ci	unsigned int authsize = crypto_aead_authsize(tfm);
26498c2ecf20Sopenharmony_ci	int src_len, dst_len;
26508c2ecf20Sopenharmony_ci
26518c2ecf20Sopenharmony_ci	/* calculate and handle src and dst sg length separately
26528c2ecf20Sopenharmony_ci	 * for inplace and out-of place operations
26538c2ecf20Sopenharmony_ci	 */
26548c2ecf20Sopenharmony_ci	if (req->src == req->dst) {
26558c2ecf20Sopenharmony_ci		src_len = req->assoclen + req->cryptlen + (op_type ?
26568c2ecf20Sopenharmony_ci							0 : authsize);
26578c2ecf20Sopenharmony_ci		dst_len = src_len;
26588c2ecf20Sopenharmony_ci	} else {
26598c2ecf20Sopenharmony_ci		src_len = req->assoclen + req->cryptlen;
26608c2ecf20Sopenharmony_ci		dst_len = req->assoclen + req->cryptlen + (op_type ?
26618c2ecf20Sopenharmony_ci						-authsize : authsize);
26628c2ecf20Sopenharmony_ci	}
26638c2ecf20Sopenharmony_ci
26648c2ecf20Sopenharmony_ci	if (!req->cryptlen || !src_len || !dst_len)
26658c2ecf20Sopenharmony_ci		return;
26668c2ecf20Sopenharmony_ci
26678c2ecf20Sopenharmony_ci	dma_unmap_single(dev, reqctx->iv_dma, (IV + reqctx->b0_len),
26688c2ecf20Sopenharmony_ci					DMA_BIDIRECTIONAL);
26698c2ecf20Sopenharmony_ci	if (req->src == req->dst) {
26708c2ecf20Sopenharmony_ci		dma_unmap_sg(dev, req->src,
26718c2ecf20Sopenharmony_ci			     sg_nents_for_len(req->src, src_len),
26728c2ecf20Sopenharmony_ci			     DMA_BIDIRECTIONAL);
26738c2ecf20Sopenharmony_ci	} else {
26748c2ecf20Sopenharmony_ci		dma_unmap_sg(dev, req->src,
26758c2ecf20Sopenharmony_ci			     sg_nents_for_len(req->src, src_len),
26768c2ecf20Sopenharmony_ci			     DMA_TO_DEVICE);
26778c2ecf20Sopenharmony_ci		dma_unmap_sg(dev, req->dst,
26788c2ecf20Sopenharmony_ci			     sg_nents_for_len(req->dst, dst_len),
26798c2ecf20Sopenharmony_ci			     DMA_FROM_DEVICE);
26808c2ecf20Sopenharmony_ci	}
26818c2ecf20Sopenharmony_ci}
26828c2ecf20Sopenharmony_ci
26838c2ecf20Sopenharmony_civoid chcr_add_aead_src_ent(struct aead_request *req,
26848c2ecf20Sopenharmony_ci			   struct ulptx_sgl *ulptx)
26858c2ecf20Sopenharmony_ci{
26868c2ecf20Sopenharmony_ci	struct ulptx_walk ulp_walk;
26878c2ecf20Sopenharmony_ci	struct chcr_aead_reqctx  *reqctx = aead_request_ctx(req);
26888c2ecf20Sopenharmony_ci
26898c2ecf20Sopenharmony_ci	if (reqctx->imm) {
26908c2ecf20Sopenharmony_ci		u8 *buf = (u8 *)ulptx;
26918c2ecf20Sopenharmony_ci
26928c2ecf20Sopenharmony_ci		if (reqctx->b0_len) {
26938c2ecf20Sopenharmony_ci			memcpy(buf, reqctx->scratch_pad, reqctx->b0_len);
26948c2ecf20Sopenharmony_ci			buf += reqctx->b0_len;
26958c2ecf20Sopenharmony_ci		}
26968c2ecf20Sopenharmony_ci		sg_pcopy_to_buffer(req->src, sg_nents(req->src),
26978c2ecf20Sopenharmony_ci				   buf, req->cryptlen + req->assoclen, 0);
26988c2ecf20Sopenharmony_ci	} else {
26998c2ecf20Sopenharmony_ci		ulptx_walk_init(&ulp_walk, ulptx);
27008c2ecf20Sopenharmony_ci		if (reqctx->b0_len)
27018c2ecf20Sopenharmony_ci			ulptx_walk_add_page(&ulp_walk, reqctx->b0_len,
27028c2ecf20Sopenharmony_ci					    reqctx->b0_dma);
27038c2ecf20Sopenharmony_ci		ulptx_walk_add_sg(&ulp_walk, req->src, req->cryptlen +
27048c2ecf20Sopenharmony_ci				  req->assoclen,  0);
27058c2ecf20Sopenharmony_ci		ulptx_walk_end(&ulp_walk);
27068c2ecf20Sopenharmony_ci	}
27078c2ecf20Sopenharmony_ci}
27088c2ecf20Sopenharmony_ci
27098c2ecf20Sopenharmony_civoid chcr_add_aead_dst_ent(struct aead_request *req,
27108c2ecf20Sopenharmony_ci			   struct cpl_rx_phys_dsgl *phys_cpl,
27118c2ecf20Sopenharmony_ci			   unsigned short qid)
27128c2ecf20Sopenharmony_ci{
27138c2ecf20Sopenharmony_ci	struct chcr_aead_reqctx  *reqctx = aead_request_ctx(req);
27148c2ecf20Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
27158c2ecf20Sopenharmony_ci	struct dsgl_walk dsgl_walk;
27168c2ecf20Sopenharmony_ci	unsigned int authsize = crypto_aead_authsize(tfm);
27178c2ecf20Sopenharmony_ci	struct chcr_context *ctx = a_ctx(tfm);
27188c2ecf20Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(ctx);
27198c2ecf20Sopenharmony_ci	u32 temp;
27208c2ecf20Sopenharmony_ci	unsigned int rx_channel_id = reqctx->rxqidx / ctx->rxq_perchan;
27218c2ecf20Sopenharmony_ci
27228c2ecf20Sopenharmony_ci	rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]);
27238c2ecf20Sopenharmony_ci	dsgl_walk_init(&dsgl_walk, phys_cpl);
27248c2ecf20Sopenharmony_ci	dsgl_walk_add_page(&dsgl_walk, IV + reqctx->b0_len, reqctx->iv_dma);
27258c2ecf20Sopenharmony_ci	temp = req->assoclen + req->cryptlen +
27268c2ecf20Sopenharmony_ci		(reqctx->op ? -authsize : authsize);
27278c2ecf20Sopenharmony_ci	dsgl_walk_add_sg(&dsgl_walk, req->dst, temp, 0);
27288c2ecf20Sopenharmony_ci	dsgl_walk_end(&dsgl_walk, qid, rx_channel_id);
27298c2ecf20Sopenharmony_ci}
27308c2ecf20Sopenharmony_ci
27318c2ecf20Sopenharmony_civoid chcr_add_cipher_src_ent(struct skcipher_request *req,
27328c2ecf20Sopenharmony_ci			     void *ulptx,
27338c2ecf20Sopenharmony_ci			     struct  cipher_wr_param *wrparam)
27348c2ecf20Sopenharmony_ci{
27358c2ecf20Sopenharmony_ci	struct ulptx_walk ulp_walk;
27368c2ecf20Sopenharmony_ci	struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req);
27378c2ecf20Sopenharmony_ci	u8 *buf = ulptx;
27388c2ecf20Sopenharmony_ci
27398c2ecf20Sopenharmony_ci	memcpy(buf, reqctx->iv, IV);
27408c2ecf20Sopenharmony_ci	buf += IV;
27418c2ecf20Sopenharmony_ci	if (reqctx->imm) {
27428c2ecf20Sopenharmony_ci		sg_pcopy_to_buffer(req->src, sg_nents(req->src),
27438c2ecf20Sopenharmony_ci				   buf, wrparam->bytes, reqctx->processed);
27448c2ecf20Sopenharmony_ci	} else {
27458c2ecf20Sopenharmony_ci		ulptx_walk_init(&ulp_walk, (struct ulptx_sgl *)buf);
27468c2ecf20Sopenharmony_ci		ulptx_walk_add_sg(&ulp_walk, reqctx->srcsg, wrparam->bytes,
27478c2ecf20Sopenharmony_ci				  reqctx->src_ofst);
27488c2ecf20Sopenharmony_ci		reqctx->srcsg = ulp_walk.last_sg;
27498c2ecf20Sopenharmony_ci		reqctx->src_ofst = ulp_walk.last_sg_len;
27508c2ecf20Sopenharmony_ci		ulptx_walk_end(&ulp_walk);
27518c2ecf20Sopenharmony_ci	}
27528c2ecf20Sopenharmony_ci}
27538c2ecf20Sopenharmony_ci
27548c2ecf20Sopenharmony_civoid chcr_add_cipher_dst_ent(struct skcipher_request *req,
27558c2ecf20Sopenharmony_ci			     struct cpl_rx_phys_dsgl *phys_cpl,
27568c2ecf20Sopenharmony_ci			     struct  cipher_wr_param *wrparam,
27578c2ecf20Sopenharmony_ci			     unsigned short qid)
27588c2ecf20Sopenharmony_ci{
27598c2ecf20Sopenharmony_ci	struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req);
27608c2ecf20Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(wrparam->req);
27618c2ecf20Sopenharmony_ci	struct chcr_context *ctx = c_ctx(tfm);
27628c2ecf20Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(ctx);
27638c2ecf20Sopenharmony_ci	struct dsgl_walk dsgl_walk;
27648c2ecf20Sopenharmony_ci	unsigned int rx_channel_id = reqctx->rxqidx / ctx->rxq_perchan;
27658c2ecf20Sopenharmony_ci
27668c2ecf20Sopenharmony_ci	rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]);
27678c2ecf20Sopenharmony_ci	dsgl_walk_init(&dsgl_walk, phys_cpl);
27688c2ecf20Sopenharmony_ci	dsgl_walk_add_sg(&dsgl_walk, reqctx->dstsg, wrparam->bytes,
27698c2ecf20Sopenharmony_ci			 reqctx->dst_ofst);
27708c2ecf20Sopenharmony_ci	reqctx->dstsg = dsgl_walk.last_sg;
27718c2ecf20Sopenharmony_ci	reqctx->dst_ofst = dsgl_walk.last_sg_len;
27728c2ecf20Sopenharmony_ci	dsgl_walk_end(&dsgl_walk, qid, rx_channel_id);
27738c2ecf20Sopenharmony_ci}
27748c2ecf20Sopenharmony_ci
27758c2ecf20Sopenharmony_civoid chcr_add_hash_src_ent(struct ahash_request *req,
27768c2ecf20Sopenharmony_ci			   struct ulptx_sgl *ulptx,
27778c2ecf20Sopenharmony_ci			   struct hash_wr_param *param)
27788c2ecf20Sopenharmony_ci{
27798c2ecf20Sopenharmony_ci	struct ulptx_walk ulp_walk;
27808c2ecf20Sopenharmony_ci	struct chcr_ahash_req_ctx *reqctx = ahash_request_ctx(req);
27818c2ecf20Sopenharmony_ci
27828c2ecf20Sopenharmony_ci	if (reqctx->hctx_wr.imm) {
27838c2ecf20Sopenharmony_ci		u8 *buf = (u8 *)ulptx;
27848c2ecf20Sopenharmony_ci
27858c2ecf20Sopenharmony_ci		if (param->bfr_len) {
27868c2ecf20Sopenharmony_ci			memcpy(buf, reqctx->reqbfr, param->bfr_len);
27878c2ecf20Sopenharmony_ci			buf += param->bfr_len;
27888c2ecf20Sopenharmony_ci		}
27898c2ecf20Sopenharmony_ci
27908c2ecf20Sopenharmony_ci		sg_pcopy_to_buffer(reqctx->hctx_wr.srcsg,
27918c2ecf20Sopenharmony_ci				   sg_nents(reqctx->hctx_wr.srcsg), buf,
27928c2ecf20Sopenharmony_ci				   param->sg_len, 0);
27938c2ecf20Sopenharmony_ci	} else {
27948c2ecf20Sopenharmony_ci		ulptx_walk_init(&ulp_walk, ulptx);
27958c2ecf20Sopenharmony_ci		if (param->bfr_len)
27968c2ecf20Sopenharmony_ci			ulptx_walk_add_page(&ulp_walk, param->bfr_len,
27978c2ecf20Sopenharmony_ci					    reqctx->hctx_wr.dma_addr);
27988c2ecf20Sopenharmony_ci		ulptx_walk_add_sg(&ulp_walk, reqctx->hctx_wr.srcsg,
27998c2ecf20Sopenharmony_ci				  param->sg_len, reqctx->hctx_wr.src_ofst);
28008c2ecf20Sopenharmony_ci		reqctx->hctx_wr.srcsg = ulp_walk.last_sg;
28018c2ecf20Sopenharmony_ci		reqctx->hctx_wr.src_ofst = ulp_walk.last_sg_len;
28028c2ecf20Sopenharmony_ci		ulptx_walk_end(&ulp_walk);
28038c2ecf20Sopenharmony_ci	}
28048c2ecf20Sopenharmony_ci}
28058c2ecf20Sopenharmony_ci
28068c2ecf20Sopenharmony_ciint chcr_hash_dma_map(struct device *dev,
28078c2ecf20Sopenharmony_ci		      struct ahash_request *req)
28088c2ecf20Sopenharmony_ci{
28098c2ecf20Sopenharmony_ci	struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req);
28108c2ecf20Sopenharmony_ci	int error = 0;
28118c2ecf20Sopenharmony_ci
28128c2ecf20Sopenharmony_ci	if (!req->nbytes)
28138c2ecf20Sopenharmony_ci		return 0;
28148c2ecf20Sopenharmony_ci	error = dma_map_sg(dev, req->src, sg_nents(req->src),
28158c2ecf20Sopenharmony_ci			   DMA_TO_DEVICE);
28168c2ecf20Sopenharmony_ci	if (!error)
28178c2ecf20Sopenharmony_ci		return -ENOMEM;
28188c2ecf20Sopenharmony_ci	req_ctx->hctx_wr.is_sg_map = 1;
28198c2ecf20Sopenharmony_ci	return 0;
28208c2ecf20Sopenharmony_ci}
28218c2ecf20Sopenharmony_ci
28228c2ecf20Sopenharmony_civoid chcr_hash_dma_unmap(struct device *dev,
28238c2ecf20Sopenharmony_ci			 struct ahash_request *req)
28248c2ecf20Sopenharmony_ci{
28258c2ecf20Sopenharmony_ci	struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req);
28268c2ecf20Sopenharmony_ci
28278c2ecf20Sopenharmony_ci	if (!req->nbytes)
28288c2ecf20Sopenharmony_ci		return;
28298c2ecf20Sopenharmony_ci
28308c2ecf20Sopenharmony_ci	dma_unmap_sg(dev, req->src, sg_nents(req->src),
28318c2ecf20Sopenharmony_ci			   DMA_TO_DEVICE);
28328c2ecf20Sopenharmony_ci	req_ctx->hctx_wr.is_sg_map = 0;
28338c2ecf20Sopenharmony_ci
28348c2ecf20Sopenharmony_ci}
28358c2ecf20Sopenharmony_ci
28368c2ecf20Sopenharmony_ciint chcr_cipher_dma_map(struct device *dev,
28378c2ecf20Sopenharmony_ci			struct skcipher_request *req)
28388c2ecf20Sopenharmony_ci{
28398c2ecf20Sopenharmony_ci	int error;
28408c2ecf20Sopenharmony_ci
28418c2ecf20Sopenharmony_ci	if (req->src == req->dst) {
28428c2ecf20Sopenharmony_ci		error = dma_map_sg(dev, req->src, sg_nents(req->src),
28438c2ecf20Sopenharmony_ci				   DMA_BIDIRECTIONAL);
28448c2ecf20Sopenharmony_ci		if (!error)
28458c2ecf20Sopenharmony_ci			goto err;
28468c2ecf20Sopenharmony_ci	} else {
28478c2ecf20Sopenharmony_ci		error = dma_map_sg(dev, req->src, sg_nents(req->src),
28488c2ecf20Sopenharmony_ci				   DMA_TO_DEVICE);
28498c2ecf20Sopenharmony_ci		if (!error)
28508c2ecf20Sopenharmony_ci			goto err;
28518c2ecf20Sopenharmony_ci		error = dma_map_sg(dev, req->dst, sg_nents(req->dst),
28528c2ecf20Sopenharmony_ci				   DMA_FROM_DEVICE);
28538c2ecf20Sopenharmony_ci		if (!error) {
28548c2ecf20Sopenharmony_ci			dma_unmap_sg(dev, req->src, sg_nents(req->src),
28558c2ecf20Sopenharmony_ci				   DMA_TO_DEVICE);
28568c2ecf20Sopenharmony_ci			goto err;
28578c2ecf20Sopenharmony_ci		}
28588c2ecf20Sopenharmony_ci	}
28598c2ecf20Sopenharmony_ci
28608c2ecf20Sopenharmony_ci	return 0;
28618c2ecf20Sopenharmony_cierr:
28628c2ecf20Sopenharmony_ci	return -ENOMEM;
28638c2ecf20Sopenharmony_ci}
28648c2ecf20Sopenharmony_ci
28658c2ecf20Sopenharmony_civoid chcr_cipher_dma_unmap(struct device *dev,
28668c2ecf20Sopenharmony_ci			   struct skcipher_request *req)
28678c2ecf20Sopenharmony_ci{
28688c2ecf20Sopenharmony_ci	if (req->src == req->dst) {
28698c2ecf20Sopenharmony_ci		dma_unmap_sg(dev, req->src, sg_nents(req->src),
28708c2ecf20Sopenharmony_ci				   DMA_BIDIRECTIONAL);
28718c2ecf20Sopenharmony_ci	} else {
28728c2ecf20Sopenharmony_ci		dma_unmap_sg(dev, req->src, sg_nents(req->src),
28738c2ecf20Sopenharmony_ci				   DMA_TO_DEVICE);
28748c2ecf20Sopenharmony_ci		dma_unmap_sg(dev, req->dst, sg_nents(req->dst),
28758c2ecf20Sopenharmony_ci				   DMA_FROM_DEVICE);
28768c2ecf20Sopenharmony_ci	}
28778c2ecf20Sopenharmony_ci}
28788c2ecf20Sopenharmony_ci
28798c2ecf20Sopenharmony_cistatic int set_msg_len(u8 *block, unsigned int msglen, int csize)
28808c2ecf20Sopenharmony_ci{
28818c2ecf20Sopenharmony_ci	__be32 data;
28828c2ecf20Sopenharmony_ci
28838c2ecf20Sopenharmony_ci	memset(block, 0, csize);
28848c2ecf20Sopenharmony_ci	block += csize;
28858c2ecf20Sopenharmony_ci
28868c2ecf20Sopenharmony_ci	if (csize >= 4)
28878c2ecf20Sopenharmony_ci		csize = 4;
28888c2ecf20Sopenharmony_ci	else if (msglen > (unsigned int)(1 << (8 * csize)))
28898c2ecf20Sopenharmony_ci		return -EOVERFLOW;
28908c2ecf20Sopenharmony_ci
28918c2ecf20Sopenharmony_ci	data = cpu_to_be32(msglen);
28928c2ecf20Sopenharmony_ci	memcpy(block - csize, (u8 *)&data + 4 - csize, csize);
28938c2ecf20Sopenharmony_ci
28948c2ecf20Sopenharmony_ci	return 0;
28958c2ecf20Sopenharmony_ci}
28968c2ecf20Sopenharmony_ci
28978c2ecf20Sopenharmony_cistatic int generate_b0(struct aead_request *req, u8 *ivptr,
28988c2ecf20Sopenharmony_ci			unsigned short op_type)
28998c2ecf20Sopenharmony_ci{
29008c2ecf20Sopenharmony_ci	unsigned int l, lp, m;
29018c2ecf20Sopenharmony_ci	int rc;
29028c2ecf20Sopenharmony_ci	struct crypto_aead *aead = crypto_aead_reqtfm(req);
29038c2ecf20Sopenharmony_ci	struct chcr_aead_reqctx *reqctx = aead_request_ctx(req);
29048c2ecf20Sopenharmony_ci	u8 *b0 = reqctx->scratch_pad;
29058c2ecf20Sopenharmony_ci
29068c2ecf20Sopenharmony_ci	m = crypto_aead_authsize(aead);
29078c2ecf20Sopenharmony_ci
29088c2ecf20Sopenharmony_ci	memcpy(b0, ivptr, 16);
29098c2ecf20Sopenharmony_ci
29108c2ecf20Sopenharmony_ci	lp = b0[0];
29118c2ecf20Sopenharmony_ci	l = lp + 1;
29128c2ecf20Sopenharmony_ci
29138c2ecf20Sopenharmony_ci	/* set m, bits 3-5 */
29148c2ecf20Sopenharmony_ci	*b0 |= (8 * ((m - 2) / 2));
29158c2ecf20Sopenharmony_ci
29168c2ecf20Sopenharmony_ci	/* set adata, bit 6, if associated data is used */
29178c2ecf20Sopenharmony_ci	if (req->assoclen)
29188c2ecf20Sopenharmony_ci		*b0 |= 64;
29198c2ecf20Sopenharmony_ci	rc = set_msg_len(b0 + 16 - l,
29208c2ecf20Sopenharmony_ci			 (op_type == CHCR_DECRYPT_OP) ?
29218c2ecf20Sopenharmony_ci			 req->cryptlen - m : req->cryptlen, l);
29228c2ecf20Sopenharmony_ci
29238c2ecf20Sopenharmony_ci	return rc;
29248c2ecf20Sopenharmony_ci}
29258c2ecf20Sopenharmony_ci
29268c2ecf20Sopenharmony_cistatic inline int crypto_ccm_check_iv(const u8 *iv)
29278c2ecf20Sopenharmony_ci{
29288c2ecf20Sopenharmony_ci	/* 2 <= L <= 8, so 1 <= L' <= 7. */
29298c2ecf20Sopenharmony_ci	if (iv[0] < 1 || iv[0] > 7)
29308c2ecf20Sopenharmony_ci		return -EINVAL;
29318c2ecf20Sopenharmony_ci
29328c2ecf20Sopenharmony_ci	return 0;
29338c2ecf20Sopenharmony_ci}
29348c2ecf20Sopenharmony_ci
29358c2ecf20Sopenharmony_cistatic int ccm_format_packet(struct aead_request *req,
29368c2ecf20Sopenharmony_ci			     u8 *ivptr,
29378c2ecf20Sopenharmony_ci			     unsigned int sub_type,
29388c2ecf20Sopenharmony_ci			     unsigned short op_type,
29398c2ecf20Sopenharmony_ci			     unsigned int assoclen)
29408c2ecf20Sopenharmony_ci{
29418c2ecf20Sopenharmony_ci	struct chcr_aead_reqctx *reqctx = aead_request_ctx(req);
29428c2ecf20Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
29438c2ecf20Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm));
29448c2ecf20Sopenharmony_ci	int rc = 0;
29458c2ecf20Sopenharmony_ci
29468c2ecf20Sopenharmony_ci	if (sub_type == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309) {
29478c2ecf20Sopenharmony_ci		ivptr[0] = 3;
29488c2ecf20Sopenharmony_ci		memcpy(ivptr + 1, &aeadctx->salt[0], 3);
29498c2ecf20Sopenharmony_ci		memcpy(ivptr + 4, req->iv, 8);
29508c2ecf20Sopenharmony_ci		memset(ivptr + 12, 0, 4);
29518c2ecf20Sopenharmony_ci	} else {
29528c2ecf20Sopenharmony_ci		memcpy(ivptr, req->iv, 16);
29538c2ecf20Sopenharmony_ci	}
29548c2ecf20Sopenharmony_ci	if (assoclen)
29558c2ecf20Sopenharmony_ci		put_unaligned_be16(assoclen, &reqctx->scratch_pad[16]);
29568c2ecf20Sopenharmony_ci
29578c2ecf20Sopenharmony_ci	rc = generate_b0(req, ivptr, op_type);
29588c2ecf20Sopenharmony_ci	/* zero the ctr value */
29598c2ecf20Sopenharmony_ci	memset(ivptr + 15 - ivptr[0], 0, ivptr[0] + 1);
29608c2ecf20Sopenharmony_ci	return rc;
29618c2ecf20Sopenharmony_ci}
29628c2ecf20Sopenharmony_ci
29638c2ecf20Sopenharmony_cistatic void fill_sec_cpl_for_aead(struct cpl_tx_sec_pdu *sec_cpl,
29648c2ecf20Sopenharmony_ci				  unsigned int dst_size,
29658c2ecf20Sopenharmony_ci				  struct aead_request *req,
29668c2ecf20Sopenharmony_ci				  unsigned short op_type)
29678c2ecf20Sopenharmony_ci{
29688c2ecf20Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
29698c2ecf20Sopenharmony_ci	struct chcr_context *ctx = a_ctx(tfm);
29708c2ecf20Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(ctx);
29718c2ecf20Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(ctx);
29728c2ecf20Sopenharmony_ci	struct chcr_aead_reqctx *reqctx = aead_request_ctx(req);
29738c2ecf20Sopenharmony_ci	unsigned int cipher_mode = CHCR_SCMD_CIPHER_MODE_AES_CCM;
29748c2ecf20Sopenharmony_ci	unsigned int mac_mode = CHCR_SCMD_AUTH_MODE_CBCMAC;
29758c2ecf20Sopenharmony_ci	unsigned int rx_channel_id = reqctx->rxqidx / ctx->rxq_perchan;
29768c2ecf20Sopenharmony_ci	unsigned int ccm_xtra;
29778c2ecf20Sopenharmony_ci	unsigned int tag_offset = 0, auth_offset = 0;
29788c2ecf20Sopenharmony_ci	unsigned int assoclen;
29798c2ecf20Sopenharmony_ci
29808c2ecf20Sopenharmony_ci	rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]);
29818c2ecf20Sopenharmony_ci
29828c2ecf20Sopenharmony_ci	if (get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309)
29838c2ecf20Sopenharmony_ci		assoclen = req->assoclen - 8;
29848c2ecf20Sopenharmony_ci	else
29858c2ecf20Sopenharmony_ci		assoclen = req->assoclen;
29868c2ecf20Sopenharmony_ci	ccm_xtra = CCM_B0_SIZE +
29878c2ecf20Sopenharmony_ci		((assoclen) ? CCM_AAD_FIELD_SIZE : 0);
29888c2ecf20Sopenharmony_ci
29898c2ecf20Sopenharmony_ci	auth_offset = req->cryptlen ?
29908c2ecf20Sopenharmony_ci		(req->assoclen + IV + 1 + ccm_xtra) : 0;
29918c2ecf20Sopenharmony_ci	if (op_type == CHCR_DECRYPT_OP) {
29928c2ecf20Sopenharmony_ci		if (crypto_aead_authsize(tfm) != req->cryptlen)
29938c2ecf20Sopenharmony_ci			tag_offset = crypto_aead_authsize(tfm);
29948c2ecf20Sopenharmony_ci		else
29958c2ecf20Sopenharmony_ci			auth_offset = 0;
29968c2ecf20Sopenharmony_ci	}
29978c2ecf20Sopenharmony_ci
29988c2ecf20Sopenharmony_ci	sec_cpl->op_ivinsrtofst = FILL_SEC_CPL_OP_IVINSR(rx_channel_id, 2, 1);
29998c2ecf20Sopenharmony_ci	sec_cpl->pldlen =
30008c2ecf20Sopenharmony_ci		htonl(req->assoclen + IV + req->cryptlen + ccm_xtra);
30018c2ecf20Sopenharmony_ci	/* For CCM there wil be b0 always. So AAD start will be 1 always */
30028c2ecf20Sopenharmony_ci	sec_cpl->aadstart_cipherstop_hi = FILL_SEC_CPL_CIPHERSTOP_HI(
30038c2ecf20Sopenharmony_ci				1 + IV,	IV + assoclen + ccm_xtra,
30048c2ecf20Sopenharmony_ci				req->assoclen + IV + 1 + ccm_xtra, 0);
30058c2ecf20Sopenharmony_ci
30068c2ecf20Sopenharmony_ci	sec_cpl->cipherstop_lo_authinsert = FILL_SEC_CPL_AUTHINSERT(0,
30078c2ecf20Sopenharmony_ci					auth_offset, tag_offset,
30088c2ecf20Sopenharmony_ci					(op_type == CHCR_ENCRYPT_OP) ? 0 :
30098c2ecf20Sopenharmony_ci					crypto_aead_authsize(tfm));
30108c2ecf20Sopenharmony_ci	sec_cpl->seqno_numivs =  FILL_SEC_CPL_SCMD0_SEQNO(op_type,
30118c2ecf20Sopenharmony_ci					(op_type == CHCR_ENCRYPT_OP) ? 0 : 1,
30128c2ecf20Sopenharmony_ci					cipher_mode, mac_mode,
30138c2ecf20Sopenharmony_ci					aeadctx->hmac_ctrl, IV >> 1);
30148c2ecf20Sopenharmony_ci
30158c2ecf20Sopenharmony_ci	sec_cpl->ivgen_hdrlen = FILL_SEC_CPL_IVGEN_HDRLEN(0, 0, 1, 0,
30168c2ecf20Sopenharmony_ci					0, dst_size);
30178c2ecf20Sopenharmony_ci}
30188c2ecf20Sopenharmony_ci
30198c2ecf20Sopenharmony_cistatic int aead_ccm_validate_input(unsigned short op_type,
30208c2ecf20Sopenharmony_ci				   struct aead_request *req,
30218c2ecf20Sopenharmony_ci				   struct chcr_aead_ctx *aeadctx,
30228c2ecf20Sopenharmony_ci				   unsigned int sub_type)
30238c2ecf20Sopenharmony_ci{
30248c2ecf20Sopenharmony_ci	if (sub_type != CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309) {
30258c2ecf20Sopenharmony_ci		if (crypto_ccm_check_iv(req->iv)) {
30268c2ecf20Sopenharmony_ci			pr_err("CCM: IV check fails\n");
30278c2ecf20Sopenharmony_ci			return -EINVAL;
30288c2ecf20Sopenharmony_ci		}
30298c2ecf20Sopenharmony_ci	} else {
30308c2ecf20Sopenharmony_ci		if (req->assoclen != 16 && req->assoclen != 20) {
30318c2ecf20Sopenharmony_ci			pr_err("RFC4309: Invalid AAD length %d\n",
30328c2ecf20Sopenharmony_ci			       req->assoclen);
30338c2ecf20Sopenharmony_ci			return -EINVAL;
30348c2ecf20Sopenharmony_ci		}
30358c2ecf20Sopenharmony_ci	}
30368c2ecf20Sopenharmony_ci	return 0;
30378c2ecf20Sopenharmony_ci}
30388c2ecf20Sopenharmony_ci
30398c2ecf20Sopenharmony_cistatic struct sk_buff *create_aead_ccm_wr(struct aead_request *req,
30408c2ecf20Sopenharmony_ci					  unsigned short qid,
30418c2ecf20Sopenharmony_ci					  int size)
30428c2ecf20Sopenharmony_ci{
30438c2ecf20Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
30448c2ecf20Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm));
30458c2ecf20Sopenharmony_ci	struct chcr_aead_reqctx *reqctx = aead_request_ctx(req);
30468c2ecf20Sopenharmony_ci	struct sk_buff *skb = NULL;
30478c2ecf20Sopenharmony_ci	struct chcr_wr *chcr_req;
30488c2ecf20Sopenharmony_ci	struct cpl_rx_phys_dsgl *phys_cpl;
30498c2ecf20Sopenharmony_ci	struct ulptx_sgl *ulptx;
30508c2ecf20Sopenharmony_ci	unsigned int transhdr_len;
30518c2ecf20Sopenharmony_ci	unsigned int dst_size = 0, kctx_len, dnents, temp, snents;
30528c2ecf20Sopenharmony_ci	unsigned int sub_type, assoclen = req->assoclen;
30538c2ecf20Sopenharmony_ci	unsigned int authsize = crypto_aead_authsize(tfm);
30548c2ecf20Sopenharmony_ci	int error = -EINVAL;
30558c2ecf20Sopenharmony_ci	u8 *ivptr;
30568c2ecf20Sopenharmony_ci	gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
30578c2ecf20Sopenharmony_ci		GFP_ATOMIC;
30588c2ecf20Sopenharmony_ci	struct adapter *adap = padap(a_ctx(tfm)->dev);
30598c2ecf20Sopenharmony_ci
30608c2ecf20Sopenharmony_ci	sub_type = get_aead_subtype(tfm);
30618c2ecf20Sopenharmony_ci	if (sub_type == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309)
30628c2ecf20Sopenharmony_ci		assoclen -= 8;
30638c2ecf20Sopenharmony_ci	reqctx->b0_len = CCM_B0_SIZE + (assoclen ? CCM_AAD_FIELD_SIZE : 0);
30648c2ecf20Sopenharmony_ci	error = chcr_aead_common_init(req);
30658c2ecf20Sopenharmony_ci	if (error)
30668c2ecf20Sopenharmony_ci		return ERR_PTR(error);
30678c2ecf20Sopenharmony_ci
30688c2ecf20Sopenharmony_ci	error = aead_ccm_validate_input(reqctx->op, req, aeadctx, sub_type);
30698c2ecf20Sopenharmony_ci	if (error)
30708c2ecf20Sopenharmony_ci		goto err;
30718c2ecf20Sopenharmony_ci	dnents = sg_nents_xlen(req->dst, req->assoclen + req->cryptlen
30728c2ecf20Sopenharmony_ci			+ (reqctx->op ? -authsize : authsize),
30738c2ecf20Sopenharmony_ci			CHCR_DST_SG_SIZE, 0);
30748c2ecf20Sopenharmony_ci	dnents += MIN_CCM_SG; // For IV and B0
30758c2ecf20Sopenharmony_ci	dst_size = get_space_for_phys_dsgl(dnents);
30768c2ecf20Sopenharmony_ci	snents = sg_nents_xlen(req->src, req->assoclen + req->cryptlen,
30778c2ecf20Sopenharmony_ci			       CHCR_SRC_SG_SIZE, 0);
30788c2ecf20Sopenharmony_ci	snents += MIN_CCM_SG; //For B0
30798c2ecf20Sopenharmony_ci	kctx_len = roundup(aeadctx->enckey_len, 16) * 2;
30808c2ecf20Sopenharmony_ci	transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, dst_size);
30818c2ecf20Sopenharmony_ci	reqctx->imm = (transhdr_len + req->assoclen + req->cryptlen +
30828c2ecf20Sopenharmony_ci		       reqctx->b0_len) <= SGE_MAX_WR_LEN;
30838c2ecf20Sopenharmony_ci	temp = reqctx->imm ? roundup(req->assoclen + req->cryptlen +
30848c2ecf20Sopenharmony_ci				     reqctx->b0_len, 16) :
30858c2ecf20Sopenharmony_ci		(sgl_len(snents) *  8);
30868c2ecf20Sopenharmony_ci	transhdr_len += temp;
30878c2ecf20Sopenharmony_ci	transhdr_len = roundup(transhdr_len, 16);
30888c2ecf20Sopenharmony_ci
30898c2ecf20Sopenharmony_ci	if (chcr_aead_need_fallback(req, dnents, T6_MAX_AAD_SIZE -
30908c2ecf20Sopenharmony_ci				reqctx->b0_len, transhdr_len, reqctx->op)) {
30918c2ecf20Sopenharmony_ci		atomic_inc(&adap->chcr_stats.fallback);
30928c2ecf20Sopenharmony_ci		chcr_aead_common_exit(req);
30938c2ecf20Sopenharmony_ci		return ERR_PTR(chcr_aead_fallback(req, reqctx->op));
30948c2ecf20Sopenharmony_ci	}
30958c2ecf20Sopenharmony_ci	skb = alloc_skb(transhdr_len,  flags);
30968c2ecf20Sopenharmony_ci
30978c2ecf20Sopenharmony_ci	if (!skb) {
30988c2ecf20Sopenharmony_ci		error = -ENOMEM;
30998c2ecf20Sopenharmony_ci		goto err;
31008c2ecf20Sopenharmony_ci	}
31018c2ecf20Sopenharmony_ci
31028c2ecf20Sopenharmony_ci	chcr_req = __skb_put_zero(skb, transhdr_len);
31038c2ecf20Sopenharmony_ci
31048c2ecf20Sopenharmony_ci	fill_sec_cpl_for_aead(&chcr_req->sec_cpl, dst_size, req, reqctx->op);
31058c2ecf20Sopenharmony_ci
31068c2ecf20Sopenharmony_ci	chcr_req->key_ctx.ctx_hdr = aeadctx->key_ctx_hdr;
31078c2ecf20Sopenharmony_ci	memcpy(chcr_req->key_ctx.key, aeadctx->key, aeadctx->enckey_len);
31088c2ecf20Sopenharmony_ci	memcpy(chcr_req->key_ctx.key + roundup(aeadctx->enckey_len, 16),
31098c2ecf20Sopenharmony_ci			aeadctx->key, aeadctx->enckey_len);
31108c2ecf20Sopenharmony_ci
31118c2ecf20Sopenharmony_ci	phys_cpl = (struct cpl_rx_phys_dsgl *)((u8 *)(chcr_req + 1) + kctx_len);
31128c2ecf20Sopenharmony_ci	ivptr = (u8 *)(phys_cpl + 1) + dst_size;
31138c2ecf20Sopenharmony_ci	ulptx = (struct ulptx_sgl *)(ivptr + IV);
31148c2ecf20Sopenharmony_ci	error = ccm_format_packet(req, ivptr, sub_type, reqctx->op, assoclen);
31158c2ecf20Sopenharmony_ci	if (error)
31168c2ecf20Sopenharmony_ci		goto dstmap_fail;
31178c2ecf20Sopenharmony_ci	chcr_add_aead_dst_ent(req, phys_cpl, qid);
31188c2ecf20Sopenharmony_ci	chcr_add_aead_src_ent(req, ulptx);
31198c2ecf20Sopenharmony_ci
31208c2ecf20Sopenharmony_ci	atomic_inc(&adap->chcr_stats.aead_rqst);
31218c2ecf20Sopenharmony_ci	temp = sizeof(struct cpl_rx_phys_dsgl) + dst_size + IV +
31228c2ecf20Sopenharmony_ci		kctx_len + (reqctx->imm ? (req->assoclen + req->cryptlen +
31238c2ecf20Sopenharmony_ci		reqctx->b0_len) : 0);
31248c2ecf20Sopenharmony_ci	create_wreq(a_ctx(tfm), chcr_req, &req->base, reqctx->imm, 0,
31258c2ecf20Sopenharmony_ci		    transhdr_len, temp, 0);
31268c2ecf20Sopenharmony_ci	reqctx->skb = skb;
31278c2ecf20Sopenharmony_ci
31288c2ecf20Sopenharmony_ci	return skb;
31298c2ecf20Sopenharmony_cidstmap_fail:
31308c2ecf20Sopenharmony_ci	kfree_skb(skb);
31318c2ecf20Sopenharmony_cierr:
31328c2ecf20Sopenharmony_ci	chcr_aead_common_exit(req);
31338c2ecf20Sopenharmony_ci	return ERR_PTR(error);
31348c2ecf20Sopenharmony_ci}
31358c2ecf20Sopenharmony_ci
31368c2ecf20Sopenharmony_cistatic struct sk_buff *create_gcm_wr(struct aead_request *req,
31378c2ecf20Sopenharmony_ci				     unsigned short qid,
31388c2ecf20Sopenharmony_ci				     int size)
31398c2ecf20Sopenharmony_ci{
31408c2ecf20Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
31418c2ecf20Sopenharmony_ci	struct chcr_context *ctx = a_ctx(tfm);
31428c2ecf20Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(ctx);
31438c2ecf20Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(ctx);
31448c2ecf20Sopenharmony_ci	struct chcr_aead_reqctx  *reqctx = aead_request_ctx(req);
31458c2ecf20Sopenharmony_ci	struct sk_buff *skb = NULL;
31468c2ecf20Sopenharmony_ci	struct chcr_wr *chcr_req;
31478c2ecf20Sopenharmony_ci	struct cpl_rx_phys_dsgl *phys_cpl;
31488c2ecf20Sopenharmony_ci	struct ulptx_sgl *ulptx;
31498c2ecf20Sopenharmony_ci	unsigned int transhdr_len, dnents = 0, snents;
31508c2ecf20Sopenharmony_ci	unsigned int dst_size = 0, temp = 0, kctx_len, assoclen = req->assoclen;
31518c2ecf20Sopenharmony_ci	unsigned int authsize = crypto_aead_authsize(tfm);
31528c2ecf20Sopenharmony_ci	int error = -EINVAL;
31538c2ecf20Sopenharmony_ci	u8 *ivptr;
31548c2ecf20Sopenharmony_ci	gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
31558c2ecf20Sopenharmony_ci		GFP_ATOMIC;
31568c2ecf20Sopenharmony_ci	struct adapter *adap = padap(ctx->dev);
31578c2ecf20Sopenharmony_ci	unsigned int rx_channel_id = reqctx->rxqidx / ctx->rxq_perchan;
31588c2ecf20Sopenharmony_ci
31598c2ecf20Sopenharmony_ci	rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]);
31608c2ecf20Sopenharmony_ci	if (get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106)
31618c2ecf20Sopenharmony_ci		assoclen = req->assoclen - 8;
31628c2ecf20Sopenharmony_ci
31638c2ecf20Sopenharmony_ci	reqctx->b0_len = 0;
31648c2ecf20Sopenharmony_ci	error = chcr_aead_common_init(req);
31658c2ecf20Sopenharmony_ci	if (error)
31668c2ecf20Sopenharmony_ci		return ERR_PTR(error);
31678c2ecf20Sopenharmony_ci	dnents = sg_nents_xlen(req->dst, req->assoclen + req->cryptlen +
31688c2ecf20Sopenharmony_ci				(reqctx->op ? -authsize : authsize),
31698c2ecf20Sopenharmony_ci				CHCR_DST_SG_SIZE, 0);
31708c2ecf20Sopenharmony_ci	snents = sg_nents_xlen(req->src, req->assoclen + req->cryptlen,
31718c2ecf20Sopenharmony_ci			       CHCR_SRC_SG_SIZE, 0);
31728c2ecf20Sopenharmony_ci	dnents += MIN_GCM_SG; // For IV
31738c2ecf20Sopenharmony_ci	dst_size = get_space_for_phys_dsgl(dnents);
31748c2ecf20Sopenharmony_ci	kctx_len = roundup(aeadctx->enckey_len, 16) + AEAD_H_SIZE;
31758c2ecf20Sopenharmony_ci	transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, dst_size);
31768c2ecf20Sopenharmony_ci	reqctx->imm = (transhdr_len + req->assoclen + req->cryptlen) <=
31778c2ecf20Sopenharmony_ci			SGE_MAX_WR_LEN;
31788c2ecf20Sopenharmony_ci	temp = reqctx->imm ? roundup(req->assoclen + req->cryptlen, 16) :
31798c2ecf20Sopenharmony_ci		(sgl_len(snents) * 8);
31808c2ecf20Sopenharmony_ci	transhdr_len += temp;
31818c2ecf20Sopenharmony_ci	transhdr_len = roundup(transhdr_len, 16);
31828c2ecf20Sopenharmony_ci	if (chcr_aead_need_fallback(req, dnents, T6_MAX_AAD_SIZE,
31838c2ecf20Sopenharmony_ci			    transhdr_len, reqctx->op)) {
31848c2ecf20Sopenharmony_ci
31858c2ecf20Sopenharmony_ci		atomic_inc(&adap->chcr_stats.fallback);
31868c2ecf20Sopenharmony_ci		chcr_aead_common_exit(req);
31878c2ecf20Sopenharmony_ci		return ERR_PTR(chcr_aead_fallback(req, reqctx->op));
31888c2ecf20Sopenharmony_ci	}
31898c2ecf20Sopenharmony_ci	skb = alloc_skb(transhdr_len, flags);
31908c2ecf20Sopenharmony_ci	if (!skb) {
31918c2ecf20Sopenharmony_ci		error = -ENOMEM;
31928c2ecf20Sopenharmony_ci		goto err;
31938c2ecf20Sopenharmony_ci	}
31948c2ecf20Sopenharmony_ci
31958c2ecf20Sopenharmony_ci	chcr_req = __skb_put_zero(skb, transhdr_len);
31968c2ecf20Sopenharmony_ci
31978c2ecf20Sopenharmony_ci	//Offset of tag from end
31988c2ecf20Sopenharmony_ci	temp = (reqctx->op == CHCR_ENCRYPT_OP) ? 0 : authsize;
31998c2ecf20Sopenharmony_ci	chcr_req->sec_cpl.op_ivinsrtofst = FILL_SEC_CPL_OP_IVINSR(
32008c2ecf20Sopenharmony_ci						rx_channel_id, 2, 1);
32018c2ecf20Sopenharmony_ci	chcr_req->sec_cpl.pldlen =
32028c2ecf20Sopenharmony_ci		htonl(req->assoclen + IV + req->cryptlen);
32038c2ecf20Sopenharmony_ci	chcr_req->sec_cpl.aadstart_cipherstop_hi = FILL_SEC_CPL_CIPHERSTOP_HI(
32048c2ecf20Sopenharmony_ci					assoclen ? 1 + IV : 0,
32058c2ecf20Sopenharmony_ci					assoclen ? IV + assoclen : 0,
32068c2ecf20Sopenharmony_ci					req->assoclen + IV + 1, 0);
32078c2ecf20Sopenharmony_ci	chcr_req->sec_cpl.cipherstop_lo_authinsert =
32088c2ecf20Sopenharmony_ci			FILL_SEC_CPL_AUTHINSERT(0, req->assoclen + IV + 1,
32098c2ecf20Sopenharmony_ci						temp, temp);
32108c2ecf20Sopenharmony_ci	chcr_req->sec_cpl.seqno_numivs =
32118c2ecf20Sopenharmony_ci			FILL_SEC_CPL_SCMD0_SEQNO(reqctx->op, (reqctx->op ==
32128c2ecf20Sopenharmony_ci					CHCR_ENCRYPT_OP) ? 1 : 0,
32138c2ecf20Sopenharmony_ci					CHCR_SCMD_CIPHER_MODE_AES_GCM,
32148c2ecf20Sopenharmony_ci					CHCR_SCMD_AUTH_MODE_GHASH,
32158c2ecf20Sopenharmony_ci					aeadctx->hmac_ctrl, IV >> 1);
32168c2ecf20Sopenharmony_ci	chcr_req->sec_cpl.ivgen_hdrlen =  FILL_SEC_CPL_IVGEN_HDRLEN(0, 0, 1,
32178c2ecf20Sopenharmony_ci					0, 0, dst_size);
32188c2ecf20Sopenharmony_ci	chcr_req->key_ctx.ctx_hdr = aeadctx->key_ctx_hdr;
32198c2ecf20Sopenharmony_ci	memcpy(chcr_req->key_ctx.key, aeadctx->key, aeadctx->enckey_len);
32208c2ecf20Sopenharmony_ci	memcpy(chcr_req->key_ctx.key + roundup(aeadctx->enckey_len, 16),
32218c2ecf20Sopenharmony_ci	       GCM_CTX(aeadctx)->ghash_h, AEAD_H_SIZE);
32228c2ecf20Sopenharmony_ci
32238c2ecf20Sopenharmony_ci	phys_cpl = (struct cpl_rx_phys_dsgl *)((u8 *)(chcr_req + 1) + kctx_len);
32248c2ecf20Sopenharmony_ci	ivptr = (u8 *)(phys_cpl + 1) + dst_size;
32258c2ecf20Sopenharmony_ci	/* prepare a 16 byte iv */
32268c2ecf20Sopenharmony_ci	/* S   A   L  T |  IV | 0x00000001 */
32278c2ecf20Sopenharmony_ci	if (get_aead_subtype(tfm) ==
32288c2ecf20Sopenharmony_ci	    CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106) {
32298c2ecf20Sopenharmony_ci		memcpy(ivptr, aeadctx->salt, 4);
32308c2ecf20Sopenharmony_ci		memcpy(ivptr + 4, req->iv, GCM_RFC4106_IV_SIZE);
32318c2ecf20Sopenharmony_ci	} else {
32328c2ecf20Sopenharmony_ci		memcpy(ivptr, req->iv, GCM_AES_IV_SIZE);
32338c2ecf20Sopenharmony_ci	}
32348c2ecf20Sopenharmony_ci	put_unaligned_be32(0x01, &ivptr[12]);
32358c2ecf20Sopenharmony_ci	ulptx = (struct ulptx_sgl *)(ivptr + 16);
32368c2ecf20Sopenharmony_ci
32378c2ecf20Sopenharmony_ci	chcr_add_aead_dst_ent(req, phys_cpl, qid);
32388c2ecf20Sopenharmony_ci	chcr_add_aead_src_ent(req, ulptx);
32398c2ecf20Sopenharmony_ci	atomic_inc(&adap->chcr_stats.aead_rqst);
32408c2ecf20Sopenharmony_ci	temp = sizeof(struct cpl_rx_phys_dsgl) + dst_size + IV +
32418c2ecf20Sopenharmony_ci		kctx_len + (reqctx->imm ? (req->assoclen + req->cryptlen) : 0);
32428c2ecf20Sopenharmony_ci	create_wreq(a_ctx(tfm), chcr_req, &req->base, reqctx->imm, size,
32438c2ecf20Sopenharmony_ci		    transhdr_len, temp, reqctx->verify);
32448c2ecf20Sopenharmony_ci	reqctx->skb = skb;
32458c2ecf20Sopenharmony_ci	return skb;
32468c2ecf20Sopenharmony_ci
32478c2ecf20Sopenharmony_cierr:
32488c2ecf20Sopenharmony_ci	chcr_aead_common_exit(req);
32498c2ecf20Sopenharmony_ci	return ERR_PTR(error);
32508c2ecf20Sopenharmony_ci}
32518c2ecf20Sopenharmony_ci
32528c2ecf20Sopenharmony_ci
32538c2ecf20Sopenharmony_ci
32548c2ecf20Sopenharmony_cistatic int chcr_aead_cra_init(struct crypto_aead *tfm)
32558c2ecf20Sopenharmony_ci{
32568c2ecf20Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm));
32578c2ecf20Sopenharmony_ci	struct aead_alg *alg = crypto_aead_alg(tfm);
32588c2ecf20Sopenharmony_ci
32598c2ecf20Sopenharmony_ci	aeadctx->sw_cipher = crypto_alloc_aead(alg->base.cra_name, 0,
32608c2ecf20Sopenharmony_ci					       CRYPTO_ALG_NEED_FALLBACK |
32618c2ecf20Sopenharmony_ci					       CRYPTO_ALG_ASYNC);
32628c2ecf20Sopenharmony_ci	if  (IS_ERR(aeadctx->sw_cipher))
32638c2ecf20Sopenharmony_ci		return PTR_ERR(aeadctx->sw_cipher);
32648c2ecf20Sopenharmony_ci	crypto_aead_set_reqsize(tfm, max(sizeof(struct chcr_aead_reqctx),
32658c2ecf20Sopenharmony_ci				 sizeof(struct aead_request) +
32668c2ecf20Sopenharmony_ci				 crypto_aead_reqsize(aeadctx->sw_cipher)));
32678c2ecf20Sopenharmony_ci	return chcr_device_init(a_ctx(tfm));
32688c2ecf20Sopenharmony_ci}
32698c2ecf20Sopenharmony_ci
32708c2ecf20Sopenharmony_cistatic void chcr_aead_cra_exit(struct crypto_aead *tfm)
32718c2ecf20Sopenharmony_ci{
32728c2ecf20Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm));
32738c2ecf20Sopenharmony_ci
32748c2ecf20Sopenharmony_ci	crypto_free_aead(aeadctx->sw_cipher);
32758c2ecf20Sopenharmony_ci}
32768c2ecf20Sopenharmony_ci
32778c2ecf20Sopenharmony_cistatic int chcr_authenc_null_setauthsize(struct crypto_aead *tfm,
32788c2ecf20Sopenharmony_ci					unsigned int authsize)
32798c2ecf20Sopenharmony_ci{
32808c2ecf20Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm));
32818c2ecf20Sopenharmony_ci
32828c2ecf20Sopenharmony_ci	aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NOP;
32838c2ecf20Sopenharmony_ci	aeadctx->mayverify = VERIFY_HW;
32848c2ecf20Sopenharmony_ci	return crypto_aead_setauthsize(aeadctx->sw_cipher, authsize);
32858c2ecf20Sopenharmony_ci}
32868c2ecf20Sopenharmony_cistatic int chcr_authenc_setauthsize(struct crypto_aead *tfm,
32878c2ecf20Sopenharmony_ci				    unsigned int authsize)
32888c2ecf20Sopenharmony_ci{
32898c2ecf20Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm));
32908c2ecf20Sopenharmony_ci	u32 maxauth = crypto_aead_maxauthsize(tfm);
32918c2ecf20Sopenharmony_ci
32928c2ecf20Sopenharmony_ci	/*SHA1 authsize in ipsec is 12 instead of 10 i.e maxauthsize / 2 is not
32938c2ecf20Sopenharmony_ci	 * true for sha1. authsize == 12 condition should be before
32948c2ecf20Sopenharmony_ci	 * authsize == (maxauth >> 1)
32958c2ecf20Sopenharmony_ci	 */
32968c2ecf20Sopenharmony_ci	if (authsize == ICV_4) {
32978c2ecf20Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL1;
32988c2ecf20Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
32998c2ecf20Sopenharmony_ci	} else if (authsize == ICV_6) {
33008c2ecf20Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL2;
33018c2ecf20Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
33028c2ecf20Sopenharmony_ci	} else if (authsize == ICV_10) {
33038c2ecf20Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_TRUNC_RFC4366;
33048c2ecf20Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
33058c2ecf20Sopenharmony_ci	} else if (authsize == ICV_12) {
33068c2ecf20Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_IPSEC_96BIT;
33078c2ecf20Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
33088c2ecf20Sopenharmony_ci	} else if (authsize == ICV_14) {
33098c2ecf20Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL3;
33108c2ecf20Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
33118c2ecf20Sopenharmony_ci	} else if (authsize == (maxauth >> 1)) {
33128c2ecf20Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_DIV2;
33138c2ecf20Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
33148c2ecf20Sopenharmony_ci	} else if (authsize == maxauth) {
33158c2ecf20Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC;
33168c2ecf20Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
33178c2ecf20Sopenharmony_ci	} else {
33188c2ecf20Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC;
33198c2ecf20Sopenharmony_ci		aeadctx->mayverify = VERIFY_SW;
33208c2ecf20Sopenharmony_ci	}
33218c2ecf20Sopenharmony_ci	return crypto_aead_setauthsize(aeadctx->sw_cipher, authsize);
33228c2ecf20Sopenharmony_ci}
33238c2ecf20Sopenharmony_ci
33248c2ecf20Sopenharmony_ci
33258c2ecf20Sopenharmony_cistatic int chcr_gcm_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
33268c2ecf20Sopenharmony_ci{
33278c2ecf20Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm));
33288c2ecf20Sopenharmony_ci
33298c2ecf20Sopenharmony_ci	switch (authsize) {
33308c2ecf20Sopenharmony_ci	case ICV_4:
33318c2ecf20Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL1;
33328c2ecf20Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
33338c2ecf20Sopenharmony_ci		break;
33348c2ecf20Sopenharmony_ci	case ICV_8:
33358c2ecf20Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_DIV2;
33368c2ecf20Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
33378c2ecf20Sopenharmony_ci		break;
33388c2ecf20Sopenharmony_ci	case ICV_12:
33398c2ecf20Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_IPSEC_96BIT;
33408c2ecf20Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
33418c2ecf20Sopenharmony_ci		break;
33428c2ecf20Sopenharmony_ci	case ICV_14:
33438c2ecf20Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL3;
33448c2ecf20Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
33458c2ecf20Sopenharmony_ci		break;
33468c2ecf20Sopenharmony_ci	case ICV_16:
33478c2ecf20Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC;
33488c2ecf20Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
33498c2ecf20Sopenharmony_ci		break;
33508c2ecf20Sopenharmony_ci	case ICV_13:
33518c2ecf20Sopenharmony_ci	case ICV_15:
33528c2ecf20Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC;
33538c2ecf20Sopenharmony_ci		aeadctx->mayverify = VERIFY_SW;
33548c2ecf20Sopenharmony_ci		break;
33558c2ecf20Sopenharmony_ci	default:
33568c2ecf20Sopenharmony_ci		return -EINVAL;
33578c2ecf20Sopenharmony_ci	}
33588c2ecf20Sopenharmony_ci	return crypto_aead_setauthsize(aeadctx->sw_cipher, authsize);
33598c2ecf20Sopenharmony_ci}
33608c2ecf20Sopenharmony_ci
33618c2ecf20Sopenharmony_cistatic int chcr_4106_4309_setauthsize(struct crypto_aead *tfm,
33628c2ecf20Sopenharmony_ci					  unsigned int authsize)
33638c2ecf20Sopenharmony_ci{
33648c2ecf20Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm));
33658c2ecf20Sopenharmony_ci
33668c2ecf20Sopenharmony_ci	switch (authsize) {
33678c2ecf20Sopenharmony_ci	case ICV_8:
33688c2ecf20Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_DIV2;
33698c2ecf20Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
33708c2ecf20Sopenharmony_ci		break;
33718c2ecf20Sopenharmony_ci	case ICV_12:
33728c2ecf20Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_IPSEC_96BIT;
33738c2ecf20Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
33748c2ecf20Sopenharmony_ci		break;
33758c2ecf20Sopenharmony_ci	case ICV_16:
33768c2ecf20Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC;
33778c2ecf20Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
33788c2ecf20Sopenharmony_ci		break;
33798c2ecf20Sopenharmony_ci	default:
33808c2ecf20Sopenharmony_ci		return -EINVAL;
33818c2ecf20Sopenharmony_ci	}
33828c2ecf20Sopenharmony_ci	return crypto_aead_setauthsize(aeadctx->sw_cipher, authsize);
33838c2ecf20Sopenharmony_ci}
33848c2ecf20Sopenharmony_ci
33858c2ecf20Sopenharmony_cistatic int chcr_ccm_setauthsize(struct crypto_aead *tfm,
33868c2ecf20Sopenharmony_ci				unsigned int authsize)
33878c2ecf20Sopenharmony_ci{
33888c2ecf20Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm));
33898c2ecf20Sopenharmony_ci
33908c2ecf20Sopenharmony_ci	switch (authsize) {
33918c2ecf20Sopenharmony_ci	case ICV_4:
33928c2ecf20Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL1;
33938c2ecf20Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
33948c2ecf20Sopenharmony_ci		break;
33958c2ecf20Sopenharmony_ci	case ICV_6:
33968c2ecf20Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL2;
33978c2ecf20Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
33988c2ecf20Sopenharmony_ci		break;
33998c2ecf20Sopenharmony_ci	case ICV_8:
34008c2ecf20Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_DIV2;
34018c2ecf20Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
34028c2ecf20Sopenharmony_ci		break;
34038c2ecf20Sopenharmony_ci	case ICV_10:
34048c2ecf20Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_TRUNC_RFC4366;
34058c2ecf20Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
34068c2ecf20Sopenharmony_ci		break;
34078c2ecf20Sopenharmony_ci	case ICV_12:
34088c2ecf20Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_IPSEC_96BIT;
34098c2ecf20Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
34108c2ecf20Sopenharmony_ci		break;
34118c2ecf20Sopenharmony_ci	case ICV_14:
34128c2ecf20Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL3;
34138c2ecf20Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
34148c2ecf20Sopenharmony_ci		break;
34158c2ecf20Sopenharmony_ci	case ICV_16:
34168c2ecf20Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC;
34178c2ecf20Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
34188c2ecf20Sopenharmony_ci		break;
34198c2ecf20Sopenharmony_ci	default:
34208c2ecf20Sopenharmony_ci		return -EINVAL;
34218c2ecf20Sopenharmony_ci	}
34228c2ecf20Sopenharmony_ci	return crypto_aead_setauthsize(aeadctx->sw_cipher, authsize);
34238c2ecf20Sopenharmony_ci}
34248c2ecf20Sopenharmony_ci
34258c2ecf20Sopenharmony_cistatic int chcr_ccm_common_setkey(struct crypto_aead *aead,
34268c2ecf20Sopenharmony_ci				const u8 *key,
34278c2ecf20Sopenharmony_ci				unsigned int keylen)
34288c2ecf20Sopenharmony_ci{
34298c2ecf20Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(aead));
34308c2ecf20Sopenharmony_ci	unsigned char ck_size, mk_size;
34318c2ecf20Sopenharmony_ci	int key_ctx_size = 0;
34328c2ecf20Sopenharmony_ci
34338c2ecf20Sopenharmony_ci	key_ctx_size = sizeof(struct _key_ctx) + roundup(keylen, 16) * 2;
34348c2ecf20Sopenharmony_ci	if (keylen == AES_KEYSIZE_128) {
34358c2ecf20Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128;
34368c2ecf20Sopenharmony_ci		mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_128;
34378c2ecf20Sopenharmony_ci	} else if (keylen == AES_KEYSIZE_192) {
34388c2ecf20Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_192;
34398c2ecf20Sopenharmony_ci		mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_192;
34408c2ecf20Sopenharmony_ci	} else if (keylen == AES_KEYSIZE_256) {
34418c2ecf20Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256;
34428c2ecf20Sopenharmony_ci		mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_256;
34438c2ecf20Sopenharmony_ci	} else {
34448c2ecf20Sopenharmony_ci		aeadctx->enckey_len = 0;
34458c2ecf20Sopenharmony_ci		return	-EINVAL;
34468c2ecf20Sopenharmony_ci	}
34478c2ecf20Sopenharmony_ci	aeadctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, mk_size, 0, 0,
34488c2ecf20Sopenharmony_ci						key_ctx_size >> 4);
34498c2ecf20Sopenharmony_ci	memcpy(aeadctx->key, key, keylen);
34508c2ecf20Sopenharmony_ci	aeadctx->enckey_len = keylen;
34518c2ecf20Sopenharmony_ci
34528c2ecf20Sopenharmony_ci	return 0;
34538c2ecf20Sopenharmony_ci}
34548c2ecf20Sopenharmony_ci
34558c2ecf20Sopenharmony_cistatic int chcr_aead_ccm_setkey(struct crypto_aead *aead,
34568c2ecf20Sopenharmony_ci				const u8 *key,
34578c2ecf20Sopenharmony_ci				unsigned int keylen)
34588c2ecf20Sopenharmony_ci{
34598c2ecf20Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(aead));
34608c2ecf20Sopenharmony_ci	int error;
34618c2ecf20Sopenharmony_ci
34628c2ecf20Sopenharmony_ci	crypto_aead_clear_flags(aeadctx->sw_cipher, CRYPTO_TFM_REQ_MASK);
34638c2ecf20Sopenharmony_ci	crypto_aead_set_flags(aeadctx->sw_cipher, crypto_aead_get_flags(aead) &
34648c2ecf20Sopenharmony_ci			      CRYPTO_TFM_REQ_MASK);
34658c2ecf20Sopenharmony_ci	error = crypto_aead_setkey(aeadctx->sw_cipher, key, keylen);
34668c2ecf20Sopenharmony_ci	if (error)
34678c2ecf20Sopenharmony_ci		return error;
34688c2ecf20Sopenharmony_ci	return chcr_ccm_common_setkey(aead, key, keylen);
34698c2ecf20Sopenharmony_ci}
34708c2ecf20Sopenharmony_ci
34718c2ecf20Sopenharmony_cistatic int chcr_aead_rfc4309_setkey(struct crypto_aead *aead, const u8 *key,
34728c2ecf20Sopenharmony_ci				    unsigned int keylen)
34738c2ecf20Sopenharmony_ci{
34748c2ecf20Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(aead));
34758c2ecf20Sopenharmony_ci	int error;
34768c2ecf20Sopenharmony_ci
34778c2ecf20Sopenharmony_ci	if (keylen < 3) {
34788c2ecf20Sopenharmony_ci		aeadctx->enckey_len = 0;
34798c2ecf20Sopenharmony_ci		return	-EINVAL;
34808c2ecf20Sopenharmony_ci	}
34818c2ecf20Sopenharmony_ci	crypto_aead_clear_flags(aeadctx->sw_cipher, CRYPTO_TFM_REQ_MASK);
34828c2ecf20Sopenharmony_ci	crypto_aead_set_flags(aeadctx->sw_cipher, crypto_aead_get_flags(aead) &
34838c2ecf20Sopenharmony_ci			      CRYPTO_TFM_REQ_MASK);
34848c2ecf20Sopenharmony_ci	error = crypto_aead_setkey(aeadctx->sw_cipher, key, keylen);
34858c2ecf20Sopenharmony_ci	if (error)
34868c2ecf20Sopenharmony_ci		return error;
34878c2ecf20Sopenharmony_ci	keylen -= 3;
34888c2ecf20Sopenharmony_ci	memcpy(aeadctx->salt, key + keylen, 3);
34898c2ecf20Sopenharmony_ci	return chcr_ccm_common_setkey(aead, key, keylen);
34908c2ecf20Sopenharmony_ci}
34918c2ecf20Sopenharmony_ci
34928c2ecf20Sopenharmony_cistatic int chcr_gcm_setkey(struct crypto_aead *aead, const u8 *key,
34938c2ecf20Sopenharmony_ci			   unsigned int keylen)
34948c2ecf20Sopenharmony_ci{
34958c2ecf20Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(aead));
34968c2ecf20Sopenharmony_ci	struct chcr_gcm_ctx *gctx = GCM_CTX(aeadctx);
34978c2ecf20Sopenharmony_ci	unsigned int ck_size;
34988c2ecf20Sopenharmony_ci	int ret = 0, key_ctx_size = 0;
34998c2ecf20Sopenharmony_ci	struct crypto_aes_ctx aes;
35008c2ecf20Sopenharmony_ci
35018c2ecf20Sopenharmony_ci	aeadctx->enckey_len = 0;
35028c2ecf20Sopenharmony_ci	crypto_aead_clear_flags(aeadctx->sw_cipher, CRYPTO_TFM_REQ_MASK);
35038c2ecf20Sopenharmony_ci	crypto_aead_set_flags(aeadctx->sw_cipher, crypto_aead_get_flags(aead)
35048c2ecf20Sopenharmony_ci			      & CRYPTO_TFM_REQ_MASK);
35058c2ecf20Sopenharmony_ci	ret = crypto_aead_setkey(aeadctx->sw_cipher, key, keylen);
35068c2ecf20Sopenharmony_ci	if (ret)
35078c2ecf20Sopenharmony_ci		goto out;
35088c2ecf20Sopenharmony_ci
35098c2ecf20Sopenharmony_ci	if (get_aead_subtype(aead) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106 &&
35108c2ecf20Sopenharmony_ci	    keylen > 3) {
35118c2ecf20Sopenharmony_ci		keylen -= 4;  /* nonce/salt is present in the last 4 bytes */
35128c2ecf20Sopenharmony_ci		memcpy(aeadctx->salt, key + keylen, 4);
35138c2ecf20Sopenharmony_ci	}
35148c2ecf20Sopenharmony_ci	if (keylen == AES_KEYSIZE_128) {
35158c2ecf20Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128;
35168c2ecf20Sopenharmony_ci	} else if (keylen == AES_KEYSIZE_192) {
35178c2ecf20Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_192;
35188c2ecf20Sopenharmony_ci	} else if (keylen == AES_KEYSIZE_256) {
35198c2ecf20Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256;
35208c2ecf20Sopenharmony_ci	} else {
35218c2ecf20Sopenharmony_ci		pr_err("GCM: Invalid key length %d\n", keylen);
35228c2ecf20Sopenharmony_ci		ret = -EINVAL;
35238c2ecf20Sopenharmony_ci		goto out;
35248c2ecf20Sopenharmony_ci	}
35258c2ecf20Sopenharmony_ci
35268c2ecf20Sopenharmony_ci	memcpy(aeadctx->key, key, keylen);
35278c2ecf20Sopenharmony_ci	aeadctx->enckey_len = keylen;
35288c2ecf20Sopenharmony_ci	key_ctx_size = sizeof(struct _key_ctx) + roundup(keylen, 16) +
35298c2ecf20Sopenharmony_ci		AEAD_H_SIZE;
35308c2ecf20Sopenharmony_ci	aeadctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size,
35318c2ecf20Sopenharmony_ci						CHCR_KEYCTX_MAC_KEY_SIZE_128,
35328c2ecf20Sopenharmony_ci						0, 0,
35338c2ecf20Sopenharmony_ci						key_ctx_size >> 4);
35348c2ecf20Sopenharmony_ci	/* Calculate the H = CIPH(K, 0 repeated 16 times).
35358c2ecf20Sopenharmony_ci	 * It will go in key context
35368c2ecf20Sopenharmony_ci	 */
35378c2ecf20Sopenharmony_ci	ret = aes_expandkey(&aes, key, keylen);
35388c2ecf20Sopenharmony_ci	if (ret) {
35398c2ecf20Sopenharmony_ci		aeadctx->enckey_len = 0;
35408c2ecf20Sopenharmony_ci		goto out;
35418c2ecf20Sopenharmony_ci	}
35428c2ecf20Sopenharmony_ci	memset(gctx->ghash_h, 0, AEAD_H_SIZE);
35438c2ecf20Sopenharmony_ci	aes_encrypt(&aes, gctx->ghash_h, gctx->ghash_h);
35448c2ecf20Sopenharmony_ci	memzero_explicit(&aes, sizeof(aes));
35458c2ecf20Sopenharmony_ci
35468c2ecf20Sopenharmony_ciout:
35478c2ecf20Sopenharmony_ci	return ret;
35488c2ecf20Sopenharmony_ci}
35498c2ecf20Sopenharmony_ci
35508c2ecf20Sopenharmony_cistatic int chcr_authenc_setkey(struct crypto_aead *authenc, const u8 *key,
35518c2ecf20Sopenharmony_ci				   unsigned int keylen)
35528c2ecf20Sopenharmony_ci{
35538c2ecf20Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(authenc));
35548c2ecf20Sopenharmony_ci	struct chcr_authenc_ctx *actx = AUTHENC_CTX(aeadctx);
35558c2ecf20Sopenharmony_ci	/* it contains auth and cipher key both*/
35568c2ecf20Sopenharmony_ci	struct crypto_authenc_keys keys;
35578c2ecf20Sopenharmony_ci	unsigned int bs, subtype;
35588c2ecf20Sopenharmony_ci	unsigned int max_authsize = crypto_aead_alg(authenc)->maxauthsize;
35598c2ecf20Sopenharmony_ci	int err = 0, i, key_ctx_len = 0;
35608c2ecf20Sopenharmony_ci	unsigned char ck_size = 0;
35618c2ecf20Sopenharmony_ci	unsigned char pad[CHCR_HASH_MAX_BLOCK_SIZE_128] = { 0 };
35628c2ecf20Sopenharmony_ci	struct crypto_shash *base_hash = ERR_PTR(-EINVAL);
35638c2ecf20Sopenharmony_ci	struct algo_param param;
35648c2ecf20Sopenharmony_ci	int align;
35658c2ecf20Sopenharmony_ci	u8 *o_ptr = NULL;
35668c2ecf20Sopenharmony_ci
35678c2ecf20Sopenharmony_ci	crypto_aead_clear_flags(aeadctx->sw_cipher, CRYPTO_TFM_REQ_MASK);
35688c2ecf20Sopenharmony_ci	crypto_aead_set_flags(aeadctx->sw_cipher, crypto_aead_get_flags(authenc)
35698c2ecf20Sopenharmony_ci			      & CRYPTO_TFM_REQ_MASK);
35708c2ecf20Sopenharmony_ci	err = crypto_aead_setkey(aeadctx->sw_cipher, key, keylen);
35718c2ecf20Sopenharmony_ci	if (err)
35728c2ecf20Sopenharmony_ci		goto out;
35738c2ecf20Sopenharmony_ci
35748c2ecf20Sopenharmony_ci	if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
35758c2ecf20Sopenharmony_ci		goto out;
35768c2ecf20Sopenharmony_ci
35778c2ecf20Sopenharmony_ci	if (get_alg_config(&param, max_authsize)) {
35788c2ecf20Sopenharmony_ci		pr_err("Unsupported digest size\n");
35798c2ecf20Sopenharmony_ci		goto out;
35808c2ecf20Sopenharmony_ci	}
35818c2ecf20Sopenharmony_ci	subtype = get_aead_subtype(authenc);
35828c2ecf20Sopenharmony_ci	if (subtype == CRYPTO_ALG_SUB_TYPE_CTR_SHA ||
35838c2ecf20Sopenharmony_ci		subtype == CRYPTO_ALG_SUB_TYPE_CTR_NULL) {
35848c2ecf20Sopenharmony_ci		if (keys.enckeylen < CTR_RFC3686_NONCE_SIZE)
35858c2ecf20Sopenharmony_ci			goto out;
35868c2ecf20Sopenharmony_ci		memcpy(aeadctx->nonce, keys.enckey + (keys.enckeylen
35878c2ecf20Sopenharmony_ci		- CTR_RFC3686_NONCE_SIZE), CTR_RFC3686_NONCE_SIZE);
35888c2ecf20Sopenharmony_ci		keys.enckeylen -= CTR_RFC3686_NONCE_SIZE;
35898c2ecf20Sopenharmony_ci	}
35908c2ecf20Sopenharmony_ci	if (keys.enckeylen == AES_KEYSIZE_128) {
35918c2ecf20Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128;
35928c2ecf20Sopenharmony_ci	} else if (keys.enckeylen == AES_KEYSIZE_192) {
35938c2ecf20Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_192;
35948c2ecf20Sopenharmony_ci	} else if (keys.enckeylen == AES_KEYSIZE_256) {
35958c2ecf20Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256;
35968c2ecf20Sopenharmony_ci	} else {
35978c2ecf20Sopenharmony_ci		pr_err("Unsupported cipher key\n");
35988c2ecf20Sopenharmony_ci		goto out;
35998c2ecf20Sopenharmony_ci	}
36008c2ecf20Sopenharmony_ci
36018c2ecf20Sopenharmony_ci	/* Copy only encryption key. We use authkey to generate h(ipad) and
36028c2ecf20Sopenharmony_ci	 * h(opad) so authkey is not needed again. authkeylen size have the
36038c2ecf20Sopenharmony_ci	 * size of the hash digest size.
36048c2ecf20Sopenharmony_ci	 */
36058c2ecf20Sopenharmony_ci	memcpy(aeadctx->key, keys.enckey, keys.enckeylen);
36068c2ecf20Sopenharmony_ci	aeadctx->enckey_len = keys.enckeylen;
36078c2ecf20Sopenharmony_ci	if (subtype == CRYPTO_ALG_SUB_TYPE_CBC_SHA ||
36088c2ecf20Sopenharmony_ci		subtype == CRYPTO_ALG_SUB_TYPE_CBC_NULL) {
36098c2ecf20Sopenharmony_ci
36108c2ecf20Sopenharmony_ci		get_aes_decrypt_key(actx->dec_rrkey, aeadctx->key,
36118c2ecf20Sopenharmony_ci			    aeadctx->enckey_len << 3);
36128c2ecf20Sopenharmony_ci	}
36138c2ecf20Sopenharmony_ci	base_hash  = chcr_alloc_shash(max_authsize);
36148c2ecf20Sopenharmony_ci	if (IS_ERR(base_hash)) {
36158c2ecf20Sopenharmony_ci		pr_err("Base driver cannot be loaded\n");
36168c2ecf20Sopenharmony_ci		goto out;
36178c2ecf20Sopenharmony_ci	}
36188c2ecf20Sopenharmony_ci	{
36198c2ecf20Sopenharmony_ci		SHASH_DESC_ON_STACK(shash, base_hash);
36208c2ecf20Sopenharmony_ci
36218c2ecf20Sopenharmony_ci		shash->tfm = base_hash;
36228c2ecf20Sopenharmony_ci		bs = crypto_shash_blocksize(base_hash);
36238c2ecf20Sopenharmony_ci		align = KEYCTX_ALIGN_PAD(max_authsize);
36248c2ecf20Sopenharmony_ci		o_ptr =  actx->h_iopad + param.result_size + align;
36258c2ecf20Sopenharmony_ci
36268c2ecf20Sopenharmony_ci		if (keys.authkeylen > bs) {
36278c2ecf20Sopenharmony_ci			err = crypto_shash_digest(shash, keys.authkey,
36288c2ecf20Sopenharmony_ci						  keys.authkeylen,
36298c2ecf20Sopenharmony_ci						  o_ptr);
36308c2ecf20Sopenharmony_ci			if (err) {
36318c2ecf20Sopenharmony_ci				pr_err("Base driver cannot be loaded\n");
36328c2ecf20Sopenharmony_ci				goto out;
36338c2ecf20Sopenharmony_ci			}
36348c2ecf20Sopenharmony_ci			keys.authkeylen = max_authsize;
36358c2ecf20Sopenharmony_ci		} else
36368c2ecf20Sopenharmony_ci			memcpy(o_ptr, keys.authkey, keys.authkeylen);
36378c2ecf20Sopenharmony_ci
36388c2ecf20Sopenharmony_ci		/* Compute the ipad-digest*/
36398c2ecf20Sopenharmony_ci		memset(pad + keys.authkeylen, 0, bs - keys.authkeylen);
36408c2ecf20Sopenharmony_ci		memcpy(pad, o_ptr, keys.authkeylen);
36418c2ecf20Sopenharmony_ci		for (i = 0; i < bs >> 2; i++)
36428c2ecf20Sopenharmony_ci			*((unsigned int *)pad + i) ^= IPAD_DATA;
36438c2ecf20Sopenharmony_ci
36448c2ecf20Sopenharmony_ci		if (chcr_compute_partial_hash(shash, pad, actx->h_iopad,
36458c2ecf20Sopenharmony_ci					      max_authsize))
36468c2ecf20Sopenharmony_ci			goto out;
36478c2ecf20Sopenharmony_ci		/* Compute the opad-digest */
36488c2ecf20Sopenharmony_ci		memset(pad + keys.authkeylen, 0, bs - keys.authkeylen);
36498c2ecf20Sopenharmony_ci		memcpy(pad, o_ptr, keys.authkeylen);
36508c2ecf20Sopenharmony_ci		for (i = 0; i < bs >> 2; i++)
36518c2ecf20Sopenharmony_ci			*((unsigned int *)pad + i) ^= OPAD_DATA;
36528c2ecf20Sopenharmony_ci
36538c2ecf20Sopenharmony_ci		if (chcr_compute_partial_hash(shash, pad, o_ptr, max_authsize))
36548c2ecf20Sopenharmony_ci			goto out;
36558c2ecf20Sopenharmony_ci
36568c2ecf20Sopenharmony_ci		/* convert the ipad and opad digest to network order */
36578c2ecf20Sopenharmony_ci		chcr_change_order(actx->h_iopad, param.result_size);
36588c2ecf20Sopenharmony_ci		chcr_change_order(o_ptr, param.result_size);
36598c2ecf20Sopenharmony_ci		key_ctx_len = sizeof(struct _key_ctx) +
36608c2ecf20Sopenharmony_ci			roundup(keys.enckeylen, 16) +
36618c2ecf20Sopenharmony_ci			(param.result_size + align) * 2;
36628c2ecf20Sopenharmony_ci		aeadctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, param.mk_size,
36638c2ecf20Sopenharmony_ci						0, 1, key_ctx_len >> 4);
36648c2ecf20Sopenharmony_ci		actx->auth_mode = param.auth_mode;
36658c2ecf20Sopenharmony_ci		chcr_free_shash(base_hash);
36668c2ecf20Sopenharmony_ci
36678c2ecf20Sopenharmony_ci		memzero_explicit(&keys, sizeof(keys));
36688c2ecf20Sopenharmony_ci		return 0;
36698c2ecf20Sopenharmony_ci	}
36708c2ecf20Sopenharmony_ciout:
36718c2ecf20Sopenharmony_ci	aeadctx->enckey_len = 0;
36728c2ecf20Sopenharmony_ci	memzero_explicit(&keys, sizeof(keys));
36738c2ecf20Sopenharmony_ci	if (!IS_ERR(base_hash))
36748c2ecf20Sopenharmony_ci		chcr_free_shash(base_hash);
36758c2ecf20Sopenharmony_ci	return -EINVAL;
36768c2ecf20Sopenharmony_ci}
36778c2ecf20Sopenharmony_ci
36788c2ecf20Sopenharmony_cistatic int chcr_aead_digest_null_setkey(struct crypto_aead *authenc,
36798c2ecf20Sopenharmony_ci					const u8 *key, unsigned int keylen)
36808c2ecf20Sopenharmony_ci{
36818c2ecf20Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(authenc));
36828c2ecf20Sopenharmony_ci	struct chcr_authenc_ctx *actx = AUTHENC_CTX(aeadctx);
36838c2ecf20Sopenharmony_ci	struct crypto_authenc_keys keys;
36848c2ecf20Sopenharmony_ci	int err;
36858c2ecf20Sopenharmony_ci	/* it contains auth and cipher key both*/
36868c2ecf20Sopenharmony_ci	unsigned int subtype;
36878c2ecf20Sopenharmony_ci	int key_ctx_len = 0;
36888c2ecf20Sopenharmony_ci	unsigned char ck_size = 0;
36898c2ecf20Sopenharmony_ci
36908c2ecf20Sopenharmony_ci	crypto_aead_clear_flags(aeadctx->sw_cipher, CRYPTO_TFM_REQ_MASK);
36918c2ecf20Sopenharmony_ci	crypto_aead_set_flags(aeadctx->sw_cipher, crypto_aead_get_flags(authenc)
36928c2ecf20Sopenharmony_ci			      & CRYPTO_TFM_REQ_MASK);
36938c2ecf20Sopenharmony_ci	err = crypto_aead_setkey(aeadctx->sw_cipher, key, keylen);
36948c2ecf20Sopenharmony_ci	if (err)
36958c2ecf20Sopenharmony_ci		goto out;
36968c2ecf20Sopenharmony_ci
36978c2ecf20Sopenharmony_ci	if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
36988c2ecf20Sopenharmony_ci		goto out;
36998c2ecf20Sopenharmony_ci
37008c2ecf20Sopenharmony_ci	subtype = get_aead_subtype(authenc);
37018c2ecf20Sopenharmony_ci	if (subtype == CRYPTO_ALG_SUB_TYPE_CTR_SHA ||
37028c2ecf20Sopenharmony_ci	    subtype == CRYPTO_ALG_SUB_TYPE_CTR_NULL) {
37038c2ecf20Sopenharmony_ci		if (keys.enckeylen < CTR_RFC3686_NONCE_SIZE)
37048c2ecf20Sopenharmony_ci			goto out;
37058c2ecf20Sopenharmony_ci		memcpy(aeadctx->nonce, keys.enckey + (keys.enckeylen
37068c2ecf20Sopenharmony_ci			- CTR_RFC3686_NONCE_SIZE), CTR_RFC3686_NONCE_SIZE);
37078c2ecf20Sopenharmony_ci		keys.enckeylen -= CTR_RFC3686_NONCE_SIZE;
37088c2ecf20Sopenharmony_ci	}
37098c2ecf20Sopenharmony_ci	if (keys.enckeylen == AES_KEYSIZE_128) {
37108c2ecf20Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128;
37118c2ecf20Sopenharmony_ci	} else if (keys.enckeylen == AES_KEYSIZE_192) {
37128c2ecf20Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_192;
37138c2ecf20Sopenharmony_ci	} else if (keys.enckeylen == AES_KEYSIZE_256) {
37148c2ecf20Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256;
37158c2ecf20Sopenharmony_ci	} else {
37168c2ecf20Sopenharmony_ci		pr_err("Unsupported cipher key %d\n", keys.enckeylen);
37178c2ecf20Sopenharmony_ci		goto out;
37188c2ecf20Sopenharmony_ci	}
37198c2ecf20Sopenharmony_ci	memcpy(aeadctx->key, keys.enckey, keys.enckeylen);
37208c2ecf20Sopenharmony_ci	aeadctx->enckey_len = keys.enckeylen;
37218c2ecf20Sopenharmony_ci	if (subtype == CRYPTO_ALG_SUB_TYPE_CBC_SHA ||
37228c2ecf20Sopenharmony_ci	    subtype == CRYPTO_ALG_SUB_TYPE_CBC_NULL) {
37238c2ecf20Sopenharmony_ci		get_aes_decrypt_key(actx->dec_rrkey, aeadctx->key,
37248c2ecf20Sopenharmony_ci				aeadctx->enckey_len << 3);
37258c2ecf20Sopenharmony_ci	}
37268c2ecf20Sopenharmony_ci	key_ctx_len =  sizeof(struct _key_ctx) + roundup(keys.enckeylen, 16);
37278c2ecf20Sopenharmony_ci
37288c2ecf20Sopenharmony_ci	aeadctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, CHCR_KEYCTX_NO_KEY, 0,
37298c2ecf20Sopenharmony_ci						0, key_ctx_len >> 4);
37308c2ecf20Sopenharmony_ci	actx->auth_mode = CHCR_SCMD_AUTH_MODE_NOP;
37318c2ecf20Sopenharmony_ci	memzero_explicit(&keys, sizeof(keys));
37328c2ecf20Sopenharmony_ci	return 0;
37338c2ecf20Sopenharmony_ciout:
37348c2ecf20Sopenharmony_ci	aeadctx->enckey_len = 0;
37358c2ecf20Sopenharmony_ci	memzero_explicit(&keys, sizeof(keys));
37368c2ecf20Sopenharmony_ci	return -EINVAL;
37378c2ecf20Sopenharmony_ci}
37388c2ecf20Sopenharmony_ci
37398c2ecf20Sopenharmony_cistatic int chcr_aead_op(struct aead_request *req,
37408c2ecf20Sopenharmony_ci			int size,
37418c2ecf20Sopenharmony_ci			create_wr_t create_wr_fn)
37428c2ecf20Sopenharmony_ci{
37438c2ecf20Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
37448c2ecf20Sopenharmony_ci	struct chcr_aead_reqctx  *reqctx = aead_request_ctx(req);
37458c2ecf20Sopenharmony_ci	struct chcr_context *ctx = a_ctx(tfm);
37468c2ecf20Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(ctx);
37478c2ecf20Sopenharmony_ci	struct sk_buff *skb;
37488c2ecf20Sopenharmony_ci	struct chcr_dev *cdev;
37498c2ecf20Sopenharmony_ci
37508c2ecf20Sopenharmony_ci	cdev = a_ctx(tfm)->dev;
37518c2ecf20Sopenharmony_ci	if (!cdev) {
37528c2ecf20Sopenharmony_ci		pr_err("%s : No crypto device.\n", __func__);
37538c2ecf20Sopenharmony_ci		return -ENXIO;
37548c2ecf20Sopenharmony_ci	}
37558c2ecf20Sopenharmony_ci
37568c2ecf20Sopenharmony_ci	if (chcr_inc_wrcount(cdev)) {
37578c2ecf20Sopenharmony_ci	/* Detach state for CHCR means lldi or padap is freed.
37588c2ecf20Sopenharmony_ci	 * We cannot increment fallback here.
37598c2ecf20Sopenharmony_ci	 */
37608c2ecf20Sopenharmony_ci		return chcr_aead_fallback(req, reqctx->op);
37618c2ecf20Sopenharmony_ci	}
37628c2ecf20Sopenharmony_ci
37638c2ecf20Sopenharmony_ci	if (cxgb4_is_crypto_q_full(u_ctx->lldi.ports[0],
37648c2ecf20Sopenharmony_ci					reqctx->txqidx) &&
37658c2ecf20Sopenharmony_ci		(!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG))) {
37668c2ecf20Sopenharmony_ci			chcr_dec_wrcount(cdev);
37678c2ecf20Sopenharmony_ci			return -ENOSPC;
37688c2ecf20Sopenharmony_ci	}
37698c2ecf20Sopenharmony_ci
37708c2ecf20Sopenharmony_ci	if (get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106 &&
37718c2ecf20Sopenharmony_ci	    crypto_ipsec_check_assoclen(req->assoclen) != 0) {
37728c2ecf20Sopenharmony_ci		pr_err("RFC4106: Invalid value of assoclen %d\n",
37738c2ecf20Sopenharmony_ci		       req->assoclen);
37748c2ecf20Sopenharmony_ci		return -EINVAL;
37758c2ecf20Sopenharmony_ci	}
37768c2ecf20Sopenharmony_ci
37778c2ecf20Sopenharmony_ci	/* Form a WR from req */
37788c2ecf20Sopenharmony_ci	skb = create_wr_fn(req, u_ctx->lldi.rxq_ids[reqctx->rxqidx], size);
37798c2ecf20Sopenharmony_ci
37808c2ecf20Sopenharmony_ci	if (IS_ERR_OR_NULL(skb)) {
37818c2ecf20Sopenharmony_ci		chcr_dec_wrcount(cdev);
37828c2ecf20Sopenharmony_ci		return PTR_ERR_OR_ZERO(skb);
37838c2ecf20Sopenharmony_ci	}
37848c2ecf20Sopenharmony_ci
37858c2ecf20Sopenharmony_ci	skb->dev = u_ctx->lldi.ports[0];
37868c2ecf20Sopenharmony_ci	set_wr_txq(skb, CPL_PRIORITY_DATA, reqctx->txqidx);
37878c2ecf20Sopenharmony_ci	chcr_send_wr(skb);
37888c2ecf20Sopenharmony_ci	return -EINPROGRESS;
37898c2ecf20Sopenharmony_ci}
37908c2ecf20Sopenharmony_ci
37918c2ecf20Sopenharmony_cistatic int chcr_aead_encrypt(struct aead_request *req)
37928c2ecf20Sopenharmony_ci{
37938c2ecf20Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
37948c2ecf20Sopenharmony_ci	struct chcr_aead_reqctx *reqctx = aead_request_ctx(req);
37958c2ecf20Sopenharmony_ci	struct chcr_context *ctx = a_ctx(tfm);
37968c2ecf20Sopenharmony_ci	unsigned int cpu;
37978c2ecf20Sopenharmony_ci
37988c2ecf20Sopenharmony_ci	cpu = get_cpu();
37998c2ecf20Sopenharmony_ci	reqctx->txqidx = cpu % ctx->ntxq;
38008c2ecf20Sopenharmony_ci	reqctx->rxqidx = cpu % ctx->nrxq;
38018c2ecf20Sopenharmony_ci	put_cpu();
38028c2ecf20Sopenharmony_ci
38038c2ecf20Sopenharmony_ci	reqctx->verify = VERIFY_HW;
38048c2ecf20Sopenharmony_ci	reqctx->op = CHCR_ENCRYPT_OP;
38058c2ecf20Sopenharmony_ci
38068c2ecf20Sopenharmony_ci	switch (get_aead_subtype(tfm)) {
38078c2ecf20Sopenharmony_ci	case CRYPTO_ALG_SUB_TYPE_CTR_SHA:
38088c2ecf20Sopenharmony_ci	case CRYPTO_ALG_SUB_TYPE_CBC_SHA:
38098c2ecf20Sopenharmony_ci	case CRYPTO_ALG_SUB_TYPE_CBC_NULL:
38108c2ecf20Sopenharmony_ci	case CRYPTO_ALG_SUB_TYPE_CTR_NULL:
38118c2ecf20Sopenharmony_ci		return chcr_aead_op(req, 0, create_authenc_wr);
38128c2ecf20Sopenharmony_ci	case CRYPTO_ALG_SUB_TYPE_AEAD_CCM:
38138c2ecf20Sopenharmony_ci	case CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309:
38148c2ecf20Sopenharmony_ci		return chcr_aead_op(req, 0, create_aead_ccm_wr);
38158c2ecf20Sopenharmony_ci	default:
38168c2ecf20Sopenharmony_ci		return chcr_aead_op(req, 0, create_gcm_wr);
38178c2ecf20Sopenharmony_ci	}
38188c2ecf20Sopenharmony_ci}
38198c2ecf20Sopenharmony_ci
38208c2ecf20Sopenharmony_cistatic int chcr_aead_decrypt(struct aead_request *req)
38218c2ecf20Sopenharmony_ci{
38228c2ecf20Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
38238c2ecf20Sopenharmony_ci	struct chcr_context *ctx = a_ctx(tfm);
38248c2ecf20Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(ctx);
38258c2ecf20Sopenharmony_ci	struct chcr_aead_reqctx *reqctx = aead_request_ctx(req);
38268c2ecf20Sopenharmony_ci	int size;
38278c2ecf20Sopenharmony_ci	unsigned int cpu;
38288c2ecf20Sopenharmony_ci
38298c2ecf20Sopenharmony_ci	cpu = get_cpu();
38308c2ecf20Sopenharmony_ci	reqctx->txqidx = cpu % ctx->ntxq;
38318c2ecf20Sopenharmony_ci	reqctx->rxqidx = cpu % ctx->nrxq;
38328c2ecf20Sopenharmony_ci	put_cpu();
38338c2ecf20Sopenharmony_ci
38348c2ecf20Sopenharmony_ci	if (aeadctx->mayverify == VERIFY_SW) {
38358c2ecf20Sopenharmony_ci		size = crypto_aead_maxauthsize(tfm);
38368c2ecf20Sopenharmony_ci		reqctx->verify = VERIFY_SW;
38378c2ecf20Sopenharmony_ci	} else {
38388c2ecf20Sopenharmony_ci		size = 0;
38398c2ecf20Sopenharmony_ci		reqctx->verify = VERIFY_HW;
38408c2ecf20Sopenharmony_ci	}
38418c2ecf20Sopenharmony_ci	reqctx->op = CHCR_DECRYPT_OP;
38428c2ecf20Sopenharmony_ci	switch (get_aead_subtype(tfm)) {
38438c2ecf20Sopenharmony_ci	case CRYPTO_ALG_SUB_TYPE_CBC_SHA:
38448c2ecf20Sopenharmony_ci	case CRYPTO_ALG_SUB_TYPE_CTR_SHA:
38458c2ecf20Sopenharmony_ci	case CRYPTO_ALG_SUB_TYPE_CBC_NULL:
38468c2ecf20Sopenharmony_ci	case CRYPTO_ALG_SUB_TYPE_CTR_NULL:
38478c2ecf20Sopenharmony_ci		return chcr_aead_op(req, size, create_authenc_wr);
38488c2ecf20Sopenharmony_ci	case CRYPTO_ALG_SUB_TYPE_AEAD_CCM:
38498c2ecf20Sopenharmony_ci	case CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309:
38508c2ecf20Sopenharmony_ci		return chcr_aead_op(req, size, create_aead_ccm_wr);
38518c2ecf20Sopenharmony_ci	default:
38528c2ecf20Sopenharmony_ci		return chcr_aead_op(req, size, create_gcm_wr);
38538c2ecf20Sopenharmony_ci	}
38548c2ecf20Sopenharmony_ci}
38558c2ecf20Sopenharmony_ci
38568c2ecf20Sopenharmony_cistatic struct chcr_alg_template driver_algs[] = {
38578c2ecf20Sopenharmony_ci	/* AES-CBC */
38588c2ecf20Sopenharmony_ci	{
38598c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_SUB_TYPE_CBC,
38608c2ecf20Sopenharmony_ci		.is_registered = 0,
38618c2ecf20Sopenharmony_ci		.alg.skcipher = {
38628c2ecf20Sopenharmony_ci			.base.cra_name		= "cbc(aes)",
38638c2ecf20Sopenharmony_ci			.base.cra_driver_name	= "cbc-aes-chcr",
38648c2ecf20Sopenharmony_ci			.base.cra_blocksize	= AES_BLOCK_SIZE,
38658c2ecf20Sopenharmony_ci
38668c2ecf20Sopenharmony_ci			.init			= chcr_init_tfm,
38678c2ecf20Sopenharmony_ci			.exit			= chcr_exit_tfm,
38688c2ecf20Sopenharmony_ci			.min_keysize		= AES_MIN_KEY_SIZE,
38698c2ecf20Sopenharmony_ci			.max_keysize		= AES_MAX_KEY_SIZE,
38708c2ecf20Sopenharmony_ci			.ivsize			= AES_BLOCK_SIZE,
38718c2ecf20Sopenharmony_ci			.setkey			= chcr_aes_cbc_setkey,
38728c2ecf20Sopenharmony_ci			.encrypt		= chcr_aes_encrypt,
38738c2ecf20Sopenharmony_ci			.decrypt		= chcr_aes_decrypt,
38748c2ecf20Sopenharmony_ci			}
38758c2ecf20Sopenharmony_ci	},
38768c2ecf20Sopenharmony_ci	{
38778c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_SUB_TYPE_XTS,
38788c2ecf20Sopenharmony_ci		.is_registered = 0,
38798c2ecf20Sopenharmony_ci		.alg.skcipher = {
38808c2ecf20Sopenharmony_ci			.base.cra_name		= "xts(aes)",
38818c2ecf20Sopenharmony_ci			.base.cra_driver_name	= "xts-aes-chcr",
38828c2ecf20Sopenharmony_ci			.base.cra_blocksize	= AES_BLOCK_SIZE,
38838c2ecf20Sopenharmony_ci
38848c2ecf20Sopenharmony_ci			.init			= chcr_init_tfm,
38858c2ecf20Sopenharmony_ci			.exit			= chcr_exit_tfm,
38868c2ecf20Sopenharmony_ci			.min_keysize		= 2 * AES_MIN_KEY_SIZE,
38878c2ecf20Sopenharmony_ci			.max_keysize		= 2 * AES_MAX_KEY_SIZE,
38888c2ecf20Sopenharmony_ci			.ivsize			= AES_BLOCK_SIZE,
38898c2ecf20Sopenharmony_ci			.setkey			= chcr_aes_xts_setkey,
38908c2ecf20Sopenharmony_ci			.encrypt		= chcr_aes_encrypt,
38918c2ecf20Sopenharmony_ci			.decrypt		= chcr_aes_decrypt,
38928c2ecf20Sopenharmony_ci			}
38938c2ecf20Sopenharmony_ci	},
38948c2ecf20Sopenharmony_ci	{
38958c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_SUB_TYPE_CTR,
38968c2ecf20Sopenharmony_ci		.is_registered = 0,
38978c2ecf20Sopenharmony_ci		.alg.skcipher = {
38988c2ecf20Sopenharmony_ci			.base.cra_name		= "ctr(aes)",
38998c2ecf20Sopenharmony_ci			.base.cra_driver_name	= "ctr-aes-chcr",
39008c2ecf20Sopenharmony_ci			.base.cra_blocksize	= 1,
39018c2ecf20Sopenharmony_ci
39028c2ecf20Sopenharmony_ci			.init			= chcr_init_tfm,
39038c2ecf20Sopenharmony_ci			.exit			= chcr_exit_tfm,
39048c2ecf20Sopenharmony_ci			.min_keysize		= AES_MIN_KEY_SIZE,
39058c2ecf20Sopenharmony_ci			.max_keysize		= AES_MAX_KEY_SIZE,
39068c2ecf20Sopenharmony_ci			.ivsize			= AES_BLOCK_SIZE,
39078c2ecf20Sopenharmony_ci			.setkey			= chcr_aes_ctr_setkey,
39088c2ecf20Sopenharmony_ci			.encrypt		= chcr_aes_encrypt,
39098c2ecf20Sopenharmony_ci			.decrypt		= chcr_aes_decrypt,
39108c2ecf20Sopenharmony_ci		}
39118c2ecf20Sopenharmony_ci	},
39128c2ecf20Sopenharmony_ci	{
39138c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_SKCIPHER |
39148c2ecf20Sopenharmony_ci			CRYPTO_ALG_SUB_TYPE_CTR_RFC3686,
39158c2ecf20Sopenharmony_ci		.is_registered = 0,
39168c2ecf20Sopenharmony_ci		.alg.skcipher = {
39178c2ecf20Sopenharmony_ci			.base.cra_name		= "rfc3686(ctr(aes))",
39188c2ecf20Sopenharmony_ci			.base.cra_driver_name	= "rfc3686-ctr-aes-chcr",
39198c2ecf20Sopenharmony_ci			.base.cra_blocksize	= 1,
39208c2ecf20Sopenharmony_ci
39218c2ecf20Sopenharmony_ci			.init			= chcr_rfc3686_init,
39228c2ecf20Sopenharmony_ci			.exit			= chcr_exit_tfm,
39238c2ecf20Sopenharmony_ci			.min_keysize		= AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
39248c2ecf20Sopenharmony_ci			.max_keysize		= AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
39258c2ecf20Sopenharmony_ci			.ivsize			= CTR_RFC3686_IV_SIZE,
39268c2ecf20Sopenharmony_ci			.setkey			= chcr_aes_rfc3686_setkey,
39278c2ecf20Sopenharmony_ci			.encrypt		= chcr_aes_encrypt,
39288c2ecf20Sopenharmony_ci			.decrypt		= chcr_aes_decrypt,
39298c2ecf20Sopenharmony_ci		}
39308c2ecf20Sopenharmony_ci	},
39318c2ecf20Sopenharmony_ci	/* SHA */
39328c2ecf20Sopenharmony_ci	{
39338c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AHASH,
39348c2ecf20Sopenharmony_ci		.is_registered = 0,
39358c2ecf20Sopenharmony_ci		.alg.hash = {
39368c2ecf20Sopenharmony_ci			.halg.digestsize = SHA1_DIGEST_SIZE,
39378c2ecf20Sopenharmony_ci			.halg.base = {
39388c2ecf20Sopenharmony_ci				.cra_name = "sha1",
39398c2ecf20Sopenharmony_ci				.cra_driver_name = "sha1-chcr",
39408c2ecf20Sopenharmony_ci				.cra_blocksize = SHA1_BLOCK_SIZE,
39418c2ecf20Sopenharmony_ci			}
39428c2ecf20Sopenharmony_ci		}
39438c2ecf20Sopenharmony_ci	},
39448c2ecf20Sopenharmony_ci	{
39458c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AHASH,
39468c2ecf20Sopenharmony_ci		.is_registered = 0,
39478c2ecf20Sopenharmony_ci		.alg.hash = {
39488c2ecf20Sopenharmony_ci			.halg.digestsize = SHA256_DIGEST_SIZE,
39498c2ecf20Sopenharmony_ci			.halg.base = {
39508c2ecf20Sopenharmony_ci				.cra_name = "sha256",
39518c2ecf20Sopenharmony_ci				.cra_driver_name = "sha256-chcr",
39528c2ecf20Sopenharmony_ci				.cra_blocksize = SHA256_BLOCK_SIZE,
39538c2ecf20Sopenharmony_ci			}
39548c2ecf20Sopenharmony_ci		}
39558c2ecf20Sopenharmony_ci	},
39568c2ecf20Sopenharmony_ci	{
39578c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AHASH,
39588c2ecf20Sopenharmony_ci		.is_registered = 0,
39598c2ecf20Sopenharmony_ci		.alg.hash = {
39608c2ecf20Sopenharmony_ci			.halg.digestsize = SHA224_DIGEST_SIZE,
39618c2ecf20Sopenharmony_ci			.halg.base = {
39628c2ecf20Sopenharmony_ci				.cra_name = "sha224",
39638c2ecf20Sopenharmony_ci				.cra_driver_name = "sha224-chcr",
39648c2ecf20Sopenharmony_ci				.cra_blocksize = SHA224_BLOCK_SIZE,
39658c2ecf20Sopenharmony_ci			}
39668c2ecf20Sopenharmony_ci		}
39678c2ecf20Sopenharmony_ci	},
39688c2ecf20Sopenharmony_ci	{
39698c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AHASH,
39708c2ecf20Sopenharmony_ci		.is_registered = 0,
39718c2ecf20Sopenharmony_ci		.alg.hash = {
39728c2ecf20Sopenharmony_ci			.halg.digestsize = SHA384_DIGEST_SIZE,
39738c2ecf20Sopenharmony_ci			.halg.base = {
39748c2ecf20Sopenharmony_ci				.cra_name = "sha384",
39758c2ecf20Sopenharmony_ci				.cra_driver_name = "sha384-chcr",
39768c2ecf20Sopenharmony_ci				.cra_blocksize = SHA384_BLOCK_SIZE,
39778c2ecf20Sopenharmony_ci			}
39788c2ecf20Sopenharmony_ci		}
39798c2ecf20Sopenharmony_ci	},
39808c2ecf20Sopenharmony_ci	{
39818c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AHASH,
39828c2ecf20Sopenharmony_ci		.is_registered = 0,
39838c2ecf20Sopenharmony_ci		.alg.hash = {
39848c2ecf20Sopenharmony_ci			.halg.digestsize = SHA512_DIGEST_SIZE,
39858c2ecf20Sopenharmony_ci			.halg.base = {
39868c2ecf20Sopenharmony_ci				.cra_name = "sha512",
39878c2ecf20Sopenharmony_ci				.cra_driver_name = "sha512-chcr",
39888c2ecf20Sopenharmony_ci				.cra_blocksize = SHA512_BLOCK_SIZE,
39898c2ecf20Sopenharmony_ci			}
39908c2ecf20Sopenharmony_ci		}
39918c2ecf20Sopenharmony_ci	},
39928c2ecf20Sopenharmony_ci	/* HMAC */
39938c2ecf20Sopenharmony_ci	{
39948c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_HMAC,
39958c2ecf20Sopenharmony_ci		.is_registered = 0,
39968c2ecf20Sopenharmony_ci		.alg.hash = {
39978c2ecf20Sopenharmony_ci			.halg.digestsize = SHA1_DIGEST_SIZE,
39988c2ecf20Sopenharmony_ci			.halg.base = {
39998c2ecf20Sopenharmony_ci				.cra_name = "hmac(sha1)",
40008c2ecf20Sopenharmony_ci				.cra_driver_name = "hmac-sha1-chcr",
40018c2ecf20Sopenharmony_ci				.cra_blocksize = SHA1_BLOCK_SIZE,
40028c2ecf20Sopenharmony_ci			}
40038c2ecf20Sopenharmony_ci		}
40048c2ecf20Sopenharmony_ci	},
40058c2ecf20Sopenharmony_ci	{
40068c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_HMAC,
40078c2ecf20Sopenharmony_ci		.is_registered = 0,
40088c2ecf20Sopenharmony_ci		.alg.hash = {
40098c2ecf20Sopenharmony_ci			.halg.digestsize = SHA224_DIGEST_SIZE,
40108c2ecf20Sopenharmony_ci			.halg.base = {
40118c2ecf20Sopenharmony_ci				.cra_name = "hmac(sha224)",
40128c2ecf20Sopenharmony_ci				.cra_driver_name = "hmac-sha224-chcr",
40138c2ecf20Sopenharmony_ci				.cra_blocksize = SHA224_BLOCK_SIZE,
40148c2ecf20Sopenharmony_ci			}
40158c2ecf20Sopenharmony_ci		}
40168c2ecf20Sopenharmony_ci	},
40178c2ecf20Sopenharmony_ci	{
40188c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_HMAC,
40198c2ecf20Sopenharmony_ci		.is_registered = 0,
40208c2ecf20Sopenharmony_ci		.alg.hash = {
40218c2ecf20Sopenharmony_ci			.halg.digestsize = SHA256_DIGEST_SIZE,
40228c2ecf20Sopenharmony_ci			.halg.base = {
40238c2ecf20Sopenharmony_ci				.cra_name = "hmac(sha256)",
40248c2ecf20Sopenharmony_ci				.cra_driver_name = "hmac-sha256-chcr",
40258c2ecf20Sopenharmony_ci				.cra_blocksize = SHA256_BLOCK_SIZE,
40268c2ecf20Sopenharmony_ci			}
40278c2ecf20Sopenharmony_ci		}
40288c2ecf20Sopenharmony_ci	},
40298c2ecf20Sopenharmony_ci	{
40308c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_HMAC,
40318c2ecf20Sopenharmony_ci		.is_registered = 0,
40328c2ecf20Sopenharmony_ci		.alg.hash = {
40338c2ecf20Sopenharmony_ci			.halg.digestsize = SHA384_DIGEST_SIZE,
40348c2ecf20Sopenharmony_ci			.halg.base = {
40358c2ecf20Sopenharmony_ci				.cra_name = "hmac(sha384)",
40368c2ecf20Sopenharmony_ci				.cra_driver_name = "hmac-sha384-chcr",
40378c2ecf20Sopenharmony_ci				.cra_blocksize = SHA384_BLOCK_SIZE,
40388c2ecf20Sopenharmony_ci			}
40398c2ecf20Sopenharmony_ci		}
40408c2ecf20Sopenharmony_ci	},
40418c2ecf20Sopenharmony_ci	{
40428c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_HMAC,
40438c2ecf20Sopenharmony_ci		.is_registered = 0,
40448c2ecf20Sopenharmony_ci		.alg.hash = {
40458c2ecf20Sopenharmony_ci			.halg.digestsize = SHA512_DIGEST_SIZE,
40468c2ecf20Sopenharmony_ci			.halg.base = {
40478c2ecf20Sopenharmony_ci				.cra_name = "hmac(sha512)",
40488c2ecf20Sopenharmony_ci				.cra_driver_name = "hmac-sha512-chcr",
40498c2ecf20Sopenharmony_ci				.cra_blocksize = SHA512_BLOCK_SIZE,
40508c2ecf20Sopenharmony_ci			}
40518c2ecf20Sopenharmony_ci		}
40528c2ecf20Sopenharmony_ci	},
40538c2ecf20Sopenharmony_ci	/* Add AEAD Algorithms */
40548c2ecf20Sopenharmony_ci	{
40558c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_AEAD_GCM,
40568c2ecf20Sopenharmony_ci		.is_registered = 0,
40578c2ecf20Sopenharmony_ci		.alg.aead = {
40588c2ecf20Sopenharmony_ci			.base = {
40598c2ecf20Sopenharmony_ci				.cra_name = "gcm(aes)",
40608c2ecf20Sopenharmony_ci				.cra_driver_name = "gcm-aes-chcr",
40618c2ecf20Sopenharmony_ci				.cra_blocksize	= 1,
40628c2ecf20Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
40638c2ecf20Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
40648c2ecf20Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
40658c2ecf20Sopenharmony_ci						sizeof(struct chcr_gcm_ctx),
40668c2ecf20Sopenharmony_ci			},
40678c2ecf20Sopenharmony_ci			.ivsize = GCM_AES_IV_SIZE,
40688c2ecf20Sopenharmony_ci			.maxauthsize = GHASH_DIGEST_SIZE,
40698c2ecf20Sopenharmony_ci			.setkey = chcr_gcm_setkey,
40708c2ecf20Sopenharmony_ci			.setauthsize = chcr_gcm_setauthsize,
40718c2ecf20Sopenharmony_ci		}
40728c2ecf20Sopenharmony_ci	},
40738c2ecf20Sopenharmony_ci	{
40748c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106,
40758c2ecf20Sopenharmony_ci		.is_registered = 0,
40768c2ecf20Sopenharmony_ci		.alg.aead = {
40778c2ecf20Sopenharmony_ci			.base = {
40788c2ecf20Sopenharmony_ci				.cra_name = "rfc4106(gcm(aes))",
40798c2ecf20Sopenharmony_ci				.cra_driver_name = "rfc4106-gcm-aes-chcr",
40808c2ecf20Sopenharmony_ci				.cra_blocksize	 = 1,
40818c2ecf20Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY + 1,
40828c2ecf20Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
40838c2ecf20Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
40848c2ecf20Sopenharmony_ci						sizeof(struct chcr_gcm_ctx),
40858c2ecf20Sopenharmony_ci
40868c2ecf20Sopenharmony_ci			},
40878c2ecf20Sopenharmony_ci			.ivsize = GCM_RFC4106_IV_SIZE,
40888c2ecf20Sopenharmony_ci			.maxauthsize	= GHASH_DIGEST_SIZE,
40898c2ecf20Sopenharmony_ci			.setkey = chcr_gcm_setkey,
40908c2ecf20Sopenharmony_ci			.setauthsize	= chcr_4106_4309_setauthsize,
40918c2ecf20Sopenharmony_ci		}
40928c2ecf20Sopenharmony_ci	},
40938c2ecf20Sopenharmony_ci	{
40948c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_AEAD_CCM,
40958c2ecf20Sopenharmony_ci		.is_registered = 0,
40968c2ecf20Sopenharmony_ci		.alg.aead = {
40978c2ecf20Sopenharmony_ci			.base = {
40988c2ecf20Sopenharmony_ci				.cra_name = "ccm(aes)",
40998c2ecf20Sopenharmony_ci				.cra_driver_name = "ccm-aes-chcr",
41008c2ecf20Sopenharmony_ci				.cra_blocksize	 = 1,
41018c2ecf20Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
41028c2ecf20Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
41038c2ecf20Sopenharmony_ci						sizeof(struct chcr_aead_ctx),
41048c2ecf20Sopenharmony_ci
41058c2ecf20Sopenharmony_ci			},
41068c2ecf20Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
41078c2ecf20Sopenharmony_ci			.maxauthsize	= GHASH_DIGEST_SIZE,
41088c2ecf20Sopenharmony_ci			.setkey = chcr_aead_ccm_setkey,
41098c2ecf20Sopenharmony_ci			.setauthsize	= chcr_ccm_setauthsize,
41108c2ecf20Sopenharmony_ci		}
41118c2ecf20Sopenharmony_ci	},
41128c2ecf20Sopenharmony_ci	{
41138c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309,
41148c2ecf20Sopenharmony_ci		.is_registered = 0,
41158c2ecf20Sopenharmony_ci		.alg.aead = {
41168c2ecf20Sopenharmony_ci			.base = {
41178c2ecf20Sopenharmony_ci				.cra_name = "rfc4309(ccm(aes))",
41188c2ecf20Sopenharmony_ci				.cra_driver_name = "rfc4309-ccm-aes-chcr",
41198c2ecf20Sopenharmony_ci				.cra_blocksize	 = 1,
41208c2ecf20Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY + 1,
41218c2ecf20Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
41228c2ecf20Sopenharmony_ci						sizeof(struct chcr_aead_ctx),
41238c2ecf20Sopenharmony_ci
41248c2ecf20Sopenharmony_ci			},
41258c2ecf20Sopenharmony_ci			.ivsize = 8,
41268c2ecf20Sopenharmony_ci			.maxauthsize	= GHASH_DIGEST_SIZE,
41278c2ecf20Sopenharmony_ci			.setkey = chcr_aead_rfc4309_setkey,
41288c2ecf20Sopenharmony_ci			.setauthsize = chcr_4106_4309_setauthsize,
41298c2ecf20Sopenharmony_ci		}
41308c2ecf20Sopenharmony_ci	},
41318c2ecf20Sopenharmony_ci	{
41328c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CBC_SHA,
41338c2ecf20Sopenharmony_ci		.is_registered = 0,
41348c2ecf20Sopenharmony_ci		.alg.aead = {
41358c2ecf20Sopenharmony_ci			.base = {
41368c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha1),cbc(aes))",
41378c2ecf20Sopenharmony_ci				.cra_driver_name =
41388c2ecf20Sopenharmony_ci					"authenc-hmac-sha1-cbc-aes-chcr",
41398c2ecf20Sopenharmony_ci				.cra_blocksize	 = AES_BLOCK_SIZE,
41408c2ecf20Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
41418c2ecf20Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
41428c2ecf20Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
41438c2ecf20Sopenharmony_ci						sizeof(struct chcr_authenc_ctx),
41448c2ecf20Sopenharmony_ci
41458c2ecf20Sopenharmony_ci			},
41468c2ecf20Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
41478c2ecf20Sopenharmony_ci			.maxauthsize = SHA1_DIGEST_SIZE,
41488c2ecf20Sopenharmony_ci			.setkey = chcr_authenc_setkey,
41498c2ecf20Sopenharmony_ci			.setauthsize = chcr_authenc_setauthsize,
41508c2ecf20Sopenharmony_ci		}
41518c2ecf20Sopenharmony_ci	},
41528c2ecf20Sopenharmony_ci	{
41538c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CBC_SHA,
41548c2ecf20Sopenharmony_ci		.is_registered = 0,
41558c2ecf20Sopenharmony_ci		.alg.aead = {
41568c2ecf20Sopenharmony_ci			.base = {
41578c2ecf20Sopenharmony_ci
41588c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha256),cbc(aes))",
41598c2ecf20Sopenharmony_ci				.cra_driver_name =
41608c2ecf20Sopenharmony_ci					"authenc-hmac-sha256-cbc-aes-chcr",
41618c2ecf20Sopenharmony_ci				.cra_blocksize	 = AES_BLOCK_SIZE,
41628c2ecf20Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
41638c2ecf20Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
41648c2ecf20Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
41658c2ecf20Sopenharmony_ci						sizeof(struct chcr_authenc_ctx),
41668c2ecf20Sopenharmony_ci
41678c2ecf20Sopenharmony_ci			},
41688c2ecf20Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
41698c2ecf20Sopenharmony_ci			.maxauthsize	= SHA256_DIGEST_SIZE,
41708c2ecf20Sopenharmony_ci			.setkey = chcr_authenc_setkey,
41718c2ecf20Sopenharmony_ci			.setauthsize = chcr_authenc_setauthsize,
41728c2ecf20Sopenharmony_ci		}
41738c2ecf20Sopenharmony_ci	},
41748c2ecf20Sopenharmony_ci	{
41758c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CBC_SHA,
41768c2ecf20Sopenharmony_ci		.is_registered = 0,
41778c2ecf20Sopenharmony_ci		.alg.aead = {
41788c2ecf20Sopenharmony_ci			.base = {
41798c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha224),cbc(aes))",
41808c2ecf20Sopenharmony_ci				.cra_driver_name =
41818c2ecf20Sopenharmony_ci					"authenc-hmac-sha224-cbc-aes-chcr",
41828c2ecf20Sopenharmony_ci				.cra_blocksize	 = AES_BLOCK_SIZE,
41838c2ecf20Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
41848c2ecf20Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
41858c2ecf20Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
41868c2ecf20Sopenharmony_ci						sizeof(struct chcr_authenc_ctx),
41878c2ecf20Sopenharmony_ci			},
41888c2ecf20Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
41898c2ecf20Sopenharmony_ci			.maxauthsize = SHA224_DIGEST_SIZE,
41908c2ecf20Sopenharmony_ci			.setkey = chcr_authenc_setkey,
41918c2ecf20Sopenharmony_ci			.setauthsize = chcr_authenc_setauthsize,
41928c2ecf20Sopenharmony_ci		}
41938c2ecf20Sopenharmony_ci	},
41948c2ecf20Sopenharmony_ci	{
41958c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CBC_SHA,
41968c2ecf20Sopenharmony_ci		.is_registered = 0,
41978c2ecf20Sopenharmony_ci		.alg.aead = {
41988c2ecf20Sopenharmony_ci			.base = {
41998c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha384),cbc(aes))",
42008c2ecf20Sopenharmony_ci				.cra_driver_name =
42018c2ecf20Sopenharmony_ci					"authenc-hmac-sha384-cbc-aes-chcr",
42028c2ecf20Sopenharmony_ci				.cra_blocksize	 = AES_BLOCK_SIZE,
42038c2ecf20Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
42048c2ecf20Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
42058c2ecf20Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
42068c2ecf20Sopenharmony_ci						sizeof(struct chcr_authenc_ctx),
42078c2ecf20Sopenharmony_ci
42088c2ecf20Sopenharmony_ci			},
42098c2ecf20Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
42108c2ecf20Sopenharmony_ci			.maxauthsize = SHA384_DIGEST_SIZE,
42118c2ecf20Sopenharmony_ci			.setkey = chcr_authenc_setkey,
42128c2ecf20Sopenharmony_ci			.setauthsize = chcr_authenc_setauthsize,
42138c2ecf20Sopenharmony_ci		}
42148c2ecf20Sopenharmony_ci	},
42158c2ecf20Sopenharmony_ci	{
42168c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CBC_SHA,
42178c2ecf20Sopenharmony_ci		.is_registered = 0,
42188c2ecf20Sopenharmony_ci		.alg.aead = {
42198c2ecf20Sopenharmony_ci			.base = {
42208c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha512),cbc(aes))",
42218c2ecf20Sopenharmony_ci				.cra_driver_name =
42228c2ecf20Sopenharmony_ci					"authenc-hmac-sha512-cbc-aes-chcr",
42238c2ecf20Sopenharmony_ci				.cra_blocksize	 = AES_BLOCK_SIZE,
42248c2ecf20Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
42258c2ecf20Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
42268c2ecf20Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
42278c2ecf20Sopenharmony_ci						sizeof(struct chcr_authenc_ctx),
42288c2ecf20Sopenharmony_ci
42298c2ecf20Sopenharmony_ci			},
42308c2ecf20Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
42318c2ecf20Sopenharmony_ci			.maxauthsize = SHA512_DIGEST_SIZE,
42328c2ecf20Sopenharmony_ci			.setkey = chcr_authenc_setkey,
42338c2ecf20Sopenharmony_ci			.setauthsize = chcr_authenc_setauthsize,
42348c2ecf20Sopenharmony_ci		}
42358c2ecf20Sopenharmony_ci	},
42368c2ecf20Sopenharmony_ci	{
42378c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CBC_NULL,
42388c2ecf20Sopenharmony_ci		.is_registered = 0,
42398c2ecf20Sopenharmony_ci		.alg.aead = {
42408c2ecf20Sopenharmony_ci			.base = {
42418c2ecf20Sopenharmony_ci				.cra_name = "authenc(digest_null,cbc(aes))",
42428c2ecf20Sopenharmony_ci				.cra_driver_name =
42438c2ecf20Sopenharmony_ci					"authenc-digest_null-cbc-aes-chcr",
42448c2ecf20Sopenharmony_ci				.cra_blocksize	 = AES_BLOCK_SIZE,
42458c2ecf20Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
42468c2ecf20Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
42478c2ecf20Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
42488c2ecf20Sopenharmony_ci						sizeof(struct chcr_authenc_ctx),
42498c2ecf20Sopenharmony_ci
42508c2ecf20Sopenharmony_ci			},
42518c2ecf20Sopenharmony_ci			.ivsize  = AES_BLOCK_SIZE,
42528c2ecf20Sopenharmony_ci			.maxauthsize = 0,
42538c2ecf20Sopenharmony_ci			.setkey  = chcr_aead_digest_null_setkey,
42548c2ecf20Sopenharmony_ci			.setauthsize = chcr_authenc_null_setauthsize,
42558c2ecf20Sopenharmony_ci		}
42568c2ecf20Sopenharmony_ci	},
42578c2ecf20Sopenharmony_ci	{
42588c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CTR_SHA,
42598c2ecf20Sopenharmony_ci		.is_registered = 0,
42608c2ecf20Sopenharmony_ci		.alg.aead = {
42618c2ecf20Sopenharmony_ci			.base = {
42628c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha1),rfc3686(ctr(aes)))",
42638c2ecf20Sopenharmony_ci				.cra_driver_name =
42648c2ecf20Sopenharmony_ci				"authenc-hmac-sha1-rfc3686-ctr-aes-chcr",
42658c2ecf20Sopenharmony_ci				.cra_blocksize	 = 1,
42668c2ecf20Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
42678c2ecf20Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
42688c2ecf20Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
42698c2ecf20Sopenharmony_ci						sizeof(struct chcr_authenc_ctx),
42708c2ecf20Sopenharmony_ci
42718c2ecf20Sopenharmony_ci			},
42728c2ecf20Sopenharmony_ci			.ivsize = CTR_RFC3686_IV_SIZE,
42738c2ecf20Sopenharmony_ci			.maxauthsize = SHA1_DIGEST_SIZE,
42748c2ecf20Sopenharmony_ci			.setkey = chcr_authenc_setkey,
42758c2ecf20Sopenharmony_ci			.setauthsize = chcr_authenc_setauthsize,
42768c2ecf20Sopenharmony_ci		}
42778c2ecf20Sopenharmony_ci	},
42788c2ecf20Sopenharmony_ci	{
42798c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CTR_SHA,
42808c2ecf20Sopenharmony_ci		.is_registered = 0,
42818c2ecf20Sopenharmony_ci		.alg.aead = {
42828c2ecf20Sopenharmony_ci			.base = {
42838c2ecf20Sopenharmony_ci
42848c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha256),rfc3686(ctr(aes)))",
42858c2ecf20Sopenharmony_ci				.cra_driver_name =
42868c2ecf20Sopenharmony_ci				"authenc-hmac-sha256-rfc3686-ctr-aes-chcr",
42878c2ecf20Sopenharmony_ci				.cra_blocksize	 = 1,
42888c2ecf20Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
42898c2ecf20Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
42908c2ecf20Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
42918c2ecf20Sopenharmony_ci						sizeof(struct chcr_authenc_ctx),
42928c2ecf20Sopenharmony_ci
42938c2ecf20Sopenharmony_ci			},
42948c2ecf20Sopenharmony_ci			.ivsize = CTR_RFC3686_IV_SIZE,
42958c2ecf20Sopenharmony_ci			.maxauthsize	= SHA256_DIGEST_SIZE,
42968c2ecf20Sopenharmony_ci			.setkey = chcr_authenc_setkey,
42978c2ecf20Sopenharmony_ci			.setauthsize = chcr_authenc_setauthsize,
42988c2ecf20Sopenharmony_ci		}
42998c2ecf20Sopenharmony_ci	},
43008c2ecf20Sopenharmony_ci	{
43018c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CTR_SHA,
43028c2ecf20Sopenharmony_ci		.is_registered = 0,
43038c2ecf20Sopenharmony_ci		.alg.aead = {
43048c2ecf20Sopenharmony_ci			.base = {
43058c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha224),rfc3686(ctr(aes)))",
43068c2ecf20Sopenharmony_ci				.cra_driver_name =
43078c2ecf20Sopenharmony_ci				"authenc-hmac-sha224-rfc3686-ctr-aes-chcr",
43088c2ecf20Sopenharmony_ci				.cra_blocksize	 = 1,
43098c2ecf20Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
43108c2ecf20Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
43118c2ecf20Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
43128c2ecf20Sopenharmony_ci						sizeof(struct chcr_authenc_ctx),
43138c2ecf20Sopenharmony_ci			},
43148c2ecf20Sopenharmony_ci			.ivsize = CTR_RFC3686_IV_SIZE,
43158c2ecf20Sopenharmony_ci			.maxauthsize = SHA224_DIGEST_SIZE,
43168c2ecf20Sopenharmony_ci			.setkey = chcr_authenc_setkey,
43178c2ecf20Sopenharmony_ci			.setauthsize = chcr_authenc_setauthsize,
43188c2ecf20Sopenharmony_ci		}
43198c2ecf20Sopenharmony_ci	},
43208c2ecf20Sopenharmony_ci	{
43218c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CTR_SHA,
43228c2ecf20Sopenharmony_ci		.is_registered = 0,
43238c2ecf20Sopenharmony_ci		.alg.aead = {
43248c2ecf20Sopenharmony_ci			.base = {
43258c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha384),rfc3686(ctr(aes)))",
43268c2ecf20Sopenharmony_ci				.cra_driver_name =
43278c2ecf20Sopenharmony_ci				"authenc-hmac-sha384-rfc3686-ctr-aes-chcr",
43288c2ecf20Sopenharmony_ci				.cra_blocksize	 = 1,
43298c2ecf20Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
43308c2ecf20Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
43318c2ecf20Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
43328c2ecf20Sopenharmony_ci						sizeof(struct chcr_authenc_ctx),
43338c2ecf20Sopenharmony_ci
43348c2ecf20Sopenharmony_ci			},
43358c2ecf20Sopenharmony_ci			.ivsize = CTR_RFC3686_IV_SIZE,
43368c2ecf20Sopenharmony_ci			.maxauthsize = SHA384_DIGEST_SIZE,
43378c2ecf20Sopenharmony_ci			.setkey = chcr_authenc_setkey,
43388c2ecf20Sopenharmony_ci			.setauthsize = chcr_authenc_setauthsize,
43398c2ecf20Sopenharmony_ci		}
43408c2ecf20Sopenharmony_ci	},
43418c2ecf20Sopenharmony_ci	{
43428c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CTR_SHA,
43438c2ecf20Sopenharmony_ci		.is_registered = 0,
43448c2ecf20Sopenharmony_ci		.alg.aead = {
43458c2ecf20Sopenharmony_ci			.base = {
43468c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha512),rfc3686(ctr(aes)))",
43478c2ecf20Sopenharmony_ci				.cra_driver_name =
43488c2ecf20Sopenharmony_ci				"authenc-hmac-sha512-rfc3686-ctr-aes-chcr",
43498c2ecf20Sopenharmony_ci				.cra_blocksize	 = 1,
43508c2ecf20Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
43518c2ecf20Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
43528c2ecf20Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
43538c2ecf20Sopenharmony_ci						sizeof(struct chcr_authenc_ctx),
43548c2ecf20Sopenharmony_ci
43558c2ecf20Sopenharmony_ci			},
43568c2ecf20Sopenharmony_ci			.ivsize = CTR_RFC3686_IV_SIZE,
43578c2ecf20Sopenharmony_ci			.maxauthsize = SHA512_DIGEST_SIZE,
43588c2ecf20Sopenharmony_ci			.setkey = chcr_authenc_setkey,
43598c2ecf20Sopenharmony_ci			.setauthsize = chcr_authenc_setauthsize,
43608c2ecf20Sopenharmony_ci		}
43618c2ecf20Sopenharmony_ci	},
43628c2ecf20Sopenharmony_ci	{
43638c2ecf20Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CTR_NULL,
43648c2ecf20Sopenharmony_ci		.is_registered = 0,
43658c2ecf20Sopenharmony_ci		.alg.aead = {
43668c2ecf20Sopenharmony_ci			.base = {
43678c2ecf20Sopenharmony_ci				.cra_name = "authenc(digest_null,rfc3686(ctr(aes)))",
43688c2ecf20Sopenharmony_ci				.cra_driver_name =
43698c2ecf20Sopenharmony_ci				"authenc-digest_null-rfc3686-ctr-aes-chcr",
43708c2ecf20Sopenharmony_ci				.cra_blocksize	 = 1,
43718c2ecf20Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
43728c2ecf20Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
43738c2ecf20Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
43748c2ecf20Sopenharmony_ci						sizeof(struct chcr_authenc_ctx),
43758c2ecf20Sopenharmony_ci
43768c2ecf20Sopenharmony_ci			},
43778c2ecf20Sopenharmony_ci			.ivsize  = CTR_RFC3686_IV_SIZE,
43788c2ecf20Sopenharmony_ci			.maxauthsize = 0,
43798c2ecf20Sopenharmony_ci			.setkey  = chcr_aead_digest_null_setkey,
43808c2ecf20Sopenharmony_ci			.setauthsize = chcr_authenc_null_setauthsize,
43818c2ecf20Sopenharmony_ci		}
43828c2ecf20Sopenharmony_ci	},
43838c2ecf20Sopenharmony_ci};
43848c2ecf20Sopenharmony_ci
43858c2ecf20Sopenharmony_ci/*
43868c2ecf20Sopenharmony_ci *	chcr_unregister_alg - Deregister crypto algorithms with
43878c2ecf20Sopenharmony_ci *	kernel framework.
43888c2ecf20Sopenharmony_ci */
43898c2ecf20Sopenharmony_cistatic int chcr_unregister_alg(void)
43908c2ecf20Sopenharmony_ci{
43918c2ecf20Sopenharmony_ci	int i;
43928c2ecf20Sopenharmony_ci
43938c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
43948c2ecf20Sopenharmony_ci		switch (driver_algs[i].type & CRYPTO_ALG_TYPE_MASK) {
43958c2ecf20Sopenharmony_ci		case CRYPTO_ALG_TYPE_SKCIPHER:
43968c2ecf20Sopenharmony_ci			if (driver_algs[i].is_registered && refcount_read(
43978c2ecf20Sopenharmony_ci			    &driver_algs[i].alg.skcipher.base.cra_refcnt)
43988c2ecf20Sopenharmony_ci			    == 1) {
43998c2ecf20Sopenharmony_ci				crypto_unregister_skcipher(
44008c2ecf20Sopenharmony_ci						&driver_algs[i].alg.skcipher);
44018c2ecf20Sopenharmony_ci				driver_algs[i].is_registered = 0;
44028c2ecf20Sopenharmony_ci			}
44038c2ecf20Sopenharmony_ci			break;
44048c2ecf20Sopenharmony_ci		case CRYPTO_ALG_TYPE_AEAD:
44058c2ecf20Sopenharmony_ci			if (driver_algs[i].is_registered && refcount_read(
44068c2ecf20Sopenharmony_ci			    &driver_algs[i].alg.aead.base.cra_refcnt) == 1) {
44078c2ecf20Sopenharmony_ci				crypto_unregister_aead(
44088c2ecf20Sopenharmony_ci						&driver_algs[i].alg.aead);
44098c2ecf20Sopenharmony_ci				driver_algs[i].is_registered = 0;
44108c2ecf20Sopenharmony_ci			}
44118c2ecf20Sopenharmony_ci			break;
44128c2ecf20Sopenharmony_ci		case CRYPTO_ALG_TYPE_AHASH:
44138c2ecf20Sopenharmony_ci			if (driver_algs[i].is_registered && refcount_read(
44148c2ecf20Sopenharmony_ci			    &driver_algs[i].alg.hash.halg.base.cra_refcnt)
44158c2ecf20Sopenharmony_ci			    == 1) {
44168c2ecf20Sopenharmony_ci				crypto_unregister_ahash(
44178c2ecf20Sopenharmony_ci						&driver_algs[i].alg.hash);
44188c2ecf20Sopenharmony_ci				driver_algs[i].is_registered = 0;
44198c2ecf20Sopenharmony_ci			}
44208c2ecf20Sopenharmony_ci			break;
44218c2ecf20Sopenharmony_ci		}
44228c2ecf20Sopenharmony_ci	}
44238c2ecf20Sopenharmony_ci	return 0;
44248c2ecf20Sopenharmony_ci}
44258c2ecf20Sopenharmony_ci
44268c2ecf20Sopenharmony_ci#define SZ_AHASH_CTX sizeof(struct chcr_context)
44278c2ecf20Sopenharmony_ci#define SZ_AHASH_H_CTX (sizeof(struct chcr_context) + sizeof(struct hmac_ctx))
44288c2ecf20Sopenharmony_ci#define SZ_AHASH_REQ_CTX sizeof(struct chcr_ahash_req_ctx)
44298c2ecf20Sopenharmony_ci
44308c2ecf20Sopenharmony_ci/*
44318c2ecf20Sopenharmony_ci *	chcr_register_alg - Register crypto algorithms with kernel framework.
44328c2ecf20Sopenharmony_ci */
44338c2ecf20Sopenharmony_cistatic int chcr_register_alg(void)
44348c2ecf20Sopenharmony_ci{
44358c2ecf20Sopenharmony_ci	struct crypto_alg ai;
44368c2ecf20Sopenharmony_ci	struct ahash_alg *a_hash;
44378c2ecf20Sopenharmony_ci	int err = 0, i;
44388c2ecf20Sopenharmony_ci	char *name = NULL;
44398c2ecf20Sopenharmony_ci
44408c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
44418c2ecf20Sopenharmony_ci		if (driver_algs[i].is_registered)
44428c2ecf20Sopenharmony_ci			continue;
44438c2ecf20Sopenharmony_ci		switch (driver_algs[i].type & CRYPTO_ALG_TYPE_MASK) {
44448c2ecf20Sopenharmony_ci		case CRYPTO_ALG_TYPE_SKCIPHER:
44458c2ecf20Sopenharmony_ci			driver_algs[i].alg.skcipher.base.cra_priority =
44468c2ecf20Sopenharmony_ci				CHCR_CRA_PRIORITY;
44478c2ecf20Sopenharmony_ci			driver_algs[i].alg.skcipher.base.cra_module = THIS_MODULE;
44488c2ecf20Sopenharmony_ci			driver_algs[i].alg.skcipher.base.cra_flags =
44498c2ecf20Sopenharmony_ci				CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_ASYNC |
44508c2ecf20Sopenharmony_ci				CRYPTO_ALG_ALLOCATES_MEMORY |
44518c2ecf20Sopenharmony_ci				CRYPTO_ALG_NEED_FALLBACK;
44528c2ecf20Sopenharmony_ci			driver_algs[i].alg.skcipher.base.cra_ctxsize =
44538c2ecf20Sopenharmony_ci				sizeof(struct chcr_context) +
44548c2ecf20Sopenharmony_ci				sizeof(struct ablk_ctx);
44558c2ecf20Sopenharmony_ci			driver_algs[i].alg.skcipher.base.cra_alignmask = 0;
44568c2ecf20Sopenharmony_ci
44578c2ecf20Sopenharmony_ci			err = crypto_register_skcipher(&driver_algs[i].alg.skcipher);
44588c2ecf20Sopenharmony_ci			name = driver_algs[i].alg.skcipher.base.cra_driver_name;
44598c2ecf20Sopenharmony_ci			break;
44608c2ecf20Sopenharmony_ci		case CRYPTO_ALG_TYPE_AEAD:
44618c2ecf20Sopenharmony_ci			driver_algs[i].alg.aead.base.cra_flags =
44628c2ecf20Sopenharmony_ci				CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK |
44638c2ecf20Sopenharmony_ci				CRYPTO_ALG_ALLOCATES_MEMORY;
44648c2ecf20Sopenharmony_ci			driver_algs[i].alg.aead.encrypt = chcr_aead_encrypt;
44658c2ecf20Sopenharmony_ci			driver_algs[i].alg.aead.decrypt = chcr_aead_decrypt;
44668c2ecf20Sopenharmony_ci			driver_algs[i].alg.aead.init = chcr_aead_cra_init;
44678c2ecf20Sopenharmony_ci			driver_algs[i].alg.aead.exit = chcr_aead_cra_exit;
44688c2ecf20Sopenharmony_ci			driver_algs[i].alg.aead.base.cra_module = THIS_MODULE;
44698c2ecf20Sopenharmony_ci			err = crypto_register_aead(&driver_algs[i].alg.aead);
44708c2ecf20Sopenharmony_ci			name = driver_algs[i].alg.aead.base.cra_driver_name;
44718c2ecf20Sopenharmony_ci			break;
44728c2ecf20Sopenharmony_ci		case CRYPTO_ALG_TYPE_AHASH:
44738c2ecf20Sopenharmony_ci			a_hash = &driver_algs[i].alg.hash;
44748c2ecf20Sopenharmony_ci			a_hash->update = chcr_ahash_update;
44758c2ecf20Sopenharmony_ci			a_hash->final = chcr_ahash_final;
44768c2ecf20Sopenharmony_ci			a_hash->finup = chcr_ahash_finup;
44778c2ecf20Sopenharmony_ci			a_hash->digest = chcr_ahash_digest;
44788c2ecf20Sopenharmony_ci			a_hash->export = chcr_ahash_export;
44798c2ecf20Sopenharmony_ci			a_hash->import = chcr_ahash_import;
44808c2ecf20Sopenharmony_ci			a_hash->halg.statesize = SZ_AHASH_REQ_CTX;
44818c2ecf20Sopenharmony_ci			a_hash->halg.base.cra_priority = CHCR_CRA_PRIORITY;
44828c2ecf20Sopenharmony_ci			a_hash->halg.base.cra_module = THIS_MODULE;
44838c2ecf20Sopenharmony_ci			a_hash->halg.base.cra_flags =
44848c2ecf20Sopenharmony_ci				CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY;
44858c2ecf20Sopenharmony_ci			a_hash->halg.base.cra_alignmask = 0;
44868c2ecf20Sopenharmony_ci			a_hash->halg.base.cra_exit = NULL;
44878c2ecf20Sopenharmony_ci
44888c2ecf20Sopenharmony_ci			if (driver_algs[i].type == CRYPTO_ALG_TYPE_HMAC) {
44898c2ecf20Sopenharmony_ci				a_hash->halg.base.cra_init = chcr_hmac_cra_init;
44908c2ecf20Sopenharmony_ci				a_hash->halg.base.cra_exit = chcr_hmac_cra_exit;
44918c2ecf20Sopenharmony_ci				a_hash->init = chcr_hmac_init;
44928c2ecf20Sopenharmony_ci				a_hash->setkey = chcr_ahash_setkey;
44938c2ecf20Sopenharmony_ci				a_hash->halg.base.cra_ctxsize = SZ_AHASH_H_CTX;
44948c2ecf20Sopenharmony_ci			} else {
44958c2ecf20Sopenharmony_ci				a_hash->init = chcr_sha_init;
44968c2ecf20Sopenharmony_ci				a_hash->halg.base.cra_ctxsize = SZ_AHASH_CTX;
44978c2ecf20Sopenharmony_ci				a_hash->halg.base.cra_init = chcr_sha_cra_init;
44988c2ecf20Sopenharmony_ci			}
44998c2ecf20Sopenharmony_ci			err = crypto_register_ahash(&driver_algs[i].alg.hash);
45008c2ecf20Sopenharmony_ci			ai = driver_algs[i].alg.hash.halg.base;
45018c2ecf20Sopenharmony_ci			name = ai.cra_driver_name;
45028c2ecf20Sopenharmony_ci			break;
45038c2ecf20Sopenharmony_ci		}
45048c2ecf20Sopenharmony_ci		if (err) {
45058c2ecf20Sopenharmony_ci			pr_err("%s : Algorithm registration failed\n", name);
45068c2ecf20Sopenharmony_ci			goto register_err;
45078c2ecf20Sopenharmony_ci		} else {
45088c2ecf20Sopenharmony_ci			driver_algs[i].is_registered = 1;
45098c2ecf20Sopenharmony_ci		}
45108c2ecf20Sopenharmony_ci	}
45118c2ecf20Sopenharmony_ci	return 0;
45128c2ecf20Sopenharmony_ci
45138c2ecf20Sopenharmony_ciregister_err:
45148c2ecf20Sopenharmony_ci	chcr_unregister_alg();
45158c2ecf20Sopenharmony_ci	return err;
45168c2ecf20Sopenharmony_ci}
45178c2ecf20Sopenharmony_ci
45188c2ecf20Sopenharmony_ci/*
45198c2ecf20Sopenharmony_ci *	start_crypto - Register the crypto algorithms.
45208c2ecf20Sopenharmony_ci *	This should called once when the first device comesup. After this
45218c2ecf20Sopenharmony_ci *	kernel will start calling driver APIs for crypto operations.
45228c2ecf20Sopenharmony_ci */
45238c2ecf20Sopenharmony_ciint start_crypto(void)
45248c2ecf20Sopenharmony_ci{
45258c2ecf20Sopenharmony_ci	return chcr_register_alg();
45268c2ecf20Sopenharmony_ci}
45278c2ecf20Sopenharmony_ci
45288c2ecf20Sopenharmony_ci/*
45298c2ecf20Sopenharmony_ci *	stop_crypto - Deregister all the crypto algorithms with kernel.
45308c2ecf20Sopenharmony_ci *	This should be called once when the last device goes down. After this
45318c2ecf20Sopenharmony_ci *	kernel will not call the driver API for crypto operations.
45328c2ecf20Sopenharmony_ci */
45338c2ecf20Sopenharmony_ciint stop_crypto(void)
45348c2ecf20Sopenharmony_ci{
45358c2ecf20Sopenharmony_ci	chcr_unregister_alg();
45368c2ecf20Sopenharmony_ci	return 0;
45378c2ecf20Sopenharmony_ci}
4538