All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V2 00/24] MIPS GIC cleanup, part 1
@ 2014-09-18 21:47 Andrew Bresticker
  2014-09-18 21:47 ` [PATCH V2 01/24] MIPS: Always use IRQ domains for CPU IRQs Andrew Bresticker
                   ` (23 more replies)
  0 siblings, 24 replies; 35+ messages in thread
From: Andrew Bresticker @ 2014-09-18 21:47 UTC (permalink / raw)
  To: Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Andrew Bresticker, Jeffrey Deans, Markos Chandras, Paul Burton,
	Qais Yousef, Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

The current MIPS GIC driver and the platform code using it are rather
ugly and could use a good cleanup before adding device-tree support [0].
This major issues addressed in this series are converting the GIC (and
platforms using it) to use IRQ domains and properly mapping interrupts
through the GIC instead of using it transparently.  For part 2 I plan
on: updating the driver to use proper iomem accessors, cleaning up and
moving the GIC clocksource driver to drivers/clocksource/, adding DT
support, and possibly converting the GIC driver to use generic irqchip.

Patches 1-16 are cleanups for the existing GIC driver and prepare platforms
using it for the switch to IRQ domains and using the GIC in a non-transparent
way.

Patches 17-24 convert the GIC driver to use IRQ domains and updates the
platforms using it to properly map GIC interrupts instead of using the static
routing tables to make the GIC appear transparent.

I've tested this series on Malta and, with additional patches, on the
DT-enabled Pistachio (formerly known as Danube) platform.  Unfortunately
I do not have SEAD-3 hardware, but Qais Yousef has tested V1 of this series
on a SEAD-3.  Compile tested on all other affected architectures (ath79,
ralink, lantiq).

Changes from v1:
 - handle core interrupts in descending order
 - dropped unnecessary irq_chip callbacks when possible
 - used separate irq_chip to deal with C0 timer/perf interrupts
 - added locking around potentially concurrent r-m-w operations

[0] https://lkml.org/lkml/2014/9/5/542

Andrew Bresticker (24):
  MIPS: Always use IRQ domains for CPU IRQs
  MIPS: Rename mips_cpu_intc_init() -> mips_cpu_irq_of_init()
  MIPS: Provide a generic plat_irq_dispatch
  MIPS: Set vint handler when mapping CPU interrupts
  MIPS: i8259: Use IRQ domains
  MIPS: Add hook to get C0 performance counter interrupt
  MIPS: smp-cps: Enable all hardware interrupts on secondary CPUs
  MIPS: Remove gic_{enable,disable}_interrupt()
  MIPS: sead3: Remove sead3-serial.c
  MIPS: sead3: Do not overlap CPU/GIC IRQ ranges
  MIPS: Malta: Move MSC01 interrupt base
  MIPS: Move MIPS_GIC_IRQ_BASE into platform irq.h
  MIPS: Move GIC to drivers/irqchip/
  irqchip: mips-gic: Remove platform irq_ack/irq_eoi callbacks
  irqchip: mips-gic: Implement irq_set_type callback
  irqchip: mips-gic: Fix gic_set_affinity() return value
  irqchip: mips-gic: Use IRQ domains
  irqchip: mips-gic: Stop using per-platform mapping tables
  irqchip: mips-gic: Probe for number of external interrupts
  irqchip: mips-gic: Use separate edge/level irq_chips
  irqchip: mips-gic: Support local interrupts
  irqchip: mips-gic: Remove unnecessary globals
  MIPS: Malta: Use generic plat_irq_dispatch
  MIPS: sead3: Use generic plat_irq_dispatch

 Documentation/devicetree/bindings/mips/cpu_irq.txt |   4 +-
 arch/mips/Kconfig                                  |  12 +-
 arch/mips/ath79/irq.c                              |   1 -
 arch/mips/ath79/setup.c                            |   5 +
 arch/mips/include/asm/gic.h                        |  82 ++-
 arch/mips/include/asm/irq_cpu.h                    |   4 +-
 arch/mips/include/asm/mach-generic/irq.h           |   6 +
 arch/mips/include/asm/mach-malta/irq.h             |   1 -
 arch/mips/include/asm/mach-sead3/irq.h             |   1 -
 arch/mips/include/asm/mips-boards/maltaint.h       |  24 +-
 arch/mips/include/asm/mips-boards/sead3int.h       |  15 +-
 arch/mips/include/asm/time.h                       |   1 +
 arch/mips/kernel/Makefile                          |   1 -
 arch/mips/kernel/cevt-gic.c                        |  14 +-
 arch/mips/kernel/cevt-r4k.c                        |   4 +-
 arch/mips/kernel/i8259.c                           |  24 +-
 arch/mips/kernel/irq-gic.c                         | 402 -------------
 arch/mips/kernel/irq_cpu.c                         |  48 +-
 arch/mips/kernel/perf_event_mipsxx.c               |  23 +-
 arch/mips/kernel/smp-cps.c                         |   4 +-
 arch/mips/kernel/smp-mt.c                          |   4 +-
 arch/mips/lantiq/irq.c                             |   8 +-
 arch/mips/mti-malta/malta-int.c                    | 307 +---------
 arch/mips/mti-malta/malta-time.c                   |  39 +-
 arch/mips/mti-sead3/sead3-ehci.c                   |   8 +-
 arch/mips/mti-sead3/sead3-int.c                    | 121 +---
 arch/mips/mti-sead3/sead3-net.c                    |  14 +-
 arch/mips/mti-sead3/sead3-platform.c               |  18 +-
 arch/mips/mti-sead3/sead3-serial.c                 |  45 --
 arch/mips/mti-sead3/sead3-time.c                   |  35 +-
 arch/mips/oprofile/op_model_mipsxx.c               |  18 +-
 arch/mips/ralink/irq.c                             |  10 +-
 drivers/irqchip/Kconfig                            |   4 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-mips-gic.c                     | 646 +++++++++++++++++++++
 35 files changed, 919 insertions(+), 1035 deletions(-)
 delete mode 100644 arch/mips/kernel/irq-gic.c
 delete mode 100644 arch/mips/mti-sead3/sead3-serial.c
 create mode 100644 drivers/irqchip/irq-mips-gic.c

-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH V2 01/24] MIPS: Always use IRQ domains for CPU IRQs
  2014-09-18 21:47 [PATCH V2 00/24] MIPS GIC cleanup, part 1 Andrew Bresticker
@ 2014-09-18 21:47 ` Andrew Bresticker
  2014-09-18 21:47 ` [PATCH V2 02/24] MIPS: Rename mips_cpu_intc_init() -> mips_cpu_irq_of_init() Andrew Bresticker
                   ` (22 subsequent siblings)
  23 siblings, 0 replies; 35+ messages in thread
From: Andrew Bresticker @ 2014-09-18 21:47 UTC (permalink / raw)
  To: Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Andrew Bresticker, Jeffrey Deans, Markos Chandras, Paul Burton,
	Qais Yousef, Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

Use an IRQ domain for the 8 CPU IRQs in both the DT and non-DT cases.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
Tested-by: Qais Yousef <qais.yousef@imgtec.com>
---
No changes from v1.
---
 arch/mips/Kconfig          |  1 +
 arch/mips/kernel/irq_cpu.c | 36 +++++++++++-------------------------
 2 files changed, 12 insertions(+), 25 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 900c7e5..9fc335c 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1051,6 +1051,7 @@ config MIPS_HUGE_TLB_SUPPORT
 
 config IRQ_CPU
 	bool
+	select IRQ_DOMAIN
 
 config IRQ_CPU_RM7K
 	bool
diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c
index e498f2b..b097f7d 100644
--- a/arch/mips/kernel/irq_cpu.c
+++ b/arch/mips/kernel/irq_cpu.c
@@ -94,28 +94,6 @@ static struct irq_chip mips_mt_cpu_irq_controller = {
 	.irq_eoi	= unmask_mips_irq,
 };
 
-void __init mips_cpu_irq_init(void)
-{
-	int irq_base = MIPS_CPU_IRQ_BASE;
-	int i;
-
-	/* Mask interrupts. */
-	clear_c0_status(ST0_IM);
-	clear_c0_cause(CAUSEF_IP);
-
-	/* Software interrupts are used for MT/CMT IPI */
-	for (i = irq_base; i < irq_base + 2; i++)
-		irq_set_chip_and_handler(i, cpu_has_mipsmt ?
-					 &mips_mt_cpu_irq_controller :
-					 &mips_cpu_irq_controller,
-					 handle_percpu_irq);
-
-	for (i = irq_base + 2; i < irq_base + 8; i++)
-		irq_set_chip_and_handler(i, &mips_cpu_irq_controller,
-					 handle_percpu_irq);
-}
-
-#ifdef CONFIG_IRQ_DOMAIN
 static int mips_cpu_intc_map(struct irq_domain *d, unsigned int irq,
 			     irq_hw_number_t hw)
 {
@@ -138,8 +116,7 @@ static const struct irq_domain_ops mips_cpu_intc_irq_domain_ops = {
 	.xlate = irq_domain_xlate_onecell,
 };
 
-int __init mips_cpu_intc_init(struct device_node *of_node,
-			      struct device_node *parent)
+static void __init __mips_cpu_irq_init(struct device_node *of_node)
 {
 	struct irq_domain *domain;
 
@@ -151,7 +128,16 @@ int __init mips_cpu_intc_init(struct device_node *of_node,
 				       &mips_cpu_intc_irq_domain_ops, NULL);
 	if (!domain)
 		panic("Failed to add irqdomain for MIPS CPU");
+}
+
+void __init mips_cpu_irq_init(void)
+{
+	__mips_cpu_irq_init(NULL);
+}
 
+int __init mips_cpu_intc_init(struct device_node *of_node,
+			      struct device_node *parent)
+{
+	__mips_cpu_irq_init(of_node);
 	return 0;
 }
-#endif /* CONFIG_IRQ_DOMAIN */
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH V2 02/24] MIPS: Rename mips_cpu_intc_init() -> mips_cpu_irq_of_init()
  2014-09-18 21:47 [PATCH V2 00/24] MIPS GIC cleanup, part 1 Andrew Bresticker
  2014-09-18 21:47 ` [PATCH V2 01/24] MIPS: Always use IRQ domains for CPU IRQs Andrew Bresticker
@ 2014-09-18 21:47 ` Andrew Bresticker
  2014-09-18 21:47 ` [PATCH V2 03/24] MIPS: Provide a generic plat_irq_dispatch Andrew Bresticker
                   ` (21 subsequent siblings)
  23 siblings, 0 replies; 35+ messages in thread
From: Andrew Bresticker @ 2014-09-18 21:47 UTC (permalink / raw)
  To: Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Andrew Bresticker, Jeffrey Deans, Markos Chandras, Paul Burton,
	Qais Yousef, Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

mips_cpu_intc_init() is used for DT-based initialization of the CPU
IRQ domain.  Give it a more appropriate name.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
Tested-by: Qais Yousef <qais.yousef@imgtec.com>
---
No changes from v1.
---
 Documentation/devicetree/bindings/mips/cpu_irq.txt | 4 ++--
 arch/mips/include/asm/irq_cpu.h                    | 4 ++--
 arch/mips/kernel/irq_cpu.c                         | 4 ++--
 arch/mips/ralink/irq.c                             | 2 +-
 4 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/Documentation/devicetree/bindings/mips/cpu_irq.txt b/Documentation/devicetree/bindings/mips/cpu_irq.txt
index 13aa4b6..fc149f3 100644
--- a/Documentation/devicetree/bindings/mips/cpu_irq.txt
+++ b/Documentation/devicetree/bindings/mips/cpu_irq.txt
@@ -1,6 +1,6 @@
 MIPS CPU interrupt controller
 
-On MIPS the mips_cpu_intc_init() helper can be used to initialize the 8 CPU
+On MIPS the mips_cpu_irq_of_init() helper can be used to initialize the 8 CPU
 IRQs from a devicetree file and create a irq_domain for IRQ controller.
 
 With the irq_domain in place we can describe how the 8 IRQs are wired to the
@@ -36,7 +36,7 @@ Example devicetree:
 
 Example platform irq.c:
 static struct of_device_id __initdata of_irq_ids[] = {
-	{ .compatible = "mti,cpu-interrupt-controller", .data = mips_cpu_intc_init },
+	{ .compatible = "mti,cpu-interrupt-controller", .data = mips_cpu_irq_of_init },
 	{ .compatible = "ralink,rt2880-intc", .data = intc_of_init },
 	{},
 };
diff --git a/arch/mips/include/asm/irq_cpu.h b/arch/mips/include/asm/irq_cpu.h
index 3f11fdb..39a160b 100644
--- a/arch/mips/include/asm/irq_cpu.h
+++ b/arch/mips/include/asm/irq_cpu.h
@@ -19,8 +19,8 @@ extern void rm9k_cpu_irq_init(void);
 
 #ifdef CONFIG_IRQ_DOMAIN
 struct device_node;
-extern int mips_cpu_intc_init(struct device_node *of_node,
-			      struct device_node *parent);
+extern int mips_cpu_irq_of_init(struct device_node *of_node,
+				struct device_node *parent);
 #endif
 
 #endif /* _ASM_IRQ_CPU_H */
diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c
index b097f7d..ca98a9f 100644
--- a/arch/mips/kernel/irq_cpu.c
+++ b/arch/mips/kernel/irq_cpu.c
@@ -135,8 +135,8 @@ void __init mips_cpu_irq_init(void)
 	__mips_cpu_irq_init(NULL);
 }
 
-int __init mips_cpu_intc_init(struct device_node *of_node,
-			      struct device_node *parent)
+int __init mips_cpu_irq_of_init(struct device_node *of_node,
+				struct device_node *parent)
 {
 	__mips_cpu_irq_init(of_node);
 	return 0;
diff --git a/arch/mips/ralink/irq.c b/arch/mips/ralink/irq.c
index 781b3d1..0495011 100644
--- a/arch/mips/ralink/irq.c
+++ b/arch/mips/ralink/irq.c
@@ -173,7 +173,7 @@ static int __init intc_of_init(struct device_node *node,
 }
 
 static struct of_device_id __initdata of_irq_ids[] = {
-	{ .compatible = "mti,cpu-interrupt-controller", .data = mips_cpu_intc_init },
+	{ .compatible = "mti,cpu-interrupt-controller", .data = mips_cpu_irq_of_init },
 	{ .compatible = "ralink,rt2880-intc", .data = intc_of_init },
 	{},
 };
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH V2 03/24] MIPS: Provide a generic plat_irq_dispatch
  2014-09-18 21:47 [PATCH V2 00/24] MIPS GIC cleanup, part 1 Andrew Bresticker
  2014-09-18 21:47 ` [PATCH V2 01/24] MIPS: Always use IRQ domains for CPU IRQs Andrew Bresticker
  2014-09-18 21:47 ` [PATCH V2 02/24] MIPS: Rename mips_cpu_intc_init() -> mips_cpu_irq_of_init() Andrew Bresticker
@ 2014-09-18 21:47 ` Andrew Bresticker
  2014-09-18 21:47 ` [PATCH V2 04/24] MIPS: Set vint handler when mapping CPU interrupts Andrew Bresticker
                   ` (20 subsequent siblings)
  23 siblings, 0 replies; 35+ messages in thread
From: Andrew Bresticker @ 2014-09-18 21:47 UTC (permalink / raw)
  To: Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Andrew Bresticker, Jeffrey Deans, Markos Chandras, Paul Burton,
	Qais Yousef, Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

For platforms which boot with device-tree or have correctly chained
all external interrupt controllers, a generic plat_irq_dispatch() can
be used.  Implement a plat_irq_dispatch() which simply handles all the
pending interrupts as reported by C0_Cause.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
Tested-by: Qais Yousef <qais.yousef@imgtec.com>
---
Changes from v1:
 - handle interrupts in descending order
---
 arch/mips/kernel/irq_cpu.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c
index ca98a9f..531b11c 100644
--- a/arch/mips/kernel/irq_cpu.c
+++ b/arch/mips/kernel/irq_cpu.c
@@ -94,6 +94,24 @@ static struct irq_chip mips_mt_cpu_irq_controller = {
 	.irq_eoi	= unmask_mips_irq,
 };
 
+asmlinkage void __weak plat_irq_dispatch(void)
+{
+	unsigned long pending = read_c0_cause() & read_c0_status() & ST0_IM;
+	int irq;
+
+	if (!pending) {
+		spurious_interrupt();
+		return;
+	}
+
+	pending >>= CAUSEB_IP;
+	while (pending) {
+		irq = fls(pending) - 1;
+		do_IRQ(MIPS_CPU_IRQ_BASE + irq);
+		pending &= ~BIT(irq);
+	}
+}
+
 static int mips_cpu_intc_map(struct irq_domain *d, unsigned int irq,
 			     irq_hw_number_t hw)
 {
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH V2 04/24] MIPS: Set vint handler when mapping CPU interrupts
  2014-09-18 21:47 [PATCH V2 00/24] MIPS GIC cleanup, part 1 Andrew Bresticker
                   ` (2 preceding siblings ...)
  2014-09-18 21:47 ` [PATCH V2 03/24] MIPS: Provide a generic plat_irq_dispatch Andrew Bresticker
@ 2014-09-18 21:47 ` Andrew Bresticker
  2014-09-18 21:47 ` [PATCH V2 05/24] MIPS: i8259: Use IRQ domains Andrew Bresticker
                   ` (19 subsequent siblings)
  23 siblings, 0 replies; 35+ messages in thread
From: Andrew Bresticker @ 2014-09-18 21:47 UTC (permalink / raw)
  To: Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Andrew Bresticker, Jeffrey Deans, Markos Chandras, Paul Burton,
	Qais Yousef, Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

When mapping an interrupt in the CPU IRQ domain, set the vint handler
for that interrupt if the CPU uses vectored interrupt handling.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
Tested-by: Qais Yousef <qais.yousef@imgtec.com>
---
No changes from v1.
---
 arch/mips/kernel/irq_cpu.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c
index 531b11c..590c2c9 100644
--- a/arch/mips/kernel/irq_cpu.c
+++ b/arch/mips/kernel/irq_cpu.c
@@ -36,6 +36,7 @@
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
 #include <asm/mipsmtregs.h>
+#include <asm/setup.h>
 
 static inline void unmask_mips_irq(struct irq_data *d)
 {
@@ -124,6 +125,9 @@ static int mips_cpu_intc_map(struct irq_domain *d, unsigned int irq,
 		chip = &mips_cpu_irq_controller;
 	}
 
+	if (cpu_has_vint)
+		set_vi_handler(hw, plat_irq_dispatch);
+
 	irq_set_chip_and_handler(irq, chip, handle_percpu_irq);
 
 	return 0;
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH V2 05/24] MIPS: i8259: Use IRQ domains
  2014-09-18 21:47 [PATCH V2 00/24] MIPS GIC cleanup, part 1 Andrew Bresticker
                   ` (3 preceding siblings ...)
  2014-09-18 21:47 ` [PATCH V2 04/24] MIPS: Set vint handler when mapping CPU interrupts Andrew Bresticker
@ 2014-09-18 21:47 ` Andrew Bresticker
  2014-09-18 21:47 ` [PATCH V2 06/24] MIPS: Add hook to get C0 performance counter interrupt Andrew Bresticker
                   ` (18 subsequent siblings)
  23 siblings, 0 replies; 35+ messages in thread
From: Andrew Bresticker @ 2014-09-18 21:47 UTC (permalink / raw)
  To: Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Andrew Bresticker, Jeffrey Deans, Markos Chandras, Paul Burton,
	Qais Yousef, Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

