diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2012-03-11 11:59:27 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2012-03-11 11:59:28 -0400 |
commit | 4c1051e37a0e2a941115c6fb7ba08c318f25a0f9 (patch) | |
tree | f228f1a90c0d7abb8308f275d0906dd7d1588ba3 /arch/s390/lib | |
parent | 8b646bd759086f6090fe27acf414c0b5faa737f4 (diff) |
[S390] rework idle code
Whenever the cpu loads an enabled wait PSW it will appear as idle to the
underlying host system. The code in default_idle calls vtime_stop_cpu
which does the necessary voodoo to get the cpu time accounting right.
The udelay code just loads an enabled wait PSW. To correct this rework
the vtime_stop_cpu/vtime_start_cpu logic and move the difficult parts
to entry[64].S, vtime_stop_cpu can now be called from anywhere and
vtime_start_cpu is gone. The correction of the cpu time during wakeup
from an enabled wait PSW is done with a critical section in entry[64].S.
As vtime_start_cpu is gone, s390_idle_check can be removed as well.
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/lib')
-rw-r--r-- | arch/s390/lib/delay.c | 31 |
1 files changed, 14 insertions, 17 deletions
diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c index db92f044024c..9f1f71e85778 100644 --- a/arch/s390/lib/delay.c +++ b/arch/s390/lib/delay.c | |||
@@ -13,6 +13,7 @@ | |||
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 | #include <asm/div64.h> |
16 | #include <asm/timer.h> | ||
16 | 17 | ||
17 | void __delay(unsigned long loops) | 18 | void __delay(unsigned long loops) |
18 | { | 19 | { |
@@ -28,36 +29,33 @@ void __delay(unsigned long loops) | |||
28 | 29 | ||
29 | static void __udelay_disabled(unsigned long long usecs) | 30 | static void __udelay_disabled(unsigned long long usecs) |
30 | { | 31 | { |
31 | unsigned long mask, cr0, cr0_saved; | 32 | unsigned long cr0, cr6, new; |
32 | u64 clock_saved; | 33 | u64 clock_saved, end; |
33 | u64 end; | ||
34 | 34 | ||
35 | mask = psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_WAIT | | ||
36 | PSW_MASK_EXT | PSW_MASK_MCHECK; | ||
37 | end = get_clock() + (usecs << 12); | 35 | end = get_clock() + (usecs << 12); |
38 | clock_saved = local_tick_disable(); | 36 | clock_saved = local_tick_disable(); |
39 | __ctl_store(cr0_saved, 0, 0); | 37 | __ctl_store(cr0, 0, 0); |
40 | cr0 = (cr0_saved & 0xffff00e0) | 0x00000800; | 38 | __ctl_store(cr6, 6, 6); |
41 | __ctl_load(cr0 , 0, 0); | 39 | new = (cr0 & 0xffff00e0) | 0x00000800; |
40 | __ctl_load(new , 0, 0); | ||
41 | new = 0; | ||
42 | __ctl_load(new, 6, 6); | ||
42 | lockdep_off(); | 43 | lockdep_off(); |
43 | do { | 44 | do { |
44 | set_clock_comparator(end); | 45 | set_clock_comparator(end); |
45 | trace_hardirqs_on(); | 46 | vtime_stop_cpu(); |
46 | __load_psw_mask(mask); | ||
47 | local_irq_disable(); | 47 | local_irq_disable(); |
48 | } while (get_clock() < end); | 48 | } while (get_clock() < end); |
49 | lockdep_on(); | 49 | lockdep_on(); |
50 | __ctl_load(cr0_saved, 0, 0); | 50 | __ctl_load(cr0, 0, 0); |
51 | __ctl_load(cr6, 6, 6); | ||
51 | local_tick_enable(clock_saved); | 52 | local_tick_enable(clock_saved); |
52 | } | 53 | } |
53 | 54 | ||
54 | static void __udelay_enabled(unsigned long long usecs) | 55 | static void __udelay_enabled(unsigned long long usecs) |
55 | { | 56 | { |
56 | unsigned long mask; | 57 | u64 clock_saved, end; |
57 | u64 clock_saved; | ||
58 | u64 end; | ||
59 | 58 | ||
60 | mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT | PSW_MASK_IO; | ||
61 | end = get_clock() + (usecs << 12); | 59 | end = get_clock() + (usecs << 12); |
62 | do { | 60 | do { |
63 | clock_saved = 0; | 61 | clock_saved = 0; |
@@ -65,8 +63,7 @@ static void __udelay_enabled(unsigned long long usecs) | |||
65 | clock_saved = local_tick_disable(); | 63 | clock_saved = local_tick_disable(); |
66 | set_clock_comparator(end); | 64 | set_clock_comparator(end); |
67 | } | 65 | } |
68 | trace_hardirqs_on(); | 66 | vtime_stop_cpu(); |
69 | __load_psw_mask(mask); | ||
70 | local_irq_disable(); | 67 | local_irq_disable(); |
71 | if (clock_saved) | 68 | if (clock_saved) |
72 | local_tick_enable(clock_saved); | 69 | local_tick_enable(clock_saved); |