Re: [PATCH V2 18/24] irqchip: mips-gic: Stop using per-platform mapping tables

From: James Hogan
Date: Thu Jan 15 2015 - 06:59:33 EST


Hi Andrew,

On 18/09/14 22:47, Andrew Bresticker wrote:
> Now that the GIC properly uses IRQ domains, kill off the per-platform
> routing tables that were used to make the GIC appear transparent.
>
> This includes:
> - removing the mapping tables and the support for applying them,
> - moving GIC IPI support to the GIC driver,
> - properly routing the i8259 through the GIC on Malta, and
> - updating IRQ assignments on SEAD-3 when the GIC is present.
>
> Platforms no longer will pass an interrupt mapping table to gic_init.
> Instead, they will pass the CPU interrupt vector (2 - 7) that they
> expect the GIC to route interrupts to. Note that in EIC mode this
> value is ignored and all GIC interrupts are routed to EIC vector 1.
>
> Signed-off-by: Andrew Bresticker <abrestic@xxxxxxxxxxxx>
> Acked-by: Jason Cooper <jason@xxxxxxxxxxxxxx>
> Reviewed-by: Qais Yousef <qais.yousef@xxxxxxxxxx>
> Tested-by: Qais Yousef <qais.yousef@xxxxxxxxxx>

This commit (18743d2781d01d34d132f952a2e16353ccb4c3de) appears to break
boot of interAptiv, dual core, dual vpe per core, on malta with
malta_defconfig.

It gets to here:
...
CPU1 revision is: 0001a120 (MIPS interAptiv (multi))
FPU revision is: 0173a000
Primary instruction cache 64kB, VIPT, 4-way, linesize 32 bytes.
Primary data cache 64kB, 4-way, PIPT, no aliases, linesize 32 bytes
MIPS secondary cache 1024kB, 8-way, linesize 32 bytes.
Synchronize counters for CPU 1: done.
Brought up 2 CPUs

and then appears to just hang. Passing nosmp works around it, allowing
it to get to userland.

Is that a problem you've already come across?

I'll keep debugging.

Thanks
James

