Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[S390] convert s390 to generic IPI infrastructure

Since etr/stp don't need the old smp_call_function semantics anymore
we can convert s390 to the generic IPI infrastructure.

Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

authored by

Heiko Carstens and committed by
Martin Schwidefsky
ca9fc75a 0b3016b7

+24 -158
+1
arch/s390/Kconfig
··· 73 73 74 74 config S390 75 75 def_bool y 76 + select USE_GENERIC_SMP_HELPERS if SMP 76 77 select HAVE_OPROFILE 77 78 select HAVE_KPROBES 78 79 select HAVE_KRETPROBES
+1
arch/s390/include/asm/sigp.h
··· 61 61 { 62 62 ec_schedule=0, 63 63 ec_call_function, 64 + ec_call_function_single, 64 65 ec_bit_last 65 66 } ec_bit_sig; 66 67
+3 -2
arch/s390/include/asm/smp.h
··· 91 91 extern struct mutex smp_cpu_state_mutex; 92 92 extern int smp_cpu_polarization[]; 93 93 94 - extern int smp_call_function_mask(cpumask_t mask, void (*func)(void *), 95 - void *info, int wait); 94 + extern void arch_send_call_function_single_ipi(int cpu); 95 + extern void arch_send_call_function_ipi(cpumask_t mask); 96 + 96 97 #endif 97 98 98 99 #ifndef CONFIG_SMP
+19 -156
arch/s390/kernel/smp.c
··· 77 77 78 78 static void smp_ext_bitcall(int, ec_bit_sig); 79 79 80 - /* 81 - * Structure and data for __smp_call_function_map(). This is designed to 82 - * minimise static memory requirements. It also looks cleaner. 83 - */ 84 - static DEFINE_SPINLOCK(call_lock); 85 - 86 - struct call_data_struct { 87 - void (*func) (void *info); 88 - void *info; 89 - cpumask_t started; 90 - cpumask_t finished; 91 - int wait; 92 - }; 93 - 94 - static struct call_data_struct *call_data; 95 - 96 - /* 97 - * 'Call function' interrupt callback 98 - */ 99 - static void do_call_function(void) 100 - { 101 - void (*func) (void *info) = call_data->func; 102 - void *info = call_data->info; 103 - int wait = call_data->wait; 104 - 105 - cpu_set(smp_processor_id(), call_data->started); 106 - (*func)(info); 107 - if (wait) 108 - cpu_set(smp_processor_id(), call_data->finished);; 109 - } 110 - 111 - static void __smp_call_function_map(void (*func) (void *info), void *info, 112 - int wait, cpumask_t map) 113 - { 114 - struct call_data_struct data; 115 - int cpu, local = 0; 116 - 117 - /* 118 - * Can deadlock when interrupts are disabled or if in wrong context. 119 - */ 120 - WARN_ON(irqs_disabled() || in_irq()); 121 - 122 - /* 123 - * Check for local function call. We have to have the same call order 124 - * as in on_each_cpu() because of machine_restart_smp(). 125 - */ 126 - if (cpu_isset(smp_processor_id(), map)) { 127 - local = 1; 128 - cpu_clear(smp_processor_id(), map); 129 - } 130 - 131 - cpus_and(map, map, cpu_online_map); 132 - if (cpus_empty(map)) 133 - goto out; 134 - 135 - data.func = func; 136 - data.info = info; 137 - data.started = CPU_MASK_NONE; 138 - data.wait = wait; 139 - if (wait) 140 - data.finished = CPU_MASK_NONE; 141 - 142 - call_data = &data; 143 - 144 - for_each_cpu_mask(cpu, map) 145 - smp_ext_bitcall(cpu, ec_call_function); 146 - 147 - /* Wait for response */ 148 - while (!cpus_equal(map, data.started)) 149 - cpu_relax(); 150 - if (wait) 151 - while (!cpus_equal(map, data.finished)) 152 - cpu_relax(); 153 - out: 154 - if (local) { 155 - local_irq_disable(); 156 - func(info); 157 - local_irq_enable(); 158 - } 159 - } 160 - 161 - /* 162 - * smp_call_function: 163 - * @func: the function to run; this must be fast and non-blocking 164 - * @info: an arbitrary pointer to pass to the function 165 - * @wait: if true, wait (atomically) until function has completed on other CPUs 166 - * 167 - * Run a function on all other CPUs. 168 - * 169 - * You must not call this function with disabled interrupts, from a 170 - * hardware interrupt handler or from a bottom half. 171 - */ 172 - int smp_call_function(void (*func) (void *info), void *info, int wait) 173 - { 174 - cpumask_t map; 175 - 176 - spin_lock(&call_lock); 177 - map = cpu_online_map; 178 - cpu_clear(smp_processor_id(), map); 179 - __smp_call_function_map(func, info, wait, map); 180 - spin_unlock(&call_lock); 181 - return 0; 182 - } 183 - EXPORT_SYMBOL(smp_call_function); 184 - 185 - /* 186 - * smp_call_function_single: 187 - * @cpu: the CPU where func should run 188 - * @func: the function to run; this must be fast and non-blocking 189 - * @info: an arbitrary pointer to pass to the function 190 - * @wait: if true, wait (atomically) until function has completed on other CPUs 191 - * 192 - * Run a function on one processor. 193 - * 194 - * You must not call this function with disabled interrupts, from a 195 - * hardware interrupt handler or from a bottom half. 196 - */ 197 - int smp_call_function_single(int cpu, void (*func) (void *info), void *info, 198 - int wait) 199 - { 200 - spin_lock(&call_lock); 201 - __smp_call_function_map(func, info, wait, cpumask_of_cpu(cpu)); 202 - spin_unlock(&call_lock); 203 - return 0; 204 - } 205 - EXPORT_SYMBOL(smp_call_function_single); 206 - 207 - /** 208 - * smp_call_function_mask(): Run a function on a set of other CPUs. 209 - * @mask: The set of cpus to run on. Must not include the current cpu. 210 - * @func: The function to run. This must be fast and non-blocking. 211 - * @info: An arbitrary pointer to pass to the function. 212 - * @wait: If true, wait (atomically) until function has completed on other CPUs. 213 - * 214 - * Returns 0 on success, else a negative status code. 215 - * 216 - * If @wait is true, then returns once @func has returned; otherwise 217 - * it returns just before the target cpu calls @func. 218 - * 219 - * You must not call this function with disabled interrupts or from a 220 - * hardware interrupt handler or from a bottom half handler. 221 - */ 222 - int smp_call_function_mask(cpumask_t mask, void (*func)(void *), void *info, 223 - int wait) 224 - { 225 - spin_lock(&call_lock); 226 - cpu_clear(smp_processor_id(), mask); 227 - __smp_call_function_map(func, info, wait, mask); 228 - spin_unlock(&call_lock); 229 - return 0; 230 - } 231 - EXPORT_SYMBOL(smp_call_function_mask); 232 - 233 80 void smp_send_stop(void) 234 81 { 235 82 int cpu, rc; ··· 118 271 bits = xchg(&S390_lowcore.ext_call_fast, 0); 119 272 120 273 if (test_bit(ec_call_function, &bits)) 121 - do_call_function(); 274 + generic_smp_call_function_interrupt(); 275 + 276 + if (test_bit(ec_call_function_single, &bits)) 277 + generic_smp_call_function_single_interrupt(); 122 278 } 123 279 124 280 /* ··· 136 286 set_bit(sig, (unsigned long *) &lowcore_ptr[cpu]->ext_call_fast); 137 287 while (signal_processor(cpu, sigp_emergency_signal) == sigp_busy) 138 288 udelay(10); 289 + } 290 + 291 + void arch_send_call_function_ipi(cpumask_t mask) 292 + { 293 + int cpu; 294 + 295 + for_each_cpu_mask(cpu, mask) 296 + smp_ext_bitcall(cpu, ec_call_function); 297 + } 298 + 299 + void arch_send_call_function_single_ipi(int cpu) 300 + { 301 + smp_ext_bitcall(cpu, ec_call_function_single); 139 302 } 140 303 141 304 #ifndef CONFIG_64BIT ··· 451 588 /* call cpu notifiers */ 452 589 notify_cpu_starting(smp_processor_id()); 453 590 /* Mark this cpu as online */ 454 - spin_lock(&call_lock); 591 + ipi_call_lock(); 455 592 cpu_set(smp_processor_id(), cpu_online_map); 456 - spin_unlock(&call_lock); 593 + ipi_call_unlock(); 457 594 /* Switch on interrupts */ 458 595 local_irq_enable(); 459 596 /* Print info about this processor */