lkml.org 
[lkml]   [2017]   [Apr]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[RFC PATCH v2 05/12] x86/ioapic: Refactor the delay logic in timer_irq_works()
    Date
    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 <douly.fnst@cn.fujitsu.com>
    ---
    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


    \
     
     \ /
      Last update: 2017-04-19 11:07    [W:2.819 / U:0.044 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site