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 --- |