Re: [PATCH v9 00/14] iio: afe: add temperature rescaling support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun, Nov 21, 2021 at 11:25:56AM +0000, Jonathan Cameron wrote:
> On Sun, 14 Nov 2021 22:43:20 -0500
> Liam Beguin <liambeguin@xxxxxxxxx> wrote:
> 
> > Hi Jonathan, Peter,
> > 
> > Apologies for not getting back to you sooner. I got caught up on other
> > work and wasn't able to dedicate time to this earlier. Hopefully, this
> > time around, I'll be able to get this to the finish line :-)
> > 
> > I left out IIO_VAL_INT overflows for now, so that I can focus on getting
> > the rest of these changes pulled in, but I don't mind adding a patch for
> > that later on.
> > 
> > This series focuses on adding temperature rescaling support to the IIO
> > Analog Front End (AFE) driver.
> > 
> > The first few patches address minor bugs in IIO inkernel functions, and
> > prepare the AFE driver for the additional features.
> > 
> > The main changes to the AFE driver include an initial Kunit test suite,
> > support for IIO_VAL_INT_PLUS_{NANO,MICRO} scales, and support for RTDs
> > and temperature transducer sensors.
> > 
> > Thanks for your time,
> > Liam
> 
> Hi Liam,

Hi Jonathan,

> I'm fine with these.  The comment about using the MICRO etc defines can
> be handled as as trivial follow up patch. Hopefully someone else can
> figure out the 0-day build issue as I didn't managed to.

I'll prepare the MICRO, NANO changes if we have a v10, otherwise I'll
send them as a follow up patch as you suggest.

I'll also try to find more time to dig more into that 0-day build issue.

> However, I've long ago lost track of the various precision discussions
> you and Peter were having so would like Peter's input before taking these.

That's my fault, apologies for letting this sit for so long.

> Thanks again for your persistence with this,

No worries, thanks for your patience :)

Cheers,
Liam

