linux-hwmon.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Ariana Lazar" <ariana.lazar@microchip.com>
Cc: linux-hwmon@vger.kernel.org, robh@kernel.org,
	devicetree@vger.kernel.org, conor+dt@kernel.org
Subject: Re: [PATCH v3 2/2] iio: adc: add support for PAC1711
Date: Wed, 09 Sep 2026 12:35:36 +0000	[thread overview]
Message-ID: <20260909123536.F15CF1F00A3A@smtp.kernel.org> (raw)
In-Reply-To: <20260909-pac1711-v3-2-dff81003b82f@microchip.com>

Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
- [High] Sample rate configuration silently fails because `val_be16` is not updated before being written back to the device via I2C.
- [High] Concurrent calls to `pac1711_set_acc_enable()` can permanently cancel the background refresh workqueue due to an unsafe early return.
- [Medium] Torn reads and data races of 64-bit values (`acc_val` and `vpower`) because they are read outside of `info->lock`.
- [Medium] Timestamp manipulation intended to force a hardware refresh fails to guarantee execution if the previous snapshot was taken very recently.
- [Medium] Incorrect wait time calculated using the old sampling rate instead of the newly applied rate.
- [Low] Assigning an `unsigned int` array to a `const int *` pointer triggers a compiler warning.
--

commit 2bd1bfeeb99a3cf2d3d02a346520acaae1f7f3ea
Author: Ariana Lazar <ariana.lazar@microchip.com>
Subject: iio: adc: add support for PAC1711

This adds the IIO driver for Microchip PAC1711, PAC1721, PAC1811, and
PAC1821 single-channel power monitors. It supports voltage, current, and
power measurements, as well as an accumulator for energy or charge.

