From patchwork Wed Feb 24 09:30:29 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Slaby X-Patchwork-Id: 62785 Delivered-To: patch@linaro.org Received: by 10.112.43.199 with SMTP id y7csp2294831lbl; Wed, 24 Feb 2016 01:31:29 -0800 (PST) X-Received: by 10.66.122.3 with SMTP id lo3mr52681299pab.25.1456306274385; Wed, 24 Feb 2016 01:31:14 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id f77si3776922pfd.94.2016.02.24.01.31.13; Wed, 24 Feb 2016 01:31:14 -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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752264AbcBXJa6 (ORCPT + 3 others); Wed, 24 Feb 2016 04:30:58 -0500 Received: from mx2.suse.de ([195.135.220.15]:39223 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752004AbcBXJaz (ORCPT ); Wed, 24 Feb 2016 04:30:55 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 52FCDAD06; Wed, 24 Feb 2016 09:30:54 +0000 (UTC) From: Jiri Slaby To: stable@vger.kernel.org Cc: Linus Walleij , linux-clk@vger.kernel.org, Pawel Moll , Russell King , Jiri Slaby Subject: [patch added to 3.12-stable] ARM: 8517/1: ICST: avoid arithmetic overflow in icst_hz() Date: Wed, 24 Feb 2016 10:30:29 +0100 Message-Id: <1456306248-31813-10-git-send-email-jslaby@suse.cz> X-Mailer: git-send-email 2.7.1 In-Reply-To: <1456306248-31813-1-git-send-email-jslaby@suse.cz> References: <1456306248-31813-1-git-send-email-jslaby@suse.cz> Sender: stable-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Linus Walleij This patch has been added to the 3.12 stable tree. If you have any objections, please let us know. -- 2.7.1 -- 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 =============== commit 5070fb14a0154f075c8b418e5bc58a620ae85a45 upstream. 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: linux-clk@vger.kernel.org Cc: Pawel Moll Signed-off-by: Linus Walleij Signed-off-by: Russell King Signed-off-by: Jiri Slaby --- arch/arm/common/icst.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm/common/icst.c b/arch/arm/common/icst.c index 3b3e58b7ba74..d7ed252708c5 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);