[PATCH] hwrng: xilinx-trng: propagate timeout before any data is read

Jain, Harsh (AECG-SSW) h.jain at amd.com
Wed Jul 1 00:31:29 PDT 2026


AMD General

Reviewed-by : Harsh Jain <h.jain at amd.com>


> -----Original Message-----
> From: Pengpeng Hou <pengpeng at iscas.ac.cn>
> Sent: Tuesday, June 23, 2026 11:37 AM
> To: Botcha, Mounika <Mounika.Botcha at amd.com>; Jain, Harsh (AECG-SSW)
> <h.jain at amd.com>; Olivia Mackall <olivia at selenic.com>; Herbert Xu
> <herbert at gondor.apana.org.au>; Simek, Michal <michal.simek at amd.com>; linux-
> crypto at vger.kernel.org; linux-arm-kernel at lists.infradead.org; linux-
> kernel at vger.kernel.org
> Cc: Pengpeng Hou <pengpeng at iscas.ac.cn>
> Subject: [PATCH] hwrng: xilinx-trng: propagate timeout before any data is read
>
>
> xtrng_readblock32() polls for 16-byte chunks but returns the number of
> bytes read even when the first poll times out. Its caller then treats a
> zero return as a short successful read, and partial reads for full
> 32-byte blocks can make the tail copy use a fixed block offset rather
> than the amount already produced.
>
> Return the poll error when no data has been read, preserve partial
> positive returns after some data is available, stop the generator on all
> collection exits, and append tail bytes at the current output count.
>
> Signed-off-by: Pengpeng Hou <pengpeng at iscas.ac.cn>
> ---
>  drivers/char/hw_random/xilinx-trng.c | 32 +++++++++++++++++++++-------
>  1 file changed, 24 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/char/hw_random/xilinx-trng.c b/drivers/char/hw_random/xilinx-
> trng.c
> index f615d5adddde..4a1a168bb46a 100644
> --- a/drivers/char/hw_random/xilinx-trng.c
> +++ b/drivers/char/hw_random/xilinx-trng.c
> @@ -87,8 +87,8 @@ static void xtrng_softreset(struct xilinx_rng *rng)
>         xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET,
> TRNG_CTRL_PRNGSRST_MASK, 0);
>  }
>
> -/* Return no. of bytes read */
> -static size_t xtrng_readblock32(void __iomem *rng_base, __be32 *buf, int
> blocks32, bool wait)
> +/* Return no. of bytes read or a negative error before any data is read. */
> +static int xtrng_readblock32(void __iomem *rng_base, __be32 *buf, int blocks32,
> bool wait)
>  {
>         int read = 0, ret;
>         int timeout = 1;
> @@ -103,8 +103,11 @@ static size_t xtrng_readblock32(void __iomem *rng_base,
> __be32 *buf, int blocks3
>                 ret = readl_poll_timeout(rng_base + TRNG_STATUS_OFFSET, val,
>                                          (val & TRNG_STATUS_QCNT_MASK) ==
>                                          TRNG_STATUS_QCNT_16_BYTES, !!wait, timeout);
> -               if (ret)
> +               if (ret) {
> +                       if (!read)
> +                               return ret;
>                         break;
> +               }
>
>                 for (idx = 0; idx < TRNG_READ_4_WORD; idx++) {
>                         *(buf + read) = cpu_to_be32(ioread32(rng_base +
> TRNG_CORE_OUTPUT_OFFSET));
> @@ -119,27 +122,40 @@ static int xtrng_collect_random_data(struct xilinx_rng
> *rng, u8 *rand_gen_buf,
>  {
>         u8 randbuf[TRNG_SEC_STRENGTH_BYTES];
>         int byteleft, blocks, count = 0;
> +       int full_blocks_bytes;
>         int ret;
>
>         byteleft = no_of_random_bytes & (TRNG_SEC_STRENGTH_BYTES - 1);
>         blocks = no_of_random_bytes >> TRNG_SEC_STRENGTH_SHIFT;
> +       full_blocks_bytes = blocks * TRNG_SEC_STRENGTH_BYTES;
>         xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET,
> TRNG_CTRL_PRNGSTART_MASK,
>                           TRNG_CTRL_PRNGSTART_MASK);
>         if (blocks) {
>                 ret = xtrng_readblock32(rng->rng_base, (__be32 *)rand_gen_buf, blocks,
> wait);
> -               if (!ret)
> -                       return 0;
> +               if (ret <= 0) {
> +                       count = ret;
> +                       goto out_stop;
> +               }
>                 count += ret;
> +               if (ret < full_blocks_bytes)
> +                       goto out_stop;
>         }
>
>         if (byteleft) {
>                 ret = xtrng_readblock32(rng->rng_base, (__be32 *)randbuf, 1, wait);
> +               if (ret < 0) {
> +                       if (!count)
> +                               count = ret;
> +                       goto out_stop;
> +               }
>                 if (!ret)
> -                       return count;
> -               memcpy(rand_gen_buf + (blocks * TRNG_SEC_STRENGTH_BYTES),
> randbuf, byteleft);
> -               count += byteleft;
> +                       goto out_stop;
> +               ret = min(ret, no_of_random_bytes - count);
> +               memcpy(rand_gen_buf + count, randbuf, ret);
> +               count += ret;
>         }
>
> +out_stop:
>         xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET,
>                           TRNG_CTRL_PRNGMODE_MASK |
> TRNG_CTRL_PRNGSTART_MASK, 0U);
>
> --
> 2.50.1 (Apple Git-155)




More information about the linux-arm-kernel mailing list