> 
> Jonathan
> 
> > 
> > Changes since v8:
> > - reword comment
> > - fix erroneous 64-bit division
> > - optimize and use 32-bit divisions when values are know to not overflow
> > - keep IIO_VAL_FRACTIONAL scale when possible, if not default to fixed
> >   point
> > - add test cases
> > - use nano precision in test cases
> > - simplify offset calculation in rtd_props()
> > 
> > Changes since v7:
> > - drop gcd() logic in rescale_process_scale()
> > - use div_s64() instead of do_div() for signed 64-bit divisions
> > - combine IIO_VAL_FRACTIONAL and IIO_VAL_FRACTIONAL_LOG2 scale cases
> > - switch to INT_PLUS_NANO when accuracy is lost with FRACTIONAL scales
> > - rework test logic to allow for small relative error
> > - rename test variables to align error output messages
> > 
> > Changes since v6:
> > - rework IIO_VAL_INT_PLUS_{NANO,MICRO} based on Peter's suggestion
> > - combine IIO_VAL_INT_PLUS_{NANO,MICRO} cases
> > - add test cases for negative IIO_VAL_INT_PLUS_{NANO,MICRO} corner cases
> > - force use of positive integers with gcd()
> > - reduce risk of integer overflow in IIO_VAL_FRACTIONAL_LOG2
> > - fix duplicate symbol build error
> > - apply Reviewed-by
> > 
> > Changes since v5:
> > - add include/linux/iio/afe/rescale.h
> > - expose functions use to process scale and offset
> > - add basic iio-rescale kunit test cases
> > - fix integer overflow case
> > - improve precision for IIO_VAL_FRACTIONAL_LOG2
> > 
> > Changes since v4:
> > - only use gcd() when necessary in overflow mitigation
> > - fix INT_PLUS_{MICRO,NANO} support
> > - apply Reviewed-by
> > - fix temperature-transducer bindings
> > 
> > Changes since v3:
> > - drop unnecessary fallthrough statements
> > - drop redundant local variables in some calculations
> > - fix s64 divisions on 32bit platforms by using do_div
> > - add comment describing iio-rescaler offset calculation
> > - drop unnecessary MAINTAINERS entry
> > 
> > Changes since v2:
> > - don't break implicit offset truncations
> > - make a best effort to get a valid value for fractional types
> > - drop return value change in iio_convert_raw_to_processed_unlocked()
> > - don't rely on processed value for offset calculation
> > - add INT_PLUS_{MICRO,NANO} support in iio-rescale
> > - revert generic implementation in favor of temperature-sense-rtd and
> >   temperature-transducer
> > - add separate section to MAINTAINERS file
> > 
> > Changes since v1:
> > - rebase on latest iio `testing` branch
> > - also apply consumer scale on integer channel scale types
> > - don't break implicit truncation in processed channel offset
> >   calculation
> > - drop temperature AFE flavors in favor of a simpler generic
> >   implementation
> > 
> > Liam Beguin (14):
> >   iio: inkern: apply consumer scale on IIO_VAL_INT cases
> >   iio: inkern: apply consumer scale when no channel scale is available
> >   iio: inkern: make a best effort on offset calculation
> >   iio: afe: rescale: expose scale processing function
> >   iio: afe: rescale: add INT_PLUS_{MICRO,NANO} support
> >   iio: afe: rescale: add offset support
> >   iio: afe: rescale: use s64 for temporary scale calculations
> >   iio: afe: rescale: reduce risk of integer overflow
> >   iio: afe: rescale: fix accuracy for small fractional scales
> >   iio: test: add basic tests for the iio-rescale driver
> >   iio: afe: rescale: add RTD temperature sensor support
> >   iio: afe: rescale: add temperature transducers
> >   dt-bindings: iio: afe: add bindings for temperature-sense-rtd
> >   dt-bindings: iio: afe: add bindings for temperature transducers
> > 
> >  .../iio/afe/temperature-sense-rtd.yaml        | 101 +++
> >  .../iio/afe/temperature-transducer.yaml       | 114 +++
> >  drivers/iio/afe/iio-rescale.c                 | 271 ++++++-
> >  drivers/iio/inkern.c                          |  40 +-
> >  drivers/iio/test/Kconfig                      |  10 +
> >  drivers/iio/test/Makefile                     |   1 +
> >  drivers/iio/test/iio-test-rescale.c           | 705 ++++++++++++++++++
> >  include/linux/iio/afe/rescale.h               |  34 +
> >  8 files changed, 1232 insertions(+), 44 deletions(-)
> >  create mode 100644 Documentation/devicetree/bindings/iio/afe/temperature-sense-rtd.yaml
> >  create mode 100644 Documentation/devicetree/bindings/iio/afe/temperature-transducer.yaml
> >  create mode 100644 drivers/iio/test/iio-test-rescale.c
> >  create mode 100644 include/linux/iio/afe/rescale.h
> > 
> > Range-diff against v8:
> >  1:  42a7a1047edc =  1:  ae3cc93baee6 iio: inkern: apply consumer scale on IIO_VAL_INT cases
> >  2:  a1cd89fdad11 =  2:  06f66e7f7403 iio: inkern: apply consumer scale when no channel scale is available
> >  3:  ed0721fb6bd1 =  3:  2dbf6b3bbaeb iio: inkern: make a best effort on offset calculation
> >  4:  f8fb78bb1112 =  4:  b083cf307268 iio: afe: rescale: expose scale processing function
> >  5:  504b7a3f830b !  5:  a0bde29ecc8c iio: afe: rescale: add INT_PLUS_{MICRO,NANO} support
> >     @@ drivers/iio/afe/iio-rescale.c: int rescale_process_scale(struct rescale *rescale
> >      +		else
> >      +			mult = 1000000LL;
> >      +		/*
> >     -+		 * For IIO_VAL_INT_PLUS_{MICRO,NANO} scale types if *val OR
> >     -+		 * *val2 is negative the schan scale is negative
> >     ++		 * For IIO_VAL_INT_PLUS_{MICRO,NANO} scale types if either *val
> >     ++		 * OR *val2 is negative the schan scale is negative, i.e.
> >     ++		 * *val = 1 and *val2 = -0.5 yields -1.5 not -0.5.
> >      +		 */
> >      +		neg = *val < 0 || *val2 < 0;
> >      +
> >  6:  c254e9ae813e =  6:  c3d0e6248033 iio: afe: rescale: add offset support
> >  7:  ee8814d6abe4 =  7:  2a81fa735103 iio: afe: rescale: use s64 for temporary scale calculations
> >  8:  62cdcfbc9836 =  8:  8315548d0fce iio: afe: rescale: reduce risk of integer overflow
> >  9:  88309a5136ee !  9:  223ed0569cd2 iio: afe: rescale: fix accuracy for small fractional scales
> >     @@ drivers/iio/afe/iio-rescale.c: int rescale_process_scale(struct rescale *rescale
> >      +
> >      +		tmp = div_s64_rem(tmp, 1000000000LL, &rem);
> >       		*val = tmp;
> >     +-		return scale_type;
> >     ++
> >     ++		if (!rem)
> >     ++			return scale_type;
> >      +
> >     -+		/*
> >     -+		 * For small values, the approximation can be costly,
> >     -+		 * change scale type to maintain accuracy.
> >     -+		 *
> >     -+		 * 100 vs. 10000000 NANO caps the error to about 100 ppm.
> >     -+		 */
> >      +		if (scale_type == IIO_VAL_FRACTIONAL)
> >      +			tmp = *val2;
> >      +		else
> >      +			tmp = 1 << *val2;
> >      +
> >     -+		 if (abs(rem) > 10000000 && abs(*val / tmp) < 100) {
> >     -+			 *val = div_s64_rem(*val, tmp, &rem2);
> >     -+
> >     -+			 *val2 = div_s64(rem, tmp);
> >     -+			 if (rem2)
> >     -+				 *val2 += div_s64(rem2 * 1000000000LL, tmp);
> >     ++		rem2 = *val % (int)tmp;
> >     ++		*val = *val / (int)tmp;
> >      +
> >     -+			 return IIO_VAL_INT_PLUS_NANO;
> >     -+		 }
> >     ++		*val2 = rem / (int)tmp;
> >     ++		if (rem2)
> >     ++			*val2 += div_s64((s64)rem2 * 1000000000LL, tmp);
> >      +
> >     - 		return scale_type;
> >     ++		return IIO_VAL_INT_PLUS_NANO;
> >       	case IIO_VAL_INT_PLUS_NANO:
> >       	case IIO_VAL_INT_PLUS_MICRO:
> >     + 		if (scale_type == IIO_VAL_INT_PLUS_NANO)
> > 10:  fb505a9f42f1 ! 10:  90044efdf8be iio: test: add basic tests for the iio-rescale driver
> >     @@ drivers/iio/test/Makefile
> >       # Keep in alphabetical order
> >      +obj-$(CONFIG_IIO_RESCALE_KUNIT_TEST) += iio-test-rescale.o ../afe/iio-rescale.o
> >       obj-$(CONFIG_IIO_TEST_FORMAT) += iio-test-format.o
> >     + CFLAGS_iio-test-format.o += $(DISABLE_STRUCTLEAK_PLUGIN)
> >      
> >       ## drivers/iio/test/iio-test-rescale.c (new) ##
> >      @@
> >     @@ drivers/iio/test/iio-test-rescale.c (new)
> >      +	 * Use cases with small scales involving divisions
> >      +	 */
> >      +	{
> >     ++		.name = "small IIO_VAL_FRACTIONAL, 261/509 scaled by 90/1373754273",
> >     ++		.numerator = 261,
> >     ++		.denominator = 509,
> >     ++		.schan_scale_type = IIO_VAL_FRACTIONAL,
> >     ++		.schan_val = 90,
> >     ++		.schan_val2 = 1373754273,
> >     ++		.expected = "0.000000033594",
> >     ++	},
> >     ++	{
> >     ++		.name = "small IIO_VAL_FRACTIONAL, 90/1373754273 scaled by 261/509",
> >     ++		.numerator = 90,
> >     ++		.denominator = 1373754273,
> >     ++		.schan_scale_type = IIO_VAL_FRACTIONAL,
> >     ++		.schan_val = 261,
> >     ++		.schan_val2 = 509,
> >     ++		.expected = "0.000000033594",
> >     ++	},
> >     ++	{
> >     ++		.name = "small IIO_VAL_FRACTIONAL, 760/1373754273 scaled by 427/2727",
> >     ++		.numerator = 760,
> >     ++		.denominator = 1373754273,
> >     ++		.schan_scale_type = IIO_VAL_FRACTIONAL,
> >     ++		.schan_val = 427,
> >     ++		.schan_val2 = 2727,
> >     ++		.expected = "0.000000086626",
> >     ++	},
> >     ++	{
> >     ++		.name = "small IIO_VAL_FRACTIONAL, 761/1373754273 scaled by 427/2727",
> >     ++		.numerator = 761,
> >     ++		.denominator = 1373754273,
> >     ++		.schan_scale_type = IIO_VAL_FRACTIONAL,
> >     ++		.schan_val = 427,
> >     ++		.schan_val2 = 2727,
> >     ++		.expected = "0.000000086740",
> >     ++	},
> >     ++	{
> >     ++		.name = "small IIO_VAL_FRACTIONAL, 5/32768 scaled by 3/10000",
> >     ++		.numerator = 5,
> >     ++		.denominator = 32768,
> >     ++		.schan_scale_type = IIO_VAL_FRACTIONAL,
> >     ++		.schan_val = 3,
> >     ++		.schan_val2 = 10000,
> >     ++		.expected = "0.0000000457763671875",
> >     ++	},
> >     ++	{
> >      +		.name = "small IIO_VAL_FRACTIONAL, 0 < scale < 1",
> >      +		.numerator = 6,
> >      +		.denominator = 6,
> >     @@ drivers/iio/test/iio-test-rescale.c (new)
> >      +		.expected = "-1.3333333333333333",
> >      +	},
> >      +	{
> >     ++		.name = "small IIO_VAL_FRACTIONAL_LOG2, 760/32768 scaled by 15/22",
> >     ++		.numerator = 760,
> >     ++		.denominator = 32768,
> >     ++		.schan_scale_type = IIO_VAL_FRACTIONAL_LOG2,
> >     ++		.schan_val = 15,
> >     ++		.schan_val2 = 22,
> >     ++		.expected = "0.000000082946",
> >     ++	},
> >     ++	{
> >     ++		.name = "small IIO_VAL_FRACTIONAL_LOG2, 761/32768 scaled by 15/22",
> >     ++		.numerator = 761,
> >     ++		.denominator = 32768,
> >     ++		.schan_scale_type = IIO_VAL_FRACTIONAL_LOG2,
> >     ++		.schan_val = 15,
> >     ++		.schan_val2 = 22,
> >     ++		.expected = "0.000000083055",
> >     ++	},
> >     ++	{
> >      +		.name = "small IIO_VAL_FRACTIONAL_LOG2, 0 < scale < 1",
> >      +		.numerator = 16,
> >      +		.denominator = 3,
> >     @@ drivers/iio/test/iio-test-rescale.c (new)
> >      +KUNIT_ARRAY_PARAM(iio_rescale_offset, offset_cases, case_to_desc);
> >      +
> >      +/**
> >     -+ * iio_str_to_micro() - Parse a fixed-point string to get an
> >     -+ *                      IIO_VAL_INT_PLUS_MICRO value
> >     ++ * iio_str_to_nano() - Parse a fixed-point string to get an
> >     ++ *                      IIO_VAL_INT_PLUS_NANO value
> >      + * @str: The string to parse
> >     -+ * @micro: The number as an integer
> >     ++ * @nano: The number as an integer
> >      + *
> >      + * Returns 0 on success, or a negative error code if the string cound not be
> >      + * parsed.
> >      + */
> >     -+static int iio_str_to_micro(const char *str, s64 *micro)
> >     ++static int iio_str_to_nano(const char *str, s64 *nano)
> >      +{
> >     -+	int fract_mult = 100000LL;
> >     ++	int fract_mult = 100000000LL;
> >      +	int tmp, tmp2;
> >      +	int ret = 0;
> >      +
> >     @@ drivers/iio/test/iio-test-rescale.c (new)
> >      +	if (tmp < 0)
> >      +		tmp2 *= -1;
> >      +
> >     -+	*micro = (s64)tmp * 10 * fract_mult + tmp2;
> >     ++	*nano = (s64)tmp * 10 * fract_mult + tmp2;
> >      +
> >      +	return ret;
> >      +}
> >      +
> >      +/**
> >     -+ * iio_test_relative_error_ppm() - Compute relative error (in ppm) between two
> >     -+ *                                 fixed-point strings
> >     ++ * iio_test_relative_error_ppm() - Compute relative error (in parts-per-million)
> >     ++ *                                 between two fixed-point strings
> >      + * @real_str: The real value as a string
> >      + * @exp_str: The expected value as a string
> >      + *
> >      + * Returns a negative error code if the strings cound not be parsed, or the
> >     -+ * relative error in ppm.
> >     ++ * relative error in parts-per-million.
> >      + */
> >      +static int iio_test_relative_error_ppm(const char *real_str, const char *exp_str)
> >      +{
> >      +	s64 real, exp, err;
> >      +	int ret;
> >      +
> >     -+	ret = iio_str_to_micro(real_str, &real);
> >     ++	ret = iio_str_to_nano(real_str, &real);
> >      +	if (ret < 0)
> >      +		return ret;
> >      +
> >     -+	ret = iio_str_to_micro(exp_str, &exp);
> >     ++	ret = iio_str_to_nano(exp_str, &exp);
> >      +	if (ret < 0)
> >      +		return ret;
> >      +
> >     ++	if (!exp) {
> >     ++		pr_err("Expected value is null, relative error is undefined\n");
> >     ++		return -EINVAL;
> >     ++	}
> >     ++
> >      +	err = 1000000 * abs(exp - real);
> >      +	err = div64_u64(err, abs(exp));
> >      +	return (int)err;
> >     @@ drivers/iio/test/iio-test-rescale.c (new)
> >      +	rel_ppm = iio_test_relative_error_ppm(buff, t->expected);
> >      +	KUNIT_EXPECT_GE_MSG(test, rel_ppm, 0, "failed to compute ppm\n");
> >      +
> >     -+	KUNIT_EXPECT_LT_MSG(test, rel_ppm, 500,
> >     ++	KUNIT_EXPECT_EQ_MSG(test, rel_ppm, 0,
> >      +			    "\t    real=%s"
> >      +			    "\texpected=%s\n",
> >      +			    buff, t->expected);
> > 11:  050487186e14 = 11:  c4ed463e5fb0 iio: afe: rescale: add RTD temperature sensor support
> > 12:  f36a44a5d898 ! 12:  ff2f0dc248a7 iio: afe: rescale: add temperature transducers
> >     @@ drivers/iio/afe/iio-rescale.c: static int rescale_temp_sense_rtd_props(struct de
> >      +	s32 offset = 0;
> >      +	s32 sense = 1;
> >      +	s32 alpha;
> >     -+	s64 tmp;
> >      +	int ret;
> >      +
> >      +	device_property_read_u32(dev, "sense-offset-millicelsius", &offset);
> >     @@ drivers/iio/afe/iio-rescale.c: static int rescale_temp_sense_rtd_props(struct de
> >      +	rescale->numerator = 1000000;
> >      +	rescale->denominator = alpha * sense;
> >      +
> >     -+	tmp = (s64)offset * (s64)alpha * (s64)sense;
> >     -+	rescale->offset = div_s64(tmp, (s32)1000000);
> >     ++	rescale->offset = div_s64((s64)offset * rescale->denominator,
> >     ++				  rescale->numerator);
> >      +
> >      +	return 0;
> >      +}
> > 13:  63be647fd110 = 13:  84bc1f7d1ab5 dt-bindings: iio: afe: add bindings for temperature-sense-rtd
> > 14:  c2f5c19dece3 = 14:  1b76cfb37e23 dt-bindings: iio: afe: add bindings for temperature transducers
> > 
> > base-commit: 2b6bff0b122785f09cfbdc34b1aa9edceea6e4c1
> 



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux