Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.git] / arch / arm / kernel / time.c
index d6bd435..09a67d7 100644 (file)
@@ -16,7 +16,6 @@
  *  1998-12-20  Updated NTP code according to technical memorandum Jan '96
  *              "A Kernel Model for Precision Timekeeping" by Dave Mills
  */
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
@@ -379,7 +378,7 @@ static int timer_dyn_tick_enable(void)
        int ret = -ENODEV;
 
        if (dyn_tick) {
-               write_seqlock_irqsave(&xtime_lock, flags);
+               spin_lock_irqsave(&dyn_tick->lock, flags);
                ret = 0;
                if (!(dyn_tick->state & DYN_TICK_ENABLED)) {
                        ret = dyn_tick->enable();
@@ -387,7 +386,7 @@ static int timer_dyn_tick_enable(void)
                        if (ret == 0)
                                dyn_tick->state |= DYN_TICK_ENABLED;
                }
-               write_sequnlock_irqrestore(&xtime_lock, flags);
+               spin_unlock_irqrestore(&dyn_tick->lock, flags);
        }
 
        return ret;
@@ -400,7 +399,7 @@ static int timer_dyn_tick_disable(void)
        int ret = -ENODEV;
 
        if (dyn_tick) {
-               write_seqlock_irqsave(&xtime_lock, flags);
+               spin_lock_irqsave(&dyn_tick->lock, flags);
                ret = 0;
                if (dyn_tick->state & DYN_TICK_ENABLED) {
                        ret = dyn_tick->disable();
@@ -408,7 +407,7 @@ static int timer_dyn_tick_disable(void)
                        if (ret == 0)
                                dyn_tick->state &= ~DYN_TICK_ENABLED;
                }
-               write_sequnlock_irqrestore(&xtime_lock, flags);
+               spin_unlock_irqrestore(&dyn_tick->lock, flags);
        }
 
        return ret;
@@ -422,15 +421,20 @@ static int timer_dyn_tick_disable(void)
 void timer_dyn_reprogram(void)
 {
        struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick;
-       unsigned long next, seq;
+       unsigned long next, seq, flags;
 
-       if (dyn_tick && (dyn_tick->state & DYN_TICK_ENABLED)) {
+       if (!dyn_tick)
+               return;
+
+       spin_lock_irqsave(&dyn_tick->lock, flags);
+       if (dyn_tick->state & DYN_TICK_ENABLED) {
                next = next_timer_interrupt();
                do {
                        seq = read_seqbegin(&xtime_lock);
-                       dyn_tick->reprogram(next_timer_interrupt() - jiffies);
+                       dyn_tick->reprogram(next - jiffies);
                } while (read_seqretry(&xtime_lock, seq));
        }
+       spin_unlock_irqrestore(&dyn_tick->lock, flags);
 }
 
 static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf)
@@ -499,5 +503,10 @@ void __init time_init(void)
        if (system_timer->offset == NULL)
                system_timer->offset = dummy_gettimeoffset;
        system_timer->init();
+
+#ifdef CONFIG_NO_IDLE_HZ
+       if (system_timer->dyn_tick)
+               system_timer->dyn_tick->lock = SPIN_LOCK_UNLOCKED;
+#endif
 }