All of lore.kernel.org
 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 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.