aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/Kconfig4
-rw-r--r--arch/s390/Makefile12
-rw-r--r--arch/s390/defconfig21
-rw-r--r--arch/s390/kernel/early.c5
-rw-r--r--arch/s390/kernel/head31.S15
-rw-r--r--arch/s390/kernel/head64.S16
-rw-r--r--arch/s390/kernel/ipl.c33
-rw-r--r--arch/s390/kernel/setup.c10
-rw-r--r--arch/s390/kernel/smp.c182
-rw-r--r--arch/s390/kernel/time.c10
-rw-r--r--arch/s390/lib/delay.c7
-rw-r--r--arch/s390/mm/init.c2
12 files changed, 144 insertions, 173 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index eaaac3788110..d9425f59be91 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -8,8 +8,8 @@ config MMU
8 default y 8 default y
9 9
10config ZONE_DMA 10config ZONE_DMA
11 bool 11 def_bool y
12 default y 12 depends on 64BIT
13 13
14config LOCKDEP_SUPPORT 14config LOCKDEP_SUPPORT
15 bool 15 bool
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index 6598e5268573..b1e558496469 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -82,18 +82,18 @@ AFLAGS += $(aflags-y)
82OBJCOPYFLAGS := -O binary 82OBJCOPYFLAGS := -O binary
83LDFLAGS_vmlinux := -e start 83LDFLAGS_vmlinux := -e start
84 84
85head-y := arch/$(ARCH)/kernel/head.o arch/$(ARCH)/kernel/init_task.o 85head-y := arch/s390/kernel/head.o arch/s390/kernel/init_task.o
86 86
87core-y += arch/$(ARCH)/mm/ arch/$(ARCH)/kernel/ arch/$(ARCH)/crypto/ \ 87core-y += arch/s390/mm/ arch/s390/kernel/ arch/s390/crypto/ \
88 arch/$(ARCH)/appldata/ arch/$(ARCH)/hypfs/ 88 arch/s390/appldata/ arch/s390/hypfs/
89libs-y += arch/$(ARCH)/lib/ 89libs-y += arch/s390/lib/
90drivers-y += drivers/s390/ 90drivers-y += drivers/s390/
91drivers-$(CONFIG_MATHEMU) += arch/$(ARCH)/math-emu/ 91drivers-$(CONFIG_MATHEMU) += arch/s390/math-emu/
92 92
93# must be linked after kernel 93# must be linked after kernel
94drivers-$(CONFIG_OPROFILE) += arch/s390/oprofile/ 94drivers-$(CONFIG_OPROFILE) += arch/s390/oprofile/
95 95
96boot := arch/$(ARCH)/boot 96boot := arch/s390/boot
97 97
98all: image 98all: image
99 99
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index 1406400bf3ea..741d2bbb2b37 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,9 +1,10 @@
1# 1#
2# Automatically generated make config: don't edit 2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.20-rc1 3# Linux kernel version: 2.6.21-rc1
4# Fri Dec 15 16:52:28 2006 4# Wed Feb 21 10:44:30 2007
5# 5#
6CONFIG_MMU=y 6CONFIG_MMU=y
7CONFIG_ZONE_DMA=y
7CONFIG_LOCKDEP_SUPPORT=y 8CONFIG_LOCKDEP_SUPPORT=y
8CONFIG_STACKTRACE_SUPPORT=y 9CONFIG_STACKTRACE_SUPPORT=y
9CONFIG_RWSEM_XCHGADD_ALGORITHM=y 10CONFIG_RWSEM_XCHGADD_ALGORITHM=y
@@ -11,6 +12,7 @@ CONFIG_RWSEM_XCHGADD_ALGORITHM=y
11# CONFIG_ARCH_HAS_ILOG2_U64 is not set 12# CONFIG_ARCH_HAS_ILOG2_U64 is not set
12CONFIG_GENERIC_HWEIGHT=y 13CONFIG_GENERIC_HWEIGHT=y
13CONFIG_GENERIC_TIME=y 14CONFIG_GENERIC_TIME=y
15CONFIG_NO_IOMEM=y
14CONFIG_S390=y 16CONFIG_S390=y
15CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" 17CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
16 18
@@ -29,6 +31,7 @@ CONFIG_LOCALVERSION_AUTO=y
29CONFIG_SWAP=y 31CONFIG_SWAP=y
30CONFIG_SYSVIPC=y 32CONFIG_SYSVIPC=y
31# CONFIG_IPC_NS is not set 33# CONFIG_IPC_NS is not set
34CONFIG_SYSVIPC_SYSCTL=y
32CONFIG_POSIX_MQUEUE=y 35CONFIG_POSIX_MQUEUE=y
33# CONFIG_BSD_PROCESS_ACCT is not set 36# CONFIG_BSD_PROCESS_ACCT is not set
34# CONFIG_TASKSTATS is not set 37# CONFIG_TASKSTATS is not set
@@ -133,6 +136,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
133# CONFIG_SPARSEMEM_STATIC is not set 136# CONFIG_SPARSEMEM_STATIC is not set
134CONFIG_SPLIT_PTLOCK_CPUS=4 137CONFIG_SPLIT_PTLOCK_CPUS=4
135CONFIG_RESOURCES_64BIT=y 138CONFIG_RESOURCES_64BIT=y
139CONFIG_ZONE_DMA_FLAG=1
136CONFIG_HOLES_IN_ZONE=y 140CONFIG_HOLES_IN_ZONE=y
137 141
138# 142#
@@ -178,7 +182,9 @@ CONFIG_UNIX=y
178CONFIG_XFRM=y 182CONFIG_XFRM=y
179# CONFIG_XFRM_USER is not set 183# CONFIG_XFRM_USER is not set
180# CONFIG_XFRM_SUB_POLICY is not set 184# CONFIG_XFRM_SUB_POLICY is not set
185# CONFIG_XFRM_MIGRATE is not set
181CONFIG_NET_KEY=y 186CONFIG_NET_KEY=y
187# CONFIG_NET_KEY_MIGRATE is not set
182CONFIG_IUCV=m 188CONFIG_IUCV=m
183CONFIG_AFIUCV=m 189CONFIG_AFIUCV=m
184CONFIG_INET=y 190CONFIG_INET=y
@@ -195,7 +201,7 @@ CONFIG_IP_FIB_HASH=y
195# CONFIG_INET_ESP is not set 201# CONFIG_INET_ESP is not set
196# CONFIG_INET_IPCOMP is not set 202# CONFIG_INET_IPCOMP is not set
197# CONFIG_INET_XFRM_TUNNEL is not set 203# CONFIG_INET_XFRM_TUNNEL is not set
198# CONFIG_INET_TUNNEL is not set 204CONFIG_INET_TUNNEL=y
199CONFIG_INET_XFRM_MODE_TRANSPORT=y 205CONFIG_INET_XFRM_MODE_TRANSPORT=y
200CONFIG_INET_XFRM_MODE_TUNNEL=y 206CONFIG_INET_XFRM_MODE_TUNNEL=y
201CONFIG_INET_XFRM_MODE_BEET=y 207CONFIG_INET_XFRM_MODE_BEET=y
@@ -313,6 +319,7 @@ CONFIG_STANDALONE=y
313CONFIG_PREVENT_FIRMWARE_BUILD=y 319CONFIG_PREVENT_FIRMWARE_BUILD=y
314# CONFIG_FW_LOADER is not set 320# CONFIG_FW_LOADER is not set
315# CONFIG_DEBUG_DRIVER is not set 321# CONFIG_DEBUG_DRIVER is not set
322# CONFIG_DEBUG_DEVRES is not set
316CONFIG_SYS_HYPERVISOR=y 323CONFIG_SYS_HYPERVISOR=y
317 324
318# 325#
@@ -686,13 +693,13 @@ CONFIG_HEADERS_CHECK=y
686CONFIG_DEBUG_KERNEL=y 693CONFIG_DEBUG_KERNEL=y
687CONFIG_LOG_BUF_SHIFT=17 694CONFIG_LOG_BUF_SHIFT=17
688# CONFIG_SCHEDSTATS is not set 695# CONFIG_SCHEDSTATS is not set
696# CONFIG_TIMER_STATS is not set
689# CONFIG_DEBUG_SLAB is not set 697# CONFIG_DEBUG_SLAB is not set
690CONFIG_DEBUG_PREEMPT=y 698CONFIG_DEBUG_PREEMPT=y
691# CONFIG_DEBUG_RT_MUTEXES is not set 699# CONFIG_DEBUG_RT_MUTEXES is not set
692# CONFIG_RT_MUTEX_TESTER is not set 700# CONFIG_RT_MUTEX_TESTER is not set
693CONFIG_DEBUG_SPINLOCK=y 701CONFIG_DEBUG_SPINLOCK=y
694CONFIG_DEBUG_MUTEXES=y 702CONFIG_DEBUG_MUTEXES=y
695# CONFIG_DEBUG_RWSEMS is not set
696# CONFIG_DEBUG_LOCK_ALLOC is not set 703# CONFIG_DEBUG_LOCK_ALLOC is not set
697# CONFIG_PROVE_LOCKING is not set 704# CONFIG_PROVE_LOCKING is not set
698CONFIG_DEBUG_SPINLOCK_SLEEP=y 705CONFIG_DEBUG_SPINLOCK_SLEEP=y
@@ -702,10 +709,10 @@ CONFIG_DEBUG_SPINLOCK_SLEEP=y
702# CONFIG_DEBUG_VM is not set 709# CONFIG_DEBUG_VM is not set
703# CONFIG_DEBUG_LIST is not set 710# CONFIG_DEBUG_LIST is not set
704# CONFIG_FRAME_POINTER is not set 711# CONFIG_FRAME_POINTER is not set
705# CONFIG_UNWIND_INFO is not set
706CONFIG_FORCED_INLINING=y 712CONFIG_FORCED_INLINING=y
707# CONFIG_RCU_TORTURE_TEST is not set 713# CONFIG_RCU_TORTURE_TEST is not set
708# CONFIG_LKDTM is not set 714# CONFIG_LKDTM is not set
715# CONFIG_FAULT_INJECTION is not set
709 716
710# 717#
711# Security options 718# Security options
@@ -733,8 +740,10 @@ CONFIG_CRYPTO_MANAGER=y
733# CONFIG_CRYPTO_GF128MUL is not set 740# CONFIG_CRYPTO_GF128MUL is not set
734CONFIG_CRYPTO_ECB=m 741CONFIG_CRYPTO_ECB=m
735CONFIG_CRYPTO_CBC=y 742CONFIG_CRYPTO_CBC=y
743CONFIG_CRYPTO_PCBC=m
736# CONFIG_CRYPTO_LRW is not set 744# CONFIG_CRYPTO_LRW is not set
737# CONFIG_CRYPTO_DES is not set 745# CONFIG_CRYPTO_DES is not set
746CONFIG_CRYPTO_FCRYPT=m
738# CONFIG_CRYPTO_BLOWFISH is not set 747# CONFIG_CRYPTO_BLOWFISH is not set
739# CONFIG_CRYPTO_TWOFISH is not set 748# CONFIG_CRYPTO_TWOFISH is not set
740# CONFIG_CRYPTO_SERPENT is not set 749# CONFIG_CRYPTO_SERPENT is not set
@@ -748,6 +757,7 @@ CONFIG_CRYPTO_CBC=y
748# CONFIG_CRYPTO_DEFLATE is not set 757# CONFIG_CRYPTO_DEFLATE is not set
749# CONFIG_CRYPTO_MICHAEL_MIC is not set 758# CONFIG_CRYPTO_MICHAEL_MIC is not set
750# CONFIG_CRYPTO_CRC32C is not set 759# CONFIG_CRYPTO_CRC32C is not set
760CONFIG_CRYPTO_CAMELLIA=m
751# CONFIG_CRYPTO_TEST is not set 761# CONFIG_CRYPTO_TEST is not set
752 762
753# 763#
@@ -768,4 +778,3 @@ CONFIG_BITREVERSE=m
768CONFIG_CRC32=m 778CONFIG_CRC32=m
769# CONFIG_LIBCRC32C is not set 779# CONFIG_LIBCRC32C is not set
770CONFIG_PLIST=y 780CONFIG_PLIST=y
771CONFIG_IOMAP_COPY=y
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index e518dd53eff5..afca1c6f4d21 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -14,6 +14,7 @@
14#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/pfn.h> 15#include <linux/pfn.h>
16#include <linux/uaccess.h> 16#include <linux/uaccess.h>
17#include <asm/ipl.h>
17#include <asm/lowcore.h> 18#include <asm/lowcore.h>
18#include <asm/processor.h> 19#include <asm/processor.h>
19#include <asm/sections.h> 20#include <asm/sections.h>
@@ -109,7 +110,7 @@ static inline void create_kernel_nss(void) { }
109 */ 110 */
110static noinline __init void clear_bss_section(void) 111static noinline __init void clear_bss_section(void)
111{ 112{
112 memset(__bss_start, 0, _end - __bss_start); 113 memset(__bss_start, 0, __bss_stop - __bss_start);
113} 114}
114 115
115/* 116/*
@@ -129,7 +130,7 @@ static noinline __init void detect_machine_type(void)
129{ 130{
130 struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data; 131 struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data;
131 132
132 asm volatile("stidp %0" : "=m" (S390_lowcore.cpu_data.cpu_id)); 133 get_cpu_id(&S390_lowcore.cpu_data.cpu_id);
133 134
134 /* Running under z/VM ? */ 135 /* Running under z/VM ? */
135 if (cpuinfo->cpu_id.version == 0xff) 136 if (cpuinfo->cpu_id.version == 0xff)
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S
index 453fd3b4edea..da7c8bb80982 100644
--- a/arch/s390/kernel/head31.S
+++ b/arch/s390/kernel/head31.S
@@ -148,20 +148,9 @@ startup_continue:
148.Lstartup_init: 148.Lstartup_init:
149 .long startup_init 149 .long startup_init
150 150
151 .globl ipl_schib
152ipl_schib:
153 .rept 13
154 .long 0
155 .endr
156
157 .globl ipl_flags
158ipl_flags:
159 .long 0
160 .globl ipl_devno
161ipl_devno:
162 .word 0
163
164 .org 0x12000 151 .org 0x12000
152 .globl _ehead
153_ehead:
165#ifdef CONFIG_SHARED_KERNEL 154#ifdef CONFIG_SHARED_KERNEL
166 .org 0x100000 155 .org 0x100000
167#endif 156#endif
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index b8fec4e5c5d4..af09e18cc5d0 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -154,21 +154,9 @@ startup_continue:
154.Lparmaddr: 154.Lparmaddr:
155 .quad PARMAREA 155 .quad PARMAREA
156 156
157 .globl ipl_schib
158ipl_schib:
159 .rept 13
160 .long 0
161 .endr
162
163 .globl ipl_flags
164ipl_flags:
165 .long 0
166 .globl ipl_devno
167ipl_devno:
168 .word 0
169
170 .org 0x12000 157 .org 0x12000
171 158 .globl _ehead
159_ehead:
172#ifdef CONFIG_SHARED_KERNEL 160#ifdef CONFIG_SHARED_KERNEL
173 .org 0x100000 161 .org 0x100000
174#endif 162#endif
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 052259530651..5a863a3bf10c 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -14,6 +14,7 @@
14#include <linux/delay.h> 14#include <linux/delay.h>
15#include <linux/reboot.h> 15#include <linux/reboot.h>
16#include <linux/ctype.h> 16#include <linux/ctype.h>
17#include <asm/ipl.h>
17#include <asm/smp.h> 18#include <asm/smp.h>
18#include <asm/setup.h> 19#include <asm/setup.h>
19#include <asm/cpcmd.h> 20#include <asm/cpcmd.h>
@@ -42,6 +43,13 @@ enum ipl_type {
42#define IPL_FCP_STR "fcp" 43#define IPL_FCP_STR "fcp"
43#define IPL_NSS_STR "nss" 44#define IPL_NSS_STR "nss"
44 45
46/*
47 * Must be in data section since the bss section
48 * is not cleared when these are accessed.
49 */
50u16 ipl_devno __attribute__((__section__(".data"))) = 0;
51u32 ipl_flags __attribute__((__section__(".data"))) = 0;
52
45static char *ipl_type_str(enum ipl_type type) 53static char *ipl_type_str(enum ipl_type type)
46{ 54{
47 switch (type) { 55 switch (type) {
@@ -90,31 +98,10 @@ static char *shutdown_action_str(enum shutdown_action action)
90 case SHUTDOWN_STOP: 98 case SHUTDOWN_STOP:
91 return SHUTDOWN_STOP_STR; 99 return SHUTDOWN_STOP_STR;
92 default: 100 default:
93 BUG(); 101 return NULL;
94 } 102 }
95} 103}
96 104
97enum diag308_subcode {
98 DIAG308_IPL = 3,
99 DIAG308_DUMP = 4,
100 DIAG308_SET = 5,
101 DIAG308_STORE = 6,
102};
103
104enum diag308_ipl_type {
105 DIAG308_IPL_TYPE_FCP = 0,
106 DIAG308_IPL_TYPE_CCW = 2,
107};
108
109enum diag308_opt {
110 DIAG308_IPL_OPT_IPL = 0x10,
111 DIAG308_IPL_OPT_DUMP = 0x20,
112};
113
114enum diag308_rc {
115 DIAG308_RC_OK = 1,
116};
117
118static int diag308_set_works = 0; 105static int diag308_set_works = 0;
119 106
120static int reipl_capabilities = IPL_TYPE_UNKNOWN; 107static int reipl_capabilities = IPL_TYPE_UNKNOWN;
@@ -134,7 +121,7 @@ static struct ipl_parameter_block *dump_block_ccw;
134 121
135static enum shutdown_action on_panic_action = SHUTDOWN_STOP; 122static enum shutdown_action on_panic_action = SHUTDOWN_STOP;
136 123
137static int diag308(unsigned long subcode, void *addr) 124int diag308(unsigned long subcode, void *addr)
138{ 125{
139 register unsigned long _addr asm("0") = (unsigned long) addr; 126 register unsigned long _addr asm("0") = (unsigned long) addr;
140 register unsigned long _rc asm("1") = 0; 127 register unsigned long _rc asm("1") = 0;
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 50c5210fbc64..863c8d08c026 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -41,6 +41,7 @@
41#include <linux/ctype.h> 41#include <linux/ctype.h>
42#include <linux/reboot.h> 42#include <linux/reboot.h>
43 43
44#include <asm/ipl.h>
44#include <asm/uaccess.h> 45#include <asm/uaccess.h>
45#include <asm/system.h> 46#include <asm/system.h>
46#include <asm/smp.h> 47#include <asm/smp.h>
@@ -106,7 +107,7 @@ void __devinit cpu_init (void)
106 /* 107 /*
107 * Store processor id in lowcore (used e.g. in timer_interrupt) 108 * Store processor id in lowcore (used e.g. in timer_interrupt)
108 */ 109 */
109 asm volatile("stidp %0": "=m" (S390_lowcore.cpu_data.cpu_id)); 110 get_cpu_id(&S390_lowcore.cpu_data.cpu_id);
110 S390_lowcore.cpu_data.cpu_addr = addr; 111 S390_lowcore.cpu_data.cpu_addr = addr;
111 112
112 /* 113 /*
@@ -689,9 +690,14 @@ setup_memory(void)
689 psw_set_key(PAGE_DEFAULT_KEY); 690 psw_set_key(PAGE_DEFAULT_KEY);
690 691
691 free_bootmem_with_active_regions(0, max_pfn); 692 free_bootmem_with_active_regions(0, max_pfn);
692 reserve_bootmem(0, PFN_PHYS(start_pfn));
693 693
694 /* 694 /*
695 * Reserve memory used for lowcore/command line/kernel image.
696 */
697 reserve_bootmem(0, (unsigned long)_ehead);
698 reserve_bootmem((unsigned long)_stext,
699 PFN_PHYS(start_pfn) - (unsigned long)_stext);
700 /*
695 * Reserve the bootmem bitmap itself as well. We do this in two 701 * Reserve the bootmem bitmap itself as well. We do this in two
696 * steps (first step was init_bootmem()) because this catches 702 * steps (first step was init_bootmem()) because this catches
697 * the (very unlikely) case of us accidentally initializing the 703 * the (very unlikely) case of us accidentally initializing the
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 83a4ea6e3d60..ecaa432a99f8 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -31,6 +31,7 @@
31#include <linux/interrupt.h> 31#include <linux/interrupt.h>
32#include <linux/cpu.h> 32#include <linux/cpu.h>
33#include <linux/timex.h> 33#include <linux/timex.h>
34#include <asm/ipl.h>
34#include <asm/setup.h> 35#include <asm/setup.h>
35#include <asm/sigp.h> 36#include <asm/sigp.h>
36#include <asm/pgalloc.h> 37#include <asm/pgalloc.h>
@@ -54,19 +55,18 @@ cpumask_t cpu_possible_map = CPU_MASK_NONE;
54static struct task_struct *current_set[NR_CPUS]; 55static struct task_struct *current_set[NR_CPUS];
55 56
56static void smp_ext_bitcall(int, ec_bit_sig); 57static void smp_ext_bitcall(int, ec_bit_sig);
57static void smp_ext_bitcall_others(ec_bit_sig);
58 58
59/* 59/*
60 * Structure and data for smp_call_function(). This is designed to minimise 60 * Structure and data for __smp_call_function_map(). This is designed to
61 * static memory requirements. It also looks cleaner. 61 * minimise static memory requirements. It also looks cleaner.
62 */ 62 */
63static DEFINE_SPINLOCK(call_lock); 63static DEFINE_SPINLOCK(call_lock);
64 64
65struct call_data_struct { 65struct call_data_struct {
66 void (*func) (void *info); 66 void (*func) (void *info);
67 void *info; 67 void *info;
68 atomic_t started; 68 cpumask_t started;
69 atomic_t finished; 69 cpumask_t finished;
70 int wait; 70 int wait;
71}; 71};
72 72
@@ -81,118 +81,113 @@ static void do_call_function(void)
81 void *info = call_data->info; 81 void *info = call_data->info;
82 int wait = call_data->wait; 82 int wait = call_data->wait;
83 83
84 atomic_inc(&call_data->started); 84 cpu_set(smp_processor_id(), call_data->started);
85 (*func)(info); 85 (*func)(info);
86 if (wait) 86 if (wait)
87 atomic_inc(&call_data->finished); 87 cpu_set(smp_processor_id(), call_data->finished);;
88} 88}
89 89
90/* 90static void __smp_call_function_map(void (*func) (void *info), void *info,
91 * this function sends a 'generic call function' IPI to all other CPUs 91 int nonatomic, int wait, cpumask_t map)
92 * in the system.
93 */
94
95int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
96 int wait)
97/*
98 * [SUMMARY] Run a function on all other CPUs.
99 * <func> The function to run. This must be fast and non-blocking.
100 * <info> An arbitrary pointer to pass to the function.
101 * <nonatomic> currently unused.
102 * <wait> If true, wait (atomically) until function has completed on other CPUs.
103 * [RETURNS] 0 on success, else a negative status code. Does not return until
104 * remote CPUs are nearly ready to execute <<func>> or are or have executed.
105 *
106 * You must not call this function with disabled interrupts or from a
107 * hardware interrupt handler.
108 */
109{ 92{
110 struct call_data_struct data; 93 struct call_data_struct data;
111 int cpus = num_online_cpus()-1; 94 int cpu, local = 0;
112 95
113 if (cpus <= 0) 96 /*
114 return 0; 97 * Can deadlock when interrupts are disabled or if in wrong context,
98 * caller must disable preemption
99 */
100 WARN_ON(irqs_disabled() || in_irq() || preemptible());
115 101
116 /* Can deadlock when interrupts are disabled or if in wrong context */ 102 /*
117 WARN_ON(irqs_disabled() || in_irq()); 103 * Check for local function call. We have to have the same call order
104 * as in on_each_cpu() because of machine_restart_smp().
105 */
106 if (cpu_isset(smp_processor_id(), map)) {
107 local = 1;
108 cpu_clear(smp_processor_id(), map);
109 }
110
111 cpus_and(map, map, cpu_online_map);
112 if (cpus_empty(map))
113 goto out;
118 114
119 data.func = func; 115 data.func = func;
120 data.info = info; 116 data.info = info;
121 atomic_set(&data.started, 0); 117 data.started = CPU_MASK_NONE;
122 data.wait = wait; 118 data.wait = wait;
123 if (wait) 119 if (wait)
124 atomic_set(&data.finished, 0); 120 data.finished = CPU_MASK_NONE;
125 121
126 spin_lock_bh(&call_lock); 122 spin_lock_bh(&call_lock);
127 call_data = &data; 123 call_data = &data;
128 /* Send a message to all other CPUs and wait for them to respond */ 124
129 smp_ext_bitcall_others(ec_call_function); 125 for_each_cpu_mask(cpu, map)
126 smp_ext_bitcall(cpu, ec_call_function);
130 127
131 /* Wait for response */ 128 /* Wait for response */
132 while (atomic_read(&data.started) != cpus) 129 while (!cpus_equal(map, data.started))
133 cpu_relax(); 130 cpu_relax();
134 131
135 if (wait) 132 if (wait)
136 while (atomic_read(&data.finished) != cpus) 133 while (!cpus_equal(map, data.finished))
137 cpu_relax(); 134 cpu_relax();
135
138 spin_unlock_bh(&call_lock); 136 spin_unlock_bh(&call_lock);
139 137
140 return 0; 138out:
139 local_irq_disable();
140 if (local)
141 func(info);
142 local_irq_enable();
141} 143}
142 144
143/* 145/*
144 * Call a function on one CPU 146 * smp_call_function:
145 * cpu : the CPU the function should be executed on 147 * @func: the function to run; this must be fast and non-blocking
148 * @info: an arbitrary pointer to pass to the function
149 * @nonatomic: unused
150 * @wait: if true, wait (atomically) until function has completed on other CPUs
146 * 151 *
147 * You must not call this function with disabled interrupts or from a 152 * Run a function on all other CPUs.
148 * hardware interrupt handler. You may call it from a bottom half.
149 * 153 *
150 * It is guaranteed that the called function runs on the specified CPU, 154 * You must not call this function with disabled interrupts or from a
151 * preemption is disabled. 155 * hardware interrupt handler. Must be called with preemption disabled.
156 * You may call it from a bottom half.
152 */ 157 */
153int smp_call_function_on(void (*func) (void *info), void *info, 158int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
154 int nonatomic, int wait, int cpu) 159 int wait)
155{ 160{
156 struct call_data_struct data; 161 cpumask_t map;
157 int curr_cpu;
158
159 if (!cpu_online(cpu))
160 return -EINVAL;
161
162 /* Can deadlock when interrupts are disabled or if in wrong context */
163 WARN_ON(irqs_disabled() || in_irq());
164
165 /* disable preemption for local function call */
166 curr_cpu = get_cpu();
167
168 if (curr_cpu == cpu) {
169 /* direct call to function */
170 func(info);
171 put_cpu();
172 return 0;
173 }
174
175 data.func = func;
176 data.info = info;
177 atomic_set(&data.started, 0);
178 data.wait = wait;
179 if (wait)
180 atomic_set(&data.finished, 0);
181
182 spin_lock_bh(&call_lock);
183 call_data = &data;
184 smp_ext_bitcall(cpu, ec_call_function);
185 162
186 /* Wait for response */ 163 map = cpu_online_map;
187 while (atomic_read(&data.started) != 1) 164 cpu_clear(smp_processor_id(), map);
188 cpu_relax(); 165 __smp_call_function_map(func, info, nonatomic, wait, map);
166 return 0;
167}
168EXPORT_SYMBOL(smp_call_function);
189 169
190 if (wait) 170/*
191 while (atomic_read(&data.finished) != 1) 171 * smp_call_function_on:
192 cpu_relax(); 172 * @func: the function to run; this must be fast and non-blocking
173 * @info: an arbitrary pointer to pass to the function
174 * @nonatomic: unused
175 * @wait: if true, wait (atomically) until function has completed on other CPUs
176 * @cpu: the CPU where func should run
177 *
178 * Run a function on one processor.
179 *
180 * You must not call this function with disabled interrupts or from a
181 * hardware interrupt handler. Must be called with preemption disabled.
182 * You may call it from a bottom half.
183 */
184int smp_call_function_on(void (*func) (void *info), void *info, int nonatomic,
185 int wait, int cpu)
186{
187 cpumask_t map = CPU_MASK_NONE;
193 188
194 spin_unlock_bh(&call_lock); 189 cpu_set(cpu, map);
195 put_cpu(); 190 __smp_call_function_map(func, info, nonatomic, wait, map);
196 return 0; 191 return 0;
197} 192}
198EXPORT_SYMBOL(smp_call_function_on); 193EXPORT_SYMBOL(smp_call_function_on);
@@ -325,26 +320,6 @@ static void smp_ext_bitcall(int cpu, ec_bit_sig sig)
325 udelay(10); 320 udelay(10);
326} 321}
327 322
328/*
329 * Send an external call sigp to every other cpu in the system and
330 * return without waiting for its completion.
331 */
332static void smp_ext_bitcall_others(ec_bit_sig sig)
333{
334 int cpu;
335
336 for_each_online_cpu(cpu) {
337 if (cpu == smp_processor_id())
338 continue;
339 /*
340 * Set signaling bit in lowcore of target cpu and kick it
341 */
342 set_bit(sig, (unsigned long *) &lowcore_ptr[cpu]->ext_call_fast);
343 while (signal_processor(cpu, sigp_emergency_signal) == sigp_busy)
344 udelay(10);
345 }
346}
347
348#ifndef CONFIG_64BIT 323#ifndef CONFIG_64BIT
349/* 324/*
350 * this function sends a 'purge tlb' signal to another CPU. 325 * this function sends a 'purge tlb' signal to another CPU.
@@ -807,6 +782,5 @@ EXPORT_SYMBOL(cpu_possible_map);
807EXPORT_SYMBOL(lowcore_ptr); 782EXPORT_SYMBOL(lowcore_ptr);
808EXPORT_SYMBOL(smp_ctl_set_bit); 783EXPORT_SYMBOL(smp_ctl_set_bit);
809EXPORT_SYMBOL(smp_ctl_clear_bit); 784EXPORT_SYMBOL(smp_ctl_clear_bit);
810EXPORT_SYMBOL(smp_call_function);
811EXPORT_SYMBOL(smp_get_cpu); 785EXPORT_SYMBOL(smp_get_cpu);
812EXPORT_SYMBOL(smp_put_cpu); 786EXPORT_SYMBOL(smp_put_cpu);
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index ee9fd7b85928..e1ad464b6f20 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -747,6 +747,7 @@ static void etr_adjust_time(unsigned long long clock, unsigned long long delay)
747 } 747 }
748} 748}
749 749
750#ifdef CONFIG_SMP
750static void etr_sync_cpu_start(void *dummy) 751static void etr_sync_cpu_start(void *dummy)
751{ 752{
752 int *in_sync = dummy; 753 int *in_sync = dummy;
@@ -758,8 +759,14 @@ static void etr_sync_cpu_start(void *dummy)
758 * __udelay will stop the cpu on an enabled wait psw until the 759 * __udelay will stop the cpu on an enabled wait psw until the
759 * TOD is running again. 760 * TOD is running again.
760 */ 761 */
761 while (*in_sync == 0) 762 while (*in_sync == 0) {
762 __udelay(1); 763 __udelay(1);
764 /*
765 * A different cpu changes *in_sync. Therefore use
766 * barrier() to force memory access.
767 */
768 barrier();
769 }
763 if (*in_sync != 1) 770 if (*in_sync != 1)
764 /* Didn't work. Clear per-cpu in sync bit again. */ 771 /* Didn't work. Clear per-cpu in sync bit again. */
765 etr_disable_sync_clock(NULL); 772 etr_disable_sync_clock(NULL);
@@ -773,6 +780,7 @@ static void etr_sync_cpu_start(void *dummy)
773static void etr_sync_cpu_end(void *dummy) 780static void etr_sync_cpu_end(void *dummy)
774{ 781{
775} 782}
783#endif /* CONFIG_SMP */
776 784
777/* 785/*
778 * Sync the TOD clock using the port refered to by aibp. This port 786 * Sync the TOD clock using the port refered to by aibp. This port
diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c
index 02854449b74b..70f2a862b670 100644
--- a/arch/s390/lib/delay.c
+++ b/arch/s390/lib/delay.c
@@ -15,6 +15,7 @@
15#include <linux/delay.h> 15#include <linux/delay.h>
16#include <linux/timex.h> 16#include <linux/timex.h>
17#include <linux/irqflags.h> 17#include <linux/irqflags.h>
18#include <linux/interrupt.h>
18 19
19void __delay(unsigned long loops) 20void __delay(unsigned long loops)
20{ 21{
@@ -35,7 +36,11 @@ void __udelay(unsigned long usecs)
35{ 36{
36 u64 end, time, jiffy_timer = 0; 37 u64 end, time, jiffy_timer = 0;
37 unsigned long flags, cr0, mask, dummy; 38 unsigned long flags, cr0, mask, dummy;
39 int irq_context;
38 40
41 irq_context = in_interrupt();
42 if (!irq_context)
43 local_bh_disable();
39 local_irq_save(flags); 44 local_irq_save(flags);
40 if (raw_irqs_disabled_flags(flags)) { 45 if (raw_irqs_disabled_flags(flags)) {
41 jiffy_timer = S390_lowcore.jiffy_timer; 46 jiffy_timer = S390_lowcore.jiffy_timer;
@@ -62,6 +67,8 @@ void __udelay(unsigned long usecs)
62 __ctl_load(cr0, 0, 0); 67 __ctl_load(cr0, 0, 0);
63 S390_lowcore.jiffy_timer = jiffy_timer; 68 S390_lowcore.jiffy_timer = jiffy_timer;
64 } 69 }
70 if (!irq_context)
71 _local_bh_enable();
65 set_clock_comparator(S390_lowcore.jiffy_timer); 72 set_clock_comparator(S390_lowcore.jiffy_timer);
66 local_irq_restore(flags); 73 local_irq_restore(flags);
67} 74}
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index b3e7c45efb63..916b72a8cde8 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -141,7 +141,9 @@ void __init paging_init(void)
141 __raw_local_irq_ssm(ssm_mask); 141 __raw_local_irq_ssm(ssm_mask);
142 142
143 memset(max_zone_pfns, 0, sizeof(max_zone_pfns)); 143 memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
144#ifdef CONFIG_ZONE_DMA
144 max_zone_pfns[ZONE_DMA] = PFN_DOWN(MAX_DMA_ADDRESS); 145 max_zone_pfns[ZONE_DMA] = PFN_DOWN(MAX_DMA_ADDRESS);
146#endif
145 max_zone_pfns[ZONE_NORMAL] = max_low_pfn; 147 max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
146 free_area_init_nodes(max_zone_pfns); 148 free_area_init_nodes(max_zone_pfns);
147} 149}