> ---
> No changes from v1.
> ---
> arch/mips/include/asm/gic.h | 35 +----
> arch/mips/include/asm/mips-boards/maltaint.h | 14 +-
> arch/mips/include/asm/mips-boards/sead3int.h | 13 ++
> arch/mips/kernel/cevt-gic.c | 3 +-
> arch/mips/mti-malta/malta-int.c | 189 +++++--------------------
> arch/mips/mti-sead3/sead3-ehci.c | 8 +-
> arch/mips/mti-sead3/sead3-int.c | 28 +---
> arch/mips/mti-sead3/sead3-net.c | 14 +-
> arch/mips/mti-sead3/sead3-platform.c | 18 ++-
> drivers/irqchip/irq-mips-gic.c | 201 ++++++++++++++-------------
> 10 files changed, 198 insertions(+), 325 deletions(-)
>
> diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h
> index efcf4de..cfbf907 100644
> --- a/arch/mips/include/asm/gic.h
> +++ b/arch/mips/include/asm/gic.h
> @@ -316,31 +316,6 @@
> GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_VPE_REG_OFF(intr, vpe)), \
> GIC_SH_MAP_TO_VPE_REG_BIT(vpe))
>
> -/*
> - * Interrupt Meta-data specification. The ipiflag helps
> - * in building ipi_map.
> - */
> -struct gic_intr_map {
> - unsigned int cpunum; /* Directed to this CPU */
> -#define GIC_UNUSED 0xdead /* Dummy data */
> - unsigned int pin; /* Directed to this Pin */
> - unsigned int polarity; /* Polarity : +/- */
> - unsigned int trigtype; /* Trigger : Edge/Levl */
> - unsigned int flags; /* Misc flags */
> -#define GIC_FLAG_TRANSPARENT 0x01
> -};
> -
> -/*
> - * This is only used in EIC mode. This helps to figure out which
> - * shared interrupts we need to process when we get a vector interrupt.
> - */
> -#define GIC_MAX_SHARED_INTR 0x5
> -struct gic_shared_intr_map {
> - unsigned int num_shared_intr;
> - unsigned int intr_list[GIC_MAX_SHARED_INTR];
> - unsigned int local_intr_mask;
> -};
> -
> /* GIC nomenclature for Core Interrupt Pins. */
> #define GIC_CPU_INT0 0 /* Core Interrupt 2 */
> #define GIC_CPU_INT1 1 /* . */
> @@ -349,6 +324,9 @@ struct gic_shared_intr_map {
> #define GIC_CPU_INT4 4 /* . */
> #define GIC_CPU_INT5 5 /* Core Interrupt 7 */
>
> +/* Add 2 to convert GIC CPU pin to core interrupt */
> +#define GIC_CPU_PIN_OFFSET 2
> +
> /* Local GIC interrupts. */
> #define GIC_INT_TMR (GIC_CPU_INT5)
> #define GIC_INT_PERFCTR (GIC_CPU_INT5)
> @@ -365,13 +343,12 @@ struct gic_shared_intr_map {
> extern unsigned int gic_present;
> extern unsigned int gic_frequency;
> extern unsigned long _gic_base;
> -extern unsigned int gic_irq_base;
> extern unsigned int gic_irq_flags[];
> -extern struct gic_shared_intr_map gic_shared_intr_map[];
> +extern unsigned int gic_cpu_pin;
>
> extern void gic_init(unsigned long gic_base_addr,
> - unsigned long gic_addrspace_size, struct gic_intr_map *intrmap,
> - unsigned int intrmap_size, unsigned int irqbase);
> + unsigned long gic_addrspace_size, unsigned int cpu_vec,
> + unsigned int irqbase);
> extern void gic_clocksource_init(unsigned int);
> extern unsigned int gic_compare_int (void);
> extern cycle_t gic_read_count(void);
> diff --git a/arch/mips/include/asm/mips-boards/maltaint.h b/arch/mips/include/asm/mips-boards/maltaint.h
> index d741628..bdd6f39 100644
> --- a/arch/mips/include/asm/mips-boards/maltaint.h
> +++ b/arch/mips/include/asm/mips-boards/maltaint.h
> @@ -20,11 +20,10 @@
> #define MIPSCPU_INT_SW1 1
> #define MIPSCPU_INT_MB0 2
> #define MIPSCPU_INT_I8259A MIPSCPU_INT_MB0
> +#define MIPSCPU_INT_GIC MIPSCPU_INT_MB0 /* GIC chained interrupt */
> #define MIPSCPU_INT_MB1 3
> #define MIPSCPU_INT_SMI MIPSCPU_INT_MB1
> -#define MIPSCPU_INT_IPI0 MIPSCPU_INT_MB1 /* GIC IPI */
> #define MIPSCPU_INT_MB2 4
> -#define MIPSCPU_INT_IPI1 MIPSCPU_INT_MB2 /* GIC IPI */
> #define MIPSCPU_INT_MB3 5
> #define MIPSCPU_INT_COREHI MIPSCPU_INT_MB3
> #define MIPSCPU_INT_MB4 6
> @@ -61,14 +60,7 @@
> #define MSC01E_INT_PERFCTR 10
> #define MSC01E_INT_CPUCTR 11
>
> -/* External Interrupts used for IPI */
> -#define GIC_IPI_EXT_INTR_RESCHED_VPE0 16
> -#define GIC_IPI_EXT_INTR_CALLFNC_VPE0 17
> -#define GIC_IPI_EXT_INTR_RESCHED_VPE1 18
> -#define GIC_IPI_EXT_INTR_CALLFNC_VPE1 19
> -#define GIC_IPI_EXT_INTR_RESCHED_VPE2 20
> -#define GIC_IPI_EXT_INTR_CALLFNC_VPE2 21
> -#define GIC_IPI_EXT_INTR_RESCHED_VPE3 22
> -#define GIC_IPI_EXT_INTR_CALLFNC_VPE3 23
> +/* GIC external interrupts */
> +#define GIC_INT_I8259A 3
>
> #endif /* !(_MIPS_MALTAINT_H) */
> diff --git a/arch/mips/include/asm/mips-boards/sead3int.h b/arch/mips/include/asm/mips-boards/sead3int.h
> index 11ebec9..a2e0095 100644
> --- a/arch/mips/include/asm/mips-boards/sead3int.h
> +++ b/arch/mips/include/asm/mips-boards/sead3int.h
> @@ -14,4 +14,17 @@
> #define GIC_BASE_ADDR 0x1b1c0000
> #define GIC_ADDRSPACE_SZ (128 * 1024)
>
> +/* CPU interrupt offsets */
> +#define CPU_INT_GIC 2
> +#define CPU_INT_EHCI 2
> +#define CPU_INT_UART0 4
> +#define CPU_INT_UART1 4
> +#define CPU_INT_NET 6
> +
> +/* GIC interrupt offsets */
> +#define GIC_INT_NET 0
> +#define GIC_INT_UART1 2
> +#define GIC_INT_UART0 3
> +#define GIC_INT_EHCI 5
> +
> #endif /* !(_MIPS_SEAD3INT_H) */
> diff --git a/arch/mips/kernel/cevt-gic.c b/arch/mips/kernel/cevt-gic.c
> index 6093716..a90bd4c 100644
> --- a/arch/mips/kernel/cevt-gic.c
> +++ b/arch/mips/kernel/cevt-gic.c
> @@ -91,7 +91,8 @@ int gic_clockevent_init(void)
>
> clockevents_register_device(cd);
>
> - GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_MAP), 0x80000002);
> + GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_MAP),
> + GIC_MAP_TO_PIN_MSK | gic_cpu_pin);
> GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_SMASK), GIC_VPE_SMASK_CMP_MSK);
>
> if (gic_timer_irq_installed)
> diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c
> index e56563c..3b3bc1d 100644
> --- a/arch/mips/mti-malta/malta-int.c
> +++ b/arch/mips/mti-malta/malta-int.c
> @@ -38,14 +38,9 @@
> #include <asm/rtlx.h>
>
> static unsigned long _msc01_biu_base;
> -static unsigned int ipi_map[NR_CPUS];
>
> static DEFINE_RAW_SPINLOCK(mips_irq_lock);
>
> -#ifdef CONFIG_MIPS_GIC_IPI
> -DECLARE_BITMAP(ipi_ints, GIC_NUM_INTRS);
> -#endif
> -
> static inline int mips_pcibios_iack(void)
> {
> int irq;
> @@ -127,24 +122,10 @@ static void malta_hw0_irqdispatch(void)
> #endif
> }
>
> -static void malta_ipi_irqdispatch(void)
> +static irqreturn_t i8259_handler(int irq, void *dev_id)
> {
> -#ifdef CONFIG_MIPS_GIC_IPI
> - unsigned long irq;
> - DECLARE_BITMAP(pending, GIC_NUM_INTRS);
> -
> - gic_get_int_mask(pending, ipi_ints);
> -
> - irq = find_first_bit(pending, GIC_NUM_INTRS);
> -
> - while (irq < GIC_NUM_INTRS) {
> - do_IRQ(MIPS_GIC_IRQ_BASE + irq);
> -
> - irq = find_next_bit(pending, GIC_NUM_INTRS, irq + 1);
> - }
> -#endif
> - if (gic_compare_int())
> - do_IRQ(MIPS_GIC_IRQ_BASE);
> + malta_hw0_irqdispatch();
> + return IRQ_HANDLED;
> }
>
> static void corehi_irqdispatch(void)
> @@ -203,6 +184,12 @@ static void corehi_irqdispatch(void)
> die("CoreHi interrupt", regs);
> }
>
> +static irqreturn_t corehi_handler(int irq, void *dev_id)
> +{
> + corehi_irqdispatch();
> + return IRQ_HANDLED;
> +}
> +
> static inline int clz(unsigned long x)
> {
> __asm__(
> @@ -286,10 +273,9 @@ asmlinkage void plat_irq_dispatch(void)
>
> irq = irq_ffs(pending);
>
> - if (irq == MIPSCPU_INT_I8259A)
> - malta_hw0_irqdispatch();
> - else if (gic_present && ((1 << irq) & ipi_map[smp_processor_id()]))
> - malta_ipi_irqdispatch();
> + /* HACK: GIC doesn't properly dispatch local interrupts yet */
> + if (gic_present && irq == MIPSCPU_INT_GIC && gic_compare_int())
> + do_IRQ(MIPS_GIC_IRQ_BASE);
> else
> do_IRQ(MIPS_CPU_IRQ_BASE + irq);
> }
> @@ -312,13 +298,6 @@ static void ipi_call_dispatch(void)
> do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ);
> }
>
> -#endif /* CONFIG_MIPS_MT_SMP */
> -
> -#ifdef CONFIG_MIPS_GIC_IPI
> -
> -#define GIC_MIPS_CPU_IPI_RESCHED_IRQ 3
> -#define GIC_MIPS_CPU_IPI_CALL_IRQ 4
> -
> static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
> {
> #ifdef CONFIG_MIPS_VPE_APSP_API_CMP
> @@ -349,31 +328,16 @@ static struct irqaction irq_call = {
> .flags = IRQF_PERCPU,
> .name = "IPI_call"
> };
> -#endif /* CONFIG_MIPS_GIC_IPI */
> -
> -static int gic_resched_int_base;
> -static int gic_call_int_base;
> -#define GIC_RESCHED_INT(cpu) (gic_resched_int_base+(cpu))
> -#define GIC_CALL_INT(cpu) (gic_call_int_base+(cpu))
> -
> -unsigned int plat_ipi_call_int_xlate(unsigned int cpu)
> -{
> - return GIC_CALL_INT(cpu);
> -}
> -
> -unsigned int plat_ipi_resched_int_xlate(unsigned int cpu)
> -{
> - return GIC_RESCHED_INT(cpu);
> -}
> +#endif /* CONFIG_MIPS_MT_SMP */
>
> static struct irqaction i8259irq = {
> - .handler = no_action,
> + .handler = i8259_handler,
> .name = "XT-PIC cascade",
> .flags = IRQF_NO_THREAD,
> };
>
> static struct irqaction corehi_irqaction = {
> - .handler = no_action,
> + .handler = corehi_handler,
> .name = "CoreHi",
> .flags = IRQF_NO_THREAD,
> };
> @@ -399,60 +363,6 @@ static msc_irqmap_t msc_eicirqmap[] __initdata = {
>
> static int msc_nr_eicirqs __initdata = ARRAY_SIZE(msc_eicirqmap);
>
> -/*
> - * This GIC specific tabular array defines the association between External
> - * Interrupts and CPUs/Core Interrupts. The nature of the External
> - * Interrupts is also defined here - polarity/trigger.
> - */
> -
> -#define GIC_CPU_NMI GIC_MAP_TO_NMI_MSK
> -#define X GIC_UNUSED
> -
> -static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = {
> - { X, X, X, X, 0 },
> - { X, X, X, X, 0 },
> - { X, X, X, X, 0 },
> - { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
> - { 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
> - { 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
> - { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
> - { 0, GIC_CPU_INT4, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
> - { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
> - { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
> - { X, X, X, X, 0 },
> - { X, X, X, X, 0 },
> - { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
> - { 0, GIC_CPU_NMI, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
> - { 0, GIC_CPU_NMI, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
> - { X, X, X, X, 0 },
> - /* The remainder of this table is initialised by fill_ipi_map */
> -};
> -#undef X
> -
> -#ifdef CONFIG_MIPS_GIC_IPI
> -static void __init fill_ipi_map1(int baseintr, int cpu, int cpupin)
> -{
> - int intr = baseintr + cpu;
> - gic_intr_map[intr].cpunum = cpu;
> - gic_intr_map[intr].pin = cpupin;
> - gic_intr_map[intr].polarity = GIC_POL_POS;
> - gic_intr_map[intr].trigtype = GIC_TRIG_EDGE;
> - gic_intr_map[intr].flags = 0;
> - ipi_map[cpu] |= (1 << (cpupin + 2));
> - bitmap_set(ipi_ints, intr, 1);
> -}
> -
> -static void __init fill_ipi_map(void)
> -{
> - int cpu;
> -
> - for (cpu = 0; cpu < nr_cpu_ids; cpu++) {
> - fill_ipi_map1(gic_resched_int_base, cpu, GIC_CPU_INT1);
> - fill_ipi_map1(gic_call_int_base, cpu, GIC_CPU_INT2);
> - }
> -}
> -#endif
> -
> void __init arch_init_ipiirq(int irq, struct irqaction *action)
> {
> setup_irq(irq, action);
> @@ -461,6 +371,8 @@ void __init arch_init_ipiirq(int irq, struct irqaction *action)
>
> void __init arch_init_irq(void)
> {
> + int corehi_irq, i8259_irq;
> +
> init_i8259_irqs();
>
> if (!cpu_has_veic)
> @@ -507,34 +419,11 @@ void __init arch_init_irq(void)
> msc_nr_irqs);
> }
>
> - if (cpu_has_veic) {
> - set_vi_handler(MSC01E_INT_I8259A, malta_hw0_irqdispatch);
> - set_vi_handler(MSC01E_INT_COREHI, corehi_irqdispatch);
> - setup_irq(MSC01E_INT_BASE+MSC01E_INT_I8259A, &i8259irq);
> - setup_irq(MSC01E_INT_BASE+MSC01E_INT_COREHI, &corehi_irqaction);
> - } else if (cpu_has_vint) {
> - set_vi_handler(MIPSCPU_INT_I8259A, malta_hw0_irqdispatch);
> - set_vi_handler(MIPSCPU_INT_COREHI, corehi_irqdispatch);
> - setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq);
> - setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI,
> - &corehi_irqaction);
> - } else {
> - setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq);
> - setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI,
> - &corehi_irqaction);
> - }
> -
> if (gic_present) {
> - /* FIXME */
> int i;
> -#if defined(CONFIG_MIPS_GIC_IPI)
> - gic_call_int_base = GIC_NUM_INTRS -
> - (NR_CPUS - nr_cpu_ids) * 2 - nr_cpu_ids;
> - gic_resched_int_base = gic_call_int_base - nr_cpu_ids;
> - fill_ipi_map();
> -#endif
> - gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map,
> - ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);
> +
> + gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, MIPSCPU_INT_GIC,
> + MIPS_GIC_IRQ_BASE);
> if (!mips_cm_present()) {
> /* Enable the GIC */
> i = REG(_msc01_biu_base, MSC01_SC_CFG);
> @@ -542,28 +431,8 @@ void __init arch_init_irq(void)
> (i | (0x1 << MSC01_SC_CFG_GICENA_SHF));
> pr_debug("GIC Enabled\n");
> }
> -#if defined(CONFIG_MIPS_GIC_IPI)
> - /* set up ipi interrupts */
> - if (cpu_has_vint) {
> - set_vi_handler(MIPSCPU_INT_IPI0, malta_ipi_irqdispatch);
> - set_vi_handler(MIPSCPU_INT_IPI1, malta_ipi_irqdispatch);
> - }
> - /* Argh.. this really needs sorting out.. */
> - pr_info("CPU%d: status register was %08x\n",
> - smp_processor_id(), read_c0_status());
> - write_c0_status(read_c0_status() | STATUSF_IP3 | STATUSF_IP4);
> - pr_info("CPU%d: status register now %08x\n",
> - smp_processor_id(), read_c0_status());
> - write_c0_status(0x1100dc00);
> - pr_info("CPU%d: status register frc %08x\n",
> - smp_processor_id(), read_c0_status());
> - for (i = 0; i < nr_cpu_ids; i++) {
> - arch_init_ipiirq(MIPS_GIC_IRQ_BASE +
> - GIC_RESCHED_INT(i), &irq_resched);
> - arch_init_ipiirq(MIPS_GIC_IRQ_BASE +
> - GIC_CALL_INT(i), &irq_call);
> - }
> -#endif
> + i8259_irq = MIPS_GIC_IRQ_BASE + GIC_INT_I8259A;
> + corehi_irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_COREHI;
> } else {
> #if defined(CONFIG_MIPS_MT_SMP)
> /* set up ipi interrupts */
> @@ -587,7 +456,21 @@ void __init arch_init_irq(void)
> arch_init_ipiirq(cpu_ipi_resched_irq, &irq_resched);
> arch_init_ipiirq(cpu_ipi_call_irq, &irq_call);
> #endif
> + if (cpu_has_veic) {
> + set_vi_handler(MSC01E_INT_I8259A,
> + malta_hw0_irqdispatch);
> + set_vi_handler(MSC01E_INT_COREHI,
> + corehi_irqdispatch);
> + i8259_irq = MSC01E_INT_BASE + MSC01E_INT_I8259A;
> + corehi_irq = MSC01E_INT_BASE + MSC01E_INT_COREHI;
> + } else {
> + i8259_irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_I8259A;
> + corehi_irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_COREHI;
> + }
> }
> +
> + setup_irq(i8259_irq, &i8259irq);
> + setup_irq(corehi_irq, &corehi_irqaction);
> }
>
> void malta_be_init(void)
> diff --git a/arch/mips/mti-sead3/sead3-ehci.c b/arch/mips/mti-sead3/sead3-ehci.c
> index 772fc05..4ddaa0f 100644
> --- a/arch/mips/mti-sead3/sead3-ehci.c
> +++ b/arch/mips/mti-sead3/sead3-ehci.c
> @@ -10,6 +10,9 @@
> #include <linux/dma-mapping.h>
> #include <linux/platform_device.h>
>
> +#include <asm/gic.h>
> +#include <asm/mips-boards/sead3int.h>
> +
> struct resource ehci_resources[] = {
> {
> .start = 0x1b200000,
> @@ -17,7 +20,6 @@ struct resource ehci_resources[] = {
> .flags = IORESOURCE_MEM
> },
> {
> - .start = MIPS_CPU_IRQ_BASE + 2,
> .flags = IORESOURCE_IRQ
> }
> };
> @@ -37,6 +39,10 @@ static struct platform_device ehci_device = {
>
> static int __init ehci_init(void)
> {
> + if (gic_present)
> + ehci_resources[1].start = MIPS_GIC_IRQ_BASE + GIC_INT_EHCI;
> + else
> + ehci_resources[1].start = MIPS_CPU_IRQ_BASE + CPU_INT_EHCI;
> return platform_device_register(&ehci_device);
> }
>
> diff --git a/arch/mips/mti-sead3/sead3-int.c b/arch/mips/mti-sead3/sead3-int.c
> index 8f36342..cb06cd9 100644
> --- a/arch/mips/mti-sead3/sead3-int.c
> +++ b/arch/mips/mti-sead3/sead3-int.c
> @@ -22,30 +22,6 @@
>
> static unsigned long sead3_config_reg;
>
> -/*
> - * This table defines the setup for each external GIC interrupt. It is
> - * indexed by interrupt number.
> - */
> -#define GIC_CPU_NMI GIC_MAP_TO_NMI_MSK
> -static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = {
> - { 0, GIC_CPU_INT4, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
> - { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
> - { 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
> - { 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
> - { 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
> - { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
> - { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
> - { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
> - { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
> - { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
> - { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
> - { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
> - { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
> - { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
> - { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
> - { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
> -};
> -
> asmlinkage void plat_irq_dispatch(void)
> {
> unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
> @@ -81,7 +57,7 @@ void __init arch_init_irq(void)
> (current_cpu_data.options & MIPS_CPU_VEIC) ? "on" : "off");
>
> if (gic_present)
> - gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map,
> - ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);
> + gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, CPU_INT_GIC,
> + MIPS_GIC_IRQ_BASE);
> }
>
> diff --git a/arch/mips/mti-sead3/sead3-net.c b/arch/mips/mti-sead3/sead3-net.c
> index dd11e7e..c9f728a 100644
> --- a/arch/mips/mti-sead3/sead3-net.c
> +++ b/arch/mips/mti-sead3/sead3-net.c
> @@ -10,6 +10,9 @@
> #include <linux/platform_device.h>
> #include <linux/smsc911x.h>
>
> +#include <asm/gic.h>
> +#include <asm/mips-boards/sead3int.h>
> +
> static struct smsc911x_platform_config sead3_smsc911x_data = {
> .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
> .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
> @@ -17,14 +20,13 @@ static struct smsc911x_platform_config sead3_smsc911x_data = {
> .phy_interface = PHY_INTERFACE_MODE_MII,
> };
>
> -struct resource sead3_net_resourcess[] = {
> +struct resource sead3_net_resources[] = {
> {
> .start = 0x1f010000,
> .end = 0x1f01ffff,
> .flags = IORESOURCE_MEM
> },
> {
> - .start = MIPS_CPU_IRQ_BASE + 6,
> .flags = IORESOURCE_IRQ
> }
> };
> @@ -35,12 +37,16 @@ static struct platform_device sead3_net_device = {
> .dev = {
> .platform_data = &sead3_smsc911x_data,
> },
> - .num_resources = ARRAY_SIZE(sead3_net_resourcess),
> - .resource = sead3_net_resourcess
> + .num_resources = ARRAY_SIZE(sead3_net_resources),
> + .resource = sead3_net_resources
> };
>
> static int __init sead3_net_init(void)
> {
> + if (gic_present)
> + sead3_net_resources[1].start = MIPS_GIC_IRQ_BASE + GIC_INT_NET;
> + else
> + sead3_net_resources[1].start = MIPS_CPU_IRQ_BASE + CPU_INT_NET;
> return platform_device_register(&sead3_net_device);
> }
>
> diff --git a/arch/mips/mti-sead3/sead3-platform.c b/arch/mips/mti-sead3/sead3-platform.c
> index 6c3b33d..d9661eb 100644
> --- a/arch/mips/mti-sead3/sead3-platform.c
> +++ b/arch/mips/mti-sead3/sead3-platform.c
> @@ -9,10 +9,13 @@
> #include <linux/init.h>
> #include <linux/serial_8250.h>
>
> -#define UART(base, int) \
> +#include <asm/gic.h>
> +#include <asm/mips-boards/sead3int.h>
> +
> +#define UART(base) \
> { \
> .mapbase = base, \
> - .irq = int, \
> + .irq = -1, \
> .uartclk = 14745600, \
> .iotype = UPIO_MEM32, \
> .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, \
> @@ -20,8 +23,8 @@
> }
>
> static struct plat_serial8250_port uart8250_data[] = {
> - UART(0x1f000900, MIPS_CPU_IRQ_BASE + 4), /* ttyS0 = USB */
> - UART(0x1f000800, MIPS_CPU_IRQ_BASE + 4), /* ttyS1 = RS232 */
> + UART(0x1f000900), /* ttyS0 = USB */
> + UART(0x1f000800), /* ttyS1 = RS232 */
> { },
> };
>
> @@ -35,6 +38,13 @@ static struct platform_device uart8250_device = {
>
> static int __init uart8250_init(void)
> {
> + if (gic_present) {
> + uart8250_data[0].irq = MIPS_GIC_IRQ_BASE + GIC_INT_UART0;
> + uart8250_data[1].irq = MIPS_GIC_IRQ_BASE + GIC_INT_UART1;
> + } else {
> + uart8250_data[0].irq = MIPS_CPU_IRQ_BASE + CPU_INT_UART0;
> + uart8250_data[1].irq = MIPS_CPU_IRQ_BASE + CPU_INT_UART1;
> + }
> return platform_device_register(&uart8250_device);
> }
>
> diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
> index 64dc5a9..6c9fcbf 100644
> --- a/drivers/irqchip/irq-mips-gic.c
> +++ b/drivers/irqchip/irq-mips-gic.c
> @@ -8,6 +8,8 @@
> */
> #include <linux/bitmap.h>
> #include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/sched.h>
> #include <linux/smp.h>
> #include <linux/irq.h>
> #include <linux/clocksource.h>
> @@ -22,11 +24,8 @@
> unsigned int gic_frequency;
> unsigned int gic_present;
> unsigned long _gic_base;
> -unsigned int gic_irq_base;
> unsigned int gic_irq_flags[GIC_NUM_INTRS];
> -
> -/* The index into this array is the vector # of the interrupt. */
> -struct gic_shared_intr_map gic_shared_intr_map[GIC_NUM_INTRS];
> +unsigned int gic_cpu_pin;
>
> struct gic_pcpu_mask {
> DECLARE_BITMAP(pcpu_mask, GIC_NUM_INTRS);
> @@ -46,6 +45,8 @@ static struct gic_intrmask_regs intrmask_regs[NR_CPUS];
> static DEFINE_SPINLOCK(gic_lock);
> static struct irq_domain *gic_irq_domain;
>
> +static void __gic_irq_dispatch(void);
> +
> #if defined(CONFIG_CSRC_GIC) || defined(CONFIG_CEVT_GIC)
> cycle_t gic_read_count(void)
> {
> @@ -117,21 +118,6 @@ void gic_send_ipi(unsigned int intr)
> GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), 0x80000000 | intr);
> }
>
> -static void gic_eic_irq_dispatch(void)
> -{
> - unsigned int cause = read_c0_cause();
> - int irq;
> -
> - irq = (cause & ST0_IM) >> STATUSB_IP2;
> - if (irq == 0)
> - irq = -1;
> -
> - if (irq >= 0)
> - do_IRQ(gic_irq_base + irq);
> - else
> - spurious_interrupt();
> -}
> -
> static void __init vpe_local_setup(unsigned int numvpes)
> {
> unsigned long timer_intr = GIC_INT_TMR;
> @@ -166,16 +152,15 @@ static void __init vpe_local_setup(unsigned int numvpes)
> GIC_MAP_TO_PIN_MSK | timer_intr);
> if (cpu_has_veic) {
> set_vi_handler(timer_intr + GIC_PIN_TO_VEC_OFFSET,
> - gic_eic_irq_dispatch);
> - gic_shared_intr_map[timer_intr + GIC_PIN_TO_VEC_OFFSET].local_intr_mask |= GIC_VPE_RMASK_TIMER_MSK;
> + __gic_irq_dispatch);
> }
>
> if (vpe_ctl & GIC_VPE_CTL_PERFCNT_RTBL_MSK)
> GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP),
> GIC_MAP_TO_PIN_MSK | perf_intr);
> if (cpu_has_veic) {
> - set_vi_handler(perf_intr + GIC_PIN_TO_VEC_OFFSET, gic_eic_irq_dispatch);
> - gic_shared_intr_map[perf_intr + GIC_PIN_TO_VEC_OFFSET].local_intr_mask |= GIC_VPE_RMASK_PERFCNT_MSK;
> + set_vi_handler(perf_intr + GIC_PIN_TO_VEC_OFFSET,
> + __gic_irq_dispatch);
> }
> }
> }
> @@ -343,64 +328,100 @@ static struct irq_chip gic_irq_controller = {
> #endif
> };
>
> -static void __init gic_setup_intr(unsigned int intr, unsigned int cpu,
> - unsigned int pin, unsigned int polarity, unsigned int trigtype,
> - unsigned int flags)
> +static void __gic_irq_dispatch(void)
> {
> - struct gic_shared_intr_map *map_ptr;
> - int i;
> -
> - /* Setup Intr to Pin mapping */
> - if (pin & GIC_MAP_TO_NMI_MSK) {
> - int i;
> + unsigned int intr, virq;
>
> - GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), pin);
> - /* FIXME: hack to route NMI to all cpu's */
> - for (i = 0; i < NR_CPUS; i += 32) {
> - GICWRITE(GIC_REG_ADDR(SHARED,
> - GIC_SH_MAP_TO_VPE_REG_OFF(intr, i)),
> - 0xffffffff);
> - }
> - } else {
> - GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)),
> - GIC_MAP_TO_PIN_MSK | pin);
> - /* Setup Intr to CPU mapping */
> - GIC_SH_MAP_TO_VPE_SMASK(intr, cpu);
> - if (cpu_has_veic) {
> - set_vi_handler(pin + GIC_PIN_TO_VEC_OFFSET,
> - gic_eic_irq_dispatch);
> - map_ptr = &gic_shared_intr_map[pin + GIC_PIN_TO_VEC_OFFSET];
> - if (map_ptr->num_shared_intr >= GIC_MAX_SHARED_INTR)
> - BUG();
> - map_ptr->intr_list[map_ptr->num_shared_intr++] = intr;
> - }
> + while ((intr = gic_get_int()) != GIC_NUM_INTRS) {
> + virq = irq_linear_revmap(gic_irq_domain, intr);
> + do_IRQ(virq);
> }
> +}
>
> - /* Setup Intr Polarity */
> - GIC_SET_POLARITY(intr, polarity);
> +static void gic_irq_dispatch(unsigned int irq, struct irq_desc *desc)
> +{
> + __gic_irq_dispatch();
> +}
> +
> +#ifdef CONFIG_MIPS_GIC_IPI
> +static int gic_resched_int_base;
> +static int gic_call_int_base;
> +
> +unsigned int plat_ipi_resched_int_xlate(unsigned int cpu)
> +{
> + return gic_resched_int_base + cpu;
> +}
>
> - /* Setup Intr Trigger Type */
> - GIC_SET_TRIGGER(intr, trigtype);
> +unsigned int plat_ipi_call_int_xlate(unsigned int cpu)
> +{
> + return gic_call_int_base + cpu;
> +}
>
> - /* Init Intr Masks */
> - GIC_CLR_INTR_MASK(intr);
> +static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
> +{
> + scheduler_ipi();
> +
> + return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
> +{
> + smp_call_function_interrupt();
> +
> + return IRQ_HANDLED;
> +}
>
> - /* Initialise per-cpu Interrupt software masks */
> +static struct irqaction irq_resched = {
> + .handler = ipi_resched_interrupt,
> + .flags = IRQF_PERCPU,
> + .name = "IPI resched"
> +};
> +
> +static struct irqaction irq_call = {
> + .handler = ipi_call_interrupt,
> + .flags = IRQF_PERCPU,
> + .name = "IPI call"
> +};
> +
> +static __init void gic_ipi_init_one(unsigned int intr, int cpu,
> + struct irqaction *action)
> +{
> + int virq = irq_create_mapping(gic_irq_domain, intr);
> + int i;
> +
> + GIC_SH_MAP_TO_VPE_SMASK(intr, cpu);
> for (i = 0; i < NR_CPUS; i++)
> clear_bit(intr, pcpu_masks[i].pcpu_mask);
> set_bit(intr, pcpu_masks[cpu].pcpu_mask);
>
> - if ((flags & GIC_FLAG_TRANSPARENT) && (cpu_has_veic == 0))
> - GIC_SET_INTR_MASK(intr);
> - if (trigtype == GIC_TRIG_EDGE)
> - gic_irq_flags[intr] |= GIC_TRIG_EDGE;
> + irq_set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
> +
> + irq_set_handler(virq, handle_percpu_irq);
> + setup_irq(virq, action);
> }
>
> -static void __init gic_basic_init(int numintrs, int numvpes,
> - struct gic_intr_map *intrmap, int mapsize)
> +static __init void gic_ipi_init(void)
> {
> - unsigned int i, cpu;
> - unsigned int pin_offset = 0;
> + int i;
> +
> + /* Use last 2 * NR_CPUS interrupts as IPIs */
> + gic_resched_int_base = GIC_NUM_INTRS - nr_cpu_ids;
> + gic_call_int_base = gic_resched_int_base - nr_cpu_ids;
> +
> + for (i = 0; i < nr_cpu_ids; i++) {
> + gic_ipi_init_one(gic_call_int_base + i, i, &irq_call);
> + gic_ipi_init_one(gic_resched_int_base + i, i, &irq_resched);
> + }
> +}
> +#else
> +static inline void gic_ipi_init(void)
> +{
> +}
> +#endif
> +
> +static void __init gic_basic_init(int numintrs, int numvpes)
> +{
> + unsigned int i;
>
> board_bind_eic_interrupt = &gic_bind_eic_interrupt;
>
> @@ -409,31 +430,8 @@ static void __init gic_basic_init(int numintrs, int numvpes,
> GIC_SET_POLARITY(i, GIC_POL_POS);
> GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL);
> GIC_CLR_INTR_MASK(i);
> - if (i < GIC_NUM_INTRS) {
> + if (i < GIC_NUM_INTRS)
> gic_irq_flags[i] = 0;
> - gic_shared_intr_map[i].num_shared_intr = 0;
> - gic_shared_intr_map[i].local_intr_mask = 0;
> - }
> - }
> -
> - /*
> - * In EIC mode, the HW_INT# is offset by (2-1). Need to subtract
> - * one because the GIC will add one (since 0=no intr).
> - */
> - if (cpu_has_veic)
> - pin_offset = (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET);
> -
> - /* Setup specifics */
> - for (i = 0; i < mapsize; i++) {
> - cpu = intrmap[i].cpunum;
> - if (cpu == GIC_UNUSED)
> - continue;
> - gic_setup_intr(i,
> - intrmap[i].cpunum,
> - intrmap[i].pin + pin_offset,
> - intrmap[i].polarity,
> - intrmap[i].trigtype,
> - intrmap[i].flags);
> }
>
> vpe_local_setup(numvpes);
> @@ -448,7 +446,7 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq,
>
> spin_lock_irqsave(&gic_lock, flags);
> GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(hw)),
> - GIC_MAP_TO_PIN_MSK | 0);
> + GIC_MAP_TO_PIN_MSK | gic_cpu_pin);
> /* Map to VPE 0 by default */
> GIC_SH_MAP_TO_VPE_SMASK(hw, 0);
> set_bit(hw, pcpu_masks[0].pcpu_mask);
> @@ -463,8 +461,7 @@ static struct irq_domain_ops gic_irq_domain_ops = {
> };
>
> void __init gic_init(unsigned long gic_base_addr,
> - unsigned long gic_addrspace_size,
> - struct gic_intr_map *intr_map, unsigned int intr_map_size,
> + unsigned long gic_addrspace_size, unsigned int cpu_vec,
> unsigned int irqbase)
> {
> unsigned int gicconfig;
> @@ -472,7 +469,6 @@ void __init gic_init(unsigned long gic_base_addr,
>
> _gic_base = (unsigned long) ioremap_nocache(gic_base_addr,
> gic_addrspace_size);
> - gic_irq_base = irqbase;
>
> GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig);
> numintrs = (gicconfig & GIC_SH_CONFIG_NUMINTRS_MSK) >>
> @@ -483,10 +479,23 @@ void __init gic_init(unsigned long gic_base_addr,
> GIC_SH_CONFIG_NUMVPES_SHF;
> numvpes = numvpes + 1;
>
> + if (cpu_has_veic) {
> + /* Always use vector 1 in EIC mode */
> + gic_cpu_pin = 0;
> + set_vi_handler(gic_cpu_pin + GIC_PIN_TO_VEC_OFFSET,
> + __gic_irq_dispatch);
> + } else {
> + gic_cpu_pin = cpu_vec - GIC_CPU_PIN_OFFSET;
> + irq_set_chained_handler(MIPS_CPU_IRQ_BASE + cpu_vec,
> + gic_irq_dispatch);
> + }
> +
> gic_irq_domain = irq_domain_add_simple(NULL, GIC_NUM_INTRS, irqbase,
> &gic_irq_domain_ops, NULL);
> if (!gic_irq_domain)
> panic("Failed to add GIC IRQ domain");
>
> - gic_basic_init(numintrs, numvpes, intr_map, intr_map_size);
> + gic_basic_init(numintrs, numvpes);
> +
> + gic_ipi_init();
> }
>

Attachment: signature.asc
Description: OpenPGP digital signature