Create a legacy IRQ domain for the 16 i8259 interrupts.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
Tested-by: Qais Yousef <qais.yousef@imgtec.com>
---
No changes from v1.
---
 arch/mips/Kconfig        |  1 +
 arch/mips/kernel/i8259.c | 24 +++++++++++++++++++-----
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 9fc335c..de72c92 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -971,6 +971,7 @@ config SYS_SUPPORTS_HOTPLUG_CPU
 
 config I8259
 	bool
+	select IRQ_DOMAIN
 
 config MIPS_BONITO64
 	bool
diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c
index 50b3648..a74ec3a 100644
--- a/arch/mips/kernel/i8259.c
+++ b/arch/mips/kernel/i8259.c
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
+#include <linux/irqdomain.h>
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
 #include <linux/syscore_ops.h>
@@ -308,6 +309,19 @@ static struct resource pic2_io_resource = {
 	.flags = IORESOURCE_BUSY
 };
 
+static int i8259A_irq_domain_map(struct irq_domain *d, unsigned int virq,
+				 irq_hw_number_t hw)
+{
+	irq_set_chip_and_handler(virq, &i8259A_chip, handle_level_irq);
+	irq_set_probe(virq);
+	return 0;
+}
+
+static struct irq_domain_ops i8259A_ops = {
+	.map = i8259A_irq_domain_map,
+	.xlate = irq_domain_xlate_onecell,
+};
+
 /*
  * On systems with i8259-style interrupt controllers we assume for
  * driver compatibility reasons interrupts 0 - 15 to be the i8259
@@ -315,17 +329,17 @@ static struct resource pic2_io_resource = {
  */
 void __init init_i8259_irqs(void)
 {
-	int i;
+	struct irq_domain *domain;
 
 	insert_resource(&ioport_resource, &pic1_io_resource);
 	insert_resource(&ioport_resource, &pic2_io_resource);
 
 	init_8259A(0);
 
-	for (i = I8259A_IRQ_BASE; i < I8259A_IRQ_BASE + 16; i++) {
-		irq_set_chip_and_handler(i, &i8259A_chip, handle_level_irq);
-		irq_set_probe(i);
-	}
+	domain = irq_domain_add_legacy(NULL, 16, I8259A_IRQ_BASE, 0,
+				       &i8259A_ops, NULL);
+	if (!domain)
+		panic("Failed to add i8259 IRQ domain");
 
 	setup_irq(I8259A_IRQ_BASE + PIC_CASCADE_IR, &irq2);
 }
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH V2 06/24] MIPS: Add hook to get C0 performance counter interrupt
  2014-09-18 21:47 [PATCH V2 00/24] MIPS GIC cleanup, part 1 Andrew Bresticker
                   ` (4 preceding siblings ...)
  2014-09-18 21:47 ` [PATCH V2 05/24] MIPS: i8259: Use IRQ domains Andrew Bresticker
@ 2014-09-18 21:47 ` Andrew Bresticker
  2014-09-18 21:47 ` [PATCH V2 07/24] MIPS: smp-cps: Enable all hardware interrupts on secondary CPUs Andrew Bresticker
                   ` (17 subsequent siblings)
  23 siblings, 0 replies; 35+ messages in thread
From: Andrew Bresticker @ 2014-09-18 21:47 UTC (permalink / raw)
  To: Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Andrew Bresticker, Jeffrey Deans, Markos Chandras, Paul Burton,
	Qais Yousef, Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

The hardware perf event driver and oprofile interpret the global
cp0_perfcount_irq differently: in the hardware perf event driver
it is an offset from MIPS_CPU_IRQ_BASE and in oprofile it is the
actual IRQ number.  This still works most of the time since
MIPS_CPU_IRQ_BASE is usually 0, but is clearly wrong.  Since the
performance counter interrupt may vary from platform to platform
like the C0 timer interrupt, add the optional get_c0_perfcount_int
hook which returns the IRQ number of the performance counter.
The hook should return < 0 if the performance counter interrupt is
shared with the timer.  If the hook is not present, the CPU vector
reported in C0_IntCtl (cp0_perfcount_irq) is used.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
Tested-by: Qais Yousef <qais.yousef@imgtec.com>
---
No changes from v1.
---
 arch/mips/ath79/irq.c                |  1 -
 arch/mips/ath79/setup.c              |  5 +++++
 arch/mips/include/asm/time.h         |  1 +
 arch/mips/kernel/perf_event_mipsxx.c | 23 +++++++----------------
 arch/mips/lantiq/irq.c               |  8 +++++++-
 arch/mips/mti-malta/malta-time.c     | 16 ++++++----------
 arch/mips/mti-sead3/sead3-time.c     |  7 ++++---
 arch/mips/oprofile/op_model_mipsxx.c | 18 ++++++++++++++----
 arch/mips/ralink/irq.c               |  8 +++++++-
 9 files changed, 51 insertions(+), 36 deletions(-)

diff --git a/arch/mips/ath79/irq.c b/arch/mips/ath79/irq.c
index 9c0e176..6adae36 100644
--- a/arch/mips/ath79/irq.c
+++ b/arch/mips/ath79/irq.c
@@ -359,7 +359,6 @@ void __init arch_init_irq(void)
 		BUG();
 	}
 
-	cp0_perfcount_irq = ATH79_MISC_IRQ(5);
 	mips_cpu_irq_init();
 	ath79_misc_irq_init();
 
diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c
index 64807a4..a73c93c 100644
--- a/arch/mips/ath79/setup.c
+++ b/arch/mips/ath79/setup.c
@@ -182,6 +182,11 @@ const char *get_system_type(void)
 	return ath79_sys_type;
 }
 
+int get_c0_perfcount_int(void)
+{
+	return ATH79_MISC_IRQ(5);
+}
+
 unsigned int get_c0_compare_int(void)
 {
 	return CP0_LEGACY_COMPARE_IRQ;
diff --git a/arch/mips/include/asm/time.h b/arch/mips/include/asm/time.h
index 8f3047d..7969933 100644
--- a/arch/mips/include/asm/time.h
+++ b/arch/mips/include/asm/time.h
@@ -46,6 +46,7 @@ extern unsigned int mips_hpt_frequency;
  * so it lives here.
  */
 extern int (*perf_irq)(void);
+extern int __weak get_c0_perfcount_int(void);
 
 /*
  * Initialize the calling CPU's compare interrupt as clockevent device
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
index b63f248..3a25096 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -1614,22 +1614,13 @@ init_hw_perf_events(void)
 		counters = counters_total_to_per_cpu(counters);
 #endif
 
-#ifdef MSC01E_INT_BASE
-	if (cpu_has_veic) {
-		/*
-		 * Using platform specific interrupt controller defines.
-		 */
-		irq = MSC01E_INT_BASE + MSC01E_INT_PERFCTR;
-	} else {
-#endif
-		if ((cp0_perfcount_irq >= 0) &&
-				(cp0_compare_irq != cp0_perfcount_irq))
-			irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
-		else
-			irq = -1;
-#ifdef MSC01E_INT_BASE
-	}
-#endif
+	if (get_c0_perfcount_int)
+		irq = get_c0_perfcount_int();
+	else if ((cp0_perfcount_irq >= 0) &&
+		 (cp0_compare_irq != cp0_perfcount_irq))
+		irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
+	else
+		irq = -1;
 
 	mipspmu.map_raw_event = mipsxx_pmu_map_raw_event;
 
diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
index 030568a..21c38ee 100644
--- a/arch/mips/lantiq/irq.c
+++ b/arch/mips/lantiq/irq.c
@@ -70,6 +70,7 @@ static struct resource ltq_eiu_irq[MAX_EIU];
 static void __iomem *ltq_icu_membase[MAX_IM];
 static void __iomem *ltq_eiu_membase;
 static struct irq_domain *ltq_domain;
+static int ltq_perfcount_irq;
 
 int ltq_eiu_get_irq(int exin)
 {
@@ -449,7 +450,7 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
 #endif
 
 	/* tell oprofile which irq to use */
-	cp0_perfcount_irq = irq_create_mapping(ltq_domain, LTQ_PERF_IRQ);
+	ltq_perfcount_irq = irq_create_mapping(ltq_domain, LTQ_PERF_IRQ);
 
 	/*
 	 * if the timer irq is not one of the mips irqs we need to
@@ -461,6 +462,11 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
 	return 0;
 }
 
+int get_c0_perfcount_int(void)
+{
+	return ltq_perfcount_irq;
+}
+
 unsigned int get_c0_compare_int(void)
 {
 	return MIPS_CPU_TIMER_IRQ;
diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c
index 3778a35..a4e035c 100644
--- a/arch/mips/mti-malta/malta-time.c
+++ b/arch/mips/mti-malta/malta-time.c
@@ -121,22 +121,20 @@ void read_persistent_clock(struct timespec *ts)
 	ts->tv_nsec = 0;
 }
 
-static void __init plat_perf_setup(void)
+int get_c0_perfcount_int(void)
 {
-#ifdef MSC01E_INT_BASE
 	if (cpu_has_veic) {
 		set_vi_handler(MSC01E_INT_PERFCTR, mips_perf_dispatch);
 		mips_cpu_perf_irq = MSC01E_INT_BASE + MSC01E_INT_PERFCTR;
-	} else
-#endif
-	if (cp0_perfcount_irq >= 0) {
+	} else if (cp0_perfcount_irq >= 0) {
 		if (cpu_has_vint)
 			set_vi_handler(cp0_perfcount_irq, mips_perf_dispatch);
 		mips_cpu_perf_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
-#ifdef CONFIG_SMP
-		irq_set_handler(mips_cpu_perf_irq, handle_percpu_irq);
-#endif
+	} else {
+		mips_cpu_perf_irq = -1;
 	}
+
+	return mips_cpu_perf_irq;
 }
 
 unsigned int get_c0_compare_int(void)
@@ -201,6 +199,4 @@ void __init plat_time_init(void)
 #endif
 	}
 #endif
-
-	plat_perf_setup();
 }
diff --git a/arch/mips/mti-sead3/sead3-time.c b/arch/mips/mti-sead3/sead3-time.c
index 678d03d..f090c51 100644
--- a/arch/mips/mti-sead3/sead3-time.c
+++ b/arch/mips/mti-sead3/sead3-time.c
@@ -81,13 +81,16 @@ void read_persistent_clock(struct timespec *ts)
 	ts->tv_nsec = 0;
 }
 
-static void __init plat_perf_setup(void)
+int get_c0_perfcount_int(void)
 {
 	if (cp0_perfcount_irq >= 0) {
 		if (cpu_has_vint)
 			set_vi_handler(cp0_perfcount_irq, mips_perf_dispatch);
 		mips_cpu_perf_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
+	} else {
+		mips_cpu_perf_irq = -1;
 	}
+	return mips_cpu_perf_irq;
 }
 
 unsigned int get_c0_compare_int(void)
@@ -108,6 +111,4 @@ void __init plat_time_init(void)
 		(est_freq % 1000000) * 100 / 1000000);
 
 	mips_scroll_message();
-
-	plat_perf_setup();
 }
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
index 42821ae..01f721a 100644
--- a/arch/mips/oprofile/op_model_mipsxx.c
+++ b/arch/mips/oprofile/op_model_mipsxx.c
@@ -11,6 +11,7 @@
 #include <linux/interrupt.h>
 #include <linux/smp.h>
 #include <asm/irq_regs.h>
+#include <asm/time.h>
 
 #include "op_impl.h"
 
@@ -35,6 +36,7 @@
 #define M_PERFCTL_COUNT_ALL_THREADS	(1UL	  << 13)
 
 static int (*save_perf_irq)(void);
+static int perfcount_irq;
 
 /*
  * XLR has only one set of counters per core. Designate the
@@ -431,8 +433,16 @@ static int __init mipsxx_init(void)
 	save_perf_irq = perf_irq;
 	perf_irq = mipsxx_perfcount_handler;
 
-	if ((cp0_perfcount_irq >= 0) && (cp0_compare_irq != cp0_perfcount_irq))
-		return request_irq(cp0_perfcount_irq, mipsxx_perfcount_int,
+	if (get_c0_perfcount_int)
+		perfcount_irq = get_c0_perfcount_int();
+	else if ((cp0_perfcount_irq >= 0) &&
+		 (cp0_compare_irq != cp0_perfcount_irq))
+		perfcount_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
+	else
+		perfcount_irq = -1;
+
+	if (perfcount_irq >= 0)
+		return request_irq(perfcount_irq, mipsxx_perfcount_int,
 			0, "Perfcounter", save_perf_irq);
 
 	return 0;
@@ -442,8 +452,8 @@ static void mipsxx_exit(void)
 {
 	int counters = op_model_mipsxx_ops.num_counters;
 
-	if ((cp0_perfcount_irq >= 0) && (cp0_compare_irq != cp0_perfcount_irq))
-		free_irq(cp0_perfcount_irq, save_perf_irq);
+	if (perfcount_irq >= 0)
+		free_irq(perfcount_irq, save_perf_irq);
 
 	counters = counters_per_cpu_to_total(counters);
 	on_each_cpu(reset_counters, (void *)(long)counters, 1);
diff --git a/arch/mips/ralink/irq.c b/arch/mips/ralink/irq.c
index 0495011..7634dcd 100644
--- a/arch/mips/ralink/irq.c
+++ b/arch/mips/ralink/irq.c
@@ -45,6 +45,7 @@
 #define RALINK_INTC_IRQ_PERFC   (RALINK_INTC_IRQ_BASE + 9)
 
 static void __iomem *rt_intc_membase;
+static int rt_perfcount_irq;
 
 static inline void rt_intc_w32(u32 val, unsigned reg)
 {
@@ -73,6 +74,11 @@ static struct irq_chip ralink_intc_irq_chip = {
 	.irq_mask_ack	= ralink_intc_irq_mask,
 };
 
+int get_c0_perfcount_int(void)
+{
+	return rt_perfcount_irq;
+}
+
 unsigned int get_c0_compare_int(void)
 {
 	return CP0_LEGACY_COMPARE_IRQ;
@@ -167,7 +173,7 @@ static int __init intc_of_init(struct device_node *node,
 	irq_set_handler_data(irq, domain);
 
 	/* tell the kernel which irq is used for performance monitoring */
-	cp0_perfcount_irq = irq_create_mapping(domain, 9);
+	rt_perfcount_irq = irq_create_mapping(domain, 9);
 
 	return 0;
 }
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH V2 07/24] MIPS: smp-cps: Enable all hardware interrupts on secondary CPUs
  2014-09-18 21:47 [PATCH V2 00/24] MIPS GIC cleanup, part 1 Andrew Bresticker
                   ` (5 preceding siblings ...)
  2014-09-18 21:47 ` [PATCH V2 06/24] MIPS: Add hook to get C0 performance counter interrupt Andrew Bresticker
@ 2014-09-18 21:47 ` Andrew Bresticker
  2014-09-18 21:47 ` [PATCH V2 08/24] MIPS: Remove gic_{enable,disable}_interrupt() Andrew Bresticker
                   ` (16 subsequent siblings)
  23 siblings, 0 replies; 35+ messages in thread
From: Andrew Bresticker @ 2014-09-18 21:47 UTC (permalink / raw)
  To: Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Andrew Bresticker, Jeffrey Deans, Markos Chandras, Paul Burton,
	Qais Yousef, Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

Currently interrupt vectors 2 and 5 are left disabled on secondary CPUs.
Since systems using CPS must also have a GIC, which is responsible for
routing all external interrupts and can map them to any hardware interrupt
vector, enable the remaining vectors.  The two software interrupt vectors
are left disabled since they are not used with CPS.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
Tested-by: Qais Yousef <qais.yousef@imgtec.com>
---
No changes from v1.
---
 arch/mips/kernel/smp-cps.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c
index e6e16a1..cd20aca 100644
--- a/arch/mips/kernel/smp-cps.c
+++ b/arch/mips/kernel/smp-cps.c
@@ -273,8 +273,8 @@ static void cps_init_secondary(void)
 	if (cpu_has_mipsmt)
 		dmt();
 
-	change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 |
-				 STATUSF_IP6 | STATUSF_IP7);
+	change_c0_status(ST0_IM, STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 |
+				 STATUSF_IP5 | STATUSF_IP6 | STATUSF_IP7);
 }
 
 static void cps_smp_finish(void)
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH V2 08/24] MIPS: Remove gic_{enable,disable}_interrupt()
  2014-09-18 21:47 [PATCH V2 00/24] MIPS GIC cleanup, part 1 Andrew Bresticker
                   ` (6 preceding siblings ...)
  2014-09-18 21:47 ` [PATCH V2 07/24] MIPS: smp-cps: Enable all hardware interrupts on secondary CPUs Andrew Bresticker
@ 2014-09-18 21:47 ` Andrew Bresticker
  2014-09-18 21:47 ` [PATCH V2 09/24] MIPS: sead3: Remove sead3-serial.c Andrew Bresticker
                   ` (15 subsequent siblings)
  23 siblings, 0 replies; 35+ messages in thread
From: Andrew Bresticker @ 2014-09-18 21:47 UTC (permalink / raw)
  To: Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Andrew Bresticker, Jeffrey Deans, Markos Chandras, Paul Burton,
	Qais Yousef, Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

Nothing calls gic_{enable,disable}_interrupt() any more.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
Tested-by: Qais Yousef <qais.yousef@imgtec.com>
---
No changes from v1.
---
 arch/mips/include/asm/gic.h     |  2 --
 arch/mips/mti-malta/malta-int.c | 10 ----------
 arch/mips/mti-sead3/sead3-int.c | 34 ----------------------------------
 3 files changed, 46 deletions(-)

diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h
index d7699cf..022d831 100644
--- a/arch/mips/include/asm/gic.h
+++ b/arch/mips/include/asm/gic.h
@@ -376,8 +376,6 @@ extern void gic_bind_eic_interrupt(int irq, int set);
 extern unsigned int gic_get_timer_pending(void);
 extern void gic_get_int_mask(unsigned long *dst, const unsigned long *src);
 extern unsigned int gic_get_int(void);
-extern void gic_enable_interrupt(int irq_vec);
-extern void gic_disable_interrupt(int irq_vec);
 extern void gic_irq_ack(struct irq_data *d);
 extern void gic_finish_irq(struct irq_data *d);
 extern void gic_platform_init(int irqs, struct irq_chip *irq_controller);
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c
index e4f43ba..5c31208 100644
--- a/arch/mips/mti-malta/malta-int.c
+++ b/arch/mips/mti-malta/malta-int.c
@@ -715,16 +715,6 @@ int malta_be_handler(struct pt_regs *regs, int is_fixup)
 	return retval;
 }
 
-void gic_enable_interrupt(int irq_vec)
-{
-	GIC_SET_INTR_MASK(irq_vec);
-}
-
-void gic_disable_interrupt(int irq_vec)
-{
-	GIC_CLR_INTR_MASK(irq_vec);
-}
-
 void gic_irq_ack(struct irq_data *d)
 {
 	int irq = (d->irq - gic_irq_base);
diff --git a/arch/mips/mti-sead3/sead3-int.c b/arch/mips/mti-sead3/sead3-int.c
index 6a560ac..9d5b5bd 100644
--- a/arch/mips/mti-sead3/sead3-int.c
+++ b/arch/mips/mti-sead3/sead3-int.c
@@ -85,40 +85,6 @@ void __init arch_init_irq(void)
 			ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);
 }
 
-void gic_enable_interrupt(int irq_vec)
-{
-	unsigned int i, irq_source;
-
-	/* enable all the interrupts associated with this vector */
-	for (i = 0; i < gic_shared_intr_map[irq_vec].num_shared_intr; i++) {
-		irq_source = gic_shared_intr_map[irq_vec].intr_list[i];
-		GIC_SET_INTR_MASK(irq_source);
-	}
-	/* enable all local interrupts associated with this vector */
-	if (gic_shared_intr_map[irq_vec].local_intr_mask) {
-		GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), 0);
-		GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_SMASK),
-			gic_shared_intr_map[irq_vec].local_intr_mask);
-	}
-}
-
-void gic_disable_interrupt(int irq_vec)
-{
-	unsigned int i, irq_source;
-
-	/* disable all the interrupts associated with this vector */
-	for (i = 0; i < gic_shared_intr_map[irq_vec].num_shared_intr; i++) {
-		irq_source = gic_shared_intr_map[irq_vec].intr_list[i];
-		GIC_CLR_INTR_MASK(irq_source);
-	}
-	/* disable all local interrupts associated with this vector */
-	if (gic_shared_intr_map[irq_vec].local_intr_mask) {
-		GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), 0);
-		GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_RMASK),
-			gic_shared_intr_map[irq_vec].local_intr_mask);
-	}
-}
-
 void gic_irq_ack(struct irq_data *d)
 {
 	GIC_CLR_INTR_MASK(d->irq - gic_irq_base);
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH V2 09/24] MIPS: sead3: Remove sead3-serial.c
  2014-09-18 21:47 [PATCH V2 00/24] MIPS GIC cleanup, part 1 Andrew Bresticker
                   ` (7 preceding siblings ...)
  2014-09-18 21:47 ` [PATCH V2 08/24] MIPS: Remove gic_{enable,disable}_interrupt() Andrew Bresticker
@ 2014-09-18 21:47 ` Andrew Bresticker
  2014-09-18 21:47 ` [PATCH V2 10/24] MIPS: sead3: Do not overlap CPU/GIC IRQ ranges Andrew Bresticker
                   ` (14 subsequent siblings)
  23 siblings, 0 replies; 35+ messages in thread
