Merge tag 'iio-fixes-for-6.17a' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/jic23/iio into char-misc-linus

Jonathan writes:

IIO: 1st set of fixes for 6.17

Usual mixed bunch of ancient issues and relatively new ones.

adi,ad7124
- Fix channel lookup to use chan->address for indexing array.
adi,ad7173
- Stop accidentally enabling more configs than supported at one time.
adi,ad7380
- Fill in missing max_conversion_rate_hz for adaq4381-4
ams,as73211
- Fix uninitialized holes in scan data exposed to userspace.
bosch,bmp280
- Check for error when requesting optional GPIO rather than simply assuming
  success or a NULL return when no GPIO provided.
invensense,icm42600
- Change error code returned to -EBUSY on a temperature read with neither
  accelerometer nor gyroscope in use.  Reduces chance of misinterpretation
  by userspace.
kionix,sca3300
- Fix uninitialized holes in scan data exposed to userspace.
maxim,thermocouple
- Use a DMA-safe buffer for spi_read().
renesas,isl29501
- Fix ordering issue for big endian systems
renesas,rsg2l
- Fix an underflow issue around suspend/resume.
- Make sure driver data is in place before enabling runtime PM that uses
  it.
rohm,bd79124
- Add missing GPIOLIB dependency.  May rework in future to allow this to be
  optional in future but for now this is the least invasive build fix.

* tag 'iio-fixes-for-6.17a' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/jic23/iio:
  iio: pressure: bmp280: Use IS_ERR() in bmp280_common_probe()
  iio: light: as73211: Ensure buffer holes are zeroed
  iio: adc: rzg2l_adc: Set driver data before enabling runtime PM
  iio: adc: rzg2l: Cleanup suspend/resume path
  iio: adc: ad7380: fix missing max_conversion_rate_hz on adaq4381-4
  iio: adc: bd79124: Add GPIOLIB dependency
  iio: imu: inv_icm42600: change invalid data error to -EBUSY
  iio: adc: ad7124: fix channel lookup in syscalib functions
  iio: temperature: maxim_thermocouple: use DMA-safe buffer for spi_read()
  iio: adc: ad7173: prevent scan if too many setups requested
  iio: proximity: isl29501: fix buffered read on big-endian systems
  iio: accel: sca3300: fix uninitialized iio scan data
This commit is contained in:
Greg Kroah-Hartman
2025-08-20 11:05:00 +02:00
11 changed files with 132 additions and 64 deletions

View File

