[PATCH v8 1/5] crypto: aspeed: Add HACE hash driver
liulongfang
liulongfang at huawei.com
Mon Aug 8 21:49:18 AEST 2022
On 2022/8/8 17:30, Neal Liu wrote:
>> -----Original Message-----
>> From: liulongfang <liulongfang at huawei.com>
>> Sent: Monday, August 8, 2022 10:53 AM
>> To: Neal Liu <neal_liu at aspeedtech.com>; Corentin Labbe
>> <clabbe.montjoie at gmail.com>; Christophe JAILLET
>> <christophe.jaillet at wanadoo.fr>; Randy Dunlap <rdunlap at infradead.org>;
>> Herbert Xu <herbert at gondor.apana.org.au>; David S . Miller
>> <davem at davemloft.net>; Rob Herring <robh+dt at kernel.org>; Krzysztof
>> Kozlowski <krzysztof.kozlowski+dt at linaro.org>; Joel Stanley <joel at jms.id.au>;
>> Andrew Jeffery <andrew at aj.id.au>; Dhananjay Phadke
>> <dhphadke at microsoft.com>; Johnny Huang
>> <johnny_huang at aspeedtech.com>
>> Cc: linux-aspeed at lists.ozlabs.org; linux-crypto at vger.kernel.org;
>> devicetree at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
>> linux-kernel at vger.kernel.org; BMC-SW <BMC-SW at aspeedtech.com>
>> Subject: Re: [PATCH v8 1/5] crypto: aspeed: Add HACE hash driver
>>
>>
>> On 2022/7/26 19:34, Neal Liu wrote:
>>> Hash and Crypto Engine (HACE) is designed to accelerate the
>>> throughput of hash data digest, encryption, and decryption.
>>>
>>> Basically, HACE can be divided into two independently engines
>>> - Hash Engine and Crypto Engine. This patch aims to add HACE
>>> hash engine driver for hash accelerator.
>>>
>>> Signed-off-by: Neal Liu <neal_liu at aspeedtech.com>
>>> Signed-off-by: Johnny Huang <johnny_huang at aspeedtech.com>
>>> ---
>>> MAINTAINERS | 7 +
>>> drivers/crypto/Kconfig | 1 +
>>> drivers/crypto/Makefile | 1 +
>>> drivers/crypto/aspeed/Kconfig | 32 +
>>> drivers/crypto/aspeed/Makefile | 6 +
>>> drivers/crypto/aspeed/aspeed-hace-hash.c | 1389
>> ++++++++++++++++++++++
>>> drivers/crypto/aspeed/aspeed-hace.c | 213 ++++
>>> drivers/crypto/aspeed/aspeed-hace.h | 186 +++
>>> 8 files changed, 1835 insertions(+)
>>> create mode 100644 drivers/crypto/aspeed/Kconfig
>>> create mode 100644 drivers/crypto/aspeed/Makefile
>>> create mode 100644 drivers/crypto/aspeed/aspeed-hace-hash.c
>>> create mode 100644 drivers/crypto/aspeed/aspeed-hace.c
>>> create mode 100644 drivers/crypto/aspeed/aspeed-hace.h
>>>
>>> diff --git a/MAINTAINERS b/MAINTAINERS
>>> index f55aea311af5..23a0215b7e42 100644
>>> --- a/MAINTAINERS
>>> +++ b/MAINTAINERS
>>> @@ -3140,6 +3140,13 @@ S: Maintained
>>> F: Documentation/devicetree/bindings/media/aspeed-video.txt
>>> F: drivers/media/platform/aspeed/
>>>
>>> +ASPEED CRYPTO DRIVER
>>> +M: Neal Liu <neal_liu at aspeedtech.com>
>>> +L: linux-aspeed at lists.ozlabs.org (moderated for non-subscribers)
>>> +S: Maintained
>>> +F:
>> Documentation/devicetree/bindings/crypto/aspeed,ast2500-hace.yaml
>>> +F: drivers/crypto/aspeed/
>>> +
>>> ASUS NOTEBOOKS AND EEEPC ACPI/WMI EXTRAS DRIVERS
>>> M: Corentin Chary <corentin.chary at gmail.com>
>>> L: acpi4asus-user at lists.sourceforge.net
>>> diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
>>> index ee99c02c84e8..b9f5ee126881 100644
>>> --- a/drivers/crypto/Kconfig
>>> +++ b/drivers/crypto/Kconfig
>>> @@ -933,5 +933,6 @@ config CRYPTO_DEV_SA2UL
>>> acceleration for cryptographic algorithms on these devices.
>>>
>>> source "drivers/crypto/keembay/Kconfig"
>>> +source "drivers/crypto/aspeed/Kconfig"
>>>
>>> endif # CRYPTO_HW
>>> diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
>>> index f81703a86b98..116de173a66c 100644
>>> --- a/drivers/crypto/Makefile
>>> +++ b/drivers/crypto/Makefile
>>> @@ -1,5 +1,6 @@
>>> # SPDX-License-Identifier: GPL-2.0
>>> obj-$(CONFIG_CRYPTO_DEV_ALLWINNER) += allwinner/
>>> +obj-$(CONFIG_CRYPTO_DEV_ASPEED) += aspeed/
>>> obj-$(CONFIG_CRYPTO_DEV_ATMEL_AES) += atmel-aes.o
>>> obj-$(CONFIG_CRYPTO_DEV_ATMEL_SHA) += atmel-sha.o
>>> obj-$(CONFIG_CRYPTO_DEV_ATMEL_TDES) += atmel-tdes.o
>>> diff --git a/drivers/crypto/aspeed/Kconfig b/drivers/crypto/aspeed/Kconfig
>>> new file mode 100644
>>> index 000000000000..059e627efef8
>>> --- /dev/null
>>> +++ b/drivers/crypto/aspeed/Kconfig
>>> @@ -0,0 +1,32 @@
>>> +config CRYPTO_DEV_ASPEED
>>> + tristate "Support for Aspeed cryptographic engine driver"
>>> + depends on ARCH_ASPEED
>>> + help
>>> + Hash and Crypto Engine (HACE) is designed to accelerate the
>>> + throughput of hash data digest, encryption and decryption.
>>> +
>>> + Select y here to have support for the cryptographic driver
>>> + available on Aspeed SoC.
>>> +
>>> +config CRYPTO_DEV_ASPEED_HACE_HASH
>>> + bool "Enable Aspeed Hash & Crypto Engine (HACE) hash"
>>> + depends on CRYPTO_DEV_ASPEED
>>> + select CRYPTO_ENGINE
>>> + select CRYPTO_SHA1
>>> + select CRYPTO_SHA256
>>> + select CRYPTO_SHA512
>>> + select CRYPTO_HMAC
>>> + help
>>> + Select here to enable Aspeed Hash & Crypto Engine (HACE)
>>> + hash driver.
>>> + Supports multiple message digest standards, including
>>> + SHA-1, SHA-224, SHA-256, SHA-384, SHA-512, and so on.
>>> +
>>> +config CRYPTO_DEV_ASPEED_HACE_HASH_DEBUG
>>> + bool "Enable HACE hash debug messages"
>>> + depends on CRYPTO_DEV_ASPEED_HACE_HASH
>>> + help
>>> + Print HACE hash debugging messages if you use this option
>>> + to ask for those messages.
>>> + Avoid enabling this option for production build to
>>> + minimize driver timing.
>>> diff --git a/drivers/crypto/aspeed/Makefile
>> b/drivers/crypto/aspeed/Makefile
>>> new file mode 100644
>>> index 000000000000..8bc8d4fed5a9
>>> --- /dev/null
>>> +++ b/drivers/crypto/aspeed/Makefile
>>> @@ -0,0 +1,6 @@
>>> +obj-$(CONFIG_CRYPTO_DEV_ASPEED) += aspeed_crypto.o
>>> +aspeed_crypto-objs := aspeed-hace.o \
>>> + $(hace-hash-y)
>>> +
>>> +obj-$(CONFIG_CRYPTO_DEV_ASPEED_HACE_HASH) += aspeed-hace-hash.o
>>> +hace-hash-$(CONFIG_CRYPTO_DEV_ASPEED_HACE_HASH) :=
>> aspeed-hace-hash.o
>>> diff --git a/drivers/crypto/aspeed/aspeed-hace-hash.c
>> b/drivers/crypto/aspeed/aspeed-hace-hash.c
>>> new file mode 100644
>>> index 000000000000..63a8ad694996
>>> --- /dev/null
>>> +++ b/drivers/crypto/aspeed/aspeed-hace-hash.c
>>> @@ -0,0 +1,1389 @@
>>> +// SPDX-License-Identifier: GPL-2.0+
>>> +/*
>>> + * Copyright (c) 2021 Aspeed Technology Inc.
>>> + */
>>> +
>>> +#include "aspeed-hace.h"
>>> +
>>> +#ifdef CONFIG_CRYPTO_DEV_ASPEED_HACE_HASH_DEBUG
>>> +#define AHASH_DBG(h, fmt, ...) \
>>> + dev_info((h)->dev, "%s() " fmt, __func__, ##__VA_ARGS__)
>>> +#else
>>> +#define AHASH_DBG(h, fmt, ...) \
>>> + dev_dbg((h)->dev, "%s() " fmt, __func__, ##__VA_ARGS__)
>>> +#endif
>>> +
>>> +/* Initialization Vectors for SHA-family */
>>> +static const __be32 sha1_iv[8] = {
>>> + cpu_to_be32(SHA1_H0), cpu_to_be32(SHA1_H1),
>>> + cpu_to_be32(SHA1_H2), cpu_to_be32(SHA1_H3),
>>> + cpu_to_be32(SHA1_H4), 0, 0, 0
>>> +};
>>> +
>>> +static const __be32 sha224_iv[8] = {
>>> + cpu_to_be32(SHA224_H0), cpu_to_be32(SHA224_H1),
>>> + cpu_to_be32(SHA224_H2), cpu_to_be32(SHA224_H3),
>>> + cpu_to_be32(SHA224_H4), cpu_to_be32(SHA224_H5),
>>> + cpu_to_be32(SHA224_H6), cpu_to_be32(SHA224_H7),
>>> +};
>>> +
>>> +static const __be32 sha256_iv[8] = {
>>> + cpu_to_be32(SHA256_H0), cpu_to_be32(SHA256_H1),
>>> + cpu_to_be32(SHA256_H2), cpu_to_be32(SHA256_H3),
>>> + cpu_to_be32(SHA256_H4), cpu_to_be32(SHA256_H5),
>>> + cpu_to_be32(SHA256_H6), cpu_to_be32(SHA256_H7),
>>> +};
>>> +
>>> +static const __be64 sha384_iv[8] = {
>>> + cpu_to_be64(SHA384_H0), cpu_to_be64(SHA384_H1),
>>> + cpu_to_be64(SHA384_H2), cpu_to_be64(SHA384_H3),
>>> + cpu_to_be64(SHA384_H4), cpu_to_be64(SHA384_H5),
>>> + cpu_to_be64(SHA384_H6), cpu_to_be64(SHA384_H7)
>>> +};
>>> +
>>> +static const __be64 sha512_iv[8] = {
>>> + cpu_to_be64(SHA512_H0), cpu_to_be64(SHA512_H1),
>>> + cpu_to_be64(SHA512_H2), cpu_to_be64(SHA512_H3),
>>> + cpu_to_be64(SHA512_H4), cpu_to_be64(SHA512_H5),
>>> + cpu_to_be64(SHA512_H6), cpu_to_be64(SHA512_H7)
>>> +};
>>> +
>>> +static const __be32 sha512_224_iv[16] = {
>>> + cpu_to_be32(0xC8373D8CUL), cpu_to_be32(0xA24D5419UL),
>>> + cpu_to_be32(0x6699E173UL), cpu_to_be32(0xD6D4DC89UL),
>>> + cpu_to_be32(0xAEB7FA1DUL), cpu_to_be32(0x829CFF32UL),
>>> + cpu_to_be32(0x14D59D67UL), cpu_to_be32(0xCF9F2F58UL),
>>> + cpu_to_be32(0x692B6D0FUL), cpu_to_be32(0xA84DD47BUL),
>>> + cpu_to_be32(0x736FE377UL), cpu_to_be32(0x4289C404UL),
>>> + cpu_to_be32(0xA8859D3FUL), cpu_to_be32(0xC8361D6AUL),
>>> + cpu_to_be32(0xADE61211UL), cpu_to_be32(0xA192D691UL)
>>> +};
>>> +
>>> +static const __be32 sha512_256_iv[16] = {
>>> + cpu_to_be32(0x94213122UL), cpu_to_be32(0x2CF72BFCUL),
>>> + cpu_to_be32(0xA35F559FUL), cpu_to_be32(0xC2644CC8UL),
>>> + cpu_to_be32(0x6BB89323UL), cpu_to_be32(0x51B1536FUL),
>>> + cpu_to_be32(0x19773896UL), cpu_to_be32(0xBDEA4059UL),
>>> + cpu_to_be32(0xE23E2896UL), cpu_to_be32(0xE3FF8EA8UL),
>>> + cpu_to_be32(0x251E5EBEUL), cpu_to_be32(0x92398653UL),
>>> + cpu_to_be32(0xFC99012BUL), cpu_to_be32(0xAAB8852CUL),
>>> + cpu_to_be32(0xDC2DB70EUL), cpu_to_be32(0xA22CC581UL)
>>> +};
>>> +
>>> +/* The purpose of this padding is to ensure that the padded message is a
>>> + * multiple of 512 bits (SHA1/SHA224/SHA256) or 1024 bits
>> (SHA384/SHA512).
>>> + * The bit "1" is appended at the end of the message followed by
>>> + * "padlen-1" zero bits. Then a 64 bits block (SHA1/SHA224/SHA256) or
>>> + * 128 bits block (SHA384/SHA512) equals to the message length in bits
>>> + * is appended.
>>> + *
>>> + * For SHA1/SHA224/SHA256, padlen is calculated as followed:
>>> + * - if message length < 56 bytes then padlen = 56 - message length
>>> + * - else padlen = 64 + 56 - message length
>>> + *
>>> + * For SHA384/SHA512, padlen is calculated as followed:
>>> + * - if message length < 112 bytes then padlen = 112 - message length
>>> + * - else padlen = 128 + 112 - message length
>>> + */
>>> +static void aspeed_ahash_fill_padding(struct aspeed_hace_dev *hace_dev,
>>> + struct aspeed_sham_reqctx *rctx)
>>> +{
>>> + unsigned int index, padlen;
>>> + __be64 bits[2];
>>> +
>>> + AHASH_DBG(hace_dev, "rctx flags:0x%x\n", (u32)rctx->flags);
>>> +
>>> + switch (rctx->flags & SHA_FLAGS_MASK) {
>>> + case SHA_FLAGS_SHA1:
>>> + case SHA_FLAGS_SHA224:
>>> + case SHA_FLAGS_SHA256:
>>> + bits[0] = cpu_to_be64(rctx->digcnt[0] << 3);
>>> + index = rctx->bufcnt & 0x3f;
>>> + padlen = (index < 56) ? (56 - index) : ((64 + 56) - index);
>>> + *(rctx->buffer + rctx->bufcnt) = 0x80;
>>> + memset(rctx->buffer + rctx->bufcnt + 1, 0, padlen - 1);
>>> + memcpy(rctx->buffer + rctx->bufcnt + padlen, bits, 8);
>>> + rctx->bufcnt += padlen + 8;
>>> + break;
>>> + default:
>>> + bits[1] = cpu_to_be64(rctx->digcnt[0] << 3);
>>> + bits[0] = cpu_to_be64(rctx->digcnt[1] << 3 |
>>> + rctx->digcnt[0] >> 61);
>>> + index = rctx->bufcnt & 0x7f;
>>> + padlen = (index < 112) ? (112 - index) : ((128 + 112) - index);
>>> + *(rctx->buffer + rctx->bufcnt) = 0x80;
>>> + memset(rctx->buffer + rctx->bufcnt + 1, 0, padlen - 1);
>>> + memcpy(rctx->buffer + rctx->bufcnt + padlen, bits, 16);
>>> + rctx->bufcnt += padlen + 16;
>>> + break;
>>> + }
>>> +}
>>> +
>>> +/*
>>> + * Prepare DMA buffer before hardware engine
>>> + * processing.
>>> + */
>>> +static int aspeed_ahash_dma_prepare(struct aspeed_hace_dev *hace_dev)
>>> +{
>>> + struct aspeed_engine_hash *hash_engine = &hace_dev->hash_engine;
>>> + struct ahash_request *req = hash_engine->req;
>>> + struct aspeed_sham_reqctx *rctx = ahash_request_ctx(req);
>>> + int length, remain;
>>> +
>>> + length = rctx->total + rctx->bufcnt;
>>> + remain = length % rctx->block_size;
>>> +
>>> + AHASH_DBG(hace_dev, "length:0x%x, remain:0x%x\n", length, remain);
>>> +
>>> + if (rctx->bufcnt)
>>> + memcpy(hash_engine->ahash_src_addr, rctx->buffer, rctx->bufcnt);
>>> +
>>> + if (rctx->total + rctx->bufcnt < ASPEED_CRYPTO_SRC_DMA_BUF_LEN) {
>>> + scatterwalk_map_and_copy(hash_engine->ahash_src_addr +
>>> + rctx->bufcnt, rctx->src_sg,
>>> + rctx->offset, rctx->total - remain, 0);
>>> + rctx->offset += rctx->total - remain;
>>> +
>>> + } else {
>>> + dev_warn(hace_dev->dev, "Hash data length is too large\n");
>>> + return -EINVAL;
>>> + }
>>> +
>>> + scatterwalk_map_and_copy(rctx->buffer, rctx->src_sg,
>>> + rctx->offset, remain, 0);
>>> +
>>> + rctx->bufcnt = remain;
>>> + rctx->digest_dma_addr = dma_map_single(hace_dev->dev, rctx->digest,
>>> + SHA512_DIGEST_SIZE,
>>> + DMA_BIDIRECTIONAL);
>>> + if (dma_mapping_error(hace_dev->dev, rctx->digest_dma_addr)) {
>>> + dev_warn(hace_dev->dev, "dma_map() rctx digest error\n");
>>> + return -ENOMEM;
>>> + }
>>> +
>>> + hash_engine->src_length = length - remain;
>>> + hash_engine->src_dma = hash_engine->ahash_src_dma_addr;
>>> + hash_engine->digest_dma = rctx->digest_dma_addr;
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +/*
>>> + * Prepare DMA buffer as SG list buffer before
>>> + * hardware engine processing.
>>> + */
>>> +static int aspeed_ahash_dma_prepare_sg(struct aspeed_hace_dev
>> *hace_dev)
>>> +{
>>> + struct aspeed_engine_hash *hash_engine = &hace_dev->hash_engine;
>>> + struct ahash_request *req = hash_engine->req;
>>> + struct aspeed_sham_reqctx *rctx = ahash_request_ctx(req);
>>> + struct aspeed_sg_list *src_list;
>>> + struct scatterlist *s;
>>> + int length, remain, sg_len, i;
>>> + int rc = 0;
>>> +
>>> + remain = (rctx->total + rctx->bufcnt) % rctx->block_size;
>>> + length = rctx->total + rctx->bufcnt - remain;
>>> +
>>> + AHASH_DBG(hace_dev, "%s:0x%x, %s:0x%x, %s:0x%x, %s:0x%x\n",
>>> + "rctx total", rctx->total, "bufcnt", rctx->bufcnt,
>>> + "length", length, "remain", remain);
>>> +
>>> + sg_len = dma_map_sg(hace_dev->dev, rctx->src_sg, rctx->src_nents,
>>> + DMA_TO_DEVICE);
>>> + if (!sg_len) {
>>> + dev_warn(hace_dev->dev, "dma_map_sg() src error\n");
>>> + rc = -ENOMEM;
>>> + goto end;
>>> + }
>>> +
>>> + src_list = (struct aspeed_sg_list *)hash_engine->ahash_src_addr;
>>> + rctx->digest_dma_addr = dma_map_single(hace_dev->dev, rctx->digest,
>>> + SHA512_DIGEST_SIZE,
>>> + DMA_BIDIRECTIONAL);
>>> + if (dma_mapping_error(hace_dev->dev, rctx->digest_dma_addr)) {
>>> + dev_warn(hace_dev->dev, "dma_map() rctx digest error\n");
>>> + rc = -ENOMEM;
>>> + goto free_src_sg;
>>> + }
>>> +
>>> + if (rctx->bufcnt != 0) {
>>> + rctx->buffer_dma_addr = dma_map_single(hace_dev->dev,
>>> + rctx->buffer,
>>> + rctx->block_size * 2,
>>> + DMA_TO_DEVICE);
>>> + if (dma_mapping_error(hace_dev->dev, rctx->buffer_dma_addr)) {
>>> + dev_warn(hace_dev->dev, "dma_map() rctx buffer error\n");
>>> + rc = -ENOMEM;
>>> + goto free_rctx_digest;
>>> + }
>>> +
>>> + src_list[0].phy_addr = rctx->buffer_dma_addr;
>>> + src_list[0].len = rctx->bufcnt;
>>> + length -= src_list[0].len;
>>> +
>>> + /* Last sg list */
>>> + if (length == 0)
>>> + src_list[0].len |= HASH_SG_LAST_LIST;
>>> +
>>> + src_list[0].phy_addr = cpu_to_le32(src_list[0].phy_addr);
>>> + src_list[0].len = cpu_to_le32(src_list[0].len);
>>> + src_list++;
>>> + }
>>> +
>>> + if (length != 0) {
>>> + for_each_sg(rctx->src_sg, s, sg_len, i) {
>>> + src_list[i].phy_addr = sg_dma_address(s);
>>> +
>>> + if (length > sg_dma_len(s)) {
>>> + src_list[i].len = sg_dma_len(s);
>>> + length -= sg_dma_len(s);
>>> +
>>> + } else {
>>> + /* Last sg list */
>>> + src_list[i].len = length;
>>> + src_list[i].len |= HASH_SG_LAST_LIST;
>>> + length = 0;
>>> + }
>>> +
>>> + src_list[i].phy_addr = cpu_to_le32(src_list[i].phy_addr);
>>> + src_list[i].len = cpu_to_le32(src_list[i].len);
>>> + }
>>> + }
>>> +
>>> + if (length != 0) {
>>> + rc = -EINVAL;
>>> + goto free_rctx_buffer;
>>> + }
>>> +
>>> + rctx->offset = rctx->total - remain;
>>> + hash_engine->src_length = rctx->total + rctx->bufcnt - remain;
>>> + hash_engine->src_dma = hash_engine->ahash_src_dma_addr;
>>> + hash_engine->digest_dma = rctx->digest_dma_addr;
>>> +
>>> + goto end;
>> Exiting via "goto xx" is not recommended in normal code logic (this requires
>> two jumps),
>> exiting via "return 0" is more efficient.
>> This code method has many times in your entire driver, it is recommended to
>> modify it.
>
> If not exiting via "goto xx", how to release related resources without any problem?
> Is there any proper way to do this?
maybe I didn't describe it clearly enough.
"in normal code logic" means rc=0
In this scenario (rc=0), "goto xx" is no longer required,
it can be replaced with "return 0"
>
>>> +
>>> +free_rctx_buffer:
>>> + if (rctx->bufcnt != 0)
>>> + dma_unmap_single(hace_dev->dev, rctx->buffer_dma_addr,
>>> + rctx->block_size * 2, DMA_TO_DEVICE);
>>> +free_rctx_digest:
>>> + dma_unmap_single(hace_dev->dev, rctx->digest_dma_addr,
>>> + SHA512_DIGEST_SIZE, DMA_BIDIRECTIONAL);
>>> +free_src_sg:
>>> + dma_unmap_sg(hace_dev->dev, rctx->src_sg, rctx->src_nents,
>>> + DMA_TO_DEVICE);
>>> +end:
>>> + return rc;
>>> +}
>>> +
>>> +static int aspeed_ahash_complete(struct aspeed_hace_dev *hace_dev)
>>> +{
>>> + struct aspeed_engine_hash *hash_engine = &hace_dev->hash_engine;
>>> + struct ahash_request *req = hash_engine->req;
>>> +
>>> + AHASH_DBG(hace_dev, "\n");
>>> +
>>> + hash_engine->flags &= ~CRYPTO_FLAGS_BUSY;
>>> +
>>> + crypto_finalize_hash_request(hace_dev->crypt_engine_hash, req, 0);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +/*
>>> + * Copy digest to the corresponding request result.
>>> + * This function will be called at final() stage.
>>> + */
>>> +static int aspeed_ahash_transfer(struct aspeed_hace_dev *hace_dev)
>>> +{
>>> + struct aspeed_engine_hash *hash_engine = &hace_dev->hash_engine;
>>> + struct ahash_request *req = hash_engine->req;
>>> + struct aspeed_sham_reqctx *rctx = ahash_request_ctx(req);
>>> +
>>> + AHASH_DBG(hace_dev, "\n");
>>> +
>>> + dma_unmap_single(hace_dev->dev, rctx->digest_dma_addr,
>>> + SHA512_DIGEST_SIZE, DMA_BIDIRECTIONAL);
>>> +
>>> + dma_unmap_single(hace_dev->dev, rctx->buffer_dma_addr,
>>> + rctx->block_size * 2, DMA_TO_DEVICE);
>>> +
>>> + memcpy(req->result, rctx->digest, rctx->digsize);
>>> +
>>> + return aspeed_ahash_complete(hace_dev);
>>> +}
>>> +
>>> +/*
>>> + * Trigger hardware engines to do the math.
>>> + */
>>> +static int aspeed_hace_ahash_trigger(struct aspeed_hace_dev *hace_dev,
>>> + aspeed_hace_fn_t resume)
>>> +{
>>> + struct aspeed_engine_hash *hash_engine = &hace_dev->hash_engine;
>>> + struct ahash_request *req = hash_engine->req;
>>> + struct aspeed_sham_reqctx *rctx = ahash_request_ctx(req);
>>> +
>>> + AHASH_DBG(hace_dev, "src_dma:0x%x, digest_dma:0x%x,
>> length:0x%x\n",
>>> + hash_engine->src_dma, hash_engine->digest_dma,
>>> + hash_engine->src_length);
>>> +
>>> + rctx->cmd |= HASH_CMD_INT_ENABLE;
>>> + hash_engine->resume = resume;
>>> +
>>> + ast_hace_write(hace_dev, hash_engine->src_dma,
>> ASPEED_HACE_HASH_SRC);
>>> + ast_hace_write(hace_dev, hash_engine->digest_dma,
>>> + ASPEED_HACE_HASH_DIGEST_BUFF);
>>> + ast_hace_write(hace_dev, hash_engine->digest_dma,
>>> + ASPEED_HACE_HASH_KEY_BUFF);
>>> + ast_hace_write(hace_dev, hash_engine->src_length,
>>> + ASPEED_HACE_HASH_DATA_LEN);
>>> +
>>> + /* Memory barrier to ensure all data setup before engine starts */
>>> + mb();
>>> +
>>> + ast_hace_write(hace_dev, rctx->cmd, ASPEED_HACE_HASH_CMD);
>> A hardware service sending requires 5 hardware commands to complete.
>> In a multi-concurrency scenario, how to ensure the order of commands?
>> (If two processes send hardware task at the same time,
>> How to ensure that the hardware recognizes which task the current
>> command belongs to?)
>
> Linux crypto engine would guarantee that only one request at each time to be dequeued from engine queue to process.
> And there has lock mechanism inside Linux crypto engine to prevent the scenario you mentioned.
> So only 1 aspeed_hace_ahash_trigger() hardware service would go through at a time.
>
> [...]
> .
>
You may not understand what I mean, the command flow in a normal scenario:
request_A: Acmd1-->Acmd2-->Acmd3-->Acmd4-->Acmd5
request_B: Bcmd1-->Bcmd2-->Bcmd3-->Bcmd4-->Bcmd5
In a multi-process concurrent scenario, multiple crypto engines can be enabled,
and each crypto engine sends a request. If multiple requests here enter
aspeed_hace_ahash_trigger() at the same time, the command flow will be
intertwined like this:
request_A, request_B: Acmd1-->Bcmd1-->Acmd2-->Acmd3-->Bcmd2-->Acmd4-->Bcmd3-->Bcmd4-->Acmd5-->Bcmd5
In this command flow, how does your hardware identify whether these commands
belong to request_A or request_B?
Thanks.
Longfang.
More information about the Linux-aspeed
mailing list