* [PATCH 0/2] crypto: hisilicon/trng - support multiple tfms sharing the device
@ 2025-11-20 13:58 Chenghai Huang
2025-11-20 13:58 ` [PATCH 1/2] crypto: hisilicon/trng - use DEFINE_MUTEX() and LIST_HEAD() Chenghai Huang
2025-11-20 13:58 ` [PATCH 2/2] crypto: hisilicon/trng - support tfms sharing the device Chenghai Huang
0 siblings, 2 replies; 8+ messages in thread
From: Chenghai Huang @ 2025-11-20 13:58 UTC (permalink / raw)
To: herbert, davem
Cc: linux-kernel, linux-crypto, fanghao11, liulongfang, qianweili,
linwenkai6, wangzhou1
Patch 1: Uses DEFINE_MUTEX() and LIST_HEAD() to automatically
initialize locks and list heads instead of runtime initialization.
Patch 2: Supports multiple tfms sharing the device to avoid
tfm creation failure.
Weili Qian (2):
crypto: hisilicon/trng - use DEFINE_MUTEX() and LIST_HEAD()
crypto: hisilicon/trng - support tfms sharing the device
drivers/crypto/hisilicon/trng/trng.c | 200 ++++++++++++++++-----------
1 file changed, 116 insertions(+), 84 deletions(-)
--
2.33.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/2] crypto: hisilicon/trng - use DEFINE_MUTEX() and LIST_HEAD()
2025-11-20 13:58 [PATCH 0/2] crypto: hisilicon/trng - support multiple tfms sharing the device Chenghai Huang
@ 2025-11-20 13:58 ` Chenghai Huang
2025-12-19 3:04 ` Herbert Xu
2025-11-20 13:58 ` [PATCH 2/2] crypto: hisilicon/trng - support tfms sharing the device Chenghai Huang
1 sibling, 1 reply; 8+ messages in thread
From: Chenghai Huang @ 2025-11-20 13:58 UTC (permalink / raw)
To: herbert, davem
Cc: linux-kernel, linux-crypto, fanghao11, liulongfang, qianweili,
linwenkai6, wangzhou1
From: Weili Qian <qianweili@huawei.com>
Runtime initialization of lock and list head is not
reliable in a concurrent environment. Therefore, use
DEFINE_MUTEX() and LIST_HEAD() for automatic initialization.
And decide whether to register the algorithm to the crypto
subsystem based on whether the list is empty, instead of
using atomic operations.
Fixes: e4d9d10ef4be ("crypto: hisilicon/trng - add support for PRNG")
Signed-off-by: Weili Qian <qianweili@huawei.com>
Signed-off-by: Chenghai Huang <huangchenghai2@huawei.com>
---
drivers/crypto/hisilicon/trng/trng.c | 104 +++++++++++++--------------
1 file changed, 48 insertions(+), 56 deletions(-)
diff --git a/drivers/crypto/hisilicon/trng/trng.c b/drivers/crypto/hisilicon/trng/trng.c
index ac74df4a9471..dae81b6f43e3 100644
--- a/drivers/crypto/hisilicon/trng/trng.c
+++ b/drivers/crypto/hisilicon/trng/trng.c
@@ -40,16 +40,10 @@
#define SEED_SHIFT_24 24
#define SEED_SHIFT_16 16
#define SEED_SHIFT_8 8
-
-struct hisi_trng_list {
- struct mutex lock;
- struct list_head list;
- bool is_init;
-};
+#define WAIT_PERIOD 20
struct hisi_trng {
void __iomem *base;
- struct hisi_trng_list *trng_list;
struct list_head list;
struct hwrng rng;
u32 ver;
@@ -61,8 +55,8 @@ struct hisi_trng_ctx {
struct hisi_trng *trng;
};
-static atomic_t trng_active_devs;
-static struct hisi_trng_list trng_devices;
+static LIST_HEAD(trng_devices_list);
+static DEFINE_MUTEX(trng_device_lock);
static void hisi_trng_set_seed(struct hisi_trng *trng, const u8 *seed)
{
@@ -157,8 +151,8 @@ static int hisi_trng_init(struct crypto_tfm *tfm)
struct hisi_trng *trng;
int ret = -EBUSY;
- mutex_lock(&trng_devices.lock);
- list_for_each_entry(trng, &trng_devices.list, list) {
+ mutex_lock(&trng_device_lock);
+ list_for_each_entry(trng, &trng_devices_list, list) {
if (!trng->is_used) {
trng->is_used = true;
ctx->trng = trng;
@@ -166,7 +160,7 @@ static int hisi_trng_init(struct crypto_tfm *tfm)
break;
}
}
- mutex_unlock(&trng_devices.lock);
+ mutex_unlock(&trng_device_lock);
return ret;
}
@@ -175,9 +169,9 @@ static void hisi_trng_exit(struct crypto_tfm *tfm)
{
struct hisi_trng_ctx *ctx = crypto_tfm_ctx(tfm);
- mutex_lock(&trng_devices.lock);
+ mutex_lock(&trng_device_lock);
ctx->trng->is_used = false;
- mutex_unlock(&trng_devices.lock);
+ mutex_unlock(&trng_device_lock);
}
static int hisi_trng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
@@ -226,24 +220,43 @@ static struct rng_alg hisi_trng_alg = {
},
};
-static void hisi_trng_add_to_list(struct hisi_trng *trng)
+static int hisi_trng_crypto_register(struct hisi_trng *trng)
{
- mutex_lock(&trng_devices.lock);
- list_add_tail(&trng->list, &trng_devices.list);
- mutex_unlock(&trng_devices.lock);
+ int ret = 0;
+
+ mutex_lock(&trng_device_lock);
+ if (trng->ver != HISI_TRNG_VER_V1 &&
+ list_empty(&trng_devices_list)) {
+ ret = crypto_register_rng(&hisi_trng_alg);
+ if (ret) {
+ pr_err("failed to register crypto(%d)\n", ret);
+ goto unlock;
+ }
+ }
+
+ list_add_tail(&trng->list, &trng_devices_list);
+unlock:
+ mutex_unlock(&trng_device_lock);
+ return ret;
}
-static int hisi_trng_del_from_list(struct hisi_trng *trng)
+static int hisi_trng_crypto_unregister(struct hisi_trng *trng)
{
int ret = -EBUSY;
- mutex_lock(&trng_devices.lock);
- if (!trng->is_used) {
- list_del(&trng->list);
- ret = 0;
- }
- mutex_unlock(&trng_devices.lock);
+ mutex_lock(&trng_device_lock);
+ if (trng->is_used)
+ goto unlock;
+
+ list_del(&trng->list);
+ if (trng->ver != HISI_TRNG_VER_V1 &&
+ list_empty(&trng_devices_list))
+ crypto_unregister_rng(&hisi_trng_alg);
+ ret = 0;
+
+unlock:
+ mutex_unlock(&trng_device_lock);
return ret;
}
@@ -264,23 +277,9 @@ static int hisi_trng_probe(struct platform_device *pdev)
trng->is_used = false;
trng->ver = readl(trng->base + HISI_TRNG_VERSION);
- if (!trng_devices.is_init) {
- INIT_LIST_HEAD(&trng_devices.list);
- mutex_init(&trng_devices.lock);
- trng_devices.is_init = true;
- }
-
- hisi_trng_add_to_list(trng);
- if (trng->ver != HISI_TRNG_VER_V1 &&
- atomic_inc_return(&trng_active_devs) == 1) {
- ret = crypto_register_rng(&hisi_trng_alg);
- if (ret) {
- dev_err(&pdev->dev,
- "failed to register crypto(%d)\n", ret);
- atomic_dec_return(&trng_active_devs);
- goto err_remove_from_list;
- }
- }
+ ret = hisi_trng_crypto_register(trng);
+ if (ret)
+ return ret;
trng->rng.name = pdev->name;
trng->rng.read = hisi_trng_read;
@@ -288,18 +287,13 @@ static int hisi_trng_probe(struct platform_device *pdev)
ret = devm_hwrng_register(&pdev->dev, &trng->rng);
if (ret) {
dev_err(&pdev->dev, "failed to register hwrng: %d!\n", ret);
- goto err_crypto_unregister;
+ goto unregister_crypto;
}
return ret;
-err_crypto_unregister:
- if (trng->ver != HISI_TRNG_VER_V1 &&
- atomic_dec_return(&trng_active_devs) == 0)
- crypto_unregister_rng(&hisi_trng_alg);
-
-err_remove_from_list:
- hisi_trng_del_from_list(trng);
+unregister_crypto:
+ hisi_trng_crypto_unregister(trng);
return ret;
}
@@ -308,12 +302,10 @@ static void hisi_trng_remove(struct platform_device *pdev)
struct hisi_trng *trng = platform_get_drvdata(pdev);
/* Wait until the task is finished */
- while (hisi_trng_del_from_list(trng))
- ;
-
- if (trng->ver != HISI_TRNG_VER_V1 &&
- atomic_dec_return(&trng_active_devs) == 0)
- crypto_unregister_rng(&hisi_trng_alg);
+ while (hisi_trng_crypto_unregister(trng)) {
+ dev_info(&pdev->dev, "trng is in using!\n");
+ msleep(WAIT_PERIOD);
+ }
}
static const struct acpi_device_id hisi_trng_acpi_match[] = {
--
2.33.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2/2] crypto: hisilicon/trng - support tfms sharing the device
2025-11-20 13:58 [PATCH 0/2] crypto: hisilicon/trng - support multiple tfms sharing the device Chenghai Huang
2025-11-20 13:58 ` [PATCH 1/2] crypto: hisilicon/trng - use DEFINE_MUTEX() and LIST_HEAD() Chenghai Huang
@ 2025-11-20 13:58 ` Chenghai Huang
2025-12-19 3:06 ` Herbert Xu
1 sibling, 1 reply; 8+ messages in thread
From: Chenghai Huang @ 2025-11-20 13:58 UTC (permalink / raw)
To: herbert, davem
Cc: linux-kernel, linux-crypto, fanghao11, liulongfang, qianweili,
linwenkai6, wangzhou1
From: Weili Qian <qianweili@huawei.com>
Since the number of devices is limited, and the number
of tfms may exceed the number of devices, to ensure that
tfms can be successfully allocated, support tfms
sharing the same device.
Fixes: e4d9d10ef4be ("crypto: hisilicon/trng - add support for PRNG")
Signed-off-by: Weili Qian <qianweili@huawei.com>
Signed-off-by: Chenghai Huang <huangchenghai2@huawei.com>
---
drivers/crypto/hisilicon/trng/trng.c | 98 ++++++++++++++++++++--------
1 file changed, 69 insertions(+), 29 deletions(-)
diff --git a/drivers/crypto/hisilicon/trng/trng.c b/drivers/crypto/hisilicon/trng/trng.c
index dae81b6f43e3..4dcb3398e020 100644
--- a/drivers/crypto/hisilicon/trng/trng.c
+++ b/drivers/crypto/hisilicon/trng/trng.c
@@ -41,14 +41,16 @@
#define SEED_SHIFT_16 16
#define SEED_SHIFT_8 8
#define WAIT_PERIOD 20
+#define SW_MAX_RANDOM_BYTES 65520
struct hisi_trng {
void __iomem *base;
struct list_head list;
struct hwrng rng;
u32 ver;
- bool is_used;
- struct mutex mutex;
+ u32 ctx_num;
+ u32 random_bytes;
+ struct mutex lock;
};
struct hisi_trng_ctx {
@@ -57,10 +59,14 @@ struct hisi_trng_ctx {
static LIST_HEAD(trng_devices_list);
static DEFINE_MUTEX(trng_device_lock);
+static int hisi_trng_read(struct hwrng *rng, void *buf, size_t max, bool wait);
-static void hisi_trng_set_seed(struct hisi_trng *trng, const u8 *seed)
+static int hisi_trng_set_seed(struct hisi_trng *trng, const u8 *seed)
{
u32 val, seed_reg, i;
+ int ret;
+
+ writel(0x0, trng->base + SW_DRBG_BLOCKS);
for (i = 0; i < SW_DRBG_SEED_SIZE;
i += SW_DRBG_SEED_SIZE / SW_DRBG_SEED_REGS_NUM) {
@@ -72,6 +78,20 @@ static void hisi_trng_set_seed(struct hisi_trng *trng, const u8 *seed)
seed_reg = (i >> SW_DRBG_NUM_SHIFT) % SW_DRBG_SEED_REGS_NUM;
writel(val, trng->base + SW_DRBG_SEED(seed_reg));
}
+
+ writel(SW_DRBG_BLOCKS_NUM | (0x1 << SW_DRBG_ENABLE_SHIFT),
+ trng->base + SW_DRBG_BLOCKS);
+ writel(0x1, trng->base + SW_DRBG_INIT);
+ ret = readl_relaxed_poll_timeout(trng->base + SW_DRBG_STATUS,
+ val, val & BIT(0), SLEEP_US, TIMEOUT_US);
+ if (ret) {
+ pr_err("failed to init trng(%d)\n", ret);
+ return -EIO;
+ }
+
+ trng->random_bytes = 0;
+
+ return 0;
}
static int hisi_trng_seed(struct crypto_rng *tfm, const u8 *seed,
@@ -79,8 +99,7 @@ static int hisi_trng_seed(struct crypto_rng *tfm, const u8 *seed,
{
struct hisi_trng_ctx *ctx = crypto_rng_ctx(tfm);
struct hisi_trng *trng = ctx->trng;
- u32 val = 0;
- int ret = 0;
+ int ret;
if (slen < SW_DRBG_SEED_SIZE) {
pr_err("slen(%u) is not matched with trng(%d)\n", slen,
@@ -88,19 +107,30 @@ static int hisi_trng_seed(struct crypto_rng *tfm, const u8 *seed,
return -EINVAL;
}
- writel(0x0, trng->base + SW_DRBG_BLOCKS);
- hisi_trng_set_seed(trng, seed);
+ mutex_lock(&trng->lock);
+ ret = hisi_trng_set_seed(trng, seed);
+ mutex_unlock(&trng->lock);
- writel(SW_DRBG_BLOCKS_NUM | (0x1 << SW_DRBG_ENABLE_SHIFT),
- trng->base + SW_DRBG_BLOCKS);
- writel(0x1, trng->base + SW_DRBG_INIT);
+ return ret;
+}
- ret = readl_relaxed_poll_timeout(trng->base + SW_DRBG_STATUS,
- val, val & BIT(0), SLEEP_US, TIMEOUT_US);
- if (ret)
- pr_err("fail to init trng(%d)\n", ret);
+static int hisi_trng_reseed(struct hisi_trng *trng)
+{
+ u8 seed[SW_DRBG_SEED_SIZE];
+ int size;
- return ret;
+ /* Allow other threads to acquire the lock and execute their jobs. */
+ mutex_unlock(&trng->lock);
+ mutex_lock(&trng->lock);
+
+ if (trng->random_bytes < SW_MAX_RANDOM_BYTES)
+ return 0;
+
+ size = hisi_trng_read(&trng->rng, seed, SW_DRBG_SEED_SIZE, false);
+ if (size != SW_DRBG_SEED_SIZE)
+ return -EIO;
+
+ return hisi_trng_set_seed(trng, seed);
}
static int hisi_trng_generate(struct crypto_rng *tfm, const u8 *src,
@@ -114,17 +144,23 @@ static int hisi_trng_generate(struct crypto_rng *tfm, const u8 *src,
int ret;
u32 i;
- if (dlen > SW_DRBG_BLOCKS_NUM * SW_DRBG_BYTES || dlen == 0) {
- pr_err("dlen(%u) exceeds limit(%d)!\n", dlen,
- SW_DRBG_BLOCKS_NUM * SW_DRBG_BYTES);
+ if (!dstn || !dlen) {
+ pr_err("output is error, dlen %u !\n", dlen);
return -EINVAL;
}
+ mutex_lock(&trng->lock);
do {
+ if (trng->random_bytes >= SW_MAX_RANDOM_BYTES) {
+ ret = hisi_trng_reseed(trng);
+ if (ret)
+ break;
+ }
+
ret = readl_relaxed_poll_timeout(trng->base + SW_DRBG_STATUS,
- val, val & BIT(1), SLEEP_US, TIMEOUT_US);
+ val, val & BIT(1), SLEEP_US, TIMEOUT_US);
if (ret) {
- pr_err("fail to generate random number(%d)!\n", ret);
+ pr_err("failed to generate random number(%d)!\n", ret);
break;
}
@@ -139,9 +175,12 @@ static int hisi_trng_generate(struct crypto_rng *tfm, const u8 *src,
currsize = dlen;
}
+ trng->random_bytes += SW_DRBG_BYTES;
writel(0x1, trng->base + SW_DRBG_GEN);
} while (currsize < dlen);
+ mutex_unlock(&trng->lock);
+
return ret;
}
@@ -149,20 +188,19 @@ static int hisi_trng_init(struct crypto_tfm *tfm)
{
struct hisi_trng_ctx *ctx = crypto_tfm_ctx(tfm);
struct hisi_trng *trng;
- int ret = -EBUSY;
+ u32 ctx_num = ~0;
mutex_lock(&trng_device_lock);
list_for_each_entry(trng, &trng_devices_list, list) {
- if (!trng->is_used) {
- trng->is_used = true;
+ if (trng->ctx_num < ctx_num) {
+ ctx_num = trng->ctx_num;
ctx->trng = trng;
- ret = 0;
- break;
}
}
+ ctx->trng->ctx_num++;
mutex_unlock(&trng_device_lock);
- return ret;
+ return 0;
}
static void hisi_trng_exit(struct crypto_tfm *tfm)
@@ -170,7 +208,7 @@ static void hisi_trng_exit(struct crypto_tfm *tfm)
struct hisi_trng_ctx *ctx = crypto_tfm_ctx(tfm);
mutex_lock(&trng_device_lock);
- ctx->trng->is_used = false;
+ ctx->trng->ctx_num--;
mutex_unlock(&trng_device_lock);
}
@@ -245,7 +283,7 @@ static int hisi_trng_crypto_unregister(struct hisi_trng *trng)
int ret = -EBUSY;
mutex_lock(&trng_device_lock);
- if (trng->is_used)
+ if (trng->ctx_num)
goto unlock;
list_del(&trng->list);
@@ -275,7 +313,9 @@ static int hisi_trng_probe(struct platform_device *pdev)
if (IS_ERR(trng->base))
return PTR_ERR(trng->base);
- trng->is_used = false;
+ trng->ctx_num = 0;
+ trng->random_bytes = SW_MAX_RANDOM_BYTES;
+ mutex_init(&trng->lock);
trng->ver = readl(trng->base + HISI_TRNG_VERSION);
ret = hisi_trng_crypto_register(trng);
if (ret)
--
2.33.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] crypto: hisilicon/trng - use DEFINE_MUTEX() and LIST_HEAD()
2025-11-20 13:58 ` [PATCH 1/2] crypto: hisilicon/trng - use DEFINE_MUTEX() and LIST_HEAD() Chenghai Huang
@ 2025-12-19 3:04 ` Herbert Xu
2025-12-22 6:10 ` huangchenghai
0 siblings, 1 reply; 8+ messages in thread
From: Herbert Xu @ 2025-12-19 3:04 UTC (permalink / raw)
To: Chenghai Huang
Cc: davem, linux-kernel, linux-crypto, fanghao11, liulongfang,
qianweili, linwenkai6, wangzhou1
On Thu, Nov 20, 2025 at 09:58:11PM +0800, Chenghai Huang wrote:
>
> @@ -308,12 +302,10 @@ static void hisi_trng_remove(struct platform_device *pdev)
> struct hisi_trng *trng = platform_get_drvdata(pdev);
>
> /* Wait until the task is finished */
> - while (hisi_trng_del_from_list(trng))
> - ;
> -
> - if (trng->ver != HISI_TRNG_VER_V1 &&
> - atomic_dec_return(&trng_active_devs) == 0)
> - crypto_unregister_rng(&hisi_trng_alg);
> + while (hisi_trng_crypto_unregister(trng)) {
> + dev_info(&pdev->dev, "trng is in using!\n");
> + msleep(WAIT_PERIOD);
> + }
Please use the new CRYPTO_ALG_DUP_FIRST flag to let the Crypto API
deal with reference count tracking. With that, you should be able
to unregister the RNG even if there are still tfms using it.
The RNG will be freed after all tfms using it are freed.
Of course you should create a way to mark the trng as dead so
that the hisi_trng_generate returns an error instead of trying
to read from the non-existant RNG.
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/2] crypto: hisilicon/trng - support tfms sharing the device
2025-11-20 13:58 ` [PATCH 2/2] crypto: hisilicon/trng - support tfms sharing the device Chenghai Huang
@ 2025-12-19 3:06 ` Herbert Xu
2025-12-22 3:36 ` huangchenghai
0 siblings, 1 reply; 8+ messages in thread
From: Herbert Xu @ 2025-12-19 3:06 UTC (permalink / raw)
To: Chenghai Huang
Cc: davem, linux-kernel, linux-crypto, fanghao11, liulongfang,
qianweili, linwenkai6, wangzhou1
On Thu, Nov 20, 2025 at 09:58:12PM +0800, Chenghai Huang wrote:
>
> +static int hisi_trng_reseed(struct hisi_trng *trng)
> +{
> + u8 seed[SW_DRBG_SEED_SIZE];
> + int size;
>
> - return ret;
> + /* Allow other threads to acquire the lock and execute their jobs. */
> + mutex_unlock(&trng->lock);
> + mutex_lock(&trng->lock);
If we have a bunch threads doing generate, then they will all hit
reseed and end up here for no reason at all.
If you want to stop one thread from hogging the lock, perhaps move
it inside the read loop in hisi_trng_generate?
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/2] crypto: hisilicon/trng - support tfms sharing the device
2025-12-19 3:06 ` Herbert Xu
@ 2025-12-22 3:36 ` huangchenghai
0 siblings, 0 replies; 8+ messages in thread
From: huangchenghai @ 2025-12-22 3:36 UTC (permalink / raw)
To: Herbert Xu
Cc: davem, linux-kernel, linux-crypto, fanghao11, liulongfang,
qianweili, linwenkai6, wangzhou1
在 2025/12/19 11:06, Herbert Xu 写道:
> On Thu, Nov 20, 2025 at 09:58:12PM +0800, Chenghai Huang wrote:
>> +static int hisi_trng_reseed(struct hisi_trng *trng)
>> +{
>> + u8 seed[SW_DRBG_SEED_SIZE];
>> + int size;
>>
>> - return ret;
>> + /* Allow other threads to acquire the lock and execute their jobs. */
>> + mutex_unlock(&trng->lock);
>> + mutex_lock(&trng->lock);
> If we have a bunch threads doing generate, then they will all hit
> reseed and end up here for no reason at all.
>
> If you want to stop one thread from hogging the lock, perhaps move
> it inside the read loop in hisi_trng_generate?
>
> Cheers,
Okay, I will move the lock inside the read loop in hisi_trng_generate.
Thanks,
Chenghai
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] crypto: hisilicon/trng - use DEFINE_MUTEX() and LIST_HEAD()
2025-12-19 3:04 ` Herbert Xu
@ 2025-12-22 6:10 ` huangchenghai
2025-12-24 2:49 ` Herbert Xu
0 siblings, 1 reply; 8+ messages in thread
From: huangchenghai @ 2025-12-22 6:10 UTC (permalink / raw)
To: Herbert Xu
Cc: davem, linux-kernel, linux-crypto, fanghao11, liulongfang,
qianweili, linwenkai6, wangzhou1
在 2025/12/19 11:04, Herbert Xu 写道:
> On Thu, Nov 20, 2025 at 09:58:11PM +0800, Chenghai Huang wrote:
>> @@ -308,12 +302,10 @@ static void hisi_trng_remove(struct platform_device *pdev)
>> struct hisi_trng *trng = platform_get_drvdata(pdev);
>>
>> /* Wait until the task is finished */
>> - while (hisi_trng_del_from_list(trng))
>> - ;
>> -
>> - if (trng->ver != HISI_TRNG_VER_V1 &&
>> - atomic_dec_return(&trng_active_devs) == 0)
>> - crypto_unregister_rng(&hisi_trng_alg);
>> + while (hisi_trng_crypto_unregister(trng)) {
>> + dev_info(&pdev->dev, "trng is in using!\n");
>> + msleep(WAIT_PERIOD);
>> + }
> Please use the new CRYPTO_ALG_DUP_FIRST flag to let the Crypto API
> deal with reference count tracking. With that, you should be able
> to unregister the RNG even if there are still tfms using it.
>
> The RNG will be freed after all tfms using it are freed.
>
> Of course you should create a way to mark the trng as dead so
> that the hisi_trng_generate returns an error instead of trying
> to read from the non-existant RNG.
>
> Cheers,
I tried to solve this scenario by adding CRYPTO_ALG_DUP_FIRST:
diff --git a/drivers/crypto/hisilicon/trng/trng.c
b/drivers/crypto/hisilicon/trng/trng.c
index ac74df4a9471..8baf0c959c29 100644
--- a/drivers/crypto/hisilicon/trng/trng.c
+++ b/drivers/crypto/hisilicon/trng/trng.c
@@ -218,6 +218,7 @@ static struct rng_alg hisi_trng_alg = {
.base = {
.cra_name = "stdrng",
.cra_driver_name = "hisi_stdrng",
+ .cra_flags = CRYPTO_ALG_DUP_FIRST,
.cra_priority = 300,
.cra_ctxsize = sizeof(struct hisi_trng_ctx),
.cra_module = THIS_MODULE,
but encountered a NULL pointer issue when unregistering the algorithm.
The log is as follows:
[ 621.533583] Unable to handle kernel NULL pointer dereference at
virtual address 0000000000000008
[ 621.533585] Mem abort info:
[ 621.533586] ESR = 0x0000000096000044
[ 621.533587] EC = 0x25: DABT (current EL), IL = 32 bits
[ 621.533589] SET = 0, FnV = 0
[ 621.533590] EA = 0, S1PTW = 0
[ 621.533591] FSC = 0x04: level 0 translation fault
[ 621.533592] Data abort info:
[ 621.533593] ISV = 0, ISS = 0x00000044, ISS2 = 0x00000000
[ 621.533595] CM = 0, WnR = 1, TnD = 0, TagAccess = 0
[ 621.533596] GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
[ 621.533597] user pgtable: 4k pages, 48-bit VAs, pgdp=0000082809aa9000
[ 621.533599] [0000000000000008] pgd=0000000000000000, p4d=0000000000000000
[ 621.533603] Internal error: Oops: 0000000096000044 [#1] SMP
[ 621.535681] Modules linked in: af_alg rfkill ipmi_si ipmi_devintf
tpm_tis_spi arm_spe_pmu arm_smmuv3_pmu ipmi_ms ghandler tpm_tis_core
coresight_tmc coresight_funnel coresight cppc_cpufreq fuse drm backlight
hisi_hpre dh_generic ecdh_generic hisi_sec2 hisi_zip ecc sm3_ce hisi_qm
spi_dw_mmio sha3_ce authenc uacce spidev hisi_trng_v2(-) spi_dw dm_mod ipv6
[ 621.649900] CPU: 0 UID: 0 PID: 9267 Comm: rmmod Kdump: loaded Not
tainted 6.18.0-rc1-gd633730bb387-dirty #11 PRE EMPT
[ 621.660494] Hardware name: To be filled by O.E.M. To be filled by
O.E.M./To be filled by O.E.M., BIOS HixxxxEVB V3.4.1 07/31/2025
[ 621.672127] pstate: a1400009 (NzCv daif +PAN -UAO -TCO +DIT -SSBS
BTYPE=--)
[ 621.679075] pc : crypto_unregister_alg+0x6c/0x110
[ 621.683772] lr : crypto_unregister_alg+0x44/0x110
[ 621.688462] sp : ffff8000a6a4bc00
[ 621.691763] x29: ffff8000a6a4bc20 x28: ffff08209bb08000 x27:
0000000000000000
[ 621.698885] x26: 0000000000000000 x25: 0000000000000000 x24:
0000000000000000
[ 621.706008] x23: ffffb1ce18b79fa0 x22: ffff082085e77490 x21:
ffffb1ce1885d100
[ 621.713130] x20: ffff8000a6a4bc08 x19: ffffb1cde59ed0e8 x18:
ffffb1ce18d150f0
[ 621.720251] x17: 6c703d4d45545359 x16: ffffb1ce16334988 x15:
0000000000000030
[ 621.727374] x14: 0000000000000004 x13: ffff082f97540000 x12:
0000000000001a9d
[ 621.734496] x11: 00000000000008df x10: ffff082f97800000 x9 :
ffff082f97540000
[ 621.741619] x8 : 00000000ffff7fff x7 : ffff082f97800000 x6 :
80000000ffff8000
[ 621.748741] x5 : 0000000000000000 x4 : 0000000000000000 x3 :
000000000000022c
[ 621.755863] x2 : 0000000000000000 x1 : ffff8000a6a4bc08 x0 :
ffffb1cde59ed0e8
[ 621.762986] Call trace:
[ 621.765419] crypto_unregister_alg+0x6c/0x110 (P)
[ 621.770110] crypto_unregister_rng+0x14/0x20
[ 621.774369] hisi_trng_remove+0x98/0xd8 [hisi_trng_v2]
[ 621.779495] platform_remove+0x20/0x30
[ 621.783233] device_remove+0x4c/0x80
[ 621.786797] device_release_driver_internal+0x1c8/0x224
[ 621.792009] driver_detach+0x4c/0x98
[ 621.795570] bus_remove_driver+0x6c/0xbc
[ 621.799480] driver_unregister+0x30/0x60
[ 621.803389] platform_driver_unregister+0x14/0x20
[ 621.808080] hisi_trng_driver_exit+0x18/0x794 [hisi_trng_v2]
[ 621.813725] __arm64_sys_delete_module+0x1c0/0x29c
[ 621.818505] invoke_syscall+0x48/0x10c
[ 621.822244] el0_svc_common.constprop.0+0xc0/0xe0
[ 621.826936] do_el0_svc+0x1c/0x28
[ 621.830239] el0_svc+0x34/0xec
[ 621.833283] el0t_64_sync_handler+0xa0/0xe4
[ 621.837453] el0t_64_sync+0x198/0x19c
[ 621.841104] Code: d2800002 aa1303e0 321b0063 b9002263 (f90004a4)
[ 621.847182] ---[ end trace 0000000000000000 ]---
[ 622.007363] pstore: backend (efi_pstore) writing error (-28)
faddr2line analysis indicates the error points to:
crypto_unregister_alg+0x6c/0x110:
__list_del at cryptodev-2.6/./include/linux/list.h:203
(inlined by) __list_del_entry at cryptodev-2.6/./include/linux/list.h:226
(inlined by) list_del_init at cryptodev-2.6/./include/linux/list.h:295
(inlined by) crypto_remove_alg at cryptodev-2.6/crypto/algapi.c:483
(inlined by) crypto_unregister_alg at cryptodev-2.6/crypto/algapi.c:495
The algorithm is duplicated by kmemdup before registration.
Should the duplicated algorithm be used during unregistration instead of
the one passed by the driver?
Regards,
Chenghai
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] crypto: hisilicon/trng - use DEFINE_MUTEX() and LIST_HEAD()
2025-12-22 6:10 ` huangchenghai
@ 2025-12-24 2:49 ` Herbert Xu
0 siblings, 0 replies; 8+ messages in thread
From: Herbert Xu @ 2025-12-24 2:49 UTC (permalink / raw)
To: huangchenghai
Cc: davem, linux-kernel, linux-crypto, fanghao11, liulongfang,
qianweili, linwenkai6, wangzhou1
On Mon, Dec 22, 2025 at 02:10:32PM +0800, huangchenghai wrote:
>
> I tried to solve this scenario by adding CRYPTO_ALG_DUP_FIRST:
You're right that it's broken. Either the duplication needs to be
moved to the driver, or the unregistration needs to find the
duplicated algorithm.
Let me fix this up first.
Thanks,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2025-12-24 2:49 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-11-20 13:58 [PATCH 0/2] crypto: hisilicon/trng - support multiple tfms sharing the device Chenghai Huang
2025-11-20 13:58 ` [PATCH 1/2] crypto: hisilicon/trng - use DEFINE_MUTEX() and LIST_HEAD() Chenghai Huang
2025-12-19 3:04 ` Herbert Xu
2025-12-22 6:10 ` huangchenghai
2025-12-24 2:49 ` Herbert Xu
2025-11-20 13:58 ` [PATCH 2/2] crypto: hisilicon/trng - support tfms sharing the device Chenghai Huang
2025-12-19 3:06 ` Herbert Xu
2025-12-22 3:36 ` huangchenghai
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®