patch-2.4.4 linux/arch/ia64/kernel/time.c
Next file: linux/arch/ia64/kernel/traps.c
Previous file: linux/arch/ia64/kernel/sys_ia64.c
Back to the patch index
Back to the overall index
- Lines: 226
- Date:
Thu Apr 5 12:51:47 2001
- Orig file:
v2.4.3/linux/arch/ia64/kernel/time.c
- Orig date:
Thu Jan 4 12:50:17 2001
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/time.c linux/arch/ia64/kernel/time.c
@@ -1,9 +1,9 @@
/*
* linux/arch/ia64/kernel/time.c
*
- * Copyright (C) 1998-2000 Hewlett-Packard Co
+ * Copyright (C) 1998-2001 Hewlett-Packard Co
* Copyright (C) 1998-2000 Stephane Eranian <eranian@hpl.hp.com>
- * Copyright (C) 1999-2000 David Mosberger <davidm@hpl.hp.com>
+ * Copyright (C) 1999-2001 David Mosberger <davidm@hpl.hp.com>
* Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
* Copyright (C) 1999-2000 VA Linux Systems
* Copyright (C) 1999-2000 Walt Drummond <drummond@valinux.com>
@@ -32,14 +32,6 @@
#endif
-static struct {
- unsigned long delta;
- union {
- unsigned long count;
- unsigned char pad[SMP_CACHE_BYTES];
- } next[NR_CPUS];
-} itm;
-
static void
do_profile (unsigned long ip)
{
@@ -61,7 +53,7 @@
ip = prof_len - 1;
atomic_inc((atomic_t *) &prof_buffer[ip]);
- }
+ }
}
/*
@@ -82,7 +74,7 @@
unsigned long now = ia64_get_itc(), last_tick;
unsigned long elapsed_cycles, lost = jiffies - wall_jiffies;
- last_tick = (itm.next[smp_processor_id()].count - (lost+1)*itm.delta);
+ last_tick = (local_cpu_data->itm_next - (lost+1)*local_cpu_data->itm_delta);
# if 1
if ((long) (now - last_tick) < 0) {
printk("Yikes: now < last_tick (now=0x%lx,last_tick=%lx)! No can do.\n",
@@ -91,7 +83,7 @@
}
# endif
elapsed_cycles = now - last_tick;
- return (elapsed_cycles*my_cpu_data.usec_per_cyc) >> IA64_USEC_PER_CYC_SHIFT;
+ return (elapsed_cycles*local_cpu_data->usec_per_cyc) >> IA64_USEC_PER_CYC_SHIFT;
#endif
}
@@ -132,7 +124,7 @@
read_lock_irqsave(&xtime_lock, flags);
{
usec = gettimeoffset();
-
+
sec = xtime.tv_sec;
usec += xtime.tv_usec;
}
@@ -150,10 +142,9 @@
static void
timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- int cpu = smp_processor_id();
unsigned long new_itm;
- new_itm = itm.next[cpu].count;
+ new_itm = local_cpu_data->itm_next;
if (!time_after(ia64_get_itc(), new_itm))
printk("Oops: timer tick before it's due (itc=%lx,itm=%lx)\n",
@@ -165,7 +156,7 @@
* four so that we can use a prof_shift of 2 to get instruction-level
* instead of just bundle-level accuracy.
*/
- if (!user_mode(regs))
+ if (!user_mode(regs))
do_profile(regs->cr_iip + 4*ia64_psr(regs)->ri);
#ifdef CONFIG_SMP
@@ -183,52 +174,50 @@
write_unlock(&xtime_lock);
}
- new_itm += itm.delta;
- itm.next[cpu].count = new_itm;
+ new_itm += local_cpu_data->itm_delta;
+ local_cpu_data->itm_next = new_itm;
if (time_after(new_itm, ia64_get_itc()))
break;
}
- /*
- * If we're too close to the next clock tick for comfort, we
- * increase the saftey margin by intentionally dropping the
- * next tick(s). We do NOT update itm.next accordingly
- * because that would force us to call do_timer() which in
- * turn would let our clock run too fast (with the potentially
- * devastating effect of losing monotony of time).
- */
- while (!time_after(new_itm, ia64_get_itc() + itm.delta/2))
- new_itm += itm.delta;
- ia64_set_itm(new_itm);
-}
-
-#ifdef CONFIG_IA64_SOFTSDV_HACKS
-
-/*
- * Interrupts must be disabled before calling this routine.
- */
-void
-ia64_reset_itm (void)
-{
- timer_interrupt(0, 0, ia64_task_regs(current));
+ do {
+ /*
+ * If we're too close to the next clock tick for comfort, we increase the
+ * saftey margin by intentionally dropping the next tick(s). We do NOT update
+ * itm.next because that would force us to call do_timer() which in turn would
+ * let our clock run too fast (with the potentially devastating effect of
+ * losing monotony of time).
+ */
+ while (!time_after(new_itm, ia64_get_itc() + local_cpu_data->itm_delta/2))
+ new_itm += local_cpu_data->itm_delta;
+ ia64_set_itm(new_itm);
+ /* double check, in case we got hit by a (slow) PMI: */
+ } while (time_after_eq(ia64_get_itc(), new_itm));
}
-#endif
-
/*
* Encapsulate access to the itm structure for SMP.
*/
void __init
-ia64_cpu_local_tick(void)
+ia64_cpu_local_tick (void)
{
-#ifdef CONFIG_IA64_SOFTSDV_HACKS
- ia64_set_itc(0);
-#endif
+ int cpu = smp_processor_id();
+ unsigned long shift = 0, delta;
/* arrange for the cycle counter to generate a timer interrupt: */
- ia64_set_itv(TIMER_IRQ, 0);
- itm.next[smp_processor_id()].count = ia64_get_itc() + itm.delta;
- ia64_set_itm(itm.next[smp_processor_id()].count);
+ ia64_set_itv(IA64_TIMER_VECTOR);
+
+ delta = local_cpu_data->itm_delta;
+ /*
+ * Stagger the timer tick for each CPU so they don't occur all at (almost) the
+ * same time:
+ */
+ if (cpu) {
+ unsigned long hi = 1UL << ia64_fls(cpu);
+ shift = (2*(cpu - hi) + 1) * delta/hi/2;
+ }
+ local_cpu_data->itm_next = ia64_get_itc() + delta + shift;
+ ia64_set_itm(local_cpu_data->itm_next);
}
void __init
@@ -258,33 +247,28 @@
itc_ratio.num = 3;
itc_ratio.den = 1;
}
-#ifdef CONFIG_IA64_SOFTSDV_HACKS
- platform_base_freq = 10000000;
- proc_ratio.num = 4; proc_ratio.den = 1;
- itc_ratio.num = 4; itc_ratio.den = 1;
-#else
if (platform_base_freq < 40000000) {
printk("Platform base frequency %lu bogus---resetting to 75MHz!\n",
platform_base_freq);
platform_base_freq = 75000000;
}
-#endif
if (!proc_ratio.den)
- proc_ratio.num = 1; /* avoid division by zero */
+ proc_ratio.den = 1; /* avoid division by zero */
if (!itc_ratio.den)
- itc_ratio.num = 1; /* avoid division by zero */
+ itc_ratio.den = 1; /* avoid division by zero */
- itc_freq = (platform_base_freq*itc_ratio.num)/itc_ratio.den;
- itm.delta = itc_freq / HZ;
- printk("CPU %d: base freq=%lu.%03luMHz, ITC ratio=%lu/%lu, ITC freq=%lu.%03luMHz\n",
+ itc_freq = (platform_base_freq*itc_ratio.num)/itc_ratio.den;
+ local_cpu_data->itm_delta = (itc_freq + HZ/2) / HZ;
+ printk("CPU %d: base freq=%lu.%03luMHz, ITC ratio=%lu/%lu, ITC freq=%lu.%03luMHz\n",
smp_processor_id(),
platform_base_freq / 1000000, (platform_base_freq / 1000) % 1000,
- itc_ratio.num, itc_ratio.den, itc_freq / 1000000, (itc_freq / 1000) % 1000);
+ itc_ratio.num, itc_ratio.den, itc_freq / 1000000, (itc_freq / 1000) % 1000);
- my_cpu_data.proc_freq = (platform_base_freq*proc_ratio.num)/proc_ratio.den;
- my_cpu_data.itc_freq = itc_freq;
- my_cpu_data.cyc_per_usec = itc_freq / 1000000;
- my_cpu_data.usec_per_cyc = (1000000UL << IA64_USEC_PER_CYC_SHIFT) / itc_freq;
+ local_cpu_data->proc_freq = (platform_base_freq*proc_ratio.num)/proc_ratio.den;
+ local_cpu_data->itc_freq = itc_freq;
+ local_cpu_data->cyc_per_usec = (itc_freq + 500000) / 1000000;
+ local_cpu_data->usec_per_cyc = ((1000000UL<<IA64_USEC_PER_CYC_SHIFT)
+ + itc_freq/2)/itc_freq;
/* Setup the CPU local timer tick */
ia64_cpu_local_tick();
@@ -299,11 +283,7 @@
void __init
time_init (void)
{
- /* we can't do request_irq() here because the kmalloc() would fail... */
- irq_desc[TIMER_IRQ].status |= IRQ_PER_CPU;
- irq_desc[TIMER_IRQ].handler = &irq_type_ia64_sapic;
- setup_irq(TIMER_IRQ, &timer_irqaction);
-
+ register_percpu_irq(IA64_TIMER_VECTOR, &timer_irqaction);
efi_gettimeofday(&xtime);
ia64_init_itm();
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)