[PATCH 1/8] pwm: tegra: Prevent 32-bit period truncation and division by zero

From: Lee Jones

Date: Thu Nov 05 2026 - 09:39:33 EST


tegra_pwm_apply() passes the 64-bit state->duty_cycle and state->period
values into tegra_pwm_config(), which accepts signed 32-bit int
parameters and performs DIV_ROUND_CLOSEST_ULL(c, period_ns) before
validating period_ns against pc->min_period_ns. If a consumer requests
a period that is a non-zero multiple of 2^32 nanoseconds, period_ns
truncates to zero and triggers a divide-by-zero panic.

Widen duty_ns and period_ns to u64 and validate that period_ns lies
within [pc->min_period_ns, U32_MAX] prior to dividing by period_ns.

Fixes: 1d7796bdb63a ("pwm: tegra: Support dynamic clock frequency configuration")
Fixes: fd3ddd4355c0 ("pwm: tegra: Implement .apply() callback")
Closes: https://sashiko.dev/#/bug/linux-5c5b97d6-4da6-4d06-9dc7-957419dcd832
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Lee Jones <lee@xxxxxxxxxx>
---
drivers/pwm/pwm-tegra.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
index 5cdbe120ba2d..f99ae2b3a276 100644
--- a/drivers/pwm/pwm-tegra.c
+++ b/drivers/pwm/pwm-tegra.c
@@ -138,7 +138,7 @@ static inline void tegra_pwm_writel(struct pwm_device *pwm, unsigned int offset,
}

static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
- int duty_ns, int period_ns)
+ u64 duty_ns, u64 period_ns)
{
struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip);
unsigned long long c = duty_ns;
@@ -146,6 +146,12 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
u32 val = 0;
int err;

+ /*
+ * min period = max clock limit / TEGRA_PWM_DEPTH
+ */
+ if (period_ns < pc->min_period_ns || period_ns > U32_MAX)
+ return -EINVAL;
+
/*
* Convert from duty_ns / period_ns to a fixed number of duty ticks
* per TEGRA_PWM_DEPTH cycles and make sure to round to the
@@ -156,12 +162,6 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,

val = (u32)c << TEGRA_PWM_DUTY_SHIFT;

- /*
- * min period = max clock limit / TEGRA_PWM_DEPTH
- */
- if (period_ns < pc->min_period_ns)
- return -EINVAL;
-
/*
* Compute the prescaler value for which TEGRA_PWM_DEPTH
* cycles at the PWM clock rate will take period_ns nanoseconds.
Cc: Sandipan Patra <spatra@xxxxxxxxxx>
Cc: "Uwe Kleine-König" <ukleinek@xxxxxxxxxx>
--
2.56.0.398.g882cbad275-goog