aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVineet Gupta <vgupta@synopsys.com>2013-11-26 04:53:44 -0500
committerVineet Gupta <vgupta@synopsys.com>2013-12-23 01:35:04 -0500
commitf2a4aa5646687f9a51616581221b1d348590d47e (patch)
tree19845c1811e71f6b2ee3d4837b3b1a8caeb47be3
parent53dc110c97436dcf2a758091c98093657116e91c (diff)
ARC: [SMP] simplify IPI code
* ipi_data is just a word, no need to keep it as struct * find_next_bit() not needed to loop thru a 32bit word, ffs suffices
-rw-r--r--arch/arc/kernel/smp.c56
1 files changed, 28 insertions, 28 deletions
diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c
index 467dd9cca18f..c00c612e8dd3 100644
--- a/arch/arc/kernel/smp.c
+++ b/arch/arc/kernel/smp.c
@@ -197,37 +197,31 @@ int __init setup_profiling_timer(unsigned int multiplier)
197/* Inter Processor Interrupt Handling */ 197/* Inter Processor Interrupt Handling */
198/*****************************************************************************/ 198/*****************************************************************************/
199 199
200/*
201 * structures for inter-processor calls
202 * A Collection of single bit ipi messages
203 *
204 */
205
206/*
207 * TODO_rajesh investigate tlb message types.
208 * IPI Timer not needed because each ARC has an individual Interrupting Timer
209 */
210enum ipi_msg_type { 200enum ipi_msg_type {
211 IPI_NOP = 0, 201 IPI_EMPTY = 0,
212 IPI_RESCHEDULE = 1, 202 IPI_RESCHEDULE = 1,
213 IPI_CALL_FUNC, 203 IPI_CALL_FUNC,
214 IPI_CPU_STOP 204 IPI_CPU_STOP,
215}; 205};
216 206
217struct ipi_data { 207/*
218 unsigned long bits; 208 * In arches with IRQ for each msg type (above), receiver can use IRQ-id to
219}; 209 * figure out what msg was sent. For those which don't (ARC has dedicated IPI
210 * IRQ), the msg-type needs to be conveyed via per-cpu data
211 */
220 212
221static DEFINE_PER_CPU(struct ipi_data, ipi_data); 213static DEFINE_PER_CPU(unsigned long, ipi_data);
222 214
223static void ipi_send_msg_one(int cpu, enum ipi_msg_type msg) 215static void ipi_send_msg_one(int cpu, enum ipi_msg_type msg)
224{ 216{
225 struct ipi_data *ipi = &per_cpu(ipi_data, cpu); 217 unsigned long __percpu *ipi_data_ptr = per_cpu_ptr(&ipi_data, cpu);
226 unsigned long flags; 218 unsigned long flags;
227 219
220 pr_debug("%d Sending msg [%d] to %d\n", smp_processor_id(), msg, cpu);
221
228 local_irq_save(flags); 222 local_irq_save(flags);
229 223
230 set_bit(msg, &ipi->bits); 224 set_bit(msg, ipi_data_ptr);
231 225
232 /* Call the platform specific cross-CPU call function */ 226 /* Call the platform specific cross-CPU call function */
233 if (plat_smp_ops.ipi_send) 227 if (plat_smp_ops.ipi_send)
@@ -275,12 +269,11 @@ static void ipi_cpu_stop(void)
275 machine_halt(); 269 machine_halt();
276} 270}
277 271
278static inline void __do_IPI(unsigned long *ops, struct ipi_data *ipi) 272static inline void __do_IPI(unsigned long pending)
279{ 273{
280 unsigned long msg = 0; 274 while (pending) {
281 275
282 do { 276 unsigned long msg = __ffs(pending);
283 msg = find_next_bit(ops, BITS_PER_LONG, msg+1);
284 277
285 switch (msg) { 278 switch (msg) {
286 case IPI_RESCHEDULE: 279 case IPI_RESCHEDULE:
@@ -294,8 +287,14 @@ static inline void __do_IPI(unsigned long *ops, struct ipi_data *ipi)
294 case IPI_CPU_STOP: 287 case IPI_CPU_STOP:
295 ipi_cpu_stop(); 288 ipi_cpu_stop();
296 break; 289 break;
290
291 default:
292 pr_warn("IPI missing msg\n");
293
297 } 294 }
298 } while (msg < BITS_PER_LONG); 295
296 pending &= ~(1U << msg);
297 }
299} 298}
300 299
301/* 300/*
@@ -304,9 +303,10 @@ static inline void __do_IPI(unsigned long *ops, struct ipi_data *ipi)
304 */ 303 */
305irqreturn_t do_IPI(int irq, void *dev_id) 304irqreturn_t do_IPI(int irq, void *dev_id)
306{ 305{
307 int cpu = smp_processor_id(); 306 unsigned long pending;
308 struct ipi_data *ipi = &per_cpu(ipi_data, cpu); 307
309 unsigned long ops; 308 pr_debug("IPI [%ld] received on cpu %d\n",
309 *this_cpu_ptr(&ipi_data), smp_processor_id());
310 310
311 if (plat_smp_ops.ipi_clear) 311 if (plat_smp_ops.ipi_clear)
312 plat_smp_ops.ipi_clear(irq); 312 plat_smp_ops.ipi_clear(irq);
@@ -315,8 +315,8 @@ irqreturn_t do_IPI(int irq, void *dev_id)
315 * XXX: is this loop really needed 315 * XXX: is this loop really needed
316 * And do we need to move ipi_clean inside 316 * And do we need to move ipi_clean inside
317 */ 317 */
318 while ((ops = xchg(&ipi->bits, 0)) != 0) 318 while ((pending = xchg(this_cpu_ptr(&ipi_data), 0)) != 0)
319 __do_IPI(&ops, ipi); 319 __do_IPI(pending);
320 320
321 return IRQ_HANDLED; 321 return IRQ_HANDLED;
322} 322}