From: Andrew Bresticker @ 2014-09-18 21:47 UTC (permalink / raw)
  To: Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Andrew Bresticker, Jeffrey Deans, Markos Chandras, Paul Burton,
	Qais Yousef, Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

It's a duplicate of sead3-platform.c and is not even compiled.
Remove it before we start fixing up IRQ assignments.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
Tested-by: Qais Yousef <qais.yousef@imgtec.com>
---
No changes from v1.
---
 arch/mips/mti-sead3/sead3-serial.c | 45 --------------------------------------
 1 file changed, 45 deletions(-)
 delete mode 100644 arch/mips/mti-sead3/sead3-serial.c

diff --git a/arch/mips/mti-sead3/sead3-serial.c b/arch/mips/mti-sead3/sead3-serial.c
deleted file mode 100644
index bc52705..0000000
--- a/arch/mips/mti-sead3/sead3-serial.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2012 MIPS Technologies, Inc.  All rights reserved.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/serial_8250.h>
-
-#define UART(base, int)							\
-{									\
-	.mapbase	= base,						\
-	.irq		= int,						\
-	.uartclk	= 14745600,					\
-	.iotype		= UPIO_MEM32,					\
-	.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, \
-	.regshift	= 2,						\
-}
-
-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 */
-	{ },
-};
-
-static struct platform_device uart8250_device = {
-	.name			= "serial8250",
-	.id			= PLAT8250_DEV_PLATFORM,
-	.dev			= {
-		.platform_data	= uart8250_data,
-	},
-};
-
-static int __init uart8250_init(void)
-{
-	return platform_device_register(&uart8250_device);
-}
-
-module_init(uart8250_init);
-
-MODULE_AUTHOR("Chris Dearman <chris@mips.com>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("8250 UART probe driver for the SEAD-3 platform");
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH V2 10/24] MIPS: sead3: Do not overlap CPU/GIC IRQ ranges
  2014-09-18 21:47 [PATCH V2 00/24] MIPS GIC cleanup, part 1 Andrew Bresticker
                   ` (8 preceding siblings ...)
  2014-09-18 21:47 ` [PATCH V2 09/24] MIPS: sead3: Remove sead3-serial.c Andrew Bresticker
@ 2014-09-18 21:47 ` Andrew Bresticker
  2014-09-18 21:47 ` [PATCH V2 11/24] MIPS: Malta: Move MSC01 interrupt base Andrew Bresticker
                   ` (13 subsequent siblings)
  23 siblings, 0 replies; 35+ messages in thread
From: Andrew Bresticker @ 2014-09-18 21:47 UTC (permalink / raw)
  To: Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Andrew Bresticker, Jeffrey Deans, Markos Chandras, Paul Burton,
	Qais Yousef, Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

In preparation for GIC IRQ domain support, assign a GIC IRQ base
that does not overlap with the CPU IRQs.

Note that this breaks SEAD-3 when the GIC is in EIC mode, though
I'm not convinced it was working before either.  It will be fixed
in the following patches.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
Tested-by: Qais Yousef <qais.yousef@imgtec.com>
---
No changes from v1.
---
 arch/mips/include/asm/mips-boards/sead3int.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/include/asm/mips-boards/sead3int.h b/arch/mips/include/asm/mips-boards/sead3int.h
index 6b17aaf..2320331 100644
--- a/arch/mips/include/asm/mips-boards/sead3int.h
+++ b/arch/mips/include/asm/mips-boards/sead3int.h
@@ -14,6 +14,6 @@
 #define GIC_BASE_ADDR		0x1b1c0000
 #define GIC_ADDRSPACE_SZ	(128 * 1024)
 
-#define MIPS_GIC_IRQ_BASE	(MIPS_CPU_IRQ_BASE + 0)
+#define MIPS_GIC_IRQ_BASE	(MIPS_CPU_IRQ_BASE + 8)
 
 #endif /* !(_MIPS_SEAD3INT_H) */
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH V2 11/24] MIPS: Malta: Move MSC01 interrupt base
  2014-09-18 21:47 [PATCH V2 00/24] MIPS GIC cleanup, part 1 Andrew Bresticker
                   ` (9 preceding siblings ...)
  2014-09-18 21:47 ` [PATCH V2 10/24] MIPS: sead3: Do not overlap CPU/GIC IRQ ranges Andrew Bresticker
@ 2014-09-18 21:47 ` Andrew Bresticker
  2014-09-18 21:47 ` [PATCH V2 12/24] MIPS: Move MIPS_GIC_IRQ_BASE into platform irq.h Andrew Bresticker
                   ` (12 subsequent siblings)
  23 siblings, 0 replies; 35+ messages in thread
From: Andrew Bresticker @ 2014-09-18 21:47 UTC (permalink / raw)
  To: Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Andrew Bresticker, Jeffrey Deans, Markos Chandras, Paul Burton,
	Qais Yousef, Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

The GIC on Malta boards supports a total of 47 interrupts (40 shared
and 7 local) and is assigned a base of 24.  This overlaps with the
MSC01 interrupt assignments which have a base of 64, so move the MSC01
interrupt base back a bit to give the GIC some room.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
Tested-by: Qais Yousef <qais.yousef@imgtec.com>
---
No changes from v1.
---
 arch/mips/include/asm/mips-boards/maltaint.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/mips/include/asm/mips-boards/maltaint.h b/arch/mips/include/asm/mips-boards/maltaint.h
index e330732..4186606 100644
--- a/arch/mips/include/asm/mips-boards/maltaint.h
+++ b/arch/mips/include/asm/mips-boards/maltaint.h
@@ -33,18 +33,18 @@
 #define MIPSCPU_INT_CORELO	MIPSCPU_INT_MB4
 
 /*
- * Interrupts 64..127 are used for Soc-it Classic interrupts
+ * Interrupts 96..127 are used for Soc-it Classic interrupts
  */
-#define MSC01C_INT_BASE		64
+#define MSC01C_INT_BASE		96
 
 /* SOC-it Classic interrupt offsets */
 #define MSC01C_INT_TMR		0
 #define MSC01C_INT_PCI		1
 
 /*
- * Interrupts 64..127 are used for Soc-it EIC interrupts
+ * Interrupts 96..127 are used for Soc-it EIC interrupts
  */
-#define MSC01E_INT_BASE		64
+#define MSC01E_INT_BASE		96
 
 /* SOC-it EIC interrupt offsets */
 #define MSC01E_INT_SW0		1
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH V2 12/24] MIPS: Move MIPS_GIC_IRQ_BASE into platform irq.h
  2014-09-18 21:47 [PATCH V2 00/24] MIPS GIC cleanup, part 1 Andrew Bresticker
                   ` (10 preceding siblings ...)
  2014-09-18 21:47 ` [PATCH V2 11/24] MIPS: Malta: Move MSC01 interrupt base Andrew Bresticker
@ 2014-09-18 21:47 ` Andrew Bresticker
  2014-09-18 21:47 ` [PATCH V2 13/24] MIPS: Move GIC to drivers/irqchip/ Andrew Bresticker
                   ` (11 subsequent siblings)
  23 siblings, 0 replies; 35+ messages in thread
From: Andrew Bresticker @ 2014-09-18 21:47 UTC (permalink / raw)
  To: Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Andrew Bresticker, Jeffrey Deans, Markos Chandras, Paul Burton,
	Qais Yousef, Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

Define a generic MIPS_GIC_IRQ_BASE which should be suitable for all
current boards in <mach-generic/irq.h>.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
Tested-by: Qais Yousef <qais.yousef@imgtec.com>
---
No changes from v1.
---
 arch/mips/include/asm/mach-generic/irq.h     | 6 ++++++
 arch/mips/include/asm/mips-boards/maltaint.h | 2 --
 arch/mips/include/asm/mips-boards/sead3int.h | 2 --
 3 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/arch/mips/include/asm/mach-generic/irq.h b/arch/mips/include/asm/mach-generic/irq.h
index 139cd20..050e18b 100644
--- a/arch/mips/include/asm/mach-generic/irq.h
+++ b/arch/mips/include/asm/mach-generic/irq.h
@@ -36,4 +36,10 @@
 
 #endif /* CONFIG_IRQ_CPU */
 
+#ifdef CONFIG_MIPS_GIC
+#ifndef MIPS_GIC_IRQ_BASE
+#define MIPS_GIC_IRQ_BASE (MIPS_CPU_IRQ_BASE + 8)
+#endif
+#endif /* CONFIG_MIPS_GIC */
+
 #endif /* __ASM_MACH_GENERIC_IRQ_H */
diff --git a/arch/mips/include/asm/mips-boards/maltaint.h b/arch/mips/include/asm/mips-boards/maltaint.h
index 4186606..d741628 100644
--- a/arch/mips/include/asm/mips-boards/maltaint.h
+++ b/arch/mips/include/asm/mips-boards/maltaint.h
@@ -10,8 +10,6 @@
 #ifndef _MIPS_MALTAINT_H
 #define _MIPS_MALTAINT_H
 
-#define MIPS_GIC_IRQ_BASE	(MIPS_CPU_IRQ_BASE + 8)
-
 /*
  * Interrupts 0..15 are used for Malta ISA compatible interrupts
  */
diff --git a/arch/mips/include/asm/mips-boards/sead3int.h b/arch/mips/include/asm/mips-boards/sead3int.h
index 2320331..11ebec9 100644
--- a/arch/mips/include/asm/mips-boards/sead3int.h
+++ b/arch/mips/include/asm/mips-boards/sead3int.h
@@ -14,6 +14,4 @@
 #define GIC_BASE_ADDR		0x1b1c0000
 #define GIC_ADDRSPACE_SZ	(128 * 1024)
 
-#define MIPS_GIC_IRQ_BASE	(MIPS_CPU_IRQ_BASE + 8)
-
 #endif /* !(_MIPS_SEAD3INT_H) */
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH V2 13/24] MIPS: Move GIC to drivers/irqchip/
  2014-09-18 21:47 [PATCH V2 00/24] MIPS GIC cleanup, part 1 Andrew Bresticker
                   ` (11 preceding siblings ...)
  2014-09-18 21:47 ` [PATCH V2 12/24] MIPS: Move MIPS_GIC_IRQ_BASE into platform irq.h Andrew Bresticker
@ 2014-09-18 21:47 ` Andrew Bresticker
  2014-09-18 21:47 ` [PATCH V2 14/24] irqchip: mips-gic: Remove platform irq_ack/irq_eoi callbacks Andrew Bresticker
                   ` (10 subsequent siblings)
  23 siblings, 0 replies; 35+ messages in thread
From: Andrew Bresticker @ 2014-09-18 21:47 UTC (permalink / raw)
  To: Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Andrew Bresticker, Jeffrey Deans, Markos Chandras, Paul Burton,
	Qais Yousef, Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

Move GIC irqchip support to drivers/irqchip/ and rename the Kconfig
option from IRQ_GIC to MIPS_GIC to avoid confusion with the ARM GIC.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Acked-by: Jason Cooper <jason@lakedaemon.net>
Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
Tested-by: Qais Yousef <qais.yousef@imgtec.com>
---
No changes from v1.
---
 arch/mips/Kconfig                                            | 10 +++-------
 arch/mips/kernel/Makefile                                    |  1 -
 arch/mips/kernel/cevt-r4k.c                                  |  2 +-
 arch/mips/kernel/smp-mt.c                                    |  4 ++--
 arch/mips/mti-malta/malta-time.c                             | 10 +++++-----
 drivers/irqchip/Kconfig                                      |  4 ++++
 drivers/irqchip/Makefile                                     |  1 +
 arch/mips/kernel/irq-gic.c => drivers/irqchip/irq-mips-gic.c |  0
 8 files changed, 16 insertions(+), 16 deletions(-)
 rename arch/mips/kernel/irq-gic.c => drivers/irqchip/irq-mips-gic.c (100%)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index de72c92..a0720d0 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -319,7 +319,7 @@ config MIPS_MALTA
 	select GENERIC_ISA_DMA
 	select HAVE_PCSPKR_PLATFORM
 	select IRQ_CPU
-	select IRQ_GIC
+	select MIPS_GIC
 	select HW_HAS_PCI
 	select I8253
 	select I8259
@@ -360,7 +360,7 @@ config MIPS_SEAD3
 	select CPU_MIPSR2_IRQ_EI
 	select DMA_NONCOHERENT
 	select IRQ_CPU
-	select IRQ_GIC
+	select MIPS_GIC
 	select LIBFDT
 	select MIPS_MSC
 	select SYS_HAS_CPU_MIPS32_R1
@@ -1069,10 +1069,6 @@ config IRQ_TXX9
 config IRQ_GT641XX
 	bool
 
-config IRQ_GIC
-	select MIPS_CM
-	bool
-
 config PCI_GT64XXX_PCI0
 	bool
 
@@ -1886,7 +1882,7 @@ config FORCE_MAX_ZONEORDER
 
 config CEVT_GIC
 	bool "Use GIC global counter for clock events"
-	depends on IRQ_GIC && !MIPS_SEAD3
+	depends on MIPS_GIC && !MIPS_SEAD3
 	help
 	  Use the GIC global counter for the clock events. The R4K clock
 	  event driver is always present, so if the platform ends up not
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 008a2fe..3982e51 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -68,7 +68,6 @@ obj-$(CONFIG_IRQ_CPU_RM7K)	+= irq-rm7000.o
 obj-$(CONFIG_MIPS_MSC)		+= irq-msc01.o
 obj-$(CONFIG_IRQ_TXX9)		+= irq_txx9.o
 obj-$(CONFIG_IRQ_GT641XX)	+= irq-gt641xx.o
-obj-$(CONFIG_IRQ_GIC)		+= irq-gic.o
 
 obj-$(CONFIG_KPROBES)		+= kprobes.o
 obj-$(CONFIG_32BIT)		+= scall32-o32.o
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
index bc127e2..5b8f8e3 100644
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -85,7 +85,7 @@ void mips_event_handler(struct clock_event_device *dev)
  */
 static int c0_compare_int_pending(void)
 {
-#ifdef CONFIG_IRQ_GIC
+#ifdef CONFIG_MIPS_GIC
 	if (cpu_has_veic)
 		return gic_get_timer_pending();
 #endif
diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c
index 21f23ad..d60475f 100644
--- a/arch/mips/kernel/smp-mt.c
+++ b/arch/mips/kernel/smp-mt.c
@@ -119,7 +119,7 @@ static void vsmp_send_ipi_single(int cpu, unsigned int action)
 	unsigned long flags;
 	int vpflags;
 
-#ifdef CONFIG_IRQ_GIC
+#ifdef CONFIG_MIPS_GIC
 	if (gic_present) {
 		gic_send_ipi_single(cpu, action);
 		return;
@@ -158,7 +158,7 @@ static void vsmp_send_ipi_mask(const struct cpumask *mask, unsigned int action)
 
 static void vsmp_init_secondary(void)
 {
-#ifdef CONFIG_IRQ_GIC
+#ifdef CONFIG_MIPS_GIC
 	/* This is Malta specific: IPI,performance and timer interrupts */
 	if (gic_present)
 		change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 |
diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c
index a4e035c..17cfc8a 100644
--- a/arch/mips/mti-malta/malta-time.c
+++ b/arch/mips/mti-malta/malta-time.c
@@ -70,7 +70,7 @@ static void __init estimate_frequencies(void)
 {
 	unsigned long flags;
 	unsigned int count, start;
-#ifdef CONFIG_IRQ_GIC
+#ifdef CONFIG_MIPS_GIC
 	unsigned int giccount = 0, gicstart = 0;
 #endif
 
@@ -87,7 +87,7 @@ static void __init estimate_frequencies(void)
 
 	/* Initialize counters. */
 	start = read_c0_count();
-#ifdef CONFIG_IRQ_GIC
+#ifdef CONFIG_MIPS_GIC
 	if (gic_present)
 		GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_31_00), gicstart);
 #endif
@@ -97,7 +97,7 @@ static void __init estimate_frequencies(void)
 	while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
 
 	count = read_c0_count();
-#ifdef CONFIG_IRQ_GIC
+#ifdef CONFIG_MIPS_GIC
 	if (gic_present)
 		GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_31_00), giccount);
 #endif
@@ -107,7 +107,7 @@ static void __init estimate_frequencies(void)
 	count -= start;
 	mips_hpt_frequency = count;
 
