| From 10a36b5d3a05e043f29dbf947081c7424fb2113b Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Mon, 24 Nov 2025 12:07:02 +0100 |
| Subject: interconnect: mediatek: Aggregate bandwidth with saturating add |
| |
| From: Nicolas Frattaroli <nicolas.frattaroli@collabora.com> |
| |
| [ Upstream commit 6ffd02b82243d9907b5f5d2c7a2fc6a62669eece ] |
| |
| By using a regular non-overflow-checking add, the MediaTek icc-emi |
| driver will happy wrap at U32_MAX + 1 to 0. As it's common for the |
| interconnect core to fill in INT_MAX values, this is not a hypothetical |
| situation, but something that actually happens in regular use. This |
| would be pretty disasterous if anything used this driver. |
| |
| Replace the addition with an overflow-checked addition from overflow.h, |
| and saturate to U32_MAX if an overflow is detected. |
| |
| Fixes: b45293799f75 ("interconnect: mediatek: Add MediaTek MT8183/8195 EMI Interconnect driver") |
| Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> |
| Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com> |
| Link: https://lore.kernel.org/r/20251124-mt8196-dvfsrc-v2-13-d9c1334db9f3@collabora.com |
| Signed-off-by: Georgi Djakov <djakov@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/interconnect/mediatek/icc-emi.c | 5 ++++- |
| 1 file changed, 4 insertions(+), 1 deletion(-) |
| |
| diff --git a/drivers/interconnect/mediatek/icc-emi.c b/drivers/interconnect/mediatek/icc-emi.c |
| index 182aa2b0623af..dfa3a9cd93998 100644 |
| --- a/drivers/interconnect/mediatek/icc-emi.c |
| +++ b/drivers/interconnect/mediatek/icc-emi.c |
| @@ -12,6 +12,7 @@ |
| #include <linux/module.h> |
| #include <linux/of.h> |
| #include <linux/of_platform.h> |
| +#include <linux/overflow.h> |
| #include <linux/platform_device.h> |
| #include <linux/soc/mediatek/dvfsrc.h> |
| |
| @@ -22,7 +23,9 @@ static int mtk_emi_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw, |
| { |
| struct mtk_icc_node *in = node->data; |
| |
| - *agg_avg += avg_bw; |
| + if (check_add_overflow(*agg_avg, avg_bw, agg_avg)) |
| + *agg_avg = U32_MAX; |
| + |
| *agg_peak = max_t(u32, *agg_peak, peak_bw); |
| |
| in->sum_avg = *agg_avg; |
| -- |
| 2.51.0 |
| |