X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=arch%2Fs390%2Flib%2Fdelay.c;h=02854449b74ba64dea7230b606f72b63c3890218;hb=5a84d159061d914c8dd4aa372ac6e9529c2be453;hp=468f4ea33f99efdf1f83802ed4433146ac485b57;hpb=b4bc7b53ccfa0cb793591ba11af49db8f1bc5a4d;p=linux-2.6-omap-h63xx.git diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c index 468f4ea33f9..02854449b74 100644 --- a/arch/s390/lib/delay.c +++ b/arch/s390/lib/delay.c @@ -1,5 +1,5 @@ /* - * arch/s390/kernel/delay.c + * arch/s390/lib/delay.c * Precise Delay Loops for S390 * * S390 version @@ -13,10 +13,8 @@ #include #include - -#ifdef CONFIG_SMP -#include -#endif +#include +#include void __delay(unsigned long loops) { @@ -27,24 +25,43 @@ void __delay(unsigned long loops) * yield the megahertz number of the cpu. The important function * is udelay and that is done using the tod clock. -- martin. */ - __asm__ __volatile__( - "0: brct %0,0b" - : /* no outputs */ : "r" ((loops/2) + 1)); + asm volatile("0: brct %0,0b" : : "d" ((loops/2) + 1)); } /* - * Waits for 'usecs' microseconds using the tod clock, giving up the time slice - * of the virtual PU inbetween to avoid congestion. + * Waits for 'usecs' microseconds using the TOD clock comparator. */ void __udelay(unsigned long usecs) { - uint64_t start_cc, end_cc; + u64 end, time, jiffy_timer = 0; + unsigned long flags, cr0, mask, dummy; + + local_irq_save(flags); + if (raw_irqs_disabled_flags(flags)) { + jiffy_timer = S390_lowcore.jiffy_timer; + S390_lowcore.jiffy_timer = -1ULL - (4096 << 12); + __ctl_store(cr0, 0, 0); + dummy = (cr0 & 0xffff00e0) | 0x00000800; + __ctl_load(dummy , 0, 0); + mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT; + } else + mask = psw_kernel_bits | PSW_MASK_WAIT | + PSW_MASK_EXT | PSW_MASK_IO; + + end = get_clock() + ((u64) usecs << 12); + do { + time = end < S390_lowcore.jiffy_timer ? + end : S390_lowcore.jiffy_timer; + set_clock_comparator(time); + trace_hardirqs_on(); + __load_psw_mask(mask); + local_irq_disable(); + } while (get_clock() < end); - if (usecs == 0) - return; - asm volatile ("STCK %0" : "=m" (start_cc)); - do { - cpu_relax(); - asm volatile ("STCK %0" : "=m" (end_cc)); - } while (((end_cc - start_cc)/4096) < usecs); + if (raw_irqs_disabled_flags(flags)) { + __ctl_load(cr0, 0, 0); + S390_lowcore.jiffy_timer = jiffy_timer; + } + set_clock_comparator(S390_lowcore.jiffy_timer); + local_irq_restore(flags); }