162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright 2016 Broadcom
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <linux/err.h>
762306a36Sopenharmony_ci#include <linux/module.h>
862306a36Sopenharmony_ci#include <linux/init.h>
962306a36Sopenharmony_ci#include <linux/errno.h>
1062306a36Sopenharmony_ci#include <linux/kernel.h>
1162306a36Sopenharmony_ci#include <linux/interrupt.h>
1262306a36Sopenharmony_ci#include <linux/platform_device.h>
1362306a36Sopenharmony_ci#include <linux/scatterlist.h>
1462306a36Sopenharmony_ci#include <linux/crypto.h>
1562306a36Sopenharmony_ci#include <linux/kthread.h>
1662306a36Sopenharmony_ci#include <linux/rtnetlink.h>
1762306a36Sopenharmony_ci#include <linux/sched.h>
1862306a36Sopenharmony_ci#include <linux/of.h>
1962306a36Sopenharmony_ci#include <linux/io.h>
2062306a36Sopenharmony_ci#include <linux/bitops.h>
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#include <crypto/algapi.h>
2362306a36Sopenharmony_ci#include <crypto/aead.h>
2462306a36Sopenharmony_ci#include <crypto/internal/aead.h>
2562306a36Sopenharmony_ci#include <crypto/aes.h>
2662306a36Sopenharmony_ci#include <crypto/internal/des.h>
2762306a36Sopenharmony_ci#include <crypto/hmac.h>
2862306a36Sopenharmony_ci#include <crypto/md5.h>
2962306a36Sopenharmony_ci#include <crypto/authenc.h>
3062306a36Sopenharmony_ci#include <crypto/skcipher.h>
3162306a36Sopenharmony_ci#include <crypto/hash.h>
3262306a36Sopenharmony_ci#include <crypto/sha1.h>
3362306a36Sopenharmony_ci#include <crypto/sha2.h>
3462306a36Sopenharmony_ci#include <crypto/sha3.h>
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci#include "util.h"
3762306a36Sopenharmony_ci#include "cipher.h"
3862306a36Sopenharmony_ci#include "spu.h"
3962306a36Sopenharmony_ci#include "spum.h"
4062306a36Sopenharmony_ci#include "spu2.h"
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci/* ================= Device Structure ================== */
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistruct bcm_device_private iproc_priv;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci/* ==================== Parameters ===================== */
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ciint flow_debug_logging;
4962306a36Sopenharmony_cimodule_param(flow_debug_logging, int, 0644);
5062306a36Sopenharmony_ciMODULE_PARM_DESC(flow_debug_logging, "Enable Flow Debug Logging");
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ciint packet_debug_logging;
5362306a36Sopenharmony_cimodule_param(packet_debug_logging, int, 0644);
5462306a36Sopenharmony_ciMODULE_PARM_DESC(packet_debug_logging, "Enable Packet Debug Logging");
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ciint debug_logging_sleep;
5762306a36Sopenharmony_cimodule_param(debug_logging_sleep, int, 0644);
5862306a36Sopenharmony_ciMODULE_PARM_DESC(debug_logging_sleep, "Packet Debug Logging Sleep");
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci/*
6162306a36Sopenharmony_ci * The value of these module parameters is used to set the priority for each
6262306a36Sopenharmony_ci * algo type when this driver registers algos with the kernel crypto API.
6362306a36Sopenharmony_ci * To use a priority other than the default, set the priority in the insmod or
6462306a36Sopenharmony_ci * modprobe. Changing the module priority after init time has no effect.
6562306a36Sopenharmony_ci *
6662306a36Sopenharmony_ci * The default priorities are chosen to be lower (less preferred) than ARMv8 CE
6762306a36Sopenharmony_ci * algos, but more preferred than generic software algos.
6862306a36Sopenharmony_ci */
6962306a36Sopenharmony_cistatic int cipher_pri = 150;
7062306a36Sopenharmony_cimodule_param(cipher_pri, int, 0644);
7162306a36Sopenharmony_ciMODULE_PARM_DESC(cipher_pri, "Priority for cipher algos");
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_cistatic int hash_pri = 100;
7462306a36Sopenharmony_cimodule_param(hash_pri, int, 0644);
7562306a36Sopenharmony_ciMODULE_PARM_DESC(hash_pri, "Priority for hash algos");
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_cistatic int aead_pri = 150;
7862306a36Sopenharmony_cimodule_param(aead_pri, int, 0644);
7962306a36Sopenharmony_ciMODULE_PARM_DESC(aead_pri, "Priority for AEAD algos");
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci/* A type 3 BCM header, expected to precede the SPU header for SPU-M.
8262306a36Sopenharmony_ci * Bits 3 and 4 in the first byte encode the channel number (the dma ringset).
8362306a36Sopenharmony_ci * 0x60 - ring 0
8462306a36Sopenharmony_ci * 0x68 - ring 1
8562306a36Sopenharmony_ci * 0x70 - ring 2
8662306a36Sopenharmony_ci * 0x78 - ring 3
8762306a36Sopenharmony_ci */
8862306a36Sopenharmony_cistatic char BCMHEADER[] = { 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28 };
8962306a36Sopenharmony_ci/*
9062306a36Sopenharmony_ci * Some SPU hw does not use BCM header on SPU messages. So BCM_HDR_LEN
9162306a36Sopenharmony_ci * is set dynamically after reading SPU type from device tree.
9262306a36Sopenharmony_ci */
9362306a36Sopenharmony_ci#define BCM_HDR_LEN  iproc_priv.bcm_hdr_len
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci/* min and max time to sleep before retrying when mbox queue is full. usec */
9662306a36Sopenharmony_ci#define MBOX_SLEEP_MIN  800
9762306a36Sopenharmony_ci#define MBOX_SLEEP_MAX 1000
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci/**
10062306a36Sopenharmony_ci * select_channel() - Select a SPU channel to handle a crypto request. Selects
10162306a36Sopenharmony_ci * channel in round robin order.
10262306a36Sopenharmony_ci *
10362306a36Sopenharmony_ci * Return:  channel index
10462306a36Sopenharmony_ci */
10562306a36Sopenharmony_cistatic u8 select_channel(void)
10662306a36Sopenharmony_ci{
10762306a36Sopenharmony_ci	u8 chan_idx = atomic_inc_return(&iproc_priv.next_chan);
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	return chan_idx % iproc_priv.spu.num_chan;
11062306a36Sopenharmony_ci}
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci/**
11362306a36Sopenharmony_ci * spu_skcipher_rx_sg_create() - Build up the scatterlist of buffers used to
11462306a36Sopenharmony_ci * receive a SPU response message for an skcipher request. Includes buffers to
11562306a36Sopenharmony_ci * catch SPU message headers and the response data.
11662306a36Sopenharmony_ci * @mssg:	mailbox message containing the receive sg
11762306a36Sopenharmony_ci * @rctx:	crypto request context
11862306a36Sopenharmony_ci * @rx_frag_num: number of scatterlist elements required to hold the
11962306a36Sopenharmony_ci *		SPU response message
12062306a36Sopenharmony_ci * @chunksize:	Number of bytes of response data expected
12162306a36Sopenharmony_ci * @stat_pad_len: Number of bytes required to pad the STAT field to
12262306a36Sopenharmony_ci *		a 4-byte boundary
12362306a36Sopenharmony_ci *
12462306a36Sopenharmony_ci * The scatterlist that gets allocated here is freed in spu_chunk_cleanup()
12562306a36Sopenharmony_ci * when the request completes, whether the request is handled successfully or
12662306a36Sopenharmony_ci * there is an error.
12762306a36Sopenharmony_ci *
12862306a36Sopenharmony_ci * Returns:
12962306a36Sopenharmony_ci *   0 if successful
13062306a36Sopenharmony_ci *   < 0 if an error
13162306a36Sopenharmony_ci */
13262306a36Sopenharmony_cistatic int
13362306a36Sopenharmony_cispu_skcipher_rx_sg_create(struct brcm_message *mssg,
13462306a36Sopenharmony_ci			    struct iproc_reqctx_s *rctx,
13562306a36Sopenharmony_ci			    u8 rx_frag_num,
13662306a36Sopenharmony_ci			    unsigned int chunksize, u32 stat_pad_len)
13762306a36Sopenharmony_ci{
13862306a36Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
13962306a36Sopenharmony_ci	struct scatterlist *sg;	/* used to build sgs in mbox message */
14062306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = rctx->ctx;
14162306a36Sopenharmony_ci	u32 datalen;		/* Number of bytes of response data expected */
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	mssg->spu.dst = kcalloc(rx_frag_num, sizeof(struct scatterlist),
14462306a36Sopenharmony_ci				rctx->gfp);
14562306a36Sopenharmony_ci	if (!mssg->spu.dst)
14662306a36Sopenharmony_ci		return -ENOMEM;
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	sg = mssg->spu.dst;
14962306a36Sopenharmony_ci	sg_init_table(sg, rx_frag_num);
15062306a36Sopenharmony_ci	/* Space for SPU message header */
15162306a36Sopenharmony_ci	sg_set_buf(sg++, rctx->msg_buf.spu_resp_hdr, ctx->spu_resp_hdr_len);
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	/* If XTS tweak in payload, add buffer to receive encrypted tweak */
15462306a36Sopenharmony_ci	if ((ctx->cipher.mode == CIPHER_MODE_XTS) &&
15562306a36Sopenharmony_ci	    spu->spu_xts_tweak_in_payload())
15662306a36Sopenharmony_ci		sg_set_buf(sg++, rctx->msg_buf.c.supdt_tweak,
15762306a36Sopenharmony_ci			   SPU_XTS_TWEAK_SIZE);
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	/* Copy in each dst sg entry from request, up to chunksize */
16062306a36Sopenharmony_ci	datalen = spu_msg_sg_add(&sg, &rctx->dst_sg, &rctx->dst_skip,
16162306a36Sopenharmony_ci				 rctx->dst_nents, chunksize);
16262306a36Sopenharmony_ci	if (datalen < chunksize) {
16362306a36Sopenharmony_ci		pr_err("%s(): failed to copy dst sg to mbox msg. chunksize %u, datalen %u",
16462306a36Sopenharmony_ci		       __func__, chunksize, datalen);
16562306a36Sopenharmony_ci		return -EFAULT;
16662306a36Sopenharmony_ci	}
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	if (stat_pad_len)
16962306a36Sopenharmony_ci		sg_set_buf(sg++, rctx->msg_buf.rx_stat_pad, stat_pad_len);
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	memset(rctx->msg_buf.rx_stat, 0, SPU_RX_STATUS_LEN);
17262306a36Sopenharmony_ci	sg_set_buf(sg, rctx->msg_buf.rx_stat, spu->spu_rx_status_len());
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	return 0;
17562306a36Sopenharmony_ci}
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci/**
17862306a36Sopenharmony_ci * spu_skcipher_tx_sg_create() - Build up the scatterlist of buffers used to
17962306a36Sopenharmony_ci * send a SPU request message for an skcipher request. Includes SPU message
18062306a36Sopenharmony_ci * headers and the request data.
18162306a36Sopenharmony_ci * @mssg:	mailbox message containing the transmit sg
18262306a36Sopenharmony_ci * @rctx:	crypto request context
18362306a36Sopenharmony_ci * @tx_frag_num: number of scatterlist elements required to construct the
18462306a36Sopenharmony_ci *		SPU request message
18562306a36Sopenharmony_ci * @chunksize:	Number of bytes of request data
18662306a36Sopenharmony_ci * @pad_len:	Number of pad bytes
18762306a36Sopenharmony_ci *
18862306a36Sopenharmony_ci * The scatterlist that gets allocated here is freed in spu_chunk_cleanup()
18962306a36Sopenharmony_ci * when the request completes, whether the request is handled successfully or
19062306a36Sopenharmony_ci * there is an error.
19162306a36Sopenharmony_ci *
19262306a36Sopenharmony_ci * Returns:
19362306a36Sopenharmony_ci *   0 if successful
19462306a36Sopenharmony_ci *   < 0 if an error
19562306a36Sopenharmony_ci */
19662306a36Sopenharmony_cistatic int
19762306a36Sopenharmony_cispu_skcipher_tx_sg_create(struct brcm_message *mssg,
19862306a36Sopenharmony_ci			    struct iproc_reqctx_s *rctx,
19962306a36Sopenharmony_ci			    u8 tx_frag_num, unsigned int chunksize, u32 pad_len)
20062306a36Sopenharmony_ci{
20162306a36Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
20262306a36Sopenharmony_ci	struct scatterlist *sg;	/* used to build sgs in mbox message */
20362306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = rctx->ctx;
20462306a36Sopenharmony_ci	u32 datalen;		/* Number of bytes of response data expected */
20562306a36Sopenharmony_ci	u32 stat_len;
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	mssg->spu.src = kcalloc(tx_frag_num, sizeof(struct scatterlist),
20862306a36Sopenharmony_ci				rctx->gfp);
20962306a36Sopenharmony_ci	if (unlikely(!mssg->spu.src))
21062306a36Sopenharmony_ci		return -ENOMEM;
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	sg = mssg->spu.src;
21362306a36Sopenharmony_ci	sg_init_table(sg, tx_frag_num);
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	sg_set_buf(sg++, rctx->msg_buf.bcm_spu_req_hdr,
21662306a36Sopenharmony_ci		   BCM_HDR_LEN + ctx->spu_req_hdr_len);
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	/* if XTS tweak in payload, copy from IV (where crypto API puts it) */
21962306a36Sopenharmony_ci	if ((ctx->cipher.mode == CIPHER_MODE_XTS) &&
22062306a36Sopenharmony_ci	    spu->spu_xts_tweak_in_payload())
22162306a36Sopenharmony_ci		sg_set_buf(sg++, rctx->msg_buf.iv_ctr, SPU_XTS_TWEAK_SIZE);
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci	/* Copy in each src sg entry from request, up to chunksize */
22462306a36Sopenharmony_ci	datalen = spu_msg_sg_add(&sg, &rctx->src_sg, &rctx->src_skip,
22562306a36Sopenharmony_ci				 rctx->src_nents, chunksize);
22662306a36Sopenharmony_ci	if (unlikely(datalen < chunksize)) {
22762306a36Sopenharmony_ci		pr_err("%s(): failed to copy src sg to mbox msg",
22862306a36Sopenharmony_ci		       __func__);
22962306a36Sopenharmony_ci		return -EFAULT;
23062306a36Sopenharmony_ci	}
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci	if (pad_len)
23362306a36Sopenharmony_ci		sg_set_buf(sg++, rctx->msg_buf.spu_req_pad, pad_len);
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	stat_len = spu->spu_tx_status_len();
23662306a36Sopenharmony_ci	if (stat_len) {
23762306a36Sopenharmony_ci		memset(rctx->msg_buf.tx_stat, 0, stat_len);
23862306a36Sopenharmony_ci		sg_set_buf(sg, rctx->msg_buf.tx_stat, stat_len);
23962306a36Sopenharmony_ci	}
24062306a36Sopenharmony_ci	return 0;
24162306a36Sopenharmony_ci}
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_cistatic int mailbox_send_message(struct brcm_message *mssg, u32 flags,
24462306a36Sopenharmony_ci				u8 chan_idx)
24562306a36Sopenharmony_ci{
24662306a36Sopenharmony_ci	int err;
24762306a36Sopenharmony_ci	int retry_cnt = 0;
24862306a36Sopenharmony_ci	struct device *dev = &(iproc_priv.pdev->dev);
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	err = mbox_send_message(iproc_priv.mbox[chan_idx], mssg);
25162306a36Sopenharmony_ci	if (flags & CRYPTO_TFM_REQ_MAY_SLEEP) {
25262306a36Sopenharmony_ci		while ((err == -ENOBUFS) && (retry_cnt < SPU_MB_RETRY_MAX)) {
25362306a36Sopenharmony_ci			/*
25462306a36Sopenharmony_ci			 * Mailbox queue is full. Since MAY_SLEEP is set, assume
25562306a36Sopenharmony_ci			 * not in atomic context and we can wait and try again.
25662306a36Sopenharmony_ci			 */
25762306a36Sopenharmony_ci			retry_cnt++;
25862306a36Sopenharmony_ci			usleep_range(MBOX_SLEEP_MIN, MBOX_SLEEP_MAX);
25962306a36Sopenharmony_ci			err = mbox_send_message(iproc_priv.mbox[chan_idx],
26062306a36Sopenharmony_ci						mssg);
26162306a36Sopenharmony_ci			atomic_inc(&iproc_priv.mb_no_spc);
26262306a36Sopenharmony_ci		}
26362306a36Sopenharmony_ci	}
26462306a36Sopenharmony_ci	if (err < 0) {
26562306a36Sopenharmony_ci		atomic_inc(&iproc_priv.mb_send_fail);
26662306a36Sopenharmony_ci		return err;
26762306a36Sopenharmony_ci	}
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci	/* Check error returned by mailbox controller */
27062306a36Sopenharmony_ci	err = mssg->error;
27162306a36Sopenharmony_ci	if (unlikely(err < 0)) {
27262306a36Sopenharmony_ci		dev_err(dev, "message error %d", err);
27362306a36Sopenharmony_ci		/* Signal txdone for mailbox channel */
27462306a36Sopenharmony_ci	}
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	/* Signal txdone for mailbox channel */
27762306a36Sopenharmony_ci	mbox_client_txdone(iproc_priv.mbox[chan_idx], err);
27862306a36Sopenharmony_ci	return err;
27962306a36Sopenharmony_ci}
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci/**
28262306a36Sopenharmony_ci * handle_skcipher_req() - Submit as much of a block cipher request as fits in
28362306a36Sopenharmony_ci * a single SPU request message, starting at the current position in the request
28462306a36Sopenharmony_ci * data.
28562306a36Sopenharmony_ci * @rctx:	Crypto request context
28662306a36Sopenharmony_ci *
28762306a36Sopenharmony_ci * This may be called on the crypto API thread, or, when a request is so large
28862306a36Sopenharmony_ci * it must be broken into multiple SPU messages, on the thread used to invoke
28962306a36Sopenharmony_ci * the response callback. When requests are broken into multiple SPU
29062306a36Sopenharmony_ci * messages, we assume subsequent messages depend on previous results, and
29162306a36Sopenharmony_ci * thus always wait for previous results before submitting the next message.
29262306a36Sopenharmony_ci * Because requests are submitted in lock step like this, there is no need
29362306a36Sopenharmony_ci * to synchronize access to request data structures.
29462306a36Sopenharmony_ci *
29562306a36Sopenharmony_ci * Return: -EINPROGRESS: request has been accepted and result will be returned
29662306a36Sopenharmony_ci *			 asynchronously
29762306a36Sopenharmony_ci *         Any other value indicates an error
29862306a36Sopenharmony_ci */
29962306a36Sopenharmony_cistatic int handle_skcipher_req(struct iproc_reqctx_s *rctx)
30062306a36Sopenharmony_ci{
30162306a36Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
30262306a36Sopenharmony_ci	struct crypto_async_request *areq = rctx->parent;
30362306a36Sopenharmony_ci	struct skcipher_request *req =
30462306a36Sopenharmony_ci	    container_of(areq, struct skcipher_request, base);
30562306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = rctx->ctx;
30662306a36Sopenharmony_ci	struct spu_cipher_parms cipher_parms;
30762306a36Sopenharmony_ci	int err;
30862306a36Sopenharmony_ci	unsigned int chunksize;	/* Num bytes of request to submit */
30962306a36Sopenharmony_ci	int remaining;	/* Bytes of request still to process */
31062306a36Sopenharmony_ci	int chunk_start;	/* Beginning of data for current SPU msg */
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	/* IV or ctr value to use in this SPU msg */
31362306a36Sopenharmony_ci	u8 local_iv_ctr[MAX_IV_SIZE];
31462306a36Sopenharmony_ci	u32 stat_pad_len;	/* num bytes to align status field */
31562306a36Sopenharmony_ci	u32 pad_len;		/* total length of all padding */
31662306a36Sopenharmony_ci	struct brcm_message *mssg;	/* mailbox message */
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	/* number of entries in src and dst sg in mailbox message. */
31962306a36Sopenharmony_ci	u8 rx_frag_num = 2;	/* response header and STATUS */
32062306a36Sopenharmony_ci	u8 tx_frag_num = 1;	/* request header */
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	flow_log("%s\n", __func__);
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	cipher_parms.alg = ctx->cipher.alg;
32562306a36Sopenharmony_ci	cipher_parms.mode = ctx->cipher.mode;
32662306a36Sopenharmony_ci	cipher_parms.type = ctx->cipher_type;
32762306a36Sopenharmony_ci	cipher_parms.key_len = ctx->enckeylen;
32862306a36Sopenharmony_ci	cipher_parms.key_buf = ctx->enckey;
32962306a36Sopenharmony_ci	cipher_parms.iv_buf = local_iv_ctr;
33062306a36Sopenharmony_ci	cipher_parms.iv_len = rctx->iv_ctr_len;
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	mssg = &rctx->mb_mssg;
33362306a36Sopenharmony_ci	chunk_start = rctx->src_sent;
33462306a36Sopenharmony_ci	remaining = rctx->total_todo - chunk_start;
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	/* determine the chunk we are breaking off and update the indexes */
33762306a36Sopenharmony_ci	if ((ctx->max_payload != SPU_MAX_PAYLOAD_INF) &&
33862306a36Sopenharmony_ci	    (remaining > ctx->max_payload))
33962306a36Sopenharmony_ci		chunksize = ctx->max_payload;
34062306a36Sopenharmony_ci	else
34162306a36Sopenharmony_ci		chunksize = remaining;
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	rctx->src_sent += chunksize;
34462306a36Sopenharmony_ci	rctx->total_sent = rctx->src_sent;
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci	/* Count number of sg entries to be included in this request */
34762306a36Sopenharmony_ci	rctx->src_nents = spu_sg_count(rctx->src_sg, rctx->src_skip, chunksize);
34862306a36Sopenharmony_ci	rctx->dst_nents = spu_sg_count(rctx->dst_sg, rctx->dst_skip, chunksize);
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	if ((ctx->cipher.mode == CIPHER_MODE_CBC) &&
35162306a36Sopenharmony_ci	    rctx->is_encrypt && chunk_start)
35262306a36Sopenharmony_ci		/*
35362306a36Sopenharmony_ci		 * Encrypting non-first first chunk. Copy last block of
35462306a36Sopenharmony_ci		 * previous result to IV for this chunk.
35562306a36Sopenharmony_ci		 */
35662306a36Sopenharmony_ci		sg_copy_part_to_buf(req->dst, rctx->msg_buf.iv_ctr,
35762306a36Sopenharmony_ci				    rctx->iv_ctr_len,
35862306a36Sopenharmony_ci				    chunk_start - rctx->iv_ctr_len);
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	if (rctx->iv_ctr_len) {
36162306a36Sopenharmony_ci		/* get our local copy of the iv */
36262306a36Sopenharmony_ci		__builtin_memcpy(local_iv_ctr, rctx->msg_buf.iv_ctr,
36362306a36Sopenharmony_ci				 rctx->iv_ctr_len);
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci		/* generate the next IV if possible */
36662306a36Sopenharmony_ci		if ((ctx->cipher.mode == CIPHER_MODE_CBC) &&
36762306a36Sopenharmony_ci		    !rctx->is_encrypt) {
36862306a36Sopenharmony_ci			/*
36962306a36Sopenharmony_ci			 * CBC Decrypt: next IV is the last ciphertext block in
37062306a36Sopenharmony_ci			 * this chunk
37162306a36Sopenharmony_ci			 */
37262306a36Sopenharmony_ci			sg_copy_part_to_buf(req->src, rctx->msg_buf.iv_ctr,
37362306a36Sopenharmony_ci					    rctx->iv_ctr_len,
37462306a36Sopenharmony_ci					    rctx->src_sent - rctx->iv_ctr_len);
37562306a36Sopenharmony_ci		} else if (ctx->cipher.mode == CIPHER_MODE_CTR) {
37662306a36Sopenharmony_ci			/*
37762306a36Sopenharmony_ci			 * The SPU hardware increments the counter once for
37862306a36Sopenharmony_ci			 * each AES block of 16 bytes. So update the counter
37962306a36Sopenharmony_ci			 * for the next chunk, if there is one. Note that for
38062306a36Sopenharmony_ci			 * this chunk, the counter has already been copied to
38162306a36Sopenharmony_ci			 * local_iv_ctr. We can assume a block size of 16,
38262306a36Sopenharmony_ci			 * because we only support CTR mode for AES, not for
38362306a36Sopenharmony_ci			 * any other cipher alg.
38462306a36Sopenharmony_ci			 */
38562306a36Sopenharmony_ci			add_to_ctr(rctx->msg_buf.iv_ctr, chunksize >> 4);
38662306a36Sopenharmony_ci		}
38762306a36Sopenharmony_ci	}
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_ci	if (ctx->max_payload == SPU_MAX_PAYLOAD_INF)
39062306a36Sopenharmony_ci		flow_log("max_payload infinite\n");
39162306a36Sopenharmony_ci	else
39262306a36Sopenharmony_ci		flow_log("max_payload %u\n", ctx->max_payload);
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	flow_log("sent:%u start:%u remains:%u size:%u\n",
39562306a36Sopenharmony_ci		 rctx->src_sent, chunk_start, remaining, chunksize);
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	/* Copy SPU header template created at setkey time */
39862306a36Sopenharmony_ci	memcpy(rctx->msg_buf.bcm_spu_req_hdr, ctx->bcm_spu_req_hdr,
39962306a36Sopenharmony_ci	       sizeof(rctx->msg_buf.bcm_spu_req_hdr));
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	spu->spu_cipher_req_finish(rctx->msg_buf.bcm_spu_req_hdr + BCM_HDR_LEN,
40262306a36Sopenharmony_ci				   ctx->spu_req_hdr_len, !(rctx->is_encrypt),
40362306a36Sopenharmony_ci				   &cipher_parms, chunksize);
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci	atomic64_add(chunksize, &iproc_priv.bytes_out);
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci	stat_pad_len = spu->spu_wordalign_padlen(chunksize);
40862306a36Sopenharmony_ci	if (stat_pad_len)
40962306a36Sopenharmony_ci		rx_frag_num++;
41062306a36Sopenharmony_ci	pad_len = stat_pad_len;
41162306a36Sopenharmony_ci	if (pad_len) {
41262306a36Sopenharmony_ci		tx_frag_num++;
41362306a36Sopenharmony_ci		spu->spu_request_pad(rctx->msg_buf.spu_req_pad, 0,
41462306a36Sopenharmony_ci				     0, ctx->auth.alg, ctx->auth.mode,
41562306a36Sopenharmony_ci				     rctx->total_sent, stat_pad_len);
41662306a36Sopenharmony_ci	}
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci	spu->spu_dump_msg_hdr(rctx->msg_buf.bcm_spu_req_hdr + BCM_HDR_LEN,
41962306a36Sopenharmony_ci			      ctx->spu_req_hdr_len);
42062306a36Sopenharmony_ci	packet_log("payload:\n");
42162306a36Sopenharmony_ci	dump_sg(rctx->src_sg, rctx->src_skip, chunksize);
42262306a36Sopenharmony_ci	packet_dump("   pad: ", rctx->msg_buf.spu_req_pad, pad_len);
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci	/*
42562306a36Sopenharmony_ci	 * Build mailbox message containing SPU request msg and rx buffers
42662306a36Sopenharmony_ci	 * to catch response message
42762306a36Sopenharmony_ci	 */
42862306a36Sopenharmony_ci	memset(mssg, 0, sizeof(*mssg));
42962306a36Sopenharmony_ci	mssg->type = BRCM_MESSAGE_SPU;
43062306a36Sopenharmony_ci	mssg->ctx = rctx;	/* Will be returned in response */
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci	/* Create rx scatterlist to catch result */
43362306a36Sopenharmony_ci	rx_frag_num += rctx->dst_nents;
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci	if ((ctx->cipher.mode == CIPHER_MODE_XTS) &&
43662306a36Sopenharmony_ci	    spu->spu_xts_tweak_in_payload())
43762306a36Sopenharmony_ci		rx_frag_num++;	/* extra sg to insert tweak */
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci	err = spu_skcipher_rx_sg_create(mssg, rctx, rx_frag_num, chunksize,
44062306a36Sopenharmony_ci					  stat_pad_len);
44162306a36Sopenharmony_ci	if (err)
44262306a36Sopenharmony_ci		return err;
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci	/* Create tx scatterlist containing SPU request message */
44562306a36Sopenharmony_ci	tx_frag_num += rctx->src_nents;
44662306a36Sopenharmony_ci	if (spu->spu_tx_status_len())
44762306a36Sopenharmony_ci		tx_frag_num++;
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_ci	if ((ctx->cipher.mode == CIPHER_MODE_XTS) &&
45062306a36Sopenharmony_ci	    spu->spu_xts_tweak_in_payload())
45162306a36Sopenharmony_ci		tx_frag_num++;	/* extra sg to insert tweak */
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci	err = spu_skcipher_tx_sg_create(mssg, rctx, tx_frag_num, chunksize,
45462306a36Sopenharmony_ci					  pad_len);
45562306a36Sopenharmony_ci	if (err)
45662306a36Sopenharmony_ci		return err;
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci	err = mailbox_send_message(mssg, req->base.flags, rctx->chan_idx);
45962306a36Sopenharmony_ci	if (unlikely(err < 0))
46062306a36Sopenharmony_ci		return err;
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci	return -EINPROGRESS;
46362306a36Sopenharmony_ci}
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_ci/**
46662306a36Sopenharmony_ci * handle_skcipher_resp() - Process a block cipher SPU response. Updates the
46762306a36Sopenharmony_ci * total received count for the request and updates global stats.
46862306a36Sopenharmony_ci * @rctx:	Crypto request context
46962306a36Sopenharmony_ci */
47062306a36Sopenharmony_cistatic void handle_skcipher_resp(struct iproc_reqctx_s *rctx)
47162306a36Sopenharmony_ci{
47262306a36Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
47362306a36Sopenharmony_ci	struct crypto_async_request *areq = rctx->parent;
47462306a36Sopenharmony_ci	struct skcipher_request *req = skcipher_request_cast(areq);
47562306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = rctx->ctx;
47662306a36Sopenharmony_ci	u32 payload_len;
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci	/* See how much data was returned */
47962306a36Sopenharmony_ci	payload_len = spu->spu_payload_length(rctx->msg_buf.spu_resp_hdr);
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	/*
48262306a36Sopenharmony_ci	 * In XTS mode, the first SPU_XTS_TWEAK_SIZE bytes may be the
48362306a36Sopenharmony_ci	 * encrypted tweak ("i") value; we don't count those.
48462306a36Sopenharmony_ci	 */
48562306a36Sopenharmony_ci	if ((ctx->cipher.mode == CIPHER_MODE_XTS) &&
48662306a36Sopenharmony_ci	    spu->spu_xts_tweak_in_payload() &&
48762306a36Sopenharmony_ci	    (payload_len >= SPU_XTS_TWEAK_SIZE))
48862306a36Sopenharmony_ci		payload_len -= SPU_XTS_TWEAK_SIZE;
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci	atomic64_add(payload_len, &iproc_priv.bytes_in);
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	flow_log("%s() offset: %u, bd_len: %u BD:\n",
49362306a36Sopenharmony_ci		 __func__, rctx->total_received, payload_len);
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_ci	dump_sg(req->dst, rctx->total_received, payload_len);
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci	rctx->total_received += payload_len;
49862306a36Sopenharmony_ci	if (rctx->total_received == rctx->total_todo) {
49962306a36Sopenharmony_ci		atomic_inc(&iproc_priv.op_counts[SPU_OP_CIPHER]);
50062306a36Sopenharmony_ci		atomic_inc(
50162306a36Sopenharmony_ci		   &iproc_priv.cipher_cnt[ctx->cipher.alg][ctx->cipher.mode]);
50262306a36Sopenharmony_ci	}
50362306a36Sopenharmony_ci}
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_ci/**
50662306a36Sopenharmony_ci * spu_ahash_rx_sg_create() - Build up the scatterlist of buffers used to
50762306a36Sopenharmony_ci * receive a SPU response message for an ahash request.
50862306a36Sopenharmony_ci * @mssg:	mailbox message containing the receive sg
50962306a36Sopenharmony_ci * @rctx:	crypto request context
51062306a36Sopenharmony_ci * @rx_frag_num: number of scatterlist elements required to hold the
51162306a36Sopenharmony_ci *		SPU response message
51262306a36Sopenharmony_ci * @digestsize: length of hash digest, in bytes
51362306a36Sopenharmony_ci * @stat_pad_len: Number of bytes required to pad the STAT field to
51462306a36Sopenharmony_ci *		a 4-byte boundary
51562306a36Sopenharmony_ci *
51662306a36Sopenharmony_ci * The scatterlist that gets allocated here is freed in spu_chunk_cleanup()
51762306a36Sopenharmony_ci * when the request completes, whether the request is handled successfully or
51862306a36Sopenharmony_ci * there is an error.
51962306a36Sopenharmony_ci *
52062306a36Sopenharmony_ci * Return:
52162306a36Sopenharmony_ci *   0 if successful
52262306a36Sopenharmony_ci *   < 0 if an error
52362306a36Sopenharmony_ci */
52462306a36Sopenharmony_cistatic int
52562306a36Sopenharmony_cispu_ahash_rx_sg_create(struct brcm_message *mssg,
52662306a36Sopenharmony_ci		       struct iproc_reqctx_s *rctx,
52762306a36Sopenharmony_ci		       u8 rx_frag_num, unsigned int digestsize,
52862306a36Sopenharmony_ci		       u32 stat_pad_len)
52962306a36Sopenharmony_ci{
53062306a36Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
53162306a36Sopenharmony_ci	struct scatterlist *sg;	/* used to build sgs in mbox message */
53262306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = rctx->ctx;
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci	mssg->spu.dst = kcalloc(rx_frag_num, sizeof(struct scatterlist),
53562306a36Sopenharmony_ci				rctx->gfp);
53662306a36Sopenharmony_ci	if (!mssg->spu.dst)
53762306a36Sopenharmony_ci		return -ENOMEM;
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci	sg = mssg->spu.dst;
54062306a36Sopenharmony_ci	sg_init_table(sg, rx_frag_num);
54162306a36Sopenharmony_ci	/* Space for SPU message header */
54262306a36Sopenharmony_ci	sg_set_buf(sg++, rctx->msg_buf.spu_resp_hdr, ctx->spu_resp_hdr_len);
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ci	/* Space for digest */
54562306a36Sopenharmony_ci	sg_set_buf(sg++, rctx->msg_buf.digest, digestsize);
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_ci	if (stat_pad_len)
54862306a36Sopenharmony_ci		sg_set_buf(sg++, rctx->msg_buf.rx_stat_pad, stat_pad_len);
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci	memset(rctx->msg_buf.rx_stat, 0, SPU_RX_STATUS_LEN);
55162306a36Sopenharmony_ci	sg_set_buf(sg, rctx->msg_buf.rx_stat, spu->spu_rx_status_len());
55262306a36Sopenharmony_ci	return 0;
55362306a36Sopenharmony_ci}
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci/**
55662306a36Sopenharmony_ci * spu_ahash_tx_sg_create() -  Build up the scatterlist of buffers used to send
55762306a36Sopenharmony_ci * a SPU request message for an ahash request. Includes SPU message headers and
55862306a36Sopenharmony_ci * the request data.
55962306a36Sopenharmony_ci * @mssg:	mailbox message containing the transmit sg
56062306a36Sopenharmony_ci * @rctx:	crypto request context
56162306a36Sopenharmony_ci * @tx_frag_num: number of scatterlist elements required to construct the
56262306a36Sopenharmony_ci *		SPU request message
56362306a36Sopenharmony_ci * @spu_hdr_len: length in bytes of SPU message header
56462306a36Sopenharmony_ci * @hash_carry_len: Number of bytes of data carried over from previous req
56562306a36Sopenharmony_ci * @new_data_len: Number of bytes of new request data
56662306a36Sopenharmony_ci * @pad_len:	Number of pad bytes
56762306a36Sopenharmony_ci *
56862306a36Sopenharmony_ci * The scatterlist that gets allocated here is freed in spu_chunk_cleanup()
56962306a36Sopenharmony_ci * when the request completes, whether the request is handled successfully or
57062306a36Sopenharmony_ci * there is an error.
57162306a36Sopenharmony_ci *
57262306a36Sopenharmony_ci * Return:
57362306a36Sopenharmony_ci *   0 if successful
57462306a36Sopenharmony_ci *   < 0 if an error
57562306a36Sopenharmony_ci */
57662306a36Sopenharmony_cistatic int
57762306a36Sopenharmony_cispu_ahash_tx_sg_create(struct brcm_message *mssg,
57862306a36Sopenharmony_ci		       struct iproc_reqctx_s *rctx,
57962306a36Sopenharmony_ci		       u8 tx_frag_num,
58062306a36Sopenharmony_ci		       u32 spu_hdr_len,
58162306a36Sopenharmony_ci		       unsigned int hash_carry_len,
58262306a36Sopenharmony_ci		       unsigned int new_data_len, u32 pad_len)
58362306a36Sopenharmony_ci{
58462306a36Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
58562306a36Sopenharmony_ci	struct scatterlist *sg;	/* used to build sgs in mbox message */
58662306a36Sopenharmony_ci	u32 datalen;		/* Number of bytes of response data expected */
58762306a36Sopenharmony_ci	u32 stat_len;
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci	mssg->spu.src = kcalloc(tx_frag_num, sizeof(struct scatterlist),
59062306a36Sopenharmony_ci				rctx->gfp);
59162306a36Sopenharmony_ci	if (!mssg->spu.src)
59262306a36Sopenharmony_ci		return -ENOMEM;
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci	sg = mssg->spu.src;
59562306a36Sopenharmony_ci	sg_init_table(sg, tx_frag_num);
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	sg_set_buf(sg++, rctx->msg_buf.bcm_spu_req_hdr,
59862306a36Sopenharmony_ci		   BCM_HDR_LEN + spu_hdr_len);
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	if (hash_carry_len)
60162306a36Sopenharmony_ci		sg_set_buf(sg++, rctx->hash_carry, hash_carry_len);
60262306a36Sopenharmony_ci
60362306a36Sopenharmony_ci	if (new_data_len) {
60462306a36Sopenharmony_ci		/* Copy in each src sg entry from request, up to chunksize */
60562306a36Sopenharmony_ci		datalen = spu_msg_sg_add(&sg, &rctx->src_sg, &rctx->src_skip,
60662306a36Sopenharmony_ci					 rctx->src_nents, new_data_len);
60762306a36Sopenharmony_ci		if (datalen < new_data_len) {
60862306a36Sopenharmony_ci			pr_err("%s(): failed to copy src sg to mbox msg",
60962306a36Sopenharmony_ci			       __func__);
61062306a36Sopenharmony_ci			return -EFAULT;
61162306a36Sopenharmony_ci		}
61262306a36Sopenharmony_ci	}
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci	if (pad_len)
61562306a36Sopenharmony_ci		sg_set_buf(sg++, rctx->msg_buf.spu_req_pad, pad_len);
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci	stat_len = spu->spu_tx_status_len();
61862306a36Sopenharmony_ci	if (stat_len) {
61962306a36Sopenharmony_ci		memset(rctx->msg_buf.tx_stat, 0, stat_len);
62062306a36Sopenharmony_ci		sg_set_buf(sg, rctx->msg_buf.tx_stat, stat_len);
62162306a36Sopenharmony_ci	}
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci	return 0;
62462306a36Sopenharmony_ci}
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci/**
62762306a36Sopenharmony_ci * handle_ahash_req() - Process an asynchronous hash request from the crypto
62862306a36Sopenharmony_ci * API.
62962306a36Sopenharmony_ci * @rctx:  Crypto request context
63062306a36Sopenharmony_ci *
63162306a36Sopenharmony_ci * Builds a SPU request message embedded in a mailbox message and submits the
63262306a36Sopenharmony_ci * mailbox message on a selected mailbox channel. The SPU request message is
63362306a36Sopenharmony_ci * constructed as a scatterlist, including entries from the crypto API's
63462306a36Sopenharmony_ci * src scatterlist to avoid copying the data to be hashed. This function is
63562306a36Sopenharmony_ci * called either on the thread from the crypto API, or, in the case that the
63662306a36Sopenharmony_ci * crypto API request is too large to fit in a single SPU request message,
63762306a36Sopenharmony_ci * on the thread that invokes the receive callback with a response message.
63862306a36Sopenharmony_ci * Because some operations require the response from one chunk before the next
63962306a36Sopenharmony_ci * chunk can be submitted, we always wait for the response for the previous
64062306a36Sopenharmony_ci * chunk before submitting the next chunk. Because requests are submitted in
64162306a36Sopenharmony_ci * lock step like this, there is no need to synchronize access to request data
64262306a36Sopenharmony_ci * structures.
64362306a36Sopenharmony_ci *
64462306a36Sopenharmony_ci * Return:
64562306a36Sopenharmony_ci *   -EINPROGRESS: request has been submitted to SPU and response will be
64662306a36Sopenharmony_ci *		   returned asynchronously
64762306a36Sopenharmony_ci *   -EAGAIN:      non-final request included a small amount of data, which for
64862306a36Sopenharmony_ci *		   efficiency we did not submit to the SPU, but instead stored
64962306a36Sopenharmony_ci *		   to be submitted to the SPU with the next part of the request
65062306a36Sopenharmony_ci *   other:        an error code
65162306a36Sopenharmony_ci */
65262306a36Sopenharmony_cistatic int handle_ahash_req(struct iproc_reqctx_s *rctx)
65362306a36Sopenharmony_ci{
65462306a36Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
65562306a36Sopenharmony_ci	struct crypto_async_request *areq = rctx->parent;
65662306a36Sopenharmony_ci	struct ahash_request *req = ahash_request_cast(areq);
65762306a36Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
65862306a36Sopenharmony_ci	struct crypto_tfm *tfm = crypto_ahash_tfm(ahash);
65962306a36Sopenharmony_ci	unsigned int blocksize = crypto_tfm_alg_blocksize(tfm);
66062306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = rctx->ctx;
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_ci	/* number of bytes still to be hashed in this req */
66362306a36Sopenharmony_ci	unsigned int nbytes_to_hash = 0;
66462306a36Sopenharmony_ci	int err;
66562306a36Sopenharmony_ci	unsigned int chunksize = 0;	/* length of hash carry + new data */
66662306a36Sopenharmony_ci	/*
66762306a36Sopenharmony_ci	 * length of new data, not from hash carry, to be submitted in
66862306a36Sopenharmony_ci	 * this hw request
66962306a36Sopenharmony_ci	 */
67062306a36Sopenharmony_ci	unsigned int new_data_len;
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci	unsigned int __maybe_unused chunk_start = 0;
67362306a36Sopenharmony_ci	u32 db_size;	 /* Length of data field, incl gcm and hash padding */
67462306a36Sopenharmony_ci	int pad_len = 0; /* total pad len, including gcm, hash, stat padding */
67562306a36Sopenharmony_ci	u32 data_pad_len = 0;	/* length of GCM/CCM padding */
67662306a36Sopenharmony_ci	u32 stat_pad_len = 0;	/* length of padding to align STATUS word */
67762306a36Sopenharmony_ci	struct brcm_message *mssg;	/* mailbox message */
67862306a36Sopenharmony_ci	struct spu_request_opts req_opts;
67962306a36Sopenharmony_ci	struct spu_cipher_parms cipher_parms;
68062306a36Sopenharmony_ci	struct spu_hash_parms hash_parms;
68162306a36Sopenharmony_ci	struct spu_aead_parms aead_parms;
68262306a36Sopenharmony_ci	unsigned int local_nbuf;
68362306a36Sopenharmony_ci	u32 spu_hdr_len;
68462306a36Sopenharmony_ci	unsigned int digestsize;
68562306a36Sopenharmony_ci	u16 rem = 0;
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_ci	/*
68862306a36Sopenharmony_ci	 * number of entries in src and dst sg. Always includes SPU msg header.
68962306a36Sopenharmony_ci	 * rx always includes a buffer to catch digest and STATUS.
69062306a36Sopenharmony_ci	 */
69162306a36Sopenharmony_ci	u8 rx_frag_num = 3;
69262306a36Sopenharmony_ci	u8 tx_frag_num = 1;
69362306a36Sopenharmony_ci
69462306a36Sopenharmony_ci	flow_log("total_todo %u, total_sent %u\n",
69562306a36Sopenharmony_ci		 rctx->total_todo, rctx->total_sent);
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_ci	memset(&req_opts, 0, sizeof(req_opts));
69862306a36Sopenharmony_ci	memset(&cipher_parms, 0, sizeof(cipher_parms));
69962306a36Sopenharmony_ci	memset(&hash_parms, 0, sizeof(hash_parms));
70062306a36Sopenharmony_ci	memset(&aead_parms, 0, sizeof(aead_parms));
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_ci	req_opts.bd_suppress = true;
70362306a36Sopenharmony_ci	hash_parms.alg = ctx->auth.alg;
70462306a36Sopenharmony_ci	hash_parms.mode = ctx->auth.mode;
70562306a36Sopenharmony_ci	hash_parms.type = HASH_TYPE_NONE;
70662306a36Sopenharmony_ci	hash_parms.key_buf = (u8 *)ctx->authkey;
70762306a36Sopenharmony_ci	hash_parms.key_len = ctx->authkeylen;
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ci	/*
71062306a36Sopenharmony_ci	 * For hash algorithms below assignment looks bit odd but
71162306a36Sopenharmony_ci	 * it's needed for AES-XCBC and AES-CMAC hash algorithms
71262306a36Sopenharmony_ci	 * to differentiate between 128, 192, 256 bit key values.
71362306a36Sopenharmony_ci	 * Based on the key values, hash algorithm is selected.
71462306a36Sopenharmony_ci	 * For example for 128 bit key, hash algorithm is AES-128.
71562306a36Sopenharmony_ci	 */
71662306a36Sopenharmony_ci	cipher_parms.type = ctx->cipher_type;
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci	mssg = &rctx->mb_mssg;
71962306a36Sopenharmony_ci	chunk_start = rctx->src_sent;
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_ci	/*
72262306a36Sopenharmony_ci	 * Compute the amount remaining to hash. This may include data
72362306a36Sopenharmony_ci	 * carried over from previous requests.
72462306a36Sopenharmony_ci	 */
72562306a36Sopenharmony_ci	nbytes_to_hash = rctx->total_todo - rctx->total_sent;
72662306a36Sopenharmony_ci	chunksize = nbytes_to_hash;
72762306a36Sopenharmony_ci	if ((ctx->max_payload != SPU_MAX_PAYLOAD_INF) &&
72862306a36Sopenharmony_ci	    (chunksize > ctx->max_payload))
72962306a36Sopenharmony_ci		chunksize = ctx->max_payload;
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	/*
73262306a36Sopenharmony_ci	 * If this is not a final request and the request data is not a multiple
73362306a36Sopenharmony_ci	 * of a full block, then simply park the extra data and prefix it to the
73462306a36Sopenharmony_ci	 * data for the next request.
73562306a36Sopenharmony_ci	 */
73662306a36Sopenharmony_ci	if (!rctx->is_final) {
73762306a36Sopenharmony_ci		u8 *dest = rctx->hash_carry + rctx->hash_carry_len;
73862306a36Sopenharmony_ci		u16 new_len;  /* len of data to add to hash carry */
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_ci		rem = chunksize % blocksize;   /* remainder */
74162306a36Sopenharmony_ci		if (rem) {
74262306a36Sopenharmony_ci			/* chunksize not a multiple of blocksize */
74362306a36Sopenharmony_ci			chunksize -= rem;
74462306a36Sopenharmony_ci			if (chunksize == 0) {
74562306a36Sopenharmony_ci				/* Don't have a full block to submit to hw */
74662306a36Sopenharmony_ci				new_len = rem - rctx->hash_carry_len;
74762306a36Sopenharmony_ci				sg_copy_part_to_buf(req->src, dest, new_len,
74862306a36Sopenharmony_ci						    rctx->src_sent);
74962306a36Sopenharmony_ci				rctx->hash_carry_len = rem;
75062306a36Sopenharmony_ci				flow_log("Exiting with hash carry len: %u\n",
75162306a36Sopenharmony_ci					 rctx->hash_carry_len);
75262306a36Sopenharmony_ci				packet_dump("  buf: ",
75362306a36Sopenharmony_ci					    rctx->hash_carry,
75462306a36Sopenharmony_ci					    rctx->hash_carry_len);
75562306a36Sopenharmony_ci				return -EAGAIN;
75662306a36Sopenharmony_ci			}
75762306a36Sopenharmony_ci		}
75862306a36Sopenharmony_ci	}
75962306a36Sopenharmony_ci
76062306a36Sopenharmony_ci	/* if we have hash carry, then prefix it to the data in this request */
76162306a36Sopenharmony_ci	local_nbuf = rctx->hash_carry_len;
76262306a36Sopenharmony_ci	rctx->hash_carry_len = 0;
76362306a36Sopenharmony_ci	if (local_nbuf)
76462306a36Sopenharmony_ci		tx_frag_num++;
76562306a36Sopenharmony_ci	new_data_len = chunksize - local_nbuf;
76662306a36Sopenharmony_ci
76762306a36Sopenharmony_ci	/* Count number of sg entries to be used in this request */
76862306a36Sopenharmony_ci	rctx->src_nents = spu_sg_count(rctx->src_sg, rctx->src_skip,
76962306a36Sopenharmony_ci				       new_data_len);
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci	/* AES hashing keeps key size in type field, so need to copy it here */
77262306a36Sopenharmony_ci	if (hash_parms.alg == HASH_ALG_AES)
77362306a36Sopenharmony_ci		hash_parms.type = (enum hash_type)cipher_parms.type;
77462306a36Sopenharmony_ci	else
77562306a36Sopenharmony_ci		hash_parms.type = spu->spu_hash_type(rctx->total_sent);
77662306a36Sopenharmony_ci
77762306a36Sopenharmony_ci	digestsize = spu->spu_digest_size(ctx->digestsize, ctx->auth.alg,
77862306a36Sopenharmony_ci					  hash_parms.type);
77962306a36Sopenharmony_ci	hash_parms.digestsize =	digestsize;
78062306a36Sopenharmony_ci
78162306a36Sopenharmony_ci	/* update the indexes */
78262306a36Sopenharmony_ci	rctx->total_sent += chunksize;
78362306a36Sopenharmony_ci	/* if you sent a prebuf then that wasn't from this req->src */
78462306a36Sopenharmony_ci	rctx->src_sent += new_data_len;
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_ci	if ((rctx->total_sent == rctx->total_todo) && rctx->is_final)
78762306a36Sopenharmony_ci		hash_parms.pad_len = spu->spu_hash_pad_len(hash_parms.alg,
78862306a36Sopenharmony_ci							   hash_parms.mode,
78962306a36Sopenharmony_ci							   chunksize,
79062306a36Sopenharmony_ci							   blocksize);
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_ci	/*
79362306a36Sopenharmony_ci	 * If a non-first chunk, then include the digest returned from the
79462306a36Sopenharmony_ci	 * previous chunk so that hw can add to it (except for AES types).
79562306a36Sopenharmony_ci	 */
79662306a36Sopenharmony_ci	if ((hash_parms.type == HASH_TYPE_UPDT) &&
79762306a36Sopenharmony_ci	    (hash_parms.alg != HASH_ALG_AES)) {
79862306a36Sopenharmony_ci		hash_parms.key_buf = rctx->incr_hash;
79962306a36Sopenharmony_ci		hash_parms.key_len = digestsize;
80062306a36Sopenharmony_ci	}
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ci	atomic64_add(chunksize, &iproc_priv.bytes_out);
80362306a36Sopenharmony_ci
80462306a36Sopenharmony_ci	flow_log("%s() final: %u nbuf: %u ",
80562306a36Sopenharmony_ci		 __func__, rctx->is_final, local_nbuf);
80662306a36Sopenharmony_ci
80762306a36Sopenharmony_ci	if (ctx->max_payload == SPU_MAX_PAYLOAD_INF)
80862306a36Sopenharmony_ci		flow_log("max_payload infinite\n");
80962306a36Sopenharmony_ci	else
81062306a36Sopenharmony_ci		flow_log("max_payload %u\n", ctx->max_payload);
81162306a36Sopenharmony_ci
81262306a36Sopenharmony_ci	flow_log("chunk_start: %u chunk_size: %u\n", chunk_start, chunksize);
81362306a36Sopenharmony_ci
81462306a36Sopenharmony_ci	/* Prepend SPU header with type 3 BCM header */
81562306a36Sopenharmony_ci	memcpy(rctx->msg_buf.bcm_spu_req_hdr, BCMHEADER, BCM_HDR_LEN);
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_ci	hash_parms.prebuf_len = local_nbuf;
81862306a36Sopenharmony_ci	spu_hdr_len = spu->spu_create_request(rctx->msg_buf.bcm_spu_req_hdr +
81962306a36Sopenharmony_ci					      BCM_HDR_LEN,
82062306a36Sopenharmony_ci					      &req_opts, &cipher_parms,
82162306a36Sopenharmony_ci					      &hash_parms, &aead_parms,
82262306a36Sopenharmony_ci					      new_data_len);
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_ci	if (spu_hdr_len == 0) {
82562306a36Sopenharmony_ci		pr_err("Failed to create SPU request header\n");
82662306a36Sopenharmony_ci		return -EFAULT;
82762306a36Sopenharmony_ci	}
82862306a36Sopenharmony_ci
82962306a36Sopenharmony_ci	/*
83062306a36Sopenharmony_ci	 * Determine total length of padding required. Put all padding in one
83162306a36Sopenharmony_ci	 * buffer.
83262306a36Sopenharmony_ci	 */
83362306a36Sopenharmony_ci	data_pad_len = spu->spu_gcm_ccm_pad_len(ctx->cipher.mode, chunksize);
83462306a36Sopenharmony_ci	db_size = spu_real_db_size(0, 0, local_nbuf, new_data_len,
83562306a36Sopenharmony_ci				   0, 0, hash_parms.pad_len);
83662306a36Sopenharmony_ci	if (spu->spu_tx_status_len())
83762306a36Sopenharmony_ci		stat_pad_len = spu->spu_wordalign_padlen(db_size);
83862306a36Sopenharmony_ci	if (stat_pad_len)
83962306a36Sopenharmony_ci		rx_frag_num++;
84062306a36Sopenharmony_ci	pad_len = hash_parms.pad_len + data_pad_len + stat_pad_len;
84162306a36Sopenharmony_ci	if (pad_len) {
84262306a36Sopenharmony_ci		tx_frag_num++;
84362306a36Sopenharmony_ci		spu->spu_request_pad(rctx->msg_buf.spu_req_pad, data_pad_len,
84462306a36Sopenharmony_ci				     hash_parms.pad_len, ctx->auth.alg,
84562306a36Sopenharmony_ci				     ctx->auth.mode, rctx->total_sent,
84662306a36Sopenharmony_ci				     stat_pad_len);
84762306a36Sopenharmony_ci	}
84862306a36Sopenharmony_ci
84962306a36Sopenharmony_ci	spu->spu_dump_msg_hdr(rctx->msg_buf.bcm_spu_req_hdr + BCM_HDR_LEN,
85062306a36Sopenharmony_ci			      spu_hdr_len);
85162306a36Sopenharmony_ci	packet_dump("    prebuf: ", rctx->hash_carry, local_nbuf);
85262306a36Sopenharmony_ci	flow_log("Data:\n");
85362306a36Sopenharmony_ci	dump_sg(rctx->src_sg, rctx->src_skip, new_data_len);
85462306a36Sopenharmony_ci	packet_dump("   pad: ", rctx->msg_buf.spu_req_pad, pad_len);
85562306a36Sopenharmony_ci
85662306a36Sopenharmony_ci	/*
85762306a36Sopenharmony_ci	 * Build mailbox message containing SPU request msg and rx buffers
85862306a36Sopenharmony_ci	 * to catch response message
85962306a36Sopenharmony_ci	 */
86062306a36Sopenharmony_ci	memset(mssg, 0, sizeof(*mssg));
86162306a36Sopenharmony_ci	mssg->type = BRCM_MESSAGE_SPU;
86262306a36Sopenharmony_ci	mssg->ctx = rctx;	/* Will be returned in response */
86362306a36Sopenharmony_ci
86462306a36Sopenharmony_ci	/* Create rx scatterlist to catch result */
86562306a36Sopenharmony_ci	err = spu_ahash_rx_sg_create(mssg, rctx, rx_frag_num, digestsize,
86662306a36Sopenharmony_ci				     stat_pad_len);
86762306a36Sopenharmony_ci	if (err)
86862306a36Sopenharmony_ci		return err;
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_ci	/* Create tx scatterlist containing SPU request message */
87162306a36Sopenharmony_ci	tx_frag_num += rctx->src_nents;
87262306a36Sopenharmony_ci	if (spu->spu_tx_status_len())
87362306a36Sopenharmony_ci		tx_frag_num++;
87462306a36Sopenharmony_ci	err = spu_ahash_tx_sg_create(mssg, rctx, tx_frag_num, spu_hdr_len,
87562306a36Sopenharmony_ci				     local_nbuf, new_data_len, pad_len);
87662306a36Sopenharmony_ci	if (err)
87762306a36Sopenharmony_ci		return err;
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_ci	err = mailbox_send_message(mssg, req->base.flags, rctx->chan_idx);
88062306a36Sopenharmony_ci	if (unlikely(err < 0))
88162306a36Sopenharmony_ci		return err;
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_ci	return -EINPROGRESS;
88462306a36Sopenharmony_ci}
88562306a36Sopenharmony_ci
88662306a36Sopenharmony_ci/**
88762306a36Sopenharmony_ci * spu_hmac_outer_hash() - Request synchonous software compute of the outer hash
88862306a36Sopenharmony_ci * for an HMAC request.
88962306a36Sopenharmony_ci * @req:  The HMAC request from the crypto API
89062306a36Sopenharmony_ci * @ctx:  The session context
89162306a36Sopenharmony_ci *
89262306a36Sopenharmony_ci * Return: 0 if synchronous hash operation successful
89362306a36Sopenharmony_ci *         -EINVAL if the hash algo is unrecognized
89462306a36Sopenharmony_ci *         any other value indicates an error
89562306a36Sopenharmony_ci */
89662306a36Sopenharmony_cistatic int spu_hmac_outer_hash(struct ahash_request *req,
89762306a36Sopenharmony_ci			       struct iproc_ctx_s *ctx)
89862306a36Sopenharmony_ci{
89962306a36Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
90062306a36Sopenharmony_ci	unsigned int blocksize =
90162306a36Sopenharmony_ci		crypto_tfm_alg_blocksize(crypto_ahash_tfm(ahash));
90262306a36Sopenharmony_ci	int rc;
90362306a36Sopenharmony_ci
90462306a36Sopenharmony_ci	switch (ctx->auth.alg) {
90562306a36Sopenharmony_ci	case HASH_ALG_MD5:
90662306a36Sopenharmony_ci		rc = do_shash("md5", req->result, ctx->opad, blocksize,
90762306a36Sopenharmony_ci			      req->result, ctx->digestsize, NULL, 0);
90862306a36Sopenharmony_ci		break;
90962306a36Sopenharmony_ci	case HASH_ALG_SHA1:
91062306a36Sopenharmony_ci		rc = do_shash("sha1", req->result, ctx->opad, blocksize,
91162306a36Sopenharmony_ci			      req->result, ctx->digestsize, NULL, 0);
91262306a36Sopenharmony_ci		break;
91362306a36Sopenharmony_ci	case HASH_ALG_SHA224:
91462306a36Sopenharmony_ci		rc = do_shash("sha224", req->result, ctx->opad, blocksize,
91562306a36Sopenharmony_ci			      req->result, ctx->digestsize, NULL, 0);
91662306a36Sopenharmony_ci		break;
91762306a36Sopenharmony_ci	case HASH_ALG_SHA256:
91862306a36Sopenharmony_ci		rc = do_shash("sha256", req->result, ctx->opad, blocksize,
91962306a36Sopenharmony_ci			      req->result, ctx->digestsize, NULL, 0);
92062306a36Sopenharmony_ci		break;
92162306a36Sopenharmony_ci	case HASH_ALG_SHA384:
92262306a36Sopenharmony_ci		rc = do_shash("sha384", req->result, ctx->opad, blocksize,
92362306a36Sopenharmony_ci			      req->result, ctx->digestsize, NULL, 0);
92462306a36Sopenharmony_ci		break;
92562306a36Sopenharmony_ci	case HASH_ALG_SHA512:
92662306a36Sopenharmony_ci		rc = do_shash("sha512", req->result, ctx->opad, blocksize,
92762306a36Sopenharmony_ci			      req->result, ctx->digestsize, NULL, 0);
92862306a36Sopenharmony_ci		break;
92962306a36Sopenharmony_ci	default:
93062306a36Sopenharmony_ci		pr_err("%s() Error : unknown hmac type\n", __func__);
93162306a36Sopenharmony_ci		rc = -EINVAL;
93262306a36Sopenharmony_ci	}
93362306a36Sopenharmony_ci	return rc;
93462306a36Sopenharmony_ci}
93562306a36Sopenharmony_ci
93662306a36Sopenharmony_ci/**
93762306a36Sopenharmony_ci * ahash_req_done() - Process a hash result from the SPU hardware.
93862306a36Sopenharmony_ci * @rctx: Crypto request context
93962306a36Sopenharmony_ci *
94062306a36Sopenharmony_ci * Return: 0 if successful
94162306a36Sopenharmony_ci *         < 0 if an error
94262306a36Sopenharmony_ci */
94362306a36Sopenharmony_cistatic int ahash_req_done(struct iproc_reqctx_s *rctx)
94462306a36Sopenharmony_ci{
94562306a36Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
94662306a36Sopenharmony_ci	struct crypto_async_request *areq = rctx->parent;
94762306a36Sopenharmony_ci	struct ahash_request *req = ahash_request_cast(areq);
94862306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = rctx->ctx;
94962306a36Sopenharmony_ci	int err;
95062306a36Sopenharmony_ci
95162306a36Sopenharmony_ci	memcpy(req->result, rctx->msg_buf.digest, ctx->digestsize);
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_ci	if (spu->spu_type == SPU_TYPE_SPUM) {
95462306a36Sopenharmony_ci		/* byte swap the output from the UPDT function to network byte
95562306a36Sopenharmony_ci		 * order
95662306a36Sopenharmony_ci		 */
95762306a36Sopenharmony_ci		if (ctx->auth.alg == HASH_ALG_MD5) {
95862306a36Sopenharmony_ci			__swab32s((u32 *)req->result);
95962306a36Sopenharmony_ci			__swab32s(((u32 *)req->result) + 1);
96062306a36Sopenharmony_ci			__swab32s(((u32 *)req->result) + 2);
96162306a36Sopenharmony_ci			__swab32s(((u32 *)req->result) + 3);
96262306a36Sopenharmony_ci			__swab32s(((u32 *)req->result) + 4);
96362306a36Sopenharmony_ci		}
96462306a36Sopenharmony_ci	}
96562306a36Sopenharmony_ci
96662306a36Sopenharmony_ci	flow_dump("  digest ", req->result, ctx->digestsize);
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_ci	/* if this an HMAC then do the outer hash */
96962306a36Sopenharmony_ci	if (rctx->is_sw_hmac) {
97062306a36Sopenharmony_ci		err = spu_hmac_outer_hash(req, ctx);
97162306a36Sopenharmony_ci		if (err < 0)
97262306a36Sopenharmony_ci			return err;
97362306a36Sopenharmony_ci		flow_dump("  hmac: ", req->result, ctx->digestsize);
97462306a36Sopenharmony_ci	}
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_ci	if (rctx->is_sw_hmac || ctx->auth.mode == HASH_MODE_HMAC) {
97762306a36Sopenharmony_ci		atomic_inc(&iproc_priv.op_counts[SPU_OP_HMAC]);
97862306a36Sopenharmony_ci		atomic_inc(&iproc_priv.hmac_cnt[ctx->auth.alg]);
97962306a36Sopenharmony_ci	} else {
98062306a36Sopenharmony_ci		atomic_inc(&iproc_priv.op_counts[SPU_OP_HASH]);
98162306a36Sopenharmony_ci		atomic_inc(&iproc_priv.hash_cnt[ctx->auth.alg]);
98262306a36Sopenharmony_ci	}
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_ci	return 0;
98562306a36Sopenharmony_ci}
98662306a36Sopenharmony_ci
98762306a36Sopenharmony_ci/**
98862306a36Sopenharmony_ci * handle_ahash_resp() - Process a SPU response message for a hash request.
98962306a36Sopenharmony_ci * Checks if the entire crypto API request has been processed, and if so,
99062306a36Sopenharmony_ci * invokes post processing on the result.
99162306a36Sopenharmony_ci * @rctx: Crypto request context
99262306a36Sopenharmony_ci */
99362306a36Sopenharmony_cistatic void handle_ahash_resp(struct iproc_reqctx_s *rctx)
99462306a36Sopenharmony_ci{
99562306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = rctx->ctx;
99662306a36Sopenharmony_ci	struct crypto_async_request *areq = rctx->parent;
99762306a36Sopenharmony_ci	struct ahash_request *req = ahash_request_cast(areq);
99862306a36Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
99962306a36Sopenharmony_ci	unsigned int blocksize =
100062306a36Sopenharmony_ci		crypto_tfm_alg_blocksize(crypto_ahash_tfm(ahash));
100162306a36Sopenharmony_ci	/*
100262306a36Sopenharmony_ci	 * Save hash to use as input to next op if incremental. Might be copying
100362306a36Sopenharmony_ci	 * too much, but that's easier than figuring out actual digest size here
100462306a36Sopenharmony_ci	 */
100562306a36Sopenharmony_ci	memcpy(rctx->incr_hash, rctx->msg_buf.digest, MAX_DIGEST_SIZE);
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci	flow_log("%s() blocksize:%u digestsize:%u\n",
100862306a36Sopenharmony_ci		 __func__, blocksize, ctx->digestsize);
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci	atomic64_add(ctx->digestsize, &iproc_priv.bytes_in);
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_ci	if (rctx->is_final && (rctx->total_sent == rctx->total_todo))
101362306a36Sopenharmony_ci		ahash_req_done(rctx);
101462306a36Sopenharmony_ci}
101562306a36Sopenharmony_ci
101662306a36Sopenharmony_ci/**
101762306a36Sopenharmony_ci * spu_aead_rx_sg_create() - Build up the scatterlist of buffers used to receive
101862306a36Sopenharmony_ci * a SPU response message for an AEAD request. Includes buffers to catch SPU
101962306a36Sopenharmony_ci * message headers and the response data.
102062306a36Sopenharmony_ci * @mssg:	mailbox message containing the receive sg
102162306a36Sopenharmony_ci * @req:	Crypto API request
102262306a36Sopenharmony_ci * @rctx:	crypto request context
102362306a36Sopenharmony_ci * @rx_frag_num: number of scatterlist elements required to hold the
102462306a36Sopenharmony_ci *		SPU response message
102562306a36Sopenharmony_ci * @assoc_len:	Length of associated data included in the crypto request
102662306a36Sopenharmony_ci * @ret_iv_len: Length of IV returned in response
102762306a36Sopenharmony_ci * @resp_len:	Number of bytes of response data expected to be written to
102862306a36Sopenharmony_ci *              dst buffer from crypto API
102962306a36Sopenharmony_ci * @digestsize: Length of hash digest, in bytes
103062306a36Sopenharmony_ci * @stat_pad_len: Number of bytes required to pad the STAT field to
103162306a36Sopenharmony_ci *		a 4-byte boundary
103262306a36Sopenharmony_ci *
103362306a36Sopenharmony_ci * The scatterlist that gets allocated here is freed in spu_chunk_cleanup()
103462306a36Sopenharmony_ci * when the request completes, whether the request is handled successfully or
103562306a36Sopenharmony_ci * there is an error.
103662306a36Sopenharmony_ci *
103762306a36Sopenharmony_ci * Returns:
103862306a36Sopenharmony_ci *   0 if successful
103962306a36Sopenharmony_ci *   < 0 if an error
104062306a36Sopenharmony_ci */
104162306a36Sopenharmony_cistatic int spu_aead_rx_sg_create(struct brcm_message *mssg,
104262306a36Sopenharmony_ci				 struct aead_request *req,
104362306a36Sopenharmony_ci				 struct iproc_reqctx_s *rctx,
104462306a36Sopenharmony_ci				 u8 rx_frag_num,
104562306a36Sopenharmony_ci				 unsigned int assoc_len,
104662306a36Sopenharmony_ci				 u32 ret_iv_len, unsigned int resp_len,
104762306a36Sopenharmony_ci				 unsigned int digestsize, u32 stat_pad_len)
104862306a36Sopenharmony_ci{
104962306a36Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
105062306a36Sopenharmony_ci	struct scatterlist *sg;	/* used to build sgs in mbox message */
105162306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = rctx->ctx;
105262306a36Sopenharmony_ci	u32 datalen;		/* Number of bytes of response data expected */
105362306a36Sopenharmony_ci	u32 assoc_buf_len;
105462306a36Sopenharmony_ci	u8 data_padlen = 0;
105562306a36Sopenharmony_ci
105662306a36Sopenharmony_ci	if (ctx->is_rfc4543) {
105762306a36Sopenharmony_ci		/* RFC4543: only pad after data, not after AAD */
105862306a36Sopenharmony_ci		data_padlen = spu->spu_gcm_ccm_pad_len(ctx->cipher.mode,
105962306a36Sopenharmony_ci							  assoc_len + resp_len);
106062306a36Sopenharmony_ci		assoc_buf_len = assoc_len;
106162306a36Sopenharmony_ci	} else {
106262306a36Sopenharmony_ci		data_padlen = spu->spu_gcm_ccm_pad_len(ctx->cipher.mode,
106362306a36Sopenharmony_ci							  resp_len);
106462306a36Sopenharmony_ci		assoc_buf_len = spu->spu_assoc_resp_len(ctx->cipher.mode,
106562306a36Sopenharmony_ci						assoc_len, ret_iv_len,
106662306a36Sopenharmony_ci						rctx->is_encrypt);
106762306a36Sopenharmony_ci	}
106862306a36Sopenharmony_ci
106962306a36Sopenharmony_ci	if (ctx->cipher.mode == CIPHER_MODE_CCM)
107062306a36Sopenharmony_ci		/* ICV (after data) must be in the next 32-bit word for CCM */
107162306a36Sopenharmony_ci		data_padlen += spu->spu_wordalign_padlen(assoc_buf_len +
107262306a36Sopenharmony_ci							 resp_len +
107362306a36Sopenharmony_ci							 data_padlen);
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ci	if (data_padlen)
107662306a36Sopenharmony_ci		/* have to catch gcm pad in separate buffer */
107762306a36Sopenharmony_ci		rx_frag_num++;
107862306a36Sopenharmony_ci
107962306a36Sopenharmony_ci	mssg->spu.dst = kcalloc(rx_frag_num, sizeof(struct scatterlist),
108062306a36Sopenharmony_ci				rctx->gfp);
108162306a36Sopenharmony_ci	if (!mssg->spu.dst)
108262306a36Sopenharmony_ci		return -ENOMEM;
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_ci	sg = mssg->spu.dst;
108562306a36Sopenharmony_ci	sg_init_table(sg, rx_frag_num);
108662306a36Sopenharmony_ci
108762306a36Sopenharmony_ci	/* Space for SPU message header */
108862306a36Sopenharmony_ci	sg_set_buf(sg++, rctx->msg_buf.spu_resp_hdr, ctx->spu_resp_hdr_len);
108962306a36Sopenharmony_ci
109062306a36Sopenharmony_ci	if (assoc_buf_len) {
109162306a36Sopenharmony_ci		/*
109262306a36Sopenharmony_ci		 * Don't write directly to req->dst, because SPU may pad the
109362306a36Sopenharmony_ci		 * assoc data in the response
109462306a36Sopenharmony_ci		 */
109562306a36Sopenharmony_ci		memset(rctx->msg_buf.a.resp_aad, 0, assoc_buf_len);
109662306a36Sopenharmony_ci		sg_set_buf(sg++, rctx->msg_buf.a.resp_aad, assoc_buf_len);
109762306a36Sopenharmony_ci	}
109862306a36Sopenharmony_ci
109962306a36Sopenharmony_ci	if (resp_len) {
110062306a36Sopenharmony_ci		/*
110162306a36Sopenharmony_ci		 * Copy in each dst sg entry from request, up to chunksize.
110262306a36Sopenharmony_ci		 * dst sg catches just the data. digest caught in separate buf.
110362306a36Sopenharmony_ci		 */
110462306a36Sopenharmony_ci		datalen = spu_msg_sg_add(&sg, &rctx->dst_sg, &rctx->dst_skip,
110562306a36Sopenharmony_ci					 rctx->dst_nents, resp_len);
110662306a36Sopenharmony_ci		if (datalen < (resp_len)) {
110762306a36Sopenharmony_ci			pr_err("%s(): failed to copy dst sg to mbox msg. expected len %u, datalen %u",
110862306a36Sopenharmony_ci			       __func__, resp_len, datalen);
110962306a36Sopenharmony_ci			return -EFAULT;
111062306a36Sopenharmony_ci		}
111162306a36Sopenharmony_ci	}
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_ci	/* If GCM/CCM data is padded, catch padding in separate buffer */
111462306a36Sopenharmony_ci	if (data_padlen) {
111562306a36Sopenharmony_ci		memset(rctx->msg_buf.a.gcmpad, 0, data_padlen);
111662306a36Sopenharmony_ci		sg_set_buf(sg++, rctx->msg_buf.a.gcmpad, data_padlen);
111762306a36Sopenharmony_ci	}
111862306a36Sopenharmony_ci
111962306a36Sopenharmony_ci	/* Always catch ICV in separate buffer */
112062306a36Sopenharmony_ci	sg_set_buf(sg++, rctx->msg_buf.digest, digestsize);
112162306a36Sopenharmony_ci
112262306a36Sopenharmony_ci	flow_log("stat_pad_len %u\n", stat_pad_len);
112362306a36Sopenharmony_ci	if (stat_pad_len) {
112462306a36Sopenharmony_ci		memset(rctx->msg_buf.rx_stat_pad, 0, stat_pad_len);
112562306a36Sopenharmony_ci		sg_set_buf(sg++, rctx->msg_buf.rx_stat_pad, stat_pad_len);
112662306a36Sopenharmony_ci	}
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_ci	memset(rctx->msg_buf.rx_stat, 0, SPU_RX_STATUS_LEN);
112962306a36Sopenharmony_ci	sg_set_buf(sg, rctx->msg_buf.rx_stat, spu->spu_rx_status_len());
113062306a36Sopenharmony_ci
113162306a36Sopenharmony_ci	return 0;
113262306a36Sopenharmony_ci}
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_ci/**
113562306a36Sopenharmony_ci * spu_aead_tx_sg_create() - Build up the scatterlist of buffers used to send a
113662306a36Sopenharmony_ci * SPU request message for an AEAD request. Includes SPU message headers and the
113762306a36Sopenharmony_ci * request data.
113862306a36Sopenharmony_ci * @mssg:	mailbox message containing the transmit sg
113962306a36Sopenharmony_ci * @rctx:	crypto request context
114062306a36Sopenharmony_ci * @tx_frag_num: number of scatterlist elements required to construct the
114162306a36Sopenharmony_ci *		SPU request message
114262306a36Sopenharmony_ci * @spu_hdr_len: length of SPU message header in bytes
114362306a36Sopenharmony_ci * @assoc:	crypto API associated data scatterlist
114462306a36Sopenharmony_ci * @assoc_len:	length of associated data
114562306a36Sopenharmony_ci * @assoc_nents: number of scatterlist entries containing assoc data
114662306a36Sopenharmony_ci * @aead_iv_len: length of AEAD IV, if included
114762306a36Sopenharmony_ci * @chunksize:	Number of bytes of request data
114862306a36Sopenharmony_ci * @aad_pad_len: Number of bytes of padding at end of AAD. For GCM/CCM.
114962306a36Sopenharmony_ci * @pad_len:	Number of pad bytes
115062306a36Sopenharmony_ci * @incl_icv:	If true, write separate ICV buffer after data and
115162306a36Sopenharmony_ci *              any padding
115262306a36Sopenharmony_ci *
115362306a36Sopenharmony_ci * The scatterlist that gets allocated here is freed in spu_chunk_cleanup()
115462306a36Sopenharmony_ci * when the request completes, whether the request is handled successfully or
115562306a36Sopenharmony_ci * there is an error.
115662306a36Sopenharmony_ci *
115762306a36Sopenharmony_ci * Return:
115862306a36Sopenharmony_ci *   0 if successful
115962306a36Sopenharmony_ci *   < 0 if an error
116062306a36Sopenharmony_ci */
116162306a36Sopenharmony_cistatic int spu_aead_tx_sg_create(struct brcm_message *mssg,
116262306a36Sopenharmony_ci				 struct iproc_reqctx_s *rctx,
116362306a36Sopenharmony_ci				 u8 tx_frag_num,
116462306a36Sopenharmony_ci				 u32 spu_hdr_len,
116562306a36Sopenharmony_ci				 struct scatterlist *assoc,
116662306a36Sopenharmony_ci				 unsigned int assoc_len,
116762306a36Sopenharmony_ci				 int assoc_nents,
116862306a36Sopenharmony_ci				 unsigned int aead_iv_len,
116962306a36Sopenharmony_ci				 unsigned int chunksize,
117062306a36Sopenharmony_ci				 u32 aad_pad_len, u32 pad_len, bool incl_icv)
117162306a36Sopenharmony_ci{
117262306a36Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
117362306a36Sopenharmony_ci	struct scatterlist *sg;	/* used to build sgs in mbox message */
117462306a36Sopenharmony_ci	struct scatterlist *assoc_sg = assoc;
117562306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = rctx->ctx;
117662306a36Sopenharmony_ci	u32 datalen;		/* Number of bytes of data to write */
117762306a36Sopenharmony_ci	u32 written;		/* Number of bytes of data written */
117862306a36Sopenharmony_ci	u32 assoc_offset = 0;
117962306a36Sopenharmony_ci	u32 stat_len;
118062306a36Sopenharmony_ci
118162306a36Sopenharmony_ci	mssg->spu.src = kcalloc(tx_frag_num, sizeof(struct scatterlist),
118262306a36Sopenharmony_ci				rctx->gfp);
118362306a36Sopenharmony_ci	if (!mssg->spu.src)
118462306a36Sopenharmony_ci		return -ENOMEM;
118562306a36Sopenharmony_ci
118662306a36Sopenharmony_ci	sg = mssg->spu.src;
118762306a36Sopenharmony_ci	sg_init_table(sg, tx_frag_num);
118862306a36Sopenharmony_ci
118962306a36Sopenharmony_ci	sg_set_buf(sg++, rctx->msg_buf.bcm_spu_req_hdr,
119062306a36Sopenharmony_ci		   BCM_HDR_LEN + spu_hdr_len);
119162306a36Sopenharmony_ci
119262306a36Sopenharmony_ci	if (assoc_len) {
119362306a36Sopenharmony_ci		/* Copy in each associated data sg entry from request */
119462306a36Sopenharmony_ci		written = spu_msg_sg_add(&sg, &assoc_sg, &assoc_offset,
119562306a36Sopenharmony_ci					 assoc_nents, assoc_len);
119662306a36Sopenharmony_ci		if (written < assoc_len) {
119762306a36Sopenharmony_ci			pr_err("%s(): failed to copy assoc sg to mbox msg",
119862306a36Sopenharmony_ci			       __func__);
119962306a36Sopenharmony_ci			return -EFAULT;
120062306a36Sopenharmony_ci		}
120162306a36Sopenharmony_ci	}
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_ci	if (aead_iv_len)
120462306a36Sopenharmony_ci		sg_set_buf(sg++, rctx->msg_buf.iv_ctr, aead_iv_len);
120562306a36Sopenharmony_ci
120662306a36Sopenharmony_ci	if (aad_pad_len) {
120762306a36Sopenharmony_ci		memset(rctx->msg_buf.a.req_aad_pad, 0, aad_pad_len);
120862306a36Sopenharmony_ci		sg_set_buf(sg++, rctx->msg_buf.a.req_aad_pad, aad_pad_len);
120962306a36Sopenharmony_ci	}
121062306a36Sopenharmony_ci
121162306a36Sopenharmony_ci	datalen = chunksize;
121262306a36Sopenharmony_ci	if ((chunksize > ctx->digestsize) && incl_icv)
121362306a36Sopenharmony_ci		datalen -= ctx->digestsize;
121462306a36Sopenharmony_ci	if (datalen) {
121562306a36Sopenharmony_ci		/* For aead, a single msg should consume the entire src sg */
121662306a36Sopenharmony_ci		written = spu_msg_sg_add(&sg, &rctx->src_sg, &rctx->src_skip,
121762306a36Sopenharmony_ci					 rctx->src_nents, datalen);
121862306a36Sopenharmony_ci		if (written < datalen) {
121962306a36Sopenharmony_ci			pr_err("%s(): failed to copy src sg to mbox msg",
122062306a36Sopenharmony_ci			       __func__);
122162306a36Sopenharmony_ci			return -EFAULT;
122262306a36Sopenharmony_ci		}
122362306a36Sopenharmony_ci	}
122462306a36Sopenharmony_ci
122562306a36Sopenharmony_ci	if (pad_len) {
122662306a36Sopenharmony_ci		memset(rctx->msg_buf.spu_req_pad, 0, pad_len);
122762306a36Sopenharmony_ci		sg_set_buf(sg++, rctx->msg_buf.spu_req_pad, pad_len);
122862306a36Sopenharmony_ci	}
122962306a36Sopenharmony_ci
123062306a36Sopenharmony_ci	if (incl_icv)
123162306a36Sopenharmony_ci		sg_set_buf(sg++, rctx->msg_buf.digest, ctx->digestsize);
123262306a36Sopenharmony_ci
123362306a36Sopenharmony_ci	stat_len = spu->spu_tx_status_len();
123462306a36Sopenharmony_ci	if (stat_len) {
123562306a36Sopenharmony_ci		memset(rctx->msg_buf.tx_stat, 0, stat_len);
123662306a36Sopenharmony_ci		sg_set_buf(sg, rctx->msg_buf.tx_stat, stat_len);
123762306a36Sopenharmony_ci	}
123862306a36Sopenharmony_ci	return 0;
123962306a36Sopenharmony_ci}
124062306a36Sopenharmony_ci
124162306a36Sopenharmony_ci/**
124262306a36Sopenharmony_ci * handle_aead_req() - Submit a SPU request message for the next chunk of the
124362306a36Sopenharmony_ci * current AEAD request.
124462306a36Sopenharmony_ci * @rctx:  Crypto request context
124562306a36Sopenharmony_ci *
124662306a36Sopenharmony_ci * Unlike other operation types, we assume the length of the request fits in
124762306a36Sopenharmony_ci * a single SPU request message. aead_enqueue() makes sure this is true.
124862306a36Sopenharmony_ci * Comments for other op types regarding threads applies here as well.
124962306a36Sopenharmony_ci *
125062306a36Sopenharmony_ci * Unlike incremental hash ops, where the spu returns the entire hash for
125162306a36Sopenharmony_ci * truncated algs like sha-224, the SPU returns just the truncated hash in
125262306a36Sopenharmony_ci * response to aead requests. So digestsize is always ctx->digestsize here.
125362306a36Sopenharmony_ci *
125462306a36Sopenharmony_ci * Return: -EINPROGRESS: crypto request has been accepted and result will be
125562306a36Sopenharmony_ci *			 returned asynchronously
125662306a36Sopenharmony_ci *         Any other value indicates an error
125762306a36Sopenharmony_ci */
125862306a36Sopenharmony_cistatic int handle_aead_req(struct iproc_reqctx_s *rctx)
125962306a36Sopenharmony_ci{
126062306a36Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
126162306a36Sopenharmony_ci	struct crypto_async_request *areq = rctx->parent;
126262306a36Sopenharmony_ci	struct aead_request *req = container_of(areq,
126362306a36Sopenharmony_ci						struct aead_request, base);
126462306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = rctx->ctx;
126562306a36Sopenharmony_ci	int err;
126662306a36Sopenharmony_ci	unsigned int chunksize;
126762306a36Sopenharmony_ci	unsigned int resp_len;
126862306a36Sopenharmony_ci	u32 spu_hdr_len;
126962306a36Sopenharmony_ci	u32 db_size;
127062306a36Sopenharmony_ci	u32 stat_pad_len;
127162306a36Sopenharmony_ci	u32 pad_len;
127262306a36Sopenharmony_ci	struct brcm_message *mssg;	/* mailbox message */
127362306a36Sopenharmony_ci	struct spu_request_opts req_opts;
127462306a36Sopenharmony_ci	struct spu_cipher_parms cipher_parms;
127562306a36Sopenharmony_ci	struct spu_hash_parms hash_parms;
127662306a36Sopenharmony_ci	struct spu_aead_parms aead_parms;
127762306a36Sopenharmony_ci	int assoc_nents = 0;
127862306a36Sopenharmony_ci	bool incl_icv = false;
127962306a36Sopenharmony_ci	unsigned int digestsize = ctx->digestsize;
128062306a36Sopenharmony_ci
128162306a36Sopenharmony_ci	/* number of entries in src and dst sg. Always includes SPU msg header.
128262306a36Sopenharmony_ci	 */
128362306a36Sopenharmony_ci	u8 rx_frag_num = 2;	/* and STATUS */
128462306a36Sopenharmony_ci	u8 tx_frag_num = 1;
128562306a36Sopenharmony_ci
128662306a36Sopenharmony_ci	/* doing the whole thing at once */
128762306a36Sopenharmony_ci	chunksize = rctx->total_todo;
128862306a36Sopenharmony_ci
128962306a36Sopenharmony_ci	flow_log("%s: chunksize %u\n", __func__, chunksize);
129062306a36Sopenharmony_ci
129162306a36Sopenharmony_ci	memset(&req_opts, 0, sizeof(req_opts));
129262306a36Sopenharmony_ci	memset(&hash_parms, 0, sizeof(hash_parms));
129362306a36Sopenharmony_ci	memset(&aead_parms, 0, sizeof(aead_parms));
129462306a36Sopenharmony_ci
129562306a36Sopenharmony_ci	req_opts.is_inbound = !(rctx->is_encrypt);
129662306a36Sopenharmony_ci	req_opts.auth_first = ctx->auth_first;
129762306a36Sopenharmony_ci	req_opts.is_aead = true;
129862306a36Sopenharmony_ci	req_opts.is_esp = ctx->is_esp;
129962306a36Sopenharmony_ci
130062306a36Sopenharmony_ci	cipher_parms.alg = ctx->cipher.alg;
130162306a36Sopenharmony_ci	cipher_parms.mode = ctx->cipher.mode;
130262306a36Sopenharmony_ci	cipher_parms.type = ctx->cipher_type;
130362306a36Sopenharmony_ci	cipher_parms.key_buf = ctx->enckey;
130462306a36Sopenharmony_ci	cipher_parms.key_len = ctx->enckeylen;
130562306a36Sopenharmony_ci	cipher_parms.iv_buf = rctx->msg_buf.iv_ctr;
130662306a36Sopenharmony_ci	cipher_parms.iv_len = rctx->iv_ctr_len;
130762306a36Sopenharmony_ci
130862306a36Sopenharmony_ci	hash_parms.alg = ctx->auth.alg;
130962306a36Sopenharmony_ci	hash_parms.mode = ctx->auth.mode;
131062306a36Sopenharmony_ci	hash_parms.type = HASH_TYPE_NONE;
131162306a36Sopenharmony_ci	hash_parms.key_buf = (u8 *)ctx->authkey;
131262306a36Sopenharmony_ci	hash_parms.key_len = ctx->authkeylen;
131362306a36Sopenharmony_ci	hash_parms.digestsize = digestsize;
131462306a36Sopenharmony_ci
131562306a36Sopenharmony_ci	if ((ctx->auth.alg == HASH_ALG_SHA224) &&
131662306a36Sopenharmony_ci	    (ctx->authkeylen < SHA224_DIGEST_SIZE))
131762306a36Sopenharmony_ci		hash_parms.key_len = SHA224_DIGEST_SIZE;
131862306a36Sopenharmony_ci
131962306a36Sopenharmony_ci	aead_parms.assoc_size = req->assoclen;
132062306a36Sopenharmony_ci	if (ctx->is_esp && !ctx->is_rfc4543) {
132162306a36Sopenharmony_ci		/*
132262306a36Sopenharmony_ci		 * 8-byte IV is included assoc data in request. SPU2
132362306a36Sopenharmony_ci		 * expects AAD to include just SPI and seqno. So
132462306a36Sopenharmony_ci		 * subtract off the IV len.
132562306a36Sopenharmony_ci		 */
132662306a36Sopenharmony_ci		aead_parms.assoc_size -= GCM_RFC4106_IV_SIZE;
132762306a36Sopenharmony_ci
132862306a36Sopenharmony_ci		if (rctx->is_encrypt) {
132962306a36Sopenharmony_ci			aead_parms.return_iv = true;
133062306a36Sopenharmony_ci			aead_parms.ret_iv_len = GCM_RFC4106_IV_SIZE;
133162306a36Sopenharmony_ci			aead_parms.ret_iv_off = GCM_ESP_SALT_SIZE;
133262306a36Sopenharmony_ci		}
133362306a36Sopenharmony_ci	} else {
133462306a36Sopenharmony_ci		aead_parms.ret_iv_len = 0;
133562306a36Sopenharmony_ci	}
133662306a36Sopenharmony_ci
133762306a36Sopenharmony_ci	/*
133862306a36Sopenharmony_ci	 * Count number of sg entries from the crypto API request that are to
133962306a36Sopenharmony_ci	 * be included in this mailbox message. For dst sg, don't count space
134062306a36Sopenharmony_ci	 * for digest. Digest gets caught in a separate buffer and copied back
134162306a36Sopenharmony_ci	 * to dst sg when processing response.
134262306a36Sopenharmony_ci	 */
134362306a36Sopenharmony_ci	rctx->src_nents = spu_sg_count(rctx->src_sg, rctx->src_skip, chunksize);
134462306a36Sopenharmony_ci	rctx->dst_nents = spu_sg_count(rctx->dst_sg, rctx->dst_skip, chunksize);
134562306a36Sopenharmony_ci	if (aead_parms.assoc_size)
134662306a36Sopenharmony_ci		assoc_nents = spu_sg_count(rctx->assoc, 0,
134762306a36Sopenharmony_ci					   aead_parms.assoc_size);
134862306a36Sopenharmony_ci
134962306a36Sopenharmony_ci	mssg = &rctx->mb_mssg;
135062306a36Sopenharmony_ci
135162306a36Sopenharmony_ci	rctx->total_sent = chunksize;
135262306a36Sopenharmony_ci	rctx->src_sent = chunksize;
135362306a36Sopenharmony_ci	if (spu->spu_assoc_resp_len(ctx->cipher.mode,
135462306a36Sopenharmony_ci				    aead_parms.assoc_size,
135562306a36Sopenharmony_ci				    aead_parms.ret_iv_len,
135662306a36Sopenharmony_ci				    rctx->is_encrypt))
135762306a36Sopenharmony_ci		rx_frag_num++;
135862306a36Sopenharmony_ci
135962306a36Sopenharmony_ci	aead_parms.iv_len = spu->spu_aead_ivlen(ctx->cipher.mode,
136062306a36Sopenharmony_ci						rctx->iv_ctr_len);
136162306a36Sopenharmony_ci
136262306a36Sopenharmony_ci	if (ctx->auth.alg == HASH_ALG_AES)
136362306a36Sopenharmony_ci		hash_parms.type = (enum hash_type)ctx->cipher_type;
136462306a36Sopenharmony_ci
136562306a36Sopenharmony_ci	/* General case AAD padding (CCM and RFC4543 special cases below) */
136662306a36Sopenharmony_ci	aead_parms.aad_pad_len = spu->spu_gcm_ccm_pad_len(ctx->cipher.mode,
136762306a36Sopenharmony_ci						 aead_parms.assoc_size);
136862306a36Sopenharmony_ci
136962306a36Sopenharmony_ci	/* General case data padding (CCM decrypt special case below) */
137062306a36Sopenharmony_ci	aead_parms.data_pad_len = spu->spu_gcm_ccm_pad_len(ctx->cipher.mode,
137162306a36Sopenharmony_ci							   chunksize);
137262306a36Sopenharmony_ci
137362306a36Sopenharmony_ci	if (ctx->cipher.mode == CIPHER_MODE_CCM) {
137462306a36Sopenharmony_ci		/*
137562306a36Sopenharmony_ci		 * for CCM, AAD len + 2 (rather than AAD len) needs to be
137662306a36Sopenharmony_ci		 * 128-bit aligned
137762306a36Sopenharmony_ci		 */
137862306a36Sopenharmony_ci		aead_parms.aad_pad_len = spu->spu_gcm_ccm_pad_len(
137962306a36Sopenharmony_ci					 ctx->cipher.mode,
138062306a36Sopenharmony_ci					 aead_parms.assoc_size + 2);
138162306a36Sopenharmony_ci
138262306a36Sopenharmony_ci		/*
138362306a36Sopenharmony_ci		 * And when decrypting CCM, need to pad without including
138462306a36Sopenharmony_ci		 * size of ICV which is tacked on to end of chunk
138562306a36Sopenharmony_ci		 */
138662306a36Sopenharmony_ci		if (!rctx->is_encrypt)
138762306a36Sopenharmony_ci			aead_parms.data_pad_len =
138862306a36Sopenharmony_ci				spu->spu_gcm_ccm_pad_len(ctx->cipher.mode,
138962306a36Sopenharmony_ci							chunksize - digestsize);
139062306a36Sopenharmony_ci
139162306a36Sopenharmony_ci		/* CCM also requires software to rewrite portions of IV: */
139262306a36Sopenharmony_ci		spu->spu_ccm_update_iv(digestsize, &cipher_parms, req->assoclen,
139362306a36Sopenharmony_ci				       chunksize, rctx->is_encrypt,
139462306a36Sopenharmony_ci				       ctx->is_esp);
139562306a36Sopenharmony_ci	}
139662306a36Sopenharmony_ci
139762306a36Sopenharmony_ci	if (ctx->is_rfc4543) {
139862306a36Sopenharmony_ci		/*
139962306a36Sopenharmony_ci		 * RFC4543: data is included in AAD, so don't pad after AAD
140062306a36Sopenharmony_ci		 * and pad data based on both AAD + data size
140162306a36Sopenharmony_ci		 */
140262306a36Sopenharmony_ci		aead_parms.aad_pad_len = 0;
140362306a36Sopenharmony_ci		if (!rctx->is_encrypt)
140462306a36Sopenharmony_ci			aead_parms.data_pad_len = spu->spu_gcm_ccm_pad_len(
140562306a36Sopenharmony_ci					ctx->cipher.mode,
140662306a36Sopenharmony_ci					aead_parms.assoc_size + chunksize -
140762306a36Sopenharmony_ci					digestsize);
140862306a36Sopenharmony_ci		else
140962306a36Sopenharmony_ci			aead_parms.data_pad_len = spu->spu_gcm_ccm_pad_len(
141062306a36Sopenharmony_ci					ctx->cipher.mode,
141162306a36Sopenharmony_ci					aead_parms.assoc_size + chunksize);
141262306a36Sopenharmony_ci
141362306a36Sopenharmony_ci		req_opts.is_rfc4543 = true;
141462306a36Sopenharmony_ci	}
141562306a36Sopenharmony_ci
141662306a36Sopenharmony_ci	if (spu_req_incl_icv(ctx->cipher.mode, rctx->is_encrypt)) {
141762306a36Sopenharmony_ci		incl_icv = true;
141862306a36Sopenharmony_ci		tx_frag_num++;
141962306a36Sopenharmony_ci		/* Copy ICV from end of src scatterlist to digest buf */
142062306a36Sopenharmony_ci		sg_copy_part_to_buf(req->src, rctx->msg_buf.digest, digestsize,
142162306a36Sopenharmony_ci				    req->assoclen + rctx->total_sent -
142262306a36Sopenharmony_ci				    digestsize);
142362306a36Sopenharmony_ci	}
142462306a36Sopenharmony_ci
142562306a36Sopenharmony_ci	atomic64_add(chunksize, &iproc_priv.bytes_out);
142662306a36Sopenharmony_ci
142762306a36Sopenharmony_ci	flow_log("%s()-sent chunksize:%u\n", __func__, chunksize);
142862306a36Sopenharmony_ci
142962306a36Sopenharmony_ci	/* Prepend SPU header with type 3 BCM header */
143062306a36Sopenharmony_ci	memcpy(rctx->msg_buf.bcm_spu_req_hdr, BCMHEADER, BCM_HDR_LEN);
143162306a36Sopenharmony_ci
143262306a36Sopenharmony_ci	spu_hdr_len = spu->spu_create_request(rctx->msg_buf.bcm_spu_req_hdr +
143362306a36Sopenharmony_ci					      BCM_HDR_LEN, &req_opts,
143462306a36Sopenharmony_ci					      &cipher_parms, &hash_parms,
143562306a36Sopenharmony_ci					      &aead_parms, chunksize);
143662306a36Sopenharmony_ci
143762306a36Sopenharmony_ci	/* Determine total length of padding. Put all padding in one buffer. */
143862306a36Sopenharmony_ci	db_size = spu_real_db_size(aead_parms.assoc_size, aead_parms.iv_len, 0,
143962306a36Sopenharmony_ci				   chunksize, aead_parms.aad_pad_len,
144062306a36Sopenharmony_ci				   aead_parms.data_pad_len, 0);
144162306a36Sopenharmony_ci
144262306a36Sopenharmony_ci	stat_pad_len = spu->spu_wordalign_padlen(db_size);
144362306a36Sopenharmony_ci
144462306a36Sopenharmony_ci	if (stat_pad_len)
144562306a36Sopenharmony_ci		rx_frag_num++;
144662306a36Sopenharmony_ci	pad_len = aead_parms.data_pad_len + stat_pad_len;
144762306a36Sopenharmony_ci	if (pad_len) {
144862306a36Sopenharmony_ci		tx_frag_num++;
144962306a36Sopenharmony_ci		spu->spu_request_pad(rctx->msg_buf.spu_req_pad,
145062306a36Sopenharmony_ci				     aead_parms.data_pad_len, 0,
145162306a36Sopenharmony_ci				     ctx->auth.alg, ctx->auth.mode,
145262306a36Sopenharmony_ci				     rctx->total_sent, stat_pad_len);
145362306a36Sopenharmony_ci	}
145462306a36Sopenharmony_ci
145562306a36Sopenharmony_ci	spu->spu_dump_msg_hdr(rctx->msg_buf.bcm_spu_req_hdr + BCM_HDR_LEN,
145662306a36Sopenharmony_ci			      spu_hdr_len);
145762306a36Sopenharmony_ci	dump_sg(rctx->assoc, 0, aead_parms.assoc_size);
145862306a36Sopenharmony_ci	packet_dump("    aead iv: ", rctx->msg_buf.iv_ctr, aead_parms.iv_len);
145962306a36Sopenharmony_ci	packet_log("BD:\n");
146062306a36Sopenharmony_ci	dump_sg(rctx->src_sg, rctx->src_skip, chunksize);
146162306a36Sopenharmony_ci	packet_dump("   pad: ", rctx->msg_buf.spu_req_pad, pad_len);
146262306a36Sopenharmony_ci
146362306a36Sopenharmony_ci	/*
146462306a36Sopenharmony_ci	 * Build mailbox message containing SPU request msg and rx buffers
146562306a36Sopenharmony_ci	 * to catch response message
146662306a36Sopenharmony_ci	 */
146762306a36Sopenharmony_ci	memset(mssg, 0, sizeof(*mssg));
146862306a36Sopenharmony_ci	mssg->type = BRCM_MESSAGE_SPU;
146962306a36Sopenharmony_ci	mssg->ctx = rctx;	/* Will be returned in response */
147062306a36Sopenharmony_ci
147162306a36Sopenharmony_ci	/* Create rx scatterlist to catch result */
147262306a36Sopenharmony_ci	rx_frag_num += rctx->dst_nents;
147362306a36Sopenharmony_ci	resp_len = chunksize;
147462306a36Sopenharmony_ci
147562306a36Sopenharmony_ci	/*
147662306a36Sopenharmony_ci	 * Always catch ICV in separate buffer. Have to for GCM/CCM because of
147762306a36Sopenharmony_ci	 * padding. Have to for SHA-224 and other truncated SHAs because SPU
147862306a36Sopenharmony_ci	 * sends entire digest back.
147962306a36Sopenharmony_ci	 */
148062306a36Sopenharmony_ci	rx_frag_num++;
148162306a36Sopenharmony_ci
148262306a36Sopenharmony_ci	if (((ctx->cipher.mode == CIPHER_MODE_GCM) ||
148362306a36Sopenharmony_ci	     (ctx->cipher.mode == CIPHER_MODE_CCM)) && !rctx->is_encrypt) {
148462306a36Sopenharmony_ci		/*
148562306a36Sopenharmony_ci		 * Input is ciphertxt plus ICV, but ICV not incl
148662306a36Sopenharmony_ci		 * in output.
148762306a36Sopenharmony_ci		 */
148862306a36Sopenharmony_ci		resp_len -= ctx->digestsize;
148962306a36Sopenharmony_ci		if (resp_len == 0)
149062306a36Sopenharmony_ci			/* no rx frags to catch output data */
149162306a36Sopenharmony_ci			rx_frag_num -= rctx->dst_nents;
149262306a36Sopenharmony_ci	}
149362306a36Sopenharmony_ci
149462306a36Sopenharmony_ci	err = spu_aead_rx_sg_create(mssg, req, rctx, rx_frag_num,
149562306a36Sopenharmony_ci				    aead_parms.assoc_size,
149662306a36Sopenharmony_ci				    aead_parms.ret_iv_len, resp_len, digestsize,
149762306a36Sopenharmony_ci				    stat_pad_len);
149862306a36Sopenharmony_ci	if (err)
149962306a36Sopenharmony_ci		return err;
150062306a36Sopenharmony_ci
150162306a36Sopenharmony_ci	/* Create tx scatterlist containing SPU request message */
150262306a36Sopenharmony_ci	tx_frag_num += rctx->src_nents;
150362306a36Sopenharmony_ci	tx_frag_num += assoc_nents;
150462306a36Sopenharmony_ci	if (aead_parms.aad_pad_len)
150562306a36Sopenharmony_ci		tx_frag_num++;
150662306a36Sopenharmony_ci	if (aead_parms.iv_len)
150762306a36Sopenharmony_ci		tx_frag_num++;
150862306a36Sopenharmony_ci	if (spu->spu_tx_status_len())
150962306a36Sopenharmony_ci		tx_frag_num++;
151062306a36Sopenharmony_ci	err = spu_aead_tx_sg_create(mssg, rctx, tx_frag_num, spu_hdr_len,
151162306a36Sopenharmony_ci				    rctx->assoc, aead_parms.assoc_size,
151262306a36Sopenharmony_ci				    assoc_nents, aead_parms.iv_len, chunksize,
151362306a36Sopenharmony_ci				    aead_parms.aad_pad_len, pad_len, incl_icv);
151462306a36Sopenharmony_ci	if (err)
151562306a36Sopenharmony_ci		return err;
151662306a36Sopenharmony_ci
151762306a36Sopenharmony_ci	err = mailbox_send_message(mssg, req->base.flags, rctx->chan_idx);
151862306a36Sopenharmony_ci	if (unlikely(err < 0))
151962306a36Sopenharmony_ci		return err;
152062306a36Sopenharmony_ci
152162306a36Sopenharmony_ci	return -EINPROGRESS;
152262306a36Sopenharmony_ci}
152362306a36Sopenharmony_ci
152462306a36Sopenharmony_ci/**
152562306a36Sopenharmony_ci * handle_aead_resp() - Process a SPU response message for an AEAD request.
152662306a36Sopenharmony_ci * @rctx:  Crypto request context
152762306a36Sopenharmony_ci */
152862306a36Sopenharmony_cistatic void handle_aead_resp(struct iproc_reqctx_s *rctx)
152962306a36Sopenharmony_ci{
153062306a36Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
153162306a36Sopenharmony_ci	struct crypto_async_request *areq = rctx->parent;
153262306a36Sopenharmony_ci	struct aead_request *req = container_of(areq,
153362306a36Sopenharmony_ci						struct aead_request, base);
153462306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = rctx->ctx;
153562306a36Sopenharmony_ci	u32 payload_len;
153662306a36Sopenharmony_ci	unsigned int icv_offset;
153762306a36Sopenharmony_ci	u32 result_len;
153862306a36Sopenharmony_ci
153962306a36Sopenharmony_ci	/* See how much data was returned */
154062306a36Sopenharmony_ci	payload_len = spu->spu_payload_length(rctx->msg_buf.spu_resp_hdr);
154162306a36Sopenharmony_ci	flow_log("payload_len %u\n", payload_len);
154262306a36Sopenharmony_ci
154362306a36Sopenharmony_ci	/* only count payload */
154462306a36Sopenharmony_ci	atomic64_add(payload_len, &iproc_priv.bytes_in);
154562306a36Sopenharmony_ci
154662306a36Sopenharmony_ci	if (req->assoclen)
154762306a36Sopenharmony_ci		packet_dump("  assoc_data ", rctx->msg_buf.a.resp_aad,
154862306a36Sopenharmony_ci			    req->assoclen);
154962306a36Sopenharmony_ci
155062306a36Sopenharmony_ci	/*
155162306a36Sopenharmony_ci	 * Copy the ICV back to the destination
155262306a36Sopenharmony_ci	 * buffer. In decrypt case, SPU gives us back the digest, but crypto
155362306a36Sopenharmony_ci	 * API doesn't expect ICV in dst buffer.
155462306a36Sopenharmony_ci	 */
155562306a36Sopenharmony_ci	result_len = req->cryptlen;
155662306a36Sopenharmony_ci	if (rctx->is_encrypt) {
155762306a36Sopenharmony_ci		icv_offset = req->assoclen + rctx->total_sent;
155862306a36Sopenharmony_ci		packet_dump("  ICV: ", rctx->msg_buf.digest, ctx->digestsize);
155962306a36Sopenharmony_ci		flow_log("copying ICV to dst sg at offset %u\n", icv_offset);
156062306a36Sopenharmony_ci		sg_copy_part_from_buf(req->dst, rctx->msg_buf.digest,
156162306a36Sopenharmony_ci				      ctx->digestsize, icv_offset);
156262306a36Sopenharmony_ci		result_len += ctx->digestsize;
156362306a36Sopenharmony_ci	}
156462306a36Sopenharmony_ci
156562306a36Sopenharmony_ci	packet_log("response data:  ");
156662306a36Sopenharmony_ci	dump_sg(req->dst, req->assoclen, result_len);
156762306a36Sopenharmony_ci
156862306a36Sopenharmony_ci	atomic_inc(&iproc_priv.op_counts[SPU_OP_AEAD]);
156962306a36Sopenharmony_ci	if (ctx->cipher.alg == CIPHER_ALG_AES) {
157062306a36Sopenharmony_ci		if (ctx->cipher.mode == CIPHER_MODE_CCM)
157162306a36Sopenharmony_ci			atomic_inc(&iproc_priv.aead_cnt[AES_CCM]);
157262306a36Sopenharmony_ci		else if (ctx->cipher.mode == CIPHER_MODE_GCM)
157362306a36Sopenharmony_ci			atomic_inc(&iproc_priv.aead_cnt[AES_GCM]);
157462306a36Sopenharmony_ci		else
157562306a36Sopenharmony_ci			atomic_inc(&iproc_priv.aead_cnt[AUTHENC]);
157662306a36Sopenharmony_ci	} else {
157762306a36Sopenharmony_ci		atomic_inc(&iproc_priv.aead_cnt[AUTHENC]);
157862306a36Sopenharmony_ci	}
157962306a36Sopenharmony_ci}
158062306a36Sopenharmony_ci
158162306a36Sopenharmony_ci/**
158262306a36Sopenharmony_ci * spu_chunk_cleanup() - Do cleanup after processing one chunk of a request
158362306a36Sopenharmony_ci * @rctx:  request context
158462306a36Sopenharmony_ci *
158562306a36Sopenharmony_ci * Mailbox scatterlists are allocated for each chunk. So free them after
158662306a36Sopenharmony_ci * processing each chunk.
158762306a36Sopenharmony_ci */
158862306a36Sopenharmony_cistatic void spu_chunk_cleanup(struct iproc_reqctx_s *rctx)
158962306a36Sopenharmony_ci{
159062306a36Sopenharmony_ci	/* mailbox message used to tx request */
159162306a36Sopenharmony_ci	struct brcm_message *mssg = &rctx->mb_mssg;
159262306a36Sopenharmony_ci
159362306a36Sopenharmony_ci	kfree(mssg->spu.src);
159462306a36Sopenharmony_ci	kfree(mssg->spu.dst);
159562306a36Sopenharmony_ci	memset(mssg, 0, sizeof(struct brcm_message));
159662306a36Sopenharmony_ci}
159762306a36Sopenharmony_ci
159862306a36Sopenharmony_ci/**
159962306a36Sopenharmony_ci * finish_req() - Used to invoke the complete callback from the requester when
160062306a36Sopenharmony_ci * a request has been handled asynchronously.
160162306a36Sopenharmony_ci * @rctx:  Request context
160262306a36Sopenharmony_ci * @err:   Indicates whether the request was successful or not
160362306a36Sopenharmony_ci *
160462306a36Sopenharmony_ci * Ensures that cleanup has been done for request
160562306a36Sopenharmony_ci */
160662306a36Sopenharmony_cistatic void finish_req(struct iproc_reqctx_s *rctx, int err)
160762306a36Sopenharmony_ci{
160862306a36Sopenharmony_ci	struct crypto_async_request *areq = rctx->parent;
160962306a36Sopenharmony_ci
161062306a36Sopenharmony_ci	flow_log("%s() err:%d\n\n", __func__, err);
161162306a36Sopenharmony_ci
161262306a36Sopenharmony_ci	/* No harm done if already called */
161362306a36Sopenharmony_ci	spu_chunk_cleanup(rctx);
161462306a36Sopenharmony_ci
161562306a36Sopenharmony_ci	if (areq)
161662306a36Sopenharmony_ci		crypto_request_complete(areq, err);
161762306a36Sopenharmony_ci}
161862306a36Sopenharmony_ci
161962306a36Sopenharmony_ci/**
162062306a36Sopenharmony_ci * spu_rx_callback() - Callback from mailbox framework with a SPU response.
162162306a36Sopenharmony_ci * @cl:		mailbox client structure for SPU driver
162262306a36Sopenharmony_ci * @msg:	mailbox message containing SPU response
162362306a36Sopenharmony_ci */
162462306a36Sopenharmony_cistatic void spu_rx_callback(struct mbox_client *cl, void *msg)
162562306a36Sopenharmony_ci{
162662306a36Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
162762306a36Sopenharmony_ci	struct brcm_message *mssg = msg;
162862306a36Sopenharmony_ci	struct iproc_reqctx_s *rctx;
162962306a36Sopenharmony_ci	int err;
163062306a36Sopenharmony_ci
163162306a36Sopenharmony_ci	rctx = mssg->ctx;
163262306a36Sopenharmony_ci	if (unlikely(!rctx)) {
163362306a36Sopenharmony_ci		/* This is fatal */
163462306a36Sopenharmony_ci		pr_err("%s(): no request context", __func__);
163562306a36Sopenharmony_ci		err = -EFAULT;
163662306a36Sopenharmony_ci		goto cb_finish;
163762306a36Sopenharmony_ci	}
163862306a36Sopenharmony_ci
163962306a36Sopenharmony_ci	/* process the SPU status */
164062306a36Sopenharmony_ci	err = spu->spu_status_process(rctx->msg_buf.rx_stat);
164162306a36Sopenharmony_ci	if (err != 0) {
164262306a36Sopenharmony_ci		if (err == SPU_INVALID_ICV)
164362306a36Sopenharmony_ci			atomic_inc(&iproc_priv.bad_icv);
164462306a36Sopenharmony_ci		err = -EBADMSG;
164562306a36Sopenharmony_ci		goto cb_finish;
164662306a36Sopenharmony_ci	}
164762306a36Sopenharmony_ci
164862306a36Sopenharmony_ci	/* Process the SPU response message */
164962306a36Sopenharmony_ci	switch (rctx->ctx->alg->type) {
165062306a36Sopenharmony_ci	case CRYPTO_ALG_TYPE_SKCIPHER:
165162306a36Sopenharmony_ci		handle_skcipher_resp(rctx);
165262306a36Sopenharmony_ci		break;
165362306a36Sopenharmony_ci	case CRYPTO_ALG_TYPE_AHASH:
165462306a36Sopenharmony_ci		handle_ahash_resp(rctx);
165562306a36Sopenharmony_ci		break;
165662306a36Sopenharmony_ci	case CRYPTO_ALG_TYPE_AEAD:
165762306a36Sopenharmony_ci		handle_aead_resp(rctx);
165862306a36Sopenharmony_ci		break;
165962306a36Sopenharmony_ci	default:
166062306a36Sopenharmony_ci		err = -EINVAL;
166162306a36Sopenharmony_ci		goto cb_finish;
166262306a36Sopenharmony_ci	}
166362306a36Sopenharmony_ci
166462306a36Sopenharmony_ci	/*
166562306a36Sopenharmony_ci	 * If this response does not complete the request, then send the next
166662306a36Sopenharmony_ci	 * request chunk.
166762306a36Sopenharmony_ci	 */
166862306a36Sopenharmony_ci	if (rctx->total_sent < rctx->total_todo) {
166962306a36Sopenharmony_ci		/* Deallocate anything specific to previous chunk */
167062306a36Sopenharmony_ci		spu_chunk_cleanup(rctx);
167162306a36Sopenharmony_ci
167262306a36Sopenharmony_ci		switch (rctx->ctx->alg->type) {
167362306a36Sopenharmony_ci		case CRYPTO_ALG_TYPE_SKCIPHER:
167462306a36Sopenharmony_ci			err = handle_skcipher_req(rctx);
167562306a36Sopenharmony_ci			break;
167662306a36Sopenharmony_ci		case CRYPTO_ALG_TYPE_AHASH:
167762306a36Sopenharmony_ci			err = handle_ahash_req(rctx);
167862306a36Sopenharmony_ci			if (err == -EAGAIN)
167962306a36Sopenharmony_ci				/*
168062306a36Sopenharmony_ci				 * we saved data in hash carry, but tell crypto
168162306a36Sopenharmony_ci				 * API we successfully completed request.
168262306a36Sopenharmony_ci				 */
168362306a36Sopenharmony_ci				err = 0;
168462306a36Sopenharmony_ci			break;
168562306a36Sopenharmony_ci		case CRYPTO_ALG_TYPE_AEAD:
168662306a36Sopenharmony_ci			err = handle_aead_req(rctx);
168762306a36Sopenharmony_ci			break;
168862306a36Sopenharmony_ci		default:
168962306a36Sopenharmony_ci			err = -EINVAL;
169062306a36Sopenharmony_ci		}
169162306a36Sopenharmony_ci
169262306a36Sopenharmony_ci		if (err == -EINPROGRESS)
169362306a36Sopenharmony_ci			/* Successfully submitted request for next chunk */
169462306a36Sopenharmony_ci			return;
169562306a36Sopenharmony_ci	}
169662306a36Sopenharmony_ci
169762306a36Sopenharmony_cicb_finish:
169862306a36Sopenharmony_ci	finish_req(rctx, err);
169962306a36Sopenharmony_ci}
170062306a36Sopenharmony_ci
170162306a36Sopenharmony_ci/* ==================== Kernel Cryptographic API ==================== */
170262306a36Sopenharmony_ci
170362306a36Sopenharmony_ci/**
170462306a36Sopenharmony_ci * skcipher_enqueue() - Handle skcipher encrypt or decrypt request.
170562306a36Sopenharmony_ci * @req:	Crypto API request
170662306a36Sopenharmony_ci * @encrypt:	true if encrypting; false if decrypting
170762306a36Sopenharmony_ci *
170862306a36Sopenharmony_ci * Return: -EINPROGRESS if request accepted and result will be returned
170962306a36Sopenharmony_ci *			asynchronously
171062306a36Sopenharmony_ci *	   < 0 if an error
171162306a36Sopenharmony_ci */
171262306a36Sopenharmony_cistatic int skcipher_enqueue(struct skcipher_request *req, bool encrypt)
171362306a36Sopenharmony_ci{
171462306a36Sopenharmony_ci	struct iproc_reqctx_s *rctx = skcipher_request_ctx(req);
171562306a36Sopenharmony_ci	struct iproc_ctx_s *ctx =
171662306a36Sopenharmony_ci	    crypto_skcipher_ctx(crypto_skcipher_reqtfm(req));
171762306a36Sopenharmony_ci	int err;
171862306a36Sopenharmony_ci
171962306a36Sopenharmony_ci	flow_log("%s() enc:%u\n", __func__, encrypt);
172062306a36Sopenharmony_ci
172162306a36Sopenharmony_ci	rctx->gfp = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
172262306a36Sopenharmony_ci		       CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
172362306a36Sopenharmony_ci	rctx->parent = &req->base;
172462306a36Sopenharmony_ci	rctx->is_encrypt = encrypt;
172562306a36Sopenharmony_ci	rctx->bd_suppress = false;
172662306a36Sopenharmony_ci	rctx->total_todo = req->cryptlen;
172762306a36Sopenharmony_ci	rctx->src_sent = 0;
172862306a36Sopenharmony_ci	rctx->total_sent = 0;
172962306a36Sopenharmony_ci	rctx->total_received = 0;
173062306a36Sopenharmony_ci	rctx->ctx = ctx;
173162306a36Sopenharmony_ci
173262306a36Sopenharmony_ci	/* Initialize current position in src and dst scatterlists */
173362306a36Sopenharmony_ci	rctx->src_sg = req->src;
173462306a36Sopenharmony_ci	rctx->src_nents = 0;
173562306a36Sopenharmony_ci	rctx->src_skip = 0;
173662306a36Sopenharmony_ci	rctx->dst_sg = req->dst;
173762306a36Sopenharmony_ci	rctx->dst_nents = 0;
173862306a36Sopenharmony_ci	rctx->dst_skip = 0;
173962306a36Sopenharmony_ci
174062306a36Sopenharmony_ci	if (ctx->cipher.mode == CIPHER_MODE_CBC ||
174162306a36Sopenharmony_ci	    ctx->cipher.mode == CIPHER_MODE_CTR ||
174262306a36Sopenharmony_ci	    ctx->cipher.mode == CIPHER_MODE_OFB ||
174362306a36Sopenharmony_ci	    ctx->cipher.mode == CIPHER_MODE_XTS ||
174462306a36Sopenharmony_ci	    ctx->cipher.mode == CIPHER_MODE_GCM ||
174562306a36Sopenharmony_ci	    ctx->cipher.mode == CIPHER_MODE_CCM) {
174662306a36Sopenharmony_ci		rctx->iv_ctr_len =
174762306a36Sopenharmony_ci		    crypto_skcipher_ivsize(crypto_skcipher_reqtfm(req));
174862306a36Sopenharmony_ci		memcpy(rctx->msg_buf.iv_ctr, req->iv, rctx->iv_ctr_len);
174962306a36Sopenharmony_ci	} else {
175062306a36Sopenharmony_ci		rctx->iv_ctr_len = 0;
175162306a36Sopenharmony_ci	}
175262306a36Sopenharmony_ci
175362306a36Sopenharmony_ci	/* Choose a SPU to process this request */
175462306a36Sopenharmony_ci	rctx->chan_idx = select_channel();
175562306a36Sopenharmony_ci	err = handle_skcipher_req(rctx);
175662306a36Sopenharmony_ci	if (err != -EINPROGRESS)
175762306a36Sopenharmony_ci		/* synchronous result */
175862306a36Sopenharmony_ci		spu_chunk_cleanup(rctx);
175962306a36Sopenharmony_ci
176062306a36Sopenharmony_ci	return err;
176162306a36Sopenharmony_ci}
176262306a36Sopenharmony_ci
176362306a36Sopenharmony_cistatic int des_setkey(struct crypto_skcipher *cipher, const u8 *key,
176462306a36Sopenharmony_ci		      unsigned int keylen)
176562306a36Sopenharmony_ci{
176662306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_skcipher_ctx(cipher);
176762306a36Sopenharmony_ci	int err;
176862306a36Sopenharmony_ci
176962306a36Sopenharmony_ci	err = verify_skcipher_des_key(cipher, key);
177062306a36Sopenharmony_ci	if (err)
177162306a36Sopenharmony_ci		return err;
177262306a36Sopenharmony_ci
177362306a36Sopenharmony_ci	ctx->cipher_type = CIPHER_TYPE_DES;
177462306a36Sopenharmony_ci	return 0;
177562306a36Sopenharmony_ci}
177662306a36Sopenharmony_ci
177762306a36Sopenharmony_cistatic int threedes_setkey(struct crypto_skcipher *cipher, const u8 *key,
177862306a36Sopenharmony_ci			   unsigned int keylen)
177962306a36Sopenharmony_ci{
178062306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_skcipher_ctx(cipher);
178162306a36Sopenharmony_ci	int err;
178262306a36Sopenharmony_ci
178362306a36Sopenharmony_ci	err = verify_skcipher_des3_key(cipher, key);
178462306a36Sopenharmony_ci	if (err)
178562306a36Sopenharmony_ci		return err;
178662306a36Sopenharmony_ci
178762306a36Sopenharmony_ci	ctx->cipher_type = CIPHER_TYPE_3DES;
178862306a36Sopenharmony_ci	return 0;
178962306a36Sopenharmony_ci}
179062306a36Sopenharmony_ci
179162306a36Sopenharmony_cistatic int aes_setkey(struct crypto_skcipher *cipher, const u8 *key,
179262306a36Sopenharmony_ci		      unsigned int keylen)
179362306a36Sopenharmony_ci{
179462306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_skcipher_ctx(cipher);
179562306a36Sopenharmony_ci
179662306a36Sopenharmony_ci	if (ctx->cipher.mode == CIPHER_MODE_XTS)
179762306a36Sopenharmony_ci		/* XTS includes two keys of equal length */
179862306a36Sopenharmony_ci		keylen = keylen / 2;
179962306a36Sopenharmony_ci
180062306a36Sopenharmony_ci	switch (keylen) {
180162306a36Sopenharmony_ci	case AES_KEYSIZE_128:
180262306a36Sopenharmony_ci		ctx->cipher_type = CIPHER_TYPE_AES128;
180362306a36Sopenharmony_ci		break;
180462306a36Sopenharmony_ci	case AES_KEYSIZE_192:
180562306a36Sopenharmony_ci		ctx->cipher_type = CIPHER_TYPE_AES192;
180662306a36Sopenharmony_ci		break;
180762306a36Sopenharmony_ci	case AES_KEYSIZE_256:
180862306a36Sopenharmony_ci		ctx->cipher_type = CIPHER_TYPE_AES256;
180962306a36Sopenharmony_ci		break;
181062306a36Sopenharmony_ci	default:
181162306a36Sopenharmony_ci		return -EINVAL;
181262306a36Sopenharmony_ci	}
181362306a36Sopenharmony_ci	WARN_ON((ctx->max_payload != SPU_MAX_PAYLOAD_INF) &&
181462306a36Sopenharmony_ci		((ctx->max_payload % AES_BLOCK_SIZE) != 0));
181562306a36Sopenharmony_ci	return 0;
181662306a36Sopenharmony_ci}
181762306a36Sopenharmony_ci
181862306a36Sopenharmony_cistatic int skcipher_setkey(struct crypto_skcipher *cipher, const u8 *key,
181962306a36Sopenharmony_ci			     unsigned int keylen)
182062306a36Sopenharmony_ci{
182162306a36Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
182262306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_skcipher_ctx(cipher);
182362306a36Sopenharmony_ci	struct spu_cipher_parms cipher_parms;
182462306a36Sopenharmony_ci	u32 alloc_len = 0;
182562306a36Sopenharmony_ci	int err;
182662306a36Sopenharmony_ci
182762306a36Sopenharmony_ci	flow_log("skcipher_setkey() keylen: %d\n", keylen);
182862306a36Sopenharmony_ci	flow_dump("  key: ", key, keylen);
182962306a36Sopenharmony_ci
183062306a36Sopenharmony_ci	switch (ctx->cipher.alg) {
183162306a36Sopenharmony_ci	case CIPHER_ALG_DES:
183262306a36Sopenharmony_ci		err = des_setkey(cipher, key, keylen);
183362306a36Sopenharmony_ci		break;
183462306a36Sopenharmony_ci	case CIPHER_ALG_3DES:
183562306a36Sopenharmony_ci		err = threedes_setkey(cipher, key, keylen);
183662306a36Sopenharmony_ci		break;
183762306a36Sopenharmony_ci	case CIPHER_ALG_AES:
183862306a36Sopenharmony_ci		err = aes_setkey(cipher, key, keylen);
183962306a36Sopenharmony_ci		break;
184062306a36Sopenharmony_ci	default:
184162306a36Sopenharmony_ci		pr_err("%s() Error: unknown cipher alg\n", __func__);
184262306a36Sopenharmony_ci		err = -EINVAL;
184362306a36Sopenharmony_ci	}
184462306a36Sopenharmony_ci	if (err)
184562306a36Sopenharmony_ci		return err;
184662306a36Sopenharmony_ci
184762306a36Sopenharmony_ci	memcpy(ctx->enckey, key, keylen);
184862306a36Sopenharmony_ci	ctx->enckeylen = keylen;
184962306a36Sopenharmony_ci
185062306a36Sopenharmony_ci	/* SPU needs XTS keys in the reverse order the crypto API presents */
185162306a36Sopenharmony_ci	if ((ctx->cipher.alg == CIPHER_ALG_AES) &&
185262306a36Sopenharmony_ci	    (ctx->cipher.mode == CIPHER_MODE_XTS)) {
185362306a36Sopenharmony_ci		unsigned int xts_keylen = keylen / 2;
185462306a36Sopenharmony_ci
185562306a36Sopenharmony_ci		memcpy(ctx->enckey, key + xts_keylen, xts_keylen);
185662306a36Sopenharmony_ci		memcpy(ctx->enckey + xts_keylen, key, xts_keylen);
185762306a36Sopenharmony_ci	}
185862306a36Sopenharmony_ci
185962306a36Sopenharmony_ci	if (spu->spu_type == SPU_TYPE_SPUM)
186062306a36Sopenharmony_ci		alloc_len = BCM_HDR_LEN + SPU_HEADER_ALLOC_LEN;
186162306a36Sopenharmony_ci	else if (spu->spu_type == SPU_TYPE_SPU2)
186262306a36Sopenharmony_ci		alloc_len = BCM_HDR_LEN + SPU2_HEADER_ALLOC_LEN;
186362306a36Sopenharmony_ci	memset(ctx->bcm_spu_req_hdr, 0, alloc_len);
186462306a36Sopenharmony_ci	cipher_parms.iv_buf = NULL;
186562306a36Sopenharmony_ci	cipher_parms.iv_len = crypto_skcipher_ivsize(cipher);
186662306a36Sopenharmony_ci	flow_log("%s: iv_len %u\n", __func__, cipher_parms.iv_len);
186762306a36Sopenharmony_ci
186862306a36Sopenharmony_ci	cipher_parms.alg = ctx->cipher.alg;
186962306a36Sopenharmony_ci	cipher_parms.mode = ctx->cipher.mode;
187062306a36Sopenharmony_ci	cipher_parms.type = ctx->cipher_type;
187162306a36Sopenharmony_ci	cipher_parms.key_buf = ctx->enckey;
187262306a36Sopenharmony_ci	cipher_parms.key_len = ctx->enckeylen;
187362306a36Sopenharmony_ci
187462306a36Sopenharmony_ci	/* Prepend SPU request message with BCM header */
187562306a36Sopenharmony_ci	memcpy(ctx->bcm_spu_req_hdr, BCMHEADER, BCM_HDR_LEN);
187662306a36Sopenharmony_ci	ctx->spu_req_hdr_len =
187762306a36Sopenharmony_ci	    spu->spu_cipher_req_init(ctx->bcm_spu_req_hdr + BCM_HDR_LEN,
187862306a36Sopenharmony_ci				     &cipher_parms);
187962306a36Sopenharmony_ci
188062306a36Sopenharmony_ci	ctx->spu_resp_hdr_len = spu->spu_response_hdr_len(ctx->authkeylen,
188162306a36Sopenharmony_ci							  ctx->enckeylen,
188262306a36Sopenharmony_ci							  false);
188362306a36Sopenharmony_ci
188462306a36Sopenharmony_ci	atomic_inc(&iproc_priv.setkey_cnt[SPU_OP_CIPHER]);
188562306a36Sopenharmony_ci
188662306a36Sopenharmony_ci	return 0;
188762306a36Sopenharmony_ci}
188862306a36Sopenharmony_ci
188962306a36Sopenharmony_cistatic int skcipher_encrypt(struct skcipher_request *req)
189062306a36Sopenharmony_ci{
189162306a36Sopenharmony_ci	flow_log("skcipher_encrypt() nbytes:%u\n", req->cryptlen);
189262306a36Sopenharmony_ci
189362306a36Sopenharmony_ci	return skcipher_enqueue(req, true);
189462306a36Sopenharmony_ci}
189562306a36Sopenharmony_ci
189662306a36Sopenharmony_cistatic int skcipher_decrypt(struct skcipher_request *req)
189762306a36Sopenharmony_ci{
189862306a36Sopenharmony_ci	flow_log("skcipher_decrypt() nbytes:%u\n", req->cryptlen);
189962306a36Sopenharmony_ci	return skcipher_enqueue(req, false);
190062306a36Sopenharmony_ci}
190162306a36Sopenharmony_ci
190262306a36Sopenharmony_cistatic int ahash_enqueue(struct ahash_request *req)
190362306a36Sopenharmony_ci{
190462306a36Sopenharmony_ci	struct iproc_reqctx_s *rctx = ahash_request_ctx(req);
190562306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
190662306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm);
190762306a36Sopenharmony_ci	int err;
190862306a36Sopenharmony_ci	const char *alg_name;
190962306a36Sopenharmony_ci
191062306a36Sopenharmony_ci	flow_log("ahash_enqueue() nbytes:%u\n", req->nbytes);
191162306a36Sopenharmony_ci
191262306a36Sopenharmony_ci	rctx->gfp = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
191362306a36Sopenharmony_ci		       CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
191462306a36Sopenharmony_ci	rctx->parent = &req->base;
191562306a36Sopenharmony_ci	rctx->ctx = ctx;
191662306a36Sopenharmony_ci	rctx->bd_suppress = true;
191762306a36Sopenharmony_ci	memset(&rctx->mb_mssg, 0, sizeof(struct brcm_message));
191862306a36Sopenharmony_ci
191962306a36Sopenharmony_ci	/* Initialize position in src scatterlist */
192062306a36Sopenharmony_ci	rctx->src_sg = req->src;
192162306a36Sopenharmony_ci	rctx->src_skip = 0;
192262306a36Sopenharmony_ci	rctx->src_nents = 0;
192362306a36Sopenharmony_ci	rctx->dst_sg = NULL;
192462306a36Sopenharmony_ci	rctx->dst_skip = 0;
192562306a36Sopenharmony_ci	rctx->dst_nents = 0;
192662306a36Sopenharmony_ci
192762306a36Sopenharmony_ci	/* SPU2 hardware does not compute hash of zero length data */
192862306a36Sopenharmony_ci	if ((rctx->is_final == 1) && (rctx->total_todo == 0) &&
192962306a36Sopenharmony_ci	    (iproc_priv.spu.spu_type == SPU_TYPE_SPU2)) {
193062306a36Sopenharmony_ci		alg_name = crypto_ahash_alg_name(tfm);
193162306a36Sopenharmony_ci		flow_log("Doing %sfinal %s zero-len hash request in software\n",
193262306a36Sopenharmony_ci			 rctx->is_final ? "" : "non-", alg_name);
193362306a36Sopenharmony_ci		err = do_shash((unsigned char *)alg_name, req->result,
193462306a36Sopenharmony_ci			       NULL, 0, NULL, 0, ctx->authkey,
193562306a36Sopenharmony_ci			       ctx->authkeylen);
193662306a36Sopenharmony_ci		if (err < 0)
193762306a36Sopenharmony_ci			flow_log("Hash request failed with error %d\n", err);
193862306a36Sopenharmony_ci		return err;
193962306a36Sopenharmony_ci	}
194062306a36Sopenharmony_ci	/* Choose a SPU to process this request */
194162306a36Sopenharmony_ci	rctx->chan_idx = select_channel();
194262306a36Sopenharmony_ci
194362306a36Sopenharmony_ci	err = handle_ahash_req(rctx);
194462306a36Sopenharmony_ci	if (err != -EINPROGRESS)
194562306a36Sopenharmony_ci		/* synchronous result */
194662306a36Sopenharmony_ci		spu_chunk_cleanup(rctx);
194762306a36Sopenharmony_ci
194862306a36Sopenharmony_ci	if (err == -EAGAIN)
194962306a36Sopenharmony_ci		/*
195062306a36Sopenharmony_ci		 * we saved data in hash carry, but tell crypto API
195162306a36Sopenharmony_ci		 * we successfully completed request.
195262306a36Sopenharmony_ci		 */
195362306a36Sopenharmony_ci		err = 0;
195462306a36Sopenharmony_ci
195562306a36Sopenharmony_ci	return err;
195662306a36Sopenharmony_ci}
195762306a36Sopenharmony_ci
195862306a36Sopenharmony_cistatic int __ahash_init(struct ahash_request *req)
195962306a36Sopenharmony_ci{
196062306a36Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
196162306a36Sopenharmony_ci	struct iproc_reqctx_s *rctx = ahash_request_ctx(req);
196262306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
196362306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm);
196462306a36Sopenharmony_ci
196562306a36Sopenharmony_ci	flow_log("%s()\n", __func__);
196662306a36Sopenharmony_ci
196762306a36Sopenharmony_ci	/* Initialize the context */
196862306a36Sopenharmony_ci	rctx->hash_carry_len = 0;
196962306a36Sopenharmony_ci	rctx->is_final = 0;
197062306a36Sopenharmony_ci
197162306a36Sopenharmony_ci	rctx->total_todo = 0;
197262306a36Sopenharmony_ci	rctx->src_sent = 0;
197362306a36Sopenharmony_ci	rctx->total_sent = 0;
197462306a36Sopenharmony_ci	rctx->total_received = 0;
197562306a36Sopenharmony_ci
197662306a36Sopenharmony_ci	ctx->digestsize = crypto_ahash_digestsize(tfm);
197762306a36Sopenharmony_ci	/* If we add a hash whose digest is larger, catch it here. */
197862306a36Sopenharmony_ci	WARN_ON(ctx->digestsize > MAX_DIGEST_SIZE);
197962306a36Sopenharmony_ci
198062306a36Sopenharmony_ci	rctx->is_sw_hmac = false;
198162306a36Sopenharmony_ci
198262306a36Sopenharmony_ci	ctx->spu_resp_hdr_len = spu->spu_response_hdr_len(ctx->authkeylen, 0,
198362306a36Sopenharmony_ci							  true);
198462306a36Sopenharmony_ci
198562306a36Sopenharmony_ci	return 0;
198662306a36Sopenharmony_ci}
198762306a36Sopenharmony_ci
198862306a36Sopenharmony_ci/**
198962306a36Sopenharmony_ci * spu_no_incr_hash() - Determine whether incremental hashing is supported.
199062306a36Sopenharmony_ci * @ctx:  Crypto session context
199162306a36Sopenharmony_ci *
199262306a36Sopenharmony_ci * SPU-2 does not support incremental hashing (we'll have to revisit and
199362306a36Sopenharmony_ci * condition based on chip revision or device tree entry if future versions do
199462306a36Sopenharmony_ci * support incremental hash)
199562306a36Sopenharmony_ci *
199662306a36Sopenharmony_ci * SPU-M also doesn't support incremental hashing of AES-XCBC
199762306a36Sopenharmony_ci *
199862306a36Sopenharmony_ci * Return: true if incremental hashing is not supported
199962306a36Sopenharmony_ci *         false otherwise
200062306a36Sopenharmony_ci */
200162306a36Sopenharmony_cistatic bool spu_no_incr_hash(struct iproc_ctx_s *ctx)
200262306a36Sopenharmony_ci{
200362306a36Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
200462306a36Sopenharmony_ci
200562306a36Sopenharmony_ci	if (spu->spu_type == SPU_TYPE_SPU2)
200662306a36Sopenharmony_ci		return true;
200762306a36Sopenharmony_ci
200862306a36Sopenharmony_ci	if ((ctx->auth.alg == HASH_ALG_AES) &&
200962306a36Sopenharmony_ci	    (ctx->auth.mode == HASH_MODE_XCBC))
201062306a36Sopenharmony_ci		return true;
201162306a36Sopenharmony_ci
201262306a36Sopenharmony_ci	/* Otherwise, incremental hashing is supported */
201362306a36Sopenharmony_ci	return false;
201462306a36Sopenharmony_ci}
201562306a36Sopenharmony_ci
201662306a36Sopenharmony_cistatic int ahash_init(struct ahash_request *req)
201762306a36Sopenharmony_ci{
201862306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
201962306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm);
202062306a36Sopenharmony_ci	const char *alg_name;
202162306a36Sopenharmony_ci	struct crypto_shash *hash;
202262306a36Sopenharmony_ci	int ret;
202362306a36Sopenharmony_ci	gfp_t gfp;
202462306a36Sopenharmony_ci
202562306a36Sopenharmony_ci	if (spu_no_incr_hash(ctx)) {
202662306a36Sopenharmony_ci		/*
202762306a36Sopenharmony_ci		 * If we get an incremental hashing request and it's not
202862306a36Sopenharmony_ci		 * supported by the hardware, we need to handle it in software
202962306a36Sopenharmony_ci		 * by calling synchronous hash functions.
203062306a36Sopenharmony_ci		 */
203162306a36Sopenharmony_ci		alg_name = crypto_ahash_alg_name(tfm);
203262306a36Sopenharmony_ci		hash = crypto_alloc_shash(alg_name, 0, 0);
203362306a36Sopenharmony_ci		if (IS_ERR(hash)) {
203462306a36Sopenharmony_ci			ret = PTR_ERR(hash);
203562306a36Sopenharmony_ci			goto err;
203662306a36Sopenharmony_ci		}
203762306a36Sopenharmony_ci
203862306a36Sopenharmony_ci		gfp = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
203962306a36Sopenharmony_ci		       CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
204062306a36Sopenharmony_ci		ctx->shash = kmalloc(sizeof(*ctx->shash) +
204162306a36Sopenharmony_ci				     crypto_shash_descsize(hash), gfp);
204262306a36Sopenharmony_ci		if (!ctx->shash) {
204362306a36Sopenharmony_ci			ret = -ENOMEM;
204462306a36Sopenharmony_ci			goto err_hash;
204562306a36Sopenharmony_ci		}
204662306a36Sopenharmony_ci		ctx->shash->tfm = hash;
204762306a36Sopenharmony_ci
204862306a36Sopenharmony_ci		/* Set the key using data we already have from setkey */
204962306a36Sopenharmony_ci		if (ctx->authkeylen > 0) {
205062306a36Sopenharmony_ci			ret = crypto_shash_setkey(hash, ctx->authkey,
205162306a36Sopenharmony_ci						  ctx->authkeylen);
205262306a36Sopenharmony_ci			if (ret)
205362306a36Sopenharmony_ci				goto err_shash;
205462306a36Sopenharmony_ci		}
205562306a36Sopenharmony_ci
205662306a36Sopenharmony_ci		/* Initialize hash w/ this key and other params */
205762306a36Sopenharmony_ci		ret = crypto_shash_init(ctx->shash);
205862306a36Sopenharmony_ci		if (ret)
205962306a36Sopenharmony_ci			goto err_shash;
206062306a36Sopenharmony_ci	} else {
206162306a36Sopenharmony_ci		/* Otherwise call the internal function which uses SPU hw */
206262306a36Sopenharmony_ci		ret = __ahash_init(req);
206362306a36Sopenharmony_ci	}
206462306a36Sopenharmony_ci
206562306a36Sopenharmony_ci	return ret;
206662306a36Sopenharmony_ci
206762306a36Sopenharmony_cierr_shash:
206862306a36Sopenharmony_ci	kfree(ctx->shash);
206962306a36Sopenharmony_cierr_hash:
207062306a36Sopenharmony_ci	crypto_free_shash(hash);
207162306a36Sopenharmony_cierr:
207262306a36Sopenharmony_ci	return ret;
207362306a36Sopenharmony_ci}
207462306a36Sopenharmony_ci
207562306a36Sopenharmony_cistatic int __ahash_update(struct ahash_request *req)
207662306a36Sopenharmony_ci{
207762306a36Sopenharmony_ci	struct iproc_reqctx_s *rctx = ahash_request_ctx(req);
207862306a36Sopenharmony_ci
207962306a36Sopenharmony_ci	flow_log("ahash_update() nbytes:%u\n", req->nbytes);
208062306a36Sopenharmony_ci
208162306a36Sopenharmony_ci	if (!req->nbytes)
208262306a36Sopenharmony_ci		return 0;
208362306a36Sopenharmony_ci	rctx->total_todo += req->nbytes;
208462306a36Sopenharmony_ci	rctx->src_sent = 0;
208562306a36Sopenharmony_ci
208662306a36Sopenharmony_ci	return ahash_enqueue(req);
208762306a36Sopenharmony_ci}
208862306a36Sopenharmony_ci
208962306a36Sopenharmony_cistatic int ahash_update(struct ahash_request *req)
209062306a36Sopenharmony_ci{
209162306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
209262306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm);
209362306a36Sopenharmony_ci	u8 *tmpbuf;
209462306a36Sopenharmony_ci	int ret;
209562306a36Sopenharmony_ci	int nents;
209662306a36Sopenharmony_ci	gfp_t gfp;
209762306a36Sopenharmony_ci
209862306a36Sopenharmony_ci	if (spu_no_incr_hash(ctx)) {
209962306a36Sopenharmony_ci		/*
210062306a36Sopenharmony_ci		 * If we get an incremental hashing request and it's not
210162306a36Sopenharmony_ci		 * supported by the hardware, we need to handle it in software
210262306a36Sopenharmony_ci		 * by calling synchronous hash functions.
210362306a36Sopenharmony_ci		 */
210462306a36Sopenharmony_ci		if (req->src)
210562306a36Sopenharmony_ci			nents = sg_nents(req->src);
210662306a36Sopenharmony_ci		else
210762306a36Sopenharmony_ci			return -EINVAL;
210862306a36Sopenharmony_ci
210962306a36Sopenharmony_ci		/* Copy data from req scatterlist to tmp buffer */
211062306a36Sopenharmony_ci		gfp = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
211162306a36Sopenharmony_ci		       CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
211262306a36Sopenharmony_ci		tmpbuf = kmalloc(req->nbytes, gfp);
211362306a36Sopenharmony_ci		if (!tmpbuf)
211462306a36Sopenharmony_ci			return -ENOMEM;
211562306a36Sopenharmony_ci
211662306a36Sopenharmony_ci		if (sg_copy_to_buffer(req->src, nents, tmpbuf, req->nbytes) !=
211762306a36Sopenharmony_ci				req->nbytes) {
211862306a36Sopenharmony_ci			kfree(tmpbuf);
211962306a36Sopenharmony_ci			return -EINVAL;
212062306a36Sopenharmony_ci		}
212162306a36Sopenharmony_ci
212262306a36Sopenharmony_ci		/* Call synchronous update */
212362306a36Sopenharmony_ci		ret = crypto_shash_update(ctx->shash, tmpbuf, req->nbytes);
212462306a36Sopenharmony_ci		kfree(tmpbuf);
212562306a36Sopenharmony_ci	} else {
212662306a36Sopenharmony_ci		/* Otherwise call the internal function which uses SPU hw */
212762306a36Sopenharmony_ci		ret = __ahash_update(req);
212862306a36Sopenharmony_ci	}
212962306a36Sopenharmony_ci
213062306a36Sopenharmony_ci	return ret;
213162306a36Sopenharmony_ci}
213262306a36Sopenharmony_ci
213362306a36Sopenharmony_cistatic int __ahash_final(struct ahash_request *req)
213462306a36Sopenharmony_ci{
213562306a36Sopenharmony_ci	struct iproc_reqctx_s *rctx = ahash_request_ctx(req);
213662306a36Sopenharmony_ci
213762306a36Sopenharmony_ci	flow_log("ahash_final() nbytes:%u\n", req->nbytes);
213862306a36Sopenharmony_ci
213962306a36Sopenharmony_ci	rctx->is_final = 1;
214062306a36Sopenharmony_ci
214162306a36Sopenharmony_ci	return ahash_enqueue(req);
214262306a36Sopenharmony_ci}
214362306a36Sopenharmony_ci
214462306a36Sopenharmony_cistatic int ahash_final(struct ahash_request *req)
214562306a36Sopenharmony_ci{
214662306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
214762306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm);
214862306a36Sopenharmony_ci	int ret;
214962306a36Sopenharmony_ci
215062306a36Sopenharmony_ci	if (spu_no_incr_hash(ctx)) {
215162306a36Sopenharmony_ci		/*
215262306a36Sopenharmony_ci		 * If we get an incremental hashing request and it's not
215362306a36Sopenharmony_ci		 * supported by the hardware, we need to handle it in software
215462306a36Sopenharmony_ci		 * by calling synchronous hash functions.
215562306a36Sopenharmony_ci		 */
215662306a36Sopenharmony_ci		ret = crypto_shash_final(ctx->shash, req->result);
215762306a36Sopenharmony_ci
215862306a36Sopenharmony_ci		/* Done with hash, can deallocate it now */
215962306a36Sopenharmony_ci		crypto_free_shash(ctx->shash->tfm);
216062306a36Sopenharmony_ci		kfree(ctx->shash);
216162306a36Sopenharmony_ci
216262306a36Sopenharmony_ci	} else {
216362306a36Sopenharmony_ci		/* Otherwise call the internal function which uses SPU hw */
216462306a36Sopenharmony_ci		ret = __ahash_final(req);
216562306a36Sopenharmony_ci	}
216662306a36Sopenharmony_ci
216762306a36Sopenharmony_ci	return ret;
216862306a36Sopenharmony_ci}
216962306a36Sopenharmony_ci
217062306a36Sopenharmony_cistatic int __ahash_finup(struct ahash_request *req)
217162306a36Sopenharmony_ci{
217262306a36Sopenharmony_ci	struct iproc_reqctx_s *rctx = ahash_request_ctx(req);
217362306a36Sopenharmony_ci
217462306a36Sopenharmony_ci	flow_log("ahash_finup() nbytes:%u\n", req->nbytes);
217562306a36Sopenharmony_ci
217662306a36Sopenharmony_ci	rctx->total_todo += req->nbytes;
217762306a36Sopenharmony_ci	rctx->src_sent = 0;
217862306a36Sopenharmony_ci	rctx->is_final = 1;
217962306a36Sopenharmony_ci
218062306a36Sopenharmony_ci	return ahash_enqueue(req);
218162306a36Sopenharmony_ci}
218262306a36Sopenharmony_ci
218362306a36Sopenharmony_cistatic int ahash_finup(struct ahash_request *req)
218462306a36Sopenharmony_ci{
218562306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
218662306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm);
218762306a36Sopenharmony_ci	u8 *tmpbuf;
218862306a36Sopenharmony_ci	int ret;
218962306a36Sopenharmony_ci	int nents;
219062306a36Sopenharmony_ci	gfp_t gfp;
219162306a36Sopenharmony_ci
219262306a36Sopenharmony_ci	if (spu_no_incr_hash(ctx)) {
219362306a36Sopenharmony_ci		/*
219462306a36Sopenharmony_ci		 * If we get an incremental hashing request and it's not
219562306a36Sopenharmony_ci		 * supported by the hardware, we need to handle it in software
219662306a36Sopenharmony_ci		 * by calling synchronous hash functions.
219762306a36Sopenharmony_ci		 */
219862306a36Sopenharmony_ci		if (req->src) {
219962306a36Sopenharmony_ci			nents = sg_nents(req->src);
220062306a36Sopenharmony_ci		} else {
220162306a36Sopenharmony_ci			ret = -EINVAL;
220262306a36Sopenharmony_ci			goto ahash_finup_exit;
220362306a36Sopenharmony_ci		}
220462306a36Sopenharmony_ci
220562306a36Sopenharmony_ci		/* Copy data from req scatterlist to tmp buffer */
220662306a36Sopenharmony_ci		gfp = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
220762306a36Sopenharmony_ci		       CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
220862306a36Sopenharmony_ci		tmpbuf = kmalloc(req->nbytes, gfp);
220962306a36Sopenharmony_ci		if (!tmpbuf) {
221062306a36Sopenharmony_ci			ret = -ENOMEM;
221162306a36Sopenharmony_ci			goto ahash_finup_exit;
221262306a36Sopenharmony_ci		}
221362306a36Sopenharmony_ci
221462306a36Sopenharmony_ci		if (sg_copy_to_buffer(req->src, nents, tmpbuf, req->nbytes) !=
221562306a36Sopenharmony_ci				req->nbytes) {
221662306a36Sopenharmony_ci			ret = -EINVAL;
221762306a36Sopenharmony_ci			goto ahash_finup_free;
221862306a36Sopenharmony_ci		}
221962306a36Sopenharmony_ci
222062306a36Sopenharmony_ci		/* Call synchronous update */
222162306a36Sopenharmony_ci		ret = crypto_shash_finup(ctx->shash, tmpbuf, req->nbytes,
222262306a36Sopenharmony_ci					 req->result);
222362306a36Sopenharmony_ci	} else {
222462306a36Sopenharmony_ci		/* Otherwise call the internal function which uses SPU hw */
222562306a36Sopenharmony_ci		return __ahash_finup(req);
222662306a36Sopenharmony_ci	}
222762306a36Sopenharmony_ciahash_finup_free:
222862306a36Sopenharmony_ci	kfree(tmpbuf);
222962306a36Sopenharmony_ci
223062306a36Sopenharmony_ciahash_finup_exit:
223162306a36Sopenharmony_ci	/* Done with hash, can deallocate it now */
223262306a36Sopenharmony_ci	crypto_free_shash(ctx->shash->tfm);
223362306a36Sopenharmony_ci	kfree(ctx->shash);
223462306a36Sopenharmony_ci	return ret;
223562306a36Sopenharmony_ci}
223662306a36Sopenharmony_ci
223762306a36Sopenharmony_cistatic int ahash_digest(struct ahash_request *req)
223862306a36Sopenharmony_ci{
223962306a36Sopenharmony_ci	int err;
224062306a36Sopenharmony_ci
224162306a36Sopenharmony_ci	flow_log("ahash_digest() nbytes:%u\n", req->nbytes);
224262306a36Sopenharmony_ci
224362306a36Sopenharmony_ci	/* whole thing at once */
224462306a36Sopenharmony_ci	err = __ahash_init(req);
224562306a36Sopenharmony_ci	if (!err)
224662306a36Sopenharmony_ci		err = __ahash_finup(req);
224762306a36Sopenharmony_ci
224862306a36Sopenharmony_ci	return err;
224962306a36Sopenharmony_ci}
225062306a36Sopenharmony_ci
225162306a36Sopenharmony_cistatic int ahash_setkey(struct crypto_ahash *ahash, const u8 *key,
225262306a36Sopenharmony_ci			unsigned int keylen)
225362306a36Sopenharmony_ci{
225462306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_ahash_ctx(ahash);
225562306a36Sopenharmony_ci
225662306a36Sopenharmony_ci	flow_log("%s() ahash:%p key:%p keylen:%u\n",
225762306a36Sopenharmony_ci		 __func__, ahash, key, keylen);
225862306a36Sopenharmony_ci	flow_dump("  key: ", key, keylen);
225962306a36Sopenharmony_ci
226062306a36Sopenharmony_ci	if (ctx->auth.alg == HASH_ALG_AES) {
226162306a36Sopenharmony_ci		switch (keylen) {
226262306a36Sopenharmony_ci		case AES_KEYSIZE_128:
226362306a36Sopenharmony_ci			ctx->cipher_type = CIPHER_TYPE_AES128;
226462306a36Sopenharmony_ci			break;
226562306a36Sopenharmony_ci		case AES_KEYSIZE_192:
226662306a36Sopenharmony_ci			ctx->cipher_type = CIPHER_TYPE_AES192;
226762306a36Sopenharmony_ci			break;
226862306a36Sopenharmony_ci		case AES_KEYSIZE_256:
226962306a36Sopenharmony_ci			ctx->cipher_type = CIPHER_TYPE_AES256;
227062306a36Sopenharmony_ci			break;
227162306a36Sopenharmony_ci		default:
227262306a36Sopenharmony_ci			pr_err("%s() Error: Invalid key length\n", __func__);
227362306a36Sopenharmony_ci			return -EINVAL;
227462306a36Sopenharmony_ci		}
227562306a36Sopenharmony_ci	} else {
227662306a36Sopenharmony_ci		pr_err("%s() Error: unknown hash alg\n", __func__);
227762306a36Sopenharmony_ci		return -EINVAL;
227862306a36Sopenharmony_ci	}
227962306a36Sopenharmony_ci	memcpy(ctx->authkey, key, keylen);
228062306a36Sopenharmony_ci	ctx->authkeylen = keylen;
228162306a36Sopenharmony_ci
228262306a36Sopenharmony_ci	return 0;
228362306a36Sopenharmony_ci}
228462306a36Sopenharmony_ci
228562306a36Sopenharmony_cistatic int ahash_export(struct ahash_request *req, void *out)
228662306a36Sopenharmony_ci{
228762306a36Sopenharmony_ci	const struct iproc_reqctx_s *rctx = ahash_request_ctx(req);
228862306a36Sopenharmony_ci	struct spu_hash_export_s *spu_exp = (struct spu_hash_export_s *)out;
228962306a36Sopenharmony_ci
229062306a36Sopenharmony_ci	spu_exp->total_todo = rctx->total_todo;
229162306a36Sopenharmony_ci	spu_exp->total_sent = rctx->total_sent;
229262306a36Sopenharmony_ci	spu_exp->is_sw_hmac = rctx->is_sw_hmac;
229362306a36Sopenharmony_ci	memcpy(spu_exp->hash_carry, rctx->hash_carry, sizeof(rctx->hash_carry));
229462306a36Sopenharmony_ci	spu_exp->hash_carry_len = rctx->hash_carry_len;
229562306a36Sopenharmony_ci	memcpy(spu_exp->incr_hash, rctx->incr_hash, sizeof(rctx->incr_hash));
229662306a36Sopenharmony_ci
229762306a36Sopenharmony_ci	return 0;
229862306a36Sopenharmony_ci}
229962306a36Sopenharmony_ci
230062306a36Sopenharmony_cistatic int ahash_import(struct ahash_request *req, const void *in)
230162306a36Sopenharmony_ci{
230262306a36Sopenharmony_ci	struct iproc_reqctx_s *rctx = ahash_request_ctx(req);
230362306a36Sopenharmony_ci	struct spu_hash_export_s *spu_exp = (struct spu_hash_export_s *)in;
230462306a36Sopenharmony_ci
230562306a36Sopenharmony_ci	rctx->total_todo = spu_exp->total_todo;
230662306a36Sopenharmony_ci	rctx->total_sent = spu_exp->total_sent;
230762306a36Sopenharmony_ci	rctx->is_sw_hmac = spu_exp->is_sw_hmac;
230862306a36Sopenharmony_ci	memcpy(rctx->hash_carry, spu_exp->hash_carry, sizeof(rctx->hash_carry));
230962306a36Sopenharmony_ci	rctx->hash_carry_len = spu_exp->hash_carry_len;
231062306a36Sopenharmony_ci	memcpy(rctx->incr_hash, spu_exp->incr_hash, sizeof(rctx->incr_hash));
231162306a36Sopenharmony_ci
231262306a36Sopenharmony_ci	return 0;
231362306a36Sopenharmony_ci}
231462306a36Sopenharmony_ci
231562306a36Sopenharmony_cistatic int ahash_hmac_setkey(struct crypto_ahash *ahash, const u8 *key,
231662306a36Sopenharmony_ci			     unsigned int keylen)
231762306a36Sopenharmony_ci{
231862306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_ahash_ctx(ahash);
231962306a36Sopenharmony_ci	unsigned int blocksize =
232062306a36Sopenharmony_ci		crypto_tfm_alg_blocksize(crypto_ahash_tfm(ahash));
232162306a36Sopenharmony_ci	unsigned int digestsize = crypto_ahash_digestsize(ahash);
232262306a36Sopenharmony_ci	unsigned int index;
232362306a36Sopenharmony_ci	int rc;
232462306a36Sopenharmony_ci
232562306a36Sopenharmony_ci	flow_log("%s() ahash:%p key:%p keylen:%u blksz:%u digestsz:%u\n",
232662306a36Sopenharmony_ci		 __func__, ahash, key, keylen, blocksize, digestsize);
232762306a36Sopenharmony_ci	flow_dump("  key: ", key, keylen);
232862306a36Sopenharmony_ci
232962306a36Sopenharmony_ci	if (keylen > blocksize) {
233062306a36Sopenharmony_ci		switch (ctx->auth.alg) {
233162306a36Sopenharmony_ci		case HASH_ALG_MD5:
233262306a36Sopenharmony_ci			rc = do_shash("md5", ctx->authkey, key, keylen, NULL,
233362306a36Sopenharmony_ci				      0, NULL, 0);
233462306a36Sopenharmony_ci			break;
233562306a36Sopenharmony_ci		case HASH_ALG_SHA1:
233662306a36Sopenharmony_ci			rc = do_shash("sha1", ctx->authkey, key, keylen, NULL,
233762306a36Sopenharmony_ci				      0, NULL, 0);
233862306a36Sopenharmony_ci			break;
233962306a36Sopenharmony_ci		case HASH_ALG_SHA224:
234062306a36Sopenharmony_ci			rc = do_shash("sha224", ctx->authkey, key, keylen, NULL,
234162306a36Sopenharmony_ci				      0, NULL, 0);
234262306a36Sopenharmony_ci			break;
234362306a36Sopenharmony_ci		case HASH_ALG_SHA256:
234462306a36Sopenharmony_ci			rc = do_shash("sha256", ctx->authkey, key, keylen, NULL,
234562306a36Sopenharmony_ci				      0, NULL, 0);
234662306a36Sopenharmony_ci			break;
234762306a36Sopenharmony_ci		case HASH_ALG_SHA384:
234862306a36Sopenharmony_ci			rc = do_shash("sha384", ctx->authkey, key, keylen, NULL,
234962306a36Sopenharmony_ci				      0, NULL, 0);
235062306a36Sopenharmony_ci			break;
235162306a36Sopenharmony_ci		case HASH_ALG_SHA512:
235262306a36Sopenharmony_ci			rc = do_shash("sha512", ctx->authkey, key, keylen, NULL,
235362306a36Sopenharmony_ci				      0, NULL, 0);
235462306a36Sopenharmony_ci			break;
235562306a36Sopenharmony_ci		case HASH_ALG_SHA3_224:
235662306a36Sopenharmony_ci			rc = do_shash("sha3-224", ctx->authkey, key, keylen,
235762306a36Sopenharmony_ci				      NULL, 0, NULL, 0);
235862306a36Sopenharmony_ci			break;
235962306a36Sopenharmony_ci		case HASH_ALG_SHA3_256:
236062306a36Sopenharmony_ci			rc = do_shash("sha3-256", ctx->authkey, key, keylen,
236162306a36Sopenharmony_ci				      NULL, 0, NULL, 0);
236262306a36Sopenharmony_ci			break;
236362306a36Sopenharmony_ci		case HASH_ALG_SHA3_384:
236462306a36Sopenharmony_ci			rc = do_shash("sha3-384", ctx->authkey, key, keylen,
236562306a36Sopenharmony_ci				      NULL, 0, NULL, 0);
236662306a36Sopenharmony_ci			break;
236762306a36Sopenharmony_ci		case HASH_ALG_SHA3_512:
236862306a36Sopenharmony_ci			rc = do_shash("sha3-512", ctx->authkey, key, keylen,
236962306a36Sopenharmony_ci				      NULL, 0, NULL, 0);
237062306a36Sopenharmony_ci			break;
237162306a36Sopenharmony_ci		default:
237262306a36Sopenharmony_ci			pr_err("%s() Error: unknown hash alg\n", __func__);
237362306a36Sopenharmony_ci			return -EINVAL;
237462306a36Sopenharmony_ci		}
237562306a36Sopenharmony_ci		if (rc < 0) {
237662306a36Sopenharmony_ci			pr_err("%s() Error %d computing shash for %s\n",
237762306a36Sopenharmony_ci			       __func__, rc, hash_alg_name[ctx->auth.alg]);
237862306a36Sopenharmony_ci			return rc;
237962306a36Sopenharmony_ci		}
238062306a36Sopenharmony_ci		ctx->authkeylen = digestsize;
238162306a36Sopenharmony_ci
238262306a36Sopenharmony_ci		flow_log("  keylen > digestsize... hashed\n");
238362306a36Sopenharmony_ci		flow_dump("  newkey: ", ctx->authkey, ctx->authkeylen);
238462306a36Sopenharmony_ci	} else {
238562306a36Sopenharmony_ci		memcpy(ctx->authkey, key, keylen);
238662306a36Sopenharmony_ci		ctx->authkeylen = keylen;
238762306a36Sopenharmony_ci	}
238862306a36Sopenharmony_ci
238962306a36Sopenharmony_ci	/*
239062306a36Sopenharmony_ci	 * Full HMAC operation in SPUM is not verified,
239162306a36Sopenharmony_ci	 * So keeping the generation of IPAD, OPAD and
239262306a36Sopenharmony_ci	 * outer hashing in software.
239362306a36Sopenharmony_ci	 */
239462306a36Sopenharmony_ci	if (iproc_priv.spu.spu_type == SPU_TYPE_SPUM) {
239562306a36Sopenharmony_ci		memcpy(ctx->ipad, ctx->authkey, ctx->authkeylen);
239662306a36Sopenharmony_ci		memset(ctx->ipad + ctx->authkeylen, 0,
239762306a36Sopenharmony_ci		       blocksize - ctx->authkeylen);
239862306a36Sopenharmony_ci		ctx->authkeylen = 0;
239962306a36Sopenharmony_ci		unsafe_memcpy(ctx->opad, ctx->ipad, blocksize,
240062306a36Sopenharmony_ci			      "fortified memcpy causes -Wrestrict warning");
240162306a36Sopenharmony_ci
240262306a36Sopenharmony_ci		for (index = 0; index < blocksize; index++) {
240362306a36Sopenharmony_ci			ctx->ipad[index] ^= HMAC_IPAD_VALUE;
240462306a36Sopenharmony_ci			ctx->opad[index] ^= HMAC_OPAD_VALUE;
240562306a36Sopenharmony_ci		}
240662306a36Sopenharmony_ci
240762306a36Sopenharmony_ci		flow_dump("  ipad: ", ctx->ipad, blocksize);
240862306a36Sopenharmony_ci		flow_dump("  opad: ", ctx->opad, blocksize);
240962306a36Sopenharmony_ci	}
241062306a36Sopenharmony_ci	ctx->digestsize = digestsize;
241162306a36Sopenharmony_ci	atomic_inc(&iproc_priv.setkey_cnt[SPU_OP_HMAC]);
241262306a36Sopenharmony_ci
241362306a36Sopenharmony_ci	return 0;
241462306a36Sopenharmony_ci}
241562306a36Sopenharmony_ci
241662306a36Sopenharmony_cistatic int ahash_hmac_init(struct ahash_request *req)
241762306a36Sopenharmony_ci{
241862306a36Sopenharmony_ci	struct iproc_reqctx_s *rctx = ahash_request_ctx(req);
241962306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
242062306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm);
242162306a36Sopenharmony_ci	unsigned int blocksize =
242262306a36Sopenharmony_ci			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
242362306a36Sopenharmony_ci
242462306a36Sopenharmony_ci	flow_log("ahash_hmac_init()\n");
242562306a36Sopenharmony_ci
242662306a36Sopenharmony_ci	/* init the context as a hash */
242762306a36Sopenharmony_ci	ahash_init(req);
242862306a36Sopenharmony_ci
242962306a36Sopenharmony_ci	if (!spu_no_incr_hash(ctx)) {
243062306a36Sopenharmony_ci		/* SPU-M can do incr hashing but needs sw for outer HMAC */
243162306a36Sopenharmony_ci		rctx->is_sw_hmac = true;
243262306a36Sopenharmony_ci		ctx->auth.mode = HASH_MODE_HASH;
243362306a36Sopenharmony_ci		/* start with a prepended ipad */
243462306a36Sopenharmony_ci		memcpy(rctx->hash_carry, ctx->ipad, blocksize);
243562306a36Sopenharmony_ci		rctx->hash_carry_len = blocksize;
243662306a36Sopenharmony_ci		rctx->total_todo += blocksize;
243762306a36Sopenharmony_ci	}
243862306a36Sopenharmony_ci
243962306a36Sopenharmony_ci	return 0;
244062306a36Sopenharmony_ci}
244162306a36Sopenharmony_ci
244262306a36Sopenharmony_cistatic int ahash_hmac_update(struct ahash_request *req)
244362306a36Sopenharmony_ci{
244462306a36Sopenharmony_ci	flow_log("ahash_hmac_update() nbytes:%u\n", req->nbytes);
244562306a36Sopenharmony_ci
244662306a36Sopenharmony_ci	if (!req->nbytes)
244762306a36Sopenharmony_ci		return 0;
244862306a36Sopenharmony_ci
244962306a36Sopenharmony_ci	return ahash_update(req);
245062306a36Sopenharmony_ci}
245162306a36Sopenharmony_ci
245262306a36Sopenharmony_cistatic int ahash_hmac_final(struct ahash_request *req)
245362306a36Sopenharmony_ci{
245462306a36Sopenharmony_ci	flow_log("ahash_hmac_final() nbytes:%u\n", req->nbytes);
245562306a36Sopenharmony_ci
245662306a36Sopenharmony_ci	return ahash_final(req);
245762306a36Sopenharmony_ci}
245862306a36Sopenharmony_ci
245962306a36Sopenharmony_cistatic int ahash_hmac_finup(struct ahash_request *req)
246062306a36Sopenharmony_ci{
246162306a36Sopenharmony_ci	flow_log("ahash_hmac_finupl() nbytes:%u\n", req->nbytes);
246262306a36Sopenharmony_ci
246362306a36Sopenharmony_ci	return ahash_finup(req);
246462306a36Sopenharmony_ci}
246562306a36Sopenharmony_ci
246662306a36Sopenharmony_cistatic int ahash_hmac_digest(struct ahash_request *req)
246762306a36Sopenharmony_ci{
246862306a36Sopenharmony_ci	struct iproc_reqctx_s *rctx = ahash_request_ctx(req);
246962306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
247062306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm);
247162306a36Sopenharmony_ci	unsigned int blocksize =
247262306a36Sopenharmony_ci			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
247362306a36Sopenharmony_ci
247462306a36Sopenharmony_ci	flow_log("ahash_hmac_digest() nbytes:%u\n", req->nbytes);
247562306a36Sopenharmony_ci
247662306a36Sopenharmony_ci	/* Perform initialization and then call finup */
247762306a36Sopenharmony_ci	__ahash_init(req);
247862306a36Sopenharmony_ci
247962306a36Sopenharmony_ci	if (iproc_priv.spu.spu_type == SPU_TYPE_SPU2) {
248062306a36Sopenharmony_ci		/*
248162306a36Sopenharmony_ci		 * SPU2 supports full HMAC implementation in the
248262306a36Sopenharmony_ci		 * hardware, need not to generate IPAD, OPAD and
248362306a36Sopenharmony_ci		 * outer hash in software.
248462306a36Sopenharmony_ci		 * Only for hash key len > hash block size, SPU2
248562306a36Sopenharmony_ci		 * expects to perform hashing on the key, shorten
248662306a36Sopenharmony_ci		 * it to digest size and feed it as hash key.
248762306a36Sopenharmony_ci		 */
248862306a36Sopenharmony_ci		rctx->is_sw_hmac = false;
248962306a36Sopenharmony_ci		ctx->auth.mode = HASH_MODE_HMAC;
249062306a36Sopenharmony_ci	} else {
249162306a36Sopenharmony_ci		rctx->is_sw_hmac = true;
249262306a36Sopenharmony_ci		ctx->auth.mode = HASH_MODE_HASH;
249362306a36Sopenharmony_ci		/* start with a prepended ipad */
249462306a36Sopenharmony_ci		memcpy(rctx->hash_carry, ctx->ipad, blocksize);
249562306a36Sopenharmony_ci		rctx->hash_carry_len = blocksize;
249662306a36Sopenharmony_ci		rctx->total_todo += blocksize;
249762306a36Sopenharmony_ci	}
249862306a36Sopenharmony_ci
249962306a36Sopenharmony_ci	return __ahash_finup(req);
250062306a36Sopenharmony_ci}
250162306a36Sopenharmony_ci
250262306a36Sopenharmony_ci/* aead helpers */
250362306a36Sopenharmony_ci
250462306a36Sopenharmony_cistatic int aead_need_fallback(struct aead_request *req)
250562306a36Sopenharmony_ci{
250662306a36Sopenharmony_ci	struct iproc_reqctx_s *rctx = aead_request_ctx(req);
250762306a36Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
250862306a36Sopenharmony_ci	struct crypto_aead *aead = crypto_aead_reqtfm(req);
250962306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_aead_ctx(aead);
251062306a36Sopenharmony_ci	u32 payload_len;
251162306a36Sopenharmony_ci
251262306a36Sopenharmony_ci	/*
251362306a36Sopenharmony_ci	 * SPU hardware cannot handle the AES-GCM/CCM case where plaintext
251462306a36Sopenharmony_ci	 * and AAD are both 0 bytes long. So use fallback in this case.
251562306a36Sopenharmony_ci	 */
251662306a36Sopenharmony_ci	if (((ctx->cipher.mode == CIPHER_MODE_GCM) ||
251762306a36Sopenharmony_ci	     (ctx->cipher.mode == CIPHER_MODE_CCM)) &&
251862306a36Sopenharmony_ci	    (req->assoclen == 0)) {
251962306a36Sopenharmony_ci		if ((rctx->is_encrypt && (req->cryptlen == 0)) ||
252062306a36Sopenharmony_ci		    (!rctx->is_encrypt && (req->cryptlen == ctx->digestsize))) {
252162306a36Sopenharmony_ci			flow_log("AES GCM/CCM needs fallback for 0 len req\n");
252262306a36Sopenharmony_ci			return 1;
252362306a36Sopenharmony_ci		}
252462306a36Sopenharmony_ci	}
252562306a36Sopenharmony_ci
252662306a36Sopenharmony_ci	/* SPU-M hardware only supports CCM digest size of 8, 12, or 16 bytes */
252762306a36Sopenharmony_ci	if ((ctx->cipher.mode == CIPHER_MODE_CCM) &&
252862306a36Sopenharmony_ci	    (spu->spu_type == SPU_TYPE_SPUM) &&
252962306a36Sopenharmony_ci	    (ctx->digestsize != 8) && (ctx->digestsize != 12) &&
253062306a36Sopenharmony_ci	    (ctx->digestsize != 16)) {
253162306a36Sopenharmony_ci		flow_log("%s() AES CCM needs fallback for digest size %d\n",
253262306a36Sopenharmony_ci			 __func__, ctx->digestsize);
253362306a36Sopenharmony_ci		return 1;
253462306a36Sopenharmony_ci	}
253562306a36Sopenharmony_ci
253662306a36Sopenharmony_ci	/*
253762306a36Sopenharmony_ci	 * SPU-M on NSP has an issue where AES-CCM hash is not correct
253862306a36Sopenharmony_ci	 * when AAD size is 0
253962306a36Sopenharmony_ci	 */
254062306a36Sopenharmony_ci	if ((ctx->cipher.mode == CIPHER_MODE_CCM) &&
254162306a36Sopenharmony_ci	    (spu->spu_subtype == SPU_SUBTYPE_SPUM_NSP) &&
254262306a36Sopenharmony_ci	    (req->assoclen == 0)) {
254362306a36Sopenharmony_ci		flow_log("%s() AES_CCM needs fallback for 0 len AAD on NSP\n",
254462306a36Sopenharmony_ci			 __func__);
254562306a36Sopenharmony_ci		return 1;
254662306a36Sopenharmony_ci	}
254762306a36Sopenharmony_ci
254862306a36Sopenharmony_ci	/*
254962306a36Sopenharmony_ci	 * RFC4106 and RFC4543 cannot handle the case where AAD is other than
255062306a36Sopenharmony_ci	 * 16 or 20 bytes long. So use fallback in this case.
255162306a36Sopenharmony_ci	 */
255262306a36Sopenharmony_ci	if (ctx->cipher.mode == CIPHER_MODE_GCM &&
255362306a36Sopenharmony_ci	    ctx->cipher.alg == CIPHER_ALG_AES &&
255462306a36Sopenharmony_ci	    rctx->iv_ctr_len == GCM_RFC4106_IV_SIZE &&
255562306a36Sopenharmony_ci	    req->assoclen != 16 && req->assoclen != 20) {
255662306a36Sopenharmony_ci		flow_log("RFC4106/RFC4543 needs fallback for assoclen"
255762306a36Sopenharmony_ci			 " other than 16 or 20 bytes\n");
255862306a36Sopenharmony_ci		return 1;
255962306a36Sopenharmony_ci	}
256062306a36Sopenharmony_ci
256162306a36Sopenharmony_ci	payload_len = req->cryptlen;
256262306a36Sopenharmony_ci	if (spu->spu_type == SPU_TYPE_SPUM)
256362306a36Sopenharmony_ci		payload_len += req->assoclen;
256462306a36Sopenharmony_ci
256562306a36Sopenharmony_ci	flow_log("%s() payload len: %u\n", __func__, payload_len);
256662306a36Sopenharmony_ci
256762306a36Sopenharmony_ci	if (ctx->max_payload == SPU_MAX_PAYLOAD_INF)
256862306a36Sopenharmony_ci		return 0;
256962306a36Sopenharmony_ci	else
257062306a36Sopenharmony_ci		return payload_len > ctx->max_payload;
257162306a36Sopenharmony_ci}
257262306a36Sopenharmony_ci
257362306a36Sopenharmony_cistatic int aead_do_fallback(struct aead_request *req, bool is_encrypt)
257462306a36Sopenharmony_ci{
257562306a36Sopenharmony_ci	struct crypto_aead *aead = crypto_aead_reqtfm(req);
257662306a36Sopenharmony_ci	struct crypto_tfm *tfm = crypto_aead_tfm(aead);
257762306a36Sopenharmony_ci	struct iproc_reqctx_s *rctx = aead_request_ctx(req);
257862306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_tfm_ctx(tfm);
257962306a36Sopenharmony_ci	struct aead_request *subreq;
258062306a36Sopenharmony_ci
258162306a36Sopenharmony_ci	flow_log("%s() enc:%u\n", __func__, is_encrypt);
258262306a36Sopenharmony_ci
258362306a36Sopenharmony_ci	if (!ctx->fallback_cipher)
258462306a36Sopenharmony_ci		return -EINVAL;
258562306a36Sopenharmony_ci
258662306a36Sopenharmony_ci	subreq = &rctx->req;
258762306a36Sopenharmony_ci	aead_request_set_tfm(subreq, ctx->fallback_cipher);
258862306a36Sopenharmony_ci	aead_request_set_callback(subreq, aead_request_flags(req),
258962306a36Sopenharmony_ci				  req->base.complete, req->base.data);
259062306a36Sopenharmony_ci	aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
259162306a36Sopenharmony_ci			       req->iv);
259262306a36Sopenharmony_ci	aead_request_set_ad(subreq, req->assoclen);
259362306a36Sopenharmony_ci
259462306a36Sopenharmony_ci	return is_encrypt ? crypto_aead_encrypt(req) :
259562306a36Sopenharmony_ci			    crypto_aead_decrypt(req);
259662306a36Sopenharmony_ci}
259762306a36Sopenharmony_ci
259862306a36Sopenharmony_cistatic int aead_enqueue(struct aead_request *req, bool is_encrypt)
259962306a36Sopenharmony_ci{
260062306a36Sopenharmony_ci	struct iproc_reqctx_s *rctx = aead_request_ctx(req);
260162306a36Sopenharmony_ci	struct crypto_aead *aead = crypto_aead_reqtfm(req);
260262306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_aead_ctx(aead);
260362306a36Sopenharmony_ci	int err;
260462306a36Sopenharmony_ci
260562306a36Sopenharmony_ci	flow_log("%s() enc:%u\n", __func__, is_encrypt);
260662306a36Sopenharmony_ci
260762306a36Sopenharmony_ci	if (req->assoclen > MAX_ASSOC_SIZE) {
260862306a36Sopenharmony_ci		pr_err
260962306a36Sopenharmony_ci		    ("%s() Error: associated data too long. (%u > %u bytes)\n",
261062306a36Sopenharmony_ci		     __func__, req->assoclen, MAX_ASSOC_SIZE);
261162306a36Sopenharmony_ci		return -EINVAL;
261262306a36Sopenharmony_ci	}
261362306a36Sopenharmony_ci
261462306a36Sopenharmony_ci	rctx->gfp = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
261562306a36Sopenharmony_ci		       CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
261662306a36Sopenharmony_ci	rctx->parent = &req->base;
261762306a36Sopenharmony_ci	rctx->is_encrypt = is_encrypt;
261862306a36Sopenharmony_ci	rctx->bd_suppress = false;
261962306a36Sopenharmony_ci	rctx->total_todo = req->cryptlen;
262062306a36Sopenharmony_ci	rctx->src_sent = 0;
262162306a36Sopenharmony_ci	rctx->total_sent = 0;
262262306a36Sopenharmony_ci	rctx->total_received = 0;
262362306a36Sopenharmony_ci	rctx->is_sw_hmac = false;
262462306a36Sopenharmony_ci	rctx->ctx = ctx;
262562306a36Sopenharmony_ci	memset(&rctx->mb_mssg, 0, sizeof(struct brcm_message));
262662306a36Sopenharmony_ci
262762306a36Sopenharmony_ci	/* assoc data is at start of src sg */
262862306a36Sopenharmony_ci	rctx->assoc = req->src;
262962306a36Sopenharmony_ci
263062306a36Sopenharmony_ci	/*
263162306a36Sopenharmony_ci	 * Init current position in src scatterlist to be after assoc data.
263262306a36Sopenharmony_ci	 * src_skip set to buffer offset where data begins. (Assoc data could
263362306a36Sopenharmony_ci	 * end in the middle of a buffer.)
263462306a36Sopenharmony_ci	 */
263562306a36Sopenharmony_ci	if (spu_sg_at_offset(req->src, req->assoclen, &rctx->src_sg,
263662306a36Sopenharmony_ci			     &rctx->src_skip) < 0) {
263762306a36Sopenharmony_ci		pr_err("%s() Error: Unable to find start of src data\n",
263862306a36Sopenharmony_ci		       __func__);
263962306a36Sopenharmony_ci		return -EINVAL;
264062306a36Sopenharmony_ci	}
264162306a36Sopenharmony_ci
264262306a36Sopenharmony_ci	rctx->src_nents = 0;
264362306a36Sopenharmony_ci	rctx->dst_nents = 0;
264462306a36Sopenharmony_ci	if (req->dst == req->src) {
264562306a36Sopenharmony_ci		rctx->dst_sg = rctx->src_sg;
264662306a36Sopenharmony_ci		rctx->dst_skip = rctx->src_skip;
264762306a36Sopenharmony_ci	} else {
264862306a36Sopenharmony_ci		/*
264962306a36Sopenharmony_ci		 * Expect req->dst to have room for assoc data followed by
265062306a36Sopenharmony_ci		 * output data and ICV, if encrypt. So initialize dst_sg
265162306a36Sopenharmony_ci		 * to point beyond assoc len offset.
265262306a36Sopenharmony_ci		 */
265362306a36Sopenharmony_ci		if (spu_sg_at_offset(req->dst, req->assoclen, &rctx->dst_sg,
265462306a36Sopenharmony_ci				     &rctx->dst_skip) < 0) {
265562306a36Sopenharmony_ci			pr_err("%s() Error: Unable to find start of dst data\n",
265662306a36Sopenharmony_ci			       __func__);
265762306a36Sopenharmony_ci			return -EINVAL;
265862306a36Sopenharmony_ci		}
265962306a36Sopenharmony_ci	}
266062306a36Sopenharmony_ci
266162306a36Sopenharmony_ci	if (ctx->cipher.mode == CIPHER_MODE_CBC ||
266262306a36Sopenharmony_ci	    ctx->cipher.mode == CIPHER_MODE_CTR ||
266362306a36Sopenharmony_ci	    ctx->cipher.mode == CIPHER_MODE_OFB ||
266462306a36Sopenharmony_ci	    ctx->cipher.mode == CIPHER_MODE_XTS ||
266562306a36Sopenharmony_ci	    ctx->cipher.mode == CIPHER_MODE_GCM) {
266662306a36Sopenharmony_ci		rctx->iv_ctr_len =
266762306a36Sopenharmony_ci			ctx->salt_len +
266862306a36Sopenharmony_ci			crypto_aead_ivsize(crypto_aead_reqtfm(req));
266962306a36Sopenharmony_ci	} else if (ctx->cipher.mode == CIPHER_MODE_CCM) {
267062306a36Sopenharmony_ci		rctx->iv_ctr_len = CCM_AES_IV_SIZE;
267162306a36Sopenharmony_ci	} else {
267262306a36Sopenharmony_ci		rctx->iv_ctr_len = 0;
267362306a36Sopenharmony_ci	}
267462306a36Sopenharmony_ci
267562306a36Sopenharmony_ci	rctx->hash_carry_len = 0;
267662306a36Sopenharmony_ci
267762306a36Sopenharmony_ci	flow_log("  src sg: %p\n", req->src);
267862306a36Sopenharmony_ci	flow_log("  rctx->src_sg: %p, src_skip %u\n",
267962306a36Sopenharmony_ci		 rctx->src_sg, rctx->src_skip);
268062306a36Sopenharmony_ci	flow_log("  assoc:  %p, assoclen %u\n", rctx->assoc, req->assoclen);
268162306a36Sopenharmony_ci	flow_log("  dst sg: %p\n", req->dst);
268262306a36Sopenharmony_ci	flow_log("  rctx->dst_sg: %p, dst_skip %u\n",
268362306a36Sopenharmony_ci		 rctx->dst_sg, rctx->dst_skip);
268462306a36Sopenharmony_ci	flow_log("  iv_ctr_len:%u\n", rctx->iv_ctr_len);
268562306a36Sopenharmony_ci	flow_dump("  iv: ", req->iv, rctx->iv_ctr_len);
268662306a36Sopenharmony_ci	flow_log("  authkeylen:%u\n", ctx->authkeylen);
268762306a36Sopenharmony_ci	flow_log("  is_esp: %s\n", ctx->is_esp ? "yes" : "no");
268862306a36Sopenharmony_ci
268962306a36Sopenharmony_ci	if (ctx->max_payload == SPU_MAX_PAYLOAD_INF)
269062306a36Sopenharmony_ci		flow_log("  max_payload infinite");
269162306a36Sopenharmony_ci	else
269262306a36Sopenharmony_ci		flow_log("  max_payload: %u\n", ctx->max_payload);
269362306a36Sopenharmony_ci
269462306a36Sopenharmony_ci	if (unlikely(aead_need_fallback(req)))
269562306a36Sopenharmony_ci		return aead_do_fallback(req, is_encrypt);
269662306a36Sopenharmony_ci
269762306a36Sopenharmony_ci	/*
269862306a36Sopenharmony_ci	 * Do memory allocations for request after fallback check, because if we
269962306a36Sopenharmony_ci	 * do fallback, we won't call finish_req() to dealloc.
270062306a36Sopenharmony_ci	 */
270162306a36Sopenharmony_ci	if (rctx->iv_ctr_len) {
270262306a36Sopenharmony_ci		if (ctx->salt_len)
270362306a36Sopenharmony_ci			memcpy(rctx->msg_buf.iv_ctr + ctx->salt_offset,
270462306a36Sopenharmony_ci			       ctx->salt, ctx->salt_len);
270562306a36Sopenharmony_ci		memcpy(rctx->msg_buf.iv_ctr + ctx->salt_offset + ctx->salt_len,
270662306a36Sopenharmony_ci		       req->iv,
270762306a36Sopenharmony_ci		       rctx->iv_ctr_len - ctx->salt_len - ctx->salt_offset);
270862306a36Sopenharmony_ci	}
270962306a36Sopenharmony_ci
271062306a36Sopenharmony_ci	rctx->chan_idx = select_channel();
271162306a36Sopenharmony_ci	err = handle_aead_req(rctx);
271262306a36Sopenharmony_ci	if (err != -EINPROGRESS)
271362306a36Sopenharmony_ci		/* synchronous result */
271462306a36Sopenharmony_ci		spu_chunk_cleanup(rctx);
271562306a36Sopenharmony_ci
271662306a36Sopenharmony_ci	return err;
271762306a36Sopenharmony_ci}
271862306a36Sopenharmony_ci
271962306a36Sopenharmony_cistatic int aead_authenc_setkey(struct crypto_aead *cipher,
272062306a36Sopenharmony_ci			       const u8 *key, unsigned int keylen)
272162306a36Sopenharmony_ci{
272262306a36Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
272362306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher);
272462306a36Sopenharmony_ci	struct crypto_tfm *tfm = crypto_aead_tfm(cipher);
272562306a36Sopenharmony_ci	struct crypto_authenc_keys keys;
272662306a36Sopenharmony_ci	int ret;
272762306a36Sopenharmony_ci
272862306a36Sopenharmony_ci	flow_log("%s() aead:%p key:%p keylen:%u\n", __func__, cipher, key,
272962306a36Sopenharmony_ci		 keylen);
273062306a36Sopenharmony_ci	flow_dump("  key: ", key, keylen);
273162306a36Sopenharmony_ci
273262306a36Sopenharmony_ci	ret = crypto_authenc_extractkeys(&keys, key, keylen);
273362306a36Sopenharmony_ci	if (ret)
273462306a36Sopenharmony_ci		goto badkey;
273562306a36Sopenharmony_ci
273662306a36Sopenharmony_ci	if (keys.enckeylen > MAX_KEY_SIZE ||
273762306a36Sopenharmony_ci	    keys.authkeylen > MAX_KEY_SIZE)
273862306a36Sopenharmony_ci		goto badkey;
273962306a36Sopenharmony_ci
274062306a36Sopenharmony_ci	ctx->enckeylen = keys.enckeylen;
274162306a36Sopenharmony_ci	ctx->authkeylen = keys.authkeylen;
274262306a36Sopenharmony_ci
274362306a36Sopenharmony_ci	memcpy(ctx->enckey, keys.enckey, keys.enckeylen);
274462306a36Sopenharmony_ci	/* May end up padding auth key. So make sure it's zeroed. */
274562306a36Sopenharmony_ci	memset(ctx->authkey, 0, sizeof(ctx->authkey));
274662306a36Sopenharmony_ci	memcpy(ctx->authkey, keys.authkey, keys.authkeylen);
274762306a36Sopenharmony_ci
274862306a36Sopenharmony_ci	switch (ctx->alg->cipher_info.alg) {
274962306a36Sopenharmony_ci	case CIPHER_ALG_DES:
275062306a36Sopenharmony_ci		if (verify_aead_des_key(cipher, keys.enckey, keys.enckeylen))
275162306a36Sopenharmony_ci			return -EINVAL;
275262306a36Sopenharmony_ci
275362306a36Sopenharmony_ci		ctx->cipher_type = CIPHER_TYPE_DES;
275462306a36Sopenharmony_ci		break;
275562306a36Sopenharmony_ci	case CIPHER_ALG_3DES:
275662306a36Sopenharmony_ci		if (verify_aead_des3_key(cipher, keys.enckey, keys.enckeylen))
275762306a36Sopenharmony_ci			return -EINVAL;
275862306a36Sopenharmony_ci
275962306a36Sopenharmony_ci		ctx->cipher_type = CIPHER_TYPE_3DES;
276062306a36Sopenharmony_ci		break;
276162306a36Sopenharmony_ci	case CIPHER_ALG_AES:
276262306a36Sopenharmony_ci		switch (ctx->enckeylen) {
276362306a36Sopenharmony_ci		case AES_KEYSIZE_128:
276462306a36Sopenharmony_ci			ctx->cipher_type = CIPHER_TYPE_AES128;
276562306a36Sopenharmony_ci			break;
276662306a36Sopenharmony_ci		case AES_KEYSIZE_192:
276762306a36Sopenharmony_ci			ctx->cipher_type = CIPHER_TYPE_AES192;
276862306a36Sopenharmony_ci			break;
276962306a36Sopenharmony_ci		case AES_KEYSIZE_256:
277062306a36Sopenharmony_ci			ctx->cipher_type = CIPHER_TYPE_AES256;
277162306a36Sopenharmony_ci			break;
277262306a36Sopenharmony_ci		default:
277362306a36Sopenharmony_ci			goto badkey;
277462306a36Sopenharmony_ci		}
277562306a36Sopenharmony_ci		break;
277662306a36Sopenharmony_ci	default:
277762306a36Sopenharmony_ci		pr_err("%s() Error: Unknown cipher alg\n", __func__);
277862306a36Sopenharmony_ci		return -EINVAL;
277962306a36Sopenharmony_ci	}
278062306a36Sopenharmony_ci
278162306a36Sopenharmony_ci	flow_log("  enckeylen:%u authkeylen:%u\n", ctx->enckeylen,
278262306a36Sopenharmony_ci		 ctx->authkeylen);
278362306a36Sopenharmony_ci	flow_dump("  enc: ", ctx->enckey, ctx->enckeylen);
278462306a36Sopenharmony_ci	flow_dump("  auth: ", ctx->authkey, ctx->authkeylen);
278562306a36Sopenharmony_ci
278662306a36Sopenharmony_ci	/* setkey the fallback just in case we needto use it */
278762306a36Sopenharmony_ci	if (ctx->fallback_cipher) {
278862306a36Sopenharmony_ci		flow_log("  running fallback setkey()\n");
278962306a36Sopenharmony_ci
279062306a36Sopenharmony_ci		ctx->fallback_cipher->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
279162306a36Sopenharmony_ci		ctx->fallback_cipher->base.crt_flags |=
279262306a36Sopenharmony_ci		    tfm->crt_flags & CRYPTO_TFM_REQ_MASK;
279362306a36Sopenharmony_ci		ret = crypto_aead_setkey(ctx->fallback_cipher, key, keylen);
279462306a36Sopenharmony_ci		if (ret)
279562306a36Sopenharmony_ci			flow_log("  fallback setkey() returned:%d\n", ret);
279662306a36Sopenharmony_ci	}
279762306a36Sopenharmony_ci
279862306a36Sopenharmony_ci	ctx->spu_resp_hdr_len = spu->spu_response_hdr_len(ctx->authkeylen,
279962306a36Sopenharmony_ci							  ctx->enckeylen,
280062306a36Sopenharmony_ci							  false);
280162306a36Sopenharmony_ci
280262306a36Sopenharmony_ci	atomic_inc(&iproc_priv.setkey_cnt[SPU_OP_AEAD]);
280362306a36Sopenharmony_ci
280462306a36Sopenharmony_ci	return ret;
280562306a36Sopenharmony_ci
280662306a36Sopenharmony_cibadkey:
280762306a36Sopenharmony_ci	ctx->enckeylen = 0;
280862306a36Sopenharmony_ci	ctx->authkeylen = 0;
280962306a36Sopenharmony_ci	ctx->digestsize = 0;
281062306a36Sopenharmony_ci
281162306a36Sopenharmony_ci	return -EINVAL;
281262306a36Sopenharmony_ci}
281362306a36Sopenharmony_ci
281462306a36Sopenharmony_cistatic int aead_gcm_ccm_setkey(struct crypto_aead *cipher,
281562306a36Sopenharmony_ci			       const u8 *key, unsigned int keylen)
281662306a36Sopenharmony_ci{
281762306a36Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
281862306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher);
281962306a36Sopenharmony_ci	struct crypto_tfm *tfm = crypto_aead_tfm(cipher);
282062306a36Sopenharmony_ci
282162306a36Sopenharmony_ci	int ret = 0;
282262306a36Sopenharmony_ci
282362306a36Sopenharmony_ci	flow_log("%s() keylen:%u\n", __func__, keylen);
282462306a36Sopenharmony_ci	flow_dump("  key: ", key, keylen);
282562306a36Sopenharmony_ci
282662306a36Sopenharmony_ci	if (!ctx->is_esp)
282762306a36Sopenharmony_ci		ctx->digestsize = keylen;
282862306a36Sopenharmony_ci
282962306a36Sopenharmony_ci	ctx->enckeylen = keylen;
283062306a36Sopenharmony_ci	ctx->authkeylen = 0;
283162306a36Sopenharmony_ci
283262306a36Sopenharmony_ci	switch (ctx->enckeylen) {
283362306a36Sopenharmony_ci	case AES_KEYSIZE_128:
283462306a36Sopenharmony_ci		ctx->cipher_type = CIPHER_TYPE_AES128;
283562306a36Sopenharmony_ci		break;
283662306a36Sopenharmony_ci	case AES_KEYSIZE_192:
283762306a36Sopenharmony_ci		ctx->cipher_type = CIPHER_TYPE_AES192;
283862306a36Sopenharmony_ci		break;
283962306a36Sopenharmony_ci	case AES_KEYSIZE_256:
284062306a36Sopenharmony_ci		ctx->cipher_type = CIPHER_TYPE_AES256;
284162306a36Sopenharmony_ci		break;
284262306a36Sopenharmony_ci	default:
284362306a36Sopenharmony_ci		goto badkey;
284462306a36Sopenharmony_ci	}
284562306a36Sopenharmony_ci
284662306a36Sopenharmony_ci	memcpy(ctx->enckey, key, ctx->enckeylen);
284762306a36Sopenharmony_ci
284862306a36Sopenharmony_ci	flow_log("  enckeylen:%u authkeylen:%u\n", ctx->enckeylen,
284962306a36Sopenharmony_ci		 ctx->authkeylen);
285062306a36Sopenharmony_ci	flow_dump("  enc: ", ctx->enckey, ctx->enckeylen);
285162306a36Sopenharmony_ci	flow_dump("  auth: ", ctx->authkey, ctx->authkeylen);
285262306a36Sopenharmony_ci
285362306a36Sopenharmony_ci	/* setkey the fallback just in case we need to use it */
285462306a36Sopenharmony_ci	if (ctx->fallback_cipher) {
285562306a36Sopenharmony_ci		flow_log("  running fallback setkey()\n");
285662306a36Sopenharmony_ci
285762306a36Sopenharmony_ci		ctx->fallback_cipher->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
285862306a36Sopenharmony_ci		ctx->fallback_cipher->base.crt_flags |=
285962306a36Sopenharmony_ci		    tfm->crt_flags & CRYPTO_TFM_REQ_MASK;
286062306a36Sopenharmony_ci		ret = crypto_aead_setkey(ctx->fallback_cipher, key,
286162306a36Sopenharmony_ci					 keylen + ctx->salt_len);
286262306a36Sopenharmony_ci		if (ret)
286362306a36Sopenharmony_ci			flow_log("  fallback setkey() returned:%d\n", ret);
286462306a36Sopenharmony_ci	}
286562306a36Sopenharmony_ci
286662306a36Sopenharmony_ci	ctx->spu_resp_hdr_len = spu->spu_response_hdr_len(ctx->authkeylen,
286762306a36Sopenharmony_ci							  ctx->enckeylen,
286862306a36Sopenharmony_ci							  false);
286962306a36Sopenharmony_ci
287062306a36Sopenharmony_ci	atomic_inc(&iproc_priv.setkey_cnt[SPU_OP_AEAD]);
287162306a36Sopenharmony_ci
287262306a36Sopenharmony_ci	flow_log("  enckeylen:%u authkeylen:%u\n", ctx->enckeylen,
287362306a36Sopenharmony_ci		 ctx->authkeylen);
287462306a36Sopenharmony_ci
287562306a36Sopenharmony_ci	return ret;
287662306a36Sopenharmony_ci
287762306a36Sopenharmony_cibadkey:
287862306a36Sopenharmony_ci	ctx->enckeylen = 0;
287962306a36Sopenharmony_ci	ctx->authkeylen = 0;
288062306a36Sopenharmony_ci	ctx->digestsize = 0;
288162306a36Sopenharmony_ci
288262306a36Sopenharmony_ci	return -EINVAL;
288362306a36Sopenharmony_ci}
288462306a36Sopenharmony_ci
288562306a36Sopenharmony_ci/**
288662306a36Sopenharmony_ci * aead_gcm_esp_setkey() - setkey() operation for ESP variant of GCM AES.
288762306a36Sopenharmony_ci * @cipher: AEAD structure
288862306a36Sopenharmony_ci * @key:    Key followed by 4 bytes of salt
288962306a36Sopenharmony_ci * @keylen: Length of key plus salt, in bytes
289062306a36Sopenharmony_ci *
289162306a36Sopenharmony_ci * Extracts salt from key and stores it to be prepended to IV on each request.
289262306a36Sopenharmony_ci * Digest is always 16 bytes
289362306a36Sopenharmony_ci *
289462306a36Sopenharmony_ci * Return: Value from generic gcm setkey.
289562306a36Sopenharmony_ci */
289662306a36Sopenharmony_cistatic int aead_gcm_esp_setkey(struct crypto_aead *cipher,
289762306a36Sopenharmony_ci			       const u8 *key, unsigned int keylen)
289862306a36Sopenharmony_ci{
289962306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher);
290062306a36Sopenharmony_ci
290162306a36Sopenharmony_ci	flow_log("%s\n", __func__);
290262306a36Sopenharmony_ci
290362306a36Sopenharmony_ci	if (keylen < GCM_ESP_SALT_SIZE)
290462306a36Sopenharmony_ci		return -EINVAL;
290562306a36Sopenharmony_ci
290662306a36Sopenharmony_ci	ctx->salt_len = GCM_ESP_SALT_SIZE;
290762306a36Sopenharmony_ci	ctx->salt_offset = GCM_ESP_SALT_OFFSET;
290862306a36Sopenharmony_ci	memcpy(ctx->salt, key + keylen - GCM_ESP_SALT_SIZE, GCM_ESP_SALT_SIZE);
290962306a36Sopenharmony_ci	keylen -= GCM_ESP_SALT_SIZE;
291062306a36Sopenharmony_ci	ctx->digestsize = GCM_ESP_DIGESTSIZE;
291162306a36Sopenharmony_ci	ctx->is_esp = true;
291262306a36Sopenharmony_ci	flow_dump("salt: ", ctx->salt, GCM_ESP_SALT_SIZE);
291362306a36Sopenharmony_ci
291462306a36Sopenharmony_ci	return aead_gcm_ccm_setkey(cipher, key, keylen);
291562306a36Sopenharmony_ci}
291662306a36Sopenharmony_ci
291762306a36Sopenharmony_ci/**
291862306a36Sopenharmony_ci * rfc4543_gcm_esp_setkey() - setkey operation for RFC4543 variant of GCM/GMAC.
291962306a36Sopenharmony_ci * @cipher: AEAD structure
292062306a36Sopenharmony_ci * @key:    Key followed by 4 bytes of salt
292162306a36Sopenharmony_ci * @keylen: Length of key plus salt, in bytes
292262306a36Sopenharmony_ci *
292362306a36Sopenharmony_ci * Extracts salt from key and stores it to be prepended to IV on each request.
292462306a36Sopenharmony_ci * Digest is always 16 bytes
292562306a36Sopenharmony_ci *
292662306a36Sopenharmony_ci * Return: Value from generic gcm setkey.
292762306a36Sopenharmony_ci */
292862306a36Sopenharmony_cistatic int rfc4543_gcm_esp_setkey(struct crypto_aead *cipher,
292962306a36Sopenharmony_ci				  const u8 *key, unsigned int keylen)
293062306a36Sopenharmony_ci{
293162306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher);
293262306a36Sopenharmony_ci
293362306a36Sopenharmony_ci	flow_log("%s\n", __func__);
293462306a36Sopenharmony_ci
293562306a36Sopenharmony_ci	if (keylen < GCM_ESP_SALT_SIZE)
293662306a36Sopenharmony_ci		return -EINVAL;
293762306a36Sopenharmony_ci
293862306a36Sopenharmony_ci	ctx->salt_len = GCM_ESP_SALT_SIZE;
293962306a36Sopenharmony_ci	ctx->salt_offset = GCM_ESP_SALT_OFFSET;
294062306a36Sopenharmony_ci	memcpy(ctx->salt, key + keylen - GCM_ESP_SALT_SIZE, GCM_ESP_SALT_SIZE);
294162306a36Sopenharmony_ci	keylen -= GCM_ESP_SALT_SIZE;
294262306a36Sopenharmony_ci	ctx->digestsize = GCM_ESP_DIGESTSIZE;
294362306a36Sopenharmony_ci	ctx->is_esp = true;
294462306a36Sopenharmony_ci	ctx->is_rfc4543 = true;
294562306a36Sopenharmony_ci	flow_dump("salt: ", ctx->salt, GCM_ESP_SALT_SIZE);
294662306a36Sopenharmony_ci
294762306a36Sopenharmony_ci	return aead_gcm_ccm_setkey(cipher, key, keylen);
294862306a36Sopenharmony_ci}
294962306a36Sopenharmony_ci
295062306a36Sopenharmony_ci/**
295162306a36Sopenharmony_ci * aead_ccm_esp_setkey() - setkey() operation for ESP variant of CCM AES.
295262306a36Sopenharmony_ci * @cipher: AEAD structure
295362306a36Sopenharmony_ci * @key:    Key followed by 4 bytes of salt
295462306a36Sopenharmony_ci * @keylen: Length of key plus salt, in bytes
295562306a36Sopenharmony_ci *
295662306a36Sopenharmony_ci * Extracts salt from key and stores it to be prepended to IV on each request.
295762306a36Sopenharmony_ci * Digest is always 16 bytes
295862306a36Sopenharmony_ci *
295962306a36Sopenharmony_ci * Return: Value from generic ccm setkey.
296062306a36Sopenharmony_ci */
296162306a36Sopenharmony_cistatic int aead_ccm_esp_setkey(struct crypto_aead *cipher,
296262306a36Sopenharmony_ci			       const u8 *key, unsigned int keylen)
296362306a36Sopenharmony_ci{
296462306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher);
296562306a36Sopenharmony_ci
296662306a36Sopenharmony_ci	flow_log("%s\n", __func__);
296762306a36Sopenharmony_ci
296862306a36Sopenharmony_ci	if (keylen < CCM_ESP_SALT_SIZE)
296962306a36Sopenharmony_ci		return -EINVAL;
297062306a36Sopenharmony_ci
297162306a36Sopenharmony_ci	ctx->salt_len = CCM_ESP_SALT_SIZE;
297262306a36Sopenharmony_ci	ctx->salt_offset = CCM_ESP_SALT_OFFSET;
297362306a36Sopenharmony_ci	memcpy(ctx->salt, key + keylen - CCM_ESP_SALT_SIZE, CCM_ESP_SALT_SIZE);
297462306a36Sopenharmony_ci	keylen -= CCM_ESP_SALT_SIZE;
297562306a36Sopenharmony_ci	ctx->is_esp = true;
297662306a36Sopenharmony_ci	flow_dump("salt: ", ctx->salt, CCM_ESP_SALT_SIZE);
297762306a36Sopenharmony_ci
297862306a36Sopenharmony_ci	return aead_gcm_ccm_setkey(cipher, key, keylen);
297962306a36Sopenharmony_ci}
298062306a36Sopenharmony_ci
298162306a36Sopenharmony_cistatic int aead_setauthsize(struct crypto_aead *cipher, unsigned int authsize)
298262306a36Sopenharmony_ci{
298362306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher);
298462306a36Sopenharmony_ci	int ret = 0;
298562306a36Sopenharmony_ci
298662306a36Sopenharmony_ci	flow_log("%s() authkeylen:%u authsize:%u\n",
298762306a36Sopenharmony_ci		 __func__, ctx->authkeylen, authsize);
298862306a36Sopenharmony_ci
298962306a36Sopenharmony_ci	ctx->digestsize = authsize;
299062306a36Sopenharmony_ci
299162306a36Sopenharmony_ci	/* setkey the fallback just in case we needto use it */
299262306a36Sopenharmony_ci	if (ctx->fallback_cipher) {
299362306a36Sopenharmony_ci		flow_log("  running fallback setauth()\n");
299462306a36Sopenharmony_ci
299562306a36Sopenharmony_ci		ret = crypto_aead_setauthsize(ctx->fallback_cipher, authsize);
299662306a36Sopenharmony_ci		if (ret)
299762306a36Sopenharmony_ci			flow_log("  fallback setauth() returned:%d\n", ret);
299862306a36Sopenharmony_ci	}
299962306a36Sopenharmony_ci
300062306a36Sopenharmony_ci	return ret;
300162306a36Sopenharmony_ci}
300262306a36Sopenharmony_ci
300362306a36Sopenharmony_cistatic int aead_encrypt(struct aead_request *req)
300462306a36Sopenharmony_ci{
300562306a36Sopenharmony_ci	flow_log("%s() cryptlen:%u %08x\n", __func__, req->cryptlen,
300662306a36Sopenharmony_ci		 req->cryptlen);
300762306a36Sopenharmony_ci	dump_sg(req->src, 0, req->cryptlen + req->assoclen);
300862306a36Sopenharmony_ci	flow_log("  assoc_len:%u\n", req->assoclen);
300962306a36Sopenharmony_ci
301062306a36Sopenharmony_ci	return aead_enqueue(req, true);
301162306a36Sopenharmony_ci}
301262306a36Sopenharmony_ci
301362306a36Sopenharmony_cistatic int aead_decrypt(struct aead_request *req)
301462306a36Sopenharmony_ci{
301562306a36Sopenharmony_ci	flow_log("%s() cryptlen:%u\n", __func__, req->cryptlen);
301662306a36Sopenharmony_ci	dump_sg(req->src, 0, req->cryptlen + req->assoclen);
301762306a36Sopenharmony_ci	flow_log("  assoc_len:%u\n", req->assoclen);
301862306a36Sopenharmony_ci
301962306a36Sopenharmony_ci	return aead_enqueue(req, false);
302062306a36Sopenharmony_ci}
302162306a36Sopenharmony_ci
302262306a36Sopenharmony_ci/* ==================== Supported Cipher Algorithms ==================== */
302362306a36Sopenharmony_ci
302462306a36Sopenharmony_cistatic struct iproc_alg_s driver_algs[] = {
302562306a36Sopenharmony_ci	{
302662306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
302762306a36Sopenharmony_ci	 .alg.aead = {
302862306a36Sopenharmony_ci		 .base = {
302962306a36Sopenharmony_ci			.cra_name = "gcm(aes)",
303062306a36Sopenharmony_ci			.cra_driver_name = "gcm-aes-iproc",
303162306a36Sopenharmony_ci			.cra_blocksize = AES_BLOCK_SIZE,
303262306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK
303362306a36Sopenharmony_ci		 },
303462306a36Sopenharmony_ci		 .setkey = aead_gcm_ccm_setkey,
303562306a36Sopenharmony_ci		 .ivsize = GCM_AES_IV_SIZE,
303662306a36Sopenharmony_ci		.maxauthsize = AES_BLOCK_SIZE,
303762306a36Sopenharmony_ci	 },
303862306a36Sopenharmony_ci	 .cipher_info = {
303962306a36Sopenharmony_ci			 .alg = CIPHER_ALG_AES,
304062306a36Sopenharmony_ci			 .mode = CIPHER_MODE_GCM,
304162306a36Sopenharmony_ci			 },
304262306a36Sopenharmony_ci	 .auth_info = {
304362306a36Sopenharmony_ci		       .alg = HASH_ALG_AES,
304462306a36Sopenharmony_ci		       .mode = HASH_MODE_GCM,
304562306a36Sopenharmony_ci		       },
304662306a36Sopenharmony_ci	 .auth_first = 0,
304762306a36Sopenharmony_ci	 },
304862306a36Sopenharmony_ci	{
304962306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
305062306a36Sopenharmony_ci	 .alg.aead = {
305162306a36Sopenharmony_ci		 .base = {
305262306a36Sopenharmony_ci			.cra_name = "ccm(aes)",
305362306a36Sopenharmony_ci			.cra_driver_name = "ccm-aes-iproc",
305462306a36Sopenharmony_ci			.cra_blocksize = AES_BLOCK_SIZE,
305562306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK
305662306a36Sopenharmony_ci		 },
305762306a36Sopenharmony_ci		 .setkey = aead_gcm_ccm_setkey,
305862306a36Sopenharmony_ci		 .ivsize = CCM_AES_IV_SIZE,
305962306a36Sopenharmony_ci		.maxauthsize = AES_BLOCK_SIZE,
306062306a36Sopenharmony_ci	 },
306162306a36Sopenharmony_ci	 .cipher_info = {
306262306a36Sopenharmony_ci			 .alg = CIPHER_ALG_AES,
306362306a36Sopenharmony_ci			 .mode = CIPHER_MODE_CCM,
306462306a36Sopenharmony_ci			 },
306562306a36Sopenharmony_ci	 .auth_info = {
306662306a36Sopenharmony_ci		       .alg = HASH_ALG_AES,
306762306a36Sopenharmony_ci		       .mode = HASH_MODE_CCM,
306862306a36Sopenharmony_ci		       },
306962306a36Sopenharmony_ci	 .auth_first = 0,
307062306a36Sopenharmony_ci	 },
307162306a36Sopenharmony_ci	{
307262306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
307362306a36Sopenharmony_ci	 .alg.aead = {
307462306a36Sopenharmony_ci		 .base = {
307562306a36Sopenharmony_ci			.cra_name = "rfc4106(gcm(aes))",
307662306a36Sopenharmony_ci			.cra_driver_name = "gcm-aes-esp-iproc",
307762306a36Sopenharmony_ci			.cra_blocksize = AES_BLOCK_SIZE,
307862306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK
307962306a36Sopenharmony_ci		 },
308062306a36Sopenharmony_ci		 .setkey = aead_gcm_esp_setkey,
308162306a36Sopenharmony_ci		 .ivsize = GCM_RFC4106_IV_SIZE,
308262306a36Sopenharmony_ci		 .maxauthsize = AES_BLOCK_SIZE,
308362306a36Sopenharmony_ci	 },
308462306a36Sopenharmony_ci	 .cipher_info = {
308562306a36Sopenharmony_ci			 .alg = CIPHER_ALG_AES,
308662306a36Sopenharmony_ci			 .mode = CIPHER_MODE_GCM,
308762306a36Sopenharmony_ci			 },
308862306a36Sopenharmony_ci	 .auth_info = {
308962306a36Sopenharmony_ci		       .alg = HASH_ALG_AES,
309062306a36Sopenharmony_ci		       .mode = HASH_MODE_GCM,
309162306a36Sopenharmony_ci		       },
309262306a36Sopenharmony_ci	 .auth_first = 0,
309362306a36Sopenharmony_ci	 },
309462306a36Sopenharmony_ci	{
309562306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
309662306a36Sopenharmony_ci	 .alg.aead = {
309762306a36Sopenharmony_ci		 .base = {
309862306a36Sopenharmony_ci			.cra_name = "rfc4309(ccm(aes))",
309962306a36Sopenharmony_ci			.cra_driver_name = "ccm-aes-esp-iproc",
310062306a36Sopenharmony_ci			.cra_blocksize = AES_BLOCK_SIZE,
310162306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK
310262306a36Sopenharmony_ci		 },
310362306a36Sopenharmony_ci		 .setkey = aead_ccm_esp_setkey,
310462306a36Sopenharmony_ci		 .ivsize = CCM_AES_IV_SIZE,
310562306a36Sopenharmony_ci		 .maxauthsize = AES_BLOCK_SIZE,
310662306a36Sopenharmony_ci	 },
310762306a36Sopenharmony_ci	 .cipher_info = {
310862306a36Sopenharmony_ci			 .alg = CIPHER_ALG_AES,
310962306a36Sopenharmony_ci			 .mode = CIPHER_MODE_CCM,
311062306a36Sopenharmony_ci			 },
311162306a36Sopenharmony_ci	 .auth_info = {
311262306a36Sopenharmony_ci		       .alg = HASH_ALG_AES,
311362306a36Sopenharmony_ci		       .mode = HASH_MODE_CCM,
311462306a36Sopenharmony_ci		       },
311562306a36Sopenharmony_ci	 .auth_first = 0,
311662306a36Sopenharmony_ci	 },
311762306a36Sopenharmony_ci	{
311862306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
311962306a36Sopenharmony_ci	 .alg.aead = {
312062306a36Sopenharmony_ci		 .base = {
312162306a36Sopenharmony_ci			.cra_name = "rfc4543(gcm(aes))",
312262306a36Sopenharmony_ci			.cra_driver_name = "gmac-aes-esp-iproc",
312362306a36Sopenharmony_ci			.cra_blocksize = AES_BLOCK_SIZE,
312462306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK
312562306a36Sopenharmony_ci		 },
312662306a36Sopenharmony_ci		 .setkey = rfc4543_gcm_esp_setkey,
312762306a36Sopenharmony_ci		 .ivsize = GCM_RFC4106_IV_SIZE,
312862306a36Sopenharmony_ci		 .maxauthsize = AES_BLOCK_SIZE,
312962306a36Sopenharmony_ci	 },
313062306a36Sopenharmony_ci	 .cipher_info = {
313162306a36Sopenharmony_ci			 .alg = CIPHER_ALG_AES,
313262306a36Sopenharmony_ci			 .mode = CIPHER_MODE_GCM,
313362306a36Sopenharmony_ci			 },
313462306a36Sopenharmony_ci	 .auth_info = {
313562306a36Sopenharmony_ci		       .alg = HASH_ALG_AES,
313662306a36Sopenharmony_ci		       .mode = HASH_MODE_GCM,
313762306a36Sopenharmony_ci		       },
313862306a36Sopenharmony_ci	 .auth_first = 0,
313962306a36Sopenharmony_ci	 },
314062306a36Sopenharmony_ci	{
314162306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
314262306a36Sopenharmony_ci	 .alg.aead = {
314362306a36Sopenharmony_ci		 .base = {
314462306a36Sopenharmony_ci			.cra_name = "authenc(hmac(md5),cbc(aes))",
314562306a36Sopenharmony_ci			.cra_driver_name = "authenc-hmac-md5-cbc-aes-iproc",
314662306a36Sopenharmony_ci			.cra_blocksize = AES_BLOCK_SIZE,
314762306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
314862306a36Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
314962306a36Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
315062306a36Sopenharmony_ci		 },
315162306a36Sopenharmony_ci		 .setkey = aead_authenc_setkey,
315262306a36Sopenharmony_ci		.ivsize = AES_BLOCK_SIZE,
315362306a36Sopenharmony_ci		.maxauthsize = MD5_DIGEST_SIZE,
315462306a36Sopenharmony_ci	 },
315562306a36Sopenharmony_ci	 .cipher_info = {
315662306a36Sopenharmony_ci			 .alg = CIPHER_ALG_AES,
315762306a36Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
315862306a36Sopenharmony_ci			 },
315962306a36Sopenharmony_ci	 .auth_info = {
316062306a36Sopenharmony_ci		       .alg = HASH_ALG_MD5,
316162306a36Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
316262306a36Sopenharmony_ci		       },
316362306a36Sopenharmony_ci	 .auth_first = 0,
316462306a36Sopenharmony_ci	 },
316562306a36Sopenharmony_ci	{
316662306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
316762306a36Sopenharmony_ci	 .alg.aead = {
316862306a36Sopenharmony_ci		 .base = {
316962306a36Sopenharmony_ci			.cra_name = "authenc(hmac(sha1),cbc(aes))",
317062306a36Sopenharmony_ci			.cra_driver_name = "authenc-hmac-sha1-cbc-aes-iproc",
317162306a36Sopenharmony_ci			.cra_blocksize = AES_BLOCK_SIZE,
317262306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
317362306a36Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
317462306a36Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
317562306a36Sopenharmony_ci		 },
317662306a36Sopenharmony_ci		 .setkey = aead_authenc_setkey,
317762306a36Sopenharmony_ci		 .ivsize = AES_BLOCK_SIZE,
317862306a36Sopenharmony_ci		 .maxauthsize = SHA1_DIGEST_SIZE,
317962306a36Sopenharmony_ci	 },
318062306a36Sopenharmony_ci	 .cipher_info = {
318162306a36Sopenharmony_ci			 .alg = CIPHER_ALG_AES,
318262306a36Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
318362306a36Sopenharmony_ci			 },
318462306a36Sopenharmony_ci	 .auth_info = {
318562306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA1,
318662306a36Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
318762306a36Sopenharmony_ci		       },
318862306a36Sopenharmony_ci	 .auth_first = 0,
318962306a36Sopenharmony_ci	 },
319062306a36Sopenharmony_ci	{
319162306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
319262306a36Sopenharmony_ci	 .alg.aead = {
319362306a36Sopenharmony_ci		 .base = {
319462306a36Sopenharmony_ci			.cra_name = "authenc(hmac(sha256),cbc(aes))",
319562306a36Sopenharmony_ci			.cra_driver_name = "authenc-hmac-sha256-cbc-aes-iproc",
319662306a36Sopenharmony_ci			.cra_blocksize = AES_BLOCK_SIZE,
319762306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
319862306a36Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
319962306a36Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
320062306a36Sopenharmony_ci		 },
320162306a36Sopenharmony_ci		 .setkey = aead_authenc_setkey,
320262306a36Sopenharmony_ci		 .ivsize = AES_BLOCK_SIZE,
320362306a36Sopenharmony_ci		 .maxauthsize = SHA256_DIGEST_SIZE,
320462306a36Sopenharmony_ci	 },
320562306a36Sopenharmony_ci	 .cipher_info = {
320662306a36Sopenharmony_ci			 .alg = CIPHER_ALG_AES,
320762306a36Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
320862306a36Sopenharmony_ci			 },
320962306a36Sopenharmony_ci	 .auth_info = {
321062306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA256,
321162306a36Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
321262306a36Sopenharmony_ci		       },
321362306a36Sopenharmony_ci	 .auth_first = 0,
321462306a36Sopenharmony_ci	 },
321562306a36Sopenharmony_ci	{
321662306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
321762306a36Sopenharmony_ci	 .alg.aead = {
321862306a36Sopenharmony_ci		 .base = {
321962306a36Sopenharmony_ci			.cra_name = "authenc(hmac(md5),cbc(des))",
322062306a36Sopenharmony_ci			.cra_driver_name = "authenc-hmac-md5-cbc-des-iproc",
322162306a36Sopenharmony_ci			.cra_blocksize = DES_BLOCK_SIZE,
322262306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
322362306a36Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
322462306a36Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
322562306a36Sopenharmony_ci		 },
322662306a36Sopenharmony_ci		 .setkey = aead_authenc_setkey,
322762306a36Sopenharmony_ci		 .ivsize = DES_BLOCK_SIZE,
322862306a36Sopenharmony_ci		 .maxauthsize = MD5_DIGEST_SIZE,
322962306a36Sopenharmony_ci	 },
323062306a36Sopenharmony_ci	 .cipher_info = {
323162306a36Sopenharmony_ci			 .alg = CIPHER_ALG_DES,
323262306a36Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
323362306a36Sopenharmony_ci			 },
323462306a36Sopenharmony_ci	 .auth_info = {
323562306a36Sopenharmony_ci		       .alg = HASH_ALG_MD5,
323662306a36Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
323762306a36Sopenharmony_ci		       },
323862306a36Sopenharmony_ci	 .auth_first = 0,
323962306a36Sopenharmony_ci	 },
324062306a36Sopenharmony_ci	{
324162306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
324262306a36Sopenharmony_ci	 .alg.aead = {
324362306a36Sopenharmony_ci		 .base = {
324462306a36Sopenharmony_ci			.cra_name = "authenc(hmac(sha1),cbc(des))",
324562306a36Sopenharmony_ci			.cra_driver_name = "authenc-hmac-sha1-cbc-des-iproc",
324662306a36Sopenharmony_ci			.cra_blocksize = DES_BLOCK_SIZE,
324762306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
324862306a36Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
324962306a36Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
325062306a36Sopenharmony_ci		 },
325162306a36Sopenharmony_ci		 .setkey = aead_authenc_setkey,
325262306a36Sopenharmony_ci		 .ivsize = DES_BLOCK_SIZE,
325362306a36Sopenharmony_ci		 .maxauthsize = SHA1_DIGEST_SIZE,
325462306a36Sopenharmony_ci	 },
325562306a36Sopenharmony_ci	 .cipher_info = {
325662306a36Sopenharmony_ci			 .alg = CIPHER_ALG_DES,
325762306a36Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
325862306a36Sopenharmony_ci			 },
325962306a36Sopenharmony_ci	 .auth_info = {
326062306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA1,
326162306a36Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
326262306a36Sopenharmony_ci		       },
326362306a36Sopenharmony_ci	 .auth_first = 0,
326462306a36Sopenharmony_ci	 },
326562306a36Sopenharmony_ci	{
326662306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
326762306a36Sopenharmony_ci	 .alg.aead = {
326862306a36Sopenharmony_ci		 .base = {
326962306a36Sopenharmony_ci			.cra_name = "authenc(hmac(sha224),cbc(des))",
327062306a36Sopenharmony_ci			.cra_driver_name = "authenc-hmac-sha224-cbc-des-iproc",
327162306a36Sopenharmony_ci			.cra_blocksize = DES_BLOCK_SIZE,
327262306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
327362306a36Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
327462306a36Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
327562306a36Sopenharmony_ci		 },
327662306a36Sopenharmony_ci		 .setkey = aead_authenc_setkey,
327762306a36Sopenharmony_ci		 .ivsize = DES_BLOCK_SIZE,
327862306a36Sopenharmony_ci		 .maxauthsize = SHA224_DIGEST_SIZE,
327962306a36Sopenharmony_ci	 },
328062306a36Sopenharmony_ci	 .cipher_info = {
328162306a36Sopenharmony_ci			 .alg = CIPHER_ALG_DES,
328262306a36Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
328362306a36Sopenharmony_ci			 },
328462306a36Sopenharmony_ci	 .auth_info = {
328562306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA224,
328662306a36Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
328762306a36Sopenharmony_ci		       },
328862306a36Sopenharmony_ci	 .auth_first = 0,
328962306a36Sopenharmony_ci	 },
329062306a36Sopenharmony_ci	{
329162306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
329262306a36Sopenharmony_ci	 .alg.aead = {
329362306a36Sopenharmony_ci		 .base = {
329462306a36Sopenharmony_ci			.cra_name = "authenc(hmac(sha256),cbc(des))",
329562306a36Sopenharmony_ci			.cra_driver_name = "authenc-hmac-sha256-cbc-des-iproc",
329662306a36Sopenharmony_ci			.cra_blocksize = DES_BLOCK_SIZE,
329762306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
329862306a36Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
329962306a36Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
330062306a36Sopenharmony_ci		 },
330162306a36Sopenharmony_ci		 .setkey = aead_authenc_setkey,
330262306a36Sopenharmony_ci		 .ivsize = DES_BLOCK_SIZE,
330362306a36Sopenharmony_ci		 .maxauthsize = SHA256_DIGEST_SIZE,
330462306a36Sopenharmony_ci	 },
330562306a36Sopenharmony_ci	 .cipher_info = {
330662306a36Sopenharmony_ci			 .alg = CIPHER_ALG_DES,
330762306a36Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
330862306a36Sopenharmony_ci			 },
330962306a36Sopenharmony_ci	 .auth_info = {
331062306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA256,
331162306a36Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
331262306a36Sopenharmony_ci		       },
331362306a36Sopenharmony_ci	 .auth_first = 0,
331462306a36Sopenharmony_ci	 },
331562306a36Sopenharmony_ci	{
331662306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
331762306a36Sopenharmony_ci	 .alg.aead = {
331862306a36Sopenharmony_ci		 .base = {
331962306a36Sopenharmony_ci			.cra_name = "authenc(hmac(sha384),cbc(des))",
332062306a36Sopenharmony_ci			.cra_driver_name = "authenc-hmac-sha384-cbc-des-iproc",
332162306a36Sopenharmony_ci			.cra_blocksize = DES_BLOCK_SIZE,
332262306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
332362306a36Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
332462306a36Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
332562306a36Sopenharmony_ci		 },
332662306a36Sopenharmony_ci		 .setkey = aead_authenc_setkey,
332762306a36Sopenharmony_ci		 .ivsize = DES_BLOCK_SIZE,
332862306a36Sopenharmony_ci		 .maxauthsize = SHA384_DIGEST_SIZE,
332962306a36Sopenharmony_ci	 },
333062306a36Sopenharmony_ci	 .cipher_info = {
333162306a36Sopenharmony_ci			 .alg = CIPHER_ALG_DES,
333262306a36Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
333362306a36Sopenharmony_ci			 },
333462306a36Sopenharmony_ci	 .auth_info = {
333562306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA384,
333662306a36Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
333762306a36Sopenharmony_ci		       },
333862306a36Sopenharmony_ci	 .auth_first = 0,
333962306a36Sopenharmony_ci	 },
334062306a36Sopenharmony_ci	{
334162306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
334262306a36Sopenharmony_ci	 .alg.aead = {
334362306a36Sopenharmony_ci		 .base = {
334462306a36Sopenharmony_ci			.cra_name = "authenc(hmac(sha512),cbc(des))",
334562306a36Sopenharmony_ci			.cra_driver_name = "authenc-hmac-sha512-cbc-des-iproc",
334662306a36Sopenharmony_ci			.cra_blocksize = DES_BLOCK_SIZE,
334762306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
334862306a36Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
334962306a36Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
335062306a36Sopenharmony_ci		 },
335162306a36Sopenharmony_ci		 .setkey = aead_authenc_setkey,
335262306a36Sopenharmony_ci		 .ivsize = DES_BLOCK_SIZE,
335362306a36Sopenharmony_ci		 .maxauthsize = SHA512_DIGEST_SIZE,
335462306a36Sopenharmony_ci	 },
335562306a36Sopenharmony_ci	 .cipher_info = {
335662306a36Sopenharmony_ci			 .alg = CIPHER_ALG_DES,
335762306a36Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
335862306a36Sopenharmony_ci			 },
335962306a36Sopenharmony_ci	 .auth_info = {
336062306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA512,
336162306a36Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
336262306a36Sopenharmony_ci		       },
336362306a36Sopenharmony_ci	 .auth_first = 0,
336462306a36Sopenharmony_ci	 },
336562306a36Sopenharmony_ci	{
336662306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
336762306a36Sopenharmony_ci	 .alg.aead = {
336862306a36Sopenharmony_ci		 .base = {
336962306a36Sopenharmony_ci			.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
337062306a36Sopenharmony_ci			.cra_driver_name = "authenc-hmac-md5-cbc-des3-iproc",
337162306a36Sopenharmony_ci			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
337262306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
337362306a36Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
337462306a36Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
337562306a36Sopenharmony_ci		 },
337662306a36Sopenharmony_ci		 .setkey = aead_authenc_setkey,
337762306a36Sopenharmony_ci		 .ivsize = DES3_EDE_BLOCK_SIZE,
337862306a36Sopenharmony_ci		 .maxauthsize = MD5_DIGEST_SIZE,
337962306a36Sopenharmony_ci	 },
338062306a36Sopenharmony_ci	 .cipher_info = {
338162306a36Sopenharmony_ci			 .alg = CIPHER_ALG_3DES,
338262306a36Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
338362306a36Sopenharmony_ci			 },
338462306a36Sopenharmony_ci	 .auth_info = {
338562306a36Sopenharmony_ci		       .alg = HASH_ALG_MD5,
338662306a36Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
338762306a36Sopenharmony_ci		       },
338862306a36Sopenharmony_ci	 .auth_first = 0,
338962306a36Sopenharmony_ci	 },
339062306a36Sopenharmony_ci	{
339162306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
339262306a36Sopenharmony_ci	 .alg.aead = {
339362306a36Sopenharmony_ci		 .base = {
339462306a36Sopenharmony_ci			.cra_name = "authenc(hmac(sha1),cbc(des3_ede))",
339562306a36Sopenharmony_ci			.cra_driver_name = "authenc-hmac-sha1-cbc-des3-iproc",
339662306a36Sopenharmony_ci			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
339762306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
339862306a36Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
339962306a36Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
340062306a36Sopenharmony_ci		 },
340162306a36Sopenharmony_ci		 .setkey = aead_authenc_setkey,
340262306a36Sopenharmony_ci		 .ivsize = DES3_EDE_BLOCK_SIZE,
340362306a36Sopenharmony_ci		 .maxauthsize = SHA1_DIGEST_SIZE,
340462306a36Sopenharmony_ci	 },
340562306a36Sopenharmony_ci	 .cipher_info = {
340662306a36Sopenharmony_ci			 .alg = CIPHER_ALG_3DES,
340762306a36Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
340862306a36Sopenharmony_ci			 },
340962306a36Sopenharmony_ci	 .auth_info = {
341062306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA1,
341162306a36Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
341262306a36Sopenharmony_ci		       },
341362306a36Sopenharmony_ci	 .auth_first = 0,
341462306a36Sopenharmony_ci	 },
341562306a36Sopenharmony_ci	{
341662306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
341762306a36Sopenharmony_ci	 .alg.aead = {
341862306a36Sopenharmony_ci		 .base = {
341962306a36Sopenharmony_ci			.cra_name = "authenc(hmac(sha224),cbc(des3_ede))",
342062306a36Sopenharmony_ci			.cra_driver_name = "authenc-hmac-sha224-cbc-des3-iproc",
342162306a36Sopenharmony_ci			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
342262306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
342362306a36Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
342462306a36Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
342562306a36Sopenharmony_ci		 },
342662306a36Sopenharmony_ci		 .setkey = aead_authenc_setkey,
342762306a36Sopenharmony_ci		 .ivsize = DES3_EDE_BLOCK_SIZE,
342862306a36Sopenharmony_ci		 .maxauthsize = SHA224_DIGEST_SIZE,
342962306a36Sopenharmony_ci	 },
343062306a36Sopenharmony_ci	 .cipher_info = {
343162306a36Sopenharmony_ci			 .alg = CIPHER_ALG_3DES,
343262306a36Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
343362306a36Sopenharmony_ci			 },
343462306a36Sopenharmony_ci	 .auth_info = {
343562306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA224,
343662306a36Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
343762306a36Sopenharmony_ci		       },
343862306a36Sopenharmony_ci	 .auth_first = 0,
343962306a36Sopenharmony_ci	 },
344062306a36Sopenharmony_ci	{
344162306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
344262306a36Sopenharmony_ci	 .alg.aead = {
344362306a36Sopenharmony_ci		 .base = {
344462306a36Sopenharmony_ci			.cra_name = "authenc(hmac(sha256),cbc(des3_ede))",
344562306a36Sopenharmony_ci			.cra_driver_name = "authenc-hmac-sha256-cbc-des3-iproc",
344662306a36Sopenharmony_ci			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
344762306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
344862306a36Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
344962306a36Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
345062306a36Sopenharmony_ci		 },
345162306a36Sopenharmony_ci		 .setkey = aead_authenc_setkey,
345262306a36Sopenharmony_ci		 .ivsize = DES3_EDE_BLOCK_SIZE,
345362306a36Sopenharmony_ci		 .maxauthsize = SHA256_DIGEST_SIZE,
345462306a36Sopenharmony_ci	 },
345562306a36Sopenharmony_ci	 .cipher_info = {
345662306a36Sopenharmony_ci			 .alg = CIPHER_ALG_3DES,
345762306a36Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
345862306a36Sopenharmony_ci			 },
345962306a36Sopenharmony_ci	 .auth_info = {
346062306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA256,
346162306a36Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
346262306a36Sopenharmony_ci		       },
346362306a36Sopenharmony_ci	 .auth_first = 0,
346462306a36Sopenharmony_ci	 },
346562306a36Sopenharmony_ci	{
346662306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
346762306a36Sopenharmony_ci	 .alg.aead = {
346862306a36Sopenharmony_ci		 .base = {
346962306a36Sopenharmony_ci			.cra_name = "authenc(hmac(sha384),cbc(des3_ede))",
347062306a36Sopenharmony_ci			.cra_driver_name = "authenc-hmac-sha384-cbc-des3-iproc",
347162306a36Sopenharmony_ci			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
347262306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
347362306a36Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
347462306a36Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
347562306a36Sopenharmony_ci		 },
347662306a36Sopenharmony_ci		 .setkey = aead_authenc_setkey,
347762306a36Sopenharmony_ci		 .ivsize = DES3_EDE_BLOCK_SIZE,
347862306a36Sopenharmony_ci		 .maxauthsize = SHA384_DIGEST_SIZE,
347962306a36Sopenharmony_ci	 },
348062306a36Sopenharmony_ci	 .cipher_info = {
348162306a36Sopenharmony_ci			 .alg = CIPHER_ALG_3DES,
348262306a36Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
348362306a36Sopenharmony_ci			 },
348462306a36Sopenharmony_ci	 .auth_info = {
348562306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA384,
348662306a36Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
348762306a36Sopenharmony_ci		       },
348862306a36Sopenharmony_ci	 .auth_first = 0,
348962306a36Sopenharmony_ci	 },
349062306a36Sopenharmony_ci	{
349162306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
349262306a36Sopenharmony_ci	 .alg.aead = {
349362306a36Sopenharmony_ci		 .base = {
349462306a36Sopenharmony_ci			.cra_name = "authenc(hmac(sha512),cbc(des3_ede))",
349562306a36Sopenharmony_ci			.cra_driver_name = "authenc-hmac-sha512-cbc-des3-iproc",
349662306a36Sopenharmony_ci			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
349762306a36Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
349862306a36Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
349962306a36Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
350062306a36Sopenharmony_ci		 },
350162306a36Sopenharmony_ci		 .setkey = aead_authenc_setkey,
350262306a36Sopenharmony_ci		 .ivsize = DES3_EDE_BLOCK_SIZE,
350362306a36Sopenharmony_ci		 .maxauthsize = SHA512_DIGEST_SIZE,
350462306a36Sopenharmony_ci	 },
350562306a36Sopenharmony_ci	 .cipher_info = {
350662306a36Sopenharmony_ci			 .alg = CIPHER_ALG_3DES,
350762306a36Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
350862306a36Sopenharmony_ci			 },
350962306a36Sopenharmony_ci	 .auth_info = {
351062306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA512,
351162306a36Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
351262306a36Sopenharmony_ci		       },
351362306a36Sopenharmony_ci	 .auth_first = 0,
351462306a36Sopenharmony_ci	 },
351562306a36Sopenharmony_ci
351662306a36Sopenharmony_ci/* SKCIPHER algorithms. */
351762306a36Sopenharmony_ci	{
351862306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_SKCIPHER,
351962306a36Sopenharmony_ci	 .alg.skcipher = {
352062306a36Sopenharmony_ci			.base.cra_name = "ofb(des)",
352162306a36Sopenharmony_ci			.base.cra_driver_name = "ofb-des-iproc",
352262306a36Sopenharmony_ci			.base.cra_blocksize = DES_BLOCK_SIZE,
352362306a36Sopenharmony_ci			.min_keysize = DES_KEY_SIZE,
352462306a36Sopenharmony_ci			.max_keysize = DES_KEY_SIZE,
352562306a36Sopenharmony_ci			.ivsize = DES_BLOCK_SIZE,
352662306a36Sopenharmony_ci			},
352762306a36Sopenharmony_ci	 .cipher_info = {
352862306a36Sopenharmony_ci			 .alg = CIPHER_ALG_DES,
352962306a36Sopenharmony_ci			 .mode = CIPHER_MODE_OFB,
353062306a36Sopenharmony_ci			 },
353162306a36Sopenharmony_ci	 .auth_info = {
353262306a36Sopenharmony_ci		       .alg = HASH_ALG_NONE,
353362306a36Sopenharmony_ci		       .mode = HASH_MODE_NONE,
353462306a36Sopenharmony_ci		       },
353562306a36Sopenharmony_ci	 },
353662306a36Sopenharmony_ci	{
353762306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_SKCIPHER,
353862306a36Sopenharmony_ci	 .alg.skcipher = {
353962306a36Sopenharmony_ci			.base.cra_name = "cbc(des)",
354062306a36Sopenharmony_ci			.base.cra_driver_name = "cbc-des-iproc",
354162306a36Sopenharmony_ci			.base.cra_blocksize = DES_BLOCK_SIZE,
354262306a36Sopenharmony_ci			.min_keysize = DES_KEY_SIZE,
354362306a36Sopenharmony_ci			.max_keysize = DES_KEY_SIZE,
354462306a36Sopenharmony_ci			.ivsize = DES_BLOCK_SIZE,
354562306a36Sopenharmony_ci			},
354662306a36Sopenharmony_ci	 .cipher_info = {
354762306a36Sopenharmony_ci			 .alg = CIPHER_ALG_DES,
354862306a36Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
354962306a36Sopenharmony_ci			 },
355062306a36Sopenharmony_ci	 .auth_info = {
355162306a36Sopenharmony_ci		       .alg = HASH_ALG_NONE,
355262306a36Sopenharmony_ci		       .mode = HASH_MODE_NONE,
355362306a36Sopenharmony_ci		       },
355462306a36Sopenharmony_ci	 },
355562306a36Sopenharmony_ci	{
355662306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_SKCIPHER,
355762306a36Sopenharmony_ci	 .alg.skcipher = {
355862306a36Sopenharmony_ci			.base.cra_name = "ecb(des)",
355962306a36Sopenharmony_ci			.base.cra_driver_name = "ecb-des-iproc",
356062306a36Sopenharmony_ci			.base.cra_blocksize = DES_BLOCK_SIZE,
356162306a36Sopenharmony_ci			.min_keysize = DES_KEY_SIZE,
356262306a36Sopenharmony_ci			.max_keysize = DES_KEY_SIZE,
356362306a36Sopenharmony_ci			.ivsize = 0,
356462306a36Sopenharmony_ci			},
356562306a36Sopenharmony_ci	 .cipher_info = {
356662306a36Sopenharmony_ci			 .alg = CIPHER_ALG_DES,
356762306a36Sopenharmony_ci			 .mode = CIPHER_MODE_ECB,
356862306a36Sopenharmony_ci			 },
356962306a36Sopenharmony_ci	 .auth_info = {
357062306a36Sopenharmony_ci		       .alg = HASH_ALG_NONE,
357162306a36Sopenharmony_ci		       .mode = HASH_MODE_NONE,
357262306a36Sopenharmony_ci		       },
357362306a36Sopenharmony_ci	 },
357462306a36Sopenharmony_ci	{
357562306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_SKCIPHER,
357662306a36Sopenharmony_ci	 .alg.skcipher = {
357762306a36Sopenharmony_ci			.base.cra_name = "ofb(des3_ede)",
357862306a36Sopenharmony_ci			.base.cra_driver_name = "ofb-des3-iproc",
357962306a36Sopenharmony_ci			.base.cra_blocksize = DES3_EDE_BLOCK_SIZE,
358062306a36Sopenharmony_ci			.min_keysize = DES3_EDE_KEY_SIZE,
358162306a36Sopenharmony_ci			.max_keysize = DES3_EDE_KEY_SIZE,
358262306a36Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
358362306a36Sopenharmony_ci			},
358462306a36Sopenharmony_ci	 .cipher_info = {
358562306a36Sopenharmony_ci			 .alg = CIPHER_ALG_3DES,
358662306a36Sopenharmony_ci			 .mode = CIPHER_MODE_OFB,
358762306a36Sopenharmony_ci			 },
358862306a36Sopenharmony_ci	 .auth_info = {
358962306a36Sopenharmony_ci		       .alg = HASH_ALG_NONE,
359062306a36Sopenharmony_ci		       .mode = HASH_MODE_NONE,
359162306a36Sopenharmony_ci		       },
359262306a36Sopenharmony_ci	 },
359362306a36Sopenharmony_ci	{
359462306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_SKCIPHER,
359562306a36Sopenharmony_ci	 .alg.skcipher = {
359662306a36Sopenharmony_ci			.base.cra_name = "cbc(des3_ede)",
359762306a36Sopenharmony_ci			.base.cra_driver_name = "cbc-des3-iproc",
359862306a36Sopenharmony_ci			.base.cra_blocksize = DES3_EDE_BLOCK_SIZE,
359962306a36Sopenharmony_ci			.min_keysize = DES3_EDE_KEY_SIZE,
360062306a36Sopenharmony_ci			.max_keysize = DES3_EDE_KEY_SIZE,
360162306a36Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
360262306a36Sopenharmony_ci			},
360362306a36Sopenharmony_ci	 .cipher_info = {
360462306a36Sopenharmony_ci			 .alg = CIPHER_ALG_3DES,
360562306a36Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
360662306a36Sopenharmony_ci			 },
360762306a36Sopenharmony_ci	 .auth_info = {
360862306a36Sopenharmony_ci		       .alg = HASH_ALG_NONE,
360962306a36Sopenharmony_ci		       .mode = HASH_MODE_NONE,
361062306a36Sopenharmony_ci		       },
361162306a36Sopenharmony_ci	 },
361262306a36Sopenharmony_ci	{
361362306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_SKCIPHER,
361462306a36Sopenharmony_ci	 .alg.skcipher = {
361562306a36Sopenharmony_ci			.base.cra_name = "ecb(des3_ede)",
361662306a36Sopenharmony_ci			.base.cra_driver_name = "ecb-des3-iproc",
361762306a36Sopenharmony_ci			.base.cra_blocksize = DES3_EDE_BLOCK_SIZE,
361862306a36Sopenharmony_ci			.min_keysize = DES3_EDE_KEY_SIZE,
361962306a36Sopenharmony_ci			.max_keysize = DES3_EDE_KEY_SIZE,
362062306a36Sopenharmony_ci			.ivsize = 0,
362162306a36Sopenharmony_ci			},
362262306a36Sopenharmony_ci	 .cipher_info = {
362362306a36Sopenharmony_ci			 .alg = CIPHER_ALG_3DES,
362462306a36Sopenharmony_ci			 .mode = CIPHER_MODE_ECB,
362562306a36Sopenharmony_ci			 },
362662306a36Sopenharmony_ci	 .auth_info = {
362762306a36Sopenharmony_ci		       .alg = HASH_ALG_NONE,
362862306a36Sopenharmony_ci		       .mode = HASH_MODE_NONE,
362962306a36Sopenharmony_ci		       },
363062306a36Sopenharmony_ci	 },
363162306a36Sopenharmony_ci	{
363262306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_SKCIPHER,
363362306a36Sopenharmony_ci	 .alg.skcipher = {
363462306a36Sopenharmony_ci			.base.cra_name = "ofb(aes)",
363562306a36Sopenharmony_ci			.base.cra_driver_name = "ofb-aes-iproc",
363662306a36Sopenharmony_ci			.base.cra_blocksize = AES_BLOCK_SIZE,
363762306a36Sopenharmony_ci			.min_keysize = AES_MIN_KEY_SIZE,
363862306a36Sopenharmony_ci			.max_keysize = AES_MAX_KEY_SIZE,
363962306a36Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
364062306a36Sopenharmony_ci			},
364162306a36Sopenharmony_ci	 .cipher_info = {
364262306a36Sopenharmony_ci			 .alg = CIPHER_ALG_AES,
364362306a36Sopenharmony_ci			 .mode = CIPHER_MODE_OFB,
364462306a36Sopenharmony_ci			 },
364562306a36Sopenharmony_ci	 .auth_info = {
364662306a36Sopenharmony_ci		       .alg = HASH_ALG_NONE,
364762306a36Sopenharmony_ci		       .mode = HASH_MODE_NONE,
364862306a36Sopenharmony_ci		       },
364962306a36Sopenharmony_ci	 },
365062306a36Sopenharmony_ci	{
365162306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_SKCIPHER,
365262306a36Sopenharmony_ci	 .alg.skcipher = {
365362306a36Sopenharmony_ci			.base.cra_name = "cbc(aes)",
365462306a36Sopenharmony_ci			.base.cra_driver_name = "cbc-aes-iproc",
365562306a36Sopenharmony_ci			.base.cra_blocksize = AES_BLOCK_SIZE,
365662306a36Sopenharmony_ci			.min_keysize = AES_MIN_KEY_SIZE,
365762306a36Sopenharmony_ci			.max_keysize = AES_MAX_KEY_SIZE,
365862306a36Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
365962306a36Sopenharmony_ci			},
366062306a36Sopenharmony_ci	 .cipher_info = {
366162306a36Sopenharmony_ci			 .alg = CIPHER_ALG_AES,
366262306a36Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
366362306a36Sopenharmony_ci			 },
366462306a36Sopenharmony_ci	 .auth_info = {
366562306a36Sopenharmony_ci		       .alg = HASH_ALG_NONE,
366662306a36Sopenharmony_ci		       .mode = HASH_MODE_NONE,
366762306a36Sopenharmony_ci		       },
366862306a36Sopenharmony_ci	 },
366962306a36Sopenharmony_ci	{
367062306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_SKCIPHER,
367162306a36Sopenharmony_ci	 .alg.skcipher = {
367262306a36Sopenharmony_ci			.base.cra_name = "ecb(aes)",
367362306a36Sopenharmony_ci			.base.cra_driver_name = "ecb-aes-iproc",
367462306a36Sopenharmony_ci			.base.cra_blocksize = AES_BLOCK_SIZE,
367562306a36Sopenharmony_ci			.min_keysize = AES_MIN_KEY_SIZE,
367662306a36Sopenharmony_ci			.max_keysize = AES_MAX_KEY_SIZE,
367762306a36Sopenharmony_ci			.ivsize = 0,
367862306a36Sopenharmony_ci			},
367962306a36Sopenharmony_ci	 .cipher_info = {
368062306a36Sopenharmony_ci			 .alg = CIPHER_ALG_AES,
368162306a36Sopenharmony_ci			 .mode = CIPHER_MODE_ECB,
368262306a36Sopenharmony_ci			 },
368362306a36Sopenharmony_ci	 .auth_info = {
368462306a36Sopenharmony_ci		       .alg = HASH_ALG_NONE,
368562306a36Sopenharmony_ci		       .mode = HASH_MODE_NONE,
368662306a36Sopenharmony_ci		       },
368762306a36Sopenharmony_ci	 },
368862306a36Sopenharmony_ci	{
368962306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_SKCIPHER,
369062306a36Sopenharmony_ci	 .alg.skcipher = {
369162306a36Sopenharmony_ci			.base.cra_name = "ctr(aes)",
369262306a36Sopenharmony_ci			.base.cra_driver_name = "ctr-aes-iproc",
369362306a36Sopenharmony_ci			.base.cra_blocksize = AES_BLOCK_SIZE,
369462306a36Sopenharmony_ci			.min_keysize = AES_MIN_KEY_SIZE,
369562306a36Sopenharmony_ci			.max_keysize = AES_MAX_KEY_SIZE,
369662306a36Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
369762306a36Sopenharmony_ci			},
369862306a36Sopenharmony_ci	 .cipher_info = {
369962306a36Sopenharmony_ci			 .alg = CIPHER_ALG_AES,
370062306a36Sopenharmony_ci			 .mode = CIPHER_MODE_CTR,
370162306a36Sopenharmony_ci			 },
370262306a36Sopenharmony_ci	 .auth_info = {
370362306a36Sopenharmony_ci		       .alg = HASH_ALG_NONE,
370462306a36Sopenharmony_ci		       .mode = HASH_MODE_NONE,
370562306a36Sopenharmony_ci		       },
370662306a36Sopenharmony_ci	 },
370762306a36Sopenharmony_ci{
370862306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_SKCIPHER,
370962306a36Sopenharmony_ci	 .alg.skcipher = {
371062306a36Sopenharmony_ci			.base.cra_name = "xts(aes)",
371162306a36Sopenharmony_ci			.base.cra_driver_name = "xts-aes-iproc",
371262306a36Sopenharmony_ci			.base.cra_blocksize = AES_BLOCK_SIZE,
371362306a36Sopenharmony_ci			.min_keysize = 2 * AES_MIN_KEY_SIZE,
371462306a36Sopenharmony_ci			.max_keysize = 2 * AES_MAX_KEY_SIZE,
371562306a36Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
371662306a36Sopenharmony_ci			},
371762306a36Sopenharmony_ci	 .cipher_info = {
371862306a36Sopenharmony_ci			 .alg = CIPHER_ALG_AES,
371962306a36Sopenharmony_ci			 .mode = CIPHER_MODE_XTS,
372062306a36Sopenharmony_ci			 },
372162306a36Sopenharmony_ci	 .auth_info = {
372262306a36Sopenharmony_ci		       .alg = HASH_ALG_NONE,
372362306a36Sopenharmony_ci		       .mode = HASH_MODE_NONE,
372462306a36Sopenharmony_ci		       },
372562306a36Sopenharmony_ci	 },
372662306a36Sopenharmony_ci
372762306a36Sopenharmony_ci/* AHASH algorithms. */
372862306a36Sopenharmony_ci	{
372962306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
373062306a36Sopenharmony_ci	 .alg.hash = {
373162306a36Sopenharmony_ci		      .halg.digestsize = MD5_DIGEST_SIZE,
373262306a36Sopenharmony_ci		      .halg.base = {
373362306a36Sopenharmony_ci				    .cra_name = "md5",
373462306a36Sopenharmony_ci				    .cra_driver_name = "md5-iproc",
373562306a36Sopenharmony_ci				    .cra_blocksize = MD5_BLOCK_WORDS * 4,
373662306a36Sopenharmony_ci				    .cra_flags = CRYPTO_ALG_ASYNC |
373762306a36Sopenharmony_ci						 CRYPTO_ALG_ALLOCATES_MEMORY,
373862306a36Sopenharmony_ci				}
373962306a36Sopenharmony_ci		      },
374062306a36Sopenharmony_ci	 .cipher_info = {
374162306a36Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
374262306a36Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
374362306a36Sopenharmony_ci			 },
374462306a36Sopenharmony_ci	 .auth_info = {
374562306a36Sopenharmony_ci		       .alg = HASH_ALG_MD5,
374662306a36Sopenharmony_ci		       .mode = HASH_MODE_HASH,
374762306a36Sopenharmony_ci		       },
374862306a36Sopenharmony_ci	 },
374962306a36Sopenharmony_ci	{
375062306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
375162306a36Sopenharmony_ci	 .alg.hash = {
375262306a36Sopenharmony_ci		      .halg.digestsize = MD5_DIGEST_SIZE,
375362306a36Sopenharmony_ci		      .halg.base = {
375462306a36Sopenharmony_ci				    .cra_name = "hmac(md5)",
375562306a36Sopenharmony_ci				    .cra_driver_name = "hmac-md5-iproc",
375662306a36Sopenharmony_ci				    .cra_blocksize = MD5_BLOCK_WORDS * 4,
375762306a36Sopenharmony_ci				}
375862306a36Sopenharmony_ci		      },
375962306a36Sopenharmony_ci	 .cipher_info = {
376062306a36Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
376162306a36Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
376262306a36Sopenharmony_ci			 },
376362306a36Sopenharmony_ci	 .auth_info = {
376462306a36Sopenharmony_ci		       .alg = HASH_ALG_MD5,
376562306a36Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
376662306a36Sopenharmony_ci		       },
376762306a36Sopenharmony_ci	 },
376862306a36Sopenharmony_ci	{.type = CRYPTO_ALG_TYPE_AHASH,
376962306a36Sopenharmony_ci	 .alg.hash = {
377062306a36Sopenharmony_ci		      .halg.digestsize = SHA1_DIGEST_SIZE,
377162306a36Sopenharmony_ci		      .halg.base = {
377262306a36Sopenharmony_ci				    .cra_name = "sha1",
377362306a36Sopenharmony_ci				    .cra_driver_name = "sha1-iproc",
377462306a36Sopenharmony_ci				    .cra_blocksize = SHA1_BLOCK_SIZE,
377562306a36Sopenharmony_ci				}
377662306a36Sopenharmony_ci		      },
377762306a36Sopenharmony_ci	 .cipher_info = {
377862306a36Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
377962306a36Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
378062306a36Sopenharmony_ci			 },
378162306a36Sopenharmony_ci	 .auth_info = {
378262306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA1,
378362306a36Sopenharmony_ci		       .mode = HASH_MODE_HASH,
378462306a36Sopenharmony_ci		       },
378562306a36Sopenharmony_ci	 },
378662306a36Sopenharmony_ci	{.type = CRYPTO_ALG_TYPE_AHASH,
378762306a36Sopenharmony_ci	 .alg.hash = {
378862306a36Sopenharmony_ci		      .halg.digestsize = SHA1_DIGEST_SIZE,
378962306a36Sopenharmony_ci		      .halg.base = {
379062306a36Sopenharmony_ci				    .cra_name = "hmac(sha1)",
379162306a36Sopenharmony_ci				    .cra_driver_name = "hmac-sha1-iproc",
379262306a36Sopenharmony_ci				    .cra_blocksize = SHA1_BLOCK_SIZE,
379362306a36Sopenharmony_ci				}
379462306a36Sopenharmony_ci		      },
379562306a36Sopenharmony_ci	 .cipher_info = {
379662306a36Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
379762306a36Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
379862306a36Sopenharmony_ci			 },
379962306a36Sopenharmony_ci	 .auth_info = {
380062306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA1,
380162306a36Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
380262306a36Sopenharmony_ci		       },
380362306a36Sopenharmony_ci	 },
380462306a36Sopenharmony_ci	{.type = CRYPTO_ALG_TYPE_AHASH,
380562306a36Sopenharmony_ci	 .alg.hash = {
380662306a36Sopenharmony_ci			.halg.digestsize = SHA224_DIGEST_SIZE,
380762306a36Sopenharmony_ci			.halg.base = {
380862306a36Sopenharmony_ci				    .cra_name = "sha224",
380962306a36Sopenharmony_ci				    .cra_driver_name = "sha224-iproc",
381062306a36Sopenharmony_ci				    .cra_blocksize = SHA224_BLOCK_SIZE,
381162306a36Sopenharmony_ci			}
381262306a36Sopenharmony_ci		      },
381362306a36Sopenharmony_ci	 .cipher_info = {
381462306a36Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
381562306a36Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
381662306a36Sopenharmony_ci			 },
381762306a36Sopenharmony_ci	 .auth_info = {
381862306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA224,
381962306a36Sopenharmony_ci		       .mode = HASH_MODE_HASH,
382062306a36Sopenharmony_ci		       },
382162306a36Sopenharmony_ci	 },
382262306a36Sopenharmony_ci	{.type = CRYPTO_ALG_TYPE_AHASH,
382362306a36Sopenharmony_ci	 .alg.hash = {
382462306a36Sopenharmony_ci		      .halg.digestsize = SHA224_DIGEST_SIZE,
382562306a36Sopenharmony_ci		      .halg.base = {
382662306a36Sopenharmony_ci				    .cra_name = "hmac(sha224)",
382762306a36Sopenharmony_ci				    .cra_driver_name = "hmac-sha224-iproc",
382862306a36Sopenharmony_ci				    .cra_blocksize = SHA224_BLOCK_SIZE,
382962306a36Sopenharmony_ci				}
383062306a36Sopenharmony_ci		      },
383162306a36Sopenharmony_ci	 .cipher_info = {
383262306a36Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
383362306a36Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
383462306a36Sopenharmony_ci			 },
383562306a36Sopenharmony_ci	 .auth_info = {
383662306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA224,
383762306a36Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
383862306a36Sopenharmony_ci		       },
383962306a36Sopenharmony_ci	 },
384062306a36Sopenharmony_ci	{.type = CRYPTO_ALG_TYPE_AHASH,
384162306a36Sopenharmony_ci	 .alg.hash = {
384262306a36Sopenharmony_ci		      .halg.digestsize = SHA256_DIGEST_SIZE,
384362306a36Sopenharmony_ci		      .halg.base = {
384462306a36Sopenharmony_ci				    .cra_name = "sha256",
384562306a36Sopenharmony_ci				    .cra_driver_name = "sha256-iproc",
384662306a36Sopenharmony_ci				    .cra_blocksize = SHA256_BLOCK_SIZE,
384762306a36Sopenharmony_ci				}
384862306a36Sopenharmony_ci		      },
384962306a36Sopenharmony_ci	 .cipher_info = {
385062306a36Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
385162306a36Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
385262306a36Sopenharmony_ci			 },
385362306a36Sopenharmony_ci	 .auth_info = {
385462306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA256,
385562306a36Sopenharmony_ci		       .mode = HASH_MODE_HASH,
385662306a36Sopenharmony_ci		       },
385762306a36Sopenharmony_ci	 },
385862306a36Sopenharmony_ci	{.type = CRYPTO_ALG_TYPE_AHASH,
385962306a36Sopenharmony_ci	 .alg.hash = {
386062306a36Sopenharmony_ci		      .halg.digestsize = SHA256_DIGEST_SIZE,
386162306a36Sopenharmony_ci		      .halg.base = {
386262306a36Sopenharmony_ci				    .cra_name = "hmac(sha256)",
386362306a36Sopenharmony_ci				    .cra_driver_name = "hmac-sha256-iproc",
386462306a36Sopenharmony_ci				    .cra_blocksize = SHA256_BLOCK_SIZE,
386562306a36Sopenharmony_ci				}
386662306a36Sopenharmony_ci		      },
386762306a36Sopenharmony_ci	 .cipher_info = {
386862306a36Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
386962306a36Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
387062306a36Sopenharmony_ci			 },
387162306a36Sopenharmony_ci	 .auth_info = {
387262306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA256,
387362306a36Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
387462306a36Sopenharmony_ci		       },
387562306a36Sopenharmony_ci	 },
387662306a36Sopenharmony_ci	{
387762306a36Sopenharmony_ci	.type = CRYPTO_ALG_TYPE_AHASH,
387862306a36Sopenharmony_ci	 .alg.hash = {
387962306a36Sopenharmony_ci		      .halg.digestsize = SHA384_DIGEST_SIZE,
388062306a36Sopenharmony_ci		      .halg.base = {
388162306a36Sopenharmony_ci				    .cra_name = "sha384",
388262306a36Sopenharmony_ci				    .cra_driver_name = "sha384-iproc",
388362306a36Sopenharmony_ci				    .cra_blocksize = SHA384_BLOCK_SIZE,
388462306a36Sopenharmony_ci				}
388562306a36Sopenharmony_ci		      },
388662306a36Sopenharmony_ci	 .cipher_info = {
388762306a36Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
388862306a36Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
388962306a36Sopenharmony_ci			 },
389062306a36Sopenharmony_ci	 .auth_info = {
389162306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA384,
389262306a36Sopenharmony_ci		       .mode = HASH_MODE_HASH,
389362306a36Sopenharmony_ci		       },
389462306a36Sopenharmony_ci	 },
389562306a36Sopenharmony_ci	{
389662306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
389762306a36Sopenharmony_ci	 .alg.hash = {
389862306a36Sopenharmony_ci		      .halg.digestsize = SHA384_DIGEST_SIZE,
389962306a36Sopenharmony_ci		      .halg.base = {
390062306a36Sopenharmony_ci				    .cra_name = "hmac(sha384)",
390162306a36Sopenharmony_ci				    .cra_driver_name = "hmac-sha384-iproc",
390262306a36Sopenharmony_ci				    .cra_blocksize = SHA384_BLOCK_SIZE,
390362306a36Sopenharmony_ci				}
390462306a36Sopenharmony_ci		      },
390562306a36Sopenharmony_ci	 .cipher_info = {
390662306a36Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
390762306a36Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
390862306a36Sopenharmony_ci			 },
390962306a36Sopenharmony_ci	 .auth_info = {
391062306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA384,
391162306a36Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
391262306a36Sopenharmony_ci		       },
391362306a36Sopenharmony_ci	 },
391462306a36Sopenharmony_ci	{
391562306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
391662306a36Sopenharmony_ci	 .alg.hash = {
391762306a36Sopenharmony_ci		      .halg.digestsize = SHA512_DIGEST_SIZE,
391862306a36Sopenharmony_ci		      .halg.base = {
391962306a36Sopenharmony_ci				    .cra_name = "sha512",
392062306a36Sopenharmony_ci				    .cra_driver_name = "sha512-iproc",
392162306a36Sopenharmony_ci				    .cra_blocksize = SHA512_BLOCK_SIZE,
392262306a36Sopenharmony_ci				}
392362306a36Sopenharmony_ci		      },
392462306a36Sopenharmony_ci	 .cipher_info = {
392562306a36Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
392662306a36Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
392762306a36Sopenharmony_ci			 },
392862306a36Sopenharmony_ci	 .auth_info = {
392962306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA512,
393062306a36Sopenharmony_ci		       .mode = HASH_MODE_HASH,
393162306a36Sopenharmony_ci		       },
393262306a36Sopenharmony_ci	 },
393362306a36Sopenharmony_ci	{
393462306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
393562306a36Sopenharmony_ci	 .alg.hash = {
393662306a36Sopenharmony_ci		      .halg.digestsize = SHA512_DIGEST_SIZE,
393762306a36Sopenharmony_ci		      .halg.base = {
393862306a36Sopenharmony_ci				    .cra_name = "hmac(sha512)",
393962306a36Sopenharmony_ci				    .cra_driver_name = "hmac-sha512-iproc",
394062306a36Sopenharmony_ci				    .cra_blocksize = SHA512_BLOCK_SIZE,
394162306a36Sopenharmony_ci				}
394262306a36Sopenharmony_ci		      },
394362306a36Sopenharmony_ci	 .cipher_info = {
394462306a36Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
394562306a36Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
394662306a36Sopenharmony_ci			 },
394762306a36Sopenharmony_ci	 .auth_info = {
394862306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA512,
394962306a36Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
395062306a36Sopenharmony_ci		       },
395162306a36Sopenharmony_ci	 },
395262306a36Sopenharmony_ci	{
395362306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
395462306a36Sopenharmony_ci	 .alg.hash = {
395562306a36Sopenharmony_ci		      .halg.digestsize = SHA3_224_DIGEST_SIZE,
395662306a36Sopenharmony_ci		      .halg.base = {
395762306a36Sopenharmony_ci				    .cra_name = "sha3-224",
395862306a36Sopenharmony_ci				    .cra_driver_name = "sha3-224-iproc",
395962306a36Sopenharmony_ci				    .cra_blocksize = SHA3_224_BLOCK_SIZE,
396062306a36Sopenharmony_ci				}
396162306a36Sopenharmony_ci		      },
396262306a36Sopenharmony_ci	 .cipher_info = {
396362306a36Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
396462306a36Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
396562306a36Sopenharmony_ci			 },
396662306a36Sopenharmony_ci	 .auth_info = {
396762306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA3_224,
396862306a36Sopenharmony_ci		       .mode = HASH_MODE_HASH,
396962306a36Sopenharmony_ci		       },
397062306a36Sopenharmony_ci	 },
397162306a36Sopenharmony_ci	{
397262306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
397362306a36Sopenharmony_ci	 .alg.hash = {
397462306a36Sopenharmony_ci		      .halg.digestsize = SHA3_224_DIGEST_SIZE,
397562306a36Sopenharmony_ci		      .halg.base = {
397662306a36Sopenharmony_ci				    .cra_name = "hmac(sha3-224)",
397762306a36Sopenharmony_ci				    .cra_driver_name = "hmac-sha3-224-iproc",
397862306a36Sopenharmony_ci				    .cra_blocksize = SHA3_224_BLOCK_SIZE,
397962306a36Sopenharmony_ci				}
398062306a36Sopenharmony_ci		      },
398162306a36Sopenharmony_ci	 .cipher_info = {
398262306a36Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
398362306a36Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
398462306a36Sopenharmony_ci			 },
398562306a36Sopenharmony_ci	 .auth_info = {
398662306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA3_224,
398762306a36Sopenharmony_ci		       .mode = HASH_MODE_HMAC
398862306a36Sopenharmony_ci		       },
398962306a36Sopenharmony_ci	 },
399062306a36Sopenharmony_ci	{
399162306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
399262306a36Sopenharmony_ci	 .alg.hash = {
399362306a36Sopenharmony_ci		      .halg.digestsize = SHA3_256_DIGEST_SIZE,
399462306a36Sopenharmony_ci		      .halg.base = {
399562306a36Sopenharmony_ci				    .cra_name = "sha3-256",
399662306a36Sopenharmony_ci				    .cra_driver_name = "sha3-256-iproc",
399762306a36Sopenharmony_ci				    .cra_blocksize = SHA3_256_BLOCK_SIZE,
399862306a36Sopenharmony_ci				}
399962306a36Sopenharmony_ci		      },
400062306a36Sopenharmony_ci	 .cipher_info = {
400162306a36Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
400262306a36Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
400362306a36Sopenharmony_ci			 },
400462306a36Sopenharmony_ci	 .auth_info = {
400562306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA3_256,
400662306a36Sopenharmony_ci		       .mode = HASH_MODE_HASH,
400762306a36Sopenharmony_ci		       },
400862306a36Sopenharmony_ci	 },
400962306a36Sopenharmony_ci	{
401062306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
401162306a36Sopenharmony_ci	 .alg.hash = {
401262306a36Sopenharmony_ci		      .halg.digestsize = SHA3_256_DIGEST_SIZE,
401362306a36Sopenharmony_ci		      .halg.base = {
401462306a36Sopenharmony_ci				    .cra_name = "hmac(sha3-256)",
401562306a36Sopenharmony_ci				    .cra_driver_name = "hmac-sha3-256-iproc",
401662306a36Sopenharmony_ci				    .cra_blocksize = SHA3_256_BLOCK_SIZE,
401762306a36Sopenharmony_ci				}
401862306a36Sopenharmony_ci		      },
401962306a36Sopenharmony_ci	 .cipher_info = {
402062306a36Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
402162306a36Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
402262306a36Sopenharmony_ci			 },
402362306a36Sopenharmony_ci	 .auth_info = {
402462306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA3_256,
402562306a36Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
402662306a36Sopenharmony_ci		       },
402762306a36Sopenharmony_ci	 },
402862306a36Sopenharmony_ci	{
402962306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
403062306a36Sopenharmony_ci	 .alg.hash = {
403162306a36Sopenharmony_ci		      .halg.digestsize = SHA3_384_DIGEST_SIZE,
403262306a36Sopenharmony_ci		      .halg.base = {
403362306a36Sopenharmony_ci				    .cra_name = "sha3-384",
403462306a36Sopenharmony_ci				    .cra_driver_name = "sha3-384-iproc",
403562306a36Sopenharmony_ci				    .cra_blocksize = SHA3_224_BLOCK_SIZE,
403662306a36Sopenharmony_ci				}
403762306a36Sopenharmony_ci		      },
403862306a36Sopenharmony_ci	 .cipher_info = {
403962306a36Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
404062306a36Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
404162306a36Sopenharmony_ci			 },
404262306a36Sopenharmony_ci	 .auth_info = {
404362306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA3_384,
404462306a36Sopenharmony_ci		       .mode = HASH_MODE_HASH,
404562306a36Sopenharmony_ci		       },
404662306a36Sopenharmony_ci	 },
404762306a36Sopenharmony_ci	{
404862306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
404962306a36Sopenharmony_ci	 .alg.hash = {
405062306a36Sopenharmony_ci		      .halg.digestsize = SHA3_384_DIGEST_SIZE,
405162306a36Sopenharmony_ci		      .halg.base = {
405262306a36Sopenharmony_ci				    .cra_name = "hmac(sha3-384)",
405362306a36Sopenharmony_ci				    .cra_driver_name = "hmac-sha3-384-iproc",
405462306a36Sopenharmony_ci				    .cra_blocksize = SHA3_384_BLOCK_SIZE,
405562306a36Sopenharmony_ci				}
405662306a36Sopenharmony_ci		      },
405762306a36Sopenharmony_ci	 .cipher_info = {
405862306a36Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
405962306a36Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
406062306a36Sopenharmony_ci			 },
406162306a36Sopenharmony_ci	 .auth_info = {
406262306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA3_384,
406362306a36Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
406462306a36Sopenharmony_ci		       },
406562306a36Sopenharmony_ci	 },
406662306a36Sopenharmony_ci	{
406762306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
406862306a36Sopenharmony_ci	 .alg.hash = {
406962306a36Sopenharmony_ci		      .halg.digestsize = SHA3_512_DIGEST_SIZE,
407062306a36Sopenharmony_ci		      .halg.base = {
407162306a36Sopenharmony_ci				    .cra_name = "sha3-512",
407262306a36Sopenharmony_ci				    .cra_driver_name = "sha3-512-iproc",
407362306a36Sopenharmony_ci				    .cra_blocksize = SHA3_512_BLOCK_SIZE,
407462306a36Sopenharmony_ci				}
407562306a36Sopenharmony_ci		      },
407662306a36Sopenharmony_ci	 .cipher_info = {
407762306a36Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
407862306a36Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
407962306a36Sopenharmony_ci			 },
408062306a36Sopenharmony_ci	 .auth_info = {
408162306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA3_512,
408262306a36Sopenharmony_ci		       .mode = HASH_MODE_HASH,
408362306a36Sopenharmony_ci		       },
408462306a36Sopenharmony_ci	 },
408562306a36Sopenharmony_ci	{
408662306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
408762306a36Sopenharmony_ci	 .alg.hash = {
408862306a36Sopenharmony_ci		      .halg.digestsize = SHA3_512_DIGEST_SIZE,
408962306a36Sopenharmony_ci		      .halg.base = {
409062306a36Sopenharmony_ci				    .cra_name = "hmac(sha3-512)",
409162306a36Sopenharmony_ci				    .cra_driver_name = "hmac-sha3-512-iproc",
409262306a36Sopenharmony_ci				    .cra_blocksize = SHA3_512_BLOCK_SIZE,
409362306a36Sopenharmony_ci				}
409462306a36Sopenharmony_ci		      },
409562306a36Sopenharmony_ci	 .cipher_info = {
409662306a36Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
409762306a36Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
409862306a36Sopenharmony_ci			 },
409962306a36Sopenharmony_ci	 .auth_info = {
410062306a36Sopenharmony_ci		       .alg = HASH_ALG_SHA3_512,
410162306a36Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
410262306a36Sopenharmony_ci		       },
410362306a36Sopenharmony_ci	 },
410462306a36Sopenharmony_ci	{
410562306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
410662306a36Sopenharmony_ci	 .alg.hash = {
410762306a36Sopenharmony_ci		      .halg.digestsize = AES_BLOCK_SIZE,
410862306a36Sopenharmony_ci		      .halg.base = {
410962306a36Sopenharmony_ci				    .cra_name = "xcbc(aes)",
411062306a36Sopenharmony_ci				    .cra_driver_name = "xcbc-aes-iproc",
411162306a36Sopenharmony_ci				    .cra_blocksize = AES_BLOCK_SIZE,
411262306a36Sopenharmony_ci				}
411362306a36Sopenharmony_ci		      },
411462306a36Sopenharmony_ci	 .cipher_info = {
411562306a36Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
411662306a36Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
411762306a36Sopenharmony_ci			 },
411862306a36Sopenharmony_ci	 .auth_info = {
411962306a36Sopenharmony_ci		       .alg = HASH_ALG_AES,
412062306a36Sopenharmony_ci		       .mode = HASH_MODE_XCBC,
412162306a36Sopenharmony_ci		       },
412262306a36Sopenharmony_ci	 },
412362306a36Sopenharmony_ci	{
412462306a36Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
412562306a36Sopenharmony_ci	 .alg.hash = {
412662306a36Sopenharmony_ci		      .halg.digestsize = AES_BLOCK_SIZE,
412762306a36Sopenharmony_ci		      .halg.base = {
412862306a36Sopenharmony_ci				    .cra_name = "cmac(aes)",
412962306a36Sopenharmony_ci				    .cra_driver_name = "cmac-aes-iproc",
413062306a36Sopenharmony_ci				    .cra_blocksize = AES_BLOCK_SIZE,
413162306a36Sopenharmony_ci				}
413262306a36Sopenharmony_ci		      },
413362306a36Sopenharmony_ci	 .cipher_info = {
413462306a36Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
413562306a36Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
413662306a36Sopenharmony_ci			 },
413762306a36Sopenharmony_ci	 .auth_info = {
413862306a36Sopenharmony_ci		       .alg = HASH_ALG_AES,
413962306a36Sopenharmony_ci		       .mode = HASH_MODE_CMAC,
414062306a36Sopenharmony_ci		       },
414162306a36Sopenharmony_ci	 },
414262306a36Sopenharmony_ci};
414362306a36Sopenharmony_ci
414462306a36Sopenharmony_cistatic int generic_cra_init(struct crypto_tfm *tfm,
414562306a36Sopenharmony_ci			    struct iproc_alg_s *cipher_alg)
414662306a36Sopenharmony_ci{
414762306a36Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
414862306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_tfm_ctx(tfm);
414962306a36Sopenharmony_ci	unsigned int blocksize = crypto_tfm_alg_blocksize(tfm);
415062306a36Sopenharmony_ci
415162306a36Sopenharmony_ci	flow_log("%s()\n", __func__);
415262306a36Sopenharmony_ci
415362306a36Sopenharmony_ci	ctx->alg = cipher_alg;
415462306a36Sopenharmony_ci	ctx->cipher = cipher_alg->cipher_info;
415562306a36Sopenharmony_ci	ctx->auth = cipher_alg->auth_info;
415662306a36Sopenharmony_ci	ctx->auth_first = cipher_alg->auth_first;
415762306a36Sopenharmony_ci	ctx->max_payload = spu->spu_ctx_max_payload(ctx->cipher.alg,
415862306a36Sopenharmony_ci						    ctx->cipher.mode,
415962306a36Sopenharmony_ci						    blocksize);
416062306a36Sopenharmony_ci	ctx->fallback_cipher = NULL;
416162306a36Sopenharmony_ci
416262306a36Sopenharmony_ci	ctx->enckeylen = 0;
416362306a36Sopenharmony_ci	ctx->authkeylen = 0;
416462306a36Sopenharmony_ci
416562306a36Sopenharmony_ci	atomic_inc(&iproc_priv.stream_count);
416662306a36Sopenharmony_ci	atomic_inc(&iproc_priv.session_count);
416762306a36Sopenharmony_ci
416862306a36Sopenharmony_ci	return 0;
416962306a36Sopenharmony_ci}
417062306a36Sopenharmony_ci
417162306a36Sopenharmony_cistatic int skcipher_init_tfm(struct crypto_skcipher *skcipher)
417262306a36Sopenharmony_ci{
417362306a36Sopenharmony_ci	struct crypto_tfm *tfm = crypto_skcipher_tfm(skcipher);
417462306a36Sopenharmony_ci	struct skcipher_alg *alg = crypto_skcipher_alg(skcipher);
417562306a36Sopenharmony_ci	struct iproc_alg_s *cipher_alg;
417662306a36Sopenharmony_ci
417762306a36Sopenharmony_ci	flow_log("%s()\n", __func__);
417862306a36Sopenharmony_ci
417962306a36Sopenharmony_ci	crypto_skcipher_set_reqsize(skcipher, sizeof(struct iproc_reqctx_s));
418062306a36Sopenharmony_ci
418162306a36Sopenharmony_ci	cipher_alg = container_of(alg, struct iproc_alg_s, alg.skcipher);
418262306a36Sopenharmony_ci	return generic_cra_init(tfm, cipher_alg);
418362306a36Sopenharmony_ci}
418462306a36Sopenharmony_ci
418562306a36Sopenharmony_cistatic int ahash_cra_init(struct crypto_tfm *tfm)
418662306a36Sopenharmony_ci{
418762306a36Sopenharmony_ci	int err;
418862306a36Sopenharmony_ci	struct crypto_alg *alg = tfm->__crt_alg;
418962306a36Sopenharmony_ci	struct iproc_alg_s *cipher_alg;
419062306a36Sopenharmony_ci
419162306a36Sopenharmony_ci	cipher_alg = container_of(__crypto_ahash_alg(alg), struct iproc_alg_s,
419262306a36Sopenharmony_ci				  alg.hash);
419362306a36Sopenharmony_ci
419462306a36Sopenharmony_ci	err = generic_cra_init(tfm, cipher_alg);
419562306a36Sopenharmony_ci	flow_log("%s()\n", __func__);
419662306a36Sopenharmony_ci
419762306a36Sopenharmony_ci	/*
419862306a36Sopenharmony_ci	 * export state size has to be < 512 bytes. So don't include msg bufs
419962306a36Sopenharmony_ci	 * in state size.
420062306a36Sopenharmony_ci	 */
420162306a36Sopenharmony_ci	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
420262306a36Sopenharmony_ci				 sizeof(struct iproc_reqctx_s));
420362306a36Sopenharmony_ci
420462306a36Sopenharmony_ci	return err;
420562306a36Sopenharmony_ci}
420662306a36Sopenharmony_ci
420762306a36Sopenharmony_cistatic int aead_cra_init(struct crypto_aead *aead)
420862306a36Sopenharmony_ci{
420962306a36Sopenharmony_ci	unsigned int reqsize = sizeof(struct iproc_reqctx_s);
421062306a36Sopenharmony_ci	struct crypto_tfm *tfm = crypto_aead_tfm(aead);
421162306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_tfm_ctx(tfm);
421262306a36Sopenharmony_ci	struct crypto_alg *alg = tfm->__crt_alg;
421362306a36Sopenharmony_ci	struct aead_alg *aalg = container_of(alg, struct aead_alg, base);
421462306a36Sopenharmony_ci	struct iproc_alg_s *cipher_alg = container_of(aalg, struct iproc_alg_s,
421562306a36Sopenharmony_ci						      alg.aead);
421662306a36Sopenharmony_ci
421762306a36Sopenharmony_ci	int err = generic_cra_init(tfm, cipher_alg);
421862306a36Sopenharmony_ci
421962306a36Sopenharmony_ci	flow_log("%s()\n", __func__);
422062306a36Sopenharmony_ci
422162306a36Sopenharmony_ci	ctx->is_esp = false;
422262306a36Sopenharmony_ci	ctx->salt_len = 0;
422362306a36Sopenharmony_ci	ctx->salt_offset = 0;
422462306a36Sopenharmony_ci
422562306a36Sopenharmony_ci	/* random first IV */
422662306a36Sopenharmony_ci	get_random_bytes(ctx->iv, MAX_IV_SIZE);
422762306a36Sopenharmony_ci	flow_dump("  iv: ", ctx->iv, MAX_IV_SIZE);
422862306a36Sopenharmony_ci
422962306a36Sopenharmony_ci	if (err)
423062306a36Sopenharmony_ci		goto out;
423162306a36Sopenharmony_ci
423262306a36Sopenharmony_ci	if (!(alg->cra_flags & CRYPTO_ALG_NEED_FALLBACK))
423362306a36Sopenharmony_ci		goto reqsize;
423462306a36Sopenharmony_ci
423562306a36Sopenharmony_ci	flow_log("%s() creating fallback cipher\n", __func__);
423662306a36Sopenharmony_ci
423762306a36Sopenharmony_ci	ctx->fallback_cipher = crypto_alloc_aead(alg->cra_name, 0,
423862306a36Sopenharmony_ci						 CRYPTO_ALG_ASYNC |
423962306a36Sopenharmony_ci						 CRYPTO_ALG_NEED_FALLBACK);
424062306a36Sopenharmony_ci	if (IS_ERR(ctx->fallback_cipher)) {
424162306a36Sopenharmony_ci		pr_err("%s() Error: failed to allocate fallback for %s\n",
424262306a36Sopenharmony_ci		       __func__, alg->cra_name);
424362306a36Sopenharmony_ci		return PTR_ERR(ctx->fallback_cipher);
424462306a36Sopenharmony_ci	}
424562306a36Sopenharmony_ci
424662306a36Sopenharmony_ci	reqsize += crypto_aead_reqsize(ctx->fallback_cipher);
424762306a36Sopenharmony_ci
424862306a36Sopenharmony_cireqsize:
424962306a36Sopenharmony_ci	crypto_aead_set_reqsize(aead, reqsize);
425062306a36Sopenharmony_ci
425162306a36Sopenharmony_ciout:
425262306a36Sopenharmony_ci	return err;
425362306a36Sopenharmony_ci}
425462306a36Sopenharmony_ci
425562306a36Sopenharmony_cistatic void generic_cra_exit(struct crypto_tfm *tfm)
425662306a36Sopenharmony_ci{
425762306a36Sopenharmony_ci	atomic_dec(&iproc_priv.session_count);
425862306a36Sopenharmony_ci}
425962306a36Sopenharmony_ci
426062306a36Sopenharmony_cistatic void skcipher_exit_tfm(struct crypto_skcipher *tfm)
426162306a36Sopenharmony_ci{
426262306a36Sopenharmony_ci	generic_cra_exit(crypto_skcipher_tfm(tfm));
426362306a36Sopenharmony_ci}
426462306a36Sopenharmony_ci
426562306a36Sopenharmony_cistatic void aead_cra_exit(struct crypto_aead *aead)
426662306a36Sopenharmony_ci{
426762306a36Sopenharmony_ci	struct crypto_tfm *tfm = crypto_aead_tfm(aead);
426862306a36Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_tfm_ctx(tfm);
426962306a36Sopenharmony_ci
427062306a36Sopenharmony_ci	generic_cra_exit(tfm);
427162306a36Sopenharmony_ci
427262306a36Sopenharmony_ci	if (ctx->fallback_cipher) {
427362306a36Sopenharmony_ci		crypto_free_aead(ctx->fallback_cipher);
427462306a36Sopenharmony_ci		ctx->fallback_cipher = NULL;
427562306a36Sopenharmony_ci	}
427662306a36Sopenharmony_ci}
427762306a36Sopenharmony_ci
427862306a36Sopenharmony_ci/**
427962306a36Sopenharmony_ci * spu_functions_register() - Specify hardware-specific SPU functions based on
428062306a36Sopenharmony_ci * SPU type read from device tree.
428162306a36Sopenharmony_ci * @dev:	device structure
428262306a36Sopenharmony_ci * @spu_type:	SPU hardware generation
428362306a36Sopenharmony_ci * @spu_subtype: SPU hardware version
428462306a36Sopenharmony_ci */
428562306a36Sopenharmony_cistatic void spu_functions_register(struct device *dev,
428662306a36Sopenharmony_ci				   enum spu_spu_type spu_type,
428762306a36Sopenharmony_ci				   enum spu_spu_subtype spu_subtype)
428862306a36Sopenharmony_ci{
428962306a36Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
429062306a36Sopenharmony_ci
429162306a36Sopenharmony_ci	if (spu_type == SPU_TYPE_SPUM) {
429262306a36Sopenharmony_ci		dev_dbg(dev, "Registering SPUM functions");
429362306a36Sopenharmony_ci		spu->spu_dump_msg_hdr = spum_dump_msg_hdr;
429462306a36Sopenharmony_ci		spu->spu_payload_length = spum_payload_length;
429562306a36Sopenharmony_ci		spu->spu_response_hdr_len = spum_response_hdr_len;
429662306a36Sopenharmony_ci		spu->spu_hash_pad_len = spum_hash_pad_len;
429762306a36Sopenharmony_ci		spu->spu_gcm_ccm_pad_len = spum_gcm_ccm_pad_len;
429862306a36Sopenharmony_ci		spu->spu_assoc_resp_len = spum_assoc_resp_len;
429962306a36Sopenharmony_ci		spu->spu_aead_ivlen = spum_aead_ivlen;
430062306a36Sopenharmony_ci		spu->spu_hash_type = spum_hash_type;
430162306a36Sopenharmony_ci		spu->spu_digest_size = spum_digest_size;
430262306a36Sopenharmony_ci		spu->spu_create_request = spum_create_request;
430362306a36Sopenharmony_ci		spu->spu_cipher_req_init = spum_cipher_req_init;
430462306a36Sopenharmony_ci		spu->spu_cipher_req_finish = spum_cipher_req_finish;
430562306a36Sopenharmony_ci		spu->spu_request_pad = spum_request_pad;
430662306a36Sopenharmony_ci		spu->spu_tx_status_len = spum_tx_status_len;
430762306a36Sopenharmony_ci		spu->spu_rx_status_len = spum_rx_status_len;
430862306a36Sopenharmony_ci		spu->spu_status_process = spum_status_process;
430962306a36Sopenharmony_ci		spu->spu_xts_tweak_in_payload = spum_xts_tweak_in_payload;
431062306a36Sopenharmony_ci		spu->spu_ccm_update_iv = spum_ccm_update_iv;
431162306a36Sopenharmony_ci		spu->spu_wordalign_padlen = spum_wordalign_padlen;
431262306a36Sopenharmony_ci		if (spu_subtype == SPU_SUBTYPE_SPUM_NS2)
431362306a36Sopenharmony_ci			spu->spu_ctx_max_payload = spum_ns2_ctx_max_payload;
431462306a36Sopenharmony_ci		else
431562306a36Sopenharmony_ci			spu->spu_ctx_max_payload = spum_nsp_ctx_max_payload;
431662306a36Sopenharmony_ci	} else {
431762306a36Sopenharmony_ci		dev_dbg(dev, "Registering SPU2 functions");
431862306a36Sopenharmony_ci		spu->spu_dump_msg_hdr = spu2_dump_msg_hdr;
431962306a36Sopenharmony_ci		spu->spu_ctx_max_payload = spu2_ctx_max_payload;
432062306a36Sopenharmony_ci		spu->spu_payload_length = spu2_payload_length;
432162306a36Sopenharmony_ci		spu->spu_response_hdr_len = spu2_response_hdr_len;
432262306a36Sopenharmony_ci		spu->spu_hash_pad_len = spu2_hash_pad_len;
432362306a36Sopenharmony_ci		spu->spu_gcm_ccm_pad_len = spu2_gcm_ccm_pad_len;
432462306a36Sopenharmony_ci		spu->spu_assoc_resp_len = spu2_assoc_resp_len;
432562306a36Sopenharmony_ci		spu->spu_aead_ivlen = spu2_aead_ivlen;
432662306a36Sopenharmony_ci		spu->spu_hash_type = spu2_hash_type;
432762306a36Sopenharmony_ci		spu->spu_digest_size = spu2_digest_size;
432862306a36Sopenharmony_ci		spu->spu_create_request = spu2_create_request;
432962306a36Sopenharmony_ci		spu->spu_cipher_req_init = spu2_cipher_req_init;
433062306a36Sopenharmony_ci		spu->spu_cipher_req_finish = spu2_cipher_req_finish;
433162306a36Sopenharmony_ci		spu->spu_request_pad = spu2_request_pad;
433262306a36Sopenharmony_ci		spu->spu_tx_status_len = spu2_tx_status_len;
433362306a36Sopenharmony_ci		spu->spu_rx_status_len = spu2_rx_status_len;
433462306a36Sopenharmony_ci		spu->spu_status_process = spu2_status_process;
433562306a36Sopenharmony_ci		spu->spu_xts_tweak_in_payload = spu2_xts_tweak_in_payload;
433662306a36Sopenharmony_ci		spu->spu_ccm_update_iv = spu2_ccm_update_iv;
433762306a36Sopenharmony_ci		spu->spu_wordalign_padlen = spu2_wordalign_padlen;
433862306a36Sopenharmony_ci	}
433962306a36Sopenharmony_ci}
434062306a36Sopenharmony_ci
434162306a36Sopenharmony_ci/**
434262306a36Sopenharmony_ci * spu_mb_init() - Initialize mailbox client. Request ownership of a mailbox
434362306a36Sopenharmony_ci * channel for the SPU being probed.
434462306a36Sopenharmony_ci * @dev:  SPU driver device structure
434562306a36Sopenharmony_ci *
434662306a36Sopenharmony_ci * Return: 0 if successful
434762306a36Sopenharmony_ci *	   < 0 otherwise
434862306a36Sopenharmony_ci */
434962306a36Sopenharmony_cistatic int spu_mb_init(struct device *dev)
435062306a36Sopenharmony_ci{
435162306a36Sopenharmony_ci	struct mbox_client *mcl = &iproc_priv.mcl;
435262306a36Sopenharmony_ci	int err, i;
435362306a36Sopenharmony_ci
435462306a36Sopenharmony_ci	iproc_priv.mbox = devm_kcalloc(dev, iproc_priv.spu.num_chan,
435562306a36Sopenharmony_ci				  sizeof(struct mbox_chan *), GFP_KERNEL);
435662306a36Sopenharmony_ci	if (!iproc_priv.mbox)
435762306a36Sopenharmony_ci		return -ENOMEM;
435862306a36Sopenharmony_ci
435962306a36Sopenharmony_ci	mcl->dev = dev;
436062306a36Sopenharmony_ci	mcl->tx_block = false;
436162306a36Sopenharmony_ci	mcl->tx_tout = 0;
436262306a36Sopenharmony_ci	mcl->knows_txdone = true;
436362306a36Sopenharmony_ci	mcl->rx_callback = spu_rx_callback;
436462306a36Sopenharmony_ci	mcl->tx_done = NULL;
436562306a36Sopenharmony_ci
436662306a36Sopenharmony_ci	for (i = 0; i < iproc_priv.spu.num_chan; i++) {
436762306a36Sopenharmony_ci		iproc_priv.mbox[i] = mbox_request_channel(mcl, i);
436862306a36Sopenharmony_ci		if (IS_ERR(iproc_priv.mbox[i])) {
436962306a36Sopenharmony_ci			err = PTR_ERR(iproc_priv.mbox[i]);
437062306a36Sopenharmony_ci			dev_err(dev,
437162306a36Sopenharmony_ci				"Mbox channel %d request failed with err %d",
437262306a36Sopenharmony_ci				i, err);
437362306a36Sopenharmony_ci			iproc_priv.mbox[i] = NULL;
437462306a36Sopenharmony_ci			goto free_channels;
437562306a36Sopenharmony_ci		}
437662306a36Sopenharmony_ci	}
437762306a36Sopenharmony_ci
437862306a36Sopenharmony_ci	return 0;
437962306a36Sopenharmony_cifree_channels:
438062306a36Sopenharmony_ci	for (i = 0; i < iproc_priv.spu.num_chan; i++) {
438162306a36Sopenharmony_ci		if (iproc_priv.mbox[i])
438262306a36Sopenharmony_ci			mbox_free_channel(iproc_priv.mbox[i]);
438362306a36Sopenharmony_ci	}
438462306a36Sopenharmony_ci
438562306a36Sopenharmony_ci	return err;
438662306a36Sopenharmony_ci}
438762306a36Sopenharmony_ci
438862306a36Sopenharmony_cistatic void spu_mb_release(struct platform_device *pdev)
438962306a36Sopenharmony_ci{
439062306a36Sopenharmony_ci	int i;
439162306a36Sopenharmony_ci
439262306a36Sopenharmony_ci	for (i = 0; i < iproc_priv.spu.num_chan; i++)
439362306a36Sopenharmony_ci		mbox_free_channel(iproc_priv.mbox[i]);
439462306a36Sopenharmony_ci}
439562306a36Sopenharmony_ci
439662306a36Sopenharmony_cistatic void spu_counters_init(void)
439762306a36Sopenharmony_ci{
439862306a36Sopenharmony_ci	int i;
439962306a36Sopenharmony_ci	int j;
440062306a36Sopenharmony_ci
440162306a36Sopenharmony_ci	atomic_set(&iproc_priv.session_count, 0);
440262306a36Sopenharmony_ci	atomic_set(&iproc_priv.stream_count, 0);
440362306a36Sopenharmony_ci	atomic_set(&iproc_priv.next_chan, (int)iproc_priv.spu.num_chan);
440462306a36Sopenharmony_ci	atomic64_set(&iproc_priv.bytes_in, 0);
440562306a36Sopenharmony_ci	atomic64_set(&iproc_priv.bytes_out, 0);
440662306a36Sopenharmony_ci	for (i = 0; i < SPU_OP_NUM; i++) {
440762306a36Sopenharmony_ci		atomic_set(&iproc_priv.op_counts[i], 0);
440862306a36Sopenharmony_ci		atomic_set(&iproc_priv.setkey_cnt[i], 0);
440962306a36Sopenharmony_ci	}
441062306a36Sopenharmony_ci	for (i = 0; i < CIPHER_ALG_LAST; i++)
441162306a36Sopenharmony_ci		for (j = 0; j < CIPHER_MODE_LAST; j++)
441262306a36Sopenharmony_ci			atomic_set(&iproc_priv.cipher_cnt[i][j], 0);
441362306a36Sopenharmony_ci
441462306a36Sopenharmony_ci	for (i = 0; i < HASH_ALG_LAST; i++) {
441562306a36Sopenharmony_ci		atomic_set(&iproc_priv.hash_cnt[i], 0);
441662306a36Sopenharmony_ci		atomic_set(&iproc_priv.hmac_cnt[i], 0);
441762306a36Sopenharmony_ci	}
441862306a36Sopenharmony_ci	for (i = 0; i < AEAD_TYPE_LAST; i++)
441962306a36Sopenharmony_ci		atomic_set(&iproc_priv.aead_cnt[i], 0);
442062306a36Sopenharmony_ci
442162306a36Sopenharmony_ci	atomic_set(&iproc_priv.mb_no_spc, 0);
442262306a36Sopenharmony_ci	atomic_set(&iproc_priv.mb_send_fail, 0);
442362306a36Sopenharmony_ci	atomic_set(&iproc_priv.bad_icv, 0);
442462306a36Sopenharmony_ci}
442562306a36Sopenharmony_ci
442662306a36Sopenharmony_cistatic int spu_register_skcipher(struct iproc_alg_s *driver_alg)
442762306a36Sopenharmony_ci{
442862306a36Sopenharmony_ci	struct skcipher_alg *crypto = &driver_alg->alg.skcipher;
442962306a36Sopenharmony_ci	int err;
443062306a36Sopenharmony_ci
443162306a36Sopenharmony_ci	crypto->base.cra_module = THIS_MODULE;
443262306a36Sopenharmony_ci	crypto->base.cra_priority = cipher_pri;
443362306a36Sopenharmony_ci	crypto->base.cra_alignmask = 0;
443462306a36Sopenharmony_ci	crypto->base.cra_ctxsize = sizeof(struct iproc_ctx_s);
443562306a36Sopenharmony_ci	crypto->base.cra_flags = CRYPTO_ALG_ASYNC |
443662306a36Sopenharmony_ci				 CRYPTO_ALG_ALLOCATES_MEMORY |
443762306a36Sopenharmony_ci				 CRYPTO_ALG_KERN_DRIVER_ONLY;
443862306a36Sopenharmony_ci
443962306a36Sopenharmony_ci	crypto->init = skcipher_init_tfm;
444062306a36Sopenharmony_ci	crypto->exit = skcipher_exit_tfm;
444162306a36Sopenharmony_ci	crypto->setkey = skcipher_setkey;
444262306a36Sopenharmony_ci	crypto->encrypt = skcipher_encrypt;
444362306a36Sopenharmony_ci	crypto->decrypt = skcipher_decrypt;
444462306a36Sopenharmony_ci
444562306a36Sopenharmony_ci	err = crypto_register_skcipher(crypto);
444662306a36Sopenharmony_ci	/* Mark alg as having been registered, if successful */
444762306a36Sopenharmony_ci	if (err == 0)
444862306a36Sopenharmony_ci		driver_alg->registered = true;
444962306a36Sopenharmony_ci	pr_debug("  registered skcipher %s\n", crypto->base.cra_driver_name);
445062306a36Sopenharmony_ci	return err;
445162306a36Sopenharmony_ci}
445262306a36Sopenharmony_ci
445362306a36Sopenharmony_cistatic int spu_register_ahash(struct iproc_alg_s *driver_alg)
445462306a36Sopenharmony_ci{
445562306a36Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
445662306a36Sopenharmony_ci	struct ahash_alg *hash = &driver_alg->alg.hash;
445762306a36Sopenharmony_ci	int err;
445862306a36Sopenharmony_ci
445962306a36Sopenharmony_ci	/* AES-XCBC is the only AES hash type currently supported on SPU-M */
446062306a36Sopenharmony_ci	if ((driver_alg->auth_info.alg == HASH_ALG_AES) &&
446162306a36Sopenharmony_ci	    (driver_alg->auth_info.mode != HASH_MODE_XCBC) &&
446262306a36Sopenharmony_ci	    (spu->spu_type == SPU_TYPE_SPUM))
446362306a36Sopenharmony_ci		return 0;
446462306a36Sopenharmony_ci
446562306a36Sopenharmony_ci	/* SHA3 algorithm variants are not registered for SPU-M or SPU2. */
446662306a36Sopenharmony_ci	if ((driver_alg->auth_info.alg >= HASH_ALG_SHA3_224) &&
446762306a36Sopenharmony_ci	    (spu->spu_subtype != SPU_SUBTYPE_SPU2_V2))
446862306a36Sopenharmony_ci		return 0;
446962306a36Sopenharmony_ci
447062306a36Sopenharmony_ci	hash->halg.base.cra_module = THIS_MODULE;
447162306a36Sopenharmony_ci	hash->halg.base.cra_priority = hash_pri;
447262306a36Sopenharmony_ci	hash->halg.base.cra_alignmask = 0;
447362306a36Sopenharmony_ci	hash->halg.base.cra_ctxsize = sizeof(struct iproc_ctx_s);
447462306a36Sopenharmony_ci	hash->halg.base.cra_init = ahash_cra_init;
447562306a36Sopenharmony_ci	hash->halg.base.cra_exit = generic_cra_exit;
447662306a36Sopenharmony_ci	hash->halg.base.cra_flags = CRYPTO_ALG_ASYNC |
447762306a36Sopenharmony_ci				    CRYPTO_ALG_ALLOCATES_MEMORY;
447862306a36Sopenharmony_ci	hash->halg.statesize = sizeof(struct spu_hash_export_s);
447962306a36Sopenharmony_ci
448062306a36Sopenharmony_ci	if (driver_alg->auth_info.mode != HASH_MODE_HMAC) {
448162306a36Sopenharmony_ci		hash->init = ahash_init;
448262306a36Sopenharmony_ci		hash->update = ahash_update;
448362306a36Sopenharmony_ci		hash->final = ahash_final;
448462306a36Sopenharmony_ci		hash->finup = ahash_finup;
448562306a36Sopenharmony_ci		hash->digest = ahash_digest;
448662306a36Sopenharmony_ci		if ((driver_alg->auth_info.alg == HASH_ALG_AES) &&
448762306a36Sopenharmony_ci		    ((driver_alg->auth_info.mode == HASH_MODE_XCBC) ||
448862306a36Sopenharmony_ci		    (driver_alg->auth_info.mode == HASH_MODE_CMAC))) {
448962306a36Sopenharmony_ci			hash->setkey = ahash_setkey;
449062306a36Sopenharmony_ci		}
449162306a36Sopenharmony_ci	} else {
449262306a36Sopenharmony_ci		hash->setkey = ahash_hmac_setkey;
449362306a36Sopenharmony_ci		hash->init = ahash_hmac_init;
449462306a36Sopenharmony_ci		hash->update = ahash_hmac_update;
449562306a36Sopenharmony_ci		hash->final = ahash_hmac_final;
449662306a36Sopenharmony_ci		hash->finup = ahash_hmac_finup;
449762306a36Sopenharmony_ci		hash->digest = ahash_hmac_digest;
449862306a36Sopenharmony_ci	}
449962306a36Sopenharmony_ci	hash->export = ahash_export;
450062306a36Sopenharmony_ci	hash->import = ahash_import;
450162306a36Sopenharmony_ci
450262306a36Sopenharmony_ci	err = crypto_register_ahash(hash);
450362306a36Sopenharmony_ci	/* Mark alg as having been registered, if successful */
450462306a36Sopenharmony_ci	if (err == 0)
450562306a36Sopenharmony_ci		driver_alg->registered = true;
450662306a36Sopenharmony_ci	pr_debug("  registered ahash %s\n",
450762306a36Sopenharmony_ci		 hash->halg.base.cra_driver_name);
450862306a36Sopenharmony_ci	return err;
450962306a36Sopenharmony_ci}
451062306a36Sopenharmony_ci
451162306a36Sopenharmony_cistatic int spu_register_aead(struct iproc_alg_s *driver_alg)
451262306a36Sopenharmony_ci{
451362306a36Sopenharmony_ci	struct aead_alg *aead = &driver_alg->alg.aead;
451462306a36Sopenharmony_ci	int err;
451562306a36Sopenharmony_ci
451662306a36Sopenharmony_ci	aead->base.cra_module = THIS_MODULE;
451762306a36Sopenharmony_ci	aead->base.cra_priority = aead_pri;
451862306a36Sopenharmony_ci	aead->base.cra_alignmask = 0;
451962306a36Sopenharmony_ci	aead->base.cra_ctxsize = sizeof(struct iproc_ctx_s);
452062306a36Sopenharmony_ci
452162306a36Sopenharmony_ci	aead->base.cra_flags |= CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY;
452262306a36Sopenharmony_ci	/* setkey set in alg initialization */
452362306a36Sopenharmony_ci	aead->setauthsize = aead_setauthsize;
452462306a36Sopenharmony_ci	aead->encrypt = aead_encrypt;
452562306a36Sopenharmony_ci	aead->decrypt = aead_decrypt;
452662306a36Sopenharmony_ci	aead->init = aead_cra_init;
452762306a36Sopenharmony_ci	aead->exit = aead_cra_exit;
452862306a36Sopenharmony_ci
452962306a36Sopenharmony_ci	err = crypto_register_aead(aead);
453062306a36Sopenharmony_ci	/* Mark alg as having been registered, if successful */
453162306a36Sopenharmony_ci	if (err == 0)
453262306a36Sopenharmony_ci		driver_alg->registered = true;
453362306a36Sopenharmony_ci	pr_debug("  registered aead %s\n", aead->base.cra_driver_name);
453462306a36Sopenharmony_ci	return err;
453562306a36Sopenharmony_ci}
453662306a36Sopenharmony_ci
453762306a36Sopenharmony_ci/* register crypto algorithms the device supports */
453862306a36Sopenharmony_cistatic int spu_algs_register(struct device *dev)
453962306a36Sopenharmony_ci{
454062306a36Sopenharmony_ci	int i, j;
454162306a36Sopenharmony_ci	int err;
454262306a36Sopenharmony_ci
454362306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
454462306a36Sopenharmony_ci		switch (driver_algs[i].type) {
454562306a36Sopenharmony_ci		case CRYPTO_ALG_TYPE_SKCIPHER:
454662306a36Sopenharmony_ci			err = spu_register_skcipher(&driver_algs[i]);
454762306a36Sopenharmony_ci			break;
454862306a36Sopenharmony_ci		case CRYPTO_ALG_TYPE_AHASH:
454962306a36Sopenharmony_ci			err = spu_register_ahash(&driver_algs[i]);
455062306a36Sopenharmony_ci			break;
455162306a36Sopenharmony_ci		case CRYPTO_ALG_TYPE_AEAD:
455262306a36Sopenharmony_ci			err = spu_register_aead(&driver_algs[i]);
455362306a36Sopenharmony_ci			break;
455462306a36Sopenharmony_ci		default:
455562306a36Sopenharmony_ci			dev_err(dev,
455662306a36Sopenharmony_ci				"iproc-crypto: unknown alg type: %d",
455762306a36Sopenharmony_ci				driver_algs[i].type);
455862306a36Sopenharmony_ci			err = -EINVAL;
455962306a36Sopenharmony_ci		}
456062306a36Sopenharmony_ci
456162306a36Sopenharmony_ci		if (err) {
456262306a36Sopenharmony_ci			dev_err(dev, "alg registration failed with error %d\n",
456362306a36Sopenharmony_ci				err);
456462306a36Sopenharmony_ci			goto err_algs;
456562306a36Sopenharmony_ci		}
456662306a36Sopenharmony_ci	}
456762306a36Sopenharmony_ci
456862306a36Sopenharmony_ci	return 0;
456962306a36Sopenharmony_ci
457062306a36Sopenharmony_cierr_algs:
457162306a36Sopenharmony_ci	for (j = 0; j < i; j++) {
457262306a36Sopenharmony_ci		/* Skip any algorithm not registered */
457362306a36Sopenharmony_ci		if (!driver_algs[j].registered)
457462306a36Sopenharmony_ci			continue;
457562306a36Sopenharmony_ci		switch (driver_algs[j].type) {
457662306a36Sopenharmony_ci		case CRYPTO_ALG_TYPE_SKCIPHER:
457762306a36Sopenharmony_ci			crypto_unregister_skcipher(&driver_algs[j].alg.skcipher);
457862306a36Sopenharmony_ci			driver_algs[j].registered = false;
457962306a36Sopenharmony_ci			break;
458062306a36Sopenharmony_ci		case CRYPTO_ALG_TYPE_AHASH:
458162306a36Sopenharmony_ci			crypto_unregister_ahash(&driver_algs[j].alg.hash);
458262306a36Sopenharmony_ci			driver_algs[j].registered = false;
458362306a36Sopenharmony_ci			break;
458462306a36Sopenharmony_ci		case CRYPTO_ALG_TYPE_AEAD:
458562306a36Sopenharmony_ci			crypto_unregister_aead(&driver_algs[j].alg.aead);
458662306a36Sopenharmony_ci			driver_algs[j].registered = false;
458762306a36Sopenharmony_ci			break;
458862306a36Sopenharmony_ci		}
458962306a36Sopenharmony_ci	}
459062306a36Sopenharmony_ci	return err;
459162306a36Sopenharmony_ci}
459262306a36Sopenharmony_ci
459362306a36Sopenharmony_ci/* ==================== Kernel Platform API ==================== */
459462306a36Sopenharmony_ci
459562306a36Sopenharmony_cistatic struct spu_type_subtype spum_ns2_types = {
459662306a36Sopenharmony_ci	SPU_TYPE_SPUM, SPU_SUBTYPE_SPUM_NS2
459762306a36Sopenharmony_ci};
459862306a36Sopenharmony_ci
459962306a36Sopenharmony_cistatic struct spu_type_subtype spum_nsp_types = {
460062306a36Sopenharmony_ci	SPU_TYPE_SPUM, SPU_SUBTYPE_SPUM_NSP
460162306a36Sopenharmony_ci};
460262306a36Sopenharmony_ci
460362306a36Sopenharmony_cistatic struct spu_type_subtype spu2_types = {
460462306a36Sopenharmony_ci	SPU_TYPE_SPU2, SPU_SUBTYPE_SPU2_V1
460562306a36Sopenharmony_ci};
460662306a36Sopenharmony_ci
460762306a36Sopenharmony_cistatic struct spu_type_subtype spu2_v2_types = {
460862306a36Sopenharmony_ci	SPU_TYPE_SPU2, SPU_SUBTYPE_SPU2_V2
460962306a36Sopenharmony_ci};
461062306a36Sopenharmony_ci
461162306a36Sopenharmony_cistatic const struct of_device_id bcm_spu_dt_ids[] = {
461262306a36Sopenharmony_ci	{
461362306a36Sopenharmony_ci		.compatible = "brcm,spum-crypto",
461462306a36Sopenharmony_ci		.data = &spum_ns2_types,
461562306a36Sopenharmony_ci	},
461662306a36Sopenharmony_ci	{
461762306a36Sopenharmony_ci		.compatible = "brcm,spum-nsp-crypto",
461862306a36Sopenharmony_ci		.data = &spum_nsp_types,
461962306a36Sopenharmony_ci	},
462062306a36Sopenharmony_ci	{
462162306a36Sopenharmony_ci		.compatible = "brcm,spu2-crypto",
462262306a36Sopenharmony_ci		.data = &spu2_types,
462362306a36Sopenharmony_ci	},
462462306a36Sopenharmony_ci	{
462562306a36Sopenharmony_ci		.compatible = "brcm,spu2-v2-crypto",
462662306a36Sopenharmony_ci		.data = &spu2_v2_types,
462762306a36Sopenharmony_ci	},
462862306a36Sopenharmony_ci	{ /* sentinel */ }
462962306a36Sopenharmony_ci};
463062306a36Sopenharmony_ci
463162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, bcm_spu_dt_ids);
463262306a36Sopenharmony_ci
463362306a36Sopenharmony_cistatic int spu_dt_read(struct platform_device *pdev)
463462306a36Sopenharmony_ci{
463562306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
463662306a36Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
463762306a36Sopenharmony_ci	struct resource *spu_ctrl_regs;
463862306a36Sopenharmony_ci	const struct spu_type_subtype *matched_spu_type;
463962306a36Sopenharmony_ci	struct device_node *dn = pdev->dev.of_node;
464062306a36Sopenharmony_ci	int err, i;
464162306a36Sopenharmony_ci
464262306a36Sopenharmony_ci	/* Count number of mailbox channels */
464362306a36Sopenharmony_ci	spu->num_chan = of_count_phandle_with_args(dn, "mboxes", "#mbox-cells");
464462306a36Sopenharmony_ci
464562306a36Sopenharmony_ci	matched_spu_type = of_device_get_match_data(dev);
464662306a36Sopenharmony_ci	if (!matched_spu_type) {
464762306a36Sopenharmony_ci		dev_err(dev, "Failed to match device\n");
464862306a36Sopenharmony_ci		return -ENODEV;
464962306a36Sopenharmony_ci	}
465062306a36Sopenharmony_ci
465162306a36Sopenharmony_ci	spu->spu_type = matched_spu_type->type;
465262306a36Sopenharmony_ci	spu->spu_subtype = matched_spu_type->subtype;
465362306a36Sopenharmony_ci
465462306a36Sopenharmony_ci	for (i = 0; (i < MAX_SPUS) && ((spu_ctrl_regs =
465562306a36Sopenharmony_ci		platform_get_resource(pdev, IORESOURCE_MEM, i)) != NULL); i++) {
465662306a36Sopenharmony_ci
465762306a36Sopenharmony_ci		spu->reg_vbase[i] = devm_ioremap_resource(dev, spu_ctrl_regs);
465862306a36Sopenharmony_ci		if (IS_ERR(spu->reg_vbase[i])) {
465962306a36Sopenharmony_ci			err = PTR_ERR(spu->reg_vbase[i]);
466062306a36Sopenharmony_ci			dev_err(dev, "Failed to map registers: %d\n",
466162306a36Sopenharmony_ci				err);
466262306a36Sopenharmony_ci			spu->reg_vbase[i] = NULL;
466362306a36Sopenharmony_ci			return err;
466462306a36Sopenharmony_ci		}
466562306a36Sopenharmony_ci	}
466662306a36Sopenharmony_ci	spu->num_spu = i;
466762306a36Sopenharmony_ci	dev_dbg(dev, "Device has %d SPUs", spu->num_spu);
466862306a36Sopenharmony_ci
466962306a36Sopenharmony_ci	return 0;
467062306a36Sopenharmony_ci}
467162306a36Sopenharmony_ci
467262306a36Sopenharmony_cistatic int bcm_spu_probe(struct platform_device *pdev)
467362306a36Sopenharmony_ci{
467462306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
467562306a36Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
467662306a36Sopenharmony_ci	int err;
467762306a36Sopenharmony_ci
467862306a36Sopenharmony_ci	iproc_priv.pdev  = pdev;
467962306a36Sopenharmony_ci	platform_set_drvdata(iproc_priv.pdev,
468062306a36Sopenharmony_ci			     &iproc_priv);
468162306a36Sopenharmony_ci
468262306a36Sopenharmony_ci	err = spu_dt_read(pdev);
468362306a36Sopenharmony_ci	if (err < 0)
468462306a36Sopenharmony_ci		goto failure;
468562306a36Sopenharmony_ci
468662306a36Sopenharmony_ci	err = spu_mb_init(dev);
468762306a36Sopenharmony_ci	if (err < 0)
468862306a36Sopenharmony_ci		goto failure;
468962306a36Sopenharmony_ci
469062306a36Sopenharmony_ci	if (spu->spu_type == SPU_TYPE_SPUM)
469162306a36Sopenharmony_ci		iproc_priv.bcm_hdr_len = 8;
469262306a36Sopenharmony_ci	else if (spu->spu_type == SPU_TYPE_SPU2)
469362306a36Sopenharmony_ci		iproc_priv.bcm_hdr_len = 0;
469462306a36Sopenharmony_ci
469562306a36Sopenharmony_ci	spu_functions_register(dev, spu->spu_type, spu->spu_subtype);
469662306a36Sopenharmony_ci
469762306a36Sopenharmony_ci	spu_counters_init();
469862306a36Sopenharmony_ci
469962306a36Sopenharmony_ci	spu_setup_debugfs();
470062306a36Sopenharmony_ci
470162306a36Sopenharmony_ci	err = spu_algs_register(dev);
470262306a36Sopenharmony_ci	if (err < 0)
470362306a36Sopenharmony_ci		goto fail_reg;
470462306a36Sopenharmony_ci
470562306a36Sopenharmony_ci	return 0;
470662306a36Sopenharmony_ci
470762306a36Sopenharmony_cifail_reg:
470862306a36Sopenharmony_ci	spu_free_debugfs();
470962306a36Sopenharmony_cifailure:
471062306a36Sopenharmony_ci	spu_mb_release(pdev);
471162306a36Sopenharmony_ci	dev_err(dev, "%s failed with error %d.\n", __func__, err);
471262306a36Sopenharmony_ci
471362306a36Sopenharmony_ci	return err;
471462306a36Sopenharmony_ci}
471562306a36Sopenharmony_ci
471662306a36Sopenharmony_cistatic int bcm_spu_remove(struct platform_device *pdev)
471762306a36Sopenharmony_ci{
471862306a36Sopenharmony_ci	int i;
471962306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
472062306a36Sopenharmony_ci	char *cdn;
472162306a36Sopenharmony_ci
472262306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
472362306a36Sopenharmony_ci		/*
472462306a36Sopenharmony_ci		 * Not all algorithms were registered, depending on whether
472562306a36Sopenharmony_ci		 * hardware is SPU or SPU2.  So here we make sure to skip
472662306a36Sopenharmony_ci		 * those algorithms that were not previously registered.
472762306a36Sopenharmony_ci		 */
472862306a36Sopenharmony_ci		if (!driver_algs[i].registered)
472962306a36Sopenharmony_ci			continue;
473062306a36Sopenharmony_ci
473162306a36Sopenharmony_ci		switch (driver_algs[i].type) {
473262306a36Sopenharmony_ci		case CRYPTO_ALG_TYPE_SKCIPHER:
473362306a36Sopenharmony_ci			crypto_unregister_skcipher(&driver_algs[i].alg.skcipher);
473462306a36Sopenharmony_ci			dev_dbg(dev, "  unregistered cipher %s\n",
473562306a36Sopenharmony_ci				driver_algs[i].alg.skcipher.base.cra_driver_name);
473662306a36Sopenharmony_ci			driver_algs[i].registered = false;
473762306a36Sopenharmony_ci			break;
473862306a36Sopenharmony_ci		case CRYPTO_ALG_TYPE_AHASH:
473962306a36Sopenharmony_ci			crypto_unregister_ahash(&driver_algs[i].alg.hash);
474062306a36Sopenharmony_ci			cdn = driver_algs[i].alg.hash.halg.base.cra_driver_name;
474162306a36Sopenharmony_ci			dev_dbg(dev, "  unregistered hash %s\n", cdn);
474262306a36Sopenharmony_ci			driver_algs[i].registered = false;
474362306a36Sopenharmony_ci			break;
474462306a36Sopenharmony_ci		case CRYPTO_ALG_TYPE_AEAD:
474562306a36Sopenharmony_ci			crypto_unregister_aead(&driver_algs[i].alg.aead);
474662306a36Sopenharmony_ci			dev_dbg(dev, "  unregistered aead %s\n",
474762306a36Sopenharmony_ci				driver_algs[i].alg.aead.base.cra_driver_name);
474862306a36Sopenharmony_ci			driver_algs[i].registered = false;
474962306a36Sopenharmony_ci			break;
475062306a36Sopenharmony_ci		}
475162306a36Sopenharmony_ci	}
475262306a36Sopenharmony_ci	spu_free_debugfs();
475362306a36Sopenharmony_ci	spu_mb_release(pdev);
475462306a36Sopenharmony_ci	return 0;
475562306a36Sopenharmony_ci}
475662306a36Sopenharmony_ci
475762306a36Sopenharmony_ci/* ===== Kernel Module API ===== */
475862306a36Sopenharmony_ci
475962306a36Sopenharmony_cistatic struct platform_driver bcm_spu_pdriver = {
476062306a36Sopenharmony_ci	.driver = {
476162306a36Sopenharmony_ci		   .name = "brcm-spu-crypto",
476262306a36Sopenharmony_ci		   .of_match_table = of_match_ptr(bcm_spu_dt_ids),
476362306a36Sopenharmony_ci		   },
476462306a36Sopenharmony_ci	.probe = bcm_spu_probe,
476562306a36Sopenharmony_ci	.remove = bcm_spu_remove,
476662306a36Sopenharmony_ci};
476762306a36Sopenharmony_cimodule_platform_driver(bcm_spu_pdriver);
476862306a36Sopenharmony_ci
476962306a36Sopenharmony_ciMODULE_AUTHOR("Rob Rice <rob.rice@broadcom.com>");
477062306a36Sopenharmony_ciMODULE_DESCRIPTION("Broadcom symmetric crypto offload driver");
477162306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
4772