diff options
Diffstat (limited to 'arch/cris/arch-v32/kernel/smp.c')
| -rw-r--r-- | arch/cris/arch-v32/kernel/smp.c | 121 |
1 files changed, 64 insertions, 57 deletions
diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c index da40d19a151..0698582467c 100644 --- a/arch/cris/arch-v32/kernel/smp.c +++ b/arch/cris/arch-v32/kernel/smp.c @@ -1,12 +1,13 @@ +#include <linux/types.h> #include <asm/delay.h> -#include <asm/arch/irq.h> -#include <asm/arch/hwregs/intr_vect.h> -#include <asm/arch/hwregs/intr_vect_defs.h> +#include <irq.h> +#include <hwregs/intr_vect.h> +#include <hwregs/intr_vect_defs.h> #include <asm/tlbflush.h> #include <asm/mmu_context.h> -#include <asm/arch/hwregs/mmu_defs_asm.h> -#include <asm/arch/hwregs/supp_reg.h> -#include <asm/atomic.h> +#include <hwregs/asm/mmu_defs_asm.h> +#include <hwregs/supp_reg.h> +#include <linux/atomic.h> #include <linux/err.h> #include <linux/init.h> @@ -20,14 +21,16 @@ #define IPI_SCHEDULE 1 #define IPI_CALL 2 #define IPI_FLUSH_TLB 4 +#define IPI_BOOT 8 #define FLUSH_ALL (void*)0xffffffff /* Vector of locks used for various atomic operations */ -spinlock_t cris_atomic_locks[] = { [0 ... LOCK_COUNT - 1] = SPIN_LOCK_UNLOCKED}; +spinlock_t cris_atomic_locks[] = { + [0 ... LOCK_COUNT - 1] = __SPIN_LOCK_UNLOCKED(cris_atomic_locks) +}; /* CPU masks */ -cpumask_t cpu_online_map = CPU_MASK_NONE; cpumask_t phys_cpu_present_map = CPU_MASK_NONE; EXPORT_SYMBOL(phys_cpu_present_map); @@ -51,19 +54,19 @@ static struct mm_struct* flush_mm; static struct vm_area_struct* flush_vma; static unsigned long flush_addr; -extern int setup_irq(int, struct irqaction *); - /* Mode registers */ -static unsigned long irq_regs[NR_CPUS] = -{ +static unsigned long irq_regs[NR_CPUS] = { regi_irq, regi_irq2 }; -static irqreturn_t crisv32_ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t crisv32_ipi_interrupt(int irq, void *dev_id); static int send_ipi(int vector, int wait, cpumask_t cpu_mask); -static struct irqaction irq_ipi = { crisv32_ipi_interrupt, SA_INTERRUPT, - CPU_MASK_NONE, "ipi", NULL, NULL}; +static struct irqaction irq_ipi = { + .handler = crisv32_ipi_interrupt, + .flags = 0, + .name = "ipi", +}; extern void cris_mmu_init(void); extern void cris_timer_init(void); @@ -78,10 +81,10 @@ void __init smp_prepare_cpus(unsigned int max_cpus) /* Mark all possible CPUs as present */ for (i = 0; i < max_cpus; i++) - cpu_set(i, phys_cpu_present_map); + cpumask_set_cpu(i, &phys_cpu_present_map); } -void __devinit smp_prepare_boot_cpu(void) +void smp_prepare_boot_cpu(void) { /* PGD pointer has moved after per_cpu initialization so * update the MMU. @@ -94,8 +97,9 @@ void __devinit smp_prepare_boot_cpu(void) SUPP_BANK_SEL(2); SUPP_REG_WR(RW_MM_TLB_PGD, pgd); - cpu_set(0, cpu_online_map); - cpu_set(0, phys_cpu_present_map); + set_cpu_online(0, true); + cpumask_set_cpu(0, &phys_cpu_present_map); + set_cpu_possible(0, true); } void __init smp_cpus_done(unsigned int max_cpus) @@ -104,21 +108,24 @@ void __init smp_cpus_done(unsigned int max_cpus) /* Bring one cpu online.*/ static int __init -smp_boot_one_cpu(int cpuid) +smp_boot_one_cpu(int cpuid, struct task_struct idle) { unsigned timeout; - struct task_struct *idle; - - idle = fork_idle(cpuid); - if (IS_ERR(idle)) - panic("SMP: fork failed for CPU:%d", cpuid); + cpumask_t cpu_mask; + cpumask_clear(&cpu_mask); task_thread_info(idle)->cpu = cpuid; /* Information to the CPU that is about to boot */ smp_init_current_idle_thread = task_thread_info(idle); cpu_now_booting = cpuid; + /* Kick it */ + set_cpu_online(cpuid, true); + cpumask_set_cpu(cpuid, &cpu_mask); + send_ipi(IPI_BOOT, 0, cpu_mask); + set_cpu_online(cpuid, false); + /* Wait for CPU to come online */ for (timeout = 0; timeout < 10000; timeout++) { if(cpu_online(cpuid)) { @@ -130,19 +137,14 @@ smp_boot_one_cpu(int cpuid) barrier(); } - put_task_struct(idle); - idle = NULL; - printk(KERN_CRIT "SMP: CPU:%d is stuck.\n", cpuid); return -1; } -/* Secondary CPUs starts uing C here. Here we need to setup CPU +/* Secondary CPUs starts using C here. Here we need to setup CPU * specific stuff such as the local timer and the MMU. */ void __init smp_callin(void) { - extern void cpu_idle(void); - int cpu = cpu_now_booting; reg_intr_vect_rw_mask vect_mask = {0}; @@ -159,13 +161,14 @@ void __init smp_callin(void) /* Enable IRQ and idle */ REG_WR(intr_vect, irq_regs[cpu], rw_mask, vect_mask); - unmask_irq(IPI_INTR_VECT); - unmask_irq(TIMER_INTR_VECT); + crisv32_unmask_irq(IPI_INTR_VECT); + crisv32_unmask_irq(TIMER0_INTR_VECT); preempt_disable(); + notify_cpu_starting(cpu); local_irq_enable(); - cpu_set(cpu, cpu_online_map); - cpu_idle(); + set_cpu_online(cpu, true); + cpu_startup_entry(CPUHP_ONLINE); } /* Stop execution on this CPU.*/ @@ -178,7 +181,7 @@ void stop_this_cpu(void* dummy) /* Other calls */ void smp_send_stop(void) { - smp_call_function(stop_this_cpu, NULL, 1, 0); + smp_call_function(stop_this_cpu, NULL, 0); } int setup_profiling_timer(unsigned int multiplier) @@ -194,16 +197,17 @@ int setup_profiling_timer(unsigned int multiplier) */ unsigned long cache_decay_ticks = 1; -int __devinit __cpu_up(unsigned int cpu) +int __cpu_up(unsigned int cpu, struct task_struct *tidle) { - smp_boot_one_cpu(cpu); + smp_boot_one_cpu(cpu, tidle); return cpu_online(cpu) ? 0 : -ENOSYS; } void smp_send_reschedule(int cpu) { - cpumask_t cpu_mask = CPU_MASK_NONE; - cpu_set(cpu, cpu_mask); + cpumask_t cpu_mask; + cpumask_clear(&cpu_mask); + cpumask_set_cpu(cpu, &cpu_mask); send_ipi(IPI_SCHEDULE, 0, cpu_mask); } @@ -219,8 +223,8 @@ void flush_tlb_common(struct mm_struct* mm, struct vm_area_struct* vma, unsigned cpumask_t cpu_mask; spin_lock_irqsave(&tlbstate_lock, flags); - cpu_mask = (mm == FLUSH_ALL ? CPU_MASK_ALL : mm->cpu_vm_mask); - cpu_clear(smp_processor_id(), cpu_mask); + cpu_mask = (mm == FLUSH_ALL ? cpu_all_mask : *mm_cpumask(mm)); + cpumask_clear_cpu(smp_processor_id(), &cpu_mask); flush_mm = mm; flush_vma = vma; flush_addr = addr; @@ -239,8 +243,8 @@ void flush_tlb_mm(struct mm_struct *mm) __flush_tlb_mm(mm); flush_tlb_common(mm, FLUSH_ALL, 0); /* No more mappings in other CPUs */ - cpus_clear(mm->cpu_vm_mask); - cpu_set(smp_processor_id(), mm->cpu_vm_mask); + cpumask_clear(mm_cpumask(mm)); + cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm)); } void flush_tlb_page(struct vm_area_struct *vma, @@ -265,10 +269,10 @@ int send_ipi(int vector, int wait, cpumask_t cpu_mask) int ret = 0; /* Calculate CPUs to send to. */ - cpus_and(cpu_mask, cpu_mask, cpu_online_map); + cpumask_and(&cpu_mask, &cpu_mask, cpu_online_mask); /* Send the IPI. */ - for_each_cpu_mask(i, cpu_mask) + for_each_cpu(i, &cpu_mask) { ipi.vector |= vector; REG_WR(intr_vect, irq_regs[i], rw_ipi, ipi); @@ -276,7 +280,7 @@ int send_ipi(int vector, int wait, cpumask_t cpu_mask) /* Wait for IPI to finish on other CPUS */ if (wait) { - for_each_cpu_mask(i, cpu_mask) { + for_each_cpu(i, &cpu_mask) { int j; for (j = 0 ; j < 1000; j++) { ipi = REG_RD(intr_vect, irq_regs[i], rw_ipi); @@ -300,14 +304,14 @@ int send_ipi(int vector, int wait, cpumask_t cpu_mask) * You must not call this function with disabled interrupts or from a * hardware interrupt handler or from a bottom half handler. */ -int smp_call_function(void (*func)(void *info), void *info, - int nonatomic, int wait) +int smp_call_function(void (*func)(void *info), void *info, int wait) { - cpumask_t cpu_mask = CPU_MASK_ALL; + cpumask_t cpu_mask; struct call_data_struct data; int ret; - cpu_clear(smp_processor_id(), cpu_mask); + cpumask_setall(&cpu_mask); + cpumask_clear_cpu(smp_processor_id(), &cpu_mask); WARN_ON(irqs_disabled()); @@ -323,7 +327,7 @@ int smp_call_function(void (*func)(void *info), void *info, return ret; } -irqreturn_t crisv32_ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t crisv32_ipi_interrupt(int irq, void *dev_id) { void (*func) (void *info) = call_data->func; void *info = call_data->info; @@ -331,15 +335,18 @@ irqreturn_t crisv32_ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs) ipi = REG_RD(intr_vect, irq_regs[smp_processor_id()], rw_ipi); + if (ipi.vector & IPI_SCHEDULE) { + scheduler_ipi(); + } if (ipi.vector & IPI_CALL) { - func(info); + func(info); } if (ipi.vector & IPI_FLUSH_TLB) { - if (flush_mm == FLUSH_ALL) - __flush_tlb_all(); - else if (flush_vma == FLUSH_ALL) + if (flush_mm == FLUSH_ALL) + __flush_tlb_all(); + else if (flush_vma == FLUSH_ALL) __flush_tlb_mm(flush_mm); - else + else __flush_tlb_page(flush_vma, flush_addr); } |
