diff mbox series

[v2,2/4] docs: hwmon: (ltc2945): change type of val to ULL in ltc2945_val_to_reg()

Message ID 20201111091259.46773-3-alexandru.ardelean@analog.com (mailing list archive)
State Changes Requested
Headers show
Series hwmon: (ltc2945): add support for sense resistor | expand

Commit Message

Alexandru Ardelean Nov. 11, 2020, 9:12 a.m. UTC
In order to account for any potential overflows that could occur.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/hwmon/ltc2945.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

Comments

Guenter Roeck Nov. 11, 2020, 2:54 p.m. UTC | #1
On 11/11/20 1:12 AM, Alexandru Ardelean wrote:
> In order to account for any potential overflows that could occur.
> 
> Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>

Thinking about it, this can only really happen if the user provides
excessive values for limit attributes. Those are currently clamped
later, after the conversion. I think it would be better to modify
the code to apply a clamp _before_ the conversion as well instead
of trying to solve the overflow problem with unsigned long long.

Either case, can you send me a register dump for this chip ?
I'd like to write a module test script to actually check if there
are any over/underflows or other problems.

Thanks,
Guenter

> ---
>  drivers/hwmon/ltc2945.c | 12 ++++++------
>  1 file changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/hwmon/ltc2945.c b/drivers/hwmon/ltc2945.c
> index 1cea710df668..6d4569a25471 100644
> --- a/drivers/hwmon/ltc2945.c
> +++ b/drivers/hwmon/ltc2945.c
> @@ -155,7 +155,7 @@ static long long ltc2945_reg_to_val(struct device *dev, u8 reg)
>  }
>  
>  static int ltc2945_val_to_reg(struct device *dev, u8 reg,
> -			      unsigned long val)
> +			      unsigned long long val)
>  {
>  	struct ltc2945_state *st = dev_get_drvdata(dev);
>  	struct regmap *regmap = st->regmap;
> @@ -181,14 +181,14 @@ static int ltc2945_val_to_reg(struct device *dev, u8 reg,
>  			return ret;
>  		if (control & CONTROL_MULT_SELECT) {
>  			/* 25 mV * 25 uV = 0.625 uV resolution. */
> -			val = DIV_ROUND_CLOSEST(val, 625);
> +			val = DIV_ROUND_CLOSEST_ULL(val, 625);
>  		} else {
>  			/*
>  			 * 0.5 mV * 25 uV = 0.0125 uV resolution.
>  			 * Divide first to avoid overflow;
>  			 * accept loss of accuracy.
>  			 */
> -			val = DIV_ROUND_CLOSEST(val, 25) * 2;
> +			val = DIV_ROUND_CLOSEST_ULL(val, 25) * 2;
>  		}
>  		break;
>  	case LTC2945_VIN_H:
> @@ -197,7 +197,7 @@ static int ltc2945_val_to_reg(struct device *dev, u8 reg,
>  	case LTC2945_MAX_VIN_THRES_H:
>  	case LTC2945_MIN_VIN_THRES_H:
>  		/* 25 mV resolution. */
> -		val /= 25;
> +		val = div_u64(val, 25);
>  		break;
>  	case LTC2945_ADIN_H:
>  	case LTC2945_MAX_ADIN_H:
> @@ -219,7 +219,7 @@ static int ltc2945_val_to_reg(struct device *dev, u8 reg,
>  		 * dividing the reported current by the sense resistor value
>  		 * in mOhm.
>  		 */
> -		val = DIV_ROUND_CLOSEST(val, 25);
> +		val = DIV_ROUND_CLOSEST_ULL(val, 25);
>  		break;
>  	default:
>  		return -EINVAL;
> @@ -247,7 +247,7 @@ static ssize_t ltc2945_value_store(struct device *dev,
>  	struct ltc2945_state *st = dev_get_drvdata(dev);
>  	struct regmap *regmap = st->regmap;
>  	u8 reg = attr->index;
> -	unsigned long val;
> +	unsigned long long val;
>  	u8 regbuf[3];
>  	int num_regs;
>  	int regval;
>
Alexandru Ardelean Nov. 11, 2020, 3:28 p.m. UTC | #2
On Wed, Nov 11, 2020 at 4:54 PM Guenter Roeck <linux@roeck-us.net> wrote:
>
> On 11/11/20 1:12 AM, Alexandru Ardelean wrote:
> > In order to account for any potential overflows that could occur.
> >
> > Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
>
> Thinking about it, this can only really happen if the user provides
> excessive values for limit attributes. Those are currently clamped
> later, after the conversion. I think it would be better to modify
> the code to apply a clamp _before_ the conversion as well instead
> of trying to solve the overflow problem with unsigned long long.
>
> Either case, can you send me a register dump for this chip ?

I asked Mark to help out on this.
Right now I don't have a board around my home-office.
I"m just pulling patches from our own tree to send upstream.
Is there a specific command you have in mind for this i2cdump?

Is the output of something like this fine:
# i2cdump -r 0x00-0x31 1 0x6f
?

We have a board that's being developed with this driver (and chip).
I think Mark will try to read values from the eval-board [since he has
one around].

Thanks
Alex

> I'd like to write a module test script to actually check if there
> are any over/underflows or other problems.
>
> Thanks,
> Guenter
>
> > ---
> >  drivers/hwmon/ltc2945.c | 12 ++++++------
> >  1 file changed, 6 insertions(+), 6 deletions(-)
> >
> > diff --git a/drivers/hwmon/ltc2945.c b/drivers/hwmon/ltc2945.c
> > index 1cea710df668..6d4569a25471 100644
> > --- a/drivers/hwmon/ltc2945.c
> > +++ b/drivers/hwmon/ltc2945.c
> > @@ -155,7 +155,7 @@ static long long ltc2945_reg_to_val(struct device *dev, u8 reg)
> >  }
> >
> >  static int ltc2945_val_to_reg(struct device *dev, u8 reg,
> > -                           unsigned long val)
> > +                           unsigned long long val)
> >  {
> >       struct ltc2945_state *st = dev_get_drvdata(dev);
> >       struct regmap *regmap = st->regmap;
> > @@ -181,14 +181,14 @@ static int ltc2945_val_to_reg(struct device *dev, u8 reg,
> >                       return ret;
> >               if (control & CONTROL_MULT_SELECT) {
> >                       /* 25 mV * 25 uV = 0.625 uV resolution. */
> > -                     val = DIV_ROUND_CLOSEST(val, 625);
> > +                     val = DIV_ROUND_CLOSEST_ULL(val, 625);
> >               } else {
> >                       /*
> >                        * 0.5 mV * 25 uV = 0.0125 uV resolution.
> >                        * Divide first to avoid overflow;
> >                        * accept loss of accuracy.
> >                        */
> > -                     val = DIV_ROUND_CLOSEST(val, 25) * 2;
> > +                     val = DIV_ROUND_CLOSEST_ULL(val, 25) * 2;
> >               }
> >               break;
> >       case LTC2945_VIN_H:
> > @@ -197,7 +197,7 @@ static int ltc2945_val_to_reg(struct device *dev, u8 reg,
> >       case LTC2945_MAX_VIN_THRES_H:
> >       case LTC2945_MIN_VIN_THRES_H:
> >               /* 25 mV resolution. */
> > -             val /= 25;
> > +             val = div_u64(val, 25);
> >               break;
> >       case LTC2945_ADIN_H:
> >       case LTC2945_MAX_ADIN_H:
> > @@ -219,7 +219,7 @@ static int ltc2945_val_to_reg(struct device *dev, u8 reg,
> >                * dividing the reported current by the sense resistor value
> >                * in mOhm.
> >                */
> > -             val = DIV_ROUND_CLOSEST(val, 25);
> > +             val = DIV_ROUND_CLOSEST_ULL(val, 25);
> >               break;
> >       default:
> >               return -EINVAL;
> > @@ -247,7 +247,7 @@ static ssize_t ltc2945_value_store(struct device *dev,
> >       struct ltc2945_state *st = dev_get_drvdata(dev);
> >       struct regmap *regmap = st->regmap;
> >       u8 reg = attr->index;
> > -     unsigned long val;
> > +     unsigned long long val;
> >       u8 regbuf[3];
> >       int num_regs;
> >       int regval;
> >
>
Guenter Roeck Nov. 11, 2020, 3:44 p.m. UTC | #3
On Wed, Nov 11, 2020 at 05:28:51PM +0200, Alexandru Ardelean wrote:
> On Wed, Nov 11, 2020 at 4:54 PM Guenter Roeck <linux@roeck-us.net> wrote:
> >
> > On 11/11/20 1:12 AM, Alexandru Ardelean wrote:
> > > In order to account for any potential overflows that could occur.
> > >
> > > Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
> >
> > Thinking about it, this can only really happen if the user provides
> > excessive values for limit attributes. Those are currently clamped
> > later, after the conversion. I think it would be better to modify
> > the code to apply a clamp _before_ the conversion as well instead
> > of trying to solve the overflow problem with unsigned long long.
> >
> > Either case, can you send me a register dump for this chip ?
> 
> I asked Mark to help out on this.
> Right now I don't have a board around my home-office.
> I"m just pulling patches from our own tree to send upstream.
> Is there a specific command you have in mind for this i2cdump?
> 
> Is the output of something like this fine:
> # i2cdump -r 0x00-0x31 1 0x6f
> ?

Yes, that should do, assuming the chip is on bus #1, address 0x6f.

Thanks,
Guenter
kernel test robot Nov. 13, 2020, 7:25 a.m. UTC | #4
Hi Alexandru,

I love your patch! Yet something to improve:

[auto build test ERROR on hwmon/hwmon-next]
[also build test ERROR on v5.10-rc3 next-20201112]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Alexandru-Ardelean/hwmon-ltc2945-add-support-for-sense-resistor/20201111-171129
base:   https://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git hwmon-next
config: powerpc64-randconfig-r005-20201111 (attached as .config)
compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project 874b0a0b9db93f5d3350ffe6b5efda2d908415d0)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install powerpc64 cross compiling tool for clang build
        # apt-get install binutils-powerpc64-linux-gnu
        # https://github.com/0day-ci/linux/commit/4e0e9315df2733ae5efe6095c5ab9b7675d07fb0
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Alexandru-Ardelean/hwmon-ltc2945-add-support-for-sense-resistor/20201111-171129
        git checkout 4e0e9315df2733ae5efe6095c5ab9b7675d07fb0
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=powerpc64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> drivers/hwmon/ltc2945.c:256:26: error: incompatible pointer types passing 'unsigned long long *' to parameter of type 'unsigned long *' [-Werror,-Wincompatible-pointer-types]
           ret = kstrtoul(buf, 10, &val);
                                   ^~~~
   include/linux/kernel.h:351:90: note: passing argument to parameter 'res' here
   static inline int __must_check kstrtoul(const char *s, unsigned int base, unsigned long *res)
                                                                                            ^
   1 error generated.

vim +256 drivers/hwmon/ltc2945.c

6700ce035f8301 Guenter Roeck      2014-01-11  241  
5614e26d84a99a Guenter Roeck      2018-12-06  242  static ssize_t ltc2945_value_store(struct device *dev,
6700ce035f8301 Guenter Roeck      2014-01-11  243  				   struct device_attribute *da,
6700ce035f8301 Guenter Roeck      2014-01-11  244  				   const char *buf, size_t count)
6700ce035f8301 Guenter Roeck      2014-01-11  245  {
6700ce035f8301 Guenter Roeck      2014-01-11  246  	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
c159257a60302f Alexandru Ardelean 2020-11-11  247  	struct ltc2945_state *st = dev_get_drvdata(dev);
c159257a60302f Alexandru Ardelean 2020-11-11  248  	struct regmap *regmap = st->regmap;
6700ce035f8301 Guenter Roeck      2014-01-11  249  	u8 reg = attr->index;
4e0e9315df2733 Alexandru Ardelean 2020-11-11  250  	unsigned long long val;
6700ce035f8301 Guenter Roeck      2014-01-11  251  	u8 regbuf[3];
6700ce035f8301 Guenter Roeck      2014-01-11  252  	int num_regs;
6700ce035f8301 Guenter Roeck      2014-01-11  253  	int regval;
6700ce035f8301 Guenter Roeck      2014-01-11  254  	int ret;
6700ce035f8301 Guenter Roeck      2014-01-11  255  
6700ce035f8301 Guenter Roeck      2014-01-11 @256  	ret = kstrtoul(buf, 10, &val);
6700ce035f8301 Guenter Roeck      2014-01-11  257  	if (ret)
6700ce035f8301 Guenter Roeck      2014-01-11  258  		return ret;
6700ce035f8301 Guenter Roeck      2014-01-11  259  
6700ce035f8301 Guenter Roeck      2014-01-11  260  	/* convert to register value, then clamp and write result */
6700ce035f8301 Guenter Roeck      2014-01-11  261  	regval = ltc2945_val_to_reg(dev, reg, val);
6700ce035f8301 Guenter Roeck      2014-01-11  262  	if (is_power_reg(reg)) {
6700ce035f8301 Guenter Roeck      2014-01-11  263  		regval = clamp_val(regval, 0, 0xffffff);
6700ce035f8301 Guenter Roeck      2014-01-11  264  		regbuf[0] = regval >> 16;
6700ce035f8301 Guenter Roeck      2014-01-11  265  		regbuf[1] = (regval >> 8) & 0xff;
6700ce035f8301 Guenter Roeck      2014-01-11  266  		regbuf[2] = regval;
6700ce035f8301 Guenter Roeck      2014-01-11  267  		num_regs = 3;
6700ce035f8301 Guenter Roeck      2014-01-11  268  	} else {
6700ce035f8301 Guenter Roeck      2014-01-11  269  		regval = clamp_val(regval, 0, 0xfff) << 4;
6700ce035f8301 Guenter Roeck      2014-01-11  270  		regbuf[0] = regval >> 8;
6700ce035f8301 Guenter Roeck      2014-01-11  271  		regbuf[1] = regval & 0xff;
6700ce035f8301 Guenter Roeck      2014-01-11  272  		num_regs = 2;
6700ce035f8301 Guenter Roeck      2014-01-11  273  	}
6700ce035f8301 Guenter Roeck      2014-01-11  274  	ret = regmap_bulk_write(regmap, reg, regbuf, num_regs);
6700ce035f8301 Guenter Roeck      2014-01-11  275  	return ret < 0 ? ret : count;
6700ce035f8301 Guenter Roeck      2014-01-11  276  }
6700ce035f8301 Guenter Roeck      2014-01-11  277  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Alexandru Ardelean Nov. 18, 2020, 2:40 p.m. UTC | #5
On Wed, Nov 11, 2020 at 4:54 PM Guenter Roeck <linux@roeck-us.net> wrote:
>
> On 11/11/20 1:12 AM, Alexandru Ardelean wrote:
> > In order to account for any potential overflows that could occur.
> >
> > Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
>
> Thinking about it, this can only really happen if the user provides
> excessive values for limit attributes. Those are currently clamped
> later, after the conversion. I think it would be better to modify
> the code to apply a clamp _before_ the conversion as well instead
> of trying to solve the overflow problem with unsigned long long.

Coming back to this, I think that using the shunt resistor value
(which is in micro-ohms), and multiplying with multiples of 1000, the
chances of overflow grow quite a lot.
I could be wrong, but that is how it looks when I try to do some math
with the shunt resistor in place.

Looking at the clamping code, it looks like the initial version is
quite simple & straightforward.
I mean when doing the math and getting values out of range, clamping
afterwards to 0xffffff for power values is quite handy.
And clamping everything else to 0xfff for voltage also looks pretty simple.
We can do some clamping before, but it looks like it's extra math that
is already done in the conversion code anyway.

Hopefully, I'm not missing something here :)

>
> Either case, can you send me a register dump for this chip ?
> I'd like to write a module test script to actually check if there
> are any over/underflows or other problems.
>
> Thanks,
> Guenter
>
> > ---
> >  drivers/hwmon/ltc2945.c | 12 ++++++------
> >  1 file changed, 6 insertions(+), 6 deletions(-)
> >
> > diff --git a/drivers/hwmon/ltc2945.c b/drivers/hwmon/ltc2945.c
> > index 1cea710df668..6d4569a25471 100644
> > --- a/drivers/hwmon/ltc2945.c
> > +++ b/drivers/hwmon/ltc2945.c
> > @@ -155,7 +155,7 @@ static long long ltc2945_reg_to_val(struct device *dev, u8 reg)
> >  }
> >
> >  static int ltc2945_val_to_reg(struct device *dev, u8 reg,
> > -                           unsigned long val)
> > +                           unsigned long long val)
> >  {
> >       struct ltc2945_state *st = dev_get_drvdata(dev);
> >       struct regmap *regmap = st->regmap;
> > @@ -181,14 +181,14 @@ static int ltc2945_val_to_reg(struct device *dev, u8 reg,
> >                       return ret;
> >               if (control & CONTROL_MULT_SELECT) {
> >                       /* 25 mV * 25 uV = 0.625 uV resolution. */
> > -                     val = DIV_ROUND_CLOSEST(val, 625);
> > +                     val = DIV_ROUND_CLOSEST_ULL(val, 625);
> >               } else {
> >                       /*
> >                        * 0.5 mV * 25 uV = 0.0125 uV resolution.
> >                        * Divide first to avoid overflow;
> >                        * accept loss of accuracy.
> >                        */
> > -                     val = DIV_ROUND_CLOSEST(val, 25) * 2;
> > +                     val = DIV_ROUND_CLOSEST_ULL(val, 25) * 2;
> >               }
> >               break;
> >       case LTC2945_VIN_H:
> > @@ -197,7 +197,7 @@ static int ltc2945_val_to_reg(struct device *dev, u8 reg,
> >       case LTC2945_MAX_VIN_THRES_H:
> >       case LTC2945_MIN_VIN_THRES_H:
> >               /* 25 mV resolution. */
> > -             val /= 25;
> > +             val = div_u64(val, 25);
> >               break;
> >       case LTC2945_ADIN_H:
> >       case LTC2945_MAX_ADIN_H:
> > @@ -219,7 +219,7 @@ static int ltc2945_val_to_reg(struct device *dev, u8 reg,
> >                * dividing the reported current by the sense resistor value
> >                * in mOhm.
> >                */
> > -             val = DIV_ROUND_CLOSEST(val, 25);
> > +             val = DIV_ROUND_CLOSEST_ULL(val, 25);
> >               break;
> >       default:
> >               return -EINVAL;
> > @@ -247,7 +247,7 @@ static ssize_t ltc2945_value_store(struct device *dev,
> >       struct ltc2945_state *st = dev_get_drvdata(dev);
> >       struct regmap *regmap = st->regmap;
> >       u8 reg = attr->index;
> > -     unsigned long val;
> > +     unsigned long long val;
> >       u8 regbuf[3];
> >       int num_regs;
> >       int regval;
> >
>
Guenter Roeck Nov. 18, 2020, 3:19 p.m. UTC | #6
On Wed, Nov 18, 2020 at 04:40:24PM +0200, Alexandru Ardelean wrote:
> On Wed, Nov 11, 2020 at 4:54 PM Guenter Roeck <linux@roeck-us.net> wrote:
> >
> > On 11/11/20 1:12 AM, Alexandru Ardelean wrote:
> > > In order to account for any potential overflows that could occur.
> > >
> > > Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
> >
> > Thinking about it, this can only really happen if the user provides
> > excessive values for limit attributes. Those are currently clamped
> > later, after the conversion. I think it would be better to modify
> > the code to apply a clamp _before_ the conversion as well instead
> > of trying to solve the overflow problem with unsigned long long.
> 
> Coming back to this, I think that using the shunt resistor value
> (which is in micro-ohms), and multiplying with multiples of 1000, the
> chances of overflow grow quite a lot.
> I could be wrong, but that is how it looks when I try to do some math
> with the shunt resistor in place.
> 
> Looking at the clamping code, it looks like the initial version is
> quite simple & straightforward.
> I mean when doing the math and getting values out of range, clamping
> afterwards to 0xffffff for power values is quite handy.
> And clamping everything else to 0xfff for voltage also looks pretty simple.
> We can do some clamping before, but it looks like it's extra math that
> is already done in the conversion code anyway.
> 
> Hopefully, I'm not missing something here :)
>

Using ull operations when not necessary can also be quite expensive,
and I'd rather avoid it. I'd rather see an extra clamp than ull.

Guenter

> >
> > Either case, can you send me a register dump for this chip ?
> > I'd like to write a module test script to actually check if there
> > are any over/underflows or other problems.
> >
> > Thanks,
> > Guenter
> >
> > > ---
> > >  drivers/hwmon/ltc2945.c | 12 ++++++------
> > >  1 file changed, 6 insertions(+), 6 deletions(-)
> > >
> > > diff --git a/drivers/hwmon/ltc2945.c b/drivers/hwmon/ltc2945.c
> > > index 1cea710df668..6d4569a25471 100644
> > > --- a/drivers/hwmon/ltc2945.c
> > > +++ b/drivers/hwmon/ltc2945.c
> > > @@ -155,7 +155,7 @@ static long long ltc2945_reg_to_val(struct device *dev, u8 reg)
> > >  }
> > >
> > >  static int ltc2945_val_to_reg(struct device *dev, u8 reg,
> > > -                           unsigned long val)
> > > +                           unsigned long long val)
> > >  {
> > >       struct ltc2945_state *st = dev_get_drvdata(dev);
> > >       struct regmap *regmap = st->regmap;
> > > @@ -181,14 +181,14 @@ static int ltc2945_val_to_reg(struct device *dev, u8 reg,
> > >                       return ret;
> > >               if (control & CONTROL_MULT_SELECT) {
> > >                       /* 25 mV * 25 uV = 0.625 uV resolution. */
> > > -                     val = DIV_ROUND_CLOSEST(val, 625);
> > > +                     val = DIV_ROUND_CLOSEST_ULL(val, 625);
> > >               } else {
> > >                       /*
> > >                        * 0.5 mV * 25 uV = 0.0125 uV resolution.
> > >                        * Divide first to avoid overflow;
> > >                        * accept loss of accuracy.
> > >                        */
> > > -                     val = DIV_ROUND_CLOSEST(val, 25) * 2;
> > > +                     val = DIV_ROUND_CLOSEST_ULL(val, 25) * 2;
> > >               }
> > >               break;
> > >       case LTC2945_VIN_H:
> > > @@ -197,7 +197,7 @@ static int ltc2945_val_to_reg(struct device *dev, u8 reg,
> > >       case LTC2945_MAX_VIN_THRES_H:
> > >       case LTC2945_MIN_VIN_THRES_H:
> > >               /* 25 mV resolution. */
> > > -             val /= 25;
> > > +             val = div_u64(val, 25);
> > >               break;
> > >       case LTC2945_ADIN_H:
> > >       case LTC2945_MAX_ADIN_H:
> > > @@ -219,7 +219,7 @@ static int ltc2945_val_to_reg(struct device *dev, u8 reg,
> > >                * dividing the reported current by the sense resistor value
> > >                * in mOhm.
> > >                */
> > > -             val = DIV_ROUND_CLOSEST(val, 25);
> > > +             val = DIV_ROUND_CLOSEST_ULL(val, 25);
> > >               break;
> > >       default:
> > >               return -EINVAL;
> > > @@ -247,7 +247,7 @@ static ssize_t ltc2945_value_store(struct device *dev,
> > >       struct ltc2945_state *st = dev_get_drvdata(dev);
> > >       struct regmap *regmap = st->regmap;
> > >       u8 reg = attr->index;
> > > -     unsigned long val;
> > > +     unsigned long long val;
> > >       u8 regbuf[3];
> > >       int num_regs;
> > >       int regval;
> > >
> >
diff mbox series

Patch

diff --git a/drivers/hwmon/ltc2945.c b/drivers/hwmon/ltc2945.c
index 1cea710df668..6d4569a25471 100644
--- a/drivers/hwmon/ltc2945.c
+++ b/drivers/hwmon/ltc2945.c
@@ -155,7 +155,7 @@  static long long ltc2945_reg_to_val(struct device *dev, u8 reg)
 }
 
 static int ltc2945_val_to_reg(struct device *dev, u8 reg,
-			      unsigned long val)
+			      unsigned long long val)
 {
 	struct ltc2945_state *st = dev_get_drvdata(dev);
 	struct regmap *regmap = st->regmap;
@@ -181,14 +181,14 @@  static int ltc2945_val_to_reg(struct device *dev, u8 reg,
 			return ret;
 		if (control & CONTROL_MULT_SELECT) {
 			/* 25 mV * 25 uV = 0.625 uV resolution. */
-			val = DIV_ROUND_CLOSEST(val, 625);
+			val = DIV_ROUND_CLOSEST_ULL(val, 625);
 		} else {
 			/*
 			 * 0.5 mV * 25 uV = 0.0125 uV resolution.
 			 * Divide first to avoid overflow;
 			 * accept loss of accuracy.
 			 */
-			val = DIV_ROUND_CLOSEST(val, 25) * 2;
+			val = DIV_ROUND_CLOSEST_ULL(val, 25) * 2;
 		}
 		break;
 	case LTC2945_VIN_H:
@@ -197,7 +197,7 @@  static int ltc2945_val_to_reg(struct device *dev, u8 reg,
 	case LTC2945_MAX_VIN_THRES_H:
 	case LTC2945_MIN_VIN_THRES_H:
 		/* 25 mV resolution. */
-		val /= 25;
+		val = div_u64(val, 25);
 		break;
 	case LTC2945_ADIN_H:
 	case LTC2945_MAX_ADIN_H:
@@ -219,7 +219,7 @@  static int ltc2945_val_to_reg(struct device *dev, u8 reg,
 		 * dividing the reported current by the sense resistor value
 		 * in mOhm.
 		 */
-		val = DIV_ROUND_CLOSEST(val, 25);
+		val = DIV_ROUND_CLOSEST_ULL(val, 25);
 		break;
 	default:
 		return -EINVAL;
@@ -247,7 +247,7 @@  static ssize_t ltc2945_value_store(struct device *dev,
 	struct ltc2945_state *st = dev_get_drvdata(dev);
 	struct regmap *regmap = st->regmap;
 	u8 reg = attr->index;
-	unsigned long val;
+	unsigned long long val;
 	u8 regbuf[3];
 	int num_regs;
 	int regval;