From: Alexander Sverdlin Date: Wed, 6 Nov 2019 09:30:49 +0000 (+0000) Subject: hwrng: ks-sa - Add minimum sleep time before ready-polling X-Git-Tag: baikal/mips/sdk5.9~14900^2~105 X-Git-Url: https://git.baikalelectronics.ru/sdk/?a=commitdiff_plain;h=641aee37fcbab1fb704e7e5180fcdeb3c17cc50d;p=kernel.git hwrng: ks-sa - Add minimum sleep time before ready-polling Current polling timeout is 25 us. The hardware is currently configured to harvest the entropy for 81920 us. This leads to timeouts even during blocking read (wait=1). Log snippet: [ 5.727589] [] (ks_sa_rng_probe) from [] (platform_drv_probe+0x58/0xb4) ... [ 5.727805] hwrng: no data available ... [ 13.157016] random: systemd: uninitialized urandom read (16 bytes read) [ 13.157033] systemd[1]: Initializing machine ID from random generator. ... [ 15.848770] random: fast init done ... [ 15.848807] random: crng init done After the patch: [ 6.223534] random: systemd: uninitialized urandom read (16 bytes read) [ 6.223551] systemd[1]: Initializing machine ID from random generator. ... [ 6.876075] random: fast init done ... [ 6.954200] random: systemd: uninitialized urandom read (16 bytes read) [ 6.955244] random: systemd: uninitialized urandom read (16 bytes read) ... [ 7.121948] random: crng init done Signed-off-by: Alexander Sverdlin Signed-off-by: Herbert Xu --- diff --git a/drivers/char/hw_random/ks-sa-rng.c b/drivers/char/hw_random/ks-sa-rng.c index 3dbd6b7a65f05..e2330e757f1ff 100644 --- a/drivers/char/hw_random/ks-sa-rng.c +++ b/drivers/char/hw_random/ks-sa-rng.c @@ -21,6 +21,7 @@ #include #include #include +#include #define SA_CMD_STATUS_OFS 0x8 @@ -85,13 +86,36 @@ struct ks_sa_rng { struct clk *clk; struct regmap *regmap_cfg; struct trng_regs __iomem *reg_rng; + u64 ready_ts; + unsigned int refill_delay_ns; }; +static unsigned int cycles_to_ns(unsigned long clk_rate, unsigned int cycles) +{ + return DIV_ROUND_UP_ULL((TRNG_DEF_CLK_DIV_CYCLES + 1) * 1000000000ull * + cycles, clk_rate); +} + +static unsigned int startup_delay_ns(unsigned long clk_rate) +{ + if (!TRNG_DEF_STARTUP_CYCLES) + return cycles_to_ns(clk_rate, BIT(24)); + return cycles_to_ns(clk_rate, 256 * TRNG_DEF_STARTUP_CYCLES); +} + +static unsigned int refill_delay_ns(unsigned long clk_rate) +{ + if (!TRNG_DEF_MAX_REFILL_CYCLES) + return cycles_to_ns(clk_rate, BIT(24)); + return cycles_to_ns(clk_rate, 256 * TRNG_DEF_MAX_REFILL_CYCLES); +} + static int ks_sa_rng_init(struct hwrng *rng) { u32 value; struct device *dev = (struct device *)rng->priv; struct ks_sa_rng *ks_sa_rng = dev_get_drvdata(dev); + unsigned long clk_rate = clk_get_rate(ks_sa_rng->clk); /* Enable RNG module */ regmap_write_bits(ks_sa_rng->regmap_cfg, SA_CMD_STATUS_OFS, @@ -120,6 +144,10 @@ static int ks_sa_rng_init(struct hwrng *rng) value |= TRNG_CNTL_REG_TRNG_ENABLE; writel(value, &ks_sa_rng->reg_rng->control); + ks_sa_rng->refill_delay_ns = refill_delay_ns(clk_rate); + ks_sa_rng->ready_ts = ktime_get_ns() + + startup_delay_ns(clk_rate); + return 0; } @@ -144,6 +172,7 @@ static int ks_sa_rng_data_read(struct hwrng *rng, u32 *data) data[1] = readl(&ks_sa_rng->reg_rng->output_h); writel(TRNG_INTACK_REG_READY, &ks_sa_rng->reg_rng->intack); + ks_sa_rng->ready_ts = ktime_get_ns() + ks_sa_rng->refill_delay_ns; return sizeof(u32) * 2; } @@ -152,10 +181,19 @@ static int ks_sa_rng_data_present(struct hwrng *rng, int wait) { struct device *dev = (struct device *)rng->priv; struct ks_sa_rng *ks_sa_rng = dev_get_drvdata(dev); + u64 now = ktime_get_ns(); u32 ready; int j; + if (wait && now < ks_sa_rng->ready_ts) { + /* Max delay expected here is 81920000 ns */ + unsigned long min_delay = + DIV_ROUND_UP((u32)(ks_sa_rng->ready_ts - now), 1000); + + usleep_range(min_delay, min_delay + SA_RNG_DATA_RETRY_DELAY); + } + for (j = 0; j < SA_MAX_RNG_DATA_RETRIES; j++) { ready = readl(&ks_sa_rng->reg_rng->status); ready &= TRNG_STATUS_REG_READY;