Devicetree
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Nikhil Gautam" <nikhilgtr@gmail.com>
Cc: conor+dt@kernel.org, robh@kernel.org, krzk+dt@kernel.org,
	devicetree@vger.kernel.org
Subject: Re: [RFC PATCH 2/2] iio: magnetometer: add support for Melexis MLX90393
Date: Mon, 11 May 2026 22:13:51 +0000	[thread overview]
Message-ID: <20260511221352.4BBDCC2BCB0@smtp.kernel.org> (raw)
In-Reply-To: <20260510191010.155380-3-nikhilgtr@gmail.com>

Thank you for your contribution! Sashiko AI review found 9 potential issue(s) to consider:
- [High] Data race on static `scale_avail` array in `mlx90393_read_avail`
- [High] `mlx90393_check_status` unconditionally rejects valid full-sensor measurements
- [High] Stack-allocated buffers are passed to I2C transfer, violating DMA safety rules
- [High] Unprotected state reads in `mlx90393_read_raw` lead to data races
- [Medium] IIO ABI violation: Magnetometer and temperature scales use incorrect units
- [Medium] `mlx90393_write_raw` improperly allows modifying the magnetometer gain via the temperature scale attribute
- [Medium] Magnetometer scale is exported as separate attributes despite utilizing a global hardware register
- [Low] Temperature channel exposes internal hardware register values for oversampling ratios
- [Low] Incorrect use of `usleep_range` for delays exceeding 200ms
--

commit b098ee066ea285eea196aa30f9837e81df63b980
Author: Nikhil Gautam <nikhilgtr@gmail.com>

iio: magnetometer: add support for Melexis MLX90393

This commit adds Industrial I/O subsystem support for the Melexis MLX90393
3-axis magnetometer and temperature sensor.

> diff --git a/drivers/iio/magnetometer/mlx90393_core.c b/drivers/iio/magnetometer/mlx90393_core.c
> index 0000000000000..c79f2b8c20d8e
> --- /dev/null
> +++ b/drivers/iio/magnetometer/mlx90393_core.c

[ ... ]

> +static const int mlx90393_osr2_avail[MLX90393_OSR2_MAX] = {
> +	0, 1, 2, 3,
> +};

Is it intentional to expose internal hardware register index limits directly
to userspace instead of the actual physical oversampling ratios?

[ ... ]

> +#define MLX90393_CHAN(idx, axis, addr) { \
> +	.type = IIO_MAGN, \
> +	.modified = 1, \
> +	.channel = idx, \
> +	.address = addr, \
> +	.channel2 = IIO_MOD_##axis, \
> +	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |	\
> +		BIT(IIO_CHAN_INFO_SCALE), \

Does using info_mask_separate for IIO_CHAN_INFO_SCALE correctly represent
the hardware capabilities? Writing to the scale of one axis will alter the
global GAIN_SEL hardware register in mlx90393_set_scale(), altering the
scale for all axes.

[ ... ]

