diff options
Diffstat (limited to 'arch/s390/kernel/smp.c')
-rw-r--r-- | arch/s390/kernel/smp.c | 54 |
1 files changed, 27 insertions, 27 deletions
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index a668993ff577..db8f1115a3bf 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -59,14 +59,13 @@ enum { | |||
59 | CPU_STATE_CONFIGURED, | 59 | CPU_STATE_CONFIGURED, |
60 | }; | 60 | }; |
61 | 61 | ||
62 | static DEFINE_PER_CPU(struct cpu *, cpu_device); | ||
63 | |||
62 | struct pcpu { | 64 | struct pcpu { |
63 | struct cpu *cpu; | ||
64 | struct _lowcore *lowcore; /* lowcore page(s) for the cpu */ | 65 | struct _lowcore *lowcore; /* lowcore page(s) for the cpu */ |
65 | unsigned long async_stack; /* async stack for the cpu */ | ||
66 | unsigned long panic_stack; /* panic stack for the cpu */ | ||
67 | unsigned long ec_mask; /* bit mask for ec_xxx functions */ | 66 | unsigned long ec_mask; /* bit mask for ec_xxx functions */ |
68 | int state; /* physical cpu state */ | 67 | signed char state; /* physical cpu state */ |
69 | int polarization; /* physical polarization */ | 68 | signed char polarization; /* physical polarization */ |
70 | u16 address; /* physical cpu address */ | 69 | u16 address; /* physical cpu address */ |
71 | }; | 70 | }; |
72 | 71 | ||
@@ -173,25 +172,30 @@ static void pcpu_ec_call(struct pcpu *pcpu, int ec_bit) | |||
173 | pcpu_sigp_retry(pcpu, order, 0); | 172 | pcpu_sigp_retry(pcpu, order, 0); |
174 | } | 173 | } |
175 | 174 | ||
175 | #define ASYNC_FRAME_OFFSET (ASYNC_SIZE - STACK_FRAME_OVERHEAD - __PT_SIZE) | ||
176 | #define PANIC_FRAME_OFFSET (PAGE_SIZE - STACK_FRAME_OVERHEAD - __PT_SIZE) | ||
177 | |||
176 | static int pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu) | 178 | static int pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu) |
177 | { | 179 | { |
180 | unsigned long async_stack, panic_stack; | ||
178 | struct _lowcore *lc; | 181 | struct _lowcore *lc; |
179 | 182 | ||
180 | if (pcpu != &pcpu_devices[0]) { | 183 | if (pcpu != &pcpu_devices[0]) { |
181 | pcpu->lowcore = (struct _lowcore *) | 184 | pcpu->lowcore = (struct _lowcore *) |
182 | __get_free_pages(GFP_KERNEL | GFP_DMA, LC_ORDER); | 185 | __get_free_pages(GFP_KERNEL | GFP_DMA, LC_ORDER); |
183 | pcpu->async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER); | 186 | async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER); |
184 | pcpu->panic_stack = __get_free_page(GFP_KERNEL); | 187 | panic_stack = __get_free_page(GFP_KERNEL); |
185 | if (!pcpu->lowcore || !pcpu->panic_stack || !pcpu->async_stack) | 188 | if (!pcpu->lowcore || !panic_stack || !async_stack) |
186 | goto out; | 189 | goto out; |
190 | } else { | ||
191 | async_stack = pcpu->lowcore->async_stack - ASYNC_FRAME_OFFSET; | ||
192 | panic_stack = pcpu->lowcore->panic_stack - PANIC_FRAME_OFFSET; | ||
187 | } | 193 | } |
188 | lc = pcpu->lowcore; | 194 | lc = pcpu->lowcore; |
189 | memcpy(lc, &S390_lowcore, 512); | 195 | memcpy(lc, &S390_lowcore, 512); |
190 | memset((char *) lc + 512, 0, sizeof(*lc) - 512); | 196 | memset((char *) lc + 512, 0, sizeof(*lc) - 512); |
191 | lc->async_stack = pcpu->async_stack + ASYNC_SIZE | 197 | lc->async_stack = async_stack + ASYNC_FRAME_OFFSET; |
192 | - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs); | 198 | lc->panic_stack = panic_stack + PANIC_FRAME_OFFSET; |
193 | lc->panic_stack = pcpu->panic_stack + PAGE_SIZE | ||
194 | - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs); | ||
195 | lc->cpu_nr = cpu; | 199 | lc->cpu_nr = cpu; |
196 | lc->spinlock_lockval = arch_spin_lockval(cpu); | 200 | lc->spinlock_lockval = arch_spin_lockval(cpu); |
197 | #ifndef CONFIG_64BIT | 201 | #ifndef CONFIG_64BIT |
@@ -212,8 +216,8 @@ static int pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu) | |||
212 | return 0; | 216 | return 0; |
213 | out: | 217 | out: |
214 | if (pcpu != &pcpu_devices[0]) { | 218 | if (pcpu != &pcpu_devices[0]) { |
215 | free_page(pcpu->panic_stack); | 219 | free_page(panic_stack); |
216 | free_pages(pcpu->async_stack, ASYNC_ORDER); | 220 | free_pages(async_stack, ASYNC_ORDER); |
217 | free_pages((unsigned long) pcpu->lowcore, LC_ORDER); | 221 | free_pages((unsigned long) pcpu->lowcore, LC_ORDER); |
218 | } | 222 | } |
219 | return -ENOMEM; | 223 | return -ENOMEM; |
@@ -235,11 +239,11 @@ static void pcpu_free_lowcore(struct pcpu *pcpu) | |||
235 | #else | 239 | #else |
236 | vdso_free_per_cpu(pcpu->lowcore); | 240 | vdso_free_per_cpu(pcpu->lowcore); |
237 | #endif | 241 | #endif |
238 | if (pcpu != &pcpu_devices[0]) { | 242 | if (pcpu == &pcpu_devices[0]) |
239 | free_page(pcpu->panic_stack); | 243 | return; |
240 | free_pages(pcpu->async_stack, ASYNC_ORDER); | 244 | free_page(pcpu->lowcore->panic_stack-PANIC_FRAME_OFFSET); |
241 | free_pages((unsigned long) pcpu->lowcore, LC_ORDER); | 245 | free_pages(pcpu->lowcore->async_stack-ASYNC_FRAME_OFFSET, ASYNC_ORDER); |
242 | } | 246 | free_pages((unsigned long) pcpu->lowcore, LC_ORDER); |
243 | } | 247 | } |
244 | 248 | ||
245 | #endif /* CONFIG_HOTPLUG_CPU */ | 249 | #endif /* CONFIG_HOTPLUG_CPU */ |
@@ -366,7 +370,8 @@ void smp_call_online_cpu(void (*func)(void *), void *data) | |||
366 | void smp_call_ipl_cpu(void (*func)(void *), void *data) | 370 | void smp_call_ipl_cpu(void (*func)(void *), void *data) |
367 | { | 371 | { |
368 | pcpu_delegate(&pcpu_devices[0], func, data, | 372 | pcpu_delegate(&pcpu_devices[0], func, data, |
369 | pcpu_devices->panic_stack + PAGE_SIZE); | 373 | pcpu_devices->lowcore->panic_stack - |
374 | PANIC_FRAME_OFFSET + PAGE_SIZE); | ||
370 | } | 375 | } |
371 | 376 | ||
372 | int smp_find_processor_id(u16 address) | 377 | int smp_find_processor_id(u16 address) |
@@ -935,10 +940,6 @@ void __init smp_prepare_boot_cpu(void) | |||
935 | pcpu->state = CPU_STATE_CONFIGURED; | 940 | pcpu->state = CPU_STATE_CONFIGURED; |
936 | pcpu->address = stap(); | 941 | pcpu->address = stap(); |
937 | pcpu->lowcore = (struct _lowcore *)(unsigned long) store_prefix(); | 942 | pcpu->lowcore = (struct _lowcore *)(unsigned long) store_prefix(); |
938 | pcpu->async_stack = S390_lowcore.async_stack - ASYNC_SIZE | ||
939 | + STACK_FRAME_OVERHEAD + sizeof(struct pt_regs); | ||
940 | pcpu->panic_stack = S390_lowcore.panic_stack - PAGE_SIZE | ||
941 | + STACK_FRAME_OVERHEAD + sizeof(struct pt_regs); | ||
942 | S390_lowcore.percpu_offset = __per_cpu_offset[0]; | 943 | S390_lowcore.percpu_offset = __per_cpu_offset[0]; |
943 | smp_cpu_set_polarization(0, POLARIZATION_UNKNOWN); | 944 | smp_cpu_set_polarization(0, POLARIZATION_UNKNOWN); |
944 | set_cpu_present(0, true); | 945 | set_cpu_present(0, true); |
@@ -1078,8 +1079,7 @@ static int smp_cpu_notify(struct notifier_block *self, unsigned long action, | |||
1078 | void *hcpu) | 1079 | void *hcpu) |
1079 | { | 1080 | { |
1080 | unsigned int cpu = (unsigned int)(long)hcpu; | 1081 | unsigned int cpu = (unsigned int)(long)hcpu; |
1081 | struct cpu *c = pcpu_devices[cpu].cpu; | 1082 | struct device *s = &per_cpu(cpu_device, cpu)->dev; |
1082 | struct device *s = &c->dev; | ||
1083 | int err = 0; | 1083 | int err = 0; |
1084 | 1084 | ||
1085 | switch (action & ~CPU_TASKS_FROZEN) { | 1085 | switch (action & ~CPU_TASKS_FROZEN) { |
@@ -1102,7 +1102,7 @@ static int smp_add_present_cpu(int cpu) | |||
1102 | c = kzalloc(sizeof(*c), GFP_KERNEL); | 1102 | c = kzalloc(sizeof(*c), GFP_KERNEL); |
1103 | if (!c) | 1103 | if (!c) |
1104 | return -ENOMEM; | 1104 | return -ENOMEM; |
1105 | pcpu_devices[cpu].cpu = c; | 1105 | per_cpu(cpu_device, cpu) = c; |
1106 | s = &c->dev; | 1106 | s = &c->dev; |
1107 | c->hotpluggable = 1; | 1107 | c->hotpluggable = 1; |
1108 | rc = register_cpu(c, cpu); | 1108 | rc = register_cpu(c, cpu); |