From da9374819eb3885636934c1006d450c3cb1a02ed Mon Sep 17 00:00:00 2001 From: Markus Burri Date: Thu, 8 May 2025 15:06:07 +0200 Subject: [PATCH 01/35] iio: backend: fix out-of-bound write MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The buffer is set to 80 character. If a caller write more characters, count is truncated to the max available space in "simple_write_to_buffer". But afterwards a string terminator is written to the buffer at offset count without boundary check. The zero termination is written OUT-OF-BOUND. Add a check that the given buffer is smaller then the buffer to prevent. Fixes: 035b4989211d ("iio: backend: make sure to NULL terminate stack buffer") Signed-off-by: Markus Burri Reviewed-by: Nuno Sá Link: https://patch.msgid.link/20250508130612.82270-2-markus.burri@mt.com Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-backend.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-backend.c index c1eb9ef9db08..266e1b29bf91 100644 --- a/drivers/iio/industrialio-backend.c +++ b/drivers/iio/industrialio-backend.c @@ -155,11 +155,14 @@ static ssize_t iio_backend_debugfs_write_reg(struct file *file, ssize_t rc; int ret; + if (count >= sizeof(buf)) + return -ENOSPC; + rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, userbuf, count); if (rc < 0) return rc; - buf[count] = '\0'; + buf[rc] = '\0'; ret = sscanf(buf, "%i %i", &back->cached_reg_addr, &val); From 16285a0931869baa618b1f5d304e1e9d090470a8 Mon Sep 17 00:00:00 2001 From: Markus Burri Date: Thu, 8 May 2025 15:06:09 +0200 Subject: [PATCH 02/35] iio: fix potential out-of-bound write The buffer is set to 20 characters. If a caller write more characters, count is truncated to the max available space in "simple_write_to_buffer". To protect from OoB access, check that the input size fit into buffer and add a zero terminator after copy to the end of the copied data. Fixes: 6d5dd486c715 iio: core: make use of simple_write_to_buffer() Signed-off-by: Markus Burri Link: https://patch.msgid.link/20250508130612.82270-4-markus.burri@mt.com Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 178e99b111de..5ffda104d4b2 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -411,12 +411,15 @@ static ssize_t iio_debugfs_write_reg(struct file *file, char buf[80]; int ret; + if (count >= sizeof(buf)) + return -EINVAL; + ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, userbuf, count); if (ret < 0) return ret; - buf[count] = '\0'; + buf[ret] = '\0'; ret = sscanf(buf, "%i %i", ®, &val); From e8ad595064f6ebd5d2d1a5d5d7ebe0efce623091 Mon Sep 17 00:00:00 2001 From: Chen Ni Date: Thu, 15 May 2025 16:31:01 +0800 Subject: [PATCH 03/35] iio: adc: stm32-adc: Fix race in installing chained IRQ handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix a race where a pending interrupt could be received and the handler called before the handler's data has been setup, by converting to irq_set_chained_handler_and_data(). Fixes: 1add69880240 ("iio: adc: Add support for STM32 ADC core") Signed-off-by: Chen Ni Reviewed-by: Nuno Sá Tested-by: Fabrice Gasnier Reviewed-by: Fabrice Gasnier Link: https://patch.msgid.link/20250515083101.3811350-1-nichen@iscas.ac.cn Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/stm32-adc-core.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c index bd3458965bff..21c04a98b3b6 100644 --- a/drivers/iio/adc/stm32-adc-core.c +++ b/drivers/iio/adc/stm32-adc-core.c @@ -430,10 +430,9 @@ static int stm32_adc_irq_probe(struct platform_device *pdev, return -ENOMEM; } - for (i = 0; i < priv->cfg->num_irqs; i++) { - irq_set_chained_handler(priv->irq[i], stm32_adc_irq_handler); - irq_set_handler_data(priv->irq[i], priv); - } + for (i = 0; i < priv->cfg->num_irqs; i++) + irq_set_chained_handler_and_data(priv->irq[i], + stm32_adc_irq_handler, priv); return 0; } From 6d21f2c2dd843bceefd9455f2919f6bb526797f0 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 16 May 2025 14:38:59 -0300 Subject: [PATCH 04/35] iio: adc: max1363: Fix MAX1363_4X_CHANS/MAX1363_8X_CHANS[] Since commit 2718f15403fb ("iio: sanity check available_scan_masks array"), booting a board populated with a MAX11601 results in a flood of warnings: max1363 1-0064: available_scan_mask 8 subset of 0. Never used max1363 1-0064: available_scan_mask 9 subset of 0. Never used max1363 1-0064: available_scan_mask 10 subset of 0. Never used max1363 1-0064: available_scan_mask 11 subset of 0. Never used max1363 1-0064: available_scan_mask 12 subset of 0. Never used max1363 1-0064: available_scan_mask 13 subset of 0. Never used ... These warnings are caused by incorrect offsets used for differential channels in the MAX1363_4X_CHANS() and MAX1363_8X_CHANS() macros. The max1363_mode_table[] defines the differential channel mappings as follows: MAX1363_MODE_DIFF_SINGLE(0, 1, 1 << 12), MAX1363_MODE_DIFF_SINGLE(2, 3, 1 << 13), MAX1363_MODE_DIFF_SINGLE(4, 5, 1 << 14), MAX1363_MODE_DIFF_SINGLE(6, 7, 1 << 15), MAX1363_MODE_DIFF_SINGLE(8, 9, 1 << 16), MAX1363_MODE_DIFF_SINGLE(10, 11, 1 << 17), MAX1363_MODE_DIFF_SINGLE(1, 0, 1 << 18), MAX1363_MODE_DIFF_SINGLE(3, 2, 1 << 19), MAX1363_MODE_DIFF_SINGLE(5, 4, 1 << 20), MAX1363_MODE_DIFF_SINGLE(7, 6, 1 << 21), MAX1363_MODE_DIFF_SINGLE(9, 8, 1 << 22), MAX1363_MODE_DIFF_SINGLE(11, 10, 1 << 23), Update the macros to follow this same pattern, ensuring that the scan masks are valid and preventing the warnings. Cc: stable@vger.kernel.org Suggested-by: Jonathan Cameron Signed-off-by: Fabio Estevam Acked-by: Matti Vaittinen Link: https://patch.msgid.link/20250516173900.677821-1-festevam@gmail.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/max1363.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c index a7e9912fb44a..bc44b4604ef4 100644 --- a/drivers/iio/adc/max1363.c +++ b/drivers/iio/adc/max1363.c @@ -511,10 +511,10 @@ static const struct iio_event_spec max1363_events[] = { MAX1363_CHAN_U(1, _s1, 1, bits, ev_spec, num_ev_spec), \ MAX1363_CHAN_U(2, _s2, 2, bits, ev_spec, num_ev_spec), \ MAX1363_CHAN_U(3, _s3, 3, bits, ev_spec, num_ev_spec), \ - MAX1363_CHAN_B(0, 1, d0m1, 4, bits, ev_spec, num_ev_spec), \ - MAX1363_CHAN_B(2, 3, d2m3, 5, bits, ev_spec, num_ev_spec), \ - MAX1363_CHAN_B(1, 0, d1m0, 6, bits, ev_spec, num_ev_spec), \ - MAX1363_CHAN_B(3, 2, d3m2, 7, bits, ev_spec, num_ev_spec), \ + MAX1363_CHAN_B(0, 1, d0m1, 12, bits, ev_spec, num_ev_spec), \ + MAX1363_CHAN_B(2, 3, d2m3, 13, bits, ev_spec, num_ev_spec), \ + MAX1363_CHAN_B(1, 0, d1m0, 18, bits, ev_spec, num_ev_spec), \ + MAX1363_CHAN_B(3, 2, d3m2, 19, bits, ev_spec, num_ev_spec), \ IIO_CHAN_SOFT_TIMESTAMP(8) \ } @@ -609,14 +609,14 @@ static const enum max1363_modes max11608_mode_list[] = { MAX1363_CHAN_U(5, _s5, 5, bits, NULL, 0), \ MAX1363_CHAN_U(6, _s6, 6, bits, NULL, 0), \ MAX1363_CHAN_U(7, _s7, 7, bits, NULL, 0), \ - MAX1363_CHAN_B(0, 1, d0m1, 8, bits, NULL, 0), \ - MAX1363_CHAN_B(2, 3, d2m3, 9, bits, NULL, 0), \ - MAX1363_CHAN_B(4, 5, d4m5, 10, bits, NULL, 0), \ - MAX1363_CHAN_B(6, 7, d6m7, 11, bits, NULL, 0), \ - MAX1363_CHAN_B(1, 0, d1m0, 12, bits, NULL, 0), \ - MAX1363_CHAN_B(3, 2, d3m2, 13, bits, NULL, 0), \ - MAX1363_CHAN_B(5, 4, d5m4, 14, bits, NULL, 0), \ - MAX1363_CHAN_B(7, 6, d7m6, 15, bits, NULL, 0), \ + MAX1363_CHAN_B(0, 1, d0m1, 12, bits, NULL, 0), \ + MAX1363_CHAN_B(2, 3, d2m3, 13, bits, NULL, 0), \ + MAX1363_CHAN_B(4, 5, d4m5, 14, bits, NULL, 0), \ + MAX1363_CHAN_B(6, 7, d6m7, 15, bits, NULL, 0), \ + MAX1363_CHAN_B(1, 0, d1m0, 18, bits, NULL, 0), \ + MAX1363_CHAN_B(3, 2, d3m2, 19, bits, NULL, 0), \ + MAX1363_CHAN_B(5, 4, d5m4, 20, bits, NULL, 0), \ + MAX1363_CHAN_B(7, 6, d7m6, 21, bits, NULL, 0), \ IIO_CHAN_SOFT_TIMESTAMP(16) \ } static const struct iio_chan_spec max11602_channels[] = MAX1363_8X_CHANS(8); From 8d8d7c1dbc46aa07a76acab7336a42ddd900be10 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 16 May 2025 14:39:00 -0300 Subject: [PATCH 05/35] iio: adc: max1363: Reorder mode_list[] entries The IIO core issues warnings when a scan mask is a subset of a previous entry in the available_scan_masks array. On a board using a MAX11601, the following warning is observed: max1363 1-0064: available_scan_mask 7 subset of 6. Never used This occurs because the entries in the max11607_mode_list[] array are not ordered correctly. To fix this, reorder the entries so that no scan mask is a subset of an earlier one. While at it, reorder the mode_list[] arrays for other supported chips as well, to prevent similar warnings on different variants. Note fixes tag dropped as these were introduced over many commits a long time back and the side effect until recently was a reduction in sampling rate due to reading too many channels when only a few were desired. Now we have a sanity check that reports this error but that is not where the issue was introduced. Cc: stable@vger.kernel.org Signed-off-by: Fabio Estevam Acked-by: Matti Vaittinen Link: https://patch.msgid.link/20250516173900.677821-2-festevam@gmail.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/max1363.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c index bc44b4604ef4..9dd547e62b6c 100644 --- a/drivers/iio/adc/max1363.c +++ b/drivers/iio/adc/max1363.c @@ -532,23 +532,23 @@ static const struct iio_chan_spec max1363_channels[] = /* Applies to max1236, max1237 */ static const enum max1363_modes max1236_mode_list[] = { _s0, _s1, _s2, _s3, - s0to1, s0to2, s0to3, + s0to1, s0to2, s2to3, s0to3, d0m1, d2m3, d1m0, d3m2, d0m1to2m3, d1m0to3m2, - s2to3, }; /* Applies to max1238, max1239 */ static const enum max1363_modes max1238_mode_list[] = { _s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s9, _s10, _s11, s0to1, s0to2, s0to3, s0to4, s0to5, s0to6, + s6to7, s6to8, s6to9, s6to10, s6to11, s0to7, s0to8, s0to9, s0to10, s0to11, d0m1, d2m3, d4m5, d6m7, d8m9, d10m11, d1m0, d3m2, d5m4, d7m6, d9m8, d11m10, - d0m1to2m3, d0m1to4m5, d0m1to6m7, d0m1to8m9, d0m1to10m11, - d1m0to3m2, d1m0to5m4, d1m0to7m6, d1m0to9m8, d1m0to11m10, - s6to7, s6to8, s6to9, s6to10, s6to11, - d6m7to8m9, d6m7to10m11, d7m6to9m8, d7m6to11m10, + d0m1to2m3, d0m1to4m5, d0m1to6m7, d6m7to8m9, + d0m1to8m9, d6m7to10m11, d0m1to10m11, d1m0to3m2, + d1m0to5m4, d1m0to7m6, d7m6to9m8, d1m0to9m8, + d7m6to11m10, d1m0to11m10, }; #define MAX1363_12X_CHANS(bits) { \ @@ -584,16 +584,15 @@ static const struct iio_chan_spec max1238_channels[] = MAX1363_12X_CHANS(12); static const enum max1363_modes max11607_mode_list[] = { _s0, _s1, _s2, _s3, - s0to1, s0to2, s0to3, - s2to3, + s0to1, s0to2, s2to3, + s0to3, d0m1, d2m3, d1m0, d3m2, d0m1to2m3, d1m0to3m2, }; static const enum max1363_modes max11608_mode_list[] = { _s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, - s0to1, s0to2, s0to3, s0to4, s0to5, s0to6, s0to7, - s6to7, + s0to1, s0to2, s0to3, s0to4, s0to5, s0to6, s6to7, s0to7, d0m1, d2m3, d4m5, d6m7, d1m0, d3m2, d5m4, d7m6, d0m1to2m3, d0m1to4m5, d0m1to6m7, From 886a94f008dd1a1702ee66dd035c266f70fd9e90 Mon Sep 17 00:00:00 2001 From: Xilin Wu Date: Fri, 13 Jun 2025 22:53:38 +0800 Subject: [PATCH 06/35] interconnect: qcom: sc7280: Add missing num_links to xm_pcie3_1 node This allows adding interconnect paths for PCIe 1 in device tree later. Fixes: 46bdcac533cc ("interconnect: qcom: Add SC7280 interconnect provider driver") Signed-off-by: Xilin Wu Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250613-sc7280-icc-pcie1-fix-v1-1-0b09813e3b09@radxa.com Signed-off-by: Georgi Djakov --- drivers/interconnect/qcom/sc7280.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/interconnect/qcom/sc7280.c b/drivers/interconnect/qcom/sc7280.c index 346f18d70e9e..905403a3a930 100644 --- a/drivers/interconnect/qcom/sc7280.c +++ b/drivers/interconnect/qcom/sc7280.c @@ -238,6 +238,7 @@ static struct qcom_icc_node xm_pcie3_1 = { .id = SC7280_MASTER_PCIE_1, .channels = 1, .buswidth = 8, + .num_links = 1, .links = { SC7280_SLAVE_ANOC_PCIE_GEM_NOC }, }; From b44f12ae21f661e5d97fb4a8b234d6689f68f706 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 23 Jun 2025 16:24:37 +0200 Subject: [PATCH 07/35] interconnect: exynos: handle node name allocation failure Add the missing error handling in case node name allocation ever fails. Fixes: 2f95b9d5cf0b ("interconnect: Add generic interconnect driver for Exynos SoCs") Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20250623142437.23068-1-johan+linaro@kernel.org Signed-off-by: Georgi Djakov --- drivers/interconnect/samsung/exynos.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/interconnect/samsung/exynos.c b/drivers/interconnect/samsung/exynos.c index 9e041365d909..8e8f56186a36 100644 --- a/drivers/interconnect/samsung/exynos.c +++ b/drivers/interconnect/samsung/exynos.c @@ -134,6 +134,11 @@ static int exynos_generic_icc_probe(struct platform_device *pdev) priv->node = icc_node; icc_node->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%pOFn", bus_dev->of_node); + if (!icc_node->name) { + icc_node_destroy(pdev->id); + return -ENOMEM; + } + if (of_property_read_u32(bus_dev->of_node, "samsung,data-clock-ratio", &priv->bus_clk_ratio)) priv->bus_clk_ratio = EXYNOS_ICC_DEFAULT_BUS_CLK_RATIO; From 1809db75bd1fa71e27e199e4c5cc9072741f6052 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 25 Jun 2025 15:34:23 +0200 Subject: [PATCH 08/35] interconnect: increase ICC_DYN_ID_START Since commit d30f83d278a9 ("interconnect: core: Add dynamic id allocation support"), interconnect node ids greater than or equal to ICC_DYN_ID_START are reserved for dynamic id allocation. Yet the icc_node_create_nolock() function allows to directly use such ids for creating nodes. This can cause problems by executing dynamic id related codepaths even for nodes intended to use static ids. For example, the 'nsscc-ipq9574' driver creates interconnect nodes with static ids starting from 19148. Because these ids belongs to the dynamic id range, the icc_node_add() function replaces the node names unexpectedly. The node names looked like this before the change: # grep nss_cc /sys/kernel/debug/interconnect/interconnect_summary nss_cc_nssnoc_ppe_clk_master 0 0 nss_cc_nssnoc_ppe_clk_slave 0 0 nss_cc_nssnoc_ppe_cfg_clk_master 0 0 ... And those have an unexpected suffix now: # grep nss_cc /sys/kernel/debug/interconnect/interconnect_summary nss_cc_nssnoc_ppe_clk_master@39b00000.clock-controller 0 0 nss_cc_nssnoc_ppe_clk_slave@39b00000.clock-controller 0 0 nss_cc_nssnoc_ppe_cfg_clk_master@39b00000.clock-controller 0 0 ... Increase the value of ICC_DYN_ID_START to avoid this. Also, add sanity check to the icc_node_create_nolock() function to prevent directly creating nodes with ids reserved for dynamic allocation in order to detect these kind of problems. Fixes: d30f83d278a9 ("interconnect: core: Add dynamic id allocation support") Signed-off-by: Gabor Juhos Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250625-icc-dyn-id-fix-v1-1-127cb5498449@gmail.com Signed-off-by: Georgi Djakov --- drivers/interconnect/core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c index 1a41e59c77f8..3a41b2717edd 100644 --- a/drivers/interconnect/core.c +++ b/drivers/interconnect/core.c @@ -20,7 +20,7 @@ #include "internal.h" -#define ICC_DYN_ID_START 10000 +#define ICC_DYN_ID_START 100000 #define CREATE_TRACE_POINTS #include "trace.h" @@ -819,6 +819,9 @@ static struct icc_node *icc_node_create_nolock(int id) { struct icc_node *node; + if (id >= ICC_DYN_ID_START) + return ERR_PTR(-EINVAL); + /* check if node already exists */ node = node_find(id); if (node) From 618c810a7b2163517ab1875bd56b633ca3cb3328 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 25 Jun 2025 19:32:35 +0200 Subject: [PATCH 09/35] interconnect: icc-clk: destroy nodes in case of memory allocation failures When memory allocation fails during creating the name of the nodes in icc_clk_register(), the code continues on the error path and it calls icc_nodes_remove() to destroy the already created nodes. However that function only destroys the nodes which were already added to the provider and the newly created nodes are never destroyed in case of error. In order to avoid a memory leaks, change the code to destroy the newly created nodes explicitly in case of memory allocation failures. Fixes: 44c5aa73ccd1 ("interconnect: icc-clk: check return values of devm_kasprintf()") Signed-off-by: Gabor Juhos Reviewed-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20250625-icc-clk-memleak-fix-v1-1-4151484cd24f@gmail.com Signed-off-by: Georgi Djakov --- drivers/interconnect/icc-clk.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/interconnect/icc-clk.c b/drivers/interconnect/icc-clk.c index 88f311c11020..93c030608d3e 100644 --- a/drivers/interconnect/icc-clk.c +++ b/drivers/interconnect/icc-clk.c @@ -117,6 +117,7 @@ struct icc_provider *icc_clk_register(struct device *dev, node->name = devm_kasprintf(dev, GFP_KERNEL, "%s_master", data[i].name); if (!node->name) { + icc_node_destroy(node->id); ret = -ENOMEM; goto err; } @@ -135,6 +136,7 @@ struct icc_provider *icc_clk_register(struct device *dev, node->name = devm_kasprintf(dev, GFP_KERNEL, "%s_slave", data[i].name); if (!node->name) { + icc_node_destroy(node->id); ret = -ENOMEM; goto err; } From c5b60592886f97b01503c1bb553f88d6a7df42ea Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Fri, 27 Jun 2025 09:58:54 +0200 Subject: [PATCH 10/35] interconnect: avoid memory allocation when 'icc_bw_lock' is held The 'icc_bw_lock' mutex is introduced in commit af42269c3523 ("interconnect: Fix locking for runpm vs reclaim") in order to decouple serialization of bw aggregation from codepaths that require memory allocation. However commit d30f83d278a9 ("interconnect: core: Add dynamic id allocation support") added a devm_kasprintf() call into a path protected by the 'icc_bw_lock' which causes the following lockdep warning on machines like the Lenovo ThinkPad X13s: ====================================================== WARNING: possible circular locking dependency detected 6.16.0-rc3 #15 Not tainted ------------------------------------------------------ (udev-worker)/342 is trying to acquire lock: ffffb973f7ec4638 (fs_reclaim){+.+.}-{0:0}, at: __kmalloc_node_track_caller_noprof+0xa0/0x3e0 but task is already holding lock: ffffb973f7f7f0e8 (icc_bw_lock){+.+.}-{4:4}, at: icc_node_add+0x44/0x154 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 (icc_bw_lock){+.+.}-{4:4}: icc_init+0x48/0x108 do_one_initcall+0x64/0x30c kernel_init_freeable+0x27c/0x500 kernel_init+0x20/0x1d8 ret_from_fork+0x10/0x20 -> #0 (fs_reclaim){+.+.}-{0:0}: __lock_acquire+0x136c/0x2114 lock_acquire+0x1c8/0x354 fs_reclaim_acquire+0x74/0xa8 __kmalloc_node_track_caller_noprof+0xa0/0x3e0 devm_kmalloc+0x54/0x124 devm_kvasprintf+0x74/0xd4 devm_kasprintf+0x58/0x80 icc_node_add+0xb4/0x154 qcom_osm_l3_probe+0x20c/0x314 [icc_osm_l3] platform_probe+0x68/0xd8 really_probe+0xc0/0x38c __driver_probe_device+0x7c/0x160 driver_probe_device+0x40/0x110 __driver_attach+0xfc/0x208 bus_for_each_dev+0x74/0xd0 driver_attach+0x24/0x30 bus_add_driver+0x110/0x234 driver_register+0x60/0x128 __platform_driver_register+0x24/0x30 osm_l3_driver_init+0x20/0x1000 [icc_osm_l3] do_one_initcall+0x64/0x30c do_init_module+0x58/0x23c load_module+0x1df8/0x1f70 init_module_from_file+0x88/0xc4 idempotent_init_module+0x188/0x280 __arm64_sys_finit_module+0x6c/0xd8 invoke_syscall+0x48/0x110 el0_svc_common.constprop.0+0xc0/0xe0 do_el0_svc+0x1c/0x28 el0_svc+0x4c/0x158 el0t_64_sync_handler+0xc8/0xcc el0t_64_sync+0x198/0x19c other info that might help us debug this: Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(icc_bw_lock); lock(fs_reclaim); lock(icc_bw_lock); lock(fs_reclaim); *** DEADLOCK *** The icc_node_add() functions is not designed to fail, and as such it should not do any memory allocation. In order to avoid this, add a new helper function for the name generation to be called by drivers which are using the new dynamic id feature. Fixes: d30f83d278a9 ("interconnect: core: Add dynamic id allocation support") Signed-off-by: Gabor Juhos Link: https://lore.kernel.org/r/20250625-icc-bw-lockdep-v3-1-2b8f8b8987c4@gmail.com Co-developed-by: Johan Hovold Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20250627075854.26943-1-johan+linaro@kernel.org Signed-off-by: Georgi Djakov --- drivers/interconnect/core.c | 29 +++++++++++++++++++++++---- drivers/interconnect/qcom/icc-rpmh.c | 7 ++++++- drivers/interconnect/qcom/osm-l3.c | 7 ++++++- include/linux/interconnect-provider.h | 7 +++++++ 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c index 3a41b2717edd..3ebf37ddfc18 100644 --- a/drivers/interconnect/core.c +++ b/drivers/interconnect/core.c @@ -909,10 +909,35 @@ void icc_node_destroy(int id) return; kfree(node->links); + if (node->id >= ICC_DYN_ID_START) + kfree(node->name); kfree(node); } EXPORT_SYMBOL_GPL(icc_node_destroy); +/** + * icc_node_set_name() - set node name + * @node: node + * @provider: node provider + * @name: node name + * + * Return: 0 on success, or -ENOMEM on allocation failure + */ +int icc_node_set_name(struct icc_node *node, const struct icc_provider *provider, const char *name) +{ + if (node->id >= ICC_DYN_ID_START) { + node->name = kasprintf(GFP_KERNEL, "%s@%s", name, + dev_name(provider->dev)); + if (!node->name) + return -ENOMEM; + } else { + node->name = name; + } + + return 0; +} +EXPORT_SYMBOL_GPL(icc_node_set_name); + /** * icc_link_nodes() - create link between two nodes * @src_node: source node @@ -1041,10 +1066,6 @@ void icc_node_add(struct icc_node *node, struct icc_provider *provider) node->avg_bw = node->init_avg; node->peak_bw = node->init_peak; - if (node->id >= ICC_DYN_ID_START) - node->name = devm_kasprintf(provider->dev, GFP_KERNEL, "%s@%s", - node->name, dev_name(provider->dev)); - if (node->avg_bw || node->peak_bw) { if (provider->pre_aggregate) provider->pre_aggregate(node); diff --git a/drivers/interconnect/qcom/icc-rpmh.c b/drivers/interconnect/qcom/icc-rpmh.c index 41bfc6e7ee1d..001404e91041 100644 --- a/drivers/interconnect/qcom/icc-rpmh.c +++ b/drivers/interconnect/qcom/icc-rpmh.c @@ -293,7 +293,12 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev) goto err_remove_nodes; } - node->name = qn->name; + ret = icc_node_set_name(node, provider, qn->name); + if (ret) { + icc_node_destroy(node->id); + goto err_remove_nodes; + } + node->data = qn; icc_node_add(node, provider); diff --git a/drivers/interconnect/qcom/osm-l3.c b/drivers/interconnect/qcom/osm-l3.c index baecbf2533f7..b33f00da1880 100644 --- a/drivers/interconnect/qcom/osm-l3.c +++ b/drivers/interconnect/qcom/osm-l3.c @@ -236,7 +236,12 @@ static int qcom_osm_l3_probe(struct platform_device *pdev) goto err; } - node->name = qnodes[i]->name; + ret = icc_node_set_name(node, provider, qnodes[i]->name); + if (ret) { + icc_node_destroy(node->id); + goto err; + } + /* Cast away const and add it back in qcom_osm_l3_set() */ node->data = (void *)qnodes[i]; icc_node_add(node, provider); diff --git a/include/linux/interconnect-provider.h b/include/linux/interconnect-provider.h index 55cfebc658e6..8a2f652a05ff 100644 --- a/include/linux/interconnect-provider.h +++ b/include/linux/interconnect-provider.h @@ -119,6 +119,7 @@ int icc_std_aggregate(struct icc_node *node, u32 tag, u32 avg_bw, struct icc_node *icc_node_create_dyn(void); struct icc_node *icc_node_create(int id); void icc_node_destroy(int id); +int icc_node_set_name(struct icc_node *node, const struct icc_provider *provider, const char *name); int icc_link_nodes(struct icc_node *src_node, struct icc_node **dst_node); int icc_link_create(struct icc_node *node, const int dst_id); void icc_node_add(struct icc_node *node, struct icc_provider *provider); @@ -152,6 +153,12 @@ static inline void icc_node_destroy(int id) { } +static inline int icc_node_set_name(struct icc_node *node, const struct icc_provider *provider, + const char *name) +{ + return -EOPNOTSUPP; +} + static inline int icc_link_nodes(struct icc_node *src_node, struct icc_node **dst_node) { return -EOPNOTSUPP; From 43d8c4a3a3c7caa7fcc01d1bb349920db7004266 Mon Sep 17 00:00:00 2001 From: Angelo Dureghello Date: Mon, 26 May 2025 15:19:08 +0200 Subject: [PATCH 11/35] dt-bindings: iio: adc: adi,ad7606: fix dt_schema validation warning Fix following dt_schema warning when offload is used: DTC [C] arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7606.dtb /home/angelo/dev-baylibre/linux-iio/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7606.dtb: adc@0: 'oneOf' conditional failed, one must be fixed: 'interrupts' is a required property 'io-backends' is a required property from schema $id: http://devicetree.org/schemas/iio/adc/adi,ad7606.yaml# There isn't any reason that we couldn't have interrupts wired up at the same time we are using io-backends or SPI offload, so dropping off the related "oneOf" block entirely. Fixes: 81fe5529e812 ("dt-bindings: iio: adc: adi,ad7606: add SPI offload properties") Signed-off-by: Angelo Dureghello Acked-by: Conor Dooley Link: https://patch.msgid.link/20250526-wip-bl-ad7606-dtschema-fixes-v2-1-9bd56d039489@baylibre.com Signed-off-by: Jonathan Cameron --- Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml index 29f12d650442..1a5209139e13 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml @@ -223,12 +223,6 @@ allOf: - required: - pwms - - oneOf: - - required: - - interrupts - - required: - - io-backends - - if: properties: compatible: From 6ac609d1fba19d5d40fb3c81201ffadcb6d00fb3 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 30 May 2025 16:50:14 -0500 Subject: [PATCH 12/35] iio: adc: adi-axi-adc: fix ad7606_bus_reg_read() Mask the value read before returning it. The value read over the parallel bus via the AXI ADC IP block contains both the address and the data, but callers expect val to only contain the data. axi_adc_raw_write() takes a u32 parameter, so addr was the wrong type. This wasn't causing any issues but is corrected anyway since we are touching the same line to add a new variable. Cc: stable@vger.kernel.org Fixes: 79c47485e438 ("iio: adc: adi-axi-adc: add support for AD7606 register writing") Signed-off-by: David Lechner Link: https://patch.msgid.link/20250530-iio-adc-adi-axi-adc-fix-ad7606_bus_reg_read-v2-1-ad2dfc0694ce@baylibre.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/adi-axi-adc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c index 4116c44197b8..2dbaa0b5b3d6 100644 --- a/drivers/iio/adc/adi-axi-adc.c +++ b/drivers/iio/adc/adi-axi-adc.c @@ -445,7 +445,7 @@ static int axi_adc_raw_read(struct iio_backend *back, u32 *val) static int ad7606_bus_reg_read(struct iio_backend *back, u32 reg, u32 *val) { struct adi_axi_adc_state *st = iio_backend_get_priv(back); - int addr; + u32 addr, reg_val; guard(mutex)(&st->lock); @@ -455,7 +455,9 @@ static int ad7606_bus_reg_read(struct iio_backend *back, u32 reg, u32 *val) */ addr = FIELD_PREP(ADI_AXI_REG_ADDRESS_MASK, reg) | ADI_AXI_REG_READ_BIT; axi_adc_raw_write(back, addr); - axi_adc_raw_read(back, val); + axi_adc_raw_read(back, ®_val); + + *val = FIELD_GET(ADI_AXI_REG_VALUE_MASK, reg_val); /* Write 0x0 on the bus to get back to ADC mode */ axi_adc_raw_write(back, 0); From 9f92e93e257b33e73622640a9205f8642ec16ddd Mon Sep 17 00:00:00 2001 From: Maud Spierings Date: Tue, 27 May 2025 08:36:08 +0200 Subject: [PATCH 13/35] iio: common: st_sensors: Fix use of uninitialize device structs Throughout the various probe functions &indio_dev->dev is used before it is initialized. This caused a kernel panic in st_sensors_power_enable() when the call to devm_regulator_bulk_get_enable() fails and then calls dev_err_probe() with the uninitialized device. This seems to only cause a panic with dev_err_probe(), dev_err(), dev_warn() and dev_info() don't seem to cause a panic, but are fixed as well. The issue is reported and traced here: [1] Link: https://lore.kernel.org/all/AM7P189MB100986A83D2F28AF3FFAF976E39EA@AM7P189MB1009.EURP189.PROD.OUTLOOK.COM/ [1] Cc: stable@vger.kernel.org Signed-off-by: Maud Spierings Reviewed-by: Andy Shevchenko Link: https://... [1] Link: https://patch.msgid.link/20250527-st_iio_fix-v4-1-12d89801c761@gocontroll.com Signed-off-by: Jonathan Cameron --- drivers/iio/accel/st_accel_core.c | 10 +++--- .../iio/common/st_sensors/st_sensors_core.c | 36 +++++++++---------- .../common/st_sensors/st_sensors_trigger.c | 20 +++++------ 3 files changed, 31 insertions(+), 35 deletions(-) diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index 99cb661fabb2..a7961c610ed2 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -1353,6 +1353,7 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev) union acpi_object *ont; union acpi_object *elements; acpi_status status; + struct device *parent = indio_dev->dev.parent; int ret = -EINVAL; unsigned int val; int i, j; @@ -1371,7 +1372,7 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev) }; - adev = ACPI_COMPANION(indio_dev->dev.parent); + adev = ACPI_COMPANION(parent); if (!adev) return -ENXIO; @@ -1380,8 +1381,7 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev) if (status == AE_NOT_FOUND) { return -ENXIO; } else if (ACPI_FAILURE(status)) { - dev_warn(&indio_dev->dev, "failed to execute _ONT: %d\n", - status); + dev_warn(parent, "failed to execute _ONT: %d\n", status); return status; } @@ -1457,12 +1457,12 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev) } ret = 0; - dev_info(&indio_dev->dev, "computed mount matrix from ACPI\n"); + dev_info(parent, "computed mount matrix from ACPI\n"); out: kfree(buffer.pointer); if (ret) - dev_dbg(&indio_dev->dev, + dev_dbg(parent, "failed to apply ACPI orientation data: %d\n", ret); return ret; diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index 8ce1dccfea4f..dac593be5695 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c @@ -154,7 +154,7 @@ static int st_sensors_set_fullscale(struct iio_dev *indio_dev, unsigned int fs) return err; st_accel_set_fullscale_error: - dev_err(&indio_dev->dev, "failed to set new fullscale.\n"); + dev_err(indio_dev->dev.parent, "failed to set new fullscale.\n"); return err; } @@ -231,8 +231,7 @@ int st_sensors_power_enable(struct iio_dev *indio_dev) ARRAY_SIZE(regulator_names), regulator_names); if (err) - return dev_err_probe(&indio_dev->dev, err, - "unable to enable supplies\n"); + return dev_err_probe(parent, err, "unable to enable supplies\n"); return 0; } @@ -241,13 +240,14 @@ EXPORT_SYMBOL_NS(st_sensors_power_enable, "IIO_ST_SENSORS"); static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev, struct st_sensors_platform_data *pdata) { + struct device *parent = indio_dev->dev.parent; struct st_sensor_data *sdata = iio_priv(indio_dev); /* Sensor does not support interrupts */ if (!sdata->sensor_settings->drdy_irq.int1.addr && !sdata->sensor_settings->drdy_irq.int2.addr) { if (pdata->drdy_int_pin) - dev_info(&indio_dev->dev, + dev_info(parent, "DRDY on pin INT%d specified, but sensor does not support interrupts\n", pdata->drdy_int_pin); return 0; @@ -256,29 +256,27 @@ static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev, switch (pdata->drdy_int_pin) { case 1: if (!sdata->sensor_settings->drdy_irq.int1.mask) { - dev_err(&indio_dev->dev, - "DRDY on INT1 not available.\n"); + dev_err(parent, "DRDY on INT1 not available.\n"); return -EINVAL; } sdata->drdy_int_pin = 1; break; case 2: if (!sdata->sensor_settings->drdy_irq.int2.mask) { - dev_err(&indio_dev->dev, - "DRDY on INT2 not available.\n"); + dev_err(parent, "DRDY on INT2 not available.\n"); return -EINVAL; } sdata->drdy_int_pin = 2; break; default: - dev_err(&indio_dev->dev, "DRDY on pdata not valid.\n"); + dev_err(parent, "DRDY on pdata not valid.\n"); return -EINVAL; } if (pdata->open_drain) { if (!sdata->sensor_settings->drdy_irq.int1.addr_od && !sdata->sensor_settings->drdy_irq.int2.addr_od) - dev_err(&indio_dev->dev, + dev_err(parent, "open drain requested but unsupported.\n"); else sdata->int_pin_open_drain = true; @@ -336,6 +334,7 @@ EXPORT_SYMBOL_NS(st_sensors_dev_name_probe, "IIO_ST_SENSORS"); int st_sensors_init_sensor(struct iio_dev *indio_dev, struct st_sensors_platform_data *pdata) { + struct device *parent = indio_dev->dev.parent; struct st_sensor_data *sdata = iio_priv(indio_dev); struct st_sensors_platform_data *of_pdata; int err = 0; @@ -343,7 +342,7 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev, mutex_init(&sdata->odr_lock); /* If OF/DT pdata exists, it will take precedence of anything else */ - of_pdata = st_sensors_dev_probe(indio_dev->dev.parent, pdata); + of_pdata = st_sensors_dev_probe(parent, pdata); if (IS_ERR(of_pdata)) return PTR_ERR(of_pdata); if (of_pdata) @@ -370,7 +369,7 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev, if (err < 0) return err; } else - dev_info(&indio_dev->dev, "Full-scale not possible\n"); + dev_info(parent, "Full-scale not possible\n"); err = st_sensors_set_odr(indio_dev, sdata->odr); if (err < 0) @@ -405,7 +404,7 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev, mask = sdata->sensor_settings->drdy_irq.int2.mask_od; } - dev_info(&indio_dev->dev, + dev_info(parent, "set interrupt line to open drain mode on pin %d\n", sdata->drdy_int_pin); err = st_sensors_write_data_with_mask(indio_dev, addr, @@ -593,21 +592,20 @@ EXPORT_SYMBOL_NS(st_sensors_get_settings_index, "IIO_ST_SENSORS"); int st_sensors_verify_id(struct iio_dev *indio_dev) { struct st_sensor_data *sdata = iio_priv(indio_dev); + struct device *parent = indio_dev->dev.parent; int wai, err; if (sdata->sensor_settings->wai_addr) { err = regmap_read(sdata->regmap, sdata->sensor_settings->wai_addr, &wai); if (err < 0) { - dev_err(&indio_dev->dev, - "failed to read Who-Am-I register.\n"); - return err; + return dev_err_probe(parent, err, + "failed to read Who-Am-I register.\n"); } if (sdata->sensor_settings->wai != wai) { - dev_warn(&indio_dev->dev, - "%s: WhoAmI mismatch (0x%x).\n", - indio_dev->name, wai); + dev_warn(parent, "%s: WhoAmI mismatch (0x%x).\n", + indio_dev->name, wai); } } diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c index 9d4bf822a15d..8a8ab688d798 100644 --- a/drivers/iio/common/st_sensors/st_sensors_trigger.c +++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c @@ -127,7 +127,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, sdata->trig = devm_iio_trigger_alloc(parent, "%s-trigger", indio_dev->name); if (sdata->trig == NULL) { - dev_err(&indio_dev->dev, "failed to allocate iio trigger.\n"); + dev_err(parent, "failed to allocate iio trigger.\n"); return -ENOMEM; } @@ -143,7 +143,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, case IRQF_TRIGGER_FALLING: case IRQF_TRIGGER_LOW: if (!sdata->sensor_settings->drdy_irq.addr_ihl) { - dev_err(&indio_dev->dev, + dev_err(parent, "falling/low specified for IRQ but hardware supports only rising/high: will request rising/high\n"); if (irq_trig == IRQF_TRIGGER_FALLING) irq_trig = IRQF_TRIGGER_RISING; @@ -156,21 +156,19 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, sdata->sensor_settings->drdy_irq.mask_ihl, 1); if (err < 0) return err; - dev_info(&indio_dev->dev, + dev_info(parent, "interrupts on the falling edge or active low level\n"); } break; case IRQF_TRIGGER_RISING: - dev_info(&indio_dev->dev, - "interrupts on the rising edge\n"); + dev_info(parent, "interrupts on the rising edge\n"); break; case IRQF_TRIGGER_HIGH: - dev_info(&indio_dev->dev, - "interrupts active high level\n"); + dev_info(parent, "interrupts active high level\n"); break; default: /* This is the most preferred mode, if possible */ - dev_err(&indio_dev->dev, + dev_err(parent, "unsupported IRQ trigger specified (%lx), enforce rising edge\n", irq_trig); irq_trig = IRQF_TRIGGER_RISING; } @@ -179,7 +177,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, if (irq_trig == IRQF_TRIGGER_FALLING || irq_trig == IRQF_TRIGGER_RISING) { if (!sdata->sensor_settings->drdy_irq.stat_drdy.addr) { - dev_err(&indio_dev->dev, + dev_err(parent, "edge IRQ not supported w/o stat register.\n"); return -EOPNOTSUPP; } @@ -214,13 +212,13 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, sdata->trig->name, sdata->trig); if (err) { - dev_err(&indio_dev->dev, "failed to request trigger IRQ.\n"); + dev_err(parent, "failed to request trigger IRQ.\n"); return err; } err = devm_iio_trigger_register(parent, sdata->trig); if (err < 0) { - dev_err(&indio_dev->dev, "failed to register iio trigger.\n"); + dev_err(parent, "failed to register iio trigger.\n"); return err; } indio_dev->trig = iio_trigger_get(sdata->trig); From fd8e6f8729629407d2d932116d83b9cd71c17d80 Mon Sep 17 00:00:00 2001 From: Rodrigo Gobbi Date: Tue, 27 May 2025 18:51:06 -0300 Subject: [PATCH 14/35] dt-bindings: iio: gyro: invensense,mpu3050: change irq maxItems The mpu3050 datasheet describes that this IC only supports one INT pin, which means one item with two cells inside binding. Change max to match this description. Signed-off-by: Rodrigo Gobbi Fixes: 749787477ae4 ("dt-bindings:iio:gyro:invensense,mpu3050: txt to yaml format conversion.") Reviewed-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20250527215818.13000-1-rodrigo.gobbi.7@gmail.com Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/gyroscope/invensense,mpu3050.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/iio/gyroscope/invensense,mpu3050.yaml b/Documentation/devicetree/bindings/iio/gyroscope/invensense,mpu3050.yaml index d1a6103fc37a..f3242dc0e7e6 100644 --- a/Documentation/devicetree/bindings/iio/gyroscope/invensense,mpu3050.yaml +++ b/Documentation/devicetree/bindings/iio/gyroscope/invensense,mpu3050.yaml @@ -21,7 +21,7 @@ properties: vlogic-supply: true interrupts: - minItems: 1 + maxItems: 1 description: Interrupt mapping for the trigger interrupt from the internal oscillator. From 3281ddcea6429f7bc1fdb39d407752dd1371aba9 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Sat, 7 Jun 2025 21:56:27 +0800 Subject: [PATCH 15/35] iio: adc: axp20x_adc: Add missing sentinel to AXP717 ADC channel maps The AXP717 ADC channel maps is missing a sentinel entry at the end. This causes a KASAN warning. Add the missing sentinel entry. Fixes: 5ba0cb92584b ("iio: adc: axp20x_adc: add support for AXP717 ADC") Signed-off-by: Chen-Yu Tsai Link: https://patch.msgid.link/20250607135627.2086850-1-wens@kernel.org Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/axp20x_adc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/adc/axp20x_adc.c b/drivers/iio/adc/axp20x_adc.c index 71584ffd3632..1b49325ec1ce 100644 --- a/drivers/iio/adc/axp20x_adc.c +++ b/drivers/iio/adc/axp20x_adc.c @@ -187,6 +187,7 @@ static struct iio_map axp717_maps[] = { .consumer_channel = "batt_chrg_i", .adc_channel_label = "batt_chrg_i", }, + { } }; /* From 1fe16dc1a2f5057772e5391ec042ed7442966c9a Mon Sep 17 00:00:00 2001 From: Sean Nyekjaer Date: Tue, 3 Jun 2025 14:25:44 +0200 Subject: [PATCH 16/35] iio: accel: fxls8962af: Fix use after free in fxls8962af_fifo_flush fxls8962af_fifo_flush() uses indio_dev->active_scan_mask (with iio_for_each_active_channel()) without making sure the indio_dev stays in buffer mode. There is a race if indio_dev exits buffer mode in the middle of the interrupt that flushes the fifo. Fix this by calling synchronize_irq() to ensure that no interrupt is currently running when disabling buffer mode. Unable to handle kernel NULL pointer dereference at virtual address 00000000 when read [...] _find_first_bit_le from fxls8962af_fifo_flush+0x17c/0x290 fxls8962af_fifo_flush from fxls8962af_interrupt+0x80/0x178 fxls8962af_interrupt from irq_thread_fn+0x1c/0x7c irq_thread_fn from irq_thread+0x110/0x1f4 irq_thread from kthread+0xe0/0xfc kthread from ret_from_fork+0x14/0x2c Fixes: 79e3a5bdd9ef ("iio: accel: fxls8962af: add hw buffered sampling") Cc: stable@vger.kernel.org Suggested-by: David Lechner Signed-off-by: Sean Nyekjaer Link: https://patch.msgid.link/20250603-fxlsrace-v2-1-5381b36ba1db@geanix.com Signed-off-by: Jonathan Cameron --- drivers/iio/accel/fxls8962af-core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/iio/accel/fxls8962af-core.c b/drivers/iio/accel/fxls8962af-core.c index 12598feaa693..b10a30960e1e 100644 --- a/drivers/iio/accel/fxls8962af-core.c +++ b/drivers/iio/accel/fxls8962af-core.c @@ -877,6 +877,8 @@ static int fxls8962af_buffer_predisable(struct iio_dev *indio_dev) if (ret) return ret; + synchronize_irq(data->irq); + ret = __fxls8962af_fifo_set_mode(data, false); if (data->enable_event) From 7b86482632788acd48d7b9ee1867f5ad3a32ccbb Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 11 Jun 2025 10:04:58 -0500 Subject: [PATCH 17/35] iio: adc: ad7949: use spi_is_bpw_supported() Use spi_is_bpw_supported() instead of directly accessing spi->controller ->bits_per_word_mask. bits_per_word_mask may be 0, which implies that 8-bits-per-word is supported. spi_is_bpw_supported() takes this into account while spi_ctrl_mask == SPI_BPW_MASK(8) does not. Fixes: 0b2a740b424e ("iio: adc: ad7949: enable use with non 14/16-bit controllers") Closes: https://lore.kernel.org/linux-spi/c8b8a963-6cef-4c9b-bfef-dab2b7bd0b0f@sirena.org.uk/ Signed-off-by: David Lechner Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20250611-iio-adc-ad7949-use-spi_is_bpw_supported-v1-1-c4e15bfd326e@baylibre.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7949.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/iio/adc/ad7949.c b/drivers/iio/adc/ad7949.c index edd0c3a35ab7..202561cad401 100644 --- a/drivers/iio/adc/ad7949.c +++ b/drivers/iio/adc/ad7949.c @@ -308,7 +308,6 @@ static void ad7949_disable_reg(void *reg) static int ad7949_spi_probe(struct spi_device *spi) { - u32 spi_ctrl_mask = spi->controller->bits_per_word_mask; struct device *dev = &spi->dev; const struct ad7949_adc_spec *spec; struct ad7949_adc_chip *ad7949_adc; @@ -337,11 +336,11 @@ static int ad7949_spi_probe(struct spi_device *spi) ad7949_adc->resolution = spec->resolution; /* Set SPI bits per word */ - if (spi_ctrl_mask & SPI_BPW_MASK(ad7949_adc->resolution)) { + if (spi_is_bpw_supported(spi, ad7949_adc->resolution)) { spi->bits_per_word = ad7949_adc->resolution; - } else if (spi_ctrl_mask == SPI_BPW_MASK(16)) { + } else if (spi_is_bpw_supported(spi, 16)) { spi->bits_per_word = 16; - } else if (spi_ctrl_mask == SPI_BPW_MASK(8)) { + } else if (spi_is_bpw_supported(spi, 8)) { spi->bits_per_word = 8; } else { dev_err(dev, "unable to find common BPW with spi controller\n"); From 24fa69894ea3f76ecb13d7160692ee574a912803 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 19 Jun 2025 10:24:22 -0500 Subject: [PATCH 18/35] iio: adc: ad7380: fix adi,gain-milli property parsing Change the data type of the "adi,gain-milli" property from u32 to u16. The devicetree binding specifies it as uint16, so we need to read it as such to avoid an -EOVERFLOW error when parsing the property. Fixes: c904e6dcf402 ("iio: adc: ad7380: add support for adaq4370-4 and adaq4380-4") Signed-off-by: David Lechner Link: https://patch.msgid.link/20250619-iio-adc-ad7380-fix-adi-gain-milli-parsing-v1-1-4c27fb426860@baylibre.com Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7380.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/iio/adc/ad7380.c b/drivers/iio/adc/ad7380.c index d96bd12dfea6..cabf5511d116 100644 --- a/drivers/iio/adc/ad7380.c +++ b/drivers/iio/adc/ad7380.c @@ -1953,8 +1953,9 @@ static int ad7380_probe(struct spi_device *spi) if (st->chip_info->has_hardware_gain) { device_for_each_child_node_scoped(dev, node) { - unsigned int channel, gain; + unsigned int channel; int gain_idx; + u16 gain; ret = fwnode_property_read_u32(node, "reg", &channel); if (ret) @@ -1966,7 +1967,7 @@ static int ad7380_probe(struct spi_device *spi) "Invalid channel number %i\n", channel); - ret = fwnode_property_read_u32(node, "adi,gain-milli", + ret = fwnode_property_read_u16(node, "adi,gain-milli", &gain); if (ret && ret != -EINVAL) return dev_err_probe(dev, ret, From 1131e70558bc70f1fc52515281de2663e961e1cc Mon Sep 17 00:00:00 2001 From: Kim Seer Paller Date: Thu, 26 Jun 2025 16:38:12 +0800 Subject: [PATCH 19/35] iio: dac: ad3530r: Fix incorrect masking for channels 4-7 in powerdown mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the current implementation of ad3530r_set_dac_powerdown() function, the macro AD3530R_OP_MODE_CHAN_MSK(chan->channel) is used to generate the bitmask for the operating mode of a specific channel. However, this macro does not account for channels 4-7, which map to the second register AD3530R_OUTPUT_OPERATING_MODE_1 for the 8 channeled device. As a result, the bitmask is incorrectly calculated for these channels, leading to improper configuration of the powerdown mode. Resolve this issue by adjusting the channel index for channels 4-7 by subtracting 4 before applying the macro. This ensures that the correct bitmask is generated for the second register. Fixes: 93583174a3df ("iio: dac: ad3530r: Add driver for AD3530R and AD3531R") Signed-off-by: Kim Seer Paller Reviewed-by: David Lechner Reviewed-by: Nuno Sá Link: https://patch.msgid.link/20250626-bug_fix-v1-1-eb3c2b370f10@analog.com Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad3530r.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/iio/dac/ad3530r.c b/drivers/iio/dac/ad3530r.c index f9752a571aa5..6134613777b8 100644 --- a/drivers/iio/dac/ad3530r.c +++ b/drivers/iio/dac/ad3530r.c @@ -166,7 +166,9 @@ static ssize_t ad3530r_set_dac_powerdown(struct iio_dev *indio_dev, AD3530R_OUTPUT_OPERATING_MODE_0 : AD3530R_OUTPUT_OPERATING_MODE_1; pdmode = powerdown ? st->chan[chan->channel].powerdown_mode : 0; - mask = AD3530R_OP_MODE_CHAN_MSK(chan->channel); + mask = chan->channel < AD3531R_MAX_CHANNELS ? + AD3530R_OP_MODE_CHAN_MSK(chan->channel) : + AD3530R_OP_MODE_CHAN_MSK(chan->channel - 4); val = field_prep(mask, pdmode); ret = regmap_update_bits(st->regmap, reg, mask, val); From 9fe58ecd1ed8162a96447fe6fbcbfb2f74be0b54 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 16 Jun 2025 11:38:42 +0200 Subject: [PATCH 20/35] mux: mmio: Fix missing CONFIG_REGMAP_MMIO MMIO mux uses now regmap_init_mmio(), so one way or another CONFIG_REGMAP_MMIO should be enabled, because there are no stubs for !REGMAP_MMIO case: ERROR: modpost: "__regmap_init_mmio_clk" [drivers/mux/mux-mmio.ko] undefined! Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202505150312.dYbBqUhG-lkp@intel.com/ Fixes: 61de83fd8256 ("mux: mmio: Do not use syscon helper to build regmap") Acked-by: Arnd Bergmann Link: https://lore.kernel.org/r/20250521152354.92720-2-krzysztof.kozlowski@linaro.org Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20250616093841.31985-2-krzysztof.kozlowski@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/mux/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig index 80f015cf6e54..c68132e38138 100644 --- a/drivers/mux/Kconfig +++ b/drivers/mux/Kconfig @@ -48,6 +48,7 @@ config MUX_GPIO config MUX_MMIO tristate "MMIO/Regmap register bitfield-controlled Multiplexer" depends on OF + select REGMAP_MMIO help MMIO/Regmap register bitfield-controlled Multiplexer controller. From ae68ad3d7a93ea1eedbce8e5813273163b971b36 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Sat, 5 Jul 2025 11:45:56 -0400 Subject: [PATCH 21/35] MAINTAINERS: add miscdevice Rust abstractions Add rust abstractions to miscdevice MAINTAINERS entry. Signed-off-by: Tamir Duberstein Acked-by: Boqun Feng Link: https://lore.kernel.org/r/20250705-miscdevice-maintainers-v1-1-9a6b67f7602f@gmail.com Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index c3f7fbd0d67a..a9a094e2c914 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5568,6 +5568,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git F: drivers/char/ F: drivers/misc/ F: include/linux/miscdevice.h +F: rust/kernel/miscdevice.rs F: samples/rust/rust_misc_device.rs X: drivers/char/agp/ X: drivers/char/hw_random/ From 2aa4ad626ee7f817a8f4715a47b318cfdc1714c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20B=C3=A4tz?= Date: Sat, 12 Jul 2025 19:17:27 +0100 Subject: [PATCH 22/35] nvmem: imx-ocotp: fix MAC address byte length MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The commit "13bcd440f2ff nvmem: core: verify cell's raw_len" caused an extension of the "mac-address" cell from 6 to 8 bytes due to word_size of 4 bytes. This led to a required byte swap of the full buffer length, which caused truncation of the mac-address when read. Previously, the mac-address was incorrectly truncated from 70:B3:D5:14:E9:0E to 00:00:70:B3:D5:14. Fix the issue by swapping only the first 6 bytes to correctly pass the mac-address to the upper layers. Fixes: 13bcd440f2ff ("nvmem: core: verify cell's raw_len") Cc: stable@vger.kernel.org Signed-off-by: Steffen Bätz Tested-by: Alexander Stein Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20250712181729.6495-3-srini@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/imx-ocotp-ele.c | 5 ++++- drivers/nvmem/imx-ocotp.c | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/nvmem/imx-ocotp-ele.c b/drivers/nvmem/imx-ocotp-ele.c index ca6dd71d8a2e..7807ec0e2d18 100644 --- a/drivers/nvmem/imx-ocotp-ele.c +++ b/drivers/nvmem/imx-ocotp-ele.c @@ -12,6 +12,7 @@ #include #include #include +#include /* ETH_ALEN */ enum fuse_type { FUSE_FSB = BIT(0), @@ -118,9 +119,11 @@ static int imx_ocotp_cell_pp(void *context, const char *id, int index, int i; /* Deal with some post processing of nvmem cell data */ - if (id && !strcmp(id, "mac-address")) + if (id && !strcmp(id, "mac-address")) { + bytes = min(bytes, ETH_ALEN); for (i = 0; i < bytes / 2; i++) swap(buf[i], buf[bytes - i - 1]); + } return 0; } diff --git a/drivers/nvmem/imx-ocotp.c b/drivers/nvmem/imx-ocotp.c index 79dd4fda0329..7bf7656d4f96 100644 --- a/drivers/nvmem/imx-ocotp.c +++ b/drivers/nvmem/imx-ocotp.c @@ -23,6 +23,7 @@ #include #include #include +#include /* ETH_ALEN */ #define IMX_OCOTP_OFFSET_B0W0 0x400 /* Offset from base address of the * OTP Bank0 Word0 @@ -227,9 +228,11 @@ static int imx_ocotp_cell_pp(void *context, const char *id, int index, int i; /* Deal with some post processing of nvmem cell data */ - if (id && !strcmp(id, "mac-address")) + if (id && !strcmp(id, "mac-address")) { + bytes = min(bytes, ETH_ALEN); for (i = 0; i < bytes / 2; i++) swap(buf[i], buf[bytes - i - 1]); + } return 0; } From 08ae4b20f5e82101d77326ecab9089e110f224cc Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 4 Jul 2025 13:04:05 +0100 Subject: [PATCH 23/35] comedi: Fail COMEDI_INSNLIST ioctl if n_insns is too large The handling of the `COMEDI_INSNLIST` ioctl allocates a kernel buffer to hold the array of `struct comedi_insn`, getting the length from the `n_insns` member of the `struct comedi_insnlist` supplied by the user. The allocation will fail with a WARNING and a stack dump if it is too large. Avoid that by failing with an `-EINVAL` error if the supplied `n_insns` value is unreasonable. Define the limit on the `n_insns` value in the `MAX_INSNS` macro. Set this to the same value as `MAX_SAMPLES` (65536), which is the maximum allowed sum of the values of the member `n` in the array of `struct comedi_insn`, and sensible comedi instructions will have an `n` of at least 1. Reported-by: syzbot+d6995b62e5ac7d79557a@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=d6995b62e5ac7d79557a Fixes: ed9eccbe8970 ("Staging: add comedi core") Tested-by: Ian Abbott Cc: stable@vger.kernel.org # 5.13+ Signed-off-by: Ian Abbott Link: https://lore.kernel.org/r/20250704120405.83028-1-abbotti@mev.co.uk Signed-off-by: Greg Kroah-Hartman --- drivers/comedi/comedi_fops.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/comedi/comedi_fops.c b/drivers/comedi/comedi_fops.c index 3383a7ce27ff..962fb9b18a52 100644 --- a/drivers/comedi/comedi_fops.c +++ b/drivers/comedi/comedi_fops.c @@ -1589,6 +1589,16 @@ static int do_insnlist_ioctl(struct comedi_device *dev, return i; } +#define MAX_INSNS MAX_SAMPLES +static int check_insnlist_len(struct comedi_device *dev, unsigned int n_insns) +{ + if (n_insns > MAX_INSNS) { + dev_dbg(dev->class_dev, "insnlist length too large\n"); + return -EINVAL; + } + return 0; +} + /* * COMEDI_INSN ioctl * synchronous instruction @@ -2239,6 +2249,9 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, rc = -EFAULT; break; } + rc = check_insnlist_len(dev, insnlist.n_insns); + if (rc) + break; insns = kcalloc(insnlist.n_insns, sizeof(*insns), GFP_KERNEL); if (!insns) { rc = -ENOMEM; @@ -3142,6 +3155,9 @@ static int compat_insnlist(struct file *file, unsigned long arg) if (copy_from_user(&insnlist32, compat_ptr(arg), sizeof(insnlist32))) return -EFAULT; + rc = check_insnlist_len(dev, insnlist32.n_insns); + if (rc) + return rc; insns = kcalloc(insnlist32.n_insns, sizeof(*insns), GFP_KERNEL); if (!insns) return -ENOMEM; From ab705c8c35e18652abc6239c07cf3441f03e2cda Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 7 Jul 2025 13:15:55 +0100 Subject: [PATCH 24/35] comedi: Fix some signed shift left operations Correct some left shifts of the signed integer constant 1 by some unsigned number less than 32. Change the constant to 1U to avoid shifting a 1 into the sign bit. The corrected functions are comedi_dio_insn_config(), comedi_dio_update_state(), and __comedi_device_postconfig(). Fixes: e523c6c86232 ("staging: comedi: drivers: introduce comedi_dio_insn_config()") Fixes: 05e60b13a36b ("staging: comedi: drivers: introduce comedi_dio_update_state()") Fixes: 09567cb4373e ("staging: comedi: initialize subdevice s->io_bits in postconfig") Cc: stable@vger.kernel.org # 5.13+ Signed-off-by: Ian Abbott Link: https://lore.kernel.org/r/20250707121555.65424-1-abbotti@mev.co.uk Signed-off-by: Greg Kroah-Hartman --- drivers/comedi/drivers.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/comedi/drivers.c b/drivers/comedi/drivers.c index 376130bfba8a..922fe20738ef 100644 --- a/drivers/comedi/drivers.c +++ b/drivers/comedi/drivers.c @@ -339,10 +339,10 @@ int comedi_dio_insn_config(struct comedi_device *dev, unsigned int *data, unsigned int mask) { - unsigned int chan_mask = 1 << CR_CHAN(insn->chanspec); + unsigned int chan = CR_CHAN(insn->chanspec); - if (!mask) - mask = chan_mask; + if (!mask && chan < 32) + mask = 1U << chan; switch (data[0]) { case INSN_CONFIG_DIO_INPUT: @@ -382,7 +382,7 @@ EXPORT_SYMBOL_GPL(comedi_dio_insn_config); unsigned int comedi_dio_update_state(struct comedi_subdevice *s, unsigned int *data) { - unsigned int chanmask = (s->n_chan < 32) ? ((1 << s->n_chan) - 1) + unsigned int chanmask = (s->n_chan < 32) ? ((1U << s->n_chan) - 1) : 0xffffffff; unsigned int mask = data[0] & chanmask; unsigned int bits = data[1]; @@ -625,8 +625,8 @@ static int insn_rw_emulate_bits(struct comedi_device *dev, if (insn->insn == INSN_WRITE) { if (!(s->subdev_flags & SDF_WRITABLE)) return -EINVAL; - _data[0] = 1 << (chan - base_chan); /* mask */ - _data[1] = data[0] ? (1 << (chan - base_chan)) : 0; /* bits */ + _data[0] = 1U << (chan - base_chan); /* mask */ + _data[1] = data[0] ? (1U << (chan - base_chan)) : 0; /* bits */ } ret = s->insn_bits(dev, s, &_insn, _data); @@ -709,7 +709,7 @@ static int __comedi_device_postconfig(struct comedi_device *dev) if (s->type == COMEDI_SUBD_DO) { if (s->n_chan < 32) - s->io_bits = (1 << s->n_chan) - 1; + s->io_bits = (1U << s->n_chan) - 1; else s->io_bits = 0xffffffff; } From ed93c6f68a3be06e4e0c331c6e751f462dee3932 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 7 Jul 2025 14:09:08 +0100 Subject: [PATCH 25/35] comedi: das16m1: Fix bit shift out of bounds When checking for a supported IRQ number, the following test is used: /* only irqs 2, 3, 4, 5, 6, 7, 10, 11, 12, 14, and 15 are valid */ if ((1 << it->options[1]) & 0xdcfc) { However, `it->options[i]` is an unchecked `int` value from userspace, so the shift amount could be negative or out of bounds. Fix the test by requiring `it->options[1]` to be within bounds before proceeding with the original test. Reported-by: syzbot+c52293513298e0fd9a94@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=c52293513298e0fd9a94 Fixes: 729988507680 ("staging: comedi: das16m1: tidy up the irq support in das16m1_attach()") Tested-by: syzbot+c52293513298e0fd9a94@syzkaller.appspotmail.com Suggested-by: "Enju, Kohei" Cc: stable@vger.kernel.org # 5.13+ Signed-off-by: Ian Abbott Link: https://lore.kernel.org/r/20250707130908.70758-1-abbotti@mev.co.uk Signed-off-by: Greg Kroah-Hartman --- drivers/comedi/drivers/das16m1.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/comedi/drivers/das16m1.c b/drivers/comedi/drivers/das16m1.c index b8ea737ad3d1..1b638f5b5a4f 100644 --- a/drivers/comedi/drivers/das16m1.c +++ b/drivers/comedi/drivers/das16m1.c @@ -522,7 +522,8 @@ static int das16m1_attach(struct comedi_device *dev, devpriv->extra_iobase = dev->iobase + DAS16M1_8255_IOBASE; /* only irqs 2, 3, 4, 5, 6, 7, 10, 11, 12, 14, and 15 are valid */ - if ((1 << it->options[1]) & 0xdcfc) { + if (it->options[1] >= 2 && it->options[1] <= 15 && + (1 << it->options[1]) & 0xdcfc) { ret = request_irq(it->options[1], das16m1_interrupt, 0, dev->board_name, dev); if (ret == 0) From b14b076ce593f72585412fc7fd3747e03a5e3632 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 7 Jul 2025 14:34:29 +0100 Subject: [PATCH 26/35] comedi: pcl812: Fix bit shift out of bounds When checking for a supported IRQ number, the following test is used: if ((1 << it->options[1]) & board->irq_bits) { However, `it->options[i]` is an unchecked `int` value from userspace, so the shift amount could be negative or out of bounds. Fix the test by requiring `it->options[1]` to be within bounds before proceeding with the original test. Valid `it->options[1]` values that select the IRQ will be in the range [1,15]. The value 0 explicitly disables the use of interrupts. Reported-by: syzbot+32de323b0addb9e114ff@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=32de323b0addb9e114ff Fixes: fcdb427bc7cf ("Staging: comedi: add pcl821 driver") Cc: stable@vger.kernel.org # 5.13+ Signed-off-by: Ian Abbott Link: https://lore.kernel.org/r/20250707133429.73202-1-abbotti@mev.co.uk Signed-off-by: Greg Kroah-Hartman --- drivers/comedi/drivers/pcl812.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/comedi/drivers/pcl812.c b/drivers/comedi/drivers/pcl812.c index 0df639c6a595..abca61a72cf7 100644 --- a/drivers/comedi/drivers/pcl812.c +++ b/drivers/comedi/drivers/pcl812.c @@ -1149,7 +1149,8 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (IS_ERR(dev->pacer)) return PTR_ERR(dev->pacer); - if ((1 << it->options[1]) & board->irq_bits) { + if (it->options[1] > 0 && it->options[1] < 16 && + (1 << it->options[1]) & board->irq_bits) { ret = request_irq(it->options[1], pcl812_interrupt, 0, dev->board_name, dev); if (ret == 0) From 66acb1586737a22dd7b78abc63213b1bcaa100e4 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 7 Jul 2025 14:46:22 +0100 Subject: [PATCH 27/35] comedi: aio_iiro_16: Fix bit shift out of bounds When checking for a supported IRQ number, the following test is used: if ((1 << it->options[1]) & 0xdcfc) { However, `it->options[i]` is an unchecked `int` value from userspace, so the shift amount could be negative or out of bounds. Fix the test by requiring `it->options[1]` to be within bounds before proceeding with the original test. Valid `it->options[1]` values that select the IRQ will be in the range [1,15]. The value 0 explicitly disables the use of interrupts. Fixes: ad7a370c8be4 ("staging: comedi: aio_iiro_16: add command support for change of state detection") Cc: stable@vger.kernel.org # 5.13+ Signed-off-by: Ian Abbott Link: https://lore.kernel.org/r/20250707134622.75403-1-abbotti@mev.co.uk Signed-off-by: Greg Kroah-Hartman --- drivers/comedi/drivers/aio_iiro_16.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/comedi/drivers/aio_iiro_16.c b/drivers/comedi/drivers/aio_iiro_16.c index b00fab0b89d4..739cc4db52ac 100644 --- a/drivers/comedi/drivers/aio_iiro_16.c +++ b/drivers/comedi/drivers/aio_iiro_16.c @@ -177,7 +177,8 @@ static int aio_iiro_16_attach(struct comedi_device *dev, * Digital input change of state interrupts are optionally supported * using IRQ 2-7, 10-12, 14, or 15. */ - if ((1 << it->options[1]) & 0xdcfc) { + if (it->options[1] > 0 && it->options[1] < 16 && + (1 << it->options[1]) & 0xdcfc) { ret = request_irq(it->options[1], aio_iiro_16_cos, 0, dev->board_name, dev); if (ret == 0) From 70f2b28b5243df557f51c054c20058ae207baaac Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 7 Jul 2025 14:57:37 +0100 Subject: [PATCH 28/35] comedi: das6402: Fix bit shift out of bounds When checking for a supported IRQ number, the following test is used: /* IRQs 2,3,5,6,7, 10,11,15 are valid for "enhanced" mode */ if ((1 << it->options[1]) & 0x8cec) { However, `it->options[i]` is an unchecked `int` value from userspace, so the shift amount could be negative or out of bounds. Fix the test by requiring `it->options[1]` to be within bounds before proceeding with the original test. Valid `it->options[1]` values that select the IRQ will be in the range [1,15]. The value 0 explicitly disables the use of interrupts. Fixes: 79e5e6addbb1 ("staging: comedi: das6402: rewrite broken driver") Cc: stable@vger.kernel.org # 5.13+ Signed-off-by: Ian Abbott Link: https://lore.kernel.org/r/20250707135737.77448-1-abbotti@mev.co.uk Signed-off-by: Greg Kroah-Hartman --- drivers/comedi/drivers/das6402.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/comedi/drivers/das6402.c b/drivers/comedi/drivers/das6402.c index 68f95330de45..7660487e563c 100644 --- a/drivers/comedi/drivers/das6402.c +++ b/drivers/comedi/drivers/das6402.c @@ -567,7 +567,8 @@ static int das6402_attach(struct comedi_device *dev, das6402_reset(dev); /* IRQs 2,3,5,6,7, 10,11,15 are valid for "enhanced" mode */ - if ((1 << it->options[1]) & 0x8cec) { + if (it->options[1] > 0 && it->options[1] < 16 && + (1 << it->options[1]) & 0x8cec) { ret = request_irq(it->options[1], das6402_interrupt, 0, dev->board_name, dev); if (ret == 0) { From e9cb26291d009243a4478a7ffb37b3a9175bfce9 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 7 Jul 2025 16:33:54 +0100 Subject: [PATCH 29/35] comedi: Fix use of uninitialized data in insn_rw_emulate_bits() For Comedi `INSN_READ` and `INSN_WRITE` instructions on "digital" subdevices (subdevice types `COMEDI_SUBD_DI`, `COMEDI_SUBD_DO`, and `COMEDI_SUBD_DIO`), it is common for the subdevice driver not to have `insn_read` and `insn_write` handler functions, but to have an `insn_bits` handler function for handling Comedi `INSN_BITS` instructions. In that case, the subdevice's `insn_read` and/or `insn_write` function handler pointers are set to point to the `insn_rw_emulate_bits()` function by `__comedi_device_postconfig()`. For `INSN_WRITE`, `insn_rw_emulate_bits()` currently assumes that the supplied `data[0]` value is a valid copy from user memory. It will at least exist because `do_insnlist_ioctl()` and `do_insn_ioctl()` in "comedi_fops.c" ensure at lease `MIN_SAMPLES` (16) elements are allocated. However, if `insn->n` is 0 (which is allowable for `INSN_READ` and `INSN_WRITE` instructions, then `data[0]` may contain uninitialized data, and certainly contains invalid data, possibly from a different instruction in the array of instructions handled by `do_insnlist_ioctl()`. This will result in an incorrect value being written to the digital output channel (or to the digital input/output channel if configured as an output), and may be reflected in the internal saved state of the channel. Fix it by returning 0 early if `insn->n` is 0, before reaching the code that accesses `data[0]`. Previously, the function always returned 1 on success, but it is supposed to be the number of data samples actually read or written up to `insn->n`, which is 0 in this case. Reported-by: syzbot+cb96ec476fb4914445c9@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=cb96ec476fb4914445c9 Fixes: ed9eccbe8970 ("Staging: add comedi core") Cc: stable@vger.kernel.org # 5.13+ Signed-off-by: Ian Abbott Link: https://lore.kernel.org/r/20250707153355.82474-1-abbotti@mev.co.uk Signed-off-by: Greg Kroah-Hartman --- drivers/comedi/drivers.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/comedi/drivers.c b/drivers/comedi/drivers.c index 922fe20738ef..9e4b7c840a8f 100644 --- a/drivers/comedi/drivers.c +++ b/drivers/comedi/drivers.c @@ -615,6 +615,9 @@ static int insn_rw_emulate_bits(struct comedi_device *dev, unsigned int _data[2]; int ret; + if (insn->n == 0) + return 0; + memset(_data, 0, sizeof(_data)); memset(&_insn, 0, sizeof(_insn)); _insn.insn = INSN_BITS; From 46d8c744136ce2454aa4c35c138cc06817f92b8e Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 7 Jul 2025 17:14:39 +0100 Subject: [PATCH 30/35] comedi: Fix initialization of data for instructions that write to subdevice Some Comedi subdevice instruction handlers are known to access instruction data elements beyond the first `insn->n` elements in some cases. The `do_insn_ioctl()` and `do_insnlist_ioctl()` functions allocate at least `MIN_SAMPLES` (16) data elements to deal with this, but they do not initialize all of that. For Comedi instruction codes that write to the subdevice, the first `insn->n` data elements are copied from user-space, but the remaining elements are left uninitialized. That could be a problem if the subdevice instruction handler reads the uninitialized data. Ensure that the first `MIN_SAMPLES` elements are initialized before calling these instruction handlers, filling the uncopied elements with 0. For `do_insnlist_ioctl()`, the same data buffer elements are used for handling a list of instructions, so ensure the first `MIN_SAMPLES` elements are initialized for each instruction that writes to the subdevice. Fixes: ed9eccbe8970 ("Staging: add comedi core") Cc: stable@vger.kernel.org # 5.13+ Signed-off-by: Ian Abbott Link: https://lore.kernel.org/r/20250707161439.88385-1-abbotti@mev.co.uk Signed-off-by: Greg Kroah-Hartman --- drivers/comedi/comedi_fops.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/comedi/comedi_fops.c b/drivers/comedi/comedi_fops.c index 962fb9b18a52..c83fd14dd7ad 100644 --- a/drivers/comedi/comedi_fops.c +++ b/drivers/comedi/comedi_fops.c @@ -1556,21 +1556,27 @@ static int do_insnlist_ioctl(struct comedi_device *dev, } for (i = 0; i < n_insns; ++i) { + unsigned int n = insns[i].n; + if (insns[i].insn & INSN_MASK_WRITE) { if (copy_from_user(data, insns[i].data, - insns[i].n * sizeof(unsigned int))) { + n * sizeof(unsigned int))) { dev_dbg(dev->class_dev, "copy_from_user failed\n"); ret = -EFAULT; goto error; } + if (n < MIN_SAMPLES) { + memset(&data[n], 0, (MIN_SAMPLES - n) * + sizeof(unsigned int)); + } } ret = parse_insn(dev, insns + i, data, file); if (ret < 0) goto error; if (insns[i].insn & INSN_MASK_READ) { if (copy_to_user(insns[i].data, data, - insns[i].n * sizeof(unsigned int))) { + n * sizeof(unsigned int))) { dev_dbg(dev->class_dev, "copy_to_user failed\n"); ret = -EFAULT; @@ -1643,6 +1649,10 @@ static int do_insn_ioctl(struct comedi_device *dev, ret = -EFAULT; goto error; } + if (insn->n < MIN_SAMPLES) { + memset(&data[insn->n], 0, + (MIN_SAMPLES - insn->n) * sizeof(unsigned int)); + } } ret = parse_insn(dev, insn, data, file); if (ret < 0) From 1b98304c09a0192598d0767f1eb8c83d7e793091 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 8 Jul 2025 14:06:27 +0100 Subject: [PATCH 31/35] comedi: comedi_test: Fix possible deletion of uninitialized timers In `waveform_common_attach()`, the two timers `&devpriv->ai_timer` and `&devpriv->ao_timer` are initialized after the allocation of the device private data by `comedi_alloc_devpriv()` and the subdevices by `comedi_alloc_subdevices()`. The function may return with an error between those function calls. In that case, `waveform_detach()` will be called by the Comedi core to clean up. The check that `waveform_detach()` uses to decide whether to delete the timers is incorrect. It only checks that the device private data was allocated, but that does not guarantee that the timers were initialized. It also needs to check that the subdevices were allocated. Fix it. Fixes: 73e0e4dfed4c ("staging: comedi: comedi_test: fix timer lock-up") Cc: stable@vger.kernel.org # 6.15+ Signed-off-by: Ian Abbott Link: https://lore.kernel.org/r/20250708130627.21743-1-abbotti@mev.co.uk Signed-off-by: Greg Kroah-Hartman --- drivers/comedi/drivers/comedi_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/comedi/drivers/comedi_test.c b/drivers/comedi/drivers/comedi_test.c index 9747e6d1f6eb..7984950f0f99 100644 --- a/drivers/comedi/drivers/comedi_test.c +++ b/drivers/comedi/drivers/comedi_test.c @@ -792,7 +792,7 @@ static void waveform_detach(struct comedi_device *dev) { struct waveform_private *devpriv = dev->private; - if (devpriv) { + if (devpriv && dev->n_subdevices) { timer_delete_sync(&devpriv->ai_timer); timer_delete_sync(&devpriv->ao_timer); } From e108b0a5d339aca9661cd93eb4258b2c661e11e8 Mon Sep 17 00:00:00 2001 From: Akshay Gupta Date: Wed, 16 Jul 2025 11:07:27 +0000 Subject: [PATCH 32/35] misc: amd-sbi: Address potential integer overflow issue reported in smatch Smatch warnings are reported for below commit, Commit bb13a84ed6b7 ("misc: amd-sbi: Add support for CPUID protocol") from Apr 28, 2025 (linux-next), leads to the following Smatch static checker warning: drivers/misc/amd-sbi/rmi-core.c:132 rmi_cpuid_read() warn: bitwise OR is zero '0xffffffff00000000 & 0xffff' drivers/misc/amd-sbi/rmi-core.c:132 rmi_cpuid_read() warn: potential integer overflow from user 'msg->cpu_in_out << 32' drivers/misc/amd-sbi/rmi-core.c:213 rmi_mca_msr_read() warn: bitwise OR is zero '0xffffffff00000000 & 0xffff' drivers/misc/amd-sbi/rmi-core.c:213 rmi_mca_msr_read() warn: potential integer overflow from user 'msg->mcamsr_in_out << 32' CPUID & MCAMSR thread data from input is available at byte 4 & 5, this patch fixes to copy the user data correctly in the argument. Previously, CPUID and MCAMSR data is return only for thread 0. Fixes: bb13a84ed6b7 ("misc: amd-sbi: Add support for CPUID protocol") Fixes: 69b1ba83d21c ("misc: amd-sbi: Add support for read MCA register protocol") Reported-by: Dan Carpenter Closes: https://lore.kernel.org/all/aDVyO8ByVsceybk9@stanley.mountain/ Reviewed-by: Naveen Krishna Chatradhi Signed-off-by: Akshay Gupta Link: https://lore.kernel.org/r/20250716110729.2193725-1-akshay.gupta@amd.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/amd-sbi/rmi-core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/misc/amd-sbi/rmi-core.c b/drivers/misc/amd-sbi/rmi-core.c index b653a21a909e..3570f3b269a9 100644 --- a/drivers/misc/amd-sbi/rmi-core.c +++ b/drivers/misc/amd-sbi/rmi-core.c @@ -42,7 +42,6 @@ #define RD_MCA_CMD 0x86 /* CPUID MCAMSR mask & index */ -#define CPUID_MCA_THRD_MASK GENMASK(15, 0) #define CPUID_MCA_THRD_INDEX 32 #define CPUID_MCA_FUNC_MASK GENMASK(31, 0) #define CPUID_EXT_FUNC_INDEX 56 @@ -129,7 +128,7 @@ static int rmi_cpuid_read(struct sbrmi_data *data, goto exit_unlock; } - thread = msg->cpu_in_out << CPUID_MCA_THRD_INDEX & CPUID_MCA_THRD_MASK; + thread = msg->cpu_in_out >> CPUID_MCA_THRD_INDEX; /* Thread > 127, Thread128 CS register, 1'b1 needs to be set to 1 */ if (thread > 127) { @@ -210,7 +209,7 @@ static int rmi_mca_msr_read(struct sbrmi_data *data, goto exit_unlock; } - thread = msg->mcamsr_in_out << CPUID_MCA_THRD_INDEX & CPUID_MCA_THRD_MASK; + thread = msg->mcamsr_in_out >> CPUID_MCA_THRD_INDEX; /* Thread > 127, Thread128 CS register, 1'b1 needs to be set to 1 */ if (thread > 127) { From bbb4013947fa5d9b2a65efdbfb08020abb060a18 Mon Sep 17 00:00:00 2001 From: Akshay Gupta Date: Wed, 16 Jul 2025 11:07:28 +0000 Subject: [PATCH 33/35] misc: amd-sbi: Address copy_to/from_user() warning reported in smatch Smatch warnings are reported for below commit, Commit bb13a84ed6b7 ("misc: amd-sbi: Add support for CPUID protocol") from Apr 28, 2025 (linux-next), leads to the following Smatch static checker warning: drivers/misc/amd-sbi/rmi-core.c:376 apml_rmi_reg_xfer() warn: maybe return -EFAULT instead of the bytes remaining? drivers/misc/amd-sbi/rmi-core.c:394 apml_mailbox_xfer() warn: maybe return -EFAULT instead of the bytes remaining? drivers/misc/amd-sbi/rmi-core.c:411 apml_cpuid_xfer() warn: maybe return -EFAULT instead of the bytes remaining? drivers/misc/amd-sbi/rmi-core.c:428 apml_mcamsr_xfer() warn: maybe return -EFAULT instead of the bytes remaining? copy_to/from_user() returns number of bytes, not copied. In case data not copied, return "-EFAULT". Additionally, fixes the "-EPROTOTYPE" error return as intended. Fixes: 35ac2034db72 ("misc: amd-sbi: Add support for AMD_SBI IOCTL") Fixes: bb13a84ed6b7 ("misc: amd-sbi: Add support for CPUID protocol") Fixes: 69b1ba83d21c ("misc: amd-sbi: Add support for read MCA register protocol") Fixes: cf141287b774 ("misc: amd-sbi: Add support for register xfer") Reported-by: Dan Carpenter Closes: https://lore.kernel.org/all/aDVyO8ByVsceybk9@stanley.mountain/ Reviewed-by: Naveen Krishna Chatradhi Signed-off-by: Akshay Gupta Link: https://lore.kernel.org/r/20250716110729.2193725-2-akshay.gupta@amd.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/amd-sbi/rmi-core.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/misc/amd-sbi/rmi-core.c b/drivers/misc/amd-sbi/rmi-core.c index 3570f3b269a9..9048517c088c 100644 --- a/drivers/misc/amd-sbi/rmi-core.c +++ b/drivers/misc/amd-sbi/rmi-core.c @@ -372,7 +372,8 @@ static int apml_rmi_reg_xfer(struct sbrmi_data *data, mutex_unlock(&data->lock); if (msg.rflag && !ret) - return copy_to_user(arg, &msg, sizeof(struct apml_reg_xfer_msg)); + if (copy_to_user(arg, &msg, sizeof(struct apml_reg_xfer_msg))) + return -EFAULT; return ret; } @@ -390,7 +391,9 @@ static int apml_mailbox_xfer(struct sbrmi_data *data, struct apml_mbox_msg __use if (ret && ret != -EPROTOTYPE) return ret; - return copy_to_user(arg, &msg, sizeof(struct apml_mbox_msg)); + if (copy_to_user(arg, &msg, sizeof(struct apml_mbox_msg))) + return -EFAULT; + return ret; } static int apml_cpuid_xfer(struct sbrmi_data *data, struct apml_cpuid_msg __user *arg) @@ -407,7 +410,9 @@ static int apml_cpuid_xfer(struct sbrmi_data *data, struct apml_cpuid_msg __user if (ret && ret != -EPROTOTYPE) return ret; - return copy_to_user(arg, &msg, sizeof(struct apml_cpuid_msg)); + if (copy_to_user(arg, &msg, sizeof(struct apml_cpuid_msg))) + return -EFAULT; + return ret; } static int apml_mcamsr_xfer(struct sbrmi_data *data, struct apml_mcamsr_msg __user *arg) @@ -424,7 +429,9 @@ static int apml_mcamsr_xfer(struct sbrmi_data *data, struct apml_mcamsr_msg __us if (ret && ret != -EPROTOTYPE) return ret; - return copy_to_user(arg, &msg, sizeof(struct apml_mcamsr_msg)); + if (copy_to_user(arg, &msg, sizeof(struct apml_mcamsr_msg))) + return -EFAULT; + return ret; } static long sbrmi_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) From 16ad3ee51fc95ae8e06b9934fa2f656a5e4a8f03 Mon Sep 17 00:00:00 2001 From: Akshay Gupta Date: Wed, 16 Jul 2025 11:07:29 +0000 Subject: [PATCH 34/35] misc: amd-sbi: Explicitly clear in/out arg "mb_in_out" - New AMD processor will support different input/output for same command. - In some scenarios the input value is not cleared, which will be added to output before reporting the data. - Clearing input explicitly will be a cleaner and safer approach. Reviewed-by: Naveen Krishna Chatradhi Signed-off-by: Akshay Gupta Link: https://lore.kernel.org/r/20250716110729.2193725-3-akshay.gupta@amd.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/amd-sbi/rmi-core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/misc/amd-sbi/rmi-core.c b/drivers/misc/amd-sbi/rmi-core.c index 9048517c088c..3dec2fc00124 100644 --- a/drivers/misc/amd-sbi/rmi-core.c +++ b/drivers/misc/amd-sbi/rmi-core.c @@ -320,6 +320,10 @@ int rmi_mailbox_xfer(struct sbrmi_data *data, ret = regmap_read(data->regmap, SBRMI_OUTBNDMSG7, &ec); if (ret || ec) goto exit_clear_alert; + + /* Clear the input value before updating the output data */ + msg->mb_in_out = 0; + /* * For a read operation, the initiator (BMC) reads the firmware * response Command Data Out[31:0] from SBRMI::OutBndMsg_inst[4:1] From 2d7521aa26ec2dc8b877bb2d1f2611a2df49a3cf Mon Sep 17 00:00:00 2001 From: "Michael C. Pratt" Date: Wed, 16 Jul 2025 15:42:10 +0100 Subject: [PATCH 35/35] nvmem: layouts: u-boot-env: remove crc32 endianness conversion On 11 Oct 2022, it was reported that the crc32 verification of the u-boot environment failed only on big-endian systems for the u-boot-env nvmem layout driver with the following error. Invalid calculated CRC32: 0x88cd6f09 (expected: 0x096fcd88) This problem has been present since the driver was introduced, and before it was made into a layout driver. The suggested fix at the time was to use further endianness conversion macros in order to have both the stored and calculated crc32 values to compare always represented in the system's endianness. This was not accepted due to sparse warnings and some disagreement on how to handle the situation. Later on in a newer revision of the patch, it was proposed to use cpu_to_le32() for both values to compare instead of le32_to_cpu() and store the values as __le32 type to remove compilation errors. The necessity of this is based on the assumption that the use of crc32() requires endianness conversion because the algorithm uses little-endian, however, this does not prove to be the case and the issue is unrelated. Upon inspecting the current kernel code, there already is an existing use of le32_to_cpu() in this driver, which suggests there already is special handling for big-endian systems, however, it is big-endian systems that have the problem. This, being the only functional difference between architectures in the driver combined with the fact that the suggested fix was to use the exact same endianness conversion for the values brings up the possibility that it was not necessary to begin with, as the same endianness conversion for two values expected to be the same is expected to be equivalent to no conversion at all. After inspecting the u-boot environment of devices of both endianness and trying to remove the existing endianness conversion, the problem is resolved in an equivalent way as the other suggested fixes. Ultimately, it seems that u-boot is agnostic to endianness at least for the purpose of environment variables. In other words, u-boot reads and writes the stored crc32 value with the same endianness that the crc32 value is calculated with in whichever endianness a certain architecture runs on. Therefore, the u-boot-env driver does not need to convert endianness. Remove the usage of endianness macros in the u-boot-env driver, and change the type of local variables to maintain the same return type. If there is a special situation in the case of endianness, it would be a corner case and should be handled by a unique "compatible". Even though it is not necessary to use endianness conversion macros here, it may be useful to use them in the future for consistent error printing. Fixes: d5542923f200 ("nvmem: add driver handling U-Boot environment variables") Reported-by: INAGAKI Hiroshi Link: https://lore.kernel.org/all/20221011024928.1807-1-musashino.open@gmail.com Cc: stable@vger.kernel.org Signed-off-by: "Michael C. Pratt" Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20250716144210.4804-1-srini@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/layouts/u-boot-env.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/nvmem/layouts/u-boot-env.c b/drivers/nvmem/layouts/u-boot-env.c index 436426d4e8f9..8571aac56295 100644 --- a/drivers/nvmem/layouts/u-boot-env.c +++ b/drivers/nvmem/layouts/u-boot-env.c @@ -92,7 +92,7 @@ int u_boot_env_parse(struct device *dev, struct nvmem_device *nvmem, size_t crc32_data_offset; size_t crc32_data_len; size_t crc32_offset; - __le32 *crc32_addr; + uint32_t *crc32_addr; size_t data_offset; size_t data_len; size_t dev_size; @@ -143,8 +143,8 @@ int u_boot_env_parse(struct device *dev, struct nvmem_device *nvmem, goto err_kfree; } - crc32_addr = (__le32 *)(buf + crc32_offset); - crc32 = le32_to_cpu(*crc32_addr); + crc32_addr = (uint32_t *)(buf + crc32_offset); + crc32 = *crc32_addr; crc32_data_len = dev_size - crc32_data_offset; data_len = dev_size - data_offset;