RE: [PATCH v6 2/4] pwm: Add support for RZ/V2M PWM driver

From: Fabrizio Castro
Date: Mon Feb 12 2024 - 15:09:16 EST


Hello Uwe,

Thanks for your reply!

> From: Uwe Kleine-König <u.kleine-koenig@xxxxxxxxxxxxxx>
> Sent: Saturday, February 10, 2024 5:27 PM
> To: Fabrizio Castro <fabrizio.castro.jz@xxxxxxxxxxx>
> Subject: Re: [PATCH v6 2/4] pwm: Add support for RZ/V2M PWM driver
>
> Hello Fabrizio,
>
> On Thu, Feb 08, 2024 at 11:24:09PM +0000, Fabrizio Castro wrote:
> > +static inline u64 rzv2m_pwm_mul_u64_u64_div_u64_roundup(u64 a, u64 b,
> u64 c)
> > +{
> > + u64 ab = a * b;
>
> This might overflow.

In the context of this driver, this cannot overflow.
The 2 formulas the above is needed for are:
1) period = (cyc + 1)*(NSEC_PER_SEC * frequency_divisor)/rate
2) duty_cycle = (cyc + 1 - low)*(NSEC_PER_SEC * frequency_divisor)/rate

With respect to 1), the dividend overflows when period * rate also
overflows (its product is calculated in rzv2m_pwm_config).
However, limiting the period to a maximum value of U64_MAX / rate
prevents the calculations from overflowing (in both directions, from period to cyc, and from cyc to period). v6 uses max_period for this.
The situation for 2) is very similar to 1), with duty_cycle<=period,
therefore limiting period to a max value (and clamping the duty cycle
accordingly) will ensure that the calculation for duty_cycle won't
overflow, either.

>
> > + return ab / c + (ab % c ? 1 : 0);
>
> This division triggered the kernel build bot error. If you want to
> divide a u64, you must not use /.

Right!
I have replicated the problem locally, and confirmed that also other divisions from the same patch are problematic.
Clearly, % can't work either.

I am going to replace / with div64_u64.
For rounding up, I think I'll go with something like:

u64 ab = a * b;
u64 d = div64_u64(ab, c);
u64 e = d * c;
return d + ((ab - e) ? 1 : 0);

I am aware that I could use DIV64_U64_ROUND_UP instead of the above,
however, the above allows for larger dividends than when using DIV64_U64_ROUND_UP.
If I were to use DIV64_U64_ROUND_UP instead, I would have to limit
max_period further to (U64_MAX + 1 - rate)/rate, which I rather avoid.

I'll send v7 to address this build issue for 32 bit platforms.

Cheers,
Fab

>
> Best regards
> Uwe
>
> --
> Pengutronix e.K. | Uwe Kleine-König |
> Industrial Linux Solutions | https://www.pengutronix.de/ |