* Re: [PATCH 17/29] crypto: talitos/aead - Use macro for algorithm definitions
From: Christophe Leroy (CS GROUP) @ 2026-06-01 12:12 UTC (permalink / raw)
To: Paul Louvel, Herbert Xu, David S. Miller
Cc: Thomas Petazzoni, Herve Codina, linux-crypto, linux-kernel
In-Reply-To: <20260528-7-1-rc1_talitos_cleanup-v1-17-cb1ad6cdea49@bootlin.com>
Le 28/05/2026 à 11:08, Paul Louvel a écrit :
> Replace the repetitive struct initializer entries in aead_driver_algs[]
> with preprocessor macros (TALITOS_AEAD_ALG, TALITOS_AEAD_ALG_HSNA).
>
> Move the function pointer assignments (init, exit, encrypt, decrypt)
> from the registration loop into the static initializer, since they are
> identical for all algorithms.
>
> The fallback setkey assignment (aead_alg->setkey ?: aead_setkey) is
> replaced by specifying the correct setkey handler directly in each macro
> invocation.
>
> Signed-off-by: Paul Louvel <paul.louvel@bootlin.com>
Reviewed-by: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
Wondering if we could go even more far with the COMMON flags, as for
instance all TALITOS_AEAD_ALG_HSNA have DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU
while TALITOS_AEAD_ALG have DESC_HDR_TYPE_IPSEC_ESP
> ---
> drivers/crypto/talitos/talitos-aead.c | 751 ++++++++++------------------------
> 1 file changed, 218 insertions(+), 533 deletions(-)
>
> diff --git a/drivers/crypto/talitos/talitos-aead.c b/drivers/crypto/talitos/talitos-aead.c
> index 38df616c9b22..cd1b8e6d371b 100644
> --- a/drivers/crypto/talitos/talitos-aead.c
> +++ b/drivers/crypto/talitos/talitos-aead.c
> @@ -405,535 +405,225 @@ static void talitos_cra_exit_aead(struct crypto_aead *tfm)
> talitos_cra_exit(crypto_aead_tfm(tfm));
> }
>
> +#define TALITOS_AEAD_ALG_COMMON(name, name_prefix, set_key, block_size, \
> + max_auth_size, template, priority) \
> + { \
> + .type = CRYPTO_ALG_TYPE_AEAD, \
> + .alg.aead = { \
> + .base = { \
> + .cra_name = name, \
> + .cra_driver_name = name"-talitos"name_prefix, \
> + .cra_blocksize = block_size, \
> + .cra_flags = CRYPTO_ALG_ASYNC | \
> + CRYPTO_ALG_ALLOCATES_MEMORY | \
> + CRYPTO_ALG_KERN_DRIVER_ONLY, \
> + .cra_priority = (priority), \
> + .cra_ctxsize = sizeof(struct talitos_ctx), \
> + .cra_module = THIS_MODULE, \
> + }, \
> + .ivsize = block_size, \
> + .maxauthsize = max_auth_size, \
> + .setkey = set_key, \
> + .init = talitos_cra_init_aead, \
> + .exit = talitos_cra_exit_aead, \
> + .encrypt = aead_encrypt, \
> + .decrypt = aead_decrypt, \
> + }, \
> + .desc_hdr_template = template, \
> + }
> +
> +#define TALITOS_AEAD_ALG(name, set_key, block_size, max_auth_size, template) \
> + TALITOS_AEAD_ALG_COMMON(name, "", set_key, block_size, max_auth_size, \
> + template, TALITOS_CRA_PRIORITY)
> +
> +#define TALITOS_AEAD_ALG_HSNA(name, set_key, block_size, max_auth_size, \
> + template) \
> + TALITOS_AEAD_ALG_COMMON(name, "-hsna", set_key, block_size, \
> + max_auth_size, template, \
> + TALITOS_CRA_PRIORITY_AEAD_HSNA)
> +
> static struct talitos_alg_template aead_driver_algs[] = {
> - { .type = CRYPTO_ALG_TYPE_AEAD,
> - .alg.aead = {
> - .base = {
> - .cra_name = "authenc(hmac(sha1),cbc(aes))",
> - .cra_driver_name = "authenc-hmac-sha1-"
> - "cbc-aes-talitos",
> - .cra_blocksize = AES_BLOCK_SIZE,
> - .cra_flags = CRYPTO_ALG_ASYNC |
> - CRYPTO_ALG_ALLOCATES_MEMORY |
> - CRYPTO_ALG_KERN_DRIVER_ONLY,
> - .cra_priority = TALITOS_CRA_PRIORITY,
> - .cra_ctxsize = sizeof(struct talitos_ctx),
> - .cra_module = THIS_MODULE,
> - },
> - .ivsize = AES_BLOCK_SIZE,
> - .maxauthsize = SHA1_DIGEST_SIZE,
> - },
> - .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
> - DESC_HDR_SEL0_AESU |
> - DESC_HDR_MODE0_AESU_CBC |
> - DESC_HDR_SEL1_MDEUA |
> - DESC_HDR_MODE1_MDEU_INIT |
> - DESC_HDR_MODE1_MDEU_PAD |
> - DESC_HDR_MODE1_MDEU_SHA1_HMAC,
> - },
> - { .type = CRYPTO_ALG_TYPE_AEAD,
> - .alg.aead = {
> - .base = {
> - .cra_name = "authenc(hmac(sha1),cbc(aes))",
> - .cra_driver_name = "authenc-hmac-sha1-"
> - "cbc-aes-talitos-hsna",
> - .cra_blocksize = AES_BLOCK_SIZE,
> - .cra_flags = CRYPTO_ALG_ASYNC |
> - CRYPTO_ALG_ALLOCATES_MEMORY |
> - CRYPTO_ALG_KERN_DRIVER_ONLY,
> - .cra_priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
> - .cra_ctxsize = sizeof(struct talitos_ctx),
> - .cra_module = THIS_MODULE,
> - },
> - .ivsize = AES_BLOCK_SIZE,
> - .maxauthsize = SHA1_DIGEST_SIZE,
> - },
> - .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
> - DESC_HDR_SEL0_AESU |
> - DESC_HDR_MODE0_AESU_CBC |
> - DESC_HDR_SEL1_MDEUA |
> - DESC_HDR_MODE1_MDEU_INIT |
> - DESC_HDR_MODE1_MDEU_PAD |
> - DESC_HDR_MODE1_MDEU_SHA1_HMAC,
> - },
> - { .type = CRYPTO_ALG_TYPE_AEAD,
> - .alg.aead = {
> - .base = {
> - .cra_name = "authenc(hmac(sha1),"
> - "cbc(des3_ede))",
> - .cra_driver_name = "authenc-hmac-sha1-"
> - "cbc-3des-talitos",
> - .cra_blocksize = DES3_EDE_BLOCK_SIZE,
> - .cra_flags = CRYPTO_ALG_ASYNC |
> - CRYPTO_ALG_ALLOCATES_MEMORY |
> - CRYPTO_ALG_KERN_DRIVER_ONLY,
> - .cra_priority = TALITOS_CRA_PRIORITY,
> - .cra_ctxsize = sizeof(struct talitos_ctx),
> - .cra_module = THIS_MODULE,
> - },
> - .ivsize = DES3_EDE_BLOCK_SIZE,
> - .maxauthsize = SHA1_DIGEST_SIZE,
> - .setkey = aead_des3_setkey,
> - },
> - .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
> - DESC_HDR_SEL0_DEU |
> - DESC_HDR_MODE0_DEU_CBC |
> - DESC_HDR_MODE0_DEU_3DES |
> - DESC_HDR_SEL1_MDEUA |
> - DESC_HDR_MODE1_MDEU_INIT |
> - DESC_HDR_MODE1_MDEU_PAD |
> - DESC_HDR_MODE1_MDEU_SHA1_HMAC,
> - },
> - { .type = CRYPTO_ALG_TYPE_AEAD,
> - .alg.aead = {
> - .base = {
> - .cra_name = "authenc(hmac(sha1),"
> - "cbc(des3_ede))",
> - .cra_driver_name = "authenc-hmac-sha1-"
> - "cbc-3des-talitos-hsna",
> - .cra_blocksize = DES3_EDE_BLOCK_SIZE,
> - .cra_flags = CRYPTO_ALG_ASYNC |
> - CRYPTO_ALG_ALLOCATES_MEMORY |
> - CRYPTO_ALG_KERN_DRIVER_ONLY,
> - .cra_priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
> - .cra_ctxsize = sizeof(struct talitos_ctx),
> - .cra_module = THIS_MODULE,
> - },
> - .ivsize = DES3_EDE_BLOCK_SIZE,
> - .maxauthsize = SHA1_DIGEST_SIZE,
> - .setkey = aead_des3_setkey,
> - },
> - .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
> - DESC_HDR_SEL0_DEU |
> - DESC_HDR_MODE0_DEU_CBC |
> - DESC_HDR_MODE0_DEU_3DES |
> - DESC_HDR_SEL1_MDEUA |
> - DESC_HDR_MODE1_MDEU_INIT |
> - DESC_HDR_MODE1_MDEU_PAD |
> - DESC_HDR_MODE1_MDEU_SHA1_HMAC,
> - },
> - { .type = CRYPTO_ALG_TYPE_AEAD,
> - .alg.aead = {
> - .base = {
> - .cra_name = "authenc(hmac(sha224),cbc(aes))",
> - .cra_driver_name = "authenc-hmac-sha224-"
> - "cbc-aes-talitos",
> - .cra_blocksize = AES_BLOCK_SIZE,
> - .cra_flags = CRYPTO_ALG_ASYNC |
> - CRYPTO_ALG_ALLOCATES_MEMORY |
> - CRYPTO_ALG_KERN_DRIVER_ONLY,
> - .cra_priority = TALITOS_CRA_PRIORITY,
> - .cra_ctxsize = sizeof(struct talitos_ctx),
> - .cra_module = THIS_MODULE,
> - },
> - .ivsize = AES_BLOCK_SIZE,
> - .maxauthsize = SHA224_DIGEST_SIZE,
> - },
> - .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
> - DESC_HDR_SEL0_AESU |
> - DESC_HDR_MODE0_AESU_CBC |
> - DESC_HDR_SEL1_MDEUA |
> - DESC_HDR_MODE1_MDEU_INIT |
> - DESC_HDR_MODE1_MDEU_PAD |
> - DESC_HDR_MODE1_MDEU_SHA224_HMAC,
> - },
> - { .type = CRYPTO_ALG_TYPE_AEAD,
> - .alg.aead = {
> - .base = {
> - .cra_name = "authenc(hmac(sha224),cbc(aes))",
> - .cra_driver_name = "authenc-hmac-sha224-"
> - "cbc-aes-talitos-hsna",
> - .cra_blocksize = AES_BLOCK_SIZE,
> - .cra_flags = CRYPTO_ALG_ASYNC |
> - CRYPTO_ALG_ALLOCATES_MEMORY |
> - CRYPTO_ALG_KERN_DRIVER_ONLY,
> - .cra_priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
> - .cra_ctxsize = sizeof(struct talitos_ctx),
> - .cra_module = THIS_MODULE,
> - },
> - .ivsize = AES_BLOCK_SIZE,
> - .maxauthsize = SHA224_DIGEST_SIZE,
> - },
> - .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
> - DESC_HDR_SEL0_AESU |
> - DESC_HDR_MODE0_AESU_CBC |
> - DESC_HDR_SEL1_MDEUA |
> - DESC_HDR_MODE1_MDEU_INIT |
> - DESC_HDR_MODE1_MDEU_PAD |
> - DESC_HDR_MODE1_MDEU_SHA224_HMAC,
> - },
> - { .type = CRYPTO_ALG_TYPE_AEAD,
> - .alg.aead = {
> - .base = {
> - .cra_name = "authenc(hmac(sha224),"
> - "cbc(des3_ede))",
> - .cra_driver_name = "authenc-hmac-sha224-"
> - "cbc-3des-talitos",
> - .cra_blocksize = DES3_EDE_BLOCK_SIZE,
> - .cra_flags = CRYPTO_ALG_ASYNC |
> - CRYPTO_ALG_ALLOCATES_MEMORY |
> - CRYPTO_ALG_KERN_DRIVER_ONLY,
> - .cra_priority = TALITOS_CRA_PRIORITY,
> - .cra_ctxsize = sizeof(struct talitos_ctx),
> - .cra_module = THIS_MODULE,
> - },
> - .ivsize = DES3_EDE_BLOCK_SIZE,
> - .maxauthsize = SHA224_DIGEST_SIZE,
> - .setkey = aead_des3_setkey,
> - },
> - .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
> - DESC_HDR_SEL0_DEU |
> - DESC_HDR_MODE0_DEU_CBC |
> - DESC_HDR_MODE0_DEU_3DES |
> - DESC_HDR_SEL1_MDEUA |
> - DESC_HDR_MODE1_MDEU_INIT |
> - DESC_HDR_MODE1_MDEU_PAD |
> - DESC_HDR_MODE1_MDEU_SHA224_HMAC,
> - },
> - { .type = CRYPTO_ALG_TYPE_AEAD,
> - .alg.aead = {
> - .base = {
> - .cra_name = "authenc(hmac(sha224),"
> - "cbc(des3_ede))",
> - .cra_driver_name = "authenc-hmac-sha224-"
> - "cbc-3des-talitos-hsna",
> - .cra_blocksize = DES3_EDE_BLOCK_SIZE,
> - .cra_flags = CRYPTO_ALG_ASYNC |
> - CRYPTO_ALG_ALLOCATES_MEMORY |
> - CRYPTO_ALG_KERN_DRIVER_ONLY,
> - .cra_priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
> - .cra_ctxsize = sizeof(struct talitos_ctx),
> - .cra_module = THIS_MODULE,
> - },
> - .ivsize = DES3_EDE_BLOCK_SIZE,
> - .maxauthsize = SHA224_DIGEST_SIZE,
> - .setkey = aead_des3_setkey,
> - },
> - .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
> - DESC_HDR_SEL0_DEU |
> - DESC_HDR_MODE0_DEU_CBC |
> - DESC_HDR_MODE0_DEU_3DES |
> - DESC_HDR_SEL1_MDEUA |
> - DESC_HDR_MODE1_MDEU_INIT |
> - DESC_HDR_MODE1_MDEU_PAD |
> - DESC_HDR_MODE1_MDEU_SHA224_HMAC,
> - },
> - { .type = CRYPTO_ALG_TYPE_AEAD,
> - .alg.aead = {
> - .base = {
> - .cra_name = "authenc(hmac(sha256),cbc(aes))",
> - .cra_driver_name = "authenc-hmac-sha256-"
> - "cbc-aes-talitos",
> - .cra_blocksize = AES_BLOCK_SIZE,
> - .cra_flags = CRYPTO_ALG_ASYNC |
> - CRYPTO_ALG_ALLOCATES_MEMORY |
> - CRYPTO_ALG_KERN_DRIVER_ONLY,
> - .cra_priority = TALITOS_CRA_PRIORITY,
> - .cra_ctxsize = sizeof(struct talitos_ctx),
> - .cra_module = THIS_MODULE,
> - },
> - .ivsize = AES_BLOCK_SIZE,
> - .maxauthsize = SHA256_DIGEST_SIZE,
> - },
> - .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
> - DESC_HDR_SEL0_AESU |
> - DESC_HDR_MODE0_AESU_CBC |
> - DESC_HDR_SEL1_MDEUA |
> - DESC_HDR_MODE1_MDEU_INIT |
> - DESC_HDR_MODE1_MDEU_PAD |
> - DESC_HDR_MODE1_MDEU_SHA256_HMAC,
> - },
> - { .type = CRYPTO_ALG_TYPE_AEAD,
> - .alg.aead = {
> - .base = {
> - .cra_name = "authenc(hmac(sha256),cbc(aes))",
> - .cra_driver_name = "authenc-hmac-sha256-"
> - "cbc-aes-talitos-hsna",
> - .cra_blocksize = AES_BLOCK_SIZE,
> - .cra_flags = CRYPTO_ALG_ASYNC |
> - CRYPTO_ALG_ALLOCATES_MEMORY |
> - CRYPTO_ALG_KERN_DRIVER_ONLY,
> - .cra_priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
> - .cra_ctxsize = sizeof(struct talitos_ctx),
> - .cra_module = THIS_MODULE,
> - },
> - .ivsize = AES_BLOCK_SIZE,
> - .maxauthsize = SHA256_DIGEST_SIZE,
> - },
> - .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
> - DESC_HDR_SEL0_AESU |
> - DESC_HDR_MODE0_AESU_CBC |
> - DESC_HDR_SEL1_MDEUA |
> - DESC_HDR_MODE1_MDEU_INIT |
> - DESC_HDR_MODE1_MDEU_PAD |
> - DESC_HDR_MODE1_MDEU_SHA256_HMAC,
> - },
> - { .type = CRYPTO_ALG_TYPE_AEAD,
> - .alg.aead = {
> - .base = {
> - .cra_name = "authenc(hmac(sha256),"
> - "cbc(des3_ede))",
> - .cra_driver_name = "authenc-hmac-sha256-"
> - "cbc-3des-talitos",
> - .cra_blocksize = DES3_EDE_BLOCK_SIZE,
> - .cra_flags = CRYPTO_ALG_ASYNC |
> - CRYPTO_ALG_ALLOCATES_MEMORY |
> - CRYPTO_ALG_KERN_DRIVER_ONLY,
> - .cra_priority = TALITOS_CRA_PRIORITY,
> - .cra_ctxsize = sizeof(struct talitos_ctx),
> - .cra_module = THIS_MODULE,
> - },
> - .ivsize = DES3_EDE_BLOCK_SIZE,
> - .maxauthsize = SHA256_DIGEST_SIZE,
> - .setkey = aead_des3_setkey,
> - },
> - .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
> - DESC_HDR_SEL0_DEU |
> - DESC_HDR_MODE0_DEU_CBC |
> - DESC_HDR_MODE0_DEU_3DES |
> - DESC_HDR_SEL1_MDEUA |
> - DESC_HDR_MODE1_MDEU_INIT |
> - DESC_HDR_MODE1_MDEU_PAD |
> - DESC_HDR_MODE1_MDEU_SHA256_HMAC,
> - },
> - { .type = CRYPTO_ALG_TYPE_AEAD,
> - .alg.aead = {
> - .base = {
> - .cra_name = "authenc(hmac(sha256),"
> - "cbc(des3_ede))",
> - .cra_driver_name = "authenc-hmac-sha256-"
> - "cbc-3des-talitos-hsna",
> - .cra_blocksize = DES3_EDE_BLOCK_SIZE,
> - .cra_flags = CRYPTO_ALG_ASYNC |
> - CRYPTO_ALG_ALLOCATES_MEMORY |
> - CRYPTO_ALG_KERN_DRIVER_ONLY,
> - .cra_priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
> - .cra_ctxsize = sizeof(struct talitos_ctx),
> - .cra_module = THIS_MODULE,
> - },
> - .ivsize = DES3_EDE_BLOCK_SIZE,
> - .maxauthsize = SHA256_DIGEST_SIZE,
> - .setkey = aead_des3_setkey,
> - },
> - .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
> - DESC_HDR_SEL0_DEU |
> - DESC_HDR_MODE0_DEU_CBC |
> - DESC_HDR_MODE0_DEU_3DES |
> - DESC_HDR_SEL1_MDEUA |
> - DESC_HDR_MODE1_MDEU_INIT |
> - DESC_HDR_MODE1_MDEU_PAD |
> - DESC_HDR_MODE1_MDEU_SHA256_HMAC,
> - },
> - { .type = CRYPTO_ALG_TYPE_AEAD,
> - .alg.aead = {
> - .base = {
> - .cra_name = "authenc(hmac(sha384),cbc(aes))",
> - .cra_driver_name = "authenc-hmac-sha384-"
> - "cbc-aes-talitos",
> - .cra_blocksize = AES_BLOCK_SIZE,
> - .cra_flags = CRYPTO_ALG_ASYNC |
> - CRYPTO_ALG_ALLOCATES_MEMORY |
> - CRYPTO_ALG_KERN_DRIVER_ONLY,
> - .cra_priority = TALITOS_CRA_PRIORITY,
> - .cra_ctxsize = sizeof(struct talitos_ctx),
> - .cra_module = THIS_MODULE,
> - },
> - .ivsize = AES_BLOCK_SIZE,
> - .maxauthsize = SHA384_DIGEST_SIZE,
> - },
> - .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
> - DESC_HDR_SEL0_AESU |
> - DESC_HDR_MODE0_AESU_CBC |
> - DESC_HDR_SEL1_MDEUB |
> - DESC_HDR_MODE1_MDEU_INIT |
> - DESC_HDR_MODE1_MDEU_PAD |
> - DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
> - },
> - { .type = CRYPTO_ALG_TYPE_AEAD,
> - .alg.aead = {
> - .base = {
> - .cra_name = "authenc(hmac(sha384),"
> - "cbc(des3_ede))",
> - .cra_driver_name = "authenc-hmac-sha384-"
> - "cbc-3des-talitos",
> - .cra_blocksize = DES3_EDE_BLOCK_SIZE,
> - .cra_flags = CRYPTO_ALG_ASYNC |
> - CRYPTO_ALG_ALLOCATES_MEMORY |
> - CRYPTO_ALG_KERN_DRIVER_ONLY,
> - .cra_priority = TALITOS_CRA_PRIORITY,
> - .cra_ctxsize = sizeof(struct talitos_ctx),
> - .cra_module = THIS_MODULE,
> - },
> - .ivsize = DES3_EDE_BLOCK_SIZE,
> - .maxauthsize = SHA384_DIGEST_SIZE,
> - .setkey = aead_des3_setkey,
> - },
> - .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
> - DESC_HDR_SEL0_DEU |
> - DESC_HDR_MODE0_DEU_CBC |
> - DESC_HDR_MODE0_DEU_3DES |
> - DESC_HDR_SEL1_MDEUB |
> - DESC_HDR_MODE1_MDEU_INIT |
> - DESC_HDR_MODE1_MDEU_PAD |
> - DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
> - },
> - { .type = CRYPTO_ALG_TYPE_AEAD,
> - .alg.aead = {
> - .base = {
> - .cra_name = "authenc(hmac(sha512),cbc(aes))",
> - .cra_driver_name = "authenc-hmac-sha512-"
> - "cbc-aes-talitos",
> - .cra_blocksize = AES_BLOCK_SIZE,
> - .cra_flags = CRYPTO_ALG_ASYNC |
> - CRYPTO_ALG_ALLOCATES_MEMORY |
> - CRYPTO_ALG_KERN_DRIVER_ONLY,
> - .cra_priority = TALITOS_CRA_PRIORITY,
> - .cra_ctxsize = sizeof(struct talitos_ctx),
> - .cra_module = THIS_MODULE,
> - },
> - .ivsize = AES_BLOCK_SIZE,
> - .maxauthsize = SHA512_DIGEST_SIZE,
> - },
> - .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
> - DESC_HDR_SEL0_AESU |
> - DESC_HDR_MODE0_AESU_CBC |
> - DESC_HDR_SEL1_MDEUB |
> - DESC_HDR_MODE1_MDEU_INIT |
> - DESC_HDR_MODE1_MDEU_PAD |
> - DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
> - },
> - { .type = CRYPTO_ALG_TYPE_AEAD,
> - .alg.aead = {
> - .base = {
> - .cra_name = "authenc(hmac(sha512),"
> - "cbc(des3_ede))",
> - .cra_driver_name = "authenc-hmac-sha512-"
> - "cbc-3des-talitos",
> - .cra_blocksize = DES3_EDE_BLOCK_SIZE,
> - .cra_flags = CRYPTO_ALG_ASYNC |
> - CRYPTO_ALG_ALLOCATES_MEMORY |
> - CRYPTO_ALG_KERN_DRIVER_ONLY,
> - .cra_priority = TALITOS_CRA_PRIORITY,
> - .cra_ctxsize = sizeof(struct talitos_ctx),
> - .cra_module = THIS_MODULE,
> - },
> - .ivsize = DES3_EDE_BLOCK_SIZE,
> - .maxauthsize = SHA512_DIGEST_SIZE,
> - .setkey = aead_des3_setkey,
> - },
> - .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
> - DESC_HDR_SEL0_DEU |
> - DESC_HDR_MODE0_DEU_CBC |
> - DESC_HDR_MODE0_DEU_3DES |
> - DESC_HDR_SEL1_MDEUB |
> - DESC_HDR_MODE1_MDEU_INIT |
> - DESC_HDR_MODE1_MDEU_PAD |
> - DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
> - },
> - { .type = CRYPTO_ALG_TYPE_AEAD,
> - .alg.aead = {
> - .base = {
> - .cra_name = "authenc(hmac(md5),cbc(aes))",
> - .cra_driver_name = "authenc-hmac-md5-"
> - "cbc-aes-talitos",
> - .cra_blocksize = AES_BLOCK_SIZE,
> - .cra_flags = CRYPTO_ALG_ASYNC |
> - CRYPTO_ALG_ALLOCATES_MEMORY |
> - CRYPTO_ALG_KERN_DRIVER_ONLY,
> - .cra_priority = TALITOS_CRA_PRIORITY,
> - .cra_ctxsize = sizeof(struct talitos_ctx),
> - .cra_module = THIS_MODULE,
> - },
> - .ivsize = AES_BLOCK_SIZE,
> - .maxauthsize = MD5_DIGEST_SIZE,
> - },
> - .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
> - DESC_HDR_SEL0_AESU |
> - DESC_HDR_MODE0_AESU_CBC |
> - DESC_HDR_SEL1_MDEUA |
> - DESC_HDR_MODE1_MDEU_INIT |
> - DESC_HDR_MODE1_MDEU_PAD |
> - DESC_HDR_MODE1_MDEU_MD5_HMAC,
> - },
> - { .type = CRYPTO_ALG_TYPE_AEAD,
> - .alg.aead = {
> - .base = {
> - .cra_name = "authenc(hmac(md5),cbc(aes))",
> - .cra_driver_name = "authenc-hmac-md5-"
> - "cbc-aes-talitos-hsna",
> - .cra_blocksize = AES_BLOCK_SIZE,
> - .cra_flags = CRYPTO_ALG_ASYNC |
> - CRYPTO_ALG_ALLOCATES_MEMORY |
> - CRYPTO_ALG_KERN_DRIVER_ONLY,
> - .cra_priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
> - .cra_ctxsize = sizeof(struct talitos_ctx),
> - .cra_module = THIS_MODULE,
> - },
> - .ivsize = AES_BLOCK_SIZE,
> - .maxauthsize = MD5_DIGEST_SIZE,
> - },
> - .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
> - DESC_HDR_SEL0_AESU |
> - DESC_HDR_MODE0_AESU_CBC |
> - DESC_HDR_SEL1_MDEUA |
> - DESC_HDR_MODE1_MDEU_INIT |
> - DESC_HDR_MODE1_MDEU_PAD |
> - DESC_HDR_MODE1_MDEU_MD5_HMAC,
> - },
> - { .type = CRYPTO_ALG_TYPE_AEAD,
> - .alg.aead = {
> - .base = {
> - .cra_name = "authenc(hmac(md5),cbc(des3_ede))",
> - .cra_driver_name = "authenc-hmac-md5-"
> - "cbc-3des-talitos",
> - .cra_blocksize = DES3_EDE_BLOCK_SIZE,
> - .cra_flags = CRYPTO_ALG_ASYNC |
> - CRYPTO_ALG_ALLOCATES_MEMORY |
> - CRYPTO_ALG_KERN_DRIVER_ONLY,
> - .cra_priority = TALITOS_CRA_PRIORITY,
> - .cra_ctxsize = sizeof(struct talitos_ctx),
> - .cra_module = THIS_MODULE,
> - },
> - .ivsize = DES3_EDE_BLOCK_SIZE,
> - .maxauthsize = MD5_DIGEST_SIZE,
> - .setkey = aead_des3_setkey,
> - },
> - .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
> - DESC_HDR_SEL0_DEU |
> - DESC_HDR_MODE0_DEU_CBC |
> - DESC_HDR_MODE0_DEU_3DES |
> - DESC_HDR_SEL1_MDEUA |
> - DESC_HDR_MODE1_MDEU_INIT |
> - DESC_HDR_MODE1_MDEU_PAD |
> - DESC_HDR_MODE1_MDEU_MD5_HMAC,
> - },
> - { .type = CRYPTO_ALG_TYPE_AEAD,
> - .alg.aead = {
> - .base = {
> - .cra_name = "authenc(hmac(md5),cbc(des3_ede))",
> - .cra_driver_name = "authenc-hmac-md5-"
> - "cbc-3des-talitos-hsna",
> - .cra_blocksize = DES3_EDE_BLOCK_SIZE,
> - .cra_flags = CRYPTO_ALG_ASYNC |
> - CRYPTO_ALG_ALLOCATES_MEMORY |
> - CRYPTO_ALG_KERN_DRIVER_ONLY,
> - .cra_priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
> - .cra_ctxsize = sizeof(struct talitos_ctx),
> - .cra_module = THIS_MODULE,
> - },
> - .ivsize = DES3_EDE_BLOCK_SIZE,
> - .maxauthsize = MD5_DIGEST_SIZE,
> - .setkey = aead_des3_setkey,
> - },
> - .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
> - DESC_HDR_SEL0_DEU |
> - DESC_HDR_MODE0_DEU_CBC |
> - DESC_HDR_MODE0_DEU_3DES |
> - DESC_HDR_SEL1_MDEUA |
> - DESC_HDR_MODE1_MDEU_INIT |
> - DESC_HDR_MODE1_MDEU_PAD |
> - DESC_HDR_MODE1_MDEU_MD5_HMAC,
> - },
> + /* AEAD algorithms. These use a single-pass ipsec_esp descriptor */
> +
> + /* sha1 auth */
> +
> + TALITOS_AEAD_ALG("authenc(hmac(sha1),cbc(aes))", aead_setkey,
> + AES_BLOCK_SIZE, SHA1_DIGEST_SIZE,
> + DESC_HDR_TYPE_IPSEC_ESP | DESC_HDR_SEL0_AESU |
> + DESC_HDR_MODE0_AESU_CBC | DESC_HDR_SEL1_MDEUA |
> + DESC_HDR_MODE1_MDEU_INIT |
> + DESC_HDR_MODE1_MDEU_PAD |
> + DESC_HDR_MODE1_MDEU_SHA1_HMAC),
> +
> + TALITOS_AEAD_ALG_HSNA(
> + "authenc(hmac(sha1),cbc(aes))", aead_setkey, AES_BLOCK_SIZE,
> + SHA1_DIGEST_SIZE,
> + DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | DESC_HDR_SEL0_AESU |
> + DESC_HDR_MODE0_AESU_CBC | DESC_HDR_SEL1_MDEUA |
> + DESC_HDR_MODE1_MDEU_INIT | DESC_HDR_MODE1_MDEU_PAD |
> + DESC_HDR_MODE1_MDEU_SHA1_HMAC),
> +
> + TALITOS_AEAD_ALG("authenc(hmac(sha1),cbc(des3_ede))", aead_des3_setkey,
> + DES3_EDE_BLOCK_SIZE, SHA1_DIGEST_SIZE,
> + DESC_HDR_TYPE_IPSEC_ESP | DESC_HDR_SEL0_DEU |
> + DESC_HDR_MODE0_DEU_CBC |
> + DESC_HDR_MODE0_DEU_3DES | DESC_HDR_SEL1_MDEUA |
> + DESC_HDR_MODE1_MDEU_INIT |
> + DESC_HDR_MODE1_MDEU_PAD |
> + DESC_HDR_MODE1_MDEU_SHA1_HMAC),
> +
> + TALITOS_AEAD_ALG_HSNA(
> + "authenc(hmac(sha1),cbc(des3_ede))", aead_des3_setkey,
> + DES3_EDE_BLOCK_SIZE, SHA1_DIGEST_SIZE,
> + DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | DESC_HDR_SEL0_DEU |
> + DESC_HDR_MODE0_DEU_CBC | DESC_HDR_MODE0_DEU_3DES |
> + DESC_HDR_SEL1_MDEUA | DESC_HDR_MODE1_MDEU_INIT |
> + DESC_HDR_MODE1_MDEU_PAD |
> + DESC_HDR_MODE1_MDEU_SHA1_HMAC),
> +
> + /* sha224 auth */
> +
> + TALITOS_AEAD_ALG("authenc(hmac(sha224),cbc(aes))", aead_setkey,
> + AES_BLOCK_SIZE, SHA224_DIGEST_SIZE,
> + DESC_HDR_TYPE_IPSEC_ESP | DESC_HDR_SEL0_AESU |
> + DESC_HDR_MODE0_AESU_CBC | DESC_HDR_SEL1_MDEUA |
> + DESC_HDR_MODE1_MDEU_INIT |
> + DESC_HDR_MODE1_MDEU_PAD |
> + DESC_HDR_MODE1_MDEU_SHA224_HMAC),
> +
> + TALITOS_AEAD_ALG_HSNA(
> + "authenc(hmac(sha224),cbc(aes))", aead_setkey, AES_BLOCK_SIZE,
> + SHA224_DIGEST_SIZE,
> + DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | DESC_HDR_SEL0_AESU |
> + DESC_HDR_MODE0_AESU_CBC | DESC_HDR_SEL1_MDEUA |
> + DESC_HDR_MODE1_MDEU_INIT | DESC_HDR_MODE1_MDEU_PAD |
> + DESC_HDR_MODE1_MDEU_SHA224_HMAC),
> +
> + TALITOS_AEAD_ALG(
> + "authenc(hmac(sha224),cbc(des3_ede))", aead_des3_setkey,
> + DES3_EDE_BLOCK_SIZE, SHA224_DIGEST_SIZE,
> + DESC_HDR_TYPE_IPSEC_ESP | DESC_HDR_SEL0_DEU |
> + DESC_HDR_MODE0_DEU_CBC | DESC_HDR_MODE0_DEU_3DES |
> + DESC_HDR_SEL1_MDEUA | DESC_HDR_MODE1_MDEU_INIT |
> + DESC_HDR_MODE1_MDEU_PAD |
> + DESC_HDR_MODE1_MDEU_SHA224_HMAC),
> +
> + TALITOS_AEAD_ALG_HSNA(
> + "authenc(hmac(sha224),cbc(des3_ede))", aead_des3_setkey,
> + DES3_EDE_BLOCK_SIZE, SHA224_DIGEST_SIZE,
> + DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | DESC_HDR_SEL0_DEU |
> + DESC_HDR_MODE0_DEU_CBC | DESC_HDR_MODE0_DEU_3DES |
> + DESC_HDR_SEL1_MDEUA | DESC_HDR_MODE1_MDEU_INIT |
> + DESC_HDR_MODE1_MDEU_PAD |
> + DESC_HDR_MODE1_MDEU_SHA224_HMAC),
> +
> + /* sha256 auth */
> +
> + TALITOS_AEAD_ALG("authenc(hmac(sha256),cbc(aes))", aead_setkey,
> + AES_BLOCK_SIZE, SHA256_DIGEST_SIZE,
> + DESC_HDR_TYPE_IPSEC_ESP | DESC_HDR_SEL0_AESU |
> + DESC_HDR_MODE0_AESU_CBC | DESC_HDR_SEL1_MDEUA |
> + DESC_HDR_MODE1_MDEU_INIT |
> + DESC_HDR_MODE1_MDEU_PAD |
> + DESC_HDR_MODE1_MDEU_SHA256_HMAC),
> +
> + TALITOS_AEAD_ALG_HSNA(
> + "authenc(hmac(sha256),cbc(aes))", aead_setkey, AES_BLOCK_SIZE,
> + SHA256_DIGEST_SIZE,
> + DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | DESC_HDR_SEL0_AESU |
> + DESC_HDR_MODE0_AESU_CBC | DESC_HDR_SEL1_MDEUA |
> + DESC_HDR_MODE1_MDEU_INIT | DESC_HDR_MODE1_MDEU_PAD |
> + DESC_HDR_MODE1_MDEU_SHA256_HMAC),
> +
> + TALITOS_AEAD_ALG(
> + "authenc(hmac(sha256),cbc(des3_ede))", aead_des3_setkey,
> + DES3_EDE_BLOCK_SIZE, SHA256_DIGEST_SIZE,
> + DESC_HDR_TYPE_IPSEC_ESP | DESC_HDR_SEL0_DEU |
> + DESC_HDR_MODE0_DEU_CBC | DESC_HDR_MODE0_DEU_3DES |
> + DESC_HDR_SEL1_MDEUA | DESC_HDR_MODE1_MDEU_INIT |
> + DESC_HDR_MODE1_MDEU_PAD |
> + DESC_HDR_MODE1_MDEU_SHA256_HMAC),
> +
> + TALITOS_AEAD_ALG_HSNA(
> + "authenc(hmac(sha256),cbc(des3_ede))", aead_des3_setkey,
> + DES3_EDE_BLOCK_SIZE, SHA256_DIGEST_SIZE,
> + DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | DESC_HDR_SEL0_DEU |
> + DESC_HDR_MODE0_DEU_CBC | DESC_HDR_MODE0_DEU_3DES |
> + DESC_HDR_SEL1_MDEUA | DESC_HDR_MODE1_MDEU_INIT |
> + DESC_HDR_MODE1_MDEU_PAD |
> + DESC_HDR_MODE1_MDEU_SHA256_HMAC),
> +
> + /* sha384 auth */
> +
> + TALITOS_AEAD_ALG("authenc(hmac(sha384),cbc(aes))", aead_setkey,
> + AES_BLOCK_SIZE, SHA384_DIGEST_SIZE,
> + DESC_HDR_TYPE_IPSEC_ESP | DESC_HDR_SEL0_AESU |
> + DESC_HDR_MODE0_AESU_CBC | DESC_HDR_SEL1_MDEUB |
> + DESC_HDR_MODE1_MDEU_INIT |
> + DESC_HDR_MODE1_MDEU_PAD |
> + DESC_HDR_MODE1_MDEUB_SHA384_HMAC),
> +
> + TALITOS_AEAD_ALG(
> + "authenc(hmac(sha384),cbc(des3_ede))", aead_des3_setkey,
> + DES3_EDE_BLOCK_SIZE, SHA384_DIGEST_SIZE,
> + DESC_HDR_TYPE_IPSEC_ESP | DESC_HDR_SEL0_DEU |
> + DESC_HDR_MODE0_DEU_CBC | DESC_HDR_MODE0_DEU_3DES |
> + DESC_HDR_SEL1_MDEUB | DESC_HDR_MODE1_MDEU_INIT |
> + DESC_HDR_MODE1_MDEU_PAD |
> + DESC_HDR_MODE1_MDEUB_SHA384_HMAC),
> +
> + /* sha512 auth */
> +
> + TALITOS_AEAD_ALG("authenc(hmac(sha512),cbc(aes))", aead_setkey,
> + AES_BLOCK_SIZE, SHA512_DIGEST_SIZE,
> + DESC_HDR_TYPE_IPSEC_ESP | DESC_HDR_SEL0_AESU |
> + DESC_HDR_MODE0_AESU_CBC | DESC_HDR_SEL1_MDEUB |
> + DESC_HDR_MODE1_MDEU_INIT |
> + DESC_HDR_MODE1_MDEU_PAD |
> + DESC_HDR_MODE1_MDEUB_SHA512_HMAC),
> +
> + TALITOS_AEAD_ALG(
> + "authenc(hmac(sha512),cbc(des3_ede))", aead_des3_setkey,
> + DES3_EDE_BLOCK_SIZE, SHA512_DIGEST_SIZE,
> + DESC_HDR_TYPE_IPSEC_ESP | DESC_HDR_SEL0_DEU |
> + DESC_HDR_MODE0_DEU_CBC | DESC_HDR_MODE0_DEU_3DES |
> + DESC_HDR_SEL1_MDEUB | DESC_HDR_MODE1_MDEU_INIT |
> + DESC_HDR_MODE1_MDEU_PAD |
> + DESC_HDR_MODE1_MDEUB_SHA512_HMAC),
> +
> + /* md5 auth */
> +
> + TALITOS_AEAD_ALG("authenc(hmac(md5),cbc(aes))", aead_setkey,
> + AES_BLOCK_SIZE, MD5_DIGEST_SIZE,
> + DESC_HDR_TYPE_IPSEC_ESP | DESC_HDR_SEL0_AESU |
> + DESC_HDR_MODE0_AESU_CBC | DESC_HDR_SEL1_MDEUA |
> + DESC_HDR_MODE1_MDEU_INIT |
> + DESC_HDR_MODE1_MDEU_PAD |
> + DESC_HDR_MODE1_MDEU_MD5_HMAC),
> +
> + TALITOS_AEAD_ALG_HSNA(
> + "authenc(hmac(md5),cbc(aes))", aead_setkey, AES_BLOCK_SIZE,
> + MD5_DIGEST_SIZE,
> + DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | DESC_HDR_SEL0_AESU |
> + DESC_HDR_MODE0_AESU_CBC | DESC_HDR_SEL1_MDEUA |
> + DESC_HDR_MODE1_MDEU_INIT | DESC_HDR_MODE1_MDEU_PAD |
> + DESC_HDR_MODE1_MDEU_MD5_HMAC),
> +
> + TALITOS_AEAD_ALG(
> + "authenc(hmac(md5),cbc(des3_ede))", aead_des3_setkey,
> + DES3_EDE_BLOCK_SIZE, MD5_DIGEST_SIZE,
> + DESC_HDR_TYPE_IPSEC_ESP | DESC_HDR_SEL0_DEU |
> + DESC_HDR_MODE0_DEU_CBC | DESC_HDR_MODE0_DEU_3DES |
> + DESC_HDR_SEL1_MDEUA | DESC_HDR_MODE1_MDEU_INIT |
> + DESC_HDR_MODE1_MDEU_PAD | DESC_HDR_MODE1_MDEU_MD5_HMAC),
> +
> + TALITOS_AEAD_ALG_HSNA(
> + "authenc(hmac(md5),cbc(des3_ede))", aead_des3_setkey,
> + DES3_EDE_BLOCK_SIZE, MD5_DIGEST_SIZE,
> + DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | DESC_HDR_SEL0_DEU |
> + DESC_HDR_MODE0_DEU_CBC | DESC_HDR_MODE0_DEU_3DES |
> + DESC_HDR_SEL1_MDEUA | DESC_HDR_MODE1_MDEU_INIT |
> + DESC_HDR_MODE1_MDEU_PAD | DESC_HDR_MODE1_MDEU_MD5_HMAC),
> };
>
> int talitos_register_aead(struct device *dev)
> @@ -955,11 +645,6 @@ int talitos_register_aead(struct device *dev)
> if (has_ftr_sec1(priv))
> alg->cra_alignmask = 3;
>
> - aead_alg->init = talitos_cra_init_aead;
> - aead_alg->exit = talitos_cra_exit_aead;
> - aead_alg->setkey = aead_alg->setkey ?: aead_setkey;
> - aead_alg->encrypt = aead_encrypt;
> - aead_alg->decrypt = aead_decrypt;
> if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
> !strncmp(alg->cra_name, "authenc(hmac(sha224)", 20)) {
> continue;
>
^ permalink raw reply
* Re: [PATCH 18/29] crypto: talitos - Split SEC1/SEC2 code into separate function variants
From: Christophe Leroy (CS GROUP) @ 2026-06-01 12:32 UTC (permalink / raw)
To: Paul Louvel, Herbert Xu, David S. Miller
Cc: Thomas Petazzoni, Herve Codina, linux-crypto, linux-kernel
In-Reply-To: <20260528-7-1-rc1_talitos_cleanup-v1-18-cb1ad6cdea49@bootlin.com>
Le 28/05/2026 à 11:08, Paul Louvel a écrit :
> Split the functions that have SEC1/SEC2-specific behavior into
> separate sec1_ and sec2_ function variants, removing the runtime
> is_sec1 checks from within each function body.
Regarding naming, I would prefer prefixing with talitos1_ and talitos2_
to stick with the already existing naming we already have today:
- talitos1_done_ch0
- talitos1_done_4ch
- talitos1_interrupt_4ch,
- talitos2_done_ch0_2,
- talitos2_done_ch1_3,
- talitos2_done_ch0,
- talitos2_done_4ch,
- talitos2_interrupt_4ch,
- talitos2_interrupt_ch0_2,
- talitos2_interrupt_ch1_3,
Christophe
>
> The callers still dispatch between the two variants using local
> is_sec1 variables and if/else checks.
>
> Signed-off-by: Paul Louvel <paul.louvel@bootlin.com>
> ---
> drivers/crypto/talitos/talitos.c | 524 +++++++++++++++++++++++++--------------
> drivers/crypto/talitos/talitos.h | 36 ++-
> 2 files changed, 357 insertions(+), 203 deletions(-)
>
> diff --git a/drivers/crypto/talitos/talitos.c b/drivers/crypto/talitos/talitos.c
> index f38a156a0459..b6793d97735e 100644
> --- a/drivers/crypto/talitos/talitos.c
> +++ b/drivers/crypto/talitos/talitos.c
> @@ -133,75 +133,124 @@ void unmap_single_talitos_ptr(struct device *dev,
> from_talitos_ptr_len(ptr, is_sec1), dir);
> }
>
> -static int reset_channel(struct device *dev, int ch)
> +static int sec1_reset_channel(struct device *dev, int ch)
> {
> struct talitos_private *priv = dev_get_drvdata(dev);
> unsigned int timeout = TALITOS_TIMEOUT;
> - bool is_sec1 = has_ftr_sec1(priv);
>
> - if (is_sec1) {
> - setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
> - TALITOS1_CCCR_LO_RESET);
> + setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS1_CCCR_LO_RESET);
>
> - while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR_LO) &
> - TALITOS1_CCCR_LO_RESET) && --timeout)
> - cpu_relax();
> - } else {
> - setbits32(priv->chan[ch].reg + TALITOS_CCCR,
> - TALITOS2_CCCR_RESET);
> + while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR_LO) &
> + TALITOS1_CCCR_LO_RESET) &&
> + --timeout)
> + cpu_relax();
>
> - while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
> - TALITOS2_CCCR_RESET) && --timeout)
> - cpu_relax();
> + if (timeout == 0) {
> + dev_err(dev, "failed to reset sec1 channel %d\n", ch);
> + return -EIO;
> }
>
> + setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
> + TALITOS_CCCR_LO_NE | TALITOS_CCCR_LO_CDIE |
> + TALITOS_CCCR_LO_CDWE);
> +
> + return 0;
> +}
> +
> +static int sec2_reset_channel(struct device *dev, int ch)
> +{
> + struct talitos_private *priv = dev_get_drvdata(dev);
> + unsigned int timeout = TALITOS_TIMEOUT;
> +
> + setbits32(priv->chan[ch].reg + TALITOS_CCCR, TALITOS2_CCCR_RESET);
> +
> + while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
> + TALITOS2_CCCR_RESET) &&
> + --timeout)
> + cpu_relax();
> +
> if (timeout == 0) {
> - dev_err(dev, "failed to reset channel %d\n", ch);
> + dev_err(dev, "failed to reset sec2 channel %d\n", ch);
> return -EIO;
> }
>
> - /* set 36-bit addressing, done writeback enable and done IRQ enable */
> - setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS_CCCR_LO_EAE |
> - TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE);
> - /* enable chaining descriptors */
> - if (is_sec1)
> - setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
> - TALITOS_CCCR_LO_NE);
> + setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
> + TALITOS_CCCR_LO_EAE | TALITOS_CCCR_LO_CDWE |
> + TALITOS_CCCR_LO_CDIE);
>
> - /* and ICCR writeback, if available */
> + /* ICCR writeback, if available */
> if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
> setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
> - TALITOS_CCCR_LO_IWSE);
> + TALITOS_CCCR_LO_IWSE);
>
> return 0;
> }
>
> -static int reset_device(struct device *dev)
> +static int sec1_reset_device(struct device *dev)
> {
> struct talitos_private *priv = dev_get_drvdata(dev);
> unsigned int timeout = TALITOS_TIMEOUT;
> - bool is_sec1 = has_ftr_sec1(priv);
> - u32 mcr = is_sec1 ? TALITOS1_MCR_SWR : TALITOS2_MCR_SWR;
>
> - setbits32(priv->reg + TALITOS_MCR, mcr);
> + setbits32(priv->reg + TALITOS_MCR, TALITOS1_MCR_SWR);
>
> - while ((in_be32(priv->reg + TALITOS_MCR) & mcr)
> - && --timeout)
> + while ((in_be32(priv->reg + TALITOS_MCR) & TALITOS1_MCR_SWR) &&
> + --timeout)
> cpu_relax();
>
> - if (priv->irq[1]) {
> - mcr = TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3;
> - setbits32(priv->reg + TALITOS_MCR, mcr);
> + if (timeout == 0) {
> + dev_err(dev, "failed to reset sec1 device\n");
> + return -EIO;
> }
>
> + return 0;
> +}
> +
> +static int sec2_reset_device(struct device *dev)
> +{
> + struct talitos_private *priv = dev_get_drvdata(dev);
> + unsigned int timeout = TALITOS_TIMEOUT;
> +
> + setbits32(priv->reg + TALITOS_MCR, TALITOS2_MCR_SWR);
> +
> + while ((in_be32(priv->reg + TALITOS_MCR) & TALITOS2_MCR_SWR) &&
> + --timeout)
> + cpu_relax();
> +
> + if (priv->irq[1])
> + setbits32(priv->reg + TALITOS_MCR,
> + TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3);
> +
> if (timeout == 0) {
> - dev_err(dev, "failed to reset device\n");
> + dev_err(dev, "failed to reset sec2 device\n");
> return -EIO;
> }
>
> return 0;
> }
>
> +static void sec1_configure_device(struct device *dev)
> +{
> + struct talitos_private *priv = dev_get_drvdata(dev);
> +
> + clrbits32(priv->reg + TALITOS_IMR, TALITOS1_IMR_INIT);
> + clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);
> + /* disable parity error check in DEU (erroneous? test vect.) */
> + setbits32(priv->reg_deu + TALITOS_EUICR, TALITOS1_DEUICR_KPE);
> +}
> +
> +static void sec2_configure_device(struct device *dev)
> +{
> + struct talitos_private *priv = dev_get_drvdata(dev);
> +
> + setbits32(priv->reg + TALITOS_IMR, TALITOS2_IMR_INIT);
> + setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);
> +
> + /* disable integrity check error interrupts (use writeback instead) */
> + if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
> + setbits32(priv->reg_mdeu + TALITOS_EUICR_LO,
> + TALITOS_MDEUICR_LO_ICE);
> +}
> +
> /*
> * Reset and initialize the device
> */
> @@ -217,80 +266,81 @@ static int init_device(struct device *dev)
> * are not fully cleared by writing the MCR:SWR bit,
> * set bit twice to completely reset
> */
> - err = reset_device(dev);
> + if (is_sec1)
> + err = sec1_reset_device(dev);
> + else
> + err = sec2_reset_device(dev);
> +
> if (err)
> return err;
>
> - err = reset_device(dev);
> + if (is_sec1)
> + err = sec1_reset_device(dev);
> + else
> + err = sec2_reset_device(dev);
> if (err)
> return err;
>
> /* reset channels */
> for (ch = 0; ch < priv->num_channels; ch++) {
> - err = reset_channel(dev, ch);
> + if (is_sec1)
> + err = sec1_reset_channel(dev, ch);
> + else
> + err = sec2_reset_channel(dev, ch);
> if (err)
> return err;
> }
>
> - /* enable channel done and error interrupts */
> - if (is_sec1) {
> - clrbits32(priv->reg + TALITOS_IMR, TALITOS1_IMR_INIT);
> - clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);
> - /* disable parity error check in DEU (erroneous? test vect.) */
> - setbits32(priv->reg_deu + TALITOS_EUICR, TALITOS1_DEUICR_KPE);
> - } else {
> - setbits32(priv->reg + TALITOS_IMR, TALITOS2_IMR_INIT);
> - setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);
> - }
> -
> - /* disable integrity check error interrupts (use writeback instead) */
> - if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
> - setbits32(priv->reg_mdeu + TALITOS_EUICR_LO,
> - TALITOS_MDEUICR_LO_ICE);
> + if (is_sec1)
> + sec1_configure_device(dev);
> + else
> + sec2_configure_device(dev);
>
> return 0;
> }
>
> -static void dma_map_request(struct device *dev, struct talitos_request *request,
> - struct talitos_desc *desc, bool is_sec1)
> +static void sec1_dma_map_request(struct device *dev,
> + struct talitos_request *request,
> + struct talitos_desc *desc)
> {
> struct talitos_edesc *edesc =
> container_of(desc, struct talitos_edesc, desc);
> dma_addr_t dma_desc, prev_dma_desc;
> struct talitos_edesc *prev_edesc = NULL;
>
> - if (is_sec1) {
> - while (edesc) {
> - edesc->desc.hdr1 = edesc->desc.hdr;
> + while (edesc) {
> + edesc->desc.hdr1 = edesc->desc.hdr;
>
> - dma_desc = dma_map_single(dev, &edesc->desc.hdr1,
> - TALITOS_DESC_SIZE,
> - DMA_BIDIRECTIONAL);
> + dma_desc = dma_map_single(dev, &edesc->desc.hdr1,
> + TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
>
> - if (!prev_edesc) {
> - request->dma_desc = dma_desc;
> - goto next;
> - }
> + if (!prev_edesc) {
> + request->dma_desc = dma_desc;
> + goto next;
> + }
>
> - /* Chain in any previous descriptors. */
> + /* Chain in any previous descriptors. */
>
> - prev_edesc->desc.next_desc = cpu_to_be32(dma_desc);
> + prev_edesc->desc.next_desc = cpu_to_be32(dma_desc);
>
> - dma_sync_single_for_device(dev, prev_dma_desc,
> - TALITOS_DESC_SIZE,
> - DMA_TO_DEVICE);
> + dma_sync_single_for_device(dev, prev_dma_desc,
> + TALITOS_DESC_SIZE, DMA_TO_DEVICE);
>
> next:
> - prev_edesc = edesc;
> - prev_dma_desc = dma_desc;
> - edesc = edesc->next_desc;
> - }
> - } else {
> - request->dma_desc = dma_map_single(dev, desc, TALITOS_DESC_SIZE,
> - DMA_BIDIRECTIONAL);
> + prev_edesc = edesc;
> + prev_dma_desc = dma_desc;
> + edesc = edesc->next_desc;
> }
> }
>
> +static void sec2_dma_map_request(struct device *dev,
> + struct talitos_request *request,
> + struct talitos_desc *desc)
> +{
> + request->dma_desc =
> + dma_map_single(dev, desc, TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
> +}
> +
> /**
> * talitos_submit - submits a descriptor to the device for processing
> * @dev: the SEC device to be used
> @@ -327,7 +377,10 @@ int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
> request = &priv->chan[ch].fifo[head];
>
> /* map descriptor and save caller data */
> - dma_map_request(dev, request, desc, is_sec1);
> + if (is_sec1)
> + sec1_dma_map_request(dev, request, desc);
> + else
> + sec2_dma_map_request(dev, request, desc);
> request->callback = callback;
> request->context = context;
>
> @@ -349,19 +402,12 @@ int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
> return -EINPROGRESS;
> }
>
> -static __be32 get_request_hdr(struct device *dev,
> - struct talitos_request *request, bool is_sec1)
> +static __be32 sec1_get_request_hdr(struct device *dev,
> + struct talitos_request *request)
> {
> struct talitos_edesc *edesc;
> dma_addr_t dma_desc;
>
> - if (!is_sec1) {
> - dma_sync_single_for_cpu(dev, request->dma_desc,
> - TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
> -
> - return request->desc->hdr;
> - }
> -
> edesc = container_of(request->desc, struct talitos_edesc, desc);
> dma_desc = request->dma_desc;
> while (edesc->next_desc) {
> @@ -375,27 +421,37 @@ static __be32 get_request_hdr(struct device *dev,
> return edesc->desc.hdr1;
> }
>
> -static void dma_unmap_request(struct device *dev,
> - struct talitos_request *request, bool is_sec1)
> +static __be32 sec2_get_request_hdr(struct device *dev,
> + struct talitos_request *request)
> +{
> + dma_sync_single_for_cpu(dev, request->dma_desc, TALITOS_DESC_SIZE,
> + DMA_BIDIRECTIONAL);
> +
> + return request->desc->hdr;
> +}
> +
> +static void sec1_dma_unmap_request(struct device *dev,
> + struct talitos_request *request)
> {
> struct talitos_edesc *edesc;
>
> - if (is_sec1) {
> - dma_unmap_single(dev, request->dma_desc, TALITOS_DESC_SIZE,
> - DMA_BIDIRECTIONAL);
> - edesc = container_of(request->desc, struct talitos_edesc, desc);
> - while (edesc->next_desc) {
> - dma_unmap_single(dev,
> - be32_to_cpu(edesc->desc.next_desc),
> - TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
> - edesc = edesc->next_desc;
> - }
> - } else {
> - dma_unmap_single(dev, request->dma_desc, TALITOS_DESC_SIZE,
> - DMA_BIDIRECTIONAL);
> + dma_unmap_single(dev, request->dma_desc, TALITOS_DESC_SIZE,
> + DMA_BIDIRECTIONAL);
> + edesc = container_of(request->desc, struct talitos_edesc, desc);
> + while (edesc->next_desc) {
> + dma_unmap_single(dev, be32_to_cpu(edesc->desc.next_desc),
> + TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
> + edesc = edesc->next_desc;
> }
> }
>
> +static void sec2_dma_unmap_request(struct device *dev,
> + struct talitos_request *request)
> +{
> + dma_unmap_single(dev, request->dma_desc, TALITOS_DESC_SIZE,
> + DMA_BIDIRECTIONAL);
> +}
> +
> /*
> * process what was done, notify callback of error if not
> */
> @@ -417,7 +473,10 @@ static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
>
> /* descriptors with their done bits set don't get the error */
> rmb();
> - hdr = get_request_hdr(dev, request, is_sec1);
> + if (is_sec1)
> + hdr = sec1_get_request_hdr(dev, request);
> + else
> + hdr = sec2_get_request_hdr(dev, request);
>
> if ((hdr & DESC_HDR_DONE) == DESC_HDR_DONE)
> status = 0;
> @@ -427,7 +486,10 @@ static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
> else
> status = error;
>
> - dma_unmap_request(dev, request, is_sec1);
> + if (is_sec1)
> + sec1_dma_unmap_request(dev, request);
> + else
> + sec2_dma_unmap_request(dev, request);
>
> /* copy entries so we can call callback outside lock */
> saved_req.desc = request->desc;
> @@ -516,21 +578,30 @@ DEF_TALITOS2_DONE(ch0, TALITOS2_ISR_CH_0_DONE)
> DEF_TALITOS2_DONE(ch0_2, TALITOS2_ISR_CH_0_2_DONE)
> DEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH_1_3_DONE)
>
> -static __be32 search_desc_hdr_in_request(struct talitos_request *request,
> - dma_addr_t cur_desc, bool is_sec1)
> +static __be32 sec1_search_desc_hdr_in_request(struct talitos_request *request,
> + dma_addr_t cur_desc)
> {
> struct talitos_edesc *edesc;
>
> - if (request->dma_desc == cur_desc) {
> +
> + if (request->dma_desc == cur_desc)
> return request->desc->hdr;
> - } else if (is_sec1) {
> - edesc = container_of(request->desc, struct talitos_edesc, desc);
> - while (edesc->next_desc) {
> - if (edesc->desc.next_desc == cpu_to_be32(cur_desc))
> - return edesc->next_desc->desc.hdr1;
> - edesc = edesc->next_desc;
> - }
> +
> + edesc = container_of(request->desc, struct talitos_edesc, desc);
> + while (edesc->next_desc) {
> + if (edesc->desc.next_desc == cpu_to_be32(cur_desc))
> + return edesc->next_desc->desc.hdr1;
> + edesc = edesc->next_desc;
> }
> +
> + return 0;
> +}
> +
> +static __be32 sec2_search_desc_hdr_in_request(struct talitos_request *request,
> + dma_addr_t cur_desc)
> +{
> + if (request->dma_desc == cur_desc)
> + return request->desc->hdr;
> return 0;
> }
>
> @@ -559,7 +630,10 @@ static __be32 current_desc_hdr(struct device *dev, int ch)
> do {
> request = &priv->chan[ch].fifo[iter];
>
> - hdr = search_desc_hdr_in_request(request, cur_desc, is_sec1);
> + if (is_sec1)
> + hdr = sec1_search_desc_hdr_in_request(request, cur_desc);
> + else
> + hdr = sec2_search_desc_hdr_in_request(request, cur_desc);
> if (hdr)
> break;
>
> @@ -647,79 +721,100 @@ static void report_eu_error(struct device *dev, int ch, __be32 desc_hdr)
> in_be32(priv->chan[ch].reg + TALITOS_DESCBUF_LO + 8*i));
> }
>
> -/*
> - * recover from error interrupts
> - */
> -static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
> +static int sec1_talitos_handle_error(struct device *dev, u32 isr, u32 isr_lo)
> +{
> + struct talitos_private *priv = dev_get_drvdata(dev);
> + int ch, error;
> + u32 v_lo;
> +
> + for (ch = 0; ch < priv->num_channels; ch++) {
> + if (!TALITOS1_CH_HAS_ERROR(isr, ch))
> + continue;
> +
> + v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO);
> +
> + error = -EINVAL;
> +
> + if (v_lo & TALITOS1_CCPSR_LO_TEA)
> + dev_err(dev, "transfer error acknowledge\n");
> + if (v_lo & TALITOS1_CCPSR_LO_PTRNC)
> + dev_err(dev, "pointer not complete error\n");
> + if (v_lo & TALITOS1_CCPSR_LO_PE)
> + dev_err(dev, "parity error\n");
> + if (v_lo & TALITOS1_CCPSR_LO_IDH)
> + dev_err(dev, "illegal descriptor header error\n");
> + if (v_lo & TALITOS1_CCPSR_LO_SA)
> + dev_err(dev, "static assignment error\n");
> + if (v_lo & TALITOS1_CCPSR_LO_EU)
> + report_eu_error(dev, ch, current_desc_hdr(dev, ch));
> +
> + flush_channel(dev, ch, error, 1);
> + priv->ops->reset_channel(dev, ch);
> + }
> +
> + if (isr_lo & TALITOS1_ISR_TEA_ERR)
> + dev_err(dev, "TEA error: ISR 0x%08x_%08x\n", isr, isr_lo);
> +
> + return (isr & ~TALITOS1_ISR_4CHERR) || isr_lo;
> +}
> +
> +static int sec2_talitos_handle_error(struct device *dev, u32 isr, u32 isr_lo)
> {
> struct talitos_private *priv = dev_get_drvdata(dev);
> unsigned int timeout = TALITOS_TIMEOUT;
> int ch, error, reset_dev = 0;
> u32 v_lo;
> - bool is_sec1 = has_ftr_sec1(priv);
> - int reset_ch = is_sec1 ? 1 : 0; /* only SEC2 supports continuation */
> + int reset_ch = 0;
>
> for (ch = 0; ch < priv->num_channels; ch++) {
> - /* skip channels without errors */
> - if (is_sec1) {
> - /* bits 29, 31, 17, 19 */
> - if (!(isr & (1 << (29 + (ch & 1) * 2 - (ch & 2) * 6))))
> - continue;
> - } else {
> - if (!(isr & (1 << (ch * 2 + 1))))
> - continue;
> - }
> + if (!TALITOS2_CH_HAS_ERROR(isr, ch))
> + continue;
>
> error = -EINVAL;
>
> v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO);
>
> - if (v_lo & TALITOS_CCPSR_LO_DOF) {
> + if (v_lo & TALITOS2_CCPSR_LO_DOF) {
> dev_err(dev, "double fetch fifo overflow error\n");
> error = -EAGAIN;
> reset_ch = 1;
> }
> - if (v_lo & TALITOS_CCPSR_LO_SOF) {
> + if (v_lo & TALITOS2_CCPSR_LO_SOF) {
> /* h/w dropped descriptor */
> dev_err(dev, "single fetch fifo overflow error\n");
> error = -EAGAIN;
> }
> - if (v_lo & TALITOS_CCPSR_LO_MDTE)
> + if (v_lo & TALITOS2_CCPSR_LO_MDTE)
> dev_err(dev, "master data transfer error\n");
> - if (v_lo & TALITOS_CCPSR_LO_SGDLZ)
> - dev_err(dev, is_sec1 ? "pointer not complete error\n"
> - : "s/g data length zero error\n");
> - if (v_lo & TALITOS_CCPSR_LO_FPZ)
> - dev_err(dev, is_sec1 ? "parity error\n"
> - : "fetch pointer zero error\n");
> - if (v_lo & TALITOS_CCPSR_LO_IDH)
> + if (v_lo & TALITOS2_CCPSR_LO_SGDLZ)
> + dev_err(dev, "s/g data length zero error\n");
> + if (v_lo & TALITOS2_CCPSR_LO_FPZ)
> + dev_err(dev, "fetch pointer zero error\n");
> + if (v_lo & TALITOS2_CCPSR_LO_IDH)
> dev_err(dev, "illegal descriptor header error\n");
> - if (v_lo & TALITOS_CCPSR_LO_IEU)
> - dev_err(dev, is_sec1 ? "static assignment error\n"
> - : "invalid exec unit error\n");
> - if (v_lo & TALITOS_CCPSR_LO_EU)
> + if (v_lo & TALITOS2_CCPSR_LO_IEU)
> + dev_err(dev, "invalid exec unit error\n");
> + if (v_lo & TALITOS2_CCPSR_LO_EU)
> report_eu_error(dev, ch, current_desc_hdr(dev, ch));
> - if (!is_sec1) {
> - if (v_lo & TALITOS_CCPSR_LO_GB)
> - dev_err(dev, "gather boundary error\n");
> - if (v_lo & TALITOS_CCPSR_LO_GRL)
> - dev_err(dev, "gather return/length error\n");
> - if (v_lo & TALITOS_CCPSR_LO_SB)
> - dev_err(dev, "scatter boundary error\n");
> - if (v_lo & TALITOS_CCPSR_LO_SRL)
> - dev_err(dev, "scatter return/length error\n");
> - }
> + if (v_lo & TALITOS2_CCPSR_LO_GB)
> + dev_err(dev, "gather boundary error\n");
> + if (v_lo & TALITOS2_CCPSR_LO_GRL)
> + dev_err(dev, "gather return/length error\n");
> + if (v_lo & TALITOS2_CCPSR_LO_SB)
> + dev_err(dev, "scatter boundary error\n");
> + if (v_lo & TALITOS2_CCPSR_LO_SRL)
> + dev_err(dev, "scatter return/length error\n");
>
> flush_channel(dev, ch, error, reset_ch);
>
> if (reset_ch) {
> - reset_channel(dev, ch);
> + priv->ops->reset_channel(dev, ch);
> } else {
> setbits32(priv->chan[ch].reg + TALITOS_CCCR,
> TALITOS2_CCCR_CONT);
> setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 0);
> while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
> - TALITOS2_CCCR_CONT) && --timeout)
> + TALITOS2_CCCR_CONT) && --timeout)
> cpu_relax();
> if (timeout == 0) {
> dev_err(dev, "failed to restart channel %d\n",
> @@ -728,14 +823,29 @@ static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
> }
> }
> }
> - if (reset_dev || (is_sec1 && isr & ~TALITOS1_ISR_4CHERR) ||
> - (!is_sec1 && isr & ~TALITOS2_ISR_4CHERR) || isr_lo) {
> - if (is_sec1 && (isr_lo & TALITOS1_ISR_TEA_ERR))
> - dev_err(dev, "TEA error: ISR 0x%08x_%08x\n",
> - isr, isr_lo);
> - else
> - dev_err(dev, "done overflow, internal time out, or "
> - "rngu error: ISR 0x%08x_%08x\n", isr, isr_lo);
> +
> + return reset_dev || (isr & ~TALITOS2_ISR_4CHERR) || isr_lo;
> +}
> +
> +/*
> + * recover from error interrupts
> + */
> +static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
> +{
> + struct talitos_private *priv = dev_get_drvdata(dev);
> + bool is_sec1 = has_ftr_sec1(priv);
> + int ch, reset_dev;
> +
> + if (is_sec1)
> + reset_dev = sec1_talitos_handle_error(dev, isr, isr_lo);
> + else
> + reset_dev = sec2_talitos_handle_error(dev, isr, isr_lo);
> +
> + if (reset_dev) {
> + dev_err(dev,
> + "done overflow, internal time out, or "
> + "rngu error: ISR 0x%08x_%08x\n",
> + isr, isr_lo);
>
> /* purge request queues */
> for (ch = 0; ch < priv->num_channels; ch++)
> @@ -1181,25 +1291,41 @@ int talitos_register_common(struct device *dev,
> return 0;
> }
>
> -static int talitos_probe_irq(struct platform_device *ofdev)
> +static int sec1_talitos_probe_irq(struct platform_device *ofdev)
> {
> struct device *dev = &ofdev->dev;
> struct device_node *np = ofdev->dev.of_node;
> struct talitos_private *priv = dev_get_drvdata(dev);
> int err;
> - bool is_sec1 = has_ftr_sec1(priv);
>
> priv->irq[0] = irq_of_parse_and_map(np, 0);
> if (!priv->irq[0]) {
> dev_err(dev, "failed to map irq\n");
> return -EINVAL;
> }
> - if (is_sec1) {
> - err = request_irq(priv->irq[0], talitos1_interrupt_4ch, 0,
> - dev_driver_string(dev), dev);
> - goto primary_out;
> + err = request_irq(priv->irq[0], talitos1_interrupt_4ch, 0,
> + dev_driver_string(dev), dev);
> + if (err) {
> + dev_err(dev, "failed to request primary irq\n");
> + irq_dispose_mapping(priv->irq[0]);
> + priv->irq[0] = 0;
> }
>
> + return err;
> +}
> +
> +static int sec2_talitos_probe_irq(struct platform_device *ofdev)
> +{
> + struct device *dev = &ofdev->dev;
> + struct device_node *np = ofdev->dev.of_node;
> + struct talitos_private *priv = dev_get_drvdata(dev);
> + int err;
> +
> + priv->irq[0] = irq_of_parse_and_map(np, 0);
> + if (!priv->irq[0]) {
> + dev_err(dev, "failed to map irq\n");
> + return -EINVAL;
> + }
> priv->irq[1] = irq_of_parse_and_map(np, 1);
>
> /* get the primary irq line */
> @@ -1235,6 +1361,36 @@ static int talitos_probe_irq(struct platform_device *ofdev)
> return err;
> }
>
> +static void sec1_init_task(struct device *dev)
> +{
> + struct talitos_private *priv = dev_get_drvdata(dev);
> +
> + if (priv->num_channels == 1)
> + tasklet_init(&priv->done_task[0], talitos1_done_ch0,
> + (unsigned long)dev);
> + else
> + tasklet_init(&priv->done_task[0], talitos1_done_4ch,
> + (unsigned long)dev);
> +}
> +
> +static void sec2_init_task(struct device *dev)
> +{
> + struct talitos_private *priv = dev_get_drvdata(dev);
> +
> + if (priv->irq[1]) {
> + tasklet_init(&priv->done_task[0], talitos2_done_ch0_2,
> + (unsigned long)dev);
> + tasklet_init(&priv->done_task[1], talitos2_done_ch1_3,
> + (unsigned long)dev);
> + } else if (priv->num_channels == 1) {
> + tasklet_init(&priv->done_task[0], talitos2_done_ch0,
> + (unsigned long)dev);
> + } else {
> + tasklet_init(&priv->done_task[0], talitos2_done_4ch,
> + (unsigned long)dev);
> + }
> +}
> +
> static int talitos_probe(struct platform_device *ofdev)
> {
> struct device *dev = &ofdev->dev;
> @@ -1317,31 +1473,17 @@ static int talitos_probe(struct platform_device *ofdev)
> stride = TALITOS2_CH_STRIDE;
> }
>
> - err = talitos_probe_irq(ofdev);
> + if (has_ftr_sec1(priv))
> + err = sec1_talitos_probe_irq(ofdev);
> + else
> + err = sec2_talitos_probe_irq(ofdev);
> if (err)
> goto err_out;
>
> - if (has_ftr_sec1(priv)) {
> - if (priv->num_channels == 1)
> - tasklet_init(&priv->done_task[0], talitos1_done_ch0,
> - (unsigned long)dev);
> - else
> - tasklet_init(&priv->done_task[0], talitos1_done_4ch,
> - (unsigned long)dev);
> - } else {
> - if (priv->irq[1]) {
> - tasklet_init(&priv->done_task[0], talitos2_done_ch0_2,
> - (unsigned long)dev);
> - tasklet_init(&priv->done_task[1], talitos2_done_ch1_3,
> - (unsigned long)dev);
> - } else if (priv->num_channels == 1) {
> - tasklet_init(&priv->done_task[0], talitos2_done_ch0,
> - (unsigned long)dev);
> - } else {
> - tasklet_init(&priv->done_task[0], talitos2_done_4ch,
> - (unsigned long)dev);
> - }
> - }
> + if (has_ftr_sec1(priv))
> + sec1_init_task(dev);
> + else
> + sec2_init_task(dev);
>
> priv->fifo_len = roundup_pow_of_two(priv->chfifo_len);
>
> diff --git a/drivers/crypto/talitos/talitos.h b/drivers/crypto/talitos/talitos.h
> index 6cf3628c52c2..904fdc9dec80 100644
> --- a/drivers/crypto/talitos/talitos.h
> +++ b/drivers/crypto/talitos/talitos.h
> @@ -301,20 +301,32 @@ static inline bool has_ftr_sec1(struct talitos_private *priv)
> #define TALITOS1_CCCR_LO_RESET 0x1 /* channel reset on SEC1 */
>
> /* CCPSR: channel pointer status register */
> +
> +/* bits 29, 31, 17, 19 */
> +#define TALITOS1_CH_HAS_ERROR(isr, ch) \
> + ((isr) & (1 << (29 + ((ch) & 1) * 2 - ((ch) & 2) * 6)))
> +#define TALITOS2_CH_HAS_ERROR(isr, ch) ((isr) & (1 << ((ch) * 2 + 1)))
> +
> #define TALITOS_CCPSR 0x10
> #define TALITOS_CCPSR_LO 0x14
> -#define TALITOS_CCPSR_LO_DOF 0x8000 /* double FF write oflow error */
> -#define TALITOS_CCPSR_LO_SOF 0x4000 /* single FF write oflow error */
> -#define TALITOS_CCPSR_LO_MDTE 0x2000 /* master data transfer error */
> -#define TALITOS_CCPSR_LO_SGDLZ 0x1000 /* s/g data len zero error */
> -#define TALITOS_CCPSR_LO_FPZ 0x0800 /* fetch ptr zero error */
> -#define TALITOS_CCPSR_LO_IDH 0x0400 /* illegal desc hdr error */
> -#define TALITOS_CCPSR_LO_IEU 0x0200 /* invalid EU error */
> -#define TALITOS_CCPSR_LO_EU 0x0100 /* EU error detected */
> -#define TALITOS_CCPSR_LO_GB 0x0080 /* gather boundary error */
> -#define TALITOS_CCPSR_LO_GRL 0x0040 /* gather return/length error */
> -#define TALITOS_CCPSR_LO_SB 0x0020 /* scatter boundary error */
> -#define TALITOS_CCPSR_LO_SRL 0x0010 /* scatter return/length error */
> +#define TALITOS1_CCPSR_LO_TEA 0x2000 /* transfer error acknowledge */
> +#define TALITOS1_CCPSR_LO_PTRNC 0x1000 /* pointer not complete error */
> +#define TALITOS1_CCPSR_LO_PE 0x0800 /* parity error */
> +#define TALITOS1_CCPSR_LO_IDH 0x0400 /* illegal desc hdr error */
> +#define TALITOS1_CCPSR_LO_SA 0x0200 /* static assignment error */
> +#define TALITOS1_CCPSR_LO_EU 0x0100 /* EU error detected */
> +#define TALITOS2_CCPSR_LO_DOF 0x8000 /* double FF write oflow error */
> +#define TALITOS2_CCPSR_LO_SOF 0x4000 /* single FF write oflow error */
> +#define TALITOS2_CCPSR_LO_MDTE 0x2000 /* master data transfer error */
> +#define TALITOS2_CCPSR_LO_SGDLZ 0x1000 /* s/g data len zero error */
> +#define TALITOS2_CCPSR_LO_FPZ 0x0800 /* fetch ptr zero error */
> +#define TALITOS2_CCPSR_LO_IDH 0x0400 /* illegal desc hdr error */
> +#define TALITOS2_CCPSR_LO_IEU 0x0200 /* invalid EU error */
> +#define TALITOS2_CCPSR_LO_EU 0x0100 /* EU error detected */
> +#define TALITOS2_CCPSR_LO_GB 0x0080 /* gather boundary error */
> +#define TALITOS2_CCPSR_LO_GRL 0x0040 /* gather return/length error */
> +#define TALITOS2_CCPSR_LO_SB 0x0020 /* scatter boundary error */
> +#define TALITOS2_CCPSR_LO_SRL 0x0010 /* scatter return/length error */
>
> /* channel fetch fifo register */
> #define TALITOS_FF 0x48
>
^ permalink raw reply
* [PATCH v2] hwrng: core - Do not read data during PM sleep transition
From: Thomas Richard (TI) @ 2026-06-01 13:19 UTC (permalink / raw)
To: Olivia Mackall, Herbert Xu
Cc: Thomas Petazzoni, linux-crypto, linux-kernel, gregory.clement,
richard.genoud, u-kumar1, a-kumar2, Thomas Richard (TI)
The hwrng_fillfn() kernel thread accesses the RNG device directly. During
suspend and resume sequences, hwrng_fillfn() may attempt to access the RNG
device while it is suspended. To address this, the hwrng_fillfn() kernel
thread checks if a PM sleep transition is in progress before to access the
RNG device.
Issue was found while doing suspend-to-ram on J721S2 EVM board with
omap-rng driver.
echo mem > /sys/power/state
[ 27.922259] PM: suspend entry (deep)
[ 27.927191] Filesystems sync: 0.000 seconds
[ 27.933858] Freezing user space processes
[ 27.939119] Freezing user space processes completed (elapsed 0.001 seconds)
[ 27.946090] OOM killer disabled.
[ 27.949315] Freezing remaining freezable tasks
[ 27.954887] Freezing remaining freezable tasks completed (elapsed 0.001 seconds)
[ 27.963337] GFP mask restricted
[ 27.967069] omap_rng 4e10000.rng: PM: calling platform_pm_suspend @ 195, parent: 4e00000.crypto
[ 27.967072] mmcblk mmc1:9fb0: PM: calling mmc_bus_suspend @ 122, parent: mmc1
[ 27.968636] mmcblk mmc1:9fb0: PM: mmc_bus_suspend returned 0 after 1546 usecs
[ 27.975778] omap_rng 4e10000.rng: PM: platform_pm_suspend returned 0 after 3 usecs
...
[ 33.510667] ti-sci 44083000.system-controller: PM: ti_sci_suspend_noirq returned 0 after 0 usecs
[ 33.510671] SError Interrupt on CPU0, code 0x00000000bf000000 -- SError
[ 33.510681] CPU: 0 UID: 0 PID: 132 Comm: hwrng Tainted: G M W 7.0.0-12695-g8923b7a6e11d #19 PREEMPT
[ 33.510690] Tainted: [M]=MACHINE_CHECK, [W]=WARN
[ 33.510693] Hardware name: Texas Instruments J721S2 EVM (DT)
[ 33.510697] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[ 33.510701] pc : omap_rng_do_read+0x3c/0xe0
[ 33.510709] lr : omap_rng_do_read+0x58/0xe0
[ 33.510712] sp : ffff80008942be00
[ 33.510713] x29: ffff80008942be00 x28: 0000000000000000 x27: 0000000000000000
[ 33.510719] x26: 0000000000000010 x25: 0000000000000010 x24: ffff0008065644e8
[ 33.510724] x23: ffff8000878b3370 x22: ffff00080148b2c0 x21: 0000000000000000
[ 33.510728] x20: ffff000806564480 x19: 0000000000000064 x18: 0000000000000000
[ 33.510732] x17: 6573752031207265 x16: 7466612030206465 x15: 6e72757465722071
[ 33.510737] x14: ffff0008062c8080 x13: 000031702bc0da42 x12: 0000000000000001
[ 33.510741] x11: 00000000000000c0 x10: 0000000000000b30 x9 : ffff80008942bc80
[ 33.510745] x8 : ffff0008062c8b90 x7 : ffff000b7dfa34c0 x6 : 0000000805ca16c1
[ 33.510749] x5 : 0000000000000000 x4 : ffff800080e17bfc x3 : ffff800087389c68
[ 33.510753] x2 : 0000000000000000 x1 : 0000000000000010 x0 : 000000000000a7c6
[ 33.510759] Kernel panic - not syncing: Asynchronous SError Interrupt
[ 33.510762] CPU: 0 UID: 0 PID: 132 Comm: hwrng Tainted: G M W 7.0.0-12695-g8923b7a6e11d #19 PREEMPT
[ 33.510767] Tainted: [M]=MACHINE_CHECK, [W]=WARN
[ 33.510768] Hardware name: Texas Instruments J721S2 EVM (DT)
[ 33.510770] Call trace:
[ 33.510772] show_stack+0x18/0x24 (C)
[ 33.510780] dump_stack_lvl+0x34/0x8c
[ 33.510788] dump_stack+0x18/0x24
[ 33.510792] vpanic+0x47c/0x4dc
[ 33.510799] do_panic_on_target_cpu+0x0/0x1c
[ 33.510803] add_taint+0x0/0xbc
[ 33.510807] arm64_serror_panic+0x70/0x80
[ 33.510812] do_serror+0x3c/0x70
[ 33.510815] el1h_64_error_handler+0x34/0x50
[ 33.510823] el1h_64_error+0x6c/0x70
[ 33.510827] omap_rng_do_read+0x3c/0xe0 (P)
[ 33.510831] hwrng_fillfn+0x98/0x330
[ 33.510834] kthread+0x130/0x13c
[ 33.510845] ret_from_fork+0x10/0x20
[ 33.510850] SMP: stopping secondary CPUs
[ 33.519442] Kernel Offset: disabled
[ 33.519444] CPU features: 0x04000000,800a0008,00040001,0400421b
[ 33.519448] Memory Limit: none
[ 33.732904] ---[ end Kernel panic - not syncing: Asynchronous SError Interrupt ]---
Signed-off-by: Thomas Richard (TI) <thomas.richard@bootlin.com>
---
This patch is related to the patch [1]. But it fixes the issue in a very
different way. Patch [1] set the hwrng_fillfn() kernel thread freezable,
but this solution was not acceptable as it could introduce an important
delay in the suspend sequence (up to 10s to freeze the freezable kernel
threads).
In this second iteration, I fixed a potential uninitialized variable use.
[1] https://lore.kernel.org/all/20260427-hw-random-set-hwrng-fillfn-kthread-freezable-v1-1-9bbe4f88b43a@bootlin.com/
---
Changes in v2:
- Initialize rc variable.
- Link to v1: https://lore.kernel.org/r/20260513-hw-random-fix-hwrng-fillfn-crash-suspend-resume-v1-1-b12551c1c7dd@bootlin.com
---
drivers/char/hw_random/core.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index aba92d777f72..7a4dddbd5b51 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -25,6 +25,7 @@
#include <linux/sched/signal.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/suspend.h>
#include <linux/uaccess.h>
#include <linux/workqueue.h>
@@ -516,7 +517,7 @@ ATTRIBUTE_GROUPS(rng_dev);
static int hwrng_fillfn(void *unused)
{
size_t entropy, entropy_credit = 0; /* in 1/1024 of a bit */
- long rc;
+ long rc = 0;
while (!kthread_should_stop()) {
unsigned short quality;
@@ -538,8 +539,9 @@ static int hwrng_fillfn(void *unused)
}
mutex_lock(&reading_mutex);
- rc = rng_get_data(rng, rng_fillbuf,
- rng_buffer_size(), 1);
+ if (!pm_sleep_transition_in_progress())
+ rc = rng_get_data(rng, rng_fillbuf,
+ rng_buffer_size(), 1);
if (current_quality != rng->quality)
rng->quality = current_quality; /* obsolete */
quality = rng->quality;
---
base-commit: f615e82f0b35c473499583a1432ade66060a02b2
change-id: 20260513-hw-random-fix-hwrng-fillfn-crash-suspend-resume-29fdb0638f59
Best regards,
--
Thomas Richard (TI) <thomas.richard@bootlin.com>
^ permalink raw reply related
* Re: [PATCH v2] crypto: sun4i-ss - clamp PRNG seed length to prevent heap overflow
From: Corentin Labbe @ 2026-06-01 14:57 UTC (permalink / raw)
To: Eric Biggers
Cc: Tianchu Chen, herbert, davem, wens, jernej.skrabec, samuel,
linux-crypto, linux-arm-kernel, linux-sunxi, linux-kernel
In-Reply-To: <20260529173341.GA566433@google.com>
Le Fri, May 29, 2026 at 05:33:41PM +0000, Eric Biggers a écrit :
> On Fri, May 29, 2026 at 07:10:06PM +0200, Corentin Labbe wrote:
> > Le Fri, May 29, 2026 at 09:10:57AM -0700, Eric Biggers a écrit :
> > > On Fri, May 29, 2026 at 08:08:01AM +0000, Tianchu Chen wrote:
> > > > From: Tianchu Chen <flynnnchen@tencent.com>
> > > >
> > > > sun4i_ss_prng_seed() copies the user-supplied seed into ss->seed
> > > > using the user-provided length with no bounds check. The crypto core
> > > > does not enforce slen <= seedsize before calling into the driver, so a
> > > > userspace caller via AF_ALG setsockopt(ALG_SET_KEY) can pass up to
> > > > sysctl_optmem_max bytes, overflowing the fixed-size buffer and
> > > > corrupting adjacent heap memory.
> > > >
> > > > Clamp the copy length to the buffer size, matching the approach used by
> > > > loongson-rng for oversized seeds.
> > > >
> > > > Discovered by Atuin - Automated Vulnerability Discovery Engine.
> > > >
> > > > Fixes: 6298e948215f ("crypto: sunxi-ss - Add Allwinner Security System crypto accelerator")
> > > > Cc: stable@vger.kernel.org
> > > > Signed-off-by: Tianchu Chen <flynnnchen@tencent.com>
> > > > ---
> > > > v2: Silently clamp oversized seeds with min_t instead of returning
> > > > -EINVAL (Herbert Xu).
> > >
> > > sun4i-ss-prng.c is useless, is still broken, and should just be deleted.
> >
> > Hello
> >
> > useless ? clearly no, it helped a lot on devices where it is.
>
> The only way this code is reachable is via "rng" algorithm type in
> AF_ALG, which is almost never used. Everyone just uses the regular
> Linux RNG (/dev/random etc) instead, as they should.
>
> In fact, anyone were to accidentally use this it would be a security
> vulnerability, seeing as sun4i_ss_prng_generate() doesn't actually fill
> in all the bytes that were requested. It also doesn't wait for the FIFO
> to be ready when reading data from it.
>
> Is it possible that there's a misunderstanding here and you think this
> provides entropy to the regular Linux RNG? It doesn't. hwrng does
> that, crypto_rng does not.
>
I believe to have used rngd for that. ( or something like that)
Anyway, I understand why want to remove it.
^ permalink raw reply
* Re: [PATCH] crypto: sun4i-ss - Remove insecure and unused rng_alg
From: Corentin Labbe @ 2026-06-01 15:08 UTC (permalink / raw)
To: Eric Biggers
Cc: linux-crypto, Herbert Xu, linux-sunxi, linux-arm-kernel,
linux-kernel, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
stable
In-Reply-To: <20260529193648.18172-1-ebiggers@kernel.org>
Le Fri, May 29, 2026 at 12:36:48PM -0700, Eric Biggers a écrit :
> Remove sun4i_ss_rng, as it is insecure and unused:
>
> - It has multiple vulnerabilities. sun4i_ss_prng_seed() is missing
> locking and has a buffer overflow. sun4i_ss_prng_generate() fails to
> fill the entire buffer with cryptographic random bytes, because it
> rounds the destination length down and also doesn't actually wait for
> the hardware to be ready before pulling bytes from it.
>
> - No user of this code is known. It's usable only theoretically via the
> "rng" algorithm type of AF_ALG. But userspace actually just uses the
> actual Linux RNG (/dev/random etc) instead. And rng_algs don't
> contribute entropy to the actual Linux RNG either. (This may have
> been confused with hwrng, which does contribute entropy.)
>
> Fixes: b8ae5c7387ad ("crypto: sun4i-ss - support the Security System PRNG")
> Cc: stable@vger.kernel.org
> Cc: Corentin Labbe <clabbe.montjoie@gmail.com>
> Signed-off-by: Eric Biggers <ebiggers@kernel.org>
> ---
Acked-by: Corentin LABBE <clabbe.montjoie@gmail.com>
^ permalink raw reply
* Re: [PATCH v2] crypto: sun4i-ss - clamp PRNG seed length to prevent heap overflow
From: Eric Biggers @ 2026-06-01 15:47 UTC (permalink / raw)
To: Corentin Labbe
Cc: Tianchu Chen, herbert, davem, wens, jernej.skrabec, samuel,
linux-crypto, linux-arm-kernel, linux-sunxi, linux-kernel
In-Reply-To: <ah2d0RyZcVp614_k@Red>
On Mon, Jun 01, 2026 at 04:57:21PM +0200, Corentin Labbe wrote:
> Le Fri, May 29, 2026 at 05:33:41PM +0000, Eric Biggers a écrit :
> > On Fri, May 29, 2026 at 07:10:06PM +0200, Corentin Labbe wrote:
> > > Le Fri, May 29, 2026 at 09:10:57AM -0700, Eric Biggers a écrit :
> > > > On Fri, May 29, 2026 at 08:08:01AM +0000, Tianchu Chen wrote:
> > > > > From: Tianchu Chen <flynnnchen@tencent.com>
> > > > >
> > > > > sun4i_ss_prng_seed() copies the user-supplied seed into ss->seed
> > > > > using the user-provided length with no bounds check. The crypto core
> > > > > does not enforce slen <= seedsize before calling into the driver, so a
> > > > > userspace caller via AF_ALG setsockopt(ALG_SET_KEY) can pass up to
> > > > > sysctl_optmem_max bytes, overflowing the fixed-size buffer and
> > > > > corrupting adjacent heap memory.
> > > > >
> > > > > Clamp the copy length to the buffer size, matching the approach used by
> > > > > loongson-rng for oversized seeds.
> > > > >
> > > > > Discovered by Atuin - Automated Vulnerability Discovery Engine.
> > > > >
> > > > > Fixes: 6298e948215f ("crypto: sunxi-ss - Add Allwinner Security System crypto accelerator")
> > > > > Cc: stable@vger.kernel.org
> > > > > Signed-off-by: Tianchu Chen <flynnnchen@tencent.com>
> > > > > ---
> > > > > v2: Silently clamp oversized seeds with min_t instead of returning
> > > > > -EINVAL (Herbert Xu).
> > > >
> > > > sun4i-ss-prng.c is useless, is still broken, and should just be deleted.
> > >
> > > Hello
> > >
> > > useless ? clearly no, it helped a lot on devices where it is.
> >
> > The only way this code is reachable is via "rng" algorithm type in
> > AF_ALG, which is almost never used. Everyone just uses the regular
> > Linux RNG (/dev/random etc) instead, as they should.
> >
> > In fact, anyone were to accidentally use this it would be a security
> > vulnerability, seeing as sun4i_ss_prng_generate() doesn't actually fill
> > in all the bytes that were requested. It also doesn't wait for the FIFO
> > to be ready when reading data from it.
> >
> > Is it possible that there's a misunderstanding here and you think this
> > provides entropy to the regular Linux RNG? It doesn't. hwrng does
> > that, crypto_rng does not.
> >
>
> I believe to have used rngd for that. ( or something like that)
>
> Anyway, I understand why want to remove it.
rngd doesn't use AF_ALG. So no, it couldn't have used this driver.
- Eric
^ permalink raw reply
* Re: [PATCH] crypto: sun4i-ss - Remove insecure and unused rng_alg
From: Eric Biggers @ 2026-06-01 15:54 UTC (permalink / raw)
To: Tianchu Chen
Cc: clabbe.montjoie, herbert, jernej.skrabec, linux-arm-kernel,
linux-crypto, linux-kernel, linux-sunxi, samuel, stable, wens
In-Reply-To: <d52449abfd8e1e46c8bfe9ebdc00d931fc0e4147@linux.dev>
On Mon, Jun 01, 2026 at 09:19:23AM +0000, Tianchu Chen wrote:
> From: Tianchu Chen <flynnnchen@tencent.com>
> In-Reply-To: <20260529193648.18172-1-ebiggers@kernel.org>
> References: <20260529193648.18172-1-ebiggers@kernel.org>
>
> On Fri, May 29, 2026 at 12:36:48PM -0700, Eric Biggers wrote:
> > Remove sun4i_ss_rng, as it is insecure and unused:
> >
> > - It has multiple vulnerabilities. sun4i_ss_prng_seed() is missing
> > locking and has a buffer overflow.
>
> Thanks for cleaning this up.
>
> For the record, the sun4i_ss_prng_seed() buffer overflow you mention here
> is the same issue we reported earlier with a targeted fix:
> https://lore.kernel.org/linux-crypto/20260529194152.GA3628@quark/
>
> It is an unauthenticated, unbounded memcpy() into the 24-byte ss->seed[]
> buffer, reachable from any user via AF_ALG ALG_SET_KEY with no privileges
> on affected Allwinner sun4i hardware.
>
> Please note that this should be treated as a security fix. For the earlier
> stable releases, keeping the rng_alg but adding a proper bounds check in
> sun4i_ss_prng_seed() might still be a preferable option to consider.
>
> Given the above, would you mind adding the following trailers to the commit
> message? Besides crediting the discovery and report, they would also make
> this security issue easier to track and reference across the stable trees:
>
> Discovered by Atuin - Automated Vulnerability Discovery Engine
> Reported-by: Tianchu Chen <flynnnchen@tencent.com>
Yes I'll add those, sorry for forgetting them.
I do think we should proceed with removal, seeing as this driver is
unused, and I found three additional vulnerabilities in it. So four
security fixes would be needed. But then we'd be removing the driver
anyway due to it being pointless, so it would just be busy work.
- Eric
^ permalink raw reply
* [PATCH v2] crypto: sun4i-ss - Remove insecure and unused rng_alg
From: Eric Biggers @ 2026-06-01 16:07 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-sunxi, linux-arm-kernel, linux-kernel, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Corentin Labbe, Eric Biggers,
stable, Tianchu Chen
Remove sun4i_ss_rng, as it is insecure and unused:
- It has multiple vulnerabilities. sun4i_ss_prng_seed() is missing
locking and has a buffer overflow. sun4i_ss_prng_generate() fails to
fill the entire buffer with cryptographic random bytes, because it
rounds the destination length down and also doesn't actually wait for
the hardware to be ready before pulling bytes from it.
- No user of this code is known. It's usable only theoretically via the
"rng" algorithm type of AF_ALG. But userspace actually just uses the
actual Linux RNG (/dev/random etc) instead. And rng_algs don't
contribute entropy to the actual Linux RNG either. (This may have
been confused with hwrng, which does contribute entropy.)
The sun4i_ss_prng_seed() buffer overflow was reported by Tianchu Chen
and discovered by Atuin - Automated Vulnerability Discovery Engine
There's no point in fixing all these vulnerabilities individually when
this is unused code, so let's just remove it.
Fixes: b8ae5c7387ad ("crypto: sun4i-ss - support the Security System PRNG")
Cc: stable@vger.kernel.org
Reported-by: Tianchu Chen <flynnnchen@tencent.com>
Closes: https://lore.kernel.org/r/af749a8447bd7f0e9dd26ca6c87e9c6afecb09d9@linux.dev/
Acked-by: Corentin LABBE <clabbe.montjoie@gmail.com>
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
This patch is targeting crypto/master
v2: rebased onto crypto/master, and added Acked-by and Reported-by
arch/arm/configs/sunxi_defconfig | 1 -
drivers/crypto/allwinner/Kconfig | 8 ---
drivers/crypto/allwinner/sun4i-ss/Makefile | 1 -
.../crypto/allwinner/sun4i-ss/sun4i-ss-core.c | 36 ----------
.../crypto/allwinner/sun4i-ss/sun4i-ss-prng.c | 69 -------------------
drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h | 20 ------
6 files changed, 135 deletions(-)
delete mode 100644 drivers/crypto/allwinner/sun4i-ss/sun4i-ss-prng.c
diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig
index a83d29fed175..f4b8d8f7dbef 100644
--- a/arch/arm/configs/sunxi_defconfig
+++ b/arch/arm/configs/sunxi_defconfig
@@ -168,11 +168,10 @@ CONFIG_NFS_V3_ACL=y
CONFIG_NFS_V4=y
CONFIG_ROOT_NFS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_CRYPTO_DEV_SUN4I_SS=y
-CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG=y
CONFIG_CRYPTO_DEV_SUN8I_CE=y
CONFIG_CRYPTO_DEV_SUN8I_SS=y
CONFIG_DMA_CMA=y
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_FS=y
diff --git a/drivers/crypto/allwinner/Kconfig b/drivers/crypto/allwinner/Kconfig
index 7270e5fbc573..1048f8e95ba8 100644
--- a/drivers/crypto/allwinner/Kconfig
+++ b/drivers/crypto/allwinner/Kconfig
@@ -23,18 +23,10 @@ config CRYPTO_DEV_SUN4I_SS
and SHA1 and MD5 hash algorithms.
To compile this driver as a module, choose M here: the module
will be called sun4i-ss.
-config CRYPTO_DEV_SUN4I_SS_PRNG
- bool "Support for Allwinner Security System PRNG"
- depends on CRYPTO_DEV_SUN4I_SS
- select CRYPTO_RNG
- help
- Select this option if you want to provide kernel-side support for
- the Pseudo-Random Number Generator found in the Security System.
-
config CRYPTO_DEV_SUN4I_SS_DEBUG
bool "Enable sun4i-ss stats"
depends on CRYPTO_DEV_SUN4I_SS
depends on DEBUG_FS
help
diff --git a/drivers/crypto/allwinner/sun4i-ss/Makefile b/drivers/crypto/allwinner/sun4i-ss/Makefile
index c0a2797d3168..06a9ae81f9f8 100644
--- a/drivers/crypto/allwinner/sun4i-ss/Makefile
+++ b/drivers/crypto/allwinner/sun4i-ss/Makefile
@@ -1,4 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_CRYPTO_DEV_SUN4I_SS) += sun4i-ss.o
sun4i-ss-y += sun4i-ss-core.o sun4i-ss-hash.o sun4i-ss-cipher.o
-sun4i-ss-$(CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG) += sun4i-ss-prng.o
diff --git a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c
index 58a76e2ba64e..35ef0930e77f 100644
--- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c
+++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c
@@ -211,27 +211,10 @@ static struct sun4i_ss_alg_template ss_algs[] = {
.cra_init = sun4i_ss_cipher_init,
.cra_exit = sun4i_ss_cipher_exit,
}
}
},
-#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG
-{
- .type = CRYPTO_ALG_TYPE_RNG,
- .alg.rng = {
- .base = {
- .cra_name = "stdrng",
- .cra_driver_name = "sun4i_ss_rng",
- .cra_priority = 300,
- .cra_ctxsize = 0,
- .cra_module = THIS_MODULE,
- },
- .generate = sun4i_ss_prng_generate,
- .seed = sun4i_ss_prng_seed,
- .seedsize = SS_SEED_LEN / BITS_PER_BYTE,
- }
-},
-#endif
};
static int sun4i_ss_debugfs_show(struct seq_file *seq, void *v)
{
unsigned int i;
@@ -245,16 +228,10 @@ static int sun4i_ss_debugfs_show(struct seq_file *seq, void *v)
ss_algs[i].alg.crypto.base.cra_driver_name,
ss_algs[i].alg.crypto.base.cra_name,
ss_algs[i].stat_req, ss_algs[i].stat_opti, ss_algs[i].stat_fb,
ss_algs[i].stat_bytes);
break;
- case CRYPTO_ALG_TYPE_RNG:
- seq_printf(seq, "%s %s reqs=%lu tsize=%lu\n",
- ss_algs[i].alg.rng.base.cra_driver_name,
- ss_algs[i].alg.rng.base.cra_name,
- ss_algs[i].stat_req, ss_algs[i].stat_bytes);
- break;
case CRYPTO_ALG_TYPE_AHASH:
seq_printf(seq, "%s %s reqs=%lu\n",
ss_algs[i].alg.hash.halg.base.cra_driver_name,
ss_algs[i].alg.hash.halg.base.cra_name,
ss_algs[i].stat_req);
@@ -469,17 +446,10 @@ static int sun4i_ss_probe(struct platform_device *pdev)
dev_err(ss->dev, "Fail to register %s\n",
ss_algs[i].alg.hash.halg.base.cra_name);
goto error_alg;
}
break;
- case CRYPTO_ALG_TYPE_RNG:
- err = crypto_register_rng(&ss_algs[i].alg.rng);
- if (err) {
- dev_err(ss->dev, "Fail to register %s\n",
- ss_algs[i].alg.rng.base.cra_name);
- }
- break;
}
}
/* Ignore error of debugfs */
ss->dbgfs_dir = debugfs_create_dir("sun4i-ss", NULL);
@@ -495,13 +465,10 @@ static int sun4i_ss_probe(struct platform_device *pdev)
crypto_unregister_skcipher(&ss_algs[i].alg.crypto);
break;
case CRYPTO_ALG_TYPE_AHASH:
crypto_unregister_ahash(&ss_algs[i].alg.hash);
break;
- case CRYPTO_ALG_TYPE_RNG:
- crypto_unregister_rng(&ss_algs[i].alg.rng);
- break;
}
}
error_pm:
sun4i_ss_pm_exit(ss);
return err;
@@ -518,13 +485,10 @@ static void sun4i_ss_remove(struct platform_device *pdev)
crypto_unregister_skcipher(&ss_algs[i].alg.crypto);
break;
case CRYPTO_ALG_TYPE_AHASH:
crypto_unregister_ahash(&ss_algs[i].alg.hash);
break;
- case CRYPTO_ALG_TYPE_RNG:
- crypto_unregister_rng(&ss_algs[i].alg.rng);
- break;
}
}
sun4i_ss_pm_exit(ss);
}
diff --git a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-prng.c b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-prng.c
deleted file mode 100644
index 491fcb7b81b4..000000000000
--- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-prng.c
+++ /dev/null
@@ -1,69 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-#include "sun4i-ss.h"
-
-int sun4i_ss_prng_seed(struct crypto_rng *tfm, const u8 *seed,
- unsigned int slen)
-{
- struct sun4i_ss_alg_template *algt;
- struct rng_alg *alg = crypto_rng_alg(tfm);
-
- algt = container_of(alg, struct sun4i_ss_alg_template, alg.rng);
- memcpy(algt->ss->seed, seed, slen);
-
- return 0;
-}
-
-int sun4i_ss_prng_generate(struct crypto_rng *tfm, const u8 *src,
- unsigned int slen, u8 *dst, unsigned int dlen)
-{
- struct sun4i_ss_alg_template *algt;
- struct rng_alg *alg = crypto_rng_alg(tfm);
- int i, err;
- u32 v;
- u32 *data = (u32 *)dst;
- const u32 mode = SS_OP_PRNG | SS_PRNG_CONTINUE | SS_ENABLED;
- size_t len;
- struct sun4i_ss_ctx *ss;
- unsigned int todo = (dlen / 4) * 4;
-
- algt = container_of(alg, struct sun4i_ss_alg_template, alg.rng);
- ss = algt->ss;
-
- err = pm_runtime_resume_and_get(ss->dev);
- if (err < 0)
- return err;
-
- if (IS_ENABLED(CONFIG_CRYPTO_DEV_SUN4I_SS_DEBUG)) {
- algt->stat_req++;
- algt->stat_bytes += todo;
- }
-
- spin_lock_bh(&ss->slock);
-
- writel(mode, ss->base + SS_CTL);
-
- while (todo > 0) {
- /* write the seed */
- for (i = 0; i < SS_SEED_LEN / BITS_PER_LONG; i++)
- writel(ss->seed[i], ss->base + SS_KEY0 + i * 4);
-
- /* Read the random data */
- len = min_t(size_t, SS_DATA_LEN / BITS_PER_BYTE, todo);
- readsl(ss->base + SS_TXFIFO, data, len / 4);
- data += len / 4;
- todo -= len;
-
- /* Update the seed */
- for (i = 0; i < SS_SEED_LEN / BITS_PER_LONG; i++) {
- v = readl(ss->base + SS_KEY0 + i * 4);
- ss->seed[i] = v;
- }
- }
-
- writel(0, ss->base + SS_CTL);
- spin_unlock_bh(&ss->slock);
-
- pm_runtime_put(ss->dev);
-
- return 0;
-}
diff --git a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h
index 6c5d4aa6453c..f7d1c79ac677 100644
--- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h
+++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h
@@ -29,12 +29,10 @@
#include <crypto/hash.h>
#include <crypto/internal/hash.h>
#include <crypto/internal/skcipher.h>
#include <crypto/aes.h>
#include <crypto/internal/des.h>
-#include <crypto/internal/rng.h>
-#include <crypto/rng.h>
#define SS_CTL 0x00
#define SS_KEY0 0x04
#define SS_KEY1 0x08
#define SS_KEY2 0x0C
@@ -60,14 +58,10 @@
#define SS_RXFIFO 0x200
#define SS_TXFIFO 0x204
/* SS_CTL configuration values */
-/* PRNG generator mode - bit 15 */
-#define SS_PRNG_ONESHOT (0 << 15)
-#define SS_PRNG_CONTINUE (1 << 15)
-
/* IV mode for hash */
#define SS_IV_ARBITRARY (1 << 14)
/* SS operation mode - bits 12-13 */
#define SS_ECB (0 << 12)
@@ -92,18 +86,14 @@
#define SS_OP_AES (0 << 4)
#define SS_OP_DES (1 << 4)
#define SS_OP_3DES (2 << 4)
#define SS_OP_SHA1 (3 << 4)
#define SS_OP_MD5 (4 << 4)
-#define SS_OP_PRNG (5 << 4)
/* Data end bit - bit 2 */
#define SS_DATA_END (1 << 2)
-/* PRNG start bit - bit 1 */
-#define SS_PRNG_START (1 << 1)
-
/* SS Enable bit - bit 0 */
#define SS_DISABLED (0 << 0)
#define SS_ENABLED (1 << 0)
/* SS_FCSR configuration values */
@@ -126,13 +116,10 @@
#define SS_RXFIFO_EMP_INT_PENDING (1 << 10)
#define SS_TXFIFO_AVA_INT_PENDING (1 << 8)
#define SS_RXFIFO_EMP_INT_ENABLE (1 << 2)
#define SS_TXFIFO_AVA_INT_ENABLE (1 << 0)
-#define SS_SEED_LEN 192
-#define SS_DATA_LEN 160
-
/*
* struct ss_variant - Describe SS hardware variant
* @sha1_in_be: The SHA1 digest is given by SS in BE, and so need to be inverted.
*/
struct ss_variant {
@@ -149,24 +136,20 @@ struct sun4i_ss_ctx {
struct device *dev;
struct resource *res;
char buf[4 * SS_RX_MAX];/* buffer for linearize SG src */
char bufo[4 * SS_TX_MAX]; /* buffer for linearize SG dst */
spinlock_t slock; /* control the use of the device */
-#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG
- u32 seed[SS_SEED_LEN / BITS_PER_LONG];
-#endif
struct dentry *dbgfs_dir;
struct dentry *dbgfs_stats;
};
struct sun4i_ss_alg_template {
u32 type;
u32 mode;
union {
struct skcipher_alg crypto;
struct ahash_alg hash;
- struct rng_alg rng;
} alg;
struct sun4i_ss_ctx *ss;
unsigned long stat_req;
unsigned long stat_fb;
unsigned long stat_bytes;
@@ -229,8 +212,5 @@ int sun4i_ss_aes_setkey(struct crypto_skcipher *tfm, const u8 *key,
unsigned int keylen);
int sun4i_ss_des_setkey(struct crypto_skcipher *tfm, const u8 *key,
unsigned int keylen);
int sun4i_ss_des3_setkey(struct crypto_skcipher *tfm, const u8 *key,
unsigned int keylen);
-int sun4i_ss_prng_generate(struct crypto_rng *tfm, const u8 *src,
- unsigned int slen, u8 *dst, unsigned int dlen);
-int sun4i_ss_prng_seed(struct crypto_rng *tfm, const u8 *seed, unsigned int slen);
base-commit: ecf3edd349dfabee9bc8a46c5ff91c9ebd858d48
--
2.54.0.1013.g208068f2d8-goog
^ permalink raw reply related
* Re: [PATCH v3 4/4] dm crypt: batch all sectors of a bio per crypto request
From: Mikulas Patocka @ 2026-06-01 16:15 UTC (permalink / raw)
To: Leonid Ravich
Cc: Herbert Xu, Alasdair Kergon, Ard Biesheuvel, Eric Biggers,
Jens Axboe, Horia Geanta, Gilad Ben-Yossef, linux-crypto,
dm-devel, linux-block
In-Reply-To: <20260601085644.13026-5-lravich@amazon.com>
On Mon, 1 Jun 2026, Leonid Ravich wrote:
> When the underlying skcipher driver advertises support for multiple
> data units in a single request (CRYPTO_ALG_SKCIPHER_MULTI_DATA_UNIT),
> configure the cipher with cc->sector_size as data_unit_size and
> submit one request per bio instead of one request per sector. This
> removes per-sector overhead in the crypto API hot path: request
> allocation, callback dispatch, completion handling, and SG setup.
>
> The optimisation is enabled automatically at table load when all
> of the following hold:
>
> - the cipher is non-aead (i.e. skcipher);
> - tfms_count is 1 (interleaved per-sector keys would break batching);
> - the IV mode is plain or plain64 (the only modes whose generator
> produces a sequential 64-bit little-endian counter that the cipher
> can extend by adding the data-unit index, matching the convention
> documented in crypto_skcipher_set_data_unit_size());
> - the iv_gen_ops->post() hook is unset (lmk and tcw use it; both are
> already excluded by the IV-mode test, but the explicit check makes
> the assumption durable against future IV modes);
> - dm-integrity is not stacked (no integrity tag or integrity IV);
> - the cipher driver advertises multi-data-unit support.
>
> A new CRYPT_MULTI_DATA_UNIT cipher_flag, set once at construction
> time, gates the multi-data-unit path. The existing per-sector path
> in crypt_convert_block_skcipher() is unchanged; the new
> crypt_convert_block_skcipher_multi() is reached from a small dispatch
> in crypt_convert() and shares the same backlog/-EBUSY/-EINPROGRESS
> flow control with the per-sector path.
>
> Heap-allocated scatterlists are stashed in dm_crypt_request and freed
> in crypt_free_req_skcipher() to avoid races between the synchronous-
> success free path and async-completion reuse from the request pool.
> On -ENOMEM during scatterlist allocation, the bio is requeued via
> BLK_STS_DEV_RESOURCE rather than failed, matching the behaviour of
> the existing -ENOMEM path for crypto request allocation.
>
> Verified end-to-end with a byte-equivalence test: encrypted output of
> plain64 dm-crypt with the multi-data-unit path matches output of the
> single-data-unit path bit-for-bit over a 256 MB device.
>
> Signed-off-by: Leonid Ravich <lravich@amazon.com>
Reviewed-by: Mikulas Patocka <mpatocka@redhat.com>
^ permalink raw reply
* Re: [PATCH v5 4/7] x86/sev: Add support to perform RMP optimizations asynchronously
From: Kalra, Ashish @ 2026-06-01 18:03 UTC (permalink / raw)
To: Ackerley Tng, tglx, mingo, bp, dave.hansen, x86, hpa, seanjc,
peterz, thomas.lendacky, herbert, davem, ardb
Cc: pbonzini, aik, Michael.Roth, KPrateek.Nayak, Tycho.Andersen,
Nathan.Fontenot, jackyli, pgonda, rientjes, jacobhxu, xin,
pawan.kumar.gupta, babu.moger, dyoung, nikunj, john.allen, darwi,
linux-kernel, linux-crypto, kvm, linux-coco
In-Reply-To: <8b7f6c93-ad5a-45e1-aa70-945518d29ddc@amd.com>
On 5/28/2026 6:52 PM, Kalra, Ashish wrote:
> Hello Ackerley,
>>> + /*
>>> + * RMPOPT scans the RMP table, stores the result of the scan in the
>>> + * reserved processor memory. The RMP scan is the most expensive
>>> + * part. If a second RMPOPT occurs, it can skip the expensive scan
>>> + * if they can see a cached result in the reserved processor memory.
>>> + *
>>> + * Do RMPOPT on one CPU alone. Then, follow that up with RMPOPT
>>> + * on every other primary thread. This potentially allows the
>>
>> I like the leader and follower comments below, thanks! With this
>> leader/follower setup, will the followers definitely see the cached scan
>> results, or might the followers still potentially not benefit from the
>> caching? If it's still only "potentially", why?
>
> I am verifying with the H/W architects if this is always going to be true or not,
> will the followers always benefit from the scan results cached by the leader (first CPU)
> or there is a possibility that the followers cannot see/access/get the cached results
> and instead do full RMP scanning ?
>
Following up on this, i have checked with the H/W architects, and the feedback is that
the: followers are "designed to" skip the scan if they see a cached result.
Thanks,
Ashish
^ permalink raw reply
* Re: [PATCH] crypto: atmel-tdes - use min3 to simplify sg_copy and crypt_start
From: Thorsten Blum @ 2026-06-01 19:13 UTC (permalink / raw)
To: Herbert Xu, David S. Miller, Nicolas Ferre, Alexandre Belloni,
Claudiu Beznea
Cc: linux-crypto, linux-arm-kernel, linux-kernel
In-Reply-To: <20260525092927.818586-2-thorsten.blum@linux.dev>
On Mon, May 25, 2026 at 11:29:27AM +0200, Thorsten Blum wrote:
> Replace multiple min() and min_t() calls with min3() to simplify the
> code. Using min3() instead of min_t() in atmel_tdes_crypt_start() is
> safe since the values are all unsigned and compatible.
>
> Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
> ---
> drivers/crypto/atmel-tdes.c | 7 +++----
> 1 file changed, 3 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c
> index 643e507f9c02..834c6d3e1b06 100644
> --- a/drivers/crypto/atmel-tdes.c
> +++ b/drivers/crypto/atmel-tdes.c
> @@ -143,8 +143,7 @@ static int atmel_tdes_sg_copy(struct scatterlist **sg, size_t *offset,
> size_t count, off = 0;
>
> while (buflen && total) {
> - count = min((*sg)->length - *offset, total);
> - count = min(count, buflen);
> + count = min3((*sg)->length - *offset, total, buflen);
>
> if (!count)
> return off;
> @@ -469,8 +468,8 @@ static int atmel_tdes_crypt_start(struct atmel_tdes_dev *dd)
>
>
> if (fast) {
> - count = min_t(size_t, dd->total, sg_dma_len(dd->in_sg));
> - count = min_t(size_t, count, sg_dma_len(dd->out_sg));
> + count = min3(sg_dma_len(dd->in_sg), sg_dma_len(dd->out_sg),
> + dd->total);
>
> err = dma_map_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
> if (!err) {
This should probably be dropped for now because of this fix:
https://lore.kernel.org/lkml/20260531204115.689052-3-thorsten.blum@linux.dev/
Thanks,
Thorsten
^ permalink raw reply
* [PATCH v2] crypto: algif_skcipher - snapshot IV for async skcipher requests
From: Max Clinton @ 2026-06-01 19:29 UTC (permalink / raw)
To: linux-crypto
Cc: linux-kernel, herbert, gregkh, davem, security, stable,
Max Clinton
In-Reply-To: <20260518233538.705966-2-maxtclinton@gmail.com>
AF_ALG skcipher AIO requests currently use the socket-wide IV buffer
during request processing. For async requests, later socket activity
can update that shared state before the original request has fully
completed, which can lead to inconsistent IV handling.
Snapshot the IV into per-request storage when preparing the skcipher
request, so in-flight operations no longer depend on mutable socket
state.
This mirrors the algif_aead fix from commit 5aa58c3a572b ("crypto:
algif_aead - snapshot IV for async AEAD requests"), which addressed
the same shape of bug in the AEAD sibling subsystem.
Tested on Debian Trixie 6.12.74+deb13+1-amd64 (unpatched) and on
v6.12.86 + this patch via virtme-ng on the same host. Reproducer
results: 10-14% race rate over 50000 iterations on the unpatched
kernel against cryptd(cbc(aes-generic)); 0 races at 50000 and
200000 iterations on the patched kernel; 0 races at 200000
iterations on the unpatched kernel with the synchronous
cbc(aes-generic) driver as a control case (confirming the race is
gated on the async dispatch path).
Fixes: e870456d8e7c ("crypto: algif_skcipher - overhaul memory management")
Cc: stable@kernel.org
Suggested-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Max Clinton <maxtclinton@gmail.com>
---
Changes since v1:
- Drop unneeded <crypto/internal/skcipher.h> include (Herbert).
- Rewrite iv pointer computation as (areq + 1) + reqsize per
Herbert's suggestion.
crypto/algif_skcipher.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index ba0a17fd9..5b5bc1204 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -103,9 +103,11 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
struct af_alg_ctx *ctx = ask->private;
struct crypto_skcipher *tfm = pask->private;
unsigned int bs = crypto_skcipher_chunksize(tfm);
+ unsigned int ivsize = crypto_skcipher_ivsize(tfm);
struct af_alg_async_req *areq;
unsigned cflags = 0;
int err = 0;
+ void *iv;
size_t len = 0;
if (!ctx->init || (ctx->more && ctx->used < bs)) {
@@ -116,10 +118,13 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
/* Allocate cipher request for current operation. */
areq = af_alg_alloc_areq(sk, sizeof(struct af_alg_async_req) +
- crypto_skcipher_reqsize(tfm));
+ crypto_skcipher_reqsize(tfm) + ivsize);
if (IS_ERR(areq))
return PTR_ERR(areq);
+ iv = (u8 *)(areq + 1) + crypto_skcipher_reqsize(tfm);
+ memcpy(iv, ctx->iv, ivsize);
+
/* convert iovecs of output buffers into RX SGL */
err = af_alg_get_rsgl(sk, msg, flags, areq, ctx->used, &len);
if (err)
@@ -159,7 +164,7 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
/* Initialize the crypto operation */
skcipher_request_set_tfm(&areq->cra_u.skcipher_req, tfm);
skcipher_request_set_crypt(&areq->cra_u.skcipher_req, areq->tsgl,
- areq->first_rsgl.sgl.sgt.sgl, len, ctx->iv);
+ areq->first_rsgl.sgl.sgt.sgl, len, iv);
if (ctx->state) {
err = crypto_skcipher_import(&areq->cra_u.skcipher_req,
--
2.47.3
^ permalink raw reply related
* Re: [PATCH 1/1] crypto: atmel-ecc - fix use after free situation
From: Thorsten Blum @ 2026-06-01 21:42 UTC (permalink / raw)
To: Lothar Rubusch
Cc: herbert, davem, nicolas.ferre, alexandre.belloni, claudiu.beznea,
tudor.ambarus, krzk+dt, linux-crypto, linux-arm-kernel,
linux-kernel
In-Reply-To: <20260529092703.33086-1-l.rubusch@gmail.com>
On Fri, May 29, 2026 at 09:27:03AM +0000, Lothar Rubusch wrote:
> Fixes a possible race condition, when having multiple of such devices
> attached (identified by sashiko feedback).
>
> The Scenario:
> Thread A (Device 1 Probe): Successfully adds i2c_priv to the global
> list (Line 324). The lock is released.
> Thread B (An active crypto request): Concurrently calls
> atmel_ecc_i2c_client_alloc(). It scans the global list, sees
> Device 1, and assigns a crypto job to it.
> Thread A: Moves to line 332. crypto_register_kpp() fails (e.g., out of
> memory or name clash).
> Thread A: Enters the error path. It removes Device 1 from the list and
> frees the i2c_priv memory.
> Thread B: Is still actively trying to talk to the I2C hardware using
> the i2c_priv pointer it grabbed in Step 2. The memory is now
> gone. Result: Kernel crash (Use-After-Free).
>
> Fixes: 11105693fa05 ("crypto: atmel-ecc - introduce Microchip / Atmel ECC driver")
> Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
> ---
> drivers/crypto/atmel-ecc.c | 10 ++++++++++
> drivers/crypto/atmel-i2c.h | 2 ++
> 2 files changed, 12 insertions(+)
>
> diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c
> index 0ca02995a1de..d391fe1462f6 100644
> --- a/drivers/crypto/atmel-ecc.c
> +++ b/drivers/crypto/atmel-ecc.c
> @@ -218,6 +218,8 @@ static struct i2c_client *atmel_ecc_i2c_client_alloc(void)
>
> list_for_each_entry(i2c_priv, &driver_data.i2c_client_list,
> i2c_client_list_node) {
> + if (!i2c_priv->ready)
> + continue;
> tfm_cnt = atomic_read(&i2c_priv->tfm_count);
> if (tfm_cnt < min_tfm_cnt) {
> min_tfm_cnt = tfm_cnt;
> @@ -322,20 +324,24 @@ static int atmel_ecc_probe(struct i2c_client *client)
> return ret;
>
> i2c_priv = i2c_get_clientdata(client);
> + i2c_priv->ready = false;
>
> spin_lock(&driver_data.i2c_list_lock);
> list_add_tail(&i2c_priv->i2c_client_list_node,
> &driver_data.i2c_client_list);
> + i2c_priv->ready = true;
> spin_unlock(&driver_data.i2c_list_lock);
>
> ret = crypto_register_kpp(&atmel_ecdh_nist_p256);
> if (ret) {
> spin_lock(&driver_data.i2c_list_lock);
> + i2c_priv->ready = false;
> list_del(&i2c_priv->i2c_client_list_node);
> spin_unlock(&driver_data.i2c_list_lock);
>
> dev_err(&client->dev, "%s alg registration failed\n",
> atmel_ecdh_nist_p256.base.cra_driver_name);
> + return ret;
> } else {
> dev_info(&client->dev, "atmel ecc algorithms registered in /proc/crypto\n");
> }
> @@ -347,6 +353,10 @@ static void atmel_ecc_remove(struct i2c_client *client)
> {
> struct atmel_i2c_client_priv *i2c_priv = i2c_get_clientdata(client);
>
> + spin_lock(&driver_data.i2c_list_lock);
> + i2c_priv->ready = false;
> + spin_unlock(&driver_data.i2c_list_lock);
> +
> /* Return EBUSY if i2c client already allocated. */
> if (atomic_read(&i2c_priv->tfm_count)) {
> /*
> diff --git a/drivers/crypto/atmel-i2c.h b/drivers/crypto/atmel-i2c.h
> index 72f04c15682f..e3b12030f9c4 100644
> --- a/drivers/crypto/atmel-i2c.h
> +++ b/drivers/crypto/atmel-i2c.h
> @@ -129,6 +129,7 @@ struct atmel_ecc_driver_data {
> * @wake_token_sz : size in bytes of the wake_token
> * @tfm_count : number of active crypto transformations on i2c client
> * @hwrng : hold the hardware generated rng
> + * @ready : hw client is ready to use
> *
> * Reads and writes from/to the i2c client are sequential. The first byte
> * transmitted to the device is treated as the byte size. Any attempt to send
> @@ -145,6 +146,7 @@ struct atmel_i2c_client_priv {
> size_t wake_token_sz;
> atomic_t tfm_count ____cacheline_aligned;
> struct hwrng hwrng;
> + bool ready;
> };
I don't think the ready flag fixes the race. A concurrent tfm can still
bind to the shared I2C client after atmel_ecc_probe() adds it to the
global list and marks it as ready, but before crypto_register_kpp()
fails.
Thanks,
Thorsten
^ permalink raw reply
* [PATCH v2 1/4] KVM: SEV: Do not allow intra-host migration/mirroring of SNP VMs
From: Atish Patra @ 2026-06-01 23:04 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Borislav Petkov, Dave Hansen,
x86, H. Peter Anvin, Tom Lendacky, Peter Gonda, Brijesh Singh,
Youngjae Lee, Ashish Kalra, Michael Roth, John Allen, Herbert Xu
Cc: clm, kvm, linux-kernel, linux-crypto, stable, Atish Patra,
Sashiko
In-Reply-To: <20260601-sev_snp_fixes-v2-0-611891b28a86@meta.com>
From: Atish Patra <atishp@meta.com>
The intra-host migration/mirroring feature is not fully implemented for
SEV-SNP VMs. The proper migration requires additional SNP-specific
state such as guest_req_mutex, guest_req_buf, and guest_resp_buf to be
transferred or initialized on the destination.
The SNP VM mirroring requires vmsa features to be copied as well otherwise
ASID would be bound to SNP range while VM is detected as a SEV VM.
Reject SNP source VMs in migration/mirroring until proper SNP state
transfer is implemented.
Fixes: 0b020f5af092 ("KVM: SEV: Add support for SEV-ES intra host migration")
Reported-by: Chris Mason <clm@meta.com>
Reported-by: Sashiko <sashiko-bot@kernel.org>
Assisted-by: Claude:claude-opus-4-6
Signed-off-by: Atish Patra <atishp@meta.com>
---
arch/x86/kvm/svm/sev.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index c2126b3c3072..e6ad6af128c9 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -2142,7 +2142,8 @@ int sev_vm_move_enc_context_from(struct kvm *kvm, unsigned int source_fd)
return ret;
if (kvm->arch.vm_type != source_kvm->arch.vm_type ||
- sev_guest(kvm) || !sev_guest(source_kvm)) {
+ sev_guest(kvm) || !sev_guest(source_kvm) ||
+ sev_snp_guest(source_kvm)) {
ret = -EINVAL;
goto out_unlock;
}
@@ -2865,6 +2866,7 @@ int sev_vm_copy_enc_context_from(struct kvm *kvm, unsigned int source_fd)
* created after SEV/SEV-ES initialization, e.g. to init intercepts.
*/
if (sev_guest(kvm) || !sev_guest(source_kvm) ||
+ sev_snp_guest(source_kvm) ||
is_mirroring_enc_context(source_kvm) || kvm->created_vcpus) {
ret = -EINVAL;
goto e_unlock;
--
2.53.0-Meta
^ permalink raw reply related
* [PATCH v2 0/4] KVM: Miscellaneous SEV/SNP related fixes
From: Atish Patra @ 2026-06-01 23:04 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Borislav Petkov, Dave Hansen,
x86, H. Peter Anvin, Tom Lendacky, Peter Gonda, Brijesh Singh,
Youngjae Lee, Ashish Kalra, Michael Roth, John Allen, Herbert Xu
Cc: clm, kvm, linux-kernel, linux-crypto, stable, Atish Patra,
Sashiko
This series addresses a few issues found during code audit of the
KVM SEV/SNP and CCP driver code. The fixes include a incorrect lock state
and incomplete state handling during intra-host migration for SNP VMs.
To: Sean Christopherson <seanjc@google.com>
To: Paolo Bonzini <pbonzini@redhat.com>
To: Borislav Petkov <bp@alien8.de>
To: Dave Hansen <dave.hansen@linux.intel.com>
To: x86@kernel.org
To: H. Peter Anvin <hpa@zytor.com>
To: Tom Lendacky <thomas.lendacky@amd.com>
To: Peter Gonda <pgonda@google.com>
To: Brijesh Singh <brijesh.singh@amd.com>
To: Youngjae Lee <youngjaelee@meta.com>
To: Ashish Kalra <ashish.kalra@amd.com>
To: Michael Roth <michael.roth@amd.com>
To: John Allen <john.allen@amd.com>
To: Herbert Xu <herbert@gondor.apana.org.au>
Cc: clm@meta.com
Cc: kvm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-crypto@vger.kernel.org
Cc: stable@vger.kernel.org
Signed-off-by: Atish Patra <atishp@meta.com>
---
Changes in v2:
- Added fixes based on the reports by Sashiko.
- Added a kselftest for validating SNP VM mirroring/migration rejection.
- Link to v1: https://lore.kernel.org/r/20260528-sev_snp_fixes-v1-0-d67a08151779@meta.com
---
Atish Patra (4):
KVM: SEV: Do not allow intra-host migration/mirroring of SNP VMs
KVM: selftests: Verify SNP VMs are rejected from migration and mirroring
crypto: ccp: Fix possible deadlock in SEV init failure path
crypto: ccp: Fix memory leak in SEV INIT_EX path
arch/x86/kvm/svm/sev.c | 4 +-
drivers/crypto/ccp/sev-dev.c | 18 +++++++--
.../testing/selftests/kvm/x86/sev_migrate_tests.c | 47 ++++++++++++++++++++++
3 files changed, 65 insertions(+), 4 deletions(-)
---
base-commit: e7ae89a0c97ce2b68b0983cd01eda67cf373517d
change-id: 20260525-sev_snp_fixes-0b73789c1a91
Best regards,
--
Atish Patra <atishp@meta.com>
^ permalink raw reply
* [PATCH v2 2/4] KVM: selftests: Verify SNP VMs are rejected from migration and mirroring
From: Atish Patra @ 2026-06-01 23:04 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Borislav Petkov, Dave Hansen,
x86, H. Peter Anvin, Tom Lendacky, Peter Gonda, Brijesh Singh,
Youngjae Lee, Ashish Kalra, Michael Roth, John Allen, Herbert Xu
Cc: clm, kvm, linux-kernel, linux-crypto, stable, Atish Patra
In-Reply-To: <20260601-sev_snp_fixes-v2-0-611891b28a86@meta.com>
From: Atish Patra <atishp@meta.com>
Migration and mirroring of SEV-SNP VMs are not supported yet.
Add two selftests that verify KVM rejects intra-host migration and
mirroring when the source VM is an SNP VM, so the restriction stays enforced
until proper SNP state transfer is implemented.
Signed-off-by: Atish Patra <atishp@meta.com>
---
.../testing/selftests/kvm/x86/sev_migrate_tests.c | 47 ++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/tools/testing/selftests/kvm/x86/sev_migrate_tests.c b/tools/testing/selftests/kvm/x86/sev_migrate_tests.c
index 6b0928e69051..acef6ab26d3d 100644
--- a/tools/testing/selftests/kvm/x86/sev_migrate_tests.c
+++ b/tools/testing/selftests/kvm/x86/sev_migrate_tests.c
@@ -313,6 +313,49 @@ static void test_sev_mirror_parameters(void)
kvm_vm_free(vm_no_vcpu);
}
+static void test_sev_snp_migrate_reject(void)
+{
+ struct kvm_vm *src_vm, *dst_vm;
+ int ret;
+
+ src_vm = vm_create_barebones_type(KVM_X86_SNP_VM);
+ snp_vm_init(src_vm);
+ __vm_vcpu_add(src_vm, 0);
+ vm_sev_launch(src_vm, snp_default_policy(), NULL);
+
+ dst_vm = vm_create_barebones_type(KVM_X86_SNP_VM);
+ __vm_vcpu_add(dst_vm, 0);
+
+ ret = __sev_migrate_from(dst_vm, src_vm);
+ TEST_ASSERT(ret == -1 && errno == EINVAL,
+ "SNP VM migration should be rejected. ret: %d, errno: %d",
+ ret, errno);
+
+ kvm_vm_free(src_vm);
+ kvm_vm_free(dst_vm);
+}
+
+static void test_sev_snp_mirror_reject(void)
+{
+ struct kvm_vm *src_vm, *dst_vm;
+ int ret;
+
+ src_vm = vm_create_barebones_type(KVM_X86_SNP_VM);
+ snp_vm_init(src_vm);
+ __vm_vcpu_add(src_vm, 0);
+ vm_sev_launch(src_vm, snp_default_policy(), NULL);
+
+ dst_vm = aux_vm_create(false);
+
+ ret = __sev_mirror_create(dst_vm, src_vm);
+ TEST_ASSERT(ret == -1 && errno == EINVAL,
+ "SNP VM mirroring should be rejected. ret: %d, errno: %d",
+ ret, errno);
+
+ kvm_vm_free(src_vm);
+ kvm_vm_free(dst_vm);
+}
+
static void test_sev_move_copy(void)
{
struct kvm_vm *dst_vm, *dst2_vm, *dst3_vm, *sev_vm, *mirror_vm,
@@ -384,12 +427,16 @@ int main(int argc, char *argv[])
test_sev_migrate_parameters();
if (kvm_has_cap(KVM_CAP_VM_COPY_ENC_CONTEXT_FROM))
test_sev_move_copy();
+ if (kvm_cpu_has(X86_FEATURE_SEV_SNP))
+ test_sev_snp_migrate_reject();
}
if (kvm_has_cap(KVM_CAP_VM_COPY_ENC_CONTEXT_FROM)) {
test_sev_mirror(/* es= */ false);
if (have_sev_es)
test_sev_mirror(/* es= */ true);
test_sev_mirror_parameters();
+ if (kvm_cpu_has(X86_FEATURE_SEV_SNP))
+ test_sev_snp_mirror_reject();
}
return 0;
}
--
2.53.0-Meta
^ permalink raw reply related
* [PATCH v2 3/4] crypto: ccp: Fix possible deadlock in SEV init failure path
From: Atish Patra @ 2026-06-01 23:04 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Borislav Petkov, Dave Hansen,
x86, H. Peter Anvin, Tom Lendacky, Peter Gonda, Brijesh Singh,
Youngjae Lee, Ashish Kalra, Michael Roth, John Allen, Herbert Xu
Cc: clm, kvm, linux-kernel, linux-crypto, stable, Atish Patra
In-Reply-To: <20260601-sev_snp_fixes-v2-0-611891b28a86@meta.com>
From: Atish Patra <atishp@meta.com>
__sev_platform_init_handle_init_ex_path() called
rmp_mark_pages_firmware() with locked=false but while the parent
function of init_ex_path already acquired the sev_cmd_mutex.
In case of a rmpupdate failure for any page after the first, the cleanup
path would invoke reclaim pages which would result in a deadlock in
sev_do_cmd.
Pass locked=true to honor the lock status of the parent function.
Fixes: 7364a6fbca45 ("crypto: ccp: Handle non-volatile INIT_EX data when SNP is enabled")
Reported-by: Chris Mason <clm@meta.com>
Assisted-by: Claude:claude-opus-4-6
Signed-off-by: Atish Patra <atishp@meta.com>
---
drivers/crypto/ccp/sev-dev.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c
index d1e9e0ac63b6..3d4793e8e34b 100644
--- a/drivers/crypto/ccp/sev-dev.c
+++ b/drivers/crypto/ccp/sev-dev.c
@@ -1557,7 +1557,7 @@ static int __sev_platform_init_handle_init_ex_path(struct sev_device *sev)
unsigned long npages;
npages = 1UL << get_order(NV_LENGTH);
- if (rmp_mark_pages_firmware(__pa(sev_init_ex_buffer), npages, false)) {
+ if (rmp_mark_pages_firmware(__pa(sev_init_ex_buffer), npages, true)) {
dev_err(sev->dev, "SEV: INIT_EX NV memory page state change failed.\n");
return -ENOMEM;
}
--
2.53.0-Meta
^ permalink raw reply related
* [PATCH v2 4/4] crypto: ccp: Fix memory leak in SEV INIT_EX path
From: Atish Patra @ 2026-06-01 23:04 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Borislav Petkov, Dave Hansen,
x86, H. Peter Anvin, Tom Lendacky, Peter Gonda, Brijesh Singh,
Youngjae Lee, Ashish Kalra, Michael Roth, John Allen, Herbert Xu
Cc: clm, kvm, linux-kernel, linux-crypto, stable, Atish Patra,
Sashiko
In-Reply-To: <20260601-sev_snp_fixes-v2-0-611891b28a86@meta.com>
From: Atish Patra <atishp@meta.com>
allocated pages in _init_ext_path are never freed and sev_init_ex_buffer
is left pointing at the leaked memory in case of any failures during the
function..
Fix by adding an error path that frees the pages and clears
sev_init_ex_buffer. Make sure we only free the memory if the failure
happens before the conversion. Otherwise, we may end up trying to free
up converted pages in case of reclaim failure. rmp_mark_pages_firmware
failures should be rare enough to avoid more code complexity to track
down which pages were reclaimed/leaked vs which are not.
Fixes: 7364a6fbca45 ("crypto: ccp: Handle non-volatile INIT_EX data when SNP is enabled")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Signed-off-by: Atish Patra <atishp@meta.com>
---
drivers/crypto/ccp/sev-dev.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c
index 3d4793e8e34b..8566f164430b 100644
--- a/drivers/crypto/ccp/sev-dev.c
+++ b/drivers/crypto/ccp/sev-dev.c
@@ -1550,7 +1550,7 @@ static int __sev_platform_init_handle_init_ex_path(struct sev_device *sev)
rc = sev_read_init_ex_file();
if (rc)
- return rc;
+ goto err_free;
/* If SEV-SNP is initialized, transition to firmware page. */
if (sev->snp_initialized) {
@@ -1559,11 +1559,23 @@ static int __sev_platform_init_handle_init_ex_path(struct sev_device *sev)
npages = 1UL << get_order(NV_LENGTH);
if (rmp_mark_pages_firmware(__pa(sev_init_ex_buffer), npages, true)) {
dev_err(sev->dev, "SEV: INIT_EX NV memory page state change failed.\n");
- return -ENOMEM;
+ rc = -ENOMEM;
+ /*
+ * Don't free on conversion failure: the rollback may
+ * have left pages firmware-owned, and a high-order
+ * block can't be partially freed.
+ */
+ goto err_reset;
}
}
return 0;
+
+err_free:
+ __free_pages(page, get_order(NV_LENGTH));
+err_reset:
+ sev_init_ex_buffer = NULL;
+ return rc;
}
static int __sev_platform_init_locked(int *error)
--
2.53.0-Meta
^ permalink raw reply related
* [PATCH] crypto: amcc - check ppc4xx_trng_probe() return value
From: Rosen Penev @ 2026-06-02 1:45 UTC (permalink / raw)
To: linux-crypto; +Cc: Herbert Xu, David S. Miller, open list
ppc4xx_trng_probe() can fail for several reasons (missing TRNG node,
iomap failure, allocation failure, hwrng registration failure). Change
its return type from void to int and propagate error codes back to the
caller in crypto4xx_probe() so that probe failures are handled properly.
Assisted-by: opencode:big-pickle
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
drivers/crypto/amcc/crypto4xx_core.c | 5 ++++-
drivers/crypto/amcc/crypto4xx_trng.c | 12 ++++++------
drivers/crypto/amcc/crypto4xx_trng.h | 6 +++---
3 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c
index 0f1b2653769c..596a90af2c90 100644
--- a/drivers/crypto/amcc/crypto4xx_core.c
+++ b/drivers/crypto/amcc/crypto4xx_core.c
@@ -1346,7 +1346,10 @@ static int crypto4xx_probe(struct platform_device *ofdev)
if (rc)
goto err_tasklet;
- ppc4xx_trng_probe(core_dev);
+ rc = ppc4xx_trng_probe(core_dev);
+ if (rc)
+ goto err_tasklet;
+
return 0;
err_tasklet:
diff --git a/drivers/crypto/amcc/crypto4xx_trng.c b/drivers/crypto/amcc/crypto4xx_trng.c
index 031dd2bf8598..f762f92dd03e 100644
--- a/drivers/crypto/amcc/crypto4xx_trng.c
+++ b/drivers/crypto/amcc/crypto4xx_trng.c
@@ -68,7 +68,7 @@ static const struct of_device_id ppc4xx_trng_match[] = {
{},
};
-void ppc4xx_trng_probe(struct crypto4xx_core_device *core_dev)
+int ppc4xx_trng_probe(struct crypto4xx_core_device *core_dev)
{
struct crypto4xx_device *dev = core_dev->dev;
struct device_node *trng = NULL;
@@ -79,17 +79,17 @@ void ppc4xx_trng_probe(struct crypto4xx_core_device *core_dev)
trng = of_find_matching_node(NULL, ppc4xx_trng_match);
if (!trng || !of_device_is_available(trng)) {
of_node_put(trng);
- return;
+ return -ENODEV;
}
dev->trng_base = devm_of_iomap(core_dev->device, trng, 0, NULL);
of_node_put(trng);
if (IS_ERR(dev->trng_base))
- return;
+ return PTR_ERR(dev->trng_base);
rng = devm_kzalloc(core_dev->device, sizeof(*rng), GFP_KERNEL);
if (!rng)
- return;
+ return -ENOMEM;
rng->name = KBUILD_MODNAME;
rng->data_present = ppc4xx_trng_data_present;
@@ -103,9 +103,9 @@ void ppc4xx_trng_probe(struct crypto4xx_core_device *core_dev)
ppc4xx_trng_enable(dev, false);
dev_err(core_dev->device, "failed to register hwrng (%d).\n",
err);
- return;
+ return err;
}
- return;
+ return 0;
}
void ppc4xx_trng_remove(struct crypto4xx_core_device *core_dev)
diff --git a/drivers/crypto/amcc/crypto4xx_trng.h b/drivers/crypto/amcc/crypto4xx_trng.h
index 7356716274cb..7c6f426ab275 100644
--- a/drivers/crypto/amcc/crypto4xx_trng.h
+++ b/drivers/crypto/amcc/crypto4xx_trng.h
@@ -13,11 +13,11 @@
#define __CRYPTO4XX_TRNG_H__
#ifdef CONFIG_HW_RANDOM_PPC4XX
-void ppc4xx_trng_probe(struct crypto4xx_core_device *core_dev);
+int ppc4xx_trng_probe(struct crypto4xx_core_device *core_dev);
void ppc4xx_trng_remove(struct crypto4xx_core_device *core_dev);
#else
-static inline void ppc4xx_trng_probe(
- struct crypto4xx_core_device *dev __maybe_unused) { }
+static inline int ppc4xx_trng_probe(
+ struct crypto4xx_core_device *dev __maybe_unused) { return -ENODEV; }
static inline void ppc4xx_trng_remove(
struct crypto4xx_core_device *dev __maybe_unused) { }
#endif
--
2.54.0
^ permalink raw reply related
* [PATCH] crypto: amcc - convert irq_of_parse_and_map to platform_get_irq
From: Rosen Penev @ 2026-06-02 1:46 UTC (permalink / raw)
To: linux-crypto; +Cc: Herbert Xu, David S. Miller, open list
Replace the deprecated irq_of_parse_and_map() call with the modern
platform_get_irq() in the probe function. This also improves error
handling: platform_get_irq() returns a negative errno on failure,
whereas irq_of_parse_and_map() returned 0.
Change the irq field in struct crypto4xx_core_device from u32 to int
to match the return type of platform_get_irq().
Assisted-by: opencode:big-pickle
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
drivers/crypto/amcc/crypto4xx_core.c | 6 +++++-
drivers/crypto/amcc/crypto4xx_core.h | 2 +-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c
index b7b6c97d2147..063282a2ad63 100644
--- a/drivers/crypto/amcc/crypto4xx_core.c
+++ b/drivers/crypto/amcc/crypto4xx_core.c
@@ -1382,7 +1382,11 @@ static int crypto4xx_probe(struct platform_device *ofdev)
}
/* Register for Crypto isr, Crypto Engine IRQ */
- core_dev->irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
+ core_dev->irq = platform_get_irq(ofdev, 0);
+ if (core_dev->irq < 0) {
+ rc = core_dev->irq;
+ goto err_iomap;
+ }
rc = devm_request_irq(&ofdev->dev, core_dev->irq,
is_revb ? crypto4xx_ce_interrupt_handler_revb :
crypto4xx_ce_interrupt_handler,
diff --git a/drivers/crypto/amcc/crypto4xx_core.h b/drivers/crypto/amcc/crypto4xx_core.h
index ee36630c670f..391475d00bdb 100644
--- a/drivers/crypto/amcc/crypto4xx_core.h
+++ b/drivers/crypto/amcc/crypto4xx_core.h
@@ -108,7 +108,7 @@ struct crypto4xx_core_device {
struct crypto4xx_device *dev;
struct hwrng *trng;
u32 int_status;
- u32 irq;
+ int irq;
struct tasklet_struct tasklet;
spinlock_t lock;
struct mutex rng_lock;
--
2.54.0
^ permalink raw reply related
* Re: [PATCH] crypto: amcc - check ppc4xx_trng_probe() return value
From: Rosen Penev @ 2026-06-02 2:04 UTC (permalink / raw)
To: linux-crypto; +Cc: Herbert Xu, David S. Miller, open list
In-Reply-To: <20260602014553.522044-1-rosenp@gmail.com>
On Mon, Jun 1, 2026 at 6:46 PM Rosen Penev <rosenp@gmail.com> wrote:
>
> ppc4xx_trng_probe() can fail for several reasons (missing TRNG node,
> iomap failure, allocation failure, hwrng registration failure). Change
> its return type from void to int and propagate error codes back to the
> caller in crypto4xx_probe() so that probe failures are handled properly.
This was prematurely sent. Please ignore.
>
> Assisted-by: opencode:big-pickle
> Signed-off-by: Rosen Penev <rosenp@gmail.com>
> ---
> drivers/crypto/amcc/crypto4xx_core.c | 5 ++++-
> drivers/crypto/amcc/crypto4xx_trng.c | 12 ++++++------
> drivers/crypto/amcc/crypto4xx_trng.h | 6 +++---
> 3 files changed, 13 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c
> index 0f1b2653769c..596a90af2c90 100644
> --- a/drivers/crypto/amcc/crypto4xx_core.c
> +++ b/drivers/crypto/amcc/crypto4xx_core.c
> @@ -1346,7 +1346,10 @@ static int crypto4xx_probe(struct platform_device *ofdev)
> if (rc)
> goto err_tasklet;
>
> - ppc4xx_trng_probe(core_dev);
> + rc = ppc4xx_trng_probe(core_dev);
> + if (rc)
> + goto err_tasklet;
> +
> return 0;
>
> err_tasklet:
> diff --git a/drivers/crypto/amcc/crypto4xx_trng.c b/drivers/crypto/amcc/crypto4xx_trng.c
> index 031dd2bf8598..f762f92dd03e 100644
> --- a/drivers/crypto/amcc/crypto4xx_trng.c
> +++ b/drivers/crypto/amcc/crypto4xx_trng.c
> @@ -68,7 +68,7 @@ static const struct of_device_id ppc4xx_trng_match[] = {
> {},
> };
>
> -void ppc4xx_trng_probe(struct crypto4xx_core_device *core_dev)
> +int ppc4xx_trng_probe(struct crypto4xx_core_device *core_dev)
> {
> struct crypto4xx_device *dev = core_dev->dev;
> struct device_node *trng = NULL;
> @@ -79,17 +79,17 @@ void ppc4xx_trng_probe(struct crypto4xx_core_device *core_dev)
> trng = of_find_matching_node(NULL, ppc4xx_trng_match);
> if (!trng || !of_device_is_available(trng)) {
> of_node_put(trng);
> - return;
> + return -ENODEV;
> }
>
> dev->trng_base = devm_of_iomap(core_dev->device, trng, 0, NULL);
> of_node_put(trng);
> if (IS_ERR(dev->trng_base))
> - return;
> + return PTR_ERR(dev->trng_base);
>
> rng = devm_kzalloc(core_dev->device, sizeof(*rng), GFP_KERNEL);
> if (!rng)
> - return;
> + return -ENOMEM;
>
> rng->name = KBUILD_MODNAME;
> rng->data_present = ppc4xx_trng_data_present;
> @@ -103,9 +103,9 @@ void ppc4xx_trng_probe(struct crypto4xx_core_device *core_dev)
> ppc4xx_trng_enable(dev, false);
> dev_err(core_dev->device, "failed to register hwrng (%d).\n",
> err);
> - return;
> + return err;
> }
> - return;
> + return 0;
> }
>
> void ppc4xx_trng_remove(struct crypto4xx_core_device *core_dev)
> diff --git a/drivers/crypto/amcc/crypto4xx_trng.h b/drivers/crypto/amcc/crypto4xx_trng.h
> index 7356716274cb..7c6f426ab275 100644
> --- a/drivers/crypto/amcc/crypto4xx_trng.h
> +++ b/drivers/crypto/amcc/crypto4xx_trng.h
> @@ -13,11 +13,11 @@
> #define __CRYPTO4XX_TRNG_H__
>
> #ifdef CONFIG_HW_RANDOM_PPC4XX
> -void ppc4xx_trng_probe(struct crypto4xx_core_device *core_dev);
> +int ppc4xx_trng_probe(struct crypto4xx_core_device *core_dev);
> void ppc4xx_trng_remove(struct crypto4xx_core_device *core_dev);
> #else
> -static inline void ppc4xx_trng_probe(
> - struct crypto4xx_core_device *dev __maybe_unused) { }
> +static inline int ppc4xx_trng_probe(
> + struct crypto4xx_core_device *dev __maybe_unused) { return -ENODEV; }
> static inline void ppc4xx_trng_remove(
> struct crypto4xx_core_device *dev __maybe_unused) { }
> #endif
> --
> 2.54.0
>
^ permalink raw reply
* [bug report] crypto: omap - switch from scatter_walk to plain offset
From: Dan Carpenter @ 2026-06-02 8:19 UTC (permalink / raw)
To: Eric Biggers; +Cc: linux-crypto
Hello Eric Biggers,
Commit 42c5675c2f5b ("crypto: omap - switch from scatter_walk to
plain offset") from Jan 5, 2025 (linux-next), leads to the following
Smatch static checker warning:
drivers/crypto/omap-des.c:842 omap_des_irq() error: we previously assumed 'dd->in_sg' could be null (see line 844)
drivers/crypto/omap-des.c:872 omap_des_irq() error: we previously assumed 'dd->out_sg' could be null (see line 874)
drivers/crypto/omap-des.c
823 static irqreturn_t omap_des_irq(int irq, void *dev_id)
824 {
825 struct omap_des_dev *dd = dev_id;
826 u32 status, i;
827 u32 *src, *dst;
828
829 status = omap_des_read(dd, DES_REG_IRQ_STATUS(dd));
830 if (status & DES_REG_IRQ_DATA_IN) {
831 omap_des_write(dd, DES_REG_IRQ_ENABLE(dd), 0x0);
832
833 BUG_ON(!dd->in_sg);
834
835 BUG_ON(dd->in_sg_offset > dd->in_sg->length);
836
837 src = sg_virt(dd->in_sg) + dd->in_sg_offset;
838
839 for (i = 0; i < DES_BLOCK_WORDS; i++) {
840 omap_des_write(dd, DES_REG_DATA_N(dd, i), *src);
841 dd->in_sg_offset += 4;
--> 842 if (dd->in_sg_offset == dd->in_sg->length) {
^^^^^^^^^
Dereference.
843 dd->in_sg = sg_next(dd->in_sg);
Imagine that sg_next() returns NULL, then the next iteration through the
loop will crash.
844 if (dd->in_sg) {
845 dd->in_sg_offset = 0;
846 src = sg_virt(dd->in_sg);
847 }
848 } else {
849 src++;
850 }
851 }
852
853 /* Clear IRQ status */
This email is a free service from the Smatch-CI project [smatch.sf.net].
regards,
dan carpenter
^ permalink raw reply
* [PATCH] MAINTAINERS: make myself the maintainer of the Qualcomm QCE driver
From: Bartosz Golaszewski @ 2026-06-02 12:46 UTC (permalink / raw)
To: Demi Marie Obenour, Herbert Xu, David S. Miller, Thara Gopinath,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
Konrad Dybcio, Russell King, Eric Biggers, Ard Biesheuvel,
Kuldeep Singh
Cc: linux-crypto, linux-arm-msm, linux-kernel, brgl,
Bartosz Golaszewski
Qualcomm wants to keep supporting and extending the crypto engine driver.
Thara has not been active for many months, so change the maintainer to
myself and upgrade the driver to Supported.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
I've considered also marking the driver as BROKEN but decided not to.
Next week I plan to address the failing self tests as well as go through
all the ciphers it provides and remove ones that are known to be weak or
deprecated.
Regarding the series that proposed to remove this[1], let this be the
official objection. Qualcomm's clients use this IP, we have support for
new features planned and intend to refactor it significantly.
[1] https://lore.kernel.org/all/20260523-delete-qce-v1-0-86105cd7f406@gmail.com/
---
MAINTAINERS | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 0ae45fed10fbe2983c37889bf075c058bc09816a..538373148cb1782651f8b47efc8ba3ed9313fe38 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -22087,10 +22087,10 @@ F: Documentation/devicetree/bindings/opp/opp-v2-kryo-cpu.yaml
F: drivers/cpufreq/qcom-cpufreq-nvmem.c
QUALCOMM CRYPTO DRIVERS
-M: Thara Gopinath <thara.gopinath@gmail.com>
+M: Bartosz Golaszewski <brgl@kernel.org>
L: linux-crypto@vger.kernel.org
L: linux-arm-msm@vger.kernel.org
-S: Maintained
+S: Supported
F: Documentation/devicetree/bindings/crypto/qcom-qce.yaml
F: drivers/crypto/qce/
---
base-commit: 08484c504b55a98bd100527fbe10a3caf55ff3ff
change-id: 20260602-qcom-qce-broken-16257bc707fd
Best regards,
--
Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
^ permalink raw reply related
* Re: [PATCH] MAINTAINERS: make myself the maintainer of the Qualcomm QCE driver
From: Krzysztof Kozlowski @ 2026-06-02 12:50 UTC (permalink / raw)
To: Bartosz Golaszewski, Demi Marie Obenour, Herbert Xu,
David S. Miller, Thara Gopinath, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Bjorn Andersson, Konrad Dybcio, Russell King,
Eric Biggers, Ard Biesheuvel, Kuldeep Singh
Cc: linux-crypto, linux-arm-msm, linux-kernel, brgl
In-Reply-To: <20260602-qcom-qce-broken-v1-1-a4ef756089e0@oss.qualcomm.com>
On 02/06/2026 14:46, Bartosz Golaszewski wrote:
> Qualcomm wants to keep supporting and extending the crypto engine driver.
> Thara has not been active for many months, so change the maintainer to
> myself and upgrade the driver to Supported.
>
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
> ---
FWIW:
Acked-by: Krzysztof Kozlowski <krzk@kernel.org>
Best regards,
Krzysztof
^ permalink raw reply
* [PATCH] crypto: marvell/octeontx - fix DMA cleanup using wrong loop index
From: Felix Gu @ 2026-06-02 14:38 UTC (permalink / raw)
To: Srujana Challa, Bharat Bhushan, Herbert Xu, David S. Miller,
Lukasz Bartosik
Cc: linux-crypto, linux-kernel, Felix Gu
The sg_cleanup path used list[i] instead of list[j] when unmapping DMA
buffers, leaking successfully mapped entries and repeatedly unmapping
the failed one.
Fixes: 10b4f09491bf ("crypto: marvell - add the Virtual Function driver for CPT")
Signed-off-by: Felix Gu <ustc.gu@gmail.com>
---
drivers/crypto/marvell/octeontx/otx_cptvf_reqmgr.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/crypto/marvell/octeontx/otx_cptvf_reqmgr.c b/drivers/crypto/marvell/octeontx/otx_cptvf_reqmgr.c
index c80baf1ad90b..89030e2711ce 100644
--- a/drivers/crypto/marvell/octeontx/otx_cptvf_reqmgr.c
+++ b/drivers/crypto/marvell/octeontx/otx_cptvf_reqmgr.c
@@ -157,8 +157,8 @@ static inline int setup_sgio_components(struct pci_dev *pdev,
sg_cleanup:
for (j = 0; j < i; j++) {
if (list[j].dma_addr) {
- dma_unmap_single(&pdev->dev, list[i].dma_addr,
- list[i].size, DMA_BIDIRECTIONAL);
+ dma_unmap_single(&pdev->dev, list[j].dma_addr,
+ list[j].size, DMA_BIDIRECTIONAL);
}
list[j].dma_addr = 0;
---
base-commit: 08484c504b55a98bd100527fbe10a3caf55ff3ff
change-id: 20260602-otx-7bca4557205f
Best regards,
--
Felix Gu <ustc.gu@gmail.com>
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox