| b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | From ce163ba0bf298f1707321ac025ef639f88e62801 Mon Sep 17 00:00:00 2001 |
| 2 | From: Eneas U de Queiroz <cotequeiroz@gmail.com> |
| 3 | Date: Fri, 7 Feb 2020 12:02:26 -0300 |
| 4 | Subject: [PATCH 10/11] crypto: qce - use AES fallback for small requests |
| 5 | |
| 6 | Process small blocks using the fallback cipher, as a workaround for an |
| 7 | observed failure (DMA-related, apparently) when computing the GCM ghash |
| 8 | key. This brings a speed gain as well, since it avoids the latency of |
| 9 | using the hardware engine to process small blocks. |
| 10 | |
| 11 | Using software for all 16-byte requests would be enough to make GCM |
| 12 | work, but to increase performance, a larger threshold would be better. |
| 13 | Measuring the performance of supported ciphers with openssl speed, |
| 14 | software matches hardware at around 768-1024 bytes. |
| 15 | |
| 16 | Considering the 256-bit ciphers, software is 2-3 times faster than qce |
| 17 | at 256-bytes, 30% faster at 512, and about even at 768-bytes. With |
| 18 | 128-bit keys, the break-even point would be around 1024-bytes. |
| 19 | |
| 20 | This adds the 'aes_sw_max_len' parameter, to set the largest request |
| 21 | length processed by the software fallback. Its default is being set to |
| 22 | 512 bytes, a little lower than the break-even point, to balance the cost |
| 23 | in CPU usage. |
| 24 | |
| 25 | Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com> |
| 26 | Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> |
| 27 | --- |
| 28 | |
| 29 | --- a/drivers/crypto/Kconfig |
| 30 | +++ b/drivers/crypto/Kconfig |
| 31 | @@ -684,6 +684,29 @@ choice |
| 32 | |
| 33 | endchoice |
| 34 | |
| 35 | +config CRYPTO_DEV_QCE_SW_MAX_LEN |
| 36 | + int "Default maximum request size to use software for AES" |
| 37 | + depends on CRYPTO_DEV_QCE && CRYPTO_DEV_QCE_SKCIPHER |
| 38 | + default 512 |
| 39 | + help |
| 40 | + This sets the default maximum request size to perform AES requests |
| 41 | + using software instead of the crypto engine. It can be changed by |
| 42 | + setting the aes_sw_max_len parameter. |
| 43 | + |
| 44 | + Small blocks are processed faster in software than hardware. |
| 45 | + Considering the 256-bit ciphers, software is 2-3 times faster than |
| 46 | + qce at 256-bytes, 30% faster at 512, and about even at 768-bytes. |
| 47 | + With 128-bit keys, the break-even point would be around 1024-bytes. |
| 48 | + |
| 49 | + The default is set a little lower, to 512 bytes, to balance the |
| 50 | + cost in CPU usage. The minimum recommended setting is 16-bytes |
| 51 | + (1 AES block), since AES-GCM will fail if you set it lower. |
| 52 | + Setting this to zero will send all requests to the hardware. |
| 53 | + |
| 54 | + Note that 192-bit keys are not supported by the hardware and are |
| 55 | + always processed by the software fallback, and all DES requests |
| 56 | + are done by the hardware. |
| 57 | + |
| 58 | config CRYPTO_DEV_QCOM_RNG |
| 59 | tristate "Qualcomm Random Number Generator Driver" |
| 60 | depends on ARCH_QCOM || COMPILE_TEST |
| 61 | --- a/drivers/crypto/qce/skcipher.c |
| 62 | +++ b/drivers/crypto/qce/skcipher.c |
| 63 | @@ -5,6 +5,7 @@ |
| 64 | |
| 65 | #include <linux/device.h> |
| 66 | #include <linux/interrupt.h> |
| 67 | +#include <linux/moduleparam.h> |
| 68 | #include <linux/types.h> |
| 69 | #include <crypto/aes.h> |
| 70 | #include <crypto/internal/des.h> |
| 71 | @@ -12,6 +13,13 @@ |
| 72 | |
| 73 | #include "cipher.h" |
| 74 | |
| 75 | +static unsigned int aes_sw_max_len = CONFIG_CRYPTO_DEV_QCE_SW_MAX_LEN; |
| 76 | +module_param(aes_sw_max_len, uint, 0644); |
| 77 | +MODULE_PARM_DESC(aes_sw_max_len, |
| 78 | + "Only use hardware for AES requests larger than this " |
| 79 | + "[0=always use hardware; anything <16 breaks AES-GCM; default=" |
| 80 | + __stringify(CONFIG_CRYPTO_DEV_QCE_SOFT_THRESHOLD)"]"); |
| 81 | + |
| 82 | static LIST_HEAD(skcipher_algs); |
| 83 | |
| 84 | static void qce_skcipher_done(void *data) |
| 85 | @@ -166,15 +174,10 @@ static int qce_skcipher_setkey(struct cr |
| 86 | switch (IS_XTS(flags) ? keylen >> 1 : keylen) { |
| 87 | case AES_KEYSIZE_128: |
| 88 | case AES_KEYSIZE_256: |
| 89 | + memcpy(ctx->enc_key, key, keylen); |
| 90 | break; |
| 91 | - default: |
| 92 | - goto fallback; |
| 93 | } |
| 94 | |
| 95 | - ctx->enc_keylen = keylen; |
| 96 | - memcpy(ctx->enc_key, key, keylen); |
| 97 | - return 0; |
| 98 | -fallback: |
| 99 | ret = crypto_sync_skcipher_setkey(ctx->fallback, key, keylen); |
| 100 | if (!ret) |
| 101 | ctx->enc_keylen = keylen; |
| 102 | @@ -224,8 +227,9 @@ static int qce_skcipher_crypt(struct skc |
| 103 | rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; |
| 104 | keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen; |
| 105 | |
| 106 | - if (IS_AES(rctx->flags) && keylen != AES_KEYSIZE_128 && |
| 107 | - keylen != AES_KEYSIZE_256) { |
| 108 | + if (IS_AES(rctx->flags) && |
| 109 | + ((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) || |
| 110 | + req->cryptlen <= aes_sw_max_len)) { |
| 111 | SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); |
| 112 | |
| 113 | skcipher_request_set_sync_tfm(subreq, ctx->fallback); |