diff mbox series

[v9,04/11] pwm: clps711x: Use 64-bit division macro

Message ID 587f9ccae68ad7e1ce97fa8da6037292af1a5095.1584473399.git.gurus@codeaurora.org
State Changes Requested
Headers show
Series [v9,01/11] drm/i915: Use 64-bit division macro | expand

Commit Message

Guru Das Srinagesh March 17, 2020, 8:05 p.m. UTC
Since the PWM framework is switching struct pwm_args.period's datatype
to u64, prepare for this transition by using DIV64_U64_ROUND_CLOSEST to
handle a 64-bit divisor.

Cc: Alexander Shiyan <shc_work@mail.ru>
Cc: Arnd Bergmann <arnd@arndb.de>

Signed-off-by: Guru Das Srinagesh <gurus@codeaurora.org>
---
 drivers/pwm/pwm-clps711x.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Arnd Bergmann March 17, 2020, 10:22 p.m. UTC | #1
On Tue, Mar 17, 2020 at 9:05 PM Guru Das Srinagesh <gurus@codeaurora.org> wrote:
>
> Since the PWM framework is switching struct pwm_args.period's datatype
> to u64, prepare for this transition by using DIV64_U64_ROUND_CLOSEST to
> handle a 64-bit divisor.
>
> Cc: Alexander Shiyan <shc_work@mail.ru>
> Cc: Arnd Bergmann <arnd@arndb.de>
>
> Signed-off-by: Guru Das Srinagesh <gurus@codeaurora.org>
> ---
>  drivers/pwm/pwm-clps711x.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/pwm/pwm-clps711x.c b/drivers/pwm/pwm-clps711x.c
> index 924d39a..ba9500a 100644
> --- a/drivers/pwm/pwm-clps711x.c
> +++ b/drivers/pwm/pwm-clps711x.c
> @@ -43,7 +43,7 @@ static void clps711x_pwm_update_val(struct clps711x_chip *priv, u32 n, u32 v)
>  static unsigned int clps711x_get_duty(struct pwm_device *pwm, unsigned int v)
>  {
>         /* Duty cycle 0..15 max */
> -       return DIV_ROUND_CLOSEST(v * 0xf, pwm->args.period);
> +       return DIV64_U64_ROUND_CLOSEST(v * 0xf, pwm->args.period);
>  }

Is it actually going to exceed U32_MAX? If not, a type cast may be
more appropriate here than the expensive 64-bit division.

       Arnd
Guru Das Srinagesh March 17, 2020, 11:30 p.m. UTC | #2
On Tue, Mar 17, 2020 at 11:22:06PM +0100, Arnd Bergmann wrote:
> > diff --git a/drivers/pwm/pwm-clps711x.c b/drivers/pwm/pwm-clps711x.c
> > index 924d39a..ba9500a 100644
> > --- a/drivers/pwm/pwm-clps711x.c
> > +++ b/drivers/pwm/pwm-clps711x.c
> > @@ -43,7 +43,7 @@ static void clps711x_pwm_update_val(struct clps711x_chip *priv, u32 n, u32 v)
> >  static unsigned int clps711x_get_duty(struct pwm_device *pwm, unsigned int v)
> >  {
> >         /* Duty cycle 0..15 max */
> > -       return DIV_ROUND_CLOSEST(v * 0xf, pwm->args.period);
> > +       return DIV64_U64_ROUND_CLOSEST(v * 0xf, pwm->args.period);
> >  }
> 
> Is it actually going to exceed U32_MAX? If not, a type cast may be
> more appropriate here than the expensive 64-bit division.

With the final change in this patch series, the framework will support
periods that exceed U32_MAX. My concern is that using a typecast would
mean that in those cases, this driver will not support > U32_MAX values.
Using DIV64_U64_ROUND_CLOSEST makes the driver future proof and able to
handle > U32_MAX values correctly. What do you think?

Thank you.

Guru Das.
Arnd Bergmann March 18, 2020, 9:49 a.m. UTC | #3
On Wed, Mar 18, 2020 at 12:30 AM Guru Das Srinagesh
<gurus@codeaurora.org> wrote:
>
> On Tue, Mar 17, 2020 at 11:22:06PM +0100, Arnd Bergmann wrote:
> > > diff --git a/drivers/pwm/pwm-clps711x.c b/drivers/pwm/pwm-clps711x.c
> > > index 924d39a..ba9500a 100644
> > > --- a/drivers/pwm/pwm-clps711x.c
> > > +++ b/drivers/pwm/pwm-clps711x.c
> > > @@ -43,7 +43,7 @@ static void clps711x_pwm_update_val(struct clps711x_chip *priv, u32 n, u32 v)
> > >  static unsigned int clps711x_get_duty(struct pwm_device *pwm, unsigned int v)
> > >  {
> > >         /* Duty cycle 0..15 max */
> > > -       return DIV_ROUND_CLOSEST(v * 0xf, pwm->args.period);
> > > +       return DIV64_U64_ROUND_CLOSEST(v * 0xf, pwm->args.period);
> > >  }
> >
> > Is it actually going to exceed U32_MAX? If not, a type cast may be
> > more appropriate here than the expensive 64-bit division.
>
> With the final change in this patch series, the framework will support
> periods that exceed U32_MAX. My concern is that using a typecast would
> mean that in those cases, this driver will not support > U32_MAX values.
> Using DIV64_U64_ROUND_CLOSEST makes the driver future proof and able to
> handle > U32_MAX values correctly. What do you think?