-#ifdef CONFIG_IRQ_GIC
+#ifdef CONFIG_MIPS_GIC
 	if (gic_present) {
 		giccount -= gicstart;
 		gic_frequency = giccount;
@@ -189,7 +189,7 @@ void __init plat_time_init(void)
 	setup_pit_timer();
 #endif
 
-#ifdef CONFIG_IRQ_GIC
+#ifdef CONFIG_MIPS_GIC
 	if (gic_present) {
 		freq = freqround(gic_frequency, 5000);
 		printk("GIC frequency %d.%02d MHz\n", freq/1000000,
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index b8632bf..ddacccf 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -113,3 +113,7 @@ config IRQ_CROSSBAR
 	  The primary irqchip invokes the crossbar's callback which inturn allocates
 	  a free irq and configures the IP. Thus the peripheral interrupts are
 	  routed to one of the free irqchip interrupt lines.
+
+config MIPS_GIC
+	bool
+	select MIPS_CM
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 73052ba..fd47e0d 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -34,3 +34,4 @@ obj-$(CONFIG_XTENSA)			+= irq-xtensa-pic.o
 obj-$(CONFIG_XTENSA_MX)			+= irq-xtensa-mx.o
 obj-$(CONFIG_IRQ_CROSSBAR)		+= irq-crossbar.o
 obj-$(CONFIG_BRCMSTB_L2_IRQ)		+= irq-brcmstb-l2.o
+obj-$(CONFIG_MIPS_GIC)			+= irq-mips-gic.o
diff --git a/arch/mips/kernel/irq-gic.c b/drivers/irqchip/irq-mips-gic.c
similarity index 100%
rename from arch/mips/kernel/irq-gic.c
rename to drivers/irqchip/irq-mips-gic.c
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH V2 14/24] irqchip: mips-gic: Remove platform irq_ack/irq_eoi callbacks
  2014-09-18 21:47 [PATCH V2 00/24] MIPS GIC cleanup, part 1 Andrew Bresticker
                   ` (12 preceding siblings ...)
  2014-09-18 21:47 ` [PATCH V2 13/24] MIPS: Move GIC to drivers/irqchip/ Andrew Bresticker
@ 2014-09-18 21:47 ` Andrew Bresticker
  2014-09-18 21:47 ` [PATCH V2 15/24] irqchip: mips-gic: Implement irq_set_type callback Andrew Bresticker
                   ` (9 subsequent siblings)
  23 siblings, 0 replies; 35+ messages in thread
From: Andrew Bresticker @ 2014-09-18 21:47 UTC (permalink / raw)
  To: Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Andrew Bresticker, Jeffrey Deans, Markos Chandras, Paul Burton,
	Qais Yousef, Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

There's no need for platforms to have their own GIC irq_ack/irq_eoi
callbacks.  irq_ack need only clear the GIC's edge detector on
edge-triggered interrupts and there's no need at all for irq_eoi.
Also get rid of the mask_ack callback since it's not necessary either.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Acked-by: Jason Cooper <jason@lakedaemon.net>
Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
Tested-by: Qais Yousef <qais.yousef@imgtec.com>
---
Changes from v1:
 - made irq_ack only clear the edge detector
 - removed irq_eoi and irq_mask_ack
---
 arch/mips/include/asm/gic.h     |  2 --
 arch/mips/mti-malta/malta-int.c | 16 ----------------
 arch/mips/mti-sead3/sead3-int.c | 21 ---------------------
 drivers/irqchip/irq-mips-gic.c  | 11 ++++++++---
 4 files changed, 8 insertions(+), 42 deletions(-)

diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h
index 022d831..1bf7985 100644
--- a/arch/mips/include/asm/gic.h
+++ b/arch/mips/include/asm/gic.h
@@ -376,7 +376,5 @@ extern void gic_bind_eic_interrupt(int irq, int set);
 extern unsigned int gic_get_timer_pending(void);
 extern void gic_get_int_mask(unsigned long *dst, const unsigned long *src);
 extern unsigned int gic_get_int(void);
-extern void gic_irq_ack(struct irq_data *d);
-extern void gic_finish_irq(struct irq_data *d);
 extern void gic_platform_init(int irqs, struct irq_chip *irq_controller);
 #endif /* _ASM_GICREGS_H */
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c
index 5c31208..b60adfd 100644
--- a/arch/mips/mti-malta/malta-int.c
+++ b/arch/mips/mti-malta/malta-int.c
@@ -715,22 +715,6 @@ int malta_be_handler(struct pt_regs *regs, int is_fixup)
 	return retval;
 }
 
-void gic_irq_ack(struct irq_data *d)
-{
-	int irq = (d->irq - gic_irq_base);
-
-	GIC_CLR_INTR_MASK(irq);
-
-	if (gic_irq_flags[irq] & GIC_TRIG_EDGE)
-		GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq);
-}
-
-void gic_finish_irq(struct irq_data *d)
-{
-	/* Enable interrupts. */
-	GIC_SET_INTR_MASK(d->irq - gic_irq_base);
-}
-
 void __init gic_platform_init(int irqs, struct irq_chip *irq_controller)
 {
 	int i;
diff --git a/arch/mips/mti-sead3/sead3-int.c b/arch/mips/mti-sead3/sead3-int.c
index 9d5b5bd..03f9865 100644
--- a/arch/mips/mti-sead3/sead3-int.c
+++ b/arch/mips/mti-sead3/sead3-int.c
@@ -85,27 +85,6 @@ void __init arch_init_irq(void)
 			ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);
 }
 
-void gic_irq_ack(struct irq_data *d)
-{
-	GIC_CLR_INTR_MASK(d->irq - gic_irq_base);
-}
-
-void gic_finish_irq(struct irq_data *d)
-{
-	unsigned int irq = (d->irq - gic_irq_base);
-	unsigned int i, irq_source;
-
-	/* Clear edge detectors. */
-	for (i = 0; i < gic_shared_intr_map[irq].num_shared_intr; i++) {
-		irq_source = gic_shared_intr_map[irq].intr_list[i];
-		if (gic_irq_flags[irq_source] & GIC_TRIG_EDGE)
-			GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq_source);
-	}
-
-	/* Enable interrupts. */
-	GIC_SET_INTR_MASK(irq);
-}
-
 void __init gic_platform_init(int irqs, struct irq_chip *irq_controller)
 {
 	int i;
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index 9e9d8b9..b0daee5 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -237,6 +237,13 @@ static void gic_unmask_irq(struct irq_data *d)
 	GIC_SET_INTR_MASK(d->irq - gic_irq_base);
 }
 
+static void gic_ack_irq(struct irq_data *d)
+{
+	/* Clear edge detector */
+	if (gic_irq_flags[d->irq - gic_irq_base] & GIC_TRIG_EDGE)
+		GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), d->irq - gic_irq_base);
+}
+
 #ifdef CONFIG_SMP
 static DEFINE_SPINLOCK(gic_lock);
 
@@ -272,11 +279,9 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
 
 static struct irq_chip gic_irq_controller = {
 	.name			=	"MIPS GIC",
-	.irq_ack		=	gic_irq_ack,
+	.irq_ack		=	gic_ack_irq,
 	.irq_mask		=	gic_mask_irq,
-	.irq_mask_ack		=	gic_mask_irq,
 	.irq_unmask		=	gic_unmask_irq,
-	.irq_eoi		=	gic_finish_irq,
 #ifdef CONFIG_SMP
 	.irq_set_affinity	=	gic_set_affinity,
 #endif
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH V2 15/24] irqchip: mips-gic: Implement irq_set_type callback
  2014-09-18 21:47 [PATCH V2 00/24] MIPS GIC cleanup, part 1 Andrew Bresticker
                   ` (13 preceding siblings ...)
  2014-09-18 21:47 ` [PATCH V2 14/24] irqchip: mips-gic: Remove platform irq_ack/irq_eoi callbacks Andrew Bresticker
@ 2014-09-18 21:47 ` Andrew Bresticker
  2014-09-18 21:47 ` [PATCH V2 16/24] irqchip: mips-gic: Fix gic_set_affinity() return value Andrew Bresticker
                   ` (8 subsequent siblings)
  23 siblings, 0 replies; 35+ messages in thread
From: Andrew Bresticker @ 2014-09-18 21:47 UTC (permalink / raw)
  To: Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Andrew Bresticker, Jeffrey Deans, Markos Chandras, Paul Burton,
	Qais Yousef, Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

Implement an irq_set_type callback for the GIC which is used to set
the polarity and trigger type of GIC interrupts.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Acked-by: Jason Cooper <jason@lakedaemon.net>
Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
Tested-by: Qais Yousef <qais.yousef@imgtec.com>
---
Changes from v1:
 - hold spinlock across gic_set_type because of r-m-w ops
---
 arch/mips/include/asm/gic.h    |  9 +++++++
 drivers/irqchip/irq-mips-gic.c | 57 ++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 64 insertions(+), 2 deletions(-)

diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h
index 1bf7985..662b567 100644
--- a/arch/mips/include/asm/gic.h
+++ b/arch/mips/include/asm/gic.h
@@ -23,6 +23,8 @@
 #define GIC_POL_NEG			0
 #define GIC_TRIG_EDGE			1
 #define GIC_TRIG_LEVEL			0
+#define GIC_TRIG_DUAL_ENABLE		1
+#define GIC_TRIG_DUAL_DISABLE		0
 
 #define MSK(n) ((1 << (n)) - 1)
 #define REG32(addr)		(*(volatile unsigned int *) (addr))
@@ -179,6 +181,13 @@
 		GIC_INTR_OFS(intr)), (1 << GIC_INTR_BIT(intr)), \
 		(trig) << GIC_INTR_BIT(intr))
 
+/* Dual edge triggering : Reset Value is always 0 */
+#define GIC_SH_SET_DUAL_OFS		0x0200
+#define GIC_SET_DUAL(intr, dual) \
+	GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_DUAL_OFS + \
+		GIC_INTR_OFS(intr)), (1 << GIC_INTR_BIT(intr)), \
+		(dual) << GIC_INTR_BIT(intr))
+
 /* Mask manipulation */
 #define GIC_SH_SMASK_OFS		0x0380
 #define GIC_SET_INTR_MASK(intr) \
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index b0daee5..e9abb08 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -43,6 +43,7 @@ struct gic_intrmask_regs {
 static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
 static struct gic_pending_regs pending_regs[NR_CPUS];
 static struct gic_intrmask_regs intrmask_regs[NR_CPUS];
+static DEFINE_SPINLOCK(gic_lock);
 
 #if defined(CONFIG_CSRC_GIC) || defined(CONFIG_CEVT_GIC)
 cycle_t gic_read_count(void)
@@ -244,9 +245,60 @@ static void gic_ack_irq(struct irq_data *d)
 		GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), d->irq - gic_irq_base);
 }
 
-#ifdef CONFIG_SMP
-static DEFINE_SPINLOCK(gic_lock);
+static int gic_set_type(struct irq_data *d, unsigned int type)
+{
+	unsigned int irq = d->irq - gic_irq_base;
+	unsigned long flags;
+	bool is_edge;
+
+	spin_lock_irqsave(&gic_lock, flags);
+	switch (type & IRQ_TYPE_SENSE_MASK) {
+	case IRQ_TYPE_EDGE_FALLING:
+		GIC_SET_POLARITY(irq, GIC_POL_NEG);
+		GIC_SET_TRIGGER(irq, GIC_TRIG_EDGE);
+		GIC_SET_DUAL(irq, GIC_TRIG_DUAL_DISABLE);
+		is_edge = true;
+		break;
+	case IRQ_TYPE_EDGE_RISING:
+		GIC_SET_POLARITY(irq, GIC_POL_POS);
+		GIC_SET_TRIGGER(irq, GIC_TRIG_EDGE);
+		GIC_SET_DUAL(irq, GIC_TRIG_DUAL_DISABLE);
+		is_edge = true;
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		/* polarity is irrelevant in this case */
+		GIC_SET_TRIGGER(irq, GIC_TRIG_EDGE);
+		GIC_SET_DUAL(irq, GIC_TRIG_DUAL_ENABLE);
+		is_edge = true;
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		GIC_SET_POLARITY(irq, GIC_POL_NEG);
+		GIC_SET_TRIGGER(irq, GIC_TRIG_LEVEL);
+		GIC_SET_DUAL(irq, GIC_TRIG_DUAL_DISABLE);
+		is_edge = false;
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+	default:
+		GIC_SET_POLARITY(irq, GIC_POL_POS);
+		GIC_SET_TRIGGER(irq, GIC_TRIG_LEVEL);
+		GIC_SET_DUAL(irq, GIC_TRIG_DUAL_DISABLE);
+		is_edge = false;
+		break;
+	}
 
+	if (is_edge) {
+		gic_irq_flags[irq] |= GIC_TRIG_EDGE;
+		__irq_set_handler_locked(d->irq, handle_edge_irq);
+	} else {
+		gic_irq_flags[irq] &= ~GIC_TRIG_EDGE;
+		__irq_set_handler_locked(d->irq, handle_level_irq);
+	}
+	spin_unlock_irqrestore(&gic_lock, flags);
+
+	return 0;
+}
+
+#ifdef CONFIG_SMP
 static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
 			    bool force)
 {
@@ -282,6 +334,7 @@ static struct irq_chip gic_irq_controller = {
 	.irq_ack		=	gic_ack_irq,
 	.irq_mask		=	gic_mask_irq,
 	.irq_unmask		=	gic_unmask_irq,
+	.irq_set_type		=	gic_set_type,
 #ifdef CONFIG_SMP
 	.irq_set_affinity	=	gic_set_affinity,
 #endif
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH V2 16/24] irqchip: mips-gic: Fix gic_set_affinity() return value
  2014-09-18 21:47 [PATCH V2 00/24] MIPS GIC cleanup, part 1 Andrew Bresticker
                   ` (14 preceding siblings ...)
  2014-09-18 21:47 ` [PATCH V2 15/24] irqchip: mips-gic: Implement irq_set_type callback Andrew Bresticker
@ 2014-09-18 21:47 ` Andrew Bresticker
  2014-09-18 21:47 ` [PATCH V2 17/24] irqchip: mips-gic: Use IRQ domains Andrew Bresticker
                   ` (7 subsequent siblings)
  23 siblings, 0 replies; 35+ messages in thread
From: Andrew Bresticker @ 2014-09-18 21:47 UTC (permalink / raw)
  To: Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Andrew Bresticker, Jeffrey Deans, Markos Chandras, Paul Burton,
	Qais Yousef, Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

If the online CPU check in gic_set_affinity() fails, return a proper
errno value instead of -1.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Acked-by: Jason Cooper <jason@lakedaemon.net>
Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
Tested-by: Qais Yousef <qais.yousef@imgtec.com>
---
No changes from v1.
---
 drivers/irqchip/irq-mips-gic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index e9abb08..5e12777 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -309,7 +309,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
 
 	cpumask_and(&tmp, cpumask, cpu_online_mask);
 	if (cpus_empty(tmp))
-		return -1;
+		return -EINVAL;
 
 	/* Assumption : cpumask refers to a single CPU */
 	spin_lock_irqsave(&gic_lock, flags);
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH V2 17/24] irqchip: mips-gic: Use IRQ domains
  2014-09-18 21:47 [PATCH V2 00/24] MIPS GIC cleanup, part 1 Andrew Bresticker
                   ` (15 preceding siblings ...)
  2014-09-18 21:47 ` [PATCH V2 16/24] irqchip: mips-gic: Fix gic_set_affinity() return value Andrew Bresticker
@ 2014-09-18 21:47 ` Andrew Bresticker
  2014-09-18 21:47 ` [PATCH V2 18/24] irqchip: mips-gic: Stop using per-platform mapping tables Andrew Bresticker
                   ` (6 subsequent siblings)
  23 siblings, 0 replies; 35+ messages in thread
From: Andrew Bresticker @ 2014-09-18 21:47 UTC (permalink / raw)
  To: Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Andrew Bresticker, Jeffrey Deans, Markos Chandras, Paul Burton,
	Qais Yousef, Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

Use a simple IRQ domain for the MIPS GIC.  Remove the gic_platform_init
callback as it's no longer necessary for it to set the irqchip.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Acked-by: Jason Cooper <jason@lakedaemon.net>
Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
Tested-by: Qais Yousef <qais.yousef@imgtec.com>
---
Changes from v1:
 - hold spinlock across gic_irq_domain_map because of r-m-w ops
---
 arch/mips/include/asm/gic.h     |  1 -
 arch/mips/mti-malta/malta-int.c |  8 -------
 arch/mips/mti-sead3/sead3-int.c | 15 -------------
 drivers/irqchip/irq-mips-gic.c  | 48 ++++++++++++++++++++++++++++++++++-------
 4 files changed, 40 insertions(+), 32 deletions(-)

diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h
index 662b567..efcf4de 100644
--- a/arch/mips/include/asm/gic.h
+++ b/arch/mips/include/asm/gic.h
@@ -385,5 +385,4 @@ extern void gic_bind_eic_interrupt(int irq, int set);
 extern unsigned int gic_get_timer_pending(void);
 extern void gic_get_int_mask(unsigned long *dst, const unsigned long *src);
 extern unsigned int gic_get_int(void);
-extern void gic_platform_init(int irqs, struct irq_chip *irq_controller);
 #endif /* _ASM_GICREGS_H */
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c
index b60adfd..e56563c 100644
--- a/arch/mips/mti-malta/malta-int.c
+++ b/arch/mips/mti-malta/malta-int.c
@@ -714,11 +714,3 @@ int malta_be_handler(struct pt_regs *regs, int is_fixup)
 
 	return retval;
 }
-
-void __init gic_platform_init(int irqs, struct irq_chip *irq_controller)
-{
-	int i;
-
-	for (i = gic_irq_base; i < (gic_irq_base + irqs); i++)
-		irq_set_chip(i, irq_controller);
-}
diff --git a/arch/mips/mti-sead3/sead3-int.c b/arch/mips/mti-sead3/sead3-int.c
index 03f9865..8f36342 100644
--- a/arch/mips/mti-sead3/sead3-int.c
+++ b/arch/mips/mti-sead3/sead3-int.c
@@ -85,18 +85,3 @@ void __init arch_init_irq(void)
 			ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);
 }
 
-void __init gic_platform_init(int irqs, struct irq_chip *irq_controller)
-{
-	int i;
-
-	/*
-	 * For non-EIC mode, we want to setup the GIC in pass-through
-	 * mode, as if the GIC didn't exist. Do not map any interrupts
-	 * for an external interrupt controller.
-	 */
-	if (!cpu_has_veic)
-		return;
-
-	for (i = gic_irq_base; i < (gic_irq_base + irqs); i++)
-		irq_set_chip_and_handler(i, irq_controller, handle_percpu_irq);
-}
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index 5e12777..64dc5a9 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -44,6 +44,7 @@ static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
 static struct gic_pending_regs pending_regs[NR_CPUS];
 static struct gic_intrmask_regs intrmask_regs[NR_CPUS];
 static DEFINE_SPINLOCK(gic_lock);
+static struct irq_domain *gic_irq_domain;
 
 #if defined(CONFIG_CSRC_GIC) || defined(CONFIG_CEVT_GIC)
 cycle_t gic_read_count(void)
@@ -230,24 +231,26 @@ unsigned int gic_get_int(void)
 
 static void gic_mask_irq(struct irq_data *d)
 {
-	GIC_CLR_INTR_MASK(d->irq - gic_irq_base);
+	GIC_CLR_INTR_MASK(d->hwirq);
 }
 
 static void gic_unmask_irq(struct irq_data *d)
 {
-	GIC_SET_INTR_MASK(d->irq - gic_irq_base);
+	GIC_SET_INTR_MASK(d->hwirq);
 }
 
 static void gic_ack_irq(struct irq_data *d)
 {
+	unsigned int irq = d->hwirq;
+
 	/* Clear edge detector */
-	if (gic_irq_flags[d->irq - gic_irq_base] & GIC_TRIG_EDGE)
-		GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), d->irq - gic_irq_base);
+	if (gic_irq_flags[irq] & GIC_TRIG_EDGE)
+		GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq);
 }
 
 static int gic_set_type(struct irq_data *d, unsigned int type)
 {
-	unsigned int irq = d->irq - gic_irq_base;
+	unsigned int irq = d->hwirq;
 	unsigned long flags;
 	bool is_edge;
 
@@ -302,7 +305,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
 static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
 			    bool force)
 {
-	unsigned int irq = (d->irq - gic_irq_base);
+	unsigned int irq = d->hwirq;
 	cpumask_t	tmp = CPU_MASK_NONE;
 	unsigned long	flags;
 	int		i;
@@ -345,6 +348,7 @@ static void __init gic_setup_intr(unsigned int intr, unsigned int cpu,
 	unsigned int flags)
 {
 	struct gic_shared_intr_map *map_ptr;
+	int i;
 
 	/* Setup Intr to Pin mapping */
 	if (pin & GIC_MAP_TO_NMI_MSK) {
@@ -382,6 +386,8 @@ static void __init gic_setup_intr(unsigned int intr, unsigned int cpu,
 	GIC_CLR_INTR_MASK(intr);
 
 	/* Initialise per-cpu Interrupt software masks */
+	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))
@@ -433,6 +439,29 @@ static void __init gic_basic_init(int numintrs, int numvpes,
 	vpe_local_setup(numvpes);
 }
 
+static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq,
+			      irq_hw_number_t hw)
+{
+	unsigned long flags;
+
+	irq_set_chip_and_handler(virq, &gic_irq_controller, handle_level_irq);
+
+	spin_lock_irqsave(&gic_lock, flags);
+	GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(hw)),
+		 GIC_MAP_TO_PIN_MSK | 0);
+	/* Map to VPE 0 by default */
+	GIC_SH_MAP_TO_VPE_SMASK(hw, 0);
+	set_bit(hw, pcpu_masks[0].pcpu_mask);
+	spin_unlock_irqrestore(&gic_lock, flags);
+
+	return 0;
+}
+
+static struct irq_domain_ops gic_irq_domain_ops = {
+	.map = gic_irq_domain_map,
+	.xlate = irq_domain_xlate_twocell,
+};
+
 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,
