lkml.org 
[lkml]   [2007]   [Mar]   [31]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[RFC PATCH 2/5] x86_64: drive set_rtc_mss from standalone timer
    This is how it's done on i386, and it makes one less bit
    of code to trim from main_timer_handler() when converting
    to clockevents.

    Signed-off-by: Chris Wright <chrisw@sous-sol.org>
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Cc: Ingo Molnar <mingo@elte.hu>
    Cc: john stultz <johnstul@us.ibm.com>
    Cc: Andi Kleen <ak@suse.de>
    ---
    arch/x86_64/kernel/time.c | 68 +++++++++++++++++++++++++++++++++++-----------
    1 file changed, 52 insertions(+), 16 deletions(-)

    --- linus-2.6.orig/arch/x86_64/kernel/time.c
    +++ linus-2.6/arch/x86_64/kernel/time.c
    @@ -81,8 +81,9 @@ EXPORT_SYMBOL(profile_pc);
    * sheet for details.
    */

    -static void set_rtc_mmss(unsigned long nowtime)
    +static int set_rtc_mmss(unsigned long nowtime)
    {
    + int retval = 0;
    int real_seconds, real_minutes, cmos_minutes;
    unsigned char control, freq_select;

    @@ -122,6 +123,7 @@ static void set_rtc_mmss(unsigned long n
    if (abs(real_minutes - cmos_minutes) >= 30) {
    printk(KERN_WARNING "time.c: can't update CMOS clock "
    "from %d to %d\n", cmos_minutes, real_minutes);
    + retval = -1;
    } else {
    BIN_TO_BCD(real_seconds);
    BIN_TO_BCD(real_minutes);
    @@ -141,12 +143,60 @@ static void set_rtc_mmss(unsigned long n
    CMOS_WRITE(freq_select, RTC_FREQ_SELECT);

    spin_unlock(&rtc_lock);
    +
    + return retval;
    +}
    +
    +static void sync_cmos_clock(unsigned long dummy);
    +
    +static DEFINE_TIMER(sync_cmos_timer, sync_cmos_clock, 0, 0);
    +
    +static void sync_cmos_clock(unsigned long dummy)
    +{
    + struct timespec now, next;
    + int fail = 1;
    +
    + /*
    + * If we have an externally synchronized Linux clock, then update
    + * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
    + * called as close as possible to 500 ms before the new second starts.
    + * This code is run on a timer. If the clock is set, that timer
    + * may not expire at the correct time. Thus, we adjust...
    + */
    + if (!ntp_synced())
    + /*
    + * Not synced, exit, do not restart a timer (if one is
    + * running, let it run out).
    + */
    + return;
    +
    + getnstimeofday(&now);
    + if (abs(xtime.tv_nsec - 500000000) <= tick_nsec / 2)
    + fail = set_rtc_mmss(now.tv_sec);
    +
    + next.tv_nsec = 500000000 - now.tv_nsec;
    + if (next.tv_nsec <= 0)
    + next.tv_nsec += NSEC_PER_SEC;
    +
    + if (!fail)
    + next.tv_sec = 659;
    + else
    + next.tv_sec = 0;
    +
    + if (next.tv_nsec >= NSEC_PER_SEC) {
    + next.tv_sec++;
    + next.tv_nsec -= NSEC_PER_SEC;
    + }
    + mod_timer(&sync_cmos_timer, jiffies + timespec_to_jiffies(&next));
    }

    +void notify_arch_cmos_timer(void)
    +{
    + mod_timer(&sync_cmos_timer, jiffies + 1);
    +}

    void main_timer_handler(void)
    {
    - static unsigned long rtc_update = 0;
    /*
    * Here we are in the timer irq handler. We have irqs locally disabled (so we
    * don't need spin_lock_irqsave()) but we don't know if the timer_bh is running
    @@ -174,20 +224,6 @@ void main_timer_handler(void)
    if (!using_apic_timer)
    smp_local_timer_interrupt();

    -/*
    - * If we have an externally synchronized Linux clock, then update CMOS clock
    - * accordingly every ~11 minutes. set_rtc_mmss() will be called in the jiffy
    - * closest to exactly 500 ms before the next second. If the update fails, we
    - * don't care, as it'll be updated on the next turn, and the problem (time way
    - * off) isn't likely to go away much sooner anyway.
    - */
    -
    - if (ntp_synced() && xtime.tv_sec > rtc_update &&
    - abs(xtime.tv_nsec - 500000000) <= tick_nsec / 2) {
    - set_rtc_mmss(xtime.tv_sec);
    - rtc_update = xtime.tv_sec + 660;
    - }
    -
    write_sequnlock(&xtime_lock);
    }

    --
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2007-03-31 10:39    [W:0.057 / U:208.756 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site