Ah, so if the period can actually be larger than U32_MAX, you need to
handle that case. However, I see that the divident in this code (v * 0xf)
is still a 32-bit number, so a correct and efficient implementation could be

   if (pwm->args.period > (UINT_MAX / 0xf))
          return 0;
   return DIV_ROUND_CLOSEST(v * 0xf, (u32)pwm->args.period);

        Arnd
Guru Das Srinagesh March 18, 2020, 5 p.m. UTC | #4
On Wed, Mar 18, 2020 at 10:49:34AM +0100, Arnd Bergmann wrote:
> On Wed, Mar 18, 2020 at 12:30 AM Guru Das Srinagesh
> <gurus@codeaurora.org> wrote:
> >
> > On Tue, Mar 17, 2020 at 11:22:06PM +0100, Arnd Bergmann wrote:
> > > > diff --git a/drivers/pwm/pwm-clps711x.c b/drivers/pwm/pwm-clps711x.c
> > > > index 924d39a..ba9500a 100644
> > > > --- a/drivers/pwm/pwm-clps711x.c
> > > > +++ b/drivers/pwm/pwm-clps711x.c
> > > > @@ -43,7 +43,7 @@ static void clps711x_pwm_update_val(struct clps711x_chip *priv, u32 n, u32 v)
> > > >  static unsigned int clps711x_get_duty(struct pwm_device *pwm, unsigned int v)
> > > >  {
> > > >         /* Duty cycle 0..15 max */
> > > > -       return DIV_ROUND_CLOSEST(v * 0xf, pwm->args.period);
> > > > +       return DIV64_U64_ROUND_CLOSEST(v * 0xf, pwm->args.period);
> > > >  }
> > >
> > > Is it actually going to exceed U32_MAX? If not, a type cast may be
> > > more appropriate here than the expensive 64-bit division.
> >
> > With the final change in this patch series, the framework will support
> > periods that exceed U32_MAX. My concern is that using a typecast would
> > mean that in those cases, this driver will not support > U32_MAX values.
> > Using DIV64_U64_ROUND_CLOSEST makes the driver future proof and able to
> > handle > U32_MAX values correctly. What do you think?
> 
> Ah, so if the period can actually be larger than U32_MAX, you need to
> handle that case. However, I see that the divident in this code (v * 0xf)
> is still a 32-bit number, so a correct and efficient implementation could be
> 
>    if (pwm->args.period > (UINT_MAX / 0xf))

Shouldn't the if condition be the following? Or am I missing
something here?

     if (pwm->args.period > (UINT_MAX / (v * 0xf)))
     					^^^^^^^^^

>           return 0;
>    return DIV_ROUND_CLOSEST(v * 0xf, (u32)pwm->args.period);

Thank you.

Guru Das.
Arnd Bergmann March 18, 2020, 7:38 p.m. UTC | #5
On Wed, Mar 18, 2020 at 6:00 PM Guru Das Srinagesh <gurus@codeaurora.org> wrote:
>
> On Wed, Mar 18, 2020 at 10:49:34AM +0100, Arnd Bergmann wrote:
> > On Wed, Mar 18, 2020 at 12:30 AM Guru Das Srinagesh
> > <gurus@codeaurora.org> wrote:
> > >
> > > On Tue, Mar 17, 2020 at 11:22:06PM +0100, Arnd Bergmann wrote:
> > > > > diff --git a/drivers/pwm/pwm-clps711x.c b/drivers/pwm/pwm-clps711x.c
> > > > > index 924d39a..ba9500a 100644
> > > > > --- a/drivers/pwm/pwm-clps711x.c
> > > > > +++ b/drivers/pwm/pwm-clps711x.c
> > > > > @@ -43,7 +43,7 @@ static void clps711x_pwm_update_val(struct clps711x_chip *priv, u32 n, u32 v)
> > > > >  static unsigned int clps711x_get_duty(struct pwm_device *pwm, unsigned int v)
> > > > >  {
> > > > >         /* Duty cycle 0..15 max */
> > > > > -       return DIV_ROUND_CLOSEST(v * 0xf, pwm->args.period);
> > > > > +       return DIV64_U64_ROUND_CLOSEST(v * 0xf, pwm->args.period);
> > > > >  }
> > > >
> > > > Is it actually going to exceed U32_MAX? If not, a type cast may be
> > > > more appropriate here than the expensive 64-bit division.
> > >
> > > With the final change in this patch series, the framework will support
> > > periods that exceed U32_MAX. My concern is that using a typecast would
> > > mean that in those cases, this driver will not support > U32_MAX values.
> > > Using DIV64_U64_ROUND_CLOSEST makes the driver future proof and able to
> > > handle > U32_MAX values correctly. What do you think?
> >
> > Ah, so if the period can actually be larger than U32_MAX, you need to
> > handle that case. However, I see that the divident in this code (v * 0xf)
> > is still a 32-bit number, so a correct and efficient implementation could be
> >
> >    if (pwm->args.period > (UINT_MAX / 0xf))
>
> Shouldn't the if condition be the following? Or am I missing
> something here?
>
>      if (pwm->args.period > (UINT_MAX / (v * 0xf)))
>                                         ^^^^^^^^^

