From: "Javier Carrasco" <javier.carrasco.cruz@gmail.com>
To: <sashiko-reviews@lists.linux.dev>,
"Javier Carrasco" <javier.carrasco.cruz@gmail.com>,
"Jonathan Cameron" <jic23@kernel.org>
Cc: <linux-kernel@vger.kernel.org>, <linux-iio@vger.kernel.org>
Subject: Re: [PATCH v4 4/4] iio: light: veml6031x00: add support for events and trigger
Date: Mon, 01 Jun 2026 12:01:10 +0200 [thread overview]
Message-ID: <DIXMJH3581S0.5DHXMLATTOV1@gmail.com> (raw)
In-Reply-To: <20260531204345.1C2A41F00893@smtp.kernel.org>
My view about the issues Sashiko reported.
On Sun May 31, 2026 at 10:43 PM CEST, sashiko-bot wrote:
> Thank you for your contribution! Sashiko AI review found 7 potential issue(s) to consider:
>
> New issues:
> - [High] Missing `.validate_device` in trigger operations allows other devices to attach to a sensor-specific trigger.
Tested with no real issues, but the trigger is mean for this device
only.
> - [High] The trigger handler performs an unintended I2C read from address 0 for the software timestamp channel.
Not a real issue.
> - [High] PM runtime usage count is leaked if the device is unbound while events are enabled.
The usage count is set to 0 by the devres action.
> - [High] Stale values in the regmap cache for the hardware-cleared `AF_TRIG` bit cause unintended triggers.
Real issue, I forgot to set CONF0 as a volatile register.
> - [Medium] Mixing `goto` error handling with `guard()` scope-based cleanup in the same function.
Not a real issue because the goto's happen after the guard, but it's easy to
get rid of them.
> - [Medium] Non-functional event sysfs attributes are exposed to userspace when the device lacks an IRQ.
Missing fix to be added to V5.
>
> Pre-existing issues:
> - [High] Unbalanced PM runtime usage counter due to mixing devm action with manual put.
Not a real issue because an underflow is not possible.
> --
>
> commit c0654b1fbfc516c85d27a7c169844b649c2a1077
> 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 facb1b8e42418..5e79eb942f09c 100644
>> --- a/drivers/iio/light/veml6031x00.c
>> +++ b/drivers/iio/light/veml6031x00.c
>
> [ ... ]
>
>> @@ -144,6 +197,8 @@ static const struct iio_chan_spec veml6031x00_channels[] = {
>> .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
>> .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME),
>> .info_mask_separate_available = BIT(IIO_CHAN_INFO_SCALE),
>> + .event_spec = veml6031x00_event_spec,
>> + .num_event_specs = ARRAY_SIZE(veml6031x00_event_spec),
>
> [Severity: Medium]
> Will this unconditionally expose event sysfs attributes even when the device
> lacks an IRQ?
>
> If i2c->irq is 0, the driver uses veml6031x00_info_no_irq to omit event
> callbacks. However, the IIO core checks num_event_specs during
> iio_check_for_dynamic_events() and creates sysfs attributes anyway. If these
> attributes are accessed from userspace without the callbacks, will they
> return -EINVAL?
>
This fix is also missing. I will add it to V5.
> [ ... ]
>
>> +static int veml6031x00_set_af_trig(struct veml6031x00_data *data, bool state)
>> +{
>> + regcache_drop_region(data->regmap, VEML6031X00_REG_CONF0,
>> + VEML6031X00_REG_CONF0);
>> +
>> + return regmap_update_bits(data->regmap, VEML6031X00_REG_CONF0,
>> + VEML6031X00_CONF0_AF_TRIG,
>> + FIELD_PREP(VEML6031X00_CONF0_AF_TRIG, state));
>> +}
>
> [Severity: High]
> Does this leave a stale AF_TRIG value in the non-volatile regmap cache?
>
> The AF_TRIG bit is cleared automatically by hardware. While this function
> drops the cache region before setting the bit, VEML6031X00_REG_CONF0 is not
> marked as volatile in veml6031x00_volatile_ranges. Because of this,
> regmap_update_bits() writes the new value to hardware and also caches it.
>
> Would any subsequent updates to CONF0 (such as changing AF or SD bits) read
> the cached AF_TRIG=1 and write it back, causing an unintended measurement
> trigger?
>
Absolutely right, I forgot to update this although I said I would do it.
> [ ... ]
>
>> +static int veml6031x00_write_event_config(struct iio_dev *iio,
>> + const struct iio_chan_spec *chan,
>> + enum iio_event_type type,
>> + enum iio_event_direction dir,
>> + bool state)
>> +{
>> + struct veml6031x00_data *data = iio_priv(iio);
>> + int ret;
>> +
>> + guard(mutex)(&data->irq_lock);
>> +
>> + /* avoid multiple increments/decrements from one source */
>> + if (state == data->ev_en)
>> + return 0;
>> +
>> + if (state) {
>> + ret = pm_runtime_resume_and_get(data->dev);
>> + if (ret)
>> + return ret;
>> + }
>
> [Severity: High]
> Is the PM runtime usage count leaked if the device is unbound while events
> are enabled?
>
> The pm_runtime_resume_and_get() call keeps the device powered on, but there
> does not appear to be a custom devres action or remove callback to disable
> the event and drop this reference if the driver is unbound. Could this
> prevent the parent I2C controller from ever entering runtime suspend?
>
The devres action that was registered in the probe function will
decrement the counter if the driver is unbound. I explained the
mechanism at the end of the mail.
> [ ... ]
>
>> +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));
>> + if (ret)
>> + goto err_disable_interrupt;
>> +
>> + ret = veml6031x00_set_af_trig(data, state);
>> + if (ret)
>> + goto err_clear_af;
>
> [Severity: Medium]
> Is it safe to mix goto-based error handling with guard() scope-based cleanup
> in this function?
>
> According to the cleanup subsystem guidelines, mixing goto with guard() or
> __free() in the same function can create confusing ownership semantics.
> Should this function either use goto entirely or be fully converted to
> scoped cleanups?
>
The real issue arises when there are goto calls before the cleanup, but
I think it is cleaner to get rid of all goto calls where cleanup magic
is used. I will remove them and add function calls and error return
in the error paths.
> [ ... ]
>
>> +static const struct iio_trigger_ops veml6031x00_trigger_ops = {
>> + .set_trigger_state = veml6031x00_set_trigger_state,
>> +};
>
> [Severity: High]
> Is a .validate_device callback needed here to prevent other devices from
> attaching to this sensor-specific trigger?
>
> Without setting .validate_device to iio_trigger_validate_own_device, another
> IIO device could attach to it. If that happens, veml6031x00_set_trigger_state()
> would enable the DRDY interrupt while the sensor is PM runtime suspended
> (since its own buffer_preenable isn't called). Would this cause the dependent
> device's buffer captures to hang?
>
This trigger is intented to be used by its own device. I will add
iio_trigger_validate_own_device to iio_trigger_ops.
> [ ... ]
>
>> +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);
>> + int ch, ret, i = 0;
>> + struct {
>> + __le16 chans[2];
>> + aligned_s64 timestamp;
>> + } scan = { };
>> +
>> + 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.chans, sizeof(scan.chans));
>> + if (ret)
>> + goto done;
>> + } else {
>> + iio_for_each_active_channel(iio, ch) {
>> + ret = regmap_bulk_read(data->regmap,
>> + iio->channels[ch].address,
>> + &scan.chans[i++],
>> + sizeof(*scan.chans));
>
> [Severity: High]
> Does this loop inadvertently perform an I2C read from address 0 for the
> software timestamp channel?
>
> When IIO_CHAN_SOFT_TIMESTAMP is active and the fast-path isn't taken, it
> iterates over all active channels. Since the timestamp channel does not define
> a hardware address, its .address is 0.
>
> Would regmap_bulk_read() read VEML6031X00_REG_CONF0 instead of data,
> wasting I2C bandwidth and writing the configuration register's value into
> the scan buffer just before the timestamp?
>
We have mentioned before that Sashiko is wrong about this. Is there any
way to tell Sashiko why this is ok?
> [ ... ]
>
>> @@ -677,12 +1102,21 @@ static int veml6031x00_probe(struct i2c_client *i2c)
>> iio->channels = veml6031x00_channels;
>> iio->num_channels = ARRAY_SIZE(veml6031x00_channels);
>> iio->modes = INDIO_DIRECT_MODE;
>>
>> ret = veml6031x00_hw_init(iio);
>> if (ret)
>> return ret;
>>
>> + if (i2c->irq) {
>> + ret = veml6031x00_setup_irq(i2c, iio);
>> + if (ret)
>> + return ret;
>> +
>> + iio->info = &veml6031x00_info;
>> + } else {
>> + iio->info = &veml6031x00_info_no_irq;
>> + }
>> +
>> ret = devm_iio_triggered_buffer_setup(dev, iio, NULL,
>> veml6031x00_trig_handler,
>> &veml6031x00_buffer_setup_ops);
>
> [Severity: High]
> This isn't a bug introduced by this patch, but is the PM runtime usage
> counter unbalanced at the end of veml6031x00_probe()?
>
> The driver acquires a reference using devm_pm_runtime_get_noresume() which
> associates a devres cleanup action. If pm_runtime_put_autosuspend() is
> called manually at the end of probe (immediately after this buffer setup),
> the devres cleanup will still fire when the device is unbound, performing a
> second put. Could this cause the PM runtime usage counter to underflow
> to -1?
This cannot happen because the devres action uses pm_runtime_put_noidle(),
which in turns uses atomic_add_unless(usage_count, -1, 0) to avoid
decrementing the usage_count if it is already 0.
Best regards,
Javier
next prev parent reply other threads:[~2026-06-01 10:01 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-31 19:58 [PATCH v4 0/4] iio: light: add support for veml6031x00 ALS series Javier Carrasco
2026-05-31 19:58 ` [PATCH v4 1/4] dt-bindings: iio: light: veml6030: add " Javier Carrasco
2026-05-31 19:58 ` [PATCH v4 2/4] iio: light: add support for " Javier Carrasco
2026-05-31 20:16 ` sashiko-bot
2026-06-01 10:21 ` Jonathan Cameron
2026-06-01 20:07 ` Javier Carrasco
2026-06-02 12:33 ` Jonathan Cameron
2026-06-02 17:54 ` Javier Carrasco
2026-06-02 10:01 ` Andy Shevchenko
2026-06-02 10:45 ` Javier Carrasco
2026-06-02 11:12 ` Andy Shevchenko
2026-06-02 11:21 ` Joshua Crofts
2026-06-02 11:35 ` Javier Carrasco
2026-06-02 11:47 ` Joshua Crofts
2026-06-02 12:22 ` Javier Carrasco
2026-06-02 12:33 ` Joshua Crofts
2026-06-02 12:34 ` Javier Carrasco
2026-06-03 11:02 ` Joshua Crofts
2026-06-02 11:42 ` Javier Carrasco
2026-06-02 11:44 ` Javier Carrasco
2026-06-02 12:38 ` Jonathan Cameron
2026-06-02 12:40 ` Javier Carrasco
2026-06-02 14:29 ` Jonathan Cameron
2026-06-02 14:33 ` Javier Carrasco
2026-05-31 19:58 ` [PATCH v4 3/4] iio: light: veml6031x00: add support for triggered buffers Javier Carrasco
2026-05-31 20:30 ` sashiko-bot
2026-06-01 10:26 ` Jonathan Cameron
2026-06-02 10:10 ` Andy Shevchenko
2026-05-31 19:58 ` [PATCH v4 4/4] iio: light: veml6031x00: add support for events and trigger Javier Carrasco
2026-05-31 20:43 ` sashiko-bot
2026-06-01 10:01 ` Javier Carrasco [this message]
2026-06-01 10:58 ` Jonathan Cameron
2026-06-01 10:47 ` Jonathan Cameron
2026-06-02 10:27 ` 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=DIXMJH3581S0.5DHXMLATTOV1@gmail.com \
--to=javier.carrasco.cruz@gmail.com \
--cc=jic23@kernel.org \
--cc=linux-iio@vger.kernel.org \
--cc=linux-kernel@vger.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.