Devicetree
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Alexandre Hamamdjian via B4 Relay"
	<devnull+azkali.limited.gmail.com@kernel.org>
Cc: krzk+dt@kernel.org, devicetree@vger.kernel.org,
	conor+dt@kernel.org, robh@kernel.org
Subject: Re: [PATCH 2/2] iio: light: bh1730: Add bh1730 light sensor driver
Date: Mon, 11 May 2026 22:09:42 +0000	[thread overview]
Message-ID: <20260511220942.B824EC2BCF5@smtp.kernel.org> (raw)
In-Reply-To: <20260511-bh1730-v1-2-e0df1f499135@gmail.com>

Thank you for your contribution! Sashiko AI review found 9 potential issue(s) to consider:
- [High] Global shared state breaks power management for multiple devices.
- [High] Regulator resource leak and probe deferral mishandling.
- [High] Unsigned integer underflow in lux calculation causes erroneous maximum brightness readings.
- [High] Missing mutex protecting concurrent IIO sysfs reads causes race conditions.
- [High] Probe error path leaves the device powered on.
- [High] Unbalanced regulator enable counts in error handling paths.
- [Medium] Incorrect I2C functionality check in probe.
- [Medium] RAW IIO channel violates ABI by returning scaled fractional values.
- [Medium] Missing integration-time tracking logic as claimed in the commit message.
--

commit 92646ec6b1c5614b002c3fd3629112d1e7719033
Author: CTCaer <ctcaer@gmail.com>

iio: light: bh1730: Add bh1730 light sensor driver

Add a driver for the ROHM BH1730FVC ambient light sensor with runtime gain
tracking and configurable integration time.

>    The driver exposes illuminance via IIO, performs runtime gain and
>    integration-time tracking to keep the ADC in range, and supports

This isn't a bug, but the commit message mentions runtime integration-time
tracking. While runtime gain tracking is implemented in bh1730_adjust_gain(),
is there equivalent runtime logic to track or adjust the integration time,
or is it only configured once during bh1730_init_config()?

> diff --git a/drivers/iio/light/bh1730.c b/drivers/iio/light/bh1730.c
> new file mode 100644
> index 0000000000000..c93290ff5661f
> --- /dev/null
> +++ b/drivers/iio/light/bh1730.c
> @@ -0,0 +1,686 @@
[ ... ]
> +static int bh1730_get_lux(struct bh1730_data *bh1730)
> +{
[ ... ]
> +	/* Calibrate based on optical window */
> +	for (i = 0; i < bh1730->cal.opt_win_coeff_count; i++) {
> +		opt_win_coeff = &bh1730->cal.opt_win_coeff[i];
> +		if (1000 * ir / visible < opt_win_coeff->rc) {
> +			lux = ((u64)opt_win_coeff->cv * visible) -
> +				   (opt_win_coeff->ci * ir);
> +			break;
> +		}
> +	}
> +
> +	/* Calculate lux */
> +	lux *= BH1730_DEFAULT_ITIME_MS;
> +	lux /= bh1730_gain_multiplier(bh1730) * bh1730->itime_us;
> +	lux = (lux * bh1730->cal.mul) / 1000;
> +
> +	if (lux > BH1730_MAX_MEASURED_LUX)
> +		lux = BH1730_MAX_MEASURED_LUX;
> +
> +	return (int)lux;
> +}

Can the subtraction underflow if the infrared component (ci * ir) is greater
than the visible component (cv * visible)? Since lux is an unsigned 64-bit
integer, this could result in a massive positive number.

The subsequent clamping logic would then set lux to
BH1730_MAX_MEASURED_LUX (100,000). Would this cause the sensor to report
maximum brightness instead of 0 lux in environments where IR light dominates?

