Commit ecc38a09 authored by Huacai Chen's avatar Huacai Chen Committed by Ralf Baechle

MIPS: Loongson-3: support irq_set_affinity() in i8259 chip

With this patch we can set irq affinity via procfs, so as to improve
network performance.
Signed-off-by: default avatarHuacai 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/16590/Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent e1b88ca8
...@@ -10,32 +10,68 @@ ...@@ -10,32 +10,68 @@
#include "smp.h" #include "smp.h"
extern void loongson3_send_irq_by_ipi(int cpu, int irqs); extern void loongson3_send_irq_by_ipi(int cpu, int irqs);
unsigned int irq_cpu[16] = {[0 ... 15] = -1};
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; unsigned int local_irq = 1<<0 | 1<<1 | 1<<2 | 1<<7 | 1<<8 | 1<<12;
int plat_set_irq_affinity(struct irq_data *d, const struct cpumask *affinity,
bool force)
{
unsigned int cpu;
struct cpumask new_affinity;
/* I/O devices are connected on package-0 */
cpumask_copy(&new_affinity, affinity);
for_each_cpu(cpu, affinity)
if (cpu_data[cpu].package > 0)
cpumask_clear_cpu(cpu, &new_affinity);
if (cpumask_empty(&new_affinity))
return -EINVAL;
cpumask_copy(d->common->affinity, &new_affinity);
return IRQ_SET_MASK_OK_NOCOPY;
}
static void ht_irqdispatch(void) static void ht_irqdispatch(void)
{ {
unsigned int i, irq, irq0, irq1; unsigned int i, irq;
static unsigned int dest_cpu = 0; struct irq_data *irqd;
struct cpumask affinity;
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 */ for (i = 0; i < ARRAY_SIZE(ht_irq); i++) {
irq1 = irq & ~local_irq; /* balanced by other cores */ if (!(irq & (0x1 << ht_irq[i])))
continue;
if (dest_cpu == 0 || !cpu_online(dest_cpu)) /* handled by local core */
irq0 |= irq1; if (local_irq & (0x1 << ht_irq[i])) {
else do_IRQ(ht_irq[i]);
loongson3_send_irq_by_ipi(dest_cpu, irq1); continue;
}
dest_cpu = dest_cpu + 1; irqd = irq_get_irq_data(ht_irq[i]);
if (dest_cpu >= num_possible_cpus() || cpu_data[dest_cpu].package > 0) cpumask_and(&affinity, irqd->common->affinity, cpu_active_mask);
dest_cpu = 0; if (cpumask_empty(&affinity)) {
do_IRQ(ht_irq[i]);
continue;
}
for (i = 0; i < ARRAY_SIZE(ht_irq); i++) { irq_cpu[ht_irq[i]] = cpumask_next(irq_cpu[ht_irq[i]], &affinity);
if (irq0 & (0x1 << ht_irq[i])) if (irq_cpu[ht_irq[i]] >= nr_cpu_ids)
irq_cpu[ht_irq[i]] = cpumask_first(&affinity);
if (irq_cpu[ht_irq[i]] == 0) {
do_IRQ(ht_irq[i]); do_IRQ(ht_irq[i]);
continue;
}
/* balanced by other cores */
loongson3_send_irq_by_ipi(irq_cpu[ht_irq[i]], (0x1 << ht_irq[i]));
} }
} }
...@@ -135,11 +171,16 @@ void irq_router_init(void) ...@@ -135,11 +171,16 @@ void irq_router_init(void)
void __init mach_init_irq(void) void __init mach_init_irq(void)
{ {
struct irq_chip *chip;
clear_c0_status(ST0_IM | ST0_BEV); clear_c0_status(ST0_IM | ST0_BEV);
irq_router_init(); irq_router_init();
mips_cpu_irq_init(); mips_cpu_irq_init();
init_i8259_irqs(); init_i8259_irqs();
chip = irq_get_chip(I8259A_IRQ_BASE);
chip->irq_set_affinity = plat_set_irq_affinity;
irq_set_chip_and_handler(LOONGSON_UART_IRQ, irq_set_chip_and_handler(LOONGSON_UART_IRQ,
&loongson_irq_chip, handle_level_irq); &loongson_irq_chip, handle_level_irq);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment