Devicetree
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Kanak Shilledar" <kanak.shilledar@axis.com>
Cc: robh@kernel.org, conor+dt@kernel.org, devicetree@vger.kernel.org
Subject: Re: [PATCH v2 2/3] iio: accel: Add support for ICM42370P
Date: Thu, 13 Aug 2026 12:41:54 +0000	[thread overview]
Message-ID: <20260813124155.71B0B1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260813-b4-inv_icm42370p-v2-2-11aedfdf76d3@axis.com>

Thank you for your contribution! Sashiko AI review found 12 potential issue(s) to consider:
- [High] Accessing MREG registers mutates a global configuration struct and permanently overwrites the active device configuration without restoring it.
- [High] The required hardware stabilization delay is bypassed, leading to premature MREG register access.
- [High] ODR mapping arrays are inverted, misconfiguring sensor sampling frequencies.
- [High] Runtime PM setup exists without implementing dev_pm_ops callbacks.
- [High] Missing iio_device_claim_direct causes concurrency race on calibbias read.
- [Medium] Incorrect negative minimum calculation in calibbias bounds check rejects valid offsets.
- [Medium] Missing `.read_avail` callback breaks `_available` sysfs attributes.
- [Medium] Unbalanced pm_runtime_use_autosuspend leaks device reference.
- [Medium] MREG error paths fail to restore block selection register.
- [Medium] IRQ handler accesses hardware registers without PM runtime guard.
- [Medium] Endianness missing in IIO_TEMP scan_type definition (Speculative).
- [Medium] Lockless reads of `data->conf` fields in sysfs read handlers.
--

--- Patch [2]: [PATCH v2 2/3] iio: accel: Add support for ICM42370P ---
commit 4a22a747a5f16a585b80aa50c0ea6c3944149d0e
Author: Kanak Shilledar <kanak.shilledar@axis.com>
Subject: iio: accel: Add support for ICM42370P

This commit adds support for the Invensense ICM42370P MEMS MotionTracking
accelerometer over I2C. It implements raw reads, basic sysfs calibration
interfaces, and mandatory temperature sensor enablement.

> diff --git a/drivers/iio/accel/inv_icm42370.h b/drivers/iio/accel/inv_icm42370.h
> index 0000000000000..a4a822f04355f
> --- /dev/null
> +++ b/drivers/iio/accel/inv_icm42370.h
[ ... ]
> +#define INV_ICM42370_TEMP_CHAN(_index) \
> +	{								\
> +		.type = IIO_TEMP,					\
> +		.info_mask_separate =					\
> +			BIT(IIO_CHAN_INFO_RAW) |			\
> +			BIT(IIO_CHAN_INFO_OFFSET) |			\
> +			BIT(IIO_CHAN_INFO_SCALE),			\
> +		.scan_index = _index,					\
> +		.scan_type = {						\
> +			.sign = 's',					\
> +			.realbits = 16,					\
> +			.storagebits = 16,				\
> +		},							\
> +	}

[Severity: Medium]
Does this missing endianness definition cause issues on little-endian
architectures? The accelerometer channel specifies IIO_BE, but this
temperature channel omits it. Since the sensor outputs big-endian
data, userspace reading the temperature from the IIO buffer might
decode mangled values.

> diff --git a/drivers/iio/accel/inv_icm42370_core.c b/drivers/iio/accel/inv_icm42370_core.c
> index 0000000000000..6266362e83f6a
> --- /dev/null
> +++ b/drivers/iio/accel/inv_icm42370_core.c
[ ... ]
> +int inv_icm42370_mreg_write(struct inv_icm42370_data *data, u8 bank, u8 addr, u8 val)
> +{
> +	int ret;
> +	unsigned int sleep;
> +
> +	/* set default conf to ensure mreg access */
> +	ret = inv_icm42370_set_accel_conf(data, &inv_icm42370_default_conf, &sleep);
> +	if (ret)
> +		return ret;
> +
> +	ret = inv_icm42370_mreg_check(data->map);
> +	if (ret)
> +		return ret;
> +
> +	ret = regmap_write(data->map, INV_ICM42370_REG_BLK_SEL_W, bank);
> +	if (ret)
> +		return -EINVAL;
> +
> +	ret = regmap_write(data->map, INV_ICM42370_REG_MADDR_W, addr);
> +	if (ret)
> +		return -EINVAL;
> +
> +	ret = regmap_write(data->map, INV_ICM42370_REG_M_W, val);
> +	if (ret)
> +		return -EINVAL;
> +
> +	fsleep(10);
> +	return regmap_write(data->map, INV_ICM42370_REG_BLK_SEL_W, 0x00);
> +}

[Severity: Medium]
If regmap_write fails at INV_ICM42370_REG_MADDR_W or
INV_ICM42370_REG_M_W, the function returns immediately. Does this leave
the hardware bank selection permanently altered since we never write
0x00 to INV_ICM42370_REG_BLK_SEL_W on the error paths? This might cause
subsequent normal data reads to fetch garbage from the wrong bank.