@@ -454,7 +483,10 @@ void __init gic_init(unsigned long gic_base_addr,
 		  GIC_SH_CONFIG_NUMVPES_SHF;
 	numvpes = numvpes + 1;
 
-	gic_basic_init(numintrs, numvpes, intr_map, intr_map_size);
+	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_platform_init(numintrs, &gic_irq_controller);
+	gic_basic_init(numintrs, numvpes, intr_map, intr_map_size);
 }
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH V2 18/24] irqchip: mips-gic: Stop using per-platform mapping tables
  2014-09-18 21:47 [PATCH V2 00/24] MIPS GIC cleanup, part 1 Andrew Bresticker
                   ` (16 preceding siblings ...)
  2014-09-18 21:47 ` [PATCH V2 17/24] irqchip: mips-gic: Use IRQ domains Andrew Bresticker
@ 2014-09-18 21:47 ` Andrew Bresticker
  2015-01-15 11:59     ` James Hogan
  2014-09-18 21:47 ` [PATCH V2 19/24] irqchip: mips-gic: Probe for number of external interrupts Andrew Bresticker
                   ` (5 subsequent siblings)
  23 siblings, 1 reply; 35+ messages in thread
From: Andrew Bresticker @ 2014-09-18 21:47 UTC (permalink / raw)
  To: Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Andrew Bresticker, Jeffrey Deans, Markos Chandras, Paul Burton,
	Qais Yousef, Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

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@chromium.org>
Acked-by: Jason Cooper <jason@lakedaemon.net>
Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
Tested-by: Qais Yousef <qais.yousef@imgtec.com>
---
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();
 }
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH V2 19/24] irqchip: mips-gic: Probe for number of external interrupts
  2014-09-18 21:47 [PATCH V2 00/24] MIPS GIC cleanup, part 1 Andrew Bresticker
                   ` (17 preceding siblings ...)
  2014-09-18 21:47 ` [PATCH V2 18/24] irqchip: mips-gic: Stop using per-platform mapping tables Andrew Bresticker
@ 2014-09-18 21:47 ` Andrew Bresticker
  2014-09-18 21:47 ` [PATCH V2 20/24] irqchip: mips-gic: Use separate edge/level irq_chips Andrew Bresticker
                   ` (4 subsequent siblings)
  23 siblings, 0 replies; 35+ messages in thread
From: Andrew Bresticker @ 2014-09-18 21:47 UTC (permalink / raw)
  To: Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Andrew Bresticker, Jeffrey Deans, Markos Chandras, Paul Burton,
	Qais Yousef, Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

Instead of requiring platforms to define the correct GIC_NUM_INTRS,
use the value reported in GIC_SH_CONFIG.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Acked-by: Jason Cooper <jason@lakedaemon.net>
Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
Tested-by: Qais Yousef <qais.yousef@imgtec.com>
---
No changes from v1.
---
 arch/mips/include/asm/gic.h            |  2 ++
 arch/mips/include/asm/mach-malta/irq.h |  1 -
 arch/mips/include/asm/mach-sead3/irq.h |  1 -
 drivers/irqchip/irq-mips-gic.c         | 40 +++++++++++++++++-----------------
 4 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h
index cfbf907..8d1e457 100644
--- a/arch/mips/include/asm/gic.h
+++ b/arch/mips/include/asm/gic.h
@@ -18,6 +18,8 @@
 
 #undef	GICISBYTELITTLEENDIAN
 
+#define GIC_MAX_INTRS			256
+
 /* Constants */
 #define GIC_POL_POS			1
 #define GIC_POL_NEG			0
diff --git a/arch/mips/include/asm/mach-malta/irq.h b/arch/mips/include/asm/mach-malta/irq.h
index f2c13d2..47cfe64 100644
--- a/arch/mips/include/asm/mach-malta/irq.h
+++ b/arch/mips/include/asm/mach-malta/irq.h
@@ -2,7 +2,6 @@
 #define __ASM_MACH_MIPS_IRQ_H
 
 
-#define GIC_NUM_INTRS (24 + NR_CPUS * 2)
 #define NR_IRQS 256
 
 #include_next <irq.h>
diff --git a/arch/mips/include/asm/mach-sead3/irq.h b/arch/mips/include/asm/mach-sead3/irq.h
index d8106f7..5d154cf 100644
--- a/arch/mips/include/asm/mach-sead3/irq.h
+++ b/arch/mips/include/asm/mach-sead3/irq.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_MACH_MIPS_IRQ_H
 #define __ASM_MACH_MIPS_IRQ_H
 
-#define GIC_NUM_INTRS (24 + NR_CPUS * 2)
 #define NR_IRQS 256
 
 
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index 6c9fcbf..1349427 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -28,15 +28,15 @@ unsigned int gic_irq_flags[GIC_NUM_INTRS];
 unsigned int gic_cpu_pin;
 
 struct gic_pcpu_mask {
-	DECLARE_BITMAP(pcpu_mask, GIC_NUM_INTRS);
+	DECLARE_BITMAP(pcpu_mask, GIC_MAX_INTRS);
 };
 
 struct gic_pending_regs {
-	DECLARE_BITMAP(pending, GIC_NUM_INTRS);
+	DECLARE_BITMAP(pending, GIC_MAX_INTRS);
 };
 
 struct gic_intrmask_regs {
-	DECLARE_BITMAP(intrmask, GIC_NUM_INTRS);
+	DECLARE_BITMAP(intrmask, GIC_MAX_INTRS);
 };
 
 static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
@@ -44,6 +44,7 @@ static struct gic_pending_regs pending_regs[NR_CPUS];
 static struct gic_intrmask_regs intrmask_regs[NR_CPUS];
 static DEFINE_SPINLOCK(gic_lock);
 static struct irq_domain *gic_irq_domain;
+static int gic_shared_intrs;
 
 static void __gic_irq_dispatch(void);
 
@@ -192,26 +193,26 @@ void gic_get_int_mask(unsigned long *dst, const unsigned long *src)
 	intrmask_abs = (unsigned long *) GIC_REG_ABS_ADDR(SHARED,
 							  GIC_SH_MASK_31_0_OFS);
 
-	for (i = 0; i < BITS_TO_LONGS(GIC_NUM_INTRS); i++) {
+	for (i = 0; i < BITS_TO_LONGS(gic_shared_intrs); i++) {
 		GICREAD(*pending_abs, pending[i]);
 		GICREAD(*intrmask_abs, intrmask[i]);
 		pending_abs++;
 		intrmask_abs++;
 	}
 
-	bitmap_and(pending, pending, intrmask, GIC_NUM_INTRS);
-	bitmap_and(pending, pending, pcpu_mask, GIC_NUM_INTRS);
-	bitmap_and(dst, src, pending, GIC_NUM_INTRS);
+	bitmap_and(pending, pending, intrmask, gic_shared_intrs);
+	bitmap_and(pending, pending, pcpu_mask, gic_shared_intrs);
+	bitmap_and(dst, src, pending, gic_shared_intrs);
 }
 
 unsigned int gic_get_int(void)
 {
-	DECLARE_BITMAP(interrupts, GIC_NUM_INTRS);
+	DECLARE_BITMAP(interrupts, GIC_MAX_INTRS);
 
-	bitmap_fill(interrupts, GIC_NUM_INTRS);
+	bitmap_fill(interrupts, gic_shared_intrs);
 	gic_get_int_mask(interrupts, interrupts);
 
-	return find_first_bit(interrupts, GIC_NUM_INTRS);
+	return find_first_bit(interrupts, gic_shared_intrs);
 }
 
 static void gic_mask_irq(struct irq_data *d)
@@ -332,7 +333,7 @@ static void __gic_irq_dispatch(void)
 {
 	unsigned int intr, virq;
 
-	while ((intr = gic_get_int()) != GIC_NUM_INTRS) {
+	while ((intr = gic_get_int()) != gic_shared_intrs) {
 		virq = irq_linear_revmap(gic_irq_domain, intr);
 		do_IRQ(virq);
 	}
@@ -405,7 +406,7 @@ static __init void gic_ipi_init(void)
 	int i;
 
 	/* Use last 2 * NR_CPUS interrupts as IPIs */
-	gic_resched_int_base = GIC_NUM_INTRS - nr_cpu_ids;
+	gic_resched_int_base = gic_shared_intrs - nr_cpu_ids;
 	gic_call_int_base = gic_resched_int_base - nr_cpu_ids;
 
 	for (i = 0; i < nr_cpu_ids; i++) {
@@ -419,19 +420,18 @@ static inline void gic_ipi_init(void)
 }
 #endif
 
-static void __init gic_basic_init(int numintrs, int numvpes)
+static void __init gic_basic_init(int numvpes)
 {
 	unsigned int i;
 
 	board_bind_eic_interrupt = &gic_bind_eic_interrupt;
 
 	/* Setup defaults */
-	for (i = 0; i < numintrs; i++) {
+	for (i = 0; i < gic_shared_intrs; i++) {
 		GIC_SET_POLARITY(i, GIC_POL_POS);
 		GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL);
 		GIC_CLR_INTR_MASK(i);
-		if (i < GIC_NUM_INTRS)
-			gic_irq_flags[i] = 0;
+		gic_irq_flags[i] = 0;
 	}
 
 	vpe_local_setup(numvpes);
@@ -471,9 +471,9 @@ void __init gic_init(unsigned long gic_base_addr,
 						    gic_addrspace_size);
 
 	GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig);
-	numintrs = (gicconfig & GIC_SH_CONFIG_NUMINTRS_MSK) >>
+	gic_shared_intrs = (gicconfig & GIC_SH_CONFIG_NUMINTRS_MSK) >>
 		   GIC_SH_CONFIG_NUMINTRS_SHF;
-	numintrs = ((numintrs + 1) * 8);
+	gic_shared_intrs = ((gic_shared_intrs + 1) * 8);
 
 	numvpes = (gicconfig & GIC_SH_CONFIG_NUMVPES_MSK) >>
 		  GIC_SH_CONFIG_NUMVPES_SHF;
@@ -490,12 +490,12 @@ void __init gic_init(unsigned long gic_base_addr,
 					gic_irq_dispatch);
 	}
 
-	gic_irq_domain = irq_domain_add_simple(NULL, GIC_NUM_INTRS, irqbase,
+	gic_irq_domain = irq_domain_add_simple(NULL, gic_shared_intrs, irqbase,
 					       &gic_irq_domain_ops, NULL);
 	if (!gic_irq_domain)
 		panic("Failed to add GIC IRQ domain");
 
-	gic_basic_init(numintrs, numvpes);
+	gic_basic_init(numvpes);
 
 	gic_ipi_init();
 }
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH V2 20/24] irqchip: mips-gic: Use separate edge/level irq_chips
  2014-09-18 21:47 [PATCH V2 00/24] MIPS GIC cleanup, part 1 Andrew Bresticker
                   ` (18 preceding siblings ...)
  2014-09-18 21:47 ` [PATCH V2 19/24] irqchip: mips-gic: Probe for number of external interrupts Andrew Bresticker
@ 2014-09-18 21:47 ` Andrew Bresticker
  2014-09-18 21:47 ` [PATCH V2 21/24] irqchip: mips-gic: Support local interrupts Andrew Bresticker
                   ` (3 subsequent siblings)
  23 siblings, 0 replies; 35+ messages in thread
From: Andrew Bresticker @ 2014-09-18 21:47 UTC (permalink / raw)
  To: Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Andrew Bresticker, Jeffrey Deans, Markos Chandras, Paul Burton,
	Qais Yousef, Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

GIC edge-triggered interrupts must be acknowledged by clearing the edge
detector via a write to GIC_SH_WEDGE.  Create a separate edge-triggered
irq_chip with the appropriate irq_ack() callback.  This also allows us
to get rid of gic_irq_flags.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Acked-by: Jason Cooper <jason@lakedaemon.net>
Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
Tested-by: Qais Yousef <qais.yousef@imgtec.com>
---
Changes from v1:
 - removed unnecessary irq_mask_ack, irq_ack, and irq_eoi callbacks
---
 arch/mips/include/asm/gic.h    |  1 -
 drivers/irqchip/irq-mips-gic.c | 32 +++++++++++++++++++++-----------
 2 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h
index 8d1e457..f245395 100644
--- a/arch/mips/include/asm/gic.h
+++ b/arch/mips/include/asm/gic.h
@@ -345,7 +345,6 @@
 extern unsigned int gic_present;
 extern unsigned int gic_frequency;
 extern unsigned long _gic_base;
-extern unsigned int gic_irq_flags[];
 extern unsigned int gic_cpu_pin;
 
 extern void gic_init(unsigned long gic_base_addr,
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index 1349427..bfe8bfb 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -24,7 +24,6 @@
 unsigned int gic_frequency;
 unsigned int gic_present;
 unsigned long _gic_base;
-unsigned int gic_irq_flags[GIC_NUM_INTRS];
 unsigned int gic_cpu_pin;
 
 struct gic_pcpu_mask {
@@ -45,6 +44,7 @@ static struct gic_intrmask_regs intrmask_regs[NR_CPUS];
 static DEFINE_SPINLOCK(gic_lock);
 static struct irq_domain *gic_irq_domain;
 static int gic_shared_intrs;
+static struct irq_chip gic_level_irq_controller, gic_edge_irq_controller;
 
 static void __gic_irq_dispatch(void);
 
@@ -229,9 +229,7 @@ static void gic_ack_irq(struct irq_data *d)
 {
 	unsigned int irq = d->hwirq;
 
-	/* Clear edge detector */
-	if (gic_irq_flags[irq] & GIC_TRIG_EDGE)
-		GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq);
+	GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq);
 }
 
 static int gic_set_type(struct irq_data *d, unsigned int type)
@@ -276,11 +274,13 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
 	}
 
 	if (is_edge) {
-		gic_irq_flags[irq] |= GIC_TRIG_EDGE;
-		__irq_set_handler_locked(d->irq, handle_edge_irq);
+		__irq_set_chip_handler_name_locked(d->irq,
+						   &gic_edge_irq_controller,
+						   handle_edge_irq, NULL);
 	} else {
-		gic_irq_flags[irq] &= ~GIC_TRIG_EDGE;
-		__irq_set_handler_locked(d->irq, handle_level_irq);
+		__irq_set_chip_handler_name_locked(d->irq,
+						   &gic_level_irq_controller,
+						   handle_level_irq, NULL);
 	}
 	spin_unlock_irqrestore(&gic_lock, flags);
 
@@ -318,7 +318,17 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
 }
 #endif
 
-static struct irq_chip gic_irq_controller = {
+static struct irq_chip gic_level_irq_controller = {
+	.name			=	"MIPS GIC",
+	.irq_mask		=	gic_mask_irq,
+	.irq_unmask		=	gic_unmask_irq,
+	.irq_set_type		=	gic_set_type,
+#ifdef CONFIG_SMP
+	.irq_set_affinity	=	gic_set_affinity,
+#endif
+};
+
+static struct irq_chip gic_edge_irq_controller = {
 	.name			=	"MIPS GIC",
 	.irq_ack		=	gic_ack_irq,
 	.irq_mask		=	gic_mask_irq,
@@ -431,7 +441,6 @@ static void __init gic_basic_init(int numvpes)
 		GIC_SET_POLARITY(i, GIC_POL_POS);
 		GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL);
 		GIC_CLR_INTR_MASK(i);
-		gic_irq_flags[i] = 0;
 	}
 
 	vpe_local_setup(numvpes);
@@ -442,7 +451,8 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq,
 {
 	unsigned long flags;
 
-	irq_set_chip_and_handler(virq, &gic_irq_controller, handle_level_irq);
+	irq_set_chip_and_handler(virq, &gic_level_irq_controller,
+				 handle_level_irq);
 
 	spin_lock_irqsave(&gic_lock, flags);
 	GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(hw)),
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH V2 21/24] irqchip: mips-gic: Support local interrupts
  2014-09-18 21:47 [PATCH V2 00/24] MIPS GIC cleanup, part 1 Andrew Bresticker
                   ` (19 preceding siblings ...)
  2014-09-18 21:47 ` [PATCH V2 20/24] irqchip: mips-gic: Use separate edge/level irq_chips Andrew Bresticker