That would require performing a division, which is an external function
call on ARMv4. My version just checks for an upper bound and completely
avoids the division. You could also just check for ">UINT_MAX" if you
find that clearer.

      Arnd
Guru Das Srinagesh March 19, 2020, 8:51 p.m. UTC | #6
On Wed, Mar 18, 2020 at 08:38:29PM +0100, Arnd Bergmann wrote:
> On Wed, Mar 18, 2020 at 6:00 PM Guru Das Srinagesh <gurus@codeaurora.org> wrote:
> >
> > On Wed, Mar 18, 2020 at 10:49:34AM +0100, Arnd Bergmann wrote:
> > > On Wed, Mar 18, 2020 at 12:30 AM Guru Das Srinagesh
> > > <gurus@codeaurora.org> wrote:
> > > >
> > > > On Tue, Mar 17, 2020 at 11:22:06PM +0100, Arnd Bergmann wrote:
> > > > > > diff --git a/drivers/pwm/pwm-clps711x.c b/drivers/pwm/pwm-clps711x.c
> > > > > > index 924d39a..ba9500a 100644
> > > > > > --- a/drivers/pwm/pwm-clps711x.c
> > > > > > +++ b/drivers/pwm/pwm-clps711x.c
> > > > > > @@ -43,7 +43,7 @@ static void clps711x_pwm_update_val(struct clps711x_chip *priv, u32 n, u32 v)
> > > > > >  static unsigned int clps711x_get_duty(struct pwm_device *pwm, unsigned int v)
> > > > > >  {
> > > > > >         /* Duty cycle 0..15 max */
> > > > > > -       return DIV_ROUND_CLOSEST(v * 0xf, pwm->args.period);
> > > > > > +       return DIV64_U64_ROUND_CLOSEST(v * 0xf, pwm->args.period);
> > > > > >  }
> > > > >
> > > > > Is it actually going to exceed U32_MAX? If not, a type cast may be
> > > > > more appropriate here than the expensive 64-bit division.
> > > >
> > > > With the final change in this patch series, the framework will support
> > > > periods that exceed U32_MAX. My concern is that using a typecast would
> > > > mean that in those cases, this driver will not support > U32_MAX values.
> > > > Using DIV64_U64_ROUND_CLOSEST makes the driver future proof and able to
> > > > handle > U32_MAX values correctly. What do you think?
> > >
> > > Ah, so if the period can actually be larger than U32_MAX, you need to
> > > handle that case. However, I see that the divident in this code (v * 0xf)
> > > is still a 32-bit number, so a correct and efficient implementation could be
> > >
> > >    if (pwm->args.period > (UINT_MAX / 0xf))
> >
> > Shouldn't the if condition be the following? Or am I missing
> > something here?
> >
> >      if (pwm->args.period > (UINT_MAX / (v * 0xf)))
> >                                         ^^^^^^^^^
> 
> That would require performing a division, which is an external function
> call on ARMv4. My version just checks for an upper bound and completely
> avoids the division. You could also just check for ">UINT_MAX" if you
> find that clearer.

Thanks, have checked for UINT_MAX in v10 of my patchset that I just
uploaded. Could you please review it?

Thank you.

Guru Das.
diff mbox series

Patch

diff --git a/drivers/pwm/pwm-clps711x.c b/drivers/pwm/pwm-clps711x.c
index 924d39a..ba9500a 100644
--- a/drivers/pwm/pwm-clps711x.c
+++ b/drivers/pwm/pwm-clps711x.c
@@ -43,7 +43,7 @@  static void clps711x_pwm_update_val(struct clps711x_chip *priv, u32 n, u32 v)
 static unsigned int clps711x_get_duty(struct pwm_device *pwm, unsigned int v)
 {
 	/* Duty cycle 0..15 max */
-	return DIV_ROUND_CLOSEST(v * 0xf, pwm->args.period);
+	return DIV64_U64_ROUND_CLOSEST(v * 0xf, pwm->args.period);
 }
 
 static int clps711x_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)