All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Rodrigo Alencar via B4 Relay"
	<devnull+rodrigo.alencar.analog.com@kernel.org>
Cc: robh@kernel.org, devicetree@vger.kernel.org, conor+dt@kernel.org
Subject: Re: [PATCH v6 10/16] iio: frequency: ad9910: add basic parallel port support
Date: Thu, 18 Jun 2026 13:41:57 +0000	[thread overview]
Message-ID: <20260618134157.B0DEC1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260618-ad9910-iio-driver-v6-10-79125ffbe430@analog.com>

Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:

New issues:
- [Medium] 32-bit truncation in the parallel frequency scale calculation causes incorrect readback.
- [Medium] 64-bit integer overflow in parallel frequency offset calculation circumvents U32_MAX capping.
- [Medium] `roundup_pow_of_two` truncates 64-bit scale calculation on 32-bit architectures.
- [Medium] Integer overflow when reading and writing the frequency offset for the parallel frequency channel.

Pre-existing issues:
- [High] Kernel panic due to division by zero if the reference clock rate is zero.
--

commit 5740831576c6dff0dd6ca6d5b5930978950cfff8
Author: Rodrigo Alencar <rodrigo.alencar@analog.com>

iio: frequency: ad9910: add basic parallel port support

Add parallel port support with amplitude, phase and frequency channels.
Those will be buffered capable channels, but only basic control of offset
and scale are implemented at this point.

> diff --git a/drivers/iio/frequency/ad9910.c b/drivers/iio/frequency/ad9910.c
> index 95b01295e4a0a..262702b62738d 100644
> --- a/drivers/iio/frequency/ad9910.c
> +++ b/drivers/iio/frequency/ad9910.c

[ ... ]