[ ... ]
> +int inv_icm42370_mreg_read(struct inv_icm42370_data *data, u8 bank, u8 addr, u8 *val)
> +{
> +	int ret;
> +	unsigned int sleep, read_val;
> +
> +	/* set default conf to ensure mreg access */
> +	ret = inv_icm42370_set_accel_conf(data, &inv_icm42370_default_conf, &sleep);
> +	if (ret)
> +		return ret;
> +
> +	ret = inv_icm42370_mreg_check(data->map);

[Severity: High]
Is it intentional to pass the global inv_icm42370_default_conf struct
directly to inv_icm42370_set_accel_conf()?

Looking at inv_icm42370_set_accel_conf(), it mutates the passed
configuration:

oldconf->fs = conf->fs;
oldconf->odr = conf->odr;

This will permanently overwrite the active device configuration in
data->conf and mutate the shared global struct.

[Severity: High]
Additionally, inv_icm42370_set_accel_conf() populates the sleep
variable with the required hardware stabilization time, but the code
proceeds directly to inv_icm42370_mreg_check() without actually
sleeping. Can this cause hardware communication failures due to
bypassing the startup delay?

[ ... ]
> +static irqreturn_t inv_icm42370_irq_handler(int irq, void *_data)
> +{
> +	struct inv_icm42370_data *data = _data;
> +	unsigned int status;
> +	int ret;
> +
> +	guard(mutex)(&data->lock);
> +
> +	ret = regmap_read(data->map, INV_ICM42370_REG_INT_STATUS, &status);

[Severity: Medium]
Should this interrupt handler use pm_runtime_get_if_active() before
accessing the hardware? If a spurious interrupt fires while the device
is in a runtime-suspended state, attempting to read
INV_ICM42370_REG_INT_STATUS without waking the hardware could lead to
I2C bus transfer errors.

[ ... ]
> +static int inv_icm42370_accel_write_offset(struct inv_icm42370_data *data,
> +					   struct iio_chan_spec const *chan,
> +					   int val, int val2)
> +{
> +	struct device *dev = regmap_get_device(data->map);
> +	s64 val64;
> +	s32 min, max;
> +	u8 regval;
> +	s16 offset;
> +	int ret;
> +
> +	if (chan->type != IIO_ACCEL)
> +		return -EINVAL;
> +
> +	/* inv_icm42370_accel_calibbias: min - step - max in micro */
> +	min = inv_icm42370_accel_calibbias[0] * (long)MEGA +
> +	      inv_icm42370_accel_calibbias[1];
> +	max = inv_icm42370_accel_calibbias[4] * (long)MEGA +
> +	      inv_icm42370_accel_calibbias[5];

[Severity: Medium]
Is the calculation for the negative minimum boundary correct here?
Because inv_icm42370_accel_calibbias[0] is negative (-10), adding the
fractional part (42010) instead of subtracting it raises the minimum
floor (e.g., -9957990 instead of -10042010). Will this reject valid
extreme negative calibration offsets?

[ ... ]
> +static int inv_icm42370_accel_read_scale(struct iio_dev *indio_dev, int *val,
> +					 int *val2)
> +{
> +	struct inv_icm42370_data *data = iio_priv(indio_dev);
> +	unsigned int idx;
> +
> +	idx = data->conf.fs;

[Severity: Medium]
Should data->lock be held when reading data->conf.fs here and
data->conf.odr in inv_icm42370_accel_read_odr()? Concurrently writing
to the scale or sampling frequency sysfs nodes might result in stale
reads or data races.

[ ... ]
> +static int inv_icm42370_accel_write_odr(struct iio_dev *indio_dev, int val,
> +					int val2)
> +{
> +	struct inv_icm42370_data *data = iio_priv(indio_dev);
> +	struct inv_sensors_timestamp *ts = &data->ts;
> +	struct device *dev = regmap_get_device(data->map);
> +	unsigned int idx;
> +	struct inv_icm42370_conf conf = INV_ICM42370_SENSOR_CONF_INIT;
> +	int ret;
> +
> +	for (idx = 0; idx < ARRAY_SIZE(inv_icm42370_accel_odr); idx += 2) {
> +		if (val == inv_icm42370_accel_odr[idx] &&
> +		    val2 == inv_icm42370_accel_odr[idx + 1])
> +			break;
> +	}
> +	if (idx >= ARRAY_SIZE(inv_icm42370_accel_odr))
> +		return -EINVAL;
> +
> +	conf.odr = inv_icm42370_accel_odr_conv[idx / 2];

[Severity: High]
Can this map the wrong frequency to the sensor? The
inv_icm42370_accel_odr array defines frequencies in ascending order,
but inv_icm42370_accel_odr_conv maps the hardware enums in descending
order. Requesting 1.5625 Hz uses index 0, which appears to configure
the hardware to 1.6 kHz.

[ ... ]
> +static int inv_icm42370_accel_read_raw(struct iio_dev *indio_dev,
> +				       struct iio_chan_spec const *chan,
> +				       int *val, int *val2, long mask)
> +{
> +	struct inv_icm42370_data *data = iio_priv(indio_dev);
> +	s16 value;
> +	int ret;
> +
> +	switch (chan->type) {
> +	case IIO_ACCEL:
> +		break;
> +
> +	case IIO_TEMP:
> +		return inv_icm42370_temp_read_raw(indio_dev, chan, val, val2, mask);
> +
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_RAW:
> +		if (!iio_device_claim_direct(indio_dev))
> +			return -EBUSY;
> +
> +		ret = inv_icm42370_accel_read_sensor(indio_dev, chan, &value);
> +		iio_device_release_direct(indio_dev);
> +		if (ret)
> +			return ret;
> +
> +		*val = value;
> +		return IIO_VAL_INT;
> +
> +	case IIO_CHAN_INFO_SCALE:
> +		return inv_icm42370_accel_read_scale(indio_dev, val, val2);
> +
> +	case IIO_CHAN_INFO_SAMP_FREQ:
> +		return inv_icm42370_accel_read_odr(data, val, val2);
> +
> +	case IIO_CHAN_INFO_CALIBBIAS:
> +		return inv_icm42370_accel_read_offset(data, chan, val, val2);

[Severity: High]
Should iio_device_claim_direct() be called before reading the
calibration bias? The MREG reads underneath
inv_icm42370_accel_read_offset() silently alter the hardware's scale
and ODR settings. If this happens while the IIO buffer is actively
streaming, it could disrupt the active sampling state.

[ ... ]
> +static const struct iio_info inv_icm42370_info = {
> +	.read_raw = inv_icm42370_accel_read_raw,
> +	.write_raw = inv_icm42370_accel_write_raw,
> +};

[Severity: Medium]
Does this missing .read_avail callback break the _available sysfs
attributes? The channel definitions set
info_mask_shared_by_type_available and
info_mask_shared_by_all_available, which causes the IIO core to expose
those sysfs entries. Without a callback, reads will unconditionally
return -EINVAL.

[ ... ]
> +	/* setup runtime power management */
> +	ret = devm_pm_runtime_set_active_enabled(dev);
> +	if (ret)
> +		return ret;
> +
> +	pm_runtime_set_autosuspend_delay(dev, INV_ICM42370_SUSPEND_DELAY_MS);
> +	pm_runtime_use_autosuspend(dev);
> +
> +	ret = devm_iio_device_register(dev, indio_dev);

[Severity: Medium]
Is there a missing cleanup action for pm_runtime_use_autosuspend(dev)?
If the driver is unbound or the probe fails after this point, the
device will remain marked for autosuspend indefinitely, leaving an
unbalanced usage counter.

> diff --git a/drivers/iio/accel/inv_icm42370_i2c.c b/drivers/iio/accel/inv_icm42370_i2c.c
> index 0000000000000..c4533671051c4
> --- /dev/null
> +++ b/drivers/iio/accel/inv_icm42370_i2c.c
[ ... ]
> +static struct i2c_driver inv_icm42370_driver = {
> +	.driver = {
> +		.name = "inv-icm42370-i2c",
> +		.of_match_table = inv_icm42370_of_matches,
> +	},
> +	.probe = inv_icm42370_probe,
> +	.id_table = inv_icm42370_id,
> +};

[Severity: High]
The core probe enables runtime PM and autosuspend, but this I2C driver
structure lacks a .pm operations pointer. Without assigning dev_pm_ops
and implementing runtime_suspend, does the hardware ever actually
power down when idle?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260813-b4-inv_icm42370p-v2-0-11aedfdf76d3@axis.com?part=2

  reply	other threads:[~2026-08-13 12:41 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-13 12:26 [PATCH v2 0/3] Add driver for Invensense ICM42370P accelerometer Kanak Shilledar
2026-08-13 12:26 ` [PATCH v2 1/3] dt-bindings: Add InvenSense ICM-42370-p accelerometer Kanak Shilledar
2026-08-13 12:34   ` sashiko-bot
2026-08-13 12:26 ` [PATCH v2 2/3] iio: accel: Add support for ICM42370P Kanak Shilledar
2026-08-13 12:41   ` sashiko-bot [this message]
2026-08-13 12:26 ` [PATCH v2 3/3] iio: accel: icm42370: Add FIFO buffer functionality Kanak Shilledar
2026-08-13 12:40   ` sashiko-bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260813124155.71B0B1F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=kanak.shilledar@axis.com \
    --cc=robh@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox