X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=arch%2Fx86%2Flib%2Fdelay_64.c;h=4c441be92641a3ae295c8dea3db10b86323e7de2;hb=cb9aa97c21c59ad01c9514d7faf45dc166fba226;hp=2dbebd308347f21be2ad931ce480a6ade16e72b2;hpb=2843483d2eb02ad104edbe8b2429fb6a39d25063;p=linux-2.6-omap-h63xx.git diff --git a/arch/x86/lib/delay_64.c b/arch/x86/lib/delay_64.c index 2dbebd30834..4c441be9264 100644 --- a/arch/x86/lib/delay_64.c +++ b/arch/x86/lib/delay_64.c @@ -10,7 +10,11 @@ #include #include +#include +#include #include +#include + #include #include @@ -18,7 +22,7 @@ #include #endif -int read_current_timer(unsigned long *timer_value) +int __devinit read_current_timer(unsigned long *timer_value) { rdtscll(*timer_value); return 0; @@ -27,20 +31,44 @@ int read_current_timer(unsigned long *timer_value) void __delay(unsigned long loops) { unsigned bclock, now; - + int cpu; + + preempt_disable(); + cpu = smp_processor_id(); rdtscl(bclock); - do - { - rep_nop(); + for (;;) { rdtscl(now); + if ((now - bclock) >= loops) + break; + + /* Allow RT tasks to run */ + preempt_enable(); + rep_nop(); + preempt_disable(); + + /* + * It is possible that we moved to another CPU, and + * since TSC's are per-cpu we need to calculate + * that. The delay must guarantee that we wait "at + * least" the amount of time. Being moved to another + * CPU could make the wait longer but we just need to + * make sure we waited long enough. Rebalance the + * counter for this CPU. + */ + if (unlikely(cpu != smp_processor_id())) { + loops -= (now - bclock); + cpu = smp_processor_id(); + rdtscl(bclock); + } } - while((now-bclock) < loops); + preempt_enable(); } EXPORT_SYMBOL(__delay); inline void __const_udelay(unsigned long xloops) { - __delay(((xloops * HZ * cpu_data[raw_smp_processor_id()].loops_per_jiffy) >> 32) + 1); + __delay(((xloops * HZ * + cpu_data(raw_smp_processor_id()).loops_per_jiffy) >> 32) + 1); } EXPORT_SYMBOL(__const_udelay);