smp.c (9bd7de51ee8537094656149eaf45338cadb7d7d4) smp.c (e03cdade0ca945a04e982525e50fef275190b77b)
1/*
2 * linux/arch/arm/kernel/smp.c
3 *
4 * Copyright (C) 2002 ARM Limited, All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.

--- 8 unchanged lines hidden (view full) ---

17#include <linux/profile.h>
18#include <linux/errno.h>
19#include <linux/mm.h>
20#include <linux/err.h>
21#include <linux/cpu.h>
22#include <linux/smp.h>
23#include <linux/seq_file.h>
24#include <linux/irq.h>
1/*
2 * linux/arch/arm/kernel/smp.c
3 *
4 * Copyright (C) 2002 ARM Limited, All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.

--- 8 unchanged lines hidden (view full) ---

17#include <linux/profile.h>
18#include <linux/errno.h>
19#include <linux/mm.h>
20#include <linux/err.h>
21#include <linux/cpu.h>
22#include <linux/smp.h>
23#include <linux/seq_file.h>
24#include <linux/irq.h>
25#include <linux/percpu.h>
26#include <linux/clockchips.h>
25
26#include <asm/atomic.h>
27#include <asm/cacheflush.h>
28#include <asm/cpu.h>
29#include <asm/mmu_context.h>
30#include <asm/pgtable.h>
31#include <asm/pgalloc.h>
32#include <asm/processor.h>
33#include <asm/tlbflush.h>
34#include <asm/ptrace.h>
27
28#include <asm/atomic.h>
29#include <asm/cacheflush.h>
30#include <asm/cpu.h>
31#include <asm/mmu_context.h>
32#include <asm/pgtable.h>
33#include <asm/pgalloc.h>
34#include <asm/processor.h>
35#include <asm/tlbflush.h>
36#include <asm/ptrace.h>
37#include <asm/localtimer.h>
35
36/*
37 * as from 2.5, kernels no longer have an init_tasks structure
38 * so we need some other way of telling a new secondary core
39 * where to place its SVC stack
40 */
41struct secondary_data secondary_data;
42

--- 115 unchanged lines hidden (view full) ---

158 ret = mach_cpu_disable(cpu);
159 if (ret)
160 return ret;
161
162 /*
163 * Take this CPU offline. Once we clear this, we can't return,
164 * and we must not schedule until we're ready to give up the cpu.
165 */
38
39/*
40 * as from 2.5, kernels no longer have an init_tasks structure
41 * so we need some other way of telling a new secondary core
42 * where to place its SVC stack
43 */
44struct secondary_data secondary_data;
45

--- 115 unchanged lines hidden (view full) ---

