aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/lib
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2012-03-11 11:59:27 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2012-03-11 11:59:28 -0400
commit4c1051e37a0e2a941115c6fb7ba08c318f25a0f9 (patch)
treef228f1a90c0d7abb8308f275d0906dd7d1588ba3 /arch/s390/lib
parent8b646bd759086f6090fe27acf414c0b5faa737f4 (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.c31
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
17void __delay(unsigned long loops) 18void __delay(unsigned long loops)
18{ 19{
@@ -28,36 +29,33 @@ void __delay(unsigned long loops)
28 29
29static void __udelay_disabled(unsigned long long usecs) 30static 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
54static void __udelay_enabled(unsigned long long usecs) 55static 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);