> diff --git a/drivers/iio/adc/pac1711.c b/drivers/iio/adc/pac1711.c
> new file mode 100644
> index 0000000000000..f23d08205952f
> --- /dev/null
> +++ b/drivers/iio/adc/pac1711.c
[ ... ]
> +static int pac1711_set_acc_enable(struct pac1711_chip_info *info, int val)
> +{
[ ... ]
> +	cancel_delayed_work_sync(&info->work_chip_refresh);
> +
> +	scoped_guard(mutex, &info->lock) {
> +		if (val == info->enable_acc)
> +			return 0;

[Severity: High]
Could this early return permanently halt the background refresh task? If
another thread updates enable_acc concurrently and this thread cancels the
just-scheduled work, returning 0 here skips the schedule_delayed_work() call
below. Does this cause the hardware accumulator to silently overflow since it
is no longer refreshed?

> +
> +		/*
> +		 * Force a hardware refresh to zero out the internal accumulators
[ ... ]
> +static ssize_t pac1711_in_coulomb_counter_raw_show(struct device *dev,
> +						   struct device_attribute *attr, char *buf)
> +{
> +	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> +	struct pac1711_chip_info *info = iio_priv(indio_dev);
> +	int ret;
> +
> +	ret = pac1711_retrieve_data(info, PAC1711_MIN_UPDATE_WAIT_TIME_US);
> +	if (ret)
> +		return ret;
> +
> +	return sysfs_emit(buf, "%lld\n", info->chip_reg_data.acc_val);

[Severity: Medium]
Can this sysfs read race with concurrent background updates? Since acc_val is
a 64-bit value accessed outside of info->lock, could this result in torn reads
on 32-bit platforms when the workqueue updates it concurrently?

> +}
[ ... ]
> +static int pac1711_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
> +			    int *val, int *val2, long mask)
> +{
> +	struct pac1711_chip_info *info = iio_priv(indio_dev);
> +	int ret;
> +	u64 tmp = 0;
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_RAW:
> +		ret = pac1711_retrieve_data(info, PAC1711_MIN_UPDATE_WAIT_TIME_US);
> +		if (ret)
> +			return ret;
> +
> +		switch (chan->type) {
[ ... ]
> +		case IIO_POWER:
> +			*val = (u32)info->chip_reg_data.vpower;
> +			*val2 = (u32)(info->chip_reg_data.vpower >> 32);
> +			return IIO_VAL_INT_64;

[Severity: Medium]
Are these 64-bit accesses safe against concurrent modification? Reading the
upper and lower 32 bits independently outside of info->lock might expose an
intermediate state if the background workqueue modifies vpower concurrently.

> +		case IIO_ENERGY:
> +			*val = (u32)info->chip_reg_data.acc_val;
> +			*val2 = (u32)(info->chip_reg_data.acc_val >> 32);
> +			return IIO_VAL_INT_64;
[ ... ]
> +static int pac1711_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
> +			     int val, int val2, long mask)
> +{
[ ... ]
> +	case IIO_CHAN_INFO_SAMP_FREQ:
> +		scoped_guard(mutex, &info->lock) {
> +			old_samp_rate = pac1711_samp_rate_map_tbl[info->sample_rate_idx];
> +			new_idx = pac1711_get_samp_rate_idx(val);
> +			if (new_idx < 0)
> +				return new_idx;
> +
> +			ret = i2c_smbus_read_i2c_block_data(client, PAC1711_CTRL_ACT_REG_ADDR,
> +							    sizeof(val_u16), (u8 *)&val_be16);
> +			if (ret != sizeof(val_u16)) {
> +				dev_err(&client->dev, "cannot read regs from 0x%02X\n",
> +					PAC1711_CTRL_ACT_REG_ADDR);
> +				return ret < 0 ? ret : -EIO;
> +			}
> +
> +			val_u16 = be16_to_cpu(val_be16);
> +			FIELD_MODIFY(PAC1711_CTRL_SAMPLE_MODE_MASK, &val_u16, new_idx);
> +			ret = i2c_smbus_write_i2c_block_data(client, PAC1711_CTRL_REG_ADDR,
> +							     sizeof(val_be16), (u8 *)&val_be16);

[Severity: High]
Does this code write the unmodified register back to the hardware? It looks like
val_u16 is updated, but is not converted and stored back into val_be16 before
calling i2c_smbus_write_i2c_block_data(). Should there be an assignment
updating val_be16 here?

> +			if (ret) {
> +				dev_err(dev, "Failed to configure sampling mode in 0x%02X\n",
> +					PAC1711_CTRL_ACT_REG_ADDR);
> +				return ret;
> +			}
> +
> +			info->sample_rate_idx = new_idx;
> +			info->chip_reg_data.ctrl_act_reg = val_u16;
> +
> +			/* Force register snapshot and timestamp update with a refresh. */
> +			refresh_time = msecs_to_jiffies(PAC1711_MIN_POLLING_TIME_MS) - 1;
> +			info->chip_reg_data.jiffies_tstamp -= refresh_time;

[Severity: Medium]
Will this reliably force a hardware refresh? Subtracting 49ms from a freshly
captured timestamp leaves it within the 50ms polling threshold. Doesn't the
time_after() check in pac1711_reg_snapshot() evaluate to false if the last
snapshot was taken very recently, causing the refresh command to be skipped?

> +		}
> +
> +		ret = pac1711_retrieve_data(info, ((1024 * 1000) / old_samp_rate));

[Severity: Medium]
Is the wait time calculation using the correct sampling rate? The chip was just
commanded to use the new rate, but old_samp_rate is used to calculate the
delay. If the rate was decreased, wouldn't this wait time be too short, causing
stale or incomplete data to be read?

> +		if (ret) {
> +			dev_err(dev, "%s - cannot snapshot ctrl and measurement regs\n", __func__);
> +			return ret;
> +		}
[ ... ]
> +static int pac1711_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec const *channel,
> +			      const int **vals, int *type, int *length, long mask)
> +{
> +	switch (mask) {
> +	case IIO_CHAN_INFO_SAMP_FREQ:
> +		*type = IIO_VAL_INT;
> +		*vals = pac1711_samp_rate_map_tbl;

[Severity: Low]
Does this pointer assignment generate a compiler warning? The global table
pac1711_samp_rate_map_tbl is declared as an unsigned int array, but the IIO
core passes a const int ** for vals. Should the mapping table be declared
as const int to match the expected signature?

> +		*length = ARRAY_SIZE(pac1711_samp_rate_map_tbl);
> +		return IIO_AVAIL_LIST;
> +	}
> +
> +	return -EINVAL;
> +}

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260909-pac1711-v3-0-dff81003b82f@microchip.com?part=2

  reply	other threads:[~2026-09-09 12:35 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-09 12:23 [PATCH v3 0/2] Add support for Microchip PAC1711 Power Monitor Ariana Lazar
2026-09-09 12:23 ` [PATCH v3 1/2] dt-bindings: iio: adc: add support for PAC1711 Ariana Lazar
2026-09-09 12:35   ` sashiko-bot
2026-09-10 11:55   ` Conor Dooley
2026-09-10 14:52     ` Ariana.Lazar
2026-09-12 10:17       ` Conor Dooley
2026-09-09 12:23 ` [PATCH v3 2/2] " Ariana Lazar
2026-09-09 12:35   ` sashiko-bot [this message]
2026-09-09 13:38   ` Andy Shevchenko
2026-09-09 14:22   ` Uwe Kleine-König

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=20260909123536.F15CF1F00A3A@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=ariana.lazar@microchip.com \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=linux-hwmon@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).