Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

pwm: mtk-disp: Fix overflow in period and duty calculation

Current calculation for period and high_width may have 64-bit overflow.
state->period and rate are u64. rate * state->period will overflow.

clk_div = div_u64(rate * state->period, NSEC_PER_SEC)
period = div64_u64(rate * state->period, div);
high_width = div64_u64(rate * state->duty_cycle, div);

This patch is to resolve it by using mul_u64_u64_div_u64().

Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>

authored by

Jitao Shi and committed by
Thierry Reding
331e049d 888a623d

+3 -3
+3 -3
drivers/pwm/pwm-mtk-disp.c
··· 119 119 * high_width = (PWM_CLK_RATE * duty_ns) / (10^9 * (clk_div + 1)) 120 120 */ 121 121 rate = clk_get_rate(mdp->clk_main); 122 - clk_div = div_u64(rate * state->period, NSEC_PER_SEC) >> 122 + clk_div = mul_u64_u64_div_u64(state->period, rate, NSEC_PER_SEC) >> 123 123 PWM_PERIOD_BIT_WIDTH; 124 124 if (clk_div > PWM_CLKDIV_MAX) { 125 125 if (!mdp->enabled) { ··· 130 130 } 131 131 132 132 div = NSEC_PER_SEC * (clk_div + 1); 133 - period = div64_u64(rate * state->period, div); 133 + period = mul_u64_u64_div_u64(state->period, rate, div); 134 134 if (period > 0) 135 135 period--; 136 136 137 - high_width = div64_u64(rate * state->duty_cycle, div); 137 + high_width = mul_u64_u64_div_u64(state->duty_cycle, rate, div); 138 138 value = period | (high_width << PWM_HIGH_WIDTH_SHIFT); 139 139 140 140 mtk_disp_pwm_update_bits(mdp, mdp->data->con0,