> +static int mlx90393_check_status(u8 cmd, u8 status)
> +{
> +	/* Always validate error bit */
> +	if (status & MLX90393_STATUS_ERROR)
> +		return -EIO;
> +
> +	switch (cmd & MLX90393_CMD_MASK) {
> +	case MLX90393_CMD_RM:
> +		/*
> +		 * D1:D0 indicates response availability
> +		 * 00 means invalid/no measurement
> +		 */
> +		if ((status & MLX90393_STATUS_RESP) == 0)
> +			return -EIO;

If MLX90393_MEASURE_ALL requests all 4 channels (T, X, Y, Z), resulting in
4 words, does the 2-bit D[1:0] field truncate this to 00? This check might
unconditionally reject valid full-sensor measurements and return -EIO.

[ ... ]

> +static int mlx90393_read_reg(struct mlx90393_data *data,
> +			     u8 reg, u16 *val)
> +{
> +	u8 tx[2];
> +	u8 rx[3];
> +	int ret;
> +
> +	tx[0] = MLX90393_CMD_RR;
> +	/* Register address is encoded in bits [7:2] */
> +	tx[1] = reg << 2;
> +
> +	ret = mlx90393_xfer(data,
> +			    tx, sizeof(tx),
> +			    rx, sizeof(rx));

Are these stack-allocated buffers DMA-safe?

When passed to ops->xfer which calls i2c_transfer(), this can lead to memory
corruption or panics if the host controller maps buffers for DMA (especially
with CONFIG_VMAP_STACK=y).

[ ... ]

> +static int mlx90393_read_measurement(struct mlx90393_data *data,
> +				     enum mlx90393_channels chan, int *val)
> +{
> +	u8 cmd;
> +	u8 rx[9];

Can this stack allocated buffer also cause DMA safety issues?

> +	int ret;
> +	int tconv_us = mlx90393_get_tconv_us(data);
> +
> +	/* Start measurement */
> +	cmd = MLX90393_CMD_SM | MLX90393_MEASURE_ALL;
> +
> +	ret = mlx90393_write_cmd(data, cmd);
> +	if (ret)
> +		return ret;
> +
> +	/* Wait conversion */
> +	usleep_range(tconv_us, tconv_us + 1000);

Depending on the configured oversampling ratio and digital filters, tconv_us
can exceed 200,000 microseconds. Is usleep_range() appropriate for delays
exceeding 20ms, or should msleep() be used here instead to avoid
unnecessarily taxing the hrtimer subsystem?

[ ... ]

> +static int mlx90393_get_scale(struct mlx90393_data *data,
> +			      const struct iio_chan_spec *chan,
> +			      int *val, int *val2)
> +{
> +	enum mlx90393_axis_type axis;
> +	u8 res;
> +
> +	if (chan->channel2 == IIO_MOD_Z) {
> +		axis = MLX90393_AXIS_TYPE_Z;
> +		res = data->res_z;
> +	} else {
> +		axis = MLX90393_AXIS_TYPE_XY;
> +		res = data->res_xy;
> +	}
> +
> +	/*
> +	 * Convert:
> +	 * µT × 1000 → nT
> +	 */
> +	*val = 0;
> +	*val2 = mlx90393_scale_table[axis][data->gain_sel][res];
> +
> +	return IIO_VAL_INT_PLUS_NANO;

Does this scale comply with the IIO ABI requirements? Returning
IIO_VAL_INT_PLUS_NANO with these values produces Tesla rather than the Gauss
units required for magnetometers.

[ ... ]

> +static int mlx90393_write_raw(struct iio_dev *indio_dev,
> +			      const struct iio_chan_spec *chan,
> +			      int val, int val2,
> +			      long mask)
> +{
> +	struct mlx90393_data *data = iio_priv(indio_dev);
> +	int ret;
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_SCALE:
> +		mutex_lock(&data->lock);
> +		ret = mlx90393_set_scale(data, chan, val, val2);
> +		mutex_unlock(&data->lock);
> +		return ret;

Does this safely handle writes to the temperature scale? 

The temperature channel exposes IIO_CHAN_INFO_SCALE, but mlx90393_set_scale()
modifies the GAIN_SEL hardware register, which might inadvertently corrupt the
magnetometer's sensitivity when a user writes to in_temp_scale.

[ ... ]

> +static int mlx90393_read_raw(struct iio_dev *indio_dev,
> +			     const struct iio_chan_spec *chan,
> +			     int *val, int *val2, long mask)
> +{
> +	struct mlx90393_data *data = iio_priv(indio_dev);
> +	int ret;
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_RAW:
> +		mutex_lock(&data->lock);
> +		ret = mlx90393_read_measurement(data, chan->address, val);
> +		mutex_unlock(&data->lock);
> +		if (ret)
> +			return ret;
> +
> +		return IIO_VAL_INT;
> +
> +	case IIO_CHAN_INFO_SCALE:
> +		switch (chan->type) {
> +		case IIO_MAGN:
> +			return mlx90393_get_scale(data, chan, val, val2);

Can this read race with concurrent sysfs writes? 

mlx90393_get_scale() reads shared state like data->gain_sel without acquiring
data->lock, while mlx90393_write_raw() modifies these fields while holding the
lock.

> +
> +		case IIO_TEMP:
> +			/* Datasheet: 22124 millidegC/LSB */
> +			*val = 0;
> +			*val2 = 22124;
> +			return IIO_VAL_INT_PLUS_MICRO;

Does returning IIO_VAL_INT_PLUS_MICRO with 22124 yield Celsius rather than
the milli-Celsius required for temperature channels by the IIO ABI?

> +
> +		default:
> +			return -EINVAL;
> +		}
> +
> +	case IIO_CHAN_INFO_OFFSET:
> +		if (chan->type == IIO_TEMP) {
> +			/* Datasheet: temperature offset */
> +			*val = -45114;
> +			return IIO_VAL_INT;
> +		}
> +		return -EINVAL;
> +
> +	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
> +		if (chan->type == IIO_TEMP)
> +			return mlx90393_get_temp_osr2(data, val);
> +		if (chan->type == IIO_MAGN)
> +			return mlx90393_get_osr(data, val);

Can these reads of data->osr and data->osr2 also race with concurrent sysfs
writes, as data->lock is not acquired here?

[ ... ]

> +static int mlx90393_read_avail(struct iio_dev *indio_dev,
> +			       const struct iio_chan_spec *chan,
> +			       const int **vals,
> +			       int *type,
> +			       int *length,
> +			       long mask)
> +{
> +	struct mlx90393_data *data = iio_priv(indio_dev);
> +
> +	static int scale_avail[MLX90393_GAIN_MAX][MLX90393_AXIS_MAX];
> +	enum mlx90393_axis_type axis;
> +	int i;
> +	u8 res;
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_SCALE:
> +		axis = chan->channel2 == IIO_MOD_Z;
> +		res = axis ? data->res_z : data->res_xy;
> +
> +		for (i = 0; i < MLX90393_GAIN_MAX; i++) {
> +			scale_avail[i][0] = 0;
> +			scale_avail[i][1] =
> +				mlx90393_scale_table[axis][i][res];
> +		}
> +
> +		*vals = &scale_avail[0][0];

Is it safe to use a global static array here?

Since scale_avail is dynamically populated based on the requested channel
axis, concurrent sysfs reads across different axes or device instances could
overwrite the array mid-operation, causing a data race and corrupted scale
values to be returned.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260510191010.155380-1-nikhilgtr@gmail.com?part=2

  parent reply	other threads:[~2026-05-11 22:13 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-10 19:10 [RFC PATCH 0/2] iio: magnetometer: add support for Melexis MLX90393 Nikhil Gautam
2026-05-10 19:10 ` [RFC PATCH 1/2] dt-bindings: iio: magnetometer: add " Nikhil Gautam
2026-05-11 13:56   ` Jonathan Cameron
2026-05-11 21:42   ` sashiko-bot
2026-05-10 19:10 ` [RFC PATCH 2/2] iio: magnetometer: add support for " Nikhil Gautam
2026-05-11 14:23   ` Jonathan Cameron
2026-05-11 22:13   ` sashiko-bot [this message]
2026-05-11 13:51 ` [RFC PATCH 0/2] " Jonathan Cameron

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=20260511221352.4BBDCC2BCB0@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=krzk+dt@kernel.org \
    --cc=nikhilgtr@gmail.com \
    --cc=robh@kernel.org \
    --cc=sashiko@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