aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Hawkes <hawkes@sgi.com>2005-12-16 13:00:24 -0500
committerTony Luck <tony.luck@intel.com>2005-12-16 13:00:24 -0500
commitf5899b5d4fa806403f547dc41312d017d94ec273 (patch)
tree4cbc38474b5ab6dfe8591f0b490686315a6aaa26
parent7b6666530e2736f190a2629c8abe34275054449f (diff)
[IA64] disable preemption in udelay()
The udelay() inline for ia64 uses the ITC. If CONFIG_PREEMPT is enabled and the platform has unsynchronized ITCs and the calling task migrates to another CPU while doing the udelay loop, then the effective delay may be too short or very, very long. This patch disables preemption around 100 usec chunks of the overall desired udelay time. This minimizes preemption-holdoffs. udelay() is now too big to be inline, move it out of line and export it. Signed-off-by: John Hawkes <hawkes@sgi.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
-rw-r--r--arch/ia64/kernel/time.c29
-rw-r--r--include/asm-ia64/delay.h10
2 files changed, 30 insertions, 9 deletions
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index 5b7e736f3b49..028a2b95936c 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -249,3 +249,32 @@ time_init (void)
249 */ 249 */
250 set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); 250 set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec);
251} 251}
252
253#define SMALLUSECS 100
254
255void
256udelay (unsigned long usecs)
257{
258 unsigned long start;
259 unsigned long cycles;
260 unsigned long smallusecs;
261
262 /*
263 * Execute the non-preemptible delay loop (because the ITC might
264 * not be synchronized between CPUS) in relatively short time
265 * chunks, allowing preemption between the chunks.
266 */
267 while (usecs > 0) {
268 smallusecs = (usecs > SMALLUSECS) ? SMALLUSECS : usecs;
269 preempt_disable();
270 cycles = smallusecs*local_cpu_data->cyc_per_usec;
271 start = ia64_get_itc();
272
273 while (ia64_get_itc() - start < cycles)
274 cpu_relax();
275
276 preempt_enable();
277 usecs -= smallusecs;
278 }
279}
280EXPORT_SYMBOL(udelay);
diff --git a/include/asm-ia64/delay.h b/include/asm-ia64/delay.h
index 57182d6f2b9a..bba702076391 100644
--- a/include/asm-ia64/delay.h
+++ b/include/asm-ia64/delay.h
@@ -84,14 +84,6 @@ __delay (unsigned long loops)
84 ia64_delay_loop (loops - 1); 84 ia64_delay_loop (loops - 1);
85} 85}
86 86
87static __inline__ void 87extern void udelay (unsigned long usecs);
88udelay (unsigned long usecs)
89{
90 unsigned long start = ia64_get_itc();
91 unsigned long cycles = usecs*local_cpu_data->cyc_per_usec;
92
93 while (ia64_get_itc() - start < cycles)
94 cpu_relax();
95}
96 88
97#endif /* _ASM_IA64_DELAY_H */ 89#endif /* _ASM_IA64_DELAY_H */