From patchwork Wed Feb 3 19:55:08 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 61150 Delivered-To: patch@linaro.org Received: by 10.112.43.199 with SMTP id y7csp51480lbl; Wed, 3 Feb 2016 11:55:22 -0800 (PST) X-Received: by 10.98.87.204 with SMTP id i73mr5107951pfj.63.1454529322561; Wed, 03 Feb 2016 11:55:22 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id vo4si11067069pab.143.2016.02.03.11.55.22; Wed, 03 Feb 2016 11:55:22 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org; dkim=neutral (body hash did not verify) header.i=@linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752200AbcBCTzV (ORCPT + 3 others); Wed, 3 Feb 2016 14:55:21 -0500 Received: from mail-lb0-f178.google.com ([209.85.217.178]:32928 "EHLO mail-lb0-f178.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752151AbcBCTzU (ORCPT ); Wed, 3 Feb 2016 14:55:20 -0500 Received: by mail-lb0-f178.google.com with SMTP id x4so19064411lbm.0 for ; Wed, 03 Feb 2016 11:55:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=YYPTKaStoSXEH3EtnZgDO7kmnsWni4JxYxtt288ZXvE=; b=DoBwI7KI/Wab/TkCFlXMzAfHAR0MgFx4HmHZJtCG+GRpdaxVRM07Vxgj11oFHfhluZ Vie0aQo3joAlIXU5XM6aPnXIwRg3zFhK6+zMPFvxSo1dB/5l3xFTIqv4JOmIKSVr3MoM p7X+xKvb+++BDjVKnAgnxYr3qQ9ppqZEbfFJ8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=YYPTKaStoSXEH3EtnZgDO7kmnsWni4JxYxtt288ZXvE=; b=WrpnlhvHNtswORcs/T5zn2hs7PTZpTeClbd3YKLJc30s4oiQb3T6n4SeHm8YZbaegu jQIYYR8PBT8JPgSzBlB0U1XpKzI3WNBmDgt+ELJWhhoaMWh4D8fNtjWN42I5aHMGyOHM C5zay5I89AQ04zb62accup3f217suzZz0MvqzCfyDLF750rAYsbx8MMaGZdcwISLXKGy 3EG6IOxxnfvw34PgORKAxOSAnmOdEPlBT5eAblj3wM4lnvfDFGKc2TyARfflf5Umyays 9J/DFDY/h5oBsP6bpXDbiCo9zobfvk4hgE8EGQ6ZvGuynldiBFQRpxRgWlXmtSmQs2QV 0ywQ== X-Gm-Message-State: AG10YOT+oW31nrgROsE0EWiOUAygbWmPB9Bj84t2fJiSXHbMY1+6iNJOSLzavvpmOMkyFdJT X-Received: by 10.112.147.1 with SMTP id tg1mr1446220lbb.119.1454529319030; Wed, 03 Feb 2016 11:55:19 -0800 (PST) Received: from localhost.localdomain.localdomain (c-3d95db54.01-192-6c756e10.cust.bredbandsbolaget.se. [84.219.149.61]) by smtp.gmail.com with ESMTPSA id l129sm1091551lfl.37.2016.02.03.11.55.17 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 03 Feb 2016 11:55:18 -0800 (PST) From: Linus Walleij To: Russell King Cc: linux-arm-kernel@lists.infradead.org, Linus Walleij , stable@vger.kernel.org, linux-clk@vger.kernel.org, Pawel Moll Subject: [PATCH] ARM: ICST: avoid arithmetic overflow in icst_hz() Date: Wed, 3 Feb 2016 20:55:08 +0100 Message-Id: <1454529308-31887-1-git-send-email-linus.walleij@linaro.org> X-Mailer: git-send-email 2.4.3 Sender: stable-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org When trying to set the ICST 307 clock to 25174000 Hz I ran into this arithmetic error: the icst_hz_to_vco() correctly figure out DIVIDE=2, RDW=100 and VDW=99 yielding a frequency of 25174000 Hz out of the VCO. (I replicated the icst_hz() function in a spreadsheet to verify this.) However, when I called icst_hz() on these VCO settings it would instead return 4122709 Hz. This causes an error in the common clock driver for ICST as the common clock framework will call .round_rate() on the clock which will utilize icst_hz_to_vco() followed by icst_hz() suggesting the erroneous frequency, and then the clock gets set to this. The error did not manifest in the old clock framework since this high frequency was only used by the CLCD, which calls clk_set_rate() without first calling clk_round_rate() and since the old clock framework would not call clk_round_rate() before setting the frequency, the correct values propagated into the VCO. After some experimenting I figured out that it was due to a simple arithmetic overflow: the divisor for 24Mhz reference frequency as reference becomes 24000000*2*(99+8)=0x132212400 and the "1" in bit 32 overflows and is lost. But introducing an explicit 64-by-32 bit do_div() and casting the divisor into (u64) we get the right frequency back, and the right frequency gets set. Tested on the ARM Versatile. Cc: stable@vger.kernel.org Cc: linux-clk@vger.kernel.org Cc: Russell King Cc: Pawel Moll Signed-off-by: Linus Walleij --- arch/arm/common/icst.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) -- 2.4.3 -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/arch/arm/common/icst.c b/arch/arm/common/icst.c index 2dc6da70ae59..d3c0e69df259 100644 --- a/arch/arm/common/icst.c +++ b/arch/arm/common/icst.c @@ -16,7 +16,7 @@ */ #include #include - +#include #include /* @@ -29,7 +29,11 @@ EXPORT_SYMBOL(icst525_s2div); unsigned long icst_hz(const struct icst_params *p, struct icst_vco vco) { - return p->ref * 2 * (vco.v + 8) / ((vco.r + 2) * p->s2div[vco.s]); + u64 dividend = p->ref * 2 * (u64)(vco.v + 8); + u32 divisor = (vco.r + 2) * p->s2div[vco.s]; + + do_div(dividend, divisor); + return (unsigned long)dividend; } EXPORT_SYMBOL(icst_hz);