> @@ -640,11 +702,60 @@ static int ad9910_read_raw(struct iio_dev *indio_dev,
>  			return -EINVAL;
>  		}
>  	case IIO_CHAN_INFO_SCALE:
> -		tmp64 = (u64)st->data.output_current_uA *
> -			AD9910_NANO_MILLIAMP_PER_MICROAMP;
> -		*val = 0;
> -		*val2 = tmp64 >> 14;
> -		return IIO_VAL_INT_PLUS_NANO;
> +		switch (chan->address) {
> +		case AD9910_CHAN_IDX_PHY:
> +			tmp64 = (u64)st->data.output_current_uA *
> +				AD9910_NANO_MILLIAMP_PER_MICROAMP;
> +			*val = 0;
> +			*val2 = tmp64 >> 14;
> +			return IIO_VAL_INT_PLUS_NANO;
> +		case AD9910_CHAN_IDX_PARALLEL_PHASE:
> +			*val = 0;
> +			*val2 = AD9910_PI_NANORAD >> 15;
> +			return IIO_VAL_INT_PLUS_NANO;
> +		case AD9910_CHAN_IDX_PARALLEL_FREQ:
> +			tmp32 = FIELD_GET(AD9910_CFR2_FM_GAIN_MSK,
> +					  st->reg[AD9910_REG_CFR2].val32);
> +			tmp64 = st->data.sysclk_freq_hz << tmp32;

[Severity: Medium]
Will this 32-bit shift overflow before being assigned to the 64-bit tmp64?

Since sysclk_freq_hz is typically around 1 GHz and tmp32 can be up to 15,
this operation appears to be strictly 32-bit and could wrap around, resulting
in a corrupted readback.

> +			tmp64 = ad9910_rational_scale(tmp64, NANO, BIT_ULL(32));
> +			*val = div_s64_rem(tmp64, NANO, val2);
> +			return IIO_VAL_INT_PLUS_NANO;
> +		case AD9910_CHAN_IDX_PARALLEL_POLAR_AMP:

[ ... ]

> +	case IIO_CHAN_INFO_OFFSET:
> +		switch (chan->address) {
> +		case AD9910_CHAN_IDX_PARALLEL_FREQ:
> +			tmp64 = (u64)st->reg[AD9910_REG_FTW].val32 * MICRO;
> +			tmp64 >>= FIELD_GET(AD9910_CFR2_FM_GAIN_MSK,
> +					    st->reg[AD9910_REG_CFR2].val32);
> +			*val = div_s64_rem(tmp64, MICRO, val2);

[Severity: Medium]
Does this operation overflow the signed 32-bit pointer val?

The Frequency Tuning Word (FTW) is an unsigned 32-bit register capable of
holding values up to 4,294,967,295. If the offset exceeds INT_MAX, the
assignment could overflow, leading to a negative value on readback.

> +			return IIO_VAL_INT_PLUS_MICRO;
> +		case AD9910_CHAN_IDX_PARALLEL_POLAR_AMP:

[ ... ]

> @@ -737,12 +848,63 @@ static int ad9910_write_raw(struct iio_dev *indio_dev,
>  	case IIO_CHAN_INFO_SAMP_FREQ:
>  		return ad9910_set_sysclk_freq(st, val, true);
>  	case IIO_CHAN_INFO_SCALE:
> -		if (val != 0 || val2 < 0)
> +		switch (chan->address) {
> +		case AD9910_CHAN_IDX_PHY:
> +			if (val != 0 || val2 < 0)
> +				return -EINVAL;
> +
> +			tmp32 = DIV_U64_ROUND_CLOSEST((u64)val2 << 14,
> +						      AD9910_NANO_MILLIAMP_PER_MICROAMP);
> +			return ad9910_set_dac_current(st, tmp32, true);
> +		case AD9910_CHAN_IDX_PARALLEL_FREQ:
> +			if (val < 0 || val2 < 0)
> +				return -EINVAL;
> +
> +			tmp64 = ad9910_rational_scale((u64)val * NANO + val2, BIT_ULL(32),
> +						      (u64)st->data.sysclk_freq_hz * NANO);

[Severity: High]
This is a pre-existing issue, but can sysclk_freq_hz be zero here? If the
reference clock returns 0 from clk_get_rate(), the driver initializes
sysclk_freq_hz to 0 without validation.

If sysclk_freq_hz is 0, the denominator passed to ad9910_rational_scale()
is 0:

drivers/iio/frequency/ad9910.c:ad9910_rational_scale() {
    return mul_u64_add_u64_div_u64(input, scale, reference >> 1, reference);
}

This forwards the zero denominator into mul_u64_add_u64_div_u64(), leading
to a kernel panic from division by zero, which is now triggerable from user
space via the newly added parallel frequency scale attribute.

> +			tmp64 = roundup_pow_of_two(max(tmp64, 1ULL));

[Severity: Medium]
Will roundup_pow_of_two() truncate the 64-bit tmp64 calculation on 32-bit
architectures?

The roundup_pow_of_two() macro explicitly casts its argument to unsigned
long. On 32-bit systems, this will drop the upper 32 bits, causing the scale
input to be incorrectly configured.

> +			tmp32 = min_t(u32, ilog2(tmp64), FIELD_MAX(AD9910_CFR2_FM_GAIN_MSK));
> +			tmp32 = FIELD_PREP(AD9910_CFR2_FM_GAIN_MSK, tmp32);
> +			return ad9910_reg32_update(st, AD9910_REG_CFR2,
> +						   AD9910_CFR2_FM_GAIN_MSK,
> +						   tmp32, true);
> +		default:
> +			return -EINVAL;
> +		}
> +	case IIO_CHAN_INFO_OFFSET:
> +		if (val < 0 || val2 < 0)
>  			return -EINVAL;
>  
> -		tmp32 = DIV_U64_ROUND_CLOSEST((u64)val2 << 14,
> -					      AD9910_NANO_MILLIAMP_PER_MICROAMP);
> -		return ad9910_set_dac_current(st, tmp32, true);
> +		switch (chan->address) {
> +		case AD9910_CHAN_IDX_PARALLEL_FREQ:
> +			tmp64 = (u64)val * MICRO + val2;

[Severity: Medium]
Is it possible to set the Frequency Tuning Word to its full unsigned 32-bit
range?

The IIO subsystem's parser restricts the val parameter to INT_MAX. This
limitation seems to prevent users from accessing or configuring the upper
half of the device's tuning word range when FM_GAIN is 0.

> +			tmp64 <<= FIELD_GET(AD9910_CFR2_FM_GAIN_MSK,
> +					    st->reg[AD9910_REG_CFR2].val32);

[Severity: Medium]
Can this unbounded left shift trigger a 64-bit overflow?

If val is a large value up to INT_MAX, tmp64 can be around 5.63e14. Shifting
this left by an FM_GAIN of 15 would yield a value greater than UINT64_MAX,
which wraps around to a small positive value.

Because the wrapped value is small, it would bypass the subsequent U32_MAX
cap check below, resulting in arbitrary wrapped-around garbage being written
to the hardware.

> +			tmp64 = min_t(u64, DIV_U64_ROUND_CLOSEST(tmp64, MICRO),
> +				      U32_MAX);
> +			return ad9910_reg32_write(st, AD9910_REG_FTW, tmp64, true);

[ ... ]

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260618-ad9910-iio-driver-v6-0-79125ffbe430@analog.com?part=10

  reply	other threads:[~2026-06-18 13:41 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-18 13:27 [PATCH v6 00/16] AD9910 Direct Digital Synthesizer Rodrigo Alencar via B4 Relay
2026-06-18 13:27 ` Rodrigo Alencar
2026-06-18 13:27 ` [PATCH v6 01/16] iio: ABI: add attributes for altcurrent channels Rodrigo Alencar via B4 Relay
2026-06-18 13:27   ` Rodrigo Alencar
2026-06-18 13:27 ` [PATCH v6 02/16] iio: ABI: scale and offset for frequency/phase channels Rodrigo Alencar via B4 Relay
2026-06-18 13:27   ` Rodrigo Alencar
2026-06-18 13:27 ` [PATCH v6 03/16] iio: ABI: add parent entry for iio channels Rodrigo Alencar via B4 Relay
2026-06-18 13:27   ` Rodrigo Alencar
2026-06-18 13:27 ` [PATCH v6 04/16] iio: add IIO_FREQUENCY channel type Rodrigo Alencar via B4 Relay
2026-06-18 13:27   ` Rodrigo Alencar
2026-06-18 13:27 ` [PATCH v6 05/16] iio: core: support 64-bit register through debugfs Rodrigo Alencar via B4 Relay
2026-06-18 13:27   ` Rodrigo Alencar
2026-06-18 14:45   ` Nuno Sá
2026-06-18 13:27 ` [PATCH v6 06/16] iio: core: create local __iio_chan_prefix_emit() for reuse Rodrigo Alencar via B4 Relay
2026-06-18 13:27   ` Rodrigo Alencar
2026-06-18 15:06   ` Nuno Sá
2026-06-18 16:14     ` Rodrigo Alencar
2026-06-18 18:14       ` Andy Shevchenko
2026-06-18 13:27 ` [PATCH v6 07/16] iio: core: add hierarchical channel relationships Rodrigo Alencar via B4 Relay
2026-06-18 13:27   ` Rodrigo Alencar
2026-06-18 13:33   ` sashiko-bot
2026-06-18 13:27 ` [PATCH v6 08/16] dt-bindings: iio: frequency: add ad9910 Rodrigo Alencar via B4 Relay
2026-06-18 13:27   ` Rodrigo Alencar
2026-06-18 13:35   ` sashiko-bot
2026-06-18 13:27 ` [PATCH v6 09/16] iio: frequency: ad9910: initial driver implementation Rodrigo Alencar via B4 Relay
2026-06-18 13:27   ` Rodrigo Alencar
2026-06-18 13:37   ` sashiko-bot
2026-06-18 13:27 ` [PATCH v6 10/16] iio: frequency: ad9910: add basic parallel port support Rodrigo Alencar via B4 Relay
2026-06-18 13:27   ` Rodrigo Alencar
2026-06-18 13:41   ` sashiko-bot [this message]
2026-06-18 13:27 ` [PATCH v6 11/16] iio: frequency: ad9910: add digital ramp generator support Rodrigo Alencar via B4 Relay
2026-06-18 13:27   ` Rodrigo Alencar
2026-06-18 13:42   ` sashiko-bot
2026-06-18 13:27 ` [PATCH v6 12/16] iio: frequency: ad9910: add RAM mode support Rodrigo Alencar via B4 Relay
2026-06-18 13:27   ` Rodrigo Alencar
2026-06-18 13:43   ` sashiko-bot
2026-06-18 13:27 ` [PATCH v6 13/16] iio: frequency: ad9910: add output shift keying support Rodrigo Alencar via B4 Relay
2026-06-18 13:27   ` Rodrigo Alencar
2026-06-18 13:27 ` [PATCH v6 14/16] iio: frequency: ad9910: show channel priority in debugfs Rodrigo Alencar via B4 Relay
2026-06-18 13:27   ` Rodrigo Alencar
2026-06-18 13:45   ` sashiko-bot
2026-06-18 13:27 ` [PATCH v6 15/16] iio: ABI: add docs for ad9910 sysfs entries Rodrigo Alencar via B4 Relay
2026-06-18 13:27   ` Rodrigo Alencar
2026-06-18 13:44   ` sashiko-bot
2026-06-18 13:27 ` [PATCH v6 16/16] docs: iio: add documentation for ad9910 driver Rodrigo Alencar via B4 Relay
2026-06-18 13:27   ` Rodrigo Alencar

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=20260618134157.B0DEC1F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=devnull+rodrigo.alencar.analog.com@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.