162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * This file is part of the Chelsio T6 Crypto driver for Linux.
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (c) 2003-2016 Chelsio Communications, Inc. All rights reserved.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * This software is available to you under a choice of one of two
762306a36Sopenharmony_ci * licenses.  You may choose to be licensed under the terms of the GNU
862306a36Sopenharmony_ci * General Public License (GPL) Version 2, available from the file
962306a36Sopenharmony_ci * COPYING in the main directory of this source tree, or the
1062306a36Sopenharmony_ci * OpenIB.org BSD license below:
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci *     Redistribution and use in source and binary forms, with or
1362306a36Sopenharmony_ci *     without modification, are permitted provided that the following
1462306a36Sopenharmony_ci *     conditions are met:
1562306a36Sopenharmony_ci *
1662306a36Sopenharmony_ci *      - Redistributions of source code must retain the above
1762306a36Sopenharmony_ci *        copyright notice, this list of conditions and the following
1862306a36Sopenharmony_ci *        disclaimer.
1962306a36Sopenharmony_ci *
2062306a36Sopenharmony_ci *      - Redistributions in binary form must reproduce the above
2162306a36Sopenharmony_ci *        copyright notice, this list of conditions and the following
2262306a36Sopenharmony_ci *        disclaimer in the documentation and/or other materials
2362306a36Sopenharmony_ci *        provided with the distribution.
2462306a36Sopenharmony_ci *
2562306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2662306a36Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2762306a36Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
2862306a36Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
2962306a36Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
3062306a36Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
3162306a36Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3262306a36Sopenharmony_ci * SOFTWARE.
3362306a36Sopenharmony_ci *
3462306a36Sopenharmony_ci * Written and Maintained by:
3562306a36Sopenharmony_ci *	Manoj Malviya (manojmalviya@chelsio.com)
3662306a36Sopenharmony_ci *	Atul Gupta (atul.gupta@chelsio.com)
3762306a36Sopenharmony_ci *	Jitendra Lulla (jlulla@chelsio.com)
3862306a36Sopenharmony_ci *	Yeshaswi M R Gowda (yeshaswi@chelsio.com)
3962306a36Sopenharmony_ci *	Harsh Jain (harsh@chelsio.com)
4062306a36Sopenharmony_ci */
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci#define pr_fmt(fmt) "chcr:" fmt
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci#include <linux/kernel.h>
4562306a36Sopenharmony_ci#include <linux/module.h>
4662306a36Sopenharmony_ci#include <linux/crypto.h>
4762306a36Sopenharmony_ci#include <linux/skbuff.h>
4862306a36Sopenharmony_ci#include <linux/rtnetlink.h>
4962306a36Sopenharmony_ci#include <linux/highmem.h>
5062306a36Sopenharmony_ci#include <linux/scatterlist.h>
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci#include <crypto/aes.h>
5362306a36Sopenharmony_ci#include <crypto/algapi.h>
5462306a36Sopenharmony_ci#include <crypto/hash.h>
5562306a36Sopenharmony_ci#include <crypto/gcm.h>
5662306a36Sopenharmony_ci#include <crypto/sha1.h>
5762306a36Sopenharmony_ci#include <crypto/sha2.h>
5862306a36Sopenharmony_ci#include <crypto/authenc.h>
5962306a36Sopenharmony_ci#include <crypto/ctr.h>
6062306a36Sopenharmony_ci#include <crypto/gf128mul.h>
6162306a36Sopenharmony_ci#include <crypto/internal/aead.h>
6262306a36Sopenharmony_ci#include <crypto/null.h>
6362306a36Sopenharmony_ci#include <crypto/internal/skcipher.h>
6462306a36Sopenharmony_ci#include <crypto/aead.h>
6562306a36Sopenharmony_ci#include <crypto/scatterwalk.h>
6662306a36Sopenharmony_ci#include <crypto/internal/hash.h>
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci#include "t4fw_api.h"
6962306a36Sopenharmony_ci#include "t4_msg.h"
7062306a36Sopenharmony_ci#include "chcr_core.h"
7162306a36Sopenharmony_ci#include "chcr_algo.h"
7262306a36Sopenharmony_ci#include "chcr_crypto.h"
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci#define IV AES_BLOCK_SIZE
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_cistatic unsigned int sgl_ent_len[] = {
7762306a36Sopenharmony_ci	0, 0, 16, 24, 40, 48, 64, 72, 88,
7862306a36Sopenharmony_ci	96, 112, 120, 136, 144, 160, 168, 184,
7962306a36Sopenharmony_ci	192, 208, 216, 232, 240, 256, 264, 280,
8062306a36Sopenharmony_ci	288, 304, 312, 328, 336, 352, 360, 376
8162306a36Sopenharmony_ci};
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_cistatic unsigned int dsgl_ent_len[] = {
8462306a36Sopenharmony_ci	0, 32, 32, 48, 48, 64, 64, 80, 80,
8562306a36Sopenharmony_ci	112, 112, 128, 128, 144, 144, 160, 160,
8662306a36Sopenharmony_ci	192, 192, 208, 208, 224, 224, 240, 240,
8762306a36Sopenharmony_ci	272, 272, 288, 288, 304, 304, 320, 320
8862306a36Sopenharmony_ci};
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_cistatic u32 round_constant[11] = {
9162306a36Sopenharmony_ci	0x01000000, 0x02000000, 0x04000000, 0x08000000,
9262306a36Sopenharmony_ci	0x10000000, 0x20000000, 0x40000000, 0x80000000,
9362306a36Sopenharmony_ci	0x1B000000, 0x36000000, 0x6C000000
9462306a36Sopenharmony_ci};
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_cistatic int chcr_handle_cipher_resp(struct skcipher_request *req,
9762306a36Sopenharmony_ci				   unsigned char *input, int err);
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cistatic inline  struct chcr_aead_ctx *AEAD_CTX(struct chcr_context *ctx)
10062306a36Sopenharmony_ci{
10162306a36Sopenharmony_ci	return &ctx->crypto_ctx->aeadctx;
10262306a36Sopenharmony_ci}
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_cistatic inline struct ablk_ctx *ABLK_CTX(struct chcr_context *ctx)
10562306a36Sopenharmony_ci{
10662306a36Sopenharmony_ci	return &ctx->crypto_ctx->ablkctx;
10762306a36Sopenharmony_ci}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_cistatic inline struct hmac_ctx *HMAC_CTX(struct chcr_context *ctx)
11062306a36Sopenharmony_ci{
11162306a36Sopenharmony_ci	return &ctx->crypto_ctx->hmacctx;
11262306a36Sopenharmony_ci}
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_cistatic inline struct chcr_gcm_ctx *GCM_CTX(struct chcr_aead_ctx *gctx)
11562306a36Sopenharmony_ci{
11662306a36Sopenharmony_ci	return gctx->ctx->gcm;
11762306a36Sopenharmony_ci}
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_cistatic inline struct chcr_authenc_ctx *AUTHENC_CTX(struct chcr_aead_ctx *gctx)
12062306a36Sopenharmony_ci{
12162306a36Sopenharmony_ci	return gctx->ctx->authenc;
12262306a36Sopenharmony_ci}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_cistatic inline struct uld_ctx *ULD_CTX(struct chcr_context *ctx)
12562306a36Sopenharmony_ci{
12662306a36Sopenharmony_ci	return container_of(ctx->dev, struct uld_ctx, dev);
12762306a36Sopenharmony_ci}
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_cistatic inline void chcr_init_hctx_per_wr(struct chcr_ahash_req_ctx *reqctx)
13062306a36Sopenharmony_ci{
13162306a36Sopenharmony_ci	memset(&reqctx->hctx_wr, 0, sizeof(struct chcr_hctx_per_wr));
13262306a36Sopenharmony_ci}
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_cistatic int sg_nents_xlen(struct scatterlist *sg, unsigned int reqlen,
13562306a36Sopenharmony_ci			 unsigned int entlen,
13662306a36Sopenharmony_ci			 unsigned int skip)
13762306a36Sopenharmony_ci{
13862306a36Sopenharmony_ci	int nents = 0;
13962306a36Sopenharmony_ci	unsigned int less;
14062306a36Sopenharmony_ci	unsigned int skip_len = 0;
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	while (sg && skip) {
14362306a36Sopenharmony_ci		if (sg_dma_len(sg) <= skip) {
14462306a36Sopenharmony_ci			skip -= sg_dma_len(sg);
14562306a36Sopenharmony_ci			skip_len = 0;
14662306a36Sopenharmony_ci			sg = sg_next(sg);
14762306a36Sopenharmony_ci		} else {
14862306a36Sopenharmony_ci			skip_len = skip;
14962306a36Sopenharmony_ci			skip = 0;
15062306a36Sopenharmony_ci		}
15162306a36Sopenharmony_ci	}
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	while (sg && reqlen) {
15462306a36Sopenharmony_ci		less = min(reqlen, sg_dma_len(sg) - skip_len);
15562306a36Sopenharmony_ci		nents += DIV_ROUND_UP(less, entlen);
15662306a36Sopenharmony_ci		reqlen -= less;
15762306a36Sopenharmony_ci		skip_len = 0;
15862306a36Sopenharmony_ci		sg = sg_next(sg);
15962306a36Sopenharmony_ci	}
16062306a36Sopenharmony_ci	return nents;
16162306a36Sopenharmony_ci}
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_cistatic inline int get_aead_subtype(struct crypto_aead *aead)
16462306a36Sopenharmony_ci{
16562306a36Sopenharmony_ci	struct aead_alg *alg = crypto_aead_alg(aead);
16662306a36Sopenharmony_ci	struct chcr_alg_template *chcr_crypto_alg =
16762306a36Sopenharmony_ci		container_of(alg, struct chcr_alg_template, alg.aead);
16862306a36Sopenharmony_ci	return chcr_crypto_alg->type & CRYPTO_ALG_SUB_TYPE_MASK;
16962306a36Sopenharmony_ci}
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_civoid chcr_verify_tag(struct aead_request *req, u8 *input, int *err)
17262306a36Sopenharmony_ci{
17362306a36Sopenharmony_ci	u8 temp[SHA512_DIGEST_SIZE];
17462306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
17562306a36Sopenharmony_ci	int authsize = crypto_aead_authsize(tfm);
17662306a36Sopenharmony_ci	struct cpl_fw6_pld *fw6_pld;
17762306a36Sopenharmony_ci	int cmp = 0;
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	fw6_pld = (struct cpl_fw6_pld *)input;
18062306a36Sopenharmony_ci	if ((get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106) ||
18162306a36Sopenharmony_ci	    (get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_GCM)) {
18262306a36Sopenharmony_ci		cmp = crypto_memneq(&fw6_pld->data[2], (fw6_pld + 1), authsize);
18362306a36Sopenharmony_ci	} else {
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci		sg_pcopy_to_buffer(req->src, sg_nents(req->src), temp,
18662306a36Sopenharmony_ci				authsize, req->assoclen +
18762306a36Sopenharmony_ci				req->cryptlen - authsize);
18862306a36Sopenharmony_ci		cmp = crypto_memneq(temp, (fw6_pld + 1), authsize);
18962306a36Sopenharmony_ci	}
19062306a36Sopenharmony_ci	if (cmp)
19162306a36Sopenharmony_ci		*err = -EBADMSG;
19262306a36Sopenharmony_ci	else
19362306a36Sopenharmony_ci		*err = 0;
19462306a36Sopenharmony_ci}
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_cistatic int chcr_inc_wrcount(struct chcr_dev *dev)
19762306a36Sopenharmony_ci{
19862306a36Sopenharmony_ci	if (dev->state == CHCR_DETACH)
19962306a36Sopenharmony_ci		return 1;
20062306a36Sopenharmony_ci	atomic_inc(&dev->inflight);
20162306a36Sopenharmony_ci	return 0;
20262306a36Sopenharmony_ci}
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_cistatic inline void chcr_dec_wrcount(struct chcr_dev *dev)
20562306a36Sopenharmony_ci{
20662306a36Sopenharmony_ci	atomic_dec(&dev->inflight);
20762306a36Sopenharmony_ci}
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_cistatic inline int chcr_handle_aead_resp(struct aead_request *req,
21062306a36Sopenharmony_ci					 unsigned char *input,
21162306a36Sopenharmony_ci					 int err)
21262306a36Sopenharmony_ci{
21362306a36Sopenharmony_ci	struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req);
21462306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
21562306a36Sopenharmony_ci	struct chcr_dev *dev = a_ctx(tfm)->dev;
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	chcr_aead_common_exit(req);
21862306a36Sopenharmony_ci	if (reqctx->verify == VERIFY_SW) {
21962306a36Sopenharmony_ci		chcr_verify_tag(req, input, &err);
22062306a36Sopenharmony_ci		reqctx->verify = VERIFY_HW;
22162306a36Sopenharmony_ci	}
22262306a36Sopenharmony_ci	chcr_dec_wrcount(dev);
22362306a36Sopenharmony_ci	aead_request_complete(req, err);
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	return err;
22662306a36Sopenharmony_ci}
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_cistatic void get_aes_decrypt_key(unsigned char *dec_key,
22962306a36Sopenharmony_ci				       const unsigned char *key,
23062306a36Sopenharmony_ci				       unsigned int keylength)
23162306a36Sopenharmony_ci{
23262306a36Sopenharmony_ci	u32 temp;
23362306a36Sopenharmony_ci	u32 w_ring[MAX_NK];
23462306a36Sopenharmony_ci	int i, j, k;
23562306a36Sopenharmony_ci	u8  nr, nk;
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	switch (keylength) {
23862306a36Sopenharmony_ci	case AES_KEYLENGTH_128BIT:
23962306a36Sopenharmony_ci		nk = KEYLENGTH_4BYTES;
24062306a36Sopenharmony_ci		nr = NUMBER_OF_ROUNDS_10;
24162306a36Sopenharmony_ci		break;
24262306a36Sopenharmony_ci	case AES_KEYLENGTH_192BIT:
24362306a36Sopenharmony_ci		nk = KEYLENGTH_6BYTES;
24462306a36Sopenharmony_ci		nr = NUMBER_OF_ROUNDS_12;
24562306a36Sopenharmony_ci		break;
24662306a36Sopenharmony_ci	case AES_KEYLENGTH_256BIT:
24762306a36Sopenharmony_ci		nk = KEYLENGTH_8BYTES;
24862306a36Sopenharmony_ci		nr = NUMBER_OF_ROUNDS_14;
24962306a36Sopenharmony_ci		break;
25062306a36Sopenharmony_ci	default:
25162306a36Sopenharmony_ci		return;
25262306a36Sopenharmony_ci	}
25362306a36Sopenharmony_ci	for (i = 0; i < nk; i++)
25462306a36Sopenharmony_ci		w_ring[i] = get_unaligned_be32(&key[i * 4]);
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	i = 0;
25762306a36Sopenharmony_ci	temp = w_ring[nk - 1];
25862306a36Sopenharmony_ci	while (i + nk < (nr + 1) * 4) {
25962306a36Sopenharmony_ci		if (!(i % nk)) {
26062306a36Sopenharmony_ci			/* RotWord(temp) */
26162306a36Sopenharmony_ci			temp = (temp << 8) | (temp >> 24);
26262306a36Sopenharmony_ci			temp = aes_ks_subword(temp);
26362306a36Sopenharmony_ci			temp ^= round_constant[i / nk];
26462306a36Sopenharmony_ci		} else if (nk == 8 && (i % 4 == 0)) {
26562306a36Sopenharmony_ci			temp = aes_ks_subword(temp);
26662306a36Sopenharmony_ci		}
26762306a36Sopenharmony_ci		w_ring[i % nk] ^= temp;
26862306a36Sopenharmony_ci		temp = w_ring[i % nk];
26962306a36Sopenharmony_ci		i++;
27062306a36Sopenharmony_ci	}
27162306a36Sopenharmony_ci	i--;
27262306a36Sopenharmony_ci	for (k = 0, j = i % nk; k < nk; k++) {
27362306a36Sopenharmony_ci		put_unaligned_be32(w_ring[j], &dec_key[k * 4]);
27462306a36Sopenharmony_ci		j--;
27562306a36Sopenharmony_ci		if (j < 0)
27662306a36Sopenharmony_ci			j += nk;
27762306a36Sopenharmony_ci	}
27862306a36Sopenharmony_ci}
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_cistatic struct crypto_shash *chcr_alloc_shash(unsigned int ds)
28162306a36Sopenharmony_ci{
28262306a36Sopenharmony_ci	struct crypto_shash *base_hash = ERR_PTR(-EINVAL);
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	switch (ds) {
28562306a36Sopenharmony_ci	case SHA1_DIGEST_SIZE:
28662306a36Sopenharmony_ci		base_hash = crypto_alloc_shash("sha1", 0, 0);
28762306a36Sopenharmony_ci		break;
28862306a36Sopenharmony_ci	case SHA224_DIGEST_SIZE:
28962306a36Sopenharmony_ci		base_hash = crypto_alloc_shash("sha224", 0, 0);
29062306a36Sopenharmony_ci		break;
29162306a36Sopenharmony_ci	case SHA256_DIGEST_SIZE:
29262306a36Sopenharmony_ci		base_hash = crypto_alloc_shash("sha256", 0, 0);
29362306a36Sopenharmony_ci		break;
29462306a36Sopenharmony_ci	case SHA384_DIGEST_SIZE:
29562306a36Sopenharmony_ci		base_hash = crypto_alloc_shash("sha384", 0, 0);
29662306a36Sopenharmony_ci		break;
29762306a36Sopenharmony_ci	case SHA512_DIGEST_SIZE:
29862306a36Sopenharmony_ci		base_hash = crypto_alloc_shash("sha512", 0, 0);
29962306a36Sopenharmony_ci		break;
30062306a36Sopenharmony_ci	}
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	return base_hash;
30362306a36Sopenharmony_ci}
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_cistatic int chcr_compute_partial_hash(struct shash_desc *desc,
30662306a36Sopenharmony_ci				     char *iopad, char *result_hash,
30762306a36Sopenharmony_ci				     int digest_size)
30862306a36Sopenharmony_ci{
30962306a36Sopenharmony_ci	struct sha1_state sha1_st;
31062306a36Sopenharmony_ci	struct sha256_state sha256_st;
31162306a36Sopenharmony_ci	struct sha512_state sha512_st;
31262306a36Sopenharmony_ci	int error;
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci	if (digest_size == SHA1_DIGEST_SIZE) {
31562306a36Sopenharmony_ci		error = crypto_shash_init(desc) ?:
31662306a36Sopenharmony_ci			crypto_shash_update(desc, iopad, SHA1_BLOCK_SIZE) ?:
31762306a36Sopenharmony_ci			crypto_shash_export(desc, (void *)&sha1_st);
31862306a36Sopenharmony_ci		memcpy(result_hash, sha1_st.state, SHA1_DIGEST_SIZE);
31962306a36Sopenharmony_ci	} else if (digest_size == SHA224_DIGEST_SIZE) {
32062306a36Sopenharmony_ci		error = crypto_shash_init(desc) ?:
32162306a36Sopenharmony_ci			crypto_shash_update(desc, iopad, SHA256_BLOCK_SIZE) ?:
32262306a36Sopenharmony_ci			crypto_shash_export(desc, (void *)&sha256_st);
32362306a36Sopenharmony_ci		memcpy(result_hash, sha256_st.state, SHA256_DIGEST_SIZE);
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	} else if (digest_size == SHA256_DIGEST_SIZE) {
32662306a36Sopenharmony_ci		error = crypto_shash_init(desc) ?:
32762306a36Sopenharmony_ci			crypto_shash_update(desc, iopad, SHA256_BLOCK_SIZE) ?:
32862306a36Sopenharmony_ci			crypto_shash_export(desc, (void *)&sha256_st);
32962306a36Sopenharmony_ci		memcpy(result_hash, sha256_st.state, SHA256_DIGEST_SIZE);
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	} else if (digest_size == SHA384_DIGEST_SIZE) {
33262306a36Sopenharmony_ci		error = crypto_shash_init(desc) ?:
33362306a36Sopenharmony_ci			crypto_shash_update(desc, iopad, SHA512_BLOCK_SIZE) ?:
33462306a36Sopenharmony_ci			crypto_shash_export(desc, (void *)&sha512_st);
33562306a36Sopenharmony_ci		memcpy(result_hash, sha512_st.state, SHA512_DIGEST_SIZE);
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	} else if (digest_size == SHA512_DIGEST_SIZE) {
33862306a36Sopenharmony_ci		error = crypto_shash_init(desc) ?:
33962306a36Sopenharmony_ci			crypto_shash_update(desc, iopad, SHA512_BLOCK_SIZE) ?:
34062306a36Sopenharmony_ci			crypto_shash_export(desc, (void *)&sha512_st);
34162306a36Sopenharmony_ci		memcpy(result_hash, sha512_st.state, SHA512_DIGEST_SIZE);
34262306a36Sopenharmony_ci	} else {
34362306a36Sopenharmony_ci		error = -EINVAL;
34462306a36Sopenharmony_ci		pr_err("Unknown digest size %d\n", digest_size);
34562306a36Sopenharmony_ci	}
34662306a36Sopenharmony_ci	return error;
34762306a36Sopenharmony_ci}
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_cistatic void chcr_change_order(char *buf, int ds)
35062306a36Sopenharmony_ci{
35162306a36Sopenharmony_ci	int i;
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci	if (ds == SHA512_DIGEST_SIZE) {
35462306a36Sopenharmony_ci		for (i = 0; i < (ds / sizeof(u64)); i++)
35562306a36Sopenharmony_ci			*((__be64 *)buf + i) =
35662306a36Sopenharmony_ci				cpu_to_be64(*((u64 *)buf + i));
35762306a36Sopenharmony_ci	} else {
35862306a36Sopenharmony_ci		for (i = 0; i < (ds / sizeof(u32)); i++)
35962306a36Sopenharmony_ci			*((__be32 *)buf + i) =
36062306a36Sopenharmony_ci				cpu_to_be32(*((u32 *)buf + i));
36162306a36Sopenharmony_ci	}
36262306a36Sopenharmony_ci}
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_cistatic inline int is_hmac(struct crypto_tfm *tfm)
36562306a36Sopenharmony_ci{
36662306a36Sopenharmony_ci	struct crypto_alg *alg = tfm->__crt_alg;
36762306a36Sopenharmony_ci	struct chcr_alg_template *chcr_crypto_alg =
36862306a36Sopenharmony_ci		container_of(__crypto_ahash_alg(alg), struct chcr_alg_template,
36962306a36Sopenharmony_ci			     alg.hash);
37062306a36Sopenharmony_ci	if (chcr_crypto_alg->type == CRYPTO_ALG_TYPE_HMAC)
37162306a36Sopenharmony_ci		return 1;
37262306a36Sopenharmony_ci	return 0;
37362306a36Sopenharmony_ci}
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_cistatic inline void dsgl_walk_init(struct dsgl_walk *walk,
37662306a36Sopenharmony_ci				   struct cpl_rx_phys_dsgl *dsgl)
37762306a36Sopenharmony_ci{
37862306a36Sopenharmony_ci	walk->dsgl = dsgl;
37962306a36Sopenharmony_ci	walk->nents = 0;
38062306a36Sopenharmony_ci	walk->to = (struct phys_sge_pairs *)(dsgl + 1);
38162306a36Sopenharmony_ci}
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_cistatic inline void dsgl_walk_end(struct dsgl_walk *walk, unsigned short qid,
38462306a36Sopenharmony_ci				 int pci_chan_id)
38562306a36Sopenharmony_ci{
38662306a36Sopenharmony_ci	struct cpl_rx_phys_dsgl *phys_cpl;
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci	phys_cpl = walk->dsgl;
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	phys_cpl->op_to_tid = htonl(CPL_RX_PHYS_DSGL_OPCODE_V(CPL_RX_PHYS_DSGL)
39162306a36Sopenharmony_ci				    | CPL_RX_PHYS_DSGL_ISRDMA_V(0));
39262306a36Sopenharmony_ci	phys_cpl->pcirlxorder_to_noofsgentr =
39362306a36Sopenharmony_ci		htonl(CPL_RX_PHYS_DSGL_PCIRLXORDER_V(0) |
39462306a36Sopenharmony_ci		      CPL_RX_PHYS_DSGL_PCINOSNOOP_V(0) |
39562306a36Sopenharmony_ci		      CPL_RX_PHYS_DSGL_PCITPHNTENB_V(0) |
39662306a36Sopenharmony_ci		      CPL_RX_PHYS_DSGL_PCITPHNT_V(0) |
39762306a36Sopenharmony_ci		      CPL_RX_PHYS_DSGL_DCAID_V(0) |
39862306a36Sopenharmony_ci		      CPL_RX_PHYS_DSGL_NOOFSGENTR_V(walk->nents));
39962306a36Sopenharmony_ci	phys_cpl->rss_hdr_int.opcode = CPL_RX_PHYS_ADDR;
40062306a36Sopenharmony_ci	phys_cpl->rss_hdr_int.qid = htons(qid);
40162306a36Sopenharmony_ci	phys_cpl->rss_hdr_int.hash_val = 0;
40262306a36Sopenharmony_ci	phys_cpl->rss_hdr_int.channel = pci_chan_id;
40362306a36Sopenharmony_ci}
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_cistatic inline void dsgl_walk_add_page(struct dsgl_walk *walk,
40662306a36Sopenharmony_ci					size_t size,
40762306a36Sopenharmony_ci					dma_addr_t addr)
40862306a36Sopenharmony_ci{
40962306a36Sopenharmony_ci	int j;
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci	if (!size)
41262306a36Sopenharmony_ci		return;
41362306a36Sopenharmony_ci	j = walk->nents;
41462306a36Sopenharmony_ci	walk->to->len[j % 8] = htons(size);
41562306a36Sopenharmony_ci	walk->to->addr[j % 8] = cpu_to_be64(addr);
41662306a36Sopenharmony_ci	j++;
41762306a36Sopenharmony_ci	if ((j % 8) == 0)
41862306a36Sopenharmony_ci		walk->to++;
41962306a36Sopenharmony_ci	walk->nents = j;
42062306a36Sopenharmony_ci}
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_cistatic void  dsgl_walk_add_sg(struct dsgl_walk *walk,
42362306a36Sopenharmony_ci			   struct scatterlist *sg,
42462306a36Sopenharmony_ci			      unsigned int slen,
42562306a36Sopenharmony_ci			      unsigned int skip)
42662306a36Sopenharmony_ci{
42762306a36Sopenharmony_ci	int skip_len = 0;
42862306a36Sopenharmony_ci	unsigned int left_size = slen, len = 0;
42962306a36Sopenharmony_ci	unsigned int j = walk->nents;
43062306a36Sopenharmony_ci	int offset, ent_len;
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci	if (!slen)
43362306a36Sopenharmony_ci		return;
43462306a36Sopenharmony_ci	while (sg && skip) {
43562306a36Sopenharmony_ci		if (sg_dma_len(sg) <= skip) {
43662306a36Sopenharmony_ci			skip -= sg_dma_len(sg);
43762306a36Sopenharmony_ci			skip_len = 0;
43862306a36Sopenharmony_ci			sg = sg_next(sg);
43962306a36Sopenharmony_ci		} else {
44062306a36Sopenharmony_ci			skip_len = skip;
44162306a36Sopenharmony_ci			skip = 0;
44262306a36Sopenharmony_ci		}
44362306a36Sopenharmony_ci	}
44462306a36Sopenharmony_ci
44562306a36Sopenharmony_ci	while (left_size && sg) {
44662306a36Sopenharmony_ci		len = min_t(u32, left_size, sg_dma_len(sg) - skip_len);
44762306a36Sopenharmony_ci		offset = 0;
44862306a36Sopenharmony_ci		while (len) {
44962306a36Sopenharmony_ci			ent_len =  min_t(u32, len, CHCR_DST_SG_SIZE);
45062306a36Sopenharmony_ci			walk->to->len[j % 8] = htons(ent_len);
45162306a36Sopenharmony_ci			walk->to->addr[j % 8] = cpu_to_be64(sg_dma_address(sg) +
45262306a36Sopenharmony_ci						      offset + skip_len);
45362306a36Sopenharmony_ci			offset += ent_len;
45462306a36Sopenharmony_ci			len -= ent_len;
45562306a36Sopenharmony_ci			j++;
45662306a36Sopenharmony_ci			if ((j % 8) == 0)
45762306a36Sopenharmony_ci				walk->to++;
45862306a36Sopenharmony_ci		}
45962306a36Sopenharmony_ci		walk->last_sg = sg;
46062306a36Sopenharmony_ci		walk->last_sg_len = min_t(u32, left_size, sg_dma_len(sg) -
46162306a36Sopenharmony_ci					  skip_len) + skip_len;
46262306a36Sopenharmony_ci		left_size -= min_t(u32, left_size, sg_dma_len(sg) - skip_len);
46362306a36Sopenharmony_ci		skip_len = 0;
46462306a36Sopenharmony_ci		sg = sg_next(sg);
46562306a36Sopenharmony_ci	}
46662306a36Sopenharmony_ci	walk->nents = j;
46762306a36Sopenharmony_ci}
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_cistatic inline void ulptx_walk_init(struct ulptx_walk *walk,
47062306a36Sopenharmony_ci				   struct ulptx_sgl *ulp)
47162306a36Sopenharmony_ci{
47262306a36Sopenharmony_ci	walk->sgl = ulp;
47362306a36Sopenharmony_ci	walk->nents = 0;
47462306a36Sopenharmony_ci	walk->pair_idx = 0;
47562306a36Sopenharmony_ci	walk->pair = ulp->sge;
47662306a36Sopenharmony_ci	walk->last_sg = NULL;
47762306a36Sopenharmony_ci	walk->last_sg_len = 0;
47862306a36Sopenharmony_ci}
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_cistatic inline void ulptx_walk_end(struct ulptx_walk *walk)
48162306a36Sopenharmony_ci{
48262306a36Sopenharmony_ci	walk->sgl->cmd_nsge = htonl(ULPTX_CMD_V(ULP_TX_SC_DSGL) |
48362306a36Sopenharmony_ci			      ULPTX_NSGE_V(walk->nents));
48462306a36Sopenharmony_ci}
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_cistatic inline void ulptx_walk_add_page(struct ulptx_walk *walk,
48862306a36Sopenharmony_ci					size_t size,
48962306a36Sopenharmony_ci					dma_addr_t addr)
49062306a36Sopenharmony_ci{
49162306a36Sopenharmony_ci	if (!size)
49262306a36Sopenharmony_ci		return;
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci	if (walk->nents == 0) {
49562306a36Sopenharmony_ci		walk->sgl->len0 = cpu_to_be32(size);
49662306a36Sopenharmony_ci		walk->sgl->addr0 = cpu_to_be64(addr);
49762306a36Sopenharmony_ci	} else {
49862306a36Sopenharmony_ci		walk->pair->addr[walk->pair_idx] = cpu_to_be64(addr);
49962306a36Sopenharmony_ci		walk->pair->len[walk->pair_idx] = cpu_to_be32(size);
50062306a36Sopenharmony_ci		walk->pair_idx = !walk->pair_idx;
50162306a36Sopenharmony_ci		if (!walk->pair_idx)
50262306a36Sopenharmony_ci			walk->pair++;
50362306a36Sopenharmony_ci	}
50462306a36Sopenharmony_ci	walk->nents++;
50562306a36Sopenharmony_ci}
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_cistatic void  ulptx_walk_add_sg(struct ulptx_walk *walk,
50862306a36Sopenharmony_ci					struct scatterlist *sg,
50962306a36Sopenharmony_ci			       unsigned int len,
51062306a36Sopenharmony_ci			       unsigned int skip)
51162306a36Sopenharmony_ci{
51262306a36Sopenharmony_ci	int small;
51362306a36Sopenharmony_ci	int skip_len = 0;
51462306a36Sopenharmony_ci	unsigned int sgmin;
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci	if (!len)
51762306a36Sopenharmony_ci		return;
51862306a36Sopenharmony_ci	while (sg && skip) {
51962306a36Sopenharmony_ci		if (sg_dma_len(sg) <= skip) {
52062306a36Sopenharmony_ci			skip -= sg_dma_len(sg);
52162306a36Sopenharmony_ci			skip_len = 0;
52262306a36Sopenharmony_ci			sg = sg_next(sg);
52362306a36Sopenharmony_ci		} else {
52462306a36Sopenharmony_ci			skip_len = skip;
52562306a36Sopenharmony_ci			skip = 0;
52662306a36Sopenharmony_ci		}
52762306a36Sopenharmony_ci	}
52862306a36Sopenharmony_ci	WARN(!sg, "SG should not be null here\n");
52962306a36Sopenharmony_ci	if (sg && (walk->nents == 0)) {
53062306a36Sopenharmony_ci		small = min_t(unsigned int, sg_dma_len(sg) - skip_len, len);
53162306a36Sopenharmony_ci		sgmin = min_t(unsigned int, small, CHCR_SRC_SG_SIZE);
53262306a36Sopenharmony_ci		walk->sgl->len0 = cpu_to_be32(sgmin);
53362306a36Sopenharmony_ci		walk->sgl->addr0 = cpu_to_be64(sg_dma_address(sg) + skip_len);
53462306a36Sopenharmony_ci		walk->nents++;
53562306a36Sopenharmony_ci		len -= sgmin;
53662306a36Sopenharmony_ci		walk->last_sg = sg;
53762306a36Sopenharmony_ci		walk->last_sg_len = sgmin + skip_len;
53862306a36Sopenharmony_ci		skip_len += sgmin;
53962306a36Sopenharmony_ci		if (sg_dma_len(sg) == skip_len) {
54062306a36Sopenharmony_ci			sg = sg_next(sg);
54162306a36Sopenharmony_ci			skip_len = 0;
54262306a36Sopenharmony_ci		}
54362306a36Sopenharmony_ci	}
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci	while (sg && len) {
54662306a36Sopenharmony_ci		small = min(sg_dma_len(sg) - skip_len, len);
54762306a36Sopenharmony_ci		sgmin = min_t(unsigned int, small, CHCR_SRC_SG_SIZE);
54862306a36Sopenharmony_ci		walk->pair->len[walk->pair_idx] = cpu_to_be32(sgmin);
54962306a36Sopenharmony_ci		walk->pair->addr[walk->pair_idx] =
55062306a36Sopenharmony_ci			cpu_to_be64(sg_dma_address(sg) + skip_len);
55162306a36Sopenharmony_ci		walk->pair_idx = !walk->pair_idx;
55262306a36Sopenharmony_ci		walk->nents++;
55362306a36Sopenharmony_ci		if (!walk->pair_idx)
55462306a36Sopenharmony_ci			walk->pair++;
55562306a36Sopenharmony_ci		len -= sgmin;
55662306a36Sopenharmony_ci		skip_len += sgmin;
55762306a36Sopenharmony_ci		walk->last_sg = sg;
55862306a36Sopenharmony_ci		walk->last_sg_len = skip_len;
55962306a36Sopenharmony_ci		if (sg_dma_len(sg) == skip_len) {
56062306a36Sopenharmony_ci			sg = sg_next(sg);
56162306a36Sopenharmony_ci			skip_len = 0;
56262306a36Sopenharmony_ci		}
56362306a36Sopenharmony_ci	}
56462306a36Sopenharmony_ci}
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_cistatic inline int get_cryptoalg_subtype(struct crypto_skcipher *tfm)
56762306a36Sopenharmony_ci{
56862306a36Sopenharmony_ci	struct skcipher_alg *alg = crypto_skcipher_alg(tfm);
56962306a36Sopenharmony_ci	struct chcr_alg_template *chcr_crypto_alg =
57062306a36Sopenharmony_ci		container_of(alg, struct chcr_alg_template, alg.skcipher);
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci	return chcr_crypto_alg->type & CRYPTO_ALG_SUB_TYPE_MASK;
57362306a36Sopenharmony_ci}
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_cistatic int cxgb4_is_crypto_q_full(struct net_device *dev, unsigned int idx)
57662306a36Sopenharmony_ci{
57762306a36Sopenharmony_ci	struct adapter *adap = netdev2adap(dev);
57862306a36Sopenharmony_ci	struct sge_uld_txq_info *txq_info =
57962306a36Sopenharmony_ci		adap->sge.uld_txq_info[CXGB4_TX_CRYPTO];
58062306a36Sopenharmony_ci	struct sge_uld_txq *txq;
58162306a36Sopenharmony_ci	int ret = 0;
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci	local_bh_disable();
58462306a36Sopenharmony_ci	txq = &txq_info->uldtxq[idx];
58562306a36Sopenharmony_ci	spin_lock(&txq->sendq.lock);
58662306a36Sopenharmony_ci	if (txq->full)
58762306a36Sopenharmony_ci		ret = -1;
58862306a36Sopenharmony_ci	spin_unlock(&txq->sendq.lock);
58962306a36Sopenharmony_ci	local_bh_enable();
59062306a36Sopenharmony_ci	return ret;
59162306a36Sopenharmony_ci}
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_cistatic int generate_copy_rrkey(struct ablk_ctx *ablkctx,
59462306a36Sopenharmony_ci			       struct _key_ctx *key_ctx)
59562306a36Sopenharmony_ci{
59662306a36Sopenharmony_ci	if (ablkctx->ciph_mode == CHCR_SCMD_CIPHER_MODE_AES_CBC) {
59762306a36Sopenharmony_ci		memcpy(key_ctx->key, ablkctx->rrkey, ablkctx->enckey_len);
59862306a36Sopenharmony_ci	} else {
59962306a36Sopenharmony_ci		memcpy(key_ctx->key,
60062306a36Sopenharmony_ci		       ablkctx->key + (ablkctx->enckey_len >> 1),
60162306a36Sopenharmony_ci		       ablkctx->enckey_len >> 1);
60262306a36Sopenharmony_ci		memcpy(key_ctx->key + (ablkctx->enckey_len >> 1),
60362306a36Sopenharmony_ci		       ablkctx->rrkey, ablkctx->enckey_len >> 1);
60462306a36Sopenharmony_ci	}
60562306a36Sopenharmony_ci	return 0;
60662306a36Sopenharmony_ci}
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_cistatic int chcr_hash_ent_in_wr(struct scatterlist *src,
60962306a36Sopenharmony_ci			     unsigned int minsg,
61062306a36Sopenharmony_ci			     unsigned int space,
61162306a36Sopenharmony_ci			     unsigned int srcskip)
61262306a36Sopenharmony_ci{
61362306a36Sopenharmony_ci	int srclen = 0;
61462306a36Sopenharmony_ci	int srcsg = minsg;
61562306a36Sopenharmony_ci	int soffset = 0, sless;
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci	if (sg_dma_len(src) == srcskip) {
61862306a36Sopenharmony_ci		src = sg_next(src);
61962306a36Sopenharmony_ci		srcskip = 0;
62062306a36Sopenharmony_ci	}
62162306a36Sopenharmony_ci	while (src && space > (sgl_ent_len[srcsg + 1])) {
62262306a36Sopenharmony_ci		sless = min_t(unsigned int, sg_dma_len(src) - soffset -	srcskip,
62362306a36Sopenharmony_ci							CHCR_SRC_SG_SIZE);
62462306a36Sopenharmony_ci		srclen += sless;
62562306a36Sopenharmony_ci		soffset += sless;
62662306a36Sopenharmony_ci		srcsg++;
62762306a36Sopenharmony_ci		if (sg_dma_len(src) == (soffset + srcskip)) {
62862306a36Sopenharmony_ci			src = sg_next(src);
62962306a36Sopenharmony_ci			soffset = 0;
63062306a36Sopenharmony_ci			srcskip = 0;
63162306a36Sopenharmony_ci		}
63262306a36Sopenharmony_ci	}
63362306a36Sopenharmony_ci	return srclen;
63462306a36Sopenharmony_ci}
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_cistatic int chcr_sg_ent_in_wr(struct scatterlist *src,
63762306a36Sopenharmony_ci			     struct scatterlist *dst,
63862306a36Sopenharmony_ci			     unsigned int minsg,
63962306a36Sopenharmony_ci			     unsigned int space,
64062306a36Sopenharmony_ci			     unsigned int srcskip,
64162306a36Sopenharmony_ci			     unsigned int dstskip)
64262306a36Sopenharmony_ci{
64362306a36Sopenharmony_ci	int srclen = 0, dstlen = 0;
64462306a36Sopenharmony_ci	int srcsg = minsg, dstsg = minsg;
64562306a36Sopenharmony_ci	int offset = 0, soffset = 0, less, sless = 0;
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci	if (sg_dma_len(src) == srcskip) {
64862306a36Sopenharmony_ci		src = sg_next(src);
64962306a36Sopenharmony_ci		srcskip = 0;
65062306a36Sopenharmony_ci	}
65162306a36Sopenharmony_ci	if (sg_dma_len(dst) == dstskip) {
65262306a36Sopenharmony_ci		dst = sg_next(dst);
65362306a36Sopenharmony_ci		dstskip = 0;
65462306a36Sopenharmony_ci	}
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_ci	while (src && dst &&
65762306a36Sopenharmony_ci	       space > (sgl_ent_len[srcsg + 1] + dsgl_ent_len[dstsg])) {
65862306a36Sopenharmony_ci		sless = min_t(unsigned int, sg_dma_len(src) - srcskip - soffset,
65962306a36Sopenharmony_ci				CHCR_SRC_SG_SIZE);
66062306a36Sopenharmony_ci		srclen += sless;
66162306a36Sopenharmony_ci		srcsg++;
66262306a36Sopenharmony_ci		offset = 0;
66362306a36Sopenharmony_ci		while (dst && ((dstsg + 1) <= MAX_DSGL_ENT) &&
66462306a36Sopenharmony_ci		       space > (sgl_ent_len[srcsg] + dsgl_ent_len[dstsg + 1])) {
66562306a36Sopenharmony_ci			if (srclen <= dstlen)
66662306a36Sopenharmony_ci				break;
66762306a36Sopenharmony_ci			less = min_t(unsigned int, sg_dma_len(dst) - offset -
66862306a36Sopenharmony_ci				     dstskip, CHCR_DST_SG_SIZE);
66962306a36Sopenharmony_ci			dstlen += less;
67062306a36Sopenharmony_ci			offset += less;
67162306a36Sopenharmony_ci			if ((offset + dstskip) == sg_dma_len(dst)) {
67262306a36Sopenharmony_ci				dst = sg_next(dst);
67362306a36Sopenharmony_ci				offset = 0;
67462306a36Sopenharmony_ci			}
67562306a36Sopenharmony_ci			dstsg++;
67662306a36Sopenharmony_ci			dstskip = 0;
67762306a36Sopenharmony_ci		}
67862306a36Sopenharmony_ci		soffset += sless;
67962306a36Sopenharmony_ci		if ((soffset + srcskip) == sg_dma_len(src)) {
68062306a36Sopenharmony_ci			src = sg_next(src);
68162306a36Sopenharmony_ci			srcskip = 0;
68262306a36Sopenharmony_ci			soffset = 0;
68362306a36Sopenharmony_ci		}
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_ci	}
68662306a36Sopenharmony_ci	return min(srclen, dstlen);
68762306a36Sopenharmony_ci}
68862306a36Sopenharmony_ci
68962306a36Sopenharmony_cistatic int chcr_cipher_fallback(struct crypto_skcipher *cipher,
69062306a36Sopenharmony_ci				struct skcipher_request *req,
69162306a36Sopenharmony_ci				u8 *iv,
69262306a36Sopenharmony_ci				unsigned short op_type)
69362306a36Sopenharmony_ci{
69462306a36Sopenharmony_ci	struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req);
69562306a36Sopenharmony_ci	int err;
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_ci	skcipher_request_set_tfm(&reqctx->fallback_req, cipher);
69862306a36Sopenharmony_ci	skcipher_request_set_callback(&reqctx->fallback_req, req->base.flags,
69962306a36Sopenharmony_ci				      req->base.complete, req->base.data);
70062306a36Sopenharmony_ci	skcipher_request_set_crypt(&reqctx->fallback_req, req->src, req->dst,
70162306a36Sopenharmony_ci				   req->cryptlen, iv);
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_ci	err = op_type ? crypto_skcipher_decrypt(&reqctx->fallback_req) :
70462306a36Sopenharmony_ci			crypto_skcipher_encrypt(&reqctx->fallback_req);
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_ci	return err;
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_ci}
70962306a36Sopenharmony_ci
71062306a36Sopenharmony_cistatic inline int get_qidxs(struct crypto_async_request *req,
71162306a36Sopenharmony_ci			    unsigned int *txqidx, unsigned int *rxqidx)
71262306a36Sopenharmony_ci{
71362306a36Sopenharmony_ci	struct crypto_tfm *tfm = req->tfm;
71462306a36Sopenharmony_ci	int ret = 0;
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_ci	switch (tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
71762306a36Sopenharmony_ci	case CRYPTO_ALG_TYPE_AEAD:
71862306a36Sopenharmony_ci	{
71962306a36Sopenharmony_ci		struct aead_request *aead_req =
72062306a36Sopenharmony_ci			container_of(req, struct aead_request, base);
72162306a36Sopenharmony_ci		struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(aead_req);
72262306a36Sopenharmony_ci		*txqidx = reqctx->txqidx;
72362306a36Sopenharmony_ci		*rxqidx = reqctx->rxqidx;
72462306a36Sopenharmony_ci		break;
72562306a36Sopenharmony_ci	}
72662306a36Sopenharmony_ci	case CRYPTO_ALG_TYPE_SKCIPHER:
72762306a36Sopenharmony_ci	{
72862306a36Sopenharmony_ci		struct skcipher_request *sk_req =
72962306a36Sopenharmony_ci			container_of(req, struct skcipher_request, base);
73062306a36Sopenharmony_ci		struct chcr_skcipher_req_ctx *reqctx =
73162306a36Sopenharmony_ci			skcipher_request_ctx(sk_req);
73262306a36Sopenharmony_ci		*txqidx = reqctx->txqidx;
73362306a36Sopenharmony_ci		*rxqidx = reqctx->rxqidx;
73462306a36Sopenharmony_ci		break;
73562306a36Sopenharmony_ci	}
73662306a36Sopenharmony_ci	case CRYPTO_ALG_TYPE_AHASH:
73762306a36Sopenharmony_ci	{
73862306a36Sopenharmony_ci		struct ahash_request *ahash_req =
73962306a36Sopenharmony_ci			container_of(req, struct ahash_request, base);
74062306a36Sopenharmony_ci		struct chcr_ahash_req_ctx *reqctx =
74162306a36Sopenharmony_ci			ahash_request_ctx(ahash_req);
74262306a36Sopenharmony_ci		*txqidx = reqctx->txqidx;
74362306a36Sopenharmony_ci		*rxqidx = reqctx->rxqidx;
74462306a36Sopenharmony_ci		break;
74562306a36Sopenharmony_ci	}
74662306a36Sopenharmony_ci	default:
74762306a36Sopenharmony_ci		ret = -EINVAL;
74862306a36Sopenharmony_ci		/* should never get here */
74962306a36Sopenharmony_ci		BUG();
75062306a36Sopenharmony_ci		break;
75162306a36Sopenharmony_ci	}
75262306a36Sopenharmony_ci	return ret;
75362306a36Sopenharmony_ci}
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_cistatic inline void create_wreq(struct chcr_context *ctx,
75662306a36Sopenharmony_ci			       struct chcr_wr *chcr_req,
75762306a36Sopenharmony_ci			       struct crypto_async_request *req,
75862306a36Sopenharmony_ci			       unsigned int imm,
75962306a36Sopenharmony_ci			       int hash_sz,
76062306a36Sopenharmony_ci			       unsigned int len16,
76162306a36Sopenharmony_ci			       unsigned int sc_len,
76262306a36Sopenharmony_ci			       unsigned int lcb)
76362306a36Sopenharmony_ci{
76462306a36Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(ctx);
76562306a36Sopenharmony_ci	unsigned int tx_channel_id, rx_channel_id;
76662306a36Sopenharmony_ci	unsigned int txqidx = 0, rxqidx = 0;
76762306a36Sopenharmony_ci	unsigned int qid, fid, portno;
76862306a36Sopenharmony_ci
76962306a36Sopenharmony_ci	get_qidxs(req, &txqidx, &rxqidx);
77062306a36Sopenharmony_ci	qid = u_ctx->lldi.rxq_ids[rxqidx];
77162306a36Sopenharmony_ci	fid = u_ctx->lldi.rxq_ids[0];
77262306a36Sopenharmony_ci	portno = rxqidx / ctx->rxq_perchan;
77362306a36Sopenharmony_ci	tx_channel_id = txqidx / ctx->txq_perchan;
77462306a36Sopenharmony_ci	rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[portno]);
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_ci
77762306a36Sopenharmony_ci	chcr_req->wreq.op_to_cctx_size = FILL_WR_OP_CCTX_SIZE;
77862306a36Sopenharmony_ci	chcr_req->wreq.pld_size_hash_size =
77962306a36Sopenharmony_ci		htonl(FW_CRYPTO_LOOKASIDE_WR_HASH_SIZE_V(hash_sz));
78062306a36Sopenharmony_ci	chcr_req->wreq.len16_pkd =
78162306a36Sopenharmony_ci		htonl(FW_CRYPTO_LOOKASIDE_WR_LEN16_V(DIV_ROUND_UP(len16, 16)));
78262306a36Sopenharmony_ci	chcr_req->wreq.cookie = cpu_to_be64((uintptr_t)req);
78362306a36Sopenharmony_ci	chcr_req->wreq.rx_chid_to_rx_q_id = FILL_WR_RX_Q_ID(rx_channel_id, qid,
78462306a36Sopenharmony_ci							    !!lcb, txqidx);
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_ci	chcr_req->ulptx.cmd_dest = FILL_ULPTX_CMD_DEST(tx_channel_id, fid);
78762306a36Sopenharmony_ci	chcr_req->ulptx.len = htonl((DIV_ROUND_UP(len16, 16) -
78862306a36Sopenharmony_ci				((sizeof(chcr_req->wreq)) >> 4)));
78962306a36Sopenharmony_ci	chcr_req->sc_imm.cmd_more = FILL_CMD_MORE(!imm);
79062306a36Sopenharmony_ci	chcr_req->sc_imm.len = cpu_to_be32(sizeof(struct cpl_tx_sec_pdu) +
79162306a36Sopenharmony_ci					   sizeof(chcr_req->key_ctx) + sc_len);
79262306a36Sopenharmony_ci}
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_ci/**
79562306a36Sopenharmony_ci *	create_cipher_wr - form the WR for cipher operations
79662306a36Sopenharmony_ci *	@wrparam: Container for create_cipher_wr()'s parameters
79762306a36Sopenharmony_ci */
79862306a36Sopenharmony_cistatic struct sk_buff *create_cipher_wr(struct cipher_wr_param *wrparam)
79962306a36Sopenharmony_ci{
80062306a36Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(wrparam->req);
80162306a36Sopenharmony_ci	struct chcr_context *ctx = c_ctx(tfm);
80262306a36Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(ctx);
80362306a36Sopenharmony_ci	struct ablk_ctx *ablkctx = ABLK_CTX(ctx);
80462306a36Sopenharmony_ci	struct sk_buff *skb = NULL;
80562306a36Sopenharmony_ci	struct chcr_wr *chcr_req;
80662306a36Sopenharmony_ci	struct cpl_rx_phys_dsgl *phys_cpl;
80762306a36Sopenharmony_ci	struct ulptx_sgl *ulptx;
80862306a36Sopenharmony_ci	struct chcr_skcipher_req_ctx *reqctx =
80962306a36Sopenharmony_ci		skcipher_request_ctx(wrparam->req);
81062306a36Sopenharmony_ci	unsigned int temp = 0, transhdr_len, dst_size;
81162306a36Sopenharmony_ci	int error;
81262306a36Sopenharmony_ci	int nents;
81362306a36Sopenharmony_ci	unsigned int kctx_len;
81462306a36Sopenharmony_ci	gfp_t flags = wrparam->req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ?
81562306a36Sopenharmony_ci			GFP_KERNEL : GFP_ATOMIC;
81662306a36Sopenharmony_ci	struct adapter *adap = padap(ctx->dev);
81762306a36Sopenharmony_ci	unsigned int rx_channel_id = reqctx->rxqidx / ctx->rxq_perchan;
81862306a36Sopenharmony_ci
81962306a36Sopenharmony_ci	rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]);
82062306a36Sopenharmony_ci	nents = sg_nents_xlen(reqctx->dstsg,  wrparam->bytes, CHCR_DST_SG_SIZE,
82162306a36Sopenharmony_ci			      reqctx->dst_ofst);
82262306a36Sopenharmony_ci	dst_size = get_space_for_phys_dsgl(nents);
82362306a36Sopenharmony_ci	kctx_len = roundup(ablkctx->enckey_len, 16);
82462306a36Sopenharmony_ci	transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, dst_size);
82562306a36Sopenharmony_ci	nents = sg_nents_xlen(reqctx->srcsg, wrparam->bytes,
82662306a36Sopenharmony_ci				  CHCR_SRC_SG_SIZE, reqctx->src_ofst);
82762306a36Sopenharmony_ci	temp = reqctx->imm ? roundup(wrparam->bytes, 16) :
82862306a36Sopenharmony_ci				     (sgl_len(nents) * 8);
82962306a36Sopenharmony_ci	transhdr_len += temp;
83062306a36Sopenharmony_ci	transhdr_len = roundup(transhdr_len, 16);
83162306a36Sopenharmony_ci	skb = alloc_skb(SGE_MAX_WR_LEN, flags);
83262306a36Sopenharmony_ci	if (!skb) {
83362306a36Sopenharmony_ci		error = -ENOMEM;
83462306a36Sopenharmony_ci		goto err;
83562306a36Sopenharmony_ci	}
83662306a36Sopenharmony_ci	chcr_req = __skb_put_zero(skb, transhdr_len);
83762306a36Sopenharmony_ci	chcr_req->sec_cpl.op_ivinsrtofst =
83862306a36Sopenharmony_ci			FILL_SEC_CPL_OP_IVINSR(rx_channel_id, 2, 1);
83962306a36Sopenharmony_ci
84062306a36Sopenharmony_ci	chcr_req->sec_cpl.pldlen = htonl(IV + wrparam->bytes);
84162306a36Sopenharmony_ci	chcr_req->sec_cpl.aadstart_cipherstop_hi =
84262306a36Sopenharmony_ci			FILL_SEC_CPL_CIPHERSTOP_HI(0, 0, IV + 1, 0);
84362306a36Sopenharmony_ci
84462306a36Sopenharmony_ci	chcr_req->sec_cpl.cipherstop_lo_authinsert =
84562306a36Sopenharmony_ci			FILL_SEC_CPL_AUTHINSERT(0, 0, 0, 0);
84662306a36Sopenharmony_ci	chcr_req->sec_cpl.seqno_numivs = FILL_SEC_CPL_SCMD0_SEQNO(reqctx->op, 0,
84762306a36Sopenharmony_ci							 ablkctx->ciph_mode,
84862306a36Sopenharmony_ci							 0, 0, IV >> 1);
84962306a36Sopenharmony_ci	chcr_req->sec_cpl.ivgen_hdrlen = FILL_SEC_CPL_IVGEN_HDRLEN(0, 0, 0,
85062306a36Sopenharmony_ci							  0, 1, dst_size);
85162306a36Sopenharmony_ci
85262306a36Sopenharmony_ci	chcr_req->key_ctx.ctx_hdr = ablkctx->key_ctx_hdr;
85362306a36Sopenharmony_ci	if ((reqctx->op == CHCR_DECRYPT_OP) &&
85462306a36Sopenharmony_ci	    (!(get_cryptoalg_subtype(tfm) ==
85562306a36Sopenharmony_ci	       CRYPTO_ALG_SUB_TYPE_CTR)) &&
85662306a36Sopenharmony_ci	    (!(get_cryptoalg_subtype(tfm) ==
85762306a36Sopenharmony_ci	       CRYPTO_ALG_SUB_TYPE_CTR_RFC3686))) {
85862306a36Sopenharmony_ci		generate_copy_rrkey(ablkctx, &chcr_req->key_ctx);
85962306a36Sopenharmony_ci	} else {
86062306a36Sopenharmony_ci		if ((ablkctx->ciph_mode == CHCR_SCMD_CIPHER_MODE_AES_CBC) ||
86162306a36Sopenharmony_ci		    (ablkctx->ciph_mode == CHCR_SCMD_CIPHER_MODE_AES_CTR)) {
86262306a36Sopenharmony_ci			memcpy(chcr_req->key_ctx.key, ablkctx->key,
86362306a36Sopenharmony_ci			       ablkctx->enckey_len);
86462306a36Sopenharmony_ci		} else {
86562306a36Sopenharmony_ci			memcpy(chcr_req->key_ctx.key, ablkctx->key +
86662306a36Sopenharmony_ci			       (ablkctx->enckey_len >> 1),
86762306a36Sopenharmony_ci			       ablkctx->enckey_len >> 1);
86862306a36Sopenharmony_ci			memcpy(chcr_req->key_ctx.key +
86962306a36Sopenharmony_ci			       (ablkctx->enckey_len >> 1),
87062306a36Sopenharmony_ci			       ablkctx->key,
87162306a36Sopenharmony_ci			       ablkctx->enckey_len >> 1);
87262306a36Sopenharmony_ci		}
87362306a36Sopenharmony_ci	}
87462306a36Sopenharmony_ci	phys_cpl = (struct cpl_rx_phys_dsgl *)((u8 *)(chcr_req + 1) + kctx_len);
87562306a36Sopenharmony_ci	ulptx = (struct ulptx_sgl *)((u8 *)(phys_cpl + 1) + dst_size);
87662306a36Sopenharmony_ci	chcr_add_cipher_src_ent(wrparam->req, ulptx, wrparam);
87762306a36Sopenharmony_ci	chcr_add_cipher_dst_ent(wrparam->req, phys_cpl, wrparam, wrparam->qid);
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_ci	atomic_inc(&adap->chcr_stats.cipher_rqst);
88062306a36Sopenharmony_ci	temp = sizeof(struct cpl_rx_phys_dsgl) + dst_size + kctx_len + IV
88162306a36Sopenharmony_ci		+ (reqctx->imm ? (wrparam->bytes) : 0);
88262306a36Sopenharmony_ci	create_wreq(c_ctx(tfm), chcr_req, &(wrparam->req->base), reqctx->imm, 0,
88362306a36Sopenharmony_ci		    transhdr_len, temp,
88462306a36Sopenharmony_ci			ablkctx->ciph_mode == CHCR_SCMD_CIPHER_MODE_AES_CBC);
88562306a36Sopenharmony_ci	reqctx->skb = skb;
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_ci	if (reqctx->op && (ablkctx->ciph_mode ==
88862306a36Sopenharmony_ci			   CHCR_SCMD_CIPHER_MODE_AES_CBC))
88962306a36Sopenharmony_ci		sg_pcopy_to_buffer(wrparam->req->src,
89062306a36Sopenharmony_ci			sg_nents(wrparam->req->src), wrparam->req->iv, 16,
89162306a36Sopenharmony_ci			reqctx->processed + wrparam->bytes - AES_BLOCK_SIZE);
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_ci	return skb;
89462306a36Sopenharmony_cierr:
89562306a36Sopenharmony_ci	return ERR_PTR(error);
89662306a36Sopenharmony_ci}
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_cistatic inline int chcr_keyctx_ck_size(unsigned int keylen)
89962306a36Sopenharmony_ci{
90062306a36Sopenharmony_ci	int ck_size = 0;
90162306a36Sopenharmony_ci
90262306a36Sopenharmony_ci	if (keylen == AES_KEYSIZE_128)
90362306a36Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128;
90462306a36Sopenharmony_ci	else if (keylen == AES_KEYSIZE_192)
90562306a36Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_192;
90662306a36Sopenharmony_ci	else if (keylen == AES_KEYSIZE_256)
90762306a36Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256;
90862306a36Sopenharmony_ci	else
90962306a36Sopenharmony_ci		ck_size = 0;
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_ci	return ck_size;
91262306a36Sopenharmony_ci}
91362306a36Sopenharmony_cistatic int chcr_cipher_fallback_setkey(struct crypto_skcipher *cipher,
91462306a36Sopenharmony_ci				       const u8 *key,
91562306a36Sopenharmony_ci				       unsigned int keylen)
91662306a36Sopenharmony_ci{
91762306a36Sopenharmony_ci	struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(cipher));
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_ci	crypto_skcipher_clear_flags(ablkctx->sw_cipher,
92062306a36Sopenharmony_ci				CRYPTO_TFM_REQ_MASK);
92162306a36Sopenharmony_ci	crypto_skcipher_set_flags(ablkctx->sw_cipher,
92262306a36Sopenharmony_ci				cipher->base.crt_flags & CRYPTO_TFM_REQ_MASK);
92362306a36Sopenharmony_ci	return crypto_skcipher_setkey(ablkctx->sw_cipher, key, keylen);
92462306a36Sopenharmony_ci}
92562306a36Sopenharmony_ci
92662306a36Sopenharmony_cistatic int chcr_aes_cbc_setkey(struct crypto_skcipher *cipher,
92762306a36Sopenharmony_ci			       const u8 *key,
92862306a36Sopenharmony_ci			       unsigned int keylen)
92962306a36Sopenharmony_ci{
93062306a36Sopenharmony_ci	struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(cipher));
93162306a36Sopenharmony_ci	unsigned int ck_size, context_size;
93262306a36Sopenharmony_ci	u16 alignment = 0;
93362306a36Sopenharmony_ci	int err;
93462306a36Sopenharmony_ci
93562306a36Sopenharmony_ci	err = chcr_cipher_fallback_setkey(cipher, key, keylen);
93662306a36Sopenharmony_ci	if (err)
93762306a36Sopenharmony_ci		goto badkey_err;
93862306a36Sopenharmony_ci
93962306a36Sopenharmony_ci	ck_size = chcr_keyctx_ck_size(keylen);
94062306a36Sopenharmony_ci	alignment = ck_size == CHCR_KEYCTX_CIPHER_KEY_SIZE_192 ? 8 : 0;
94162306a36Sopenharmony_ci	memcpy(ablkctx->key, key, keylen);
94262306a36Sopenharmony_ci	ablkctx->enckey_len = keylen;
94362306a36Sopenharmony_ci	get_aes_decrypt_key(ablkctx->rrkey, ablkctx->key, keylen << 3);
94462306a36Sopenharmony_ci	context_size = (KEY_CONTEXT_HDR_SALT_AND_PAD +
94562306a36Sopenharmony_ci			keylen + alignment) >> 4;
94662306a36Sopenharmony_ci
94762306a36Sopenharmony_ci	ablkctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, CHCR_KEYCTX_NO_KEY,
94862306a36Sopenharmony_ci						0, 0, context_size);
94962306a36Sopenharmony_ci	ablkctx->ciph_mode = CHCR_SCMD_CIPHER_MODE_AES_CBC;
95062306a36Sopenharmony_ci	return 0;
95162306a36Sopenharmony_cibadkey_err:
95262306a36Sopenharmony_ci	ablkctx->enckey_len = 0;
95362306a36Sopenharmony_ci
95462306a36Sopenharmony_ci	return err;
95562306a36Sopenharmony_ci}
95662306a36Sopenharmony_ci
95762306a36Sopenharmony_cistatic int chcr_aes_ctr_setkey(struct crypto_skcipher *cipher,
95862306a36Sopenharmony_ci				   const u8 *key,
95962306a36Sopenharmony_ci				   unsigned int keylen)
96062306a36Sopenharmony_ci{
96162306a36Sopenharmony_ci	struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(cipher));
96262306a36Sopenharmony_ci	unsigned int ck_size, context_size;
96362306a36Sopenharmony_ci	u16 alignment = 0;
96462306a36Sopenharmony_ci	int err;
96562306a36Sopenharmony_ci
96662306a36Sopenharmony_ci	err = chcr_cipher_fallback_setkey(cipher, key, keylen);
96762306a36Sopenharmony_ci	if (err)
96862306a36Sopenharmony_ci		goto badkey_err;
96962306a36Sopenharmony_ci	ck_size = chcr_keyctx_ck_size(keylen);
97062306a36Sopenharmony_ci	alignment = (ck_size == CHCR_KEYCTX_CIPHER_KEY_SIZE_192) ? 8 : 0;
97162306a36Sopenharmony_ci	memcpy(ablkctx->key, key, keylen);
97262306a36Sopenharmony_ci	ablkctx->enckey_len = keylen;
97362306a36Sopenharmony_ci	context_size = (KEY_CONTEXT_HDR_SALT_AND_PAD +
97462306a36Sopenharmony_ci			keylen + alignment) >> 4;
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_ci	ablkctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, CHCR_KEYCTX_NO_KEY,
97762306a36Sopenharmony_ci						0, 0, context_size);
97862306a36Sopenharmony_ci	ablkctx->ciph_mode = CHCR_SCMD_CIPHER_MODE_AES_CTR;
97962306a36Sopenharmony_ci
98062306a36Sopenharmony_ci	return 0;
98162306a36Sopenharmony_cibadkey_err:
98262306a36Sopenharmony_ci	ablkctx->enckey_len = 0;
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_ci	return err;
98562306a36Sopenharmony_ci}
98662306a36Sopenharmony_ci
98762306a36Sopenharmony_cistatic int chcr_aes_rfc3686_setkey(struct crypto_skcipher *cipher,
98862306a36Sopenharmony_ci				   const u8 *key,
98962306a36Sopenharmony_ci				   unsigned int keylen)
99062306a36Sopenharmony_ci{
99162306a36Sopenharmony_ci	struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(cipher));
99262306a36Sopenharmony_ci	unsigned int ck_size, context_size;
99362306a36Sopenharmony_ci	u16 alignment = 0;
99462306a36Sopenharmony_ci	int err;
99562306a36Sopenharmony_ci
99662306a36Sopenharmony_ci	if (keylen < CTR_RFC3686_NONCE_SIZE)
99762306a36Sopenharmony_ci		return -EINVAL;
99862306a36Sopenharmony_ci	memcpy(ablkctx->nonce, key + (keylen - CTR_RFC3686_NONCE_SIZE),
99962306a36Sopenharmony_ci	       CTR_RFC3686_NONCE_SIZE);
100062306a36Sopenharmony_ci
100162306a36Sopenharmony_ci	keylen -= CTR_RFC3686_NONCE_SIZE;
100262306a36Sopenharmony_ci	err = chcr_cipher_fallback_setkey(cipher, key, keylen);
100362306a36Sopenharmony_ci	if (err)
100462306a36Sopenharmony_ci		goto badkey_err;
100562306a36Sopenharmony_ci
100662306a36Sopenharmony_ci	ck_size = chcr_keyctx_ck_size(keylen);
100762306a36Sopenharmony_ci	alignment = (ck_size == CHCR_KEYCTX_CIPHER_KEY_SIZE_192) ? 8 : 0;
100862306a36Sopenharmony_ci	memcpy(ablkctx->key, key, keylen);
100962306a36Sopenharmony_ci	ablkctx->enckey_len = keylen;
101062306a36Sopenharmony_ci	context_size = (KEY_CONTEXT_HDR_SALT_AND_PAD +
101162306a36Sopenharmony_ci			keylen + alignment) >> 4;
101262306a36Sopenharmony_ci
101362306a36Sopenharmony_ci	ablkctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, CHCR_KEYCTX_NO_KEY,
101462306a36Sopenharmony_ci						0, 0, context_size);
101562306a36Sopenharmony_ci	ablkctx->ciph_mode = CHCR_SCMD_CIPHER_MODE_AES_CTR;
101662306a36Sopenharmony_ci
101762306a36Sopenharmony_ci	return 0;
101862306a36Sopenharmony_cibadkey_err:
101962306a36Sopenharmony_ci	ablkctx->enckey_len = 0;
102062306a36Sopenharmony_ci
102162306a36Sopenharmony_ci	return err;
102262306a36Sopenharmony_ci}
102362306a36Sopenharmony_cistatic void ctr_add_iv(u8 *dstiv, u8 *srciv, u32 add)
102462306a36Sopenharmony_ci{
102562306a36Sopenharmony_ci	unsigned int size = AES_BLOCK_SIZE;
102662306a36Sopenharmony_ci	__be32 *b = (__be32 *)(dstiv + size);
102762306a36Sopenharmony_ci	u32 c, prev;
102862306a36Sopenharmony_ci
102962306a36Sopenharmony_ci	memcpy(dstiv, srciv, AES_BLOCK_SIZE);
103062306a36Sopenharmony_ci	for (; size >= 4; size -= 4) {
103162306a36Sopenharmony_ci		prev = be32_to_cpu(*--b);
103262306a36Sopenharmony_ci		c = prev + add;
103362306a36Sopenharmony_ci		*b = cpu_to_be32(c);
103462306a36Sopenharmony_ci		if (prev < c)
103562306a36Sopenharmony_ci			break;
103662306a36Sopenharmony_ci		add = 1;
103762306a36Sopenharmony_ci	}
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_ci}
104062306a36Sopenharmony_ci
104162306a36Sopenharmony_cistatic unsigned int adjust_ctr_overflow(u8 *iv, u32 bytes)
104262306a36Sopenharmony_ci{
104362306a36Sopenharmony_ci	__be32 *b = (__be32 *)(iv + AES_BLOCK_SIZE);
104462306a36Sopenharmony_ci	u64 c;
104562306a36Sopenharmony_ci	u32 temp = be32_to_cpu(*--b);
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_ci	temp = ~temp;
104862306a36Sopenharmony_ci	c = (u64)temp +  1; // No of block can processed without overflow
104962306a36Sopenharmony_ci	if ((bytes / AES_BLOCK_SIZE) >= c)
105062306a36Sopenharmony_ci		bytes = c * AES_BLOCK_SIZE;
105162306a36Sopenharmony_ci	return bytes;
105262306a36Sopenharmony_ci}
105362306a36Sopenharmony_ci
105462306a36Sopenharmony_cistatic int chcr_update_tweak(struct skcipher_request *req, u8 *iv,
105562306a36Sopenharmony_ci			     u32 isfinal)
105662306a36Sopenharmony_ci{
105762306a36Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
105862306a36Sopenharmony_ci	struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(tfm));
105962306a36Sopenharmony_ci	struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req);
106062306a36Sopenharmony_ci	struct crypto_aes_ctx aes;
106162306a36Sopenharmony_ci	int ret, i;
106262306a36Sopenharmony_ci	u8 *key;
106362306a36Sopenharmony_ci	unsigned int keylen;
106462306a36Sopenharmony_ci	int round = reqctx->last_req_len / AES_BLOCK_SIZE;
106562306a36Sopenharmony_ci	int round8 = round / 8;
106662306a36Sopenharmony_ci
106762306a36Sopenharmony_ci	memcpy(iv, reqctx->iv, AES_BLOCK_SIZE);
106862306a36Sopenharmony_ci
106962306a36Sopenharmony_ci	keylen = ablkctx->enckey_len / 2;
107062306a36Sopenharmony_ci	key = ablkctx->key + keylen;
107162306a36Sopenharmony_ci	/* For a 192 bit key remove the padded zeroes which was
107262306a36Sopenharmony_ci	 * added in chcr_xts_setkey
107362306a36Sopenharmony_ci	 */
107462306a36Sopenharmony_ci	if (KEY_CONTEXT_CK_SIZE_G(ntohl(ablkctx->key_ctx_hdr))
107562306a36Sopenharmony_ci			== CHCR_KEYCTX_CIPHER_KEY_SIZE_192)
107662306a36Sopenharmony_ci		ret = aes_expandkey(&aes, key, keylen - 8);
107762306a36Sopenharmony_ci	else
107862306a36Sopenharmony_ci		ret = aes_expandkey(&aes, key, keylen);
107962306a36Sopenharmony_ci	if (ret)
108062306a36Sopenharmony_ci		return ret;
108162306a36Sopenharmony_ci	aes_encrypt(&aes, iv, iv);
108262306a36Sopenharmony_ci	for (i = 0; i < round8; i++)
108362306a36Sopenharmony_ci		gf128mul_x8_ble((le128 *)iv, (le128 *)iv);
108462306a36Sopenharmony_ci
108562306a36Sopenharmony_ci	for (i = 0; i < (round % 8); i++)
108662306a36Sopenharmony_ci		gf128mul_x_ble((le128 *)iv, (le128 *)iv);
108762306a36Sopenharmony_ci
108862306a36Sopenharmony_ci	if (!isfinal)
108962306a36Sopenharmony_ci		aes_decrypt(&aes, iv, iv);
109062306a36Sopenharmony_ci
109162306a36Sopenharmony_ci	memzero_explicit(&aes, sizeof(aes));
109262306a36Sopenharmony_ci	return 0;
109362306a36Sopenharmony_ci}
109462306a36Sopenharmony_ci
109562306a36Sopenharmony_cistatic int chcr_update_cipher_iv(struct skcipher_request *req,
109662306a36Sopenharmony_ci				   struct cpl_fw6_pld *fw6_pld, u8 *iv)
109762306a36Sopenharmony_ci{
109862306a36Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
109962306a36Sopenharmony_ci	struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req);
110062306a36Sopenharmony_ci	int subtype = get_cryptoalg_subtype(tfm);
110162306a36Sopenharmony_ci	int ret = 0;
110262306a36Sopenharmony_ci
110362306a36Sopenharmony_ci	if (subtype == CRYPTO_ALG_SUB_TYPE_CTR)
110462306a36Sopenharmony_ci		ctr_add_iv(iv, req->iv, (reqctx->processed /
110562306a36Sopenharmony_ci			   AES_BLOCK_SIZE));
110662306a36Sopenharmony_ci	else if (subtype == CRYPTO_ALG_SUB_TYPE_CTR_RFC3686)
110762306a36Sopenharmony_ci		*(__be32 *)(reqctx->iv + CTR_RFC3686_NONCE_SIZE +
110862306a36Sopenharmony_ci			CTR_RFC3686_IV_SIZE) = cpu_to_be32((reqctx->processed /
110962306a36Sopenharmony_ci						AES_BLOCK_SIZE) + 1);
111062306a36Sopenharmony_ci	else if (subtype == CRYPTO_ALG_SUB_TYPE_XTS)
111162306a36Sopenharmony_ci		ret = chcr_update_tweak(req, iv, 0);
111262306a36Sopenharmony_ci	else if (subtype == CRYPTO_ALG_SUB_TYPE_CBC) {
111362306a36Sopenharmony_ci		if (reqctx->op)
111462306a36Sopenharmony_ci			/*Updated before sending last WR*/
111562306a36Sopenharmony_ci			memcpy(iv, req->iv, AES_BLOCK_SIZE);
111662306a36Sopenharmony_ci		else
111762306a36Sopenharmony_ci			memcpy(iv, &fw6_pld->data[2], AES_BLOCK_SIZE);
111862306a36Sopenharmony_ci	}
111962306a36Sopenharmony_ci
112062306a36Sopenharmony_ci	return ret;
112162306a36Sopenharmony_ci
112262306a36Sopenharmony_ci}
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_ci/* We need separate function for final iv because in rfc3686  Initial counter
112562306a36Sopenharmony_ci * starts from 1 and buffer size of iv is 8 byte only which remains constant
112662306a36Sopenharmony_ci * for subsequent update requests
112762306a36Sopenharmony_ci */
112862306a36Sopenharmony_ci
112962306a36Sopenharmony_cistatic int chcr_final_cipher_iv(struct skcipher_request *req,
113062306a36Sopenharmony_ci				   struct cpl_fw6_pld *fw6_pld, u8 *iv)
113162306a36Sopenharmony_ci{
113262306a36Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
113362306a36Sopenharmony_ci	struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req);
113462306a36Sopenharmony_ci	int subtype = get_cryptoalg_subtype(tfm);
113562306a36Sopenharmony_ci	int ret = 0;
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_ci	if (subtype == CRYPTO_ALG_SUB_TYPE_CTR)
113862306a36Sopenharmony_ci		ctr_add_iv(iv, req->iv, DIV_ROUND_UP(reqctx->processed,
113962306a36Sopenharmony_ci						       AES_BLOCK_SIZE));
114062306a36Sopenharmony_ci	else if (subtype == CRYPTO_ALG_SUB_TYPE_XTS) {
114162306a36Sopenharmony_ci		if (!reqctx->partial_req)
114262306a36Sopenharmony_ci			memcpy(iv, reqctx->iv, AES_BLOCK_SIZE);
114362306a36Sopenharmony_ci		else
114462306a36Sopenharmony_ci			ret = chcr_update_tweak(req, iv, 1);
114562306a36Sopenharmony_ci	}
114662306a36Sopenharmony_ci	else if (subtype == CRYPTO_ALG_SUB_TYPE_CBC) {
114762306a36Sopenharmony_ci		/*Already updated for Decrypt*/
114862306a36Sopenharmony_ci		if (!reqctx->op)
114962306a36Sopenharmony_ci			memcpy(iv, &fw6_pld->data[2], AES_BLOCK_SIZE);
115062306a36Sopenharmony_ci
115162306a36Sopenharmony_ci	}
115262306a36Sopenharmony_ci	return ret;
115362306a36Sopenharmony_ci
115462306a36Sopenharmony_ci}
115562306a36Sopenharmony_ci
115662306a36Sopenharmony_cistatic int chcr_handle_cipher_resp(struct skcipher_request *req,
115762306a36Sopenharmony_ci				   unsigned char *input, int err)
115862306a36Sopenharmony_ci{
115962306a36Sopenharmony_ci	struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req);
116062306a36Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
116162306a36Sopenharmony_ci	struct cpl_fw6_pld *fw6_pld = (struct cpl_fw6_pld *)input;
116262306a36Sopenharmony_ci	struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(tfm));
116362306a36Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(c_ctx(tfm));
116462306a36Sopenharmony_ci	struct chcr_dev *dev = c_ctx(tfm)->dev;
116562306a36Sopenharmony_ci	struct chcr_context *ctx = c_ctx(tfm);
116662306a36Sopenharmony_ci	struct adapter *adap = padap(ctx->dev);
116762306a36Sopenharmony_ci	struct cipher_wr_param wrparam;
116862306a36Sopenharmony_ci	struct sk_buff *skb;
116962306a36Sopenharmony_ci	int bytes;
117062306a36Sopenharmony_ci
117162306a36Sopenharmony_ci	if (err)
117262306a36Sopenharmony_ci		goto unmap;
117362306a36Sopenharmony_ci	if (req->cryptlen == reqctx->processed) {
117462306a36Sopenharmony_ci		chcr_cipher_dma_unmap(&ULD_CTX(c_ctx(tfm))->lldi.pdev->dev,
117562306a36Sopenharmony_ci				      req);
117662306a36Sopenharmony_ci		err = chcr_final_cipher_iv(req, fw6_pld, req->iv);
117762306a36Sopenharmony_ci		goto complete;
117862306a36Sopenharmony_ci	}
117962306a36Sopenharmony_ci
118062306a36Sopenharmony_ci	if (!reqctx->imm) {
118162306a36Sopenharmony_ci		bytes = chcr_sg_ent_in_wr(reqctx->srcsg, reqctx->dstsg, 0,
118262306a36Sopenharmony_ci					  CIP_SPACE_LEFT(ablkctx->enckey_len),
118362306a36Sopenharmony_ci					  reqctx->src_ofst, reqctx->dst_ofst);
118462306a36Sopenharmony_ci		if ((bytes + reqctx->processed) >= req->cryptlen)
118562306a36Sopenharmony_ci			bytes  = req->cryptlen - reqctx->processed;
118662306a36Sopenharmony_ci		else
118762306a36Sopenharmony_ci			bytes = rounddown(bytes, 16);
118862306a36Sopenharmony_ci	} else {
118962306a36Sopenharmony_ci		/*CTR mode counter overfloa*/
119062306a36Sopenharmony_ci		bytes  = req->cryptlen - reqctx->processed;
119162306a36Sopenharmony_ci	}
119262306a36Sopenharmony_ci	err = chcr_update_cipher_iv(req, fw6_pld, reqctx->iv);
119362306a36Sopenharmony_ci	if (err)
119462306a36Sopenharmony_ci		goto unmap;
119562306a36Sopenharmony_ci
119662306a36Sopenharmony_ci	if (unlikely(bytes == 0)) {
119762306a36Sopenharmony_ci		chcr_cipher_dma_unmap(&ULD_CTX(c_ctx(tfm))->lldi.pdev->dev,
119862306a36Sopenharmony_ci				      req);
119962306a36Sopenharmony_ci		memcpy(req->iv, reqctx->init_iv, IV);
120062306a36Sopenharmony_ci		atomic_inc(&adap->chcr_stats.fallback);
120162306a36Sopenharmony_ci		err = chcr_cipher_fallback(ablkctx->sw_cipher, req, req->iv,
120262306a36Sopenharmony_ci					   reqctx->op);
120362306a36Sopenharmony_ci		goto complete;
120462306a36Sopenharmony_ci	}
120562306a36Sopenharmony_ci
120662306a36Sopenharmony_ci	if (get_cryptoalg_subtype(tfm) ==
120762306a36Sopenharmony_ci	    CRYPTO_ALG_SUB_TYPE_CTR)
120862306a36Sopenharmony_ci		bytes = adjust_ctr_overflow(reqctx->iv, bytes);
120962306a36Sopenharmony_ci	wrparam.qid = u_ctx->lldi.rxq_ids[reqctx->rxqidx];
121062306a36Sopenharmony_ci	wrparam.req = req;
121162306a36Sopenharmony_ci	wrparam.bytes = bytes;
121262306a36Sopenharmony_ci	skb = create_cipher_wr(&wrparam);
121362306a36Sopenharmony_ci	if (IS_ERR(skb)) {
121462306a36Sopenharmony_ci		pr_err("%s : Failed to form WR. No memory\n", __func__);
121562306a36Sopenharmony_ci		err = PTR_ERR(skb);
121662306a36Sopenharmony_ci		goto unmap;
121762306a36Sopenharmony_ci	}
121862306a36Sopenharmony_ci	skb->dev = u_ctx->lldi.ports[0];
121962306a36Sopenharmony_ci	set_wr_txq(skb, CPL_PRIORITY_DATA, reqctx->txqidx);
122062306a36Sopenharmony_ci	chcr_send_wr(skb);
122162306a36Sopenharmony_ci	reqctx->last_req_len = bytes;
122262306a36Sopenharmony_ci	reqctx->processed += bytes;
122362306a36Sopenharmony_ci	if (get_cryptoalg_subtype(tfm) ==
122462306a36Sopenharmony_ci		CRYPTO_ALG_SUB_TYPE_CBC && req->base.flags ==
122562306a36Sopenharmony_ci			CRYPTO_TFM_REQ_MAY_SLEEP ) {
122662306a36Sopenharmony_ci		complete(&ctx->cbc_aes_aio_done);
122762306a36Sopenharmony_ci	}
122862306a36Sopenharmony_ci	return 0;
122962306a36Sopenharmony_ciunmap:
123062306a36Sopenharmony_ci	chcr_cipher_dma_unmap(&ULD_CTX(c_ctx(tfm))->lldi.pdev->dev, req);
123162306a36Sopenharmony_cicomplete:
123262306a36Sopenharmony_ci	if (get_cryptoalg_subtype(tfm) ==
123362306a36Sopenharmony_ci		CRYPTO_ALG_SUB_TYPE_CBC && req->base.flags ==
123462306a36Sopenharmony_ci			CRYPTO_TFM_REQ_MAY_SLEEP ) {
123562306a36Sopenharmony_ci		complete(&ctx->cbc_aes_aio_done);
123662306a36Sopenharmony_ci	}
123762306a36Sopenharmony_ci	chcr_dec_wrcount(dev);
123862306a36Sopenharmony_ci	skcipher_request_complete(req, err);
123962306a36Sopenharmony_ci	return err;
124062306a36Sopenharmony_ci}
124162306a36Sopenharmony_ci
124262306a36Sopenharmony_cistatic int process_cipher(struct skcipher_request *req,
124362306a36Sopenharmony_ci				  unsigned short qid,
124462306a36Sopenharmony_ci				  struct sk_buff **skb,
124562306a36Sopenharmony_ci				  unsigned short op_type)
124662306a36Sopenharmony_ci{
124762306a36Sopenharmony_ci	struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req);
124862306a36Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
124962306a36Sopenharmony_ci	unsigned int ivsize = crypto_skcipher_ivsize(tfm);
125062306a36Sopenharmony_ci	struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(tfm));
125162306a36Sopenharmony_ci	struct adapter *adap = padap(c_ctx(tfm)->dev);
125262306a36Sopenharmony_ci	struct	cipher_wr_param wrparam;
125362306a36Sopenharmony_ci	int bytes, err = -EINVAL;
125462306a36Sopenharmony_ci	int subtype;
125562306a36Sopenharmony_ci
125662306a36Sopenharmony_ci	reqctx->processed = 0;
125762306a36Sopenharmony_ci	reqctx->partial_req = 0;
125862306a36Sopenharmony_ci	if (!req->iv)
125962306a36Sopenharmony_ci		goto error;
126062306a36Sopenharmony_ci	subtype = get_cryptoalg_subtype(tfm);
126162306a36Sopenharmony_ci	if ((ablkctx->enckey_len == 0) || (ivsize > AES_BLOCK_SIZE) ||
126262306a36Sopenharmony_ci	    (req->cryptlen == 0) ||
126362306a36Sopenharmony_ci	    (req->cryptlen % crypto_skcipher_blocksize(tfm))) {
126462306a36Sopenharmony_ci		if (req->cryptlen == 0 && subtype != CRYPTO_ALG_SUB_TYPE_XTS)
126562306a36Sopenharmony_ci			goto fallback;
126662306a36Sopenharmony_ci		else if (req->cryptlen % crypto_skcipher_blocksize(tfm) &&
126762306a36Sopenharmony_ci			 subtype == CRYPTO_ALG_SUB_TYPE_XTS)
126862306a36Sopenharmony_ci			goto fallback;
126962306a36Sopenharmony_ci		pr_err("AES: Invalid value of Key Len %d nbytes %d IV Len %d\n",
127062306a36Sopenharmony_ci		       ablkctx->enckey_len, req->cryptlen, ivsize);
127162306a36Sopenharmony_ci		goto error;
127262306a36Sopenharmony_ci	}
127362306a36Sopenharmony_ci
127462306a36Sopenharmony_ci	err = chcr_cipher_dma_map(&ULD_CTX(c_ctx(tfm))->lldi.pdev->dev, req);
127562306a36Sopenharmony_ci	if (err)
127662306a36Sopenharmony_ci		goto error;
127762306a36Sopenharmony_ci	if (req->cryptlen < (SGE_MAX_WR_LEN - (sizeof(struct chcr_wr) +
127862306a36Sopenharmony_ci					    AES_MIN_KEY_SIZE +
127962306a36Sopenharmony_ci					    sizeof(struct cpl_rx_phys_dsgl) +
128062306a36Sopenharmony_ci					/*Min dsgl size*/
128162306a36Sopenharmony_ci					    32))) {
128262306a36Sopenharmony_ci		/* Can be sent as Imm*/
128362306a36Sopenharmony_ci		unsigned int dnents = 0, transhdr_len, phys_dsgl, kctx_len;
128462306a36Sopenharmony_ci
128562306a36Sopenharmony_ci		dnents = sg_nents_xlen(req->dst, req->cryptlen,
128662306a36Sopenharmony_ci				       CHCR_DST_SG_SIZE, 0);
128762306a36Sopenharmony_ci		phys_dsgl = get_space_for_phys_dsgl(dnents);
128862306a36Sopenharmony_ci		kctx_len = roundup(ablkctx->enckey_len, 16);
128962306a36Sopenharmony_ci		transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, phys_dsgl);
129062306a36Sopenharmony_ci		reqctx->imm = (transhdr_len + IV + req->cryptlen) <=
129162306a36Sopenharmony_ci			SGE_MAX_WR_LEN;
129262306a36Sopenharmony_ci		bytes = IV + req->cryptlen;
129362306a36Sopenharmony_ci
129462306a36Sopenharmony_ci	} else {
129562306a36Sopenharmony_ci		reqctx->imm = 0;
129662306a36Sopenharmony_ci	}
129762306a36Sopenharmony_ci
129862306a36Sopenharmony_ci	if (!reqctx->imm) {
129962306a36Sopenharmony_ci		bytes = chcr_sg_ent_in_wr(req->src, req->dst, 0,
130062306a36Sopenharmony_ci					  CIP_SPACE_LEFT(ablkctx->enckey_len),
130162306a36Sopenharmony_ci					  0, 0);
130262306a36Sopenharmony_ci		if ((bytes + reqctx->processed) >= req->cryptlen)
130362306a36Sopenharmony_ci			bytes  = req->cryptlen - reqctx->processed;
130462306a36Sopenharmony_ci		else
130562306a36Sopenharmony_ci			bytes = rounddown(bytes, 16);
130662306a36Sopenharmony_ci	} else {
130762306a36Sopenharmony_ci		bytes = req->cryptlen;
130862306a36Sopenharmony_ci	}
130962306a36Sopenharmony_ci	if (subtype == CRYPTO_ALG_SUB_TYPE_CTR) {
131062306a36Sopenharmony_ci		bytes = adjust_ctr_overflow(req->iv, bytes);
131162306a36Sopenharmony_ci	}
131262306a36Sopenharmony_ci	if (subtype == CRYPTO_ALG_SUB_TYPE_CTR_RFC3686) {
131362306a36Sopenharmony_ci		memcpy(reqctx->iv, ablkctx->nonce, CTR_RFC3686_NONCE_SIZE);
131462306a36Sopenharmony_ci		memcpy(reqctx->iv + CTR_RFC3686_NONCE_SIZE, req->iv,
131562306a36Sopenharmony_ci				CTR_RFC3686_IV_SIZE);
131662306a36Sopenharmony_ci
131762306a36Sopenharmony_ci		/* initialize counter portion of counter block */
131862306a36Sopenharmony_ci		*(__be32 *)(reqctx->iv + CTR_RFC3686_NONCE_SIZE +
131962306a36Sopenharmony_ci			CTR_RFC3686_IV_SIZE) = cpu_to_be32(1);
132062306a36Sopenharmony_ci		memcpy(reqctx->init_iv, reqctx->iv, IV);
132162306a36Sopenharmony_ci
132262306a36Sopenharmony_ci	} else {
132362306a36Sopenharmony_ci
132462306a36Sopenharmony_ci		memcpy(reqctx->iv, req->iv, IV);
132562306a36Sopenharmony_ci		memcpy(reqctx->init_iv, req->iv, IV);
132662306a36Sopenharmony_ci	}
132762306a36Sopenharmony_ci	if (unlikely(bytes == 0)) {
132862306a36Sopenharmony_ci		chcr_cipher_dma_unmap(&ULD_CTX(c_ctx(tfm))->lldi.pdev->dev,
132962306a36Sopenharmony_ci				      req);
133062306a36Sopenharmony_cifallback:       atomic_inc(&adap->chcr_stats.fallback);
133162306a36Sopenharmony_ci		err = chcr_cipher_fallback(ablkctx->sw_cipher, req,
133262306a36Sopenharmony_ci					   subtype ==
133362306a36Sopenharmony_ci					   CRYPTO_ALG_SUB_TYPE_CTR_RFC3686 ?
133462306a36Sopenharmony_ci					   reqctx->iv : req->iv,
133562306a36Sopenharmony_ci					   op_type);
133662306a36Sopenharmony_ci		goto error;
133762306a36Sopenharmony_ci	}
133862306a36Sopenharmony_ci	reqctx->op = op_type;
133962306a36Sopenharmony_ci	reqctx->srcsg = req->src;
134062306a36Sopenharmony_ci	reqctx->dstsg = req->dst;
134162306a36Sopenharmony_ci	reqctx->src_ofst = 0;
134262306a36Sopenharmony_ci	reqctx->dst_ofst = 0;
134362306a36Sopenharmony_ci	wrparam.qid = qid;
134462306a36Sopenharmony_ci	wrparam.req = req;
134562306a36Sopenharmony_ci	wrparam.bytes = bytes;
134662306a36Sopenharmony_ci	*skb = create_cipher_wr(&wrparam);
134762306a36Sopenharmony_ci	if (IS_ERR(*skb)) {
134862306a36Sopenharmony_ci		err = PTR_ERR(*skb);
134962306a36Sopenharmony_ci		goto unmap;
135062306a36Sopenharmony_ci	}
135162306a36Sopenharmony_ci	reqctx->processed = bytes;
135262306a36Sopenharmony_ci	reqctx->last_req_len = bytes;
135362306a36Sopenharmony_ci	reqctx->partial_req = !!(req->cryptlen - reqctx->processed);
135462306a36Sopenharmony_ci
135562306a36Sopenharmony_ci	return 0;
135662306a36Sopenharmony_ciunmap:
135762306a36Sopenharmony_ci	chcr_cipher_dma_unmap(&ULD_CTX(c_ctx(tfm))->lldi.pdev->dev, req);
135862306a36Sopenharmony_cierror:
135962306a36Sopenharmony_ci	return err;
136062306a36Sopenharmony_ci}
136162306a36Sopenharmony_ci
136262306a36Sopenharmony_cistatic int chcr_aes_encrypt(struct skcipher_request *req)
136362306a36Sopenharmony_ci{
136462306a36Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
136562306a36Sopenharmony_ci	struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req);
136662306a36Sopenharmony_ci	struct chcr_dev *dev = c_ctx(tfm)->dev;
136762306a36Sopenharmony_ci	struct sk_buff *skb = NULL;
136862306a36Sopenharmony_ci	int err;
136962306a36Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(c_ctx(tfm));
137062306a36Sopenharmony_ci	struct chcr_context *ctx = c_ctx(tfm);
137162306a36Sopenharmony_ci	unsigned int cpu;
137262306a36Sopenharmony_ci
137362306a36Sopenharmony_ci	cpu = get_cpu();
137462306a36Sopenharmony_ci	reqctx->txqidx = cpu % ctx->ntxq;
137562306a36Sopenharmony_ci	reqctx->rxqidx = cpu % ctx->nrxq;
137662306a36Sopenharmony_ci	put_cpu();
137762306a36Sopenharmony_ci
137862306a36Sopenharmony_ci	err = chcr_inc_wrcount(dev);
137962306a36Sopenharmony_ci	if (err)
138062306a36Sopenharmony_ci		return -ENXIO;
138162306a36Sopenharmony_ci	if (unlikely(cxgb4_is_crypto_q_full(u_ctx->lldi.ports[0],
138262306a36Sopenharmony_ci						reqctx->txqidx) &&
138362306a36Sopenharmony_ci		(!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)))) {
138462306a36Sopenharmony_ci			err = -ENOSPC;
138562306a36Sopenharmony_ci			goto error;
138662306a36Sopenharmony_ci	}
138762306a36Sopenharmony_ci
138862306a36Sopenharmony_ci	err = process_cipher(req, u_ctx->lldi.rxq_ids[reqctx->rxqidx],
138962306a36Sopenharmony_ci			     &skb, CHCR_ENCRYPT_OP);
139062306a36Sopenharmony_ci	if (err || !skb)
139162306a36Sopenharmony_ci		return  err;
139262306a36Sopenharmony_ci	skb->dev = u_ctx->lldi.ports[0];
139362306a36Sopenharmony_ci	set_wr_txq(skb, CPL_PRIORITY_DATA, reqctx->txqidx);
139462306a36Sopenharmony_ci	chcr_send_wr(skb);
139562306a36Sopenharmony_ci	if (get_cryptoalg_subtype(tfm) ==
139662306a36Sopenharmony_ci		CRYPTO_ALG_SUB_TYPE_CBC && req->base.flags ==
139762306a36Sopenharmony_ci			CRYPTO_TFM_REQ_MAY_SLEEP ) {
139862306a36Sopenharmony_ci			reqctx->partial_req = 1;
139962306a36Sopenharmony_ci			wait_for_completion(&ctx->cbc_aes_aio_done);
140062306a36Sopenharmony_ci        }
140162306a36Sopenharmony_ci	return -EINPROGRESS;
140262306a36Sopenharmony_cierror:
140362306a36Sopenharmony_ci	chcr_dec_wrcount(dev);
140462306a36Sopenharmony_ci	return err;
140562306a36Sopenharmony_ci}
140662306a36Sopenharmony_ci
140762306a36Sopenharmony_cistatic int chcr_aes_decrypt(struct skcipher_request *req)
140862306a36Sopenharmony_ci{
140962306a36Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
141062306a36Sopenharmony_ci	struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req);
141162306a36Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(c_ctx(tfm));
141262306a36Sopenharmony_ci	struct chcr_dev *dev = c_ctx(tfm)->dev;
141362306a36Sopenharmony_ci	struct sk_buff *skb = NULL;
141462306a36Sopenharmony_ci	int err;
141562306a36Sopenharmony_ci	struct chcr_context *ctx = c_ctx(tfm);
141662306a36Sopenharmony_ci	unsigned int cpu;
141762306a36Sopenharmony_ci
141862306a36Sopenharmony_ci	cpu = get_cpu();
141962306a36Sopenharmony_ci	reqctx->txqidx = cpu % ctx->ntxq;
142062306a36Sopenharmony_ci	reqctx->rxqidx = cpu % ctx->nrxq;
142162306a36Sopenharmony_ci	put_cpu();
142262306a36Sopenharmony_ci
142362306a36Sopenharmony_ci	err = chcr_inc_wrcount(dev);
142462306a36Sopenharmony_ci	if (err)
142562306a36Sopenharmony_ci		return -ENXIO;
142662306a36Sopenharmony_ci
142762306a36Sopenharmony_ci	if (unlikely(cxgb4_is_crypto_q_full(u_ctx->lldi.ports[0],
142862306a36Sopenharmony_ci						reqctx->txqidx) &&
142962306a36Sopenharmony_ci		(!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG))))
143062306a36Sopenharmony_ci			return -ENOSPC;
143162306a36Sopenharmony_ci	err = process_cipher(req, u_ctx->lldi.rxq_ids[reqctx->rxqidx],
143262306a36Sopenharmony_ci			     &skb, CHCR_DECRYPT_OP);
143362306a36Sopenharmony_ci	if (err || !skb)
143462306a36Sopenharmony_ci		return err;
143562306a36Sopenharmony_ci	skb->dev = u_ctx->lldi.ports[0];
143662306a36Sopenharmony_ci	set_wr_txq(skb, CPL_PRIORITY_DATA, reqctx->txqidx);
143762306a36Sopenharmony_ci	chcr_send_wr(skb);
143862306a36Sopenharmony_ci	return -EINPROGRESS;
143962306a36Sopenharmony_ci}
144062306a36Sopenharmony_cistatic int chcr_device_init(struct chcr_context *ctx)
144162306a36Sopenharmony_ci{
144262306a36Sopenharmony_ci	struct uld_ctx *u_ctx = NULL;
144362306a36Sopenharmony_ci	int txq_perchan, ntxq;
144462306a36Sopenharmony_ci	int err = 0, rxq_perchan;
144562306a36Sopenharmony_ci
144662306a36Sopenharmony_ci	if (!ctx->dev) {
144762306a36Sopenharmony_ci		u_ctx = assign_chcr_device();
144862306a36Sopenharmony_ci		if (!u_ctx) {
144962306a36Sopenharmony_ci			err = -ENXIO;
145062306a36Sopenharmony_ci			pr_err("chcr device assignment fails\n");
145162306a36Sopenharmony_ci			goto out;
145262306a36Sopenharmony_ci		}
145362306a36Sopenharmony_ci		ctx->dev = &u_ctx->dev;
145462306a36Sopenharmony_ci		ntxq = u_ctx->lldi.ntxq;
145562306a36Sopenharmony_ci		rxq_perchan = u_ctx->lldi.nrxq / u_ctx->lldi.nchan;
145662306a36Sopenharmony_ci		txq_perchan = ntxq / u_ctx->lldi.nchan;
145762306a36Sopenharmony_ci		ctx->ntxq = ntxq;
145862306a36Sopenharmony_ci		ctx->nrxq = u_ctx->lldi.nrxq;
145962306a36Sopenharmony_ci		ctx->rxq_perchan = rxq_perchan;
146062306a36Sopenharmony_ci		ctx->txq_perchan = txq_perchan;
146162306a36Sopenharmony_ci	}
146262306a36Sopenharmony_ciout:
146362306a36Sopenharmony_ci	return err;
146462306a36Sopenharmony_ci}
146562306a36Sopenharmony_ci
146662306a36Sopenharmony_cistatic int chcr_init_tfm(struct crypto_skcipher *tfm)
146762306a36Sopenharmony_ci{
146862306a36Sopenharmony_ci	struct skcipher_alg *alg = crypto_skcipher_alg(tfm);
146962306a36Sopenharmony_ci	struct chcr_context *ctx = crypto_skcipher_ctx(tfm);
147062306a36Sopenharmony_ci	struct ablk_ctx *ablkctx = ABLK_CTX(ctx);
147162306a36Sopenharmony_ci
147262306a36Sopenharmony_ci	ablkctx->sw_cipher = crypto_alloc_skcipher(alg->base.cra_name, 0,
147362306a36Sopenharmony_ci				CRYPTO_ALG_NEED_FALLBACK);
147462306a36Sopenharmony_ci	if (IS_ERR(ablkctx->sw_cipher)) {
147562306a36Sopenharmony_ci		pr_err("failed to allocate fallback for %s\n", alg->base.cra_name);
147662306a36Sopenharmony_ci		return PTR_ERR(ablkctx->sw_cipher);
147762306a36Sopenharmony_ci	}
147862306a36Sopenharmony_ci	init_completion(&ctx->cbc_aes_aio_done);
147962306a36Sopenharmony_ci	crypto_skcipher_set_reqsize(tfm, sizeof(struct chcr_skcipher_req_ctx) +
148062306a36Sopenharmony_ci					 crypto_skcipher_reqsize(ablkctx->sw_cipher));
148162306a36Sopenharmony_ci
148262306a36Sopenharmony_ci	return chcr_device_init(ctx);
148362306a36Sopenharmony_ci}
148462306a36Sopenharmony_ci
148562306a36Sopenharmony_cistatic int chcr_rfc3686_init(struct crypto_skcipher *tfm)
148662306a36Sopenharmony_ci{
148762306a36Sopenharmony_ci	struct skcipher_alg *alg = crypto_skcipher_alg(tfm);
148862306a36Sopenharmony_ci	struct chcr_context *ctx = crypto_skcipher_ctx(tfm);
148962306a36Sopenharmony_ci	struct ablk_ctx *ablkctx = ABLK_CTX(ctx);
149062306a36Sopenharmony_ci
149162306a36Sopenharmony_ci	/*RFC3686 initialises IV counter value to 1, rfc3686(ctr(aes))
149262306a36Sopenharmony_ci	 * cannot be used as fallback in chcr_handle_cipher_response
149362306a36Sopenharmony_ci	 */
149462306a36Sopenharmony_ci	ablkctx->sw_cipher = crypto_alloc_skcipher("ctr(aes)", 0,
149562306a36Sopenharmony_ci				CRYPTO_ALG_NEED_FALLBACK);
149662306a36Sopenharmony_ci	if (IS_ERR(ablkctx->sw_cipher)) {
149762306a36Sopenharmony_ci		pr_err("failed to allocate fallback for %s\n", alg->base.cra_name);
149862306a36Sopenharmony_ci		return PTR_ERR(ablkctx->sw_cipher);
149962306a36Sopenharmony_ci	}
150062306a36Sopenharmony_ci	crypto_skcipher_set_reqsize(tfm, sizeof(struct chcr_skcipher_req_ctx) +
150162306a36Sopenharmony_ci				    crypto_skcipher_reqsize(ablkctx->sw_cipher));
150262306a36Sopenharmony_ci	return chcr_device_init(ctx);
150362306a36Sopenharmony_ci}
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_ci
150662306a36Sopenharmony_cistatic void chcr_exit_tfm(struct crypto_skcipher *tfm)
150762306a36Sopenharmony_ci{
150862306a36Sopenharmony_ci	struct chcr_context *ctx = crypto_skcipher_ctx(tfm);
150962306a36Sopenharmony_ci	struct ablk_ctx *ablkctx = ABLK_CTX(ctx);
151062306a36Sopenharmony_ci
151162306a36Sopenharmony_ci	crypto_free_skcipher(ablkctx->sw_cipher);
151262306a36Sopenharmony_ci}
151362306a36Sopenharmony_ci
151462306a36Sopenharmony_cistatic int get_alg_config(struct algo_param *params,
151562306a36Sopenharmony_ci			  unsigned int auth_size)
151662306a36Sopenharmony_ci{
151762306a36Sopenharmony_ci	switch (auth_size) {
151862306a36Sopenharmony_ci	case SHA1_DIGEST_SIZE:
151962306a36Sopenharmony_ci		params->mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_160;
152062306a36Sopenharmony_ci		params->auth_mode = CHCR_SCMD_AUTH_MODE_SHA1;
152162306a36Sopenharmony_ci		params->result_size = SHA1_DIGEST_SIZE;
152262306a36Sopenharmony_ci		break;
152362306a36Sopenharmony_ci	case SHA224_DIGEST_SIZE:
152462306a36Sopenharmony_ci		params->mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_256;
152562306a36Sopenharmony_ci		params->auth_mode = CHCR_SCMD_AUTH_MODE_SHA224;
152662306a36Sopenharmony_ci		params->result_size = SHA256_DIGEST_SIZE;
152762306a36Sopenharmony_ci		break;
152862306a36Sopenharmony_ci	case SHA256_DIGEST_SIZE:
152962306a36Sopenharmony_ci		params->mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_256;
153062306a36Sopenharmony_ci		params->auth_mode = CHCR_SCMD_AUTH_MODE_SHA256;
153162306a36Sopenharmony_ci		params->result_size = SHA256_DIGEST_SIZE;
153262306a36Sopenharmony_ci		break;
153362306a36Sopenharmony_ci	case SHA384_DIGEST_SIZE:
153462306a36Sopenharmony_ci		params->mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_512;
153562306a36Sopenharmony_ci		params->auth_mode = CHCR_SCMD_AUTH_MODE_SHA512_384;
153662306a36Sopenharmony_ci		params->result_size = SHA512_DIGEST_SIZE;
153762306a36Sopenharmony_ci		break;
153862306a36Sopenharmony_ci	case SHA512_DIGEST_SIZE:
153962306a36Sopenharmony_ci		params->mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_512;
154062306a36Sopenharmony_ci		params->auth_mode = CHCR_SCMD_AUTH_MODE_SHA512_512;
154162306a36Sopenharmony_ci		params->result_size = SHA512_DIGEST_SIZE;
154262306a36Sopenharmony_ci		break;
154362306a36Sopenharmony_ci	default:
154462306a36Sopenharmony_ci		pr_err("ERROR, unsupported digest size\n");
154562306a36Sopenharmony_ci		return -EINVAL;
154662306a36Sopenharmony_ci	}
154762306a36Sopenharmony_ci	return 0;
154862306a36Sopenharmony_ci}
154962306a36Sopenharmony_ci
155062306a36Sopenharmony_cistatic inline void chcr_free_shash(struct crypto_shash *base_hash)
155162306a36Sopenharmony_ci{
155262306a36Sopenharmony_ci		crypto_free_shash(base_hash);
155362306a36Sopenharmony_ci}
155462306a36Sopenharmony_ci
155562306a36Sopenharmony_ci/**
155662306a36Sopenharmony_ci *	create_hash_wr - Create hash work request
155762306a36Sopenharmony_ci *	@req: Cipher req base
155862306a36Sopenharmony_ci *	@param: Container for create_hash_wr()'s parameters
155962306a36Sopenharmony_ci */
156062306a36Sopenharmony_cistatic struct sk_buff *create_hash_wr(struct ahash_request *req,
156162306a36Sopenharmony_ci				      struct hash_wr_param *param)
156262306a36Sopenharmony_ci{
156362306a36Sopenharmony_ci	struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req);
156462306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
156562306a36Sopenharmony_ci	struct chcr_context *ctx = h_ctx(tfm);
156662306a36Sopenharmony_ci	struct hmac_ctx *hmacctx = HMAC_CTX(ctx);
156762306a36Sopenharmony_ci	struct sk_buff *skb = NULL;
156862306a36Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(ctx);
156962306a36Sopenharmony_ci	struct chcr_wr *chcr_req;
157062306a36Sopenharmony_ci	struct ulptx_sgl *ulptx;
157162306a36Sopenharmony_ci	unsigned int nents = 0, transhdr_len;
157262306a36Sopenharmony_ci	unsigned int temp = 0;
157362306a36Sopenharmony_ci	gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
157462306a36Sopenharmony_ci		GFP_ATOMIC;
157562306a36Sopenharmony_ci	struct adapter *adap = padap(h_ctx(tfm)->dev);
157662306a36Sopenharmony_ci	int error = 0;
157762306a36Sopenharmony_ci	unsigned int rx_channel_id = req_ctx->rxqidx / ctx->rxq_perchan;
157862306a36Sopenharmony_ci
157962306a36Sopenharmony_ci	rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]);
158062306a36Sopenharmony_ci	transhdr_len = HASH_TRANSHDR_SIZE(param->kctx_len);
158162306a36Sopenharmony_ci	req_ctx->hctx_wr.imm = (transhdr_len + param->bfr_len +
158262306a36Sopenharmony_ci				param->sg_len) <= SGE_MAX_WR_LEN;
158362306a36Sopenharmony_ci	nents = sg_nents_xlen(req_ctx->hctx_wr.srcsg, param->sg_len,
158462306a36Sopenharmony_ci		      CHCR_SRC_SG_SIZE, req_ctx->hctx_wr.src_ofst);
158562306a36Sopenharmony_ci	nents += param->bfr_len ? 1 : 0;
158662306a36Sopenharmony_ci	transhdr_len += req_ctx->hctx_wr.imm ? roundup(param->bfr_len +
158762306a36Sopenharmony_ci				param->sg_len, 16) : (sgl_len(nents) * 8);
158862306a36Sopenharmony_ci	transhdr_len = roundup(transhdr_len, 16);
158962306a36Sopenharmony_ci
159062306a36Sopenharmony_ci	skb = alloc_skb(transhdr_len, flags);
159162306a36Sopenharmony_ci	if (!skb)
159262306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
159362306a36Sopenharmony_ci	chcr_req = __skb_put_zero(skb, transhdr_len);
159462306a36Sopenharmony_ci
159562306a36Sopenharmony_ci	chcr_req->sec_cpl.op_ivinsrtofst =
159662306a36Sopenharmony_ci		FILL_SEC_CPL_OP_IVINSR(rx_channel_id, 2, 0);
159762306a36Sopenharmony_ci
159862306a36Sopenharmony_ci	chcr_req->sec_cpl.pldlen = htonl(param->bfr_len + param->sg_len);
159962306a36Sopenharmony_ci
160062306a36Sopenharmony_ci	chcr_req->sec_cpl.aadstart_cipherstop_hi =
160162306a36Sopenharmony_ci		FILL_SEC_CPL_CIPHERSTOP_HI(0, 0, 0, 0);
160262306a36Sopenharmony_ci	chcr_req->sec_cpl.cipherstop_lo_authinsert =
160362306a36Sopenharmony_ci		FILL_SEC_CPL_AUTHINSERT(0, 1, 0, 0);
160462306a36Sopenharmony_ci	chcr_req->sec_cpl.seqno_numivs =
160562306a36Sopenharmony_ci		FILL_SEC_CPL_SCMD0_SEQNO(0, 0, 0, param->alg_prm.auth_mode,
160662306a36Sopenharmony_ci					 param->opad_needed, 0);
160762306a36Sopenharmony_ci
160862306a36Sopenharmony_ci	chcr_req->sec_cpl.ivgen_hdrlen =
160962306a36Sopenharmony_ci		FILL_SEC_CPL_IVGEN_HDRLEN(param->last, param->more, 0, 1, 0, 0);
161062306a36Sopenharmony_ci
161162306a36Sopenharmony_ci	memcpy(chcr_req->key_ctx.key, req_ctx->partial_hash,
161262306a36Sopenharmony_ci	       param->alg_prm.result_size);
161362306a36Sopenharmony_ci
161462306a36Sopenharmony_ci	if (param->opad_needed)
161562306a36Sopenharmony_ci		memcpy(chcr_req->key_ctx.key +
161662306a36Sopenharmony_ci		       ((param->alg_prm.result_size <= 32) ? 32 :
161762306a36Sopenharmony_ci			CHCR_HASH_MAX_DIGEST_SIZE),
161862306a36Sopenharmony_ci		       hmacctx->opad, param->alg_prm.result_size);
161962306a36Sopenharmony_ci
162062306a36Sopenharmony_ci	chcr_req->key_ctx.ctx_hdr = FILL_KEY_CTX_HDR(CHCR_KEYCTX_NO_KEY,
162162306a36Sopenharmony_ci					    param->alg_prm.mk_size, 0,
162262306a36Sopenharmony_ci					    param->opad_needed,
162362306a36Sopenharmony_ci					    ((param->kctx_len +
162462306a36Sopenharmony_ci					     sizeof(chcr_req->key_ctx)) >> 4));
162562306a36Sopenharmony_ci	chcr_req->sec_cpl.scmd1 = cpu_to_be64((u64)param->scmd1);
162662306a36Sopenharmony_ci	ulptx = (struct ulptx_sgl *)((u8 *)(chcr_req + 1) + param->kctx_len +
162762306a36Sopenharmony_ci				     DUMMY_BYTES);
162862306a36Sopenharmony_ci	if (param->bfr_len != 0) {
162962306a36Sopenharmony_ci		req_ctx->hctx_wr.dma_addr =
163062306a36Sopenharmony_ci			dma_map_single(&u_ctx->lldi.pdev->dev, req_ctx->reqbfr,
163162306a36Sopenharmony_ci				       param->bfr_len, DMA_TO_DEVICE);
163262306a36Sopenharmony_ci		if (dma_mapping_error(&u_ctx->lldi.pdev->dev,
163362306a36Sopenharmony_ci				       req_ctx->hctx_wr. dma_addr)) {
163462306a36Sopenharmony_ci			error = -ENOMEM;
163562306a36Sopenharmony_ci			goto err;
163662306a36Sopenharmony_ci		}
163762306a36Sopenharmony_ci		req_ctx->hctx_wr.dma_len = param->bfr_len;
163862306a36Sopenharmony_ci	} else {
163962306a36Sopenharmony_ci		req_ctx->hctx_wr.dma_addr = 0;
164062306a36Sopenharmony_ci	}
164162306a36Sopenharmony_ci	chcr_add_hash_src_ent(req, ulptx, param);
164262306a36Sopenharmony_ci	/* Request upto max wr size */
164362306a36Sopenharmony_ci	temp = param->kctx_len + DUMMY_BYTES + (req_ctx->hctx_wr.imm ?
164462306a36Sopenharmony_ci				(param->sg_len + param->bfr_len) : 0);
164562306a36Sopenharmony_ci	atomic_inc(&adap->chcr_stats.digest_rqst);
164662306a36Sopenharmony_ci	create_wreq(h_ctx(tfm), chcr_req, &req->base, req_ctx->hctx_wr.imm,
164762306a36Sopenharmony_ci		    param->hash_size, transhdr_len,
164862306a36Sopenharmony_ci		    temp,  0);
164962306a36Sopenharmony_ci	req_ctx->hctx_wr.skb = skb;
165062306a36Sopenharmony_ci	return skb;
165162306a36Sopenharmony_cierr:
165262306a36Sopenharmony_ci	kfree_skb(skb);
165362306a36Sopenharmony_ci	return  ERR_PTR(error);
165462306a36Sopenharmony_ci}
165562306a36Sopenharmony_ci
165662306a36Sopenharmony_cistatic int chcr_ahash_update(struct ahash_request *req)
165762306a36Sopenharmony_ci{
165862306a36Sopenharmony_ci	struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req);
165962306a36Sopenharmony_ci	struct crypto_ahash *rtfm = crypto_ahash_reqtfm(req);
166062306a36Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(h_ctx(rtfm));
166162306a36Sopenharmony_ci	struct chcr_context *ctx = h_ctx(rtfm);
166262306a36Sopenharmony_ci	struct chcr_dev *dev = h_ctx(rtfm)->dev;
166362306a36Sopenharmony_ci	struct sk_buff *skb;
166462306a36Sopenharmony_ci	u8 remainder = 0, bs;
166562306a36Sopenharmony_ci	unsigned int nbytes = req->nbytes;
166662306a36Sopenharmony_ci	struct hash_wr_param params;
166762306a36Sopenharmony_ci	int error;
166862306a36Sopenharmony_ci	unsigned int cpu;
166962306a36Sopenharmony_ci
167062306a36Sopenharmony_ci	cpu = get_cpu();
167162306a36Sopenharmony_ci	req_ctx->txqidx = cpu % ctx->ntxq;
167262306a36Sopenharmony_ci	req_ctx->rxqidx = cpu % ctx->nrxq;
167362306a36Sopenharmony_ci	put_cpu();
167462306a36Sopenharmony_ci
167562306a36Sopenharmony_ci	bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(rtfm));
167662306a36Sopenharmony_ci
167762306a36Sopenharmony_ci	if (nbytes + req_ctx->reqlen >= bs) {
167862306a36Sopenharmony_ci		remainder = (nbytes + req_ctx->reqlen) % bs;
167962306a36Sopenharmony_ci		nbytes = nbytes + req_ctx->reqlen - remainder;
168062306a36Sopenharmony_ci	} else {
168162306a36Sopenharmony_ci		sg_pcopy_to_buffer(req->src, sg_nents(req->src), req_ctx->reqbfr
168262306a36Sopenharmony_ci				   + req_ctx->reqlen, nbytes, 0);
168362306a36Sopenharmony_ci		req_ctx->reqlen += nbytes;
168462306a36Sopenharmony_ci		return 0;
168562306a36Sopenharmony_ci	}
168662306a36Sopenharmony_ci	error = chcr_inc_wrcount(dev);
168762306a36Sopenharmony_ci	if (error)
168862306a36Sopenharmony_ci		return -ENXIO;
168962306a36Sopenharmony_ci	/* Detach state for CHCR means lldi or padap is freed. Increasing
169062306a36Sopenharmony_ci	 * inflight count for dev guarantees that lldi and padap is valid
169162306a36Sopenharmony_ci	 */
169262306a36Sopenharmony_ci	if (unlikely(cxgb4_is_crypto_q_full(u_ctx->lldi.ports[0],
169362306a36Sopenharmony_ci						req_ctx->txqidx) &&
169462306a36Sopenharmony_ci		(!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)))) {
169562306a36Sopenharmony_ci			error = -ENOSPC;
169662306a36Sopenharmony_ci			goto err;
169762306a36Sopenharmony_ci	}
169862306a36Sopenharmony_ci
169962306a36Sopenharmony_ci	chcr_init_hctx_per_wr(req_ctx);
170062306a36Sopenharmony_ci	error = chcr_hash_dma_map(&u_ctx->lldi.pdev->dev, req);
170162306a36Sopenharmony_ci	if (error) {
170262306a36Sopenharmony_ci		error = -ENOMEM;
170362306a36Sopenharmony_ci		goto err;
170462306a36Sopenharmony_ci	}
170562306a36Sopenharmony_ci	get_alg_config(&params.alg_prm, crypto_ahash_digestsize(rtfm));
170662306a36Sopenharmony_ci	params.kctx_len = roundup(params.alg_prm.result_size, 16);
170762306a36Sopenharmony_ci	params.sg_len = chcr_hash_ent_in_wr(req->src, !!req_ctx->reqlen,
170862306a36Sopenharmony_ci				     HASH_SPACE_LEFT(params.kctx_len), 0);
170962306a36Sopenharmony_ci	if (params.sg_len > req->nbytes)
171062306a36Sopenharmony_ci		params.sg_len = req->nbytes;
171162306a36Sopenharmony_ci	params.sg_len = rounddown(params.sg_len + req_ctx->reqlen, bs) -
171262306a36Sopenharmony_ci			req_ctx->reqlen;
171362306a36Sopenharmony_ci	params.opad_needed = 0;
171462306a36Sopenharmony_ci	params.more = 1;
171562306a36Sopenharmony_ci	params.last = 0;
171662306a36Sopenharmony_ci	params.bfr_len = req_ctx->reqlen;
171762306a36Sopenharmony_ci	params.scmd1 = 0;
171862306a36Sopenharmony_ci	req_ctx->hctx_wr.srcsg = req->src;
171962306a36Sopenharmony_ci
172062306a36Sopenharmony_ci	params.hash_size = params.alg_prm.result_size;
172162306a36Sopenharmony_ci	req_ctx->data_len += params.sg_len + params.bfr_len;
172262306a36Sopenharmony_ci	skb = create_hash_wr(req, &params);
172362306a36Sopenharmony_ci	if (IS_ERR(skb)) {
172462306a36Sopenharmony_ci		error = PTR_ERR(skb);
172562306a36Sopenharmony_ci		goto unmap;
172662306a36Sopenharmony_ci	}
172762306a36Sopenharmony_ci
172862306a36Sopenharmony_ci	req_ctx->hctx_wr.processed += params.sg_len;
172962306a36Sopenharmony_ci	if (remainder) {
173062306a36Sopenharmony_ci		/* Swap buffers */
173162306a36Sopenharmony_ci		swap(req_ctx->reqbfr, req_ctx->skbfr);
173262306a36Sopenharmony_ci		sg_pcopy_to_buffer(req->src, sg_nents(req->src),
173362306a36Sopenharmony_ci				   req_ctx->reqbfr, remainder, req->nbytes -
173462306a36Sopenharmony_ci				   remainder);
173562306a36Sopenharmony_ci	}
173662306a36Sopenharmony_ci	req_ctx->reqlen = remainder;
173762306a36Sopenharmony_ci	skb->dev = u_ctx->lldi.ports[0];
173862306a36Sopenharmony_ci	set_wr_txq(skb, CPL_PRIORITY_DATA, req_ctx->txqidx);
173962306a36Sopenharmony_ci	chcr_send_wr(skb);
174062306a36Sopenharmony_ci	return -EINPROGRESS;
174162306a36Sopenharmony_ciunmap:
174262306a36Sopenharmony_ci	chcr_hash_dma_unmap(&u_ctx->lldi.pdev->dev, req);
174362306a36Sopenharmony_cierr:
174462306a36Sopenharmony_ci	chcr_dec_wrcount(dev);
174562306a36Sopenharmony_ci	return error;
174662306a36Sopenharmony_ci}
174762306a36Sopenharmony_ci
174862306a36Sopenharmony_cistatic void create_last_hash_block(char *bfr_ptr, unsigned int bs, u64 scmd1)
174962306a36Sopenharmony_ci{
175062306a36Sopenharmony_ci	memset(bfr_ptr, 0, bs);
175162306a36Sopenharmony_ci	*bfr_ptr = 0x80;
175262306a36Sopenharmony_ci	if (bs == 64)
175362306a36Sopenharmony_ci		*(__be64 *)(bfr_ptr + 56) = cpu_to_be64(scmd1  << 3);
175462306a36Sopenharmony_ci	else
175562306a36Sopenharmony_ci		*(__be64 *)(bfr_ptr + 120) =  cpu_to_be64(scmd1  << 3);
175662306a36Sopenharmony_ci}
175762306a36Sopenharmony_ci
175862306a36Sopenharmony_cistatic int chcr_ahash_final(struct ahash_request *req)
175962306a36Sopenharmony_ci{
176062306a36Sopenharmony_ci	struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req);
176162306a36Sopenharmony_ci	struct crypto_ahash *rtfm = crypto_ahash_reqtfm(req);
176262306a36Sopenharmony_ci	struct chcr_dev *dev = h_ctx(rtfm)->dev;
176362306a36Sopenharmony_ci	struct hash_wr_param params;
176462306a36Sopenharmony_ci	struct sk_buff *skb;
176562306a36Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(h_ctx(rtfm));
176662306a36Sopenharmony_ci	struct chcr_context *ctx = h_ctx(rtfm);
176762306a36Sopenharmony_ci	u8 bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(rtfm));
176862306a36Sopenharmony_ci	int error;
176962306a36Sopenharmony_ci	unsigned int cpu;
177062306a36Sopenharmony_ci
177162306a36Sopenharmony_ci	cpu = get_cpu();
177262306a36Sopenharmony_ci	req_ctx->txqidx = cpu % ctx->ntxq;
177362306a36Sopenharmony_ci	req_ctx->rxqidx = cpu % ctx->nrxq;
177462306a36Sopenharmony_ci	put_cpu();
177562306a36Sopenharmony_ci
177662306a36Sopenharmony_ci	error = chcr_inc_wrcount(dev);
177762306a36Sopenharmony_ci	if (error)
177862306a36Sopenharmony_ci		return -ENXIO;
177962306a36Sopenharmony_ci
178062306a36Sopenharmony_ci	chcr_init_hctx_per_wr(req_ctx);
178162306a36Sopenharmony_ci	if (is_hmac(crypto_ahash_tfm(rtfm)))
178262306a36Sopenharmony_ci		params.opad_needed = 1;
178362306a36Sopenharmony_ci	else
178462306a36Sopenharmony_ci		params.opad_needed = 0;
178562306a36Sopenharmony_ci	params.sg_len = 0;
178662306a36Sopenharmony_ci	req_ctx->hctx_wr.isfinal = 1;
178762306a36Sopenharmony_ci	get_alg_config(&params.alg_prm, crypto_ahash_digestsize(rtfm));
178862306a36Sopenharmony_ci	params.kctx_len = roundup(params.alg_prm.result_size, 16);
178962306a36Sopenharmony_ci	if (is_hmac(crypto_ahash_tfm(rtfm))) {
179062306a36Sopenharmony_ci		params.opad_needed = 1;
179162306a36Sopenharmony_ci		params.kctx_len *= 2;
179262306a36Sopenharmony_ci	} else {
179362306a36Sopenharmony_ci		params.opad_needed = 0;
179462306a36Sopenharmony_ci	}
179562306a36Sopenharmony_ci
179662306a36Sopenharmony_ci	req_ctx->hctx_wr.result = 1;
179762306a36Sopenharmony_ci	params.bfr_len = req_ctx->reqlen;
179862306a36Sopenharmony_ci	req_ctx->data_len += params.bfr_len + params.sg_len;
179962306a36Sopenharmony_ci	req_ctx->hctx_wr.srcsg = req->src;
180062306a36Sopenharmony_ci	if (req_ctx->reqlen == 0) {
180162306a36Sopenharmony_ci		create_last_hash_block(req_ctx->reqbfr, bs, req_ctx->data_len);
180262306a36Sopenharmony_ci		params.last = 0;
180362306a36Sopenharmony_ci		params.more = 1;
180462306a36Sopenharmony_ci		params.scmd1 = 0;
180562306a36Sopenharmony_ci		params.bfr_len = bs;
180662306a36Sopenharmony_ci
180762306a36Sopenharmony_ci	} else {
180862306a36Sopenharmony_ci		params.scmd1 = req_ctx->data_len;
180962306a36Sopenharmony_ci		params.last = 1;
181062306a36Sopenharmony_ci		params.more = 0;
181162306a36Sopenharmony_ci	}
181262306a36Sopenharmony_ci	params.hash_size = crypto_ahash_digestsize(rtfm);
181362306a36Sopenharmony_ci	skb = create_hash_wr(req, &params);
181462306a36Sopenharmony_ci	if (IS_ERR(skb)) {
181562306a36Sopenharmony_ci		error = PTR_ERR(skb);
181662306a36Sopenharmony_ci		goto err;
181762306a36Sopenharmony_ci	}
181862306a36Sopenharmony_ci	req_ctx->reqlen = 0;
181962306a36Sopenharmony_ci	skb->dev = u_ctx->lldi.ports[0];
182062306a36Sopenharmony_ci	set_wr_txq(skb, CPL_PRIORITY_DATA, req_ctx->txqidx);
182162306a36Sopenharmony_ci	chcr_send_wr(skb);
182262306a36Sopenharmony_ci	return -EINPROGRESS;
182362306a36Sopenharmony_cierr:
182462306a36Sopenharmony_ci	chcr_dec_wrcount(dev);
182562306a36Sopenharmony_ci	return error;
182662306a36Sopenharmony_ci}
182762306a36Sopenharmony_ci
182862306a36Sopenharmony_cistatic int chcr_ahash_finup(struct ahash_request *req)
182962306a36Sopenharmony_ci{
183062306a36Sopenharmony_ci	struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req);
183162306a36Sopenharmony_ci	struct crypto_ahash *rtfm = crypto_ahash_reqtfm(req);
183262306a36Sopenharmony_ci	struct chcr_dev *dev = h_ctx(rtfm)->dev;
183362306a36Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(h_ctx(rtfm));
183462306a36Sopenharmony_ci	struct chcr_context *ctx = h_ctx(rtfm);
183562306a36Sopenharmony_ci	struct sk_buff *skb;
183662306a36Sopenharmony_ci	struct hash_wr_param params;
183762306a36Sopenharmony_ci	u8  bs;
183862306a36Sopenharmony_ci	int error;
183962306a36Sopenharmony_ci	unsigned int cpu;
184062306a36Sopenharmony_ci
184162306a36Sopenharmony_ci	cpu = get_cpu();
184262306a36Sopenharmony_ci	req_ctx->txqidx = cpu % ctx->ntxq;
184362306a36Sopenharmony_ci	req_ctx->rxqidx = cpu % ctx->nrxq;
184462306a36Sopenharmony_ci	put_cpu();
184562306a36Sopenharmony_ci
184662306a36Sopenharmony_ci	bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(rtfm));
184762306a36Sopenharmony_ci	error = chcr_inc_wrcount(dev);
184862306a36Sopenharmony_ci	if (error)
184962306a36Sopenharmony_ci		return -ENXIO;
185062306a36Sopenharmony_ci
185162306a36Sopenharmony_ci	if (unlikely(cxgb4_is_crypto_q_full(u_ctx->lldi.ports[0],
185262306a36Sopenharmony_ci						req_ctx->txqidx) &&
185362306a36Sopenharmony_ci		(!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)))) {
185462306a36Sopenharmony_ci			error = -ENOSPC;
185562306a36Sopenharmony_ci			goto err;
185662306a36Sopenharmony_ci	}
185762306a36Sopenharmony_ci	chcr_init_hctx_per_wr(req_ctx);
185862306a36Sopenharmony_ci	error = chcr_hash_dma_map(&u_ctx->lldi.pdev->dev, req);
185962306a36Sopenharmony_ci	if (error) {
186062306a36Sopenharmony_ci		error = -ENOMEM;
186162306a36Sopenharmony_ci		goto err;
186262306a36Sopenharmony_ci	}
186362306a36Sopenharmony_ci
186462306a36Sopenharmony_ci	get_alg_config(&params.alg_prm, crypto_ahash_digestsize(rtfm));
186562306a36Sopenharmony_ci	params.kctx_len = roundup(params.alg_prm.result_size, 16);
186662306a36Sopenharmony_ci	if (is_hmac(crypto_ahash_tfm(rtfm))) {
186762306a36Sopenharmony_ci		params.kctx_len *= 2;
186862306a36Sopenharmony_ci		params.opad_needed = 1;
186962306a36Sopenharmony_ci	} else {
187062306a36Sopenharmony_ci		params.opad_needed = 0;
187162306a36Sopenharmony_ci	}
187262306a36Sopenharmony_ci
187362306a36Sopenharmony_ci	params.sg_len = chcr_hash_ent_in_wr(req->src, !!req_ctx->reqlen,
187462306a36Sopenharmony_ci				    HASH_SPACE_LEFT(params.kctx_len), 0);
187562306a36Sopenharmony_ci	if (params.sg_len < req->nbytes) {
187662306a36Sopenharmony_ci		if (is_hmac(crypto_ahash_tfm(rtfm))) {
187762306a36Sopenharmony_ci			params.kctx_len /= 2;
187862306a36Sopenharmony_ci			params.opad_needed = 0;
187962306a36Sopenharmony_ci		}
188062306a36Sopenharmony_ci		params.last = 0;
188162306a36Sopenharmony_ci		params.more = 1;
188262306a36Sopenharmony_ci		params.sg_len = rounddown(params.sg_len + req_ctx->reqlen, bs)
188362306a36Sopenharmony_ci					- req_ctx->reqlen;
188462306a36Sopenharmony_ci		params.hash_size = params.alg_prm.result_size;
188562306a36Sopenharmony_ci		params.scmd1 = 0;
188662306a36Sopenharmony_ci	} else {
188762306a36Sopenharmony_ci		params.last = 1;
188862306a36Sopenharmony_ci		params.more = 0;
188962306a36Sopenharmony_ci		params.sg_len = req->nbytes;
189062306a36Sopenharmony_ci		params.hash_size = crypto_ahash_digestsize(rtfm);
189162306a36Sopenharmony_ci		params.scmd1 = req_ctx->data_len + req_ctx->reqlen +
189262306a36Sopenharmony_ci				params.sg_len;
189362306a36Sopenharmony_ci	}
189462306a36Sopenharmony_ci	params.bfr_len = req_ctx->reqlen;
189562306a36Sopenharmony_ci	req_ctx->data_len += params.bfr_len + params.sg_len;
189662306a36Sopenharmony_ci	req_ctx->hctx_wr.result = 1;
189762306a36Sopenharmony_ci	req_ctx->hctx_wr.srcsg = req->src;
189862306a36Sopenharmony_ci	if ((req_ctx->reqlen + req->nbytes) == 0) {
189962306a36Sopenharmony_ci		create_last_hash_block(req_ctx->reqbfr, bs, req_ctx->data_len);
190062306a36Sopenharmony_ci		params.last = 0;
190162306a36Sopenharmony_ci		params.more = 1;
190262306a36Sopenharmony_ci		params.scmd1 = 0;
190362306a36Sopenharmony_ci		params.bfr_len = bs;
190462306a36Sopenharmony_ci	}
190562306a36Sopenharmony_ci	skb = create_hash_wr(req, &params);
190662306a36Sopenharmony_ci	if (IS_ERR(skb)) {
190762306a36Sopenharmony_ci		error = PTR_ERR(skb);
190862306a36Sopenharmony_ci		goto unmap;
190962306a36Sopenharmony_ci	}
191062306a36Sopenharmony_ci	req_ctx->reqlen = 0;
191162306a36Sopenharmony_ci	req_ctx->hctx_wr.processed += params.sg_len;
191262306a36Sopenharmony_ci	skb->dev = u_ctx->lldi.ports[0];
191362306a36Sopenharmony_ci	set_wr_txq(skb, CPL_PRIORITY_DATA, req_ctx->txqidx);
191462306a36Sopenharmony_ci	chcr_send_wr(skb);
191562306a36Sopenharmony_ci	return -EINPROGRESS;
191662306a36Sopenharmony_ciunmap:
191762306a36Sopenharmony_ci	chcr_hash_dma_unmap(&u_ctx->lldi.pdev->dev, req);
191862306a36Sopenharmony_cierr:
191962306a36Sopenharmony_ci	chcr_dec_wrcount(dev);
192062306a36Sopenharmony_ci	return error;
192162306a36Sopenharmony_ci}
192262306a36Sopenharmony_ci
192362306a36Sopenharmony_cistatic int chcr_ahash_digest(struct ahash_request *req)
192462306a36Sopenharmony_ci{
192562306a36Sopenharmony_ci	struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req);
192662306a36Sopenharmony_ci	struct crypto_ahash *rtfm = crypto_ahash_reqtfm(req);
192762306a36Sopenharmony_ci	struct chcr_dev *dev = h_ctx(rtfm)->dev;
192862306a36Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(h_ctx(rtfm));
192962306a36Sopenharmony_ci	struct chcr_context *ctx = h_ctx(rtfm);
193062306a36Sopenharmony_ci	struct sk_buff *skb;
193162306a36Sopenharmony_ci	struct hash_wr_param params;
193262306a36Sopenharmony_ci	u8  bs;
193362306a36Sopenharmony_ci	int error;
193462306a36Sopenharmony_ci	unsigned int cpu;
193562306a36Sopenharmony_ci
193662306a36Sopenharmony_ci	cpu = get_cpu();
193762306a36Sopenharmony_ci	req_ctx->txqidx = cpu % ctx->ntxq;
193862306a36Sopenharmony_ci	req_ctx->rxqidx = cpu % ctx->nrxq;
193962306a36Sopenharmony_ci	put_cpu();
194062306a36Sopenharmony_ci
194162306a36Sopenharmony_ci	rtfm->init(req);
194262306a36Sopenharmony_ci	bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(rtfm));
194362306a36Sopenharmony_ci	error = chcr_inc_wrcount(dev);
194462306a36Sopenharmony_ci	if (error)
194562306a36Sopenharmony_ci		return -ENXIO;
194662306a36Sopenharmony_ci
194762306a36Sopenharmony_ci	if (unlikely(cxgb4_is_crypto_q_full(u_ctx->lldi.ports[0],
194862306a36Sopenharmony_ci						req_ctx->txqidx) &&
194962306a36Sopenharmony_ci		(!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)))) {
195062306a36Sopenharmony_ci			error = -ENOSPC;
195162306a36Sopenharmony_ci			goto err;
195262306a36Sopenharmony_ci	}
195362306a36Sopenharmony_ci
195462306a36Sopenharmony_ci	chcr_init_hctx_per_wr(req_ctx);
195562306a36Sopenharmony_ci	error = chcr_hash_dma_map(&u_ctx->lldi.pdev->dev, req);
195662306a36Sopenharmony_ci	if (error) {
195762306a36Sopenharmony_ci		error = -ENOMEM;
195862306a36Sopenharmony_ci		goto err;
195962306a36Sopenharmony_ci	}
196062306a36Sopenharmony_ci
196162306a36Sopenharmony_ci	get_alg_config(&params.alg_prm, crypto_ahash_digestsize(rtfm));
196262306a36Sopenharmony_ci	params.kctx_len = roundup(params.alg_prm.result_size, 16);
196362306a36Sopenharmony_ci	if (is_hmac(crypto_ahash_tfm(rtfm))) {
196462306a36Sopenharmony_ci		params.kctx_len *= 2;
196562306a36Sopenharmony_ci		params.opad_needed = 1;
196662306a36Sopenharmony_ci	} else {
196762306a36Sopenharmony_ci		params.opad_needed = 0;
196862306a36Sopenharmony_ci	}
196962306a36Sopenharmony_ci	params.sg_len = chcr_hash_ent_in_wr(req->src, !!req_ctx->reqlen,
197062306a36Sopenharmony_ci				HASH_SPACE_LEFT(params.kctx_len), 0);
197162306a36Sopenharmony_ci	if (params.sg_len < req->nbytes) {
197262306a36Sopenharmony_ci		if (is_hmac(crypto_ahash_tfm(rtfm))) {
197362306a36Sopenharmony_ci			params.kctx_len /= 2;
197462306a36Sopenharmony_ci			params.opad_needed = 0;
197562306a36Sopenharmony_ci		}
197662306a36Sopenharmony_ci		params.last = 0;
197762306a36Sopenharmony_ci		params.more = 1;
197862306a36Sopenharmony_ci		params.scmd1 = 0;
197962306a36Sopenharmony_ci		params.sg_len = rounddown(params.sg_len, bs);
198062306a36Sopenharmony_ci		params.hash_size = params.alg_prm.result_size;
198162306a36Sopenharmony_ci	} else {
198262306a36Sopenharmony_ci		params.sg_len = req->nbytes;
198362306a36Sopenharmony_ci		params.hash_size = crypto_ahash_digestsize(rtfm);
198462306a36Sopenharmony_ci		params.last = 1;
198562306a36Sopenharmony_ci		params.more = 0;
198662306a36Sopenharmony_ci		params.scmd1 = req->nbytes + req_ctx->data_len;
198762306a36Sopenharmony_ci
198862306a36Sopenharmony_ci	}
198962306a36Sopenharmony_ci	params.bfr_len = 0;
199062306a36Sopenharmony_ci	req_ctx->hctx_wr.result = 1;
199162306a36Sopenharmony_ci	req_ctx->hctx_wr.srcsg = req->src;
199262306a36Sopenharmony_ci	req_ctx->data_len += params.bfr_len + params.sg_len;
199362306a36Sopenharmony_ci
199462306a36Sopenharmony_ci	if (req->nbytes == 0) {
199562306a36Sopenharmony_ci		create_last_hash_block(req_ctx->reqbfr, bs, req_ctx->data_len);
199662306a36Sopenharmony_ci		params.more = 1;
199762306a36Sopenharmony_ci		params.bfr_len = bs;
199862306a36Sopenharmony_ci	}
199962306a36Sopenharmony_ci
200062306a36Sopenharmony_ci	skb = create_hash_wr(req, &params);
200162306a36Sopenharmony_ci	if (IS_ERR(skb)) {
200262306a36Sopenharmony_ci		error = PTR_ERR(skb);
200362306a36Sopenharmony_ci		goto unmap;
200462306a36Sopenharmony_ci	}
200562306a36Sopenharmony_ci	req_ctx->hctx_wr.processed += params.sg_len;
200662306a36Sopenharmony_ci	skb->dev = u_ctx->lldi.ports[0];
200762306a36Sopenharmony_ci	set_wr_txq(skb, CPL_PRIORITY_DATA, req_ctx->txqidx);
200862306a36Sopenharmony_ci	chcr_send_wr(skb);
200962306a36Sopenharmony_ci	return -EINPROGRESS;
201062306a36Sopenharmony_ciunmap:
201162306a36Sopenharmony_ci	chcr_hash_dma_unmap(&u_ctx->lldi.pdev->dev, req);
201262306a36Sopenharmony_cierr:
201362306a36Sopenharmony_ci	chcr_dec_wrcount(dev);
201462306a36Sopenharmony_ci	return error;
201562306a36Sopenharmony_ci}
201662306a36Sopenharmony_ci
201762306a36Sopenharmony_cistatic int chcr_ahash_continue(struct ahash_request *req)
201862306a36Sopenharmony_ci{
201962306a36Sopenharmony_ci	struct chcr_ahash_req_ctx *reqctx = ahash_request_ctx(req);
202062306a36Sopenharmony_ci	struct chcr_hctx_per_wr *hctx_wr = &reqctx->hctx_wr;
202162306a36Sopenharmony_ci	struct crypto_ahash *rtfm = crypto_ahash_reqtfm(req);
202262306a36Sopenharmony_ci	struct chcr_context *ctx = h_ctx(rtfm);
202362306a36Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(ctx);
202462306a36Sopenharmony_ci	struct sk_buff *skb;
202562306a36Sopenharmony_ci	struct hash_wr_param params;
202662306a36Sopenharmony_ci	u8  bs;
202762306a36Sopenharmony_ci	int error;
202862306a36Sopenharmony_ci	unsigned int cpu;
202962306a36Sopenharmony_ci
203062306a36Sopenharmony_ci	cpu = get_cpu();
203162306a36Sopenharmony_ci	reqctx->txqidx = cpu % ctx->ntxq;
203262306a36Sopenharmony_ci	reqctx->rxqidx = cpu % ctx->nrxq;
203362306a36Sopenharmony_ci	put_cpu();
203462306a36Sopenharmony_ci
203562306a36Sopenharmony_ci	bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(rtfm));
203662306a36Sopenharmony_ci	get_alg_config(&params.alg_prm, crypto_ahash_digestsize(rtfm));
203762306a36Sopenharmony_ci	params.kctx_len = roundup(params.alg_prm.result_size, 16);
203862306a36Sopenharmony_ci	if (is_hmac(crypto_ahash_tfm(rtfm))) {
203962306a36Sopenharmony_ci		params.kctx_len *= 2;
204062306a36Sopenharmony_ci		params.opad_needed = 1;
204162306a36Sopenharmony_ci	} else {
204262306a36Sopenharmony_ci		params.opad_needed = 0;
204362306a36Sopenharmony_ci	}
204462306a36Sopenharmony_ci	params.sg_len = chcr_hash_ent_in_wr(hctx_wr->srcsg, 0,
204562306a36Sopenharmony_ci					    HASH_SPACE_LEFT(params.kctx_len),
204662306a36Sopenharmony_ci					    hctx_wr->src_ofst);
204762306a36Sopenharmony_ci	if ((params.sg_len + hctx_wr->processed) > req->nbytes)
204862306a36Sopenharmony_ci		params.sg_len = req->nbytes - hctx_wr->processed;
204962306a36Sopenharmony_ci	if (!hctx_wr->result ||
205062306a36Sopenharmony_ci	    ((params.sg_len + hctx_wr->processed) < req->nbytes)) {
205162306a36Sopenharmony_ci		if (is_hmac(crypto_ahash_tfm(rtfm))) {
205262306a36Sopenharmony_ci			params.kctx_len /= 2;
205362306a36Sopenharmony_ci			params.opad_needed = 0;
205462306a36Sopenharmony_ci		}
205562306a36Sopenharmony_ci		params.last = 0;
205662306a36Sopenharmony_ci		params.more = 1;
205762306a36Sopenharmony_ci		params.sg_len = rounddown(params.sg_len, bs);
205862306a36Sopenharmony_ci		params.hash_size = params.alg_prm.result_size;
205962306a36Sopenharmony_ci		params.scmd1 = 0;
206062306a36Sopenharmony_ci	} else {
206162306a36Sopenharmony_ci		params.last = 1;
206262306a36Sopenharmony_ci		params.more = 0;
206362306a36Sopenharmony_ci		params.hash_size = crypto_ahash_digestsize(rtfm);
206462306a36Sopenharmony_ci		params.scmd1 = reqctx->data_len + params.sg_len;
206562306a36Sopenharmony_ci	}
206662306a36Sopenharmony_ci	params.bfr_len = 0;
206762306a36Sopenharmony_ci	reqctx->data_len += params.sg_len;
206862306a36Sopenharmony_ci	skb = create_hash_wr(req, &params);
206962306a36Sopenharmony_ci	if (IS_ERR(skb)) {
207062306a36Sopenharmony_ci		error = PTR_ERR(skb);
207162306a36Sopenharmony_ci		goto err;
207262306a36Sopenharmony_ci	}
207362306a36Sopenharmony_ci	hctx_wr->processed += params.sg_len;
207462306a36Sopenharmony_ci	skb->dev = u_ctx->lldi.ports[0];
207562306a36Sopenharmony_ci	set_wr_txq(skb, CPL_PRIORITY_DATA, reqctx->txqidx);
207662306a36Sopenharmony_ci	chcr_send_wr(skb);
207762306a36Sopenharmony_ci	return 0;
207862306a36Sopenharmony_cierr:
207962306a36Sopenharmony_ci	return error;
208062306a36Sopenharmony_ci}
208162306a36Sopenharmony_ci
208262306a36Sopenharmony_cistatic inline void chcr_handle_ahash_resp(struct ahash_request *req,
208362306a36Sopenharmony_ci					  unsigned char *input,
208462306a36Sopenharmony_ci					  int err)
208562306a36Sopenharmony_ci{
208662306a36Sopenharmony_ci	struct chcr_ahash_req_ctx *reqctx = ahash_request_ctx(req);
208762306a36Sopenharmony_ci	struct chcr_hctx_per_wr *hctx_wr = &reqctx->hctx_wr;
208862306a36Sopenharmony_ci	int digestsize, updated_digestsize;
208962306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
209062306a36Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(h_ctx(tfm));
209162306a36Sopenharmony_ci	struct chcr_dev *dev = h_ctx(tfm)->dev;
209262306a36Sopenharmony_ci
209362306a36Sopenharmony_ci	if (input == NULL)
209462306a36Sopenharmony_ci		goto out;
209562306a36Sopenharmony_ci	digestsize = crypto_ahash_digestsize(crypto_ahash_reqtfm(req));
209662306a36Sopenharmony_ci	updated_digestsize = digestsize;
209762306a36Sopenharmony_ci	if (digestsize == SHA224_DIGEST_SIZE)
209862306a36Sopenharmony_ci		updated_digestsize = SHA256_DIGEST_SIZE;
209962306a36Sopenharmony_ci	else if (digestsize == SHA384_DIGEST_SIZE)
210062306a36Sopenharmony_ci		updated_digestsize = SHA512_DIGEST_SIZE;
210162306a36Sopenharmony_ci
210262306a36Sopenharmony_ci	if (hctx_wr->dma_addr) {
210362306a36Sopenharmony_ci		dma_unmap_single(&u_ctx->lldi.pdev->dev, hctx_wr->dma_addr,
210462306a36Sopenharmony_ci				 hctx_wr->dma_len, DMA_TO_DEVICE);
210562306a36Sopenharmony_ci		hctx_wr->dma_addr = 0;
210662306a36Sopenharmony_ci	}
210762306a36Sopenharmony_ci	if (hctx_wr->isfinal || ((hctx_wr->processed + reqctx->reqlen) ==
210862306a36Sopenharmony_ci				 req->nbytes)) {
210962306a36Sopenharmony_ci		if (hctx_wr->result == 1) {
211062306a36Sopenharmony_ci			hctx_wr->result = 0;
211162306a36Sopenharmony_ci			memcpy(req->result, input + sizeof(struct cpl_fw6_pld),
211262306a36Sopenharmony_ci			       digestsize);
211362306a36Sopenharmony_ci		} else {
211462306a36Sopenharmony_ci			memcpy(reqctx->partial_hash,
211562306a36Sopenharmony_ci			       input + sizeof(struct cpl_fw6_pld),
211662306a36Sopenharmony_ci			       updated_digestsize);
211762306a36Sopenharmony_ci
211862306a36Sopenharmony_ci		}
211962306a36Sopenharmony_ci		goto unmap;
212062306a36Sopenharmony_ci	}
212162306a36Sopenharmony_ci	memcpy(reqctx->partial_hash, input + sizeof(struct cpl_fw6_pld),
212262306a36Sopenharmony_ci	       updated_digestsize);
212362306a36Sopenharmony_ci
212462306a36Sopenharmony_ci	err = chcr_ahash_continue(req);
212562306a36Sopenharmony_ci	if (err)
212662306a36Sopenharmony_ci		goto unmap;
212762306a36Sopenharmony_ci	return;
212862306a36Sopenharmony_ciunmap:
212962306a36Sopenharmony_ci	if (hctx_wr->is_sg_map)
213062306a36Sopenharmony_ci		chcr_hash_dma_unmap(&u_ctx->lldi.pdev->dev, req);
213162306a36Sopenharmony_ci
213262306a36Sopenharmony_ci
213362306a36Sopenharmony_ciout:
213462306a36Sopenharmony_ci	chcr_dec_wrcount(dev);
213562306a36Sopenharmony_ci	ahash_request_complete(req, err);
213662306a36Sopenharmony_ci}
213762306a36Sopenharmony_ci
213862306a36Sopenharmony_ci/*
213962306a36Sopenharmony_ci *	chcr_handle_resp - Unmap the DMA buffers associated with the request
214062306a36Sopenharmony_ci *	@req: crypto request
214162306a36Sopenharmony_ci */
214262306a36Sopenharmony_ciint chcr_handle_resp(struct crypto_async_request *req, unsigned char *input,
214362306a36Sopenharmony_ci			 int err)
214462306a36Sopenharmony_ci{
214562306a36Sopenharmony_ci	struct crypto_tfm *tfm = req->tfm;
214662306a36Sopenharmony_ci	struct chcr_context *ctx = crypto_tfm_ctx(tfm);
214762306a36Sopenharmony_ci	struct adapter *adap = padap(ctx->dev);
214862306a36Sopenharmony_ci
214962306a36Sopenharmony_ci	switch (tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
215062306a36Sopenharmony_ci	case CRYPTO_ALG_TYPE_AEAD:
215162306a36Sopenharmony_ci		err = chcr_handle_aead_resp(aead_request_cast(req), input, err);
215262306a36Sopenharmony_ci		break;
215362306a36Sopenharmony_ci
215462306a36Sopenharmony_ci	case CRYPTO_ALG_TYPE_SKCIPHER:
215562306a36Sopenharmony_ci		 chcr_handle_cipher_resp(skcipher_request_cast(req),
215662306a36Sopenharmony_ci					       input, err);
215762306a36Sopenharmony_ci		break;
215862306a36Sopenharmony_ci	case CRYPTO_ALG_TYPE_AHASH:
215962306a36Sopenharmony_ci		chcr_handle_ahash_resp(ahash_request_cast(req), input, err);
216062306a36Sopenharmony_ci		}
216162306a36Sopenharmony_ci	atomic_inc(&adap->chcr_stats.complete);
216262306a36Sopenharmony_ci	return err;
216362306a36Sopenharmony_ci}
216462306a36Sopenharmony_cistatic int chcr_ahash_export(struct ahash_request *areq, void *out)
216562306a36Sopenharmony_ci{
216662306a36Sopenharmony_ci	struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
216762306a36Sopenharmony_ci	struct chcr_ahash_req_ctx *state = out;
216862306a36Sopenharmony_ci
216962306a36Sopenharmony_ci	state->reqlen = req_ctx->reqlen;
217062306a36Sopenharmony_ci	state->data_len = req_ctx->data_len;
217162306a36Sopenharmony_ci	memcpy(state->bfr1, req_ctx->reqbfr, req_ctx->reqlen);
217262306a36Sopenharmony_ci	memcpy(state->partial_hash, req_ctx->partial_hash,
217362306a36Sopenharmony_ci	       CHCR_HASH_MAX_DIGEST_SIZE);
217462306a36Sopenharmony_ci	chcr_init_hctx_per_wr(state);
217562306a36Sopenharmony_ci	return 0;
217662306a36Sopenharmony_ci}
217762306a36Sopenharmony_ci
217862306a36Sopenharmony_cistatic int chcr_ahash_import(struct ahash_request *areq, const void *in)
217962306a36Sopenharmony_ci{
218062306a36Sopenharmony_ci	struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
218162306a36Sopenharmony_ci	struct chcr_ahash_req_ctx *state = (struct chcr_ahash_req_ctx *)in;
218262306a36Sopenharmony_ci
218362306a36Sopenharmony_ci	req_ctx->reqlen = state->reqlen;
218462306a36Sopenharmony_ci	req_ctx->data_len = state->data_len;
218562306a36Sopenharmony_ci	req_ctx->reqbfr = req_ctx->bfr1;
218662306a36Sopenharmony_ci	req_ctx->skbfr = req_ctx->bfr2;
218762306a36Sopenharmony_ci	memcpy(req_ctx->bfr1, state->bfr1, CHCR_HASH_MAX_BLOCK_SIZE_128);
218862306a36Sopenharmony_ci	memcpy(req_ctx->partial_hash, state->partial_hash,
218962306a36Sopenharmony_ci	       CHCR_HASH_MAX_DIGEST_SIZE);
219062306a36Sopenharmony_ci	chcr_init_hctx_per_wr(req_ctx);
219162306a36Sopenharmony_ci	return 0;
219262306a36Sopenharmony_ci}
219362306a36Sopenharmony_ci
219462306a36Sopenharmony_cistatic int chcr_ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
219562306a36Sopenharmony_ci			     unsigned int keylen)
219662306a36Sopenharmony_ci{
219762306a36Sopenharmony_ci	struct hmac_ctx *hmacctx = HMAC_CTX(h_ctx(tfm));
219862306a36Sopenharmony_ci	unsigned int digestsize = crypto_ahash_digestsize(tfm);
219962306a36Sopenharmony_ci	unsigned int bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
220062306a36Sopenharmony_ci	unsigned int i, err = 0, updated_digestsize;
220162306a36Sopenharmony_ci
220262306a36Sopenharmony_ci	SHASH_DESC_ON_STACK(shash, hmacctx->base_hash);
220362306a36Sopenharmony_ci
220462306a36Sopenharmony_ci	/* use the key to calculate the ipad and opad. ipad will sent with the
220562306a36Sopenharmony_ci	 * first request's data. opad will be sent with the final hash result
220662306a36Sopenharmony_ci	 * ipad in hmacctx->ipad and opad in hmacctx->opad location
220762306a36Sopenharmony_ci	 */
220862306a36Sopenharmony_ci	shash->tfm = hmacctx->base_hash;
220962306a36Sopenharmony_ci	if (keylen > bs) {
221062306a36Sopenharmony_ci		err = crypto_shash_digest(shash, key, keylen,
221162306a36Sopenharmony_ci					  hmacctx->ipad);
221262306a36Sopenharmony_ci		if (err)
221362306a36Sopenharmony_ci			goto out;
221462306a36Sopenharmony_ci		keylen = digestsize;
221562306a36Sopenharmony_ci	} else {
221662306a36Sopenharmony_ci		memcpy(hmacctx->ipad, key, keylen);
221762306a36Sopenharmony_ci	}
221862306a36Sopenharmony_ci	memset(hmacctx->ipad + keylen, 0, bs - keylen);
221962306a36Sopenharmony_ci	unsafe_memcpy(hmacctx->opad, hmacctx->ipad, bs,
222062306a36Sopenharmony_ci		      "fortified memcpy causes -Wrestrict warning");
222162306a36Sopenharmony_ci
222262306a36Sopenharmony_ci	for (i = 0; i < bs / sizeof(int); i++) {
222362306a36Sopenharmony_ci		*((unsigned int *)(&hmacctx->ipad) + i) ^= IPAD_DATA;
222462306a36Sopenharmony_ci		*((unsigned int *)(&hmacctx->opad) + i) ^= OPAD_DATA;
222562306a36Sopenharmony_ci	}
222662306a36Sopenharmony_ci
222762306a36Sopenharmony_ci	updated_digestsize = digestsize;
222862306a36Sopenharmony_ci	if (digestsize == SHA224_DIGEST_SIZE)
222962306a36Sopenharmony_ci		updated_digestsize = SHA256_DIGEST_SIZE;
223062306a36Sopenharmony_ci	else if (digestsize == SHA384_DIGEST_SIZE)
223162306a36Sopenharmony_ci		updated_digestsize = SHA512_DIGEST_SIZE;
223262306a36Sopenharmony_ci	err = chcr_compute_partial_hash(shash, hmacctx->ipad,
223362306a36Sopenharmony_ci					hmacctx->ipad, digestsize);
223462306a36Sopenharmony_ci	if (err)
223562306a36Sopenharmony_ci		goto out;
223662306a36Sopenharmony_ci	chcr_change_order(hmacctx->ipad, updated_digestsize);
223762306a36Sopenharmony_ci
223862306a36Sopenharmony_ci	err = chcr_compute_partial_hash(shash, hmacctx->opad,
223962306a36Sopenharmony_ci					hmacctx->opad, digestsize);
224062306a36Sopenharmony_ci	if (err)
224162306a36Sopenharmony_ci		goto out;
224262306a36Sopenharmony_ci	chcr_change_order(hmacctx->opad, updated_digestsize);
224362306a36Sopenharmony_ciout:
224462306a36Sopenharmony_ci	return err;
224562306a36Sopenharmony_ci}
224662306a36Sopenharmony_ci
224762306a36Sopenharmony_cistatic int chcr_aes_xts_setkey(struct crypto_skcipher *cipher, const u8 *key,
224862306a36Sopenharmony_ci			       unsigned int key_len)
224962306a36Sopenharmony_ci{
225062306a36Sopenharmony_ci	struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(cipher));
225162306a36Sopenharmony_ci	unsigned short context_size = 0;
225262306a36Sopenharmony_ci	int err;
225362306a36Sopenharmony_ci
225462306a36Sopenharmony_ci	err = chcr_cipher_fallback_setkey(cipher, key, key_len);
225562306a36Sopenharmony_ci	if (err)
225662306a36Sopenharmony_ci		goto badkey_err;
225762306a36Sopenharmony_ci
225862306a36Sopenharmony_ci	memcpy(ablkctx->key, key, key_len);
225962306a36Sopenharmony_ci	ablkctx->enckey_len = key_len;
226062306a36Sopenharmony_ci	get_aes_decrypt_key(ablkctx->rrkey, ablkctx->key, key_len << 2);
226162306a36Sopenharmony_ci	context_size = (KEY_CONTEXT_HDR_SALT_AND_PAD + key_len) >> 4;
226262306a36Sopenharmony_ci	/* Both keys for xts must be aligned to 16 byte boundary
226362306a36Sopenharmony_ci	 * by padding with zeros. So for 24 byte keys padding 8 zeroes.
226462306a36Sopenharmony_ci	 */
226562306a36Sopenharmony_ci	if (key_len == 48) {
226662306a36Sopenharmony_ci		context_size = (KEY_CONTEXT_HDR_SALT_AND_PAD + key_len
226762306a36Sopenharmony_ci				+ 16) >> 4;
226862306a36Sopenharmony_ci		memmove(ablkctx->key + 32, ablkctx->key + 24, 24);
226962306a36Sopenharmony_ci		memset(ablkctx->key + 24, 0, 8);
227062306a36Sopenharmony_ci		memset(ablkctx->key + 56, 0, 8);
227162306a36Sopenharmony_ci		ablkctx->enckey_len = 64;
227262306a36Sopenharmony_ci		ablkctx->key_ctx_hdr =
227362306a36Sopenharmony_ci			FILL_KEY_CTX_HDR(CHCR_KEYCTX_CIPHER_KEY_SIZE_192,
227462306a36Sopenharmony_ci					 CHCR_KEYCTX_NO_KEY, 1,
227562306a36Sopenharmony_ci					 0, context_size);
227662306a36Sopenharmony_ci	} else {
227762306a36Sopenharmony_ci		ablkctx->key_ctx_hdr =
227862306a36Sopenharmony_ci		FILL_KEY_CTX_HDR((key_len == AES_KEYSIZE_256) ?
227962306a36Sopenharmony_ci				 CHCR_KEYCTX_CIPHER_KEY_SIZE_128 :
228062306a36Sopenharmony_ci				 CHCR_KEYCTX_CIPHER_KEY_SIZE_256,
228162306a36Sopenharmony_ci				 CHCR_KEYCTX_NO_KEY, 1,
228262306a36Sopenharmony_ci				 0, context_size);
228362306a36Sopenharmony_ci	}
228462306a36Sopenharmony_ci	ablkctx->ciph_mode = CHCR_SCMD_CIPHER_MODE_AES_XTS;
228562306a36Sopenharmony_ci	return 0;
228662306a36Sopenharmony_cibadkey_err:
228762306a36Sopenharmony_ci	ablkctx->enckey_len = 0;
228862306a36Sopenharmony_ci
228962306a36Sopenharmony_ci	return err;
229062306a36Sopenharmony_ci}
229162306a36Sopenharmony_ci
229262306a36Sopenharmony_cistatic int chcr_sha_init(struct ahash_request *areq)
229362306a36Sopenharmony_ci{
229462306a36Sopenharmony_ci	struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
229562306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
229662306a36Sopenharmony_ci	int digestsize =  crypto_ahash_digestsize(tfm);
229762306a36Sopenharmony_ci
229862306a36Sopenharmony_ci	req_ctx->data_len = 0;
229962306a36Sopenharmony_ci	req_ctx->reqlen = 0;
230062306a36Sopenharmony_ci	req_ctx->reqbfr = req_ctx->bfr1;
230162306a36Sopenharmony_ci	req_ctx->skbfr = req_ctx->bfr2;
230262306a36Sopenharmony_ci	copy_hash_init_values(req_ctx->partial_hash, digestsize);
230362306a36Sopenharmony_ci
230462306a36Sopenharmony_ci	return 0;
230562306a36Sopenharmony_ci}
230662306a36Sopenharmony_ci
230762306a36Sopenharmony_cistatic int chcr_sha_cra_init(struct crypto_tfm *tfm)
230862306a36Sopenharmony_ci{
230962306a36Sopenharmony_ci	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
231062306a36Sopenharmony_ci				 sizeof(struct chcr_ahash_req_ctx));
231162306a36Sopenharmony_ci	return chcr_device_init(crypto_tfm_ctx(tfm));
231262306a36Sopenharmony_ci}
231362306a36Sopenharmony_ci
231462306a36Sopenharmony_cistatic int chcr_hmac_init(struct ahash_request *areq)
231562306a36Sopenharmony_ci{
231662306a36Sopenharmony_ci	struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
231762306a36Sopenharmony_ci	struct crypto_ahash *rtfm = crypto_ahash_reqtfm(areq);
231862306a36Sopenharmony_ci	struct hmac_ctx *hmacctx = HMAC_CTX(h_ctx(rtfm));
231962306a36Sopenharmony_ci	unsigned int digestsize = crypto_ahash_digestsize(rtfm);
232062306a36Sopenharmony_ci	unsigned int bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(rtfm));
232162306a36Sopenharmony_ci
232262306a36Sopenharmony_ci	chcr_sha_init(areq);
232362306a36Sopenharmony_ci	req_ctx->data_len = bs;
232462306a36Sopenharmony_ci	if (is_hmac(crypto_ahash_tfm(rtfm))) {
232562306a36Sopenharmony_ci		if (digestsize == SHA224_DIGEST_SIZE)
232662306a36Sopenharmony_ci			memcpy(req_ctx->partial_hash, hmacctx->ipad,
232762306a36Sopenharmony_ci			       SHA256_DIGEST_SIZE);
232862306a36Sopenharmony_ci		else if (digestsize == SHA384_DIGEST_SIZE)
232962306a36Sopenharmony_ci			memcpy(req_ctx->partial_hash, hmacctx->ipad,
233062306a36Sopenharmony_ci			       SHA512_DIGEST_SIZE);
233162306a36Sopenharmony_ci		else
233262306a36Sopenharmony_ci			memcpy(req_ctx->partial_hash, hmacctx->ipad,
233362306a36Sopenharmony_ci			       digestsize);
233462306a36Sopenharmony_ci	}
233562306a36Sopenharmony_ci	return 0;
233662306a36Sopenharmony_ci}
233762306a36Sopenharmony_ci
233862306a36Sopenharmony_cistatic int chcr_hmac_cra_init(struct crypto_tfm *tfm)
233962306a36Sopenharmony_ci{
234062306a36Sopenharmony_ci	struct chcr_context *ctx = crypto_tfm_ctx(tfm);
234162306a36Sopenharmony_ci	struct hmac_ctx *hmacctx = HMAC_CTX(ctx);
234262306a36Sopenharmony_ci	unsigned int digestsize =
234362306a36Sopenharmony_ci		crypto_ahash_digestsize(__crypto_ahash_cast(tfm));
234462306a36Sopenharmony_ci
234562306a36Sopenharmony_ci	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
234662306a36Sopenharmony_ci				 sizeof(struct chcr_ahash_req_ctx));
234762306a36Sopenharmony_ci	hmacctx->base_hash = chcr_alloc_shash(digestsize);
234862306a36Sopenharmony_ci	if (IS_ERR(hmacctx->base_hash))
234962306a36Sopenharmony_ci		return PTR_ERR(hmacctx->base_hash);
235062306a36Sopenharmony_ci	return chcr_device_init(crypto_tfm_ctx(tfm));
235162306a36Sopenharmony_ci}
235262306a36Sopenharmony_ci
235362306a36Sopenharmony_cistatic void chcr_hmac_cra_exit(struct crypto_tfm *tfm)
235462306a36Sopenharmony_ci{
235562306a36Sopenharmony_ci	struct chcr_context *ctx = crypto_tfm_ctx(tfm);
235662306a36Sopenharmony_ci	struct hmac_ctx *hmacctx = HMAC_CTX(ctx);
235762306a36Sopenharmony_ci
235862306a36Sopenharmony_ci	if (hmacctx->base_hash) {
235962306a36Sopenharmony_ci		chcr_free_shash(hmacctx->base_hash);
236062306a36Sopenharmony_ci		hmacctx->base_hash = NULL;
236162306a36Sopenharmony_ci	}
236262306a36Sopenharmony_ci}
236362306a36Sopenharmony_ci
236462306a36Sopenharmony_ciinline void chcr_aead_common_exit(struct aead_request *req)
236562306a36Sopenharmony_ci{
236662306a36Sopenharmony_ci	struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req);
236762306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
236862306a36Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(a_ctx(tfm));
236962306a36Sopenharmony_ci
237062306a36Sopenharmony_ci	chcr_aead_dma_unmap(&u_ctx->lldi.pdev->dev, req, reqctx->op);
237162306a36Sopenharmony_ci}
237262306a36Sopenharmony_ci
237362306a36Sopenharmony_cistatic int chcr_aead_common_init(struct aead_request *req)
237462306a36Sopenharmony_ci{
237562306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
237662306a36Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm));
237762306a36Sopenharmony_ci	struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req);
237862306a36Sopenharmony_ci	unsigned int authsize = crypto_aead_authsize(tfm);
237962306a36Sopenharmony_ci	int error = -EINVAL;
238062306a36Sopenharmony_ci
238162306a36Sopenharmony_ci	/* validate key size */
238262306a36Sopenharmony_ci	if (aeadctx->enckey_len == 0)
238362306a36Sopenharmony_ci		goto err;
238462306a36Sopenharmony_ci	if (reqctx->op && req->cryptlen < authsize)
238562306a36Sopenharmony_ci		goto err;
238662306a36Sopenharmony_ci	if (reqctx->b0_len)
238762306a36Sopenharmony_ci		reqctx->scratch_pad = reqctx->iv + IV;
238862306a36Sopenharmony_ci	else
238962306a36Sopenharmony_ci		reqctx->scratch_pad = NULL;
239062306a36Sopenharmony_ci
239162306a36Sopenharmony_ci	error = chcr_aead_dma_map(&ULD_CTX(a_ctx(tfm))->lldi.pdev->dev, req,
239262306a36Sopenharmony_ci				  reqctx->op);
239362306a36Sopenharmony_ci	if (error) {
239462306a36Sopenharmony_ci		error = -ENOMEM;
239562306a36Sopenharmony_ci		goto err;
239662306a36Sopenharmony_ci	}
239762306a36Sopenharmony_ci
239862306a36Sopenharmony_ci	return 0;
239962306a36Sopenharmony_cierr:
240062306a36Sopenharmony_ci	return error;
240162306a36Sopenharmony_ci}
240262306a36Sopenharmony_ci
240362306a36Sopenharmony_cistatic int chcr_aead_need_fallback(struct aead_request *req, int dst_nents,
240462306a36Sopenharmony_ci				   int aadmax, int wrlen,
240562306a36Sopenharmony_ci				   unsigned short op_type)
240662306a36Sopenharmony_ci{
240762306a36Sopenharmony_ci	unsigned int authsize = crypto_aead_authsize(crypto_aead_reqtfm(req));
240862306a36Sopenharmony_ci
240962306a36Sopenharmony_ci	if (((req->cryptlen - (op_type ? authsize : 0)) == 0) ||
241062306a36Sopenharmony_ci	    dst_nents > MAX_DSGL_ENT ||
241162306a36Sopenharmony_ci	    (req->assoclen > aadmax) ||
241262306a36Sopenharmony_ci	    (wrlen > SGE_MAX_WR_LEN))
241362306a36Sopenharmony_ci		return 1;
241462306a36Sopenharmony_ci	return 0;
241562306a36Sopenharmony_ci}
241662306a36Sopenharmony_ci
241762306a36Sopenharmony_cistatic int chcr_aead_fallback(struct aead_request *req, unsigned short op_type)
241862306a36Sopenharmony_ci{
241962306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
242062306a36Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm));
242162306a36Sopenharmony_ci	struct aead_request *subreq = aead_request_ctx_dma(req);
242262306a36Sopenharmony_ci
242362306a36Sopenharmony_ci	aead_request_set_tfm(subreq, aeadctx->sw_cipher);
242462306a36Sopenharmony_ci	aead_request_set_callback(subreq, req->base.flags,
242562306a36Sopenharmony_ci				  req->base.complete, req->base.data);
242662306a36Sopenharmony_ci	aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
242762306a36Sopenharmony_ci				 req->iv);
242862306a36Sopenharmony_ci	aead_request_set_ad(subreq, req->assoclen);
242962306a36Sopenharmony_ci	return op_type ? crypto_aead_decrypt(subreq) :
243062306a36Sopenharmony_ci		crypto_aead_encrypt(subreq);
243162306a36Sopenharmony_ci}
243262306a36Sopenharmony_ci
243362306a36Sopenharmony_cistatic struct sk_buff *create_authenc_wr(struct aead_request *req,
243462306a36Sopenharmony_ci					 unsigned short qid,
243562306a36Sopenharmony_ci					 int size)
243662306a36Sopenharmony_ci{
243762306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
243862306a36Sopenharmony_ci	struct chcr_context *ctx = a_ctx(tfm);
243962306a36Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(ctx);
244062306a36Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(ctx);
244162306a36Sopenharmony_ci	struct chcr_authenc_ctx *actx = AUTHENC_CTX(aeadctx);
244262306a36Sopenharmony_ci	struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req);
244362306a36Sopenharmony_ci	struct sk_buff *skb = NULL;
244462306a36Sopenharmony_ci	struct chcr_wr *chcr_req;
244562306a36Sopenharmony_ci	struct cpl_rx_phys_dsgl *phys_cpl;
244662306a36Sopenharmony_ci	struct ulptx_sgl *ulptx;
244762306a36Sopenharmony_ci	unsigned int transhdr_len;
244862306a36Sopenharmony_ci	unsigned int dst_size = 0, temp, subtype = get_aead_subtype(tfm);
244962306a36Sopenharmony_ci	unsigned int   kctx_len = 0, dnents, snents;
245062306a36Sopenharmony_ci	unsigned int  authsize = crypto_aead_authsize(tfm);
245162306a36Sopenharmony_ci	int error = -EINVAL;
245262306a36Sopenharmony_ci	u8 *ivptr;
245362306a36Sopenharmony_ci	int null = 0;
245462306a36Sopenharmony_ci	gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
245562306a36Sopenharmony_ci		GFP_ATOMIC;
245662306a36Sopenharmony_ci	struct adapter *adap = padap(ctx->dev);
245762306a36Sopenharmony_ci	unsigned int rx_channel_id = reqctx->rxqidx / ctx->rxq_perchan;
245862306a36Sopenharmony_ci
245962306a36Sopenharmony_ci	rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]);
246062306a36Sopenharmony_ci	if (req->cryptlen == 0)
246162306a36Sopenharmony_ci		return NULL;
246262306a36Sopenharmony_ci
246362306a36Sopenharmony_ci	reqctx->b0_len = 0;
246462306a36Sopenharmony_ci	error = chcr_aead_common_init(req);
246562306a36Sopenharmony_ci	if (error)
246662306a36Sopenharmony_ci		return ERR_PTR(error);
246762306a36Sopenharmony_ci
246862306a36Sopenharmony_ci	if (subtype == CRYPTO_ALG_SUB_TYPE_CBC_NULL ||
246962306a36Sopenharmony_ci		subtype == CRYPTO_ALG_SUB_TYPE_CTR_NULL) {
247062306a36Sopenharmony_ci		null = 1;
247162306a36Sopenharmony_ci	}
247262306a36Sopenharmony_ci	dnents = sg_nents_xlen(req->dst, req->assoclen + req->cryptlen +
247362306a36Sopenharmony_ci		(reqctx->op ? -authsize : authsize), CHCR_DST_SG_SIZE, 0);
247462306a36Sopenharmony_ci	dnents += MIN_AUTH_SG; // For IV
247562306a36Sopenharmony_ci	snents = sg_nents_xlen(req->src, req->assoclen + req->cryptlen,
247662306a36Sopenharmony_ci			       CHCR_SRC_SG_SIZE, 0);
247762306a36Sopenharmony_ci	dst_size = get_space_for_phys_dsgl(dnents);
247862306a36Sopenharmony_ci	kctx_len = (KEY_CONTEXT_CTX_LEN_G(ntohl(aeadctx->key_ctx_hdr)) << 4)
247962306a36Sopenharmony_ci		- sizeof(chcr_req->key_ctx);
248062306a36Sopenharmony_ci	transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, dst_size);
248162306a36Sopenharmony_ci	reqctx->imm = (transhdr_len + req->assoclen + req->cryptlen) <
248262306a36Sopenharmony_ci			SGE_MAX_WR_LEN;
248362306a36Sopenharmony_ci	temp = reqctx->imm ? roundup(req->assoclen + req->cryptlen, 16)
248462306a36Sopenharmony_ci			: (sgl_len(snents) * 8);
248562306a36Sopenharmony_ci	transhdr_len += temp;
248662306a36Sopenharmony_ci	transhdr_len = roundup(transhdr_len, 16);
248762306a36Sopenharmony_ci
248862306a36Sopenharmony_ci	if (chcr_aead_need_fallback(req, dnents, T6_MAX_AAD_SIZE,
248962306a36Sopenharmony_ci				    transhdr_len, reqctx->op)) {
249062306a36Sopenharmony_ci		atomic_inc(&adap->chcr_stats.fallback);
249162306a36Sopenharmony_ci		chcr_aead_common_exit(req);
249262306a36Sopenharmony_ci		return ERR_PTR(chcr_aead_fallback(req, reqctx->op));
249362306a36Sopenharmony_ci	}
249462306a36Sopenharmony_ci	skb = alloc_skb(transhdr_len, flags);
249562306a36Sopenharmony_ci	if (!skb) {
249662306a36Sopenharmony_ci		error = -ENOMEM;
249762306a36Sopenharmony_ci		goto err;
249862306a36Sopenharmony_ci	}
249962306a36Sopenharmony_ci
250062306a36Sopenharmony_ci	chcr_req = __skb_put_zero(skb, transhdr_len);
250162306a36Sopenharmony_ci
250262306a36Sopenharmony_ci	temp  = (reqctx->op == CHCR_ENCRYPT_OP) ? 0 : authsize;
250362306a36Sopenharmony_ci
250462306a36Sopenharmony_ci	/*
250562306a36Sopenharmony_ci	 * Input order	is AAD,IV and Payload. where IV should be included as
250662306a36Sopenharmony_ci	 * the part of authdata. All other fields should be filled according
250762306a36Sopenharmony_ci	 * to the hardware spec
250862306a36Sopenharmony_ci	 */
250962306a36Sopenharmony_ci	chcr_req->sec_cpl.op_ivinsrtofst =
251062306a36Sopenharmony_ci				FILL_SEC_CPL_OP_IVINSR(rx_channel_id, 2, 1);
251162306a36Sopenharmony_ci	chcr_req->sec_cpl.pldlen = htonl(req->assoclen + IV + req->cryptlen);
251262306a36Sopenharmony_ci	chcr_req->sec_cpl.aadstart_cipherstop_hi = FILL_SEC_CPL_CIPHERSTOP_HI(
251362306a36Sopenharmony_ci					null ? 0 : 1 + IV,
251462306a36Sopenharmony_ci					null ? 0 : IV + req->assoclen,
251562306a36Sopenharmony_ci					req->assoclen + IV + 1,
251662306a36Sopenharmony_ci					(temp & 0x1F0) >> 4);
251762306a36Sopenharmony_ci	chcr_req->sec_cpl.cipherstop_lo_authinsert = FILL_SEC_CPL_AUTHINSERT(
251862306a36Sopenharmony_ci					temp & 0xF,
251962306a36Sopenharmony_ci					null ? 0 : req->assoclen + IV + 1,
252062306a36Sopenharmony_ci					temp, temp);
252162306a36Sopenharmony_ci	if (subtype == CRYPTO_ALG_SUB_TYPE_CTR_NULL ||
252262306a36Sopenharmony_ci	    subtype == CRYPTO_ALG_SUB_TYPE_CTR_SHA)
252362306a36Sopenharmony_ci		temp = CHCR_SCMD_CIPHER_MODE_AES_CTR;
252462306a36Sopenharmony_ci	else
252562306a36Sopenharmony_ci		temp = CHCR_SCMD_CIPHER_MODE_AES_CBC;
252662306a36Sopenharmony_ci	chcr_req->sec_cpl.seqno_numivs = FILL_SEC_CPL_SCMD0_SEQNO(reqctx->op,
252762306a36Sopenharmony_ci					(reqctx->op == CHCR_ENCRYPT_OP) ? 1 : 0,
252862306a36Sopenharmony_ci					temp,
252962306a36Sopenharmony_ci					actx->auth_mode, aeadctx->hmac_ctrl,
253062306a36Sopenharmony_ci					IV >> 1);
253162306a36Sopenharmony_ci	chcr_req->sec_cpl.ivgen_hdrlen =  FILL_SEC_CPL_IVGEN_HDRLEN(0, 0, 1,
253262306a36Sopenharmony_ci					 0, 0, dst_size);
253362306a36Sopenharmony_ci
253462306a36Sopenharmony_ci	chcr_req->key_ctx.ctx_hdr = aeadctx->key_ctx_hdr;
253562306a36Sopenharmony_ci	if (reqctx->op == CHCR_ENCRYPT_OP ||
253662306a36Sopenharmony_ci		subtype == CRYPTO_ALG_SUB_TYPE_CTR_SHA ||
253762306a36Sopenharmony_ci		subtype == CRYPTO_ALG_SUB_TYPE_CTR_NULL)
253862306a36Sopenharmony_ci		memcpy(chcr_req->key_ctx.key, aeadctx->key,
253962306a36Sopenharmony_ci		       aeadctx->enckey_len);
254062306a36Sopenharmony_ci	else
254162306a36Sopenharmony_ci		memcpy(chcr_req->key_ctx.key, actx->dec_rrkey,
254262306a36Sopenharmony_ci		       aeadctx->enckey_len);
254362306a36Sopenharmony_ci
254462306a36Sopenharmony_ci	memcpy(chcr_req->key_ctx.key + roundup(aeadctx->enckey_len, 16),
254562306a36Sopenharmony_ci	       actx->h_iopad, kctx_len - roundup(aeadctx->enckey_len, 16));
254662306a36Sopenharmony_ci	phys_cpl = (struct cpl_rx_phys_dsgl *)((u8 *)(chcr_req + 1) + kctx_len);
254762306a36Sopenharmony_ci	ivptr = (u8 *)(phys_cpl + 1) + dst_size;
254862306a36Sopenharmony_ci	ulptx = (struct ulptx_sgl *)(ivptr + IV);
254962306a36Sopenharmony_ci	if (subtype == CRYPTO_ALG_SUB_TYPE_CTR_SHA ||
255062306a36Sopenharmony_ci	    subtype == CRYPTO_ALG_SUB_TYPE_CTR_NULL) {
255162306a36Sopenharmony_ci		memcpy(ivptr, aeadctx->nonce, CTR_RFC3686_NONCE_SIZE);
255262306a36Sopenharmony_ci		memcpy(ivptr + CTR_RFC3686_NONCE_SIZE, req->iv,
255362306a36Sopenharmony_ci				CTR_RFC3686_IV_SIZE);
255462306a36Sopenharmony_ci		*(__be32 *)(ivptr + CTR_RFC3686_NONCE_SIZE +
255562306a36Sopenharmony_ci			CTR_RFC3686_IV_SIZE) = cpu_to_be32(1);
255662306a36Sopenharmony_ci	} else {
255762306a36Sopenharmony_ci		memcpy(ivptr, req->iv, IV);
255862306a36Sopenharmony_ci	}
255962306a36Sopenharmony_ci	chcr_add_aead_dst_ent(req, phys_cpl, qid);
256062306a36Sopenharmony_ci	chcr_add_aead_src_ent(req, ulptx);
256162306a36Sopenharmony_ci	atomic_inc(&adap->chcr_stats.cipher_rqst);
256262306a36Sopenharmony_ci	temp = sizeof(struct cpl_rx_phys_dsgl) + dst_size + IV +
256362306a36Sopenharmony_ci		kctx_len + (reqctx->imm ? (req->assoclen + req->cryptlen) : 0);
256462306a36Sopenharmony_ci	create_wreq(a_ctx(tfm), chcr_req, &req->base, reqctx->imm, size,
256562306a36Sopenharmony_ci		   transhdr_len, temp, 0);
256662306a36Sopenharmony_ci	reqctx->skb = skb;
256762306a36Sopenharmony_ci
256862306a36Sopenharmony_ci	return skb;
256962306a36Sopenharmony_cierr:
257062306a36Sopenharmony_ci	chcr_aead_common_exit(req);
257162306a36Sopenharmony_ci
257262306a36Sopenharmony_ci	return ERR_PTR(error);
257362306a36Sopenharmony_ci}
257462306a36Sopenharmony_ci
257562306a36Sopenharmony_ciint chcr_aead_dma_map(struct device *dev,
257662306a36Sopenharmony_ci		      struct aead_request *req,
257762306a36Sopenharmony_ci		      unsigned short op_type)
257862306a36Sopenharmony_ci{
257962306a36Sopenharmony_ci	int error;
258062306a36Sopenharmony_ci	struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req);
258162306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
258262306a36Sopenharmony_ci	unsigned int authsize = crypto_aead_authsize(tfm);
258362306a36Sopenharmony_ci	int src_len, dst_len;
258462306a36Sopenharmony_ci
258562306a36Sopenharmony_ci	/* calculate and handle src and dst sg length separately
258662306a36Sopenharmony_ci	 * for inplace and out-of place operations
258762306a36Sopenharmony_ci	 */
258862306a36Sopenharmony_ci	if (req->src == req->dst) {
258962306a36Sopenharmony_ci		src_len = req->assoclen + req->cryptlen + (op_type ?
259062306a36Sopenharmony_ci							0 : authsize);
259162306a36Sopenharmony_ci		dst_len = src_len;
259262306a36Sopenharmony_ci	} else {
259362306a36Sopenharmony_ci		src_len = req->assoclen + req->cryptlen;
259462306a36Sopenharmony_ci		dst_len = req->assoclen + req->cryptlen + (op_type ?
259562306a36Sopenharmony_ci							-authsize : authsize);
259662306a36Sopenharmony_ci	}
259762306a36Sopenharmony_ci
259862306a36Sopenharmony_ci	if (!req->cryptlen || !src_len || !dst_len)
259962306a36Sopenharmony_ci		return 0;
260062306a36Sopenharmony_ci	reqctx->iv_dma = dma_map_single(dev, reqctx->iv, (IV + reqctx->b0_len),
260162306a36Sopenharmony_ci					DMA_BIDIRECTIONAL);
260262306a36Sopenharmony_ci	if (dma_mapping_error(dev, reqctx->iv_dma))
260362306a36Sopenharmony_ci		return -ENOMEM;
260462306a36Sopenharmony_ci	if (reqctx->b0_len)
260562306a36Sopenharmony_ci		reqctx->b0_dma = reqctx->iv_dma + IV;
260662306a36Sopenharmony_ci	else
260762306a36Sopenharmony_ci		reqctx->b0_dma = 0;
260862306a36Sopenharmony_ci	if (req->src == req->dst) {
260962306a36Sopenharmony_ci		error = dma_map_sg(dev, req->src,
261062306a36Sopenharmony_ci				sg_nents_for_len(req->src, src_len),
261162306a36Sopenharmony_ci					DMA_BIDIRECTIONAL);
261262306a36Sopenharmony_ci		if (!error)
261362306a36Sopenharmony_ci			goto err;
261462306a36Sopenharmony_ci	} else {
261562306a36Sopenharmony_ci		error = dma_map_sg(dev, req->src,
261662306a36Sopenharmony_ci				   sg_nents_for_len(req->src, src_len),
261762306a36Sopenharmony_ci				   DMA_TO_DEVICE);
261862306a36Sopenharmony_ci		if (!error)
261962306a36Sopenharmony_ci			goto err;
262062306a36Sopenharmony_ci		error = dma_map_sg(dev, req->dst,
262162306a36Sopenharmony_ci				   sg_nents_for_len(req->dst, dst_len),
262262306a36Sopenharmony_ci				   DMA_FROM_DEVICE);
262362306a36Sopenharmony_ci		if (!error) {
262462306a36Sopenharmony_ci			dma_unmap_sg(dev, req->src,
262562306a36Sopenharmony_ci				     sg_nents_for_len(req->src, src_len),
262662306a36Sopenharmony_ci				     DMA_TO_DEVICE);
262762306a36Sopenharmony_ci			goto err;
262862306a36Sopenharmony_ci		}
262962306a36Sopenharmony_ci	}
263062306a36Sopenharmony_ci
263162306a36Sopenharmony_ci	return 0;
263262306a36Sopenharmony_cierr:
263362306a36Sopenharmony_ci	dma_unmap_single(dev, reqctx->iv_dma, IV, DMA_BIDIRECTIONAL);
263462306a36Sopenharmony_ci	return -ENOMEM;
263562306a36Sopenharmony_ci}
263662306a36Sopenharmony_ci
263762306a36Sopenharmony_civoid chcr_aead_dma_unmap(struct device *dev,
263862306a36Sopenharmony_ci			 struct aead_request *req,
263962306a36Sopenharmony_ci			 unsigned short op_type)
264062306a36Sopenharmony_ci{
264162306a36Sopenharmony_ci	struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req);
264262306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
264362306a36Sopenharmony_ci	unsigned int authsize = crypto_aead_authsize(tfm);
264462306a36Sopenharmony_ci	int src_len, dst_len;
264562306a36Sopenharmony_ci
264662306a36Sopenharmony_ci	/* calculate and handle src and dst sg length separately
264762306a36Sopenharmony_ci	 * for inplace and out-of place operations
264862306a36Sopenharmony_ci	 */
264962306a36Sopenharmony_ci	if (req->src == req->dst) {
265062306a36Sopenharmony_ci		src_len = req->assoclen + req->cryptlen + (op_type ?
265162306a36Sopenharmony_ci							0 : authsize);
265262306a36Sopenharmony_ci		dst_len = src_len;
265362306a36Sopenharmony_ci	} else {
265462306a36Sopenharmony_ci		src_len = req->assoclen + req->cryptlen;
265562306a36Sopenharmony_ci		dst_len = req->assoclen + req->cryptlen + (op_type ?
265662306a36Sopenharmony_ci						-authsize : authsize);
265762306a36Sopenharmony_ci	}
265862306a36Sopenharmony_ci
265962306a36Sopenharmony_ci	if (!req->cryptlen || !src_len || !dst_len)
266062306a36Sopenharmony_ci		return;
266162306a36Sopenharmony_ci
266262306a36Sopenharmony_ci	dma_unmap_single(dev, reqctx->iv_dma, (IV + reqctx->b0_len),
266362306a36Sopenharmony_ci					DMA_BIDIRECTIONAL);
266462306a36Sopenharmony_ci	if (req->src == req->dst) {
266562306a36Sopenharmony_ci		dma_unmap_sg(dev, req->src,
266662306a36Sopenharmony_ci			     sg_nents_for_len(req->src, src_len),
266762306a36Sopenharmony_ci			     DMA_BIDIRECTIONAL);
266862306a36Sopenharmony_ci	} else {
266962306a36Sopenharmony_ci		dma_unmap_sg(dev, req->src,
267062306a36Sopenharmony_ci			     sg_nents_for_len(req->src, src_len),
267162306a36Sopenharmony_ci			     DMA_TO_DEVICE);
267262306a36Sopenharmony_ci		dma_unmap_sg(dev, req->dst,
267362306a36Sopenharmony_ci			     sg_nents_for_len(req->dst, dst_len),
267462306a36Sopenharmony_ci			     DMA_FROM_DEVICE);
267562306a36Sopenharmony_ci	}
267662306a36Sopenharmony_ci}
267762306a36Sopenharmony_ci
267862306a36Sopenharmony_civoid chcr_add_aead_src_ent(struct aead_request *req,
267962306a36Sopenharmony_ci			   struct ulptx_sgl *ulptx)
268062306a36Sopenharmony_ci{
268162306a36Sopenharmony_ci	struct ulptx_walk ulp_walk;
268262306a36Sopenharmony_ci	struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req);
268362306a36Sopenharmony_ci
268462306a36Sopenharmony_ci	if (reqctx->imm) {
268562306a36Sopenharmony_ci		u8 *buf = (u8 *)ulptx;
268662306a36Sopenharmony_ci
268762306a36Sopenharmony_ci		if (reqctx->b0_len) {
268862306a36Sopenharmony_ci			memcpy(buf, reqctx->scratch_pad, reqctx->b0_len);
268962306a36Sopenharmony_ci			buf += reqctx->b0_len;
269062306a36Sopenharmony_ci		}
269162306a36Sopenharmony_ci		sg_pcopy_to_buffer(req->src, sg_nents(req->src),
269262306a36Sopenharmony_ci				   buf, req->cryptlen + req->assoclen, 0);
269362306a36Sopenharmony_ci	} else {
269462306a36Sopenharmony_ci		ulptx_walk_init(&ulp_walk, ulptx);
269562306a36Sopenharmony_ci		if (reqctx->b0_len)
269662306a36Sopenharmony_ci			ulptx_walk_add_page(&ulp_walk, reqctx->b0_len,
269762306a36Sopenharmony_ci					    reqctx->b0_dma);
269862306a36Sopenharmony_ci		ulptx_walk_add_sg(&ulp_walk, req->src, req->cryptlen +
269962306a36Sopenharmony_ci				  req->assoclen,  0);
270062306a36Sopenharmony_ci		ulptx_walk_end(&ulp_walk);
270162306a36Sopenharmony_ci	}
270262306a36Sopenharmony_ci}
270362306a36Sopenharmony_ci
270462306a36Sopenharmony_civoid chcr_add_aead_dst_ent(struct aead_request *req,
270562306a36Sopenharmony_ci			   struct cpl_rx_phys_dsgl *phys_cpl,
270662306a36Sopenharmony_ci			   unsigned short qid)
270762306a36Sopenharmony_ci{
270862306a36Sopenharmony_ci	struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req);
270962306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
271062306a36Sopenharmony_ci	struct dsgl_walk dsgl_walk;
271162306a36Sopenharmony_ci	unsigned int authsize = crypto_aead_authsize(tfm);
271262306a36Sopenharmony_ci	struct chcr_context *ctx = a_ctx(tfm);
271362306a36Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(ctx);
271462306a36Sopenharmony_ci	u32 temp;
271562306a36Sopenharmony_ci	unsigned int rx_channel_id = reqctx->rxqidx / ctx->rxq_perchan;
271662306a36Sopenharmony_ci
271762306a36Sopenharmony_ci	rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]);
271862306a36Sopenharmony_ci	dsgl_walk_init(&dsgl_walk, phys_cpl);
271962306a36Sopenharmony_ci	dsgl_walk_add_page(&dsgl_walk, IV + reqctx->b0_len, reqctx->iv_dma);
272062306a36Sopenharmony_ci	temp = req->assoclen + req->cryptlen +
272162306a36Sopenharmony_ci		(reqctx->op ? -authsize : authsize);
272262306a36Sopenharmony_ci	dsgl_walk_add_sg(&dsgl_walk, req->dst, temp, 0);
272362306a36Sopenharmony_ci	dsgl_walk_end(&dsgl_walk, qid, rx_channel_id);
272462306a36Sopenharmony_ci}
272562306a36Sopenharmony_ci
272662306a36Sopenharmony_civoid chcr_add_cipher_src_ent(struct skcipher_request *req,
272762306a36Sopenharmony_ci			     void *ulptx,
272862306a36Sopenharmony_ci			     struct  cipher_wr_param *wrparam)
272962306a36Sopenharmony_ci{
273062306a36Sopenharmony_ci	struct ulptx_walk ulp_walk;
273162306a36Sopenharmony_ci	struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req);
273262306a36Sopenharmony_ci	u8 *buf = ulptx;
273362306a36Sopenharmony_ci
273462306a36Sopenharmony_ci	memcpy(buf, reqctx->iv, IV);
273562306a36Sopenharmony_ci	buf += IV;
273662306a36Sopenharmony_ci	if (reqctx->imm) {
273762306a36Sopenharmony_ci		sg_pcopy_to_buffer(req->src, sg_nents(req->src),
273862306a36Sopenharmony_ci				   buf, wrparam->bytes, reqctx->processed);
273962306a36Sopenharmony_ci	} else {
274062306a36Sopenharmony_ci		ulptx_walk_init(&ulp_walk, (struct ulptx_sgl *)buf);
274162306a36Sopenharmony_ci		ulptx_walk_add_sg(&ulp_walk, reqctx->srcsg, wrparam->bytes,
274262306a36Sopenharmony_ci				  reqctx->src_ofst);
274362306a36Sopenharmony_ci		reqctx->srcsg = ulp_walk.last_sg;
274462306a36Sopenharmony_ci		reqctx->src_ofst = ulp_walk.last_sg_len;
274562306a36Sopenharmony_ci		ulptx_walk_end(&ulp_walk);
274662306a36Sopenharmony_ci	}
274762306a36Sopenharmony_ci}
274862306a36Sopenharmony_ci
274962306a36Sopenharmony_civoid chcr_add_cipher_dst_ent(struct skcipher_request *req,
275062306a36Sopenharmony_ci			     struct cpl_rx_phys_dsgl *phys_cpl,
275162306a36Sopenharmony_ci			     struct  cipher_wr_param *wrparam,
275262306a36Sopenharmony_ci			     unsigned short qid)
275362306a36Sopenharmony_ci{
275462306a36Sopenharmony_ci	struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req);
275562306a36Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(wrparam->req);
275662306a36Sopenharmony_ci	struct chcr_context *ctx = c_ctx(tfm);
275762306a36Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(ctx);
275862306a36Sopenharmony_ci	struct dsgl_walk dsgl_walk;
275962306a36Sopenharmony_ci	unsigned int rx_channel_id = reqctx->rxqidx / ctx->rxq_perchan;
276062306a36Sopenharmony_ci
276162306a36Sopenharmony_ci	rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]);
276262306a36Sopenharmony_ci	dsgl_walk_init(&dsgl_walk, phys_cpl);
276362306a36Sopenharmony_ci	dsgl_walk_add_sg(&dsgl_walk, reqctx->dstsg, wrparam->bytes,
276462306a36Sopenharmony_ci			 reqctx->dst_ofst);
276562306a36Sopenharmony_ci	reqctx->dstsg = dsgl_walk.last_sg;
276662306a36Sopenharmony_ci	reqctx->dst_ofst = dsgl_walk.last_sg_len;
276762306a36Sopenharmony_ci	dsgl_walk_end(&dsgl_walk, qid, rx_channel_id);
276862306a36Sopenharmony_ci}
276962306a36Sopenharmony_ci
277062306a36Sopenharmony_civoid chcr_add_hash_src_ent(struct ahash_request *req,
277162306a36Sopenharmony_ci			   struct ulptx_sgl *ulptx,
277262306a36Sopenharmony_ci			   struct hash_wr_param *param)
277362306a36Sopenharmony_ci{
277462306a36Sopenharmony_ci	struct ulptx_walk ulp_walk;
277562306a36Sopenharmony_ci	struct chcr_ahash_req_ctx *reqctx = ahash_request_ctx(req);
277662306a36Sopenharmony_ci
277762306a36Sopenharmony_ci	if (reqctx->hctx_wr.imm) {
277862306a36Sopenharmony_ci		u8 *buf = (u8 *)ulptx;
277962306a36Sopenharmony_ci
278062306a36Sopenharmony_ci		if (param->bfr_len) {
278162306a36Sopenharmony_ci			memcpy(buf, reqctx->reqbfr, param->bfr_len);
278262306a36Sopenharmony_ci			buf += param->bfr_len;
278362306a36Sopenharmony_ci		}
278462306a36Sopenharmony_ci
278562306a36Sopenharmony_ci		sg_pcopy_to_buffer(reqctx->hctx_wr.srcsg,
278662306a36Sopenharmony_ci				   sg_nents(reqctx->hctx_wr.srcsg), buf,
278762306a36Sopenharmony_ci				   param->sg_len, 0);
278862306a36Sopenharmony_ci	} else {
278962306a36Sopenharmony_ci		ulptx_walk_init(&ulp_walk, ulptx);
279062306a36Sopenharmony_ci		if (param->bfr_len)
279162306a36Sopenharmony_ci			ulptx_walk_add_page(&ulp_walk, param->bfr_len,
279262306a36Sopenharmony_ci					    reqctx->hctx_wr.dma_addr);
279362306a36Sopenharmony_ci		ulptx_walk_add_sg(&ulp_walk, reqctx->hctx_wr.srcsg,
279462306a36Sopenharmony_ci				  param->sg_len, reqctx->hctx_wr.src_ofst);
279562306a36Sopenharmony_ci		reqctx->hctx_wr.srcsg = ulp_walk.last_sg;
279662306a36Sopenharmony_ci		reqctx->hctx_wr.src_ofst = ulp_walk.last_sg_len;
279762306a36Sopenharmony_ci		ulptx_walk_end(&ulp_walk);
279862306a36Sopenharmony_ci	}
279962306a36Sopenharmony_ci}
280062306a36Sopenharmony_ci
280162306a36Sopenharmony_ciint chcr_hash_dma_map(struct device *dev,
280262306a36Sopenharmony_ci		      struct ahash_request *req)
280362306a36Sopenharmony_ci{
280462306a36Sopenharmony_ci	struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req);
280562306a36Sopenharmony_ci	int error = 0;
280662306a36Sopenharmony_ci
280762306a36Sopenharmony_ci	if (!req->nbytes)
280862306a36Sopenharmony_ci		return 0;
280962306a36Sopenharmony_ci	error = dma_map_sg(dev, req->src, sg_nents(req->src),
281062306a36Sopenharmony_ci			   DMA_TO_DEVICE);
281162306a36Sopenharmony_ci	if (!error)
281262306a36Sopenharmony_ci		return -ENOMEM;
281362306a36Sopenharmony_ci	req_ctx->hctx_wr.is_sg_map = 1;
281462306a36Sopenharmony_ci	return 0;
281562306a36Sopenharmony_ci}
281662306a36Sopenharmony_ci
281762306a36Sopenharmony_civoid chcr_hash_dma_unmap(struct device *dev,
281862306a36Sopenharmony_ci			 struct ahash_request *req)
281962306a36Sopenharmony_ci{
282062306a36Sopenharmony_ci	struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req);
282162306a36Sopenharmony_ci
282262306a36Sopenharmony_ci	if (!req->nbytes)
282362306a36Sopenharmony_ci		return;
282462306a36Sopenharmony_ci
282562306a36Sopenharmony_ci	dma_unmap_sg(dev, req->src, sg_nents(req->src),
282662306a36Sopenharmony_ci			   DMA_TO_DEVICE);
282762306a36Sopenharmony_ci	req_ctx->hctx_wr.is_sg_map = 0;
282862306a36Sopenharmony_ci
282962306a36Sopenharmony_ci}
283062306a36Sopenharmony_ci
283162306a36Sopenharmony_ciint chcr_cipher_dma_map(struct device *dev,
283262306a36Sopenharmony_ci			struct skcipher_request *req)
283362306a36Sopenharmony_ci{
283462306a36Sopenharmony_ci	int error;
283562306a36Sopenharmony_ci
283662306a36Sopenharmony_ci	if (req->src == req->dst) {
283762306a36Sopenharmony_ci		error = dma_map_sg(dev, req->src, sg_nents(req->src),
283862306a36Sopenharmony_ci				   DMA_BIDIRECTIONAL);
283962306a36Sopenharmony_ci		if (!error)
284062306a36Sopenharmony_ci			goto err;
284162306a36Sopenharmony_ci	} else {
284262306a36Sopenharmony_ci		error = dma_map_sg(dev, req->src, sg_nents(req->src),
284362306a36Sopenharmony_ci				   DMA_TO_DEVICE);
284462306a36Sopenharmony_ci		if (!error)
284562306a36Sopenharmony_ci			goto err;
284662306a36Sopenharmony_ci		error = dma_map_sg(dev, req->dst, sg_nents(req->dst),
284762306a36Sopenharmony_ci				   DMA_FROM_DEVICE);
284862306a36Sopenharmony_ci		if (!error) {
284962306a36Sopenharmony_ci			dma_unmap_sg(dev, req->src, sg_nents(req->src),
285062306a36Sopenharmony_ci				   DMA_TO_DEVICE);
285162306a36Sopenharmony_ci			goto err;
285262306a36Sopenharmony_ci		}
285362306a36Sopenharmony_ci	}
285462306a36Sopenharmony_ci
285562306a36Sopenharmony_ci	return 0;
285662306a36Sopenharmony_cierr:
285762306a36Sopenharmony_ci	return -ENOMEM;
285862306a36Sopenharmony_ci}
285962306a36Sopenharmony_ci
286062306a36Sopenharmony_civoid chcr_cipher_dma_unmap(struct device *dev,
286162306a36Sopenharmony_ci			   struct skcipher_request *req)
286262306a36Sopenharmony_ci{
286362306a36Sopenharmony_ci	if (req->src == req->dst) {
286462306a36Sopenharmony_ci		dma_unmap_sg(dev, req->src, sg_nents(req->src),
286562306a36Sopenharmony_ci				   DMA_BIDIRECTIONAL);
286662306a36Sopenharmony_ci	} else {
286762306a36Sopenharmony_ci		dma_unmap_sg(dev, req->src, sg_nents(req->src),
286862306a36Sopenharmony_ci				   DMA_TO_DEVICE);
286962306a36Sopenharmony_ci		dma_unmap_sg(dev, req->dst, sg_nents(req->dst),
287062306a36Sopenharmony_ci				   DMA_FROM_DEVICE);
287162306a36Sopenharmony_ci	}
287262306a36Sopenharmony_ci}
287362306a36Sopenharmony_ci
287462306a36Sopenharmony_cistatic int set_msg_len(u8 *block, unsigned int msglen, int csize)
287562306a36Sopenharmony_ci{
287662306a36Sopenharmony_ci	__be32 data;
287762306a36Sopenharmony_ci
287862306a36Sopenharmony_ci	memset(block, 0, csize);
287962306a36Sopenharmony_ci	block += csize;
288062306a36Sopenharmony_ci
288162306a36Sopenharmony_ci	if (csize >= 4)
288262306a36Sopenharmony_ci		csize = 4;
288362306a36Sopenharmony_ci	else if (msglen > (unsigned int)(1 << (8 * csize)))
288462306a36Sopenharmony_ci		return -EOVERFLOW;
288562306a36Sopenharmony_ci
288662306a36Sopenharmony_ci	data = cpu_to_be32(msglen);
288762306a36Sopenharmony_ci	memcpy(block - csize, (u8 *)&data + 4 - csize, csize);
288862306a36Sopenharmony_ci
288962306a36Sopenharmony_ci	return 0;
289062306a36Sopenharmony_ci}
289162306a36Sopenharmony_ci
289262306a36Sopenharmony_cistatic int generate_b0(struct aead_request *req, u8 *ivptr,
289362306a36Sopenharmony_ci			unsigned short op_type)
289462306a36Sopenharmony_ci{
289562306a36Sopenharmony_ci	unsigned int l, lp, m;
289662306a36Sopenharmony_ci	int rc;
289762306a36Sopenharmony_ci	struct crypto_aead *aead = crypto_aead_reqtfm(req);
289862306a36Sopenharmony_ci	struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req);
289962306a36Sopenharmony_ci	u8 *b0 = reqctx->scratch_pad;
290062306a36Sopenharmony_ci
290162306a36Sopenharmony_ci	m = crypto_aead_authsize(aead);
290262306a36Sopenharmony_ci
290362306a36Sopenharmony_ci	memcpy(b0, ivptr, 16);
290462306a36Sopenharmony_ci
290562306a36Sopenharmony_ci	lp = b0[0];
290662306a36Sopenharmony_ci	l = lp + 1;
290762306a36Sopenharmony_ci
290862306a36Sopenharmony_ci	/* set m, bits 3-5 */
290962306a36Sopenharmony_ci	*b0 |= (8 * ((m - 2) / 2));
291062306a36Sopenharmony_ci
291162306a36Sopenharmony_ci	/* set adata, bit 6, if associated data is used */
291262306a36Sopenharmony_ci	if (req->assoclen)
291362306a36Sopenharmony_ci		*b0 |= 64;
291462306a36Sopenharmony_ci	rc = set_msg_len(b0 + 16 - l,
291562306a36Sopenharmony_ci			 (op_type == CHCR_DECRYPT_OP) ?
291662306a36Sopenharmony_ci			 req->cryptlen - m : req->cryptlen, l);
291762306a36Sopenharmony_ci
291862306a36Sopenharmony_ci	return rc;
291962306a36Sopenharmony_ci}
292062306a36Sopenharmony_ci
292162306a36Sopenharmony_cistatic inline int crypto_ccm_check_iv(const u8 *iv)
292262306a36Sopenharmony_ci{
292362306a36Sopenharmony_ci	/* 2 <= L <= 8, so 1 <= L' <= 7. */
292462306a36Sopenharmony_ci	if (iv[0] < 1 || iv[0] > 7)
292562306a36Sopenharmony_ci		return -EINVAL;
292662306a36Sopenharmony_ci
292762306a36Sopenharmony_ci	return 0;
292862306a36Sopenharmony_ci}
292962306a36Sopenharmony_ci
293062306a36Sopenharmony_cistatic int ccm_format_packet(struct aead_request *req,
293162306a36Sopenharmony_ci			     u8 *ivptr,
293262306a36Sopenharmony_ci			     unsigned int sub_type,
293362306a36Sopenharmony_ci			     unsigned short op_type,
293462306a36Sopenharmony_ci			     unsigned int assoclen)
293562306a36Sopenharmony_ci{
293662306a36Sopenharmony_ci	struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req);
293762306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
293862306a36Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm));
293962306a36Sopenharmony_ci	int rc = 0;
294062306a36Sopenharmony_ci
294162306a36Sopenharmony_ci	if (sub_type == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309) {
294262306a36Sopenharmony_ci		ivptr[0] = 3;
294362306a36Sopenharmony_ci		memcpy(ivptr + 1, &aeadctx->salt[0], 3);
294462306a36Sopenharmony_ci		memcpy(ivptr + 4, req->iv, 8);
294562306a36Sopenharmony_ci		memset(ivptr + 12, 0, 4);
294662306a36Sopenharmony_ci	} else {
294762306a36Sopenharmony_ci		memcpy(ivptr, req->iv, 16);
294862306a36Sopenharmony_ci	}
294962306a36Sopenharmony_ci	if (assoclen)
295062306a36Sopenharmony_ci		put_unaligned_be16(assoclen, &reqctx->scratch_pad[16]);
295162306a36Sopenharmony_ci
295262306a36Sopenharmony_ci	rc = generate_b0(req, ivptr, op_type);
295362306a36Sopenharmony_ci	/* zero the ctr value */
295462306a36Sopenharmony_ci	memset(ivptr + 15 - ivptr[0], 0, ivptr[0] + 1);
295562306a36Sopenharmony_ci	return rc;
295662306a36Sopenharmony_ci}
295762306a36Sopenharmony_ci
295862306a36Sopenharmony_cistatic void fill_sec_cpl_for_aead(struct cpl_tx_sec_pdu *sec_cpl,
295962306a36Sopenharmony_ci				  unsigned int dst_size,
296062306a36Sopenharmony_ci				  struct aead_request *req,
296162306a36Sopenharmony_ci				  unsigned short op_type)
296262306a36Sopenharmony_ci{
296362306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
296462306a36Sopenharmony_ci	struct chcr_context *ctx = a_ctx(tfm);
296562306a36Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(ctx);
296662306a36Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(ctx);
296762306a36Sopenharmony_ci	struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req);
296862306a36Sopenharmony_ci	unsigned int cipher_mode = CHCR_SCMD_CIPHER_MODE_AES_CCM;
296962306a36Sopenharmony_ci	unsigned int mac_mode = CHCR_SCMD_AUTH_MODE_CBCMAC;
297062306a36Sopenharmony_ci	unsigned int rx_channel_id = reqctx->rxqidx / ctx->rxq_perchan;
297162306a36Sopenharmony_ci	unsigned int ccm_xtra;
297262306a36Sopenharmony_ci	unsigned int tag_offset = 0, auth_offset = 0;
297362306a36Sopenharmony_ci	unsigned int assoclen;
297462306a36Sopenharmony_ci
297562306a36Sopenharmony_ci	rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]);
297662306a36Sopenharmony_ci
297762306a36Sopenharmony_ci	if (get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309)
297862306a36Sopenharmony_ci		assoclen = req->assoclen - 8;
297962306a36Sopenharmony_ci	else
298062306a36Sopenharmony_ci		assoclen = req->assoclen;
298162306a36Sopenharmony_ci	ccm_xtra = CCM_B0_SIZE +
298262306a36Sopenharmony_ci		((assoclen) ? CCM_AAD_FIELD_SIZE : 0);
298362306a36Sopenharmony_ci
298462306a36Sopenharmony_ci	auth_offset = req->cryptlen ?
298562306a36Sopenharmony_ci		(req->assoclen + IV + 1 + ccm_xtra) : 0;
298662306a36Sopenharmony_ci	if (op_type == CHCR_DECRYPT_OP) {
298762306a36Sopenharmony_ci		if (crypto_aead_authsize(tfm) != req->cryptlen)
298862306a36Sopenharmony_ci			tag_offset = crypto_aead_authsize(tfm);
298962306a36Sopenharmony_ci		else
299062306a36Sopenharmony_ci			auth_offset = 0;
299162306a36Sopenharmony_ci	}
299262306a36Sopenharmony_ci
299362306a36Sopenharmony_ci	sec_cpl->op_ivinsrtofst = FILL_SEC_CPL_OP_IVINSR(rx_channel_id, 2, 1);
299462306a36Sopenharmony_ci	sec_cpl->pldlen =
299562306a36Sopenharmony_ci		htonl(req->assoclen + IV + req->cryptlen + ccm_xtra);
299662306a36Sopenharmony_ci	/* For CCM there wil be b0 always. So AAD start will be 1 always */
299762306a36Sopenharmony_ci	sec_cpl->aadstart_cipherstop_hi = FILL_SEC_CPL_CIPHERSTOP_HI(
299862306a36Sopenharmony_ci				1 + IV,	IV + assoclen + ccm_xtra,
299962306a36Sopenharmony_ci				req->assoclen + IV + 1 + ccm_xtra, 0);
300062306a36Sopenharmony_ci
300162306a36Sopenharmony_ci	sec_cpl->cipherstop_lo_authinsert = FILL_SEC_CPL_AUTHINSERT(0,
300262306a36Sopenharmony_ci					auth_offset, tag_offset,
300362306a36Sopenharmony_ci					(op_type == CHCR_ENCRYPT_OP) ? 0 :
300462306a36Sopenharmony_ci					crypto_aead_authsize(tfm));
300562306a36Sopenharmony_ci	sec_cpl->seqno_numivs =  FILL_SEC_CPL_SCMD0_SEQNO(op_type,
300662306a36Sopenharmony_ci					(op_type == CHCR_ENCRYPT_OP) ? 0 : 1,
300762306a36Sopenharmony_ci					cipher_mode, mac_mode,
300862306a36Sopenharmony_ci					aeadctx->hmac_ctrl, IV >> 1);
300962306a36Sopenharmony_ci
301062306a36Sopenharmony_ci	sec_cpl->ivgen_hdrlen = FILL_SEC_CPL_IVGEN_HDRLEN(0, 0, 1, 0,
301162306a36Sopenharmony_ci					0, dst_size);
301262306a36Sopenharmony_ci}
301362306a36Sopenharmony_ci
301462306a36Sopenharmony_cistatic int aead_ccm_validate_input(unsigned short op_type,
301562306a36Sopenharmony_ci				   struct aead_request *req,
301662306a36Sopenharmony_ci				   struct chcr_aead_ctx *aeadctx,
301762306a36Sopenharmony_ci				   unsigned int sub_type)
301862306a36Sopenharmony_ci{
301962306a36Sopenharmony_ci	if (sub_type != CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309) {
302062306a36Sopenharmony_ci		if (crypto_ccm_check_iv(req->iv)) {
302162306a36Sopenharmony_ci			pr_err("CCM: IV check fails\n");
302262306a36Sopenharmony_ci			return -EINVAL;
302362306a36Sopenharmony_ci		}
302462306a36Sopenharmony_ci	} else {
302562306a36Sopenharmony_ci		if (req->assoclen != 16 && req->assoclen != 20) {
302662306a36Sopenharmony_ci			pr_err("RFC4309: Invalid AAD length %d\n",
302762306a36Sopenharmony_ci			       req->assoclen);
302862306a36Sopenharmony_ci			return -EINVAL;
302962306a36Sopenharmony_ci		}
303062306a36Sopenharmony_ci	}
303162306a36Sopenharmony_ci	return 0;
303262306a36Sopenharmony_ci}
303362306a36Sopenharmony_ci
303462306a36Sopenharmony_cistatic struct sk_buff *create_aead_ccm_wr(struct aead_request *req,
303562306a36Sopenharmony_ci					  unsigned short qid,
303662306a36Sopenharmony_ci					  int size)
303762306a36Sopenharmony_ci{
303862306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
303962306a36Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm));
304062306a36Sopenharmony_ci	struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req);
304162306a36Sopenharmony_ci	struct sk_buff *skb = NULL;
304262306a36Sopenharmony_ci	struct chcr_wr *chcr_req;
304362306a36Sopenharmony_ci	struct cpl_rx_phys_dsgl *phys_cpl;
304462306a36Sopenharmony_ci	struct ulptx_sgl *ulptx;
304562306a36Sopenharmony_ci	unsigned int transhdr_len;
304662306a36Sopenharmony_ci	unsigned int dst_size = 0, kctx_len, dnents, temp, snents;
304762306a36Sopenharmony_ci	unsigned int sub_type, assoclen = req->assoclen;
304862306a36Sopenharmony_ci	unsigned int authsize = crypto_aead_authsize(tfm);
304962306a36Sopenharmony_ci	int error = -EINVAL;
305062306a36Sopenharmony_ci	u8 *ivptr;
305162306a36Sopenharmony_ci	gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
305262306a36Sopenharmony_ci		GFP_ATOMIC;
305362306a36Sopenharmony_ci	struct adapter *adap = padap(a_ctx(tfm)->dev);
305462306a36Sopenharmony_ci
305562306a36Sopenharmony_ci	sub_type = get_aead_subtype(tfm);
305662306a36Sopenharmony_ci	if (sub_type == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309)
305762306a36Sopenharmony_ci		assoclen -= 8;
305862306a36Sopenharmony_ci	reqctx->b0_len = CCM_B0_SIZE + (assoclen ? CCM_AAD_FIELD_SIZE : 0);
305962306a36Sopenharmony_ci	error = chcr_aead_common_init(req);
306062306a36Sopenharmony_ci	if (error)
306162306a36Sopenharmony_ci		return ERR_PTR(error);
306262306a36Sopenharmony_ci
306362306a36Sopenharmony_ci	error = aead_ccm_validate_input(reqctx->op, req, aeadctx, sub_type);
306462306a36Sopenharmony_ci	if (error)
306562306a36Sopenharmony_ci		goto err;
306662306a36Sopenharmony_ci	dnents = sg_nents_xlen(req->dst, req->assoclen + req->cryptlen
306762306a36Sopenharmony_ci			+ (reqctx->op ? -authsize : authsize),
306862306a36Sopenharmony_ci			CHCR_DST_SG_SIZE, 0);
306962306a36Sopenharmony_ci	dnents += MIN_CCM_SG; // For IV and B0
307062306a36Sopenharmony_ci	dst_size = get_space_for_phys_dsgl(dnents);
307162306a36Sopenharmony_ci	snents = sg_nents_xlen(req->src, req->assoclen + req->cryptlen,
307262306a36Sopenharmony_ci			       CHCR_SRC_SG_SIZE, 0);
307362306a36Sopenharmony_ci	snents += MIN_CCM_SG; //For B0
307462306a36Sopenharmony_ci	kctx_len = roundup(aeadctx->enckey_len, 16) * 2;
307562306a36Sopenharmony_ci	transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, dst_size);
307662306a36Sopenharmony_ci	reqctx->imm = (transhdr_len + req->assoclen + req->cryptlen +
307762306a36Sopenharmony_ci		       reqctx->b0_len) <= SGE_MAX_WR_LEN;
307862306a36Sopenharmony_ci	temp = reqctx->imm ? roundup(req->assoclen + req->cryptlen +
307962306a36Sopenharmony_ci				     reqctx->b0_len, 16) :
308062306a36Sopenharmony_ci		(sgl_len(snents) *  8);
308162306a36Sopenharmony_ci	transhdr_len += temp;
308262306a36Sopenharmony_ci	transhdr_len = roundup(transhdr_len, 16);
308362306a36Sopenharmony_ci
308462306a36Sopenharmony_ci	if (chcr_aead_need_fallback(req, dnents, T6_MAX_AAD_SIZE -
308562306a36Sopenharmony_ci				reqctx->b0_len, transhdr_len, reqctx->op)) {
308662306a36Sopenharmony_ci		atomic_inc(&adap->chcr_stats.fallback);
308762306a36Sopenharmony_ci		chcr_aead_common_exit(req);
308862306a36Sopenharmony_ci		return ERR_PTR(chcr_aead_fallback(req, reqctx->op));
308962306a36Sopenharmony_ci	}
309062306a36Sopenharmony_ci	skb = alloc_skb(transhdr_len,  flags);
309162306a36Sopenharmony_ci
309262306a36Sopenharmony_ci	if (!skb) {
309362306a36Sopenharmony_ci		error = -ENOMEM;
309462306a36Sopenharmony_ci		goto err;
309562306a36Sopenharmony_ci	}
309662306a36Sopenharmony_ci
309762306a36Sopenharmony_ci	chcr_req = __skb_put_zero(skb, transhdr_len);
309862306a36Sopenharmony_ci
309962306a36Sopenharmony_ci	fill_sec_cpl_for_aead(&chcr_req->sec_cpl, dst_size, req, reqctx->op);
310062306a36Sopenharmony_ci
310162306a36Sopenharmony_ci	chcr_req->key_ctx.ctx_hdr = aeadctx->key_ctx_hdr;
310262306a36Sopenharmony_ci	memcpy(chcr_req->key_ctx.key, aeadctx->key, aeadctx->enckey_len);
310362306a36Sopenharmony_ci	memcpy(chcr_req->key_ctx.key + roundup(aeadctx->enckey_len, 16),
310462306a36Sopenharmony_ci			aeadctx->key, aeadctx->enckey_len);
310562306a36Sopenharmony_ci
310662306a36Sopenharmony_ci	phys_cpl = (struct cpl_rx_phys_dsgl *)((u8 *)(chcr_req + 1) + kctx_len);
310762306a36Sopenharmony_ci	ivptr = (u8 *)(phys_cpl + 1) + dst_size;
310862306a36Sopenharmony_ci	ulptx = (struct ulptx_sgl *)(ivptr + IV);
310962306a36Sopenharmony_ci	error = ccm_format_packet(req, ivptr, sub_type, reqctx->op, assoclen);
311062306a36Sopenharmony_ci	if (error)
311162306a36Sopenharmony_ci		goto dstmap_fail;
311262306a36Sopenharmony_ci	chcr_add_aead_dst_ent(req, phys_cpl, qid);
311362306a36Sopenharmony_ci	chcr_add_aead_src_ent(req, ulptx);
311462306a36Sopenharmony_ci
311562306a36Sopenharmony_ci	atomic_inc(&adap->chcr_stats.aead_rqst);
311662306a36Sopenharmony_ci	temp = sizeof(struct cpl_rx_phys_dsgl) + dst_size + IV +
311762306a36Sopenharmony_ci		kctx_len + (reqctx->imm ? (req->assoclen + req->cryptlen +
311862306a36Sopenharmony_ci		reqctx->b0_len) : 0);
311962306a36Sopenharmony_ci	create_wreq(a_ctx(tfm), chcr_req, &req->base, reqctx->imm, 0,
312062306a36Sopenharmony_ci		    transhdr_len, temp, 0);
312162306a36Sopenharmony_ci	reqctx->skb = skb;
312262306a36Sopenharmony_ci
312362306a36Sopenharmony_ci	return skb;
312462306a36Sopenharmony_cidstmap_fail:
312562306a36Sopenharmony_ci	kfree_skb(skb);
312662306a36Sopenharmony_cierr:
312762306a36Sopenharmony_ci	chcr_aead_common_exit(req);
312862306a36Sopenharmony_ci	return ERR_PTR(error);
312962306a36Sopenharmony_ci}
313062306a36Sopenharmony_ci
313162306a36Sopenharmony_cistatic struct sk_buff *create_gcm_wr(struct aead_request *req,
313262306a36Sopenharmony_ci				     unsigned short qid,
313362306a36Sopenharmony_ci				     int size)
313462306a36Sopenharmony_ci{
313562306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
313662306a36Sopenharmony_ci	struct chcr_context *ctx = a_ctx(tfm);
313762306a36Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(ctx);
313862306a36Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(ctx);
313962306a36Sopenharmony_ci	struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req);
314062306a36Sopenharmony_ci	struct sk_buff *skb = NULL;
314162306a36Sopenharmony_ci	struct chcr_wr *chcr_req;
314262306a36Sopenharmony_ci	struct cpl_rx_phys_dsgl *phys_cpl;
314362306a36Sopenharmony_ci	struct ulptx_sgl *ulptx;
314462306a36Sopenharmony_ci	unsigned int transhdr_len, dnents = 0, snents;
314562306a36Sopenharmony_ci	unsigned int dst_size = 0, temp = 0, kctx_len, assoclen = req->assoclen;
314662306a36Sopenharmony_ci	unsigned int authsize = crypto_aead_authsize(tfm);
314762306a36Sopenharmony_ci	int error = -EINVAL;
314862306a36Sopenharmony_ci	u8 *ivptr;
314962306a36Sopenharmony_ci	gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
315062306a36Sopenharmony_ci		GFP_ATOMIC;
315162306a36Sopenharmony_ci	struct adapter *adap = padap(ctx->dev);
315262306a36Sopenharmony_ci	unsigned int rx_channel_id = reqctx->rxqidx / ctx->rxq_perchan;
315362306a36Sopenharmony_ci
315462306a36Sopenharmony_ci	rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]);
315562306a36Sopenharmony_ci	if (get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106)
315662306a36Sopenharmony_ci		assoclen = req->assoclen - 8;
315762306a36Sopenharmony_ci
315862306a36Sopenharmony_ci	reqctx->b0_len = 0;
315962306a36Sopenharmony_ci	error = chcr_aead_common_init(req);
316062306a36Sopenharmony_ci	if (error)
316162306a36Sopenharmony_ci		return ERR_PTR(error);
316262306a36Sopenharmony_ci	dnents = sg_nents_xlen(req->dst, req->assoclen + req->cryptlen +
316362306a36Sopenharmony_ci				(reqctx->op ? -authsize : authsize),
316462306a36Sopenharmony_ci				CHCR_DST_SG_SIZE, 0);
316562306a36Sopenharmony_ci	snents = sg_nents_xlen(req->src, req->assoclen + req->cryptlen,
316662306a36Sopenharmony_ci			       CHCR_SRC_SG_SIZE, 0);
316762306a36Sopenharmony_ci	dnents += MIN_GCM_SG; // For IV
316862306a36Sopenharmony_ci	dst_size = get_space_for_phys_dsgl(dnents);
316962306a36Sopenharmony_ci	kctx_len = roundup(aeadctx->enckey_len, 16) + AEAD_H_SIZE;
317062306a36Sopenharmony_ci	transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, dst_size);
317162306a36Sopenharmony_ci	reqctx->imm = (transhdr_len + req->assoclen + req->cryptlen) <=
317262306a36Sopenharmony_ci			SGE_MAX_WR_LEN;
317362306a36Sopenharmony_ci	temp = reqctx->imm ? roundup(req->assoclen + req->cryptlen, 16) :
317462306a36Sopenharmony_ci		(sgl_len(snents) * 8);
317562306a36Sopenharmony_ci	transhdr_len += temp;
317662306a36Sopenharmony_ci	transhdr_len = roundup(transhdr_len, 16);
317762306a36Sopenharmony_ci	if (chcr_aead_need_fallback(req, dnents, T6_MAX_AAD_SIZE,
317862306a36Sopenharmony_ci			    transhdr_len, reqctx->op)) {
317962306a36Sopenharmony_ci
318062306a36Sopenharmony_ci		atomic_inc(&adap->chcr_stats.fallback);
318162306a36Sopenharmony_ci		chcr_aead_common_exit(req);
318262306a36Sopenharmony_ci		return ERR_PTR(chcr_aead_fallback(req, reqctx->op));
318362306a36Sopenharmony_ci	}
318462306a36Sopenharmony_ci	skb = alloc_skb(transhdr_len, flags);
318562306a36Sopenharmony_ci	if (!skb) {
318662306a36Sopenharmony_ci		error = -ENOMEM;
318762306a36Sopenharmony_ci		goto err;
318862306a36Sopenharmony_ci	}
318962306a36Sopenharmony_ci
319062306a36Sopenharmony_ci	chcr_req = __skb_put_zero(skb, transhdr_len);
319162306a36Sopenharmony_ci
319262306a36Sopenharmony_ci	//Offset of tag from end
319362306a36Sopenharmony_ci	temp = (reqctx->op == CHCR_ENCRYPT_OP) ? 0 : authsize;
319462306a36Sopenharmony_ci	chcr_req->sec_cpl.op_ivinsrtofst = FILL_SEC_CPL_OP_IVINSR(
319562306a36Sopenharmony_ci						rx_channel_id, 2, 1);
319662306a36Sopenharmony_ci	chcr_req->sec_cpl.pldlen =
319762306a36Sopenharmony_ci		htonl(req->assoclen + IV + req->cryptlen);
319862306a36Sopenharmony_ci	chcr_req->sec_cpl.aadstart_cipherstop_hi = FILL_SEC_CPL_CIPHERSTOP_HI(
319962306a36Sopenharmony_ci					assoclen ? 1 + IV : 0,
320062306a36Sopenharmony_ci					assoclen ? IV + assoclen : 0,
320162306a36Sopenharmony_ci					req->assoclen + IV + 1, 0);
320262306a36Sopenharmony_ci	chcr_req->sec_cpl.cipherstop_lo_authinsert =
320362306a36Sopenharmony_ci			FILL_SEC_CPL_AUTHINSERT(0, req->assoclen + IV + 1,
320462306a36Sopenharmony_ci						temp, temp);
320562306a36Sopenharmony_ci	chcr_req->sec_cpl.seqno_numivs =
320662306a36Sopenharmony_ci			FILL_SEC_CPL_SCMD0_SEQNO(reqctx->op, (reqctx->op ==
320762306a36Sopenharmony_ci					CHCR_ENCRYPT_OP) ? 1 : 0,
320862306a36Sopenharmony_ci					CHCR_SCMD_CIPHER_MODE_AES_GCM,
320962306a36Sopenharmony_ci					CHCR_SCMD_AUTH_MODE_GHASH,
321062306a36Sopenharmony_ci					aeadctx->hmac_ctrl, IV >> 1);
321162306a36Sopenharmony_ci	chcr_req->sec_cpl.ivgen_hdrlen =  FILL_SEC_CPL_IVGEN_HDRLEN(0, 0, 1,
321262306a36Sopenharmony_ci					0, 0, dst_size);
321362306a36Sopenharmony_ci	chcr_req->key_ctx.ctx_hdr = aeadctx->key_ctx_hdr;
321462306a36Sopenharmony_ci	memcpy(chcr_req->key_ctx.key, aeadctx->key, aeadctx->enckey_len);
321562306a36Sopenharmony_ci	memcpy(chcr_req->key_ctx.key + roundup(aeadctx->enckey_len, 16),
321662306a36Sopenharmony_ci	       GCM_CTX(aeadctx)->ghash_h, AEAD_H_SIZE);
321762306a36Sopenharmony_ci
321862306a36Sopenharmony_ci	phys_cpl = (struct cpl_rx_phys_dsgl *)((u8 *)(chcr_req + 1) + kctx_len);
321962306a36Sopenharmony_ci	ivptr = (u8 *)(phys_cpl + 1) + dst_size;
322062306a36Sopenharmony_ci	/* prepare a 16 byte iv */
322162306a36Sopenharmony_ci	/* S   A   L  T |  IV | 0x00000001 */
322262306a36Sopenharmony_ci	if (get_aead_subtype(tfm) ==
322362306a36Sopenharmony_ci	    CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106) {
322462306a36Sopenharmony_ci		memcpy(ivptr, aeadctx->salt, 4);
322562306a36Sopenharmony_ci		memcpy(ivptr + 4, req->iv, GCM_RFC4106_IV_SIZE);
322662306a36Sopenharmony_ci	} else {
322762306a36Sopenharmony_ci		memcpy(ivptr, req->iv, GCM_AES_IV_SIZE);
322862306a36Sopenharmony_ci	}
322962306a36Sopenharmony_ci	put_unaligned_be32(0x01, &ivptr[12]);
323062306a36Sopenharmony_ci	ulptx = (struct ulptx_sgl *)(ivptr + 16);
323162306a36Sopenharmony_ci
323262306a36Sopenharmony_ci	chcr_add_aead_dst_ent(req, phys_cpl, qid);
323362306a36Sopenharmony_ci	chcr_add_aead_src_ent(req, ulptx);
323462306a36Sopenharmony_ci	atomic_inc(&adap->chcr_stats.aead_rqst);
323562306a36Sopenharmony_ci	temp = sizeof(struct cpl_rx_phys_dsgl) + dst_size + IV +
323662306a36Sopenharmony_ci		kctx_len + (reqctx->imm ? (req->assoclen + req->cryptlen) : 0);
323762306a36Sopenharmony_ci	create_wreq(a_ctx(tfm), chcr_req, &req->base, reqctx->imm, size,
323862306a36Sopenharmony_ci		    transhdr_len, temp, reqctx->verify);
323962306a36Sopenharmony_ci	reqctx->skb = skb;
324062306a36Sopenharmony_ci	return skb;
324162306a36Sopenharmony_ci
324262306a36Sopenharmony_cierr:
324362306a36Sopenharmony_ci	chcr_aead_common_exit(req);
324462306a36Sopenharmony_ci	return ERR_PTR(error);
324562306a36Sopenharmony_ci}
324662306a36Sopenharmony_ci
324762306a36Sopenharmony_ci
324862306a36Sopenharmony_ci
324962306a36Sopenharmony_cistatic int chcr_aead_cra_init(struct crypto_aead *tfm)
325062306a36Sopenharmony_ci{
325162306a36Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm));
325262306a36Sopenharmony_ci	struct aead_alg *alg = crypto_aead_alg(tfm);
325362306a36Sopenharmony_ci
325462306a36Sopenharmony_ci	aeadctx->sw_cipher = crypto_alloc_aead(alg->base.cra_name, 0,
325562306a36Sopenharmony_ci					       CRYPTO_ALG_NEED_FALLBACK |
325662306a36Sopenharmony_ci					       CRYPTO_ALG_ASYNC);
325762306a36Sopenharmony_ci	if  (IS_ERR(aeadctx->sw_cipher))
325862306a36Sopenharmony_ci		return PTR_ERR(aeadctx->sw_cipher);
325962306a36Sopenharmony_ci	crypto_aead_set_reqsize_dma(
326062306a36Sopenharmony_ci		tfm, max(sizeof(struct chcr_aead_reqctx),
326162306a36Sopenharmony_ci			 sizeof(struct aead_request) +
326262306a36Sopenharmony_ci			 crypto_aead_reqsize(aeadctx->sw_cipher)));
326362306a36Sopenharmony_ci	return chcr_device_init(a_ctx(tfm));
326462306a36Sopenharmony_ci}
326562306a36Sopenharmony_ci
326662306a36Sopenharmony_cistatic void chcr_aead_cra_exit(struct crypto_aead *tfm)
326762306a36Sopenharmony_ci{
326862306a36Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm));
326962306a36Sopenharmony_ci
327062306a36Sopenharmony_ci	crypto_free_aead(aeadctx->sw_cipher);
327162306a36Sopenharmony_ci}
327262306a36Sopenharmony_ci
327362306a36Sopenharmony_cistatic int chcr_authenc_null_setauthsize(struct crypto_aead *tfm,
327462306a36Sopenharmony_ci					unsigned int authsize)
327562306a36Sopenharmony_ci{
327662306a36Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm));
327762306a36Sopenharmony_ci
327862306a36Sopenharmony_ci	aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NOP;
327962306a36Sopenharmony_ci	aeadctx->mayverify = VERIFY_HW;
328062306a36Sopenharmony_ci	return crypto_aead_setauthsize(aeadctx->sw_cipher, authsize);
328162306a36Sopenharmony_ci}
328262306a36Sopenharmony_cistatic int chcr_authenc_setauthsize(struct crypto_aead *tfm,
328362306a36Sopenharmony_ci				    unsigned int authsize)
328462306a36Sopenharmony_ci{
328562306a36Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm));
328662306a36Sopenharmony_ci	u32 maxauth = crypto_aead_maxauthsize(tfm);
328762306a36Sopenharmony_ci
328862306a36Sopenharmony_ci	/*SHA1 authsize in ipsec is 12 instead of 10 i.e maxauthsize / 2 is not
328962306a36Sopenharmony_ci	 * true for sha1. authsize == 12 condition should be before
329062306a36Sopenharmony_ci	 * authsize == (maxauth >> 1)
329162306a36Sopenharmony_ci	 */
329262306a36Sopenharmony_ci	if (authsize == ICV_4) {
329362306a36Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL1;
329462306a36Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
329562306a36Sopenharmony_ci	} else if (authsize == ICV_6) {
329662306a36Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL2;
329762306a36Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
329862306a36Sopenharmony_ci	} else if (authsize == ICV_10) {
329962306a36Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_TRUNC_RFC4366;
330062306a36Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
330162306a36Sopenharmony_ci	} else if (authsize == ICV_12) {
330262306a36Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_IPSEC_96BIT;
330362306a36Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
330462306a36Sopenharmony_ci	} else if (authsize == ICV_14) {
330562306a36Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL3;
330662306a36Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
330762306a36Sopenharmony_ci	} else if (authsize == (maxauth >> 1)) {
330862306a36Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_DIV2;
330962306a36Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
331062306a36Sopenharmony_ci	} else if (authsize == maxauth) {
331162306a36Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC;
331262306a36Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
331362306a36Sopenharmony_ci	} else {
331462306a36Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC;
331562306a36Sopenharmony_ci		aeadctx->mayverify = VERIFY_SW;
331662306a36Sopenharmony_ci	}
331762306a36Sopenharmony_ci	return crypto_aead_setauthsize(aeadctx->sw_cipher, authsize);
331862306a36Sopenharmony_ci}
331962306a36Sopenharmony_ci
332062306a36Sopenharmony_ci
332162306a36Sopenharmony_cistatic int chcr_gcm_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
332262306a36Sopenharmony_ci{
332362306a36Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm));
332462306a36Sopenharmony_ci
332562306a36Sopenharmony_ci	switch (authsize) {
332662306a36Sopenharmony_ci	case ICV_4:
332762306a36Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL1;
332862306a36Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
332962306a36Sopenharmony_ci		break;
333062306a36Sopenharmony_ci	case ICV_8:
333162306a36Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_DIV2;
333262306a36Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
333362306a36Sopenharmony_ci		break;
333462306a36Sopenharmony_ci	case ICV_12:
333562306a36Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_IPSEC_96BIT;
333662306a36Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
333762306a36Sopenharmony_ci		break;
333862306a36Sopenharmony_ci	case ICV_14:
333962306a36Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL3;
334062306a36Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
334162306a36Sopenharmony_ci		break;
334262306a36Sopenharmony_ci	case ICV_16:
334362306a36Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC;
334462306a36Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
334562306a36Sopenharmony_ci		break;
334662306a36Sopenharmony_ci	case ICV_13:
334762306a36Sopenharmony_ci	case ICV_15:
334862306a36Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC;
334962306a36Sopenharmony_ci		aeadctx->mayverify = VERIFY_SW;
335062306a36Sopenharmony_ci		break;
335162306a36Sopenharmony_ci	default:
335262306a36Sopenharmony_ci		return -EINVAL;
335362306a36Sopenharmony_ci	}
335462306a36Sopenharmony_ci	return crypto_aead_setauthsize(aeadctx->sw_cipher, authsize);
335562306a36Sopenharmony_ci}
335662306a36Sopenharmony_ci
335762306a36Sopenharmony_cistatic int chcr_4106_4309_setauthsize(struct crypto_aead *tfm,
335862306a36Sopenharmony_ci					  unsigned int authsize)
335962306a36Sopenharmony_ci{
336062306a36Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm));
336162306a36Sopenharmony_ci
336262306a36Sopenharmony_ci	switch (authsize) {
336362306a36Sopenharmony_ci	case ICV_8:
336462306a36Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_DIV2;
336562306a36Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
336662306a36Sopenharmony_ci		break;
336762306a36Sopenharmony_ci	case ICV_12:
336862306a36Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_IPSEC_96BIT;
336962306a36Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
337062306a36Sopenharmony_ci		break;
337162306a36Sopenharmony_ci	case ICV_16:
337262306a36Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC;
337362306a36Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
337462306a36Sopenharmony_ci		break;
337562306a36Sopenharmony_ci	default:
337662306a36Sopenharmony_ci		return -EINVAL;
337762306a36Sopenharmony_ci	}
337862306a36Sopenharmony_ci	return crypto_aead_setauthsize(aeadctx->sw_cipher, authsize);
337962306a36Sopenharmony_ci}
338062306a36Sopenharmony_ci
338162306a36Sopenharmony_cistatic int chcr_ccm_setauthsize(struct crypto_aead *tfm,
338262306a36Sopenharmony_ci				unsigned int authsize)
338362306a36Sopenharmony_ci{
338462306a36Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm));
338562306a36Sopenharmony_ci
338662306a36Sopenharmony_ci	switch (authsize) {
338762306a36Sopenharmony_ci	case ICV_4:
338862306a36Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL1;
338962306a36Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
339062306a36Sopenharmony_ci		break;
339162306a36Sopenharmony_ci	case ICV_6:
339262306a36Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL2;
339362306a36Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
339462306a36Sopenharmony_ci		break;
339562306a36Sopenharmony_ci	case ICV_8:
339662306a36Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_DIV2;
339762306a36Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
339862306a36Sopenharmony_ci		break;
339962306a36Sopenharmony_ci	case ICV_10:
340062306a36Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_TRUNC_RFC4366;
340162306a36Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
340262306a36Sopenharmony_ci		break;
340362306a36Sopenharmony_ci	case ICV_12:
340462306a36Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_IPSEC_96BIT;
340562306a36Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
340662306a36Sopenharmony_ci		break;
340762306a36Sopenharmony_ci	case ICV_14:
340862306a36Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL3;
340962306a36Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
341062306a36Sopenharmony_ci		break;
341162306a36Sopenharmony_ci	case ICV_16:
341262306a36Sopenharmony_ci		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC;
341362306a36Sopenharmony_ci		aeadctx->mayverify = VERIFY_HW;
341462306a36Sopenharmony_ci		break;
341562306a36Sopenharmony_ci	default:
341662306a36Sopenharmony_ci		return -EINVAL;
341762306a36Sopenharmony_ci	}
341862306a36Sopenharmony_ci	return crypto_aead_setauthsize(aeadctx->sw_cipher, authsize);
341962306a36Sopenharmony_ci}
342062306a36Sopenharmony_ci
342162306a36Sopenharmony_cistatic int chcr_ccm_common_setkey(struct crypto_aead *aead,
342262306a36Sopenharmony_ci				const u8 *key,
342362306a36Sopenharmony_ci				unsigned int keylen)
342462306a36Sopenharmony_ci{
342562306a36Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(aead));
342662306a36Sopenharmony_ci	unsigned char ck_size, mk_size;
342762306a36Sopenharmony_ci	int key_ctx_size = 0;
342862306a36Sopenharmony_ci
342962306a36Sopenharmony_ci	key_ctx_size = sizeof(struct _key_ctx) + roundup(keylen, 16) * 2;
343062306a36Sopenharmony_ci	if (keylen == AES_KEYSIZE_128) {
343162306a36Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128;
343262306a36Sopenharmony_ci		mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_128;
343362306a36Sopenharmony_ci	} else if (keylen == AES_KEYSIZE_192) {
343462306a36Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_192;
343562306a36Sopenharmony_ci		mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_192;
343662306a36Sopenharmony_ci	} else if (keylen == AES_KEYSIZE_256) {
343762306a36Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256;
343862306a36Sopenharmony_ci		mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_256;
343962306a36Sopenharmony_ci	} else {
344062306a36Sopenharmony_ci		aeadctx->enckey_len = 0;
344162306a36Sopenharmony_ci		return	-EINVAL;
344262306a36Sopenharmony_ci	}
344362306a36Sopenharmony_ci	aeadctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, mk_size, 0, 0,
344462306a36Sopenharmony_ci						key_ctx_size >> 4);
344562306a36Sopenharmony_ci	memcpy(aeadctx->key, key, keylen);
344662306a36Sopenharmony_ci	aeadctx->enckey_len = keylen;
344762306a36Sopenharmony_ci
344862306a36Sopenharmony_ci	return 0;
344962306a36Sopenharmony_ci}
345062306a36Sopenharmony_ci
345162306a36Sopenharmony_cistatic int chcr_aead_ccm_setkey(struct crypto_aead *aead,
345262306a36Sopenharmony_ci				const u8 *key,
345362306a36Sopenharmony_ci				unsigned int keylen)
345462306a36Sopenharmony_ci{
345562306a36Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(aead));
345662306a36Sopenharmony_ci	int error;
345762306a36Sopenharmony_ci
345862306a36Sopenharmony_ci	crypto_aead_clear_flags(aeadctx->sw_cipher, CRYPTO_TFM_REQ_MASK);
345962306a36Sopenharmony_ci	crypto_aead_set_flags(aeadctx->sw_cipher, crypto_aead_get_flags(aead) &
346062306a36Sopenharmony_ci			      CRYPTO_TFM_REQ_MASK);
346162306a36Sopenharmony_ci	error = crypto_aead_setkey(aeadctx->sw_cipher, key, keylen);
346262306a36Sopenharmony_ci	if (error)
346362306a36Sopenharmony_ci		return error;
346462306a36Sopenharmony_ci	return chcr_ccm_common_setkey(aead, key, keylen);
346562306a36Sopenharmony_ci}
346662306a36Sopenharmony_ci
346762306a36Sopenharmony_cistatic int chcr_aead_rfc4309_setkey(struct crypto_aead *aead, const u8 *key,
346862306a36Sopenharmony_ci				    unsigned int keylen)
346962306a36Sopenharmony_ci{
347062306a36Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(aead));
347162306a36Sopenharmony_ci	int error;
347262306a36Sopenharmony_ci
347362306a36Sopenharmony_ci	if (keylen < 3) {
347462306a36Sopenharmony_ci		aeadctx->enckey_len = 0;
347562306a36Sopenharmony_ci		return	-EINVAL;
347662306a36Sopenharmony_ci	}
347762306a36Sopenharmony_ci	crypto_aead_clear_flags(aeadctx->sw_cipher, CRYPTO_TFM_REQ_MASK);
347862306a36Sopenharmony_ci	crypto_aead_set_flags(aeadctx->sw_cipher, crypto_aead_get_flags(aead) &
347962306a36Sopenharmony_ci			      CRYPTO_TFM_REQ_MASK);
348062306a36Sopenharmony_ci	error = crypto_aead_setkey(aeadctx->sw_cipher, key, keylen);
348162306a36Sopenharmony_ci	if (error)
348262306a36Sopenharmony_ci		return error;
348362306a36Sopenharmony_ci	keylen -= 3;
348462306a36Sopenharmony_ci	memcpy(aeadctx->salt, key + keylen, 3);
348562306a36Sopenharmony_ci	return chcr_ccm_common_setkey(aead, key, keylen);
348662306a36Sopenharmony_ci}
348762306a36Sopenharmony_ci
348862306a36Sopenharmony_cistatic int chcr_gcm_setkey(struct crypto_aead *aead, const u8 *key,
348962306a36Sopenharmony_ci			   unsigned int keylen)
349062306a36Sopenharmony_ci{
349162306a36Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(aead));
349262306a36Sopenharmony_ci	struct chcr_gcm_ctx *gctx = GCM_CTX(aeadctx);
349362306a36Sopenharmony_ci	unsigned int ck_size;
349462306a36Sopenharmony_ci	int ret = 0, key_ctx_size = 0;
349562306a36Sopenharmony_ci	struct crypto_aes_ctx aes;
349662306a36Sopenharmony_ci
349762306a36Sopenharmony_ci	aeadctx->enckey_len = 0;
349862306a36Sopenharmony_ci	crypto_aead_clear_flags(aeadctx->sw_cipher, CRYPTO_TFM_REQ_MASK);
349962306a36Sopenharmony_ci	crypto_aead_set_flags(aeadctx->sw_cipher, crypto_aead_get_flags(aead)
350062306a36Sopenharmony_ci			      & CRYPTO_TFM_REQ_MASK);
350162306a36Sopenharmony_ci	ret = crypto_aead_setkey(aeadctx->sw_cipher, key, keylen);
350262306a36Sopenharmony_ci	if (ret)
350362306a36Sopenharmony_ci		goto out;
350462306a36Sopenharmony_ci
350562306a36Sopenharmony_ci	if (get_aead_subtype(aead) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106 &&
350662306a36Sopenharmony_ci	    keylen > 3) {
350762306a36Sopenharmony_ci		keylen -= 4;  /* nonce/salt is present in the last 4 bytes */
350862306a36Sopenharmony_ci		memcpy(aeadctx->salt, key + keylen, 4);
350962306a36Sopenharmony_ci	}
351062306a36Sopenharmony_ci	if (keylen == AES_KEYSIZE_128) {
351162306a36Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128;
351262306a36Sopenharmony_ci	} else if (keylen == AES_KEYSIZE_192) {
351362306a36Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_192;
351462306a36Sopenharmony_ci	} else if (keylen == AES_KEYSIZE_256) {
351562306a36Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256;
351662306a36Sopenharmony_ci	} else {
351762306a36Sopenharmony_ci		pr_err("GCM: Invalid key length %d\n", keylen);
351862306a36Sopenharmony_ci		ret = -EINVAL;
351962306a36Sopenharmony_ci		goto out;
352062306a36Sopenharmony_ci	}
352162306a36Sopenharmony_ci
352262306a36Sopenharmony_ci	memcpy(aeadctx->key, key, keylen);
352362306a36Sopenharmony_ci	aeadctx->enckey_len = keylen;
352462306a36Sopenharmony_ci	key_ctx_size = sizeof(struct _key_ctx) + roundup(keylen, 16) +
352562306a36Sopenharmony_ci		AEAD_H_SIZE;
352662306a36Sopenharmony_ci	aeadctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size,
352762306a36Sopenharmony_ci						CHCR_KEYCTX_MAC_KEY_SIZE_128,
352862306a36Sopenharmony_ci						0, 0,
352962306a36Sopenharmony_ci						key_ctx_size >> 4);
353062306a36Sopenharmony_ci	/* Calculate the H = CIPH(K, 0 repeated 16 times).
353162306a36Sopenharmony_ci	 * It will go in key context
353262306a36Sopenharmony_ci	 */
353362306a36Sopenharmony_ci	ret = aes_expandkey(&aes, key, keylen);
353462306a36Sopenharmony_ci	if (ret) {
353562306a36Sopenharmony_ci		aeadctx->enckey_len = 0;
353662306a36Sopenharmony_ci		goto out;
353762306a36Sopenharmony_ci	}
353862306a36Sopenharmony_ci	memset(gctx->ghash_h, 0, AEAD_H_SIZE);
353962306a36Sopenharmony_ci	aes_encrypt(&aes, gctx->ghash_h, gctx->ghash_h);
354062306a36Sopenharmony_ci	memzero_explicit(&aes, sizeof(aes));
354162306a36Sopenharmony_ci
354262306a36Sopenharmony_ciout:
354362306a36Sopenharmony_ci	return ret;
354462306a36Sopenharmony_ci}
354562306a36Sopenharmony_ci
354662306a36Sopenharmony_cistatic int chcr_authenc_setkey(struct crypto_aead *authenc, const u8 *key,
354762306a36Sopenharmony_ci				   unsigned int keylen)
354862306a36Sopenharmony_ci{
354962306a36Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(authenc));
355062306a36Sopenharmony_ci	struct chcr_authenc_ctx *actx = AUTHENC_CTX(aeadctx);
355162306a36Sopenharmony_ci	/* it contains auth and cipher key both*/
355262306a36Sopenharmony_ci	struct crypto_authenc_keys keys;
355362306a36Sopenharmony_ci	unsigned int bs, subtype;
355462306a36Sopenharmony_ci	unsigned int max_authsize = crypto_aead_alg(authenc)->maxauthsize;
355562306a36Sopenharmony_ci	int err = 0, i, key_ctx_len = 0;
355662306a36Sopenharmony_ci	unsigned char ck_size = 0;
355762306a36Sopenharmony_ci	unsigned char pad[CHCR_HASH_MAX_BLOCK_SIZE_128] = { 0 };
355862306a36Sopenharmony_ci	struct crypto_shash *base_hash = ERR_PTR(-EINVAL);
355962306a36Sopenharmony_ci	struct algo_param param;
356062306a36Sopenharmony_ci	int align;
356162306a36Sopenharmony_ci	u8 *o_ptr = NULL;
356262306a36Sopenharmony_ci
356362306a36Sopenharmony_ci	crypto_aead_clear_flags(aeadctx->sw_cipher, CRYPTO_TFM_REQ_MASK);
356462306a36Sopenharmony_ci	crypto_aead_set_flags(aeadctx->sw_cipher, crypto_aead_get_flags(authenc)
356562306a36Sopenharmony_ci			      & CRYPTO_TFM_REQ_MASK);
356662306a36Sopenharmony_ci	err = crypto_aead_setkey(aeadctx->sw_cipher, key, keylen);
356762306a36Sopenharmony_ci	if (err)
356862306a36Sopenharmony_ci		goto out;
356962306a36Sopenharmony_ci
357062306a36Sopenharmony_ci	if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
357162306a36Sopenharmony_ci		goto out;
357262306a36Sopenharmony_ci
357362306a36Sopenharmony_ci	if (get_alg_config(&param, max_authsize)) {
357462306a36Sopenharmony_ci		pr_err("Unsupported digest size\n");
357562306a36Sopenharmony_ci		goto out;
357662306a36Sopenharmony_ci	}
357762306a36Sopenharmony_ci	subtype = get_aead_subtype(authenc);
357862306a36Sopenharmony_ci	if (subtype == CRYPTO_ALG_SUB_TYPE_CTR_SHA ||
357962306a36Sopenharmony_ci		subtype == CRYPTO_ALG_SUB_TYPE_CTR_NULL) {
358062306a36Sopenharmony_ci		if (keys.enckeylen < CTR_RFC3686_NONCE_SIZE)
358162306a36Sopenharmony_ci			goto out;
358262306a36Sopenharmony_ci		memcpy(aeadctx->nonce, keys.enckey + (keys.enckeylen
358362306a36Sopenharmony_ci		- CTR_RFC3686_NONCE_SIZE), CTR_RFC3686_NONCE_SIZE);
358462306a36Sopenharmony_ci		keys.enckeylen -= CTR_RFC3686_NONCE_SIZE;
358562306a36Sopenharmony_ci	}
358662306a36Sopenharmony_ci	if (keys.enckeylen == AES_KEYSIZE_128) {
358762306a36Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128;
358862306a36Sopenharmony_ci	} else if (keys.enckeylen == AES_KEYSIZE_192) {
358962306a36Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_192;
359062306a36Sopenharmony_ci	} else if (keys.enckeylen == AES_KEYSIZE_256) {
359162306a36Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256;
359262306a36Sopenharmony_ci	} else {
359362306a36Sopenharmony_ci		pr_err("Unsupported cipher key\n");
359462306a36Sopenharmony_ci		goto out;
359562306a36Sopenharmony_ci	}
359662306a36Sopenharmony_ci
359762306a36Sopenharmony_ci	/* Copy only encryption key. We use authkey to generate h(ipad) and
359862306a36Sopenharmony_ci	 * h(opad) so authkey is not needed again. authkeylen size have the
359962306a36Sopenharmony_ci	 * size of the hash digest size.
360062306a36Sopenharmony_ci	 */
360162306a36Sopenharmony_ci	memcpy(aeadctx->key, keys.enckey, keys.enckeylen);
360262306a36Sopenharmony_ci	aeadctx->enckey_len = keys.enckeylen;
360362306a36Sopenharmony_ci	if (subtype == CRYPTO_ALG_SUB_TYPE_CBC_SHA ||
360462306a36Sopenharmony_ci		subtype == CRYPTO_ALG_SUB_TYPE_CBC_NULL) {
360562306a36Sopenharmony_ci
360662306a36Sopenharmony_ci		get_aes_decrypt_key(actx->dec_rrkey, aeadctx->key,
360762306a36Sopenharmony_ci			    aeadctx->enckey_len << 3);
360862306a36Sopenharmony_ci	}
360962306a36Sopenharmony_ci	base_hash  = chcr_alloc_shash(max_authsize);
361062306a36Sopenharmony_ci	if (IS_ERR(base_hash)) {
361162306a36Sopenharmony_ci		pr_err("Base driver cannot be loaded\n");
361262306a36Sopenharmony_ci		goto out;
361362306a36Sopenharmony_ci	}
361462306a36Sopenharmony_ci	{
361562306a36Sopenharmony_ci		SHASH_DESC_ON_STACK(shash, base_hash);
361662306a36Sopenharmony_ci
361762306a36Sopenharmony_ci		shash->tfm = base_hash;
361862306a36Sopenharmony_ci		bs = crypto_shash_blocksize(base_hash);
361962306a36Sopenharmony_ci		align = KEYCTX_ALIGN_PAD(max_authsize);
362062306a36Sopenharmony_ci		o_ptr =  actx->h_iopad + param.result_size + align;
362162306a36Sopenharmony_ci
362262306a36Sopenharmony_ci		if (keys.authkeylen > bs) {
362362306a36Sopenharmony_ci			err = crypto_shash_digest(shash, keys.authkey,
362462306a36Sopenharmony_ci						  keys.authkeylen,
362562306a36Sopenharmony_ci						  o_ptr);
362662306a36Sopenharmony_ci			if (err) {
362762306a36Sopenharmony_ci				pr_err("Base driver cannot be loaded\n");
362862306a36Sopenharmony_ci				goto out;
362962306a36Sopenharmony_ci			}
363062306a36Sopenharmony_ci			keys.authkeylen = max_authsize;
363162306a36Sopenharmony_ci		} else
363262306a36Sopenharmony_ci			memcpy(o_ptr, keys.authkey, keys.authkeylen);
363362306a36Sopenharmony_ci
363462306a36Sopenharmony_ci		/* Compute the ipad-digest*/
363562306a36Sopenharmony_ci		memset(pad + keys.authkeylen, 0, bs - keys.authkeylen);
363662306a36Sopenharmony_ci		memcpy(pad, o_ptr, keys.authkeylen);
363762306a36Sopenharmony_ci		for (i = 0; i < bs >> 2; i++)
363862306a36Sopenharmony_ci			*((unsigned int *)pad + i) ^= IPAD_DATA;
363962306a36Sopenharmony_ci
364062306a36Sopenharmony_ci		if (chcr_compute_partial_hash(shash, pad, actx->h_iopad,
364162306a36Sopenharmony_ci					      max_authsize))
364262306a36Sopenharmony_ci			goto out;
364362306a36Sopenharmony_ci		/* Compute the opad-digest */
364462306a36Sopenharmony_ci		memset(pad + keys.authkeylen, 0, bs - keys.authkeylen);
364562306a36Sopenharmony_ci		memcpy(pad, o_ptr, keys.authkeylen);
364662306a36Sopenharmony_ci		for (i = 0; i < bs >> 2; i++)
364762306a36Sopenharmony_ci			*((unsigned int *)pad + i) ^= OPAD_DATA;
364862306a36Sopenharmony_ci
364962306a36Sopenharmony_ci		if (chcr_compute_partial_hash(shash, pad, o_ptr, max_authsize))
365062306a36Sopenharmony_ci			goto out;
365162306a36Sopenharmony_ci
365262306a36Sopenharmony_ci		/* convert the ipad and opad digest to network order */
365362306a36Sopenharmony_ci		chcr_change_order(actx->h_iopad, param.result_size);
365462306a36Sopenharmony_ci		chcr_change_order(o_ptr, param.result_size);
365562306a36Sopenharmony_ci		key_ctx_len = sizeof(struct _key_ctx) +
365662306a36Sopenharmony_ci			roundup(keys.enckeylen, 16) +
365762306a36Sopenharmony_ci			(param.result_size + align) * 2;
365862306a36Sopenharmony_ci		aeadctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, param.mk_size,
365962306a36Sopenharmony_ci						0, 1, key_ctx_len >> 4);
366062306a36Sopenharmony_ci		actx->auth_mode = param.auth_mode;
366162306a36Sopenharmony_ci		chcr_free_shash(base_hash);
366262306a36Sopenharmony_ci
366362306a36Sopenharmony_ci		memzero_explicit(&keys, sizeof(keys));
366462306a36Sopenharmony_ci		return 0;
366562306a36Sopenharmony_ci	}
366662306a36Sopenharmony_ciout:
366762306a36Sopenharmony_ci	aeadctx->enckey_len = 0;
366862306a36Sopenharmony_ci	memzero_explicit(&keys, sizeof(keys));
366962306a36Sopenharmony_ci	if (!IS_ERR(base_hash))
367062306a36Sopenharmony_ci		chcr_free_shash(base_hash);
367162306a36Sopenharmony_ci	return -EINVAL;
367262306a36Sopenharmony_ci}
367362306a36Sopenharmony_ci
367462306a36Sopenharmony_cistatic int chcr_aead_digest_null_setkey(struct crypto_aead *authenc,
367562306a36Sopenharmony_ci					const u8 *key, unsigned int keylen)
367662306a36Sopenharmony_ci{
367762306a36Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(authenc));
367862306a36Sopenharmony_ci	struct chcr_authenc_ctx *actx = AUTHENC_CTX(aeadctx);
367962306a36Sopenharmony_ci	struct crypto_authenc_keys keys;
368062306a36Sopenharmony_ci	int err;
368162306a36Sopenharmony_ci	/* it contains auth and cipher key both*/
368262306a36Sopenharmony_ci	unsigned int subtype;
368362306a36Sopenharmony_ci	int key_ctx_len = 0;
368462306a36Sopenharmony_ci	unsigned char ck_size = 0;
368562306a36Sopenharmony_ci
368662306a36Sopenharmony_ci	crypto_aead_clear_flags(aeadctx->sw_cipher, CRYPTO_TFM_REQ_MASK);
368762306a36Sopenharmony_ci	crypto_aead_set_flags(aeadctx->sw_cipher, crypto_aead_get_flags(authenc)
368862306a36Sopenharmony_ci			      & CRYPTO_TFM_REQ_MASK);
368962306a36Sopenharmony_ci	err = crypto_aead_setkey(aeadctx->sw_cipher, key, keylen);
369062306a36Sopenharmony_ci	if (err)
369162306a36Sopenharmony_ci		goto out;
369262306a36Sopenharmony_ci
369362306a36Sopenharmony_ci	if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
369462306a36Sopenharmony_ci		goto out;
369562306a36Sopenharmony_ci
369662306a36Sopenharmony_ci	subtype = get_aead_subtype(authenc);
369762306a36Sopenharmony_ci	if (subtype == CRYPTO_ALG_SUB_TYPE_CTR_SHA ||
369862306a36Sopenharmony_ci	    subtype == CRYPTO_ALG_SUB_TYPE_CTR_NULL) {
369962306a36Sopenharmony_ci		if (keys.enckeylen < CTR_RFC3686_NONCE_SIZE)
370062306a36Sopenharmony_ci			goto out;
370162306a36Sopenharmony_ci		memcpy(aeadctx->nonce, keys.enckey + (keys.enckeylen
370262306a36Sopenharmony_ci			- CTR_RFC3686_NONCE_SIZE), CTR_RFC3686_NONCE_SIZE);
370362306a36Sopenharmony_ci		keys.enckeylen -= CTR_RFC3686_NONCE_SIZE;
370462306a36Sopenharmony_ci	}
370562306a36Sopenharmony_ci	if (keys.enckeylen == AES_KEYSIZE_128) {
370662306a36Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128;
370762306a36Sopenharmony_ci	} else if (keys.enckeylen == AES_KEYSIZE_192) {
370862306a36Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_192;
370962306a36Sopenharmony_ci	} else if (keys.enckeylen == AES_KEYSIZE_256) {
371062306a36Sopenharmony_ci		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256;
371162306a36Sopenharmony_ci	} else {
371262306a36Sopenharmony_ci		pr_err("Unsupported cipher key %d\n", keys.enckeylen);
371362306a36Sopenharmony_ci		goto out;
371462306a36Sopenharmony_ci	}
371562306a36Sopenharmony_ci	memcpy(aeadctx->key, keys.enckey, keys.enckeylen);
371662306a36Sopenharmony_ci	aeadctx->enckey_len = keys.enckeylen;
371762306a36Sopenharmony_ci	if (subtype == CRYPTO_ALG_SUB_TYPE_CBC_SHA ||
371862306a36Sopenharmony_ci	    subtype == CRYPTO_ALG_SUB_TYPE_CBC_NULL) {
371962306a36Sopenharmony_ci		get_aes_decrypt_key(actx->dec_rrkey, aeadctx->key,
372062306a36Sopenharmony_ci				aeadctx->enckey_len << 3);
372162306a36Sopenharmony_ci	}
372262306a36Sopenharmony_ci	key_ctx_len =  sizeof(struct _key_ctx) + roundup(keys.enckeylen, 16);
372362306a36Sopenharmony_ci
372462306a36Sopenharmony_ci	aeadctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, CHCR_KEYCTX_NO_KEY, 0,
372562306a36Sopenharmony_ci						0, key_ctx_len >> 4);
372662306a36Sopenharmony_ci	actx->auth_mode = CHCR_SCMD_AUTH_MODE_NOP;
372762306a36Sopenharmony_ci	memzero_explicit(&keys, sizeof(keys));
372862306a36Sopenharmony_ci	return 0;
372962306a36Sopenharmony_ciout:
373062306a36Sopenharmony_ci	aeadctx->enckey_len = 0;
373162306a36Sopenharmony_ci	memzero_explicit(&keys, sizeof(keys));
373262306a36Sopenharmony_ci	return -EINVAL;
373362306a36Sopenharmony_ci}
373462306a36Sopenharmony_ci
373562306a36Sopenharmony_cistatic int chcr_aead_op(struct aead_request *req,
373662306a36Sopenharmony_ci			int size,
373762306a36Sopenharmony_ci			create_wr_t create_wr_fn)
373862306a36Sopenharmony_ci{
373962306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
374062306a36Sopenharmony_ci	struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req);
374162306a36Sopenharmony_ci	struct chcr_context *ctx = a_ctx(tfm);
374262306a36Sopenharmony_ci	struct uld_ctx *u_ctx = ULD_CTX(ctx);
374362306a36Sopenharmony_ci	struct sk_buff *skb;
374462306a36Sopenharmony_ci	struct chcr_dev *cdev;
374562306a36Sopenharmony_ci
374662306a36Sopenharmony_ci	cdev = a_ctx(tfm)->dev;
374762306a36Sopenharmony_ci	if (!cdev) {
374862306a36Sopenharmony_ci		pr_err("%s : No crypto device.\n", __func__);
374962306a36Sopenharmony_ci		return -ENXIO;
375062306a36Sopenharmony_ci	}
375162306a36Sopenharmony_ci
375262306a36Sopenharmony_ci	if (chcr_inc_wrcount(cdev)) {
375362306a36Sopenharmony_ci	/* Detach state for CHCR means lldi or padap is freed.
375462306a36Sopenharmony_ci	 * We cannot increment fallback here.
375562306a36Sopenharmony_ci	 */
375662306a36Sopenharmony_ci		return chcr_aead_fallback(req, reqctx->op);
375762306a36Sopenharmony_ci	}
375862306a36Sopenharmony_ci
375962306a36Sopenharmony_ci	if (cxgb4_is_crypto_q_full(u_ctx->lldi.ports[0],
376062306a36Sopenharmony_ci					reqctx->txqidx) &&
376162306a36Sopenharmony_ci		(!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG))) {
376262306a36Sopenharmony_ci			chcr_dec_wrcount(cdev);
376362306a36Sopenharmony_ci			return -ENOSPC;
376462306a36Sopenharmony_ci	}
376562306a36Sopenharmony_ci
376662306a36Sopenharmony_ci	if (get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106 &&
376762306a36Sopenharmony_ci	    crypto_ipsec_check_assoclen(req->assoclen) != 0) {
376862306a36Sopenharmony_ci		pr_err("RFC4106: Invalid value of assoclen %d\n",
376962306a36Sopenharmony_ci		       req->assoclen);
377062306a36Sopenharmony_ci		return -EINVAL;
377162306a36Sopenharmony_ci	}
377262306a36Sopenharmony_ci
377362306a36Sopenharmony_ci	/* Form a WR from req */
377462306a36Sopenharmony_ci	skb = create_wr_fn(req, u_ctx->lldi.rxq_ids[reqctx->rxqidx], size);
377562306a36Sopenharmony_ci
377662306a36Sopenharmony_ci	if (IS_ERR_OR_NULL(skb)) {
377762306a36Sopenharmony_ci		chcr_dec_wrcount(cdev);
377862306a36Sopenharmony_ci		return PTR_ERR_OR_ZERO(skb);
377962306a36Sopenharmony_ci	}
378062306a36Sopenharmony_ci
378162306a36Sopenharmony_ci	skb->dev = u_ctx->lldi.ports[0];
378262306a36Sopenharmony_ci	set_wr_txq(skb, CPL_PRIORITY_DATA, reqctx->txqidx);
378362306a36Sopenharmony_ci	chcr_send_wr(skb);
378462306a36Sopenharmony_ci	return -EINPROGRESS;
378562306a36Sopenharmony_ci}
378662306a36Sopenharmony_ci
378762306a36Sopenharmony_cistatic int chcr_aead_encrypt(struct aead_request *req)
378862306a36Sopenharmony_ci{
378962306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
379062306a36Sopenharmony_ci	struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req);
379162306a36Sopenharmony_ci	struct chcr_context *ctx = a_ctx(tfm);
379262306a36Sopenharmony_ci	unsigned int cpu;
379362306a36Sopenharmony_ci
379462306a36Sopenharmony_ci	cpu = get_cpu();
379562306a36Sopenharmony_ci	reqctx->txqidx = cpu % ctx->ntxq;
379662306a36Sopenharmony_ci	reqctx->rxqidx = cpu % ctx->nrxq;
379762306a36Sopenharmony_ci	put_cpu();
379862306a36Sopenharmony_ci
379962306a36Sopenharmony_ci	reqctx->verify = VERIFY_HW;
380062306a36Sopenharmony_ci	reqctx->op = CHCR_ENCRYPT_OP;
380162306a36Sopenharmony_ci
380262306a36Sopenharmony_ci	switch (get_aead_subtype(tfm)) {
380362306a36Sopenharmony_ci	case CRYPTO_ALG_SUB_TYPE_CTR_SHA:
380462306a36Sopenharmony_ci	case CRYPTO_ALG_SUB_TYPE_CBC_SHA:
380562306a36Sopenharmony_ci	case CRYPTO_ALG_SUB_TYPE_CBC_NULL:
380662306a36Sopenharmony_ci	case CRYPTO_ALG_SUB_TYPE_CTR_NULL:
380762306a36Sopenharmony_ci		return chcr_aead_op(req, 0, create_authenc_wr);
380862306a36Sopenharmony_ci	case CRYPTO_ALG_SUB_TYPE_AEAD_CCM:
380962306a36Sopenharmony_ci	case CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309:
381062306a36Sopenharmony_ci		return chcr_aead_op(req, 0, create_aead_ccm_wr);
381162306a36Sopenharmony_ci	default:
381262306a36Sopenharmony_ci		return chcr_aead_op(req, 0, create_gcm_wr);
381362306a36Sopenharmony_ci	}
381462306a36Sopenharmony_ci}
381562306a36Sopenharmony_ci
381662306a36Sopenharmony_cistatic int chcr_aead_decrypt(struct aead_request *req)
381762306a36Sopenharmony_ci{
381862306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
381962306a36Sopenharmony_ci	struct chcr_context *ctx = a_ctx(tfm);
382062306a36Sopenharmony_ci	struct chcr_aead_ctx *aeadctx = AEAD_CTX(ctx);
382162306a36Sopenharmony_ci	struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req);
382262306a36Sopenharmony_ci	int size;
382362306a36Sopenharmony_ci	unsigned int cpu;
382462306a36Sopenharmony_ci
382562306a36Sopenharmony_ci	cpu = get_cpu();
382662306a36Sopenharmony_ci	reqctx->txqidx = cpu % ctx->ntxq;
382762306a36Sopenharmony_ci	reqctx->rxqidx = cpu % ctx->nrxq;
382862306a36Sopenharmony_ci	put_cpu();
382962306a36Sopenharmony_ci
383062306a36Sopenharmony_ci	if (aeadctx->mayverify == VERIFY_SW) {
383162306a36Sopenharmony_ci		size = crypto_aead_maxauthsize(tfm);
383262306a36Sopenharmony_ci		reqctx->verify = VERIFY_SW;
383362306a36Sopenharmony_ci	} else {
383462306a36Sopenharmony_ci		size = 0;
383562306a36Sopenharmony_ci		reqctx->verify = VERIFY_HW;
383662306a36Sopenharmony_ci	}
383762306a36Sopenharmony_ci	reqctx->op = CHCR_DECRYPT_OP;
383862306a36Sopenharmony_ci	switch (get_aead_subtype(tfm)) {
383962306a36Sopenharmony_ci	case CRYPTO_ALG_SUB_TYPE_CBC_SHA:
384062306a36Sopenharmony_ci	case CRYPTO_ALG_SUB_TYPE_CTR_SHA:
384162306a36Sopenharmony_ci	case CRYPTO_ALG_SUB_TYPE_CBC_NULL:
384262306a36Sopenharmony_ci	case CRYPTO_ALG_SUB_TYPE_CTR_NULL:
384362306a36Sopenharmony_ci		return chcr_aead_op(req, size, create_authenc_wr);
384462306a36Sopenharmony_ci	case CRYPTO_ALG_SUB_TYPE_AEAD_CCM:
384562306a36Sopenharmony_ci	case CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309:
384662306a36Sopenharmony_ci		return chcr_aead_op(req, size, create_aead_ccm_wr);
384762306a36Sopenharmony_ci	default:
384862306a36Sopenharmony_ci		return chcr_aead_op(req, size, create_gcm_wr);
384962306a36Sopenharmony_ci	}
385062306a36Sopenharmony_ci}
385162306a36Sopenharmony_ci
385262306a36Sopenharmony_cistatic struct chcr_alg_template driver_algs[] = {
385362306a36Sopenharmony_ci	/* AES-CBC */
385462306a36Sopenharmony_ci	{
385562306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_SUB_TYPE_CBC,
385662306a36Sopenharmony_ci		.is_registered = 0,
385762306a36Sopenharmony_ci		.alg.skcipher = {
385862306a36Sopenharmony_ci			.base.cra_name		= "cbc(aes)",
385962306a36Sopenharmony_ci			.base.cra_driver_name	= "cbc-aes-chcr",
386062306a36Sopenharmony_ci			.base.cra_blocksize	= AES_BLOCK_SIZE,
386162306a36Sopenharmony_ci
386262306a36Sopenharmony_ci			.init			= chcr_init_tfm,
386362306a36Sopenharmony_ci			.exit			= chcr_exit_tfm,
386462306a36Sopenharmony_ci			.min_keysize		= AES_MIN_KEY_SIZE,
386562306a36Sopenharmony_ci			.max_keysize		= AES_MAX_KEY_SIZE,
386662306a36Sopenharmony_ci			.ivsize			= AES_BLOCK_SIZE,
386762306a36Sopenharmony_ci			.setkey			= chcr_aes_cbc_setkey,
386862306a36Sopenharmony_ci			.encrypt		= chcr_aes_encrypt,
386962306a36Sopenharmony_ci			.decrypt		= chcr_aes_decrypt,
387062306a36Sopenharmony_ci			}
387162306a36Sopenharmony_ci	},
387262306a36Sopenharmony_ci	{
387362306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_SUB_TYPE_XTS,
387462306a36Sopenharmony_ci		.is_registered = 0,
387562306a36Sopenharmony_ci		.alg.skcipher = {
387662306a36Sopenharmony_ci			.base.cra_name		= "xts(aes)",
387762306a36Sopenharmony_ci			.base.cra_driver_name	= "xts-aes-chcr",
387862306a36Sopenharmony_ci			.base.cra_blocksize	= AES_BLOCK_SIZE,
387962306a36Sopenharmony_ci
388062306a36Sopenharmony_ci			.init			= chcr_init_tfm,
388162306a36Sopenharmony_ci			.exit			= chcr_exit_tfm,
388262306a36Sopenharmony_ci			.min_keysize		= 2 * AES_MIN_KEY_SIZE,
388362306a36Sopenharmony_ci			.max_keysize		= 2 * AES_MAX_KEY_SIZE,
388462306a36Sopenharmony_ci			.ivsize			= AES_BLOCK_SIZE,
388562306a36Sopenharmony_ci			.setkey			= chcr_aes_xts_setkey,
388662306a36Sopenharmony_ci			.encrypt		= chcr_aes_encrypt,
388762306a36Sopenharmony_ci			.decrypt		= chcr_aes_decrypt,
388862306a36Sopenharmony_ci			}
388962306a36Sopenharmony_ci	},
389062306a36Sopenharmony_ci	{
389162306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_SUB_TYPE_CTR,
389262306a36Sopenharmony_ci		.is_registered = 0,
389362306a36Sopenharmony_ci		.alg.skcipher = {
389462306a36Sopenharmony_ci			.base.cra_name		= "ctr(aes)",
389562306a36Sopenharmony_ci			.base.cra_driver_name	= "ctr-aes-chcr",
389662306a36Sopenharmony_ci			.base.cra_blocksize	= 1,
389762306a36Sopenharmony_ci
389862306a36Sopenharmony_ci			.init			= chcr_init_tfm,
389962306a36Sopenharmony_ci			.exit			= chcr_exit_tfm,
390062306a36Sopenharmony_ci			.min_keysize		= AES_MIN_KEY_SIZE,
390162306a36Sopenharmony_ci			.max_keysize		= AES_MAX_KEY_SIZE,
390262306a36Sopenharmony_ci			.ivsize			= AES_BLOCK_SIZE,
390362306a36Sopenharmony_ci			.setkey			= chcr_aes_ctr_setkey,
390462306a36Sopenharmony_ci			.encrypt		= chcr_aes_encrypt,
390562306a36Sopenharmony_ci			.decrypt		= chcr_aes_decrypt,
390662306a36Sopenharmony_ci		}
390762306a36Sopenharmony_ci	},
390862306a36Sopenharmony_ci	{
390962306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_SKCIPHER |
391062306a36Sopenharmony_ci			CRYPTO_ALG_SUB_TYPE_CTR_RFC3686,
391162306a36Sopenharmony_ci		.is_registered = 0,
391262306a36Sopenharmony_ci		.alg.skcipher = {
391362306a36Sopenharmony_ci			.base.cra_name		= "rfc3686(ctr(aes))",
391462306a36Sopenharmony_ci			.base.cra_driver_name	= "rfc3686-ctr-aes-chcr",
391562306a36Sopenharmony_ci			.base.cra_blocksize	= 1,
391662306a36Sopenharmony_ci
391762306a36Sopenharmony_ci			.init			= chcr_rfc3686_init,
391862306a36Sopenharmony_ci			.exit			= chcr_exit_tfm,
391962306a36Sopenharmony_ci			.min_keysize		= AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
392062306a36Sopenharmony_ci			.max_keysize		= AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
392162306a36Sopenharmony_ci			.ivsize			= CTR_RFC3686_IV_SIZE,
392262306a36Sopenharmony_ci			.setkey			= chcr_aes_rfc3686_setkey,
392362306a36Sopenharmony_ci			.encrypt		= chcr_aes_encrypt,
392462306a36Sopenharmony_ci			.decrypt		= chcr_aes_decrypt,
392562306a36Sopenharmony_ci		}
392662306a36Sopenharmony_ci	},
392762306a36Sopenharmony_ci	/* SHA */
392862306a36Sopenharmony_ci	{
392962306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AHASH,
393062306a36Sopenharmony_ci		.is_registered = 0,
393162306a36Sopenharmony_ci		.alg.hash = {
393262306a36Sopenharmony_ci			.halg.digestsize = SHA1_DIGEST_SIZE,
393362306a36Sopenharmony_ci			.halg.base = {
393462306a36Sopenharmony_ci				.cra_name = "sha1",
393562306a36Sopenharmony_ci				.cra_driver_name = "sha1-chcr",
393662306a36Sopenharmony_ci				.cra_blocksize = SHA1_BLOCK_SIZE,
393762306a36Sopenharmony_ci			}
393862306a36Sopenharmony_ci		}
393962306a36Sopenharmony_ci	},
394062306a36Sopenharmony_ci	{
394162306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AHASH,
394262306a36Sopenharmony_ci		.is_registered = 0,
394362306a36Sopenharmony_ci		.alg.hash = {
394462306a36Sopenharmony_ci			.halg.digestsize = SHA256_DIGEST_SIZE,
394562306a36Sopenharmony_ci			.halg.base = {
394662306a36Sopenharmony_ci				.cra_name = "sha256",
394762306a36Sopenharmony_ci				.cra_driver_name = "sha256-chcr",
394862306a36Sopenharmony_ci				.cra_blocksize = SHA256_BLOCK_SIZE,
394962306a36Sopenharmony_ci			}
395062306a36Sopenharmony_ci		}
395162306a36Sopenharmony_ci	},
395262306a36Sopenharmony_ci	{
395362306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AHASH,
395462306a36Sopenharmony_ci		.is_registered = 0,
395562306a36Sopenharmony_ci		.alg.hash = {
395662306a36Sopenharmony_ci			.halg.digestsize = SHA224_DIGEST_SIZE,
395762306a36Sopenharmony_ci			.halg.base = {
395862306a36Sopenharmony_ci				.cra_name = "sha224",
395962306a36Sopenharmony_ci				.cra_driver_name = "sha224-chcr",
396062306a36Sopenharmony_ci				.cra_blocksize = SHA224_BLOCK_SIZE,
396162306a36Sopenharmony_ci			}
396262306a36Sopenharmony_ci		}
396362306a36Sopenharmony_ci	},
396462306a36Sopenharmony_ci	{
396562306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AHASH,
396662306a36Sopenharmony_ci		.is_registered = 0,
396762306a36Sopenharmony_ci		.alg.hash = {
396862306a36Sopenharmony_ci			.halg.digestsize = SHA384_DIGEST_SIZE,
396962306a36Sopenharmony_ci			.halg.base = {
397062306a36Sopenharmony_ci				.cra_name = "sha384",
397162306a36Sopenharmony_ci				.cra_driver_name = "sha384-chcr",
397262306a36Sopenharmony_ci				.cra_blocksize = SHA384_BLOCK_SIZE,
397362306a36Sopenharmony_ci			}
397462306a36Sopenharmony_ci		}
397562306a36Sopenharmony_ci	},
397662306a36Sopenharmony_ci	{
397762306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AHASH,
397862306a36Sopenharmony_ci		.is_registered = 0,
397962306a36Sopenharmony_ci		.alg.hash = {
398062306a36Sopenharmony_ci			.halg.digestsize = SHA512_DIGEST_SIZE,
398162306a36Sopenharmony_ci			.halg.base = {
398262306a36Sopenharmony_ci				.cra_name = "sha512",
398362306a36Sopenharmony_ci				.cra_driver_name = "sha512-chcr",
398462306a36Sopenharmony_ci				.cra_blocksize = SHA512_BLOCK_SIZE,
398562306a36Sopenharmony_ci			}
398662306a36Sopenharmony_ci		}
398762306a36Sopenharmony_ci	},
398862306a36Sopenharmony_ci	/* HMAC */
398962306a36Sopenharmony_ci	{
399062306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_HMAC,
399162306a36Sopenharmony_ci		.is_registered = 0,
399262306a36Sopenharmony_ci		.alg.hash = {
399362306a36Sopenharmony_ci			.halg.digestsize = SHA1_DIGEST_SIZE,
399462306a36Sopenharmony_ci			.halg.base = {
399562306a36Sopenharmony_ci				.cra_name = "hmac(sha1)",
399662306a36Sopenharmony_ci				.cra_driver_name = "hmac-sha1-chcr",
399762306a36Sopenharmony_ci				.cra_blocksize = SHA1_BLOCK_SIZE,
399862306a36Sopenharmony_ci			}
399962306a36Sopenharmony_ci		}
400062306a36Sopenharmony_ci	},
400162306a36Sopenharmony_ci	{
400262306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_HMAC,
400362306a36Sopenharmony_ci		.is_registered = 0,
400462306a36Sopenharmony_ci		.alg.hash = {
400562306a36Sopenharmony_ci			.halg.digestsize = SHA224_DIGEST_SIZE,
400662306a36Sopenharmony_ci			.halg.base = {
400762306a36Sopenharmony_ci				.cra_name = "hmac(sha224)",
400862306a36Sopenharmony_ci				.cra_driver_name = "hmac-sha224-chcr",
400962306a36Sopenharmony_ci				.cra_blocksize = SHA224_BLOCK_SIZE,
401062306a36Sopenharmony_ci			}
401162306a36Sopenharmony_ci		}
401262306a36Sopenharmony_ci	},
401362306a36Sopenharmony_ci	{
401462306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_HMAC,
401562306a36Sopenharmony_ci		.is_registered = 0,
401662306a36Sopenharmony_ci		.alg.hash = {
401762306a36Sopenharmony_ci			.halg.digestsize = SHA256_DIGEST_SIZE,
401862306a36Sopenharmony_ci			.halg.base = {
401962306a36Sopenharmony_ci				.cra_name = "hmac(sha256)",
402062306a36Sopenharmony_ci				.cra_driver_name = "hmac-sha256-chcr",
402162306a36Sopenharmony_ci				.cra_blocksize = SHA256_BLOCK_SIZE,
402262306a36Sopenharmony_ci			}
402362306a36Sopenharmony_ci		}
402462306a36Sopenharmony_ci	},
402562306a36Sopenharmony_ci	{
402662306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_HMAC,
402762306a36Sopenharmony_ci		.is_registered = 0,
402862306a36Sopenharmony_ci		.alg.hash = {
402962306a36Sopenharmony_ci			.halg.digestsize = SHA384_DIGEST_SIZE,
403062306a36Sopenharmony_ci			.halg.base = {
403162306a36Sopenharmony_ci				.cra_name = "hmac(sha384)",
403262306a36Sopenharmony_ci				.cra_driver_name = "hmac-sha384-chcr",
403362306a36Sopenharmony_ci				.cra_blocksize = SHA384_BLOCK_SIZE,
403462306a36Sopenharmony_ci			}
403562306a36Sopenharmony_ci		}
403662306a36Sopenharmony_ci	},
403762306a36Sopenharmony_ci	{
403862306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_HMAC,
403962306a36Sopenharmony_ci		.is_registered = 0,
404062306a36Sopenharmony_ci		.alg.hash = {
404162306a36Sopenharmony_ci			.halg.digestsize = SHA512_DIGEST_SIZE,
404262306a36Sopenharmony_ci			.halg.base = {
404362306a36Sopenharmony_ci				.cra_name = "hmac(sha512)",
404462306a36Sopenharmony_ci				.cra_driver_name = "hmac-sha512-chcr",
404562306a36Sopenharmony_ci				.cra_blocksize = SHA512_BLOCK_SIZE,
404662306a36Sopenharmony_ci			}
404762306a36Sopenharmony_ci		}
404862306a36Sopenharmony_ci	},
404962306a36Sopenharmony_ci	/* Add AEAD Algorithms */
405062306a36Sopenharmony_ci	{
405162306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_AEAD_GCM,
405262306a36Sopenharmony_ci		.is_registered = 0,
405362306a36Sopenharmony_ci		.alg.aead = {
405462306a36Sopenharmony_ci			.base = {
405562306a36Sopenharmony_ci				.cra_name = "gcm(aes)",
405662306a36Sopenharmony_ci				.cra_driver_name = "gcm-aes-chcr",
405762306a36Sopenharmony_ci				.cra_blocksize	= 1,
405862306a36Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
405962306a36Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
406062306a36Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
406162306a36Sopenharmony_ci						sizeof(struct chcr_gcm_ctx),
406262306a36Sopenharmony_ci			},
406362306a36Sopenharmony_ci			.ivsize = GCM_AES_IV_SIZE,
406462306a36Sopenharmony_ci			.maxauthsize = GHASH_DIGEST_SIZE,
406562306a36Sopenharmony_ci			.setkey = chcr_gcm_setkey,
406662306a36Sopenharmony_ci			.setauthsize = chcr_gcm_setauthsize,
406762306a36Sopenharmony_ci		}
406862306a36Sopenharmony_ci	},
406962306a36Sopenharmony_ci	{
407062306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106,
407162306a36Sopenharmony_ci		.is_registered = 0,
407262306a36Sopenharmony_ci		.alg.aead = {
407362306a36Sopenharmony_ci			.base = {
407462306a36Sopenharmony_ci				.cra_name = "rfc4106(gcm(aes))",
407562306a36Sopenharmony_ci				.cra_driver_name = "rfc4106-gcm-aes-chcr",
407662306a36Sopenharmony_ci				.cra_blocksize	 = 1,
407762306a36Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY + 1,
407862306a36Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
407962306a36Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
408062306a36Sopenharmony_ci						sizeof(struct chcr_gcm_ctx),
408162306a36Sopenharmony_ci
408262306a36Sopenharmony_ci			},
408362306a36Sopenharmony_ci			.ivsize = GCM_RFC4106_IV_SIZE,
408462306a36Sopenharmony_ci			.maxauthsize	= GHASH_DIGEST_SIZE,
408562306a36Sopenharmony_ci			.setkey = chcr_gcm_setkey,
408662306a36Sopenharmony_ci			.setauthsize	= chcr_4106_4309_setauthsize,
408762306a36Sopenharmony_ci		}
408862306a36Sopenharmony_ci	},
408962306a36Sopenharmony_ci	{
409062306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_AEAD_CCM,
409162306a36Sopenharmony_ci		.is_registered = 0,
409262306a36Sopenharmony_ci		.alg.aead = {
409362306a36Sopenharmony_ci			.base = {
409462306a36Sopenharmony_ci				.cra_name = "ccm(aes)",
409562306a36Sopenharmony_ci				.cra_driver_name = "ccm-aes-chcr",
409662306a36Sopenharmony_ci				.cra_blocksize	 = 1,
409762306a36Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
409862306a36Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
409962306a36Sopenharmony_ci						sizeof(struct chcr_aead_ctx),
410062306a36Sopenharmony_ci
410162306a36Sopenharmony_ci			},
410262306a36Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
410362306a36Sopenharmony_ci			.maxauthsize	= GHASH_DIGEST_SIZE,
410462306a36Sopenharmony_ci			.setkey = chcr_aead_ccm_setkey,
410562306a36Sopenharmony_ci			.setauthsize	= chcr_ccm_setauthsize,
410662306a36Sopenharmony_ci		}
410762306a36Sopenharmony_ci	},
410862306a36Sopenharmony_ci	{
410962306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309,
411062306a36Sopenharmony_ci		.is_registered = 0,
411162306a36Sopenharmony_ci		.alg.aead = {
411262306a36Sopenharmony_ci			.base = {
411362306a36Sopenharmony_ci				.cra_name = "rfc4309(ccm(aes))",
411462306a36Sopenharmony_ci				.cra_driver_name = "rfc4309-ccm-aes-chcr",
411562306a36Sopenharmony_ci				.cra_blocksize	 = 1,
411662306a36Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY + 1,
411762306a36Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
411862306a36Sopenharmony_ci						sizeof(struct chcr_aead_ctx),
411962306a36Sopenharmony_ci
412062306a36Sopenharmony_ci			},
412162306a36Sopenharmony_ci			.ivsize = 8,
412262306a36Sopenharmony_ci			.maxauthsize	= GHASH_DIGEST_SIZE,
412362306a36Sopenharmony_ci			.setkey = chcr_aead_rfc4309_setkey,
412462306a36Sopenharmony_ci			.setauthsize = chcr_4106_4309_setauthsize,
412562306a36Sopenharmony_ci		}
412662306a36Sopenharmony_ci	},
412762306a36Sopenharmony_ci	{
412862306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CBC_SHA,
412962306a36Sopenharmony_ci		.is_registered = 0,
413062306a36Sopenharmony_ci		.alg.aead = {
413162306a36Sopenharmony_ci			.base = {
413262306a36Sopenharmony_ci				.cra_name = "authenc(hmac(sha1),cbc(aes))",
413362306a36Sopenharmony_ci				.cra_driver_name =
413462306a36Sopenharmony_ci					"authenc-hmac-sha1-cbc-aes-chcr",
413562306a36Sopenharmony_ci				.cra_blocksize	 = AES_BLOCK_SIZE,
413662306a36Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
413762306a36Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
413862306a36Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
413962306a36Sopenharmony_ci						sizeof(struct chcr_authenc_ctx),
414062306a36Sopenharmony_ci
414162306a36Sopenharmony_ci			},
414262306a36Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
414362306a36Sopenharmony_ci			.maxauthsize = SHA1_DIGEST_SIZE,
414462306a36Sopenharmony_ci			.setkey = chcr_authenc_setkey,
414562306a36Sopenharmony_ci			.setauthsize = chcr_authenc_setauthsize,
414662306a36Sopenharmony_ci		}
414762306a36Sopenharmony_ci	},
414862306a36Sopenharmony_ci	{
414962306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CBC_SHA,
415062306a36Sopenharmony_ci		.is_registered = 0,
415162306a36Sopenharmony_ci		.alg.aead = {
415262306a36Sopenharmony_ci			.base = {
415362306a36Sopenharmony_ci
415462306a36Sopenharmony_ci				.cra_name = "authenc(hmac(sha256),cbc(aes))",
415562306a36Sopenharmony_ci				.cra_driver_name =
415662306a36Sopenharmony_ci					"authenc-hmac-sha256-cbc-aes-chcr",
415762306a36Sopenharmony_ci				.cra_blocksize	 = AES_BLOCK_SIZE,
415862306a36Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
415962306a36Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
416062306a36Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
416162306a36Sopenharmony_ci						sizeof(struct chcr_authenc_ctx),
416262306a36Sopenharmony_ci
416362306a36Sopenharmony_ci			},
416462306a36Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
416562306a36Sopenharmony_ci			.maxauthsize	= SHA256_DIGEST_SIZE,
416662306a36Sopenharmony_ci			.setkey = chcr_authenc_setkey,
416762306a36Sopenharmony_ci			.setauthsize = chcr_authenc_setauthsize,
416862306a36Sopenharmony_ci		}
416962306a36Sopenharmony_ci	},
417062306a36Sopenharmony_ci	{
417162306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CBC_SHA,
417262306a36Sopenharmony_ci		.is_registered = 0,
417362306a36Sopenharmony_ci		.alg.aead = {
417462306a36Sopenharmony_ci			.base = {
417562306a36Sopenharmony_ci				.cra_name = "authenc(hmac(sha224),cbc(aes))",
417662306a36Sopenharmony_ci				.cra_driver_name =
417762306a36Sopenharmony_ci					"authenc-hmac-sha224-cbc-aes-chcr",
417862306a36Sopenharmony_ci				.cra_blocksize	 = AES_BLOCK_SIZE,
417962306a36Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
418062306a36Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
418162306a36Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
418262306a36Sopenharmony_ci						sizeof(struct chcr_authenc_ctx),
418362306a36Sopenharmony_ci			},
418462306a36Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
418562306a36Sopenharmony_ci			.maxauthsize = SHA224_DIGEST_SIZE,
418662306a36Sopenharmony_ci			.setkey = chcr_authenc_setkey,
418762306a36Sopenharmony_ci			.setauthsize = chcr_authenc_setauthsize,
418862306a36Sopenharmony_ci		}
418962306a36Sopenharmony_ci	},
419062306a36Sopenharmony_ci	{
419162306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CBC_SHA,
419262306a36Sopenharmony_ci		.is_registered = 0,
419362306a36Sopenharmony_ci		.alg.aead = {
419462306a36Sopenharmony_ci			.base = {
419562306a36Sopenharmony_ci				.cra_name = "authenc(hmac(sha384),cbc(aes))",
419662306a36Sopenharmony_ci				.cra_driver_name =
419762306a36Sopenharmony_ci					"authenc-hmac-sha384-cbc-aes-chcr",
419862306a36Sopenharmony_ci				.cra_blocksize	 = AES_BLOCK_SIZE,
419962306a36Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
420062306a36Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
420162306a36Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
420262306a36Sopenharmony_ci						sizeof(struct chcr_authenc_ctx),
420362306a36Sopenharmony_ci
420462306a36Sopenharmony_ci			},
420562306a36Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
420662306a36Sopenharmony_ci			.maxauthsize = SHA384_DIGEST_SIZE,
420762306a36Sopenharmony_ci			.setkey = chcr_authenc_setkey,
420862306a36Sopenharmony_ci			.setauthsize = chcr_authenc_setauthsize,
420962306a36Sopenharmony_ci		}
421062306a36Sopenharmony_ci	},
421162306a36Sopenharmony_ci	{
421262306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CBC_SHA,
421362306a36Sopenharmony_ci		.is_registered = 0,
421462306a36Sopenharmony_ci		.alg.aead = {
421562306a36Sopenharmony_ci			.base = {
421662306a36Sopenharmony_ci				.cra_name = "authenc(hmac(sha512),cbc(aes))",
421762306a36Sopenharmony_ci				.cra_driver_name =
421862306a36Sopenharmony_ci					"authenc-hmac-sha512-cbc-aes-chcr",
421962306a36Sopenharmony_ci				.cra_blocksize	 = AES_BLOCK_SIZE,
422062306a36Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
422162306a36Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
422262306a36Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
422362306a36Sopenharmony_ci						sizeof(struct chcr_authenc_ctx),
422462306a36Sopenharmony_ci
422562306a36Sopenharmony_ci			},
422662306a36Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
422762306a36Sopenharmony_ci			.maxauthsize = SHA512_DIGEST_SIZE,
422862306a36Sopenharmony_ci			.setkey = chcr_authenc_setkey,
422962306a36Sopenharmony_ci			.setauthsize = chcr_authenc_setauthsize,
423062306a36Sopenharmony_ci		}
423162306a36Sopenharmony_ci	},
423262306a36Sopenharmony_ci	{
423362306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CBC_NULL,
423462306a36Sopenharmony_ci		.is_registered = 0,
423562306a36Sopenharmony_ci		.alg.aead = {
423662306a36Sopenharmony_ci			.base = {
423762306a36Sopenharmony_ci				.cra_name = "authenc(digest_null,cbc(aes))",
423862306a36Sopenharmony_ci				.cra_driver_name =
423962306a36Sopenharmony_ci					"authenc-digest_null-cbc-aes-chcr",
424062306a36Sopenharmony_ci				.cra_blocksize	 = AES_BLOCK_SIZE,
424162306a36Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
424262306a36Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
424362306a36Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
424462306a36Sopenharmony_ci						sizeof(struct chcr_authenc_ctx),
424562306a36Sopenharmony_ci
424662306a36Sopenharmony_ci			},
424762306a36Sopenharmony_ci			.ivsize  = AES_BLOCK_SIZE,
424862306a36Sopenharmony_ci			.maxauthsize = 0,
424962306a36Sopenharmony_ci			.setkey  = chcr_aead_digest_null_setkey,
425062306a36Sopenharmony_ci			.setauthsize = chcr_authenc_null_setauthsize,
425162306a36Sopenharmony_ci		}
425262306a36Sopenharmony_ci	},
425362306a36Sopenharmony_ci	{
425462306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CTR_SHA,
425562306a36Sopenharmony_ci		.is_registered = 0,
425662306a36Sopenharmony_ci		.alg.aead = {
425762306a36Sopenharmony_ci			.base = {
425862306a36Sopenharmony_ci				.cra_name = "authenc(hmac(sha1),rfc3686(ctr(aes)))",
425962306a36Sopenharmony_ci				.cra_driver_name =
426062306a36Sopenharmony_ci				"authenc-hmac-sha1-rfc3686-ctr-aes-chcr",
426162306a36Sopenharmony_ci				.cra_blocksize	 = 1,
426262306a36Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
426362306a36Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
426462306a36Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
426562306a36Sopenharmony_ci						sizeof(struct chcr_authenc_ctx),
426662306a36Sopenharmony_ci
426762306a36Sopenharmony_ci			},
426862306a36Sopenharmony_ci			.ivsize = CTR_RFC3686_IV_SIZE,
426962306a36Sopenharmony_ci			.maxauthsize = SHA1_DIGEST_SIZE,
427062306a36Sopenharmony_ci			.setkey = chcr_authenc_setkey,
427162306a36Sopenharmony_ci			.setauthsize = chcr_authenc_setauthsize,
427262306a36Sopenharmony_ci		}
427362306a36Sopenharmony_ci	},
427462306a36Sopenharmony_ci	{
427562306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CTR_SHA,
427662306a36Sopenharmony_ci		.is_registered = 0,
427762306a36Sopenharmony_ci		.alg.aead = {
427862306a36Sopenharmony_ci			.base = {
427962306a36Sopenharmony_ci
428062306a36Sopenharmony_ci				.cra_name = "authenc(hmac(sha256),rfc3686(ctr(aes)))",
428162306a36Sopenharmony_ci				.cra_driver_name =
428262306a36Sopenharmony_ci				"authenc-hmac-sha256-rfc3686-ctr-aes-chcr",
428362306a36Sopenharmony_ci				.cra_blocksize	 = 1,
428462306a36Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
428562306a36Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
428662306a36Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
428762306a36Sopenharmony_ci						sizeof(struct chcr_authenc_ctx),
428862306a36Sopenharmony_ci
428962306a36Sopenharmony_ci			},
429062306a36Sopenharmony_ci			.ivsize = CTR_RFC3686_IV_SIZE,
429162306a36Sopenharmony_ci			.maxauthsize	= SHA256_DIGEST_SIZE,
429262306a36Sopenharmony_ci			.setkey = chcr_authenc_setkey,
429362306a36Sopenharmony_ci			.setauthsize = chcr_authenc_setauthsize,
429462306a36Sopenharmony_ci		}
429562306a36Sopenharmony_ci	},
429662306a36Sopenharmony_ci	{
429762306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CTR_SHA,
429862306a36Sopenharmony_ci		.is_registered = 0,
429962306a36Sopenharmony_ci		.alg.aead = {
430062306a36Sopenharmony_ci			.base = {
430162306a36Sopenharmony_ci				.cra_name = "authenc(hmac(sha224),rfc3686(ctr(aes)))",
430262306a36Sopenharmony_ci				.cra_driver_name =
430362306a36Sopenharmony_ci				"authenc-hmac-sha224-rfc3686-ctr-aes-chcr",
430462306a36Sopenharmony_ci				.cra_blocksize	 = 1,
430562306a36Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
430662306a36Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
430762306a36Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
430862306a36Sopenharmony_ci						sizeof(struct chcr_authenc_ctx),
430962306a36Sopenharmony_ci			},
431062306a36Sopenharmony_ci			.ivsize = CTR_RFC3686_IV_SIZE,
431162306a36Sopenharmony_ci			.maxauthsize = SHA224_DIGEST_SIZE,
431262306a36Sopenharmony_ci			.setkey = chcr_authenc_setkey,
431362306a36Sopenharmony_ci			.setauthsize = chcr_authenc_setauthsize,
431462306a36Sopenharmony_ci		}
431562306a36Sopenharmony_ci	},
431662306a36Sopenharmony_ci	{
431762306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CTR_SHA,
431862306a36Sopenharmony_ci		.is_registered = 0,
431962306a36Sopenharmony_ci		.alg.aead = {
432062306a36Sopenharmony_ci			.base = {
432162306a36Sopenharmony_ci				.cra_name = "authenc(hmac(sha384),rfc3686(ctr(aes)))",
432262306a36Sopenharmony_ci				.cra_driver_name =
432362306a36Sopenharmony_ci				"authenc-hmac-sha384-rfc3686-ctr-aes-chcr",
432462306a36Sopenharmony_ci				.cra_blocksize	 = 1,
432562306a36Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
432662306a36Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
432762306a36Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
432862306a36Sopenharmony_ci						sizeof(struct chcr_authenc_ctx),
432962306a36Sopenharmony_ci
433062306a36Sopenharmony_ci			},
433162306a36Sopenharmony_ci			.ivsize = CTR_RFC3686_IV_SIZE,
433262306a36Sopenharmony_ci			.maxauthsize = SHA384_DIGEST_SIZE,
433362306a36Sopenharmony_ci			.setkey = chcr_authenc_setkey,
433462306a36Sopenharmony_ci			.setauthsize = chcr_authenc_setauthsize,
433562306a36Sopenharmony_ci		}
433662306a36Sopenharmony_ci	},
433762306a36Sopenharmony_ci	{
433862306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CTR_SHA,
433962306a36Sopenharmony_ci		.is_registered = 0,
434062306a36Sopenharmony_ci		.alg.aead = {
434162306a36Sopenharmony_ci			.base = {
434262306a36Sopenharmony_ci				.cra_name = "authenc(hmac(sha512),rfc3686(ctr(aes)))",
434362306a36Sopenharmony_ci				.cra_driver_name =
434462306a36Sopenharmony_ci				"authenc-hmac-sha512-rfc3686-ctr-aes-chcr",
434562306a36Sopenharmony_ci				.cra_blocksize	 = 1,
434662306a36Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
434762306a36Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
434862306a36Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
434962306a36Sopenharmony_ci						sizeof(struct chcr_authenc_ctx),
435062306a36Sopenharmony_ci
435162306a36Sopenharmony_ci			},
435262306a36Sopenharmony_ci			.ivsize = CTR_RFC3686_IV_SIZE,
435362306a36Sopenharmony_ci			.maxauthsize = SHA512_DIGEST_SIZE,
435462306a36Sopenharmony_ci			.setkey = chcr_authenc_setkey,
435562306a36Sopenharmony_ci			.setauthsize = chcr_authenc_setauthsize,
435662306a36Sopenharmony_ci		}
435762306a36Sopenharmony_ci	},
435862306a36Sopenharmony_ci	{
435962306a36Sopenharmony_ci		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CTR_NULL,
436062306a36Sopenharmony_ci		.is_registered = 0,
436162306a36Sopenharmony_ci		.alg.aead = {
436262306a36Sopenharmony_ci			.base = {
436362306a36Sopenharmony_ci				.cra_name = "authenc(digest_null,rfc3686(ctr(aes)))",
436462306a36Sopenharmony_ci				.cra_driver_name =
436562306a36Sopenharmony_ci				"authenc-digest_null-rfc3686-ctr-aes-chcr",
436662306a36Sopenharmony_ci				.cra_blocksize	 = 1,
436762306a36Sopenharmony_ci				.cra_priority = CHCR_AEAD_PRIORITY,
436862306a36Sopenharmony_ci				.cra_ctxsize =	sizeof(struct chcr_context) +
436962306a36Sopenharmony_ci						sizeof(struct chcr_aead_ctx) +
437062306a36Sopenharmony_ci						sizeof(struct chcr_authenc_ctx),
437162306a36Sopenharmony_ci
437262306a36Sopenharmony_ci			},
437362306a36Sopenharmony_ci			.ivsize  = CTR_RFC3686_IV_SIZE,
437462306a36Sopenharmony_ci			.maxauthsize = 0,
437562306a36Sopenharmony_ci			.setkey  = chcr_aead_digest_null_setkey,
437662306a36Sopenharmony_ci			.setauthsize = chcr_authenc_null_setauthsize,
437762306a36Sopenharmony_ci		}
437862306a36Sopenharmony_ci	},
437962306a36Sopenharmony_ci};
438062306a36Sopenharmony_ci
438162306a36Sopenharmony_ci/*
438262306a36Sopenharmony_ci *	chcr_unregister_alg - Deregister crypto algorithms with
438362306a36Sopenharmony_ci *	kernel framework.
438462306a36Sopenharmony_ci */
438562306a36Sopenharmony_cistatic int chcr_unregister_alg(void)
438662306a36Sopenharmony_ci{
438762306a36Sopenharmony_ci	int i;
438862306a36Sopenharmony_ci
438962306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
439062306a36Sopenharmony_ci		switch (driver_algs[i].type & CRYPTO_ALG_TYPE_MASK) {
439162306a36Sopenharmony_ci		case CRYPTO_ALG_TYPE_SKCIPHER:
439262306a36Sopenharmony_ci			if (driver_algs[i].is_registered && refcount_read(
439362306a36Sopenharmony_ci			    &driver_algs[i].alg.skcipher.base.cra_refcnt)
439462306a36Sopenharmony_ci			    == 1) {
439562306a36Sopenharmony_ci				crypto_unregister_skcipher(
439662306a36Sopenharmony_ci						&driver_algs[i].alg.skcipher);
439762306a36Sopenharmony_ci				driver_algs[i].is_registered = 0;
439862306a36Sopenharmony_ci			}
439962306a36Sopenharmony_ci			break;
440062306a36Sopenharmony_ci		case CRYPTO_ALG_TYPE_AEAD:
440162306a36Sopenharmony_ci			if (driver_algs[i].is_registered && refcount_read(
440262306a36Sopenharmony_ci			    &driver_algs[i].alg.aead.base.cra_refcnt) == 1) {
440362306a36Sopenharmony_ci				crypto_unregister_aead(
440462306a36Sopenharmony_ci						&driver_algs[i].alg.aead);
440562306a36Sopenharmony_ci				driver_algs[i].is_registered = 0;
440662306a36Sopenharmony_ci			}
440762306a36Sopenharmony_ci			break;
440862306a36Sopenharmony_ci		case CRYPTO_ALG_TYPE_AHASH:
440962306a36Sopenharmony_ci			if (driver_algs[i].is_registered && refcount_read(
441062306a36Sopenharmony_ci			    &driver_algs[i].alg.hash.halg.base.cra_refcnt)
441162306a36Sopenharmony_ci			    == 1) {
441262306a36Sopenharmony_ci				crypto_unregister_ahash(
441362306a36Sopenharmony_ci						&driver_algs[i].alg.hash);
441462306a36Sopenharmony_ci				driver_algs[i].is_registered = 0;
441562306a36Sopenharmony_ci			}
441662306a36Sopenharmony_ci			break;
441762306a36Sopenharmony_ci		}
441862306a36Sopenharmony_ci	}
441962306a36Sopenharmony_ci	return 0;
442062306a36Sopenharmony_ci}
442162306a36Sopenharmony_ci
442262306a36Sopenharmony_ci#define SZ_AHASH_CTX sizeof(struct chcr_context)
442362306a36Sopenharmony_ci#define SZ_AHASH_H_CTX (sizeof(struct chcr_context) + sizeof(struct hmac_ctx))
442462306a36Sopenharmony_ci#define SZ_AHASH_REQ_CTX sizeof(struct chcr_ahash_req_ctx)
442562306a36Sopenharmony_ci
442662306a36Sopenharmony_ci/*
442762306a36Sopenharmony_ci *	chcr_register_alg - Register crypto algorithms with kernel framework.
442862306a36Sopenharmony_ci */
442962306a36Sopenharmony_cistatic int chcr_register_alg(void)
443062306a36Sopenharmony_ci{
443162306a36Sopenharmony_ci	struct crypto_alg ai;
443262306a36Sopenharmony_ci	struct ahash_alg *a_hash;
443362306a36Sopenharmony_ci	int err = 0, i;
443462306a36Sopenharmony_ci	char *name = NULL;
443562306a36Sopenharmony_ci
443662306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
443762306a36Sopenharmony_ci		if (driver_algs[i].is_registered)
443862306a36Sopenharmony_ci			continue;
443962306a36Sopenharmony_ci		switch (driver_algs[i].type & CRYPTO_ALG_TYPE_MASK) {
444062306a36Sopenharmony_ci		case CRYPTO_ALG_TYPE_SKCIPHER:
444162306a36Sopenharmony_ci			driver_algs[i].alg.skcipher.base.cra_priority =
444262306a36Sopenharmony_ci				CHCR_CRA_PRIORITY;
444362306a36Sopenharmony_ci			driver_algs[i].alg.skcipher.base.cra_module = THIS_MODULE;
444462306a36Sopenharmony_ci			driver_algs[i].alg.skcipher.base.cra_flags =
444562306a36Sopenharmony_ci				CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_ASYNC |
444662306a36Sopenharmony_ci				CRYPTO_ALG_ALLOCATES_MEMORY |
444762306a36Sopenharmony_ci				CRYPTO_ALG_NEED_FALLBACK;
444862306a36Sopenharmony_ci			driver_algs[i].alg.skcipher.base.cra_ctxsize =
444962306a36Sopenharmony_ci				sizeof(struct chcr_context) +
445062306a36Sopenharmony_ci				sizeof(struct ablk_ctx);
445162306a36Sopenharmony_ci			driver_algs[i].alg.skcipher.base.cra_alignmask = 0;
445262306a36Sopenharmony_ci
445362306a36Sopenharmony_ci			err = crypto_register_skcipher(&driver_algs[i].alg.skcipher);
445462306a36Sopenharmony_ci			name = driver_algs[i].alg.skcipher.base.cra_driver_name;
445562306a36Sopenharmony_ci			break;
445662306a36Sopenharmony_ci		case CRYPTO_ALG_TYPE_AEAD:
445762306a36Sopenharmony_ci			driver_algs[i].alg.aead.base.cra_flags =
445862306a36Sopenharmony_ci				CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK |
445962306a36Sopenharmony_ci				CRYPTO_ALG_ALLOCATES_MEMORY;
446062306a36Sopenharmony_ci			driver_algs[i].alg.aead.encrypt = chcr_aead_encrypt;
446162306a36Sopenharmony_ci			driver_algs[i].alg.aead.decrypt = chcr_aead_decrypt;
446262306a36Sopenharmony_ci			driver_algs[i].alg.aead.init = chcr_aead_cra_init;
446362306a36Sopenharmony_ci			driver_algs[i].alg.aead.exit = chcr_aead_cra_exit;
446462306a36Sopenharmony_ci			driver_algs[i].alg.aead.base.cra_module = THIS_MODULE;
446562306a36Sopenharmony_ci			err = crypto_register_aead(&driver_algs[i].alg.aead);
446662306a36Sopenharmony_ci			name = driver_algs[i].alg.aead.base.cra_driver_name;
446762306a36Sopenharmony_ci			break;
446862306a36Sopenharmony_ci		case CRYPTO_ALG_TYPE_AHASH:
446962306a36Sopenharmony_ci			a_hash = &driver_algs[i].alg.hash;
447062306a36Sopenharmony_ci			a_hash->update = chcr_ahash_update;
447162306a36Sopenharmony_ci			a_hash->final = chcr_ahash_final;
447262306a36Sopenharmony_ci			a_hash->finup = chcr_ahash_finup;
447362306a36Sopenharmony_ci			a_hash->digest = chcr_ahash_digest;
447462306a36Sopenharmony_ci			a_hash->export = chcr_ahash_export;
447562306a36Sopenharmony_ci			a_hash->import = chcr_ahash_import;
447662306a36Sopenharmony_ci			a_hash->halg.statesize = SZ_AHASH_REQ_CTX;
447762306a36Sopenharmony_ci			a_hash->halg.base.cra_priority = CHCR_CRA_PRIORITY;
447862306a36Sopenharmony_ci			a_hash->halg.base.cra_module = THIS_MODULE;
447962306a36Sopenharmony_ci			a_hash->halg.base.cra_flags =
448062306a36Sopenharmony_ci				CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY;
448162306a36Sopenharmony_ci			a_hash->halg.base.cra_alignmask = 0;
448262306a36Sopenharmony_ci			a_hash->halg.base.cra_exit = NULL;
448362306a36Sopenharmony_ci
448462306a36Sopenharmony_ci			if (driver_algs[i].type == CRYPTO_ALG_TYPE_HMAC) {
448562306a36Sopenharmony_ci				a_hash->halg.base.cra_init = chcr_hmac_cra_init;
448662306a36Sopenharmony_ci				a_hash->halg.base.cra_exit = chcr_hmac_cra_exit;
448762306a36Sopenharmony_ci				a_hash->init = chcr_hmac_init;
448862306a36Sopenharmony_ci				a_hash->setkey = chcr_ahash_setkey;
448962306a36Sopenharmony_ci				a_hash->halg.base.cra_ctxsize = SZ_AHASH_H_CTX;
449062306a36Sopenharmony_ci			} else {
449162306a36Sopenharmony_ci				a_hash->init = chcr_sha_init;
449262306a36Sopenharmony_ci				a_hash->halg.base.cra_ctxsize = SZ_AHASH_CTX;
449362306a36Sopenharmony_ci				a_hash->halg.base.cra_init = chcr_sha_cra_init;
449462306a36Sopenharmony_ci			}
449562306a36Sopenharmony_ci			err = crypto_register_ahash(&driver_algs[i].alg.hash);
449662306a36Sopenharmony_ci			ai = driver_algs[i].alg.hash.halg.base;
449762306a36Sopenharmony_ci			name = ai.cra_driver_name;
449862306a36Sopenharmony_ci			break;
449962306a36Sopenharmony_ci		}
450062306a36Sopenharmony_ci		if (err) {
450162306a36Sopenharmony_ci			pr_err("%s : Algorithm registration failed\n", name);
450262306a36Sopenharmony_ci			goto register_err;
450362306a36Sopenharmony_ci		} else {
450462306a36Sopenharmony_ci			driver_algs[i].is_registered = 1;
450562306a36Sopenharmony_ci		}
450662306a36Sopenharmony_ci	}
450762306a36Sopenharmony_ci	return 0;
450862306a36Sopenharmony_ci
450962306a36Sopenharmony_ciregister_err:
451062306a36Sopenharmony_ci	chcr_unregister_alg();
451162306a36Sopenharmony_ci	return err;
451262306a36Sopenharmony_ci}
451362306a36Sopenharmony_ci
451462306a36Sopenharmony_ci/*
451562306a36Sopenharmony_ci *	start_crypto - Register the crypto algorithms.
451662306a36Sopenharmony_ci *	This should called once when the first device comesup. After this
451762306a36Sopenharmony_ci *	kernel will start calling driver APIs for crypto operations.
451862306a36Sopenharmony_ci */
451962306a36Sopenharmony_ciint start_crypto(void)
452062306a36Sopenharmony_ci{
452162306a36Sopenharmony_ci	return chcr_register_alg();
452262306a36Sopenharmony_ci}
452362306a36Sopenharmony_ci
452462306a36Sopenharmony_ci/*
452562306a36Sopenharmony_ci *	stop_crypto - Deregister all the crypto algorithms with kernel.
452662306a36Sopenharmony_ci *	This should be called once when the last device goes down. After this
452762306a36Sopenharmony_ci *	kernel will not call the driver API for crypto operations.
452862306a36Sopenharmony_ci */
452962306a36Sopenharmony_ciint stop_crypto(void)
453062306a36Sopenharmony_ci{
453162306a36Sopenharmony_ci	chcr_unregister_alg();
453262306a36Sopenharmony_ci	return 0;
453362306a36Sopenharmony_ci}
4534