All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Javier Carrasco" <javier.carrasco.cruz@gmail.com>
To: <sashiko-reviews@lists.linux.dev>,
	"Javier Carrasco" <javier.carrasco.cruz@gmail.com>
Cc: <robh@kernel.org>, <devicetree@vger.kernel.org>, <conor+dt@kernel.org>
Subject: Re: [PATCH v5 4/4] iio: light: veml6031x00: add support for events and trigger
Date: Sat, 08 Aug 2026 08:35:08 +0200	[thread overview]
Message-ID: <DKJCQRNBH477.3C9CC4KCFAMNK@gmail.com> (raw)
In-Reply-To: <20260807150823.49A101F000E9@smtp.kernel.org>

On Fri Aug 7, 2026 at 5:08 PM CEST, sashiko-bot wrote:
> Thank you for your contribution! Sashiko AI review found 7 potential issue(s) to consider:
> - [High] Unbalanced PM runtime usage counter causes an underflow on device unbind or probe error.
> - [High] Uninitialized padding in the local `scan` buffer leaks kernel stack memory to userspace.
> - [High] Spurious interrupts cause I2C reads while the device is runtime suspended.
> - [High] Initialization order and use-after-destroy race due to early IRQ/trigger registration.
> - [High] Triggered buffer is unconditionally registered on the no-IRQ path with a malformed channels array.
> - [Medium] Missing timestamp acquisition for nested trigger handler.
> - [Medium] Trigger disable sequence violates hardware constraints by clearing AF before AF_TRIG.
> --
>
> --- Patch [4]: [PATCH v5 4/4] iio: light: veml6031x00: add support for events and trigger ---
> commit aeccd415dcc79cfa9463cf8b5eec2292ee46dfab
> Author: Javier Carrasco <javier.carrasco.cruz@gmail.com>
>
> iio: light: veml6031x00: add support for events and trigger
>
> The device provides a shared interrupt line for to notify events and
> data ready, which can be used as a trigger. The interrupt line is not a
> requirement for the device to work. Implement variants for the cases
> whether the interrupt line is provided or not.
>
>> diff --git a/drivers/iio/light/veml6031x00.c b/drivers/iio/light/veml6031x00.c
>> index 0cccd40d729eb..e193f87e6740f 100644
>> --- a/drivers/iio/light/veml6031x00.c
>> +++ b/drivers/iio/light/veml6031x00.c
> [ ... ]
>> @@ -494,13 +686,205 @@ static int veml6031x00_write_raw_get_fmt(struct iio_dev *indio_dev,
> [ ... ]
>> +static irqreturn_t veml6031x00_interrupt(int irq, void *private)
>> +{
>> +	struct iio_dev *iio = private;
>> +	struct veml6031x00_data *data = iio_priv(iio);
>> +	s64 timestamp;
>> +	int regval, ret;
>> +	bool trigger_poll;
>> +
>> +	scoped_guard(mutex, &data->irq_lock) {
>> +		ret = regmap_read(data->regmap, VEML6031X00_REG_INT, &regval);
>
> [Severity: High]
> If a spurious interrupt fires while both ev_en and trig_en are false,
> could this unconditionally read from the I2C bus while the device is
> runtime suspended?
>
> It looks like this might hit a powered-off device since it doesn't
> use pm_runtime_get_if_active() or check software state before
> the register read.
>

The I2C interface stays accessible even while the device is powered down,
so this read doesn't fail or have side effects in case of a spurious
interrupt.

>> +		if (ret) {
>> +			dev_dbg(regmap_get_device(data->regmap),
>> +				"Failed to read interrupt register %d\n", ret);
>> +			return IRQ_NONE;
>> +		}
> [ ... ]
>> @@ -535,11 +919,78 @@ static int veml6031x00_buffer_postdisable(struct iio_dev *iio)
>>  	return 0;
>>  }
>>
>> +static int veml6031x00_set_trigger_state(struct iio_trigger *trig, bool state)
>> +{
>> +	struct iio_dev *iio = iio_trigger_get_drvdata(trig);
>> +	struct veml6031x00_data *data = iio_priv(iio);
>> +	int ret;
>> +
>> +	guard(mutex)(&data->irq_lock);
>> +
>> +	if (state == data->trig_en)
>> +		return 0;
>> +
>> +	ret = veml6031x00_set_interrupt(data, state);
>> +	if (ret)
>> +		return ret;
>> +
>> +	/* The AF bit must be set before setting AF_TRIG */
>> +	ret = regmap_update_bits(data->regmap, VEML6031X00_REG_CONF0,
>> +				 VEML6031X00_CONF0_AF,
>> +				 FIELD_PREP(VEML6031X00_CONF0_AF, state));
>
> [Severity: Medium]
> Since the AF bit must be set before setting AF_TRIG, does the
> disable sequence need to happen in reverse order?
>
> When state is false, this clears the AF bit first, creating a window
> where AF_TRIG is still active but AF is disabled.
>

Disabling AF is what actually turns off auto-force mode, so it should be
done in the current order.

>> +	if (ret) {
>> +		veml6031x00_set_interrupt(data, !state);
>> +
>> +		return ret;
>> +	}
>> +
>> +	ret = regmap_update_bits(data->regmap, VEML6031X00_REG_CONF0,
>> +				 VEML6031X00_CONF0_AF_TRIG,
>> +				 FIELD_PREP(VEML6031X00_CONF0_AF_TRIG, state));
> [ ... ]
>> +static irqreturn_t veml6031x00_trig_handler(int irq, void *p)
>> +{
>> +	struct iio_poll_func *pf = p;
>> +	struct iio_dev *iio = pf->indio_dev;
>> +	struct veml6031x00_data *data = iio_priv(iio);
>> +	IIO_DECLARE_BUFFER_WITH_TS(__le16, scan, 2);
>
> [Severity: High]
> Could this leak uninitialized kernel stack memory to userspace?
>
> The IIO_DECLARE_BUFFER_WITH_TS macro allocates the buffer on the stack
> without zeroing the padding bytes between the channel data and the
> timestamp.
>

Already addressed in the reply to Sashiko's feedback about [3/4].

>> +	unsigned int i = 0;
>> +	int ch, ret;
>> +
>> +	if (test_bit(VEML6031X00_SCAN_ALS, iio->active_scan_mask) &&
>> +	    test_bit(VEML6031X00_SCAN_IR, iio->active_scan_mask)) {
>> +		ret = regmap_bulk_read(data->regmap,
>> +				       VEML6031X00_REG_ALS_L,
>> +				       scan,
>> +				       2 * sizeof(*scan));
>> +		if (ret)
>> +			goto done;
>> +	} else {
>> +		iio_for_each_active_channel(iio, ch) {
>> +			ret = regmap_bulk_read(data->regmap,
>> +					       iio->channels[ch].address,
>> +					       &scan[i++],
>> +					       sizeof(*scan));
>> +			if (ret)
>> +				goto done;
>> +		}
>> +	}
>> +
>> +	iio_push_to_buffers_with_ts(iio, scan, sizeof(scan), pf->timestamp);
>
> [Severity: Medium]
> Since this trigger handler is executed synchronously from the interrupt
> handler via iio_trigger_poll_nested() bypassing the top-half
> iio_pollfunc_store_time(), will pf->timestamp always be zero here?
>

The timestamp is already captured in the interrupt handler. I will assign
it to pollfunc->timestamp before calling iio_trigger_poll_nested().

>> +
>> +done:
>> +	iio_trigger_notify_done(iio->trig);
>> +
>> +	return IRQ_HANDLED;
>> +}
> [ ... ]
>> @@ -636,15 +1142,29 @@ static int veml6031x00_probe(struct i2c_client *i2c)
>>  				     "Failed to set regmap\n");
>>
>>  	iio->name = data->chip->name;
>> -	iio->channels = veml6031x00_channels;
>> -	iio->num_channels = ARRAY_SIZE(veml6031x00_channels);
>>  	iio->modes = INDIO_DIRECT_MODE;
>> -	iio->info = &veml6031x00_info;
>> +	if (i2c->irq) {
>> +		iio->channels = veml6031x00_channels_irq;
>> +		iio->num_channels = ARRAY_SIZE(veml6031x00_channels_irq);
>> +		ret = veml6031x00_setup_irq(i2c, iio);
>
> [Severity: High]
> Does registering the IRQ and trigger here expose a race condition?
>
> veml6031x00_setup_irq() requests the threaded IRQ before devm_mutex_init()
> allocates data->irq_lock and veml6031x00_regfield_init() allocates
> data->rf.int_en. If an interrupt fires immediately, the handler will try
> to lock an uninitialized mutex.
>
> Additionally, since devres cleans up in reverse order, won't the mutex
> be destroyed before the IRQ is unregistered during unbind?
>

For V6: mutex_init and regfield_init moved before setup_irq().

>> +		if (ret)
>> +			return ret;
>> +
>> +		iio->info = &veml6031x00_info;
>> +	} else {
>> +		iio->channels = veml6031x00_channels;
>
> [Severity: High]
> If the device does not provide an interrupt, it falls back to
> veml6031x00_channels which lacks scan_index and scan_type definitions.
>
> Will setting up a triggered buffer unconditionally at the end of probe
> cause IIO core undefined behavior if a user attaches an external
> sysfs/hrtimer trigger, since both channels would default to a
> scan_index of 0 and 0 storage bits?
>

Already addressed in the reply to Sashiko's feedback about [3/4].

>> +		iio->num_channels = ARRAY_SIZE(veml6031x00_channels);
>> +		iio->info = &veml6031x00_info_no_irq;
>> +	}
>>
>>  	ret = devm_mutex_init(&i2c->dev, &data->scale_lock);
>>  	if (ret)
>>  		return ret;
>>
>> +	ret = devm_mutex_init(&i2c->dev, &data->irq_lock);
>> +	if (ret)
>> +		return ret;
>> +
>>  	ret = veml6031x00_regfield_init(data);
>>  	if (ret)
>>  		return dev_err_probe(&i2c->dev, ret, "Failed to init regfield\n");
>> @@ -672,6 +1192,12 @@ static int veml6031x00_probe(struct i2c_client *i2c)
>>  	if (ret)
>>  		return dev_err_probe(&i2c->dev, ret, "Failed to get runtime PM\n");
>>
>
> [Severity: High]
> Could the devm_pm_runtime_get_noresume() call just above this hunk cause
> a usage counter underflow?
>
> The devres action will eventually call pm_runtime_put_noidle() during
> driver unbind. However, the driver also manually calls
> pm_runtime_put_autosuspend() at the end of veml6031x00_probe() to drop
> the initial reference.
>
> This double-put could underflow the usage counter to -1 and corrupt
> device power management. If the driver manually manages the initial
> reference, should it use the non-devm pm_runtime_get_noresume() variant?
>

Already addressed in the reply to Sashiko's feedback about [3/4].


Best regards,
Javier

  reply	other threads:[~2026-08-08  6:35 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-07 13:51 [PATCH v5 0/4] iio: light: add support for veml6031x00 ALS series Javier Carrasco
2026-08-07 13:51 ` [PATCH v5 1/4] dt-bindings: iio: light: veml6030: add " Javier Carrasco
2026-08-07 14:06   ` sashiko-bot
2026-08-07 14:34     ` Javier Carrasco
2026-08-07 15:33   ` Rob Herring (Arm)
2026-08-10  6:23   ` Krzysztof Kozlowski
2026-08-10  7:23     ` Javier Carrasco
2026-08-07 13:51 ` [PATCH v5 2/4] iio: light: add support for " Javier Carrasco
2026-08-07 14:19   ` sashiko-bot
2026-08-07 14:53     ` Javier Carrasco
2026-08-07 21:02   ` Uwe Kleine-König
2026-08-10 13:38   ` Andy Shevchenko
2026-08-10 23:06     ` Javier Carrasco
2026-08-11  5:40       ` Andy Shevchenko
2026-08-07 13:51 ` [PATCH v5 3/4] iio: light: veml6031x00: add support for triggered buffers Javier Carrasco
2026-08-07 14:49   ` sashiko-bot
2026-08-07 20:33     ` Javier Carrasco
2026-08-07 13:51 ` [PATCH v5 4/4] iio: light: veml6031x00: add support for events and trigger Javier Carrasco
2026-08-07 15:08   ` sashiko-bot
2026-08-08  6:35     ` Javier Carrasco [this message]
2026-08-10 15:32   ` Andy Shevchenko
2026-08-10 23:09     ` Javier Carrasco
2026-08-11  5:42       ` Andy Shevchenko

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=DKJCQRNBH477.3C9CC4KCFAMNK@gmail.com \
    --to=javier.carrasco.cruz@gmail.com \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --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.