Path: blob/master/arch/mips/mti-malta/malta-smtc.c
10817 views
/*1* Malta Platform-specific hooks for SMP operation2*/3#include <linux/irq.h>4#include <linux/init.h>56#include <asm/mipsregs.h>7#include <asm/mipsmtregs.h>8#include <asm/smtc.h>9#include <asm/smtc_ipi.h>1011/* VPE/SMP Prototype implements platform interfaces directly */1213/*14* Cause the specified action to be performed on a targeted "CPU"15*/1617static void msmtc_send_ipi_single(int cpu, unsigned int action)18{19/* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */20smtc_send_ipi(cpu, LINUX_SMP_IPI, action);21}2223static void msmtc_send_ipi_mask(const struct cpumask *mask, unsigned int action)24{25unsigned int i;2627for_each_cpu(i, mask)28msmtc_send_ipi_single(i, action);29}3031/*32* Post-config but pre-boot cleanup entry point33*/34static void __cpuinit msmtc_init_secondary(void)35{36int myvpe;3738/* Don't enable Malta I/O interrupts (IP2) for secondary VPEs */39myvpe = read_c0_tcbind() & TCBIND_CURVPE;40if (myvpe != 0) {41/* Ideally, this should be done only once per VPE, but... */42clear_c0_status(ST0_IM);43set_c0_status((0x100 << cp0_compare_irq)44| (0x100 << MIPS_CPU_IPI_IRQ));45if (cp0_perfcount_irq >= 0)46set_c0_status(0x100 << cp0_perfcount_irq);47}4849smtc_init_secondary();50}5152/*53* Platform "CPU" startup hook54*/55static void __cpuinit msmtc_boot_secondary(int cpu, struct task_struct *idle)56{57smtc_boot_secondary(cpu, idle);58}5960/*61* SMP initialization finalization entry point62*/63static void __cpuinit msmtc_smp_finish(void)64{65smtc_smp_finish();66}6768/*69* Hook for after all CPUs are online70*/7172static void msmtc_cpus_done(void)73{74}7576/*77* Platform SMP pre-initialization78*79* As noted above, we can assume a single CPU for now80* but it may be multithreaded.81*/8283static void __init msmtc_smp_setup(void)84{85/*86* we won't get the definitive value until87* we've run smtc_prepare_cpus later, but88* we would appear to need an upper bound now.89*/90smp_num_siblings = smtc_build_cpu_map(0);91}9293static void __init msmtc_prepare_cpus(unsigned int max_cpus)94{95smtc_prepare_cpus(max_cpus);96}9798struct plat_smp_ops msmtc_smp_ops = {99.send_ipi_single = msmtc_send_ipi_single,100.send_ipi_mask = msmtc_send_ipi_mask,101.init_secondary = msmtc_init_secondary,102.smp_finish = msmtc_smp_finish,103.cpus_done = msmtc_cpus_done,104.boot_secondary = msmtc_boot_secondary,105.smp_setup = msmtc_smp_setup,106.prepare_cpus = msmtc_prepare_cpus,107};108109#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF110/*111* IRQ affinity hook112*/113114115int plat_set_irq_affinity(struct irq_data *d, const struct cpumask *affinity,116bool force)117{118cpumask_t tmask;119int cpu = 0;120void smtc_set_irq_affinity(unsigned int irq, cpumask_t aff);121122/*123* On the legacy Malta development board, all I/O interrupts124* are routed through the 8259 and combined in a single signal125* to the CPU daughterboard, and on the CoreFPGA2/3 34K models,126* that signal is brought to IP2 of both VPEs. To avoid racing127* concurrent interrupt service events, IP2 is enabled only on128* one VPE, by convention VPE0. So long as no bits are ever129* cleared in the affinity mask, there will never be any130* interrupt forwarding. But as soon as a program or operator131* sets affinity for one of the related IRQs, we need to make132* sure that we don't ever try to forward across the VPE boundary,133* at least not until we engineer a system where the interrupt134* _ack() or _end() function can somehow know that it corresponds135* to an interrupt taken on another VPE, and perform the appropriate136* restoration of Status.IM state using MFTR/MTTR instead of the137* normal local behavior. We also ensure that no attempt will138* be made to forward to an offline "CPU".139*/140141cpumask_copy(&tmask, affinity);142for_each_cpu(cpu, affinity) {143if ((cpu_data[cpu].vpe_id != 0) || !cpu_online(cpu))144cpu_clear(cpu, tmask);145}146cpumask_copy(d->affinity, &tmask);147148if (cpus_empty(tmask))149/*150* We could restore a default mask here, but the151* runtime code can anyway deal with the null set152*/153printk(KERN_WARNING154"IRQ affinity leaves no legal CPU for IRQ %d\n", irq);155156/* Do any generic SMTC IRQ affinity setup */157smtc_set_irq_affinity(d->irq, tmask);158159return IRQ_SET_MASK_OK_NOCOPY;160}161#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */162163164