18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright 2016 Broadcom
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include <linux/err.h>
78c2ecf20Sopenharmony_ci#include <linux/module.h>
88c2ecf20Sopenharmony_ci#include <linux/init.h>
98c2ecf20Sopenharmony_ci#include <linux/errno.h>
108c2ecf20Sopenharmony_ci#include <linux/kernel.h>
118c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
128c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
138c2ecf20Sopenharmony_ci#include <linux/scatterlist.h>
148c2ecf20Sopenharmony_ci#include <linux/crypto.h>
158c2ecf20Sopenharmony_ci#include <linux/kthread.h>
168c2ecf20Sopenharmony_ci#include <linux/rtnetlink.h>
178c2ecf20Sopenharmony_ci#include <linux/sched.h>
188c2ecf20Sopenharmony_ci#include <linux/of_address.h>
198c2ecf20Sopenharmony_ci#include <linux/of_device.h>
208c2ecf20Sopenharmony_ci#include <linux/io.h>
218c2ecf20Sopenharmony_ci#include <linux/bitops.h>
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#include <crypto/algapi.h>
248c2ecf20Sopenharmony_ci#include <crypto/aead.h>
258c2ecf20Sopenharmony_ci#include <crypto/internal/aead.h>
268c2ecf20Sopenharmony_ci#include <crypto/aes.h>
278c2ecf20Sopenharmony_ci#include <crypto/internal/des.h>
288c2ecf20Sopenharmony_ci#include <crypto/hmac.h>
298c2ecf20Sopenharmony_ci#include <crypto/sha.h>
308c2ecf20Sopenharmony_ci#include <crypto/md5.h>
318c2ecf20Sopenharmony_ci#include <crypto/authenc.h>
328c2ecf20Sopenharmony_ci#include <crypto/skcipher.h>
338c2ecf20Sopenharmony_ci#include <crypto/hash.h>
348c2ecf20Sopenharmony_ci#include <crypto/sha3.h>
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#include "util.h"
378c2ecf20Sopenharmony_ci#include "cipher.h"
388c2ecf20Sopenharmony_ci#include "spu.h"
398c2ecf20Sopenharmony_ci#include "spum.h"
408c2ecf20Sopenharmony_ci#include "spu2.h"
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci/* ================= Device Structure ================== */
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_cistruct bcm_device_private iproc_priv;
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci/* ==================== Parameters ===================== */
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ciint flow_debug_logging;
498c2ecf20Sopenharmony_cimodule_param(flow_debug_logging, int, 0644);
508c2ecf20Sopenharmony_ciMODULE_PARM_DESC(flow_debug_logging, "Enable Flow Debug Logging");
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ciint packet_debug_logging;
538c2ecf20Sopenharmony_cimodule_param(packet_debug_logging, int, 0644);
548c2ecf20Sopenharmony_ciMODULE_PARM_DESC(packet_debug_logging, "Enable Packet Debug Logging");
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ciint debug_logging_sleep;
578c2ecf20Sopenharmony_cimodule_param(debug_logging_sleep, int, 0644);
588c2ecf20Sopenharmony_ciMODULE_PARM_DESC(debug_logging_sleep, "Packet Debug Logging Sleep");
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci/*
618c2ecf20Sopenharmony_ci * The value of these module parameters is used to set the priority for each
628c2ecf20Sopenharmony_ci * algo type when this driver registers algos with the kernel crypto API.
638c2ecf20Sopenharmony_ci * To use a priority other than the default, set the priority in the insmod or
648c2ecf20Sopenharmony_ci * modprobe. Changing the module priority after init time has no effect.
658c2ecf20Sopenharmony_ci *
668c2ecf20Sopenharmony_ci * The default priorities are chosen to be lower (less preferred) than ARMv8 CE
678c2ecf20Sopenharmony_ci * algos, but more preferred than generic software algos.
688c2ecf20Sopenharmony_ci */
698c2ecf20Sopenharmony_cistatic int cipher_pri = 150;
708c2ecf20Sopenharmony_cimodule_param(cipher_pri, int, 0644);
718c2ecf20Sopenharmony_ciMODULE_PARM_DESC(cipher_pri, "Priority for cipher algos");
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_cistatic int hash_pri = 100;
748c2ecf20Sopenharmony_cimodule_param(hash_pri, int, 0644);
758c2ecf20Sopenharmony_ciMODULE_PARM_DESC(hash_pri, "Priority for hash algos");
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_cistatic int aead_pri = 150;
788c2ecf20Sopenharmony_cimodule_param(aead_pri, int, 0644);
798c2ecf20Sopenharmony_ciMODULE_PARM_DESC(aead_pri, "Priority for AEAD algos");
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci/* A type 3 BCM header, expected to precede the SPU header for SPU-M.
828c2ecf20Sopenharmony_ci * Bits 3 and 4 in the first byte encode the channel number (the dma ringset).
838c2ecf20Sopenharmony_ci * 0x60 - ring 0
848c2ecf20Sopenharmony_ci * 0x68 - ring 1
858c2ecf20Sopenharmony_ci * 0x70 - ring 2
868c2ecf20Sopenharmony_ci * 0x78 - ring 3
878c2ecf20Sopenharmony_ci */
888c2ecf20Sopenharmony_cistatic char BCMHEADER[] = { 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28 };
898c2ecf20Sopenharmony_ci/*
908c2ecf20Sopenharmony_ci * Some SPU hw does not use BCM header on SPU messages. So BCM_HDR_LEN
918c2ecf20Sopenharmony_ci * is set dynamically after reading SPU type from device tree.
928c2ecf20Sopenharmony_ci */
938c2ecf20Sopenharmony_ci#define BCM_HDR_LEN  iproc_priv.bcm_hdr_len
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci/* min and max time to sleep before retrying when mbox queue is full. usec */
968c2ecf20Sopenharmony_ci#define MBOX_SLEEP_MIN  800
978c2ecf20Sopenharmony_ci#define MBOX_SLEEP_MAX 1000
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci/**
1008c2ecf20Sopenharmony_ci * select_channel() - Select a SPU channel to handle a crypto request. Selects
1018c2ecf20Sopenharmony_ci * channel in round robin order.
1028c2ecf20Sopenharmony_ci *
1038c2ecf20Sopenharmony_ci * Return:  channel index
1048c2ecf20Sopenharmony_ci */
1058c2ecf20Sopenharmony_cistatic u8 select_channel(void)
1068c2ecf20Sopenharmony_ci{
1078c2ecf20Sopenharmony_ci	u8 chan_idx = atomic_inc_return(&iproc_priv.next_chan);
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	return chan_idx % iproc_priv.spu.num_chan;
1108c2ecf20Sopenharmony_ci}
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci/**
1138c2ecf20Sopenharmony_ci * spu_skcipher_rx_sg_create() - Build up the scatterlist of buffers used to
1148c2ecf20Sopenharmony_ci * receive a SPU response message for an skcipher request. Includes buffers to
1158c2ecf20Sopenharmony_ci * catch SPU message headers and the response data.
1168c2ecf20Sopenharmony_ci * @mssg:	mailbox message containing the receive sg
1178c2ecf20Sopenharmony_ci * @rctx:	crypto request context
1188c2ecf20Sopenharmony_ci * @rx_frag_num: number of scatterlist elements required to hold the
1198c2ecf20Sopenharmony_ci *		SPU response message
1208c2ecf20Sopenharmony_ci * @chunksize:	Number of bytes of response data expected
1218c2ecf20Sopenharmony_ci * @stat_pad_len: Number of bytes required to pad the STAT field to
1228c2ecf20Sopenharmony_ci *		a 4-byte boundary
1238c2ecf20Sopenharmony_ci *
1248c2ecf20Sopenharmony_ci * The scatterlist that gets allocated here is freed in spu_chunk_cleanup()
1258c2ecf20Sopenharmony_ci * when the request completes, whether the request is handled successfully or
1268c2ecf20Sopenharmony_ci * there is an error.
1278c2ecf20Sopenharmony_ci *
1288c2ecf20Sopenharmony_ci * Returns:
1298c2ecf20Sopenharmony_ci *   0 if successful
1308c2ecf20Sopenharmony_ci *   < 0 if an error
1318c2ecf20Sopenharmony_ci */
1328c2ecf20Sopenharmony_cistatic int
1338c2ecf20Sopenharmony_cispu_skcipher_rx_sg_create(struct brcm_message *mssg,
1348c2ecf20Sopenharmony_ci			    struct iproc_reqctx_s *rctx,
1358c2ecf20Sopenharmony_ci			    u8 rx_frag_num,
1368c2ecf20Sopenharmony_ci			    unsigned int chunksize, u32 stat_pad_len)
1378c2ecf20Sopenharmony_ci{
1388c2ecf20Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
1398c2ecf20Sopenharmony_ci	struct scatterlist *sg;	/* used to build sgs in mbox message */
1408c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = rctx->ctx;
1418c2ecf20Sopenharmony_ci	u32 datalen;		/* Number of bytes of response data expected */
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	mssg->spu.dst = kcalloc(rx_frag_num, sizeof(struct scatterlist),
1448c2ecf20Sopenharmony_ci				rctx->gfp);
1458c2ecf20Sopenharmony_ci	if (!mssg->spu.dst)
1468c2ecf20Sopenharmony_ci		return -ENOMEM;
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	sg = mssg->spu.dst;
1498c2ecf20Sopenharmony_ci	sg_init_table(sg, rx_frag_num);
1508c2ecf20Sopenharmony_ci	/* Space for SPU message header */
1518c2ecf20Sopenharmony_ci	sg_set_buf(sg++, rctx->msg_buf.spu_resp_hdr, ctx->spu_resp_hdr_len);
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci	/* If XTS tweak in payload, add buffer to receive encrypted tweak */
1548c2ecf20Sopenharmony_ci	if ((ctx->cipher.mode == CIPHER_MODE_XTS) &&
1558c2ecf20Sopenharmony_ci	    spu->spu_xts_tweak_in_payload())
1568c2ecf20Sopenharmony_ci		sg_set_buf(sg++, rctx->msg_buf.c.supdt_tweak,
1578c2ecf20Sopenharmony_ci			   SPU_XTS_TWEAK_SIZE);
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci	/* Copy in each dst sg entry from request, up to chunksize */
1608c2ecf20Sopenharmony_ci	datalen = spu_msg_sg_add(&sg, &rctx->dst_sg, &rctx->dst_skip,
1618c2ecf20Sopenharmony_ci				 rctx->dst_nents, chunksize);
1628c2ecf20Sopenharmony_ci	if (datalen < chunksize) {
1638c2ecf20Sopenharmony_ci		pr_err("%s(): failed to copy dst sg to mbox msg. chunksize %u, datalen %u",
1648c2ecf20Sopenharmony_ci		       __func__, chunksize, datalen);
1658c2ecf20Sopenharmony_ci		return -EFAULT;
1668c2ecf20Sopenharmony_ci	}
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	if (stat_pad_len)
1698c2ecf20Sopenharmony_ci		sg_set_buf(sg++, rctx->msg_buf.rx_stat_pad, stat_pad_len);
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	memset(rctx->msg_buf.rx_stat, 0, SPU_RX_STATUS_LEN);
1728c2ecf20Sopenharmony_ci	sg_set_buf(sg, rctx->msg_buf.rx_stat, spu->spu_rx_status_len());
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	return 0;
1758c2ecf20Sopenharmony_ci}
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci/**
1788c2ecf20Sopenharmony_ci * spu_skcipher_tx_sg_create() - Build up the scatterlist of buffers used to
1798c2ecf20Sopenharmony_ci * send a SPU request message for an skcipher request. Includes SPU message
1808c2ecf20Sopenharmony_ci * headers and the request data.
1818c2ecf20Sopenharmony_ci * @mssg:	mailbox message containing the transmit sg
1828c2ecf20Sopenharmony_ci * @rctx:	crypto request context
1838c2ecf20Sopenharmony_ci * @tx_frag_num: number of scatterlist elements required to construct the
1848c2ecf20Sopenharmony_ci *		SPU request message
1858c2ecf20Sopenharmony_ci * @chunksize:	Number of bytes of request data
1868c2ecf20Sopenharmony_ci * @pad_len:	Number of pad bytes
1878c2ecf20Sopenharmony_ci *
1888c2ecf20Sopenharmony_ci * The scatterlist that gets allocated here is freed in spu_chunk_cleanup()
1898c2ecf20Sopenharmony_ci * when the request completes, whether the request is handled successfully or
1908c2ecf20Sopenharmony_ci * there is an error.
1918c2ecf20Sopenharmony_ci *
1928c2ecf20Sopenharmony_ci * Returns:
1938c2ecf20Sopenharmony_ci *   0 if successful
1948c2ecf20Sopenharmony_ci *   < 0 if an error
1958c2ecf20Sopenharmony_ci */
1968c2ecf20Sopenharmony_cistatic int
1978c2ecf20Sopenharmony_cispu_skcipher_tx_sg_create(struct brcm_message *mssg,
1988c2ecf20Sopenharmony_ci			    struct iproc_reqctx_s *rctx,
1998c2ecf20Sopenharmony_ci			    u8 tx_frag_num, unsigned int chunksize, u32 pad_len)
2008c2ecf20Sopenharmony_ci{
2018c2ecf20Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
2028c2ecf20Sopenharmony_ci	struct scatterlist *sg;	/* used to build sgs in mbox message */
2038c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = rctx->ctx;
2048c2ecf20Sopenharmony_ci	u32 datalen;		/* Number of bytes of response data expected */
2058c2ecf20Sopenharmony_ci	u32 stat_len;
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	mssg->spu.src = kcalloc(tx_frag_num, sizeof(struct scatterlist),
2088c2ecf20Sopenharmony_ci				rctx->gfp);
2098c2ecf20Sopenharmony_ci	if (unlikely(!mssg->spu.src))
2108c2ecf20Sopenharmony_ci		return -ENOMEM;
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	sg = mssg->spu.src;
2138c2ecf20Sopenharmony_ci	sg_init_table(sg, tx_frag_num);
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	sg_set_buf(sg++, rctx->msg_buf.bcm_spu_req_hdr,
2168c2ecf20Sopenharmony_ci		   BCM_HDR_LEN + ctx->spu_req_hdr_len);
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	/* if XTS tweak in payload, copy from IV (where crypto API puts it) */
2198c2ecf20Sopenharmony_ci	if ((ctx->cipher.mode == CIPHER_MODE_XTS) &&
2208c2ecf20Sopenharmony_ci	    spu->spu_xts_tweak_in_payload())
2218c2ecf20Sopenharmony_ci		sg_set_buf(sg++, rctx->msg_buf.iv_ctr, SPU_XTS_TWEAK_SIZE);
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci	/* Copy in each src sg entry from request, up to chunksize */
2248c2ecf20Sopenharmony_ci	datalen = spu_msg_sg_add(&sg, &rctx->src_sg, &rctx->src_skip,
2258c2ecf20Sopenharmony_ci				 rctx->src_nents, chunksize);
2268c2ecf20Sopenharmony_ci	if (unlikely(datalen < chunksize)) {
2278c2ecf20Sopenharmony_ci		pr_err("%s(): failed to copy src sg to mbox msg",
2288c2ecf20Sopenharmony_ci		       __func__);
2298c2ecf20Sopenharmony_ci		return -EFAULT;
2308c2ecf20Sopenharmony_ci	}
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	if (pad_len)
2338c2ecf20Sopenharmony_ci		sg_set_buf(sg++, rctx->msg_buf.spu_req_pad, pad_len);
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	stat_len = spu->spu_tx_status_len();
2368c2ecf20Sopenharmony_ci	if (stat_len) {
2378c2ecf20Sopenharmony_ci		memset(rctx->msg_buf.tx_stat, 0, stat_len);
2388c2ecf20Sopenharmony_ci		sg_set_buf(sg, rctx->msg_buf.tx_stat, stat_len);
2398c2ecf20Sopenharmony_ci	}
2408c2ecf20Sopenharmony_ci	return 0;
2418c2ecf20Sopenharmony_ci}
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_cistatic int mailbox_send_message(struct brcm_message *mssg, u32 flags,
2448c2ecf20Sopenharmony_ci				u8 chan_idx)
2458c2ecf20Sopenharmony_ci{
2468c2ecf20Sopenharmony_ci	int err;
2478c2ecf20Sopenharmony_ci	int retry_cnt = 0;
2488c2ecf20Sopenharmony_ci	struct device *dev = &(iproc_priv.pdev->dev);
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	err = mbox_send_message(iproc_priv.mbox[chan_idx], mssg);
2518c2ecf20Sopenharmony_ci	if (flags & CRYPTO_TFM_REQ_MAY_SLEEP) {
2528c2ecf20Sopenharmony_ci		while ((err == -ENOBUFS) && (retry_cnt < SPU_MB_RETRY_MAX)) {
2538c2ecf20Sopenharmony_ci			/*
2548c2ecf20Sopenharmony_ci			 * Mailbox queue is full. Since MAY_SLEEP is set, assume
2558c2ecf20Sopenharmony_ci			 * not in atomic context and we can wait and try again.
2568c2ecf20Sopenharmony_ci			 */
2578c2ecf20Sopenharmony_ci			retry_cnt++;
2588c2ecf20Sopenharmony_ci			usleep_range(MBOX_SLEEP_MIN, MBOX_SLEEP_MAX);
2598c2ecf20Sopenharmony_ci			err = mbox_send_message(iproc_priv.mbox[chan_idx],
2608c2ecf20Sopenharmony_ci						mssg);
2618c2ecf20Sopenharmony_ci			atomic_inc(&iproc_priv.mb_no_spc);
2628c2ecf20Sopenharmony_ci		}
2638c2ecf20Sopenharmony_ci	}
2648c2ecf20Sopenharmony_ci	if (err < 0) {
2658c2ecf20Sopenharmony_ci		atomic_inc(&iproc_priv.mb_send_fail);
2668c2ecf20Sopenharmony_ci		return err;
2678c2ecf20Sopenharmony_ci	}
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci	/* Check error returned by mailbox controller */
2708c2ecf20Sopenharmony_ci	err = mssg->error;
2718c2ecf20Sopenharmony_ci	if (unlikely(err < 0)) {
2728c2ecf20Sopenharmony_ci		dev_err(dev, "message error %d", err);
2738c2ecf20Sopenharmony_ci		/* Signal txdone for mailbox channel */
2748c2ecf20Sopenharmony_ci	}
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	/* Signal txdone for mailbox channel */
2778c2ecf20Sopenharmony_ci	mbox_client_txdone(iproc_priv.mbox[chan_idx], err);
2788c2ecf20Sopenharmony_ci	return err;
2798c2ecf20Sopenharmony_ci}
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci/**
2828c2ecf20Sopenharmony_ci * handle_skcipher_req() - Submit as much of a block cipher request as fits in
2838c2ecf20Sopenharmony_ci * a single SPU request message, starting at the current position in the request
2848c2ecf20Sopenharmony_ci * data.
2858c2ecf20Sopenharmony_ci * @rctx:	Crypto request context
2868c2ecf20Sopenharmony_ci *
2878c2ecf20Sopenharmony_ci * This may be called on the crypto API thread, or, when a request is so large
2888c2ecf20Sopenharmony_ci * it must be broken into multiple SPU messages, on the thread used to invoke
2898c2ecf20Sopenharmony_ci * the response callback. When requests are broken into multiple SPU
2908c2ecf20Sopenharmony_ci * messages, we assume subsequent messages depend on previous results, and
2918c2ecf20Sopenharmony_ci * thus always wait for previous results before submitting the next message.
2928c2ecf20Sopenharmony_ci * Because requests are submitted in lock step like this, there is no need
2938c2ecf20Sopenharmony_ci * to synchronize access to request data structures.
2948c2ecf20Sopenharmony_ci *
2958c2ecf20Sopenharmony_ci * Return: -EINPROGRESS: request has been accepted and result will be returned
2968c2ecf20Sopenharmony_ci *			 asynchronously
2978c2ecf20Sopenharmony_ci *         Any other value indicates an error
2988c2ecf20Sopenharmony_ci */
2998c2ecf20Sopenharmony_cistatic int handle_skcipher_req(struct iproc_reqctx_s *rctx)
3008c2ecf20Sopenharmony_ci{
3018c2ecf20Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
3028c2ecf20Sopenharmony_ci	struct crypto_async_request *areq = rctx->parent;
3038c2ecf20Sopenharmony_ci	struct skcipher_request *req =
3048c2ecf20Sopenharmony_ci	    container_of(areq, struct skcipher_request, base);
3058c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = rctx->ctx;
3068c2ecf20Sopenharmony_ci	struct spu_cipher_parms cipher_parms;
3078c2ecf20Sopenharmony_ci	int err;
3088c2ecf20Sopenharmony_ci	unsigned int chunksize;	/* Num bytes of request to submit */
3098c2ecf20Sopenharmony_ci	int remaining;	/* Bytes of request still to process */
3108c2ecf20Sopenharmony_ci	int chunk_start;	/* Beginning of data for current SPU msg */
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	/* IV or ctr value to use in this SPU msg */
3138c2ecf20Sopenharmony_ci	u8 local_iv_ctr[MAX_IV_SIZE];
3148c2ecf20Sopenharmony_ci	u32 stat_pad_len;	/* num bytes to align status field */
3158c2ecf20Sopenharmony_ci	u32 pad_len;		/* total length of all padding */
3168c2ecf20Sopenharmony_ci	struct brcm_message *mssg;	/* mailbox message */
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	/* number of entries in src and dst sg in mailbox message. */
3198c2ecf20Sopenharmony_ci	u8 rx_frag_num = 2;	/* response header and STATUS */
3208c2ecf20Sopenharmony_ci	u8 tx_frag_num = 1;	/* request header */
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	flow_log("%s\n", __func__);
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	cipher_parms.alg = ctx->cipher.alg;
3258c2ecf20Sopenharmony_ci	cipher_parms.mode = ctx->cipher.mode;
3268c2ecf20Sopenharmony_ci	cipher_parms.type = ctx->cipher_type;
3278c2ecf20Sopenharmony_ci	cipher_parms.key_len = ctx->enckeylen;
3288c2ecf20Sopenharmony_ci	cipher_parms.key_buf = ctx->enckey;
3298c2ecf20Sopenharmony_ci	cipher_parms.iv_buf = local_iv_ctr;
3308c2ecf20Sopenharmony_ci	cipher_parms.iv_len = rctx->iv_ctr_len;
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	mssg = &rctx->mb_mssg;
3338c2ecf20Sopenharmony_ci	chunk_start = rctx->src_sent;
3348c2ecf20Sopenharmony_ci	remaining = rctx->total_todo - chunk_start;
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	/* determine the chunk we are breaking off and update the indexes */
3378c2ecf20Sopenharmony_ci	if ((ctx->max_payload != SPU_MAX_PAYLOAD_INF) &&
3388c2ecf20Sopenharmony_ci	    (remaining > ctx->max_payload))
3398c2ecf20Sopenharmony_ci		chunksize = ctx->max_payload;
3408c2ecf20Sopenharmony_ci	else
3418c2ecf20Sopenharmony_ci		chunksize = remaining;
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci	rctx->src_sent += chunksize;
3448c2ecf20Sopenharmony_ci	rctx->total_sent = rctx->src_sent;
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	/* Count number of sg entries to be included in this request */
3478c2ecf20Sopenharmony_ci	rctx->src_nents = spu_sg_count(rctx->src_sg, rctx->src_skip, chunksize);
3488c2ecf20Sopenharmony_ci	rctx->dst_nents = spu_sg_count(rctx->dst_sg, rctx->dst_skip, chunksize);
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci	if ((ctx->cipher.mode == CIPHER_MODE_CBC) &&
3518c2ecf20Sopenharmony_ci	    rctx->is_encrypt && chunk_start)
3528c2ecf20Sopenharmony_ci		/*
3538c2ecf20Sopenharmony_ci		 * Encrypting non-first first chunk. Copy last block of
3548c2ecf20Sopenharmony_ci		 * previous result to IV for this chunk.
3558c2ecf20Sopenharmony_ci		 */
3568c2ecf20Sopenharmony_ci		sg_copy_part_to_buf(req->dst, rctx->msg_buf.iv_ctr,
3578c2ecf20Sopenharmony_ci				    rctx->iv_ctr_len,
3588c2ecf20Sopenharmony_ci				    chunk_start - rctx->iv_ctr_len);
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci	if (rctx->iv_ctr_len) {
3618c2ecf20Sopenharmony_ci		/* get our local copy of the iv */
3628c2ecf20Sopenharmony_ci		__builtin_memcpy(local_iv_ctr, rctx->msg_buf.iv_ctr,
3638c2ecf20Sopenharmony_ci				 rctx->iv_ctr_len);
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci		/* generate the next IV if possible */
3668c2ecf20Sopenharmony_ci		if ((ctx->cipher.mode == CIPHER_MODE_CBC) &&
3678c2ecf20Sopenharmony_ci		    !rctx->is_encrypt) {
3688c2ecf20Sopenharmony_ci			/*
3698c2ecf20Sopenharmony_ci			 * CBC Decrypt: next IV is the last ciphertext block in
3708c2ecf20Sopenharmony_ci			 * this chunk
3718c2ecf20Sopenharmony_ci			 */
3728c2ecf20Sopenharmony_ci			sg_copy_part_to_buf(req->src, rctx->msg_buf.iv_ctr,
3738c2ecf20Sopenharmony_ci					    rctx->iv_ctr_len,
3748c2ecf20Sopenharmony_ci					    rctx->src_sent - rctx->iv_ctr_len);
3758c2ecf20Sopenharmony_ci		} else if (ctx->cipher.mode == CIPHER_MODE_CTR) {
3768c2ecf20Sopenharmony_ci			/*
3778c2ecf20Sopenharmony_ci			 * The SPU hardware increments the counter once for
3788c2ecf20Sopenharmony_ci			 * each AES block of 16 bytes. So update the counter
3798c2ecf20Sopenharmony_ci			 * for the next chunk, if there is one. Note that for
3808c2ecf20Sopenharmony_ci			 * this chunk, the counter has already been copied to
3818c2ecf20Sopenharmony_ci			 * local_iv_ctr. We can assume a block size of 16,
3828c2ecf20Sopenharmony_ci			 * because we only support CTR mode for AES, not for
3838c2ecf20Sopenharmony_ci			 * any other cipher alg.
3848c2ecf20Sopenharmony_ci			 */
3858c2ecf20Sopenharmony_ci			add_to_ctr(rctx->msg_buf.iv_ctr, chunksize >> 4);
3868c2ecf20Sopenharmony_ci		}
3878c2ecf20Sopenharmony_ci	}
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci	if (ctx->max_payload == SPU_MAX_PAYLOAD_INF)
3908c2ecf20Sopenharmony_ci		flow_log("max_payload infinite\n");
3918c2ecf20Sopenharmony_ci	else
3928c2ecf20Sopenharmony_ci		flow_log("max_payload %u\n", ctx->max_payload);
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	flow_log("sent:%u start:%u remains:%u size:%u\n",
3958c2ecf20Sopenharmony_ci		 rctx->src_sent, chunk_start, remaining, chunksize);
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci	/* Copy SPU header template created at setkey time */
3988c2ecf20Sopenharmony_ci	memcpy(rctx->msg_buf.bcm_spu_req_hdr, ctx->bcm_spu_req_hdr,
3998c2ecf20Sopenharmony_ci	       sizeof(rctx->msg_buf.bcm_spu_req_hdr));
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci	spu->spu_cipher_req_finish(rctx->msg_buf.bcm_spu_req_hdr + BCM_HDR_LEN,
4028c2ecf20Sopenharmony_ci				   ctx->spu_req_hdr_len, !(rctx->is_encrypt),
4038c2ecf20Sopenharmony_ci				   &cipher_parms, chunksize);
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_ci	atomic64_add(chunksize, &iproc_priv.bytes_out);
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	stat_pad_len = spu->spu_wordalign_padlen(chunksize);
4088c2ecf20Sopenharmony_ci	if (stat_pad_len)
4098c2ecf20Sopenharmony_ci		rx_frag_num++;
4108c2ecf20Sopenharmony_ci	pad_len = stat_pad_len;
4118c2ecf20Sopenharmony_ci	if (pad_len) {
4128c2ecf20Sopenharmony_ci		tx_frag_num++;
4138c2ecf20Sopenharmony_ci		spu->spu_request_pad(rctx->msg_buf.spu_req_pad, 0,
4148c2ecf20Sopenharmony_ci				     0, ctx->auth.alg, ctx->auth.mode,
4158c2ecf20Sopenharmony_ci				     rctx->total_sent, stat_pad_len);
4168c2ecf20Sopenharmony_ci	}
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci	spu->spu_dump_msg_hdr(rctx->msg_buf.bcm_spu_req_hdr + BCM_HDR_LEN,
4198c2ecf20Sopenharmony_ci			      ctx->spu_req_hdr_len);
4208c2ecf20Sopenharmony_ci	packet_log("payload:\n");
4218c2ecf20Sopenharmony_ci	dump_sg(rctx->src_sg, rctx->src_skip, chunksize);
4228c2ecf20Sopenharmony_ci	packet_dump("   pad: ", rctx->msg_buf.spu_req_pad, pad_len);
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci	/*
4258c2ecf20Sopenharmony_ci	 * Build mailbox message containing SPU request msg and rx buffers
4268c2ecf20Sopenharmony_ci	 * to catch response message
4278c2ecf20Sopenharmony_ci	 */
4288c2ecf20Sopenharmony_ci	memset(mssg, 0, sizeof(*mssg));
4298c2ecf20Sopenharmony_ci	mssg->type = BRCM_MESSAGE_SPU;
4308c2ecf20Sopenharmony_ci	mssg->ctx = rctx;	/* Will be returned in response */
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci	/* Create rx scatterlist to catch result */
4338c2ecf20Sopenharmony_ci	rx_frag_num += rctx->dst_nents;
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	if ((ctx->cipher.mode == CIPHER_MODE_XTS) &&
4368c2ecf20Sopenharmony_ci	    spu->spu_xts_tweak_in_payload())
4378c2ecf20Sopenharmony_ci		rx_frag_num++;	/* extra sg to insert tweak */
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci	err = spu_skcipher_rx_sg_create(mssg, rctx, rx_frag_num, chunksize,
4408c2ecf20Sopenharmony_ci					  stat_pad_len);
4418c2ecf20Sopenharmony_ci	if (err)
4428c2ecf20Sopenharmony_ci		return err;
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	/* Create tx scatterlist containing SPU request message */
4458c2ecf20Sopenharmony_ci	tx_frag_num += rctx->src_nents;
4468c2ecf20Sopenharmony_ci	if (spu->spu_tx_status_len())
4478c2ecf20Sopenharmony_ci		tx_frag_num++;
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ci	if ((ctx->cipher.mode == CIPHER_MODE_XTS) &&
4508c2ecf20Sopenharmony_ci	    spu->spu_xts_tweak_in_payload())
4518c2ecf20Sopenharmony_ci		tx_frag_num++;	/* extra sg to insert tweak */
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	err = spu_skcipher_tx_sg_create(mssg, rctx, tx_frag_num, chunksize,
4548c2ecf20Sopenharmony_ci					  pad_len);
4558c2ecf20Sopenharmony_ci	if (err)
4568c2ecf20Sopenharmony_ci		return err;
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci	err = mailbox_send_message(mssg, req->base.flags, rctx->chan_idx);
4598c2ecf20Sopenharmony_ci	if (unlikely(err < 0))
4608c2ecf20Sopenharmony_ci		return err;
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	return -EINPROGRESS;
4638c2ecf20Sopenharmony_ci}
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci/**
4668c2ecf20Sopenharmony_ci * handle_skcipher_resp() - Process a block cipher SPU response. Updates the
4678c2ecf20Sopenharmony_ci * total received count for the request and updates global stats.
4688c2ecf20Sopenharmony_ci * @rctx:	Crypto request context
4698c2ecf20Sopenharmony_ci */
4708c2ecf20Sopenharmony_cistatic void handle_skcipher_resp(struct iproc_reqctx_s *rctx)
4718c2ecf20Sopenharmony_ci{
4728c2ecf20Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
4738c2ecf20Sopenharmony_ci#ifdef DEBUG
4748c2ecf20Sopenharmony_ci	struct crypto_async_request *areq = rctx->parent;
4758c2ecf20Sopenharmony_ci	struct skcipher_request *req = skcipher_request_cast(areq);
4768c2ecf20Sopenharmony_ci#endif
4778c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = rctx->ctx;
4788c2ecf20Sopenharmony_ci	u32 payload_len;
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci	/* See how much data was returned */
4818c2ecf20Sopenharmony_ci	payload_len = spu->spu_payload_length(rctx->msg_buf.spu_resp_hdr);
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci	/*
4848c2ecf20Sopenharmony_ci	 * In XTS mode, the first SPU_XTS_TWEAK_SIZE bytes may be the
4858c2ecf20Sopenharmony_ci	 * encrypted tweak ("i") value; we don't count those.
4868c2ecf20Sopenharmony_ci	 */
4878c2ecf20Sopenharmony_ci	if ((ctx->cipher.mode == CIPHER_MODE_XTS) &&
4888c2ecf20Sopenharmony_ci	    spu->spu_xts_tweak_in_payload() &&
4898c2ecf20Sopenharmony_ci	    (payload_len >= SPU_XTS_TWEAK_SIZE))
4908c2ecf20Sopenharmony_ci		payload_len -= SPU_XTS_TWEAK_SIZE;
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci	atomic64_add(payload_len, &iproc_priv.bytes_in);
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci	flow_log("%s() offset: %u, bd_len: %u BD:\n",
4958c2ecf20Sopenharmony_ci		 __func__, rctx->total_received, payload_len);
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci	dump_sg(req->dst, rctx->total_received, payload_len);
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci	rctx->total_received += payload_len;
5008c2ecf20Sopenharmony_ci	if (rctx->total_received == rctx->total_todo) {
5018c2ecf20Sopenharmony_ci		atomic_inc(&iproc_priv.op_counts[SPU_OP_CIPHER]);
5028c2ecf20Sopenharmony_ci		atomic_inc(
5038c2ecf20Sopenharmony_ci		   &iproc_priv.cipher_cnt[ctx->cipher.alg][ctx->cipher.mode]);
5048c2ecf20Sopenharmony_ci	}
5058c2ecf20Sopenharmony_ci}
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci/**
5088c2ecf20Sopenharmony_ci * spu_ahash_rx_sg_create() - Build up the scatterlist of buffers used to
5098c2ecf20Sopenharmony_ci * receive a SPU response message for an ahash request.
5108c2ecf20Sopenharmony_ci * @mssg:	mailbox message containing the receive sg
5118c2ecf20Sopenharmony_ci * @rctx:	crypto request context
5128c2ecf20Sopenharmony_ci * @rx_frag_num: number of scatterlist elements required to hold the
5138c2ecf20Sopenharmony_ci *		SPU response message
5148c2ecf20Sopenharmony_ci * @digestsize: length of hash digest, in bytes
5158c2ecf20Sopenharmony_ci * @stat_pad_len: Number of bytes required to pad the STAT field to
5168c2ecf20Sopenharmony_ci *		a 4-byte boundary
5178c2ecf20Sopenharmony_ci *
5188c2ecf20Sopenharmony_ci * The scatterlist that gets allocated here is freed in spu_chunk_cleanup()
5198c2ecf20Sopenharmony_ci * when the request completes, whether the request is handled successfully or
5208c2ecf20Sopenharmony_ci * there is an error.
5218c2ecf20Sopenharmony_ci *
5228c2ecf20Sopenharmony_ci * Return:
5238c2ecf20Sopenharmony_ci *   0 if successful
5248c2ecf20Sopenharmony_ci *   < 0 if an error
5258c2ecf20Sopenharmony_ci */
5268c2ecf20Sopenharmony_cistatic int
5278c2ecf20Sopenharmony_cispu_ahash_rx_sg_create(struct brcm_message *mssg,
5288c2ecf20Sopenharmony_ci		       struct iproc_reqctx_s *rctx,
5298c2ecf20Sopenharmony_ci		       u8 rx_frag_num, unsigned int digestsize,
5308c2ecf20Sopenharmony_ci		       u32 stat_pad_len)
5318c2ecf20Sopenharmony_ci{
5328c2ecf20Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
5338c2ecf20Sopenharmony_ci	struct scatterlist *sg;	/* used to build sgs in mbox message */
5348c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = rctx->ctx;
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci	mssg->spu.dst = kcalloc(rx_frag_num, sizeof(struct scatterlist),
5378c2ecf20Sopenharmony_ci				rctx->gfp);
5388c2ecf20Sopenharmony_ci	if (!mssg->spu.dst)
5398c2ecf20Sopenharmony_ci		return -ENOMEM;
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_ci	sg = mssg->spu.dst;
5428c2ecf20Sopenharmony_ci	sg_init_table(sg, rx_frag_num);
5438c2ecf20Sopenharmony_ci	/* Space for SPU message header */
5448c2ecf20Sopenharmony_ci	sg_set_buf(sg++, rctx->msg_buf.spu_resp_hdr, ctx->spu_resp_hdr_len);
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ci	/* Space for digest */
5478c2ecf20Sopenharmony_ci	sg_set_buf(sg++, rctx->msg_buf.digest, digestsize);
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	if (stat_pad_len)
5508c2ecf20Sopenharmony_ci		sg_set_buf(sg++, rctx->msg_buf.rx_stat_pad, stat_pad_len);
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci	memset(rctx->msg_buf.rx_stat, 0, SPU_RX_STATUS_LEN);
5538c2ecf20Sopenharmony_ci	sg_set_buf(sg, rctx->msg_buf.rx_stat, spu->spu_rx_status_len());
5548c2ecf20Sopenharmony_ci	return 0;
5558c2ecf20Sopenharmony_ci}
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci/**
5588c2ecf20Sopenharmony_ci * spu_ahash_tx_sg_create() -  Build up the scatterlist of buffers used to send
5598c2ecf20Sopenharmony_ci * a SPU request message for an ahash request. Includes SPU message headers and
5608c2ecf20Sopenharmony_ci * the request data.
5618c2ecf20Sopenharmony_ci * @mssg:	mailbox message containing the transmit sg
5628c2ecf20Sopenharmony_ci * @rctx:	crypto request context
5638c2ecf20Sopenharmony_ci * @tx_frag_num: number of scatterlist elements required to construct the
5648c2ecf20Sopenharmony_ci *		SPU request message
5658c2ecf20Sopenharmony_ci * @spu_hdr_len: length in bytes of SPU message header
5668c2ecf20Sopenharmony_ci * @hash_carry_len: Number of bytes of data carried over from previous req
5678c2ecf20Sopenharmony_ci * @new_data_len: Number of bytes of new request data
5688c2ecf20Sopenharmony_ci * @pad_len:	Number of pad bytes
5698c2ecf20Sopenharmony_ci *
5708c2ecf20Sopenharmony_ci * The scatterlist that gets allocated here is freed in spu_chunk_cleanup()
5718c2ecf20Sopenharmony_ci * when the request completes, whether the request is handled successfully or
5728c2ecf20Sopenharmony_ci * there is an error.
5738c2ecf20Sopenharmony_ci *
5748c2ecf20Sopenharmony_ci * Return:
5758c2ecf20Sopenharmony_ci *   0 if successful
5768c2ecf20Sopenharmony_ci *   < 0 if an error
5778c2ecf20Sopenharmony_ci */
5788c2ecf20Sopenharmony_cistatic int
5798c2ecf20Sopenharmony_cispu_ahash_tx_sg_create(struct brcm_message *mssg,
5808c2ecf20Sopenharmony_ci		       struct iproc_reqctx_s *rctx,
5818c2ecf20Sopenharmony_ci		       u8 tx_frag_num,
5828c2ecf20Sopenharmony_ci		       u32 spu_hdr_len,
5838c2ecf20Sopenharmony_ci		       unsigned int hash_carry_len,
5848c2ecf20Sopenharmony_ci		       unsigned int new_data_len, u32 pad_len)
5858c2ecf20Sopenharmony_ci{
5868c2ecf20Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
5878c2ecf20Sopenharmony_ci	struct scatterlist *sg;	/* used to build sgs in mbox message */
5888c2ecf20Sopenharmony_ci	u32 datalen;		/* Number of bytes of response data expected */
5898c2ecf20Sopenharmony_ci	u32 stat_len;
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_ci	mssg->spu.src = kcalloc(tx_frag_num, sizeof(struct scatterlist),
5928c2ecf20Sopenharmony_ci				rctx->gfp);
5938c2ecf20Sopenharmony_ci	if (!mssg->spu.src)
5948c2ecf20Sopenharmony_ci		return -ENOMEM;
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci	sg = mssg->spu.src;
5978c2ecf20Sopenharmony_ci	sg_init_table(sg, tx_frag_num);
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	sg_set_buf(sg++, rctx->msg_buf.bcm_spu_req_hdr,
6008c2ecf20Sopenharmony_ci		   BCM_HDR_LEN + spu_hdr_len);
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	if (hash_carry_len)
6038c2ecf20Sopenharmony_ci		sg_set_buf(sg++, rctx->hash_carry, hash_carry_len);
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ci	if (new_data_len) {
6068c2ecf20Sopenharmony_ci		/* Copy in each src sg entry from request, up to chunksize */
6078c2ecf20Sopenharmony_ci		datalen = spu_msg_sg_add(&sg, &rctx->src_sg, &rctx->src_skip,
6088c2ecf20Sopenharmony_ci					 rctx->src_nents, new_data_len);
6098c2ecf20Sopenharmony_ci		if (datalen < new_data_len) {
6108c2ecf20Sopenharmony_ci			pr_err("%s(): failed to copy src sg to mbox msg",
6118c2ecf20Sopenharmony_ci			       __func__);
6128c2ecf20Sopenharmony_ci			return -EFAULT;
6138c2ecf20Sopenharmony_ci		}
6148c2ecf20Sopenharmony_ci	}
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci	if (pad_len)
6178c2ecf20Sopenharmony_ci		sg_set_buf(sg++, rctx->msg_buf.spu_req_pad, pad_len);
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	stat_len = spu->spu_tx_status_len();
6208c2ecf20Sopenharmony_ci	if (stat_len) {
6218c2ecf20Sopenharmony_ci		memset(rctx->msg_buf.tx_stat, 0, stat_len);
6228c2ecf20Sopenharmony_ci		sg_set_buf(sg, rctx->msg_buf.tx_stat, stat_len);
6238c2ecf20Sopenharmony_ci	}
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_ci	return 0;
6268c2ecf20Sopenharmony_ci}
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci/**
6298c2ecf20Sopenharmony_ci * handle_ahash_req() - Process an asynchronous hash request from the crypto
6308c2ecf20Sopenharmony_ci * API.
6318c2ecf20Sopenharmony_ci * @rctx:  Crypto request context
6328c2ecf20Sopenharmony_ci *
6338c2ecf20Sopenharmony_ci * Builds a SPU request message embedded in a mailbox message and submits the
6348c2ecf20Sopenharmony_ci * mailbox message on a selected mailbox channel. The SPU request message is
6358c2ecf20Sopenharmony_ci * constructed as a scatterlist, including entries from the crypto API's
6368c2ecf20Sopenharmony_ci * src scatterlist to avoid copying the data to be hashed. This function is
6378c2ecf20Sopenharmony_ci * called either on the thread from the crypto API, or, in the case that the
6388c2ecf20Sopenharmony_ci * crypto API request is too large to fit in a single SPU request message,
6398c2ecf20Sopenharmony_ci * on the thread that invokes the receive callback with a response message.
6408c2ecf20Sopenharmony_ci * Because some operations require the response from one chunk before the next
6418c2ecf20Sopenharmony_ci * chunk can be submitted, we always wait for the response for the previous
6428c2ecf20Sopenharmony_ci * chunk before submitting the next chunk. Because requests are submitted in
6438c2ecf20Sopenharmony_ci * lock step like this, there is no need to synchronize access to request data
6448c2ecf20Sopenharmony_ci * structures.
6458c2ecf20Sopenharmony_ci *
6468c2ecf20Sopenharmony_ci * Return:
6478c2ecf20Sopenharmony_ci *   -EINPROGRESS: request has been submitted to SPU and response will be
6488c2ecf20Sopenharmony_ci *		   returned asynchronously
6498c2ecf20Sopenharmony_ci *   -EAGAIN:      non-final request included a small amount of data, which for
6508c2ecf20Sopenharmony_ci *		   efficiency we did not submit to the SPU, but instead stored
6518c2ecf20Sopenharmony_ci *		   to be submitted to the SPU with the next part of the request
6528c2ecf20Sopenharmony_ci *   other:        an error code
6538c2ecf20Sopenharmony_ci */
6548c2ecf20Sopenharmony_cistatic int handle_ahash_req(struct iproc_reqctx_s *rctx)
6558c2ecf20Sopenharmony_ci{
6568c2ecf20Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
6578c2ecf20Sopenharmony_ci	struct crypto_async_request *areq = rctx->parent;
6588c2ecf20Sopenharmony_ci	struct ahash_request *req = ahash_request_cast(areq);
6598c2ecf20Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
6608c2ecf20Sopenharmony_ci	struct crypto_tfm *tfm = crypto_ahash_tfm(ahash);
6618c2ecf20Sopenharmony_ci	unsigned int blocksize = crypto_tfm_alg_blocksize(tfm);
6628c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = rctx->ctx;
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_ci	/* number of bytes still to be hashed in this req */
6658c2ecf20Sopenharmony_ci	unsigned int nbytes_to_hash = 0;
6668c2ecf20Sopenharmony_ci	int err;
6678c2ecf20Sopenharmony_ci	unsigned int chunksize = 0;	/* length of hash carry + new data */
6688c2ecf20Sopenharmony_ci	/*
6698c2ecf20Sopenharmony_ci	 * length of new data, not from hash carry, to be submitted in
6708c2ecf20Sopenharmony_ci	 * this hw request
6718c2ecf20Sopenharmony_ci	 */
6728c2ecf20Sopenharmony_ci	unsigned int new_data_len;
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci	unsigned int __maybe_unused chunk_start = 0;
6758c2ecf20Sopenharmony_ci	u32 db_size;	 /* Length of data field, incl gcm and hash padding */
6768c2ecf20Sopenharmony_ci	int pad_len = 0; /* total pad len, including gcm, hash, stat padding */
6778c2ecf20Sopenharmony_ci	u32 data_pad_len = 0;	/* length of GCM/CCM padding */
6788c2ecf20Sopenharmony_ci	u32 stat_pad_len = 0;	/* length of padding to align STATUS word */
6798c2ecf20Sopenharmony_ci	struct brcm_message *mssg;	/* mailbox message */
6808c2ecf20Sopenharmony_ci	struct spu_request_opts req_opts;
6818c2ecf20Sopenharmony_ci	struct spu_cipher_parms cipher_parms;
6828c2ecf20Sopenharmony_ci	struct spu_hash_parms hash_parms;
6838c2ecf20Sopenharmony_ci	struct spu_aead_parms aead_parms;
6848c2ecf20Sopenharmony_ci	unsigned int local_nbuf;
6858c2ecf20Sopenharmony_ci	u32 spu_hdr_len;
6868c2ecf20Sopenharmony_ci	unsigned int digestsize;
6878c2ecf20Sopenharmony_ci	u16 rem = 0;
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci	/*
6908c2ecf20Sopenharmony_ci	 * number of entries in src and dst sg. Always includes SPU msg header.
6918c2ecf20Sopenharmony_ci	 * rx always includes a buffer to catch digest and STATUS.
6928c2ecf20Sopenharmony_ci	 */
6938c2ecf20Sopenharmony_ci	u8 rx_frag_num = 3;
6948c2ecf20Sopenharmony_ci	u8 tx_frag_num = 1;
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci	flow_log("total_todo %u, total_sent %u\n",
6978c2ecf20Sopenharmony_ci		 rctx->total_todo, rctx->total_sent);
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_ci	memset(&req_opts, 0, sizeof(req_opts));
7008c2ecf20Sopenharmony_ci	memset(&cipher_parms, 0, sizeof(cipher_parms));
7018c2ecf20Sopenharmony_ci	memset(&hash_parms, 0, sizeof(hash_parms));
7028c2ecf20Sopenharmony_ci	memset(&aead_parms, 0, sizeof(aead_parms));
7038c2ecf20Sopenharmony_ci
7048c2ecf20Sopenharmony_ci	req_opts.bd_suppress = true;
7058c2ecf20Sopenharmony_ci	hash_parms.alg = ctx->auth.alg;
7068c2ecf20Sopenharmony_ci	hash_parms.mode = ctx->auth.mode;
7078c2ecf20Sopenharmony_ci	hash_parms.type = HASH_TYPE_NONE;
7088c2ecf20Sopenharmony_ci	hash_parms.key_buf = (u8 *)ctx->authkey;
7098c2ecf20Sopenharmony_ci	hash_parms.key_len = ctx->authkeylen;
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_ci	/*
7128c2ecf20Sopenharmony_ci	 * For hash algorithms below assignment looks bit odd but
7138c2ecf20Sopenharmony_ci	 * it's needed for AES-XCBC and AES-CMAC hash algorithms
7148c2ecf20Sopenharmony_ci	 * to differentiate between 128, 192, 256 bit key values.
7158c2ecf20Sopenharmony_ci	 * Based on the key values, hash algorithm is selected.
7168c2ecf20Sopenharmony_ci	 * For example for 128 bit key, hash algorithm is AES-128.
7178c2ecf20Sopenharmony_ci	 */
7188c2ecf20Sopenharmony_ci	cipher_parms.type = ctx->cipher_type;
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_ci	mssg = &rctx->mb_mssg;
7218c2ecf20Sopenharmony_ci	chunk_start = rctx->src_sent;
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	/*
7248c2ecf20Sopenharmony_ci	 * Compute the amount remaining to hash. This may include data
7258c2ecf20Sopenharmony_ci	 * carried over from previous requests.
7268c2ecf20Sopenharmony_ci	 */
7278c2ecf20Sopenharmony_ci	nbytes_to_hash = rctx->total_todo - rctx->total_sent;
7288c2ecf20Sopenharmony_ci	chunksize = nbytes_to_hash;
7298c2ecf20Sopenharmony_ci	if ((ctx->max_payload != SPU_MAX_PAYLOAD_INF) &&
7308c2ecf20Sopenharmony_ci	    (chunksize > ctx->max_payload))
7318c2ecf20Sopenharmony_ci		chunksize = ctx->max_payload;
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ci	/*
7348c2ecf20Sopenharmony_ci	 * If this is not a final request and the request data is not a multiple
7358c2ecf20Sopenharmony_ci	 * of a full block, then simply park the extra data and prefix it to the
7368c2ecf20Sopenharmony_ci	 * data for the next request.
7378c2ecf20Sopenharmony_ci	 */
7388c2ecf20Sopenharmony_ci	if (!rctx->is_final) {
7398c2ecf20Sopenharmony_ci		u8 *dest = rctx->hash_carry + rctx->hash_carry_len;
7408c2ecf20Sopenharmony_ci		u16 new_len;  /* len of data to add to hash carry */
7418c2ecf20Sopenharmony_ci
7428c2ecf20Sopenharmony_ci		rem = chunksize % blocksize;   /* remainder */
7438c2ecf20Sopenharmony_ci		if (rem) {
7448c2ecf20Sopenharmony_ci			/* chunksize not a multiple of blocksize */
7458c2ecf20Sopenharmony_ci			chunksize -= rem;
7468c2ecf20Sopenharmony_ci			if (chunksize == 0) {
7478c2ecf20Sopenharmony_ci				/* Don't have a full block to submit to hw */
7488c2ecf20Sopenharmony_ci				new_len = rem - rctx->hash_carry_len;
7498c2ecf20Sopenharmony_ci				sg_copy_part_to_buf(req->src, dest, new_len,
7508c2ecf20Sopenharmony_ci						    rctx->src_sent);
7518c2ecf20Sopenharmony_ci				rctx->hash_carry_len = rem;
7528c2ecf20Sopenharmony_ci				flow_log("Exiting with hash carry len: %u\n",
7538c2ecf20Sopenharmony_ci					 rctx->hash_carry_len);
7548c2ecf20Sopenharmony_ci				packet_dump("  buf: ",
7558c2ecf20Sopenharmony_ci					    rctx->hash_carry,
7568c2ecf20Sopenharmony_ci					    rctx->hash_carry_len);
7578c2ecf20Sopenharmony_ci				return -EAGAIN;
7588c2ecf20Sopenharmony_ci			}
7598c2ecf20Sopenharmony_ci		}
7608c2ecf20Sopenharmony_ci	}
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci	/* if we have hash carry, then prefix it to the data in this request */
7638c2ecf20Sopenharmony_ci	local_nbuf = rctx->hash_carry_len;
7648c2ecf20Sopenharmony_ci	rctx->hash_carry_len = 0;
7658c2ecf20Sopenharmony_ci	if (local_nbuf)
7668c2ecf20Sopenharmony_ci		tx_frag_num++;
7678c2ecf20Sopenharmony_ci	new_data_len = chunksize - local_nbuf;
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci	/* Count number of sg entries to be used in this request */
7708c2ecf20Sopenharmony_ci	rctx->src_nents = spu_sg_count(rctx->src_sg, rctx->src_skip,
7718c2ecf20Sopenharmony_ci				       new_data_len);
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci	/* AES hashing keeps key size in type field, so need to copy it here */
7748c2ecf20Sopenharmony_ci	if (hash_parms.alg == HASH_ALG_AES)
7758c2ecf20Sopenharmony_ci		hash_parms.type = (enum hash_type)cipher_parms.type;
7768c2ecf20Sopenharmony_ci	else
7778c2ecf20Sopenharmony_ci		hash_parms.type = spu->spu_hash_type(rctx->total_sent);
7788c2ecf20Sopenharmony_ci
7798c2ecf20Sopenharmony_ci	digestsize = spu->spu_digest_size(ctx->digestsize, ctx->auth.alg,
7808c2ecf20Sopenharmony_ci					  hash_parms.type);
7818c2ecf20Sopenharmony_ci	hash_parms.digestsize =	digestsize;
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_ci	/* update the indexes */
7848c2ecf20Sopenharmony_ci	rctx->total_sent += chunksize;
7858c2ecf20Sopenharmony_ci	/* if you sent a prebuf then that wasn't from this req->src */
7868c2ecf20Sopenharmony_ci	rctx->src_sent += new_data_len;
7878c2ecf20Sopenharmony_ci
7888c2ecf20Sopenharmony_ci	if ((rctx->total_sent == rctx->total_todo) && rctx->is_final)
7898c2ecf20Sopenharmony_ci		hash_parms.pad_len = spu->spu_hash_pad_len(hash_parms.alg,
7908c2ecf20Sopenharmony_ci							   hash_parms.mode,
7918c2ecf20Sopenharmony_ci							   chunksize,
7928c2ecf20Sopenharmony_ci							   blocksize);
7938c2ecf20Sopenharmony_ci
7948c2ecf20Sopenharmony_ci	/*
7958c2ecf20Sopenharmony_ci	 * If a non-first chunk, then include the digest returned from the
7968c2ecf20Sopenharmony_ci	 * previous chunk so that hw can add to it (except for AES types).
7978c2ecf20Sopenharmony_ci	 */
7988c2ecf20Sopenharmony_ci	if ((hash_parms.type == HASH_TYPE_UPDT) &&
7998c2ecf20Sopenharmony_ci	    (hash_parms.alg != HASH_ALG_AES)) {
8008c2ecf20Sopenharmony_ci		hash_parms.key_buf = rctx->incr_hash;
8018c2ecf20Sopenharmony_ci		hash_parms.key_len = digestsize;
8028c2ecf20Sopenharmony_ci	}
8038c2ecf20Sopenharmony_ci
8048c2ecf20Sopenharmony_ci	atomic64_add(chunksize, &iproc_priv.bytes_out);
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_ci	flow_log("%s() final: %u nbuf: %u ",
8078c2ecf20Sopenharmony_ci		 __func__, rctx->is_final, local_nbuf);
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci	if (ctx->max_payload == SPU_MAX_PAYLOAD_INF)
8108c2ecf20Sopenharmony_ci		flow_log("max_payload infinite\n");
8118c2ecf20Sopenharmony_ci	else
8128c2ecf20Sopenharmony_ci		flow_log("max_payload %u\n", ctx->max_payload);
8138c2ecf20Sopenharmony_ci
8148c2ecf20Sopenharmony_ci	flow_log("chunk_start: %u chunk_size: %u\n", chunk_start, chunksize);
8158c2ecf20Sopenharmony_ci
8168c2ecf20Sopenharmony_ci	/* Prepend SPU header with type 3 BCM header */
8178c2ecf20Sopenharmony_ci	memcpy(rctx->msg_buf.bcm_spu_req_hdr, BCMHEADER, BCM_HDR_LEN);
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci	hash_parms.prebuf_len = local_nbuf;
8208c2ecf20Sopenharmony_ci	spu_hdr_len = spu->spu_create_request(rctx->msg_buf.bcm_spu_req_hdr +
8218c2ecf20Sopenharmony_ci					      BCM_HDR_LEN,
8228c2ecf20Sopenharmony_ci					      &req_opts, &cipher_parms,
8238c2ecf20Sopenharmony_ci					      &hash_parms, &aead_parms,
8248c2ecf20Sopenharmony_ci					      new_data_len);
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_ci	if (spu_hdr_len == 0) {
8278c2ecf20Sopenharmony_ci		pr_err("Failed to create SPU request header\n");
8288c2ecf20Sopenharmony_ci		return -EFAULT;
8298c2ecf20Sopenharmony_ci	}
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_ci	/*
8328c2ecf20Sopenharmony_ci	 * Determine total length of padding required. Put all padding in one
8338c2ecf20Sopenharmony_ci	 * buffer.
8348c2ecf20Sopenharmony_ci	 */
8358c2ecf20Sopenharmony_ci	data_pad_len = spu->spu_gcm_ccm_pad_len(ctx->cipher.mode, chunksize);
8368c2ecf20Sopenharmony_ci	db_size = spu_real_db_size(0, 0, local_nbuf, new_data_len,
8378c2ecf20Sopenharmony_ci				   0, 0, hash_parms.pad_len);
8388c2ecf20Sopenharmony_ci	if (spu->spu_tx_status_len())
8398c2ecf20Sopenharmony_ci		stat_pad_len = spu->spu_wordalign_padlen(db_size);
8408c2ecf20Sopenharmony_ci	if (stat_pad_len)
8418c2ecf20Sopenharmony_ci		rx_frag_num++;
8428c2ecf20Sopenharmony_ci	pad_len = hash_parms.pad_len + data_pad_len + stat_pad_len;
8438c2ecf20Sopenharmony_ci	if (pad_len) {
8448c2ecf20Sopenharmony_ci		tx_frag_num++;
8458c2ecf20Sopenharmony_ci		spu->spu_request_pad(rctx->msg_buf.spu_req_pad, data_pad_len,
8468c2ecf20Sopenharmony_ci				     hash_parms.pad_len, ctx->auth.alg,
8478c2ecf20Sopenharmony_ci				     ctx->auth.mode, rctx->total_sent,
8488c2ecf20Sopenharmony_ci				     stat_pad_len);
8498c2ecf20Sopenharmony_ci	}
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci	spu->spu_dump_msg_hdr(rctx->msg_buf.bcm_spu_req_hdr + BCM_HDR_LEN,
8528c2ecf20Sopenharmony_ci			      spu_hdr_len);
8538c2ecf20Sopenharmony_ci	packet_dump("    prebuf: ", rctx->hash_carry, local_nbuf);
8548c2ecf20Sopenharmony_ci	flow_log("Data:\n");
8558c2ecf20Sopenharmony_ci	dump_sg(rctx->src_sg, rctx->src_skip, new_data_len);
8568c2ecf20Sopenharmony_ci	packet_dump("   pad: ", rctx->msg_buf.spu_req_pad, pad_len);
8578c2ecf20Sopenharmony_ci
8588c2ecf20Sopenharmony_ci	/*
8598c2ecf20Sopenharmony_ci	 * Build mailbox message containing SPU request msg and rx buffers
8608c2ecf20Sopenharmony_ci	 * to catch response message
8618c2ecf20Sopenharmony_ci	 */
8628c2ecf20Sopenharmony_ci	memset(mssg, 0, sizeof(*mssg));
8638c2ecf20Sopenharmony_ci	mssg->type = BRCM_MESSAGE_SPU;
8648c2ecf20Sopenharmony_ci	mssg->ctx = rctx;	/* Will be returned in response */
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_ci	/* Create rx scatterlist to catch result */
8678c2ecf20Sopenharmony_ci	err = spu_ahash_rx_sg_create(mssg, rctx, rx_frag_num, digestsize,
8688c2ecf20Sopenharmony_ci				     stat_pad_len);
8698c2ecf20Sopenharmony_ci	if (err)
8708c2ecf20Sopenharmony_ci		return err;
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_ci	/* Create tx scatterlist containing SPU request message */
8738c2ecf20Sopenharmony_ci	tx_frag_num += rctx->src_nents;
8748c2ecf20Sopenharmony_ci	if (spu->spu_tx_status_len())
8758c2ecf20Sopenharmony_ci		tx_frag_num++;
8768c2ecf20Sopenharmony_ci	err = spu_ahash_tx_sg_create(mssg, rctx, tx_frag_num, spu_hdr_len,
8778c2ecf20Sopenharmony_ci				     local_nbuf, new_data_len, pad_len);
8788c2ecf20Sopenharmony_ci	if (err)
8798c2ecf20Sopenharmony_ci		return err;
8808c2ecf20Sopenharmony_ci
8818c2ecf20Sopenharmony_ci	err = mailbox_send_message(mssg, req->base.flags, rctx->chan_idx);
8828c2ecf20Sopenharmony_ci	if (unlikely(err < 0))
8838c2ecf20Sopenharmony_ci		return err;
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci	return -EINPROGRESS;
8868c2ecf20Sopenharmony_ci}
8878c2ecf20Sopenharmony_ci
8888c2ecf20Sopenharmony_ci/**
8898c2ecf20Sopenharmony_ci * spu_hmac_outer_hash() - Request synchonous software compute of the outer hash
8908c2ecf20Sopenharmony_ci * for an HMAC request.
8918c2ecf20Sopenharmony_ci * @req:  The HMAC request from the crypto API
8928c2ecf20Sopenharmony_ci * @ctx:  The session context
8938c2ecf20Sopenharmony_ci *
8948c2ecf20Sopenharmony_ci * Return: 0 if synchronous hash operation successful
8958c2ecf20Sopenharmony_ci *         -EINVAL if the hash algo is unrecognized
8968c2ecf20Sopenharmony_ci *         any other value indicates an error
8978c2ecf20Sopenharmony_ci */
8988c2ecf20Sopenharmony_cistatic int spu_hmac_outer_hash(struct ahash_request *req,
8998c2ecf20Sopenharmony_ci			       struct iproc_ctx_s *ctx)
9008c2ecf20Sopenharmony_ci{
9018c2ecf20Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
9028c2ecf20Sopenharmony_ci	unsigned int blocksize =
9038c2ecf20Sopenharmony_ci		crypto_tfm_alg_blocksize(crypto_ahash_tfm(ahash));
9048c2ecf20Sopenharmony_ci	int rc;
9058c2ecf20Sopenharmony_ci
9068c2ecf20Sopenharmony_ci	switch (ctx->auth.alg) {
9078c2ecf20Sopenharmony_ci	case HASH_ALG_MD5:
9088c2ecf20Sopenharmony_ci		rc = do_shash("md5", req->result, ctx->opad, blocksize,
9098c2ecf20Sopenharmony_ci			      req->result, ctx->digestsize, NULL, 0);
9108c2ecf20Sopenharmony_ci		break;
9118c2ecf20Sopenharmony_ci	case HASH_ALG_SHA1:
9128c2ecf20Sopenharmony_ci		rc = do_shash("sha1", req->result, ctx->opad, blocksize,
9138c2ecf20Sopenharmony_ci			      req->result, ctx->digestsize, NULL, 0);
9148c2ecf20Sopenharmony_ci		break;
9158c2ecf20Sopenharmony_ci	case HASH_ALG_SHA224:
9168c2ecf20Sopenharmony_ci		rc = do_shash("sha224", req->result, ctx->opad, blocksize,
9178c2ecf20Sopenharmony_ci			      req->result, ctx->digestsize, NULL, 0);
9188c2ecf20Sopenharmony_ci		break;
9198c2ecf20Sopenharmony_ci	case HASH_ALG_SHA256:
9208c2ecf20Sopenharmony_ci		rc = do_shash("sha256", req->result, ctx->opad, blocksize,
9218c2ecf20Sopenharmony_ci			      req->result, ctx->digestsize, NULL, 0);
9228c2ecf20Sopenharmony_ci		break;
9238c2ecf20Sopenharmony_ci	case HASH_ALG_SHA384:
9248c2ecf20Sopenharmony_ci		rc = do_shash("sha384", req->result, ctx->opad, blocksize,
9258c2ecf20Sopenharmony_ci			      req->result, ctx->digestsize, NULL, 0);
9268c2ecf20Sopenharmony_ci		break;
9278c2ecf20Sopenharmony_ci	case HASH_ALG_SHA512:
9288c2ecf20Sopenharmony_ci		rc = do_shash("sha512", req->result, ctx->opad, blocksize,
9298c2ecf20Sopenharmony_ci			      req->result, ctx->digestsize, NULL, 0);
9308c2ecf20Sopenharmony_ci		break;
9318c2ecf20Sopenharmony_ci	default:
9328c2ecf20Sopenharmony_ci		pr_err("%s() Error : unknown hmac type\n", __func__);
9338c2ecf20Sopenharmony_ci		rc = -EINVAL;
9348c2ecf20Sopenharmony_ci	}
9358c2ecf20Sopenharmony_ci	return rc;
9368c2ecf20Sopenharmony_ci}
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci/**
9398c2ecf20Sopenharmony_ci * ahash_req_done() - Process a hash result from the SPU hardware.
9408c2ecf20Sopenharmony_ci * @rctx: Crypto request context
9418c2ecf20Sopenharmony_ci *
9428c2ecf20Sopenharmony_ci * Return: 0 if successful
9438c2ecf20Sopenharmony_ci *         < 0 if an error
9448c2ecf20Sopenharmony_ci */
9458c2ecf20Sopenharmony_cistatic int ahash_req_done(struct iproc_reqctx_s *rctx)
9468c2ecf20Sopenharmony_ci{
9478c2ecf20Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
9488c2ecf20Sopenharmony_ci	struct crypto_async_request *areq = rctx->parent;
9498c2ecf20Sopenharmony_ci	struct ahash_request *req = ahash_request_cast(areq);
9508c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = rctx->ctx;
9518c2ecf20Sopenharmony_ci	int err;
9528c2ecf20Sopenharmony_ci
9538c2ecf20Sopenharmony_ci	memcpy(req->result, rctx->msg_buf.digest, ctx->digestsize);
9548c2ecf20Sopenharmony_ci
9558c2ecf20Sopenharmony_ci	if (spu->spu_type == SPU_TYPE_SPUM) {
9568c2ecf20Sopenharmony_ci		/* byte swap the output from the UPDT function to network byte
9578c2ecf20Sopenharmony_ci		 * order
9588c2ecf20Sopenharmony_ci		 */
9598c2ecf20Sopenharmony_ci		if (ctx->auth.alg == HASH_ALG_MD5) {
9608c2ecf20Sopenharmony_ci			__swab32s((u32 *)req->result);
9618c2ecf20Sopenharmony_ci			__swab32s(((u32 *)req->result) + 1);
9628c2ecf20Sopenharmony_ci			__swab32s(((u32 *)req->result) + 2);
9638c2ecf20Sopenharmony_ci			__swab32s(((u32 *)req->result) + 3);
9648c2ecf20Sopenharmony_ci			__swab32s(((u32 *)req->result) + 4);
9658c2ecf20Sopenharmony_ci		}
9668c2ecf20Sopenharmony_ci	}
9678c2ecf20Sopenharmony_ci
9688c2ecf20Sopenharmony_ci	flow_dump("  digest ", req->result, ctx->digestsize);
9698c2ecf20Sopenharmony_ci
9708c2ecf20Sopenharmony_ci	/* if this an HMAC then do the outer hash */
9718c2ecf20Sopenharmony_ci	if (rctx->is_sw_hmac) {
9728c2ecf20Sopenharmony_ci		err = spu_hmac_outer_hash(req, ctx);
9738c2ecf20Sopenharmony_ci		if (err < 0)
9748c2ecf20Sopenharmony_ci			return err;
9758c2ecf20Sopenharmony_ci		flow_dump("  hmac: ", req->result, ctx->digestsize);
9768c2ecf20Sopenharmony_ci	}
9778c2ecf20Sopenharmony_ci
9788c2ecf20Sopenharmony_ci	if (rctx->is_sw_hmac || ctx->auth.mode == HASH_MODE_HMAC) {
9798c2ecf20Sopenharmony_ci		atomic_inc(&iproc_priv.op_counts[SPU_OP_HMAC]);
9808c2ecf20Sopenharmony_ci		atomic_inc(&iproc_priv.hmac_cnt[ctx->auth.alg]);
9818c2ecf20Sopenharmony_ci	} else {
9828c2ecf20Sopenharmony_ci		atomic_inc(&iproc_priv.op_counts[SPU_OP_HASH]);
9838c2ecf20Sopenharmony_ci		atomic_inc(&iproc_priv.hash_cnt[ctx->auth.alg]);
9848c2ecf20Sopenharmony_ci	}
9858c2ecf20Sopenharmony_ci
9868c2ecf20Sopenharmony_ci	return 0;
9878c2ecf20Sopenharmony_ci}
9888c2ecf20Sopenharmony_ci
9898c2ecf20Sopenharmony_ci/**
9908c2ecf20Sopenharmony_ci * handle_ahash_resp() - Process a SPU response message for a hash request.
9918c2ecf20Sopenharmony_ci * Checks if the entire crypto API request has been processed, and if so,
9928c2ecf20Sopenharmony_ci * invokes post processing on the result.
9938c2ecf20Sopenharmony_ci * @rctx: Crypto request context
9948c2ecf20Sopenharmony_ci */
9958c2ecf20Sopenharmony_cistatic void handle_ahash_resp(struct iproc_reqctx_s *rctx)
9968c2ecf20Sopenharmony_ci{
9978c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = rctx->ctx;
9988c2ecf20Sopenharmony_ci#ifdef DEBUG
9998c2ecf20Sopenharmony_ci	struct crypto_async_request *areq = rctx->parent;
10008c2ecf20Sopenharmony_ci	struct ahash_request *req = ahash_request_cast(areq);
10018c2ecf20Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
10028c2ecf20Sopenharmony_ci	unsigned int blocksize =
10038c2ecf20Sopenharmony_ci		crypto_tfm_alg_blocksize(crypto_ahash_tfm(ahash));
10048c2ecf20Sopenharmony_ci#endif
10058c2ecf20Sopenharmony_ci	/*
10068c2ecf20Sopenharmony_ci	 * Save hash to use as input to next op if incremental. Might be copying
10078c2ecf20Sopenharmony_ci	 * too much, but that's easier than figuring out actual digest size here
10088c2ecf20Sopenharmony_ci	 */
10098c2ecf20Sopenharmony_ci	memcpy(rctx->incr_hash, rctx->msg_buf.digest, MAX_DIGEST_SIZE);
10108c2ecf20Sopenharmony_ci
10118c2ecf20Sopenharmony_ci	flow_log("%s() blocksize:%u digestsize:%u\n",
10128c2ecf20Sopenharmony_ci		 __func__, blocksize, ctx->digestsize);
10138c2ecf20Sopenharmony_ci
10148c2ecf20Sopenharmony_ci	atomic64_add(ctx->digestsize, &iproc_priv.bytes_in);
10158c2ecf20Sopenharmony_ci
10168c2ecf20Sopenharmony_ci	if (rctx->is_final && (rctx->total_sent == rctx->total_todo))
10178c2ecf20Sopenharmony_ci		ahash_req_done(rctx);
10188c2ecf20Sopenharmony_ci}
10198c2ecf20Sopenharmony_ci
10208c2ecf20Sopenharmony_ci/**
10218c2ecf20Sopenharmony_ci * spu_aead_rx_sg_create() - Build up the scatterlist of buffers used to receive
10228c2ecf20Sopenharmony_ci * a SPU response message for an AEAD request. Includes buffers to catch SPU
10238c2ecf20Sopenharmony_ci * message headers and the response data.
10248c2ecf20Sopenharmony_ci * @mssg:	mailbox message containing the receive sg
10258c2ecf20Sopenharmony_ci * @rctx:	crypto request context
10268c2ecf20Sopenharmony_ci * @rx_frag_num: number of scatterlist elements required to hold the
10278c2ecf20Sopenharmony_ci *		SPU response message
10288c2ecf20Sopenharmony_ci * @assoc_len:	Length of associated data included in the crypto request
10298c2ecf20Sopenharmony_ci * @ret_iv_len: Length of IV returned in response
10308c2ecf20Sopenharmony_ci * @resp_len:	Number of bytes of response data expected to be written to
10318c2ecf20Sopenharmony_ci *              dst buffer from crypto API
10328c2ecf20Sopenharmony_ci * @digestsize: Length of hash digest, in bytes
10338c2ecf20Sopenharmony_ci * @stat_pad_len: Number of bytes required to pad the STAT field to
10348c2ecf20Sopenharmony_ci *		a 4-byte boundary
10358c2ecf20Sopenharmony_ci *
10368c2ecf20Sopenharmony_ci * The scatterlist that gets allocated here is freed in spu_chunk_cleanup()
10378c2ecf20Sopenharmony_ci * when the request completes, whether the request is handled successfully or
10388c2ecf20Sopenharmony_ci * there is an error.
10398c2ecf20Sopenharmony_ci *
10408c2ecf20Sopenharmony_ci * Returns:
10418c2ecf20Sopenharmony_ci *   0 if successful
10428c2ecf20Sopenharmony_ci *   < 0 if an error
10438c2ecf20Sopenharmony_ci */
10448c2ecf20Sopenharmony_cistatic int spu_aead_rx_sg_create(struct brcm_message *mssg,
10458c2ecf20Sopenharmony_ci				 struct aead_request *req,
10468c2ecf20Sopenharmony_ci				 struct iproc_reqctx_s *rctx,
10478c2ecf20Sopenharmony_ci				 u8 rx_frag_num,
10488c2ecf20Sopenharmony_ci				 unsigned int assoc_len,
10498c2ecf20Sopenharmony_ci				 u32 ret_iv_len, unsigned int resp_len,
10508c2ecf20Sopenharmony_ci				 unsigned int digestsize, u32 stat_pad_len)
10518c2ecf20Sopenharmony_ci{
10528c2ecf20Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
10538c2ecf20Sopenharmony_ci	struct scatterlist *sg;	/* used to build sgs in mbox message */
10548c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = rctx->ctx;
10558c2ecf20Sopenharmony_ci	u32 datalen;		/* Number of bytes of response data expected */
10568c2ecf20Sopenharmony_ci	u32 assoc_buf_len;
10578c2ecf20Sopenharmony_ci	u8 data_padlen = 0;
10588c2ecf20Sopenharmony_ci
10598c2ecf20Sopenharmony_ci	if (ctx->is_rfc4543) {
10608c2ecf20Sopenharmony_ci		/* RFC4543: only pad after data, not after AAD */
10618c2ecf20Sopenharmony_ci		data_padlen = spu->spu_gcm_ccm_pad_len(ctx->cipher.mode,
10628c2ecf20Sopenharmony_ci							  assoc_len + resp_len);
10638c2ecf20Sopenharmony_ci		assoc_buf_len = assoc_len;
10648c2ecf20Sopenharmony_ci	} else {
10658c2ecf20Sopenharmony_ci		data_padlen = spu->spu_gcm_ccm_pad_len(ctx->cipher.mode,
10668c2ecf20Sopenharmony_ci							  resp_len);
10678c2ecf20Sopenharmony_ci		assoc_buf_len = spu->spu_assoc_resp_len(ctx->cipher.mode,
10688c2ecf20Sopenharmony_ci						assoc_len, ret_iv_len,
10698c2ecf20Sopenharmony_ci						rctx->is_encrypt);
10708c2ecf20Sopenharmony_ci	}
10718c2ecf20Sopenharmony_ci
10728c2ecf20Sopenharmony_ci	if (ctx->cipher.mode == CIPHER_MODE_CCM)
10738c2ecf20Sopenharmony_ci		/* ICV (after data) must be in the next 32-bit word for CCM */
10748c2ecf20Sopenharmony_ci		data_padlen += spu->spu_wordalign_padlen(assoc_buf_len +
10758c2ecf20Sopenharmony_ci							 resp_len +
10768c2ecf20Sopenharmony_ci							 data_padlen);
10778c2ecf20Sopenharmony_ci
10788c2ecf20Sopenharmony_ci	if (data_padlen)
10798c2ecf20Sopenharmony_ci		/* have to catch gcm pad in separate buffer */
10808c2ecf20Sopenharmony_ci		rx_frag_num++;
10818c2ecf20Sopenharmony_ci
10828c2ecf20Sopenharmony_ci	mssg->spu.dst = kcalloc(rx_frag_num, sizeof(struct scatterlist),
10838c2ecf20Sopenharmony_ci				rctx->gfp);
10848c2ecf20Sopenharmony_ci	if (!mssg->spu.dst)
10858c2ecf20Sopenharmony_ci		return -ENOMEM;
10868c2ecf20Sopenharmony_ci
10878c2ecf20Sopenharmony_ci	sg = mssg->spu.dst;
10888c2ecf20Sopenharmony_ci	sg_init_table(sg, rx_frag_num);
10898c2ecf20Sopenharmony_ci
10908c2ecf20Sopenharmony_ci	/* Space for SPU message header */
10918c2ecf20Sopenharmony_ci	sg_set_buf(sg++, rctx->msg_buf.spu_resp_hdr, ctx->spu_resp_hdr_len);
10928c2ecf20Sopenharmony_ci
10938c2ecf20Sopenharmony_ci	if (assoc_buf_len) {
10948c2ecf20Sopenharmony_ci		/*
10958c2ecf20Sopenharmony_ci		 * Don't write directly to req->dst, because SPU may pad the
10968c2ecf20Sopenharmony_ci		 * assoc data in the response
10978c2ecf20Sopenharmony_ci		 */
10988c2ecf20Sopenharmony_ci		memset(rctx->msg_buf.a.resp_aad, 0, assoc_buf_len);
10998c2ecf20Sopenharmony_ci		sg_set_buf(sg++, rctx->msg_buf.a.resp_aad, assoc_buf_len);
11008c2ecf20Sopenharmony_ci	}
11018c2ecf20Sopenharmony_ci
11028c2ecf20Sopenharmony_ci	if (resp_len) {
11038c2ecf20Sopenharmony_ci		/*
11048c2ecf20Sopenharmony_ci		 * Copy in each dst sg entry from request, up to chunksize.
11058c2ecf20Sopenharmony_ci		 * dst sg catches just the data. digest caught in separate buf.
11068c2ecf20Sopenharmony_ci		 */
11078c2ecf20Sopenharmony_ci		datalen = spu_msg_sg_add(&sg, &rctx->dst_sg, &rctx->dst_skip,
11088c2ecf20Sopenharmony_ci					 rctx->dst_nents, resp_len);
11098c2ecf20Sopenharmony_ci		if (datalen < (resp_len)) {
11108c2ecf20Sopenharmony_ci			pr_err("%s(): failed to copy dst sg to mbox msg. expected len %u, datalen %u",
11118c2ecf20Sopenharmony_ci			       __func__, resp_len, datalen);
11128c2ecf20Sopenharmony_ci			return -EFAULT;
11138c2ecf20Sopenharmony_ci		}
11148c2ecf20Sopenharmony_ci	}
11158c2ecf20Sopenharmony_ci
11168c2ecf20Sopenharmony_ci	/* If GCM/CCM data is padded, catch padding in separate buffer */
11178c2ecf20Sopenharmony_ci	if (data_padlen) {
11188c2ecf20Sopenharmony_ci		memset(rctx->msg_buf.a.gcmpad, 0, data_padlen);
11198c2ecf20Sopenharmony_ci		sg_set_buf(sg++, rctx->msg_buf.a.gcmpad, data_padlen);
11208c2ecf20Sopenharmony_ci	}
11218c2ecf20Sopenharmony_ci
11228c2ecf20Sopenharmony_ci	/* Always catch ICV in separate buffer */
11238c2ecf20Sopenharmony_ci	sg_set_buf(sg++, rctx->msg_buf.digest, digestsize);
11248c2ecf20Sopenharmony_ci
11258c2ecf20Sopenharmony_ci	flow_log("stat_pad_len %u\n", stat_pad_len);
11268c2ecf20Sopenharmony_ci	if (stat_pad_len) {
11278c2ecf20Sopenharmony_ci		memset(rctx->msg_buf.rx_stat_pad, 0, stat_pad_len);
11288c2ecf20Sopenharmony_ci		sg_set_buf(sg++, rctx->msg_buf.rx_stat_pad, stat_pad_len);
11298c2ecf20Sopenharmony_ci	}
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_ci	memset(rctx->msg_buf.rx_stat, 0, SPU_RX_STATUS_LEN);
11328c2ecf20Sopenharmony_ci	sg_set_buf(sg, rctx->msg_buf.rx_stat, spu->spu_rx_status_len());
11338c2ecf20Sopenharmony_ci
11348c2ecf20Sopenharmony_ci	return 0;
11358c2ecf20Sopenharmony_ci}
11368c2ecf20Sopenharmony_ci
11378c2ecf20Sopenharmony_ci/**
11388c2ecf20Sopenharmony_ci * spu_aead_tx_sg_create() - Build up the scatterlist of buffers used to send a
11398c2ecf20Sopenharmony_ci * SPU request message for an AEAD request. Includes SPU message headers and the
11408c2ecf20Sopenharmony_ci * request data.
11418c2ecf20Sopenharmony_ci * @mssg:	mailbox message containing the transmit sg
11428c2ecf20Sopenharmony_ci * @rctx:	crypto request context
11438c2ecf20Sopenharmony_ci * @tx_frag_num: number of scatterlist elements required to construct the
11448c2ecf20Sopenharmony_ci *		SPU request message
11458c2ecf20Sopenharmony_ci * @spu_hdr_len: length of SPU message header in bytes
11468c2ecf20Sopenharmony_ci * @assoc:	crypto API associated data scatterlist
11478c2ecf20Sopenharmony_ci * @assoc_len:	length of associated data
11488c2ecf20Sopenharmony_ci * @assoc_nents: number of scatterlist entries containing assoc data
11498c2ecf20Sopenharmony_ci * @aead_iv_len: length of AEAD IV, if included
11508c2ecf20Sopenharmony_ci * @chunksize:	Number of bytes of request data
11518c2ecf20Sopenharmony_ci * @aad_pad_len: Number of bytes of padding at end of AAD. For GCM/CCM.
11528c2ecf20Sopenharmony_ci * @pad_len:	Number of pad bytes
11538c2ecf20Sopenharmony_ci * @incl_icv:	If true, write separate ICV buffer after data and
11548c2ecf20Sopenharmony_ci *              any padding
11558c2ecf20Sopenharmony_ci *
11568c2ecf20Sopenharmony_ci * The scatterlist that gets allocated here is freed in spu_chunk_cleanup()
11578c2ecf20Sopenharmony_ci * when the request completes, whether the request is handled successfully or
11588c2ecf20Sopenharmony_ci * there is an error.
11598c2ecf20Sopenharmony_ci *
11608c2ecf20Sopenharmony_ci * Return:
11618c2ecf20Sopenharmony_ci *   0 if successful
11628c2ecf20Sopenharmony_ci *   < 0 if an error
11638c2ecf20Sopenharmony_ci */
11648c2ecf20Sopenharmony_cistatic int spu_aead_tx_sg_create(struct brcm_message *mssg,
11658c2ecf20Sopenharmony_ci				 struct iproc_reqctx_s *rctx,
11668c2ecf20Sopenharmony_ci				 u8 tx_frag_num,
11678c2ecf20Sopenharmony_ci				 u32 spu_hdr_len,
11688c2ecf20Sopenharmony_ci				 struct scatterlist *assoc,
11698c2ecf20Sopenharmony_ci				 unsigned int assoc_len,
11708c2ecf20Sopenharmony_ci				 int assoc_nents,
11718c2ecf20Sopenharmony_ci				 unsigned int aead_iv_len,
11728c2ecf20Sopenharmony_ci				 unsigned int chunksize,
11738c2ecf20Sopenharmony_ci				 u32 aad_pad_len, u32 pad_len, bool incl_icv)
11748c2ecf20Sopenharmony_ci{
11758c2ecf20Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
11768c2ecf20Sopenharmony_ci	struct scatterlist *sg;	/* used to build sgs in mbox message */
11778c2ecf20Sopenharmony_ci	struct scatterlist *assoc_sg = assoc;
11788c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = rctx->ctx;
11798c2ecf20Sopenharmony_ci	u32 datalen;		/* Number of bytes of data to write */
11808c2ecf20Sopenharmony_ci	u32 written;		/* Number of bytes of data written */
11818c2ecf20Sopenharmony_ci	u32 assoc_offset = 0;
11828c2ecf20Sopenharmony_ci	u32 stat_len;
11838c2ecf20Sopenharmony_ci
11848c2ecf20Sopenharmony_ci	mssg->spu.src = kcalloc(tx_frag_num, sizeof(struct scatterlist),
11858c2ecf20Sopenharmony_ci				rctx->gfp);
11868c2ecf20Sopenharmony_ci	if (!mssg->spu.src)
11878c2ecf20Sopenharmony_ci		return -ENOMEM;
11888c2ecf20Sopenharmony_ci
11898c2ecf20Sopenharmony_ci	sg = mssg->spu.src;
11908c2ecf20Sopenharmony_ci	sg_init_table(sg, tx_frag_num);
11918c2ecf20Sopenharmony_ci
11928c2ecf20Sopenharmony_ci	sg_set_buf(sg++, rctx->msg_buf.bcm_spu_req_hdr,
11938c2ecf20Sopenharmony_ci		   BCM_HDR_LEN + spu_hdr_len);
11948c2ecf20Sopenharmony_ci
11958c2ecf20Sopenharmony_ci	if (assoc_len) {
11968c2ecf20Sopenharmony_ci		/* Copy in each associated data sg entry from request */
11978c2ecf20Sopenharmony_ci		written = spu_msg_sg_add(&sg, &assoc_sg, &assoc_offset,
11988c2ecf20Sopenharmony_ci					 assoc_nents, assoc_len);
11998c2ecf20Sopenharmony_ci		if (written < assoc_len) {
12008c2ecf20Sopenharmony_ci			pr_err("%s(): failed to copy assoc sg to mbox msg",
12018c2ecf20Sopenharmony_ci			       __func__);
12028c2ecf20Sopenharmony_ci			return -EFAULT;
12038c2ecf20Sopenharmony_ci		}
12048c2ecf20Sopenharmony_ci	}
12058c2ecf20Sopenharmony_ci
12068c2ecf20Sopenharmony_ci	if (aead_iv_len)
12078c2ecf20Sopenharmony_ci		sg_set_buf(sg++, rctx->msg_buf.iv_ctr, aead_iv_len);
12088c2ecf20Sopenharmony_ci
12098c2ecf20Sopenharmony_ci	if (aad_pad_len) {
12108c2ecf20Sopenharmony_ci		memset(rctx->msg_buf.a.req_aad_pad, 0, aad_pad_len);
12118c2ecf20Sopenharmony_ci		sg_set_buf(sg++, rctx->msg_buf.a.req_aad_pad, aad_pad_len);
12128c2ecf20Sopenharmony_ci	}
12138c2ecf20Sopenharmony_ci
12148c2ecf20Sopenharmony_ci	datalen = chunksize;
12158c2ecf20Sopenharmony_ci	if ((chunksize > ctx->digestsize) && incl_icv)
12168c2ecf20Sopenharmony_ci		datalen -= ctx->digestsize;
12178c2ecf20Sopenharmony_ci	if (datalen) {
12188c2ecf20Sopenharmony_ci		/* For aead, a single msg should consume the entire src sg */
12198c2ecf20Sopenharmony_ci		written = spu_msg_sg_add(&sg, &rctx->src_sg, &rctx->src_skip,
12208c2ecf20Sopenharmony_ci					 rctx->src_nents, datalen);
12218c2ecf20Sopenharmony_ci		if (written < datalen) {
12228c2ecf20Sopenharmony_ci			pr_err("%s(): failed to copy src sg to mbox msg",
12238c2ecf20Sopenharmony_ci			       __func__);
12248c2ecf20Sopenharmony_ci			return -EFAULT;
12258c2ecf20Sopenharmony_ci		}
12268c2ecf20Sopenharmony_ci	}
12278c2ecf20Sopenharmony_ci
12288c2ecf20Sopenharmony_ci	if (pad_len) {
12298c2ecf20Sopenharmony_ci		memset(rctx->msg_buf.spu_req_pad, 0, pad_len);
12308c2ecf20Sopenharmony_ci		sg_set_buf(sg++, rctx->msg_buf.spu_req_pad, pad_len);
12318c2ecf20Sopenharmony_ci	}
12328c2ecf20Sopenharmony_ci
12338c2ecf20Sopenharmony_ci	if (incl_icv)
12348c2ecf20Sopenharmony_ci		sg_set_buf(sg++, rctx->msg_buf.digest, ctx->digestsize);
12358c2ecf20Sopenharmony_ci
12368c2ecf20Sopenharmony_ci	stat_len = spu->spu_tx_status_len();
12378c2ecf20Sopenharmony_ci	if (stat_len) {
12388c2ecf20Sopenharmony_ci		memset(rctx->msg_buf.tx_stat, 0, stat_len);
12398c2ecf20Sopenharmony_ci		sg_set_buf(sg, rctx->msg_buf.tx_stat, stat_len);
12408c2ecf20Sopenharmony_ci	}
12418c2ecf20Sopenharmony_ci	return 0;
12428c2ecf20Sopenharmony_ci}
12438c2ecf20Sopenharmony_ci
12448c2ecf20Sopenharmony_ci/**
12458c2ecf20Sopenharmony_ci * handle_aead_req() - Submit a SPU request message for the next chunk of the
12468c2ecf20Sopenharmony_ci * current AEAD request.
12478c2ecf20Sopenharmony_ci * @rctx:  Crypto request context
12488c2ecf20Sopenharmony_ci *
12498c2ecf20Sopenharmony_ci * Unlike other operation types, we assume the length of the request fits in
12508c2ecf20Sopenharmony_ci * a single SPU request message. aead_enqueue() makes sure this is true.
12518c2ecf20Sopenharmony_ci * Comments for other op types regarding threads applies here as well.
12528c2ecf20Sopenharmony_ci *
12538c2ecf20Sopenharmony_ci * Unlike incremental hash ops, where the spu returns the entire hash for
12548c2ecf20Sopenharmony_ci * truncated algs like sha-224, the SPU returns just the truncated hash in
12558c2ecf20Sopenharmony_ci * response to aead requests. So digestsize is always ctx->digestsize here.
12568c2ecf20Sopenharmony_ci *
12578c2ecf20Sopenharmony_ci * Return: -EINPROGRESS: crypto request has been accepted and result will be
12588c2ecf20Sopenharmony_ci *			 returned asynchronously
12598c2ecf20Sopenharmony_ci *         Any other value indicates an error
12608c2ecf20Sopenharmony_ci */
12618c2ecf20Sopenharmony_cistatic int handle_aead_req(struct iproc_reqctx_s *rctx)
12628c2ecf20Sopenharmony_ci{
12638c2ecf20Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
12648c2ecf20Sopenharmony_ci	struct crypto_async_request *areq = rctx->parent;
12658c2ecf20Sopenharmony_ci	struct aead_request *req = container_of(areq,
12668c2ecf20Sopenharmony_ci						struct aead_request, base);
12678c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = rctx->ctx;
12688c2ecf20Sopenharmony_ci	int err;
12698c2ecf20Sopenharmony_ci	unsigned int chunksize;
12708c2ecf20Sopenharmony_ci	unsigned int resp_len;
12718c2ecf20Sopenharmony_ci	u32 spu_hdr_len;
12728c2ecf20Sopenharmony_ci	u32 db_size;
12738c2ecf20Sopenharmony_ci	u32 stat_pad_len;
12748c2ecf20Sopenharmony_ci	u32 pad_len;
12758c2ecf20Sopenharmony_ci	struct brcm_message *mssg;	/* mailbox message */
12768c2ecf20Sopenharmony_ci	struct spu_request_opts req_opts;
12778c2ecf20Sopenharmony_ci	struct spu_cipher_parms cipher_parms;
12788c2ecf20Sopenharmony_ci	struct spu_hash_parms hash_parms;
12798c2ecf20Sopenharmony_ci	struct spu_aead_parms aead_parms;
12808c2ecf20Sopenharmony_ci	int assoc_nents = 0;
12818c2ecf20Sopenharmony_ci	bool incl_icv = false;
12828c2ecf20Sopenharmony_ci	unsigned int digestsize = ctx->digestsize;
12838c2ecf20Sopenharmony_ci
12848c2ecf20Sopenharmony_ci	/* number of entries in src and dst sg. Always includes SPU msg header.
12858c2ecf20Sopenharmony_ci	 */
12868c2ecf20Sopenharmony_ci	u8 rx_frag_num = 2;	/* and STATUS */
12878c2ecf20Sopenharmony_ci	u8 tx_frag_num = 1;
12888c2ecf20Sopenharmony_ci
12898c2ecf20Sopenharmony_ci	/* doing the whole thing at once */
12908c2ecf20Sopenharmony_ci	chunksize = rctx->total_todo;
12918c2ecf20Sopenharmony_ci
12928c2ecf20Sopenharmony_ci	flow_log("%s: chunksize %u\n", __func__, chunksize);
12938c2ecf20Sopenharmony_ci
12948c2ecf20Sopenharmony_ci	memset(&req_opts, 0, sizeof(req_opts));
12958c2ecf20Sopenharmony_ci	memset(&hash_parms, 0, sizeof(hash_parms));
12968c2ecf20Sopenharmony_ci	memset(&aead_parms, 0, sizeof(aead_parms));
12978c2ecf20Sopenharmony_ci
12988c2ecf20Sopenharmony_ci	req_opts.is_inbound = !(rctx->is_encrypt);
12998c2ecf20Sopenharmony_ci	req_opts.auth_first = ctx->auth_first;
13008c2ecf20Sopenharmony_ci	req_opts.is_aead = true;
13018c2ecf20Sopenharmony_ci	req_opts.is_esp = ctx->is_esp;
13028c2ecf20Sopenharmony_ci
13038c2ecf20Sopenharmony_ci	cipher_parms.alg = ctx->cipher.alg;
13048c2ecf20Sopenharmony_ci	cipher_parms.mode = ctx->cipher.mode;
13058c2ecf20Sopenharmony_ci	cipher_parms.type = ctx->cipher_type;
13068c2ecf20Sopenharmony_ci	cipher_parms.key_buf = ctx->enckey;
13078c2ecf20Sopenharmony_ci	cipher_parms.key_len = ctx->enckeylen;
13088c2ecf20Sopenharmony_ci	cipher_parms.iv_buf = rctx->msg_buf.iv_ctr;
13098c2ecf20Sopenharmony_ci	cipher_parms.iv_len = rctx->iv_ctr_len;
13108c2ecf20Sopenharmony_ci
13118c2ecf20Sopenharmony_ci	hash_parms.alg = ctx->auth.alg;
13128c2ecf20Sopenharmony_ci	hash_parms.mode = ctx->auth.mode;
13138c2ecf20Sopenharmony_ci	hash_parms.type = HASH_TYPE_NONE;
13148c2ecf20Sopenharmony_ci	hash_parms.key_buf = (u8 *)ctx->authkey;
13158c2ecf20Sopenharmony_ci	hash_parms.key_len = ctx->authkeylen;
13168c2ecf20Sopenharmony_ci	hash_parms.digestsize = digestsize;
13178c2ecf20Sopenharmony_ci
13188c2ecf20Sopenharmony_ci	if ((ctx->auth.alg == HASH_ALG_SHA224) &&
13198c2ecf20Sopenharmony_ci	    (ctx->authkeylen < SHA224_DIGEST_SIZE))
13208c2ecf20Sopenharmony_ci		hash_parms.key_len = SHA224_DIGEST_SIZE;
13218c2ecf20Sopenharmony_ci
13228c2ecf20Sopenharmony_ci	aead_parms.assoc_size = req->assoclen;
13238c2ecf20Sopenharmony_ci	if (ctx->is_esp && !ctx->is_rfc4543) {
13248c2ecf20Sopenharmony_ci		/*
13258c2ecf20Sopenharmony_ci		 * 8-byte IV is included assoc data in request. SPU2
13268c2ecf20Sopenharmony_ci		 * expects AAD to include just SPI and seqno. So
13278c2ecf20Sopenharmony_ci		 * subtract off the IV len.
13288c2ecf20Sopenharmony_ci		 */
13298c2ecf20Sopenharmony_ci		aead_parms.assoc_size -= GCM_RFC4106_IV_SIZE;
13308c2ecf20Sopenharmony_ci
13318c2ecf20Sopenharmony_ci		if (rctx->is_encrypt) {
13328c2ecf20Sopenharmony_ci			aead_parms.return_iv = true;
13338c2ecf20Sopenharmony_ci			aead_parms.ret_iv_len = GCM_RFC4106_IV_SIZE;
13348c2ecf20Sopenharmony_ci			aead_parms.ret_iv_off = GCM_ESP_SALT_SIZE;
13358c2ecf20Sopenharmony_ci		}
13368c2ecf20Sopenharmony_ci	} else {
13378c2ecf20Sopenharmony_ci		aead_parms.ret_iv_len = 0;
13388c2ecf20Sopenharmony_ci	}
13398c2ecf20Sopenharmony_ci
13408c2ecf20Sopenharmony_ci	/*
13418c2ecf20Sopenharmony_ci	 * Count number of sg entries from the crypto API request that are to
13428c2ecf20Sopenharmony_ci	 * be included in this mailbox message. For dst sg, don't count space
13438c2ecf20Sopenharmony_ci	 * for digest. Digest gets caught in a separate buffer and copied back
13448c2ecf20Sopenharmony_ci	 * to dst sg when processing response.
13458c2ecf20Sopenharmony_ci	 */
13468c2ecf20Sopenharmony_ci	rctx->src_nents = spu_sg_count(rctx->src_sg, rctx->src_skip, chunksize);
13478c2ecf20Sopenharmony_ci	rctx->dst_nents = spu_sg_count(rctx->dst_sg, rctx->dst_skip, chunksize);
13488c2ecf20Sopenharmony_ci	if (aead_parms.assoc_size)
13498c2ecf20Sopenharmony_ci		assoc_nents = spu_sg_count(rctx->assoc, 0,
13508c2ecf20Sopenharmony_ci					   aead_parms.assoc_size);
13518c2ecf20Sopenharmony_ci
13528c2ecf20Sopenharmony_ci	mssg = &rctx->mb_mssg;
13538c2ecf20Sopenharmony_ci
13548c2ecf20Sopenharmony_ci	rctx->total_sent = chunksize;
13558c2ecf20Sopenharmony_ci	rctx->src_sent = chunksize;
13568c2ecf20Sopenharmony_ci	if (spu->spu_assoc_resp_len(ctx->cipher.mode,
13578c2ecf20Sopenharmony_ci				    aead_parms.assoc_size,
13588c2ecf20Sopenharmony_ci				    aead_parms.ret_iv_len,
13598c2ecf20Sopenharmony_ci				    rctx->is_encrypt))
13608c2ecf20Sopenharmony_ci		rx_frag_num++;
13618c2ecf20Sopenharmony_ci
13628c2ecf20Sopenharmony_ci	aead_parms.iv_len = spu->spu_aead_ivlen(ctx->cipher.mode,
13638c2ecf20Sopenharmony_ci						rctx->iv_ctr_len);
13648c2ecf20Sopenharmony_ci
13658c2ecf20Sopenharmony_ci	if (ctx->auth.alg == HASH_ALG_AES)
13668c2ecf20Sopenharmony_ci		hash_parms.type = (enum hash_type)ctx->cipher_type;
13678c2ecf20Sopenharmony_ci
13688c2ecf20Sopenharmony_ci	/* General case AAD padding (CCM and RFC4543 special cases below) */
13698c2ecf20Sopenharmony_ci	aead_parms.aad_pad_len = spu->spu_gcm_ccm_pad_len(ctx->cipher.mode,
13708c2ecf20Sopenharmony_ci						 aead_parms.assoc_size);
13718c2ecf20Sopenharmony_ci
13728c2ecf20Sopenharmony_ci	/* General case data padding (CCM decrypt special case below) */
13738c2ecf20Sopenharmony_ci	aead_parms.data_pad_len = spu->spu_gcm_ccm_pad_len(ctx->cipher.mode,
13748c2ecf20Sopenharmony_ci							   chunksize);
13758c2ecf20Sopenharmony_ci
13768c2ecf20Sopenharmony_ci	if (ctx->cipher.mode == CIPHER_MODE_CCM) {
13778c2ecf20Sopenharmony_ci		/*
13788c2ecf20Sopenharmony_ci		 * for CCM, AAD len + 2 (rather than AAD len) needs to be
13798c2ecf20Sopenharmony_ci		 * 128-bit aligned
13808c2ecf20Sopenharmony_ci		 */
13818c2ecf20Sopenharmony_ci		aead_parms.aad_pad_len = spu->spu_gcm_ccm_pad_len(
13828c2ecf20Sopenharmony_ci					 ctx->cipher.mode,
13838c2ecf20Sopenharmony_ci					 aead_parms.assoc_size + 2);
13848c2ecf20Sopenharmony_ci
13858c2ecf20Sopenharmony_ci		/*
13868c2ecf20Sopenharmony_ci		 * And when decrypting CCM, need to pad without including
13878c2ecf20Sopenharmony_ci		 * size of ICV which is tacked on to end of chunk
13888c2ecf20Sopenharmony_ci		 */
13898c2ecf20Sopenharmony_ci		if (!rctx->is_encrypt)
13908c2ecf20Sopenharmony_ci			aead_parms.data_pad_len =
13918c2ecf20Sopenharmony_ci				spu->spu_gcm_ccm_pad_len(ctx->cipher.mode,
13928c2ecf20Sopenharmony_ci							chunksize - digestsize);
13938c2ecf20Sopenharmony_ci
13948c2ecf20Sopenharmony_ci		/* CCM also requires software to rewrite portions of IV: */
13958c2ecf20Sopenharmony_ci		spu->spu_ccm_update_iv(digestsize, &cipher_parms, req->assoclen,
13968c2ecf20Sopenharmony_ci				       chunksize, rctx->is_encrypt,
13978c2ecf20Sopenharmony_ci				       ctx->is_esp);
13988c2ecf20Sopenharmony_ci	}
13998c2ecf20Sopenharmony_ci
14008c2ecf20Sopenharmony_ci	if (ctx->is_rfc4543) {
14018c2ecf20Sopenharmony_ci		/*
14028c2ecf20Sopenharmony_ci		 * RFC4543: data is included in AAD, so don't pad after AAD
14038c2ecf20Sopenharmony_ci		 * and pad data based on both AAD + data size
14048c2ecf20Sopenharmony_ci		 */
14058c2ecf20Sopenharmony_ci		aead_parms.aad_pad_len = 0;
14068c2ecf20Sopenharmony_ci		if (!rctx->is_encrypt)
14078c2ecf20Sopenharmony_ci			aead_parms.data_pad_len = spu->spu_gcm_ccm_pad_len(
14088c2ecf20Sopenharmony_ci					ctx->cipher.mode,
14098c2ecf20Sopenharmony_ci					aead_parms.assoc_size + chunksize -
14108c2ecf20Sopenharmony_ci					digestsize);
14118c2ecf20Sopenharmony_ci		else
14128c2ecf20Sopenharmony_ci			aead_parms.data_pad_len = spu->spu_gcm_ccm_pad_len(
14138c2ecf20Sopenharmony_ci					ctx->cipher.mode,
14148c2ecf20Sopenharmony_ci					aead_parms.assoc_size + chunksize);
14158c2ecf20Sopenharmony_ci
14168c2ecf20Sopenharmony_ci		req_opts.is_rfc4543 = true;
14178c2ecf20Sopenharmony_ci	}
14188c2ecf20Sopenharmony_ci
14198c2ecf20Sopenharmony_ci	if (spu_req_incl_icv(ctx->cipher.mode, rctx->is_encrypt)) {
14208c2ecf20Sopenharmony_ci		incl_icv = true;
14218c2ecf20Sopenharmony_ci		tx_frag_num++;
14228c2ecf20Sopenharmony_ci		/* Copy ICV from end of src scatterlist to digest buf */
14238c2ecf20Sopenharmony_ci		sg_copy_part_to_buf(req->src, rctx->msg_buf.digest, digestsize,
14248c2ecf20Sopenharmony_ci				    req->assoclen + rctx->total_sent -
14258c2ecf20Sopenharmony_ci				    digestsize);
14268c2ecf20Sopenharmony_ci	}
14278c2ecf20Sopenharmony_ci
14288c2ecf20Sopenharmony_ci	atomic64_add(chunksize, &iproc_priv.bytes_out);
14298c2ecf20Sopenharmony_ci
14308c2ecf20Sopenharmony_ci	flow_log("%s()-sent chunksize:%u\n", __func__, chunksize);
14318c2ecf20Sopenharmony_ci
14328c2ecf20Sopenharmony_ci	/* Prepend SPU header with type 3 BCM header */
14338c2ecf20Sopenharmony_ci	memcpy(rctx->msg_buf.bcm_spu_req_hdr, BCMHEADER, BCM_HDR_LEN);
14348c2ecf20Sopenharmony_ci
14358c2ecf20Sopenharmony_ci	spu_hdr_len = spu->spu_create_request(rctx->msg_buf.bcm_spu_req_hdr +
14368c2ecf20Sopenharmony_ci					      BCM_HDR_LEN, &req_opts,
14378c2ecf20Sopenharmony_ci					      &cipher_parms, &hash_parms,
14388c2ecf20Sopenharmony_ci					      &aead_parms, chunksize);
14398c2ecf20Sopenharmony_ci
14408c2ecf20Sopenharmony_ci	/* Determine total length of padding. Put all padding in one buffer. */
14418c2ecf20Sopenharmony_ci	db_size = spu_real_db_size(aead_parms.assoc_size, aead_parms.iv_len, 0,
14428c2ecf20Sopenharmony_ci				   chunksize, aead_parms.aad_pad_len,
14438c2ecf20Sopenharmony_ci				   aead_parms.data_pad_len, 0);
14448c2ecf20Sopenharmony_ci
14458c2ecf20Sopenharmony_ci	stat_pad_len = spu->spu_wordalign_padlen(db_size);
14468c2ecf20Sopenharmony_ci
14478c2ecf20Sopenharmony_ci	if (stat_pad_len)
14488c2ecf20Sopenharmony_ci		rx_frag_num++;
14498c2ecf20Sopenharmony_ci	pad_len = aead_parms.data_pad_len + stat_pad_len;
14508c2ecf20Sopenharmony_ci	if (pad_len) {
14518c2ecf20Sopenharmony_ci		tx_frag_num++;
14528c2ecf20Sopenharmony_ci		spu->spu_request_pad(rctx->msg_buf.spu_req_pad,
14538c2ecf20Sopenharmony_ci				     aead_parms.data_pad_len, 0,
14548c2ecf20Sopenharmony_ci				     ctx->auth.alg, ctx->auth.mode,
14558c2ecf20Sopenharmony_ci				     rctx->total_sent, stat_pad_len);
14568c2ecf20Sopenharmony_ci	}
14578c2ecf20Sopenharmony_ci
14588c2ecf20Sopenharmony_ci	spu->spu_dump_msg_hdr(rctx->msg_buf.bcm_spu_req_hdr + BCM_HDR_LEN,
14598c2ecf20Sopenharmony_ci			      spu_hdr_len);
14608c2ecf20Sopenharmony_ci	dump_sg(rctx->assoc, 0, aead_parms.assoc_size);
14618c2ecf20Sopenharmony_ci	packet_dump("    aead iv: ", rctx->msg_buf.iv_ctr, aead_parms.iv_len);
14628c2ecf20Sopenharmony_ci	packet_log("BD:\n");
14638c2ecf20Sopenharmony_ci	dump_sg(rctx->src_sg, rctx->src_skip, chunksize);
14648c2ecf20Sopenharmony_ci	packet_dump("   pad: ", rctx->msg_buf.spu_req_pad, pad_len);
14658c2ecf20Sopenharmony_ci
14668c2ecf20Sopenharmony_ci	/*
14678c2ecf20Sopenharmony_ci	 * Build mailbox message containing SPU request msg and rx buffers
14688c2ecf20Sopenharmony_ci	 * to catch response message
14698c2ecf20Sopenharmony_ci	 */
14708c2ecf20Sopenharmony_ci	memset(mssg, 0, sizeof(*mssg));
14718c2ecf20Sopenharmony_ci	mssg->type = BRCM_MESSAGE_SPU;
14728c2ecf20Sopenharmony_ci	mssg->ctx = rctx;	/* Will be returned in response */
14738c2ecf20Sopenharmony_ci
14748c2ecf20Sopenharmony_ci	/* Create rx scatterlist to catch result */
14758c2ecf20Sopenharmony_ci	rx_frag_num += rctx->dst_nents;
14768c2ecf20Sopenharmony_ci	resp_len = chunksize;
14778c2ecf20Sopenharmony_ci
14788c2ecf20Sopenharmony_ci	/*
14798c2ecf20Sopenharmony_ci	 * Always catch ICV in separate buffer. Have to for GCM/CCM because of
14808c2ecf20Sopenharmony_ci	 * padding. Have to for SHA-224 and other truncated SHAs because SPU
14818c2ecf20Sopenharmony_ci	 * sends entire digest back.
14828c2ecf20Sopenharmony_ci	 */
14838c2ecf20Sopenharmony_ci	rx_frag_num++;
14848c2ecf20Sopenharmony_ci
14858c2ecf20Sopenharmony_ci	if (((ctx->cipher.mode == CIPHER_MODE_GCM) ||
14868c2ecf20Sopenharmony_ci	     (ctx->cipher.mode == CIPHER_MODE_CCM)) && !rctx->is_encrypt) {
14878c2ecf20Sopenharmony_ci		/*
14888c2ecf20Sopenharmony_ci		 * Input is ciphertxt plus ICV, but ICV not incl
14898c2ecf20Sopenharmony_ci		 * in output.
14908c2ecf20Sopenharmony_ci		 */
14918c2ecf20Sopenharmony_ci		resp_len -= ctx->digestsize;
14928c2ecf20Sopenharmony_ci		if (resp_len == 0)
14938c2ecf20Sopenharmony_ci			/* no rx frags to catch output data */
14948c2ecf20Sopenharmony_ci			rx_frag_num -= rctx->dst_nents;
14958c2ecf20Sopenharmony_ci	}
14968c2ecf20Sopenharmony_ci
14978c2ecf20Sopenharmony_ci	err = spu_aead_rx_sg_create(mssg, req, rctx, rx_frag_num,
14988c2ecf20Sopenharmony_ci				    aead_parms.assoc_size,
14998c2ecf20Sopenharmony_ci				    aead_parms.ret_iv_len, resp_len, digestsize,
15008c2ecf20Sopenharmony_ci				    stat_pad_len);
15018c2ecf20Sopenharmony_ci	if (err)
15028c2ecf20Sopenharmony_ci		return err;
15038c2ecf20Sopenharmony_ci
15048c2ecf20Sopenharmony_ci	/* Create tx scatterlist containing SPU request message */
15058c2ecf20Sopenharmony_ci	tx_frag_num += rctx->src_nents;
15068c2ecf20Sopenharmony_ci	tx_frag_num += assoc_nents;
15078c2ecf20Sopenharmony_ci	if (aead_parms.aad_pad_len)
15088c2ecf20Sopenharmony_ci		tx_frag_num++;
15098c2ecf20Sopenharmony_ci	if (aead_parms.iv_len)
15108c2ecf20Sopenharmony_ci		tx_frag_num++;
15118c2ecf20Sopenharmony_ci	if (spu->spu_tx_status_len())
15128c2ecf20Sopenharmony_ci		tx_frag_num++;
15138c2ecf20Sopenharmony_ci	err = spu_aead_tx_sg_create(mssg, rctx, tx_frag_num, spu_hdr_len,
15148c2ecf20Sopenharmony_ci				    rctx->assoc, aead_parms.assoc_size,
15158c2ecf20Sopenharmony_ci				    assoc_nents, aead_parms.iv_len, chunksize,
15168c2ecf20Sopenharmony_ci				    aead_parms.aad_pad_len, pad_len, incl_icv);
15178c2ecf20Sopenharmony_ci	if (err)
15188c2ecf20Sopenharmony_ci		return err;
15198c2ecf20Sopenharmony_ci
15208c2ecf20Sopenharmony_ci	err = mailbox_send_message(mssg, req->base.flags, rctx->chan_idx);
15218c2ecf20Sopenharmony_ci	if (unlikely(err < 0))
15228c2ecf20Sopenharmony_ci		return err;
15238c2ecf20Sopenharmony_ci
15248c2ecf20Sopenharmony_ci	return -EINPROGRESS;
15258c2ecf20Sopenharmony_ci}
15268c2ecf20Sopenharmony_ci
15278c2ecf20Sopenharmony_ci/**
15288c2ecf20Sopenharmony_ci * handle_aead_resp() - Process a SPU response message for an AEAD request.
15298c2ecf20Sopenharmony_ci * @rctx:  Crypto request context
15308c2ecf20Sopenharmony_ci */
15318c2ecf20Sopenharmony_cistatic void handle_aead_resp(struct iproc_reqctx_s *rctx)
15328c2ecf20Sopenharmony_ci{
15338c2ecf20Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
15348c2ecf20Sopenharmony_ci	struct crypto_async_request *areq = rctx->parent;
15358c2ecf20Sopenharmony_ci	struct aead_request *req = container_of(areq,
15368c2ecf20Sopenharmony_ci						struct aead_request, base);
15378c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = rctx->ctx;
15388c2ecf20Sopenharmony_ci	u32 payload_len;
15398c2ecf20Sopenharmony_ci	unsigned int icv_offset;
15408c2ecf20Sopenharmony_ci	u32 result_len;
15418c2ecf20Sopenharmony_ci
15428c2ecf20Sopenharmony_ci	/* See how much data was returned */
15438c2ecf20Sopenharmony_ci	payload_len = spu->spu_payload_length(rctx->msg_buf.spu_resp_hdr);
15448c2ecf20Sopenharmony_ci	flow_log("payload_len %u\n", payload_len);
15458c2ecf20Sopenharmony_ci
15468c2ecf20Sopenharmony_ci	/* only count payload */
15478c2ecf20Sopenharmony_ci	atomic64_add(payload_len, &iproc_priv.bytes_in);
15488c2ecf20Sopenharmony_ci
15498c2ecf20Sopenharmony_ci	if (req->assoclen)
15508c2ecf20Sopenharmony_ci		packet_dump("  assoc_data ", rctx->msg_buf.a.resp_aad,
15518c2ecf20Sopenharmony_ci			    req->assoclen);
15528c2ecf20Sopenharmony_ci
15538c2ecf20Sopenharmony_ci	/*
15548c2ecf20Sopenharmony_ci	 * Copy the ICV back to the destination
15558c2ecf20Sopenharmony_ci	 * buffer. In decrypt case, SPU gives us back the digest, but crypto
15568c2ecf20Sopenharmony_ci	 * API doesn't expect ICV in dst buffer.
15578c2ecf20Sopenharmony_ci	 */
15588c2ecf20Sopenharmony_ci	result_len = req->cryptlen;
15598c2ecf20Sopenharmony_ci	if (rctx->is_encrypt) {
15608c2ecf20Sopenharmony_ci		icv_offset = req->assoclen + rctx->total_sent;
15618c2ecf20Sopenharmony_ci		packet_dump("  ICV: ", rctx->msg_buf.digest, ctx->digestsize);
15628c2ecf20Sopenharmony_ci		flow_log("copying ICV to dst sg at offset %u\n", icv_offset);
15638c2ecf20Sopenharmony_ci		sg_copy_part_from_buf(req->dst, rctx->msg_buf.digest,
15648c2ecf20Sopenharmony_ci				      ctx->digestsize, icv_offset);
15658c2ecf20Sopenharmony_ci		result_len += ctx->digestsize;
15668c2ecf20Sopenharmony_ci	}
15678c2ecf20Sopenharmony_ci
15688c2ecf20Sopenharmony_ci	packet_log("response data:  ");
15698c2ecf20Sopenharmony_ci	dump_sg(req->dst, req->assoclen, result_len);
15708c2ecf20Sopenharmony_ci
15718c2ecf20Sopenharmony_ci	atomic_inc(&iproc_priv.op_counts[SPU_OP_AEAD]);
15728c2ecf20Sopenharmony_ci	if (ctx->cipher.alg == CIPHER_ALG_AES) {
15738c2ecf20Sopenharmony_ci		if (ctx->cipher.mode == CIPHER_MODE_CCM)
15748c2ecf20Sopenharmony_ci			atomic_inc(&iproc_priv.aead_cnt[AES_CCM]);
15758c2ecf20Sopenharmony_ci		else if (ctx->cipher.mode == CIPHER_MODE_GCM)
15768c2ecf20Sopenharmony_ci			atomic_inc(&iproc_priv.aead_cnt[AES_GCM]);
15778c2ecf20Sopenharmony_ci		else
15788c2ecf20Sopenharmony_ci			atomic_inc(&iproc_priv.aead_cnt[AUTHENC]);
15798c2ecf20Sopenharmony_ci	} else {
15808c2ecf20Sopenharmony_ci		atomic_inc(&iproc_priv.aead_cnt[AUTHENC]);
15818c2ecf20Sopenharmony_ci	}
15828c2ecf20Sopenharmony_ci}
15838c2ecf20Sopenharmony_ci
15848c2ecf20Sopenharmony_ci/**
15858c2ecf20Sopenharmony_ci * spu_chunk_cleanup() - Do cleanup after processing one chunk of a request
15868c2ecf20Sopenharmony_ci * @rctx:  request context
15878c2ecf20Sopenharmony_ci *
15888c2ecf20Sopenharmony_ci * Mailbox scatterlists are allocated for each chunk. So free them after
15898c2ecf20Sopenharmony_ci * processing each chunk.
15908c2ecf20Sopenharmony_ci */
15918c2ecf20Sopenharmony_cistatic void spu_chunk_cleanup(struct iproc_reqctx_s *rctx)
15928c2ecf20Sopenharmony_ci{
15938c2ecf20Sopenharmony_ci	/* mailbox message used to tx request */
15948c2ecf20Sopenharmony_ci	struct brcm_message *mssg = &rctx->mb_mssg;
15958c2ecf20Sopenharmony_ci
15968c2ecf20Sopenharmony_ci	kfree(mssg->spu.src);
15978c2ecf20Sopenharmony_ci	kfree(mssg->spu.dst);
15988c2ecf20Sopenharmony_ci	memset(mssg, 0, sizeof(struct brcm_message));
15998c2ecf20Sopenharmony_ci}
16008c2ecf20Sopenharmony_ci
16018c2ecf20Sopenharmony_ci/**
16028c2ecf20Sopenharmony_ci * finish_req() - Used to invoke the complete callback from the requester when
16038c2ecf20Sopenharmony_ci * a request has been handled asynchronously.
16048c2ecf20Sopenharmony_ci * @rctx:  Request context
16058c2ecf20Sopenharmony_ci * @err:   Indicates whether the request was successful or not
16068c2ecf20Sopenharmony_ci *
16078c2ecf20Sopenharmony_ci * Ensures that cleanup has been done for request
16088c2ecf20Sopenharmony_ci */
16098c2ecf20Sopenharmony_cistatic void finish_req(struct iproc_reqctx_s *rctx, int err)
16108c2ecf20Sopenharmony_ci{
16118c2ecf20Sopenharmony_ci	struct crypto_async_request *areq = rctx->parent;
16128c2ecf20Sopenharmony_ci
16138c2ecf20Sopenharmony_ci	flow_log("%s() err:%d\n\n", __func__, err);
16148c2ecf20Sopenharmony_ci
16158c2ecf20Sopenharmony_ci	/* No harm done if already called */
16168c2ecf20Sopenharmony_ci	spu_chunk_cleanup(rctx);
16178c2ecf20Sopenharmony_ci
16188c2ecf20Sopenharmony_ci	if (areq)
16198c2ecf20Sopenharmony_ci		areq->complete(areq, err);
16208c2ecf20Sopenharmony_ci}
16218c2ecf20Sopenharmony_ci
16228c2ecf20Sopenharmony_ci/**
16238c2ecf20Sopenharmony_ci * spu_rx_callback() - Callback from mailbox framework with a SPU response.
16248c2ecf20Sopenharmony_ci * @cl:		mailbox client structure for SPU driver
16258c2ecf20Sopenharmony_ci * @msg:	mailbox message containing SPU response
16268c2ecf20Sopenharmony_ci */
16278c2ecf20Sopenharmony_cistatic void spu_rx_callback(struct mbox_client *cl, void *msg)
16288c2ecf20Sopenharmony_ci{
16298c2ecf20Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
16308c2ecf20Sopenharmony_ci	struct brcm_message *mssg = msg;
16318c2ecf20Sopenharmony_ci	struct iproc_reqctx_s *rctx;
16328c2ecf20Sopenharmony_ci	int err;
16338c2ecf20Sopenharmony_ci
16348c2ecf20Sopenharmony_ci	rctx = mssg->ctx;
16358c2ecf20Sopenharmony_ci	if (unlikely(!rctx)) {
16368c2ecf20Sopenharmony_ci		/* This is fatal */
16378c2ecf20Sopenharmony_ci		pr_err("%s(): no request context", __func__);
16388c2ecf20Sopenharmony_ci		err = -EFAULT;
16398c2ecf20Sopenharmony_ci		goto cb_finish;
16408c2ecf20Sopenharmony_ci	}
16418c2ecf20Sopenharmony_ci
16428c2ecf20Sopenharmony_ci	/* process the SPU status */
16438c2ecf20Sopenharmony_ci	err = spu->spu_status_process(rctx->msg_buf.rx_stat);
16448c2ecf20Sopenharmony_ci	if (err != 0) {
16458c2ecf20Sopenharmony_ci		if (err == SPU_INVALID_ICV)
16468c2ecf20Sopenharmony_ci			atomic_inc(&iproc_priv.bad_icv);
16478c2ecf20Sopenharmony_ci		err = -EBADMSG;
16488c2ecf20Sopenharmony_ci		goto cb_finish;
16498c2ecf20Sopenharmony_ci	}
16508c2ecf20Sopenharmony_ci
16518c2ecf20Sopenharmony_ci	/* Process the SPU response message */
16528c2ecf20Sopenharmony_ci	switch (rctx->ctx->alg->type) {
16538c2ecf20Sopenharmony_ci	case CRYPTO_ALG_TYPE_SKCIPHER:
16548c2ecf20Sopenharmony_ci		handle_skcipher_resp(rctx);
16558c2ecf20Sopenharmony_ci		break;
16568c2ecf20Sopenharmony_ci	case CRYPTO_ALG_TYPE_AHASH:
16578c2ecf20Sopenharmony_ci		handle_ahash_resp(rctx);
16588c2ecf20Sopenharmony_ci		break;
16598c2ecf20Sopenharmony_ci	case CRYPTO_ALG_TYPE_AEAD:
16608c2ecf20Sopenharmony_ci		handle_aead_resp(rctx);
16618c2ecf20Sopenharmony_ci		break;
16628c2ecf20Sopenharmony_ci	default:
16638c2ecf20Sopenharmony_ci		err = -EINVAL;
16648c2ecf20Sopenharmony_ci		goto cb_finish;
16658c2ecf20Sopenharmony_ci	}
16668c2ecf20Sopenharmony_ci
16678c2ecf20Sopenharmony_ci	/*
16688c2ecf20Sopenharmony_ci	 * If this response does not complete the request, then send the next
16698c2ecf20Sopenharmony_ci	 * request chunk.
16708c2ecf20Sopenharmony_ci	 */
16718c2ecf20Sopenharmony_ci	if (rctx->total_sent < rctx->total_todo) {
16728c2ecf20Sopenharmony_ci		/* Deallocate anything specific to previous chunk */
16738c2ecf20Sopenharmony_ci		spu_chunk_cleanup(rctx);
16748c2ecf20Sopenharmony_ci
16758c2ecf20Sopenharmony_ci		switch (rctx->ctx->alg->type) {
16768c2ecf20Sopenharmony_ci		case CRYPTO_ALG_TYPE_SKCIPHER:
16778c2ecf20Sopenharmony_ci			err = handle_skcipher_req(rctx);
16788c2ecf20Sopenharmony_ci			break;
16798c2ecf20Sopenharmony_ci		case CRYPTO_ALG_TYPE_AHASH:
16808c2ecf20Sopenharmony_ci			err = handle_ahash_req(rctx);
16818c2ecf20Sopenharmony_ci			if (err == -EAGAIN)
16828c2ecf20Sopenharmony_ci				/*
16838c2ecf20Sopenharmony_ci				 * we saved data in hash carry, but tell crypto
16848c2ecf20Sopenharmony_ci				 * API we successfully completed request.
16858c2ecf20Sopenharmony_ci				 */
16868c2ecf20Sopenharmony_ci				err = 0;
16878c2ecf20Sopenharmony_ci			break;
16888c2ecf20Sopenharmony_ci		case CRYPTO_ALG_TYPE_AEAD:
16898c2ecf20Sopenharmony_ci			err = handle_aead_req(rctx);
16908c2ecf20Sopenharmony_ci			break;
16918c2ecf20Sopenharmony_ci		default:
16928c2ecf20Sopenharmony_ci			err = -EINVAL;
16938c2ecf20Sopenharmony_ci		}
16948c2ecf20Sopenharmony_ci
16958c2ecf20Sopenharmony_ci		if (err == -EINPROGRESS)
16968c2ecf20Sopenharmony_ci			/* Successfully submitted request for next chunk */
16978c2ecf20Sopenharmony_ci			return;
16988c2ecf20Sopenharmony_ci	}
16998c2ecf20Sopenharmony_ci
17008c2ecf20Sopenharmony_cicb_finish:
17018c2ecf20Sopenharmony_ci	finish_req(rctx, err);
17028c2ecf20Sopenharmony_ci}
17038c2ecf20Sopenharmony_ci
17048c2ecf20Sopenharmony_ci/* ==================== Kernel Cryptographic API ==================== */
17058c2ecf20Sopenharmony_ci
17068c2ecf20Sopenharmony_ci/**
17078c2ecf20Sopenharmony_ci * skcipher_enqueue() - Handle skcipher encrypt or decrypt request.
17088c2ecf20Sopenharmony_ci * @req:	Crypto API request
17098c2ecf20Sopenharmony_ci * @encrypt:	true if encrypting; false if decrypting
17108c2ecf20Sopenharmony_ci *
17118c2ecf20Sopenharmony_ci * Return: -EINPROGRESS if request accepted and result will be returned
17128c2ecf20Sopenharmony_ci *			asynchronously
17138c2ecf20Sopenharmony_ci *	   < 0 if an error
17148c2ecf20Sopenharmony_ci */
17158c2ecf20Sopenharmony_cistatic int skcipher_enqueue(struct skcipher_request *req, bool encrypt)
17168c2ecf20Sopenharmony_ci{
17178c2ecf20Sopenharmony_ci	struct iproc_reqctx_s *rctx = skcipher_request_ctx(req);
17188c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx =
17198c2ecf20Sopenharmony_ci	    crypto_skcipher_ctx(crypto_skcipher_reqtfm(req));
17208c2ecf20Sopenharmony_ci	int err;
17218c2ecf20Sopenharmony_ci
17228c2ecf20Sopenharmony_ci	flow_log("%s() enc:%u\n", __func__, encrypt);
17238c2ecf20Sopenharmony_ci
17248c2ecf20Sopenharmony_ci	rctx->gfp = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
17258c2ecf20Sopenharmony_ci		       CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
17268c2ecf20Sopenharmony_ci	rctx->parent = &req->base;
17278c2ecf20Sopenharmony_ci	rctx->is_encrypt = encrypt;
17288c2ecf20Sopenharmony_ci	rctx->bd_suppress = false;
17298c2ecf20Sopenharmony_ci	rctx->total_todo = req->cryptlen;
17308c2ecf20Sopenharmony_ci	rctx->src_sent = 0;
17318c2ecf20Sopenharmony_ci	rctx->total_sent = 0;
17328c2ecf20Sopenharmony_ci	rctx->total_received = 0;
17338c2ecf20Sopenharmony_ci	rctx->ctx = ctx;
17348c2ecf20Sopenharmony_ci
17358c2ecf20Sopenharmony_ci	/* Initialize current position in src and dst scatterlists */
17368c2ecf20Sopenharmony_ci	rctx->src_sg = req->src;
17378c2ecf20Sopenharmony_ci	rctx->src_nents = 0;
17388c2ecf20Sopenharmony_ci	rctx->src_skip = 0;
17398c2ecf20Sopenharmony_ci	rctx->dst_sg = req->dst;
17408c2ecf20Sopenharmony_ci	rctx->dst_nents = 0;
17418c2ecf20Sopenharmony_ci	rctx->dst_skip = 0;
17428c2ecf20Sopenharmony_ci
17438c2ecf20Sopenharmony_ci	if (ctx->cipher.mode == CIPHER_MODE_CBC ||
17448c2ecf20Sopenharmony_ci	    ctx->cipher.mode == CIPHER_MODE_CTR ||
17458c2ecf20Sopenharmony_ci	    ctx->cipher.mode == CIPHER_MODE_OFB ||
17468c2ecf20Sopenharmony_ci	    ctx->cipher.mode == CIPHER_MODE_XTS ||
17478c2ecf20Sopenharmony_ci	    ctx->cipher.mode == CIPHER_MODE_GCM ||
17488c2ecf20Sopenharmony_ci	    ctx->cipher.mode == CIPHER_MODE_CCM) {
17498c2ecf20Sopenharmony_ci		rctx->iv_ctr_len =
17508c2ecf20Sopenharmony_ci		    crypto_skcipher_ivsize(crypto_skcipher_reqtfm(req));
17518c2ecf20Sopenharmony_ci		memcpy(rctx->msg_buf.iv_ctr, req->iv, rctx->iv_ctr_len);
17528c2ecf20Sopenharmony_ci	} else {
17538c2ecf20Sopenharmony_ci		rctx->iv_ctr_len = 0;
17548c2ecf20Sopenharmony_ci	}
17558c2ecf20Sopenharmony_ci
17568c2ecf20Sopenharmony_ci	/* Choose a SPU to process this request */
17578c2ecf20Sopenharmony_ci	rctx->chan_idx = select_channel();
17588c2ecf20Sopenharmony_ci	err = handle_skcipher_req(rctx);
17598c2ecf20Sopenharmony_ci	if (err != -EINPROGRESS)
17608c2ecf20Sopenharmony_ci		/* synchronous result */
17618c2ecf20Sopenharmony_ci		spu_chunk_cleanup(rctx);
17628c2ecf20Sopenharmony_ci
17638c2ecf20Sopenharmony_ci	return err;
17648c2ecf20Sopenharmony_ci}
17658c2ecf20Sopenharmony_ci
17668c2ecf20Sopenharmony_cistatic int des_setkey(struct crypto_skcipher *cipher, const u8 *key,
17678c2ecf20Sopenharmony_ci		      unsigned int keylen)
17688c2ecf20Sopenharmony_ci{
17698c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_skcipher_ctx(cipher);
17708c2ecf20Sopenharmony_ci	int err;
17718c2ecf20Sopenharmony_ci
17728c2ecf20Sopenharmony_ci	err = verify_skcipher_des_key(cipher, key);
17738c2ecf20Sopenharmony_ci	if (err)
17748c2ecf20Sopenharmony_ci		return err;
17758c2ecf20Sopenharmony_ci
17768c2ecf20Sopenharmony_ci	ctx->cipher_type = CIPHER_TYPE_DES;
17778c2ecf20Sopenharmony_ci	return 0;
17788c2ecf20Sopenharmony_ci}
17798c2ecf20Sopenharmony_ci
17808c2ecf20Sopenharmony_cistatic int threedes_setkey(struct crypto_skcipher *cipher, const u8 *key,
17818c2ecf20Sopenharmony_ci			   unsigned int keylen)
17828c2ecf20Sopenharmony_ci{
17838c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_skcipher_ctx(cipher);
17848c2ecf20Sopenharmony_ci	int err;
17858c2ecf20Sopenharmony_ci
17868c2ecf20Sopenharmony_ci	err = verify_skcipher_des3_key(cipher, key);
17878c2ecf20Sopenharmony_ci	if (err)
17888c2ecf20Sopenharmony_ci		return err;
17898c2ecf20Sopenharmony_ci
17908c2ecf20Sopenharmony_ci	ctx->cipher_type = CIPHER_TYPE_3DES;
17918c2ecf20Sopenharmony_ci	return 0;
17928c2ecf20Sopenharmony_ci}
17938c2ecf20Sopenharmony_ci
17948c2ecf20Sopenharmony_cistatic int aes_setkey(struct crypto_skcipher *cipher, const u8 *key,
17958c2ecf20Sopenharmony_ci		      unsigned int keylen)
17968c2ecf20Sopenharmony_ci{
17978c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_skcipher_ctx(cipher);
17988c2ecf20Sopenharmony_ci
17998c2ecf20Sopenharmony_ci	if (ctx->cipher.mode == CIPHER_MODE_XTS)
18008c2ecf20Sopenharmony_ci		/* XTS includes two keys of equal length */
18018c2ecf20Sopenharmony_ci		keylen = keylen / 2;
18028c2ecf20Sopenharmony_ci
18038c2ecf20Sopenharmony_ci	switch (keylen) {
18048c2ecf20Sopenharmony_ci	case AES_KEYSIZE_128:
18058c2ecf20Sopenharmony_ci		ctx->cipher_type = CIPHER_TYPE_AES128;
18068c2ecf20Sopenharmony_ci		break;
18078c2ecf20Sopenharmony_ci	case AES_KEYSIZE_192:
18088c2ecf20Sopenharmony_ci		ctx->cipher_type = CIPHER_TYPE_AES192;
18098c2ecf20Sopenharmony_ci		break;
18108c2ecf20Sopenharmony_ci	case AES_KEYSIZE_256:
18118c2ecf20Sopenharmony_ci		ctx->cipher_type = CIPHER_TYPE_AES256;
18128c2ecf20Sopenharmony_ci		break;
18138c2ecf20Sopenharmony_ci	default:
18148c2ecf20Sopenharmony_ci		return -EINVAL;
18158c2ecf20Sopenharmony_ci	}
18168c2ecf20Sopenharmony_ci	WARN_ON((ctx->max_payload != SPU_MAX_PAYLOAD_INF) &&
18178c2ecf20Sopenharmony_ci		((ctx->max_payload % AES_BLOCK_SIZE) != 0));
18188c2ecf20Sopenharmony_ci	return 0;
18198c2ecf20Sopenharmony_ci}
18208c2ecf20Sopenharmony_ci
18218c2ecf20Sopenharmony_cistatic int skcipher_setkey(struct crypto_skcipher *cipher, const u8 *key,
18228c2ecf20Sopenharmony_ci			     unsigned int keylen)
18238c2ecf20Sopenharmony_ci{
18248c2ecf20Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
18258c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_skcipher_ctx(cipher);
18268c2ecf20Sopenharmony_ci	struct spu_cipher_parms cipher_parms;
18278c2ecf20Sopenharmony_ci	u32 alloc_len = 0;
18288c2ecf20Sopenharmony_ci	int err;
18298c2ecf20Sopenharmony_ci
18308c2ecf20Sopenharmony_ci	flow_log("skcipher_setkey() keylen: %d\n", keylen);
18318c2ecf20Sopenharmony_ci	flow_dump("  key: ", key, keylen);
18328c2ecf20Sopenharmony_ci
18338c2ecf20Sopenharmony_ci	switch (ctx->cipher.alg) {
18348c2ecf20Sopenharmony_ci	case CIPHER_ALG_DES:
18358c2ecf20Sopenharmony_ci		err = des_setkey(cipher, key, keylen);
18368c2ecf20Sopenharmony_ci		break;
18378c2ecf20Sopenharmony_ci	case CIPHER_ALG_3DES:
18388c2ecf20Sopenharmony_ci		err = threedes_setkey(cipher, key, keylen);
18398c2ecf20Sopenharmony_ci		break;
18408c2ecf20Sopenharmony_ci	case CIPHER_ALG_AES:
18418c2ecf20Sopenharmony_ci		err = aes_setkey(cipher, key, keylen);
18428c2ecf20Sopenharmony_ci		break;
18438c2ecf20Sopenharmony_ci	default:
18448c2ecf20Sopenharmony_ci		pr_err("%s() Error: unknown cipher alg\n", __func__);
18458c2ecf20Sopenharmony_ci		err = -EINVAL;
18468c2ecf20Sopenharmony_ci	}
18478c2ecf20Sopenharmony_ci	if (err)
18488c2ecf20Sopenharmony_ci		return err;
18498c2ecf20Sopenharmony_ci
18508c2ecf20Sopenharmony_ci	memcpy(ctx->enckey, key, keylen);
18518c2ecf20Sopenharmony_ci	ctx->enckeylen = keylen;
18528c2ecf20Sopenharmony_ci
18538c2ecf20Sopenharmony_ci	/* SPU needs XTS keys in the reverse order the crypto API presents */
18548c2ecf20Sopenharmony_ci	if ((ctx->cipher.alg == CIPHER_ALG_AES) &&
18558c2ecf20Sopenharmony_ci	    (ctx->cipher.mode == CIPHER_MODE_XTS)) {
18568c2ecf20Sopenharmony_ci		unsigned int xts_keylen = keylen / 2;
18578c2ecf20Sopenharmony_ci
18588c2ecf20Sopenharmony_ci		memcpy(ctx->enckey, key + xts_keylen, xts_keylen);
18598c2ecf20Sopenharmony_ci		memcpy(ctx->enckey + xts_keylen, key, xts_keylen);
18608c2ecf20Sopenharmony_ci	}
18618c2ecf20Sopenharmony_ci
18628c2ecf20Sopenharmony_ci	if (spu->spu_type == SPU_TYPE_SPUM)
18638c2ecf20Sopenharmony_ci		alloc_len = BCM_HDR_LEN + SPU_HEADER_ALLOC_LEN;
18648c2ecf20Sopenharmony_ci	else if (spu->spu_type == SPU_TYPE_SPU2)
18658c2ecf20Sopenharmony_ci		alloc_len = BCM_HDR_LEN + SPU2_HEADER_ALLOC_LEN;
18668c2ecf20Sopenharmony_ci	memset(ctx->bcm_spu_req_hdr, 0, alloc_len);
18678c2ecf20Sopenharmony_ci	cipher_parms.iv_buf = NULL;
18688c2ecf20Sopenharmony_ci	cipher_parms.iv_len = crypto_skcipher_ivsize(cipher);
18698c2ecf20Sopenharmony_ci	flow_log("%s: iv_len %u\n", __func__, cipher_parms.iv_len);
18708c2ecf20Sopenharmony_ci
18718c2ecf20Sopenharmony_ci	cipher_parms.alg = ctx->cipher.alg;
18728c2ecf20Sopenharmony_ci	cipher_parms.mode = ctx->cipher.mode;
18738c2ecf20Sopenharmony_ci	cipher_parms.type = ctx->cipher_type;
18748c2ecf20Sopenharmony_ci	cipher_parms.key_buf = ctx->enckey;
18758c2ecf20Sopenharmony_ci	cipher_parms.key_len = ctx->enckeylen;
18768c2ecf20Sopenharmony_ci
18778c2ecf20Sopenharmony_ci	/* Prepend SPU request message with BCM header */
18788c2ecf20Sopenharmony_ci	memcpy(ctx->bcm_spu_req_hdr, BCMHEADER, BCM_HDR_LEN);
18798c2ecf20Sopenharmony_ci	ctx->spu_req_hdr_len =
18808c2ecf20Sopenharmony_ci	    spu->spu_cipher_req_init(ctx->bcm_spu_req_hdr + BCM_HDR_LEN,
18818c2ecf20Sopenharmony_ci				     &cipher_parms);
18828c2ecf20Sopenharmony_ci
18838c2ecf20Sopenharmony_ci	ctx->spu_resp_hdr_len = spu->spu_response_hdr_len(ctx->authkeylen,
18848c2ecf20Sopenharmony_ci							  ctx->enckeylen,
18858c2ecf20Sopenharmony_ci							  false);
18868c2ecf20Sopenharmony_ci
18878c2ecf20Sopenharmony_ci	atomic_inc(&iproc_priv.setkey_cnt[SPU_OP_CIPHER]);
18888c2ecf20Sopenharmony_ci
18898c2ecf20Sopenharmony_ci	return 0;
18908c2ecf20Sopenharmony_ci}
18918c2ecf20Sopenharmony_ci
18928c2ecf20Sopenharmony_cistatic int skcipher_encrypt(struct skcipher_request *req)
18938c2ecf20Sopenharmony_ci{
18948c2ecf20Sopenharmony_ci	flow_log("skcipher_encrypt() nbytes:%u\n", req->cryptlen);
18958c2ecf20Sopenharmony_ci
18968c2ecf20Sopenharmony_ci	return skcipher_enqueue(req, true);
18978c2ecf20Sopenharmony_ci}
18988c2ecf20Sopenharmony_ci
18998c2ecf20Sopenharmony_cistatic int skcipher_decrypt(struct skcipher_request *req)
19008c2ecf20Sopenharmony_ci{
19018c2ecf20Sopenharmony_ci	flow_log("skcipher_decrypt() nbytes:%u\n", req->cryptlen);
19028c2ecf20Sopenharmony_ci	return skcipher_enqueue(req, false);
19038c2ecf20Sopenharmony_ci}
19048c2ecf20Sopenharmony_ci
19058c2ecf20Sopenharmony_cistatic int ahash_enqueue(struct ahash_request *req)
19068c2ecf20Sopenharmony_ci{
19078c2ecf20Sopenharmony_ci	struct iproc_reqctx_s *rctx = ahash_request_ctx(req);
19088c2ecf20Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
19098c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm);
19108c2ecf20Sopenharmony_ci	int err;
19118c2ecf20Sopenharmony_ci	const char *alg_name;
19128c2ecf20Sopenharmony_ci
19138c2ecf20Sopenharmony_ci	flow_log("ahash_enqueue() nbytes:%u\n", req->nbytes);
19148c2ecf20Sopenharmony_ci
19158c2ecf20Sopenharmony_ci	rctx->gfp = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
19168c2ecf20Sopenharmony_ci		       CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
19178c2ecf20Sopenharmony_ci	rctx->parent = &req->base;
19188c2ecf20Sopenharmony_ci	rctx->ctx = ctx;
19198c2ecf20Sopenharmony_ci	rctx->bd_suppress = true;
19208c2ecf20Sopenharmony_ci	memset(&rctx->mb_mssg, 0, sizeof(struct brcm_message));
19218c2ecf20Sopenharmony_ci
19228c2ecf20Sopenharmony_ci	/* Initialize position in src scatterlist */
19238c2ecf20Sopenharmony_ci	rctx->src_sg = req->src;
19248c2ecf20Sopenharmony_ci	rctx->src_skip = 0;
19258c2ecf20Sopenharmony_ci	rctx->src_nents = 0;
19268c2ecf20Sopenharmony_ci	rctx->dst_sg = NULL;
19278c2ecf20Sopenharmony_ci	rctx->dst_skip = 0;
19288c2ecf20Sopenharmony_ci	rctx->dst_nents = 0;
19298c2ecf20Sopenharmony_ci
19308c2ecf20Sopenharmony_ci	/* SPU2 hardware does not compute hash of zero length data */
19318c2ecf20Sopenharmony_ci	if ((rctx->is_final == 1) && (rctx->total_todo == 0) &&
19328c2ecf20Sopenharmony_ci	    (iproc_priv.spu.spu_type == SPU_TYPE_SPU2)) {
19338c2ecf20Sopenharmony_ci		alg_name = crypto_tfm_alg_name(crypto_ahash_tfm(tfm));
19348c2ecf20Sopenharmony_ci		flow_log("Doing %sfinal %s zero-len hash request in software\n",
19358c2ecf20Sopenharmony_ci			 rctx->is_final ? "" : "non-", alg_name);
19368c2ecf20Sopenharmony_ci		err = do_shash((unsigned char *)alg_name, req->result,
19378c2ecf20Sopenharmony_ci			       NULL, 0, NULL, 0, ctx->authkey,
19388c2ecf20Sopenharmony_ci			       ctx->authkeylen);
19398c2ecf20Sopenharmony_ci		if (err < 0)
19408c2ecf20Sopenharmony_ci			flow_log("Hash request failed with error %d\n", err);
19418c2ecf20Sopenharmony_ci		return err;
19428c2ecf20Sopenharmony_ci	}
19438c2ecf20Sopenharmony_ci	/* Choose a SPU to process this request */
19448c2ecf20Sopenharmony_ci	rctx->chan_idx = select_channel();
19458c2ecf20Sopenharmony_ci
19468c2ecf20Sopenharmony_ci	err = handle_ahash_req(rctx);
19478c2ecf20Sopenharmony_ci	if (err != -EINPROGRESS)
19488c2ecf20Sopenharmony_ci		/* synchronous result */
19498c2ecf20Sopenharmony_ci		spu_chunk_cleanup(rctx);
19508c2ecf20Sopenharmony_ci
19518c2ecf20Sopenharmony_ci	if (err == -EAGAIN)
19528c2ecf20Sopenharmony_ci		/*
19538c2ecf20Sopenharmony_ci		 * we saved data in hash carry, but tell crypto API
19548c2ecf20Sopenharmony_ci		 * we successfully completed request.
19558c2ecf20Sopenharmony_ci		 */
19568c2ecf20Sopenharmony_ci		err = 0;
19578c2ecf20Sopenharmony_ci
19588c2ecf20Sopenharmony_ci	return err;
19598c2ecf20Sopenharmony_ci}
19608c2ecf20Sopenharmony_ci
19618c2ecf20Sopenharmony_cistatic int __ahash_init(struct ahash_request *req)
19628c2ecf20Sopenharmony_ci{
19638c2ecf20Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
19648c2ecf20Sopenharmony_ci	struct iproc_reqctx_s *rctx = ahash_request_ctx(req);
19658c2ecf20Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
19668c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm);
19678c2ecf20Sopenharmony_ci
19688c2ecf20Sopenharmony_ci	flow_log("%s()\n", __func__);
19698c2ecf20Sopenharmony_ci
19708c2ecf20Sopenharmony_ci	/* Initialize the context */
19718c2ecf20Sopenharmony_ci	rctx->hash_carry_len = 0;
19728c2ecf20Sopenharmony_ci	rctx->is_final = 0;
19738c2ecf20Sopenharmony_ci
19748c2ecf20Sopenharmony_ci	rctx->total_todo = 0;
19758c2ecf20Sopenharmony_ci	rctx->src_sent = 0;
19768c2ecf20Sopenharmony_ci	rctx->total_sent = 0;
19778c2ecf20Sopenharmony_ci	rctx->total_received = 0;
19788c2ecf20Sopenharmony_ci
19798c2ecf20Sopenharmony_ci	ctx->digestsize = crypto_ahash_digestsize(tfm);
19808c2ecf20Sopenharmony_ci	/* If we add a hash whose digest is larger, catch it here. */
19818c2ecf20Sopenharmony_ci	WARN_ON(ctx->digestsize > MAX_DIGEST_SIZE);
19828c2ecf20Sopenharmony_ci
19838c2ecf20Sopenharmony_ci	rctx->is_sw_hmac = false;
19848c2ecf20Sopenharmony_ci
19858c2ecf20Sopenharmony_ci	ctx->spu_resp_hdr_len = spu->spu_response_hdr_len(ctx->authkeylen, 0,
19868c2ecf20Sopenharmony_ci							  true);
19878c2ecf20Sopenharmony_ci
19888c2ecf20Sopenharmony_ci	return 0;
19898c2ecf20Sopenharmony_ci}
19908c2ecf20Sopenharmony_ci
19918c2ecf20Sopenharmony_ci/**
19928c2ecf20Sopenharmony_ci * spu_no_incr_hash() - Determine whether incremental hashing is supported.
19938c2ecf20Sopenharmony_ci * @ctx:  Crypto session context
19948c2ecf20Sopenharmony_ci *
19958c2ecf20Sopenharmony_ci * SPU-2 does not support incremental hashing (we'll have to revisit and
19968c2ecf20Sopenharmony_ci * condition based on chip revision or device tree entry if future versions do
19978c2ecf20Sopenharmony_ci * support incremental hash)
19988c2ecf20Sopenharmony_ci *
19998c2ecf20Sopenharmony_ci * SPU-M also doesn't support incremental hashing of AES-XCBC
20008c2ecf20Sopenharmony_ci *
20018c2ecf20Sopenharmony_ci * Return: true if incremental hashing is not supported
20028c2ecf20Sopenharmony_ci *         false otherwise
20038c2ecf20Sopenharmony_ci */
20048c2ecf20Sopenharmony_cistatic bool spu_no_incr_hash(struct iproc_ctx_s *ctx)
20058c2ecf20Sopenharmony_ci{
20068c2ecf20Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
20078c2ecf20Sopenharmony_ci
20088c2ecf20Sopenharmony_ci	if (spu->spu_type == SPU_TYPE_SPU2)
20098c2ecf20Sopenharmony_ci		return true;
20108c2ecf20Sopenharmony_ci
20118c2ecf20Sopenharmony_ci	if ((ctx->auth.alg == HASH_ALG_AES) &&
20128c2ecf20Sopenharmony_ci	    (ctx->auth.mode == HASH_MODE_XCBC))
20138c2ecf20Sopenharmony_ci		return true;
20148c2ecf20Sopenharmony_ci
20158c2ecf20Sopenharmony_ci	/* Otherwise, incremental hashing is supported */
20168c2ecf20Sopenharmony_ci	return false;
20178c2ecf20Sopenharmony_ci}
20188c2ecf20Sopenharmony_ci
20198c2ecf20Sopenharmony_cistatic int ahash_init(struct ahash_request *req)
20208c2ecf20Sopenharmony_ci{
20218c2ecf20Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
20228c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm);
20238c2ecf20Sopenharmony_ci	const char *alg_name;
20248c2ecf20Sopenharmony_ci	struct crypto_shash *hash;
20258c2ecf20Sopenharmony_ci	int ret;
20268c2ecf20Sopenharmony_ci	gfp_t gfp;
20278c2ecf20Sopenharmony_ci
20288c2ecf20Sopenharmony_ci	if (spu_no_incr_hash(ctx)) {
20298c2ecf20Sopenharmony_ci		/*
20308c2ecf20Sopenharmony_ci		 * If we get an incremental hashing request and it's not
20318c2ecf20Sopenharmony_ci		 * supported by the hardware, we need to handle it in software
20328c2ecf20Sopenharmony_ci		 * by calling synchronous hash functions.
20338c2ecf20Sopenharmony_ci		 */
20348c2ecf20Sopenharmony_ci		alg_name = crypto_tfm_alg_name(crypto_ahash_tfm(tfm));
20358c2ecf20Sopenharmony_ci		hash = crypto_alloc_shash(alg_name, 0, 0);
20368c2ecf20Sopenharmony_ci		if (IS_ERR(hash)) {
20378c2ecf20Sopenharmony_ci			ret = PTR_ERR(hash);
20388c2ecf20Sopenharmony_ci			goto err;
20398c2ecf20Sopenharmony_ci		}
20408c2ecf20Sopenharmony_ci
20418c2ecf20Sopenharmony_ci		gfp = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
20428c2ecf20Sopenharmony_ci		       CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
20438c2ecf20Sopenharmony_ci		ctx->shash = kmalloc(sizeof(*ctx->shash) +
20448c2ecf20Sopenharmony_ci				     crypto_shash_descsize(hash), gfp);
20458c2ecf20Sopenharmony_ci		if (!ctx->shash) {
20468c2ecf20Sopenharmony_ci			ret = -ENOMEM;
20478c2ecf20Sopenharmony_ci			goto err_hash;
20488c2ecf20Sopenharmony_ci		}
20498c2ecf20Sopenharmony_ci		ctx->shash->tfm = hash;
20508c2ecf20Sopenharmony_ci
20518c2ecf20Sopenharmony_ci		/* Set the key using data we already have from setkey */
20528c2ecf20Sopenharmony_ci		if (ctx->authkeylen > 0) {
20538c2ecf20Sopenharmony_ci			ret = crypto_shash_setkey(hash, ctx->authkey,
20548c2ecf20Sopenharmony_ci						  ctx->authkeylen);
20558c2ecf20Sopenharmony_ci			if (ret)
20568c2ecf20Sopenharmony_ci				goto err_shash;
20578c2ecf20Sopenharmony_ci		}
20588c2ecf20Sopenharmony_ci
20598c2ecf20Sopenharmony_ci		/* Initialize hash w/ this key and other params */
20608c2ecf20Sopenharmony_ci		ret = crypto_shash_init(ctx->shash);
20618c2ecf20Sopenharmony_ci		if (ret)
20628c2ecf20Sopenharmony_ci			goto err_shash;
20638c2ecf20Sopenharmony_ci	} else {
20648c2ecf20Sopenharmony_ci		/* Otherwise call the internal function which uses SPU hw */
20658c2ecf20Sopenharmony_ci		ret = __ahash_init(req);
20668c2ecf20Sopenharmony_ci	}
20678c2ecf20Sopenharmony_ci
20688c2ecf20Sopenharmony_ci	return ret;
20698c2ecf20Sopenharmony_ci
20708c2ecf20Sopenharmony_cierr_shash:
20718c2ecf20Sopenharmony_ci	kfree(ctx->shash);
20728c2ecf20Sopenharmony_cierr_hash:
20738c2ecf20Sopenharmony_ci	crypto_free_shash(hash);
20748c2ecf20Sopenharmony_cierr:
20758c2ecf20Sopenharmony_ci	return ret;
20768c2ecf20Sopenharmony_ci}
20778c2ecf20Sopenharmony_ci
20788c2ecf20Sopenharmony_cistatic int __ahash_update(struct ahash_request *req)
20798c2ecf20Sopenharmony_ci{
20808c2ecf20Sopenharmony_ci	struct iproc_reqctx_s *rctx = ahash_request_ctx(req);
20818c2ecf20Sopenharmony_ci
20828c2ecf20Sopenharmony_ci	flow_log("ahash_update() nbytes:%u\n", req->nbytes);
20838c2ecf20Sopenharmony_ci
20848c2ecf20Sopenharmony_ci	if (!req->nbytes)
20858c2ecf20Sopenharmony_ci		return 0;
20868c2ecf20Sopenharmony_ci	rctx->total_todo += req->nbytes;
20878c2ecf20Sopenharmony_ci	rctx->src_sent = 0;
20888c2ecf20Sopenharmony_ci
20898c2ecf20Sopenharmony_ci	return ahash_enqueue(req);
20908c2ecf20Sopenharmony_ci}
20918c2ecf20Sopenharmony_ci
20928c2ecf20Sopenharmony_cistatic int ahash_update(struct ahash_request *req)
20938c2ecf20Sopenharmony_ci{
20948c2ecf20Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
20958c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm);
20968c2ecf20Sopenharmony_ci	u8 *tmpbuf;
20978c2ecf20Sopenharmony_ci	int ret;
20988c2ecf20Sopenharmony_ci	int nents;
20998c2ecf20Sopenharmony_ci	gfp_t gfp;
21008c2ecf20Sopenharmony_ci
21018c2ecf20Sopenharmony_ci	if (spu_no_incr_hash(ctx)) {
21028c2ecf20Sopenharmony_ci		/*
21038c2ecf20Sopenharmony_ci		 * If we get an incremental hashing request and it's not
21048c2ecf20Sopenharmony_ci		 * supported by the hardware, we need to handle it in software
21058c2ecf20Sopenharmony_ci		 * by calling synchronous hash functions.
21068c2ecf20Sopenharmony_ci		 */
21078c2ecf20Sopenharmony_ci		if (req->src)
21088c2ecf20Sopenharmony_ci			nents = sg_nents(req->src);
21098c2ecf20Sopenharmony_ci		else
21108c2ecf20Sopenharmony_ci			return -EINVAL;
21118c2ecf20Sopenharmony_ci
21128c2ecf20Sopenharmony_ci		/* Copy data from req scatterlist to tmp buffer */
21138c2ecf20Sopenharmony_ci		gfp = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
21148c2ecf20Sopenharmony_ci		       CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
21158c2ecf20Sopenharmony_ci		tmpbuf = kmalloc(req->nbytes, gfp);
21168c2ecf20Sopenharmony_ci		if (!tmpbuf)
21178c2ecf20Sopenharmony_ci			return -ENOMEM;
21188c2ecf20Sopenharmony_ci
21198c2ecf20Sopenharmony_ci		if (sg_copy_to_buffer(req->src, nents, tmpbuf, req->nbytes) !=
21208c2ecf20Sopenharmony_ci				req->nbytes) {
21218c2ecf20Sopenharmony_ci			kfree(tmpbuf);
21228c2ecf20Sopenharmony_ci			return -EINVAL;
21238c2ecf20Sopenharmony_ci		}
21248c2ecf20Sopenharmony_ci
21258c2ecf20Sopenharmony_ci		/* Call synchronous update */
21268c2ecf20Sopenharmony_ci		ret = crypto_shash_update(ctx->shash, tmpbuf, req->nbytes);
21278c2ecf20Sopenharmony_ci		kfree(tmpbuf);
21288c2ecf20Sopenharmony_ci	} else {
21298c2ecf20Sopenharmony_ci		/* Otherwise call the internal function which uses SPU hw */
21308c2ecf20Sopenharmony_ci		ret = __ahash_update(req);
21318c2ecf20Sopenharmony_ci	}
21328c2ecf20Sopenharmony_ci
21338c2ecf20Sopenharmony_ci	return ret;
21348c2ecf20Sopenharmony_ci}
21358c2ecf20Sopenharmony_ci
21368c2ecf20Sopenharmony_cistatic int __ahash_final(struct ahash_request *req)
21378c2ecf20Sopenharmony_ci{
21388c2ecf20Sopenharmony_ci	struct iproc_reqctx_s *rctx = ahash_request_ctx(req);
21398c2ecf20Sopenharmony_ci
21408c2ecf20Sopenharmony_ci	flow_log("ahash_final() nbytes:%u\n", req->nbytes);
21418c2ecf20Sopenharmony_ci
21428c2ecf20Sopenharmony_ci	rctx->is_final = 1;
21438c2ecf20Sopenharmony_ci
21448c2ecf20Sopenharmony_ci	return ahash_enqueue(req);
21458c2ecf20Sopenharmony_ci}
21468c2ecf20Sopenharmony_ci
21478c2ecf20Sopenharmony_cistatic int ahash_final(struct ahash_request *req)
21488c2ecf20Sopenharmony_ci{
21498c2ecf20Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
21508c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm);
21518c2ecf20Sopenharmony_ci	int ret;
21528c2ecf20Sopenharmony_ci
21538c2ecf20Sopenharmony_ci	if (spu_no_incr_hash(ctx)) {
21548c2ecf20Sopenharmony_ci		/*
21558c2ecf20Sopenharmony_ci		 * If we get an incremental hashing request and it's not
21568c2ecf20Sopenharmony_ci		 * supported by the hardware, we need to handle it in software
21578c2ecf20Sopenharmony_ci		 * by calling synchronous hash functions.
21588c2ecf20Sopenharmony_ci		 */
21598c2ecf20Sopenharmony_ci		ret = crypto_shash_final(ctx->shash, req->result);
21608c2ecf20Sopenharmony_ci
21618c2ecf20Sopenharmony_ci		/* Done with hash, can deallocate it now */
21628c2ecf20Sopenharmony_ci		crypto_free_shash(ctx->shash->tfm);
21638c2ecf20Sopenharmony_ci		kfree(ctx->shash);
21648c2ecf20Sopenharmony_ci
21658c2ecf20Sopenharmony_ci	} else {
21668c2ecf20Sopenharmony_ci		/* Otherwise call the internal function which uses SPU hw */
21678c2ecf20Sopenharmony_ci		ret = __ahash_final(req);
21688c2ecf20Sopenharmony_ci	}
21698c2ecf20Sopenharmony_ci
21708c2ecf20Sopenharmony_ci	return ret;
21718c2ecf20Sopenharmony_ci}
21728c2ecf20Sopenharmony_ci
21738c2ecf20Sopenharmony_cistatic int __ahash_finup(struct ahash_request *req)
21748c2ecf20Sopenharmony_ci{
21758c2ecf20Sopenharmony_ci	struct iproc_reqctx_s *rctx = ahash_request_ctx(req);
21768c2ecf20Sopenharmony_ci
21778c2ecf20Sopenharmony_ci	flow_log("ahash_finup() nbytes:%u\n", req->nbytes);
21788c2ecf20Sopenharmony_ci
21798c2ecf20Sopenharmony_ci	rctx->total_todo += req->nbytes;
21808c2ecf20Sopenharmony_ci	rctx->src_sent = 0;
21818c2ecf20Sopenharmony_ci	rctx->is_final = 1;
21828c2ecf20Sopenharmony_ci
21838c2ecf20Sopenharmony_ci	return ahash_enqueue(req);
21848c2ecf20Sopenharmony_ci}
21858c2ecf20Sopenharmony_ci
21868c2ecf20Sopenharmony_cistatic int ahash_finup(struct ahash_request *req)
21878c2ecf20Sopenharmony_ci{
21888c2ecf20Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
21898c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm);
21908c2ecf20Sopenharmony_ci	u8 *tmpbuf;
21918c2ecf20Sopenharmony_ci	int ret;
21928c2ecf20Sopenharmony_ci	int nents;
21938c2ecf20Sopenharmony_ci	gfp_t gfp;
21948c2ecf20Sopenharmony_ci
21958c2ecf20Sopenharmony_ci	if (spu_no_incr_hash(ctx)) {
21968c2ecf20Sopenharmony_ci		/*
21978c2ecf20Sopenharmony_ci		 * If we get an incremental hashing request and it's not
21988c2ecf20Sopenharmony_ci		 * supported by the hardware, we need to handle it in software
21998c2ecf20Sopenharmony_ci		 * by calling synchronous hash functions.
22008c2ecf20Sopenharmony_ci		 */
22018c2ecf20Sopenharmony_ci		if (req->src) {
22028c2ecf20Sopenharmony_ci			nents = sg_nents(req->src);
22038c2ecf20Sopenharmony_ci		} else {
22048c2ecf20Sopenharmony_ci			ret = -EINVAL;
22058c2ecf20Sopenharmony_ci			goto ahash_finup_exit;
22068c2ecf20Sopenharmony_ci		}
22078c2ecf20Sopenharmony_ci
22088c2ecf20Sopenharmony_ci		/* Copy data from req scatterlist to tmp buffer */
22098c2ecf20Sopenharmony_ci		gfp = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
22108c2ecf20Sopenharmony_ci		       CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
22118c2ecf20Sopenharmony_ci		tmpbuf = kmalloc(req->nbytes, gfp);
22128c2ecf20Sopenharmony_ci		if (!tmpbuf) {
22138c2ecf20Sopenharmony_ci			ret = -ENOMEM;
22148c2ecf20Sopenharmony_ci			goto ahash_finup_exit;
22158c2ecf20Sopenharmony_ci		}
22168c2ecf20Sopenharmony_ci
22178c2ecf20Sopenharmony_ci		if (sg_copy_to_buffer(req->src, nents, tmpbuf, req->nbytes) !=
22188c2ecf20Sopenharmony_ci				req->nbytes) {
22198c2ecf20Sopenharmony_ci			ret = -EINVAL;
22208c2ecf20Sopenharmony_ci			goto ahash_finup_free;
22218c2ecf20Sopenharmony_ci		}
22228c2ecf20Sopenharmony_ci
22238c2ecf20Sopenharmony_ci		/* Call synchronous update */
22248c2ecf20Sopenharmony_ci		ret = crypto_shash_finup(ctx->shash, tmpbuf, req->nbytes,
22258c2ecf20Sopenharmony_ci					 req->result);
22268c2ecf20Sopenharmony_ci	} else {
22278c2ecf20Sopenharmony_ci		/* Otherwise call the internal function which uses SPU hw */
22288c2ecf20Sopenharmony_ci		return __ahash_finup(req);
22298c2ecf20Sopenharmony_ci	}
22308c2ecf20Sopenharmony_ciahash_finup_free:
22318c2ecf20Sopenharmony_ci	kfree(tmpbuf);
22328c2ecf20Sopenharmony_ci
22338c2ecf20Sopenharmony_ciahash_finup_exit:
22348c2ecf20Sopenharmony_ci	/* Done with hash, can deallocate it now */
22358c2ecf20Sopenharmony_ci	crypto_free_shash(ctx->shash->tfm);
22368c2ecf20Sopenharmony_ci	kfree(ctx->shash);
22378c2ecf20Sopenharmony_ci	return ret;
22388c2ecf20Sopenharmony_ci}
22398c2ecf20Sopenharmony_ci
22408c2ecf20Sopenharmony_cistatic int ahash_digest(struct ahash_request *req)
22418c2ecf20Sopenharmony_ci{
22428c2ecf20Sopenharmony_ci	int err;
22438c2ecf20Sopenharmony_ci
22448c2ecf20Sopenharmony_ci	flow_log("ahash_digest() nbytes:%u\n", req->nbytes);
22458c2ecf20Sopenharmony_ci
22468c2ecf20Sopenharmony_ci	/* whole thing at once */
22478c2ecf20Sopenharmony_ci	err = __ahash_init(req);
22488c2ecf20Sopenharmony_ci	if (!err)
22498c2ecf20Sopenharmony_ci		err = __ahash_finup(req);
22508c2ecf20Sopenharmony_ci
22518c2ecf20Sopenharmony_ci	return err;
22528c2ecf20Sopenharmony_ci}
22538c2ecf20Sopenharmony_ci
22548c2ecf20Sopenharmony_cistatic int ahash_setkey(struct crypto_ahash *ahash, const u8 *key,
22558c2ecf20Sopenharmony_ci			unsigned int keylen)
22568c2ecf20Sopenharmony_ci{
22578c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_ahash_ctx(ahash);
22588c2ecf20Sopenharmony_ci
22598c2ecf20Sopenharmony_ci	flow_log("%s() ahash:%p key:%p keylen:%u\n",
22608c2ecf20Sopenharmony_ci		 __func__, ahash, key, keylen);
22618c2ecf20Sopenharmony_ci	flow_dump("  key: ", key, keylen);
22628c2ecf20Sopenharmony_ci
22638c2ecf20Sopenharmony_ci	if (ctx->auth.alg == HASH_ALG_AES) {
22648c2ecf20Sopenharmony_ci		switch (keylen) {
22658c2ecf20Sopenharmony_ci		case AES_KEYSIZE_128:
22668c2ecf20Sopenharmony_ci			ctx->cipher_type = CIPHER_TYPE_AES128;
22678c2ecf20Sopenharmony_ci			break;
22688c2ecf20Sopenharmony_ci		case AES_KEYSIZE_192:
22698c2ecf20Sopenharmony_ci			ctx->cipher_type = CIPHER_TYPE_AES192;
22708c2ecf20Sopenharmony_ci			break;
22718c2ecf20Sopenharmony_ci		case AES_KEYSIZE_256:
22728c2ecf20Sopenharmony_ci			ctx->cipher_type = CIPHER_TYPE_AES256;
22738c2ecf20Sopenharmony_ci			break;
22748c2ecf20Sopenharmony_ci		default:
22758c2ecf20Sopenharmony_ci			pr_err("%s() Error: Invalid key length\n", __func__);
22768c2ecf20Sopenharmony_ci			return -EINVAL;
22778c2ecf20Sopenharmony_ci		}
22788c2ecf20Sopenharmony_ci	} else {
22798c2ecf20Sopenharmony_ci		pr_err("%s() Error: unknown hash alg\n", __func__);
22808c2ecf20Sopenharmony_ci		return -EINVAL;
22818c2ecf20Sopenharmony_ci	}
22828c2ecf20Sopenharmony_ci	memcpy(ctx->authkey, key, keylen);
22838c2ecf20Sopenharmony_ci	ctx->authkeylen = keylen;
22848c2ecf20Sopenharmony_ci
22858c2ecf20Sopenharmony_ci	return 0;
22868c2ecf20Sopenharmony_ci}
22878c2ecf20Sopenharmony_ci
22888c2ecf20Sopenharmony_cistatic int ahash_export(struct ahash_request *req, void *out)
22898c2ecf20Sopenharmony_ci{
22908c2ecf20Sopenharmony_ci	const struct iproc_reqctx_s *rctx = ahash_request_ctx(req);
22918c2ecf20Sopenharmony_ci	struct spu_hash_export_s *spu_exp = (struct spu_hash_export_s *)out;
22928c2ecf20Sopenharmony_ci
22938c2ecf20Sopenharmony_ci	spu_exp->total_todo = rctx->total_todo;
22948c2ecf20Sopenharmony_ci	spu_exp->total_sent = rctx->total_sent;
22958c2ecf20Sopenharmony_ci	spu_exp->is_sw_hmac = rctx->is_sw_hmac;
22968c2ecf20Sopenharmony_ci	memcpy(spu_exp->hash_carry, rctx->hash_carry, sizeof(rctx->hash_carry));
22978c2ecf20Sopenharmony_ci	spu_exp->hash_carry_len = rctx->hash_carry_len;
22988c2ecf20Sopenharmony_ci	memcpy(spu_exp->incr_hash, rctx->incr_hash, sizeof(rctx->incr_hash));
22998c2ecf20Sopenharmony_ci
23008c2ecf20Sopenharmony_ci	return 0;
23018c2ecf20Sopenharmony_ci}
23028c2ecf20Sopenharmony_ci
23038c2ecf20Sopenharmony_cistatic int ahash_import(struct ahash_request *req, const void *in)
23048c2ecf20Sopenharmony_ci{
23058c2ecf20Sopenharmony_ci	struct iproc_reqctx_s *rctx = ahash_request_ctx(req);
23068c2ecf20Sopenharmony_ci	struct spu_hash_export_s *spu_exp = (struct spu_hash_export_s *)in;
23078c2ecf20Sopenharmony_ci
23088c2ecf20Sopenharmony_ci	rctx->total_todo = spu_exp->total_todo;
23098c2ecf20Sopenharmony_ci	rctx->total_sent = spu_exp->total_sent;
23108c2ecf20Sopenharmony_ci	rctx->is_sw_hmac = spu_exp->is_sw_hmac;
23118c2ecf20Sopenharmony_ci	memcpy(rctx->hash_carry, spu_exp->hash_carry, sizeof(rctx->hash_carry));
23128c2ecf20Sopenharmony_ci	rctx->hash_carry_len = spu_exp->hash_carry_len;
23138c2ecf20Sopenharmony_ci	memcpy(rctx->incr_hash, spu_exp->incr_hash, sizeof(rctx->incr_hash));
23148c2ecf20Sopenharmony_ci
23158c2ecf20Sopenharmony_ci	return 0;
23168c2ecf20Sopenharmony_ci}
23178c2ecf20Sopenharmony_ci
23188c2ecf20Sopenharmony_cistatic int ahash_hmac_setkey(struct crypto_ahash *ahash, const u8 *key,
23198c2ecf20Sopenharmony_ci			     unsigned int keylen)
23208c2ecf20Sopenharmony_ci{
23218c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_ahash_ctx(ahash);
23228c2ecf20Sopenharmony_ci	unsigned int blocksize =
23238c2ecf20Sopenharmony_ci		crypto_tfm_alg_blocksize(crypto_ahash_tfm(ahash));
23248c2ecf20Sopenharmony_ci	unsigned int digestsize = crypto_ahash_digestsize(ahash);
23258c2ecf20Sopenharmony_ci	unsigned int index;
23268c2ecf20Sopenharmony_ci	int rc;
23278c2ecf20Sopenharmony_ci
23288c2ecf20Sopenharmony_ci	flow_log("%s() ahash:%p key:%p keylen:%u blksz:%u digestsz:%u\n",
23298c2ecf20Sopenharmony_ci		 __func__, ahash, key, keylen, blocksize, digestsize);
23308c2ecf20Sopenharmony_ci	flow_dump("  key: ", key, keylen);
23318c2ecf20Sopenharmony_ci
23328c2ecf20Sopenharmony_ci	if (keylen > blocksize) {
23338c2ecf20Sopenharmony_ci		switch (ctx->auth.alg) {
23348c2ecf20Sopenharmony_ci		case HASH_ALG_MD5:
23358c2ecf20Sopenharmony_ci			rc = do_shash("md5", ctx->authkey, key, keylen, NULL,
23368c2ecf20Sopenharmony_ci				      0, NULL, 0);
23378c2ecf20Sopenharmony_ci			break;
23388c2ecf20Sopenharmony_ci		case HASH_ALG_SHA1:
23398c2ecf20Sopenharmony_ci			rc = do_shash("sha1", ctx->authkey, key, keylen, NULL,
23408c2ecf20Sopenharmony_ci				      0, NULL, 0);
23418c2ecf20Sopenharmony_ci			break;
23428c2ecf20Sopenharmony_ci		case HASH_ALG_SHA224:
23438c2ecf20Sopenharmony_ci			rc = do_shash("sha224", ctx->authkey, key, keylen, NULL,
23448c2ecf20Sopenharmony_ci				      0, NULL, 0);
23458c2ecf20Sopenharmony_ci			break;
23468c2ecf20Sopenharmony_ci		case HASH_ALG_SHA256:
23478c2ecf20Sopenharmony_ci			rc = do_shash("sha256", ctx->authkey, key, keylen, NULL,
23488c2ecf20Sopenharmony_ci				      0, NULL, 0);
23498c2ecf20Sopenharmony_ci			break;
23508c2ecf20Sopenharmony_ci		case HASH_ALG_SHA384:
23518c2ecf20Sopenharmony_ci			rc = do_shash("sha384", ctx->authkey, key, keylen, NULL,
23528c2ecf20Sopenharmony_ci				      0, NULL, 0);
23538c2ecf20Sopenharmony_ci			break;
23548c2ecf20Sopenharmony_ci		case HASH_ALG_SHA512:
23558c2ecf20Sopenharmony_ci			rc = do_shash("sha512", ctx->authkey, key, keylen, NULL,
23568c2ecf20Sopenharmony_ci				      0, NULL, 0);
23578c2ecf20Sopenharmony_ci			break;
23588c2ecf20Sopenharmony_ci		case HASH_ALG_SHA3_224:
23598c2ecf20Sopenharmony_ci			rc = do_shash("sha3-224", ctx->authkey, key, keylen,
23608c2ecf20Sopenharmony_ci				      NULL, 0, NULL, 0);
23618c2ecf20Sopenharmony_ci			break;
23628c2ecf20Sopenharmony_ci		case HASH_ALG_SHA3_256:
23638c2ecf20Sopenharmony_ci			rc = do_shash("sha3-256", ctx->authkey, key, keylen,
23648c2ecf20Sopenharmony_ci				      NULL, 0, NULL, 0);
23658c2ecf20Sopenharmony_ci			break;
23668c2ecf20Sopenharmony_ci		case HASH_ALG_SHA3_384:
23678c2ecf20Sopenharmony_ci			rc = do_shash("sha3-384", ctx->authkey, key, keylen,
23688c2ecf20Sopenharmony_ci				      NULL, 0, NULL, 0);
23698c2ecf20Sopenharmony_ci			break;
23708c2ecf20Sopenharmony_ci		case HASH_ALG_SHA3_512:
23718c2ecf20Sopenharmony_ci			rc = do_shash("sha3-512", ctx->authkey, key, keylen,
23728c2ecf20Sopenharmony_ci				      NULL, 0, NULL, 0);
23738c2ecf20Sopenharmony_ci			break;
23748c2ecf20Sopenharmony_ci		default:
23758c2ecf20Sopenharmony_ci			pr_err("%s() Error: unknown hash alg\n", __func__);
23768c2ecf20Sopenharmony_ci			return -EINVAL;
23778c2ecf20Sopenharmony_ci		}
23788c2ecf20Sopenharmony_ci		if (rc < 0) {
23798c2ecf20Sopenharmony_ci			pr_err("%s() Error %d computing shash for %s\n",
23808c2ecf20Sopenharmony_ci			       __func__, rc, hash_alg_name[ctx->auth.alg]);
23818c2ecf20Sopenharmony_ci			return rc;
23828c2ecf20Sopenharmony_ci		}
23838c2ecf20Sopenharmony_ci		ctx->authkeylen = digestsize;
23848c2ecf20Sopenharmony_ci
23858c2ecf20Sopenharmony_ci		flow_log("  keylen > digestsize... hashed\n");
23868c2ecf20Sopenharmony_ci		flow_dump("  newkey: ", ctx->authkey, ctx->authkeylen);
23878c2ecf20Sopenharmony_ci	} else {
23888c2ecf20Sopenharmony_ci		memcpy(ctx->authkey, key, keylen);
23898c2ecf20Sopenharmony_ci		ctx->authkeylen = keylen;
23908c2ecf20Sopenharmony_ci	}
23918c2ecf20Sopenharmony_ci
23928c2ecf20Sopenharmony_ci	/*
23938c2ecf20Sopenharmony_ci	 * Full HMAC operation in SPUM is not verified,
23948c2ecf20Sopenharmony_ci	 * So keeping the generation of IPAD, OPAD and
23958c2ecf20Sopenharmony_ci	 * outer hashing in software.
23968c2ecf20Sopenharmony_ci	 */
23978c2ecf20Sopenharmony_ci	if (iproc_priv.spu.spu_type == SPU_TYPE_SPUM) {
23988c2ecf20Sopenharmony_ci		memcpy(ctx->ipad, ctx->authkey, ctx->authkeylen);
23998c2ecf20Sopenharmony_ci		memset(ctx->ipad + ctx->authkeylen, 0,
24008c2ecf20Sopenharmony_ci		       blocksize - ctx->authkeylen);
24018c2ecf20Sopenharmony_ci		ctx->authkeylen = 0;
24028c2ecf20Sopenharmony_ci		memcpy(ctx->opad, ctx->ipad, blocksize);
24038c2ecf20Sopenharmony_ci
24048c2ecf20Sopenharmony_ci		for (index = 0; index < blocksize; index++) {
24058c2ecf20Sopenharmony_ci			ctx->ipad[index] ^= HMAC_IPAD_VALUE;
24068c2ecf20Sopenharmony_ci			ctx->opad[index] ^= HMAC_OPAD_VALUE;
24078c2ecf20Sopenharmony_ci		}
24088c2ecf20Sopenharmony_ci
24098c2ecf20Sopenharmony_ci		flow_dump("  ipad: ", ctx->ipad, blocksize);
24108c2ecf20Sopenharmony_ci		flow_dump("  opad: ", ctx->opad, blocksize);
24118c2ecf20Sopenharmony_ci	}
24128c2ecf20Sopenharmony_ci	ctx->digestsize = digestsize;
24138c2ecf20Sopenharmony_ci	atomic_inc(&iproc_priv.setkey_cnt[SPU_OP_HMAC]);
24148c2ecf20Sopenharmony_ci
24158c2ecf20Sopenharmony_ci	return 0;
24168c2ecf20Sopenharmony_ci}
24178c2ecf20Sopenharmony_ci
24188c2ecf20Sopenharmony_cistatic int ahash_hmac_init(struct ahash_request *req)
24198c2ecf20Sopenharmony_ci{
24208c2ecf20Sopenharmony_ci	struct iproc_reqctx_s *rctx = ahash_request_ctx(req);
24218c2ecf20Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
24228c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm);
24238c2ecf20Sopenharmony_ci	unsigned int blocksize =
24248c2ecf20Sopenharmony_ci			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
24258c2ecf20Sopenharmony_ci
24268c2ecf20Sopenharmony_ci	flow_log("ahash_hmac_init()\n");
24278c2ecf20Sopenharmony_ci
24288c2ecf20Sopenharmony_ci	/* init the context as a hash */
24298c2ecf20Sopenharmony_ci	ahash_init(req);
24308c2ecf20Sopenharmony_ci
24318c2ecf20Sopenharmony_ci	if (!spu_no_incr_hash(ctx)) {
24328c2ecf20Sopenharmony_ci		/* SPU-M can do incr hashing but needs sw for outer HMAC */
24338c2ecf20Sopenharmony_ci		rctx->is_sw_hmac = true;
24348c2ecf20Sopenharmony_ci		ctx->auth.mode = HASH_MODE_HASH;
24358c2ecf20Sopenharmony_ci		/* start with a prepended ipad */
24368c2ecf20Sopenharmony_ci		memcpy(rctx->hash_carry, ctx->ipad, blocksize);
24378c2ecf20Sopenharmony_ci		rctx->hash_carry_len = blocksize;
24388c2ecf20Sopenharmony_ci		rctx->total_todo += blocksize;
24398c2ecf20Sopenharmony_ci	}
24408c2ecf20Sopenharmony_ci
24418c2ecf20Sopenharmony_ci	return 0;
24428c2ecf20Sopenharmony_ci}
24438c2ecf20Sopenharmony_ci
24448c2ecf20Sopenharmony_cistatic int ahash_hmac_update(struct ahash_request *req)
24458c2ecf20Sopenharmony_ci{
24468c2ecf20Sopenharmony_ci	flow_log("ahash_hmac_update() nbytes:%u\n", req->nbytes);
24478c2ecf20Sopenharmony_ci
24488c2ecf20Sopenharmony_ci	if (!req->nbytes)
24498c2ecf20Sopenharmony_ci		return 0;
24508c2ecf20Sopenharmony_ci
24518c2ecf20Sopenharmony_ci	return ahash_update(req);
24528c2ecf20Sopenharmony_ci}
24538c2ecf20Sopenharmony_ci
24548c2ecf20Sopenharmony_cistatic int ahash_hmac_final(struct ahash_request *req)
24558c2ecf20Sopenharmony_ci{
24568c2ecf20Sopenharmony_ci	flow_log("ahash_hmac_final() nbytes:%u\n", req->nbytes);
24578c2ecf20Sopenharmony_ci
24588c2ecf20Sopenharmony_ci	return ahash_final(req);
24598c2ecf20Sopenharmony_ci}
24608c2ecf20Sopenharmony_ci
24618c2ecf20Sopenharmony_cistatic int ahash_hmac_finup(struct ahash_request *req)
24628c2ecf20Sopenharmony_ci{
24638c2ecf20Sopenharmony_ci	flow_log("ahash_hmac_finupl() nbytes:%u\n", req->nbytes);
24648c2ecf20Sopenharmony_ci
24658c2ecf20Sopenharmony_ci	return ahash_finup(req);
24668c2ecf20Sopenharmony_ci}
24678c2ecf20Sopenharmony_ci
24688c2ecf20Sopenharmony_cistatic int ahash_hmac_digest(struct ahash_request *req)
24698c2ecf20Sopenharmony_ci{
24708c2ecf20Sopenharmony_ci	struct iproc_reqctx_s *rctx = ahash_request_ctx(req);
24718c2ecf20Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
24728c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm);
24738c2ecf20Sopenharmony_ci	unsigned int blocksize =
24748c2ecf20Sopenharmony_ci			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
24758c2ecf20Sopenharmony_ci
24768c2ecf20Sopenharmony_ci	flow_log("ahash_hmac_digest() nbytes:%u\n", req->nbytes);
24778c2ecf20Sopenharmony_ci
24788c2ecf20Sopenharmony_ci	/* Perform initialization and then call finup */
24798c2ecf20Sopenharmony_ci	__ahash_init(req);
24808c2ecf20Sopenharmony_ci
24818c2ecf20Sopenharmony_ci	if (iproc_priv.spu.spu_type == SPU_TYPE_SPU2) {
24828c2ecf20Sopenharmony_ci		/*
24838c2ecf20Sopenharmony_ci		 * SPU2 supports full HMAC implementation in the
24848c2ecf20Sopenharmony_ci		 * hardware, need not to generate IPAD, OPAD and
24858c2ecf20Sopenharmony_ci		 * outer hash in software.
24868c2ecf20Sopenharmony_ci		 * Only for hash key len > hash block size, SPU2
24878c2ecf20Sopenharmony_ci		 * expects to perform hashing on the key, shorten
24888c2ecf20Sopenharmony_ci		 * it to digest size and feed it as hash key.
24898c2ecf20Sopenharmony_ci		 */
24908c2ecf20Sopenharmony_ci		rctx->is_sw_hmac = false;
24918c2ecf20Sopenharmony_ci		ctx->auth.mode = HASH_MODE_HMAC;
24928c2ecf20Sopenharmony_ci	} else {
24938c2ecf20Sopenharmony_ci		rctx->is_sw_hmac = true;
24948c2ecf20Sopenharmony_ci		ctx->auth.mode = HASH_MODE_HASH;
24958c2ecf20Sopenharmony_ci		/* start with a prepended ipad */
24968c2ecf20Sopenharmony_ci		memcpy(rctx->hash_carry, ctx->ipad, blocksize);
24978c2ecf20Sopenharmony_ci		rctx->hash_carry_len = blocksize;
24988c2ecf20Sopenharmony_ci		rctx->total_todo += blocksize;
24998c2ecf20Sopenharmony_ci	}
25008c2ecf20Sopenharmony_ci
25018c2ecf20Sopenharmony_ci	return __ahash_finup(req);
25028c2ecf20Sopenharmony_ci}
25038c2ecf20Sopenharmony_ci
25048c2ecf20Sopenharmony_ci/* aead helpers */
25058c2ecf20Sopenharmony_ci
25068c2ecf20Sopenharmony_cistatic int aead_need_fallback(struct aead_request *req)
25078c2ecf20Sopenharmony_ci{
25088c2ecf20Sopenharmony_ci	struct iproc_reqctx_s *rctx = aead_request_ctx(req);
25098c2ecf20Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
25108c2ecf20Sopenharmony_ci	struct crypto_aead *aead = crypto_aead_reqtfm(req);
25118c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_aead_ctx(aead);
25128c2ecf20Sopenharmony_ci	u32 payload_len;
25138c2ecf20Sopenharmony_ci
25148c2ecf20Sopenharmony_ci	/*
25158c2ecf20Sopenharmony_ci	 * SPU hardware cannot handle the AES-GCM/CCM case where plaintext
25168c2ecf20Sopenharmony_ci	 * and AAD are both 0 bytes long. So use fallback in this case.
25178c2ecf20Sopenharmony_ci	 */
25188c2ecf20Sopenharmony_ci	if (((ctx->cipher.mode == CIPHER_MODE_GCM) ||
25198c2ecf20Sopenharmony_ci	     (ctx->cipher.mode == CIPHER_MODE_CCM)) &&
25208c2ecf20Sopenharmony_ci	    (req->assoclen == 0)) {
25218c2ecf20Sopenharmony_ci		if ((rctx->is_encrypt && (req->cryptlen == 0)) ||
25228c2ecf20Sopenharmony_ci		    (!rctx->is_encrypt && (req->cryptlen == ctx->digestsize))) {
25238c2ecf20Sopenharmony_ci			flow_log("AES GCM/CCM needs fallback for 0 len req\n");
25248c2ecf20Sopenharmony_ci			return 1;
25258c2ecf20Sopenharmony_ci		}
25268c2ecf20Sopenharmony_ci	}
25278c2ecf20Sopenharmony_ci
25288c2ecf20Sopenharmony_ci	/* SPU-M hardware only supports CCM digest size of 8, 12, or 16 bytes */
25298c2ecf20Sopenharmony_ci	if ((ctx->cipher.mode == CIPHER_MODE_CCM) &&
25308c2ecf20Sopenharmony_ci	    (spu->spu_type == SPU_TYPE_SPUM) &&
25318c2ecf20Sopenharmony_ci	    (ctx->digestsize != 8) && (ctx->digestsize != 12) &&
25328c2ecf20Sopenharmony_ci	    (ctx->digestsize != 16)) {
25338c2ecf20Sopenharmony_ci		flow_log("%s() AES CCM needs fallback for digest size %d\n",
25348c2ecf20Sopenharmony_ci			 __func__, ctx->digestsize);
25358c2ecf20Sopenharmony_ci		return 1;
25368c2ecf20Sopenharmony_ci	}
25378c2ecf20Sopenharmony_ci
25388c2ecf20Sopenharmony_ci	/*
25398c2ecf20Sopenharmony_ci	 * SPU-M on NSP has an issue where AES-CCM hash is not correct
25408c2ecf20Sopenharmony_ci	 * when AAD size is 0
25418c2ecf20Sopenharmony_ci	 */
25428c2ecf20Sopenharmony_ci	if ((ctx->cipher.mode == CIPHER_MODE_CCM) &&
25438c2ecf20Sopenharmony_ci	    (spu->spu_subtype == SPU_SUBTYPE_SPUM_NSP) &&
25448c2ecf20Sopenharmony_ci	    (req->assoclen == 0)) {
25458c2ecf20Sopenharmony_ci		flow_log("%s() AES_CCM needs fallback for 0 len AAD on NSP\n",
25468c2ecf20Sopenharmony_ci			 __func__);
25478c2ecf20Sopenharmony_ci		return 1;
25488c2ecf20Sopenharmony_ci	}
25498c2ecf20Sopenharmony_ci
25508c2ecf20Sopenharmony_ci	/*
25518c2ecf20Sopenharmony_ci	 * RFC4106 and RFC4543 cannot handle the case where AAD is other than
25528c2ecf20Sopenharmony_ci	 * 16 or 20 bytes long. So use fallback in this case.
25538c2ecf20Sopenharmony_ci	 */
25548c2ecf20Sopenharmony_ci	if (ctx->cipher.mode == CIPHER_MODE_GCM &&
25558c2ecf20Sopenharmony_ci	    ctx->cipher.alg == CIPHER_ALG_AES &&
25568c2ecf20Sopenharmony_ci	    rctx->iv_ctr_len == GCM_RFC4106_IV_SIZE &&
25578c2ecf20Sopenharmony_ci	    req->assoclen != 16 && req->assoclen != 20) {
25588c2ecf20Sopenharmony_ci		flow_log("RFC4106/RFC4543 needs fallback for assoclen"
25598c2ecf20Sopenharmony_ci			 " other than 16 or 20 bytes\n");
25608c2ecf20Sopenharmony_ci		return 1;
25618c2ecf20Sopenharmony_ci	}
25628c2ecf20Sopenharmony_ci
25638c2ecf20Sopenharmony_ci	payload_len = req->cryptlen;
25648c2ecf20Sopenharmony_ci	if (spu->spu_type == SPU_TYPE_SPUM)
25658c2ecf20Sopenharmony_ci		payload_len += req->assoclen;
25668c2ecf20Sopenharmony_ci
25678c2ecf20Sopenharmony_ci	flow_log("%s() payload len: %u\n", __func__, payload_len);
25688c2ecf20Sopenharmony_ci
25698c2ecf20Sopenharmony_ci	if (ctx->max_payload == SPU_MAX_PAYLOAD_INF)
25708c2ecf20Sopenharmony_ci		return 0;
25718c2ecf20Sopenharmony_ci	else
25728c2ecf20Sopenharmony_ci		return payload_len > ctx->max_payload;
25738c2ecf20Sopenharmony_ci}
25748c2ecf20Sopenharmony_ci
25758c2ecf20Sopenharmony_cistatic void aead_complete(struct crypto_async_request *areq, int err)
25768c2ecf20Sopenharmony_ci{
25778c2ecf20Sopenharmony_ci	struct aead_request *req =
25788c2ecf20Sopenharmony_ci	    container_of(areq, struct aead_request, base);
25798c2ecf20Sopenharmony_ci	struct iproc_reqctx_s *rctx = aead_request_ctx(req);
25808c2ecf20Sopenharmony_ci	struct crypto_aead *aead = crypto_aead_reqtfm(req);
25818c2ecf20Sopenharmony_ci
25828c2ecf20Sopenharmony_ci	flow_log("%s() err:%d\n", __func__, err);
25838c2ecf20Sopenharmony_ci
25848c2ecf20Sopenharmony_ci	areq->tfm = crypto_aead_tfm(aead);
25858c2ecf20Sopenharmony_ci
25868c2ecf20Sopenharmony_ci	areq->complete = rctx->old_complete;
25878c2ecf20Sopenharmony_ci	areq->data = rctx->old_data;
25888c2ecf20Sopenharmony_ci
25898c2ecf20Sopenharmony_ci	areq->complete(areq, err);
25908c2ecf20Sopenharmony_ci}
25918c2ecf20Sopenharmony_ci
25928c2ecf20Sopenharmony_cistatic int aead_do_fallback(struct aead_request *req, bool is_encrypt)
25938c2ecf20Sopenharmony_ci{
25948c2ecf20Sopenharmony_ci	struct crypto_aead *aead = crypto_aead_reqtfm(req);
25958c2ecf20Sopenharmony_ci	struct crypto_tfm *tfm = crypto_aead_tfm(aead);
25968c2ecf20Sopenharmony_ci	struct iproc_reqctx_s *rctx = aead_request_ctx(req);
25978c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_tfm_ctx(tfm);
25988c2ecf20Sopenharmony_ci	int err;
25998c2ecf20Sopenharmony_ci	u32 req_flags;
26008c2ecf20Sopenharmony_ci
26018c2ecf20Sopenharmony_ci	flow_log("%s() enc:%u\n", __func__, is_encrypt);
26028c2ecf20Sopenharmony_ci
26038c2ecf20Sopenharmony_ci	if (ctx->fallback_cipher) {
26048c2ecf20Sopenharmony_ci		/* Store the cipher tfm and then use the fallback tfm */
26058c2ecf20Sopenharmony_ci		rctx->old_tfm = tfm;
26068c2ecf20Sopenharmony_ci		aead_request_set_tfm(req, ctx->fallback_cipher);
26078c2ecf20Sopenharmony_ci		/*
26088c2ecf20Sopenharmony_ci		 * Save the callback and chain ourselves in, so we can restore
26098c2ecf20Sopenharmony_ci		 * the tfm
26108c2ecf20Sopenharmony_ci		 */
26118c2ecf20Sopenharmony_ci		rctx->old_complete = req->base.complete;
26128c2ecf20Sopenharmony_ci		rctx->old_data = req->base.data;
26138c2ecf20Sopenharmony_ci		req_flags = aead_request_flags(req);
26148c2ecf20Sopenharmony_ci		aead_request_set_callback(req, req_flags, aead_complete, req);
26158c2ecf20Sopenharmony_ci		err = is_encrypt ? crypto_aead_encrypt(req) :
26168c2ecf20Sopenharmony_ci		    crypto_aead_decrypt(req);
26178c2ecf20Sopenharmony_ci
26188c2ecf20Sopenharmony_ci		if (err == 0) {
26198c2ecf20Sopenharmony_ci			/*
26208c2ecf20Sopenharmony_ci			 * fallback was synchronous (did not return
26218c2ecf20Sopenharmony_ci			 * -EINPROGRESS). So restore request state here.
26228c2ecf20Sopenharmony_ci			 */
26238c2ecf20Sopenharmony_ci			aead_request_set_callback(req, req_flags,
26248c2ecf20Sopenharmony_ci						  rctx->old_complete, req);
26258c2ecf20Sopenharmony_ci			req->base.data = rctx->old_data;
26268c2ecf20Sopenharmony_ci			aead_request_set_tfm(req, aead);
26278c2ecf20Sopenharmony_ci			flow_log("%s() fallback completed successfully\n\n",
26288c2ecf20Sopenharmony_ci				 __func__);
26298c2ecf20Sopenharmony_ci		}
26308c2ecf20Sopenharmony_ci	} else {
26318c2ecf20Sopenharmony_ci		err = -EINVAL;
26328c2ecf20Sopenharmony_ci	}
26338c2ecf20Sopenharmony_ci
26348c2ecf20Sopenharmony_ci	return err;
26358c2ecf20Sopenharmony_ci}
26368c2ecf20Sopenharmony_ci
26378c2ecf20Sopenharmony_cistatic int aead_enqueue(struct aead_request *req, bool is_encrypt)
26388c2ecf20Sopenharmony_ci{
26398c2ecf20Sopenharmony_ci	struct iproc_reqctx_s *rctx = aead_request_ctx(req);
26408c2ecf20Sopenharmony_ci	struct crypto_aead *aead = crypto_aead_reqtfm(req);
26418c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_aead_ctx(aead);
26428c2ecf20Sopenharmony_ci	int err;
26438c2ecf20Sopenharmony_ci
26448c2ecf20Sopenharmony_ci	flow_log("%s() enc:%u\n", __func__, is_encrypt);
26458c2ecf20Sopenharmony_ci
26468c2ecf20Sopenharmony_ci	if (req->assoclen > MAX_ASSOC_SIZE) {
26478c2ecf20Sopenharmony_ci		pr_err
26488c2ecf20Sopenharmony_ci		    ("%s() Error: associated data too long. (%u > %u bytes)\n",
26498c2ecf20Sopenharmony_ci		     __func__, req->assoclen, MAX_ASSOC_SIZE);
26508c2ecf20Sopenharmony_ci		return -EINVAL;
26518c2ecf20Sopenharmony_ci	}
26528c2ecf20Sopenharmony_ci
26538c2ecf20Sopenharmony_ci	rctx->gfp = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
26548c2ecf20Sopenharmony_ci		       CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
26558c2ecf20Sopenharmony_ci	rctx->parent = &req->base;
26568c2ecf20Sopenharmony_ci	rctx->is_encrypt = is_encrypt;
26578c2ecf20Sopenharmony_ci	rctx->bd_suppress = false;
26588c2ecf20Sopenharmony_ci	rctx->total_todo = req->cryptlen;
26598c2ecf20Sopenharmony_ci	rctx->src_sent = 0;
26608c2ecf20Sopenharmony_ci	rctx->total_sent = 0;
26618c2ecf20Sopenharmony_ci	rctx->total_received = 0;
26628c2ecf20Sopenharmony_ci	rctx->is_sw_hmac = false;
26638c2ecf20Sopenharmony_ci	rctx->ctx = ctx;
26648c2ecf20Sopenharmony_ci	memset(&rctx->mb_mssg, 0, sizeof(struct brcm_message));
26658c2ecf20Sopenharmony_ci
26668c2ecf20Sopenharmony_ci	/* assoc data is at start of src sg */
26678c2ecf20Sopenharmony_ci	rctx->assoc = req->src;
26688c2ecf20Sopenharmony_ci
26698c2ecf20Sopenharmony_ci	/*
26708c2ecf20Sopenharmony_ci	 * Init current position in src scatterlist to be after assoc data.
26718c2ecf20Sopenharmony_ci	 * src_skip set to buffer offset where data begins. (Assoc data could
26728c2ecf20Sopenharmony_ci	 * end in the middle of a buffer.)
26738c2ecf20Sopenharmony_ci	 */
26748c2ecf20Sopenharmony_ci	if (spu_sg_at_offset(req->src, req->assoclen, &rctx->src_sg,
26758c2ecf20Sopenharmony_ci			     &rctx->src_skip) < 0) {
26768c2ecf20Sopenharmony_ci		pr_err("%s() Error: Unable to find start of src data\n",
26778c2ecf20Sopenharmony_ci		       __func__);
26788c2ecf20Sopenharmony_ci		return -EINVAL;
26798c2ecf20Sopenharmony_ci	}
26808c2ecf20Sopenharmony_ci
26818c2ecf20Sopenharmony_ci	rctx->src_nents = 0;
26828c2ecf20Sopenharmony_ci	rctx->dst_nents = 0;
26838c2ecf20Sopenharmony_ci	if (req->dst == req->src) {
26848c2ecf20Sopenharmony_ci		rctx->dst_sg = rctx->src_sg;
26858c2ecf20Sopenharmony_ci		rctx->dst_skip = rctx->src_skip;
26868c2ecf20Sopenharmony_ci	} else {
26878c2ecf20Sopenharmony_ci		/*
26888c2ecf20Sopenharmony_ci		 * Expect req->dst to have room for assoc data followed by
26898c2ecf20Sopenharmony_ci		 * output data and ICV, if encrypt. So initialize dst_sg
26908c2ecf20Sopenharmony_ci		 * to point beyond assoc len offset.
26918c2ecf20Sopenharmony_ci		 */
26928c2ecf20Sopenharmony_ci		if (spu_sg_at_offset(req->dst, req->assoclen, &rctx->dst_sg,
26938c2ecf20Sopenharmony_ci				     &rctx->dst_skip) < 0) {
26948c2ecf20Sopenharmony_ci			pr_err("%s() Error: Unable to find start of dst data\n",
26958c2ecf20Sopenharmony_ci			       __func__);
26968c2ecf20Sopenharmony_ci			return -EINVAL;
26978c2ecf20Sopenharmony_ci		}
26988c2ecf20Sopenharmony_ci	}
26998c2ecf20Sopenharmony_ci
27008c2ecf20Sopenharmony_ci	if (ctx->cipher.mode == CIPHER_MODE_CBC ||
27018c2ecf20Sopenharmony_ci	    ctx->cipher.mode == CIPHER_MODE_CTR ||
27028c2ecf20Sopenharmony_ci	    ctx->cipher.mode == CIPHER_MODE_OFB ||
27038c2ecf20Sopenharmony_ci	    ctx->cipher.mode == CIPHER_MODE_XTS ||
27048c2ecf20Sopenharmony_ci	    ctx->cipher.mode == CIPHER_MODE_GCM) {
27058c2ecf20Sopenharmony_ci		rctx->iv_ctr_len =
27068c2ecf20Sopenharmony_ci			ctx->salt_len +
27078c2ecf20Sopenharmony_ci			crypto_aead_ivsize(crypto_aead_reqtfm(req));
27088c2ecf20Sopenharmony_ci	} else if (ctx->cipher.mode == CIPHER_MODE_CCM) {
27098c2ecf20Sopenharmony_ci		rctx->iv_ctr_len = CCM_AES_IV_SIZE;
27108c2ecf20Sopenharmony_ci	} else {
27118c2ecf20Sopenharmony_ci		rctx->iv_ctr_len = 0;
27128c2ecf20Sopenharmony_ci	}
27138c2ecf20Sopenharmony_ci
27148c2ecf20Sopenharmony_ci	rctx->hash_carry_len = 0;
27158c2ecf20Sopenharmony_ci
27168c2ecf20Sopenharmony_ci	flow_log("  src sg: %p\n", req->src);
27178c2ecf20Sopenharmony_ci	flow_log("  rctx->src_sg: %p, src_skip %u\n",
27188c2ecf20Sopenharmony_ci		 rctx->src_sg, rctx->src_skip);
27198c2ecf20Sopenharmony_ci	flow_log("  assoc:  %p, assoclen %u\n", rctx->assoc, req->assoclen);
27208c2ecf20Sopenharmony_ci	flow_log("  dst sg: %p\n", req->dst);
27218c2ecf20Sopenharmony_ci	flow_log("  rctx->dst_sg: %p, dst_skip %u\n",
27228c2ecf20Sopenharmony_ci		 rctx->dst_sg, rctx->dst_skip);
27238c2ecf20Sopenharmony_ci	flow_log("  iv_ctr_len:%u\n", rctx->iv_ctr_len);
27248c2ecf20Sopenharmony_ci	flow_dump("  iv: ", req->iv, rctx->iv_ctr_len);
27258c2ecf20Sopenharmony_ci	flow_log("  authkeylen:%u\n", ctx->authkeylen);
27268c2ecf20Sopenharmony_ci	flow_log("  is_esp: %s\n", ctx->is_esp ? "yes" : "no");
27278c2ecf20Sopenharmony_ci
27288c2ecf20Sopenharmony_ci	if (ctx->max_payload == SPU_MAX_PAYLOAD_INF)
27298c2ecf20Sopenharmony_ci		flow_log("  max_payload infinite");
27308c2ecf20Sopenharmony_ci	else
27318c2ecf20Sopenharmony_ci		flow_log("  max_payload: %u\n", ctx->max_payload);
27328c2ecf20Sopenharmony_ci
27338c2ecf20Sopenharmony_ci	if (unlikely(aead_need_fallback(req)))
27348c2ecf20Sopenharmony_ci		return aead_do_fallback(req, is_encrypt);
27358c2ecf20Sopenharmony_ci
27368c2ecf20Sopenharmony_ci	/*
27378c2ecf20Sopenharmony_ci	 * Do memory allocations for request after fallback check, because if we
27388c2ecf20Sopenharmony_ci	 * do fallback, we won't call finish_req() to dealloc.
27398c2ecf20Sopenharmony_ci	 */
27408c2ecf20Sopenharmony_ci	if (rctx->iv_ctr_len) {
27418c2ecf20Sopenharmony_ci		if (ctx->salt_len)
27428c2ecf20Sopenharmony_ci			memcpy(rctx->msg_buf.iv_ctr + ctx->salt_offset,
27438c2ecf20Sopenharmony_ci			       ctx->salt, ctx->salt_len);
27448c2ecf20Sopenharmony_ci		memcpy(rctx->msg_buf.iv_ctr + ctx->salt_offset + ctx->salt_len,
27458c2ecf20Sopenharmony_ci		       req->iv,
27468c2ecf20Sopenharmony_ci		       rctx->iv_ctr_len - ctx->salt_len - ctx->salt_offset);
27478c2ecf20Sopenharmony_ci	}
27488c2ecf20Sopenharmony_ci
27498c2ecf20Sopenharmony_ci	rctx->chan_idx = select_channel();
27508c2ecf20Sopenharmony_ci	err = handle_aead_req(rctx);
27518c2ecf20Sopenharmony_ci	if (err != -EINPROGRESS)
27528c2ecf20Sopenharmony_ci		/* synchronous result */
27538c2ecf20Sopenharmony_ci		spu_chunk_cleanup(rctx);
27548c2ecf20Sopenharmony_ci
27558c2ecf20Sopenharmony_ci	return err;
27568c2ecf20Sopenharmony_ci}
27578c2ecf20Sopenharmony_ci
27588c2ecf20Sopenharmony_cistatic int aead_authenc_setkey(struct crypto_aead *cipher,
27598c2ecf20Sopenharmony_ci			       const u8 *key, unsigned int keylen)
27608c2ecf20Sopenharmony_ci{
27618c2ecf20Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
27628c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher);
27638c2ecf20Sopenharmony_ci	struct crypto_tfm *tfm = crypto_aead_tfm(cipher);
27648c2ecf20Sopenharmony_ci	struct crypto_authenc_keys keys;
27658c2ecf20Sopenharmony_ci	int ret;
27668c2ecf20Sopenharmony_ci
27678c2ecf20Sopenharmony_ci	flow_log("%s() aead:%p key:%p keylen:%u\n", __func__, cipher, key,
27688c2ecf20Sopenharmony_ci		 keylen);
27698c2ecf20Sopenharmony_ci	flow_dump("  key: ", key, keylen);
27708c2ecf20Sopenharmony_ci
27718c2ecf20Sopenharmony_ci	ret = crypto_authenc_extractkeys(&keys, key, keylen);
27728c2ecf20Sopenharmony_ci	if (ret)
27738c2ecf20Sopenharmony_ci		goto badkey;
27748c2ecf20Sopenharmony_ci
27758c2ecf20Sopenharmony_ci	if (keys.enckeylen > MAX_KEY_SIZE ||
27768c2ecf20Sopenharmony_ci	    keys.authkeylen > MAX_KEY_SIZE)
27778c2ecf20Sopenharmony_ci		goto badkey;
27788c2ecf20Sopenharmony_ci
27798c2ecf20Sopenharmony_ci	ctx->enckeylen = keys.enckeylen;
27808c2ecf20Sopenharmony_ci	ctx->authkeylen = keys.authkeylen;
27818c2ecf20Sopenharmony_ci
27828c2ecf20Sopenharmony_ci	memcpy(ctx->enckey, keys.enckey, keys.enckeylen);
27838c2ecf20Sopenharmony_ci	/* May end up padding auth key. So make sure it's zeroed. */
27848c2ecf20Sopenharmony_ci	memset(ctx->authkey, 0, sizeof(ctx->authkey));
27858c2ecf20Sopenharmony_ci	memcpy(ctx->authkey, keys.authkey, keys.authkeylen);
27868c2ecf20Sopenharmony_ci
27878c2ecf20Sopenharmony_ci	switch (ctx->alg->cipher_info.alg) {
27888c2ecf20Sopenharmony_ci	case CIPHER_ALG_DES:
27898c2ecf20Sopenharmony_ci		if (verify_aead_des_key(cipher, keys.enckey, keys.enckeylen))
27908c2ecf20Sopenharmony_ci			return -EINVAL;
27918c2ecf20Sopenharmony_ci
27928c2ecf20Sopenharmony_ci		ctx->cipher_type = CIPHER_TYPE_DES;
27938c2ecf20Sopenharmony_ci		break;
27948c2ecf20Sopenharmony_ci	case CIPHER_ALG_3DES:
27958c2ecf20Sopenharmony_ci		if (verify_aead_des3_key(cipher, keys.enckey, keys.enckeylen))
27968c2ecf20Sopenharmony_ci			return -EINVAL;
27978c2ecf20Sopenharmony_ci
27988c2ecf20Sopenharmony_ci		ctx->cipher_type = CIPHER_TYPE_3DES;
27998c2ecf20Sopenharmony_ci		break;
28008c2ecf20Sopenharmony_ci	case CIPHER_ALG_AES:
28018c2ecf20Sopenharmony_ci		switch (ctx->enckeylen) {
28028c2ecf20Sopenharmony_ci		case AES_KEYSIZE_128:
28038c2ecf20Sopenharmony_ci			ctx->cipher_type = CIPHER_TYPE_AES128;
28048c2ecf20Sopenharmony_ci			break;
28058c2ecf20Sopenharmony_ci		case AES_KEYSIZE_192:
28068c2ecf20Sopenharmony_ci			ctx->cipher_type = CIPHER_TYPE_AES192;
28078c2ecf20Sopenharmony_ci			break;
28088c2ecf20Sopenharmony_ci		case AES_KEYSIZE_256:
28098c2ecf20Sopenharmony_ci			ctx->cipher_type = CIPHER_TYPE_AES256;
28108c2ecf20Sopenharmony_ci			break;
28118c2ecf20Sopenharmony_ci		default:
28128c2ecf20Sopenharmony_ci			goto badkey;
28138c2ecf20Sopenharmony_ci		}
28148c2ecf20Sopenharmony_ci		break;
28158c2ecf20Sopenharmony_ci	default:
28168c2ecf20Sopenharmony_ci		pr_err("%s() Error: Unknown cipher alg\n", __func__);
28178c2ecf20Sopenharmony_ci		return -EINVAL;
28188c2ecf20Sopenharmony_ci	}
28198c2ecf20Sopenharmony_ci
28208c2ecf20Sopenharmony_ci	flow_log("  enckeylen:%u authkeylen:%u\n", ctx->enckeylen,
28218c2ecf20Sopenharmony_ci		 ctx->authkeylen);
28228c2ecf20Sopenharmony_ci	flow_dump("  enc: ", ctx->enckey, ctx->enckeylen);
28238c2ecf20Sopenharmony_ci	flow_dump("  auth: ", ctx->authkey, ctx->authkeylen);
28248c2ecf20Sopenharmony_ci
28258c2ecf20Sopenharmony_ci	/* setkey the fallback just in case we needto use it */
28268c2ecf20Sopenharmony_ci	if (ctx->fallback_cipher) {
28278c2ecf20Sopenharmony_ci		flow_log("  running fallback setkey()\n");
28288c2ecf20Sopenharmony_ci
28298c2ecf20Sopenharmony_ci		ctx->fallback_cipher->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
28308c2ecf20Sopenharmony_ci		ctx->fallback_cipher->base.crt_flags |=
28318c2ecf20Sopenharmony_ci		    tfm->crt_flags & CRYPTO_TFM_REQ_MASK;
28328c2ecf20Sopenharmony_ci		ret = crypto_aead_setkey(ctx->fallback_cipher, key, keylen);
28338c2ecf20Sopenharmony_ci		if (ret)
28348c2ecf20Sopenharmony_ci			flow_log("  fallback setkey() returned:%d\n", ret);
28358c2ecf20Sopenharmony_ci	}
28368c2ecf20Sopenharmony_ci
28378c2ecf20Sopenharmony_ci	ctx->spu_resp_hdr_len = spu->spu_response_hdr_len(ctx->authkeylen,
28388c2ecf20Sopenharmony_ci							  ctx->enckeylen,
28398c2ecf20Sopenharmony_ci							  false);
28408c2ecf20Sopenharmony_ci
28418c2ecf20Sopenharmony_ci	atomic_inc(&iproc_priv.setkey_cnt[SPU_OP_AEAD]);
28428c2ecf20Sopenharmony_ci
28438c2ecf20Sopenharmony_ci	return ret;
28448c2ecf20Sopenharmony_ci
28458c2ecf20Sopenharmony_cibadkey:
28468c2ecf20Sopenharmony_ci	ctx->enckeylen = 0;
28478c2ecf20Sopenharmony_ci	ctx->authkeylen = 0;
28488c2ecf20Sopenharmony_ci	ctx->digestsize = 0;
28498c2ecf20Sopenharmony_ci
28508c2ecf20Sopenharmony_ci	return -EINVAL;
28518c2ecf20Sopenharmony_ci}
28528c2ecf20Sopenharmony_ci
28538c2ecf20Sopenharmony_cistatic int aead_gcm_ccm_setkey(struct crypto_aead *cipher,
28548c2ecf20Sopenharmony_ci			       const u8 *key, unsigned int keylen)
28558c2ecf20Sopenharmony_ci{
28568c2ecf20Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
28578c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher);
28588c2ecf20Sopenharmony_ci	struct crypto_tfm *tfm = crypto_aead_tfm(cipher);
28598c2ecf20Sopenharmony_ci
28608c2ecf20Sopenharmony_ci	int ret = 0;
28618c2ecf20Sopenharmony_ci
28628c2ecf20Sopenharmony_ci	flow_log("%s() keylen:%u\n", __func__, keylen);
28638c2ecf20Sopenharmony_ci	flow_dump("  key: ", key, keylen);
28648c2ecf20Sopenharmony_ci
28658c2ecf20Sopenharmony_ci	if (!ctx->is_esp)
28668c2ecf20Sopenharmony_ci		ctx->digestsize = keylen;
28678c2ecf20Sopenharmony_ci
28688c2ecf20Sopenharmony_ci	ctx->enckeylen = keylen;
28698c2ecf20Sopenharmony_ci	ctx->authkeylen = 0;
28708c2ecf20Sopenharmony_ci
28718c2ecf20Sopenharmony_ci	switch (ctx->enckeylen) {
28728c2ecf20Sopenharmony_ci	case AES_KEYSIZE_128:
28738c2ecf20Sopenharmony_ci		ctx->cipher_type = CIPHER_TYPE_AES128;
28748c2ecf20Sopenharmony_ci		break;
28758c2ecf20Sopenharmony_ci	case AES_KEYSIZE_192:
28768c2ecf20Sopenharmony_ci		ctx->cipher_type = CIPHER_TYPE_AES192;
28778c2ecf20Sopenharmony_ci		break;
28788c2ecf20Sopenharmony_ci	case AES_KEYSIZE_256:
28798c2ecf20Sopenharmony_ci		ctx->cipher_type = CIPHER_TYPE_AES256;
28808c2ecf20Sopenharmony_ci		break;
28818c2ecf20Sopenharmony_ci	default:
28828c2ecf20Sopenharmony_ci		goto badkey;
28838c2ecf20Sopenharmony_ci	}
28848c2ecf20Sopenharmony_ci
28858c2ecf20Sopenharmony_ci	memcpy(ctx->enckey, key, ctx->enckeylen);
28868c2ecf20Sopenharmony_ci
28878c2ecf20Sopenharmony_ci	flow_log("  enckeylen:%u authkeylen:%u\n", ctx->enckeylen,
28888c2ecf20Sopenharmony_ci		 ctx->authkeylen);
28898c2ecf20Sopenharmony_ci	flow_dump("  enc: ", ctx->enckey, ctx->enckeylen);
28908c2ecf20Sopenharmony_ci	flow_dump("  auth: ", ctx->authkey, ctx->authkeylen);
28918c2ecf20Sopenharmony_ci
28928c2ecf20Sopenharmony_ci	/* setkey the fallback just in case we need to use it */
28938c2ecf20Sopenharmony_ci	if (ctx->fallback_cipher) {
28948c2ecf20Sopenharmony_ci		flow_log("  running fallback setkey()\n");
28958c2ecf20Sopenharmony_ci
28968c2ecf20Sopenharmony_ci		ctx->fallback_cipher->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
28978c2ecf20Sopenharmony_ci		ctx->fallback_cipher->base.crt_flags |=
28988c2ecf20Sopenharmony_ci		    tfm->crt_flags & CRYPTO_TFM_REQ_MASK;
28998c2ecf20Sopenharmony_ci		ret = crypto_aead_setkey(ctx->fallback_cipher, key,
29008c2ecf20Sopenharmony_ci					 keylen + ctx->salt_len);
29018c2ecf20Sopenharmony_ci		if (ret)
29028c2ecf20Sopenharmony_ci			flow_log("  fallback setkey() returned:%d\n", ret);
29038c2ecf20Sopenharmony_ci	}
29048c2ecf20Sopenharmony_ci
29058c2ecf20Sopenharmony_ci	ctx->spu_resp_hdr_len = spu->spu_response_hdr_len(ctx->authkeylen,
29068c2ecf20Sopenharmony_ci							  ctx->enckeylen,
29078c2ecf20Sopenharmony_ci							  false);
29088c2ecf20Sopenharmony_ci
29098c2ecf20Sopenharmony_ci	atomic_inc(&iproc_priv.setkey_cnt[SPU_OP_AEAD]);
29108c2ecf20Sopenharmony_ci
29118c2ecf20Sopenharmony_ci	flow_log("  enckeylen:%u authkeylen:%u\n", ctx->enckeylen,
29128c2ecf20Sopenharmony_ci		 ctx->authkeylen);
29138c2ecf20Sopenharmony_ci
29148c2ecf20Sopenharmony_ci	return ret;
29158c2ecf20Sopenharmony_ci
29168c2ecf20Sopenharmony_cibadkey:
29178c2ecf20Sopenharmony_ci	ctx->enckeylen = 0;
29188c2ecf20Sopenharmony_ci	ctx->authkeylen = 0;
29198c2ecf20Sopenharmony_ci	ctx->digestsize = 0;
29208c2ecf20Sopenharmony_ci
29218c2ecf20Sopenharmony_ci	return -EINVAL;
29228c2ecf20Sopenharmony_ci}
29238c2ecf20Sopenharmony_ci
29248c2ecf20Sopenharmony_ci/**
29258c2ecf20Sopenharmony_ci * aead_gcm_esp_setkey() - setkey() operation for ESP variant of GCM AES.
29268c2ecf20Sopenharmony_ci * @cipher: AEAD structure
29278c2ecf20Sopenharmony_ci * @key:    Key followed by 4 bytes of salt
29288c2ecf20Sopenharmony_ci * @keylen: Length of key plus salt, in bytes
29298c2ecf20Sopenharmony_ci *
29308c2ecf20Sopenharmony_ci * Extracts salt from key and stores it to be prepended to IV on each request.
29318c2ecf20Sopenharmony_ci * Digest is always 16 bytes
29328c2ecf20Sopenharmony_ci *
29338c2ecf20Sopenharmony_ci * Return: Value from generic gcm setkey.
29348c2ecf20Sopenharmony_ci */
29358c2ecf20Sopenharmony_cistatic int aead_gcm_esp_setkey(struct crypto_aead *cipher,
29368c2ecf20Sopenharmony_ci			       const u8 *key, unsigned int keylen)
29378c2ecf20Sopenharmony_ci{
29388c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher);
29398c2ecf20Sopenharmony_ci
29408c2ecf20Sopenharmony_ci	flow_log("%s\n", __func__);
29418c2ecf20Sopenharmony_ci
29428c2ecf20Sopenharmony_ci	if (keylen < GCM_ESP_SALT_SIZE)
29438c2ecf20Sopenharmony_ci		return -EINVAL;
29448c2ecf20Sopenharmony_ci
29458c2ecf20Sopenharmony_ci	ctx->salt_len = GCM_ESP_SALT_SIZE;
29468c2ecf20Sopenharmony_ci	ctx->salt_offset = GCM_ESP_SALT_OFFSET;
29478c2ecf20Sopenharmony_ci	memcpy(ctx->salt, key + keylen - GCM_ESP_SALT_SIZE, GCM_ESP_SALT_SIZE);
29488c2ecf20Sopenharmony_ci	keylen -= GCM_ESP_SALT_SIZE;
29498c2ecf20Sopenharmony_ci	ctx->digestsize = GCM_ESP_DIGESTSIZE;
29508c2ecf20Sopenharmony_ci	ctx->is_esp = true;
29518c2ecf20Sopenharmony_ci	flow_dump("salt: ", ctx->salt, GCM_ESP_SALT_SIZE);
29528c2ecf20Sopenharmony_ci
29538c2ecf20Sopenharmony_ci	return aead_gcm_ccm_setkey(cipher, key, keylen);
29548c2ecf20Sopenharmony_ci}
29558c2ecf20Sopenharmony_ci
29568c2ecf20Sopenharmony_ci/**
29578c2ecf20Sopenharmony_ci * rfc4543_gcm_esp_setkey() - setkey operation for RFC4543 variant of GCM/GMAC.
29588c2ecf20Sopenharmony_ci * cipher: AEAD structure
29598c2ecf20Sopenharmony_ci * key:    Key followed by 4 bytes of salt
29608c2ecf20Sopenharmony_ci * keylen: Length of key plus salt, in bytes
29618c2ecf20Sopenharmony_ci *
29628c2ecf20Sopenharmony_ci * Extracts salt from key and stores it to be prepended to IV on each request.
29638c2ecf20Sopenharmony_ci * Digest is always 16 bytes
29648c2ecf20Sopenharmony_ci *
29658c2ecf20Sopenharmony_ci * Return: Value from generic gcm setkey.
29668c2ecf20Sopenharmony_ci */
29678c2ecf20Sopenharmony_cistatic int rfc4543_gcm_esp_setkey(struct crypto_aead *cipher,
29688c2ecf20Sopenharmony_ci				  const u8 *key, unsigned int keylen)
29698c2ecf20Sopenharmony_ci{
29708c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher);
29718c2ecf20Sopenharmony_ci
29728c2ecf20Sopenharmony_ci	flow_log("%s\n", __func__);
29738c2ecf20Sopenharmony_ci
29748c2ecf20Sopenharmony_ci	if (keylen < GCM_ESP_SALT_SIZE)
29758c2ecf20Sopenharmony_ci		return -EINVAL;
29768c2ecf20Sopenharmony_ci
29778c2ecf20Sopenharmony_ci	ctx->salt_len = GCM_ESP_SALT_SIZE;
29788c2ecf20Sopenharmony_ci	ctx->salt_offset = GCM_ESP_SALT_OFFSET;
29798c2ecf20Sopenharmony_ci	memcpy(ctx->salt, key + keylen - GCM_ESP_SALT_SIZE, GCM_ESP_SALT_SIZE);
29808c2ecf20Sopenharmony_ci	keylen -= GCM_ESP_SALT_SIZE;
29818c2ecf20Sopenharmony_ci	ctx->digestsize = GCM_ESP_DIGESTSIZE;
29828c2ecf20Sopenharmony_ci	ctx->is_esp = true;
29838c2ecf20Sopenharmony_ci	ctx->is_rfc4543 = true;
29848c2ecf20Sopenharmony_ci	flow_dump("salt: ", ctx->salt, GCM_ESP_SALT_SIZE);
29858c2ecf20Sopenharmony_ci
29868c2ecf20Sopenharmony_ci	return aead_gcm_ccm_setkey(cipher, key, keylen);
29878c2ecf20Sopenharmony_ci}
29888c2ecf20Sopenharmony_ci
29898c2ecf20Sopenharmony_ci/**
29908c2ecf20Sopenharmony_ci * aead_ccm_esp_setkey() - setkey() operation for ESP variant of CCM AES.
29918c2ecf20Sopenharmony_ci * @cipher: AEAD structure
29928c2ecf20Sopenharmony_ci * @key:    Key followed by 4 bytes of salt
29938c2ecf20Sopenharmony_ci * @keylen: Length of key plus salt, in bytes
29948c2ecf20Sopenharmony_ci *
29958c2ecf20Sopenharmony_ci * Extracts salt from key and stores it to be prepended to IV on each request.
29968c2ecf20Sopenharmony_ci * Digest is always 16 bytes
29978c2ecf20Sopenharmony_ci *
29988c2ecf20Sopenharmony_ci * Return: Value from generic ccm setkey.
29998c2ecf20Sopenharmony_ci */
30008c2ecf20Sopenharmony_cistatic int aead_ccm_esp_setkey(struct crypto_aead *cipher,
30018c2ecf20Sopenharmony_ci			       const u8 *key, unsigned int keylen)
30028c2ecf20Sopenharmony_ci{
30038c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher);
30048c2ecf20Sopenharmony_ci
30058c2ecf20Sopenharmony_ci	flow_log("%s\n", __func__);
30068c2ecf20Sopenharmony_ci
30078c2ecf20Sopenharmony_ci	if (keylen < CCM_ESP_SALT_SIZE)
30088c2ecf20Sopenharmony_ci		return -EINVAL;
30098c2ecf20Sopenharmony_ci
30108c2ecf20Sopenharmony_ci	ctx->salt_len = CCM_ESP_SALT_SIZE;
30118c2ecf20Sopenharmony_ci	ctx->salt_offset = CCM_ESP_SALT_OFFSET;
30128c2ecf20Sopenharmony_ci	memcpy(ctx->salt, key + keylen - CCM_ESP_SALT_SIZE, CCM_ESP_SALT_SIZE);
30138c2ecf20Sopenharmony_ci	keylen -= CCM_ESP_SALT_SIZE;
30148c2ecf20Sopenharmony_ci	ctx->is_esp = true;
30158c2ecf20Sopenharmony_ci	flow_dump("salt: ", ctx->salt, CCM_ESP_SALT_SIZE);
30168c2ecf20Sopenharmony_ci
30178c2ecf20Sopenharmony_ci	return aead_gcm_ccm_setkey(cipher, key, keylen);
30188c2ecf20Sopenharmony_ci}
30198c2ecf20Sopenharmony_ci
30208c2ecf20Sopenharmony_cistatic int aead_setauthsize(struct crypto_aead *cipher, unsigned int authsize)
30218c2ecf20Sopenharmony_ci{
30228c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher);
30238c2ecf20Sopenharmony_ci	int ret = 0;
30248c2ecf20Sopenharmony_ci
30258c2ecf20Sopenharmony_ci	flow_log("%s() authkeylen:%u authsize:%u\n",
30268c2ecf20Sopenharmony_ci		 __func__, ctx->authkeylen, authsize);
30278c2ecf20Sopenharmony_ci
30288c2ecf20Sopenharmony_ci	ctx->digestsize = authsize;
30298c2ecf20Sopenharmony_ci
30308c2ecf20Sopenharmony_ci	/* setkey the fallback just in case we needto use it */
30318c2ecf20Sopenharmony_ci	if (ctx->fallback_cipher) {
30328c2ecf20Sopenharmony_ci		flow_log("  running fallback setauth()\n");
30338c2ecf20Sopenharmony_ci
30348c2ecf20Sopenharmony_ci		ret = crypto_aead_setauthsize(ctx->fallback_cipher, authsize);
30358c2ecf20Sopenharmony_ci		if (ret)
30368c2ecf20Sopenharmony_ci			flow_log("  fallback setauth() returned:%d\n", ret);
30378c2ecf20Sopenharmony_ci	}
30388c2ecf20Sopenharmony_ci
30398c2ecf20Sopenharmony_ci	return ret;
30408c2ecf20Sopenharmony_ci}
30418c2ecf20Sopenharmony_ci
30428c2ecf20Sopenharmony_cistatic int aead_encrypt(struct aead_request *req)
30438c2ecf20Sopenharmony_ci{
30448c2ecf20Sopenharmony_ci	flow_log("%s() cryptlen:%u %08x\n", __func__, req->cryptlen,
30458c2ecf20Sopenharmony_ci		 req->cryptlen);
30468c2ecf20Sopenharmony_ci	dump_sg(req->src, 0, req->cryptlen + req->assoclen);
30478c2ecf20Sopenharmony_ci	flow_log("  assoc_len:%u\n", req->assoclen);
30488c2ecf20Sopenharmony_ci
30498c2ecf20Sopenharmony_ci	return aead_enqueue(req, true);
30508c2ecf20Sopenharmony_ci}
30518c2ecf20Sopenharmony_ci
30528c2ecf20Sopenharmony_cistatic int aead_decrypt(struct aead_request *req)
30538c2ecf20Sopenharmony_ci{
30548c2ecf20Sopenharmony_ci	flow_log("%s() cryptlen:%u\n", __func__, req->cryptlen);
30558c2ecf20Sopenharmony_ci	dump_sg(req->src, 0, req->cryptlen + req->assoclen);
30568c2ecf20Sopenharmony_ci	flow_log("  assoc_len:%u\n", req->assoclen);
30578c2ecf20Sopenharmony_ci
30588c2ecf20Sopenharmony_ci	return aead_enqueue(req, false);
30598c2ecf20Sopenharmony_ci}
30608c2ecf20Sopenharmony_ci
30618c2ecf20Sopenharmony_ci/* ==================== Supported Cipher Algorithms ==================== */
30628c2ecf20Sopenharmony_ci
30638c2ecf20Sopenharmony_cistatic struct iproc_alg_s driver_algs[] = {
30648c2ecf20Sopenharmony_ci	{
30658c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
30668c2ecf20Sopenharmony_ci	 .alg.aead = {
30678c2ecf20Sopenharmony_ci		 .base = {
30688c2ecf20Sopenharmony_ci			.cra_name = "gcm(aes)",
30698c2ecf20Sopenharmony_ci			.cra_driver_name = "gcm-aes-iproc",
30708c2ecf20Sopenharmony_ci			.cra_blocksize = AES_BLOCK_SIZE,
30718c2ecf20Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK
30728c2ecf20Sopenharmony_ci		 },
30738c2ecf20Sopenharmony_ci		 .setkey = aead_gcm_ccm_setkey,
30748c2ecf20Sopenharmony_ci		 .ivsize = GCM_AES_IV_SIZE,
30758c2ecf20Sopenharmony_ci		.maxauthsize = AES_BLOCK_SIZE,
30768c2ecf20Sopenharmony_ci	 },
30778c2ecf20Sopenharmony_ci	 .cipher_info = {
30788c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_AES,
30798c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_GCM,
30808c2ecf20Sopenharmony_ci			 },
30818c2ecf20Sopenharmony_ci	 .auth_info = {
30828c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_AES,
30838c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_GCM,
30848c2ecf20Sopenharmony_ci		       },
30858c2ecf20Sopenharmony_ci	 .auth_first = 0,
30868c2ecf20Sopenharmony_ci	 },
30878c2ecf20Sopenharmony_ci	{
30888c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
30898c2ecf20Sopenharmony_ci	 .alg.aead = {
30908c2ecf20Sopenharmony_ci		 .base = {
30918c2ecf20Sopenharmony_ci			.cra_name = "ccm(aes)",
30928c2ecf20Sopenharmony_ci			.cra_driver_name = "ccm-aes-iproc",
30938c2ecf20Sopenharmony_ci			.cra_blocksize = AES_BLOCK_SIZE,
30948c2ecf20Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK
30958c2ecf20Sopenharmony_ci		 },
30968c2ecf20Sopenharmony_ci		 .setkey = aead_gcm_ccm_setkey,
30978c2ecf20Sopenharmony_ci		 .ivsize = CCM_AES_IV_SIZE,
30988c2ecf20Sopenharmony_ci		.maxauthsize = AES_BLOCK_SIZE,
30998c2ecf20Sopenharmony_ci	 },
31008c2ecf20Sopenharmony_ci	 .cipher_info = {
31018c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_AES,
31028c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_CCM,
31038c2ecf20Sopenharmony_ci			 },
31048c2ecf20Sopenharmony_ci	 .auth_info = {
31058c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_AES,
31068c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_CCM,
31078c2ecf20Sopenharmony_ci		       },
31088c2ecf20Sopenharmony_ci	 .auth_first = 0,
31098c2ecf20Sopenharmony_ci	 },
31108c2ecf20Sopenharmony_ci	{
31118c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
31128c2ecf20Sopenharmony_ci	 .alg.aead = {
31138c2ecf20Sopenharmony_ci		 .base = {
31148c2ecf20Sopenharmony_ci			.cra_name = "rfc4106(gcm(aes))",
31158c2ecf20Sopenharmony_ci			.cra_driver_name = "gcm-aes-esp-iproc",
31168c2ecf20Sopenharmony_ci			.cra_blocksize = AES_BLOCK_SIZE,
31178c2ecf20Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK
31188c2ecf20Sopenharmony_ci		 },
31198c2ecf20Sopenharmony_ci		 .setkey = aead_gcm_esp_setkey,
31208c2ecf20Sopenharmony_ci		 .ivsize = GCM_RFC4106_IV_SIZE,
31218c2ecf20Sopenharmony_ci		 .maxauthsize = AES_BLOCK_SIZE,
31228c2ecf20Sopenharmony_ci	 },
31238c2ecf20Sopenharmony_ci	 .cipher_info = {
31248c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_AES,
31258c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_GCM,
31268c2ecf20Sopenharmony_ci			 },
31278c2ecf20Sopenharmony_ci	 .auth_info = {
31288c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_AES,
31298c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_GCM,
31308c2ecf20Sopenharmony_ci		       },
31318c2ecf20Sopenharmony_ci	 .auth_first = 0,
31328c2ecf20Sopenharmony_ci	 },
31338c2ecf20Sopenharmony_ci	{
31348c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
31358c2ecf20Sopenharmony_ci	 .alg.aead = {
31368c2ecf20Sopenharmony_ci		 .base = {
31378c2ecf20Sopenharmony_ci			.cra_name = "rfc4309(ccm(aes))",
31388c2ecf20Sopenharmony_ci			.cra_driver_name = "ccm-aes-esp-iproc",
31398c2ecf20Sopenharmony_ci			.cra_blocksize = AES_BLOCK_SIZE,
31408c2ecf20Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK
31418c2ecf20Sopenharmony_ci		 },
31428c2ecf20Sopenharmony_ci		 .setkey = aead_ccm_esp_setkey,
31438c2ecf20Sopenharmony_ci		 .ivsize = CCM_AES_IV_SIZE,
31448c2ecf20Sopenharmony_ci		 .maxauthsize = AES_BLOCK_SIZE,
31458c2ecf20Sopenharmony_ci	 },
31468c2ecf20Sopenharmony_ci	 .cipher_info = {
31478c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_AES,
31488c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_CCM,
31498c2ecf20Sopenharmony_ci			 },
31508c2ecf20Sopenharmony_ci	 .auth_info = {
31518c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_AES,
31528c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_CCM,
31538c2ecf20Sopenharmony_ci		       },
31548c2ecf20Sopenharmony_ci	 .auth_first = 0,
31558c2ecf20Sopenharmony_ci	 },
31568c2ecf20Sopenharmony_ci	{
31578c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
31588c2ecf20Sopenharmony_ci	 .alg.aead = {
31598c2ecf20Sopenharmony_ci		 .base = {
31608c2ecf20Sopenharmony_ci			.cra_name = "rfc4543(gcm(aes))",
31618c2ecf20Sopenharmony_ci			.cra_driver_name = "gmac-aes-esp-iproc",
31628c2ecf20Sopenharmony_ci			.cra_blocksize = AES_BLOCK_SIZE,
31638c2ecf20Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK
31648c2ecf20Sopenharmony_ci		 },
31658c2ecf20Sopenharmony_ci		 .setkey = rfc4543_gcm_esp_setkey,
31668c2ecf20Sopenharmony_ci		 .ivsize = GCM_RFC4106_IV_SIZE,
31678c2ecf20Sopenharmony_ci		 .maxauthsize = AES_BLOCK_SIZE,
31688c2ecf20Sopenharmony_ci	 },
31698c2ecf20Sopenharmony_ci	 .cipher_info = {
31708c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_AES,
31718c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_GCM,
31728c2ecf20Sopenharmony_ci			 },
31738c2ecf20Sopenharmony_ci	 .auth_info = {
31748c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_AES,
31758c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_GCM,
31768c2ecf20Sopenharmony_ci		       },
31778c2ecf20Sopenharmony_ci	 .auth_first = 0,
31788c2ecf20Sopenharmony_ci	 },
31798c2ecf20Sopenharmony_ci	{
31808c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
31818c2ecf20Sopenharmony_ci	 .alg.aead = {
31828c2ecf20Sopenharmony_ci		 .base = {
31838c2ecf20Sopenharmony_ci			.cra_name = "authenc(hmac(md5),cbc(aes))",
31848c2ecf20Sopenharmony_ci			.cra_driver_name = "authenc-hmac-md5-cbc-aes-iproc",
31858c2ecf20Sopenharmony_ci			.cra_blocksize = AES_BLOCK_SIZE,
31868c2ecf20Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
31878c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
31888c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
31898c2ecf20Sopenharmony_ci		 },
31908c2ecf20Sopenharmony_ci		 .setkey = aead_authenc_setkey,
31918c2ecf20Sopenharmony_ci		.ivsize = AES_BLOCK_SIZE,
31928c2ecf20Sopenharmony_ci		.maxauthsize = MD5_DIGEST_SIZE,
31938c2ecf20Sopenharmony_ci	 },
31948c2ecf20Sopenharmony_ci	 .cipher_info = {
31958c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_AES,
31968c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
31978c2ecf20Sopenharmony_ci			 },
31988c2ecf20Sopenharmony_ci	 .auth_info = {
31998c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_MD5,
32008c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
32018c2ecf20Sopenharmony_ci		       },
32028c2ecf20Sopenharmony_ci	 .auth_first = 0,
32038c2ecf20Sopenharmony_ci	 },
32048c2ecf20Sopenharmony_ci	{
32058c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
32068c2ecf20Sopenharmony_ci	 .alg.aead = {
32078c2ecf20Sopenharmony_ci		 .base = {
32088c2ecf20Sopenharmony_ci			.cra_name = "authenc(hmac(sha1),cbc(aes))",
32098c2ecf20Sopenharmony_ci			.cra_driver_name = "authenc-hmac-sha1-cbc-aes-iproc",
32108c2ecf20Sopenharmony_ci			.cra_blocksize = AES_BLOCK_SIZE,
32118c2ecf20Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
32128c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
32138c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
32148c2ecf20Sopenharmony_ci		 },
32158c2ecf20Sopenharmony_ci		 .setkey = aead_authenc_setkey,
32168c2ecf20Sopenharmony_ci		 .ivsize = AES_BLOCK_SIZE,
32178c2ecf20Sopenharmony_ci		 .maxauthsize = SHA1_DIGEST_SIZE,
32188c2ecf20Sopenharmony_ci	 },
32198c2ecf20Sopenharmony_ci	 .cipher_info = {
32208c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_AES,
32218c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
32228c2ecf20Sopenharmony_ci			 },
32238c2ecf20Sopenharmony_ci	 .auth_info = {
32248c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA1,
32258c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
32268c2ecf20Sopenharmony_ci		       },
32278c2ecf20Sopenharmony_ci	 .auth_first = 0,
32288c2ecf20Sopenharmony_ci	 },
32298c2ecf20Sopenharmony_ci	{
32308c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
32318c2ecf20Sopenharmony_ci	 .alg.aead = {
32328c2ecf20Sopenharmony_ci		 .base = {
32338c2ecf20Sopenharmony_ci			.cra_name = "authenc(hmac(sha256),cbc(aes))",
32348c2ecf20Sopenharmony_ci			.cra_driver_name = "authenc-hmac-sha256-cbc-aes-iproc",
32358c2ecf20Sopenharmony_ci			.cra_blocksize = AES_BLOCK_SIZE,
32368c2ecf20Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
32378c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
32388c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
32398c2ecf20Sopenharmony_ci		 },
32408c2ecf20Sopenharmony_ci		 .setkey = aead_authenc_setkey,
32418c2ecf20Sopenharmony_ci		 .ivsize = AES_BLOCK_SIZE,
32428c2ecf20Sopenharmony_ci		 .maxauthsize = SHA256_DIGEST_SIZE,
32438c2ecf20Sopenharmony_ci	 },
32448c2ecf20Sopenharmony_ci	 .cipher_info = {
32458c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_AES,
32468c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
32478c2ecf20Sopenharmony_ci			 },
32488c2ecf20Sopenharmony_ci	 .auth_info = {
32498c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA256,
32508c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
32518c2ecf20Sopenharmony_ci		       },
32528c2ecf20Sopenharmony_ci	 .auth_first = 0,
32538c2ecf20Sopenharmony_ci	 },
32548c2ecf20Sopenharmony_ci	{
32558c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
32568c2ecf20Sopenharmony_ci	 .alg.aead = {
32578c2ecf20Sopenharmony_ci		 .base = {
32588c2ecf20Sopenharmony_ci			.cra_name = "authenc(hmac(md5),cbc(des))",
32598c2ecf20Sopenharmony_ci			.cra_driver_name = "authenc-hmac-md5-cbc-des-iproc",
32608c2ecf20Sopenharmony_ci			.cra_blocksize = DES_BLOCK_SIZE,
32618c2ecf20Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
32628c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
32638c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
32648c2ecf20Sopenharmony_ci		 },
32658c2ecf20Sopenharmony_ci		 .setkey = aead_authenc_setkey,
32668c2ecf20Sopenharmony_ci		 .ivsize = DES_BLOCK_SIZE,
32678c2ecf20Sopenharmony_ci		 .maxauthsize = MD5_DIGEST_SIZE,
32688c2ecf20Sopenharmony_ci	 },
32698c2ecf20Sopenharmony_ci	 .cipher_info = {
32708c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_DES,
32718c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
32728c2ecf20Sopenharmony_ci			 },
32738c2ecf20Sopenharmony_ci	 .auth_info = {
32748c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_MD5,
32758c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
32768c2ecf20Sopenharmony_ci		       },
32778c2ecf20Sopenharmony_ci	 .auth_first = 0,
32788c2ecf20Sopenharmony_ci	 },
32798c2ecf20Sopenharmony_ci	{
32808c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
32818c2ecf20Sopenharmony_ci	 .alg.aead = {
32828c2ecf20Sopenharmony_ci		 .base = {
32838c2ecf20Sopenharmony_ci			.cra_name = "authenc(hmac(sha1),cbc(des))",
32848c2ecf20Sopenharmony_ci			.cra_driver_name = "authenc-hmac-sha1-cbc-des-iproc",
32858c2ecf20Sopenharmony_ci			.cra_blocksize = DES_BLOCK_SIZE,
32868c2ecf20Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
32878c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
32888c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
32898c2ecf20Sopenharmony_ci		 },
32908c2ecf20Sopenharmony_ci		 .setkey = aead_authenc_setkey,
32918c2ecf20Sopenharmony_ci		 .ivsize = DES_BLOCK_SIZE,
32928c2ecf20Sopenharmony_ci		 .maxauthsize = SHA1_DIGEST_SIZE,
32938c2ecf20Sopenharmony_ci	 },
32948c2ecf20Sopenharmony_ci	 .cipher_info = {
32958c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_DES,
32968c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
32978c2ecf20Sopenharmony_ci			 },
32988c2ecf20Sopenharmony_ci	 .auth_info = {
32998c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA1,
33008c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
33018c2ecf20Sopenharmony_ci		       },
33028c2ecf20Sopenharmony_ci	 .auth_first = 0,
33038c2ecf20Sopenharmony_ci	 },
33048c2ecf20Sopenharmony_ci	{
33058c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
33068c2ecf20Sopenharmony_ci	 .alg.aead = {
33078c2ecf20Sopenharmony_ci		 .base = {
33088c2ecf20Sopenharmony_ci			.cra_name = "authenc(hmac(sha224),cbc(des))",
33098c2ecf20Sopenharmony_ci			.cra_driver_name = "authenc-hmac-sha224-cbc-des-iproc",
33108c2ecf20Sopenharmony_ci			.cra_blocksize = DES_BLOCK_SIZE,
33118c2ecf20Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
33128c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
33138c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
33148c2ecf20Sopenharmony_ci		 },
33158c2ecf20Sopenharmony_ci		 .setkey = aead_authenc_setkey,
33168c2ecf20Sopenharmony_ci		 .ivsize = DES_BLOCK_SIZE,
33178c2ecf20Sopenharmony_ci		 .maxauthsize = SHA224_DIGEST_SIZE,
33188c2ecf20Sopenharmony_ci	 },
33198c2ecf20Sopenharmony_ci	 .cipher_info = {
33208c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_DES,
33218c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
33228c2ecf20Sopenharmony_ci			 },
33238c2ecf20Sopenharmony_ci	 .auth_info = {
33248c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA224,
33258c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
33268c2ecf20Sopenharmony_ci		       },
33278c2ecf20Sopenharmony_ci	 .auth_first = 0,
33288c2ecf20Sopenharmony_ci	 },
33298c2ecf20Sopenharmony_ci	{
33308c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
33318c2ecf20Sopenharmony_ci	 .alg.aead = {
33328c2ecf20Sopenharmony_ci		 .base = {
33338c2ecf20Sopenharmony_ci			.cra_name = "authenc(hmac(sha256),cbc(des))",
33348c2ecf20Sopenharmony_ci			.cra_driver_name = "authenc-hmac-sha256-cbc-des-iproc",
33358c2ecf20Sopenharmony_ci			.cra_blocksize = DES_BLOCK_SIZE,
33368c2ecf20Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
33378c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
33388c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
33398c2ecf20Sopenharmony_ci		 },
33408c2ecf20Sopenharmony_ci		 .setkey = aead_authenc_setkey,
33418c2ecf20Sopenharmony_ci		 .ivsize = DES_BLOCK_SIZE,
33428c2ecf20Sopenharmony_ci		 .maxauthsize = SHA256_DIGEST_SIZE,
33438c2ecf20Sopenharmony_ci	 },
33448c2ecf20Sopenharmony_ci	 .cipher_info = {
33458c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_DES,
33468c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
33478c2ecf20Sopenharmony_ci			 },
33488c2ecf20Sopenharmony_ci	 .auth_info = {
33498c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA256,
33508c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
33518c2ecf20Sopenharmony_ci		       },
33528c2ecf20Sopenharmony_ci	 .auth_first = 0,
33538c2ecf20Sopenharmony_ci	 },
33548c2ecf20Sopenharmony_ci	{
33558c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
33568c2ecf20Sopenharmony_ci	 .alg.aead = {
33578c2ecf20Sopenharmony_ci		 .base = {
33588c2ecf20Sopenharmony_ci			.cra_name = "authenc(hmac(sha384),cbc(des))",
33598c2ecf20Sopenharmony_ci			.cra_driver_name = "authenc-hmac-sha384-cbc-des-iproc",
33608c2ecf20Sopenharmony_ci			.cra_blocksize = DES_BLOCK_SIZE,
33618c2ecf20Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
33628c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
33638c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
33648c2ecf20Sopenharmony_ci		 },
33658c2ecf20Sopenharmony_ci		 .setkey = aead_authenc_setkey,
33668c2ecf20Sopenharmony_ci		 .ivsize = DES_BLOCK_SIZE,
33678c2ecf20Sopenharmony_ci		 .maxauthsize = SHA384_DIGEST_SIZE,
33688c2ecf20Sopenharmony_ci	 },
33698c2ecf20Sopenharmony_ci	 .cipher_info = {
33708c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_DES,
33718c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
33728c2ecf20Sopenharmony_ci			 },
33738c2ecf20Sopenharmony_ci	 .auth_info = {
33748c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA384,
33758c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
33768c2ecf20Sopenharmony_ci		       },
33778c2ecf20Sopenharmony_ci	 .auth_first = 0,
33788c2ecf20Sopenharmony_ci	 },
33798c2ecf20Sopenharmony_ci	{
33808c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
33818c2ecf20Sopenharmony_ci	 .alg.aead = {
33828c2ecf20Sopenharmony_ci		 .base = {
33838c2ecf20Sopenharmony_ci			.cra_name = "authenc(hmac(sha512),cbc(des))",
33848c2ecf20Sopenharmony_ci			.cra_driver_name = "authenc-hmac-sha512-cbc-des-iproc",
33858c2ecf20Sopenharmony_ci			.cra_blocksize = DES_BLOCK_SIZE,
33868c2ecf20Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
33878c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
33888c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
33898c2ecf20Sopenharmony_ci		 },
33908c2ecf20Sopenharmony_ci		 .setkey = aead_authenc_setkey,
33918c2ecf20Sopenharmony_ci		 .ivsize = DES_BLOCK_SIZE,
33928c2ecf20Sopenharmony_ci		 .maxauthsize = SHA512_DIGEST_SIZE,
33938c2ecf20Sopenharmony_ci	 },
33948c2ecf20Sopenharmony_ci	 .cipher_info = {
33958c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_DES,
33968c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
33978c2ecf20Sopenharmony_ci			 },
33988c2ecf20Sopenharmony_ci	 .auth_info = {
33998c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA512,
34008c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
34018c2ecf20Sopenharmony_ci		       },
34028c2ecf20Sopenharmony_ci	 .auth_first = 0,
34038c2ecf20Sopenharmony_ci	 },
34048c2ecf20Sopenharmony_ci	{
34058c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
34068c2ecf20Sopenharmony_ci	 .alg.aead = {
34078c2ecf20Sopenharmony_ci		 .base = {
34088c2ecf20Sopenharmony_ci			.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
34098c2ecf20Sopenharmony_ci			.cra_driver_name = "authenc-hmac-md5-cbc-des3-iproc",
34108c2ecf20Sopenharmony_ci			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
34118c2ecf20Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
34128c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
34138c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
34148c2ecf20Sopenharmony_ci		 },
34158c2ecf20Sopenharmony_ci		 .setkey = aead_authenc_setkey,
34168c2ecf20Sopenharmony_ci		 .ivsize = DES3_EDE_BLOCK_SIZE,
34178c2ecf20Sopenharmony_ci		 .maxauthsize = MD5_DIGEST_SIZE,
34188c2ecf20Sopenharmony_ci	 },
34198c2ecf20Sopenharmony_ci	 .cipher_info = {
34208c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_3DES,
34218c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
34228c2ecf20Sopenharmony_ci			 },
34238c2ecf20Sopenharmony_ci	 .auth_info = {
34248c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_MD5,
34258c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
34268c2ecf20Sopenharmony_ci		       },
34278c2ecf20Sopenharmony_ci	 .auth_first = 0,
34288c2ecf20Sopenharmony_ci	 },
34298c2ecf20Sopenharmony_ci	{
34308c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
34318c2ecf20Sopenharmony_ci	 .alg.aead = {
34328c2ecf20Sopenharmony_ci		 .base = {
34338c2ecf20Sopenharmony_ci			.cra_name = "authenc(hmac(sha1),cbc(des3_ede))",
34348c2ecf20Sopenharmony_ci			.cra_driver_name = "authenc-hmac-sha1-cbc-des3-iproc",
34358c2ecf20Sopenharmony_ci			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
34368c2ecf20Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
34378c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
34388c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
34398c2ecf20Sopenharmony_ci		 },
34408c2ecf20Sopenharmony_ci		 .setkey = aead_authenc_setkey,
34418c2ecf20Sopenharmony_ci		 .ivsize = DES3_EDE_BLOCK_SIZE,
34428c2ecf20Sopenharmony_ci		 .maxauthsize = SHA1_DIGEST_SIZE,
34438c2ecf20Sopenharmony_ci	 },
34448c2ecf20Sopenharmony_ci	 .cipher_info = {
34458c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_3DES,
34468c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
34478c2ecf20Sopenharmony_ci			 },
34488c2ecf20Sopenharmony_ci	 .auth_info = {
34498c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA1,
34508c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
34518c2ecf20Sopenharmony_ci		       },
34528c2ecf20Sopenharmony_ci	 .auth_first = 0,
34538c2ecf20Sopenharmony_ci	 },
34548c2ecf20Sopenharmony_ci	{
34558c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
34568c2ecf20Sopenharmony_ci	 .alg.aead = {
34578c2ecf20Sopenharmony_ci		 .base = {
34588c2ecf20Sopenharmony_ci			.cra_name = "authenc(hmac(sha224),cbc(des3_ede))",
34598c2ecf20Sopenharmony_ci			.cra_driver_name = "authenc-hmac-sha224-cbc-des3-iproc",
34608c2ecf20Sopenharmony_ci			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
34618c2ecf20Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
34628c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
34638c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
34648c2ecf20Sopenharmony_ci		 },
34658c2ecf20Sopenharmony_ci		 .setkey = aead_authenc_setkey,
34668c2ecf20Sopenharmony_ci		 .ivsize = DES3_EDE_BLOCK_SIZE,
34678c2ecf20Sopenharmony_ci		 .maxauthsize = SHA224_DIGEST_SIZE,
34688c2ecf20Sopenharmony_ci	 },
34698c2ecf20Sopenharmony_ci	 .cipher_info = {
34708c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_3DES,
34718c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
34728c2ecf20Sopenharmony_ci			 },
34738c2ecf20Sopenharmony_ci	 .auth_info = {
34748c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA224,
34758c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
34768c2ecf20Sopenharmony_ci		       },
34778c2ecf20Sopenharmony_ci	 .auth_first = 0,
34788c2ecf20Sopenharmony_ci	 },
34798c2ecf20Sopenharmony_ci	{
34808c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
34818c2ecf20Sopenharmony_ci	 .alg.aead = {
34828c2ecf20Sopenharmony_ci		 .base = {
34838c2ecf20Sopenharmony_ci			.cra_name = "authenc(hmac(sha256),cbc(des3_ede))",
34848c2ecf20Sopenharmony_ci			.cra_driver_name = "authenc-hmac-sha256-cbc-des3-iproc",
34858c2ecf20Sopenharmony_ci			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
34868c2ecf20Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
34878c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
34888c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
34898c2ecf20Sopenharmony_ci		 },
34908c2ecf20Sopenharmony_ci		 .setkey = aead_authenc_setkey,
34918c2ecf20Sopenharmony_ci		 .ivsize = DES3_EDE_BLOCK_SIZE,
34928c2ecf20Sopenharmony_ci		 .maxauthsize = SHA256_DIGEST_SIZE,
34938c2ecf20Sopenharmony_ci	 },
34948c2ecf20Sopenharmony_ci	 .cipher_info = {
34958c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_3DES,
34968c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
34978c2ecf20Sopenharmony_ci			 },
34988c2ecf20Sopenharmony_ci	 .auth_info = {
34998c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA256,
35008c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
35018c2ecf20Sopenharmony_ci		       },
35028c2ecf20Sopenharmony_ci	 .auth_first = 0,
35038c2ecf20Sopenharmony_ci	 },
35048c2ecf20Sopenharmony_ci	{
35058c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
35068c2ecf20Sopenharmony_ci	 .alg.aead = {
35078c2ecf20Sopenharmony_ci		 .base = {
35088c2ecf20Sopenharmony_ci			.cra_name = "authenc(hmac(sha384),cbc(des3_ede))",
35098c2ecf20Sopenharmony_ci			.cra_driver_name = "authenc-hmac-sha384-cbc-des3-iproc",
35108c2ecf20Sopenharmony_ci			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
35118c2ecf20Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
35128c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
35138c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
35148c2ecf20Sopenharmony_ci		 },
35158c2ecf20Sopenharmony_ci		 .setkey = aead_authenc_setkey,
35168c2ecf20Sopenharmony_ci		 .ivsize = DES3_EDE_BLOCK_SIZE,
35178c2ecf20Sopenharmony_ci		 .maxauthsize = SHA384_DIGEST_SIZE,
35188c2ecf20Sopenharmony_ci	 },
35198c2ecf20Sopenharmony_ci	 .cipher_info = {
35208c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_3DES,
35218c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
35228c2ecf20Sopenharmony_ci			 },
35238c2ecf20Sopenharmony_ci	 .auth_info = {
35248c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA384,
35258c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
35268c2ecf20Sopenharmony_ci		       },
35278c2ecf20Sopenharmony_ci	 .auth_first = 0,
35288c2ecf20Sopenharmony_ci	 },
35298c2ecf20Sopenharmony_ci	{
35308c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AEAD,
35318c2ecf20Sopenharmony_ci	 .alg.aead = {
35328c2ecf20Sopenharmony_ci		 .base = {
35338c2ecf20Sopenharmony_ci			.cra_name = "authenc(hmac(sha512),cbc(des3_ede))",
35348c2ecf20Sopenharmony_ci			.cra_driver_name = "authenc-hmac-sha512-cbc-des3-iproc",
35358c2ecf20Sopenharmony_ci			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
35368c2ecf20Sopenharmony_ci			.cra_flags = CRYPTO_ALG_NEED_FALLBACK |
35378c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ASYNC |
35388c2ecf20Sopenharmony_ci				     CRYPTO_ALG_ALLOCATES_MEMORY
35398c2ecf20Sopenharmony_ci		 },
35408c2ecf20Sopenharmony_ci		 .setkey = aead_authenc_setkey,
35418c2ecf20Sopenharmony_ci		 .ivsize = DES3_EDE_BLOCK_SIZE,
35428c2ecf20Sopenharmony_ci		 .maxauthsize = SHA512_DIGEST_SIZE,
35438c2ecf20Sopenharmony_ci	 },
35448c2ecf20Sopenharmony_ci	 .cipher_info = {
35458c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_3DES,
35468c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
35478c2ecf20Sopenharmony_ci			 },
35488c2ecf20Sopenharmony_ci	 .auth_info = {
35498c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA512,
35508c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
35518c2ecf20Sopenharmony_ci		       },
35528c2ecf20Sopenharmony_ci	 .auth_first = 0,
35538c2ecf20Sopenharmony_ci	 },
35548c2ecf20Sopenharmony_ci
35558c2ecf20Sopenharmony_ci/* SKCIPHER algorithms. */
35568c2ecf20Sopenharmony_ci	{
35578c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_SKCIPHER,
35588c2ecf20Sopenharmony_ci	 .alg.skcipher = {
35598c2ecf20Sopenharmony_ci			.base.cra_name = "ofb(des)",
35608c2ecf20Sopenharmony_ci			.base.cra_driver_name = "ofb-des-iproc",
35618c2ecf20Sopenharmony_ci			.base.cra_blocksize = DES_BLOCK_SIZE,
35628c2ecf20Sopenharmony_ci			.min_keysize = DES_KEY_SIZE,
35638c2ecf20Sopenharmony_ci			.max_keysize = DES_KEY_SIZE,
35648c2ecf20Sopenharmony_ci			.ivsize = DES_BLOCK_SIZE,
35658c2ecf20Sopenharmony_ci			},
35668c2ecf20Sopenharmony_ci	 .cipher_info = {
35678c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_DES,
35688c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_OFB,
35698c2ecf20Sopenharmony_ci			 },
35708c2ecf20Sopenharmony_ci	 .auth_info = {
35718c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_NONE,
35728c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_NONE,
35738c2ecf20Sopenharmony_ci		       },
35748c2ecf20Sopenharmony_ci	 },
35758c2ecf20Sopenharmony_ci	{
35768c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_SKCIPHER,
35778c2ecf20Sopenharmony_ci	 .alg.skcipher = {
35788c2ecf20Sopenharmony_ci			.base.cra_name = "cbc(des)",
35798c2ecf20Sopenharmony_ci			.base.cra_driver_name = "cbc-des-iproc",
35808c2ecf20Sopenharmony_ci			.base.cra_blocksize = DES_BLOCK_SIZE,
35818c2ecf20Sopenharmony_ci			.min_keysize = DES_KEY_SIZE,
35828c2ecf20Sopenharmony_ci			.max_keysize = DES_KEY_SIZE,
35838c2ecf20Sopenharmony_ci			.ivsize = DES_BLOCK_SIZE,
35848c2ecf20Sopenharmony_ci			},
35858c2ecf20Sopenharmony_ci	 .cipher_info = {
35868c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_DES,
35878c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
35888c2ecf20Sopenharmony_ci			 },
35898c2ecf20Sopenharmony_ci	 .auth_info = {
35908c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_NONE,
35918c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_NONE,
35928c2ecf20Sopenharmony_ci		       },
35938c2ecf20Sopenharmony_ci	 },
35948c2ecf20Sopenharmony_ci	{
35958c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_SKCIPHER,
35968c2ecf20Sopenharmony_ci	 .alg.skcipher = {
35978c2ecf20Sopenharmony_ci			.base.cra_name = "ecb(des)",
35988c2ecf20Sopenharmony_ci			.base.cra_driver_name = "ecb-des-iproc",
35998c2ecf20Sopenharmony_ci			.base.cra_blocksize = DES_BLOCK_SIZE,
36008c2ecf20Sopenharmony_ci			.min_keysize = DES_KEY_SIZE,
36018c2ecf20Sopenharmony_ci			.max_keysize = DES_KEY_SIZE,
36028c2ecf20Sopenharmony_ci			.ivsize = 0,
36038c2ecf20Sopenharmony_ci			},
36048c2ecf20Sopenharmony_ci	 .cipher_info = {
36058c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_DES,
36068c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_ECB,
36078c2ecf20Sopenharmony_ci			 },
36088c2ecf20Sopenharmony_ci	 .auth_info = {
36098c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_NONE,
36108c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_NONE,
36118c2ecf20Sopenharmony_ci		       },
36128c2ecf20Sopenharmony_ci	 },
36138c2ecf20Sopenharmony_ci	{
36148c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_SKCIPHER,
36158c2ecf20Sopenharmony_ci	 .alg.skcipher = {
36168c2ecf20Sopenharmony_ci			.base.cra_name = "ofb(des3_ede)",
36178c2ecf20Sopenharmony_ci			.base.cra_driver_name = "ofb-des3-iproc",
36188c2ecf20Sopenharmony_ci			.base.cra_blocksize = DES3_EDE_BLOCK_SIZE,
36198c2ecf20Sopenharmony_ci			.min_keysize = DES3_EDE_KEY_SIZE,
36208c2ecf20Sopenharmony_ci			.max_keysize = DES3_EDE_KEY_SIZE,
36218c2ecf20Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
36228c2ecf20Sopenharmony_ci			},
36238c2ecf20Sopenharmony_ci	 .cipher_info = {
36248c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_3DES,
36258c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_OFB,
36268c2ecf20Sopenharmony_ci			 },
36278c2ecf20Sopenharmony_ci	 .auth_info = {
36288c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_NONE,
36298c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_NONE,
36308c2ecf20Sopenharmony_ci		       },
36318c2ecf20Sopenharmony_ci	 },
36328c2ecf20Sopenharmony_ci	{
36338c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_SKCIPHER,
36348c2ecf20Sopenharmony_ci	 .alg.skcipher = {
36358c2ecf20Sopenharmony_ci			.base.cra_name = "cbc(des3_ede)",
36368c2ecf20Sopenharmony_ci			.base.cra_driver_name = "cbc-des3-iproc",
36378c2ecf20Sopenharmony_ci			.base.cra_blocksize = DES3_EDE_BLOCK_SIZE,
36388c2ecf20Sopenharmony_ci			.min_keysize = DES3_EDE_KEY_SIZE,
36398c2ecf20Sopenharmony_ci			.max_keysize = DES3_EDE_KEY_SIZE,
36408c2ecf20Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
36418c2ecf20Sopenharmony_ci			},
36428c2ecf20Sopenharmony_ci	 .cipher_info = {
36438c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_3DES,
36448c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
36458c2ecf20Sopenharmony_ci			 },
36468c2ecf20Sopenharmony_ci	 .auth_info = {
36478c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_NONE,
36488c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_NONE,
36498c2ecf20Sopenharmony_ci		       },
36508c2ecf20Sopenharmony_ci	 },
36518c2ecf20Sopenharmony_ci	{
36528c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_SKCIPHER,
36538c2ecf20Sopenharmony_ci	 .alg.skcipher = {
36548c2ecf20Sopenharmony_ci			.base.cra_name = "ecb(des3_ede)",
36558c2ecf20Sopenharmony_ci			.base.cra_driver_name = "ecb-des3-iproc",
36568c2ecf20Sopenharmony_ci			.base.cra_blocksize = DES3_EDE_BLOCK_SIZE,
36578c2ecf20Sopenharmony_ci			.min_keysize = DES3_EDE_KEY_SIZE,
36588c2ecf20Sopenharmony_ci			.max_keysize = DES3_EDE_KEY_SIZE,
36598c2ecf20Sopenharmony_ci			.ivsize = 0,
36608c2ecf20Sopenharmony_ci			},
36618c2ecf20Sopenharmony_ci	 .cipher_info = {
36628c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_3DES,
36638c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_ECB,
36648c2ecf20Sopenharmony_ci			 },
36658c2ecf20Sopenharmony_ci	 .auth_info = {
36668c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_NONE,
36678c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_NONE,
36688c2ecf20Sopenharmony_ci		       },
36698c2ecf20Sopenharmony_ci	 },
36708c2ecf20Sopenharmony_ci	{
36718c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_SKCIPHER,
36728c2ecf20Sopenharmony_ci	 .alg.skcipher = {
36738c2ecf20Sopenharmony_ci			.base.cra_name = "ofb(aes)",
36748c2ecf20Sopenharmony_ci			.base.cra_driver_name = "ofb-aes-iproc",
36758c2ecf20Sopenharmony_ci			.base.cra_blocksize = AES_BLOCK_SIZE,
36768c2ecf20Sopenharmony_ci			.min_keysize = AES_MIN_KEY_SIZE,
36778c2ecf20Sopenharmony_ci			.max_keysize = AES_MAX_KEY_SIZE,
36788c2ecf20Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
36798c2ecf20Sopenharmony_ci			},
36808c2ecf20Sopenharmony_ci	 .cipher_info = {
36818c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_AES,
36828c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_OFB,
36838c2ecf20Sopenharmony_ci			 },
36848c2ecf20Sopenharmony_ci	 .auth_info = {
36858c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_NONE,
36868c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_NONE,
36878c2ecf20Sopenharmony_ci		       },
36888c2ecf20Sopenharmony_ci	 },
36898c2ecf20Sopenharmony_ci	{
36908c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_SKCIPHER,
36918c2ecf20Sopenharmony_ci	 .alg.skcipher = {
36928c2ecf20Sopenharmony_ci			.base.cra_name = "cbc(aes)",
36938c2ecf20Sopenharmony_ci			.base.cra_driver_name = "cbc-aes-iproc",
36948c2ecf20Sopenharmony_ci			.base.cra_blocksize = AES_BLOCK_SIZE,
36958c2ecf20Sopenharmony_ci			.min_keysize = AES_MIN_KEY_SIZE,
36968c2ecf20Sopenharmony_ci			.max_keysize = AES_MAX_KEY_SIZE,
36978c2ecf20Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
36988c2ecf20Sopenharmony_ci			},
36998c2ecf20Sopenharmony_ci	 .cipher_info = {
37008c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_AES,
37018c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_CBC,
37028c2ecf20Sopenharmony_ci			 },
37038c2ecf20Sopenharmony_ci	 .auth_info = {
37048c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_NONE,
37058c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_NONE,
37068c2ecf20Sopenharmony_ci		       },
37078c2ecf20Sopenharmony_ci	 },
37088c2ecf20Sopenharmony_ci	{
37098c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_SKCIPHER,
37108c2ecf20Sopenharmony_ci	 .alg.skcipher = {
37118c2ecf20Sopenharmony_ci			.base.cra_name = "ecb(aes)",
37128c2ecf20Sopenharmony_ci			.base.cra_driver_name = "ecb-aes-iproc",
37138c2ecf20Sopenharmony_ci			.base.cra_blocksize = AES_BLOCK_SIZE,
37148c2ecf20Sopenharmony_ci			.min_keysize = AES_MIN_KEY_SIZE,
37158c2ecf20Sopenharmony_ci			.max_keysize = AES_MAX_KEY_SIZE,
37168c2ecf20Sopenharmony_ci			.ivsize = 0,
37178c2ecf20Sopenharmony_ci			},
37188c2ecf20Sopenharmony_ci	 .cipher_info = {
37198c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_AES,
37208c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_ECB,
37218c2ecf20Sopenharmony_ci			 },
37228c2ecf20Sopenharmony_ci	 .auth_info = {
37238c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_NONE,
37248c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_NONE,
37258c2ecf20Sopenharmony_ci		       },
37268c2ecf20Sopenharmony_ci	 },
37278c2ecf20Sopenharmony_ci	{
37288c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_SKCIPHER,
37298c2ecf20Sopenharmony_ci	 .alg.skcipher = {
37308c2ecf20Sopenharmony_ci			.base.cra_name = "ctr(aes)",
37318c2ecf20Sopenharmony_ci			.base.cra_driver_name = "ctr-aes-iproc",
37328c2ecf20Sopenharmony_ci			.base.cra_blocksize = AES_BLOCK_SIZE,
37338c2ecf20Sopenharmony_ci			.min_keysize = AES_MIN_KEY_SIZE,
37348c2ecf20Sopenharmony_ci			.max_keysize = AES_MAX_KEY_SIZE,
37358c2ecf20Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
37368c2ecf20Sopenharmony_ci			},
37378c2ecf20Sopenharmony_ci	 .cipher_info = {
37388c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_AES,
37398c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_CTR,
37408c2ecf20Sopenharmony_ci			 },
37418c2ecf20Sopenharmony_ci	 .auth_info = {
37428c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_NONE,
37438c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_NONE,
37448c2ecf20Sopenharmony_ci		       },
37458c2ecf20Sopenharmony_ci	 },
37468c2ecf20Sopenharmony_ci{
37478c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_SKCIPHER,
37488c2ecf20Sopenharmony_ci	 .alg.skcipher = {
37498c2ecf20Sopenharmony_ci			.base.cra_name = "xts(aes)",
37508c2ecf20Sopenharmony_ci			.base.cra_driver_name = "xts-aes-iproc",
37518c2ecf20Sopenharmony_ci			.base.cra_blocksize = AES_BLOCK_SIZE,
37528c2ecf20Sopenharmony_ci			.min_keysize = 2 * AES_MIN_KEY_SIZE,
37538c2ecf20Sopenharmony_ci			.max_keysize = 2 * AES_MAX_KEY_SIZE,
37548c2ecf20Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
37558c2ecf20Sopenharmony_ci			},
37568c2ecf20Sopenharmony_ci	 .cipher_info = {
37578c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_AES,
37588c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_XTS,
37598c2ecf20Sopenharmony_ci			 },
37608c2ecf20Sopenharmony_ci	 .auth_info = {
37618c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_NONE,
37628c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_NONE,
37638c2ecf20Sopenharmony_ci		       },
37648c2ecf20Sopenharmony_ci	 },
37658c2ecf20Sopenharmony_ci
37668c2ecf20Sopenharmony_ci/* AHASH algorithms. */
37678c2ecf20Sopenharmony_ci	{
37688c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
37698c2ecf20Sopenharmony_ci	 .alg.hash = {
37708c2ecf20Sopenharmony_ci		      .halg.digestsize = MD5_DIGEST_SIZE,
37718c2ecf20Sopenharmony_ci		      .halg.base = {
37728c2ecf20Sopenharmony_ci				    .cra_name = "md5",
37738c2ecf20Sopenharmony_ci				    .cra_driver_name = "md5-iproc",
37748c2ecf20Sopenharmony_ci				    .cra_blocksize = MD5_BLOCK_WORDS * 4,
37758c2ecf20Sopenharmony_ci				    .cra_flags = CRYPTO_ALG_ASYNC |
37768c2ecf20Sopenharmony_ci						 CRYPTO_ALG_ALLOCATES_MEMORY,
37778c2ecf20Sopenharmony_ci				}
37788c2ecf20Sopenharmony_ci		      },
37798c2ecf20Sopenharmony_ci	 .cipher_info = {
37808c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
37818c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
37828c2ecf20Sopenharmony_ci			 },
37838c2ecf20Sopenharmony_ci	 .auth_info = {
37848c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_MD5,
37858c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HASH,
37868c2ecf20Sopenharmony_ci		       },
37878c2ecf20Sopenharmony_ci	 },
37888c2ecf20Sopenharmony_ci	{
37898c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
37908c2ecf20Sopenharmony_ci	 .alg.hash = {
37918c2ecf20Sopenharmony_ci		      .halg.digestsize = MD5_DIGEST_SIZE,
37928c2ecf20Sopenharmony_ci		      .halg.base = {
37938c2ecf20Sopenharmony_ci				    .cra_name = "hmac(md5)",
37948c2ecf20Sopenharmony_ci				    .cra_driver_name = "hmac-md5-iproc",
37958c2ecf20Sopenharmony_ci				    .cra_blocksize = MD5_BLOCK_WORDS * 4,
37968c2ecf20Sopenharmony_ci				}
37978c2ecf20Sopenharmony_ci		      },
37988c2ecf20Sopenharmony_ci	 .cipher_info = {
37998c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
38008c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
38018c2ecf20Sopenharmony_ci			 },
38028c2ecf20Sopenharmony_ci	 .auth_info = {
38038c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_MD5,
38048c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
38058c2ecf20Sopenharmony_ci		       },
38068c2ecf20Sopenharmony_ci	 },
38078c2ecf20Sopenharmony_ci	{.type = CRYPTO_ALG_TYPE_AHASH,
38088c2ecf20Sopenharmony_ci	 .alg.hash = {
38098c2ecf20Sopenharmony_ci		      .halg.digestsize = SHA1_DIGEST_SIZE,
38108c2ecf20Sopenharmony_ci		      .halg.base = {
38118c2ecf20Sopenharmony_ci				    .cra_name = "sha1",
38128c2ecf20Sopenharmony_ci				    .cra_driver_name = "sha1-iproc",
38138c2ecf20Sopenharmony_ci				    .cra_blocksize = SHA1_BLOCK_SIZE,
38148c2ecf20Sopenharmony_ci				}
38158c2ecf20Sopenharmony_ci		      },
38168c2ecf20Sopenharmony_ci	 .cipher_info = {
38178c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
38188c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
38198c2ecf20Sopenharmony_ci			 },
38208c2ecf20Sopenharmony_ci	 .auth_info = {
38218c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA1,
38228c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HASH,
38238c2ecf20Sopenharmony_ci		       },
38248c2ecf20Sopenharmony_ci	 },
38258c2ecf20Sopenharmony_ci	{.type = CRYPTO_ALG_TYPE_AHASH,
38268c2ecf20Sopenharmony_ci	 .alg.hash = {
38278c2ecf20Sopenharmony_ci		      .halg.digestsize = SHA1_DIGEST_SIZE,
38288c2ecf20Sopenharmony_ci		      .halg.base = {
38298c2ecf20Sopenharmony_ci				    .cra_name = "hmac(sha1)",
38308c2ecf20Sopenharmony_ci				    .cra_driver_name = "hmac-sha1-iproc",
38318c2ecf20Sopenharmony_ci				    .cra_blocksize = SHA1_BLOCK_SIZE,
38328c2ecf20Sopenharmony_ci				}
38338c2ecf20Sopenharmony_ci		      },
38348c2ecf20Sopenharmony_ci	 .cipher_info = {
38358c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
38368c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
38378c2ecf20Sopenharmony_ci			 },
38388c2ecf20Sopenharmony_ci	 .auth_info = {
38398c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA1,
38408c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
38418c2ecf20Sopenharmony_ci		       },
38428c2ecf20Sopenharmony_ci	 },
38438c2ecf20Sopenharmony_ci	{.type = CRYPTO_ALG_TYPE_AHASH,
38448c2ecf20Sopenharmony_ci	 .alg.hash = {
38458c2ecf20Sopenharmony_ci			.halg.digestsize = SHA224_DIGEST_SIZE,
38468c2ecf20Sopenharmony_ci			.halg.base = {
38478c2ecf20Sopenharmony_ci				    .cra_name = "sha224",
38488c2ecf20Sopenharmony_ci				    .cra_driver_name = "sha224-iproc",
38498c2ecf20Sopenharmony_ci				    .cra_blocksize = SHA224_BLOCK_SIZE,
38508c2ecf20Sopenharmony_ci			}
38518c2ecf20Sopenharmony_ci		      },
38528c2ecf20Sopenharmony_ci	 .cipher_info = {
38538c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
38548c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
38558c2ecf20Sopenharmony_ci			 },
38568c2ecf20Sopenharmony_ci	 .auth_info = {
38578c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA224,
38588c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HASH,
38598c2ecf20Sopenharmony_ci		       },
38608c2ecf20Sopenharmony_ci	 },
38618c2ecf20Sopenharmony_ci	{.type = CRYPTO_ALG_TYPE_AHASH,
38628c2ecf20Sopenharmony_ci	 .alg.hash = {
38638c2ecf20Sopenharmony_ci		      .halg.digestsize = SHA224_DIGEST_SIZE,
38648c2ecf20Sopenharmony_ci		      .halg.base = {
38658c2ecf20Sopenharmony_ci				    .cra_name = "hmac(sha224)",
38668c2ecf20Sopenharmony_ci				    .cra_driver_name = "hmac-sha224-iproc",
38678c2ecf20Sopenharmony_ci				    .cra_blocksize = SHA224_BLOCK_SIZE,
38688c2ecf20Sopenharmony_ci				}
38698c2ecf20Sopenharmony_ci		      },
38708c2ecf20Sopenharmony_ci	 .cipher_info = {
38718c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
38728c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
38738c2ecf20Sopenharmony_ci			 },
38748c2ecf20Sopenharmony_ci	 .auth_info = {
38758c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA224,
38768c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
38778c2ecf20Sopenharmony_ci		       },
38788c2ecf20Sopenharmony_ci	 },
38798c2ecf20Sopenharmony_ci	{.type = CRYPTO_ALG_TYPE_AHASH,
38808c2ecf20Sopenharmony_ci	 .alg.hash = {
38818c2ecf20Sopenharmony_ci		      .halg.digestsize = SHA256_DIGEST_SIZE,
38828c2ecf20Sopenharmony_ci		      .halg.base = {
38838c2ecf20Sopenharmony_ci				    .cra_name = "sha256",
38848c2ecf20Sopenharmony_ci				    .cra_driver_name = "sha256-iproc",
38858c2ecf20Sopenharmony_ci				    .cra_blocksize = SHA256_BLOCK_SIZE,
38868c2ecf20Sopenharmony_ci				}
38878c2ecf20Sopenharmony_ci		      },
38888c2ecf20Sopenharmony_ci	 .cipher_info = {
38898c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
38908c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
38918c2ecf20Sopenharmony_ci			 },
38928c2ecf20Sopenharmony_ci	 .auth_info = {
38938c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA256,
38948c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HASH,
38958c2ecf20Sopenharmony_ci		       },
38968c2ecf20Sopenharmony_ci	 },
38978c2ecf20Sopenharmony_ci	{.type = CRYPTO_ALG_TYPE_AHASH,
38988c2ecf20Sopenharmony_ci	 .alg.hash = {
38998c2ecf20Sopenharmony_ci		      .halg.digestsize = SHA256_DIGEST_SIZE,
39008c2ecf20Sopenharmony_ci		      .halg.base = {
39018c2ecf20Sopenharmony_ci				    .cra_name = "hmac(sha256)",
39028c2ecf20Sopenharmony_ci				    .cra_driver_name = "hmac-sha256-iproc",
39038c2ecf20Sopenharmony_ci				    .cra_blocksize = SHA256_BLOCK_SIZE,
39048c2ecf20Sopenharmony_ci				}
39058c2ecf20Sopenharmony_ci		      },
39068c2ecf20Sopenharmony_ci	 .cipher_info = {
39078c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
39088c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
39098c2ecf20Sopenharmony_ci			 },
39108c2ecf20Sopenharmony_ci	 .auth_info = {
39118c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA256,
39128c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
39138c2ecf20Sopenharmony_ci		       },
39148c2ecf20Sopenharmony_ci	 },
39158c2ecf20Sopenharmony_ci	{
39168c2ecf20Sopenharmony_ci	.type = CRYPTO_ALG_TYPE_AHASH,
39178c2ecf20Sopenharmony_ci	 .alg.hash = {
39188c2ecf20Sopenharmony_ci		      .halg.digestsize = SHA384_DIGEST_SIZE,
39198c2ecf20Sopenharmony_ci		      .halg.base = {
39208c2ecf20Sopenharmony_ci				    .cra_name = "sha384",
39218c2ecf20Sopenharmony_ci				    .cra_driver_name = "sha384-iproc",
39228c2ecf20Sopenharmony_ci				    .cra_blocksize = SHA384_BLOCK_SIZE,
39238c2ecf20Sopenharmony_ci				}
39248c2ecf20Sopenharmony_ci		      },
39258c2ecf20Sopenharmony_ci	 .cipher_info = {
39268c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
39278c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
39288c2ecf20Sopenharmony_ci			 },
39298c2ecf20Sopenharmony_ci	 .auth_info = {
39308c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA384,
39318c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HASH,
39328c2ecf20Sopenharmony_ci		       },
39338c2ecf20Sopenharmony_ci	 },
39348c2ecf20Sopenharmony_ci	{
39358c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
39368c2ecf20Sopenharmony_ci	 .alg.hash = {
39378c2ecf20Sopenharmony_ci		      .halg.digestsize = SHA384_DIGEST_SIZE,
39388c2ecf20Sopenharmony_ci		      .halg.base = {
39398c2ecf20Sopenharmony_ci				    .cra_name = "hmac(sha384)",
39408c2ecf20Sopenharmony_ci				    .cra_driver_name = "hmac-sha384-iproc",
39418c2ecf20Sopenharmony_ci				    .cra_blocksize = SHA384_BLOCK_SIZE,
39428c2ecf20Sopenharmony_ci				}
39438c2ecf20Sopenharmony_ci		      },
39448c2ecf20Sopenharmony_ci	 .cipher_info = {
39458c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
39468c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
39478c2ecf20Sopenharmony_ci			 },
39488c2ecf20Sopenharmony_ci	 .auth_info = {
39498c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA384,
39508c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
39518c2ecf20Sopenharmony_ci		       },
39528c2ecf20Sopenharmony_ci	 },
39538c2ecf20Sopenharmony_ci	{
39548c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
39558c2ecf20Sopenharmony_ci	 .alg.hash = {
39568c2ecf20Sopenharmony_ci		      .halg.digestsize = SHA512_DIGEST_SIZE,
39578c2ecf20Sopenharmony_ci		      .halg.base = {
39588c2ecf20Sopenharmony_ci				    .cra_name = "sha512",
39598c2ecf20Sopenharmony_ci				    .cra_driver_name = "sha512-iproc",
39608c2ecf20Sopenharmony_ci				    .cra_blocksize = SHA512_BLOCK_SIZE,
39618c2ecf20Sopenharmony_ci				}
39628c2ecf20Sopenharmony_ci		      },
39638c2ecf20Sopenharmony_ci	 .cipher_info = {
39648c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
39658c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
39668c2ecf20Sopenharmony_ci			 },
39678c2ecf20Sopenharmony_ci	 .auth_info = {
39688c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA512,
39698c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HASH,
39708c2ecf20Sopenharmony_ci		       },
39718c2ecf20Sopenharmony_ci	 },
39728c2ecf20Sopenharmony_ci	{
39738c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
39748c2ecf20Sopenharmony_ci	 .alg.hash = {
39758c2ecf20Sopenharmony_ci		      .halg.digestsize = SHA512_DIGEST_SIZE,
39768c2ecf20Sopenharmony_ci		      .halg.base = {
39778c2ecf20Sopenharmony_ci				    .cra_name = "hmac(sha512)",
39788c2ecf20Sopenharmony_ci				    .cra_driver_name = "hmac-sha512-iproc",
39798c2ecf20Sopenharmony_ci				    .cra_blocksize = SHA512_BLOCK_SIZE,
39808c2ecf20Sopenharmony_ci				}
39818c2ecf20Sopenharmony_ci		      },
39828c2ecf20Sopenharmony_ci	 .cipher_info = {
39838c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
39848c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
39858c2ecf20Sopenharmony_ci			 },
39868c2ecf20Sopenharmony_ci	 .auth_info = {
39878c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA512,
39888c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
39898c2ecf20Sopenharmony_ci		       },
39908c2ecf20Sopenharmony_ci	 },
39918c2ecf20Sopenharmony_ci	{
39928c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
39938c2ecf20Sopenharmony_ci	 .alg.hash = {
39948c2ecf20Sopenharmony_ci		      .halg.digestsize = SHA3_224_DIGEST_SIZE,
39958c2ecf20Sopenharmony_ci		      .halg.base = {
39968c2ecf20Sopenharmony_ci				    .cra_name = "sha3-224",
39978c2ecf20Sopenharmony_ci				    .cra_driver_name = "sha3-224-iproc",
39988c2ecf20Sopenharmony_ci				    .cra_blocksize = SHA3_224_BLOCK_SIZE,
39998c2ecf20Sopenharmony_ci				}
40008c2ecf20Sopenharmony_ci		      },
40018c2ecf20Sopenharmony_ci	 .cipher_info = {
40028c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
40038c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
40048c2ecf20Sopenharmony_ci			 },
40058c2ecf20Sopenharmony_ci	 .auth_info = {
40068c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA3_224,
40078c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HASH,
40088c2ecf20Sopenharmony_ci		       },
40098c2ecf20Sopenharmony_ci	 },
40108c2ecf20Sopenharmony_ci	{
40118c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
40128c2ecf20Sopenharmony_ci	 .alg.hash = {
40138c2ecf20Sopenharmony_ci		      .halg.digestsize = SHA3_224_DIGEST_SIZE,
40148c2ecf20Sopenharmony_ci		      .halg.base = {
40158c2ecf20Sopenharmony_ci				    .cra_name = "hmac(sha3-224)",
40168c2ecf20Sopenharmony_ci				    .cra_driver_name = "hmac-sha3-224-iproc",
40178c2ecf20Sopenharmony_ci				    .cra_blocksize = SHA3_224_BLOCK_SIZE,
40188c2ecf20Sopenharmony_ci				}
40198c2ecf20Sopenharmony_ci		      },
40208c2ecf20Sopenharmony_ci	 .cipher_info = {
40218c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
40228c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
40238c2ecf20Sopenharmony_ci			 },
40248c2ecf20Sopenharmony_ci	 .auth_info = {
40258c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA3_224,
40268c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HMAC
40278c2ecf20Sopenharmony_ci		       },
40288c2ecf20Sopenharmony_ci	 },
40298c2ecf20Sopenharmony_ci	{
40308c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
40318c2ecf20Sopenharmony_ci	 .alg.hash = {
40328c2ecf20Sopenharmony_ci		      .halg.digestsize = SHA3_256_DIGEST_SIZE,
40338c2ecf20Sopenharmony_ci		      .halg.base = {
40348c2ecf20Sopenharmony_ci				    .cra_name = "sha3-256",
40358c2ecf20Sopenharmony_ci				    .cra_driver_name = "sha3-256-iproc",
40368c2ecf20Sopenharmony_ci				    .cra_blocksize = SHA3_256_BLOCK_SIZE,
40378c2ecf20Sopenharmony_ci				}
40388c2ecf20Sopenharmony_ci		      },
40398c2ecf20Sopenharmony_ci	 .cipher_info = {
40408c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
40418c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
40428c2ecf20Sopenharmony_ci			 },
40438c2ecf20Sopenharmony_ci	 .auth_info = {
40448c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA3_256,
40458c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HASH,
40468c2ecf20Sopenharmony_ci		       },
40478c2ecf20Sopenharmony_ci	 },
40488c2ecf20Sopenharmony_ci	{
40498c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
40508c2ecf20Sopenharmony_ci	 .alg.hash = {
40518c2ecf20Sopenharmony_ci		      .halg.digestsize = SHA3_256_DIGEST_SIZE,
40528c2ecf20Sopenharmony_ci		      .halg.base = {
40538c2ecf20Sopenharmony_ci				    .cra_name = "hmac(sha3-256)",
40548c2ecf20Sopenharmony_ci				    .cra_driver_name = "hmac-sha3-256-iproc",
40558c2ecf20Sopenharmony_ci				    .cra_blocksize = SHA3_256_BLOCK_SIZE,
40568c2ecf20Sopenharmony_ci				}
40578c2ecf20Sopenharmony_ci		      },
40588c2ecf20Sopenharmony_ci	 .cipher_info = {
40598c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
40608c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
40618c2ecf20Sopenharmony_ci			 },
40628c2ecf20Sopenharmony_ci	 .auth_info = {
40638c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA3_256,
40648c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
40658c2ecf20Sopenharmony_ci		       },
40668c2ecf20Sopenharmony_ci	 },
40678c2ecf20Sopenharmony_ci	{
40688c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
40698c2ecf20Sopenharmony_ci	 .alg.hash = {
40708c2ecf20Sopenharmony_ci		      .halg.digestsize = SHA3_384_DIGEST_SIZE,
40718c2ecf20Sopenharmony_ci		      .halg.base = {
40728c2ecf20Sopenharmony_ci				    .cra_name = "sha3-384",
40738c2ecf20Sopenharmony_ci				    .cra_driver_name = "sha3-384-iproc",
40748c2ecf20Sopenharmony_ci				    .cra_blocksize = SHA3_224_BLOCK_SIZE,
40758c2ecf20Sopenharmony_ci				}
40768c2ecf20Sopenharmony_ci		      },
40778c2ecf20Sopenharmony_ci	 .cipher_info = {
40788c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
40798c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
40808c2ecf20Sopenharmony_ci			 },
40818c2ecf20Sopenharmony_ci	 .auth_info = {
40828c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA3_384,
40838c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HASH,
40848c2ecf20Sopenharmony_ci		       },
40858c2ecf20Sopenharmony_ci	 },
40868c2ecf20Sopenharmony_ci	{
40878c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
40888c2ecf20Sopenharmony_ci	 .alg.hash = {
40898c2ecf20Sopenharmony_ci		      .halg.digestsize = SHA3_384_DIGEST_SIZE,
40908c2ecf20Sopenharmony_ci		      .halg.base = {
40918c2ecf20Sopenharmony_ci				    .cra_name = "hmac(sha3-384)",
40928c2ecf20Sopenharmony_ci				    .cra_driver_name = "hmac-sha3-384-iproc",
40938c2ecf20Sopenharmony_ci				    .cra_blocksize = SHA3_384_BLOCK_SIZE,
40948c2ecf20Sopenharmony_ci				}
40958c2ecf20Sopenharmony_ci		      },
40968c2ecf20Sopenharmony_ci	 .cipher_info = {
40978c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
40988c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
40998c2ecf20Sopenharmony_ci			 },
41008c2ecf20Sopenharmony_ci	 .auth_info = {
41018c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA3_384,
41028c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
41038c2ecf20Sopenharmony_ci		       },
41048c2ecf20Sopenharmony_ci	 },
41058c2ecf20Sopenharmony_ci	{
41068c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
41078c2ecf20Sopenharmony_ci	 .alg.hash = {
41088c2ecf20Sopenharmony_ci		      .halg.digestsize = SHA3_512_DIGEST_SIZE,
41098c2ecf20Sopenharmony_ci		      .halg.base = {
41108c2ecf20Sopenharmony_ci				    .cra_name = "sha3-512",
41118c2ecf20Sopenharmony_ci				    .cra_driver_name = "sha3-512-iproc",
41128c2ecf20Sopenharmony_ci				    .cra_blocksize = SHA3_512_BLOCK_SIZE,
41138c2ecf20Sopenharmony_ci				}
41148c2ecf20Sopenharmony_ci		      },
41158c2ecf20Sopenharmony_ci	 .cipher_info = {
41168c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
41178c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
41188c2ecf20Sopenharmony_ci			 },
41198c2ecf20Sopenharmony_ci	 .auth_info = {
41208c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA3_512,
41218c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HASH,
41228c2ecf20Sopenharmony_ci		       },
41238c2ecf20Sopenharmony_ci	 },
41248c2ecf20Sopenharmony_ci	{
41258c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
41268c2ecf20Sopenharmony_ci	 .alg.hash = {
41278c2ecf20Sopenharmony_ci		      .halg.digestsize = SHA3_512_DIGEST_SIZE,
41288c2ecf20Sopenharmony_ci		      .halg.base = {
41298c2ecf20Sopenharmony_ci				    .cra_name = "hmac(sha3-512)",
41308c2ecf20Sopenharmony_ci				    .cra_driver_name = "hmac-sha3-512-iproc",
41318c2ecf20Sopenharmony_ci				    .cra_blocksize = SHA3_512_BLOCK_SIZE,
41328c2ecf20Sopenharmony_ci				}
41338c2ecf20Sopenharmony_ci		      },
41348c2ecf20Sopenharmony_ci	 .cipher_info = {
41358c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
41368c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
41378c2ecf20Sopenharmony_ci			 },
41388c2ecf20Sopenharmony_ci	 .auth_info = {
41398c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_SHA3_512,
41408c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_HMAC,
41418c2ecf20Sopenharmony_ci		       },
41428c2ecf20Sopenharmony_ci	 },
41438c2ecf20Sopenharmony_ci	{
41448c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
41458c2ecf20Sopenharmony_ci	 .alg.hash = {
41468c2ecf20Sopenharmony_ci		      .halg.digestsize = AES_BLOCK_SIZE,
41478c2ecf20Sopenharmony_ci		      .halg.base = {
41488c2ecf20Sopenharmony_ci				    .cra_name = "xcbc(aes)",
41498c2ecf20Sopenharmony_ci				    .cra_driver_name = "xcbc-aes-iproc",
41508c2ecf20Sopenharmony_ci				    .cra_blocksize = AES_BLOCK_SIZE,
41518c2ecf20Sopenharmony_ci				}
41528c2ecf20Sopenharmony_ci		      },
41538c2ecf20Sopenharmony_ci	 .cipher_info = {
41548c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
41558c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
41568c2ecf20Sopenharmony_ci			 },
41578c2ecf20Sopenharmony_ci	 .auth_info = {
41588c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_AES,
41598c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_XCBC,
41608c2ecf20Sopenharmony_ci		       },
41618c2ecf20Sopenharmony_ci	 },
41628c2ecf20Sopenharmony_ci	{
41638c2ecf20Sopenharmony_ci	 .type = CRYPTO_ALG_TYPE_AHASH,
41648c2ecf20Sopenharmony_ci	 .alg.hash = {
41658c2ecf20Sopenharmony_ci		      .halg.digestsize = AES_BLOCK_SIZE,
41668c2ecf20Sopenharmony_ci		      .halg.base = {
41678c2ecf20Sopenharmony_ci				    .cra_name = "cmac(aes)",
41688c2ecf20Sopenharmony_ci				    .cra_driver_name = "cmac-aes-iproc",
41698c2ecf20Sopenharmony_ci				    .cra_blocksize = AES_BLOCK_SIZE,
41708c2ecf20Sopenharmony_ci				}
41718c2ecf20Sopenharmony_ci		      },
41728c2ecf20Sopenharmony_ci	 .cipher_info = {
41738c2ecf20Sopenharmony_ci			 .alg = CIPHER_ALG_NONE,
41748c2ecf20Sopenharmony_ci			 .mode = CIPHER_MODE_NONE,
41758c2ecf20Sopenharmony_ci			 },
41768c2ecf20Sopenharmony_ci	 .auth_info = {
41778c2ecf20Sopenharmony_ci		       .alg = HASH_ALG_AES,
41788c2ecf20Sopenharmony_ci		       .mode = HASH_MODE_CMAC,
41798c2ecf20Sopenharmony_ci		       },
41808c2ecf20Sopenharmony_ci	 },
41818c2ecf20Sopenharmony_ci};
41828c2ecf20Sopenharmony_ci
41838c2ecf20Sopenharmony_cistatic int generic_cra_init(struct crypto_tfm *tfm,
41848c2ecf20Sopenharmony_ci			    struct iproc_alg_s *cipher_alg)
41858c2ecf20Sopenharmony_ci{
41868c2ecf20Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
41878c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_tfm_ctx(tfm);
41888c2ecf20Sopenharmony_ci	unsigned int blocksize = crypto_tfm_alg_blocksize(tfm);
41898c2ecf20Sopenharmony_ci
41908c2ecf20Sopenharmony_ci	flow_log("%s()\n", __func__);
41918c2ecf20Sopenharmony_ci
41928c2ecf20Sopenharmony_ci	ctx->alg = cipher_alg;
41938c2ecf20Sopenharmony_ci	ctx->cipher = cipher_alg->cipher_info;
41948c2ecf20Sopenharmony_ci	ctx->auth = cipher_alg->auth_info;
41958c2ecf20Sopenharmony_ci	ctx->auth_first = cipher_alg->auth_first;
41968c2ecf20Sopenharmony_ci	ctx->max_payload = spu->spu_ctx_max_payload(ctx->cipher.alg,
41978c2ecf20Sopenharmony_ci						    ctx->cipher.mode,
41988c2ecf20Sopenharmony_ci						    blocksize);
41998c2ecf20Sopenharmony_ci	ctx->fallback_cipher = NULL;
42008c2ecf20Sopenharmony_ci
42018c2ecf20Sopenharmony_ci	ctx->enckeylen = 0;
42028c2ecf20Sopenharmony_ci	ctx->authkeylen = 0;
42038c2ecf20Sopenharmony_ci
42048c2ecf20Sopenharmony_ci	atomic_inc(&iproc_priv.stream_count);
42058c2ecf20Sopenharmony_ci	atomic_inc(&iproc_priv.session_count);
42068c2ecf20Sopenharmony_ci
42078c2ecf20Sopenharmony_ci	return 0;
42088c2ecf20Sopenharmony_ci}
42098c2ecf20Sopenharmony_ci
42108c2ecf20Sopenharmony_cistatic int skcipher_init_tfm(struct crypto_skcipher *skcipher)
42118c2ecf20Sopenharmony_ci{
42128c2ecf20Sopenharmony_ci	struct crypto_tfm *tfm = crypto_skcipher_tfm(skcipher);
42138c2ecf20Sopenharmony_ci	struct skcipher_alg *alg = crypto_skcipher_alg(skcipher);
42148c2ecf20Sopenharmony_ci	struct iproc_alg_s *cipher_alg;
42158c2ecf20Sopenharmony_ci
42168c2ecf20Sopenharmony_ci	flow_log("%s()\n", __func__);
42178c2ecf20Sopenharmony_ci
42188c2ecf20Sopenharmony_ci	crypto_skcipher_set_reqsize(skcipher, sizeof(struct iproc_reqctx_s));
42198c2ecf20Sopenharmony_ci
42208c2ecf20Sopenharmony_ci	cipher_alg = container_of(alg, struct iproc_alg_s, alg.skcipher);
42218c2ecf20Sopenharmony_ci	return generic_cra_init(tfm, cipher_alg);
42228c2ecf20Sopenharmony_ci}
42238c2ecf20Sopenharmony_ci
42248c2ecf20Sopenharmony_cistatic int ahash_cra_init(struct crypto_tfm *tfm)
42258c2ecf20Sopenharmony_ci{
42268c2ecf20Sopenharmony_ci	int err;
42278c2ecf20Sopenharmony_ci	struct crypto_alg *alg = tfm->__crt_alg;
42288c2ecf20Sopenharmony_ci	struct iproc_alg_s *cipher_alg;
42298c2ecf20Sopenharmony_ci
42308c2ecf20Sopenharmony_ci	cipher_alg = container_of(__crypto_ahash_alg(alg), struct iproc_alg_s,
42318c2ecf20Sopenharmony_ci				  alg.hash);
42328c2ecf20Sopenharmony_ci
42338c2ecf20Sopenharmony_ci	err = generic_cra_init(tfm, cipher_alg);
42348c2ecf20Sopenharmony_ci	flow_log("%s()\n", __func__);
42358c2ecf20Sopenharmony_ci
42368c2ecf20Sopenharmony_ci	/*
42378c2ecf20Sopenharmony_ci	 * export state size has to be < 512 bytes. So don't include msg bufs
42388c2ecf20Sopenharmony_ci	 * in state size.
42398c2ecf20Sopenharmony_ci	 */
42408c2ecf20Sopenharmony_ci	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
42418c2ecf20Sopenharmony_ci				 sizeof(struct iproc_reqctx_s));
42428c2ecf20Sopenharmony_ci
42438c2ecf20Sopenharmony_ci	return err;
42448c2ecf20Sopenharmony_ci}
42458c2ecf20Sopenharmony_ci
42468c2ecf20Sopenharmony_cistatic int aead_cra_init(struct crypto_aead *aead)
42478c2ecf20Sopenharmony_ci{
42488c2ecf20Sopenharmony_ci	struct crypto_tfm *tfm = crypto_aead_tfm(aead);
42498c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_tfm_ctx(tfm);
42508c2ecf20Sopenharmony_ci	struct crypto_alg *alg = tfm->__crt_alg;
42518c2ecf20Sopenharmony_ci	struct aead_alg *aalg = container_of(alg, struct aead_alg, base);
42528c2ecf20Sopenharmony_ci	struct iproc_alg_s *cipher_alg = container_of(aalg, struct iproc_alg_s,
42538c2ecf20Sopenharmony_ci						      alg.aead);
42548c2ecf20Sopenharmony_ci
42558c2ecf20Sopenharmony_ci	int err = generic_cra_init(tfm, cipher_alg);
42568c2ecf20Sopenharmony_ci
42578c2ecf20Sopenharmony_ci	flow_log("%s()\n", __func__);
42588c2ecf20Sopenharmony_ci
42598c2ecf20Sopenharmony_ci	crypto_aead_set_reqsize(aead, sizeof(struct iproc_reqctx_s));
42608c2ecf20Sopenharmony_ci	ctx->is_esp = false;
42618c2ecf20Sopenharmony_ci	ctx->salt_len = 0;
42628c2ecf20Sopenharmony_ci	ctx->salt_offset = 0;
42638c2ecf20Sopenharmony_ci
42648c2ecf20Sopenharmony_ci	/* random first IV */
42658c2ecf20Sopenharmony_ci	get_random_bytes(ctx->iv, MAX_IV_SIZE);
42668c2ecf20Sopenharmony_ci	flow_dump("  iv: ", ctx->iv, MAX_IV_SIZE);
42678c2ecf20Sopenharmony_ci
42688c2ecf20Sopenharmony_ci	if (!err) {
42698c2ecf20Sopenharmony_ci		if (alg->cra_flags & CRYPTO_ALG_NEED_FALLBACK) {
42708c2ecf20Sopenharmony_ci			flow_log("%s() creating fallback cipher\n", __func__);
42718c2ecf20Sopenharmony_ci
42728c2ecf20Sopenharmony_ci			ctx->fallback_cipher =
42738c2ecf20Sopenharmony_ci			    crypto_alloc_aead(alg->cra_name, 0,
42748c2ecf20Sopenharmony_ci					      CRYPTO_ALG_ASYNC |
42758c2ecf20Sopenharmony_ci					      CRYPTO_ALG_NEED_FALLBACK);
42768c2ecf20Sopenharmony_ci			if (IS_ERR(ctx->fallback_cipher)) {
42778c2ecf20Sopenharmony_ci				pr_err("%s() Error: failed to allocate fallback for %s\n",
42788c2ecf20Sopenharmony_ci				       __func__, alg->cra_name);
42798c2ecf20Sopenharmony_ci				return PTR_ERR(ctx->fallback_cipher);
42808c2ecf20Sopenharmony_ci			}
42818c2ecf20Sopenharmony_ci		}
42828c2ecf20Sopenharmony_ci	}
42838c2ecf20Sopenharmony_ci
42848c2ecf20Sopenharmony_ci	return err;
42858c2ecf20Sopenharmony_ci}
42868c2ecf20Sopenharmony_ci
42878c2ecf20Sopenharmony_cistatic void generic_cra_exit(struct crypto_tfm *tfm)
42888c2ecf20Sopenharmony_ci{
42898c2ecf20Sopenharmony_ci	atomic_dec(&iproc_priv.session_count);
42908c2ecf20Sopenharmony_ci}
42918c2ecf20Sopenharmony_ci
42928c2ecf20Sopenharmony_cistatic void skcipher_exit_tfm(struct crypto_skcipher *tfm)
42938c2ecf20Sopenharmony_ci{
42948c2ecf20Sopenharmony_ci	generic_cra_exit(crypto_skcipher_tfm(tfm));
42958c2ecf20Sopenharmony_ci}
42968c2ecf20Sopenharmony_ci
42978c2ecf20Sopenharmony_cistatic void aead_cra_exit(struct crypto_aead *aead)
42988c2ecf20Sopenharmony_ci{
42998c2ecf20Sopenharmony_ci	struct crypto_tfm *tfm = crypto_aead_tfm(aead);
43008c2ecf20Sopenharmony_ci	struct iproc_ctx_s *ctx = crypto_tfm_ctx(tfm);
43018c2ecf20Sopenharmony_ci
43028c2ecf20Sopenharmony_ci	generic_cra_exit(tfm);
43038c2ecf20Sopenharmony_ci
43048c2ecf20Sopenharmony_ci	if (ctx->fallback_cipher) {
43058c2ecf20Sopenharmony_ci		crypto_free_aead(ctx->fallback_cipher);
43068c2ecf20Sopenharmony_ci		ctx->fallback_cipher = NULL;
43078c2ecf20Sopenharmony_ci	}
43088c2ecf20Sopenharmony_ci}
43098c2ecf20Sopenharmony_ci
43108c2ecf20Sopenharmony_ci/**
43118c2ecf20Sopenharmony_ci * spu_functions_register() - Specify hardware-specific SPU functions based on
43128c2ecf20Sopenharmony_ci * SPU type read from device tree.
43138c2ecf20Sopenharmony_ci * @dev:	device structure
43148c2ecf20Sopenharmony_ci * @spu_type:	SPU hardware generation
43158c2ecf20Sopenharmony_ci * @spu_subtype: SPU hardware version
43168c2ecf20Sopenharmony_ci */
43178c2ecf20Sopenharmony_cistatic void spu_functions_register(struct device *dev,
43188c2ecf20Sopenharmony_ci				   enum spu_spu_type spu_type,
43198c2ecf20Sopenharmony_ci				   enum spu_spu_subtype spu_subtype)
43208c2ecf20Sopenharmony_ci{
43218c2ecf20Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
43228c2ecf20Sopenharmony_ci
43238c2ecf20Sopenharmony_ci	if (spu_type == SPU_TYPE_SPUM) {
43248c2ecf20Sopenharmony_ci		dev_dbg(dev, "Registering SPUM functions");
43258c2ecf20Sopenharmony_ci		spu->spu_dump_msg_hdr = spum_dump_msg_hdr;
43268c2ecf20Sopenharmony_ci		spu->spu_payload_length = spum_payload_length;
43278c2ecf20Sopenharmony_ci		spu->spu_response_hdr_len = spum_response_hdr_len;
43288c2ecf20Sopenharmony_ci		spu->spu_hash_pad_len = spum_hash_pad_len;
43298c2ecf20Sopenharmony_ci		spu->spu_gcm_ccm_pad_len = spum_gcm_ccm_pad_len;
43308c2ecf20Sopenharmony_ci		spu->spu_assoc_resp_len = spum_assoc_resp_len;
43318c2ecf20Sopenharmony_ci		spu->spu_aead_ivlen = spum_aead_ivlen;
43328c2ecf20Sopenharmony_ci		spu->spu_hash_type = spum_hash_type;
43338c2ecf20Sopenharmony_ci		spu->spu_digest_size = spum_digest_size;
43348c2ecf20Sopenharmony_ci		spu->spu_create_request = spum_create_request;
43358c2ecf20Sopenharmony_ci		spu->spu_cipher_req_init = spum_cipher_req_init;
43368c2ecf20Sopenharmony_ci		spu->spu_cipher_req_finish = spum_cipher_req_finish;
43378c2ecf20Sopenharmony_ci		spu->spu_request_pad = spum_request_pad;
43388c2ecf20Sopenharmony_ci		spu->spu_tx_status_len = spum_tx_status_len;
43398c2ecf20Sopenharmony_ci		spu->spu_rx_status_len = spum_rx_status_len;
43408c2ecf20Sopenharmony_ci		spu->spu_status_process = spum_status_process;
43418c2ecf20Sopenharmony_ci		spu->spu_xts_tweak_in_payload = spum_xts_tweak_in_payload;
43428c2ecf20Sopenharmony_ci		spu->spu_ccm_update_iv = spum_ccm_update_iv;
43438c2ecf20Sopenharmony_ci		spu->spu_wordalign_padlen = spum_wordalign_padlen;
43448c2ecf20Sopenharmony_ci		if (spu_subtype == SPU_SUBTYPE_SPUM_NS2)
43458c2ecf20Sopenharmony_ci			spu->spu_ctx_max_payload = spum_ns2_ctx_max_payload;
43468c2ecf20Sopenharmony_ci		else
43478c2ecf20Sopenharmony_ci			spu->spu_ctx_max_payload = spum_nsp_ctx_max_payload;
43488c2ecf20Sopenharmony_ci	} else {
43498c2ecf20Sopenharmony_ci		dev_dbg(dev, "Registering SPU2 functions");
43508c2ecf20Sopenharmony_ci		spu->spu_dump_msg_hdr = spu2_dump_msg_hdr;
43518c2ecf20Sopenharmony_ci		spu->spu_ctx_max_payload = spu2_ctx_max_payload;
43528c2ecf20Sopenharmony_ci		spu->spu_payload_length = spu2_payload_length;
43538c2ecf20Sopenharmony_ci		spu->spu_response_hdr_len = spu2_response_hdr_len;
43548c2ecf20Sopenharmony_ci		spu->spu_hash_pad_len = spu2_hash_pad_len;
43558c2ecf20Sopenharmony_ci		spu->spu_gcm_ccm_pad_len = spu2_gcm_ccm_pad_len;
43568c2ecf20Sopenharmony_ci		spu->spu_assoc_resp_len = spu2_assoc_resp_len;
43578c2ecf20Sopenharmony_ci		spu->spu_aead_ivlen = spu2_aead_ivlen;
43588c2ecf20Sopenharmony_ci		spu->spu_hash_type = spu2_hash_type;
43598c2ecf20Sopenharmony_ci		spu->spu_digest_size = spu2_digest_size;
43608c2ecf20Sopenharmony_ci		spu->spu_create_request = spu2_create_request;
43618c2ecf20Sopenharmony_ci		spu->spu_cipher_req_init = spu2_cipher_req_init;
43628c2ecf20Sopenharmony_ci		spu->spu_cipher_req_finish = spu2_cipher_req_finish;
43638c2ecf20Sopenharmony_ci		spu->spu_request_pad = spu2_request_pad;
43648c2ecf20Sopenharmony_ci		spu->spu_tx_status_len = spu2_tx_status_len;
43658c2ecf20Sopenharmony_ci		spu->spu_rx_status_len = spu2_rx_status_len;
43668c2ecf20Sopenharmony_ci		spu->spu_status_process = spu2_status_process;
43678c2ecf20Sopenharmony_ci		spu->spu_xts_tweak_in_payload = spu2_xts_tweak_in_payload;
43688c2ecf20Sopenharmony_ci		spu->spu_ccm_update_iv = spu2_ccm_update_iv;
43698c2ecf20Sopenharmony_ci		spu->spu_wordalign_padlen = spu2_wordalign_padlen;
43708c2ecf20Sopenharmony_ci	}
43718c2ecf20Sopenharmony_ci}
43728c2ecf20Sopenharmony_ci
43738c2ecf20Sopenharmony_ci/**
43748c2ecf20Sopenharmony_ci * spu_mb_init() - Initialize mailbox client. Request ownership of a mailbox
43758c2ecf20Sopenharmony_ci * channel for the SPU being probed.
43768c2ecf20Sopenharmony_ci * @dev:  SPU driver device structure
43778c2ecf20Sopenharmony_ci *
43788c2ecf20Sopenharmony_ci * Return: 0 if successful
43798c2ecf20Sopenharmony_ci *	   < 0 otherwise
43808c2ecf20Sopenharmony_ci */
43818c2ecf20Sopenharmony_cistatic int spu_mb_init(struct device *dev)
43828c2ecf20Sopenharmony_ci{
43838c2ecf20Sopenharmony_ci	struct mbox_client *mcl = &iproc_priv.mcl;
43848c2ecf20Sopenharmony_ci	int err, i;
43858c2ecf20Sopenharmony_ci
43868c2ecf20Sopenharmony_ci	iproc_priv.mbox = devm_kcalloc(dev, iproc_priv.spu.num_chan,
43878c2ecf20Sopenharmony_ci				  sizeof(struct mbox_chan *), GFP_KERNEL);
43888c2ecf20Sopenharmony_ci	if (!iproc_priv.mbox)
43898c2ecf20Sopenharmony_ci		return -ENOMEM;
43908c2ecf20Sopenharmony_ci
43918c2ecf20Sopenharmony_ci	mcl->dev = dev;
43928c2ecf20Sopenharmony_ci	mcl->tx_block = false;
43938c2ecf20Sopenharmony_ci	mcl->tx_tout = 0;
43948c2ecf20Sopenharmony_ci	mcl->knows_txdone = true;
43958c2ecf20Sopenharmony_ci	mcl->rx_callback = spu_rx_callback;
43968c2ecf20Sopenharmony_ci	mcl->tx_done = NULL;
43978c2ecf20Sopenharmony_ci
43988c2ecf20Sopenharmony_ci	for (i = 0; i < iproc_priv.spu.num_chan; i++) {
43998c2ecf20Sopenharmony_ci		iproc_priv.mbox[i] = mbox_request_channel(mcl, i);
44008c2ecf20Sopenharmony_ci		if (IS_ERR(iproc_priv.mbox[i])) {
44018c2ecf20Sopenharmony_ci			err = PTR_ERR(iproc_priv.mbox[i]);
44028c2ecf20Sopenharmony_ci			dev_err(dev,
44038c2ecf20Sopenharmony_ci				"Mbox channel %d request failed with err %d",
44048c2ecf20Sopenharmony_ci				i, err);
44058c2ecf20Sopenharmony_ci			iproc_priv.mbox[i] = NULL;
44068c2ecf20Sopenharmony_ci			goto free_channels;
44078c2ecf20Sopenharmony_ci		}
44088c2ecf20Sopenharmony_ci	}
44098c2ecf20Sopenharmony_ci
44108c2ecf20Sopenharmony_ci	return 0;
44118c2ecf20Sopenharmony_cifree_channels:
44128c2ecf20Sopenharmony_ci	for (i = 0; i < iproc_priv.spu.num_chan; i++) {
44138c2ecf20Sopenharmony_ci		if (iproc_priv.mbox[i])
44148c2ecf20Sopenharmony_ci			mbox_free_channel(iproc_priv.mbox[i]);
44158c2ecf20Sopenharmony_ci	}
44168c2ecf20Sopenharmony_ci
44178c2ecf20Sopenharmony_ci	return err;
44188c2ecf20Sopenharmony_ci}
44198c2ecf20Sopenharmony_ci
44208c2ecf20Sopenharmony_cistatic void spu_mb_release(struct platform_device *pdev)
44218c2ecf20Sopenharmony_ci{
44228c2ecf20Sopenharmony_ci	int i;
44238c2ecf20Sopenharmony_ci
44248c2ecf20Sopenharmony_ci	for (i = 0; i < iproc_priv.spu.num_chan; i++)
44258c2ecf20Sopenharmony_ci		mbox_free_channel(iproc_priv.mbox[i]);
44268c2ecf20Sopenharmony_ci}
44278c2ecf20Sopenharmony_ci
44288c2ecf20Sopenharmony_cistatic void spu_counters_init(void)
44298c2ecf20Sopenharmony_ci{
44308c2ecf20Sopenharmony_ci	int i;
44318c2ecf20Sopenharmony_ci	int j;
44328c2ecf20Sopenharmony_ci
44338c2ecf20Sopenharmony_ci	atomic_set(&iproc_priv.session_count, 0);
44348c2ecf20Sopenharmony_ci	atomic_set(&iproc_priv.stream_count, 0);
44358c2ecf20Sopenharmony_ci	atomic_set(&iproc_priv.next_chan, (int)iproc_priv.spu.num_chan);
44368c2ecf20Sopenharmony_ci	atomic64_set(&iproc_priv.bytes_in, 0);
44378c2ecf20Sopenharmony_ci	atomic64_set(&iproc_priv.bytes_out, 0);
44388c2ecf20Sopenharmony_ci	for (i = 0; i < SPU_OP_NUM; i++) {
44398c2ecf20Sopenharmony_ci		atomic_set(&iproc_priv.op_counts[i], 0);
44408c2ecf20Sopenharmony_ci		atomic_set(&iproc_priv.setkey_cnt[i], 0);
44418c2ecf20Sopenharmony_ci	}
44428c2ecf20Sopenharmony_ci	for (i = 0; i < CIPHER_ALG_LAST; i++)
44438c2ecf20Sopenharmony_ci		for (j = 0; j < CIPHER_MODE_LAST; j++)
44448c2ecf20Sopenharmony_ci			atomic_set(&iproc_priv.cipher_cnt[i][j], 0);
44458c2ecf20Sopenharmony_ci
44468c2ecf20Sopenharmony_ci	for (i = 0; i < HASH_ALG_LAST; i++) {
44478c2ecf20Sopenharmony_ci		atomic_set(&iproc_priv.hash_cnt[i], 0);
44488c2ecf20Sopenharmony_ci		atomic_set(&iproc_priv.hmac_cnt[i], 0);
44498c2ecf20Sopenharmony_ci	}
44508c2ecf20Sopenharmony_ci	for (i = 0; i < AEAD_TYPE_LAST; i++)
44518c2ecf20Sopenharmony_ci		atomic_set(&iproc_priv.aead_cnt[i], 0);
44528c2ecf20Sopenharmony_ci
44538c2ecf20Sopenharmony_ci	atomic_set(&iproc_priv.mb_no_spc, 0);
44548c2ecf20Sopenharmony_ci	atomic_set(&iproc_priv.mb_send_fail, 0);
44558c2ecf20Sopenharmony_ci	atomic_set(&iproc_priv.bad_icv, 0);
44568c2ecf20Sopenharmony_ci}
44578c2ecf20Sopenharmony_ci
44588c2ecf20Sopenharmony_cistatic int spu_register_skcipher(struct iproc_alg_s *driver_alg)
44598c2ecf20Sopenharmony_ci{
44608c2ecf20Sopenharmony_ci	struct skcipher_alg *crypto = &driver_alg->alg.skcipher;
44618c2ecf20Sopenharmony_ci	int err;
44628c2ecf20Sopenharmony_ci
44638c2ecf20Sopenharmony_ci	crypto->base.cra_module = THIS_MODULE;
44648c2ecf20Sopenharmony_ci	crypto->base.cra_priority = cipher_pri;
44658c2ecf20Sopenharmony_ci	crypto->base.cra_alignmask = 0;
44668c2ecf20Sopenharmony_ci	crypto->base.cra_ctxsize = sizeof(struct iproc_ctx_s);
44678c2ecf20Sopenharmony_ci	crypto->base.cra_flags = CRYPTO_ALG_ASYNC |
44688c2ecf20Sopenharmony_ci				 CRYPTO_ALG_ALLOCATES_MEMORY |
44698c2ecf20Sopenharmony_ci				 CRYPTO_ALG_KERN_DRIVER_ONLY;
44708c2ecf20Sopenharmony_ci
44718c2ecf20Sopenharmony_ci	crypto->init = skcipher_init_tfm;
44728c2ecf20Sopenharmony_ci	crypto->exit = skcipher_exit_tfm;
44738c2ecf20Sopenharmony_ci	crypto->setkey = skcipher_setkey;
44748c2ecf20Sopenharmony_ci	crypto->encrypt = skcipher_encrypt;
44758c2ecf20Sopenharmony_ci	crypto->decrypt = skcipher_decrypt;
44768c2ecf20Sopenharmony_ci
44778c2ecf20Sopenharmony_ci	err = crypto_register_skcipher(crypto);
44788c2ecf20Sopenharmony_ci	/* Mark alg as having been registered, if successful */
44798c2ecf20Sopenharmony_ci	if (err == 0)
44808c2ecf20Sopenharmony_ci		driver_alg->registered = true;
44818c2ecf20Sopenharmony_ci	pr_debug("  registered skcipher %s\n", crypto->base.cra_driver_name);
44828c2ecf20Sopenharmony_ci	return err;
44838c2ecf20Sopenharmony_ci}
44848c2ecf20Sopenharmony_ci
44858c2ecf20Sopenharmony_cistatic int spu_register_ahash(struct iproc_alg_s *driver_alg)
44868c2ecf20Sopenharmony_ci{
44878c2ecf20Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
44888c2ecf20Sopenharmony_ci	struct ahash_alg *hash = &driver_alg->alg.hash;
44898c2ecf20Sopenharmony_ci	int err;
44908c2ecf20Sopenharmony_ci
44918c2ecf20Sopenharmony_ci	/* AES-XCBC is the only AES hash type currently supported on SPU-M */
44928c2ecf20Sopenharmony_ci	if ((driver_alg->auth_info.alg == HASH_ALG_AES) &&
44938c2ecf20Sopenharmony_ci	    (driver_alg->auth_info.mode != HASH_MODE_XCBC) &&
44948c2ecf20Sopenharmony_ci	    (spu->spu_type == SPU_TYPE_SPUM))
44958c2ecf20Sopenharmony_ci		return 0;
44968c2ecf20Sopenharmony_ci
44978c2ecf20Sopenharmony_ci	/* SHA3 algorithm variants are not registered for SPU-M or SPU2. */
44988c2ecf20Sopenharmony_ci	if ((driver_alg->auth_info.alg >= HASH_ALG_SHA3_224) &&
44998c2ecf20Sopenharmony_ci	    (spu->spu_subtype != SPU_SUBTYPE_SPU2_V2))
45008c2ecf20Sopenharmony_ci		return 0;
45018c2ecf20Sopenharmony_ci
45028c2ecf20Sopenharmony_ci	hash->halg.base.cra_module = THIS_MODULE;
45038c2ecf20Sopenharmony_ci	hash->halg.base.cra_priority = hash_pri;
45048c2ecf20Sopenharmony_ci	hash->halg.base.cra_alignmask = 0;
45058c2ecf20Sopenharmony_ci	hash->halg.base.cra_ctxsize = sizeof(struct iproc_ctx_s);
45068c2ecf20Sopenharmony_ci	hash->halg.base.cra_init = ahash_cra_init;
45078c2ecf20Sopenharmony_ci	hash->halg.base.cra_exit = generic_cra_exit;
45088c2ecf20Sopenharmony_ci	hash->halg.base.cra_flags = CRYPTO_ALG_ASYNC |
45098c2ecf20Sopenharmony_ci				    CRYPTO_ALG_ALLOCATES_MEMORY;
45108c2ecf20Sopenharmony_ci	hash->halg.statesize = sizeof(struct spu_hash_export_s);
45118c2ecf20Sopenharmony_ci
45128c2ecf20Sopenharmony_ci	if (driver_alg->auth_info.mode != HASH_MODE_HMAC) {
45138c2ecf20Sopenharmony_ci		hash->init = ahash_init;
45148c2ecf20Sopenharmony_ci		hash->update = ahash_update;
45158c2ecf20Sopenharmony_ci		hash->final = ahash_final;
45168c2ecf20Sopenharmony_ci		hash->finup = ahash_finup;
45178c2ecf20Sopenharmony_ci		hash->digest = ahash_digest;
45188c2ecf20Sopenharmony_ci		if ((driver_alg->auth_info.alg == HASH_ALG_AES) &&
45198c2ecf20Sopenharmony_ci		    ((driver_alg->auth_info.mode == HASH_MODE_XCBC) ||
45208c2ecf20Sopenharmony_ci		    (driver_alg->auth_info.mode == HASH_MODE_CMAC))) {
45218c2ecf20Sopenharmony_ci			hash->setkey = ahash_setkey;
45228c2ecf20Sopenharmony_ci		}
45238c2ecf20Sopenharmony_ci	} else {
45248c2ecf20Sopenharmony_ci		hash->setkey = ahash_hmac_setkey;
45258c2ecf20Sopenharmony_ci		hash->init = ahash_hmac_init;
45268c2ecf20Sopenharmony_ci		hash->update = ahash_hmac_update;
45278c2ecf20Sopenharmony_ci		hash->final = ahash_hmac_final;
45288c2ecf20Sopenharmony_ci		hash->finup = ahash_hmac_finup;
45298c2ecf20Sopenharmony_ci		hash->digest = ahash_hmac_digest;
45308c2ecf20Sopenharmony_ci	}
45318c2ecf20Sopenharmony_ci	hash->export = ahash_export;
45328c2ecf20Sopenharmony_ci	hash->import = ahash_import;
45338c2ecf20Sopenharmony_ci
45348c2ecf20Sopenharmony_ci	err = crypto_register_ahash(hash);
45358c2ecf20Sopenharmony_ci	/* Mark alg as having been registered, if successful */
45368c2ecf20Sopenharmony_ci	if (err == 0)
45378c2ecf20Sopenharmony_ci		driver_alg->registered = true;
45388c2ecf20Sopenharmony_ci	pr_debug("  registered ahash %s\n",
45398c2ecf20Sopenharmony_ci		 hash->halg.base.cra_driver_name);
45408c2ecf20Sopenharmony_ci	return err;
45418c2ecf20Sopenharmony_ci}
45428c2ecf20Sopenharmony_ci
45438c2ecf20Sopenharmony_cistatic int spu_register_aead(struct iproc_alg_s *driver_alg)
45448c2ecf20Sopenharmony_ci{
45458c2ecf20Sopenharmony_ci	struct aead_alg *aead = &driver_alg->alg.aead;
45468c2ecf20Sopenharmony_ci	int err;
45478c2ecf20Sopenharmony_ci
45488c2ecf20Sopenharmony_ci	aead->base.cra_module = THIS_MODULE;
45498c2ecf20Sopenharmony_ci	aead->base.cra_priority = aead_pri;
45508c2ecf20Sopenharmony_ci	aead->base.cra_alignmask = 0;
45518c2ecf20Sopenharmony_ci	aead->base.cra_ctxsize = sizeof(struct iproc_ctx_s);
45528c2ecf20Sopenharmony_ci
45538c2ecf20Sopenharmony_ci	aead->base.cra_flags |= CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY;
45548c2ecf20Sopenharmony_ci	/* setkey set in alg initialization */
45558c2ecf20Sopenharmony_ci	aead->setauthsize = aead_setauthsize;
45568c2ecf20Sopenharmony_ci	aead->encrypt = aead_encrypt;
45578c2ecf20Sopenharmony_ci	aead->decrypt = aead_decrypt;
45588c2ecf20Sopenharmony_ci	aead->init = aead_cra_init;
45598c2ecf20Sopenharmony_ci	aead->exit = aead_cra_exit;
45608c2ecf20Sopenharmony_ci
45618c2ecf20Sopenharmony_ci	err = crypto_register_aead(aead);
45628c2ecf20Sopenharmony_ci	/* Mark alg as having been registered, if successful */
45638c2ecf20Sopenharmony_ci	if (err == 0)
45648c2ecf20Sopenharmony_ci		driver_alg->registered = true;
45658c2ecf20Sopenharmony_ci	pr_debug("  registered aead %s\n", aead->base.cra_driver_name);
45668c2ecf20Sopenharmony_ci	return err;
45678c2ecf20Sopenharmony_ci}
45688c2ecf20Sopenharmony_ci
45698c2ecf20Sopenharmony_ci/* register crypto algorithms the device supports */
45708c2ecf20Sopenharmony_cistatic int spu_algs_register(struct device *dev)
45718c2ecf20Sopenharmony_ci{
45728c2ecf20Sopenharmony_ci	int i, j;
45738c2ecf20Sopenharmony_ci	int err;
45748c2ecf20Sopenharmony_ci
45758c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
45768c2ecf20Sopenharmony_ci		switch (driver_algs[i].type) {
45778c2ecf20Sopenharmony_ci		case CRYPTO_ALG_TYPE_SKCIPHER:
45788c2ecf20Sopenharmony_ci			err = spu_register_skcipher(&driver_algs[i]);
45798c2ecf20Sopenharmony_ci			break;
45808c2ecf20Sopenharmony_ci		case CRYPTO_ALG_TYPE_AHASH:
45818c2ecf20Sopenharmony_ci			err = spu_register_ahash(&driver_algs[i]);
45828c2ecf20Sopenharmony_ci			break;
45838c2ecf20Sopenharmony_ci		case CRYPTO_ALG_TYPE_AEAD:
45848c2ecf20Sopenharmony_ci			err = spu_register_aead(&driver_algs[i]);
45858c2ecf20Sopenharmony_ci			break;
45868c2ecf20Sopenharmony_ci		default:
45878c2ecf20Sopenharmony_ci			dev_err(dev,
45888c2ecf20Sopenharmony_ci				"iproc-crypto: unknown alg type: %d",
45898c2ecf20Sopenharmony_ci				driver_algs[i].type);
45908c2ecf20Sopenharmony_ci			err = -EINVAL;
45918c2ecf20Sopenharmony_ci		}
45928c2ecf20Sopenharmony_ci
45938c2ecf20Sopenharmony_ci		if (err) {
45948c2ecf20Sopenharmony_ci			dev_err(dev, "alg registration failed with error %d\n",
45958c2ecf20Sopenharmony_ci				err);
45968c2ecf20Sopenharmony_ci			goto err_algs;
45978c2ecf20Sopenharmony_ci		}
45988c2ecf20Sopenharmony_ci	}
45998c2ecf20Sopenharmony_ci
46008c2ecf20Sopenharmony_ci	return 0;
46018c2ecf20Sopenharmony_ci
46028c2ecf20Sopenharmony_cierr_algs:
46038c2ecf20Sopenharmony_ci	for (j = 0; j < i; j++) {
46048c2ecf20Sopenharmony_ci		/* Skip any algorithm not registered */
46058c2ecf20Sopenharmony_ci		if (!driver_algs[j].registered)
46068c2ecf20Sopenharmony_ci			continue;
46078c2ecf20Sopenharmony_ci		switch (driver_algs[j].type) {
46088c2ecf20Sopenharmony_ci		case CRYPTO_ALG_TYPE_SKCIPHER:
46098c2ecf20Sopenharmony_ci			crypto_unregister_skcipher(&driver_algs[j].alg.skcipher);
46108c2ecf20Sopenharmony_ci			driver_algs[j].registered = false;
46118c2ecf20Sopenharmony_ci			break;
46128c2ecf20Sopenharmony_ci		case CRYPTO_ALG_TYPE_AHASH:
46138c2ecf20Sopenharmony_ci			crypto_unregister_ahash(&driver_algs[j].alg.hash);
46148c2ecf20Sopenharmony_ci			driver_algs[j].registered = false;
46158c2ecf20Sopenharmony_ci			break;
46168c2ecf20Sopenharmony_ci		case CRYPTO_ALG_TYPE_AEAD:
46178c2ecf20Sopenharmony_ci			crypto_unregister_aead(&driver_algs[j].alg.aead);
46188c2ecf20Sopenharmony_ci			driver_algs[j].registered = false;
46198c2ecf20Sopenharmony_ci			break;
46208c2ecf20Sopenharmony_ci		}
46218c2ecf20Sopenharmony_ci	}
46228c2ecf20Sopenharmony_ci	return err;
46238c2ecf20Sopenharmony_ci}
46248c2ecf20Sopenharmony_ci
46258c2ecf20Sopenharmony_ci/* ==================== Kernel Platform API ==================== */
46268c2ecf20Sopenharmony_ci
46278c2ecf20Sopenharmony_cistatic struct spu_type_subtype spum_ns2_types = {
46288c2ecf20Sopenharmony_ci	SPU_TYPE_SPUM, SPU_SUBTYPE_SPUM_NS2
46298c2ecf20Sopenharmony_ci};
46308c2ecf20Sopenharmony_ci
46318c2ecf20Sopenharmony_cistatic struct spu_type_subtype spum_nsp_types = {
46328c2ecf20Sopenharmony_ci	SPU_TYPE_SPUM, SPU_SUBTYPE_SPUM_NSP
46338c2ecf20Sopenharmony_ci};
46348c2ecf20Sopenharmony_ci
46358c2ecf20Sopenharmony_cistatic struct spu_type_subtype spu2_types = {
46368c2ecf20Sopenharmony_ci	SPU_TYPE_SPU2, SPU_SUBTYPE_SPU2_V1
46378c2ecf20Sopenharmony_ci};
46388c2ecf20Sopenharmony_ci
46398c2ecf20Sopenharmony_cistatic struct spu_type_subtype spu2_v2_types = {
46408c2ecf20Sopenharmony_ci	SPU_TYPE_SPU2, SPU_SUBTYPE_SPU2_V2
46418c2ecf20Sopenharmony_ci};
46428c2ecf20Sopenharmony_ci
46438c2ecf20Sopenharmony_cistatic const struct of_device_id bcm_spu_dt_ids[] = {
46448c2ecf20Sopenharmony_ci	{
46458c2ecf20Sopenharmony_ci		.compatible = "brcm,spum-crypto",
46468c2ecf20Sopenharmony_ci		.data = &spum_ns2_types,
46478c2ecf20Sopenharmony_ci	},
46488c2ecf20Sopenharmony_ci	{
46498c2ecf20Sopenharmony_ci		.compatible = "brcm,spum-nsp-crypto",
46508c2ecf20Sopenharmony_ci		.data = &spum_nsp_types,
46518c2ecf20Sopenharmony_ci	},
46528c2ecf20Sopenharmony_ci	{
46538c2ecf20Sopenharmony_ci		.compatible = "brcm,spu2-crypto",
46548c2ecf20Sopenharmony_ci		.data = &spu2_types,
46558c2ecf20Sopenharmony_ci	},
46568c2ecf20Sopenharmony_ci	{
46578c2ecf20Sopenharmony_ci		.compatible = "brcm,spu2-v2-crypto",
46588c2ecf20Sopenharmony_ci		.data = &spu2_v2_types,
46598c2ecf20Sopenharmony_ci	},
46608c2ecf20Sopenharmony_ci	{ /* sentinel */ }
46618c2ecf20Sopenharmony_ci};
46628c2ecf20Sopenharmony_ci
46638c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, bcm_spu_dt_ids);
46648c2ecf20Sopenharmony_ci
46658c2ecf20Sopenharmony_cistatic int spu_dt_read(struct platform_device *pdev)
46668c2ecf20Sopenharmony_ci{
46678c2ecf20Sopenharmony_ci	struct device *dev = &pdev->dev;
46688c2ecf20Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
46698c2ecf20Sopenharmony_ci	struct resource *spu_ctrl_regs;
46708c2ecf20Sopenharmony_ci	const struct spu_type_subtype *matched_spu_type;
46718c2ecf20Sopenharmony_ci	struct device_node *dn = pdev->dev.of_node;
46728c2ecf20Sopenharmony_ci	int err, i;
46738c2ecf20Sopenharmony_ci
46748c2ecf20Sopenharmony_ci	/* Count number of mailbox channels */
46758c2ecf20Sopenharmony_ci	spu->num_chan = of_count_phandle_with_args(dn, "mboxes", "#mbox-cells");
46768c2ecf20Sopenharmony_ci
46778c2ecf20Sopenharmony_ci	matched_spu_type = of_device_get_match_data(dev);
46788c2ecf20Sopenharmony_ci	if (!matched_spu_type) {
46798c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to match device\n");
46808c2ecf20Sopenharmony_ci		return -ENODEV;
46818c2ecf20Sopenharmony_ci	}
46828c2ecf20Sopenharmony_ci
46838c2ecf20Sopenharmony_ci	spu->spu_type = matched_spu_type->type;
46848c2ecf20Sopenharmony_ci	spu->spu_subtype = matched_spu_type->subtype;
46858c2ecf20Sopenharmony_ci
46868c2ecf20Sopenharmony_ci	for (i = 0; (i < MAX_SPUS) && ((spu_ctrl_regs =
46878c2ecf20Sopenharmony_ci		platform_get_resource(pdev, IORESOURCE_MEM, i)) != NULL); i++) {
46888c2ecf20Sopenharmony_ci
46898c2ecf20Sopenharmony_ci		spu->reg_vbase[i] = devm_ioremap_resource(dev, spu_ctrl_regs);
46908c2ecf20Sopenharmony_ci		if (IS_ERR(spu->reg_vbase[i])) {
46918c2ecf20Sopenharmony_ci			err = PTR_ERR(spu->reg_vbase[i]);
46928c2ecf20Sopenharmony_ci			dev_err(dev, "Failed to map registers: %d\n",
46938c2ecf20Sopenharmony_ci				err);
46948c2ecf20Sopenharmony_ci			spu->reg_vbase[i] = NULL;
46958c2ecf20Sopenharmony_ci			return err;
46968c2ecf20Sopenharmony_ci		}
46978c2ecf20Sopenharmony_ci	}
46988c2ecf20Sopenharmony_ci	spu->num_spu = i;
46998c2ecf20Sopenharmony_ci	dev_dbg(dev, "Device has %d SPUs", spu->num_spu);
47008c2ecf20Sopenharmony_ci
47018c2ecf20Sopenharmony_ci	return 0;
47028c2ecf20Sopenharmony_ci}
47038c2ecf20Sopenharmony_ci
47048c2ecf20Sopenharmony_cistatic int bcm_spu_probe(struct platform_device *pdev)
47058c2ecf20Sopenharmony_ci{
47068c2ecf20Sopenharmony_ci	struct device *dev = &pdev->dev;
47078c2ecf20Sopenharmony_ci	struct spu_hw *spu = &iproc_priv.spu;
47088c2ecf20Sopenharmony_ci	int err;
47098c2ecf20Sopenharmony_ci
47108c2ecf20Sopenharmony_ci	iproc_priv.pdev  = pdev;
47118c2ecf20Sopenharmony_ci	platform_set_drvdata(iproc_priv.pdev,
47128c2ecf20Sopenharmony_ci			     &iproc_priv);
47138c2ecf20Sopenharmony_ci
47148c2ecf20Sopenharmony_ci	err = spu_dt_read(pdev);
47158c2ecf20Sopenharmony_ci	if (err < 0)
47168c2ecf20Sopenharmony_ci		goto failure;
47178c2ecf20Sopenharmony_ci
47188c2ecf20Sopenharmony_ci	err = spu_mb_init(dev);
47198c2ecf20Sopenharmony_ci	if (err < 0)
47208c2ecf20Sopenharmony_ci		goto failure;
47218c2ecf20Sopenharmony_ci
47228c2ecf20Sopenharmony_ci	if (spu->spu_type == SPU_TYPE_SPUM)
47238c2ecf20Sopenharmony_ci		iproc_priv.bcm_hdr_len = 8;
47248c2ecf20Sopenharmony_ci	else if (spu->spu_type == SPU_TYPE_SPU2)
47258c2ecf20Sopenharmony_ci		iproc_priv.bcm_hdr_len = 0;
47268c2ecf20Sopenharmony_ci
47278c2ecf20Sopenharmony_ci	spu_functions_register(dev, spu->spu_type, spu->spu_subtype);
47288c2ecf20Sopenharmony_ci
47298c2ecf20Sopenharmony_ci	spu_counters_init();
47308c2ecf20Sopenharmony_ci
47318c2ecf20Sopenharmony_ci	spu_setup_debugfs();
47328c2ecf20Sopenharmony_ci
47338c2ecf20Sopenharmony_ci	err = spu_algs_register(dev);
47348c2ecf20Sopenharmony_ci	if (err < 0)
47358c2ecf20Sopenharmony_ci		goto fail_reg;
47368c2ecf20Sopenharmony_ci
47378c2ecf20Sopenharmony_ci	return 0;
47388c2ecf20Sopenharmony_ci
47398c2ecf20Sopenharmony_cifail_reg:
47408c2ecf20Sopenharmony_ci	spu_free_debugfs();
47418c2ecf20Sopenharmony_cifailure:
47428c2ecf20Sopenharmony_ci	spu_mb_release(pdev);
47438c2ecf20Sopenharmony_ci	dev_err(dev, "%s failed with error %d.\n", __func__, err);
47448c2ecf20Sopenharmony_ci
47458c2ecf20Sopenharmony_ci	return err;
47468c2ecf20Sopenharmony_ci}
47478c2ecf20Sopenharmony_ci
47488c2ecf20Sopenharmony_cistatic int bcm_spu_remove(struct platform_device *pdev)
47498c2ecf20Sopenharmony_ci{
47508c2ecf20Sopenharmony_ci	int i;
47518c2ecf20Sopenharmony_ci	struct device *dev = &pdev->dev;
47528c2ecf20Sopenharmony_ci	char *cdn;
47538c2ecf20Sopenharmony_ci
47548c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
47558c2ecf20Sopenharmony_ci		/*
47568c2ecf20Sopenharmony_ci		 * Not all algorithms were registered, depending on whether
47578c2ecf20Sopenharmony_ci		 * hardware is SPU or SPU2.  So here we make sure to skip
47588c2ecf20Sopenharmony_ci		 * those algorithms that were not previously registered.
47598c2ecf20Sopenharmony_ci		 */
47608c2ecf20Sopenharmony_ci		if (!driver_algs[i].registered)
47618c2ecf20Sopenharmony_ci			continue;
47628c2ecf20Sopenharmony_ci
47638c2ecf20Sopenharmony_ci		switch (driver_algs[i].type) {
47648c2ecf20Sopenharmony_ci		case CRYPTO_ALG_TYPE_SKCIPHER:
47658c2ecf20Sopenharmony_ci			crypto_unregister_skcipher(&driver_algs[i].alg.skcipher);
47668c2ecf20Sopenharmony_ci			dev_dbg(dev, "  unregistered cipher %s\n",
47678c2ecf20Sopenharmony_ci				driver_algs[i].alg.skcipher.base.cra_driver_name);
47688c2ecf20Sopenharmony_ci			driver_algs[i].registered = false;
47698c2ecf20Sopenharmony_ci			break;
47708c2ecf20Sopenharmony_ci		case CRYPTO_ALG_TYPE_AHASH:
47718c2ecf20Sopenharmony_ci			crypto_unregister_ahash(&driver_algs[i].alg.hash);
47728c2ecf20Sopenharmony_ci			cdn = driver_algs[i].alg.hash.halg.base.cra_driver_name;
47738c2ecf20Sopenharmony_ci			dev_dbg(dev, "  unregistered hash %s\n", cdn);
47748c2ecf20Sopenharmony_ci			driver_algs[i].registered = false;
47758c2ecf20Sopenharmony_ci			break;
47768c2ecf20Sopenharmony_ci		case CRYPTO_ALG_TYPE_AEAD:
47778c2ecf20Sopenharmony_ci			crypto_unregister_aead(&driver_algs[i].alg.aead);
47788c2ecf20Sopenharmony_ci			dev_dbg(dev, "  unregistered aead %s\n",
47798c2ecf20Sopenharmony_ci				driver_algs[i].alg.aead.base.cra_driver_name);
47808c2ecf20Sopenharmony_ci			driver_algs[i].registered = false;
47818c2ecf20Sopenharmony_ci			break;
47828c2ecf20Sopenharmony_ci		}
47838c2ecf20Sopenharmony_ci	}
47848c2ecf20Sopenharmony_ci	spu_free_debugfs();
47858c2ecf20Sopenharmony_ci	spu_mb_release(pdev);
47868c2ecf20Sopenharmony_ci	return 0;
47878c2ecf20Sopenharmony_ci}
47888c2ecf20Sopenharmony_ci
47898c2ecf20Sopenharmony_ci/* ===== Kernel Module API ===== */
47908c2ecf20Sopenharmony_ci
47918c2ecf20Sopenharmony_cistatic struct platform_driver bcm_spu_pdriver = {
47928c2ecf20Sopenharmony_ci	.driver = {
47938c2ecf20Sopenharmony_ci		   .name = "brcm-spu-crypto",
47948c2ecf20Sopenharmony_ci		   .of_match_table = of_match_ptr(bcm_spu_dt_ids),
47958c2ecf20Sopenharmony_ci		   },
47968c2ecf20Sopenharmony_ci	.probe = bcm_spu_probe,
47978c2ecf20Sopenharmony_ci	.remove = bcm_spu_remove,
47988c2ecf20Sopenharmony_ci};
47998c2ecf20Sopenharmony_cimodule_platform_driver(bcm_spu_pdriver);
48008c2ecf20Sopenharmony_ci
48018c2ecf20Sopenharmony_ciMODULE_AUTHOR("Rob Rice <rob.rice@broadcom.com>");
48028c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Broadcom symmetric crypto offload driver");
48038c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
4804