Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1761528AbdDSJGM (ORCPT ); Wed, 19 Apr 2017 05:06:12 -0400 Received: from cn.fujitsu.com ([59.151.112.132]:17946 "EHLO heian.cn.fujitsu.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1761375AbdDSJGE (ORCPT ); Wed, 19 Apr 2017 05:06:04 -0400 X-IronPort-AV: E=Sophos;i="5.22,518,1449504000"; d="scan'208";a="17913923" From: Dou Liyang To: , CC: , , , , , , Dou Liyang Subject: [RFC PATCH v2 05/12] x86/ioapic: Refactor the delay logic in timer_irq_works() Date: Wed, 19 Apr 2017 17:05:19 +0800 Message-ID: <2058afd49c1ecec0fb300da71727d04793812c01.1492589715.git.douly.fnst@cn.fujitsu.com> X-Mailer: git-send-email 2.5.5 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.167.226.106] X-yoursite-MailScanner-ID: E4CF547CE24B.A497B X-yoursite-MailScanner: Found to be clean X-yoursite-MailScanner-From: douly.fnst@cn.fujitsu.com Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2943 Lines: 100 Timer_irq_works() calls mdelay(10) to delay ten ticks and checks whether the timer IRQ works or not. The mdelay() depends on the loops_per_jiffy which is set up in calibrate_delay(). Timer_irq_works() has been in advance of calibrate_delay(). the mdelay() doesn't work well in timer_irq_works(). Refactor the delay logic by replace the mdelay() with __delay() and regard 2**MAX_BAND as the maximum threshold of CPU frequency. Signed-off-by: Dou Liyang --- arch/x86/kernel/apic/io_apic.c | 47 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 347bb9f..d3b0268 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -1608,6 +1608,18 @@ static int __init notimercheck(char *s) __setup("no_timer_check", notimercheck); /* + * The loops_per_jiffy is not be set, udelay() or mdelay() cannot + * be called here. + * Set 16GHZ(loops_per_jiffy almost is 2**24) as the maximum threshold + * of CPU frequency. Exceed the threshold indicates the timer interrupt + * doesn't work. + * + * FIXME: Explore a new way to check the timer interrupt work. + */ + +#define MAX_BAND 24 + +/* * There is a nasty bug in some older SMP boards, their mptable lies * about the timer IRQ. We do the following to work around the situation: * @@ -1617,28 +1629,51 @@ __setup("no_timer_check", notimercheck); */ static int __init timer_irq_works(void) { - unsigned long t1 = jiffies; + unsigned long ticks; unsigned long flags; + /* Set up approx 2 Bo*oMips to start */ + int band = 11; + int loop_times; if (no_timer_check) return 1; local_save_flags(flags); local_irq_enable(); - /* Let ten ticks pass... */ - mdelay((10 * 1000) / HZ); - local_irq_restore(flags); + /* + * Estimate the loops in (1,2] jiffies. + * + * After the loops (2**12+2**13+...+2**MAX_BAND) times, + * if time_before(jiffies, ticks + 2) is also n, That the + * timer interrupt did not work, return 0. + */ + ticks = jiffies; + do { + if (band++ == MAX_BAND) { + local_irq_restore(flags); + return 0; + } + + __delay(1 << band); + } while (time_before(jiffies, ticks + 2)); /* * Expect a few ticks at least, to be sure some possible * glue logic does not lock up after one or two first * ticks in a non-ExtINT mode. Also the local APIC - * might have cached one ExtINT interrupt. Finally, at + * might have cached one ExtINT interrupt. Finally, at * least one tick may be lost due to delays. + * + * As 2**12+2**13+...+2**band < 2**(1 + band), + * it certainly delayed for more than 4 ticks. */ + for (loop_times = 0; loop_times < 4; loop_times++) + __delay(1 << (1 + band)); + + local_irq_restore(flags); /* jiffies wrap? */ - if (time_after(jiffies, t1 + 4)) + if (time_after(jiffies, ticks + 4)) return 1; return 0; } -- 2.5.5