From 5dd2ecf1d7cd12d2dc353801145749352d2508fc Mon Sep 17 00:00:00 2001 From: Biao Long Date: Mon, 11 Jan 2021 12:00:16 +0800 Subject: [PATCH] devfreq: Fix 64-bit div compilation issue Currently 32-bit div() is used on a 64-bit data which can truncate the data. Fix this by using 64-bit division macro. Change-Id: Icfde1182bfd5b9d9ea855da1e341913900e91f65 Signed-off-by: Biao Long --- drivers/devfreq/devfreq_icc.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/drivers/devfreq/devfreq_icc.c b/drivers/devfreq/devfreq_icc.c index f7dc42e81c2b..7573e2a80fd7 100644 --- a/drivers/devfreq/devfreq_icc.c +++ b/drivers/devfreq/devfreq_icc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2013-2014, 2018-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2014, 2018-2021, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "devfreq-icc: " fmt @@ -60,24 +60,34 @@ static unsigned long l3_freqs[MAX_L3_ENTRIES]; static DEFINE_MUTEX(l3_freqs_lock); static bool use_cached_l3_freqs; +static u64 mbps_to_hz_icc(u32 in, uint width) +{ + u64 result; + u32 quot = in / width; + u32 rem = in % width; + + result = quot * MBYTE + div_u64(rem * MBYTE, width); + return result; +} + static int set_bw(struct device *dev, u32 new_ib, u32 new_ab) { struct dev_data *d = dev_get_drvdata(dev); int ret; - u32 icc_ib = new_ib, icc_ab = new_ab; + u64 icc_ib = new_ib, icc_ab = new_ab; if (d->cur_ib == new_ib && d->cur_ab == new_ab) return 0; if (d->spec->type == L3_MBPS_DEV) { - icc_ib = MBPS_TO_HZ(new_ib, d->width); - icc_ab = MBPS_TO_HZ(new_ab, d->width); + icc_ib = mbps_to_hz_icc(new_ib, d->width); + icc_ab = mbps_to_hz_icc(new_ab, d->width); } else if (d->spec->type == STD_MBPS_DEV) { - icc_ib = MBPS_TO_ICC(new_ib); - icc_ab = MBPS_TO_ICC(new_ab); + icc_ib = mbps_to_hz_icc(new_ib, 1000); + icc_ab = mbps_to_hz_icc(new_ab, 1000); } - dev_dbg(dev, "ICC BW: AB: %u IB: %u\n", icc_ab, icc_ib); + dev_dbg(dev, "ICC BW: AB: %llu IB: %llu\n", icc_ab, icc_ib); ret = icc_set_bw(d->icc_path, icc_ab, icc_ib); if (ret < 0) {