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

Configure Feed

Select the types of activity you want to include in your feed.

pwm: samsung: Fix to use lowest div for large enough modulation bits

From pwm_samsung_calc_tin(), there is routine to find the lowest divider
possible to generate lower frequency than requested one. But it is
always possible to generate requested frequency with large enough
modulation bits except on s3c24xx, so this patch fixes to use lowest div
for the case. This patch removes following UBSAN warning:

UBSAN: Undefined behaviour in drivers/pwm/pwm-samsung.c:197:13
shift exponent 32 is too large for 32-bit type 'long unsigned int'
[...]
[<c0670248>] (ubsan_epilogue) from [<c06707b4>] (__ubsan_handle_shift_out_of_bounds+0xd8/0x120)
[<c06707b4>] (__ubsan_handle_shift_out_of_bounds) from [<c0694b28>] (pwm_samsung_config+0x508/0x6a4)
[<c0694b28>] (pwm_samsung_config) from [<c069286c>] (pwm_apply_state+0x174/0x40c)
[<c069286c>] (pwm_apply_state) from [<c0b2e070>] (pwm_fan_probe+0xc8/0x488)
[<c0b2e070>] (pwm_fan_probe) from [<c07ba8b0>] (platform_drv_probe+0x70/0x150)
[...]

Cc: Tomasz Figa <tomasz.figa@gmail.com>
Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Reviewed-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>

authored by

Seung-Woo Kim and committed by
Thierry Reding
04d68dea 549c50af

+12 -3
+12 -3
drivers/pwm/pwm-samsung.c
··· 193 193 * divider settings and choose the lowest divisor that can generate 194 194 * frequencies lower than requested. 195 195 */ 196 - for (div = variant->div_base; div < 4; ++div) 197 - if ((rate >> (variant->bits + div)) < freq) 198 - break; 196 + if (variant->bits < 32) { 197 + /* Only for s3c24xx */ 198 + for (div = variant->div_base; div < 4; ++div) 199 + if ((rate >> (variant->bits + div)) < freq) 200 + break; 201 + } else { 202 + /* 203 + * Other variants have enough counter bits to generate any 204 + * requested rate, so no need to check higher divisors. 205 + */ 206 + div = variant->div_base; 207 + } 199 208 200 209 pwm_samsung_set_divisor(chip, chan, BIT(div)); 201 210