@ 2014-09-18 21:47 ` Andrew Bresticker
  2014-09-18 21:47 ` [PATCH V2 22/24] irqchip: mips-gic: Remove unnecessary globals Andrew Bresticker
                   ` (2 subsequent siblings)
  23 siblings, 0 replies; 35+ messages in thread
From: Andrew Bresticker @ 2014-09-18 21:47 UTC (permalink / raw)
  To: Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Andrew Bresticker, Jeffrey Deans, Markos Chandras, Paul Burton,
	Qais Yousef, Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

The MIPS GIC supports 7 local interrupts, 2 of which are the GIC
local watchdog and count/compare timer.  The remainder are CPU
interrupts which may optionally be re-routed through the GIC.
GIC hardware IRQs 0-6 are now used for local interrupts while
hardware IRQs 7+ are used for external (shared) interrupts.

Note that the 5 CPU interrupts may not be re-routable through
the GIC.  In that case mapping will fail and the vectors reported
in C0_IntCtl should be used instead.  gic_get_c0_compare_int() and
gic_get_c0_perfcount_int() will return the correct IRQ number to
use for the C0 timer and perfcounter interrupts based on the
routability of those interrupts through the GIC.

A separate irq_chip, with callbacks that mask/unmask the local
interrupt on all CPUs, is used for the C0 timer and performance
counter interrupts since all other platforms do not use the percpu
IRQ API for those interrupts.

Malta, SEAD-3, and the GIC clockevent driver have been updated
to use local interrupts and the R4K clockevent driver has been
updated to poll for C0 timer interrupts through the GIC when
the GIC is present.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Acked-by: Jason Cooper <jason@lakedaemon.net>
Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
Tested-by: Qais Yousef <qais.yousef@imgtec.com>
---
Changes from v1:
 - allow SWINTs to be routable in non-EIC mode
 - use separate irq_chip for C0 timer/perf interrupts
 - mask all routable local interrupts initially
 - remove unnecessary irq_ack, irq_mask_ack, and irq_eoi callbacks
---
 arch/mips/include/asm/gic.h                  |  29 ++-
 arch/mips/include/asm/mips-boards/maltaint.h |   4 +-
 arch/mips/include/asm/mips-boards/sead3int.h |  10 +-
 arch/mips/kernel/cevt-gic.c                  |  15 +-
 arch/mips/kernel/cevt-r4k.c                  |   2 +-
 arch/mips/mti-malta/malta-int.c              |   6 +-
 arch/mips/mti-malta/malta-time.c             |  13 +-
 arch/mips/mti-sead3/sead3-time.c             |  34 +---
 drivers/irqchip/irq-mips-gic.c               | 291 ++++++++++++++++++++-------
 9 files changed, 279 insertions(+), 125 deletions(-)

diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h
index f245395..6b99610 100644
--- a/arch/mips/include/asm/gic.h
+++ b/arch/mips/include/asm/gic.h
@@ -209,6 +209,7 @@
 #define GIC_VPE_WD_MAP_OFS		0x0040
 #define GIC_VPE_COMPARE_MAP_OFS		0x0044
 #define GIC_VPE_TIMER_MAP_OFS		0x0048
+#define GIC_VPE_FDC_MAP_OFS		0x004c
 #define GIC_VPE_PERFCTR_MAP_OFS		0x0050
 #define GIC_VPE_SWINT0_MAP_OFS		0x0054
 #define GIC_VPE_SWINT1_MAP_OFS		0x0058
@@ -262,6 +263,10 @@
 #define GIC_MAP_MSK			(MSK(6) << GIC_MAP_SHF)
 
 /* GIC_VPE_CTL Masks */
+#define GIC_VPE_CTL_FDC_RTBL_SHF	4
+#define GIC_VPE_CTL_FDC_RTBL_MSK	(MSK(1) << GIC_VPE_CTL_FDC_RTBL_SHF)
+#define GIC_VPE_CTL_SWINT_RTBL_SHF	3
+#define GIC_VPE_CTL_SWINT_RTBL_MSK	(MSK(1) << GIC_VPE_CTL_SWINT_RTBL_SHF)
 #define GIC_VPE_CTL_PERFCNT_RTBL_SHF	2
 #define GIC_VPE_CTL_PERFCNT_RTBL_MSK	(MSK(1) << GIC_VPE_CTL_PERFCNT_RTBL_SHF)
 #define GIC_VPE_CTL_TIMER_RTBL_SHF	1
@@ -329,16 +334,30 @@
 /* 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)
-
 /* Add 2 to convert non-EIC hardware interrupt to EIC vector number. */
 #define GIC_CPU_TO_VEC_OFFSET	(2)
 
 /* Mapped interrupt to pin X, then GIC will generate the vector (X+1). */
 #define GIC_PIN_TO_VEC_OFFSET	(1)
 
+/* Local GIC interrupts. */
+#define GIC_LOCAL_INT_WD	0 /* GIC watchdog */
+#define GIC_LOCAL_INT_COMPARE	1 /* GIC count and compare timer */
+#define GIC_LOCAL_INT_TIMER	2 /* CPU timer interrupt */
+#define GIC_LOCAL_INT_PERFCTR	3 /* CPU performance counter */
+#define GIC_LOCAL_INT_SWINT0	4 /* CPU software interrupt 0 */
+#define GIC_LOCAL_INT_SWINT1	5 /* CPU software interrupt 1 */
+#define GIC_LOCAL_INT_FDC	6 /* CPU fast debug channel */
+#define GIC_NUM_LOCAL_INTRS	7
+
+/* Convert between local/shared IRQ number and GIC HW IRQ number. */
+#define GIC_LOCAL_HWIRQ_BASE	0
+#define GIC_LOCAL_TO_HWIRQ(x)	(GIC_LOCAL_HWIRQ_BASE + (x))
+#define GIC_HWIRQ_TO_LOCAL(x)	((x) - GIC_LOCAL_HWIRQ_BASE)
+#define GIC_SHARED_HWIRQ_BASE	GIC_NUM_LOCAL_INTRS
+#define GIC_SHARED_TO_HWIRQ(x)	(GIC_SHARED_HWIRQ_BASE + (x))
+#define GIC_HWIRQ_TO_SHARED(x)	((x) - GIC_SHARED_HWIRQ_BASE)
+
 #include <linux/clocksource.h>
 #include <linux/irq.h>
 
@@ -363,4 +382,6 @@ extern void gic_bind_eic_interrupt(int irq, int set);
 extern unsigned int gic_get_timer_pending(void);
 extern void gic_get_int_mask(unsigned long *dst, const unsigned long *src);
 extern unsigned int gic_get_int(void);
+extern int gic_get_c0_compare_int(void);
+extern int gic_get_c0_perfcount_int(void);
 #endif /* _ASM_GICREGS_H */
diff --git a/arch/mips/include/asm/mips-boards/maltaint.h b/arch/mips/include/asm/mips-boards/maltaint.h
index bdd6f39..38b06a0 100644
--- a/arch/mips/include/asm/mips-boards/maltaint.h
+++ b/arch/mips/include/asm/mips-boards/maltaint.h
@@ -10,6 +10,8 @@
 #ifndef _MIPS_MALTAINT_H
 #define _MIPS_MALTAINT_H
 
+#include <asm/gic.h>
+
 /*
  * Interrupts 0..15 are used for Malta ISA compatible interrupts
  */
@@ -61,6 +63,6 @@
 #define MSC01E_INT_CPUCTR	11
 
 /* GIC external interrupts */
-#define GIC_INT_I8259A		3
+#define GIC_INT_I8259A		GIC_SHARED_TO_HWIRQ(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 a2e0095..59d6c32 100644
--- a/arch/mips/include/asm/mips-boards/sead3int.h
+++ b/arch/mips/include/asm/mips-boards/sead3int.h
@@ -10,6 +10,8 @@
 #ifndef _MIPS_SEAD3INT_H
 #define _MIPS_SEAD3INT_H
 
+#include <asm/gic.h>
+
 /* SEAD-3 GIC address space definitions. */
 #define GIC_BASE_ADDR		0x1b1c0000
 #define GIC_ADDRSPACE_SZ	(128 * 1024)
@@ -22,9 +24,9 @@
 #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
+#define GIC_INT_NET		GIC_SHARED_TO_HWIRQ(0)
+#define GIC_INT_UART1		GIC_SHARED_TO_HWIRQ(2)
+#define GIC_INT_UART0		GIC_SHARED_TO_HWIRQ(3)
+#define GIC_INT_EHCI		GIC_SHARED_TO_HWIRQ(5)
 
 #endif /* !(_MIPS_SEAD3INT_H) */
diff --git a/arch/mips/kernel/cevt-gic.c b/arch/mips/kernel/cevt-gic.c
index a90bd4c..4f9262a 100644
--- a/arch/mips/kernel/cevt-gic.c
+++ b/arch/mips/kernel/cevt-gic.c
@@ -68,7 +68,7 @@ int gic_clockevent_init(void)
 	if (!cpu_has_counter || !gic_frequency)
 		return -ENXIO;
 
-	irq = MIPS_GIC_IRQ_BASE;
+	irq = MIPS_GIC_IRQ_BASE + GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_COMPARE);
 
 	cd = &per_cpu(gic_clockevent_device, cpu);
 
@@ -91,16 +91,13 @@ int gic_clockevent_init(void)
 
 	clockevents_register_device(cd);
 
-	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) {
+		setup_percpu_irq(irq, &gic_compare_irqaction);
+		gic_timer_irq_installed = 1;
+	}
 
-	if (gic_timer_irq_installed)
-		return 0;
+	enable_percpu_irq(irq, IRQ_TYPE_NONE);
 
-	gic_timer_irq_installed = 1;
 
-	setup_irq(irq, &gic_compare_irqaction);
-	irq_set_handler(irq, handle_percpu_irq);
 	return 0;
 }
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
index 5b8f8e3..fd0ef8d 100644
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -86,7 +86,7 @@ void mips_event_handler(struct clock_event_device *dev)
 static int c0_compare_int_pending(void)
 {
 #ifdef CONFIG_MIPS_GIC
-	if (cpu_has_veic)
+	if (gic_present)
 		return gic_get_timer_pending();
 #endif
 	return (read_c0_cause() >> cp0_compare_irq_shift) & (1ul << CAUSEB_IP);
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c
index 3b3bc1d..c6b3548 100644
--- a/arch/mips/mti-malta/malta-int.c
+++ b/arch/mips/mti-malta/malta-int.c
@@ -273,11 +273,7 @@ asmlinkage void plat_irq_dispatch(void)
 
 	irq = irq_ffs(pending);
 
-	/* 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);
+	do_IRQ(MIPS_CPU_IRQ_BASE + irq);
 }
 
 #ifdef CONFIG_MIPS_MT_SMP
diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c
index 17cfc8a..f6ca8ea 100644
--- a/arch/mips/mti-malta/malta-time.c
+++ b/arch/mips/mti-malta/malta-time.c
@@ -126,9 +126,9 @@ int get_c0_perfcount_int(void)
 	if (cpu_has_veic) {
 		set_vi_handler(MSC01E_INT_PERFCTR, mips_perf_dispatch);
 		mips_cpu_perf_irq = MSC01E_INT_BASE + MSC01E_INT_PERFCTR;
+	} else if (gic_present) {
+		mips_cpu_perf_irq = gic_get_c0_perfcount_int();
 	} else if (cp0_perfcount_irq >= 0) {
-		if (cpu_has_vint)
-			set_vi_handler(cp0_perfcount_irq, mips_perf_dispatch);
 		mips_cpu_perf_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
 	} else {
 		mips_cpu_perf_irq = -1;
@@ -139,15 +139,12 @@ int get_c0_perfcount_int(void)
 
 unsigned int get_c0_compare_int(void)
 {
-#ifdef MSC01E_INT_BASE
 	if (cpu_has_veic) {
 		set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch);
 		mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR;
-	} else
-#endif
-	{
-		if (cpu_has_vint)
-			set_vi_handler(cp0_compare_irq, mips_timer_dispatch);
+	} else if (gic_present) {
+		mips_cpu_timer_irq = gic_get_c0_compare_int();
+	} else {
 		mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
 	}
 
diff --git a/arch/mips/mti-sead3/sead3-time.c b/arch/mips/mti-sead3/sead3-time.c
index f090c51..fd40de3 100644
--- a/arch/mips/mti-sead3/sead3-time.c
+++ b/arch/mips/mti-sead3/sead3-time.c
@@ -8,24 +8,12 @@
 #include <linux/init.h>
 
 #include <asm/cpu.h>
+#include <asm/gic.h>
 #include <asm/setup.h>
 #include <asm/time.h>
 #include <asm/irq.h>
 #include <asm/mips-boards/generic.h>
 
-static int mips_cpu_timer_irq;
-static int mips_cpu_perf_irq;
-
-static void mips_timer_dispatch(void)
-{
-	do_IRQ(mips_cpu_timer_irq);
-}
-
-static void mips_perf_dispatch(void)
-{
-	do_IRQ(mips_cpu_perf_irq);
-}
-
 static void __iomem *status_reg = (void __iomem *)0xbf000410;
 
 /*
@@ -83,22 +71,18 @@ void read_persistent_clock(struct timespec *ts)
 
 int get_c0_perfcount_int(void)
 {
-	if (cp0_perfcount_irq >= 0) {
-		if (cpu_has_vint)
-			set_vi_handler(cp0_perfcount_irq, mips_perf_dispatch);
-		mips_cpu_perf_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
-	} else {
-		mips_cpu_perf_irq = -1;
-	}
-	return mips_cpu_perf_irq;
+	if (gic_present)
+		return gic_get_c0_compare_int();
+	if (cp0_perfcount_irq >= 0)
+		return MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
+	return -1;
 }
 
 unsigned int get_c0_compare_int(void)
 {
-	if (cpu_has_vint)
-		set_vi_handler(cp0_compare_irq, mips_timer_dispatch);
-	mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
-	return mips_cpu_timer_irq;
+	if (gic_present)
+		return gic_get_c0_compare_int();
+	return MIPS_CPU_IRQ_BASE + cp0_compare_irq;
 }
 
 void __init plat_time_init(void)
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index bfe8bfb..b28f7ad 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -44,6 +44,7 @@ static struct gic_intrmask_regs intrmask_regs[NR_CPUS];
 static DEFINE_SPINLOCK(gic_lock);
 static struct irq_domain *gic_irq_domain;
 static int gic_shared_intrs;
+static int gic_vpes;
 static struct irq_chip gic_level_irq_controller, gic_edge_irq_controller;
 
 static void __gic_irq_dispatch(void);
@@ -96,12 +97,35 @@ cycle_t gic_read_compare(void)
 }
 #endif
 
+static bool gic_local_irq_is_routable(int intr)
+{
+	u32 vpe_ctl;
+
+	/* All local interrupts are routable in EIC mode. */
+	if (cpu_has_veic)
+		return true;
+
+	GICREAD(GIC_REG(VPE_LOCAL, GIC_VPE_CTL), vpe_ctl);
+	switch (intr) {
+	case GIC_LOCAL_INT_TIMER:
+		return vpe_ctl & GIC_VPE_CTL_TIMER_RTBL_MSK;
+	case GIC_LOCAL_INT_PERFCTR:
+		return vpe_ctl & GIC_VPE_CTL_PERFCNT_RTBL_MSK;
+	case GIC_LOCAL_INT_FDC:
+		return vpe_ctl & GIC_VPE_CTL_FDC_RTBL_MSK;
+	case GIC_LOCAL_INT_SWINT0:
+	case GIC_LOCAL_INT_SWINT1:
+		return vpe_ctl & GIC_VPE_CTL_SWINT_RTBL_MSK;
+	default:
+		return true;
+	}
+}
+
 unsigned int gic_get_timer_pending(void)
 {
 	unsigned int vpe_pending;
 
-	GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), 0);
-	GICREAD(GIC_REG(VPE_OTHER, GIC_VPE_PEND), vpe_pending);
+	GICREAD(GIC_REG(VPE_LOCAL, GIC_VPE_PEND), vpe_pending);
 	return (vpe_pending & GIC_VPE_PEND_TIMER_MSK);
 }
 
@@ -119,53 +143,6 @@ void gic_send_ipi(unsigned int intr)
 	GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), 0x80000000 | intr);
 }
 
-static void __init vpe_local_setup(unsigned int numvpes)
-{
-	unsigned long timer_intr = GIC_INT_TMR;
-	unsigned long perf_intr = GIC_INT_PERFCTR;
-	unsigned int vpe_ctl;
-	int i;
-
-	if (cpu_has_veic) {
-		/*
-		 * GIC timer interrupt -> CPU HW Int X (vector X+2) ->
-		 * map to pin X+2-1 (since GIC adds 1)
-		 */
-		timer_intr += (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET);
-		/*
-		 * GIC perfcnt interrupt -> CPU HW Int X (vector X+2) ->
-		 * map to pin X+2-1 (since GIC adds 1)
-		 */
-		perf_intr += (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET);
-	}
-
-	/*
-	 * Setup the default performance counter timer interrupts
-	 * for all VPEs
-	 */
-	for (i = 0; i < numvpes; i++) {
-		GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i);
-
-		/* Are Interrupts locally routable? */
-		GICREAD(GIC_REG(VPE_OTHER, GIC_VPE_CTL), vpe_ctl);
-		if (vpe_ctl & GIC_VPE_CTL_TIMER_RTBL_MSK)
-			GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP),
-				 GIC_MAP_TO_PIN_MSK | timer_intr);
-		if (cpu_has_veic) {
-			set_vi_handler(timer_intr + GIC_PIN_TO_VEC_OFFSET,
-				       __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_irq_dispatch);
-		}
-	}
-}
-
 unsigned int gic_compare_int(void)
 {
 	unsigned int pending;
@@ -177,6 +154,26 @@ unsigned int gic_compare_int(void)
 		return 0;
 }
 
+int gic_get_c0_compare_int(void)
+{
+	if (!gic_local_irq_is_routable(GIC_LOCAL_INT_TIMER))
+		return MIPS_CPU_IRQ_BASE + cp0_compare_irq;
+	return irq_create_mapping(gic_irq_domain,
+				  GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_TIMER));
+}
+
+int gic_get_c0_perfcount_int(void)
+{
+	if (!gic_local_irq_is_routable(GIC_LOCAL_INT_PERFCTR)) {
+		/* Is the erformance counter shared with the timer? */
+		if (cp0_perfcount_irq < 0)
+			return -1;
+		return MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
+	}
+	return irq_create_mapping(gic_irq_domain,
+				  GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_PERFCTR));
+}
+
 void gic_get_int_mask(unsigned long *dst, const unsigned long *src)
 {
 	unsigned int i;
@@ -217,24 +214,24 @@ unsigned int gic_get_int(void)
 
 static void gic_mask_irq(struct irq_data *d)
 {
-	GIC_CLR_INTR_MASK(d->hwirq);
+	GIC_CLR_INTR_MASK(GIC_HWIRQ_TO_SHARED(d->hwirq));
 }
 
 static void gic_unmask_irq(struct irq_data *d)
 {
-	GIC_SET_INTR_MASK(d->hwirq);
+	GIC_SET_INTR_MASK(GIC_HWIRQ_TO_SHARED(d->hwirq));
 }
 
 static void gic_ack_irq(struct irq_data *d)
 {
-	unsigned int irq = d->hwirq;
+	unsigned int irq = GIC_HWIRQ_TO_SHARED(d->hwirq);
 
 	GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq);
 }
 
 static int gic_set_type(struct irq_data *d, unsigned int type)
 {
-	unsigned int irq = d->hwirq;
+	unsigned int irq = GIC_HWIRQ_TO_SHARED(d->hwirq);
 	unsigned long flags;
 	bool is_edge;
 
@@ -291,7 +288,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
 static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
 			    bool force)
 {
-	unsigned int irq = d->hwirq;
+	unsigned int irq = GIC_HWIRQ_TO_SHARED(d->hwirq);
 	cpumask_t	tmp = CPU_MASK_NONE;
 	unsigned long	flags;
 	int		i;
@@ -339,12 +336,85 @@ static struct irq_chip gic_edge_irq_controller = {
 #endif
 };
 
+static unsigned int gic_get_local_int(void)
+{
+	unsigned long pending, masked;
+
+	GICREAD(GIC_REG(VPE_LOCAL, GIC_VPE_PEND), pending);
+	GICREAD(GIC_REG(VPE_LOCAL, GIC_VPE_MASK), masked);
+
+	bitmap_and(&pending, &pending, &masked, GIC_NUM_LOCAL_INTRS);
+
+	return find_first_bit(&pending, GIC_NUM_LOCAL_INTRS);
+}
+
+static void gic_mask_local_irq(struct irq_data *d)
+{
+	int intr = GIC_HWIRQ_TO_LOCAL(d->hwirq);
+
+	GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_RMASK), 1 << intr);
+}
+
+static void gic_unmask_local_irq(struct irq_data *d)
+{
+	int intr = GIC_HWIRQ_TO_LOCAL(d->hwirq);
+
+	GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_SMASK), 1 << intr);
+}
+
+static struct irq_chip gic_local_irq_controller = {
+	.name			=	"MIPS GIC Local",
+	.irq_mask		=	gic_mask_local_irq,
+	.irq_unmask		=	gic_unmask_local_irq,
+};
+
+static void gic_mask_local_irq_all_vpes(struct irq_data *d)
+{
+	int intr = GIC_HWIRQ_TO_LOCAL(d->hwirq);
+	int i;
+	unsigned long flags;
+
+	spin_lock_irqsave(&gic_lock, flags);
+	for (i = 0; i < gic_vpes; i++) {
+		GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i);
+		GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_RMASK), 1 << intr);
+	}
+	spin_unlock_irqrestore(&gic_lock, flags);
+}
+
+static void gic_unmask_local_irq_all_vpes(struct irq_data *d)
+{
+	int intr = GIC_HWIRQ_TO_LOCAL(d->hwirq);
+	int i;
+	unsigned long flags;
+
+	spin_lock_irqsave(&gic_lock, flags);
+	for (i = 0; i < gic_vpes; i++) {
+		GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i);
+		GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_SMASK), 1 << intr);
+	}
+	spin_unlock_irqrestore(&gic_lock, flags);
+}
+
+static struct irq_chip gic_all_vpes_local_irq_controller = {
+	.name			=	"MIPS GIC Local",
+	.irq_mask		=	gic_mask_local_irq_all_vpes,
+	.irq_unmask		=	gic_unmask_local_irq_all_vpes,
+};
+
 static void __gic_irq_dispatch(void)
 {
 	unsigned int intr, virq;
 
+	while ((intr = gic_get_local_int()) != GIC_NUM_LOCAL_INTRS) {
+		virq = irq_linear_revmap(gic_irq_domain,
+					 GIC_LOCAL_TO_HWIRQ(intr));
+		do_IRQ(virq);
+	}
+
 	while ((intr = gic_get_int()) != gic_shared_intrs) {
-		virq = irq_linear_revmap(gic_irq_domain, intr);
+		virq = irq_linear_revmap(gic_irq_domain,
+					 GIC_SHARED_TO_HWIRQ(intr));
 		do_IRQ(virq);
 	}
 }
@@ -397,7 +467,8 @@ static struct irqaction irq_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 virq = irq_create_mapping(gic_irq_domain,
+				      GIC_SHARED_TO_HWIRQ(intr));
 	int i;
 
 	GIC_SH_MAP_TO_VPE_SMASK(intr, cpu);
@@ -430,7 +501,7 @@ static inline void gic_ipi_init(void)
 }
 #endif
 
-static void __init gic_basic_init(int numvpes)
+static void __init gic_basic_init(void)
 {
 	unsigned int i;
 
@@ -443,28 +514,112 @@ static void __init gic_basic_init(int numvpes)
 		GIC_CLR_INTR_MASK(i);
 	}
 
-	vpe_local_setup(numvpes);
+	for (i = 0; i < gic_vpes; i++) {
+		unsigned int j;
+
+		GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i);
+		for (j = 0; j < GIC_NUM_LOCAL_INTRS; j++) {
+			if (!gic_local_irq_is_routable(j))
+				continue;
+			GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_RMASK), 1 << j);
+		}
+	}
 }
 
-static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq,
-			      irq_hw_number_t hw)
+static int gic_local_irq_domain_map(struct irq_domain *d, unsigned int virq,
+				    irq_hw_number_t hw)
 {
+	int intr = GIC_HWIRQ_TO_LOCAL(hw);
+	int ret = 0;
+	int i;
+	unsigned long flags;
+
+	if (!gic_local_irq_is_routable(intr))
+		return -EPERM;
+
+	/*
+	 * HACK: These are all really percpu interrupts, but the rest
+	 * of the MIPS kernel code does not use the percpu IRQ API for
+	 * the CP0 timer and performance counter interrupts.
+	 */
+	if (intr != GIC_LOCAL_INT_TIMER && intr != GIC_LOCAL_INT_PERFCTR) {
+		irq_set_chip_and_handler(virq,
+					 &gic_local_irq_controller,
+					 handle_percpu_devid_irq);
+		irq_set_percpu_devid(virq);
+	} else {
+		irq_set_chip_and_handler(virq,
+					 &gic_all_vpes_local_irq_controller,
+					 handle_percpu_irq);
+	}
+
+	spin_lock_irqsave(&gic_lock, flags);
+	for (i = 0; i < gic_vpes; i++) {
+		u32 val = GIC_MAP_TO_PIN_MSK | gic_cpu_pin;
+
+		GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i);
+
+		switch (intr) {
+		case GIC_LOCAL_INT_WD:
+			GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_WD_MAP), val);
+			break;
+		case GIC_LOCAL_INT_COMPARE:
+			GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_MAP), val);
+			break;
+		case GIC_LOCAL_INT_TIMER:
+			GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP), val);
+			break;
+		case GIC_LOCAL_INT_PERFCTR:
+			GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP), val);
+			break;
+		case GIC_LOCAL_INT_SWINT0:
+			GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_SWINT0_MAP), val);
+			break;
+		case GIC_LOCAL_INT_SWINT1:
+			GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_SWINT1_MAP), val);
+			break;
+		case GIC_LOCAL_INT_FDC:
+			GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_FDC_MAP), val);
+			break;
+		default:
+			pr_err("Invalid local IRQ %d\n", intr);
+			ret = -EINVAL;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&gic_lock, flags);
+
+	return ret;
+}
+
+static int gic_shared_irq_domain_map(struct irq_domain *d, unsigned int virq,
+				     irq_hw_number_t hw)
+{
+	int intr = GIC_HWIRQ_TO_SHARED(hw);
 	unsigned long flags;
 
 	irq_set_chip_and_handler(virq, &gic_level_irq_controller,
 				 handle_level_irq);
 
 	spin_lock_irqsave(&gic_lock, flags);
-	GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(hw)),
+	GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)),
 		 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);
+	GIC_SH_MAP_TO_VPE_SMASK(intr, 0);
+	set_bit(intr, pcpu_masks[0].pcpu_mask);
 	spin_unlock_irqrestore(&gic_lock, flags);
 
 	return 0;
 }
 
+static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq,
+			      irq_hw_number_t hw)
+{
+	if (GIC_HWIRQ_TO_LOCAL(hw) < GIC_NUM_LOCAL_INTRS)
+		return gic_local_irq_domain_map(d, virq, hw);
+	return gic_shared_irq_domain_map(d, virq, hw);
+}
+
 static struct irq_domain_ops gic_irq_domain_ops = {
 	.map = gic_irq_domain_map,
 	.xlate = irq_domain_xlate_twocell,
@@ -475,7 +630,6 @@ void __init gic_init(unsigned long gic_base_addr,
 		     unsigned int irqbase)
 {
 	unsigned int gicconfig;
-	int numvpes, numintrs;
 
 	_gic_base = (unsigned long) ioremap_nocache(gic_base_addr,
 						    gic_addrspace_size);
@@ -485,9 +639,9 @@ void __init gic_init(unsigned long gic_base_addr,
 		   GIC_SH_CONFIG_NUMINTRS_SHF;
 	gic_shared_intrs = ((gic_shared_intrs + 1) * 8);
 
-	numvpes = (gicconfig & GIC_SH_CONFIG_NUMVPES_MSK) >>
+	gic_vpes = (gicconfig & GIC_SH_CONFIG_NUMVPES_MSK) >>
 		  GIC_SH_CONFIG_NUMVPES_SHF;
-	numvpes = numvpes + 1;
+	gic_vpes = gic_vpes + 1;
 
 	if (cpu_has_veic) {
 		/* Always use vector 1 in EIC mode */
@@ -500,12 +654,13 @@ void __init gic_init(unsigned long gic_base_addr,
 					gic_irq_dispatch);
 	}
 
-	gic_irq_domain = irq_domain_add_simple(NULL, gic_shared_intrs, irqbase,
+	gic_irq_domain = irq_domain_add_simple(NULL, GIC_NUM_LOCAL_INTRS +
+					       gic_shared_intrs, irqbase,
 					       &gic_irq_domain_ops, NULL);
 	if (!gic_irq_domain)
 		panic("Failed to add GIC IRQ domain");
 
-	gic_basic_init(numvpes);
+	gic_basic_init();
 
 	gic_ipi_init();
 }
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH V2 22/24] irqchip: mips-gic: Remove unnecessary globals
  2014-09-18 21:47 [PATCH V2 00/24] MIPS GIC cleanup, part 1 Andrew Bresticker
                   ` (20 preceding siblings ...)
  2014-09-18 21:47 ` [PATCH V2 21/24] irqchip: mips-gic: Support local interrupts Andrew Bresticker
@ 2014-09-18 21:47 ` Andrew Bresticker
  2014-09-18 21:47 ` [PATCH V2 23/24] MIPS: Malta: Use generic plat_irq_dispatch Andrew Bresticker
  2014-09-18 21:47 ` [PATCH V2 24/24] MIPS: sead3: " Andrew Bresticker
  23 siblings, 0 replies; 35+ messages in thread
