diff options
Diffstat (limited to 'arch/s390/lib/delay.c')
-rw-r--r-- | arch/s390/lib/delay.c | 31 |
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 | ||
16 | void __delay(unsigned long loops) | 17 | void __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 | ||
49 | static void __udelay_enabled(unsigned long long usecs) | 53 | static 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 | |||
121 | void __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 | } | ||
133 | EXPORT_SYMBOL(__ndelay); | ||