From 48a5c36577ebe0144f8ede70e59b59ea18b75089 Mon Sep 17 00:00:00 2001 From: Felix Gu Date: Sat, 28 Feb 2026 01:48:19 +0800 Subject: [PATCH 01/63] iio: adc: ti-ads1119: Fix unbalanced pm reference count in ds1119_single_conversion() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In ads1119_single_conversion(), if pm_runtime_resume_and_get() fails, the code jumps to the pdown label, which calls pm_runtime_put_autosuspend(). Since pm_runtime_resume_and_get() automatically decrements the usage counter on failure, the subsequent call to pm_runtime_put_autosuspend() causes an unbalanced reference counter. Fixes: a9306887eba4 ("iio: adc: ti-ads1119: Add driver") Signed-off-by: Felix Gu Reviewed-by: João Paulo Gonçalves Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ti-ads1119.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/ti-ads1119.c b/drivers/iio/adc/ti-ads1119.c index c9cedc59cdcd..4454f28b2b58 100644 --- a/drivers/iio/adc/ti-ads1119.c +++ b/drivers/iio/adc/ti-ads1119.c @@ -274,7 +274,7 @@ static int ads1119_single_conversion(struct ads1119_state *st, ret = pm_runtime_resume_and_get(dev); if (ret) - goto pdown; + return ret; ret = ads1119_configure_channel(st, mux, gain, datarate); if (ret) From c53bca092486809d266b5921b9e6f9df2688fc26 Mon Sep 17 00:00:00 2001 From: Felix Gu Date: Fri, 27 Feb 2026 21:54:29 +0800 Subject: [PATCH 02/63] iio: pressure: abp2030pa: Remove IRQF_ONESHOT from devm_request_irq() Since commit aef30c8d569c ("genirq: Warn about using IRQF_ONESHOT without a threaded handler"), the IRQ core checks IRQF_ONESHOT flag in IRQ request and gives a warning if there is no threaded handler. Remove IRQF_ONESHOT from devm_request_irq(). Fixes: 47d323ce1e89 ("iio: pressure: add Honeywell ABP2 driver") Reviewed-by: Sebastian Andrzej Siewior Signed-off-by: Felix Gu Tested-by: Petre Rodan Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/abp2030pa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/pressure/abp2030pa.c b/drivers/iio/pressure/abp2030pa.c index 4ca056a73cef..b44f1bf4c633 100644 --- a/drivers/iio/pressure/abp2030pa.c +++ b/drivers/iio/pressure/abp2030pa.c @@ -520,7 +520,7 @@ int abp2_common_probe(struct device *dev, const struct abp2_ops *ops, int irq) data->p_offset = div_s64(odelta * data->pmin, pdelta) - data->outmin; if (data->irq > 0) { - ret = devm_request_irq(dev, irq, abp2_eoc_handler, IRQF_ONESHOT, + ret = devm_request_irq(dev, irq, abp2_eoc_handler, 0, dev_name(dev), data); if (ret) return ret; From 0206dd36418c104c0b3dea4ed7047e21eccb30b0 Mon Sep 17 00:00:00 2001 From: Antoniu Miclaus Date: Fri, 27 Feb 2026 15:33:30 +0200 Subject: [PATCH 03/63] iio: adc: ade9000: move mutex init before IRQ registration Move devm_mutex_init() before ade9000_request_irq() calls so that st->lock is initialized before any handler that depends on it can run. Fixes: 81de7b4619fc ("iio: adc: add ade9000 support") Signed-off-by: Antoniu Miclaus Reviewed-by: Andy Shevchenko Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ade9000.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/iio/adc/ade9000.c b/drivers/iio/adc/ade9000.c index db085dc5e526..c62c6480dd0a 100644 --- a/drivers/iio/adc/ade9000.c +++ b/drivers/iio/adc/ade9000.c @@ -1706,6 +1706,10 @@ static int ade9000_probe(struct spi_device *spi) init_completion(&st->reset_completion); + ret = devm_mutex_init(dev, &st->lock); + if (ret) + return ret; + ret = ade9000_request_irq(dev, "irq0", ade9000_irq0_thread, indio_dev); if (ret) return ret; @@ -1718,10 +1722,6 @@ static int ade9000_probe(struct spi_device *spi) if (ret) return ret; - ret = devm_mutex_init(dev, &st->lock); - if (ret) - return ret; - /* External CMOS clock input (optional - crystal can be used instead) */ st->clkin = devm_clk_get_optional_enabled(dev, NULL); if (IS_ERR(st->clkin)) From bd66aa1c8b8cabf459064a46d3430a5ec5138418 Mon Sep 17 00:00:00 2001 From: Antoniu Miclaus Date: Fri, 27 Feb 2026 14:43:05 +0200 Subject: [PATCH 04/63] iio: accel: adxl380: fix FIFO watermark bit 8 always written as 0 FIELD_PREP(BIT(0), fifo_samples & BIT(8)) produces either 0 or 256, and since FIELD_PREP masks to bit 0, 256 & 1 evaluates to 0. Use !! to convert the result to a proper 0-or-1 value. Fixes: df36de13677a ("iio: accel: add ADXL380 driver") Signed-off-by: Antoniu Miclaus Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/accel/adxl380.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/accel/adxl380.c b/drivers/iio/accel/adxl380.c index 8fab2fdbe147..a51d1d61c412 100644 --- a/drivers/iio/accel/adxl380.c +++ b/drivers/iio/accel/adxl380.c @@ -877,7 +877,7 @@ static int adxl380_set_fifo_samples(struct adxl380_state *st) ret = regmap_update_bits(st->regmap, ADXL380_FIFO_CONFIG_0_REG, ADXL380_FIFO_SAMPLES_8_MSK, FIELD_PREP(ADXL380_FIFO_SAMPLES_8_MSK, - (fifo_samples & BIT(8)))); + !!(fifo_samples & BIT(8)))); if (ret) return ret; From 86133fb1ec36b2f5cec29d71fbae84877c3a1358 Mon Sep 17 00:00:00 2001 From: Giorgi Tchankvetadze Date: Thu, 26 Feb 2026 18:07:02 +0400 Subject: [PATCH 05/63] iio: adc: ade9000: fix wrong register in CALIBBIAS case for active power The switch statement in ade9000_write_raw() attempts to match chan->address against ADE9000_REG_AWATTOS (0x00F) to dispatch the calibration offset write for active power channels. However, chan->address is set via ADE9000_ADDR_ADJUST(ADE9000_REG_AWATT, num), so after masking the phase bits, tmp holds ADE9000_REG_AWATT (0x210), which never matches 0x00F. As a result, writing IIO_CHAN_INFO_CALIBBIAS for IIO_POWER always falls through to the default case and returns -EINVAL, making active power offset calibration silently broken. Fix this by matching against ADE9000_REG_AWATT instead, which is the actual base address stored in chan->address for watt channels. Reference:ADE9000 datasheet (Rev. B), AWATTOS is the offset correction register at 0x00F (p. 44), while AWATT is the total active power register at 0x210 (p. 48). Fixes: 81de7b4619fc ("iio: adc: add ade9000 support") Signed-off-by: Giorgi Tchankvetadze Reviewed-by: Antoniu Miclaus Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ade9000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/ade9000.c b/drivers/iio/adc/ade9000.c index c62c6480dd0a..945a159e5de6 100644 --- a/drivers/iio/adc/ade9000.c +++ b/drivers/iio/adc/ade9000.c @@ -1123,7 +1123,7 @@ static int ade9000_write_raw(struct iio_dev *indio_dev, tmp &= ~ADE9000_PHASE_C_POS_BIT; switch (tmp) { - case ADE9000_REG_AWATTOS: + case ADE9000_REG_AWATT: return regmap_write(st->regmap, ADE9000_ADDR_ADJUST(ADE9000_REG_AWATTOS, chan->channel), val); From 57b207e38d414a27fda9fff638a0d3e7ef16b917 Mon Sep 17 00:00:00 2001 From: Giorgi Tchankvetadze Date: Tue, 24 Feb 2026 17:23:55 +0400 Subject: [PATCH 06/63] iio: adc: ade9000: fix wrong return type in streaming push The else branch of ade9000_iio_push_streaming() incorrectly returns IRQ_HANDLED on regmap_write failure. This function returns int (0 on success, negative errno on failure), so IRQ_HANDLED (1) would be misinterpreted as a non-error by callers. Return ret instead, consistent with every other error path in the function. Fixes: 81de7b4619fc ("iio: adc: add ade9000 support") Signed-off-by: Giorgi Tchankvetadze Reviewed-by: Antoniu Miclaus Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ade9000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/ade9000.c b/drivers/iio/adc/ade9000.c index 945a159e5de6..1abbfdfcd554 100644 --- a/drivers/iio/adc/ade9000.c +++ b/drivers/iio/adc/ade9000.c @@ -787,7 +787,7 @@ static int ade9000_iio_push_streaming(struct iio_dev *indio_dev) ADE9000_MIDDLE_PAGE_BIT); if (ret) { dev_err_ratelimited(dev, "IRQ0 WFB write fail"); - return IRQ_HANDLED; + return ret; } ade9000_configure_scan(indio_dev, ADE9000_REG_WF_BUFF); From b403981da8a26f57f07859a9704392b1183e2a6e Mon Sep 17 00:00:00 2001 From: Felix Gu Date: Wed, 25 Feb 2026 22:48:57 +0800 Subject: [PATCH 07/63] iio: dac: mcp47feb02: Fix mutex used before initialization The mcp47feb02_parse_fw() function uses data->lock, but the mutex was initialized after this function in probe path. Since mcp47feb02_parse_fw() is only called from probe(), remove the lock. Fixes: bf394cc80369 ("iio: dac: adding support for Microchip MCP47FEB02") Signed-off-by: Felix Gu Signed-off-by: Jonathan Cameron --- drivers/iio/dac/mcp47feb02.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/iio/dac/mcp47feb02.c b/drivers/iio/dac/mcp47feb02.c index b218f0c3a0bd..08fb85359697 100644 --- a/drivers/iio/dac/mcp47feb02.c +++ b/drivers/iio/dac/mcp47feb02.c @@ -955,8 +955,6 @@ static int mcp47feb02_parse_fw(struct iio_dev *indio_dev, u32 num_channels; u8 chan_idx = 0; - guard(mutex)(&data->lock); - num_channels = device_get_child_node_count(dev); if (num_channels > chip_features->phys_channels) return dev_err_probe(dev, -EINVAL, "More channels than the chip supports\n"); From 630748afa7030b272b7bee5df857e7bcf132ed51 Mon Sep 17 00:00:00 2001 From: Francesco Lavra Date: Wed, 25 Feb 2026 11:06:00 +0100 Subject: [PATCH 08/63] iio: imu: st_lsm6dsx: Set FIFO ODR for accelerometer and gyroscope only The st_lsm6dsx_set_fifo_odr() function, which is called when enabling and disabling the hardware FIFO, checks the contents of the hw->settings->batch array at index sensor->id, and then sets the current ODR value in sensor registers that depend on whether the register address is set in the above array element. This logic is valid for internal sensors only, i.e. the accelerometer and gyroscope; however, since commit c91c1c844ebd ("iio: imu: st_lsm6dsx: add i2c embedded controller support"), this function is called also when configuring the hardware FIFO for external sensors (i.e. sensors accessed through the sensor hub functionality), which can result in unrelated device registers being written. Add a check to the beginning of st_lsm6dsx_set_fifo_odr() so that it does not touch any registers unless it is called for internal sensors. Fixes: c91c1c844ebd ("iio: imu: st_lsm6dsx: add i2c embedded controller support") Signed-off-by: Francesco Lavra Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c index 55d877745575..1ee2fc5f5f1f 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c @@ -225,6 +225,10 @@ static int st_lsm6dsx_set_fifo_odr(struct st_lsm6dsx_sensor *sensor, const struct st_lsm6dsx_reg *batch_reg; u8 data; + /* Only internal sensors have a FIFO ODR configuration register. */ + if (sensor->id >= ARRAY_SIZE(hw->settings->batch)) + return 0; + batch_reg = &hw->settings->batch[sensor->id]; if (batch_reg->addr) { int val; From 679c04c10d65d32a3f269e696b22912ff0a001b9 Mon Sep 17 00:00:00 2001 From: Francesco Lavra Date: Wed, 25 Feb 2026 11:06:01 +0100 Subject: [PATCH 09/63] iio: imu: st_lsm6dsx: Set buffer sampling frequency for accelerometer only The st_lsm6dsx_hwfifo_odr_store() function, which is called when userspace writes the buffer sampling frequency sysfs attribute, calls st_lsm6dsx_check_odr(), which accesses the odr_table array at index `sensor->id`; since this array is only 2 entries long, an access for any sensor type other than accelerometer or gyroscope is an out-of-bounds access. The motivation for being able to set a buffer frequency different from the sensor sampling frequency is to support use cases that need accurate event detection (which requires a high sampling frequency) while retrieving sensor data at low frequency. Since all the supported event types are generated from acceleration data only, do not create the buffer sampling frequency attribute for sensor types other than the accelerometer. Fixes: 6b648a36c200 ("iio: imu: st_lsm6dsx: Decouple sensor ODR from FIFO batch data rate") Signed-off-by: Francesco Lavra Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c index 1ee2fc5f5f1f..5b28a3ffcc3d 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c @@ -862,12 +862,21 @@ int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw) int i, ret; for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { + const struct iio_dev_attr **attrs; + if (!hw->iio_devs[i]) continue; + /* + * For the accelerometer, allow setting FIFO sampling frequency + * values different from the sensor sampling frequency, which + * may be needed to keep FIFO data rate low while sampling + * acceleration data at high rates for accurate event detection. + */ + attrs = i == ST_LSM6DSX_ID_ACC ? st_lsm6dsx_buffer_attrs : NULL; ret = devm_iio_kfifo_buffer_setup_ext(hw->dev, hw->iio_devs[i], &st_lsm6dsx_buffer_ops, - st_lsm6dsx_buffer_attrs); + attrs); if (ret) return ret; } From edb11a1aef4011a4b7b22cc3c3396c6fe371f4a6 Mon Sep 17 00:00:00 2001 From: Ethan Tidmore Date: Tue, 24 Feb 2026 16:48:15 -0600 Subject: [PATCH 10/63] iio: gyro: mpu3050: Fix incorrect free_irq() variable The handler for the IRQ part of this driver is mpu3050->trig but, in the teardown free_irq() is called with handler mpu3050. Use correct IRQ handler when calling free_irq(). Fixes: 3904b28efb2c7 ("iio: gyro: Add driver for the MPU-3050 gyroscope") Reviewed-by: Linus Walleij Signed-off-by: Ethan Tidmore Reviewed-by: Andy Shevchenko Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/mpu3050-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/gyro/mpu3050-core.c b/drivers/iio/gyro/mpu3050-core.c index 317e7b217ec6..8df1f524d342 100644 --- a/drivers/iio/gyro/mpu3050-core.c +++ b/drivers/iio/gyro/mpu3050-core.c @@ -1269,7 +1269,7 @@ void mpu3050_common_remove(struct device *dev) pm_runtime_disable(dev); iio_triggered_buffer_cleanup(indio_dev); if (mpu3050->irq) - free_irq(mpu3050->irq, mpu3050); + free_irq(mpu3050->irq, mpu3050->trig); iio_device_unregister(indio_dev); mpu3050_power_down(mpu3050); } From 4216db1043a3be72ef9c2b7b9f393d7fa72496e6 Mon Sep 17 00:00:00 2001 From: Ethan Tidmore Date: Tue, 24 Feb 2026 16:48:16 -0600 Subject: [PATCH 11/63] iio: gyro: mpu3050: Fix irq resource leak The interrupt handler is setup but only a few lines down if iio_trigger_register() fails the function returns without properly releasing the handler. Add cleanup goto to resolve resource leak. Detected by Smatch: drivers/iio/gyro/mpu3050-core.c:1128 mpu3050_trigger_probe() warn: 'irq' from request_threaded_irq() not released on lines: 1124. Fixes: 3904b28efb2c7 ("iio: gyro: Add driver for the MPU-3050 gyroscope") Reviewed-by: Linus Walleij Signed-off-by: Ethan Tidmore Reviewed-by: Andy Shevchenko Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/mpu3050-core.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/iio/gyro/mpu3050-core.c b/drivers/iio/gyro/mpu3050-core.c index 8df1f524d342..d2f0899ac46b 100644 --- a/drivers/iio/gyro/mpu3050-core.c +++ b/drivers/iio/gyro/mpu3050-core.c @@ -1129,11 +1129,16 @@ static int mpu3050_trigger_probe(struct iio_dev *indio_dev, int irq) ret = iio_trigger_register(mpu3050->trig); if (ret) - return ret; + goto err_iio_trigger; indio_dev->trig = iio_trigger_get(mpu3050->trig); return 0; + +err_iio_trigger: + free_irq(mpu3050->irq, mpu3050->trig); + + return ret; } int mpu3050_common_probe(struct device *dev, From 4c05799449108fb0e0a6bd30e65fffc71e60db4d Mon Sep 17 00:00:00 2001 From: Ethan Tidmore Date: Tue, 24 Feb 2026 16:48:17 -0600 Subject: [PATCH 12/63] iio: gyro: mpu3050: Move iio_device_register() to correct location iio_device_register() should be at the end of the probe function to prevent race conditions. Place iio_device_register() at the end of the probe function and place iio_device_unregister() accordingly. Fixes: 3904b28efb2c7 ("iio: gyro: Add driver for the MPU-3050 gyroscope") Suggested-by: Jonathan Cameron Reviewed-by: Linus Walleij Signed-off-by: Ethan Tidmore Reviewed-by: Andy Shevchenko Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/mpu3050-core.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/iio/gyro/mpu3050-core.c b/drivers/iio/gyro/mpu3050-core.c index d2f0899ac46b..2e92daf047bd 100644 --- a/drivers/iio/gyro/mpu3050-core.c +++ b/drivers/iio/gyro/mpu3050-core.c @@ -1226,12 +1226,6 @@ int mpu3050_common_probe(struct device *dev, goto err_power_down; } - ret = iio_device_register(indio_dev); - if (ret) { - dev_err(dev, "device register failed\n"); - goto err_cleanup_buffer; - } - dev_set_drvdata(dev, indio_dev); /* Check if we have an assigned IRQ to use as trigger */ @@ -1254,9 +1248,20 @@ int mpu3050_common_probe(struct device *dev, pm_runtime_use_autosuspend(dev); pm_runtime_put(dev); + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(dev, "device register failed\n"); + goto err_iio_device_register; + } + return 0; -err_cleanup_buffer: +err_iio_device_register: + pm_runtime_get_sync(dev); + pm_runtime_put_noidle(dev); + pm_runtime_disable(dev); + if (irq) + free_irq(mpu3050->irq, mpu3050->trig); iio_triggered_buffer_cleanup(indio_dev); err_power_down: mpu3050_power_down(mpu3050); @@ -1269,13 +1274,13 @@ void mpu3050_common_remove(struct device *dev) struct iio_dev *indio_dev = dev_get_drvdata(dev); struct mpu3050 *mpu3050 = iio_priv(indio_dev); + iio_device_unregister(indio_dev); pm_runtime_get_sync(dev); pm_runtime_put_noidle(dev); pm_runtime_disable(dev); iio_triggered_buffer_cleanup(indio_dev); if (mpu3050->irq) free_irq(mpu3050->irq, mpu3050->trig); - iio_device_unregister(indio_dev); mpu3050_power_down(mpu3050); } From d14116f6529fa085b1a1b1f224dc9604e4d2a29c Mon Sep 17 00:00:00 2001 From: Ethan Tidmore Date: Tue, 24 Feb 2026 16:48:18 -0600 Subject: [PATCH 13/63] iio: gyro: mpu3050: Fix out-of-sequence free_irq() The triggered buffer is initialized before the IRQ is requested. The removal path currently calls iio_triggered_buffer_cleanup() before free_irq(). This violates the expected LIFO. Place free_irq() in the correct location relative to iio_triggered_buffer_cleanup(). Fixes: 3904b28efb2c7 ("iio: gyro: Add driver for the MPU-3050 gyroscope") Suggested-by: Jonathan Cameron Reviewed-by: Linus Walleij Signed-off-by: Ethan Tidmore Reviewed-by: Andy Shevchenko Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/mpu3050-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/gyro/mpu3050-core.c b/drivers/iio/gyro/mpu3050-core.c index 2e92daf047bd..d84e04e4b431 100644 --- a/drivers/iio/gyro/mpu3050-core.c +++ b/drivers/iio/gyro/mpu3050-core.c @@ -1278,9 +1278,9 @@ void mpu3050_common_remove(struct device *dev) pm_runtime_get_sync(dev); pm_runtime_put_noidle(dev); pm_runtime_disable(dev); - iio_triggered_buffer_cleanup(indio_dev); if (mpu3050->irq) free_irq(mpu3050->irq, mpu3050->trig); + iio_triggered_buffer_cleanup(indio_dev); mpu3050_power_down(mpu3050); } From 20c2a46da4c65ac9c84f2876e2369a260b50e95b Mon Sep 17 00:00:00 2001 From: Felix Gu Date: Mon, 23 Feb 2026 14:45:13 +0800 Subject: [PATCH 14/63] iio: adc: ad4062: Replace IRQF_ONESHOT with IRQF_NO_THREAD In ad4062_request_irq(), when request irq for "gp1", the code uses IRQF_ONESHOT flag, which is not appropriate for a primary handler that does not have a secondary threaded handler. And since commit aef30c8d569c ("genirq: Warn about using IRQF_ONESHOT without a threaded handler"), the IRQ core checks IRQF_ONESHOT flag in IRQ request and gives a warning if there is no threaded handler. Since there is no threaded handler, replace devm_request_threaded_irq with devm_request_irq, and replace IRQF_ONESHOT with IRQF_NO_THREAD. Also remove an extraneous semicolon at the end of ad4062_write_raw_dispatch(). Found by code review, compile pass. Fixes: d5284402d28f ("iio: adc: Add support for ad4062") Signed-off-by: Felix Gu Reviewed-by: Sebastian Andrzej Siewior Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad4062.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/iio/adc/ad4062.c b/drivers/iio/adc/ad4062.c index dd4ad32aa6f5..8b03736d55fc 100644 --- a/drivers/iio/adc/ad4062.c +++ b/drivers/iio/adc/ad4062.c @@ -719,10 +719,8 @@ static int ad4062_request_irq(struct iio_dev *indio_dev) } st->gpo_irq[1] = true; - return devm_request_threaded_irq(dev, ret, - ad4062_irq_handler_drdy, - NULL, IRQF_ONESHOT, indio_dev->name, - indio_dev); + return devm_request_irq(dev, ret, ad4062_irq_handler_drdy, + IRQF_NO_THREAD, indio_dev->name, indio_dev); } static const struct iio_trigger_ops ad4062_trigger_ops = { @@ -955,7 +953,7 @@ static int ad4062_write_raw_dispatch(struct ad4062_state *st, int val, int val2, default: return -EINVAL; } -}; +} static int ad4062_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, From c47ac75f5f24020cc0c8b835457a7637ad450939 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Fri, 20 Feb 2026 14:45:14 -0800 Subject: [PATCH 15/63] iio: hid-sensors: Use software trigger Recent changes linux mainline resulted in warning: "genirq: Warn about using IRQF_ONESHOT without a threaded handler" when HID sensor hub is used. When INDIO_BUFFER_TRIGGERED is used, the core attaches a poll function when enabling the buffer. This poll function uses request_threaded_irq() with both bottom half and top half handlers. But when using HID sensor hub, bottom half (thread handler) is not registered. In HID sensors, once a sensor is powered on, the hub collects samples and pushes data to the host when programmed thresholds are met. When this data is received for a sensor, it is pushed using iio_push_to_buffers_with_ts(). The sensor is powered ON or OFF based on the trigger callback set_trigger_state() when the poll function is attached. During the call to iio_triggered_buffer_setup_ext(), the HID sensor specifies only a handler function but provides no thread handler, as there is no data to read from the hub in thread context. Internally, this results in calling request_threaded_irq(). Recent kernel changes now warn when request_threaded_irq() is called without a thread handler. To address this issue, fundamental changes are required to avoid using iio_triggered_buffer_setup_ext(). HID sensors can use INDIO_BUFFER_SOFTWARE instead of INDIO_BUFFER_TRIGGERED, as this can work in trigger-less mode. In this approach, when user space opens the buffer, the sensor is powered on, and when the buffer is closed, the sensor is powered off using iio_buffer_setup_ops callbacks. Signed-off-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron --- .../common/hid-sensors/hid-sensor-trigger.c | 48 ++++++++++++------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c index 5540e2d28f4a..417c4ab8c1b2 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "hid-sensor-trigger.h" static ssize_t _hid_sensor_set_report_latency(struct device *dev, @@ -202,12 +203,21 @@ static void hid_sensor_set_power_work(struct work_struct *work) _hid_sensor_power_state(attrb, true); } -static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, - bool state) +static int buffer_postenable(struct iio_dev *indio_dev) { - return hid_sensor_power_state(iio_trigger_get_drvdata(trig), state); + return hid_sensor_power_state(iio_device_get_drvdata(indio_dev), 1); } +static int buffer_predisable(struct iio_dev *indio_dev) +{ + return hid_sensor_power_state(iio_device_get_drvdata(indio_dev), 0); +} + +static const struct iio_buffer_setup_ops hid_sensor_buffer_ops = { + .postenable = buffer_postenable, + .predisable = buffer_predisable, +}; + void hid_sensor_remove_trigger(struct iio_dev *indio_dev, struct hid_sensor_common *attrb) { @@ -219,14 +229,9 @@ void hid_sensor_remove_trigger(struct iio_dev *indio_dev, cancel_work_sync(&attrb->work); iio_trigger_unregister(attrb->trigger); iio_trigger_free(attrb->trigger); - iio_triggered_buffer_cleanup(indio_dev); } EXPORT_SYMBOL_NS(hid_sensor_remove_trigger, "IIO_HID"); -static const struct iio_trigger_ops hid_sensor_trigger_ops = { - .set_trigger_state = &hid_sensor_data_rdy_trigger_set_state, -}; - int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, struct hid_sensor_common *attrb) { @@ -239,25 +244,34 @@ int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, else fifo_attrs = NULL; - ret = iio_triggered_buffer_setup_ext(indio_dev, - &iio_pollfunc_store_time, NULL, - IIO_BUFFER_DIRECTION_IN, - NULL, fifo_attrs); + indio_dev->modes = INDIO_DIRECT_MODE | INDIO_HARDWARE_TRIGGERED; + + ret = devm_iio_kfifo_buffer_setup_ext(&indio_dev->dev, indio_dev, + &hid_sensor_buffer_ops, + fifo_attrs); if (ret) { - dev_err(&indio_dev->dev, "Triggered Buffer Setup Failed\n"); + dev_err(&indio_dev->dev, "Kfifo Buffer Setup Failed\n"); return ret; } + /* + * The current user space in distro "iio-sensor-proxy" is not working in + * trigerless mode and it expects + * /sys/bus/iio/devices/iio:device0/trigger/current_trigger. + * The change replacing iio_triggered_buffer_setup_ext() with + * devm_iio_kfifo_buffer_setup_ext() will not create attribute without + * registering a trigger with INDIO_HARDWARE_TRIGGERED. + * So the below code fragment is still required. + */ + trig = iio_trigger_alloc(indio_dev->dev.parent, "%s-dev%d", name, iio_device_id(indio_dev)); if (trig == NULL) { dev_err(&indio_dev->dev, "Trigger Allocate Failed\n"); - ret = -ENOMEM; - goto error_triggered_buffer_cleanup; + return -ENOMEM; } iio_trigger_set_drvdata(trig, attrb); - trig->ops = &hid_sensor_trigger_ops; ret = iio_trigger_register(trig); if (ret) { @@ -284,8 +298,6 @@ int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, iio_trigger_unregister(trig); error_free_trig: iio_trigger_free(trig); -error_triggered_buffer_cleanup: - iio_triggered_buffer_cleanup(indio_dev); return ret; } EXPORT_SYMBOL_NS(hid_sensor_setup_trigger, "IIO_HID"); From 773ef9f95385bae52dcb7fd129fefba3a71a04db Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 14 Feb 2026 16:33:54 -0600 Subject: [PATCH 16/63] iio: imu: bno055: fix BNO055_SCAN_CH_COUNT off by one Fix an off-by-one error in the BNO055_SCAN_CH_COUNT macro. The count is derived by taking the difference of the last and first register addresses, dividing by the size of each channel (2 bytes). It needs to also add 1 to account for the fact that the count is inclusive of both the first and last channels. Thanks to the aligned_s64 timestamp field, there was already extra padding in the buffer, so there were no runtime issues caused by this bug. Fixes: 4aefe1c2bd0c ("iio: imu: add Bosch Sensortec BNO055 core driver") Signed-off-by: David Lechner Signed-off-by: Jonathan Cameron --- drivers/iio/imu/bno055/bno055.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/imu/bno055/bno055.c b/drivers/iio/imu/bno055/bno055.c index 303bc308f80a..c96fec2ebb3e 100644 --- a/drivers/iio/imu/bno055/bno055.c +++ b/drivers/iio/imu/bno055/bno055.c @@ -64,7 +64,7 @@ #define BNO055_GRAVITY_DATA_X_LSB_REG 0x2E #define BNO055_GRAVITY_DATA_Y_LSB_REG 0x30 #define BNO055_GRAVITY_DATA_Z_LSB_REG 0x32 -#define BNO055_SCAN_CH_COUNT ((BNO055_GRAVITY_DATA_Z_LSB_REG - BNO055_ACC_DATA_X_LSB_REG) / 2) +#define BNO055_SCAN_CH_COUNT ((BNO055_GRAVITY_DATA_Z_LSB_REG - BNO055_ACC_DATA_X_LSB_REG) / 2 + 1) #define BNO055_TEMP_REG 0x34 #define BNO055_CALIB_STAT_REG 0x35 #define BNO055_CALIB_STAT_MAGN_SHIFT 0 From 36f6d4db3c5cb0f58fb02b1f54f9e86522d2f918 Mon Sep 17 00:00:00 2001 From: Felix Gu Date: Tue, 3 Mar 2026 00:00:04 +0800 Subject: [PATCH 17/63] iio: adc: ti-ads1119: Replace IRQF_ONESHOT with IRQF_NO_THREAD As there is no threaded handler, replace devm_request_threaded_irq() with devm_request_irq(), and as the handler calls iio_trigger_poll() which may not be called from a threaded handler replace IRQF_ONESHOT with IRQF_NO_THREAD. Since commit aef30c8d569c ("genirq: Warn about using IRQF_ONESHOT without a threaded handler"), the IRQ core checks IRQF_ONESHOT flag in IRQ request and gives a warning if there is no threaded handler. Fixes: a9306887eba4 ("iio: adc: ti-ads1119: Add driver") Signed-off-by: Felix Gu Reviewed-by: David Lechner Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ti-ads1119.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/iio/adc/ti-ads1119.c b/drivers/iio/adc/ti-ads1119.c index 4454f28b2b58..7f771c7023b8 100644 --- a/drivers/iio/adc/ti-ads1119.c +++ b/drivers/iio/adc/ti-ads1119.c @@ -735,10 +735,8 @@ static int ads1119_probe(struct i2c_client *client) return dev_err_probe(dev, ret, "Failed to setup IIO buffer\n"); if (client->irq > 0) { - ret = devm_request_threaded_irq(dev, client->irq, - ads1119_irq_handler, - NULL, IRQF_ONESHOT, - "ads1119", indio_dev); + ret = devm_request_irq(dev, client->irq, ads1119_irq_handler, + IRQF_NO_THREAD, "ads1119", indio_dev); if (ret) return dev_err_probe(dev, ret, "Failed to allocate irq\n"); From 56bd57e7b161f75535df91b229b0b2c64c6e5581 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 28 Feb 2026 14:02:22 -0600 Subject: [PATCH 18/63] iio: add IIO_DECLARE_QUATERNION() macro Add a new IIO_DECLARE_QUATERNION() macro that is used to declare the field in an IIO buffer struct that contains a quaternion vector. Quaternions are currently the only IIO data type that uses the .repeat feature of struct iio_scan_type. This has an implicit rule that the element in the buffer must be aligned to the entire size of the repeated element. This macro will make that requirement explicit. Since this is the only user, we just call the macro IIO_DECLARE_QUATERNION() instead of something more generic. Signed-off-by: David Lechner Reviewed-by: Andy Shevchenko Cc: Signed-off-by: Jonathan Cameron --- include/linux/iio/iio.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index a9ecff191bd9..2c91b7659ce9 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -931,6 +931,18 @@ static inline void *iio_device_get_drvdata(const struct iio_dev *indio_dev) #define IIO_DECLARE_DMA_BUFFER_WITH_TS(type, name, count) \ __IIO_DECLARE_BUFFER_WITH_TS(type, name, count) __aligned(IIO_DMA_MINALIGN) +/** + * IIO_DECLARE_QUATERNION() - Declare a quaternion element + * @type: element type of the individual vectors + * @name: identifier name + * + * Quaternions are a vector composed of 4 elements (W, X, Y, Z). Use this macro + * to declare a quaternion element in a struct to ensure proper alignment in + * an IIO buffer. + */ +#define IIO_DECLARE_QUATERNION(type, name) \ + type name[4] __aligned(sizeof(type) * 4) + struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv); /* The information at the returned address is guaranteed to be cacheline aligned */ From 50d4cc74b8a720a9682a9c94f7e62a5de6b2ed3a Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 28 Feb 2026 14:02:23 -0600 Subject: [PATCH 19/63] iio: orientation: hid-sensor-rotation: fix quaternion alignment Restore the alignment of sampled_vals to 16 bytes by using IIO_DECLARE_QUATERNION(). This field contains a quaternion value which has scan_type.repeat = 4 and storagebits = 32. So the alignment must be 16 bytes to match the assumptions of iio_storage_bytes_for_si() and also to not break userspace. Reported-by: Lixu Zhang Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221077 Fixes: b31a74075cb4 ("iio: orientation: hid-sensor-rotation: remove unnecessary alignment") Tested-by: Lixu Zhang Signed-off-by: David Lechner Reviewed-by: Andy Shevchenko Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/orientation/hid-sensor-rotation.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/orientation/hid-sensor-rotation.c b/drivers/iio/orientation/hid-sensor-rotation.c index e759f91a710a..6806481873be 100644 --- a/drivers/iio/orientation/hid-sensor-rotation.c +++ b/drivers/iio/orientation/hid-sensor-rotation.c @@ -19,7 +19,7 @@ struct dev_rot_state { struct hid_sensor_common common_attributes; struct hid_sensor_hub_attribute_info quaternion; struct { - s32 sampled_vals[4]; + IIO_DECLARE_QUATERNION(s32, sampled_vals); aligned_s64 timestamp; } scan; int scale_pre_decml; From e2fa075d5ce1963e7cb7b0ac708ba567e5af66db Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 5 Mar 2026 11:21:52 -0800 Subject: [PATCH 20/63] iio: adc: ti-ads7950: normalize return value of gpio_get The GPIO get callback is expected to return 0 or 1 (or a negative error code). Ensure that the value returned by ti_ads7950_get() for output pins is normalized to the [0, 1] range. Fixes: 86ef402d805d ("gpiolib: sanitize the return value of gpio_chip::get()") Reviewed-by: Andy Shevchenko Reviewed-by: Bartosz Golaszewski Reviewed-by: Linus Walleij Signed-off-by: Dmitry Torokhov Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ti-ads7950.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/ti-ads7950.c b/drivers/iio/adc/ti-ads7950.c index bbe1ce577789..b8cc39fc39fb 100644 --- a/drivers/iio/adc/ti-ads7950.c +++ b/drivers/iio/adc/ti-ads7950.c @@ -433,7 +433,7 @@ static int ti_ads7950_get(struct gpio_chip *chip, unsigned int offset) /* If set as output, return the output */ if (st->gpio_cmd_settings_bitmask & BIT(offset)) { - ret = st->cmd_settings_bitmask & BIT(offset); + ret = (st->cmd_settings_bitmask & BIT(offset)) ? 1 : 0; goto out; } From d20bbae6e5d408a8a7c2a4344d76dd1ac557a149 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 5 Mar 2026 11:21:53 -0800 Subject: [PATCH 21/63] iio: adc: ti-ads7950: do not clobber gpio state in ti_ads7950_get() GPIO state was inadvertently overwritten by the result of spi_sync(), resulting in ti_ads7950_get() only returning 0 as GPIO state (or error). Fix this by introducing a separate variable to hold the state. Fixes: c97dce792dc8 ("iio: adc: ti-ads7950: add GPIO support") Reported-by: David Lechner Signed-off-by: Dmitry Torokhov Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ti-ads7950.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/iio/adc/ti-ads7950.c b/drivers/iio/adc/ti-ads7950.c index b8cc39fc39fb..cdc624889559 100644 --- a/drivers/iio/adc/ti-ads7950.c +++ b/drivers/iio/adc/ti-ads7950.c @@ -427,13 +427,15 @@ static int ti_ads7950_set(struct gpio_chip *chip, unsigned int offset, static int ti_ads7950_get(struct gpio_chip *chip, unsigned int offset) { struct ti_ads7950_state *st = gpiochip_get_data(chip); + bool state; int ret; mutex_lock(&st->slock); /* If set as output, return the output */ if (st->gpio_cmd_settings_bitmask & BIT(offset)) { - ret = (st->cmd_settings_bitmask & BIT(offset)) ? 1 : 0; + state = st->cmd_settings_bitmask & BIT(offset); + ret = 0; goto out; } @@ -444,7 +446,7 @@ static int ti_ads7950_get(struct gpio_chip *chip, unsigned int offset) if (ret) goto out; - ret = ((st->single_rx >> 12) & BIT(offset)) ? 1 : 0; + state = (st->single_rx >> 12) & BIT(offset); /* Revert back to original settings */ st->cmd_settings_bitmask &= ~TI_ADS7950_CR_GPIO_DATA; @@ -456,7 +458,7 @@ static int ti_ads7950_get(struct gpio_chip *chip, unsigned int offset) out: mutex_unlock(&st->slock); - return ret; + return ret ?: state; } static int ti_ads7950_get_direction(struct gpio_chip *chip, From 6f658d19a5a29a602c372e8cfe8d4a623367d211 Mon Sep 17 00:00:00 2001 From: Chunyang Chen Date: Thu, 5 Mar 2026 20:43:02 +0800 Subject: [PATCH 22/63] iio: adc: ti-ads1018: fix type overflow for data rate The variable 'drate' is currently defined as u8. However, the data rate values in ads1018 can reach up to 3300 Hz, which exceeds the maximum value of 255 that a u8 can hold. Change the type of 'drate' to u32 to match the data_rate_mode_to_hz array definition and ensure the data rate is handled correctly. Fixes: bf0bba486b5b ("iio: adc: Add ti-ads1018 driver") Signed-off-by: Chunyang Chen Reviewed-by: Andy Shevchenko Reviewed-by: Kurt Borja Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ti-ads1018.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/ti-ads1018.c b/drivers/iio/adc/ti-ads1018.c index 6246b3cab71f..0780abd0d0db 100644 --- a/drivers/iio/adc/ti-ads1018.c +++ b/drivers/iio/adc/ti-ads1018.c @@ -249,7 +249,7 @@ static int ads1018_single_shot(struct ads1018 *ads1018, struct iio_chan_spec const *chan, u16 *cnv) { u8 max_drate_mode = ads1018->chip_info->num_data_rate_mode_to_hz - 1; - u8 drate = ads1018->chip_info->data_rate_mode_to_hz[max_drate_mode]; + u32 drate = ads1018->chip_info->data_rate_mode_to_hz[max_drate_mode]; u8 pga_mode = ads1018->chan_data[chan->scan_index].pga_mode; struct spi_transfer xfer[2] = { { From 2f168094177f8553a36046afce139001801ca917 Mon Sep 17 00:00:00 2001 From: Felix Gu Date: Tue, 3 Mar 2026 21:47:33 +0800 Subject: [PATCH 23/63] iio: adc: ti-ads1119: Reinit completion before wait_for_completion_timeout() The completion is not reinit before wait_for_completion_timeout(), so wait_for_completion_timeout() will return immediately after the first successful completion. Fixes: a9306887eba4 ("iio: adc: ti-ads1119: Add driver") Signed-off-by: Felix Gu Reviewed-by: Francesco Dolcini Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ti-ads1119.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/iio/adc/ti-ads1119.c b/drivers/iio/adc/ti-ads1119.c index 7f771c7023b8..79be71b4de96 100644 --- a/drivers/iio/adc/ti-ads1119.c +++ b/drivers/iio/adc/ti-ads1119.c @@ -280,6 +280,9 @@ static int ads1119_single_conversion(struct ads1119_state *st, if (ret) goto pdown; + if (st->client->irq) + reinit_completion(&st->completion); + ret = i2c_smbus_write_byte(st->client, ADS1119_CMD_START_SYNC); if (ret) goto pdown; From 7cf2f6ed8e7a3bf481ef70b6b4a2edb8abfa5c57 Mon Sep 17 00:00:00 2001 From: Billy Tsai Date: Tue, 3 Mar 2026 10:38:26 +0800 Subject: [PATCH 24/63] iio: adc: aspeed: clear reference voltage bits before configuring vref Ensures the reference voltage bits are cleared in the ADC engine control register before configuring the voltage reference. This avoids potential misconfigurations caused by residual bits. Fixes: 1b5ceb55fec2 ("iio: adc: aspeed: Support ast2600 adc.") Signed-off-by: Billy Tsai Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/aspeed_adc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/adc/aspeed_adc.c b/drivers/iio/adc/aspeed_adc.c index 4be44c524b4d..83a9885b9ae4 100644 --- a/drivers/iio/adc/aspeed_adc.c +++ b/drivers/iio/adc/aspeed_adc.c @@ -415,6 +415,7 @@ static int aspeed_adc_vref_config(struct iio_dev *indio_dev) } adc_engine_control_reg_val = readl(data->base + ASPEED_REG_ENGINE_CONTROL); + adc_engine_control_reg_val &= ~ASPEED_ADC_REF_VOLTAGE; ret = devm_regulator_get_enable_read_voltage(data->dev, "vref"); if (ret < 0 && ret != -ENODEV) From ea7e2e43d768102e2601dbbda42041c78d7a99f9 Mon Sep 17 00:00:00 2001 From: Antoniu Miclaus Date: Fri, 27 Feb 2026 14:20:46 +0200 Subject: [PATCH 25/63] iio: imu: adis16550: fix swapped gyro/accel filter functions The low-pass filter handlers for IIO_ANGL_VEL and IIO_ACCEL call each other's filter functions in both read_raw and write_raw. Swap them so each channel type uses its correct filter accessor. Fixes: bac4368fab62 ("iio: imu: adis16550: add adis16550 support") Signed-off-by: Antoniu Miclaus Acked-by: Robert Budai Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/imu/adis16550.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/iio/imu/adis16550.c b/drivers/iio/imu/adis16550.c index 28f0dbd0226c..1f2af506f4bd 100644 --- a/drivers/iio/imu/adis16550.c +++ b/drivers/iio/imu/adis16550.c @@ -643,12 +643,12 @@ static int adis16550_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: switch (chan->type) { case IIO_ANGL_VEL: - ret = adis16550_get_accl_filter_freq(st, val); + ret = adis16550_get_gyro_filter_freq(st, val); if (ret) return ret; return IIO_VAL_INT; case IIO_ACCEL: - ret = adis16550_get_gyro_filter_freq(st, val); + ret = adis16550_get_accl_filter_freq(st, val); if (ret) return ret; return IIO_VAL_INT; @@ -681,9 +681,9 @@ static int adis16550_write_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: switch (chan->type) { case IIO_ANGL_VEL: - return adis16550_set_accl_filter_freq(st, val); - case IIO_ACCEL: return adis16550_set_gyro_filter_freq(st, val); + case IIO_ACCEL: + return adis16550_set_accl_filter_freq(st, val); default: return -EINVAL; } From dbbd550d7c8d90d3af9fe8a12a9caff077ddb8e3 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Sat, 14 Mar 2026 03:29:33 +0200 Subject: [PATCH 26/63] interconnect: qcom: sm8450: Fix NULL pointer dereference in icc_link_nodes() The change to dynamic IDs for SM8450 platform interconnects left two links unconverted, fix it to avoid the NULL pointer dereference in runtime, when a pointer to a destination interconnect is not valid: Unable to handle kernel NULL pointer dereference at virtual address 0000000000000008 <...> Call trace: icc_link_nodes+0x3c/0x100 (P) qcom_icc_rpmh_probe+0x1b4/0x528 platform_probe+0x64/0xc0 really_probe+0xc4/0x2a8 __driver_probe_device+0x80/0x140 driver_probe_device+0x48/0x170 __device_attach_driver+0xc0/0x148 bus_for_each_drv+0x88/0xf0 __device_attach+0xb0/0x1c0 device_initial_probe+0x58/0x68 bus_probe_device+0x40/0xb8 deferred_probe_work_func+0x90/0xd0 process_one_work+0x15c/0x3c0 worker_thread+0x2e8/0x400 kthread+0x150/0x208 ret_from_fork+0x10/0x20 Code: 900310f4 911d6294 91008280 94176078 (f94002a0) ---[ end trace 0000000000000000 ]--- Kernel panic - not syncing: Oops: Fatal exception Fixes: 51513bec806f ("interconnect: qcom: sm8450: convert to dynamic IDs") Signed-off-by: Vladimir Zapolskiy Reviewed-by: Dmitry Baryshkov Link: https://msgid.link/20260314012933.350644-1-vladimir.zapolskiy@linaro.org Signed-off-by: Georgi Djakov --- drivers/interconnect/qcom/sm8450.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/interconnect/qcom/sm8450.c b/drivers/interconnect/qcom/sm8450.c index 669a638bf3ef..c88327d200ac 100644 --- a/drivers/interconnect/qcom/sm8450.c +++ b/drivers/interconnect/qcom/sm8450.c @@ -800,7 +800,7 @@ static struct qcom_icc_node qhs_compute_cfg = { .channels = 1, .buswidth = 4, .num_links = 1, - .link_nodes = { MASTER_CDSP_NOC_CFG }, + .link_nodes = { &qhm_nsp_noc_config }, }; static struct qcom_icc_node qhs_cpr_cx = { @@ -874,7 +874,7 @@ static struct qcom_icc_node qhs_lpass_cfg = { .channels = 1, .buswidth = 4, .num_links = 1, - .link_nodes = { MASTER_CNOC_LPASS_AG_NOC }, + .link_nodes = { &qhm_config_noc }, }; static struct qcom_icc_node qhs_mss_cfg = { From 9978d74031f25fde575bef3e4e3e35c5009091ce Mon Sep 17 00:00:00 2001 From: Felix Gu Date: Wed, 4 Mar 2026 22:14:32 +0800 Subject: [PATCH 27/63] iio: proximity: rfd77402: Fix completion race condition in IRQ mode In IRQ mode, the completion was being reinitialized after the measurement command had already been sent to the hardware. This created a race condition where the IRQ handler could call complete() before reinit_completion() was executed. Consequently, wait_for_completion_timeout() would fail to see the signal and wait until it timed out. Move reinit_completion() to occur before the measurement command is triggered to ensure the synchronization primitive is ready to capture the interrupt. Fixes: dc81be96a73a ("iio: proximity: rfd77402: Add interrupt handling support") Signed-off-by: Felix Gu Reviewed-by: Shrikant Raskar Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/rfd77402.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/iio/proximity/rfd77402.c b/drivers/iio/proximity/rfd77402.c index 6afdbfca3e5a..81b8daf17a54 100644 --- a/drivers/iio/proximity/rfd77402.c +++ b/drivers/iio/proximity/rfd77402.c @@ -173,10 +173,8 @@ static int rfd77402_wait_for_result(struct rfd77402_data *data) struct i2c_client *client = data->client; int val, ret; - if (data->irq_en) { - reinit_completion(&data->completion); + if (data->irq_en) return rfd77402_wait_for_irq(data); - } /* * As per RFD77402 datasheet section '3.1.1 Single Measure', the @@ -204,6 +202,9 @@ static int rfd77402_measure(struct rfd77402_data *data) if (ret < 0) return ret; + if (data->irq_en) + reinit_completion(&data->completion); + ret = i2c_smbus_write_byte_data(client, RFD77402_CMD_R, RFD77402_CMD_SINGLE | RFD77402_CMD_VALID); From 79a86a6cc3669416a21fef32d0767d39ba84b3aa Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 7 Mar 2026 19:44:09 -0600 Subject: [PATCH 28/63] iio: orientation: hid-sensor-rotation: add timestamp hack to not break userspace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a hack to push two timestamps in the hid-sensor-rotation scan data to avoid breaking userspace applications that depend on the timestamp being at the incorrect location in the scan data due to unintentional misalignment in older kernels. When this driver was written, the timestamp was in the correct location because of the way iio_compute_scan_bytes() was implemented at the time. (Samples were 24 bytes each.) Then commit 883f61653069 ("iio: buffer: align the size of scan bytes to size of the largest element") changed the computed scan_bytes to be a different size (32 bytes), which caused iio_push_to_buffers_with_timestamp() to place the timestamp at an incorrect offset. There have been long periods of time (6 years each) where the timestamp was in either location, so to not break either case, we open-code the timestamps to be pushed to both locations in the scan data. Reported-by: Jonathan Cameron Closes: https://lore.kernel.org/linux-iio/20260215162351.79f40b32@jic23-huawei/ Fixes: 883f61653069 ("iio: buffer: align the size of scan bytes to size of the largest element") Signed-off-by: David Lechner Reviewed-by: Nuno Sá Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/orientation/hid-sensor-rotation.c | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/drivers/iio/orientation/hid-sensor-rotation.c b/drivers/iio/orientation/hid-sensor-rotation.c index 6806481873be..5a5e6e4fbe34 100644 --- a/drivers/iio/orientation/hid-sensor-rotation.c +++ b/drivers/iio/orientation/hid-sensor-rotation.c @@ -20,7 +20,12 @@ struct dev_rot_state { struct hid_sensor_hub_attribute_info quaternion; struct { IIO_DECLARE_QUATERNION(s32, sampled_vals); - aligned_s64 timestamp; + /* + * ABI regression avoidance: There are two copies of the same + * timestamp in case of userspace depending on broken alignment + * from older kernels. + */ + aligned_s64 timestamp[2]; } scan; int scale_pre_decml; int scale_post_decml; @@ -154,8 +159,19 @@ static int dev_rot_proc_event(struct hid_sensor_hub_device *hsdev, if (!rot_state->timestamp) rot_state->timestamp = iio_get_time_ns(indio_dev); - iio_push_to_buffers_with_timestamp(indio_dev, &rot_state->scan, - rot_state->timestamp); + /* + * ABI regression avoidance: IIO previously had an incorrect + * implementation of iio_push_to_buffers_with_timestamp() that + * put the timestamp in the last 8 bytes of the buffer, which + * was incorrect according to the IIO ABI. To avoid breaking + * userspace that may be depending on this broken behavior, we + * put the timestamp in both the correct place [0] and the old + * incorrect place [1]. + */ + rot_state->scan.timestamp[0] = rot_state->timestamp; + rot_state->scan.timestamp[1] = rot_state->timestamp; + + iio_push_to_buffers(indio_dev, &rot_state->scan); rot_state->timestamp = 0; } From c05a87d9ec3bf8727a5d746ce855003c6f2f8bb4 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Mon, 9 Mar 2026 20:45:45 -0700 Subject: [PATCH 29/63] iio: imu: bmi160: Remove potential undefined behavior in bmi160_config_pin() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If 'pin' is not one of its expected values, the value of 'int_out_ctrl_shift' is undefined. With UBSAN enabled, this causes Clang to generate undefined behavior, resulting in the following warning: drivers/iio/imu/bmi160/bmi160_core.o: warning: objtool: bmi160_setup_irq() falls through to next function __cfi_bmi160_core_runtime_resume() Prevent the UB and improve error handling by returning an error if 'pin' has an unexpected value. While at it, simplify the code a bit by moving the 'pin_name' assignment to the first switch statement. Fixes: 895bf81e6bbf ("iio:bmi160: add drdy interrupt support") Reported-by: Arnd Bergmann Closes: https://lore.kernel.org/a426d669-58bb-4be1-9eaa-6f3d83109e2d@app.fastmail.com Signed-off-by: Josh Poimboeuf Reviewed-by: Nuno Sá Reviewed-by: Andy Shevchenko Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/imu/bmi160/bmi160_core.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/iio/imu/bmi160/bmi160_core.c b/drivers/iio/imu/bmi160/bmi160_core.c index 5f47708b4c5d..4abb83b75e2e 100644 --- a/drivers/iio/imu/bmi160/bmi160_core.c +++ b/drivers/iio/imu/bmi160/bmi160_core.c @@ -573,12 +573,16 @@ static int bmi160_config_pin(struct regmap *regmap, enum bmi160_int_pin pin, int_out_ctrl_shift = BMI160_INT1_OUT_CTRL_SHIFT; int_latch_mask = BMI160_INT1_LATCH_MASK; int_map_mask = BMI160_INT1_MAP_DRDY_EN; + pin_name = "INT1"; break; case BMI160_PIN_INT2: int_out_ctrl_shift = BMI160_INT2_OUT_CTRL_SHIFT; int_latch_mask = BMI160_INT2_LATCH_MASK; int_map_mask = BMI160_INT2_MAP_DRDY_EN; + pin_name = "INT2"; break; + default: + return -EINVAL; } int_out_ctrl_mask = BMI160_INT_OUT_CTRL_MASK << int_out_ctrl_shift; @@ -612,17 +616,8 @@ static int bmi160_config_pin(struct regmap *regmap, enum bmi160_int_pin pin, ret = bmi160_write_conf_reg(regmap, BMI160_REG_INT_MAP, int_map_mask, int_map_mask, write_usleep); - if (ret) { - switch (pin) { - case BMI160_PIN_INT1: - pin_name = "INT1"; - break; - case BMI160_PIN_INT2: - pin_name = "INT2"; - break; - } + if (ret) dev_err(dev, "Failed to configure %s IRQ pin", pin_name); - } return ret; } From dd154646d292cce7de952f216760c58c35cfecde Mon Sep 17 00:00:00 2001 From: Ariana Lazar Date: Tue, 10 Mar 2026 13:56:44 +0200 Subject: [PATCH 30/63] iio: dac: mcp47feb02: Fix Vref validation [1-999] case Store reference voltages in uV instead of mV to avoid invalid error code in dev_err_probe() call. Vref variables store the actual value returned by devm_regulator_get_enable_read_voltage() function instead of the results of dividing it by MILLI. The corner case [1-999] divided by MILLI of the voltage reference variable value would become 0 is covered too. Fixes: bf394cc80369 ("iio: dac: adding support for Microchip MCP47FEB02") Link: https://lore.kernel.org/all/aYXvP5FLA5BvkoVX@stanley.mountain/ Signed-off-by: Ariana Lazar Reviewed-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/dac/mcp47feb02.c | 49 ++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/drivers/iio/dac/mcp47feb02.c b/drivers/iio/dac/mcp47feb02.c index 08fb85359697..faccb804a5ed 100644 --- a/drivers/iio/dac/mcp47feb02.c +++ b/drivers/iio/dac/mcp47feb02.c @@ -65,7 +65,7 @@ #define MCP47FEB02_MAX_SCALES_CH 3 #define MCP47FEB02_DAC_WIPER_UNLOCKED 0 #define MCP47FEB02_NORMAL_OPERATION 0 -#define MCP47FEB02_INTERNAL_BAND_GAP_mV 2440 +#define MCP47FEB02_INTERNAL_BAND_GAP_uV 2440000 #define NV_DAC_ADDR_OFFSET 0x10 enum mcp47feb02_vref_mode { @@ -697,44 +697,40 @@ static const struct iio_chan_spec mcp47febxx_ch_template = { }; static void mcp47feb02_init_scale(struct mcp47feb02_data *data, enum mcp47feb02_scale scale, - int vref_mV, int scale_avail[]) + int vref_uV, int scale_avail[]) { u32 value_micro, value_int; u64 tmp; - /* vref_mV should not be negative */ - tmp = (u64)vref_mV * MICRO >> data->chip_features->resolution; + /* vref_uV should not be negative */ + tmp = (u64)vref_uV * MILLI >> data->chip_features->resolution; value_int = div_u64_rem(tmp, MICRO, &value_micro); scale_avail[scale * 2] = value_int; scale_avail[scale * 2 + 1] = value_micro; } -static int mcp47feb02_init_scales_avail(struct mcp47feb02_data *data, int vdd_mV, - int vref_mV, int vref1_mV) +static int mcp47feb02_init_scales_avail(struct mcp47feb02_data *data, int vdd_uV, + int vref_uV, int vref1_uV) { - struct device *dev = regmap_get_device(data->regmap); int tmp_vref; - mcp47feb02_init_scale(data, MCP47FEB02_SCALE_VDD, vdd_mV, data->scale); + mcp47feb02_init_scale(data, MCP47FEB02_SCALE_VDD, vdd_uV, data->scale); if (data->use_vref) - tmp_vref = vref_mV; + tmp_vref = vref_uV; else - tmp_vref = MCP47FEB02_INTERNAL_BAND_GAP_mV; + tmp_vref = MCP47FEB02_INTERNAL_BAND_GAP_uV; mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X1, tmp_vref, data->scale); mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X2, tmp_vref * 2, data->scale); if (data->phys_channels >= 4) { - mcp47feb02_init_scale(data, MCP47FEB02_SCALE_VDD, vdd_mV, data->scale_1); - - if (data->use_vref1 && vref1_mV <= 0) - return dev_err_probe(dev, vref1_mV, "Invalid voltage for Vref1\n"); + mcp47feb02_init_scale(data, MCP47FEB02_SCALE_VDD, vdd_uV, data->scale_1); if (data->use_vref1) - tmp_vref = vref1_mV; + tmp_vref = vref1_uV; else - tmp_vref = MCP47FEB02_INTERNAL_BAND_GAP_mV; + tmp_vref = MCP47FEB02_INTERNAL_BAND_GAP_uV; mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X1, tmp_vref, data->scale_1); @@ -1078,8 +1074,8 @@ static int mcp47feb02_init_ctrl_regs(struct mcp47feb02_data *data) return 0; } -static int mcp47feb02_init_ch_scales(struct mcp47feb02_data *data, int vdd_mV, - int vref_mV, int vref1_mV) +static int mcp47feb02_init_ch_scales(struct mcp47feb02_data *data, int vdd_uV, + int vref_uV, int vref1_uV) { unsigned int i; @@ -1087,7 +1083,7 @@ static int mcp47feb02_init_ch_scales(struct mcp47feb02_data *data, int vdd_mV, struct device *dev = regmap_get_device(data->regmap); int ret; - ret = mcp47feb02_init_scales_avail(data, vdd_mV, vref_mV, vref1_mV); + ret = mcp47feb02_init_scales_avail(data, vdd_uV, vref_uV, vref1_uV); if (ret) return dev_err_probe(dev, ret, "failed to init scales for ch %u\n", i); } @@ -1101,10 +1097,7 @@ static int mcp47feb02_probe(struct i2c_client *client) struct device *dev = &client->dev; struct mcp47feb02_data *data; struct iio_dev *indio_dev; - int vref1_mV = 0; - int vref_mV = 0; - int vdd_mV; - int ret; + int vref1_uV, vref_uV, vdd_uV, ret; indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); if (!indio_dev) @@ -1141,13 +1134,14 @@ static int mcp47feb02_probe(struct i2c_client *client) if (ret < 0) return ret; - vdd_mV = ret / MILLI; + vdd_uV = ret; ret = devm_regulator_get_enable_read_voltage(dev, "vref"); if (ret > 0) { - vref_mV = ret / MILLI; + vref_uV = ret; data->use_vref = true; } else { + vref_uV = 0; dev_dbg(dev, "using internal band gap as voltage reference.\n"); dev_dbg(dev, "Vref is unavailable.\n"); } @@ -1155,9 +1149,10 @@ static int mcp47feb02_probe(struct i2c_client *client) if (chip_features->have_ext_vref1) { ret = devm_regulator_get_enable_read_voltage(dev, "vref1"); if (ret > 0) { - vref1_mV = ret / MILLI; + vref1_uV = ret; data->use_vref1 = true; } else { + vref1_uV = 0; dev_dbg(dev, "using internal band gap as voltage reference 1.\n"); dev_dbg(dev, "Vref1 is unavailable.\n"); } @@ -1167,7 +1162,7 @@ static int mcp47feb02_probe(struct i2c_client *client) if (ret) return dev_err_probe(dev, ret, "Error initialising vref register\n"); - ret = mcp47feb02_init_ch_scales(data, vdd_mV, vref_mV, vref1_mV); + ret = mcp47feb02_init_ch_scales(data, vdd_uV, vref_uV, vref1_uV); if (ret) return ret; From 24869650dff34a6fc8fd1cc91b2058a72f9abc95 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 14 Mar 2026 18:13:31 -0500 Subject: [PATCH 31/63] iio: adc: ti-adc161s626: fix buffer read on big-endian Rework ti_adc_trigger_handler() to properly handle data on big-endian architectures. The scan data format is 16-bit CPU-endian, so we can't cast it to a int * on big-endian and expect it to work. Instead, we introduce a local int variable to read the data into, and then copy it to the buffer. Since the buffer isn't passed to any SPI functions, we don't need it to be DMA-safe. So we can drop it from the driver data struct and just use stack memory for the scan data. Since there is only one data value (plus timestamp), we don't need an array and can just declare a struct with the correct data type instead. Also fix alignment of iio_get_time_ns() to ( while we are touching this. Fixes: 4d671b71beef ("iio: adc: ti-adc161s626: add support for TI 1-channel differential ADCs") Signed-off-by: David Lechner Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ti-adc161s626.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/iio/adc/ti-adc161s626.c b/drivers/iio/adc/ti-adc161s626.c index 28aa6b80160c..42968d96572b 100644 --- a/drivers/iio/adc/ti-adc161s626.c +++ b/drivers/iio/adc/ti-adc161s626.c @@ -70,8 +70,6 @@ struct ti_adc_data { u8 read_size; u8 shift; - - u8 buffer[16] __aligned(IIO_DMA_MINALIGN); }; static int ti_adc_read_measurement(struct ti_adc_data *data, @@ -114,15 +112,20 @@ static irqreturn_t ti_adc_trigger_handler(int irq, void *private) struct iio_poll_func *pf = private; struct iio_dev *indio_dev = pf->indio_dev; struct ti_adc_data *data = iio_priv(indio_dev); - int ret; + struct { + s16 data; + aligned_s64 timestamp; + } scan = { }; + int ret, val; - ret = ti_adc_read_measurement(data, &indio_dev->channels[0], - (int *) &data->buffer); - if (!ret) - iio_push_to_buffers_with_timestamp(indio_dev, - data->buffer, - iio_get_time_ns(indio_dev)); + ret = ti_adc_read_measurement(data, &indio_dev->channels[0], &val); + if (ret) + goto exit_notify_done; + scan.data = val; + iio_push_to_buffers_with_timestamp(indio_dev, &scan, iio_get_time_ns(indio_dev)); + + exit_notify_done: iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; From 768461517a28d80fe81ea4d5d03a90cd184ea6ad Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 14 Mar 2026 18:13:32 -0500 Subject: [PATCH 32/63] iio: adc: ti-adc161s626: use DMA-safe memory for spi_read() Add a DMA-safe buffer and use it for spi_read() instead of a stack memory. All SPI buffers must be DMA-safe. Since we only need up to 3 bytes, we just use a u8[] instead of __be16 and __be32 and change the conversion functions appropriately. Fixes: 4d671b71beef ("iio: adc: ti-adc161s626: add support for TI 1-channel differential ADCs") Signed-off-by: David Lechner Reviewed-by: Andy Shevchenko Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ti-adc161s626.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/iio/adc/ti-adc161s626.c b/drivers/iio/adc/ti-adc161s626.c index 42968d96572b..be1cc2e77862 100644 --- a/drivers/iio/adc/ti-adc161s626.c +++ b/drivers/iio/adc/ti-adc161s626.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -70,6 +71,7 @@ struct ti_adc_data { u8 read_size; u8 shift; + u8 buf[3] __aligned(IIO_DMA_MINALIGN); }; static int ti_adc_read_measurement(struct ti_adc_data *data, @@ -78,26 +80,20 @@ static int ti_adc_read_measurement(struct ti_adc_data *data, int ret; switch (data->read_size) { - case 2: { - __be16 buf; - - ret = spi_read(data->spi, (void *) &buf, 2); + case 2: + ret = spi_read(data->spi, data->buf, 2); if (ret) return ret; - *val = be16_to_cpu(buf); + *val = get_unaligned_be16(data->buf); break; - } - case 3: { - __be32 buf; - - ret = spi_read(data->spi, (void *) &buf, 3); + case 3: + ret = spi_read(data->spi, data->buf, 3); if (ret) return ret; - *val = be32_to_cpu(buf) >> 8; + *val = get_unaligned_be24(data->buf); break; - } default: return -EINVAL; } From fdc7aa54a5d44c05880a4aad7cfb41aacfd16d7b Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 14 Mar 2026 17:18:10 -0500 Subject: [PATCH 33/63] iio: light: vcnl4035: fix scan buffer on big-endian Rework vcnl4035_trigger_consumer_handler() so that we are not passing what should be a u16 value as an int * to regmap_read(). This won't work on bit endian systems. Instead, add a new unsigned int variable to pass to regmap_read(). Then copy that value into the buffer struct. The buffer array is replaced with a struct since there is only one value being read. This allows us to use the correct u16 data type and has a side-effect of simplifying the alignment specification. Also fix the endianness of the scan format from little-endian to CPU endianness. Since we are using regmap to read the value, it will be CPU-endian. Fixes: 55707294c4eb ("iio: light: Add support for vishay vcnl4035") Signed-off-by: David Lechner Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/light/vcnl4035.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/iio/light/vcnl4035.c b/drivers/iio/light/vcnl4035.c index 963747927425..16aeb17067bc 100644 --- a/drivers/iio/light/vcnl4035.c +++ b/drivers/iio/light/vcnl4035.c @@ -103,17 +103,23 @@ static irqreturn_t vcnl4035_trigger_consumer_handler(int irq, void *p) struct iio_dev *indio_dev = pf->indio_dev; struct vcnl4035_data *data = iio_priv(indio_dev); /* Ensure naturally aligned timestamp */ - u8 buffer[ALIGN(sizeof(u16), sizeof(s64)) + sizeof(s64)] __aligned(8) = { }; + struct { + u16 als_data; + aligned_s64 timestamp; + } buffer = { }; + unsigned int val; int ret; - ret = regmap_read(data->regmap, VCNL4035_ALS_DATA, (int *)buffer); + ret = regmap_read(data->regmap, VCNL4035_ALS_DATA, &val); if (ret < 0) { dev_err(&data->client->dev, "Trigger consumer can't read from sensor.\n"); goto fail_read; } - iio_push_to_buffers_with_timestamp(indio_dev, buffer, - iio_get_time_ns(indio_dev)); + + buffer.als_data = val; + iio_push_to_buffers_with_timestamp(indio_dev, &buffer, + iio_get_time_ns(indio_dev)); fail_read: iio_trigger_notify_done(indio_dev->trig); @@ -381,7 +387,7 @@ static const struct iio_chan_spec vcnl4035_channels[] = { .sign = 'u', .realbits = 16, .storagebits = 16, - .endianness = IIO_LE, + .endianness = IIO_CPU, }, }, { @@ -395,7 +401,7 @@ static const struct iio_chan_spec vcnl4035_channels[] = { .sign = 'u', .realbits = 16, .storagebits = 16, - .endianness = IIO_LE, + .endianness = IIO_CPU, }, }, }; From 67c3f99bed6f422ba343d2b70a2eeeccdfd91bef Mon Sep 17 00:00:00 2001 From: Cosmin Tanislav Date: Fri, 30 Jan 2026 14:23:52 +0200 Subject: [PATCH 34/63] counter: rz-mtu3-cnt: prevent counter from being toggled multiple times Runtime PM counter is incremented / decremented each time the sysfs enable file is written to. If user writes 0 to the sysfs enable file multiple times, runtime PM usage count underflows, generating the following message. rz-mtu3-counter rz-mtu3-counter.0: Runtime PM usage count underflow! At the same time, hardware registers end up being accessed with clocks off in rz_mtu3_terminate_counter() to disable an already disabled channel. If user writes 1 to the sysfs enable file multiple times, runtime PM usage count will be incremented each time, requiring the same number of 0 writes to get it back to 0. If user writes 0 to the sysfs enable file while PWM is in progress, PWM is stopped without counter being the owner of the underlying MTU3 channel. Check against the cached count_is_enabled value and exit if the user is trying to set the same enable value. Cc: stable@vger.kernel.org Fixes: 0be8907359df ("counter: Add Renesas RZ/G2L MTU3a counter driver") Signed-off-by: Cosmin Tanislav Link: https://lore.kernel.org/r/20260130122353.2263273-5-cosmin-gabriel.tanislav.xa@renesas.com Signed-off-by: William Breathitt Gray --- drivers/counter/rz-mtu3-cnt.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/counter/rz-mtu3-cnt.c b/drivers/counter/rz-mtu3-cnt.c index e755d54dfece..a4a8ef2d88f0 100644 --- a/drivers/counter/rz-mtu3-cnt.c +++ b/drivers/counter/rz-mtu3-cnt.c @@ -499,21 +499,25 @@ static int rz_mtu3_count_enable_write(struct counter_device *counter, struct rz_mtu3_cnt *const priv = counter_priv(counter); int ret = 0; + mutex_lock(&priv->lock); + + if (priv->count_is_enabled[count->id] == enable) + goto exit; + if (enable) { - mutex_lock(&priv->lock); pm_runtime_get_sync(ch->dev); ret = rz_mtu3_initialize_counter(counter, count->id); if (ret == 0) priv->count_is_enabled[count->id] = true; - mutex_unlock(&priv->lock); } else { - mutex_lock(&priv->lock); rz_mtu3_terminate_counter(counter, count->id); priv->count_is_enabled[count->id] = false; pm_runtime_put(ch->dev); - mutex_unlock(&priv->lock); } +exit: + mutex_unlock(&priv->lock); + return ret; } From 2932095c114b98cbb40ccf34fc00d613cb17cead Mon Sep 17 00:00:00 2001 From: Cosmin Tanislav Date: Fri, 30 Jan 2026 14:23:53 +0200 Subject: [PATCH 35/63] counter: rz-mtu3-cnt: do not use struct rz_mtu3_channel's dev member The counter driver can use HW channels 1 and 2, while the PWM driver can use HW channels 0, 1, 2, 3, 4, 6, 7. The dev member is assigned both by the counter driver and the PWM driver for channels 1 and 2, to their own struct device instance, overwriting the previous value. The sub-drivers race to assign their own struct device pointer to the same struct rz_mtu3_channel's dev member. The dev member of struct rz_mtu3_channel is used by the counter sub-driver for runtime PM. Depending on the probe order of the counter and PWM sub-drivers, the dev member may point to the wrong struct device instance, causing the counter sub-driver to do runtime PM actions on the wrong device. To fix this, use the parent pointer of the counter, which is assigned during probe to the correct struct device, not the struct device pointer inside the shared struct rz_mtu3_channel. Cc: stable@vger.kernel.org Fixes: 0be8907359df ("counter: Add Renesas RZ/G2L MTU3a counter driver") Signed-off-by: Cosmin Tanislav Link: https://lore.kernel.org/r/20260130122353.2263273-6-cosmin-gabriel.tanislav.xa@renesas.com Signed-off-by: William Breathitt Gray --- drivers/counter/rz-mtu3-cnt.c | 55 +++++++++++++++++------------------ 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/drivers/counter/rz-mtu3-cnt.c b/drivers/counter/rz-mtu3-cnt.c index a4a8ef2d88f0..7bfb6979193c 100644 --- a/drivers/counter/rz-mtu3-cnt.c +++ b/drivers/counter/rz-mtu3-cnt.c @@ -107,9 +107,9 @@ static bool rz_mtu3_is_counter_invalid(struct counter_device *counter, int id) struct rz_mtu3_cnt *const priv = counter_priv(counter); unsigned long tmdr; - pm_runtime_get_sync(priv->ch->dev); + pm_runtime_get_sync(counter->parent); tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3); - pm_runtime_put(priv->ch->dev); + pm_runtime_put(counter->parent); if (id == RZ_MTU3_32_BIT_CH && test_bit(RZ_MTU3_TMDR3_LWA, &tmdr)) return false; @@ -165,12 +165,12 @@ static int rz_mtu3_count_read(struct counter_device *counter, if (ret) return ret; - pm_runtime_get_sync(ch->dev); + pm_runtime_get_sync(counter->parent); if (count->id == RZ_MTU3_32_BIT_CH) *val = rz_mtu3_32bit_ch_read(ch, RZ_MTU3_TCNTLW); else *val = rz_mtu3_16bit_ch_read(ch, RZ_MTU3_TCNT); - pm_runtime_put(ch->dev); + pm_runtime_put(counter->parent); mutex_unlock(&priv->lock); return 0; @@ -187,26 +187,26 @@ static int rz_mtu3_count_write(struct counter_device *counter, if (ret) return ret; - pm_runtime_get_sync(ch->dev); + pm_runtime_get_sync(counter->parent); if (count->id == RZ_MTU3_32_BIT_CH) rz_mtu3_32bit_ch_write(ch, RZ_MTU3_TCNTLW, val); else rz_mtu3_16bit_ch_write(ch, RZ_MTU3_TCNT, val); - pm_runtime_put(ch->dev); + pm_runtime_put(counter->parent); mutex_unlock(&priv->lock); return 0; } static int rz_mtu3_count_function_read_helper(struct rz_mtu3_channel *const ch, - struct rz_mtu3_cnt *const priv, + struct counter_device *const counter, enum counter_function *function) { u8 timer_mode; - pm_runtime_get_sync(ch->dev); + pm_runtime_get_sync(counter->parent); timer_mode = rz_mtu3_8bit_ch_read(ch, RZ_MTU3_TMDR1); - pm_runtime_put(ch->dev); + pm_runtime_put(counter->parent); switch (timer_mode & RZ_MTU3_TMDR1_PH_CNT_MODE_MASK) { case RZ_MTU3_TMDR1_PH_CNT_MODE_1: @@ -240,7 +240,7 @@ static int rz_mtu3_count_function_read(struct counter_device *counter, if (ret) return ret; - ret = rz_mtu3_count_function_read_helper(ch, priv, function); + ret = rz_mtu3_count_function_read_helper(ch, counter, function); mutex_unlock(&priv->lock); return ret; @@ -279,9 +279,9 @@ static int rz_mtu3_count_function_write(struct counter_device *counter, return -EINVAL; } - pm_runtime_get_sync(ch->dev); + pm_runtime_get_sync(counter->parent); rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TMDR1, timer_mode); - pm_runtime_put(ch->dev); + pm_runtime_put(counter->parent); mutex_unlock(&priv->lock); return 0; @@ -300,9 +300,9 @@ static int rz_mtu3_count_direction_read(struct counter_device *counter, if (ret) return ret; - pm_runtime_get_sync(ch->dev); + pm_runtime_get_sync(counter->parent); tsr = rz_mtu3_8bit_ch_read(ch, RZ_MTU3_TSR); - pm_runtime_put(ch->dev); + pm_runtime_put(counter->parent); *direction = (tsr & RZ_MTU3_TSR_TCFD) ? COUNTER_COUNT_DIRECTION_FORWARD : COUNTER_COUNT_DIRECTION_BACKWARD; @@ -377,14 +377,14 @@ static int rz_mtu3_count_ceiling_write(struct counter_device *counter, return -EINVAL; } - pm_runtime_get_sync(ch->dev); + pm_runtime_get_sync(counter->parent); if (count->id == RZ_MTU3_32_BIT_CH) rz_mtu3_32bit_ch_write(ch, RZ_MTU3_TGRALW, ceiling); else rz_mtu3_16bit_ch_write(ch, RZ_MTU3_TGRA, ceiling); rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TCR, RZ_MTU3_TCR_CCLR_TGRA); - pm_runtime_put(ch->dev); + pm_runtime_put(counter->parent); mutex_unlock(&priv->lock); return 0; @@ -495,7 +495,6 @@ static int rz_mtu3_count_enable_read(struct counter_device *counter, static int rz_mtu3_count_enable_write(struct counter_device *counter, struct counter_count *count, u8 enable) { - struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id); struct rz_mtu3_cnt *const priv = counter_priv(counter); int ret = 0; @@ -505,14 +504,14 @@ static int rz_mtu3_count_enable_write(struct counter_device *counter, goto exit; if (enable) { - pm_runtime_get_sync(ch->dev); + pm_runtime_get_sync(counter->parent); ret = rz_mtu3_initialize_counter(counter, count->id); if (ret == 0) priv->count_is_enabled[count->id] = true; } else { rz_mtu3_terminate_counter(counter, count->id); priv->count_is_enabled[count->id] = false; - pm_runtime_put(ch->dev); + pm_runtime_put(counter->parent); } exit: @@ -544,9 +543,9 @@ static int rz_mtu3_cascade_counts_enable_get(struct counter_device *counter, if (ret) return ret; - pm_runtime_get_sync(priv->ch->dev); + pm_runtime_get_sync(counter->parent); tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3); - pm_runtime_put(priv->ch->dev); + pm_runtime_put(counter->parent); *cascade_enable = test_bit(RZ_MTU3_TMDR3_LWA, &tmdr); mutex_unlock(&priv->lock); @@ -563,10 +562,10 @@ static int rz_mtu3_cascade_counts_enable_set(struct counter_device *counter, if (ret) return ret; - pm_runtime_get_sync(priv->ch->dev); + pm_runtime_get_sync(counter->parent); rz_mtu3_shared_reg_update_bit(priv->ch, RZ_MTU3_TMDR3, RZ_MTU3_TMDR3_LWA, cascade_enable); - pm_runtime_put(priv->ch->dev); + pm_runtime_put(counter->parent); mutex_unlock(&priv->lock); return 0; @@ -583,9 +582,9 @@ static int rz_mtu3_ext_input_phase_clock_select_get(struct counter_device *count if (ret) return ret; - pm_runtime_get_sync(priv->ch->dev); + pm_runtime_get_sync(counter->parent); tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3); - pm_runtime_put(priv->ch->dev); + pm_runtime_put(counter->parent); *ext_input_phase_clock_select = test_bit(RZ_MTU3_TMDR3_PHCKSEL, &tmdr); mutex_unlock(&priv->lock); @@ -602,11 +601,11 @@ static int rz_mtu3_ext_input_phase_clock_select_set(struct counter_device *count if (ret) return ret; - pm_runtime_get_sync(priv->ch->dev); + pm_runtime_get_sync(counter->parent); rz_mtu3_shared_reg_update_bit(priv->ch, RZ_MTU3_TMDR3, RZ_MTU3_TMDR3_PHCKSEL, ext_input_phase_clock_select); - pm_runtime_put(priv->ch->dev); + pm_runtime_put(counter->parent); mutex_unlock(&priv->lock); return 0; @@ -644,7 +643,7 @@ static int rz_mtu3_action_read(struct counter_device *counter, if (ret) return ret; - ret = rz_mtu3_count_function_read_helper(ch, priv, &function); + ret = rz_mtu3_count_function_read_helper(ch, counter, &function); if (ret) { mutex_unlock(&priv->lock); return ret; From 4f51e6c0baae80e52bd013092e82a55678be31fc Mon Sep 17 00:00:00 2001 From: Valek Andrej Date: Fri, 13 Mar 2026 10:24:13 +0100 Subject: [PATCH 36/63] iio: accel: fix ADXL355 temperature signature value Temperature was wrongly represented as 12-bit signed, confirmed by checking the datasheet. Even if the temperature is negative, the value in the register stays unsigned. Fixes: 12ed27863ea3 iio: accel: Add driver support for ADXL355 Signed-off-by: Valek Andrej Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/accel/adxl355_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/accel/adxl355_core.c b/drivers/iio/accel/adxl355_core.c index 1c1d64d5cbcb..8f90c58f4100 100644 --- a/drivers/iio/accel/adxl355_core.c +++ b/drivers/iio/accel/adxl355_core.c @@ -745,7 +745,7 @@ static const struct iio_chan_spec adxl355_channels[] = { BIT(IIO_CHAN_INFO_OFFSET), .scan_index = 3, .scan_type = { - .sign = 's', + .sign = 'u', .realbits = 12, .storagebits = 16, .endianness = IIO_BE, From c354521708175d776d896f8bdae44b18711eccb6 Mon Sep 17 00:00:00 2001 From: Antoniu Miclaus Date: Thu, 12 Mar 2026 13:20:24 +0200 Subject: [PATCH 37/63] iio: dac: ad5770r: fix error return in ad5770r_read_raw() Return the error code from regmap_bulk_read() instead of 0 so that I/O failures are properly propagated. Fixes: cbbb819837f6 ("iio: dac: ad5770r: Add AD5770R support") Signed-off-by: Antoniu Miclaus Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5770r.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/dac/ad5770r.c b/drivers/iio/dac/ad5770r.c index cd47cb1c685c..6027e8d88b27 100644 --- a/drivers/iio/dac/ad5770r.c +++ b/drivers/iio/dac/ad5770r.c @@ -322,7 +322,7 @@ static int ad5770r_read_raw(struct iio_dev *indio_dev, chan->address, st->transf_buf, 2); if (ret) - return 0; + return ret; buf16 = get_unaligned_le16(st->transf_buf); *val = buf16 >> 2; From 9d3fa23d5d55a137fd4396d3d4799102587a7f2b Mon Sep 17 00:00:00 2001 From: Antoniu Miclaus Date: Thu, 12 Mar 2026 13:20:23 +0200 Subject: [PATCH 38/63] iio: accel: adxl313: add missing error check in predisable Check the return value of the FIFO bypass regmap_write() before proceeding to disable interrupts. Fixes: ff8093fa6ba4 ("iio: accel: adxl313: add buffered FIFO watermark with interrupt handling") Signed-off-by: Antoniu Miclaus Reviewed-by: Andy Shevchenko Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/accel/adxl313_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/iio/accel/adxl313_core.c b/drivers/iio/accel/adxl313_core.c index 9f5d4d2cb325..83dcac17a042 100644 --- a/drivers/iio/accel/adxl313_core.c +++ b/drivers/iio/accel/adxl313_core.c @@ -998,6 +998,8 @@ static int adxl313_buffer_predisable(struct iio_dev *indio_dev) ret = regmap_write(data->regmap, ADXL313_REG_FIFO_CTL, FIELD_PREP(ADXL313_REG_FIFO_CTL_MODE_MSK, ADXL313_FIFO_BYPASS)); + if (ret) + return ret; ret = regmap_write(data->regmap, ADXL313_REG_INT_ENABLE, 0); if (ret) From 2452969ca1081fea6bd9ab7ad5e168a5d11f28ec Mon Sep 17 00:00:00 2001 From: Felix Gu Date: Sun, 22 Feb 2026 17:45:39 +0800 Subject: [PATCH 39/63] iio: adc: nxp-sar-adc: Fix DMA channel leak in trigger mode The DMA channel was requested in nxp_sar_adc_buffer_postenable() but was only released in nxp_sar_adc_buffer_software_do_predisable(). This caused a DMA channel resource leak when operating in trigger mode. Fix this by moving dma_request_chan() from nxp_sar_adc_buffer_postenable() into nxp_sar_adc_buffer_software_do_postenable(), ensuring the DMA channel is only requested in software mode. Fixes: 4434072a893e ("iio: adc: Add the NXP SAR ADC support for the s32g2/3 platforms") Signed-off-by: Felix Gu Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/nxp-sar-adc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/iio/adc/nxp-sar-adc.c b/drivers/iio/adc/nxp-sar-adc.c index 9efa883c277d..58103bf16aff 100644 --- a/drivers/iio/adc/nxp-sar-adc.c +++ b/drivers/iio/adc/nxp-sar-adc.c @@ -718,6 +718,10 @@ static int nxp_sar_adc_buffer_software_do_postenable(struct iio_dev *indio_dev) struct nxp_sar_adc *info = iio_priv(indio_dev); int ret; + info->dma_chan = dma_request_chan(indio_dev->dev.parent, "rx"); + if (IS_ERR(info->dma_chan)) + return PTR_ERR(info->dma_chan); + nxp_sar_adc_dma_channels_enable(info, *indio_dev->active_scan_mask); nxp_sar_adc_dma_cfg(info, true); @@ -738,6 +742,7 @@ static int nxp_sar_adc_buffer_software_do_postenable(struct iio_dev *indio_dev) out_dma_channels_disable: nxp_sar_adc_dma_cfg(info, false); nxp_sar_adc_dma_channels_disable(info, *indio_dev->active_scan_mask); + dma_release_channel(info->dma_chan); return ret; } @@ -765,10 +770,6 @@ static int nxp_sar_adc_buffer_postenable(struct iio_dev *indio_dev) unsigned long channel; int ret; - info->dma_chan = dma_request_chan(indio_dev->dev.parent, "rx"); - if (IS_ERR(info->dma_chan)) - return PTR_ERR(info->dma_chan); - info->channels_used = 0; /* From d0b224cf9ab12e86a4d1ca55c760dfaa5c19cbe7 Mon Sep 17 00:00:00 2001 From: Aldo Conte Date: Wed, 25 Mar 2026 12:32:16 +0100 Subject: [PATCH 40/63] iio: light: veml6070: fix veml6070_read() return value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit veml6070_read() computes the sensor value in ret but returns 0 instead of the actual result. This causes veml6070_read_raw() to always report 0. Return the computed value instead of 0. Running make W=1 returns no errors. I was unable to test the patch because I do not have the hardware. Found by code inspection. Fixes: fc38525135dd ("iio: light: veml6070: use guard to handle mutex") Signed-off-by: Aldo Conte Reviewed-by: Nuno Sá Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/light/veml6070.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/iio/light/veml6070.c b/drivers/iio/light/veml6070.c index 6d4483c85f30..74d7246e5225 100644 --- a/drivers/iio/light/veml6070.c +++ b/drivers/iio/light/veml6070.c @@ -134,9 +134,7 @@ static int veml6070_read(struct veml6070_data *data) if (ret < 0) return ret; - ret = (msb << 8) | lsb; - - return 0; + return (msb << 8) | lsb; } static const struct iio_chan_spec veml6070_channels[] = { From ec327abae5edd1d5b60ea9f920212970133171d2 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Sat, 14 Mar 2026 11:19:51 +0000 Subject: [PATCH 41/63] rust_binder: use AssertSync for BINDER_VM_OPS When declaring an immutable global variable in Rust, the compiler checks that it looks thread safe, because it is generally safe to access said global variable. When using C bindings types for these globals, we don't really want this check, because it is conservative and assumes pointers are not thread safe. In the case of BINDER_VM_OPS, this is a challenge when combined with the patch 'userfaultfd: introduce vm_uffd_ops' [1], which introduces a pointer field to vm_operations_struct. It previously only held function pointers, which are considered thread safe. Rust Binder should not be assuming that vm_operations_struct contains no pointer fields, so to fix this, use AssertSync (which Rust Binder has already declared for another similar global of type struct file_operations with the same problem). This ensures that even if another commit adds a pointer field to vm_operations_struct, this does not cause problems. Fixes: 8ef2c15aeae0 ("rust_binder: check ownership before using vma") Cc: stable Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202603121235.tpnRxFKO-lkp@intel.com/ Link: https://lore.kernel.org/r/20260306171815.3160826-8-rppt@kernel.org [1] Signed-off-by: Alice Ryhl Reviewed-by: Gary Guo Link: https://patch.msgid.link/20260314111951.4139029-1-aliceryhl@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder/page_range.rs | 8 +++++--- drivers/android/binder/rust_binder_main.rs | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/android/binder/page_range.rs b/drivers/android/binder/page_range.rs index 9dfc154e5dd4..b57e0c7ba3f1 100644 --- a/drivers/android/binder/page_range.rs +++ b/drivers/android/binder/page_range.rs @@ -13,6 +13,8 @@ // // The shrinker will use trylock methods because it locks them in a different order. +use crate::AssertSync; + use core::{ marker::PhantomPinned, mem::{size_of, size_of_val, MaybeUninit}, @@ -143,14 +145,14 @@ pub(crate) struct ShrinkablePageRange { } // We do not define any ops. For now, used only to check identity of vmas. -static BINDER_VM_OPS: bindings::vm_operations_struct = pin_init::zeroed(); +static BINDER_VM_OPS: AssertSync = AssertSync(pin_init::zeroed()); // To ensure that we do not accidentally install pages into or zap pages from the wrong vma, we // check its vm_ops and private data before using it. fn check_vma(vma: &virt::VmaRef, owner: *const ShrinkablePageRange) -> Option<&virt::VmaMixedMap> { // SAFETY: Just reading the vm_ops pointer of any active vma is safe. let vm_ops = unsafe { (*vma.as_ptr()).vm_ops }; - if !ptr::eq(vm_ops, &BINDER_VM_OPS) { + if !ptr::eq(vm_ops, &BINDER_VM_OPS.0) { return None; } @@ -342,7 +344,7 @@ pub(crate) fn register_with_vma(&self, vma: &virt::VmaNew) -> Result { // SAFETY: We own the vma, and we don't use any methods on VmaNew that rely on // `vm_ops`. - unsafe { (*vma.as_ptr()).vm_ops = &BINDER_VM_OPS }; + unsafe { (*vma.as_ptr()).vm_ops = &BINDER_VM_OPS.0 }; Ok(num_pages) } diff --git a/drivers/android/binder/rust_binder_main.rs b/drivers/android/binder/rust_binder_main.rs index aa5f2a75adb4..014010662df8 100644 --- a/drivers/android/binder/rust_binder_main.rs +++ b/drivers/android/binder/rust_binder_main.rs @@ -306,7 +306,7 @@ fn init(_module: &'static kernel::ThisModule) -> Result { /// Makes the inner type Sync. #[repr(transparent)] pub struct AssertSync(T); -// SAFETY: Used only to insert `file_operations` into a global, which is safe. +// SAFETY: Used only to insert C bindings types into globals, which is safe. unsafe impl Sync for AssertSync {} /// File operations that rust_binderfs.c can use. From 8c27b1bce059a11a8d3c8682984e13866f0714af Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Mon, 30 Mar 2026 11:38:30 +0300 Subject: [PATCH 42/63] mei: me: reduce the scope on unexpected reset After commit 2cedb296988c ("mei: me: trigger link reset if hw ready is unexpected") some devices started to show long resume times (5-7 seconds). This happens as mei falsely detects unready hardware, starts parallel link reset flow and triggers link reset timeouts in the resume callback. Address it by performing detection of unready hardware only when driver is in the MEI_DEV_ENABLED state instead of blacklisting states as done in the original patch. This eliminates active waitqueue check as in MEI_DEV_ENABLED state there will be no active waitqueue. Reviewed-by: Rafael J. Wysocki (Intel) Reported-by: Todd Brandt Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221023 Tested-by: Todd Brandt Fixes: 2cedb296988c ("mei: me: trigger link reset if hw ready is unexpected") Cc: stable Signed-off-by: Alexander Usyskin Link: https://patch.msgid.link/20260330083830.536056-1-alexander.usyskin@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw-me.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index d4612c659784..1e4a41ac428f 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c @@ -1337,19 +1337,13 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id) /* check if we need to start the dev */ if (!mei_host_is_ready(dev)) { if (mei_hw_is_ready(dev)) { - /* synchronized by dev mutex */ - if (waitqueue_active(&dev->wait_hw_ready)) { - dev_dbg(&dev->dev, "we need to start the dev.\n"); - dev->recvd_hw_ready = true; - wake_up(&dev->wait_hw_ready); - } else if (dev->dev_state != MEI_DEV_UNINITIALIZED && - dev->dev_state != MEI_DEV_POWERING_DOWN && - dev->dev_state != MEI_DEV_POWER_DOWN) { + if (dev->dev_state == MEI_DEV_ENABLED) { dev_dbg(&dev->dev, "Force link reset.\n"); schedule_work(&dev->reset_work); } else { - dev_dbg(&dev->dev, "Ignore this interrupt in state = %d\n", - dev->dev_state); + dev_dbg(&dev->dev, "we need to start the dev.\n"); + dev->recvd_hw_ready = true; + wake_up(&dev->wait_hw_ready); } } else { dev_dbg(&dev->dev, "Spurious Interrupt\n"); From 69335152910b775e7835939d5c863c580c605275 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 27 Jan 2026 20:11:05 +0100 Subject: [PATCH 43/63] misc/mei: INTEL_MEI should depend on X86 or DRM_XE The Intel Management Engine Interface is only present on x86 platforms and Intel Xe graphics cards. Hence add a dependency on X86 or DRM_XE, to prevent asking the user about this driver when configuring a kernel for a non-x86 architecture and without Xe graphics support. Fixes: 25f9b0d35155 ("misc/mei: Allow building Intel ME interface on non-x86") Cc: stable Signed-off-by: Geert Uytterhoeven Link: https://patch.msgid.link/8e2646fb71b148b3d38beb13f19b14e3634a1e1a.1769541024.git.geert+renesas@glider.be Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/misc/mei/Kconfig b/drivers/misc/mei/Kconfig index 5902dd1ee44b..094fb1dde0fe 100644 --- a/drivers/misc/mei/Kconfig +++ b/drivers/misc/mei/Kconfig @@ -3,6 +3,7 @@ config INTEL_MEI tristate "Intel Management Engine Interface" depends on PCI + depends on X86 || DRM_XE!=n || COMPILE_TEST default X86_64 || MATOM help The Intel Management Engine (Intel ME) provides Manageability, From 8c0ef7b56d6bbbc53f2d43d99c195144f01b0775 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 11 Mar 2026 22:14:00 -0700 Subject: [PATCH 44/63] lis3lv02d: fix kernel-doc warnings Use the correct kernel-doc format to avoid kernel-doc warnings: Warning: include/linux/lis3lv02d.h:125 struct member 'st_min_limits' not described in 'lis3lv02d_platform_data' Warning: include/linux/lis3lv02d.h:125 struct member 'st_max_limits' not described in 'lis3lv02d_platform_data' Signed-off-by: Randy Dunlap Link: https://patch.msgid.link/20260312051400.682991-1-rdunlap@infradead.org Signed-off-by: Greg Kroah-Hartman --- include/linux/lis3lv02d.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/lis3lv02d.h b/include/linux/lis3lv02d.h index b72b8cdba765..feb60ba4e30e 100644 --- a/include/linux/lis3lv02d.h +++ b/include/linux/lis3lv02d.h @@ -30,8 +30,8 @@ * @default_rate: Default sampling rate. 0 means reset default * @setup_resources: Interrupt line setup call back function * @release_resources: Interrupt line release call back function - * @st_min_limits[3]: Selftest acceptance minimum values - * @st_max_limits[3]: Selftest acceptance maximum values + * @st_min_limits: Selftest acceptance minimum values (x, y, z) + * @st_max_limits: Selftest acceptance maximum values (x, y, z) * @irq2: Irq line 2 number * * Platform data is used to setup the sensor chip. Meaning of the different From f40b1401b6ad0f4dadfca4e7a69744352a2e4f8f Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 26 Mar 2026 19:04:36 +0100 Subject: [PATCH 45/63] lis3lv02d: Omit IRQF_ONESHOT if no threaded handler is provided The lis3lv02d started triggering a WARN in the IRQ code because it passes IRQF_ONESHOT to request_threaded_irq() even when thread_fn is NULL, which is an invalid combination. So set the flag only if thread_fn is non-NULL. Cc: Eric Piel Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Signed-off-by: Ard Biesheuvel Link: https://patch.msgid.link/20260326180436.14968-2-ardb@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/misc/lis3lv02d/lis3lv02d.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/misc/lis3lv02d/lis3lv02d.c b/drivers/misc/lis3lv02d/lis3lv02d.c index 9c68f8b1d5d6..21e8ad0a7444 100644 --- a/drivers/misc/lis3lv02d/lis3lv02d.c +++ b/drivers/misc/lis3lv02d/lis3lv02d.c @@ -1230,10 +1230,12 @@ int lis3lv02d_init_device(struct lis3lv02d *lis3) else thread_fn = NULL; + if (thread_fn) + irq_flags |= IRQF_ONESHOT; + err = request_threaded_irq(lis3->irq, lis302dl_interrupt, thread_fn, - IRQF_TRIGGER_RISING | IRQF_ONESHOT | - irq_flags, + irq_flags | IRQF_TRIGGER_RISING, DRIVER_NAME, lis3); if (err < 0) { From 579af7204d762587f9cce0d6236a710a771f1f6f Mon Sep 17 00:00:00 2001 From: Dave Penkler Date: Mon, 2 Feb 2026 10:47:55 +0100 Subject: [PATCH 46/63] gpib: Fix fluke driver s390 compile issue The following errors were reported for a s390 randconfig build of the fluke gpib driver: >> drivers/gpib/eastwood/fluke_gpib.c:1002:23: error: call to undeclared function 'ioremap'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] 1002 | nec_priv->mmiobase = ioremap(e_priv->gpib_iomem_res->start, | ^ >> drivers/gpib/eastwood/fluke_gpib.c:1002:21: error: incompatible integer to pointer conversion assigning to 'void *' from 'int' [-Wint-conversion] 1002 | nec_priv->mmiobase = ioremap(e_priv->gpib_iomem_res->start, | ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1003 | resource_size(e_priv->gpib_iomem_res)); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/gpib/eastwood/fluke_gpib.c:1036:33: error: incompatible integer to pointer conversion assigning to 'void *' from 'int' [-Wint-conversion] 1036 | e_priv->write_transfer_counter = ioremap(e_priv->write_transfer_counter_res->start, | ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1037 | resource_size(e_priv->write_transfer_counter_res)); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Add HAS_IOMEM dependency to Kconfig for fluke driver option Suggested-by: Arnd Bergmann Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202601221748.AFAqHieJ-lkp@intel.com/ Fixes: baf8855c9160 ("staging: gpib: fix address space mixup") Cc: stable Signed-off-by: Dave Penkler Link: https://patch.msgid.link/20260202094755.4259-1-dpenkler@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/gpib/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpib/Kconfig b/drivers/gpib/Kconfig index eeb50956ce85..d43a28c62ed7 100644 --- a/drivers/gpib/Kconfig +++ b/drivers/gpib/Kconfig @@ -122,6 +122,7 @@ config GPIB_FLUKE depends on OF select GPIB_COMMON select GPIB_NEC7210 + depends on HAS_IOMEM help GPIB driver for Fluke based cda devices. From 5cefb52c1af6f69ea719e42788f6ec6a087eb74c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 10 Mar 2026 11:51:27 +0100 Subject: [PATCH 47/63] gpib: lpvo_usb: fix memory leak on disconnect The driver iterates over the registered USB interfaces during GPIB attach and takes a reference to their USB devices until a match is found. These references are never released which leads to a memory leak when devices are disconnected. Fix the leak by dropping the unnecessary references. Fixes: fce79512a96a ("staging: gpib: Add LPVO DIY USB GPIB driver") Cc: stable # 6.13 Cc: Dave Penkler Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260310105127.17538-1-johan@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c b/drivers/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c index ee781d2f0b8e..0f9d385bc50b 100644 --- a/drivers/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c +++ b/drivers/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c @@ -406,7 +406,7 @@ static int usb_gpib_attach(struct gpib_board *board, const struct gpib_board_con for (j = 0 ; j < MAX_DEV ; j++) { if ((assigned_usb_minors & 1 << j) == 0) continue; - udev = usb_get_dev(interface_to_usbdev(lpvo_usb_interfaces[j])); + udev = interface_to_usbdev(lpvo_usb_interfaces[j]); device_path = kobject_get_path(&udev->dev.kobj, GFP_KERNEL); match = gpib_match_device_path(&lpvo_usb_interfaces[j]->dev, config->device_path); @@ -421,7 +421,7 @@ static int usb_gpib_attach(struct gpib_board *board, const struct gpib_board_con for (j = 0 ; j < MAX_DEV ; j++) { if ((assigned_usb_minors & 1 << j) == 0) continue; - udev = usb_get_dev(interface_to_usbdev(lpvo_usb_interfaces[j])); + udev = interface_to_usbdev(lpvo_usb_interfaces[j]); DIA_LOG(1, "dev. %d: bus %d -> %d dev: %d -> %d\n", j, udev->bus->busnum, config->pci_bus, udev->devnum, config->pci_slot); if (config->pci_bus == udev->bus->busnum && From d1857f8296dceb75d00ab857fc3c61bc00c7f5c6 Mon Sep 17 00:00:00 2001 From: Adam Crosser Date: Tue, 17 Mar 2026 19:25:28 +0700 Subject: [PATCH 48/63] gpib: fix use-after-free in IO ioctl handlers The IBRD, IBWRT, IBCMD, and IBWAIT ioctl handlers use a gpib_descriptor pointer after board->big_gpib_mutex has been released. A concurrent IBCLOSEDEV ioctl can free the descriptor via close_dev_ioctl() during this window, causing a use-after-free. The IO handlers (read_ioctl, write_ioctl, command_ioctl) explicitly release big_gpib_mutex before calling their handler. wait_ioctl() is called with big_gpib_mutex held, but ibwait() releases it internally when wait_mask is non-zero. In all four cases, the descriptor pointer obtained from handle_to_descriptor() becomes unprotected. Fix this by introducing a kernel-only descriptor_busy reference count in struct gpib_descriptor. Each handler atomically increments descriptor_busy under file_priv->descriptors_mutex before releasing the lock, and decrements it when done. close_dev_ioctl() checks descriptor_busy under the same lock and rejects the close with -EBUSY if the count is non-zero. A reference count rather than a simple flag is necessary because multiple handlers can operate on the same descriptor concurrently (e.g. IBRD and IBWAIT on the same handle from different threads). A separate counter is needed because io_in_progress can be cleared from unprivileged userspace via the IBWAIT ioctl (through general_ibstatus() with set_mask containing CMPL), which would allow an attacker to bypass a check based solely on io_in_progress. The new descriptor_busy counter is only modified by the kernel IO paths. The lock ordering is consistent (big_gpib_mutex -> descriptors_mutex) and the handlers only hold descriptors_mutex briefly during the lookup, so there is no deadlock risk and no impact on IO throughput. Signed-off-by: Adam Crosser Cc: stable Reviewed-by: Dave Penkler Tested-by: Dave Penkler Signed-off-by: Greg Kroah-Hartman --- drivers/gpib/common/gpib_os.c | 96 +++++++++++++++++++++++-------- drivers/gpib/include/gpib_types.h | 8 +++ 2 files changed, 81 insertions(+), 23 deletions(-) diff --git a/drivers/gpib/common/gpib_os.c b/drivers/gpib/common/gpib_os.c index be757db993a5..97c98f0a7a43 100644 --- a/drivers/gpib/common/gpib_os.c +++ b/drivers/gpib/common/gpib_os.c @@ -888,10 +888,6 @@ static int read_ioctl(struct gpib_file_private *file_priv, struct gpib_board *bo if (read_cmd.completed_transfer_count > read_cmd.requested_transfer_count) return -EINVAL; - desc = handle_to_descriptor(file_priv, read_cmd.handle); - if (!desc) - return -EINVAL; - if (WARN_ON_ONCE(sizeof(userbuf) > sizeof(read_cmd.buffer_ptr))) return -EFAULT; @@ -904,6 +900,17 @@ static int read_ioctl(struct gpib_file_private *file_priv, struct gpib_board *bo if (!access_ok(userbuf, remain)) return -EFAULT; + /* Lock descriptors to prevent concurrent close from freeing descriptor */ + if (mutex_lock_interruptible(&file_priv->descriptors_mutex)) + return -ERESTARTSYS; + desc = handle_to_descriptor(file_priv, read_cmd.handle); + if (!desc) { + mutex_unlock(&file_priv->descriptors_mutex); + return -EINVAL; + } + atomic_inc(&desc->descriptor_busy); + mutex_unlock(&file_priv->descriptors_mutex); + atomic_set(&desc->io_in_progress, 1); /* Read buffer loads till we fill the user supplied buffer */ @@ -937,6 +944,7 @@ static int read_ioctl(struct gpib_file_private *file_priv, struct gpib_board *bo retval = copy_to_user((void __user *)arg, &read_cmd, sizeof(read_cmd)); atomic_set(&desc->io_in_progress, 0); + atomic_dec(&desc->descriptor_busy); wake_up_interruptible(&board->wait); if (retval) @@ -964,10 +972,6 @@ static int command_ioctl(struct gpib_file_private *file_priv, if (cmd.completed_transfer_count > cmd.requested_transfer_count) return -EINVAL; - desc = handle_to_descriptor(file_priv, cmd.handle); - if (!desc) - return -EINVAL; - userbuf = (u8 __user *)(unsigned long)cmd.buffer_ptr; userbuf += cmd.completed_transfer_count; @@ -980,6 +984,17 @@ static int command_ioctl(struct gpib_file_private *file_priv, if (!access_ok(userbuf, remain)) return -EFAULT; + /* Lock descriptors to prevent concurrent close from freeing descriptor */ + if (mutex_lock_interruptible(&file_priv->descriptors_mutex)) + return -ERESTARTSYS; + desc = handle_to_descriptor(file_priv, cmd.handle); + if (!desc) { + mutex_unlock(&file_priv->descriptors_mutex); + return -EINVAL; + } + atomic_inc(&desc->descriptor_busy); + mutex_unlock(&file_priv->descriptors_mutex); + /* * Write buffer loads till we empty the user supplied buffer. * Call drivers at least once, even if remain is zero, in @@ -1003,6 +1018,7 @@ static int command_ioctl(struct gpib_file_private *file_priv, userbuf += bytes_written; if (retval < 0) { atomic_set(&desc->io_in_progress, 0); + atomic_dec(&desc->descriptor_busy); wake_up_interruptible(&board->wait); break; @@ -1022,6 +1038,7 @@ static int command_ioctl(struct gpib_file_private *file_priv, */ if (!no_clear_io_in_prog || fault) atomic_set(&desc->io_in_progress, 0); + atomic_dec(&desc->descriptor_busy); wake_up_interruptible(&board->wait); if (fault) @@ -1047,10 +1064,6 @@ static int write_ioctl(struct gpib_file_private *file_priv, struct gpib_board *b if (write_cmd.completed_transfer_count > write_cmd.requested_transfer_count) return -EINVAL; - desc = handle_to_descriptor(file_priv, write_cmd.handle); - if (!desc) - return -EINVAL; - userbuf = (u8 __user *)(unsigned long)write_cmd.buffer_ptr; userbuf += write_cmd.completed_transfer_count; @@ -1060,6 +1073,17 @@ static int write_ioctl(struct gpib_file_private *file_priv, struct gpib_board *b if (!access_ok(userbuf, remain)) return -EFAULT; + /* Lock descriptors to prevent concurrent close from freeing descriptor */ + if (mutex_lock_interruptible(&file_priv->descriptors_mutex)) + return -ERESTARTSYS; + desc = handle_to_descriptor(file_priv, write_cmd.handle); + if (!desc) { + mutex_unlock(&file_priv->descriptors_mutex); + return -EINVAL; + } + atomic_inc(&desc->descriptor_busy); + mutex_unlock(&file_priv->descriptors_mutex); + atomic_set(&desc->io_in_progress, 1); /* Write buffer loads till we empty the user supplied buffer */ @@ -1094,6 +1118,7 @@ static int write_ioctl(struct gpib_file_private *file_priv, struct gpib_board *b fault = copy_to_user((void __user *)arg, &write_cmd, sizeof(write_cmd)); atomic_set(&desc->io_in_progress, 0); + atomic_dec(&desc->descriptor_busy); wake_up_interruptible(&board->wait); if (fault) @@ -1276,6 +1301,9 @@ static int close_dev_ioctl(struct file *filep, struct gpib_board *board, unsigne { struct gpib_close_dev_ioctl cmd; struct gpib_file_private *file_priv = filep->private_data; + struct gpib_descriptor *desc; + unsigned int pad; + int sad; int retval; retval = copy_from_user(&cmd, (void __user *)arg, sizeof(cmd)); @@ -1284,19 +1312,27 @@ static int close_dev_ioctl(struct file *filep, struct gpib_board *board, unsigne if (cmd.handle >= GPIB_MAX_NUM_DESCRIPTORS) return -EINVAL; - if (!file_priv->descriptors[cmd.handle]) + + mutex_lock(&file_priv->descriptors_mutex); + desc = file_priv->descriptors[cmd.handle]; + if (!desc) { + mutex_unlock(&file_priv->descriptors_mutex); return -EINVAL; - - retval = decrement_open_device_count(board, &board->device_list, - file_priv->descriptors[cmd.handle]->pad, - file_priv->descriptors[cmd.handle]->sad); - if (retval < 0) - return retval; - - kfree(file_priv->descriptors[cmd.handle]); + } + if (atomic_read(&desc->descriptor_busy)) { + mutex_unlock(&file_priv->descriptors_mutex); + return -EBUSY; + } + /* Remove from table while holding lock to prevent new IO from starting */ file_priv->descriptors[cmd.handle] = NULL; + pad = desc->pad; + sad = desc->sad; + mutex_unlock(&file_priv->descriptors_mutex); - return 0; + retval = decrement_open_device_count(board, &board->device_list, pad, sad); + + kfree(desc); + return retval; } static int serial_poll_ioctl(struct gpib_board *board, unsigned long arg) @@ -1331,12 +1367,25 @@ static int wait_ioctl(struct gpib_file_private *file_priv, struct gpib_board *bo if (retval) return -EFAULT; + /* + * Lock descriptors to prevent concurrent close from freeing + * descriptor. ibwait() releases big_gpib_mutex when wait_mask + * is non-zero, so desc must be pinned with descriptor_busy. + */ + mutex_lock(&file_priv->descriptors_mutex); desc = handle_to_descriptor(file_priv, wait_cmd.handle); - if (!desc) + if (!desc) { + mutex_unlock(&file_priv->descriptors_mutex); return -EINVAL; + } + atomic_inc(&desc->descriptor_busy); + mutex_unlock(&file_priv->descriptors_mutex); retval = ibwait(board, wait_cmd.wait_mask, wait_cmd.clear_mask, wait_cmd.set_mask, &wait_cmd.ibsta, wait_cmd.usec_timeout, desc); + + atomic_dec(&desc->descriptor_busy); + if (retval < 0) return retval; @@ -2035,6 +2084,7 @@ void init_gpib_descriptor(struct gpib_descriptor *desc) desc->is_board = 0; desc->autopoll_enabled = 0; atomic_set(&desc->io_in_progress, 0); + atomic_set(&desc->descriptor_busy, 0); } int gpib_register_driver(struct gpib_interface *interface, struct module *provider_module) diff --git a/drivers/gpib/include/gpib_types.h b/drivers/gpib/include/gpib_types.h index 5a0978ae27e7..28b73157ffb7 100644 --- a/drivers/gpib/include/gpib_types.h +++ b/drivers/gpib/include/gpib_types.h @@ -364,6 +364,14 @@ struct gpib_descriptor { unsigned int pad; /* primary gpib address */ int sad; /* secondary gpib address (negative means disabled) */ atomic_t io_in_progress; + /* + * Kernel-only reference count to prevent descriptor from being + * freed while IO handlers hold a pointer to it. Incremented + * before each IO operation, decremented when done. Unlike + * io_in_progress, this cannot be modified from userspace via + * general_ibstatus(). + */ + atomic_t descriptor_busy; unsigned is_board : 1; unsigned autopoll_enabled : 1; }; From 101ab946b79ad83b36d5cfd47de587492a80acf0 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 28 Jan 2026 15:00:10 +0000 Subject: [PATCH 49/63] comedi: ni_atmio16d: Fix invalid clean-up after failed attach If the driver's COMEDI "attach" handler function (`atmio16d_attach()`) returns an error, the COMEDI core will call the driver's "detach" handler function (`atmio16d_detach()`) to clean up. This calls `reset_atmio16d()` unconditionally, but depending on where the error occurred in the attach handler, the device may not have been sufficiently initialized to call `reset_atmio16d()`. It uses `dev->iobase` as the I/O port base address and `dev->private` as the pointer to the COMEDI device's private data structure. `dev->iobase` may still be set to its initial value of 0, which would result in undesired writes to low I/O port addresses. `dev->private` may still be `NULL`, which would result in null pointer dereferences. Fix `atmio16d_detach()` by checking that `dev->private` is valid (non-null) before calling `reset_atmio16d()`. This implies that `dev->iobase` was set correctly since that is set up before `dev->private`. Fixes: 2323b276308a ("Staging: comedi: add ni_at_atmio16d driver") Cc: stable Signed-off-by: Ian Abbott Link: https://patch.msgid.link/20260128150011.5006-1-abbotti@mev.co.uk Signed-off-by: Greg Kroah-Hartman --- drivers/comedi/drivers/ni_atmio16d.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/comedi/drivers/ni_atmio16d.c b/drivers/comedi/drivers/ni_atmio16d.c index e5e7cc423c87..b057b3b3582e 100644 --- a/drivers/comedi/drivers/ni_atmio16d.c +++ b/drivers/comedi/drivers/ni_atmio16d.c @@ -698,7 +698,8 @@ static int atmio16d_attach(struct comedi_device *dev, static void atmio16d_detach(struct comedi_device *dev) { - reset_atmio16d(dev); + if (dev->private) + reset_atmio16d(dev); comedi_legacy_detach(dev); } From 3fb43a7a5b44713f892c58ead2e5f3a1bc9f4ee7 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 5 Feb 2026 13:39:49 +0000 Subject: [PATCH 50/63] comedi: me4000: Fix potential overrun of firmware buffer `me4000_xilinx_download()` loads the firmware that was requested by `request_firmware()`. It is possible for it to overrun the source buffer because it blindly trusts the file format. It reads a data stream length from the first 4 bytes into variable `file_length` and reads the data stream contents of length `file_length` from offset 16 onwards. Add a test to ensure that the supplied firmware is long enough to contain the header and the data stream. On failure, log an error and return `-EINVAL`. Note: The firmware loading was totally broken before commit ac584af59945 ("staging: comedi: me4000: fix firmware downloading"), but that is the most sensible target for this fix. Fixes: ac584af59945 ("staging: comedi: me4000: fix firmware downloading") Cc: stable Signed-off-by: Ian Abbott Link: https://patch.msgid.link/20260205133949.71722-1-abbotti@mev.co.uk Signed-off-by: Greg Kroah-Hartman --- drivers/comedi/drivers/me4000.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/comedi/drivers/me4000.c b/drivers/comedi/drivers/me4000.c index 7dd3a0071863..effe9fdbbafe 100644 --- a/drivers/comedi/drivers/me4000.c +++ b/drivers/comedi/drivers/me4000.c @@ -315,6 +315,18 @@ static int me4000_xilinx_download(struct comedi_device *dev, unsigned int val; unsigned int i; + /* Get data stream length from header. */ + if (size >= 4) { + file_length = (((unsigned int)data[0] & 0xff) << 24) + + (((unsigned int)data[1] & 0xff) << 16) + + (((unsigned int)data[2] & 0xff) << 8) + + ((unsigned int)data[3] & 0xff); + } + if (size < 16 || file_length > size - 16) { + dev_err(dev->class_dev, "Firmware length inconsistency\n"); + return -EINVAL; + } + if (!xilinx_iobase) return -ENODEV; @@ -346,10 +358,6 @@ static int me4000_xilinx_download(struct comedi_device *dev, outl(val, devpriv->plx_regbase + PLX9052_CNTRL); /* Download Xilinx firmware */ - file_length = (((unsigned int)data[0] & 0xff) << 24) + - (((unsigned int)data[1] & 0xff) << 16) + - (((unsigned int)data[2] & 0xff) << 8) + - ((unsigned int)data[3] & 0xff); usleep_range(10, 1000); for (i = 0; i < file_length; i++) { From cc797d4821c754c701d9714b58bea947e31dbbe0 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 5 Feb 2026 14:01:30 +0000 Subject: [PATCH 51/63] comedi: me_daq: Fix potential overrun of firmware buffer `me2600_xilinx_download()` loads the firmware that was requested by `request_firmware()`. It is possible for it to overrun the source buffer because it blindly trusts the file format. It reads a data stream length from the first 4 bytes into variable `file_length` and reads the data stream contents of length `file_length` from offset 16 onwards. Although it checks that the supplied firmware is at least 16 bytes long, it does not check that it is long enough to contain the data stream. Add a test to ensure that the supplied firmware is long enough to contain the header and the data stream. On failure, log an error and return `-EINVAL`. Fixes: 85acac61096f9 ("Staging: comedi: add me_daq driver") Cc: stable Signed-off-by: Ian Abbott Link: https://patch.msgid.link/20260205140130.76697-1-abbotti@mev.co.uk Signed-off-by: Greg Kroah-Hartman --- drivers/comedi/drivers/me_daq.c | 35 ++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/drivers/comedi/drivers/me_daq.c b/drivers/comedi/drivers/me_daq.c index 076b15097afd..2f2ea029cffc 100644 --- a/drivers/comedi/drivers/me_daq.c +++ b/drivers/comedi/drivers/me_daq.c @@ -344,6 +344,25 @@ static int me2600_xilinx_download(struct comedi_device *dev, unsigned int file_length; unsigned int i; + /* + * Format of the firmware + * Build longs from the byte-wise coded header + * Byte 1-3: length of the array + * Byte 4-7: version + * Byte 8-11: date + * Byte 12-15: reserved + */ + if (size >= 4) { + file_length = (((unsigned int)data[0] & 0xff) << 24) + + (((unsigned int)data[1] & 0xff) << 16) + + (((unsigned int)data[2] & 0xff) << 8) + + ((unsigned int)data[3] & 0xff); + } + if (size < 16 || file_length > size - 16) { + dev_err(dev->class_dev, "Firmware length inconsistency\n"); + return -EINVAL; + } + /* disable irq's on PLX */ writel(0x00, devpriv->plx_regbase + PLX9052_INTCSR); @@ -357,22 +376,6 @@ static int me2600_xilinx_download(struct comedi_device *dev, writeb(0x00, dev->mmio + 0x0); sleep(1); - /* - * Format of the firmware - * Build longs from the byte-wise coded header - * Byte 1-3: length of the array - * Byte 4-7: version - * Byte 8-11: date - * Byte 12-15: reserved - */ - if (size < 16) - return -EINVAL; - - file_length = (((unsigned int)data[0] & 0xff) << 24) + - (((unsigned int)data[1] & 0xff) << 16) + - (((unsigned int)data[2] & 0xff) << 8) + - ((unsigned int)data[3] & 0xff); - /* * Loop for writing firmware byte by byte to xilinx * Firmware data start at offset 16 From 4b9a9a6d71e3e252032f959fb3895a33acb5865c Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 25 Feb 2026 13:24:27 +0000 Subject: [PATCH 52/63] comedi: Reinit dev->spinlock between attachments to low-level drivers `struct comedi_device` is the main controlling structure for a COMEDI device created by the COMEDI subsystem. It contains a member `spinlock` containing a spin-lock that is initialized by the COMEDI subsystem, but is reserved for use by a low-level driver attached to the COMEDI device (at least since commit 25436dc9d84f ("Staging: comedi: remove RT code")). Some COMEDI devices (those created on initialization of the COMEDI subsystem when the "comedi.comedi_num_legacy_minors" parameter is non-zero) can be attached to different low-level drivers over their lifetime using the `COMEDI_DEVCONFIG` ioctl command. This can result in inconsistent lock states being reported when there is a mismatch in the spin-lock locking levels used by each low-level driver to which the COMEDI device has been attached. Fix it by reinitializing `dev->spinlock` before calling the low-level driver's `attach` function pointer if `CONFIG_LOCKDEP` is enabled. Reported-by: syzbot+cc9f7f4a7df09f53c4a4@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=cc9f7f4a7df09f53c4a4 Fixes: ed9eccbe8970 ("Staging: add comedi core") Cc: stable Signed-off-by: Ian Abbott Link: https://patch.msgid.link/20260225132427.86578-1-abbotti@mev.co.uk Signed-off-by: Greg Kroah-Hartman --- drivers/comedi/drivers.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/comedi/drivers.c b/drivers/comedi/drivers.c index db225a3bf012..5ab96b5eefd1 100644 --- a/drivers/comedi/drivers.c +++ b/drivers/comedi/drivers.c @@ -1063,6 +1063,14 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it) ret = -EIO; goto out; } + if (IS_ENABLED(CONFIG_LOCKDEP)) { + /* + * dev->spinlock is for private use by the attached low-level + * driver. Reinitialize it to stop lock-dependency tracking + * between attachments to different low-level drivers. + */ + spin_lock_init(&dev->spinlock); + } dev->driver = driv; dev->board_name = dev->board_ptr ? *(const char **)dev->board_ptr : dev->driver->driver_name; From 29f644f14b89e6c4965e3c89251929e451190a66 Mon Sep 17 00:00:00 2001 From: Edward Adam Davis Date: Tue, 10 Mar 2026 11:11:04 +0000 Subject: [PATCH 53/63] comedi: runflags cannot determine whether to reclaim chanlist syzbot reported a memory leak [1], because commit 4e1da516debb ("comedi: Add reference counting for Comedi command handling") did not consider the exceptional exit case in do_cmd_ioctl() where runflags is not set. This caused chanlist not to be properly freed by do_become_nonbusy(), as it only frees chanlist when runflags is correctly set. Added a check in do_become_nonbusy() for the case where runflags is not set, to properly free the chanlist memory. [1] BUG: memory leak backtrace (crc 844a0efa): __comedi_get_user_chanlist drivers/comedi/comedi_fops.c:1815 [inline] do_cmd_ioctl.part.0+0x112/0x350 drivers/comedi/comedi_fops.c:1890 do_cmd_ioctl drivers/comedi/comedi_fops.c:1858 [inline] Fixes: 4e1da516debb ("comedi: Add reference counting for Comedi command handling") Reported-by: syzbot+f238baf6ded841b5a82e@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=f238baf6ded841b5a82e Signed-off-by: Edward Adam Davis Reviewed-by: Ian Abbott Cc: stable # 6.19 Signed-off-by: Ian Abbott Link: https://patch.msgid.link/20260310111104.70959-1-abbotti@mev.co.uk Signed-off-by: Greg Kroah-Hartman --- drivers/comedi/comedi_fops.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/comedi/comedi_fops.c b/drivers/comedi/comedi_fops.c index 48a8a607a84c..0df9f4636fb6 100644 --- a/drivers/comedi/comedi_fops.c +++ b/drivers/comedi/comedi_fops.c @@ -793,13 +793,15 @@ static void do_become_nonbusy(struct comedi_device *dev, __comedi_clear_subdevice_runflags(s, COMEDI_SRF_RUNNING | COMEDI_SRF_BUSY); spin_unlock_irqrestore(&s->spin_lock, flags); - if (comedi_is_runflags_busy(runflags)) { + if (async) { /* * "Run active" counter was set to 1 when setting up the * command. Decrement it and wait for it to become 0. */ - comedi_put_is_subdevice_running(s); - wait_for_completion(&async->run_complete); + if (comedi_is_runflags_busy(runflags)) { + comedi_put_is_subdevice_running(s); + wait_for_completion(&async->run_complete); + } comedi_buf_reset(s); async->inttrig = NULL; kfree(async->cmd.chanlist); From 93853512f565e625df2397f0d8050d6aafd7c3ad Mon Sep 17 00:00:00 2001 From: Deepanshu Kartikey Date: Mon, 9 Mar 2026 16:18:59 +0530 Subject: [PATCH 54/63] comedi: dt2815: add hardware detection to prevent crash The dt2815 driver crashes when attached to I/O ports without actual hardware present. This occurs because syzkaller or users can attach the driver to arbitrary I/O addresses via COMEDI_DEVCONFIG ioctl. When no hardware exists at the specified port, inb() operations return 0xff (floating bus), but outb() operations can trigger page faults due to undefined behavior, especially under race conditions: BUG: unable to handle page fault for address: 000000007fffff90 #PF: supervisor write access in kernel mode #PF: error_code(0x0002) - not-present page RIP: 0010:dt2815_attach+0x6e0/0x1110 Add hardware detection by reading the status register before attempting any write operations. If the read returns 0xff, assume no hardware is present and fail the attach with -ENODEV. This prevents crashes from outb() operations on non-existent hardware. Reported-by: syzbot+72f94b474d6e50b71ffc@syzkaller.appspotmail.com Cc: stable Closes: https://syzkaller.appspot.com/bug?extid=72f94b474d6e50b71ffc Tested-by: syzbot+72f94b474d6e50b71ffc@syzkaller.appspotmail.com Reviewed-by: Ian Abbott Signed-off-by: Deepanshu Kartikey Link: [https://lore.kernel.org/all/20260126070458.10974-1-kartikey406@gmail.com/T/] Link: [https://lore.kernel.org/all/20260126070458.10974-1-kartikey406@gmail.com/T/ Link: https://patch.msgid.link/20260309104859.503529-1-kartikey406@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/comedi/drivers/dt2815.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/comedi/drivers/dt2815.c b/drivers/comedi/drivers/dt2815.c index 03ba2fd18a21..d066dc303520 100644 --- a/drivers/comedi/drivers/dt2815.c +++ b/drivers/comedi/drivers/dt2815.c @@ -175,6 +175,18 @@ static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it) ? current_range_type : voltage_range_type; } + /* + * Check if hardware is present before attempting any I/O operations. + * Reading 0xff from status register typically indicates no hardware + * on the bus (floating bus reads as all 1s). + */ + if (inb(dev->iobase + DT2815_STATUS) == 0xff) { + dev_err(dev->class_dev, + "No hardware detected at I/O base 0x%lx\n", + dev->iobase); + return -ENODEV; + } + /* Init the 2815 */ outb(0x00, dev->iobase + DT2815_STATUS); for (i = 0; i < 100; i++) { From ba2c83167b215da30fa2aae56b140198cf8d8408 Mon Sep 17 00:00:00 2001 From: Xingjing Deng Date: Fri, 30 Jan 2026 07:41:40 +0800 Subject: [PATCH 55/63] misc: fastrpc: possible double-free of cctx->remote_heap fastrpc_init_create_static_process() may free cctx->remote_heap on the err_map path but does not clear the pointer. Later, fastrpc_rpmsg_remove() frees cctx->remote_heap again if it is non-NULL, which can lead to a double-free if the INIT_CREATE_STATIC ioctl hits the error path and the rpmsg device is subsequently removed/unbound. Clear cctx->remote_heap after freeing it in the error path to prevent the later cleanup from freeing it again. This issue was found by an in-house analysis workflow that extracts AST-based information and runs static checks, with LLM assistance for triage, and was confirmed by manual code review. No hardware testing was performed. Fixes: 0871561055e66 ("misc: fastrpc: Add support for audiopd") Cc: stable@vger.kernel.org # 6.2+ Signed-off-by: Xingjing Deng Reviewed-by: Dmitry Baryshkov Link: https://patch.msgid.link/20260129234140.410983-1-xjdeng@buaa.edu.cn Signed-off-by: Greg Kroah-Hartman --- drivers/misc/fastrpc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 47356a5d5804..19cfc487df7c 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -1401,6 +1401,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, } err_map: fastrpc_buf_free(fl->cctx->remote_heap); + fl->cctx->remote_heap = NULL; err_name: kfree(name); err: From 6a502776f4a4f80fb839b22f12aeaf0267fca344 Mon Sep 17 00:00:00 2001 From: Xingjing Deng Date: Sat, 31 Jan 2026 14:55:39 +0800 Subject: [PATCH 56/63] misc: fastrpc: check qcom_scm_assign_mem() return in rpmsg_probe In the SDSP probe path, qcom_scm_assign_mem() is used to assign the reserved memory to the configured VMIDs, but its return value was not checked. Fail the probe if the SCM call fails to avoid continuing with an unexpected/incorrect memory permission configuration. This issue was found by an in-house analysis workflow that extracts AST-based information and runs static checks, with LLM assistance for triage, and was confirmed by manual code review. No hardware testing was performed. Fixes: c3c0363bc72d4 ("misc: fastrpc: support complete DMA pool access to the DSP") Cc: stable@vger.kernel.org # 6.11-rc1 Signed-off-by: Xingjing Deng Reviewed-by: Dmitry Baryshkov Link: https://patch.msgid.link/20260131065539.2124047-1-xjdeng@buaa.edu.cn Signed-off-by: Greg Kroah-Hartman --- drivers/misc/fastrpc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 19cfc487df7c..1080f9acf70a 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -2390,8 +2390,10 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) if (!err) { src_perms = BIT(QCOM_SCM_VMID_HLOS); - qcom_scm_assign_mem(res.start, resource_size(&res), &src_perms, + err = qcom_scm_assign_mem(res.start, resource_size(&res), &src_perms, data->vmperms, data->vmcount); + if (err) + goto err_free_data; } } From 48b5163c957548f5854f14c90bfdedc33afbea3c Mon Sep 17 00:00:00 2001 From: Christian Eggers Date: Fri, 27 Mar 2026 13:16:44 +0000 Subject: [PATCH 57/63] nvmem: imx: assign nvmem_cell_info::raw_len Avoid getting error messages at startup like the following on i.MX6ULL: nvmem imx-ocotp0: cell mac-addr raw len 6 unaligned to nvmem word size 4 nvmem imx-ocotp0: cell mac-addr raw len 6 unaligned to nvmem word size 4 This shouldn't cause any functional change as this alignment would otherwise be done in nvmem_cell_info_to_nvmem_cell_entry_nodup(). Cc: stable@vger.kernel.org Fixes: 13bcd440f2ff ("nvmem: core: verify cell's raw_len") Signed-off-by: Christian Eggers Signed-off-by: Fabio Estevam Signed-off-by: Srinivas Kandagatla Link: https://patch.msgid.link/20260327131645.3025781-2-srini@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/imx-ocotp-ele.c | 1 + drivers/nvmem/imx-ocotp.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/nvmem/imx-ocotp-ele.c b/drivers/nvmem/imx-ocotp-ele.c index 7cf7e809a8f5..a0d2985c6d03 100644 --- a/drivers/nvmem/imx-ocotp-ele.c +++ b/drivers/nvmem/imx-ocotp-ele.c @@ -131,6 +131,7 @@ static int imx_ocotp_cell_pp(void *context, const char *id, int index, static void imx_ocotp_fixup_dt_cell_info(struct nvmem_device *nvmem, struct nvmem_cell_info *cell) { + cell->raw_len = round_up(cell->bytes, 4); cell->read_post_process = imx_ocotp_cell_pp; } diff --git a/drivers/nvmem/imx-ocotp.c b/drivers/nvmem/imx-ocotp.c index 7bf7656d4f96..108d78d7f6cb 100644 --- a/drivers/nvmem/imx-ocotp.c +++ b/drivers/nvmem/imx-ocotp.c @@ -589,6 +589,7 @@ MODULE_DEVICE_TABLE(of, imx_ocotp_dt_ids); static void imx_ocotp_fixup_dt_cell_info(struct nvmem_device *nvmem, struct nvmem_cell_info *cell) { + cell->raw_len = round_up(cell->bytes, 4); cell->read_post_process = imx_ocotp_cell_pp; } From f9b88613ff402aa6fe8fd020573cb95867ae947e Mon Sep 17 00:00:00 2001 From: Ivan Vera Date: Fri, 27 Mar 2026 13:16:45 +0000 Subject: [PATCH 58/63] nvmem: zynqmp_nvmem: Fix buffer size in DMA and memcpy Buffer size used in dma allocation and memcpy is wrong. It can lead to undersized DMA buffer access and possible memory corruption. use correct buffer size in dma_alloc_coherent and memcpy. Fixes: 737c0c8d07b5 ("nvmem: zynqmp_nvmem: Add support to access efuse") Cc: stable@vger.kernel.org Signed-off-by: Ivan Vera Signed-off-by: Harish Ediga Signed-off-by: Harsh Jain Signed-off-by: Srinivas Kandagatla Link: https://patch.msgid.link/20260327131645.3025781-3-srini@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/zynqmp_nvmem.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/nvmem/zynqmp_nvmem.c b/drivers/nvmem/zynqmp_nvmem.c index 7da717d6c7fa..d297ff150dc0 100644 --- a/drivers/nvmem/zynqmp_nvmem.c +++ b/drivers/nvmem/zynqmp_nvmem.c @@ -66,7 +66,7 @@ static int zynqmp_efuse_access(void *context, unsigned int offset, dma_addr_t dma_buf; size_t words = bytes / WORD_INBYTES; int ret; - int value; + unsigned int value; char *data; if (bytes % WORD_INBYTES != 0) { @@ -80,7 +80,7 @@ static int zynqmp_efuse_access(void *context, unsigned int offset, } if (pufflag == 1 && flag == EFUSE_WRITE) { - memcpy(&value, val, bytes); + memcpy(&value, val, sizeof(value)); if ((offset == EFUSE_PUF_START_OFFSET || offset == EFUSE_PUF_MID_OFFSET) && value & P_USER_0_64_UPPER_MASK) { @@ -100,7 +100,7 @@ static int zynqmp_efuse_access(void *context, unsigned int offset, if (!efuse) return -ENOMEM; - data = dma_alloc_coherent(dev, sizeof(bytes), + data = dma_alloc_coherent(dev, bytes, &dma_buf, GFP_KERNEL); if (!data) { ret = -ENOMEM; @@ -134,7 +134,7 @@ static int zynqmp_efuse_access(void *context, unsigned int offset, if (flag == EFUSE_READ) memcpy(val, data, bytes); efuse_access_err: - dma_free_coherent(dev, sizeof(bytes), + dma_free_coherent(dev, bytes, data, dma_buf); efuse_data_fail: dma_free_coherent(dev, sizeof(struct xilinx_efuse), From d78ceee1e6205ffcd84ff581ccb40a008d39136f Mon Sep 17 00:00:00 2001 From: Askar Safin Date: Tue, 24 Mar 2026 08:29:28 +0000 Subject: [PATCH 59/63] .get_maintainer.ignore: add myself I don't want get_maintainer.pl to automatically print my email. Signed-off-by: Askar Safin Link: https://patch.msgid.link/20260324082928.3473789-1-safinaskar@gmail.com Signed-off-by: Greg Kroah-Hartman --- .get_maintainer.ignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.get_maintainer.ignore b/.get_maintainer.ignore index e8d2269bad9d..60b6b2a374cd 100644 --- a/.get_maintainer.ignore +++ b/.get_maintainer.ignore @@ -1,6 +1,7 @@ Alan Cox Alan Cox Alyssa Rosenzweig +Askar Safin Christoph Hellwig Jeff Kirsher Marc Gonzalez From f2b1cbef153636fa498324b47e822e8b4d1774aa Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 3 Apr 2026 08:20:16 +0200 Subject: [PATCH 60/63] Documentation: minor updates to the security contacts This clarifies the fact that the bug reporters must use a valid e-mail address to send their report, and that the security team assists developers working on a fix but doesn't always produce fixes on its own. Cc: Eric Dumazet Cc: Greg KH Signed-off-by: Willy Tarreau Link: https://patch.msgid.link/20260403062018.31080-2-w@1wt.eu Signed-off-by: Greg Kroah-Hartman --- Documentation/process/security-bugs.rst | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Documentation/process/security-bugs.rst b/Documentation/process/security-bugs.rst index c0cf93e11565..da7937fd59df 100644 --- a/Documentation/process/security-bugs.rst +++ b/Documentation/process/security-bugs.rst @@ -8,6 +8,10 @@ like to know when a security bug is found so that it can be fixed and disclosed as quickly as possible. Please report security bugs to the Linux kernel security team. +Reports are to be sent over e-mail exclusively. Please use a working e-mail +address, preferably the same that you want to appear in ``Reported-by`` tags +if any. If unsure, send your report to yourself first. + The security team and maintainers almost always require additional information beyond what was initially provided in a report and rely on active and efficient collaboration with the reporter to perform further @@ -27,11 +31,9 @@ made public. The Linux kernel security team can be contacted by email at . This is a private list of security officers -who will help verify the bug report and develop and release a fix. -If you already have a fix, please include it with your report, as -that can speed up the process considerably. It is possible that the -security team will bring in extra help from area maintainers to -understand and fix the security vulnerability. +who will help verify the bug report and assist developers working on a fix. +It is possible that the security team will bring in extra help from area +maintainers to understand and fix the security vulnerability. Please send **plain text** emails without attachments where possible. It is much harder to have a context-quoted discussion about a complex From a72b832a482372001a158c8014d116b053089b5d Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 3 Apr 2026 08:20:17 +0200 Subject: [PATCH 61/63] Documentation: explain how to find maintainers addresses for security reports These days, 80% of the work done by the security team consists in locating the affected subsystem in a report, running get_maintainers on it, forwarding the report to these persons and responding to the reporter with them in Cc. This is a huge and unneeded overhead that we must try to lower for a better overall efficiency. This patch adds a complete section explaining how to figure the list of recipients to send the report to. Cc: Eric Dumazet Cc: Greg KH Signed-off-by: Willy Tarreau Link: https://patch.msgid.link/20260403062018.31080-3-w@1wt.eu Signed-off-by: Greg Kroah-Hartman --- Documentation/process/security-bugs.rst | 76 ++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 3 deletions(-) diff --git a/Documentation/process/security-bugs.rst b/Documentation/process/security-bugs.rst index da7937fd59df..ac97fc78fecd 100644 --- a/Documentation/process/security-bugs.rst +++ b/Documentation/process/security-bugs.rst @@ -5,8 +5,75 @@ Security bugs Linux kernel developers take security very seriously. As such, we'd like to know when a security bug is found so that it can be fixed and -disclosed as quickly as possible. Please report security bugs to the -Linux kernel security team. +disclosed as quickly as possible. + +Identifying contacts +-------------------- + +The most effective way to report a security bug is to send it directly to the +affected subsystem's maintainers and Cc: the Linux kernel security team. Do +not send it to a public list at this stage, unless you have good reasons to +consider the issue as being public or trivial to discover (e.g. result of a +widely available automated vulnerability scanning tool that can be repeated by +anyone). + +If you're sending a report for issues affecting multiple parts in the kernel, +even if they're fairly similar issues, please send individual messages (think +that maintainers will not all work on the issues at the same time). The only +exception is when an issue concerns closely related parts maintained by the +exact same subset of maintainers, and these parts are expected to be fixed all +at once by the same commit, then it may be acceptable to report them at once. + +One difficulty for most first-time reporters is to figure the right list of +recipients to send a report to. In the Linux kernel, all official maintainers +are trusted, so the consequences of accidentally including the wrong maintainer +are essentially a bit more noise for that person, i.e. nothing dramatic. As +such, a suitable method to figure the list of maintainers (which kernel +security officers use) is to rely on the get_maintainers.pl script, tuned to +only report maintainers. This script, when passed a file name, will look for +its path in the MAINTAINERS file to figure a hierarchical list of relevant +maintainers. Calling it a first time with the finest level of filtering will +most of the time return a short list of this specific file's maintainers:: + + $ ./scripts/get_maintainer.pl --no-l --no-r --pattern-depth 1 \ + drivers/example.c + Developer One (maintainer:example driver) + Developer Two (maintainer:example driver) + +These two maintainers should then receive the message. If the command does not +return anything, it means the affected file is part of a wider subsystem, so we +should be less specific:: + + $ ./scripts/get_maintainer.pl --no-l --no-r drivers/example.c + Developer One (maintainer:example subsystem) + Developer Two (maintainer:example subsystem) + Developer Three (maintainer:example subsystem [GENERAL]) + Developer Four (maintainer:example subsystem [GENERAL]) + +Here, picking the first, most specific ones, is sufficient. When the list is +long, it is possible to produce a comma-delimited e-mail address list on a +single line suitable for use in the To: field of a mailer like this:: + + $ ./scripts/get_maintainer.pl --no-tree --no-l --no-r --no-n --m \ + --no-git-fallback --no-substatus --no-rolestats --no-multiline \ + --pattern-depth 1 drivers/example.c + dev1@example.com, dev2@example.org + +or this for the wider list:: + + $ ./scripts/get_maintainer.pl --no-tree --no-l --no-r --no-n --m \ + --no-git-fallback --no-substatus --no-rolestats --no-multiline \ + drivers/example.c + dev1@example.com, dev2@example.org, dev3@example.com, dev4@example.org + +If at this point you're still facing difficulties spotting the right +maintainers, **and only in this case**, it's possible to send your report to +the Linux kernel security team only. Your message will be triaged, and you +will receive instructions about whom to contact, if needed. Your message may +equally be forwarded as-is to the relevant maintainers. + +Sending the report +------------------ Reports are to be sent over e-mail exclusively. Please use a working e-mail address, preferably the same that you want to appear in ``Reported-by`` tags @@ -29,6 +96,7 @@ information is helpful. Any exploit code is very helpful and will not be released without consent from the reporter unless it has already been made public. +The report must be sent to maintainers, with the security team in ``Cc:``. The Linux kernel security team can be contacted by email at . This is a private list of security officers who will help verify the bug report and assist developers working on a fix. @@ -44,7 +112,9 @@ reproduction steps, and follow it with a proposed fix, all in plain text. Markdown, HTML and RST formatted reports are particularly frowned upon since they're quite hard to read for humans and encourage to use dedicated viewers, sometimes online, which by definition is not acceptable for a confidential -security report. +security report. Note that some mailers tend to mangle formatting of plain +text by default, please consult Documentation/process/email-clients.rst for +more info. Disclosure and embargoed information ------------------------------------ From 496fa1befba1e8ff149af5120cd9c9616bb05120 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 3 Apr 2026 08:20:18 +0200 Subject: [PATCH 62/63] Documentation: clarify the mandatory and desirable info for security reports A significant part of the effort of the security team consists in begging reporters for patch proposals, or asking them to provide them in regular format, and most of the time they're willing to provide this, they just didn't know that it would help. So let's add a section detailing the required and desirable contents in a security report to help reporters write more actionable reports which do not require round trips. Cc: Eric Dumazet Cc: Greg KH Signed-off-by: Willy Tarreau Link: https://patch.msgid.link/20260403062018.31080-4-w@1wt.eu Signed-off-by: Greg Kroah-Hartman --- Documentation/process/security-bugs.rst | 66 ++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 7 deletions(-) diff --git a/Documentation/process/security-bugs.rst b/Documentation/process/security-bugs.rst index ac97fc78fecd..0b1f6d8e3cbe 100644 --- a/Documentation/process/security-bugs.rst +++ b/Documentation/process/security-bugs.rst @@ -7,6 +7,65 @@ Linux kernel developers take security very seriously. As such, we'd like to know when a security bug is found so that it can be fixed and disclosed as quickly as possible. +Preparing your report +--------------------- + +Like with any bug report, a security bug report requires a lot of analysis work +from the developers, so the more information you can share about the issue, the +better. Please review the procedure outlined in +Documentation/admin-guide/reporting-issues.rst if you are unclear about what +information is helpful. The following information are absolutely necessary in +**any** security bug report: + + * **affected kernel version range**: with no version indication, your report + will not be processed. A significant part of reports are for bugs that + have already been fixed, so it is extremely important that vulnerabilities + are verified on recent versions (development tree or latest stable + version), at least by verifying that the code has not changed since the + version where it was detected. + + * **description of the problem**: a detailed description of the problem, with + traces showing its manifestation, and why you consider that the observed + behavior as a problem in the kernel, is necessary. + + * **reproducer**: developers will need to be able to reproduce the problem to + consider a fix as effective. This includes both a way to trigger the issue + and a way to confirm it happens. A reproducer with low complexity + dependencies will be needed (source code, shell script, sequence of + instructions, file-system image etc). Binary-only executables are not + accepted. Working exploits are extremely helpful and will not be released + without consent from the reporter, unless they are already public. By + definition if an issue cannot be reproduced, it is not exploitable, thus it + is not a security bug. + + * **conditions**: if the bug depends on certain configuration options, + sysctls, permissions, timing, code modifications etc, these should be + indicated. + +In addition, the following information are highly desirable: + + * **suspected location of the bug**: the file names and functions where the + bug is suspected to be present are very important, at least to help forward + the report to the appropriate maintainers. When not possible (for example, + "system freezes each time I run this command"), the security team will help + identify the source of the bug. + + * **a proposed fix**: bug reporters who have analyzed the cause of a bug in + the source code almost always have an accurate idea on how to fix it, + because they spent a long time studying it and its implications. Proposing + a tested fix will save maintainers a lot of time, even if the fix ends up + not being the right one, because it helps understand the bug. When + proposing a tested fix, please always format it in a way that can be + immediately merged (see Documentation/process/submitting-patches.rst). + This will save some back-and-forth exchanges if it is accepted, and you + will be credited for finding and fixing this issue. Note that in this case + only a ``Signed-off-by:`` tag is needed, without ``Reported-by:` when the + reporter and author are the same. + + * **mitigations**: very often during a bug analysis, some ways of mitigating + the issue appear. It is useful to share them, as they can be helpful to + keep end users protected during the time it takes them to apply the fix. + Identifying contacts -------------------- @@ -89,13 +148,6 @@ run additional tests. Reports where the reporter does not respond promptly or cannot effectively discuss their findings may be abandoned if the communication does not quickly improve. -As it is with any bug, the more information provided the easier it -will be to diagnose and fix. Please review the procedure outlined in -'Documentation/admin-guide/reporting-issues.rst' if you are unclear about what -information is helpful. Any exploit code is very helpful and will not -be released without consent from the reporter unless it has already been -made public. - The report must be sent to maintainers, with the security team in ``Cc:``. The Linux kernel security team can be contacted by email at . This is a private list of security officers From f387e2e2b9d302688dbdceebe9aade221c90f09e Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sat, 4 Apr 2026 10:20:33 +0200 Subject: [PATCH 63/63] Documentation: fix two typos in latest update to the security report howto In previous patch "Documentation: clarify the mandatory and desirable info for security reports" I left two typos that I didn't detect in local checks. One is "get_maintainers.pl" (no 's' in the script name), and the other one is a missing closing quote after "Reported-by", which didn't have effect here but I don't know if it can break rendering elsewhere (e.g. on the public HTML page). Better fix it before it gets merged. Signed-off-by: Willy Tarreau Link: https://patch.msgid.link/20260404082033.5160-1-w@1wt.eu Signed-off-by: Greg Kroah-Hartman --- Documentation/process/security-bugs.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/process/security-bugs.rst b/Documentation/process/security-bugs.rst index 0b1f6d8e3cbe..27b028e85861 100644 --- a/Documentation/process/security-bugs.rst +++ b/Documentation/process/security-bugs.rst @@ -59,7 +59,7 @@ In addition, the following information are highly desirable: immediately merged (see Documentation/process/submitting-patches.rst). This will save some back-and-forth exchanges if it is accepted, and you will be credited for finding and fixing this issue. Note that in this case - only a ``Signed-off-by:`` tag is needed, without ``Reported-by:` when the + only a ``Signed-off-by:`` tag is needed, without ``Reported-by:`` when the reporter and author are the same. * **mitigations**: very often during a bug analysis, some ways of mitigating @@ -88,7 +88,7 @@ recipients to send a report to. In the Linux kernel, all official maintainers are trusted, so the consequences of accidentally including the wrong maintainer are essentially a bit more noise for that person, i.e. nothing dramatic. As such, a suitable method to figure the list of maintainers (which kernel -security officers use) is to rely on the get_maintainers.pl script, tuned to +security officers use) is to rely on the get_maintainer.pl script, tuned to only report maintainers. This script, when passed a file name, will look for its path in the MAINTAINERS file to figure a hierarchical list of relevant maintainers. Calling it a first time with the finest level of filtering will