From: Andrew Bresticker @ 2014-09-18 21:47 UTC (permalink / raw)
  To: Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Andrew Bresticker, Jeffrey Deans, Markos Chandras, Paul Burton,
	Qais Yousef, Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

Now that all GIC interrupt routing and handling logic is in the GIC
driver itself, un-export variables/functions which are no longer used
outside the GIC driver.  This also allows us to remove gic_compare_int
and combine gic_get_int_mask with gic_get_int since these interfaces
are no longer used.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Acked-by: Jason Cooper <jason@lakedaemon.net>
Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
Tested-by: Qais Yousef <qais.yousef@imgtec.com>
---
No changes from v1.
---
 arch/mips/include/asm/gic.h    |  5 -----
 drivers/irqchip/irq-mips-gic.c | 28 ++++------------------------
 2 files changed, 4 insertions(+), 29 deletions(-)

diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h
index 6b99610..727b7bf 100644
--- a/arch/mips/include/asm/gic.h
+++ b/arch/mips/include/asm/gic.h
@@ -364,13 +364,11 @@
 extern unsigned int gic_present;
 extern unsigned int gic_frequency;
 extern unsigned long _gic_base;
-extern unsigned int gic_cpu_pin;
 
 extern void gic_init(unsigned long gic_base_addr,
 	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);
 extern cycle_t gic_read_compare(void);
 extern void gic_write_compare(cycle_t cnt);
@@ -378,10 +376,7 @@ extern void gic_write_cpu_compare(cycle_t cnt, int cpu);
 extern void gic_send_ipi(unsigned int intr);
 extern unsigned int plat_ipi_call_int_xlate(unsigned int);
 extern unsigned int plat_ipi_resched_int_xlate(unsigned int);
-extern void gic_bind_eic_interrupt(int irq, int set);
 extern unsigned int gic_get_timer_pending(void);
-extern void gic_get_int_mask(unsigned long *dst, const unsigned long *src);
-extern unsigned int gic_get_int(void);
 extern int gic_get_c0_compare_int(void);
 extern int gic_get_c0_perfcount_int(void);
 #endif /* _ASM_GICREGS_H */
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index b28f7ad..02c7d2a 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -24,7 +24,6 @@
 unsigned int gic_frequency;
 unsigned int gic_present;
 unsigned long _gic_base;
-unsigned int gic_cpu_pin;
 
 struct gic_pcpu_mask {
 	DECLARE_BITMAP(pcpu_mask, GIC_MAX_INTRS);
@@ -45,6 +44,7 @@ static DEFINE_SPINLOCK(gic_lock);
 static struct irq_domain *gic_irq_domain;
 static int gic_shared_intrs;
 static int gic_vpes;
+static unsigned int gic_cpu_pin;
 static struct irq_chip gic_level_irq_controller, gic_edge_irq_controller;
 
 static void __gic_irq_dispatch(void);
@@ -129,7 +129,7 @@ unsigned int gic_get_timer_pending(void)
 	return (vpe_pending & GIC_VPE_PEND_TIMER_MSK);
 }
 
-void gic_bind_eic_interrupt(int irq, int set)
+static void gic_bind_eic_interrupt(int irq, int set)
 {
 	/* Convert irq vector # to hw int # */
 	irq -= GIC_PIN_TO_VEC_OFFSET;
@@ -143,17 +143,6 @@ void gic_send_ipi(unsigned int intr)
 	GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), 0x80000000 | intr);
 }
 
-unsigned int gic_compare_int(void)
-{
-	unsigned int pending;
-
-	GICREAD(GIC_REG(VPE_LOCAL, GIC_VPE_PEND), pending);
-	if (pending & GIC_VPE_PEND_CMP_MSK)
-		return 1;
-	else
-		return 0;
-}
-
 int gic_get_c0_compare_int(void)
 {
 	if (!gic_local_irq_is_routable(GIC_LOCAL_INT_TIMER))
@@ -174,7 +163,7 @@ int gic_get_c0_perfcount_int(void)
 				  GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_PERFCTR));
 }
 
-void gic_get_int_mask(unsigned long *dst, const unsigned long *src)
+static unsigned int gic_get_int(void)
 {
 	unsigned int i;
 	unsigned long *pending, *intrmask, *pcpu_mask;
@@ -199,17 +188,8 @@ void gic_get_int_mask(unsigned long *dst, const unsigned long *src)
 
 	bitmap_and(pending, pending, intrmask, gic_shared_intrs);
 	bitmap_and(pending, pending, pcpu_mask, gic_shared_intrs);
-	bitmap_and(dst, src, pending, gic_shared_intrs);
-}
-
-unsigned int gic_get_int(void)
-{
-	DECLARE_BITMAP(interrupts, GIC_MAX_INTRS);
-
-	bitmap_fill(interrupts, gic_shared_intrs);
-	gic_get_int_mask(interrupts, interrupts);
 
-	return find_first_bit(interrupts, gic_shared_intrs);
+	return find_first_bit(pending, gic_shared_intrs);
 }
 
 static void gic_mask_irq(struct irq_data *d)
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH V2 23/24] MIPS: Malta: Use generic plat_irq_dispatch
  2014-09-18 21:47 [PATCH V2 00/24] MIPS GIC cleanup, part 1 Andrew Bresticker
                   ` (21 preceding siblings ...)
  2014-09-18 21:47 ` [PATCH V2 22/24] irqchip: mips-gic: Remove unnecessary globals Andrew Bresticker
@ 2014-09-18 21:47 ` Andrew Bresticker
  2014-09-18 21:47 ` [PATCH V2 24/24] MIPS: sead3: " Andrew Bresticker
  23 siblings, 0 replies; 35+ messages in thread
From: Andrew Bresticker @ 2014-09-18 21:47 UTC (permalink / raw)
  To: Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Andrew Bresticker, Jeffrey Deans, Markos Chandras, Paul Burton,
	Qais Yousef, Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

The generic plat_irq_dispatch provided in irq_cpu.c is sufficient for
dispatching interrupts on Malta in legacy and vectored interrupt modes.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
Tested-by: Qais Yousef <qais.yousef@imgtec.com>
---
No changes from v1.
---
 arch/mips/mti-malta/malta-int.c | 92 -----------------------------------------
 1 file changed, 92 deletions(-)

diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c
index c6b3548..bcab0b1 100644
--- a/arch/mips/mti-malta/malta-int.c
+++ b/arch/mips/mti-malta/malta-int.c
@@ -190,92 +190,6 @@ static irqreturn_t corehi_handler(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static inline int clz(unsigned long x)
-{
-	__asm__(
-	"	.set	push					\n"
-	"	.set	mips32					\n"
-	"	clz	%0, %1					\n"
-	"	.set	pop					\n"
-	: "=r" (x)
-	: "r" (x));
-
-	return x;
-}
-
-/*
- * Version of ffs that only looks at bits 12..15.
- */
-static inline unsigned int irq_ffs(unsigned int pending)
-{
-#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
-	return -clz(pending) + 31 - CAUSEB_IP;
-#else
-	unsigned int a0 = 7;
-	unsigned int t0;
-
-	t0 = pending & 0xf000;
-	t0 = t0 < 1;
-	t0 = t0 << 2;
-	a0 = a0 - t0;
-	pending = pending << t0;
-
-	t0 = pending & 0xc000;
-	t0 = t0 < 1;
-	t0 = t0 << 1;
-	a0 = a0 - t0;
-	pending = pending << t0;
-
-	t0 = pending & 0x8000;
-	t0 = t0 < 1;
-	/* t0 = t0 << 2; */
-	a0 = a0 - t0;
-	/* pending = pending << t0; */
-
-	return a0;
-#endif
-}
-
-/*
- * IRQs on the Malta board look basically (barring software IRQs which we
- * don't use at all and all external interrupt sources are combined together
- * on hardware interrupt 0 (MIPS IRQ 2)) like:
- *
- *	MIPS IRQ	Source
- *	--------	------
- *	       0	Software (ignored)
- *	       1	Software (ignored)
- *	       2	Combined hardware interrupt (hw0)
- *	       3	Hardware (ignored)
- *	       4	Hardware (ignored)
- *	       5	Hardware (ignored)
- *	       6	Hardware (ignored)
- *	       7	R4k timer (what we use)
- *
- * We handle the IRQ according to _our_ priority which is:
- *
- * Highest ----	    R4k Timer
- * Lowest  ----	    Combined hardware interrupt
- *
- * then we just return, if multiple IRQs are pending then we will just take
- * another exception, big deal.
- */
-
-asmlinkage void plat_irq_dispatch(void)
-{
-	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
-	int irq;
-
-	if (unlikely(!pending)) {
-		spurious_interrupt();
-		return;
-	}
-
-	irq = irq_ffs(pending);
-
-	do_IRQ(MIPS_CPU_IRQ_BASE + irq);
-}
-
 #ifdef CONFIG_MIPS_MT_SMP
 
 #define MIPS_CPU_IPI_RESCHED_IRQ 0	/* SW int 0 for resched */
@@ -438,12 +352,6 @@ void __init arch_init_irq(void)
 			cpu_ipi_resched_irq = MSC01E_INT_SW0;
 			cpu_ipi_call_irq = MSC01E_INT_SW1;
 		} else {
-			if (cpu_has_vint) {
-				set_vi_handler (MIPS_CPU_IPI_RESCHED_IRQ,
-					ipi_resched_dispatch);
-				set_vi_handler (MIPS_CPU_IPI_CALL_IRQ,
-					ipi_call_dispatch);
-			}
 			cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE +
 				MIPS_CPU_IPI_RESCHED_IRQ;
 			cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE +
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH V2 24/24] MIPS: sead3: Use generic plat_irq_dispatch
  2014-09-18 21:47 [PATCH V2 00/24] MIPS GIC cleanup, part 1 Andrew Bresticker
                   ` (22 preceding siblings ...)
  2014-09-18 21:47 ` [PATCH V2 23/24] MIPS: Malta: Use generic plat_irq_dispatch Andrew Bresticker
@ 2014-09-18 21:47 ` Andrew Bresticker
  23 siblings, 0 replies; 35+ messages in thread
From: Andrew Bresticker @ 2014-09-18 21:47 UTC (permalink / raw)
  To: Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Andrew Bresticker, Jeffrey Deans, Markos Chandras, Paul Burton,
	Qais Yousef, Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

The generic plat_irq_dispatch provided in irq_cpu.c is sufficient for
dispatching interrupts on SEAD-3 in legacy and vectored interrupt modes.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
Tested-by: Qais Yousef <qais.yousef@imgtec.com>
---
No changes from v1.
---
 arch/mips/mti-sead3/sead3-int.c | 23 +----------------------
 1 file changed, 1 insertion(+), 22 deletions(-)

diff --git a/arch/mips/mti-sead3/sead3-int.c b/arch/mips/mti-sead3/sead3-int.c
index cb06cd9..69ae185 100644
--- a/arch/mips/mti-sead3/sead3-int.c
+++ b/arch/mips/mti-sead3/sead3-int.c
@@ -22,32 +22,11 @@
 
 static unsigned long sead3_config_reg;
 
-asmlinkage void plat_irq_dispatch(void)
-{
-	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
-	int irq;
-
-	irq = (fls(pending) - CAUSEB_IP - 1);
-	if (irq >= 0)
-		do_IRQ(MIPS_CPU_IRQ_BASE + irq);
-	else
-		spurious_interrupt();
-}
-
 void __init arch_init_irq(void)
 {
-	int i;
-
-	if (!cpu_has_veic) {
+	if (!cpu_has_veic)
 		mips_cpu_irq_init();
 
-		if (cpu_has_vint) {
-			/* install generic handler */
-			for (i = 0; i < 8; i++)
-				set_vi_handler(i, plat_irq_dispatch);
-		}
-	}
-
 	sead3_config_reg = (unsigned long)ioremap_nocache(SEAD_CONFIG_BASE,
 		SEAD_CONFIG_SIZE);
 	gic_present = (REG32(sead3_config_reg) & SEAD_CONFIG_GIC_PRESENT_MSK) >>
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* Re: [PATCH V2 18/24] irqchip: mips-gic: Stop using per-platform mapping tables
@ 2015-01-15 11:59     ` James Hogan
  0 siblings, 0 replies; 35+ messages in thread
