From: Xichao Zhao zhao.xichao@vivo.com
[ Upstream commit 817fcdbd4ca29834014a5dadbe8e11efeb12800c ]
It is better to replace ns_to_ktime() with us_to_ktime(), which can make the code clearer.
Signed-off-by: Xichao Zhao zhao.xichao@vivo.com Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Sasha Levin sashal@kernel.org ---
LLM Generated explanations, may be completely bogus:
YES
- What changed: The probe assigns `priv->period` using `us_to_ktime(period)` instead of `ns_to_ktime(period * NSEC_PER_USEC)`, i.e. a unit conversion moved inside a dedicated helper. See `drivers/char/hw_random/timeriomem-rng.c:155` (old code shown) and the diff replacing it with `us_to_ktime(period)`. - Code context shows `period` is specified in microseconds: - Read from DT as a 32-bit value “period” and stored into local `int period` (microseconds): `drivers/char/hw_random/timeriomem- rng.c:137`. - Printed as microseconds: `drivers/char/hw_random/timeriomem- rng.c:178` (“@ %dus”). - The driver later converts `priv->period` back to microseconds to sleep between reads: `drivers/char/hw_random/timeriomem-rng.c:50`. - Why this matters: The old expression performs the multiplication in C before passing to `ns_to_ktime`. On 32-bit architectures, `NSEC_PER_USEC` is `1000L` (32-bit long), so `period * NSEC_PER_USEC` is computed in 32-bit and can overflow when `period > LONG_MAX/1000 ≈ 2,147,483us (~2.147s)`. See `include/vdso/time64.h:8`. That overflow would yield an incorrect `priv->period`, which then: - Produces a wrong `period_us = ktime_to_us(priv->period)` used in `usleep_range()` (timing skew): `drivers/char/hw_random/timeriomem- rng.c:50` and `drivers/char/hw_random/timeriomem-rng.c:70-72`. - Forwards the hrtimer by a wrong amount via `hrtimer_forward_now(&priv->timer, priv->period)`: `drivers/char/hw_random/timeriomem-rng.c:86`. - Why the new helper is safer: `us_to_ktime(u64 us)` multiplies in 64-bit, avoiding the 32-bit intermediate overflow (see `include/linux/ktime.h:225`). Passing the `int period` argument promotes it to `u64` before multiplication, making this robust on 32-bit systems as well. - Scope and risk: - Single-line change in a contained driver (`drivers/char/hw_random/timeriomem-rng.c`), no interface/ABI changes, no architectural churn. - Behavior is unchanged for typical periods (1us–1s), but correctness improves for larger microsecond values by eliminating potential overflow on 32-bit. - No dependency on newer APIs; `us_to_ktime()` exists alongside `ns_to_ktime()` in stable trees (`include/linux/ktime.h:225`). - History/context sanity check: The driver explicitly handles a wide range of periods and uses that period both to schedule an hrtimer and to compute sleeps, so a wrong `ktime_t` directly affects observable timing. Prior fixes to this driver have targeted timing behavior (e.g., cooldown tolerance), underscoring that timing correctness matters here.
Given the minimal, self-contained nature of the change, its alignment with existing helper usage elsewhere in the kernel, and its elimination of a plausible 32-bit overflow hazard, this is a low-risk improvement with tangible correctness benefits. It is suitable for stable backporting.
drivers/char/hw_random/timeriomem-rng.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/char/hw_random/timeriomem-rng.c b/drivers/char/hw_random/timeriomem-rng.c index b95f6d0f17ede..e61f063932090 100644 --- a/drivers/char/hw_random/timeriomem-rng.c +++ b/drivers/char/hw_random/timeriomem-rng.c @@ -150,7 +150,7 @@ static int timeriomem_rng_probe(struct platform_device *pdev) priv->rng_ops.quality = pdata->quality; }
- priv->period = ns_to_ktime(period * NSEC_PER_USEC); + priv->period = us_to_ktime(period); init_completion(&priv->completion); hrtimer_setup(&priv->timer, timeriomem_rng_trigger, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);