From patchwork Fri Apr 10 11:25:37 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Mason X-Patchwork-Id: 6194641 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 077829F313 for ; Fri, 10 Apr 2015 11:28:27 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 2E8DC200C6 for ; Fri, 10 Apr 2015 11:28:26 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id F12A1203C4 for ; Fri, 10 Apr 2015 11:28:24 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1YgX4c-0002jZ-HY; Fri, 10 Apr 2015 11:26:10 +0000 Received: from smtp2-g21.free.fr ([212.27.42.2]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1YgX4X-0002SV-Ld for linux-arm-kernel@lists.infradead.org; Fri, 10 Apr 2015 11:26:06 +0000 Received: from [172.27.0.114] (unknown [83.142.147.193]) (Authenticated sender: shill) by smtp2-g21.free.fr (Postfix) with ESMTPSA id 312E34B01FF; Fri, 10 Apr 2015 13:23:17 +0200 (CEST) Message-ID: <5527B331.5000205@free.fr> Date: Fri, 10 Apr 2015 13:25:37 +0200 From: Mason User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:35.0) Gecko/20100101 Firefox/35.0 SeaMonkey/2.32.1 MIME-Version: 1.0 To: Linux ARM Subject: Guarantee udelay(N) spins at least N microseconds X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150410_042605_881048_728F58A2 X-CRM114-Status: UNSURE ( 8.81 ) X-CRM114-Notice: Please train this message. X-Spam-Score: -0.7 (/) Cc: Stephen Boyd , Will Deacon , Jonathan Austin X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00,FREEMAIL_FROM, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Hello everyone, This is take 2 of my tiny delay.c patch Problem statement When converting microseconds to timer cycles in __timer_udelay() and __timer_const_udelay(), the result is rounded down(*), which means the system will not spin as long as requested (specifically, between epsilon and 1 cycle shorter). If I understand correctly, most drivers expect udelay(N) to spin for at least N µs. Is that correct? In that use case, spinning less might introduce subtle heisenbugs. Typical example timer->freq = 90 kHz && HZ = 100 (thus UDELAY_MULT = 107374 && ticks_per_jiffy = 900) udelay(10) => __timer_const_udelay(10*107374) => __timer_delay((1073740*900) >> 30) => __timer_delay(0) So udelay(10) resolves to no delay at all. (*) 2^41 / 10^6 = 2199023,255552 2199023 < 2^41 / 10^6 UDELAY_MULT = 2199023*HZ / 2^11 < 2^30*HZ / 10^6 cycles = N * UDELAY_MULT * freq/HZ / 2^30 < N * 2^30*HZ / 10^6 * freq/HZ / 2^30 < N / 10^6 * freq Proposed fix Since results are always rounded down, all we need is to increment the result by 1 to round it up. Would someone ACK the patch below? Regards. Patch against 4.0-rc4 diff --git a/arch/arm/lib/delay.c b/arch/arm/lib/delay.c index 312d43e..3cfbd07 100644 --- a/arch/arm/lib/delay.c +++ b/arch/arm/lib/delay.c @@ -66,7 +66,7 @@ static void __timer_const_udelay(unsigned long xloops) { unsigned long long loops = xloops; loops *= arm_delay_ops.ticks_per_jiffy; - __timer_delay(loops >> UDELAY_SHIFT); + __timer_delay((loops >> UDELAY_SHIFT) + 1); } static void __timer_udelay(unsigned long usecs)