From: Greg Kroah-Hartman Date: Fri, 6 Dec 2024 12:25:39 +0000 (+0100) Subject: 5.4-stable patches X-Git-Tag: v6.6.64~24 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1840afc008a21aa0b49db149bc01b4a5803a9633;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: i3c-master-fix-miss-free-init_dyn_addr-at-i3c_master_put_i3c_addrs.patch util_macros.h-fix-rework-find_closest-macros.patch --- diff --git a/queue-5.4/i3c-master-fix-miss-free-init_dyn_addr-at-i3c_master_put_i3c_addrs.patch b/queue-5.4/i3c-master-fix-miss-free-init_dyn_addr-at-i3c_master_put_i3c_addrs.patch new file mode 100644 index 00000000000..2c2a5fa1f8d --- /dev/null +++ b/queue-5.4/i3c-master-fix-miss-free-init_dyn_addr-at-i3c_master_put_i3c_addrs.patch @@ -0,0 +1,38 @@ +From 3082990592f7c6d7510a9133afa46e31bbe26533 Mon Sep 17 00:00:00 2001 +From: Frank Li +Date: Tue, 1 Oct 2024 12:26:08 -0400 +Subject: i3c: master: Fix miss free init_dyn_addr at i3c_master_put_i3c_addrs() + +From: Frank Li + +commit 3082990592f7c6d7510a9133afa46e31bbe26533 upstream. + +if (dev->boardinfo && dev->boardinfo->init_dyn_addr) + ^^^ here check "init_dyn_addr" + i3c_bus_set_addr_slot_status(&master->bus, dev->info.dyn_addr, ...) + ^^^^ + free "dyn_addr" +Fix copy/paste error "dyn_addr" by replacing it with "init_dyn_addr". + +Cc: stable@kernel.org +Fixes: 3a379bbcea0a ("i3c: Add core I3C infrastructure") +Reviewed-by: Miquel Raynal +Signed-off-by: Frank Li +Link: https://lore.kernel.org/r/20241001162608.224039-1-Frank.Li@nxp.com +Signed-off-by: Alexandre Belloni +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i3c/master.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/i3c/master.c ++++ b/drivers/i3c/master.c +@@ -1263,7 +1263,7 @@ static void i3c_master_put_i3c_addrs(str + I3C_ADDR_SLOT_FREE); + + if (dev->boardinfo && dev->boardinfo->init_dyn_addr) +- i3c_bus_set_addr_slot_status(&master->bus, dev->info.dyn_addr, ++ i3c_bus_set_addr_slot_status(&master->bus, dev->boardinfo->init_dyn_addr, + I3C_ADDR_SLOT_FREE); + } + diff --git a/queue-5.4/series b/queue-5.4/series index cf5ce71e3eb..ccf6ea1527e 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -212,3 +212,5 @@ ovl-filter-invalid-inodes-with-missing-lookup-function.patch ftrace-fix-regression-with-module-command-in-stack_trace_filter.patch clk-qcom-gcc-qcs404-fix-initial-rate-of-gpll3.patch ad7780-fix-division-by-zero-in-ad7780_write_raw.patch +util_macros.h-fix-rework-find_closest-macros.patch +i3c-master-fix-miss-free-init_dyn_addr-at-i3c_master_put_i3c_addrs.patch diff --git a/queue-5.4/util_macros.h-fix-rework-find_closest-macros.patch b/queue-5.4/util_macros.h-fix-rework-find_closest-macros.patch new file mode 100644 index 00000000000..4d32f9146b9 --- /dev/null +++ b/queue-5.4/util_macros.h-fix-rework-find_closest-macros.patch @@ -0,0 +1,187 @@ +From bc73b4186736341ab5cd2c199da82db6e1134e13 Mon Sep 17 00:00:00 2001 +From: Alexandru Ardelean +Date: Tue, 5 Nov 2024 16:54:05 +0200 +Subject: util_macros.h: fix/rework find_closest() macros + +From: Alexandru Ardelean + +commit bc73b4186736341ab5cd2c199da82db6e1134e13 upstream. + +A bug was found in the find_closest() (find_closest_descending() is also +affected after some testing), where for certain values with small +progressions, the rounding (done by averaging 2 values) causes an +incorrect index to be returned. The rounding issues occur for +progressions of 1, 2 and 3. It goes away when the progression/interval +between two values is 4 or larger. + +It's particularly bad for progressions of 1. For example if there's an +array of 'a = { 1, 2, 3 }', using 'find_closest(2, a ...)' would return 0 +(the index of '1'), rather than returning 1 (the index of '2'). This +means that for exact values (with a progression of 1), find_closest() will +misbehave and return the index of the value smaller than the one we're +searching for. + +For progressions of 2 and 3, the exact values are obtained correctly; but +values aren't approximated correctly (as one would expect). Starting with +progressions of 4, all seems to be good (one gets what one would expect). + +While one could argue that 'find_closest()' should not be used for arrays +with progressions of 1 (i.e. '{1, 2, 3, ...}', the macro should still +behave correctly. + +The bug was found while testing the 'drivers/iio/adc/ad7606.c', +specifically the oversampling feature. +For reference, the oversampling values are listed as: + static const unsigned int ad7606_oversampling_avail[7] = { + 1, 2, 4, 8, 16, 32, 64, + }; + +When doing: + 1. $ echo 1 > /sys/bus/iio/devices/iio\:device0/oversampling_ratio + $ cat /sys/bus/iio/devices/iio\:device0/oversampling_ratio + 1 # this is fine + 2. $ echo 2 > /sys/bus/iio/devices/iio\:device0/oversampling_ratio + $ cat /sys/bus/iio/devices/iio\:device0/oversampling_ratio + 1 # this is wrong; 2 should be returned here + 3. $ echo 3 > /sys/bus/iio/devices/iio\:device0/oversampling_ratio + $ cat /sys/bus/iio/devices/iio\:device0/oversampling_ratio + 2 # this is fine + 4. $ echo 4 > /sys/bus/iio/devices/iio\:device0/oversampling_ratio + $ cat /sys/bus/iio/devices/iio\:device0/oversampling_ratio + 4 # this is fine +And from here-on, the values are as correct (one gets what one would +expect.) + +While writing a kunit test for this bug, a peculiar issue was found for the +array in the 'drivers/hwmon/ina2xx.c' & 'drivers/iio/adc/ina2xx-adc.c' +drivers. While running the kunit test (for 'ina226_avg_tab' from these +drivers): + * idx = find_closest([-1 to 2], ina226_avg_tab, ARRAY_SIZE(ina226_avg_tab)); + This returns idx == 0, so value. + * idx = find_closest(3, ina226_avg_tab, ARRAY_SIZE(ina226_avg_tab)); + This returns idx == 0, value 1; and now one could argue whether 3 is + closer to 4 or to 1. This quirk only appears for value '3' in this + array, but it seems to be a another rounding issue. + * And from 4 onwards the 'find_closest'() works fine (one gets what one + would expect). + +This change reworks the find_closest() macros to also check the difference +between the left and right elements when 'x'. If the distance to the right +is smaller (than the distance to the left), the index is incremented by 1. +This also makes redundant the need for using the DIV_ROUND_CLOSEST() macro. + +In order to accommodate for any mix of negative + positive values, the +internal variables '__fc_x', '__fc_mid_x', '__fc_left' & '__fc_right' are +forced to 'long' type. This also addresses any potential bugs/issues with +'x' being of an unsigned type. In those situations any comparison between +signed & unsigned would be promoted to a comparison between 2 unsigned +numbers; this is especially annoying when '__fc_left' & '__fc_right' +underflow. + +The find_closest_descending() macro was also reworked and duplicated from +the find_closest(), and it is being iterated in reverse. The main reason +for this is to get the same indices as 'find_closest()' (but in reverse). +The comparison for '__fc_right < __fc_left' favors going the array in +ascending order. +For example for array '{ 1024, 512, 256, 128, 64, 16, 4, 1 }' and x = 3, we +get: + __fc_mid_x = 2 + __fc_left = -1 + __fc_right = -2 + Then '__fc_right < __fc_left' evaluates to true and '__fc_i++' becomes 7 + which is not quite incorrect, but 3 is closer to 4 than to 1. + +This change has been validated with the kunit from the next patch. + +Link: https://lkml.kernel.org/r/20241105145406.554365-1-aardelean@baylibre.com +Fixes: 95d119528b0b ("util_macros.h: add find_closest() macro") +Signed-off-by: Alexandru Ardelean +Cc: Bartosz Golaszewski +Cc: Greg Kroah-Hartman +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/util_macros.h | 56 +++++++++++++++++++++++++++++++------------- + 1 file changed, 40 insertions(+), 16 deletions(-) + +--- a/include/linux/util_macros.h ++++ b/include/linux/util_macros.h +@@ -2,19 +2,6 @@ + #ifndef _LINUX_HELPER_MACROS_H_ + #define _LINUX_HELPER_MACROS_H_ + +-#define __find_closest(x, a, as, op) \ +-({ \ +- typeof(as) __fc_i, __fc_as = (as) - 1; \ +- typeof(x) __fc_x = (x); \ +- typeof(*a) const *__fc_a = (a); \ +- for (__fc_i = 0; __fc_i < __fc_as; __fc_i++) { \ +- if (__fc_x op DIV_ROUND_CLOSEST(__fc_a[__fc_i] + \ +- __fc_a[__fc_i + 1], 2)) \ +- break; \ +- } \ +- (__fc_i); \ +-}) +- + /** + * find_closest - locate the closest element in a sorted array + * @x: The reference value. +@@ -23,8 +10,27 @@ + * @as: Size of 'a'. + * + * Returns the index of the element closest to 'x'. ++ * Note: If using an array of negative numbers (or mixed positive numbers), ++ * then be sure that 'x' is of a signed-type to get good results. + */ +-#define find_closest(x, a, as) __find_closest(x, a, as, <=) ++#define find_closest(x, a, as) \ ++({ \ ++ typeof(as) __fc_i, __fc_as = (as) - 1; \ ++ long __fc_mid_x, __fc_x = (x); \ ++ long __fc_left, __fc_right; \ ++ typeof(*a) const *__fc_a = (a); \ ++ for (__fc_i = 0; __fc_i < __fc_as; __fc_i++) { \ ++ __fc_mid_x = (__fc_a[__fc_i] + __fc_a[__fc_i + 1]) / 2; \ ++ if (__fc_x <= __fc_mid_x) { \ ++ __fc_left = __fc_x - __fc_a[__fc_i]; \ ++ __fc_right = __fc_a[__fc_i + 1] - __fc_x; \ ++ if (__fc_right < __fc_left) \ ++ __fc_i++; \ ++ break; \ ++ } \ ++ } \ ++ (__fc_i); \ ++}) + + /** + * find_closest_descending - locate the closest element in a sorted array +@@ -34,8 +40,26 @@ + * @as: Size of 'a'. + * + * Similar to find_closest() but 'a' is expected to be sorted in descending +- * order. ++ * order. The iteration is done in reverse order, so that the comparison ++ * of '__fc_right' & '__fc_left' also works for unsigned numbers. + */ +-#define find_closest_descending(x, a, as) __find_closest(x, a, as, >=) ++#define find_closest_descending(x, a, as) \ ++({ \ ++ typeof(as) __fc_i, __fc_as = (as) - 1; \ ++ long __fc_mid_x, __fc_x = (x); \ ++ long __fc_left, __fc_right; \ ++ typeof(*a) const *__fc_a = (a); \ ++ for (__fc_i = __fc_as; __fc_i >= 1; __fc_i--) { \ ++ __fc_mid_x = (__fc_a[__fc_i] + __fc_a[__fc_i - 1]) / 2; \ ++ if (__fc_x <= __fc_mid_x) { \ ++ __fc_left = __fc_x - __fc_a[__fc_i]; \ ++ __fc_right = __fc_a[__fc_i - 1] - __fc_x; \ ++ if (__fc_right < __fc_left) \ ++ __fc_i--; \ ++ break; \ ++ } \ ++ } \ ++ (__fc_i); \ ++}) + + #endif