aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/lib/delay.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/lib/delay.c')
-rw-r--r--arch/s390/lib/delay.c31
1 files changed, 24 insertions, 7 deletions
diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c
index 752b362bf651..a65229d91c92 100644
--- a/arch/s390/lib/delay.c
+++ b/arch/s390/lib/delay.c
@@ -12,6 +12,7 @@
12#include <linux/module.h> 12#include <linux/module.h>
13#include <linux/irqflags.h> 13#include <linux/irqflags.h>
14#include <linux/interrupt.h> 14#include <linux/interrupt.h>
15#include <asm/div64.h>
15 16
16void __delay(unsigned long loops) 17void __delay(unsigned long loops)
17{ 18{
@@ -29,21 +30,24 @@ static void __udelay_disabled(unsigned long long usecs)
29{ 30{
30 unsigned long mask, cr0, cr0_saved; 31 unsigned long mask, cr0, cr0_saved;
31 u64 clock_saved; 32 u64 clock_saved;
33 u64 end;
32 34
35 mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT;
36 end = get_clock() + (usecs << 12);
33 clock_saved = local_tick_disable(); 37 clock_saved = local_tick_disable();
34 set_clock_comparator(get_clock() + (usecs << 12));
35 __ctl_store(cr0_saved, 0, 0); 38 __ctl_store(cr0_saved, 0, 0);
36 cr0 = (cr0_saved & 0xffff00e0) | 0x00000800; 39 cr0 = (cr0_saved & 0xffff00e0) | 0x00000800;
37 __ctl_load(cr0 , 0, 0); 40 __ctl_load(cr0 , 0, 0);
38 mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT;
39 lockdep_off(); 41 lockdep_off();
40 trace_hardirqs_on(); 42 do {
41 __load_psw_mask(mask); 43 set_clock_comparator(end);
42 local_irq_disable(); 44 trace_hardirqs_on();
45 __load_psw_mask(mask);
46 local_irq_disable();
47 } while (get_clock() < end);
43 lockdep_on(); 48 lockdep_on();
44 __ctl_load(cr0_saved, 0, 0); 49 __ctl_load(cr0_saved, 0, 0);
45 local_tick_enable(clock_saved); 50 local_tick_enable(clock_saved);
46 set_clock_comparator(S390_lowcore.clock_comparator);
47} 51}
48 52
49static void __udelay_enabled(unsigned long long usecs) 53static void __udelay_enabled(unsigned long long usecs)
@@ -66,7 +70,6 @@ static void __udelay_enabled(unsigned long long usecs)
66 if (clock_saved) 70 if (clock_saved)
67 local_tick_enable(clock_saved); 71 local_tick_enable(clock_saved);
68 } while (get_clock() < end); 72 } while (get_clock() < end);
69 set_clock_comparator(S390_lowcore.clock_comparator);
70} 73}
71 74
72/* 75/*
@@ -114,3 +117,17 @@ void udelay_simple(unsigned long long usecs)
114 while (get_clock() < end) 117 while (get_clock() < end)
115 cpu_relax(); 118 cpu_relax();
116} 119}
120
121void __ndelay(unsigned long long nsecs)
122{
123 u64 end;
124
125 nsecs <<= 9;
126 do_div(nsecs, 125);
127 end = get_clock() + nsecs;
128 if (nsecs & ~0xfffUL)
129 __udelay(nsecs >> 12);
130 while (get_clock() < end)
131 barrier();
132}
133EXPORT_SYMBOL(__ndelay);