All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.