MIPS: Loongson-3: IRQ balancing for PCI devices
IRQ0 (HPET), IRQ1 (Keyboard), IRQ2 (Cascade), IRQ7 (SCI), IRQ8 (RTC) and IRQ12 (Mouse) are handled by core-0 locally. Other PCI IRQs (3, 4, 5, 6, 14, 15) are balanced by all cores from Node-0. This can improve I/O performance significantly. Signed-off-by: Huacai Chen <chenhc@lemote.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J . Hill <Steven.Hill@cavium.com> Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/16589/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
parent
99b0b5a3a1
commit
e1b88ca8d7
|
@ -9,17 +9,32 @@
|
||||||
|
|
||||||
#include "smp.h"
|
#include "smp.h"
|
||||||
|
|
||||||
|
extern void loongson3_send_irq_by_ipi(int cpu, int irqs);
|
||||||
unsigned int ht_irq[] = {0, 1, 3, 4, 5, 6, 7, 8, 12, 14, 15};
|
unsigned int ht_irq[] = {0, 1, 3, 4, 5, 6, 7, 8, 12, 14, 15};
|
||||||
|
unsigned int local_irq = 1<<0 | 1<<1 | 1<<2 | 1<<7 | 1<<8 | 1<<12;
|
||||||
|
|
||||||
static void ht_irqdispatch(void)
|
static void ht_irqdispatch(void)
|
||||||
{
|
{
|
||||||
unsigned int i, irq;
|
unsigned int i, irq, irq0, irq1;
|
||||||
|
static unsigned int dest_cpu = 0;
|
||||||
|
|
||||||
irq = LOONGSON_HT1_INT_VECTOR(0);
|
irq = LOONGSON_HT1_INT_VECTOR(0);
|
||||||
LOONGSON_HT1_INT_VECTOR(0) = irq; /* Acknowledge the IRQs */
|
LOONGSON_HT1_INT_VECTOR(0) = irq; /* Acknowledge the IRQs */
|
||||||
|
|
||||||
|
irq0 = irq & local_irq; /* handled by local core */
|
||||||
|
irq1 = irq & ~local_irq; /* balanced by other cores */
|
||||||
|
|
||||||
|
if (dest_cpu == 0 || !cpu_online(dest_cpu))
|
||||||
|
irq0 |= irq1;
|
||||||
|
else
|
||||||
|
loongson3_send_irq_by_ipi(dest_cpu, irq1);
|
||||||
|
|
||||||
|
dest_cpu = dest_cpu + 1;
|
||||||
|
if (dest_cpu >= num_possible_cpus() || cpu_data[dest_cpu].package > 0)
|
||||||
|
dest_cpu = 0;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(ht_irq); i++) {
|
for (i = 0; i < ARRAY_SIZE(ht_irq); i++) {
|
||||||
if (irq & (0x1 << ht_irq[i]))
|
if (irq0 & (0x1 << ht_irq[i]))
|
||||||
do_IRQ(ht_irq[i]);
|
do_IRQ(ht_irq[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -254,13 +254,21 @@ loongson3_send_ipi_mask(const struct cpumask *mask, unsigned int action)
|
||||||
loongson3_ipi_write32((u32)action, ipi_set0_regs[cpu_logical_map(i)]);
|
loongson3_ipi_write32((u32)action, ipi_set0_regs[cpu_logical_map(i)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define IPI_IRQ_OFFSET 6
|
||||||
|
|
||||||
|
void loongson3_send_irq_by_ipi(int cpu, int irqs)
|
||||||
|
{
|
||||||
|
loongson3_ipi_write32(irqs << IPI_IRQ_OFFSET, ipi_set0_regs[cpu_logical_map(cpu)]);
|
||||||
|
}
|
||||||
|
|
||||||
void loongson3_ipi_interrupt(struct pt_regs *regs)
|
void loongson3_ipi_interrupt(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
int i, cpu = smp_processor_id();
|
int i, cpu = smp_processor_id();
|
||||||
unsigned int action, c0count;
|
unsigned int action, c0count, irqs;
|
||||||
|
|
||||||
/* Load the ipi register to figure out what we're supposed to do */
|
/* Load the ipi register to figure out what we're supposed to do */
|
||||||
action = loongson3_ipi_read32(ipi_status0_regs[cpu_logical_map(cpu)]);
|
action = loongson3_ipi_read32(ipi_status0_regs[cpu_logical_map(cpu)]);
|
||||||
|
irqs = action >> IPI_IRQ_OFFSET;
|
||||||
|
|
||||||
/* Clear the ipi register to clear the interrupt */
|
/* Clear the ipi register to clear the interrupt */
|
||||||
loongson3_ipi_write32((u32)action, ipi_clear0_regs[cpu_logical_map(cpu)]);
|
loongson3_ipi_write32((u32)action, ipi_clear0_regs[cpu_logical_map(cpu)]);
|
||||||
|
@ -282,6 +290,14 @@ void loongson3_ipi_interrupt(struct pt_regs *regs)
|
||||||
core0_c0count[i] = c0count;
|
core0_c0count[i] = c0count;
|
||||||
__wbflush(); /* Let others see the result ASAP */
|
__wbflush(); /* Let others see the result ASAP */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (irqs) {
|
||||||
|
int irq;
|
||||||
|
while ((irq = ffs(irqs))) {
|
||||||
|
do_IRQ(irq-1);
|
||||||
|
irqs &= ~(1<<(irq-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_LOOPS 800
|
#define MAX_LOOPS 800
|
||||||
|
|
Loading…
Reference in New Issue