[PATCH 14/15] iio: scmi: use 64-bit divisions for rates and intervals

From: Greg Kroah-Hartman

Date: Tue Oct 27 2026 - 12:50:40 EST


From: Josef Bacik <josef@xxxxxxxxxxxxxx>

do_div() only uses the low 32 bits of its divisor. Two divisors in this
driver need more:

- scmi_iio_set_odr_val() divides by the requested sampling frequency in
micro-Hertz, which exceeds 32 bits from 4295 Hz on. The update interval
sent to the firmware is then computed from the wrong frequency.
- convert_ns_to_freq() divides by the update interval in nanoseconds, which
exceeds 32 bits from 4.3 seconds on. The sampling frequency and the list
of available frequencies of a slow sensor are reported wrong.

Use div64_u64(). A requested frequency of 0, which was a division by zero,
is refused with -EINVAL like other values that cannot be represented.

Fixes: f774117c96f9 ("iio/scmi: Adding support for IIO SCMI Based Sensors")
Cc: stable <stable@xxxxxxxxxx>
Cc: Jyoti Bhayana <jbhayana@xxxxxxxxxx>
Cc: David Lechner <dlechner@xxxxxxxxxxxx>
Cc: "Nuno Sá" <nuno.sa@xxxxxxxxxx>
Cc: Andy Shevchenko <andy@xxxxxxxxxx>
Signed-off-by: Josef Bacik <josef@xxxxxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
---
drivers/iio/common/scmi_sensors/scmi_iio.c | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/iio/common/scmi_sensors/scmi_iio.c b/drivers/iio/common/scmi_sensors/scmi_iio.c
index 442b40ef27cf..0e51e9c16b90 100644
--- a/drivers/iio/common/scmi_sensors/scmi_iio.c
+++ b/drivers/iio/common/scmi_sensors/scmi_iio.c
@@ -161,8 +161,7 @@ static int scmi_iio_set_odr_val(struct iio_dev *iio_dev, int val, int val2)
do_div(sf, MICROHZ_PER_HZ);
mult = scnprintf(buf, sizeof(buf), "%llu", sf) - 1;

- sec = int_pow(10, mult) * MICROHZ_PER_HZ;
- do_div(sec, uHz);
+ sec = uHz ? div64_u64(int_pow(10, mult) * MICROHZ_PER_HZ, uHz) : 0;
if (sec == 0) {
dev_err(&iio_dev->dev,
"Trying to set invalid sensor update value for sensor %s",
@@ -237,13 +236,10 @@ static int scmi_iio_read_avail(struct iio_dev *iio_dev,

static void convert_ns_to_freq(u64 interval_ns, u64 *hz, u64 *uhz)
{
- u64 rem, freq;
+ u64 rem;

- freq = NSEC_PER_SEC;
- rem = do_div(freq, interval_ns);
- *hz = freq;
- *uhz = rem * 1000000UL;
- do_div(*uhz, interval_ns);
+ *hz = div64_u64_rem(NSEC_PER_SEC, interval_ns, &rem);
+ *uhz = div64_u64(rem * 1000000UL, interval_ns);
}

static int scmi_iio_get_odr_val(struct iio_dev *iio_dev, int *val, int *val2)

--
2.56.0