From nobody Sun Feb 8 12:31:14 2026 Received: from canpmsgout09.his.huawei.com (canpmsgout09.his.huawei.com [113.46.200.224]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6B6D73328F0; Sat, 17 Jan 2026 07:18:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.224 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768634317; cv=none; b=SnZU+3m1Ff3sezAV1DTJAKM6DbMiaFMB67EPDhMpoMaZqJzU8iXDL++Opsf6WUlVit46QfI4/NKEfRUx5AtGel23HAxrooQ9G2ze1fttrMr9A9fLEOZgqYJMehviKiUXVG7Uh1S8yyrpQkcK9yGIznyhcPqVoZR+T3ZDuYDeNWU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768634317; c=relaxed/simple; bh=m7ypszcyRE+j1YfFwMEFgprbqnN23cBYMPVkoNZ5A64=; h=From:To:CC:Subject:Date:Message-ID:MIME-Version:Content-Type; b=j0rJ59NBlCi/MoQl1xW5P48AzK2BdQO0Xn0EdMNFLJ7Gp89Z1SbeDEWKxhHsWx4djrUuN6kfkXCyUO7rtlczYxnhhBT7Bo6iyCJxs9+faeT4fdmHAq7wEFoYQKpaT6MDPs53q2+acK4PIEwXulqXJiQQyFItfpYwtuuq67N2RdI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=InCCALc6; arc=none smtp.client-ip=113.46.200.224 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="InCCALc6" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=KP/QP16EL7Xb/a0ANgsfCcTf3hBNM79ugnxRANRcRjY=; b=InCCALc6eKas3ixqt908EA+NaCgQWneOy4Af3HTLFZAQPOnYC9bO1rerJ1e+uMxLi8T0Fvn20 UxyHy1gUhrDd8ptKMurQYlZdE4LG3kmwpVyhxlfM+snb6maI7cDOoEneZtS66ENXYBkFUiyL4He yNFEiQuGQ/ACHTdrLAK1SSc= Received: from mail.maildlp.com (unknown [172.19.163.200]) by canpmsgout09.his.huawei.com (SkyGuard) with ESMTPS id 4dtSfF6hYcz1cyNs; Sat, 17 Jan 2026 15:15:01 +0800 (CST) Received: from dggemv706-chm.china.huawei.com (unknown [10.3.19.33]) by mail.maildlp.com (Postfix) with ESMTPS id C11864055B; Sat, 17 Jan 2026 15:18:22 +0800 (CST) Received: from kwepemq200001.china.huawei.com (7.202.195.16) by dggemv706-chm.china.huawei.com (10.3.19.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Sat, 17 Jan 2026 15:18:22 +0800 Received: from localhost.huawei.com (10.90.31.46) by kwepemq200001.china.huawei.com (7.202.195.16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Sat, 17 Jan 2026 15:18:21 +0800 From: Chenghai Huang To: , CC: , , , , , Subject: [PATCH V2] crypto: hisilicon/trng - support tfms sharing the device Date: Sat, 17 Jan 2026 15:18:21 +0800 Message-ID: <20260117071821.1786428-1-huangchenghai2@huawei.com> X-Mailer: git-send-email 2.33.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems100001.china.huawei.com (7.221.188.238) To kwepemq200001.china.huawei.com (7.202.195.16) Content-Type: text/plain; charset="utf-8" From: Weili Qian 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 Signed-off-by: Chenghai Huang --- Changes in v2: - Move the device lock to the hisi_trng_generate(), unlock after generating a block of random numbers, to prevent one thread from hogging the lock. --- drivers/crypto/hisilicon/trng/trng.c | 121 +++++++++++++++++++-------- 1 file changed, 86 insertions(+), 35 deletions(-) diff --git a/drivers/crypto/hisilicon/trng/trng.c b/drivers/crypto/hisilico= n/trng/trng.c index ac74df4a9471..5ca0b90859a8 100644 --- a/drivers/crypto/hisilicon/trng/trng.c +++ b/drivers/crypto/hisilicon/trng/trng.c @@ -40,6 +40,7 @@ #define SEED_SHIFT_24 24 #define SEED_SHIFT_16 16 #define SEED_SHIFT_8 8 +#define SW_MAX_RANDOM_BYTES 65520 =20 struct hisi_trng_list { struct mutex lock; @@ -53,8 +54,10 @@ struct hisi_trng { struct list_head list; struct hwrng rng; u32 ver; - bool is_used; - struct mutex mutex; + u32 ctx_num; + /* The bytes of the random number generated since the last seeding. */ + u32 random_bytes; + struct mutex lock; }; =20 struct hisi_trng_ctx { @@ -63,10 +66,14 @@ struct hisi_trng_ctx { =20 static atomic_t trng_active_devs; static struct hisi_trng_list trng_devices; +static int hisi_trng_read(struct hwrng *rng, void *buf, size_t max, bool w= ait); =20 -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); =20 for (i =3D 0; i < SW_DRBG_SEED_SIZE; i +=3D SW_DRBG_SEED_SIZE / SW_DRBG_SEED_REGS_NUM) { @@ -78,6 +85,20 @@ static void hisi_trng_set_seed(struct hisi_trng *trng, c= onst u8 *seed) seed_reg =3D (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 =3D 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 =3D 0; + + return 0; } =20 static int hisi_trng_seed(struct crypto_rng *tfm, const u8 *seed, @@ -85,8 +106,7 @@ static int hisi_trng_seed(struct crypto_rng *tfm, const = u8 *seed, { struct hisi_trng_ctx *ctx =3D crypto_rng_ctx(tfm); struct hisi_trng *trng =3D ctx->trng; - u32 val =3D 0; - int ret =3D 0; + int ret; =20 if (slen < SW_DRBG_SEED_SIZE) { pr_err("slen(%u) is not matched with trng(%d)\n", slen, @@ -94,43 +114,45 @@ static int hisi_trng_seed(struct crypto_rng *tfm, cons= t u8 *seed, return -EINVAL; } =20 - writel(0x0, trng->base + SW_DRBG_BLOCKS); - hisi_trng_set_seed(trng, seed); + mutex_lock(&trng->lock); + ret =3D hisi_trng_set_seed(trng, seed); + mutex_unlock(&trng->lock); =20 - writel(SW_DRBG_BLOCKS_NUM | (0x1 << SW_DRBG_ENABLE_SHIFT), - trng->base + SW_DRBG_BLOCKS); - writel(0x1, trng->base + SW_DRBG_INIT); + return ret; +} =20 - ret =3D 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; =20 - return ret; + if (!trng->random_bytes) + return 0; + + size =3D hisi_trng_read(&trng->rng, seed, SW_DRBG_SEED_SIZE, false); + if (size !=3D SW_DRBG_SEED_SIZE) + return -EIO; + + return hisi_trng_set_seed(trng, seed); } =20 -static int hisi_trng_generate(struct crypto_rng *tfm, const u8 *src, - unsigned int slen, u8 *dstn, unsigned int dlen) +static int hisi_trng_get_bytes(struct hisi_trng *trng, u8 *dstn, unsigned = int dlen) { - struct hisi_trng_ctx *ctx =3D crypto_rng_ctx(tfm); - struct hisi_trng *trng =3D ctx->trng; u32 data[SW_DRBG_DATA_NUM]; u32 currsize =3D 0; u32 val =3D 0; int ret; u32 i; =20 - if (dlen > SW_DRBG_BLOCKS_NUM * SW_DRBG_BYTES || dlen =3D=3D 0) { - pr_err("dlen(%u) exceeds limit(%d)!\n", dlen, - SW_DRBG_BLOCKS_NUM * SW_DRBG_BYTES); - return -EINVAL; - } + ret =3D hisi_trng_reseed(trng); + if (ret) + return ret; =20 do { ret =3D 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; } =20 @@ -145,30 +167,57 @@ static int hisi_trng_generate(struct crypto_rng *tfm,= const u8 *src, currsize =3D dlen; } =20 + trng->random_bytes +=3D SW_DRBG_BYTES; writel(0x1, trng->base + SW_DRBG_GEN); } while (currsize < dlen); =20 return ret; } =20 +static int hisi_trng_generate(struct crypto_rng *tfm, const u8 *src, + unsigned int slen, u8 *dstn, unsigned int dlen) +{ + struct hisi_trng_ctx *ctx =3D crypto_rng_ctx(tfm); + struct hisi_trng *trng =3D ctx->trng; + unsigned int currsize =3D 0; + unsigned int block_size; + int ret; + + if (!dstn || !dlen) { + pr_err("output is error, dlen %u!\n", dlen); + return -EINVAL; + } + + do { + block_size =3D min_t(unsigned int, dlen - currsize, SW_MAX_RANDOM_BYTES); + mutex_lock(&trng->lock); + ret =3D hisi_trng_get_bytes(trng, dstn + currsize, block_size); + mutex_unlock(&trng->lock); + if (ret) + return ret; + currsize +=3D block_size; + } while (currsize < dlen); + + return 0; +} + static int hisi_trng_init(struct crypto_tfm *tfm) { struct hisi_trng_ctx *ctx =3D crypto_tfm_ctx(tfm); struct hisi_trng *trng; - int ret =3D -EBUSY; + u32 ctx_num =3D ~0; =20 mutex_lock(&trng_devices.lock); list_for_each_entry(trng, &trng_devices.list, list) { - if (!trng->is_used) { - trng->is_used =3D true; + if (trng->ctx_num < ctx_num) { + ctx_num =3D trng->ctx_num; ctx->trng =3D trng; - ret =3D 0; - break; } } + ctx->trng->ctx_num++; mutex_unlock(&trng_devices.lock); =20 - return ret; + return 0; } =20 static void hisi_trng_exit(struct crypto_tfm *tfm) @@ -176,7 +225,7 @@ static void hisi_trng_exit(struct crypto_tfm *tfm) struct hisi_trng_ctx *ctx =3D crypto_tfm_ctx(tfm); =20 mutex_lock(&trng_devices.lock); - ctx->trng->is_used =3D false; + ctx->trng->ctx_num--; mutex_unlock(&trng_devices.lock); } =20 @@ -238,7 +287,7 @@ static int hisi_trng_del_from_list(struct hisi_trng *tr= ng) int ret =3D -EBUSY; =20 mutex_lock(&trng_devices.lock); - if (!trng->is_used) { + if (!trng->ctx_num) { list_del(&trng->list); ret =3D 0; } @@ -262,7 +311,9 @@ static int hisi_trng_probe(struct platform_device *pdev) if (IS_ERR(trng->base)) return PTR_ERR(trng->base); =20 - trng->is_used =3D false; + trng->ctx_num =3D 0; + trng->random_bytes =3D SW_MAX_RANDOM_BYTES; + mutex_init(&trng->lock); trng->ver =3D readl(trng->base + HISI_TRNG_VERSION); if (!trng_devices.is_init) { INIT_LIST_HEAD(&trng_devices.list); --=20 2.43.0