diff options
author | David Daney <ddaney@caviumnetworks.com> | 2010-07-23 21:43:47 +0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2010-08-05 16:26:10 +0400 |
commit | 3508920f5811fcb8bdbf02943eb5ed531834bbc4 (patch) | |
tree | 20e03cb5fb1d982990760bccdbccde4736e14d85 /arch/mips/cavium-octeon/octeon-irq.c | |
parent | 5aae1fd4d41ea69da845e11d4766ab61666494ed (diff) | |
download | linux-3508920f5811fcb8bdbf02943eb5ed531834bbc4.tar.xz |
MIPS: Octeon: Fix fixup_irqs for HOTPLUG_CPU
The original version went behind the back of everything, leaving
things in an inconsistent state.
Now we use the irq_set_affinity() to do the work for us. This has the
advantage that the IRQ core's view of the affinity stays consistent.
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
To: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/1486/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/cavium-octeon/octeon-irq.c')
-rw-r--r-- | arch/mips/cavium-octeon/octeon-irq.c | 108 |
1 files changed, 69 insertions, 39 deletions
diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index 8fb9fb667779..ce7500cdf5b7 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c @@ -788,54 +788,84 @@ asmlinkage void plat_irq_dispatch(void) } #ifdef CONFIG_HOTPLUG_CPU -static int is_irq_enabled_on_cpu(unsigned int irq, unsigned int cpu) -{ - unsigned int isset; - int coreid = octeon_coreid_for_cpu(cpu); - int bit = (irq < OCTEON_IRQ_WDOG0) ? - irq - OCTEON_IRQ_WORKQ0 : irq - OCTEON_IRQ_WDOG0; - if (irq < 64) { - isset = (cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)) & - (1ull << bit)) >> bit; - } else { - isset = (cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)) & - (1ull << bit)) >> bit; - } - return isset; -} void fixup_irqs(void) { - int irq; + int irq; + struct irq_desc *desc; + cpumask_t new_affinity; + unsigned long flags; + int do_set_affinity; + int cpu; + + cpu = smp_processor_id(); for (irq = OCTEON_IRQ_SW0; irq <= OCTEON_IRQ_TIMER; irq++) octeon_irq_core_disable_local(irq); - for (irq = OCTEON_IRQ_WORKQ0; irq <= OCTEON_IRQ_GPIO15; irq++) { - if (is_irq_enabled_on_cpu(irq, smp_processor_id())) { - /* ciu irq migrates to next cpu */ - octeon_irq_chip_ciu0.disable(irq); - octeon_irq_ciu0_set_affinity(irq, &cpu_online_map); - } - } + for (irq = OCTEON_IRQ_WORKQ0; irq < OCTEON_IRQ_LAST; irq++) { + desc = irq_to_desc(irq); + switch (irq) { + case OCTEON_IRQ_MBOX0: + case OCTEON_IRQ_MBOX1: + /* The eoi function will disable them on this CPU. */ + desc->chip->eoi(irq); + break; + case OCTEON_IRQ_WDOG0: + case OCTEON_IRQ_WDOG1: + case OCTEON_IRQ_WDOG2: + case OCTEON_IRQ_WDOG3: + case OCTEON_IRQ_WDOG4: + case OCTEON_IRQ_WDOG5: + case OCTEON_IRQ_WDOG6: + case OCTEON_IRQ_WDOG7: + case OCTEON_IRQ_WDOG8: + case OCTEON_IRQ_WDOG9: + case OCTEON_IRQ_WDOG10: + case OCTEON_IRQ_WDOG11: + case OCTEON_IRQ_WDOG12: + case OCTEON_IRQ_WDOG13: + case OCTEON_IRQ_WDOG14: + case OCTEON_IRQ_WDOG15: + /* + * These have special per CPU semantics and + * are handled in the watchdog driver. + */ + break; + default: + raw_spin_lock_irqsave(&desc->lock, flags); + /* + * If this irq has an action, it is in use and + * must be migrated if it has affinity to this + * cpu. + */ + if (desc->action && cpumask_test_cpu(cpu, desc->affinity)) { + if (cpumask_weight(desc->affinity) > 1) { + /* + * It has multi CPU affinity, + * just remove this CPU from + * the affinity set. + */ + cpumask_copy(&new_affinity, desc->affinity); + cpumask_clear_cpu(cpu, &new_affinity); + } else { + /* + * Otherwise, put it on lowest + * numbered online CPU. + */ + cpumask_clear(&new_affinity); + cpumask_set_cpu(cpumask_first(cpu_online_mask), &new_affinity); + } + do_set_affinity = 1; + } else { + do_set_affinity = 0; + } + raw_spin_unlock_irqrestore(&desc->lock, flags); -#if 0 - for (irq = OCTEON_IRQ_MBOX0; irq <= OCTEON_IRQ_MBOX1; irq++) - octeon_irq_mailbox_mask(irq); -#endif - for (irq = OCTEON_IRQ_UART0; irq <= OCTEON_IRQ_BOOTDMA; irq++) { - if (is_irq_enabled_on_cpu(irq, smp_processor_id())) { - /* ciu irq migrates to next cpu */ - octeon_irq_chip_ciu0.disable(irq); - octeon_irq_ciu0_set_affinity(irq, &cpu_online_map); - } - } + if (do_set_affinity) + irq_set_affinity(irq, &new_affinity); - for (irq = OCTEON_IRQ_UART2; irq <= OCTEON_IRQ_RESERVED135; irq++) { - if (is_irq_enabled_on_cpu(irq, smp_processor_id())) { - /* ciu irq migrates to next cpu */ - octeon_irq_chip_ciu1.disable(irq); - octeon_irq_ciu1_set_affinity(irq, &cpu_online_map); + break; } } } |