161 ret = mach_cpu_disable(cpu);
162 if (ret)
163 return ret;
164
165 /*
166 * Take this CPU offline. Once we clear this, we can't return,
167 * and we must not schedule until we're ready to give up the cpu.
168 */
166 cpu_clear(cpu, cpu_online_map);
169 set_cpu_online(cpu, false);
167
168 /*
169 * OK - migrate IRQs away from this CPU
170 */
171 migrate_irqs();
172
173 /*
174 * Stop the local timer for this CPU.

--- 94 unchanged lines hidden (view full) ---

269 /*
270 * Enable local interrupts.
271 */
272 notify_cpu_starting(cpu);
273 local_irq_enable();
274 local_fiq_enable();
275
276 /*
170
171 /*
172 * OK - migrate IRQs away from this CPU
173 */
174 migrate_irqs();
175
176 /*
177 * Stop the local timer for this CPU.

--- 94 unchanged lines hidden (view full) ---

272 /*
273 * Enable local interrupts.
274 */
275 notify_cpu_starting(cpu);
276 local_irq_enable();
277 local_fiq_enable();
278
279 /*
277 * Setup local timer for this CPU.
280 * Setup the percpu timer for this CPU.
278 */
281 */
279 local_timer_setup();
282 percpu_timer_setup();
280
281 calibrate_delay();
282
283 smp_store_cpu_info(cpu);
284
285 /*
286 * OK, now it's safe to let the boot CPU continue
287 */
283
284 calibrate_delay();
285
286 smp_store_cpu_info(cpu);
287
288 /*
289 * OK, now it's safe to let the boot CPU continue
290 */
288 cpu_set(cpu, cpu_online_map);
291 set_cpu_online(cpu, true);
289
290 /*
291 * OK, it's off to the idle thread for us
292 */
293 cpu_idle();
294}
295
296/*

--- 81 unchanged lines hidden (view full) ---

378 seq_printf(p, "LOC: ");
379
380 for_each_present_cpu(cpu)
381 seq_printf(p, "%10u ", irq_stat[cpu].local_timer_irqs);
382
383 seq_putc(p, '\n');
384}
385
292
293 /*
294 * OK, it's off to the idle thread for us
295 */
296 cpu_idle();
297}
298
299/*

--- 81 unchanged lines hidden (view full) ---

381 seq_printf(p, "LOC: ");
382
383 for_each_present_cpu(cpu)
384 seq_printf(p, "%10u ", irq_stat[cpu].local_timer_irqs);
385
386 seq_putc(p, '\n');
387}
388
389/*
390 * Timer (local or broadcast) support
391 */
392static DEFINE_PER_CPU(struct clock_event_device, percpu_clockevent);
393
386static void ipi_timer(void)
387{
394static void ipi_timer(void)
395{
396 struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent);
388 irq_enter();
397 irq_enter();
389 local_timer_interrupt();
398 evt->event_handler(evt);
390 irq_exit();
391}
392
393#ifdef CONFIG_LOCAL_TIMERS
394asmlinkage void __exception do_local_timer(struct pt_regs *regs)
395{
396 struct pt_regs *old_regs = set_irq_regs(regs);
397 int cpu = smp_processor_id();
398
399 if (local_timer_ack()) {
400 irq_stat[cpu].local_timer_irqs++;
401 ipi_timer();
402 }
403
404 set_irq_regs(old_regs);
405}
406#endif
407
399 irq_exit();
400}
401
402#ifdef CONFIG_LOCAL_TIMERS
403asmlinkage void __exception do_local_timer(struct pt_regs *regs)
404{
405 struct pt_regs *old_regs = set_irq_regs(regs);
406 int cpu = smp_processor_id();
407
408 if (local_timer_ack()) {
409 irq_stat[cpu].local_timer_irqs++;
410 ipi_timer();
411 }
412
413 set_irq_regs(old_regs);
414}
415#endif
416
417#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
418static void smp_timer_broadcast(const struct cpumask *mask)
419{
420 send_ipi_message(mask, IPI_TIMER);
421}
422
423static void broadcast_timer_set_mode(enum clock_event_mode mode,
424 struct clock_event_device *evt)
425{
426}
427
428static void local_timer_setup(struct clock_event_device *evt)
429{
430 evt->name = "dummy_timer";
431 evt->features = CLOCK_EVT_FEAT_ONESHOT |
432 CLOCK_EVT_FEAT_PERIODIC |
433 CLOCK_EVT_FEAT_DUMMY;
434 evt->rating = 400;
435 evt->mult = 1;
436 evt->set_mode = broadcast_timer_set_mode;
437 evt->broadcast = smp_timer_broadcast;
438
439 clockevents_register_device(evt);
440}
441#endif
442
443void __cpuinit percpu_timer_setup(void)
444{
445 unsigned int cpu = smp_processor_id();
446 struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
447
448 evt->cpumask = cpumask_of(cpu);
449
450 local_timer_setup(evt);
451}
452
408static DEFINE_SPINLOCK(stop_lock);
409
410/*
411 * ipi_cpu_stop - handle IPI from smp_send_stop()
412 */
413static void ipi_cpu_stop(unsigned int cpu)
414{
415 spin_lock(&stop_lock);
416 printk(KERN_CRIT "CPU%u: stopping\n", cpu);
417 dump_stack();
418 spin_unlock(&stop_lock);
419
453static DEFINE_SPINLOCK(stop_lock);
454
455/*
456 * ipi_cpu_stop - handle IPI from smp_send_stop()
457 */
458static void ipi_cpu_stop(unsigned int cpu)
459{
460 spin_lock(&stop_lock);
461 printk(KERN_CRIT "CPU%u: stopping\n", cpu);
462 dump_stack();
463 spin_unlock(&stop_lock);
464
420 cpu_clear(cpu, cpu_online_map);
465 set_cpu_online(cpu, false);
421
422 local_fiq_disable();
423 local_irq_disable();
424
425 while (1)
426 cpu_relax();
427}
428

--- 67 unchanged lines hidden (view full) ---

496 set_irq_regs(old_regs);
497}
498
499void smp_send_reschedule(int cpu)
500{
501 send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE);
502}
503
466
467 local_fiq_disable();
468 local_irq_disable();
469
470 while (1)
471 cpu_relax();
472}
473

--- 67 unchanged lines hidden (view full) ---

541 set_irq_regs(old_regs);
542}
543
544void smp_send_reschedule(int cpu)
545{
546 send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE);
547}
548
504void smp_timer_broadcast(const struct cpumask *mask)
505{
506 send_ipi_message(mask, IPI_TIMER);
507}
508
509void smp_send_stop(void)
510{
511 cpumask_t mask = cpu_online_map;
512 cpu_clear(smp_processor_id(), mask);
513 send_ipi_message(&mask, IPI_CPU_STOP);
514}
515
516/*

--- 121 unchanged lines hidden ---
549void smp_send_stop(void)
550{
551 cpumask_t mask = cpu_online_map;
552 cpu_clear(smp_processor_id(), mask);
553 send_ipi_message(&mask, IPI_CPU_STOP);
554}
555
556/*

--- 121 unchanged lines hidden ---