[ ... ]
> +static int bh1730_power_ctrl(struct bh1730_data *bh1730, bool enable)
> +{
> +	struct device *dev = &bh1730->client->dev;
> +	static bool enabled;
> +	int ret = 0;
> +
> +	if (enabled == enable)
> +		return ret;

Will this global static variable break power management for multiple devices?

If a system contains multiple BH1730 sensors, powering on the first sensor sets
enabled = true. When the second sensor attempts to power on during probe,
would the enabled == enable check evaluate to true and return immediately
without enabling the regulators for the second device?

> +	if (enable) {
> +		if (!IS_ERR_OR_NULL(bh1730->reg_vdd)) {
> +			ret = regulator_enable(bh1730->reg_vdd);
> +			if (ret) {
> +				dev_err(dev, "%s: Failed to enable vdd: %d\n",
> +					__func__, ret);
> +				return ret;
> +			}
> +		}
> +
> +		if (!IS_ERR_OR_NULL(bh1730->reg_vid)) {
> +			ret = regulator_enable(bh1730->reg_vid);
> +			if (ret) {
> +				dev_err(dev, "%s: Failed to enable vid: %d\n",
> +					__func__, ret);
> +				return ret;
> +			}
> +		}

If regulator_enable(bh1730->reg_vdd) succeeds but the subsequent
regulator_enable(bh1730->reg_vid) fails, will this return without
disabling the vdd regulator and leave an unbalanced enable count?

[ ... ]
> +static int bh1730_power_off(struct bh1730_data *bh1730)
> +{
> +	int ret = bh1730_write(bh1730, BH1730_REG_CONTROL, 0);
> +
> +	if (ret < 0)
> +		return ret;
> +
> +	return bh1730_power_ctrl(bh1730, false);
> +}

If the initial I2C write fails here, the function returns early without calling
bh1730_power_ctrl(..., false). Will this permanently leak the regulator
enable references upon an I2C error during device removal or suspend?

[ ... ]
> +static int bh1730_read_raw(struct iio_dev *indio_dev,
> +			   struct iio_chan_spec const *chan,
> +			   int *val, int *val2, long mask)
> +{
> +	struct bh1730_data *bh1730 = iio_priv(indio_dev);
> +	int data_reg, ret;
> +
> +	ret = bh1730_adjust_gain(bh1730);
> +	if (ret < 0)
> +		return ret;

Is a mutex needed here to protect concurrent IIO sysfs reads?

Without a driver-level lock, if multiple userspace threads read from the IIO
sysfs attributes concurrently, their executions will interleave.

Could concurrent access allow threads to trample the hardware gain state
in bh1730_adjust_gain(), corrupt I2C read sequences, and read invalid
mid-integration data?

> +	switch (mask) {
> +	case IIO_CHAN_INFO_PROCESSED:
> +		ret = bh1730_get_lux(bh1730);
> +		if (ret < 0)
> +			return ret;
> +		*val = ret;
> +		return IIO_VAL_INT;
> +	case IIO_CHAN_INFO_RAW:
> +		switch (chan->channel2) {
> +		case IIO_MOD_LIGHT_CLEAR:
> +			data_reg = BH1730_REG_DATA0LOW;
> +			break;
> +		case IIO_MOD_LIGHT_IR:
> +			data_reg = BH1730_REG_DATA1LOW;
> +			break;
> +		default:
> +			return -EINVAL;
> +		}
> +		ret = bh1730_read_word(bh1730, data_reg);
> +		if (ret < 0)
> +			return ret;
> +		ret = ret * 1000 / bh1730_gain_multiplier(bh1730);
> +		*val = ret / 1000;
> +		*val2 = (ret % 1000) * 1000;
> +		return IIO_VAL_INT_PLUS_MICRO;

Is it permissible to return a scaled fractional value for IIO_CHAN_INFO_RAW? 

The IIO ABI specifies that IIO_CHAN_INFO_RAW must return the exact, unscaled
integer value from the hardware. Should the driver expose the raw ADC count
using IIO_VAL_INT and provide a separate IIO_CHAN_INFO_SCALE attribute so that
userspace can properly interpret and scale the value?

[ ... ]
> +static int bh1730_parse_dt(struct bh1730_data *bh1730, struct device_node *dn)
> +{
> +	struct device *dev = &bh1730->client->dev;
> +	int ret;
> +	u32 *opt_win_coeff = NULL;
> +	u32 *gain_coeff = NULL;
> +	int opt_win_coeff_count = 0, gain_coeff_count = 0, cycle = 0, mul = 0;
> +
> +	memcpy(&bh1730->cal, &def_lux_data, sizeof(struct lux_cal_data_t));
> +
> +	if (dn) {
> +		/* Get regulators */
> +		bh1730->reg_vdd = regulator_get(dev, "als-vdd");
> +		if (IS_ERR_OR_NULL(bh1730->reg_vdd)) {
> +			bh1730->reg_vdd = NULL;
> +			dev_warn(dev, "failed to get als-vdd");
> +		}

Are the regulator resources leaked here? regulator_get() is used to acquire
them, but there are no corresponding regulator_put() calls in bh1730_remove()
or any of the probe error paths.

Also, does checking the return value with IS_ERR_OR_NULL incorrectly swallow
the -EPROBE_DEFER error code? 

If a regulator is not yet available, the pointer is set to NULL and the driver
proceeds instead of properly deferring the probe, which could break power
management. Could devm_regulator_get_optional() be used here instead?

[ ... ]
> +static int bh1730_probe(struct i2c_client *client)
> +{
> +	struct bh1730_data *bh1730;
> +	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
> +	struct iio_dev *indio_dev;
> +	int ret;
> +
> +	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
> +		return -EIO;

Is I2C_FUNC_SMBUS_BYTE the correct functionality to check? The driver actively
uses i2c_smbus_read_word_data() and i2c_smbus_write_byte_data().

Should this verify I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA
instead? Relying on I2C_FUNC_SMBUS_BYTE might cause the driver to bind to an
I2C adapter that does not support the required operations.

> +
> +	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*bh1730));
> +	if (!indio_dev)
> +		return -ENOMEM;
> +
> +	bh1730 = iio_priv(indio_dev);
> +	bh1730->client = client;
> +	i2c_set_clientdata(client, indio_dev);
> +
> +	ret = bh1730_parse_dt(bh1730, client->dev.of_node);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = bh1730_power_on(bh1730);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = bh1730_init_config(bh1730);
> +	if (ret < 0)
> +		return ret;

If bh1730_init_config() fails, does this return early and leave the
device powered on? 

Returning directly here would leak the regulator enable count instead of
jumping to the out_power_off label to properly clean up the state.

> +
> +	indio_dev->dev.parent = &client->dev;

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260511-bh1730-v1-0-e0df1f499135@gmail.com?part=2

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

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-10 18:09 [PATCH 0/2] iio: light: Add ROHM BH1730FVC ambient light sensor driver Alexandre Hamamdjian via B4 Relay
2026-05-10 18:09 ` [PATCH 1/2] dt-bindings: iio: light: Add ROHM BH1730FVC binding Alexandre Hamamdjian via B4 Relay
2026-05-11  8:22   ` Matti Vaittinen
2026-05-11 10:43     ` Matti Vaittinen
2026-05-11 15:14       ` Jonathan Cameron
2026-05-12  4:42         ` Matti Vaittinen
2026-05-12 11:55           ` Jonathan Cameron
2026-05-11 15:20   ` Jonathan Cameron
2026-05-11 21:47   ` sashiko-bot
2026-05-10 18:09 ` [PATCH 2/2] iio: light: bh1730: Add bh1730 light sensor driver Alexandre Hamamdjian via B4 Relay
2026-05-10 18:18   ` Andy Shevchenko
2026-05-10 18:20     ` Andy Shevchenko
     [not found]       ` <CAL5cOWuXAD7+rJEKB9FjnwdCjoUJK+WNKXZXt8tfnq1WLmv5eg@mail.gmail.com>
2026-05-11  7:31         ` Andy Shevchenko
2026-05-11  8:26       ` Matti Vaittinen
2026-05-11 10:17   ` Matti Vaittinen
2026-05-11 15:50   ` Jonathan Cameron
2026-05-11 22:09   ` sashiko-bot [this message]
2026-05-10 18:13 ` [PATCH 0/2] iio: light: Add ROHM BH1730FVC ambient " 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=20260511220942.B824EC2BCF5@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=devnull+azkali.limited.gmail.com@kernel.org \
    --cc=krzk+dt@kernel.org \
    --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