@@ -477,7 +477,7 @@ static irqreturn_t sca3300_trigger_handler(int irq, void *p)
struct iio_dev *indio_dev = pf->indio_dev;
struct sca3300_data *data = iio_priv(indio_dev);
int bit, ret, val, i = 0;
IIO_DECLARE_BUFFER_WITH_TS(s16, channels, SCA3300_SCAN_MAX);
IIO_DECLARE_BUFFER_WITH_TS(s16, channels, SCA3300_SCAN_MAX) = { };
iio_for_each_active_channel(indio_dev, bit) {
ret = sca3300_read_reg(data, indio_dev->channels[bit].address, &val);

View File

@@ -1300,7 +1300,7 @@ config RN5T618_ADC
config ROHM_BD79124
tristate "Rohm BD79124 ADC driver"
depends on I2C
depends on I2C && GPIOLIB
select REGMAP_I2C
select IIO_ADC_HELPER
help

View File

@@ -849,7 +849,7 @@ enum {
static int ad7124_syscalib_locked(struct ad7124_state *st, const struct iio_chan_spec *chan)
{
struct device *dev = &st->sd.spi->dev;
struct ad7124_channel *ch = &st->channels[chan->channel];
struct ad7124_channel *ch = &st->channels[chan->address];
int ret;
if (ch->syscalib_mode == AD7124_SYSCALIB_ZERO_SCALE) {
@@ -865,8 +865,8 @@ static int ad7124_syscalib_locked(struct ad7124_state *st, const struct iio_chan
if (ret < 0)
return ret;
dev_dbg(dev, "offset for channel %d after zero-scale calibration: 0x%x\n",
chan->channel, ch->cfg.calibration_offset);
dev_dbg(dev, "offset for channel %lu after zero-scale calibration: 0x%x\n",
chan->address, ch->cfg.calibration_offset);
} else {
ch->cfg.calibration_gain = st->gain_default;
@@ -880,8 +880,8 @@ static int ad7124_syscalib_locked(struct ad7124_state *st, const struct iio_chan
if (ret < 0)
return ret;
dev_dbg(dev, "gain for channel %d after full-scale calibration: 0x%x\n",
chan->channel, ch->cfg.calibration_gain);
dev_dbg(dev, "gain for channel %lu after full-scale calibration: 0x%x\n",
chan->address, ch->cfg.calibration_gain);
}
return 0;
@@ -924,7 +924,7 @@ static int ad7124_set_syscalib_mode(struct iio_dev *indio_dev,
{
struct ad7124_state *st = iio_priv(indio_dev);
st->channels[chan->channel].syscalib_mode = mode;
st->channels[chan->address].syscalib_mode = mode;
return 0;
}
@@ -934,7 +934,7 @@ static int ad7124_get_syscalib_mode(struct iio_dev *indio_dev,
{
struct ad7124_state *st = iio_priv(indio_dev);
return st->channels[chan->channel].syscalib_mode;
return st->channels[chan->address].syscalib_mode;
}
static const struct iio_enum ad7124_syscalib_mode_enum = {

View File

@@ -200,7 +200,7 @@ struct ad7173_channel_config {
/*
* Following fields are used to compare equality. If you
* make adaptations in it, you most likely also have to adapt
* ad7173_find_live_config(), too.
* ad7173_is_setup_equal(), too.
*/
struct_group(config_props,
bool bipolar;
@@ -561,12 +561,19 @@ static void ad7173_reset_usage_cnts(struct ad7173_state *st)
st->config_usage_counter = 0;
}
static struct ad7173_channel_config *
ad7173_find_live_config(struct ad7173_state *st, struct ad7173_channel_config *cfg)
/**
* ad7173_is_setup_equal - Compare two channel setups
* @cfg1: First channel configuration
* @cfg2: Second channel configuration
*
* Compares all configuration options that affect the registers connected to
* SETUP_SEL, namely CONFIGx, FILTERx, GAINx and OFFSETx.
*
* Returns: true if the setups are identical, false otherwise
*/
static bool ad7173_is_setup_equal(const struct ad7173_channel_config *cfg1,
const struct ad7173_channel_config *cfg2)
{
struct ad7173_channel_config *cfg_aux;
int i;
/*
* This is just to make sure that the comparison is adapted after
* struct ad7173_channel_config was changed.
@@ -579,14 +586,22 @@ ad7173_find_live_config(struct ad7173_state *st, struct ad7173_channel_config *c
u8 ref_sel;
}));
return cfg1->bipolar == cfg2->bipolar &&
cfg1->input_buf == cfg2->input_buf &&
cfg1->odr == cfg2->odr &&
cfg1->ref_sel == cfg2->ref_sel;
}
static struct ad7173_channel_config *
ad7173_find_live_config(struct ad7173_state *st, struct ad7173_channel_config *cfg)
{
struct ad7173_channel_config *cfg_aux;
int i;
for (i = 0; i < st->num_channels; i++) {
cfg_aux = &st->channels[i].cfg;
if (cfg_aux->live &&
cfg->bipolar == cfg_aux->bipolar &&
cfg->input_buf == cfg_aux->input_buf &&
cfg->odr == cfg_aux->odr &&
cfg->ref_sel == cfg_aux->ref_sel)
if (cfg_aux->live && ad7173_is_setup_equal(cfg, cfg_aux))
return cfg_aux;
}
return NULL;
@@ -1228,7 +1243,7 @@ static int ad7173_update_scan_mode(struct iio_dev *indio_dev,
const unsigned long *scan_mask)
{
struct ad7173_state *st = iio_priv(indio_dev);
int i, ret;
int i, j, k, ret;
for (i = 0; i < indio_dev->num_channels; i++) {
if (test_bit(i, scan_mask))
@@ -1239,6 +1254,54 @@ static int ad7173_update_scan_mode(struct iio_dev *indio_dev,
return ret;
}
/*
* On some chips, there are more channels that setups, so if there were
* more unique setups requested than the number of available slots,
* ad7173_set_channel() will have written over some of the slots. We
* can detect this by making sure each assigned cfg_slot matches the
* requested configuration. If it doesn't, we know that the slot was
* overwritten by a different channel.
*/
for_each_set_bit(i, scan_mask, indio_dev->num_channels) {
const struct ad7173_channel_config *cfg1, *cfg2;
cfg1 = &st->channels[i].cfg;
for_each_set_bit(j, scan_mask, indio_dev->num_channels) {
cfg2 = &st->channels[j].cfg;
/*
* Only compare configs that are assigned to the same
* SETUP_SEL slot and don't compare channel to itself.
*/
if (i == j || cfg1->cfg_slot != cfg2->cfg_slot)
continue;
/*
* If we find two different configs trying to use the
* same SETUP_SEL slot, then we know that the that we
* have too many unique configurations requested for
* the available slots and at least one was overwritten.
*/
if (!ad7173_is_setup_equal(cfg1, cfg2)) {
/*
* At this point, there isn't a way to tell
* which setups are actually programmed in the
* ADC anymore, so we could read them back to
* see, but it is simpler to just turn off all
* of the live flags so that everything gets
* reprogramed on the next attempt read a sample.
*/
for (k = 0; k < st->num_channels; k++)
st->channels[k].cfg.live = false;
dev_err(&st->sd.spi->dev,
"Too many unique channel configurations requested for scan\n");
return -EINVAL;
}
}
}
return 0;
}

View File

@@ -873,6 +873,7 @@ static const struct ad7380_chip_info adaq4381_4_chip_info = {
.has_hardware_gain = true,
.available_scan_masks = ad7380_4_channel_scan_masks,
.timing_specs = &ad7380_4_timing,
.max_conversion_rate_hz = 4 * MEGA,
};
static const struct spi_offload_config ad7380_offload_config = {

View File

@@ -89,7 +89,6 @@ struct rzg2l_adc {
struct completion completion;
struct mutex lock;
u16 last_val[RZG2L_ADC_MAX_CHANNELS];
bool was_rpm_active;
};
/**
@@ -428,6 +427,8 @@ static int rzg2l_adc_probe(struct platform_device *pdev)
if (!indio_dev)
return -ENOMEM;
platform_set_drvdata(pdev, indio_dev);
adc = iio_priv(indio_dev);
adc->hw_params = device_get_match_data(dev);
@@ -460,8 +461,6 @@ static int rzg2l_adc_probe(struct platform_device *pdev)
if (ret)
return ret;
platform_set_drvdata(pdev, indio_dev);
ret = rzg2l_adc_hw_init(dev, adc);
if (ret)
return dev_err_probe(&pdev->dev, ret,
@@ -541,14 +540,9 @@ static int rzg2l_adc_suspend(struct device *dev)
};
int ret;
if (pm_runtime_suspended(dev)) {
adc->was_rpm_active = false;
} else {
ret = pm_runtime_force_suspend(dev);
if (ret)
return ret;
adc->was_rpm_active = true;
}
ret = pm_runtime_force_suspend(dev);
if (ret)
return ret;
ret = reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
if (ret)
@@ -557,9 +551,7 @@ static int rzg2l_adc_suspend(struct device *dev)
return 0;
rpm_restore:
if (adc->was_rpm_active)
pm_runtime_force_resume(dev);
pm_runtime_force_resume(dev);
return ret;
}
@@ -577,11 +569,9 @@ static int rzg2l_adc_resume(struct device *dev)
if (ret)
return ret;
if (adc->was_rpm_active) {
ret = pm_runtime_force_resume(dev);
if (ret)
goto resets_restore;
}
ret = pm_runtime_force_resume(dev);
if (ret)
goto resets_restore;
ret = rzg2l_adc_hw_init(dev, adc);
if (ret)
@@ -590,10 +580,7 @@ static int rzg2l_adc_resume(struct device *dev)
return 0;
rpm_restore:
if (adc->was_rpm_active) {
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
}
pm_runtime_force_suspend(dev);
resets_restore:
reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
return ret;

View File

@@ -32,8 +32,12 @@ static int inv_icm42600_temp_read(struct inv_icm42600_state *st, s16 *temp)
goto exit;
*temp = (s16)be16_to_cpup(raw);
/*
* Temperature data is invalid if both accel and gyro are off.
* Return -EBUSY in this case.
*/
if (*temp == INV_ICM42600_DATA_INVALID)
ret = -EINVAL;
ret = -EBUSY;
exit:
mutex_unlock(&st->lock);

View File

@@ -639,7 +639,7 @@ static irqreturn_t as73211_trigger_handler(int irq __always_unused, void *p)
struct {
__le16 chan[4];
aligned_s64 ts;
} scan;
} scan = { };
int data_result, ret;
mutex_lock(&data->mutex);

View File

@@ -3213,11 +3213,12 @@ int bmp280_common_probe(struct device *dev,
/* Bring chip out of reset if there is an assigned GPIO line */
gpiod = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(gpiod))
return dev_err_probe(dev, PTR_ERR(gpiod), "failed to get reset GPIO\n");
/* Deassert the signal */
if (gpiod) {
dev_info(dev, "release reset\n");
gpiod_set_value(gpiod, 0);
}
dev_info(dev, "release reset\n");
gpiod_set_value(gpiod, 0);
data->regmap = regmap;

View File

@@ -938,12 +938,18 @@ static irqreturn_t isl29501_trigger_handler(int irq, void *p)
struct iio_dev *indio_dev = pf->indio_dev;
struct isl29501_private *isl29501 = iio_priv(indio_dev);
const unsigned long *active_mask = indio_dev->active_scan_mask;
u32 buffer[4] __aligned(8) = {}; /* 1x16-bit + naturally aligned ts */
u32 value;
struct {
u16 data;
aligned_s64 ts;
} scan = { };
if (test_bit(ISL29501_DISTANCE_SCAN_INDEX, active_mask))
isl29501_register_read(isl29501, REG_DISTANCE, buffer);
if (test_bit(ISL29501_DISTANCE_SCAN_INDEX, active_mask)) {
isl29501_register_read(isl29501, REG_DISTANCE, &value);
scan.data = value;
}
iio_push_to_buffers_with_timestamp(indio_dev, buffer, pf->timestamp);
iio_push_to_buffers_with_timestamp(indio_dev, &scan, pf->timestamp);
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;

View File

@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/err.h>
#include <linux/spi/spi.h>
#include <linux/types.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger.h>
@@ -121,8 +122,15 @@ struct maxim_thermocouple_data {
struct spi_device *spi;
const struct maxim_thermocouple_chip *chip;
char tc_type;
u8 buffer[16] __aligned(IIO_DMA_MINALIGN);
/* Buffer for reading up to 2 hardware channels. */
struct {
union {
__be16 raw16;
__be32 raw32;
__be16 raw[2];
};
aligned_s64 timestamp;
} buffer __aligned(IIO_DMA_MINALIGN);
};
static int maxim_thermocouple_read(struct maxim_thermocouple_data *data,
@@ -130,18 +138,16 @@ static int maxim_thermocouple_read(struct maxim_thermocouple_data *data,
{
unsigned int storage_bytes = data->chip->read_size;
unsigned int shift = chan->scan_type.shift + (chan->address * 8);
__be16 buf16;
__be32 buf32;
int ret;
switch (storage_bytes) {
case 2:
ret = spi_read(data->spi, (void *)&buf16, storage_bytes);
*val = be16_to_cpu(buf16);
ret = spi_read(data->spi, &data->buffer.raw16, storage_bytes);
*val = be16_to_cpu(data->buffer.raw16);
break;
case 4:
ret = spi_read(data->spi, (void *)&buf32, storage_bytes);
*val = be32_to_cpu(buf32);
ret = spi_read(data->spi, &data->buffer.raw32, storage_bytes);
*val = be32_to_cpu(data->buffer.raw32);
break;
default:
ret = -EINVAL;
@@ -166,9 +172,9 @@ static irqreturn_t maxim_thermocouple_trigger_handler(int irq, void *private)
struct maxim_thermocouple_data *data = iio_priv(indio_dev);
int ret;
ret = spi_read(data->spi, data->buffer, data->chip->read_size);
ret = spi_read(data->spi, data->buffer.raw, data->chip->read_size);
if (!ret) {
iio_push_to_buffers_with_ts(indio_dev, data->buffer,
iio_push_to_buffers_with_ts(indio_dev, &data->buffer,
sizeof(data->buffer),
iio_get_time_ns(indio_dev));
}