cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

iio-test-rescale.c (17733B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Kunit tests for IIO rescale conversions
      4 *
      5 * Copyright (c) 2021 Liam Beguin <liambeguin@gmail.com>
      6 */
      7
      8#include <linux/gcd.h>
      9#include <linux/overflow.h>
     10
     11#include <linux/iio/afe/rescale.h>
     12#include <linux/iio/iio.h>
     13
     14#include <kunit/test.h>
     15
     16struct rescale_tc_data {
     17	const char *name;
     18
     19	const s32 numerator;
     20	const s32 denominator;
     21	const s32 offset;
     22
     23	const int schan_val;
     24	const int schan_val2;
     25	const int schan_off;
     26	const int schan_scale_type;
     27
     28	const char *expected;
     29	const char *expected_off;
     30};
     31
     32const struct rescale_tc_data scale_cases[] = {
     33	/*
     34	 * Typical use cases
     35	 */
     36	{
     37		.name = "typical IIO_VAL_INT, positive",
     38		.numerator = 1000000,
     39		.denominator = 8060,
     40		.schan_scale_type = IIO_VAL_INT,
     41		.schan_val = 42,
     42		.expected = "5210.918114143",
     43	},
     44	{
     45		.name = "typical IIO_VAL_INT, negative",
     46		.numerator = -1000000,
     47		.denominator = 8060,
     48		.schan_scale_type = IIO_VAL_INT,
     49		.schan_val = 42,
     50		.expected = "-5210.918114143",
     51	},
     52	{
     53		.name = "typical IIO_VAL_FRACTIONAL, positive",
     54		.numerator = 1000000,
     55		.denominator = 8060,
     56		.schan_scale_type = IIO_VAL_FRACTIONAL,
     57		.schan_val = 42,
     58		.schan_val2 = 20,
     59		.expected = "260.545905707",
     60	},
     61	{
     62		.name = "typical IIO_VAL_FRACTIONAL, negative",
     63		.numerator = -1000000,
     64		.denominator = 8060,
     65		.schan_scale_type = IIO_VAL_FRACTIONAL,
     66		.schan_val = 42,
     67		.schan_val2 = 20,
     68		.expected = "-260.545905707",
     69	},
     70	{
     71		.name = "typical IIO_VAL_FRACTIONAL_LOG2, positive",
     72		.numerator = 42,
     73		.denominator = 53,
     74		.schan_scale_type = IIO_VAL_FRACTIONAL_LOG2,
     75		.schan_val = 4096,
     76		.schan_val2 = 16,
     77		.expected = "0.049528301",
     78	},
     79	{
     80		.name = "typical IIO_VAL_FRACTIONAL_LOG2, negative",
     81		.numerator = -42,
     82		.denominator = 53,
     83		.schan_scale_type = IIO_VAL_FRACTIONAL_LOG2,
     84		.schan_val = 4096,
     85		.schan_val2 = 16,
     86		.expected = "-0.049528301",
     87	},
     88	{
     89		.name = "typical IIO_VAL_INT_PLUS_NANO, positive",
     90		.numerator = 1000000,
     91		.denominator = 8060,
     92		.schan_scale_type = IIO_VAL_INT_PLUS_NANO,
     93		.schan_val = 10,
     94		.schan_val2 = 123456,
     95		.expected = "1240.710106203",
     96	},
     97	{
     98		.name = "typical IIO_VAL_INT_PLUS_NANO, negative",
     99		.numerator = -1000000,
    100		.denominator = 8060,
    101		.schan_scale_type = IIO_VAL_INT_PLUS_NANO,
    102		.schan_val = 10,
    103		.schan_val2 = 123456,
    104		.expected = "-1240.710106203",
    105	},
    106	{
    107		.name = "typical IIO_VAL_INT_PLUS_MICRO, positive",
    108		.numerator = 1000000,
    109		.denominator = 8060,
    110		.schan_scale_type = IIO_VAL_INT_PLUS_MICRO,
    111		.schan_val = 10,
    112		.schan_val2 = 1234,
    113		.expected = "1240.84789",
    114	},
    115	{
    116		.name = "typical IIO_VAL_INT_PLUS_MICRO, negative",
    117		.numerator = -1000000,
    118		.denominator = 8060,
    119		.schan_scale_type = IIO_VAL_INT_PLUS_MICRO,
    120		.schan_val = 10,
    121		.schan_val2 = 1234,
    122		.expected = "-1240.84789",
    123	},
    124	/*
    125	 * Use cases with small scales involving divisions
    126	 */
    127	{
    128		.name = "small IIO_VAL_FRACTIONAL, 261/509 scaled by 90/1373754273",
    129		.numerator = 261,
    130		.denominator = 509,
    131		.schan_scale_type = IIO_VAL_FRACTIONAL,
    132		.schan_val = 90,
    133		.schan_val2 = 1373754273,
    134		.expected = "0.000000033594",
    135	},
    136	{
    137		.name = "small IIO_VAL_FRACTIONAL, 90/1373754273 scaled by 261/509",
    138		.numerator = 90,
    139		.denominator = 1373754273,
    140		.schan_scale_type = IIO_VAL_FRACTIONAL,
    141		.schan_val = 261,
    142		.schan_val2 = 509,
    143		.expected = "0.000000033594",
    144	},
    145	{
    146		.name = "small IIO_VAL_FRACTIONAL, 760/1373754273 scaled by 427/2727",
    147		.numerator = 760,
    148		.denominator = 1373754273,
    149		.schan_scale_type = IIO_VAL_FRACTIONAL,
    150		.schan_val = 427,
    151		.schan_val2 = 2727,
    152		.expected = "0.000000086626",
    153	},
    154	{
    155		.name = "small IIO_VAL_FRACTIONAL, 761/1373754273 scaled by 427/2727",
    156		.numerator = 761,
    157		.denominator = 1373754273,
    158		.schan_scale_type = IIO_VAL_FRACTIONAL,
    159		.schan_val = 427,
    160		.schan_val2 = 2727,
    161		.expected = "0.000000086740",
    162	},
    163	{
    164		.name = "small IIO_VAL_FRACTIONAL, 5/32768 scaled by 3/10000",
    165		.numerator = 5,
    166		.denominator = 32768,
    167		.schan_scale_type = IIO_VAL_FRACTIONAL,
    168		.schan_val = 3,
    169		.schan_val2 = 10000,
    170		.expected = "0.0000000457763671875",
    171	},
    172	{
    173		.name = "small IIO_VAL_FRACTIONAL, 0 < scale < 1",
    174		.numerator = 6,
    175		.denominator = 6,
    176		.schan_scale_type = IIO_VAL_FRACTIONAL,
    177		.schan_val = 1,
    178		.schan_val2 = 3,
    179		.expected = "0.3333333333333333",
    180	},
    181	{
    182		.name = "small IIO_VAL_FRACTIONAL, -1 < scale < 0",
    183		.numerator = -6,
    184		.denominator = 6,
    185		.schan_scale_type = IIO_VAL_FRACTIONAL,
    186		.schan_val = 1,
    187		.schan_val2 = 3,
    188		.expected = "-0.3333333333333333",
    189	},
    190	{
    191		.name = "small IIO_VAL_FRACTIONAL, 0 < scale < 2",
    192		.numerator = 8,
    193		.denominator = 2,
    194		.schan_scale_type = IIO_VAL_FRACTIONAL,
    195		.schan_val = 1,
    196		.schan_val2 = 3,
    197		.expected = "1.3333333333333333",
    198	},
    199	{
    200		.name = "small IIO_VAL_FRACTIONAL, -2 < scale < 0",
    201		.numerator = -8,
    202		.denominator = 2,
    203		.schan_scale_type = IIO_VAL_FRACTIONAL,
    204		.schan_val = 1,
    205		.schan_val2 = 3,
    206		.expected = "-1.3333333333333333",
    207	},
    208	{
    209		.name = "small IIO_VAL_FRACTIONAL_LOG2, 760/32768 scaled by 15/22",
    210		.numerator = 760,
    211		.denominator = 32768,
    212		.schan_scale_type = IIO_VAL_FRACTIONAL_LOG2,
    213		.schan_val = 15,
    214		.schan_val2 = 22,
    215		.expected = "0.000000082946",
    216	},
    217	{
    218		.name = "small IIO_VAL_FRACTIONAL_LOG2, 761/32768 scaled by 15/22",
    219		.numerator = 761,
    220		.denominator = 32768,
    221		.schan_scale_type = IIO_VAL_FRACTIONAL_LOG2,
    222		.schan_val = 15,
    223		.schan_val2 = 22,
    224		.expected = "0.000000083055",
    225	},
    226	{
    227		.name = "small IIO_VAL_FRACTIONAL_LOG2, 0 < scale < 1",
    228		.numerator = 16,
    229		.denominator = 3,
    230		.schan_scale_type = IIO_VAL_FRACTIONAL_LOG2,
    231		.schan_val = 1,
    232		.schan_val2 = 4,
    233		.expected = "0.3333333333333333",
    234	},
    235	{
    236		.name = "small IIO_VAL_FRACTIONAL_LOG2, -1 < scale < 0",
    237		.numerator = -16,
    238		.denominator = 3,
    239		.schan_scale_type = IIO_VAL_FRACTIONAL_LOG2,
    240		.schan_val = 1,
    241		.schan_val2 = 4,
    242		.expected = "-0.3333333333333333",
    243	},
    244	{
    245		.name = "small IIO_VAL_FRACTIONAL_LOG2, 0 < scale < 2",
    246		.numerator = 8,
    247		.denominator = 3,
    248		.schan_scale_type = IIO_VAL_FRACTIONAL_LOG2,
    249		.schan_val = 1,
    250		.schan_val2 = 1,
    251		.expected = "1.3333333333333333",
    252	},
    253	{
    254		.name = "small IIO_VAL_FRACTIONAL_LOG2, -2 < scale < 0",
    255		.numerator = -8,
    256		.denominator = 3,
    257		.schan_scale_type = IIO_VAL_FRACTIONAL_LOG2,
    258		.schan_val = 1,
    259		.schan_val2 = 1,
    260		.expected = "-1.3333333333333333",
    261	},
    262	{
    263		.name = "small IIO_VAL_INT_PLUS_MICRO, positive",
    264		.numerator = 1,
    265		.denominator = 2,
    266		.schan_scale_type = IIO_VAL_INT_PLUS_MICRO,
    267		.schan_val = 5,
    268		.schan_val2 = 1234,
    269		.expected = "2.500617",
    270	},
    271	{
    272		.name = "small IIO_VAL_INT_PLUS_MICRO, negative",
    273		.numerator = -1,
    274		.denominator = 2,
    275		.schan_scale_type = IIO_VAL_INT_PLUS_MICRO,
    276		.schan_val = 5,
    277		.schan_val2 = 1234,
    278		.expected = "-2.500617",
    279	},
    280	/*
    281	 * INT_PLUS_{MICRO,NANO} positive/negative corner cases
    282	 */
    283	{
    284		.name = "negative IIO_VAL_INT_PLUS_NANO, negative schan",
    285		.numerator = 1000000,
    286		.denominator = 8060,
    287		.schan_scale_type = IIO_VAL_INT_PLUS_NANO,
    288		.schan_val = -10,
    289		.schan_val2 = 123456,
    290		.expected = "-1240.710106203",
    291	},
    292	{
    293		.name = "negative IIO_VAL_INT_PLUS_NANO, both negative",
    294		.numerator = -1000000,
    295		.denominator = 8060,
    296		.schan_scale_type = IIO_VAL_INT_PLUS_NANO,
    297		.schan_val = -10,
    298		.schan_val2 = 123456,
    299		.expected = "1240.710106203",
    300	},
    301	{
    302		.name = "negative IIO_VAL_INT_PLUS_NANO, 3 negative",
    303		.numerator = -1000000,
    304		.denominator = -8060,
    305		.schan_scale_type = IIO_VAL_INT_PLUS_NANO,
    306		.schan_val = -10,
    307		.schan_val2 = 123456,
    308		.expected = "-1240.710106203",
    309	},
    310	{
    311		.name = "negative IIO_VAL_INT_PLUS_NANO, 4 negative",
    312		.numerator = -1000000,
    313		.denominator = -8060,
    314		.schan_scale_type = IIO_VAL_INT_PLUS_NANO,
    315		.schan_val = -10,
    316		.schan_val2 = -123456,
    317		.expected = "-1240.710106203",
    318	},
    319	{
    320		.name = "negative IIO_VAL_INT_PLUS_NANO, negative, *val = 0",
    321		.numerator = 1,
    322		.denominator = -10,
    323		.schan_scale_type = IIO_VAL_INT_PLUS_NANO,
    324		.schan_val = 0,
    325		.schan_val2 = 123456789,
    326		.expected = "-0.012345678",
    327	},
    328	/*
    329	 * INT_PLUS_{MICRO,NANO} decimal part overflow
    330	 */
    331	{
    332		.name = "decimal overflow IIO_VAL_INT_PLUS_NANO, positive",
    333		.numerator = 1000000,
    334		.denominator = 8060,
    335		.schan_scale_type = IIO_VAL_INT_PLUS_NANO,
    336		.schan_val = 10,
    337		.schan_val2 = 123456789,
    338		.expected = "1256.01200856",
    339	},
    340	{
    341		.name = "decimal overflow IIO_VAL_INT_PLUS_NANO, negative",
    342		.numerator = -1000000,
    343		.denominator = 8060,
    344		.schan_scale_type = IIO_VAL_INT_PLUS_NANO,
    345		.schan_val = 10,
    346		.schan_val2 = 123456789,
    347		.expected = "-1256.01200856",
    348	},
    349	{
    350		.name = "decimal overflow IIO_VAL_INT_PLUS_NANO, negative schan",
    351		.numerator = 1000000,
    352		.denominator = 8060,
    353		.schan_scale_type = IIO_VAL_INT_PLUS_NANO,
    354		.schan_val = -10,
    355		.schan_val2 = 123456789,
    356		.expected = "-1256.01200856",
    357	},
    358	{
    359		.name = "decimal overflow IIO_VAL_INT_PLUS_MICRO, positive",
    360		.numerator = 1000000,
    361		.denominator = 8060,
    362		.schan_scale_type = IIO_VAL_INT_PLUS_MICRO,
    363		.schan_val = 10,
    364		.schan_val2 = 123456789,
    365		.expected = "16557.914267",
    366	},
    367	{
    368		.name = "decimal overflow IIO_VAL_INT_PLUS_MICRO, negative",
    369		.numerator = -1000000,
    370		.denominator = 8060,
    371		.schan_scale_type = IIO_VAL_INT_PLUS_MICRO,
    372		.schan_val = 10,
    373		.schan_val2 = 123456789,
    374		.expected = "-16557.914267",
    375	},
    376	{
    377		.name = "decimal overflow IIO_VAL_INT_PLUS_MICRO, negative schan",
    378		.numerator = 1000000,
    379		.denominator = 8060,
    380		.schan_scale_type = IIO_VAL_INT_PLUS_MICRO,
    381		.schan_val = -10,
    382		.schan_val2 = 123456789,
    383		.expected = "-16557.914267",
    384	},
    385	/*
    386	 * 32-bit overflow conditions
    387	 */
    388	{
    389		.name = "overflow IIO_VAL_FRACTIONAL, positive",
    390		.numerator = 2,
    391		.denominator = 20,
    392		.schan_scale_type = IIO_VAL_FRACTIONAL,
    393		.schan_val = S32_MAX,
    394		.schan_val2 = 1,
    395		.expected = "214748364.7",
    396	},
    397	{
    398		.name = "overflow IIO_VAL_FRACTIONAL, negative",
    399		.numerator = -2,
    400		.denominator = 20,
    401		.schan_scale_type = IIO_VAL_FRACTIONAL,
    402		.schan_val = S32_MAX,
    403		.schan_val2 = 1,
    404		.expected = "-214748364.7",
    405	},
    406	{
    407		.name = "overflow IIO_VAL_FRACTIONAL_LOG2, positive",
    408		.numerator = S32_MAX,
    409		.denominator = 4096,
    410		.schan_scale_type = IIO_VAL_FRACTIONAL_LOG2,
    411		.schan_val = 4096,
    412		.schan_val2 = 16,
    413		.expected = "32767.99998474121",
    414	},
    415	{
    416		.name = "overflow IIO_VAL_FRACTIONAL_LOG2, negative",
    417		.numerator = S32_MAX,
    418		.denominator = 4096,
    419		.schan_scale_type = IIO_VAL_FRACTIONAL_LOG2,
    420		.schan_val = -4096,
    421		.schan_val2 = 16,
    422		.expected = "-32767.99998474121",
    423	},
    424	{
    425		.name = "overflow IIO_VAL_INT_PLUS_NANO, positive",
    426		.numerator = 2,
    427		.denominator = 20,
    428		.schan_scale_type = IIO_VAL_INT_PLUS_NANO,
    429		.schan_val = 10,
    430		.schan_val2 = S32_MAX,
    431		.expected = "1.214748364",
    432	},
    433	{
    434		.name = "overflow IIO_VAL_INT_PLUS_NANO, negative",
    435		.numerator = -2,
    436		.denominator = 20,
    437		.schan_scale_type = IIO_VAL_INT_PLUS_NANO,
    438		.schan_val = 10,
    439		.schan_val2 = S32_MAX,
    440		.expected = "-1.214748364",
    441	},
    442	{
    443		.name = "overflow IIO_VAL_INT_PLUS_NANO, negative schan",
    444		.numerator = 2,
    445		.denominator = 20,
    446		.schan_scale_type = IIO_VAL_INT_PLUS_NANO,
    447		.schan_val = -10,
    448		.schan_val2 = S32_MAX,
    449		.expected = "-1.214748364",
    450	},
    451	{
    452		.name = "overflow IIO_VAL_INT_PLUS_MICRO, positive",
    453		.numerator = 2,
    454		.denominator = 20,
    455		.schan_scale_type = IIO_VAL_INT_PLUS_MICRO,
    456		.schan_val = 10,
    457		.schan_val2 = S32_MAX,
    458		.expected = "215.748364",
    459	},
    460	{
    461		.name = "overflow IIO_VAL_INT_PLUS_MICRO, negative",
    462		.numerator = -2,
    463		.denominator = 20,
    464		.schan_scale_type = IIO_VAL_INT_PLUS_MICRO,
    465		.schan_val = 10,
    466		.schan_val2 = S32_MAX,
    467		.expected = "-215.748364",
    468	},
    469	{
    470		.name = "overflow IIO_VAL_INT_PLUS_MICRO, negative schan",
    471		.numerator = 2,
    472		.denominator = 20,
    473		.schan_scale_type = IIO_VAL_INT_PLUS_MICRO,
    474		.schan_val = -10,
    475		.schan_val2 = S32_MAX,
    476		.expected = "-215.748364",
    477	},
    478};
    479
    480const struct rescale_tc_data offset_cases[] = {
    481	/*
    482	 * Typical use cases
    483	 */
    484	{
    485		.name = "typical IIO_VAL_INT, positive",
    486		.offset = 1234,
    487		.schan_scale_type = IIO_VAL_INT,
    488		.schan_val = 123,
    489		.schan_val2 = 0,
    490		.schan_off = 14,
    491		.expected_off = "24", /* 23.872 */
    492	},
    493	{
    494		.name = "typical IIO_VAL_INT, negative",
    495		.offset = -1234,
    496		.schan_scale_type = IIO_VAL_INT,
    497		.schan_val = 12,
    498		.schan_val2 = 0,
    499		.schan_off = 14,
    500		.expected_off = "-88", /* -88.83333333333333 */
    501	},
    502	{
    503		.name = "typical IIO_VAL_FRACTIONAL, positive",
    504		.offset = 1234,
    505		.schan_scale_type = IIO_VAL_FRACTIONAL,
    506		.schan_val = 12,
    507		.schan_val2 = 34,
    508		.schan_off = 14,
    509		.expected_off = "3510", /* 3510.333333333333 */
    510	},
    511	{
    512		.name = "typical IIO_VAL_FRACTIONAL, negative",
    513		.offset = -1234,
    514		.schan_scale_type = IIO_VAL_FRACTIONAL,
    515		.schan_val = 12,
    516		.schan_val2 = 34,
    517		.schan_off = 14,
    518		.expected_off = "-3482", /* -3482.333333333333 */
    519	},
    520	{
    521		.name = "typical IIO_VAL_FRACTIONAL_LOG2, positive",
    522		.offset = 1234,
    523		.schan_scale_type = IIO_VAL_FRACTIONAL_LOG2,
    524		.schan_val = 12,
    525		.schan_val2 = 16,
    526		.schan_off = 14,
    527		.expected_off = "6739299", /* 6739299.333333333 */
    528	},
    529	{
    530		.name = "typical IIO_VAL_FRACTIONAL_LOG2, negative",
    531		.offset = -1234,
    532		.schan_scale_type = IIO_VAL_FRACTIONAL_LOG2,
    533		.schan_val = 12,
    534		.schan_val2 = 16,
    535		.schan_off = 14,
    536		.expected_off = "-6739271", /* -6739271.333333333 */
    537	},
    538	{
    539		.name = "typical IIO_VAL_INT_PLUS_NANO, positive",
    540		.offset = 1234,
    541		.schan_scale_type = IIO_VAL_INT_PLUS_NANO,
    542		.schan_val = 10,
    543		.schan_val2 = 123456789,
    544		.schan_off = 14,
    545		.expected_off = "135", /* 135.8951219647469 */
    546	},
    547	{
    548		.name = "typical IIO_VAL_INT_PLUS_NANO, negative",
    549		.offset = -1234,
    550		.schan_scale_type = IIO_VAL_INT_PLUS_NANO,
    551		.schan_val = 10,
    552		.schan_val2 = 123456789,
    553		.schan_off = 14,
    554		.expected_off = "-107", /* -107.89512196474689 */
    555	},
    556	{
    557		.name = "typical IIO_VAL_INT_PLUS_MICRO, positive",
    558		.offset = 1234,
    559		.schan_scale_type = IIO_VAL_INT_PLUS_MICRO,
    560		.schan_val = 10,
    561		.schan_val2 = 123456789,
    562		.schan_off = 14,
    563		.expected_off = "23", /* 23.246438560723952 */
    564	},
    565	{
    566		.name = "typical IIO_VAL_INT_PLUS_MICRO, negative",
    567		.offset = -12345,
    568		.schan_scale_type = IIO_VAL_INT_PLUS_MICRO,
    569		.schan_val = 10,
    570		.schan_val2 = 123456789,
    571		.schan_off = 14,
    572		.expected_off = "-78", /* -78.50185091745313 */
    573	},
    574};
    575
    576static void case_to_desc(const struct rescale_tc_data *t, char *desc)
    577{
    578	strcpy(desc, t->name);
    579}
    580
    581KUNIT_ARRAY_PARAM(iio_rescale_scale, scale_cases, case_to_desc);
    582KUNIT_ARRAY_PARAM(iio_rescale_offset, offset_cases, case_to_desc);
    583
    584/**
    585 * iio_str_to_nano() - Parse a fixed-point string to get an
    586 *                      IIO_VAL_INT_PLUS_NANO value
    587 * @str: The string to parse
    588 * @nano: The number as an integer
    589 *
    590 * Returns 0 on success, or a negative error code if the string cound not be
    591 * parsed.
    592 */
    593static int iio_str_to_nano(const char *str, s64 *nano)
    594{
    595	int tmp, tmp2;
    596	int ret = 0;
    597
    598	/*
    599	 * iio_str_to_fixpoint() uses 10^8 here instead of 10^9 as fract_mult is
    600	 * the multiplier for the first decimal place.
    601	 */
    602	ret = iio_str_to_fixpoint(str, 100000000, &tmp, &tmp2);
    603	if (ret < 0)
    604		return ret;
    605
    606	if (tmp < 0)
    607		tmp2 *= -1;
    608
    609	*nano = (s64)tmp * 1000000000UL + tmp2;
    610
    611	return ret;
    612}
    613
    614/**
    615 * iio_test_relative_error_ppm() - Compute relative error (in parts-per-million)
    616 *                                 between two fixed-point strings
    617 * @real_str: The real value as a string
    618 * @exp_str: The expected value as a string
    619 *
    620 * Returns a negative error code if the strings cound not be parsed, or the
    621 * relative error in parts-per-million.
    622 */
    623static int iio_test_relative_error_ppm(const char *real_str, const char *exp_str)
    624{
    625	s64 real, exp, err;
    626	int ret;
    627
    628	ret = iio_str_to_nano(real_str, &real);
    629	if (ret < 0)
    630		return ret;
    631
    632	ret = iio_str_to_nano(exp_str, &exp);
    633	if (ret < 0)
    634		return ret;
    635
    636	if (!exp) {
    637		pr_err("Expected value is null, relative error is undefined\n");
    638		return -EINVAL;
    639	}
    640
    641	err = 1000000UL * abs(exp - real);
    642
    643	return (int)div64_u64(err, abs(exp));
    644}
    645
    646static void iio_rescale_test_scale(struct kunit *test)
    647{
    648	struct rescale_tc_data *t = (struct rescale_tc_data *)test->param_value;
    649	char *buff = kunit_kmalloc(test, PAGE_SIZE, GFP_KERNEL);
    650	struct rescale rescale;
    651	int values[2];
    652	int rel_ppm;
    653	int ret;
    654
    655	rescale.numerator = t->numerator;
    656	rescale.denominator = t->denominator;
    657	rescale.offset = t->offset;
    658	values[0] = t->schan_val;
    659	values[1] = t->schan_val2;
    660
    661	ret = rescale_process_scale(&rescale, t->schan_scale_type,
    662				    &values[0], &values[1]);
    663
    664	ret = iio_format_value(buff, ret, 2, values);
    665	KUNIT_EXPECT_EQ(test, (int)strlen(buff), ret);
    666
    667	rel_ppm = iio_test_relative_error_ppm(buff, t->expected);
    668	KUNIT_EXPECT_GE_MSG(test, rel_ppm, 0, "failed to compute ppm\n");
    669
    670	KUNIT_EXPECT_EQ_MSG(test, rel_ppm, 0,
    671			    "\t    real=%s"
    672			    "\texpected=%s\n",
    673			    buff, t->expected);
    674}
    675
    676static void iio_rescale_test_offset(struct kunit *test)
    677{
    678	struct rescale_tc_data *t = (struct rescale_tc_data *)test->param_value;
    679	char *buff_off = kunit_kmalloc(test, PAGE_SIZE, GFP_KERNEL);
    680	struct rescale rescale;
    681	int values[2];
    682	int ret;
    683
    684	rescale.numerator = t->numerator;
    685	rescale.denominator = t->denominator;
    686	rescale.offset = t->offset;
    687	values[0] = t->schan_val;
    688	values[1] = t->schan_val2;
    689
    690	ret = rescale_process_offset(&rescale, t->schan_scale_type,
    691				     t->schan_val, t->schan_val2, t->schan_off,
    692				     &values[0], &values[1]);
    693
    694	ret = iio_format_value(buff_off, ret, 2, values);
    695	KUNIT_EXPECT_EQ(test, (int)strlen(buff_off), ret);
    696
    697	KUNIT_EXPECT_STREQ(test, strim(buff_off), t->expected_off);
    698}
    699
    700static struct kunit_case iio_rescale_test_cases[] = {
    701	KUNIT_CASE_PARAM(iio_rescale_test_scale, iio_rescale_scale_gen_params),
    702	KUNIT_CASE_PARAM(iio_rescale_test_offset, iio_rescale_offset_gen_params),
    703	{}
    704};
    705
    706static struct kunit_suite iio_rescale_test_suite = {
    707	.name = "iio-rescale",
    708	.test_cases = iio_rescale_test_cases,
    709};
    710kunit_test_suite(iio_rescale_test_suite);