From: James Hogan @ 2015-01-15 11:59 UTC (permalink / raw)
  To: Andrew Bresticker, Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Jeffrey Deans, Markos Chandras, Paul Burton, Qais Yousef,
	Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

[-- Attachment #1: Type: text/plain, Size: 33044 bytes --]

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@chromium.org>
> Acked-by: Jason Cooper <jason@lakedaemon.net>
> Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
> Tested-by: Qais Yousef <qais.yousef@imgtec.com>

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 #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH V2 18/24] irqchip: mips-gic: Stop using per-platform mapping tables
@ 2015-01-15 11:59     ` James Hogan
  0 siblings, 0 replies; 35+ messages in thread
From: James Hogan @ 2015-01-15 11:59 UTC (permalink / raw)
  To: Andrew Bresticker, Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Jeffrey Deans, Markos Chandras, Paul Burton, Qais Yousef,
	Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

[-- Attachment #1: Type: text/plain, Size: 33044 bytes --]

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@chromium.org>
> Acked-by: Jason Cooper <jason@lakedaemon.net>
> Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
> Tested-by: Qais Yousef <qais.yousef@imgtec.com>

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 #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH V2 18/24] irqchip: mips-gic: Stop using per-platform mapping tables
@ 2015-01-15 16:29       ` James Hogan
  0 siblings, 0 replies; 35+ messages in thread
From: James Hogan @ 2015-01-15 16:29 UTC (permalink / raw)
  To: Andrew Bresticker, Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Jeffrey Deans, Markos Chandras, Paul Burton, Qais Yousef,
	Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2283 bytes --]

On 15/01/15 11:59, James Hogan wrote:
> 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@chromium.org>
>> Acked-by: Jason Cooper <jason@lakedaemon.net>
>> Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
>> Tested-by: Qais Yousef <qais.yousef@imgtec.com>
> 
> 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.

Right, it appears the CPU IRQ line that the GIC is using doesn't get
unmasked (STATUSF_IP2) when a new VPE is brought up, so only the first
CPU will actually get any interrupts after your patch (including the
rather critical IPIs), i.e. hacking it in vsmp_init_secondary() in
smp-mt.c allows it to boot.

Hmm, I'll have a think about what the most generic fix is, since
arbitrary stuff may or may not have registered handlers for the raw CPU
interrupts (timer, performance counter, gic etc)...

Cheers
James


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH V2 18/24] irqchip: mips-gic: Stop using per-platform mapping tables
@ 2015-01-15 16:29       ` James Hogan
  0 siblings, 0 replies; 35+ messages in thread
From: James Hogan @ 2015-01-15 16:29 UTC (permalink / raw)
  To: Andrew Bresticker, Ralf Baechle, Thomas Gleixner, Jason Cooper
  Cc: Jeffrey Deans, Markos Chandras, Paul Burton, Qais Yousef,
	Jonas Gorski, John Crispin, David Daney, linux-mips,
	linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2283 bytes --]

On 15/01/15 11:59, James Hogan wrote:
> 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@chromium.org>
>> Acked-by: Jason Cooper <jason@lakedaemon.net>
>> Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
>> Tested-by: Qais Yousef <qais.yousef@imgtec.com>
> 
> 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.

Right, it appears the CPU IRQ line that the GIC is using doesn't get
unmasked (STATUSF_IP2) when a new VPE is brought up, so only the first
CPU will actually get any interrupts after your patch (including the
rather critical IPIs), i.e. hacking it in vsmp_init_secondary() in
smp-mt.c allows it to boot.

Hmm, I'll have a think about what the most generic fix is, since
arbitrary stuff may or may not have registered handlers for the raw CPU
interrupts (timer, performance counter, gic etc)...

Cheers
James


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH V2 18/24] irqchip: mips-gic: Stop using per-platform mapping tables
@ 2015-01-15 16:36         ` Qais Yousef
  0 siblings, 0 replies; 35+ messages in thread
From: Qais Yousef @ 2015-01-15 16:36 UTC (permalink / raw)
  To: James Hogan
  Cc: Andrew Bresticker, Ralf Baechle, Thomas Gleixner, Jason Cooper,
	Jeffrey Deans, Markos Chandras, Paul Burton, Jonas Gorski,
	John Crispin, David Daney, linux-mips, linux-kernel

On 01/15/2015 04:29 PM, James Hogan wrote:
> On 15/01/15 11:59, James Hogan wrote:
>> 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@chromium.org>
>>> Acked-by: Jason Cooper <jason@lakedaemon.net>
>>> Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
>>> Tested-by: Qais Yousef <qais.yousef@imgtec.com>
>> 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.
> Right, it appears the CPU IRQ line that the GIC is using doesn't get
> unmasked (STATUSF_IP2) when a new VPE is brought up, so only the first
> CPU will actually get any interrupts after your patch (including the
> rather critical IPIs), i.e. hacking it in vsmp_init_secondary() in
> smp-mt.c allows it to boot.
>
> Hmm, I'll have a think about what the most generic fix is, since
> arbitrary stuff may or may not have registered handlers for the raw CPU
> interrupts (timer, performance counter, gic etc)...
>
> Cheers
> James
>

Is this similar to the issue addressed by this (ff1e29ade4c6 MIPS: 
smp-cps: Enable all hardware interrupts on secondary CPUs)?

Qais

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH V2 18/24] irqchip: mips-gic: Stop using per-platform mapping tables
@ 2015-01-15 16:36         ` Qais Yousef
  0 siblings, 0 replies; 35+ messages in thread
From: Qais Yousef @ 2015-01-15 16:36 UTC (permalink / raw)
  To: James Hogan
  Cc: Andrew Bresticker, Ralf Baechle, Thomas Gleixner, Jason Cooper,
	Jeffrey Deans, Markos Chandras, Paul Burton, Jonas Gorski,
	John Crispin, David Daney, linux-mips, linux-kernel

On 01/15/2015 04:29 PM, James Hogan wrote:
> On 15/01/15 11:59, James Hogan wrote:
>> 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@chromium.org>
>>> Acked-by: Jason Cooper <jason@lakedaemon.net>
>>> Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
>>> Tested-by: Qais Yousef <qais.yousef@imgtec.com>
>> 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.
> Right, it appears the CPU IRQ line that the GIC is using doesn't get
> unmasked (STATUSF_IP2) when a new VPE is brought up, so only the first
> CPU will actually get any interrupts after your patch (including the
> rather critical IPIs), i.e. hacking it in vsmp_init_secondary() in
> smp-mt.c allows it to boot.
>
> Hmm, I'll have a think about what the most generic fix is, since
> arbitrary stuff may or may not have registered handlers for the raw CPU
> interrupts (timer, performance counter, gic etc)...
>
> Cheers
> James
>

Is this similar to the issue addressed by this (ff1e29ade4c6 MIPS: 
smp-cps: Enable all hardware interrupts on secondary CPUs)?

Qais

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH V2 18/24] irqchip: mips-gic: Stop using per-platform mapping tables
@ 2015-01-15 16:50           ` James Hogan
  0 siblings, 0 replies; 35+ messages in thread
From: James Hogan @ 2015-01-15 16:50 UTC (permalink / raw)
  To: Qais Yousef
  Cc: Andrew Bresticker, Ralf Baechle, Thomas Gleixner, Jason Cooper,
	Jeffrey Deans, Markos Chandras, Paul Burton, Jonas Gorski,
	John Crispin, David Daney, linux-mips, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2726 bytes --]

On 15/01/15 16:36, Qais Yousef wrote:
> On 01/15/2015 04:29 PM, James Hogan wrote:
>> On 15/01/15 11:59, James Hogan wrote:
>>> 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@chromium.org>
>>>> Acked-by: Jason Cooper <jason@lakedaemon.net>
>>>> Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
>>>> Tested-by: Qais Yousef <qais.yousef@imgtec.com>
>>> 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.
>> Right, it appears the CPU IRQ line that the GIC is using doesn't get
>> unmasked (STATUSF_IP2) when a new VPE is brought up, so only the first
>> CPU will actually get any interrupts after your patch (including the
>> rather critical IPIs), i.e. hacking it in vsmp_init_secondary() in
>> smp-mt.c allows it to boot.
>>
>> Hmm, I'll have a think about what the most generic fix is, since
>> arbitrary stuff may or may not have registered handlers for the raw CPU
>> interrupts (timer, performance counter, gic etc)...
>>
>> Cheers
>> James
>>
> 
> Is this similar to the issue addressed by this (ff1e29ade4c6 MIPS:
> smp-cps: Enable all hardware interrupts on secondary CPUs)?

Thanks Qais. Yes, enabling CPS also works around the problem thanks to
that commit.

Cheers
James


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH V2 18/24] irqchip: mips-gic: Stop using per-platform mapping tables
@ 2015-01-15 16:50           ` James Hogan
  0 siblings, 0 replies; 35+ messages in thread
From: James Hogan @ 2015-01-15 16:50 UTC (permalink / raw)
  To: Qais Yousef
  Cc: Andrew Bresticker, Ralf Baechle, Thomas Gleixner, Jason Cooper,
	Jeffrey Deans, Markos Chandras, Paul Burton, Jonas Gorski,
	John Crispin, David Daney, linux-mips, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2726 bytes --]

On 15/01/15 16:36, Qais Yousef wrote:
> On 01/15/2015 04:29 PM, James Hogan wrote:
>> On 15/01/15 11:59, James Hogan wrote:
>>> 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@chromium.org>
>>>> Acked-by: Jason Cooper <jason@lakedaemon.net>
>>>> Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
>>>> Tested-by: Qais Yousef <qais.yousef@imgtec.com>
>>> 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.
>> Right, it appears the CPU IRQ line that the GIC is using doesn't get
>> unmasked (STATUSF_IP2) when a new VPE is brought up, so only the first
>> CPU will actually get any interrupts after your patch (including the
>> rather critical IPIs), i.e. hacking it in vsmp_init_secondary() in
>> smp-mt.c allows it to boot.
>>
>> Hmm, I'll have a think about what the most generic fix is, since
>> arbitrary stuff may or may not have registered handlers for the raw CPU
>> interrupts (timer, performance counter, gic etc)...
>>
>> Cheers
>> James
>>
> 
> Is this similar to the issue addressed by this (ff1e29ade4c6 MIPS:
> smp-cps: Enable all hardware interrupts on secondary CPUs)?

Thanks Qais. Yes, enabling CPS also works around the problem thanks to
that commit.

Cheers
James


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH V2 18/24] irqchip: mips-gic: Stop using per-platform mapping tables
  2015-01-15 16:36         ` Qais Yousef
  (?)
  (?)
@ 2015-01-15 16:58         ` Andrew Bresticker
  2015-01-15 17:25           ` James Hogan
  -1 siblings, 1 reply; 35+ messages in thread
From: Andrew Bresticker @ 2015-01-15 16:58 UTC (permalink / raw)
  To: Qais Yousef
  Cc: James Hogan, Ralf Baechle, Thomas Gleixner, Jason Cooper,
	Jeffrey Deans, Markos Chandras, Paul Burton, Jonas Gorski,
	John Crispin, David Daney, Linux-MIPS, linux-kernel

Hi James, Qais,

On Thu, Jan 15, 2015 at 8:36 AM, Qais Yousef <qais.yousef@imgtec.com> wrote:
> On 01/15/2015 04:29 PM, James Hogan wrote:
>>
>> On 15/01/15 11:59, James Hogan wrote:
>>>
>>> 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@chromium.org>
>>>> Acked-by: Jason Cooper <jason@lakedaemon.net>
>>>> Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
>>>> Tested-by: Qais Yousef <qais.yousef@imgtec.com>
>>>
>>> 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.
>>
>> Right, it appears the CPU IRQ line that the GIC is using doesn't get
>> unmasked (STATUSF_IP2) when a new VPE is brought up, so only the first
>> CPU will actually get any interrupts after your patch (including the
>> rather critical IPIs), i.e. hacking it in vsmp_init_secondary() in
>> smp-mt.c allows it to boot.
>>
>> Hmm, I'll have a think about what the most generic fix is, since
>> arbitrary stuff may or may not have registered handlers for the raw CPU
>> interrupts (timer, performance counter, gic etc)...
>>
>> Cheers
>> James
>>
>
> Is this similar to the issue addressed by this (ff1e29ade4c6 MIPS: smp-cps:
> Enable all hardware interrupts on secondary CPUs)?

I believe so.

James, I think you can apply a similar patch to smp-mt.c:vsmp_init_secondary.

Thanks,
Andrew

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH V2 18/24] irqchip: mips-gic: Stop using per-platform mapping tables
  2015-01-15 16:58         ` Andrew Bresticker
@ 2015-01-15 17:25           ` James Hogan
  0 siblings, 0 replies; 35+ messages in thread
From: James Hogan @ 2015-01-15 17:25 UTC (permalink / raw)
  To: Andrew Bresticker, Qais Yousef
  Cc: Ralf Baechle, Thomas Gleixner, Jason Cooper, Jeffrey Deans,
	Markos Chandras, Paul Burton, Jonas Gorski, John Crispin,
	David Daney, Linux-MIPS, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 3039 bytes --]

On 15/01/15 16:58, Andrew Bresticker wrote:
> Hi James, Qais,
> 
> On Thu, Jan 15, 2015 at 8:36 AM, Qais Yousef <qais.yousef@imgtec.com> wrote:
>> On 01/15/2015 04:29 PM, James Hogan wrote:
>>>
>>> On 15/01/15 11:59, James Hogan wrote:
>>>>
>>>> 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@chromium.org>
>>>>> Acked-by: Jason Cooper <jason@lakedaemon.net>
>>>>> Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
>>>>> Tested-by: Qais Yousef <qais.yousef@imgtec.com>
>>>>
>>>> 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.
>>>
>>> Right, it appears the CPU IRQ line that the GIC is using doesn't get
>>> unmasked (STATUSF_IP2) when a new VPE is brought up, so only the first
>>> CPU will actually get any interrupts after your patch (including the
>>> rather critical IPIs), i.e. hacking it in vsmp_init_secondary() in
>>> smp-mt.c allows it to boot.
>>>
>>> Hmm, I'll have a think about what the most generic fix is, since
>>> arbitrary stuff may or may not have registered handlers for the raw CPU
>>> interrupts (timer, performance counter, gic etc)...
>>>
>>> Cheers
>>> James
>>>
>>
>> Is this similar to the issue addressed by this (ff1e29ade4c6 MIPS: smp-cps:
>> Enable all hardware interrupts on secondary CPUs)?
> 
> I believe so.
> 
> James, I think you can apply a similar patch to smp-mt.c:vsmp_init_secondary.

Yes, I've come to the same conclusion. smp-cmp.c is also affected. I'll
post patches tomorrow.

Thanks
James


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 35+ messages in thread

end of thread, other threads:[~2015-01-15 17:25 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-18 21:47 [PATCH V2 00/24] MIPS GIC cleanup, part 1 Andrew Bresticker
2014-09-18 21:47 ` [PATCH V2 01/24] MIPS: Always use IRQ domains for CPU IRQs Andrew Bresticker
2014-09-18 21:47 ` [PATCH V2 02/24] MIPS: Rename mips_cpu_intc_init() -> mips_cpu_irq_of_init() Andrew Bresticker
2014-09-18 21:47 ` [PATCH V2 03/24] MIPS: Provide a generic plat_irq_dispatch Andrew Bresticker
2014-09-18 21:47 ` [PATCH V2 04/24] MIPS: Set vint handler when mapping CPU interrupts Andrew Bresticker
2014-09-18 21:47 ` [PATCH V2 05/24] MIPS: i8259: Use IRQ domains Andrew Bresticker
2014-09-18 21:47 ` [PATCH V2 06/24] MIPS: Add hook to get C0 performance counter interrupt Andrew Bresticker
2014-09-18 21:47 ` [PATCH V2 07/24] MIPS: smp-cps: Enable all hardware interrupts on secondary CPUs Andrew Bresticker
2014-09-18 21:47 ` [PATCH V2 08/24] MIPS: Remove gic_{enable,disable}_interrupt() Andrew Bresticker
2014-09-18 21:47 ` [PATCH V2 09/24] MIPS: sead3: Remove sead3-serial.c Andrew Bresticker
2014-09-18 21:47 ` [PATCH V2 10/24] MIPS: sead3: Do not overlap CPU/GIC IRQ ranges Andrew Bresticker
2014-09-18 21:47 ` [PATCH V2 11/24] MIPS: Malta: Move MSC01 interrupt base Andrew Bresticker
2014-09-18 21:47 ` [PATCH V2 12/24] MIPS: Move MIPS_GIC_IRQ_BASE into platform irq.h Andrew Bresticker
2014-09-18 21:47 ` [PATCH V2 13/24] MIPS: Move GIC to drivers/irqchip/ Andrew Bresticker
2014-09-18 21:47 ` [PATCH V2 14/24] irqchip: mips-gic: Remove platform irq_ack/irq_eoi callbacks Andrew Bresticker
2014-09-18 21:47 ` [PATCH V2 15/24] irqchip: mips-gic: Implement irq_set_type callback Andrew Bresticker
2014-09-18 21:47 ` [PATCH V2 16/24] irqchip: mips-gic: Fix gic_set_affinity() return value Andrew Bresticker
2014-09-18 21:47 ` [PATCH V2 17/24] irqchip: mips-gic: Use IRQ domains Andrew Bresticker
2014-09-18 21:47 ` [PATCH V2 18/24] irqchip: mips-gic: Stop using per-platform mapping tables Andrew Bresticker
2015-01-15 11:59   ` James Hogan
2015-01-15 11:59     ` James Hogan
2015-01-15 16:29     ` James Hogan
2015-01-15 16:29       ` James Hogan
2015-01-15 16:36       ` Qais Yousef
2015-01-15 16:36         ` Qais Yousef
2015-01-15 16:50         ` James Hogan
2015-01-15 16:50           ` James Hogan
2015-01-15 16:58         ` Andrew Bresticker
2015-01-15 17:25           ` James Hogan
2014-09-18 21:47 ` [PATCH V2 19/24] irqchip: mips-gic: Probe for number of external interrupts Andrew Bresticker
2014-09-18 21:47 ` [PATCH V2 20/24] irqchip: mips-gic: Use separate edge/level irq_chips Andrew Bresticker
2014-09-18 21:47 ` [PATCH V2 21/24] irqchip: mips-gic: Support local interrupts Andrew Bresticker
2014-09-18 21:47 ` [PATCH V2 22/24] irqchip: mips-gic: Remove unnecessary globals Andrew Bresticker
2014-09-18 21:47 ` [PATCH V2 23/24] MIPS: Malta: Use generic plat_irq_dispatch Andrew Bresticker
2014-09-18 21:47 ` [PATCH V2 24/24] MIPS: sead3: " Andrew Bresticker

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.