Skip to contentSkip to conversation

ARM: EXYNOS4: Adds External GIC

PATCH New Changhwan Youn 7 participants 28 messages Jun 20, 2011 – Nov 2, 2011

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover ARM: EXYNOS4: Adds External GIC

This patch adds implementation External GIC on EXYNOS4 SoC.

Note: need to update timer codes for supporting old type of EXYNOS4 SoCs.

[PATCH 1/7] ARM: EXYNOS4: Add external GIC io memory mapping
[PATCH 2/7] ARM: EXYNOS4: modify interrupt mappings for external GIC [PATCH 3/7] ARM: EXYNOS4: set the affinity of mct1 interrupt using IRQ_MCT_L1 [PATCH 4/7] ARM: GIC: move gic_chip_data structure declaration to header [PATCH 5/7] ARM: EXYNOS4: Add support external GIC
[PATCH 6/7] ARM: EXYNOS4: Remove clock event timers using ARM private timers [PATCH 7/7] ARM: EXYNOS4: Add chained enrty/exit function to uart interrupt handler

#1 lore raw

PATCH 1/7 ARM: EXYNOS4: Add external GIC io memory mapping

This patch adds external GIC io memory mapping
to support external GIC on EXYNOS4.

---
 arch/arm/mach-exynos4/cpu.c              |   10 ++++++++++
 arch/arm/mach-exynos4/include/mach/map.h |    5 +++--
 arch/arm/plat-s5p/include/plat/map-s5p.h |    5 +++--
 3 files changed, 16 insertions(+), 4 deletions(-)
arch/arm/mach-exynos4/cpu.c +10 -0
index 1196f39..6a1ed74 100644
@@ -107,6 +107,16 @@ static struct map_desc exynos4_iodesc[] __initdata = {
 		.pfn		= __phys_to_pfn(EXYNOS4_PA_AUDSS),
 		.length		= SZ_1K,
 		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_GIC_CPU,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_GIC_CPU),
+		.length		= SZ_64K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_GIC_DIST,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_GIC_DIST),
+		.length		= SZ_64K,
+		.type		= MT_DEVICE,
 	},
 };
 
arch/arm/mach-exynos4/include/mach/map.h +3 -2
index 57d8074..9d5d797 100644
@@ -61,10 +61,11 @@
 
 #define EXYNOS4_PA_COMBINER		0x10448000
 
+#define EXYNOS4_PA_GIC_CPU		0x10480000
+#define EXYNOS4_PA_GIC_DIST		0x10490000
+
 #define EXYNOS4_PA_COREPERI		0x10500000
-#define EXYNOS4_PA_GIC_CPU		0x10500100
 #define EXYNOS4_PA_TWD			0x10500600
-#define EXYNOS4_PA_GIC_DIST		0x10501000
 #define EXYNOS4_PA_L2CC			0x10502000
 
 #define EXYNOS4_PA_MDMA			0x10810000
arch/arm/plat-s5p/include/plat/map-s5p.h +3 -2
index daa4a44..264df2d 100644
@@ -35,9 +35,10 @@
 #define S5P_VA_COREPERI_BASE	S3C_ADDR(0x02800000)
 #define S5P_VA_COREPERI(x)	(S5P_VA_COREPERI_BASE + (x))
 #define S5P_VA_SCU		S5P_VA_COREPERI(0x0)
-#define S5P_VA_GIC_CPU		S5P_VA_COREPERI(0x100)
 #define S5P_VA_TWD		S5P_VA_COREPERI(0x600)
-#define S5P_VA_GIC_DIST		S5P_VA_COREPERI(0x1000)
+
+#define S5P_VA_GIC_CPU		S3C_ADDR(0x02810000)
+#define S5P_VA_GIC_DIST		S3C_ADDR(0x02820000)
 
 #define S3C_VA_USB_HSPHY	S3C_ADDR(0x02900000)
 #define S5P_VA_AUDSS		S3C_ADDR(0x02A00000)
Signature · 1 line
1.7.1
#2 lore raw

PATCH 1/7 ARM: EXYNOS4: Add external GIC io memory mapping

Quoted 10 lines · Changhwan Youn

This patch adds external GIC io memory mapping
to support external GIC on EXYNOS4.

---

?arch/arm/mach-exynos4/cpu.c ? ? ? ? ? ? ?| ? 10 ++++++++++
?arch/arm/mach-exynos4/include/mach/map.h | ? ?5 +++--
?arch/arm/plat-s5p/include/plat/map-s5p.h | ? ?5 +++--

?3 files changed, 16 insertions(+), 4 deletions(-)

Hello,

It appears that something is missing in the patch series. A patch related with "AUDSS" is required before applying this patch. I get patch fail errors at cpu.c and map-s5p.h.

Cheers!

- MyungJoo

Signature · 5 lines
MyungJoo Ham, Ph.D.
Mobile Software Platform Lab,
Digital Media and Communications (DMC) Business
Samsung Electronics
cell: 82-10-6714-2858
#3 lore raw

PATCH 1/7 ARM: EXYNOS4: Add external GIC io memory mapping

In reply to Changhwan Youn
Quoted 37 lines · Changhwan Youn

This patch adds external GIC io memory mapping
to support external GIC on EXYNOS4.

---

?arch/arm/mach-exynos4/cpu.c ? ? ? ? ? ? ?| ? 10 ++++++++++
?arch/arm/mach-exynos4/include/mach/map.h | ? ?5 +++--
?arch/arm/plat-s5p/include/plat/map-s5p.h | ? ?5 +++--

?3 files changed, 16 insertions(+), 4 deletions(-)

arch/arm/mach-exynos4/cpu.c +10 -0
index 1196f39..6a1ed74 100644
@@ -107,6 +107,16 @@ static struct map_desc exynos4_iodesc[] __initdata = {
 ? ? ? ? ? ? ? ?.pfn ? ? ? ? ? ?= __phys_to_pfn(EXYNOS4_PA_AUDSS),
 ? ? ? ? ? ? ? ?.length ? ? ? ? = SZ_1K,
 ? ? ? ? ? ? ? ?.type ? ? ? ? ? = MT_DEVICE,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .virtual ? ? ? ?= (unsigned long)S5P_VA_GIC_CPU,
+ ? ? ? ? ? ? ? .pfn ? ? ? ? ? ?= __phys_to_pfn(EXYNOS4_PA_GIC_CPU),
+ ? ? ? ? ? ? ? .length ? ? ? ? = SZ_64K,
+ ? ? ? ? ? ? ? .type ? ? ? ? ? = MT_DEVICE,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .virtual ? ? ? ?= (unsigned long)S5P_VA_GIC_DIST,
+ ? ? ? ? ? ? ? .pfn ? ? ? ? ? ?= __phys_to_pfn(EXYNOS4_PA_GIC_DIST),
+ ? ? ? ? ? ? ? .length ? ? ? ? = SZ_64K,
+ ? ? ? ? ? ? ? .type ? ? ? ? ? = MT_DEVICE,
 ? ? ? ?},
 ?};
 
arch/arm/mach-exynos4/include/mach/map.h +0 -0
index 57d8074..9d5d797 100644
@@ -61,10 +61,11 @@
 
Quoted 1 line

?#define EXYNOS4_PA_COMBINER ? ? ? ? ? ?0x10448000

Isn't this 0x10440000 if we are going to use External GIC?

The user manual says it's 0x10440000 for Ext-GIC and 0x10448000 for Internal-GIC.

Signature · 5 lines
MyungJoo Ham, Ph.D.
Mobile Software Platform Lab,
Digital Media and Communications (DMC) Business
Samsung Electronics
cell: 82-10-6714-2858
#4 lore raw

PATCH 1/7 ARM: EXYNOS4: Add external GIC io memory mapping

Quoted 5 lines · MyungJoo Ham
Quoted 2 lines

?#define EXYNOS4_PA_COMBINER ? ? ? ? ? ?0x10448000

Isn't this 0x10440000 if we are going to use External GIC?

Oops, you're right, thanks for your pointing out.
Yes, should be 0x10440000.

When I apply this, I will fix it.

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <[email protected]>, Senior Engineer, SW Solution Development Team, Samsung Electronics Co., Ltd.

#5 lore raw

PATCH 2/7 ARM: EXYNOS4: modify interrupt mappings for external GIC

In reply to Changhwan Youn

To support external GIC needs to update mapping of interrupt number. This patch modifies it for external GIC and accordingly removes the unused code.

---
 arch/arm/mach-exynos4/cpu.c               |    8 --
 arch/arm/mach-exynos4/include/mach/irqs.h |  188 ++++++++++++++---------------
 2 files changed, 93 insertions(+), 103 deletions(-)
arch/arm/mach-exynos4/cpu.c +0 -8
index 6a1ed74..fa33294 100644
@@ -167,14 +167,6 @@ void __init exynos4_init_irq(void)
 
 	for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
 
-		/*
-		 * From SPI(0) to SPI(39) and SPI(51), SPI(53) are
-		 * connected to the interrupt combiner. These irqs
-		 * should be initialized to support cascade interrupt.
-		 */
-		if ((irq >= 40) && !(irq == 51) && !(irq == 53))
-			continue;
-
 		combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
 				COMBINER_IRQ(irq, 0));
 		combiner_cascade_irq(irq, IRQ_SPI(irq));
arch/arm/mach-exynos4/include/mach/irqs.h +93 -95

202 lines not on this page · raw message

Signature · 1 line
1.7.1
#6 lore raw

PATCH 3/7 ARM: EXYNOS4: set the affinity of mct1 interrupt using IRQ_MCT_L1

In reply to Changhwan Youn

IRQ_MCT_L1 is connected directly to GIC in external GIC mapping, while in internal GIC mapping, it is connected to GIC through interrupt combiner. Therfore the affinity for mct1 event timer interrupt should be changed through IRQ_MCT_L1.

---
 arch/arm/mach-exynos4/mct.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
arch/arm/mach-exynos4/mct.c +1 -1
index 14ac10b..1ae059b 100644
@@ -383,8 +383,8 @@ static void exynos4_mct_tick_init(struct clock_event_device *evt)
 		setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq);
 	} else {
 		mct_tick1_event_irq.dev_id = &mct_tick[cpu];
-		irq_set_affinity(IRQ_MCT1, cpumask_of(1));
 		setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq);
+		irq_set_affinity(IRQ_MCT_L1, cpumask_of(1));
 	}
 }
 
Signature · 1 line
1.7.1
#7 lore raw

PATCH 4/7 ARM: GIC: move gic_chip_data structure declaration to header

In reply to Changhwan Youn

Since Samsung EXYNOS4210 cannot support register banking in GIC, so needs to update CPU interface base address.
The 'gic_chip_data' is used for it, this patch moves gic_chip_data structure declaraton to arch/arm/include/asm/hardware/gic.h to use it.

---
 arch/arm/common/gic.c               |    6 ------
 arch/arm/include/asm/hardware/gic.h |    6 ++++++
 2 files changed, 6 insertions(+), 6 deletions(-)
arch/arm/common/gic.c +0 -6
index 4ddd0a6..23564ed 100644
@@ -38,12 +38,6 @@ static DEFINE_SPINLOCK(irq_controller_lock);
 /* Address of GIC 0 CPU interface */
 void __iomem *gic_cpu_base_addr __read_mostly;
 
-struct gic_chip_data {
-	unsigned int irq_offset;
-	void __iomem *dist_base;
-	void __iomem *cpu_base;
-};
-
 /*
  * Supported arch specific GIC irq extension.
  * Default make them NULL.
arch/arm/include/asm/hardware/gic.h +6 -0
index 0691f9d..435d3f8 100644
@@ -41,6 +41,12 @@ void gic_secondary_init(unsigned int);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
 void gic_enable_ppi(unsigned int);
+
+struct gic_chip_data {
+	unsigned int irq_offset;
+	void __iomem *dist_base;
+	void __iomem *cpu_base;
+};
 #endif
 
 #endif
Signature · 1 line
1.7.1
#8 lore raw

PATCH 4/7 ARM: GIC: move gic_chip_data structure declaration to header

Quoted 8 lines · Changhwan Youn

Since Samsung EXYNOS4210 cannot support register banking in GIC, so needs to update CPU interface base address.
The 'gic_chip_data' is used for it, this patch moves gic_chip_data structure declaraton to arch/arm/include/asm/hardware/gic.h to use it.

Cc Russell King <[email protected]>

Russell, how do you think this?

As I know, this is needed on Samsung SoC, EXYNOS4210.

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <[email protected]>, Senior Engineer, SW Solution Development Team, Samsung Electronics Co., Ltd.

Quoted 43 lines
---
 arch/arm/common/gic.c               |    6 ------
 arch/arm/include/asm/hardware/gic.h |    6 ++++++
 2 files changed, 6 insertions(+), 6 deletions(-)
arch/arm/common/gic.c +0 -6
index 4ddd0a6..23564ed 100644
@@ -38,12 +38,6 @@ static DEFINE_SPINLOCK(irq_controller_lock);
 /* Address of GIC 0 CPU interface */
 void __iomem *gic_cpu_base_addr __read_mostly;
 
-struct gic_chip_data {
-	unsigned int irq_offset;
-	void __iomem *dist_base;
-	void __iomem *cpu_base;
-};
-
 /*
  * Supported arch specific GIC irq extension.
  * Default make them NULL.
arch/arm/include/asm/hardware/gic.h +6 -1
index 0691f9d..435d3f8 100644
@@ -41,6 +41,12 @@ void gic_secondary_init(unsigned int);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
 void gic_enable_ppi(unsigned int);
+
+struct gic_chip_data {
+	unsigned int irq_offset;
+	void __iomem *dist_base;
+	void __iomem *cpu_base;
+};
 #endif
 
 #endif
--

1.7.1

#9 lore raw

PATCH 5/7 ARM: EXYNOS4: Add support external GIC

In reply to Changhwan Youn

For full support of power modes, this patch adds implementation external GIC on EXYNOS4.

External GIC of Exynos4 cannot support register banking so several interrupt related code for CPU1 should be different from that of CPU0.

---
 arch/arm/mach-exynos4/cpu.c                      |   10 ++++++++
 arch/arm/mach-exynos4/include/mach/entry-macro.S |    5 ++++
 arch/arm/mach-exynos4/include/mach/map.h         |    1 +
 arch/arm/mach-exynos4/platsmp.c                  |   27 +++++++++++++++++++++-
 4 files changed, 42 insertions(+), 1 deletions(-)
arch/arm/mach-exynos4/cpu.c +10 -0
index fa33294..40a866c 100644
@@ -16,6 +16,7 @@
 
 #include <asm/proc-fns.h>
 #include <asm/hardware/cache-l2x0.h>
+#include <asm/hardware/gic.h>
 
 #include <plat/cpu.h>
 #include <plat/clock.h>
@@ -159,11 +160,20 @@ void __init exynos4_init_clocks(int xtal)
 	exynos4_setup_clocks();
 }
 
+static void exynos4_gic_irq_eoi(struct irq_data *d)
+{
+	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
+
+	gic_data->cpu_base = S5P_VA_GIC_CPU +
+			    (EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
+}
+
 void __init exynos4_init_irq(void)
 {
 	int irq;
 
 	gic_init(0, IRQ_LOCALTIMER, S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+	gic_arch_extn.irq_eoi = exynos4_gic_irq_eoi;
 
 	for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
 
arch/arm/mach-exynos4/include/mach/entry-macro.S +5 -0
index d8f38c2..4fad076 100644
@@ -10,6 +10,7 @@
 */
 
 #include <mach/hardware.h>
+#include <mach/map.h>
 #include <asm/hardware/gic.h>
 
 		.macro	disable_fiq
@@ -18,6 +19,10 @@
 		.macro  get_irqnr_preamble, base, tmp
 		ldr	\base, =gic_cpu_base_addr
 		ldr	\base, [\base]
+		mrc     p15, 0, \tmp, c0, c0, 5
+		and     \tmp, \tmp, #3
+		cmp     \tmp, #1
+		addeq   \base, \base, #EXYNOS4_GIC_BANK_OFFSET
 		.endm
 
 		.macro  arch_ret_to_user, tmp1, tmp2
arch/arm/mach-exynos4/include/mach/map.h +1 -0
index 9d5d797..2339a70 100644
@@ -63,6 +63,7 @@
 
 #define EXYNOS4_PA_GIC_CPU		0x10480000
 #define EXYNOS4_PA_GIC_DIST		0x10490000
+#define EXYNOS4_GIC_BANK_OFFSET		0x8000
 
 #define EXYNOS4_PA_COREPERI		0x10500000
 #define EXYNOS4_PA_TWD			0x10500600
arch/arm/mach-exynos4/platsmp.c +26 -1
index c5e65a0..decf528 100644
@@ -58,6 +58,31 @@ static void __iomem *scu_base_addr(void)
 
 static DEFINE_SPINLOCK(boot_lock);
 
+static void __cpuinit exynos4_gic_secondary_init(void)
+{
+	void __iomem *dist_base = S5P_VA_GIC_DIST +
+				 (EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
+	void __iomem *cpu_base = S5P_VA_GIC_CPU +
+				(EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
+	int i;
+
+	/*
+	 * Deal with the banked PPI and SGI interrupts - disable all
+	 * PPI interrupts, ensure all SGI interrupts are enabled.
+	 */
+	__raw_writel(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR);
+	__raw_writel(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET);
+
+	/*
+	 * Set priority on PPI and SGI interrupts
+	 */
+	for (i = 0; i < 32; i += 4)
+		__raw_writel(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4);
+
+	__raw_writel(0xf0, cpu_base + GIC_CPU_PRIMASK);
+	__raw_writel(1, cpu_base + GIC_CPU_CTRL);
+}
+
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
 	/*
@@ -65,7 +90,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
 	 * core (e.g. timer irq), then they will not have been enabled
 	 * for us: do so
 	 */
-	gic_secondary_init(0);
+	exynos4_gic_secondary_init();
 
 	/*
 	 * let the primary processor know we're out of the
Signature · 1 line
1.7.1
#10 lore raw

PATCH 5/7 ARM: EXYNOS4: Add support external GIC

Hi Changhwan,

Quoted 6 lines · Changhwan Youn

For full support of power modes, this patch adds implementation external GIC on EXYNOS4.

External GIC of Exynos4 cannot support register banking so several interrupt related code for CPU1 should be different from that of CPU0.

I just realized that patch has made it to mainline... Unfortunately, it seems quite broken to me:

Quoted 21 lines
---
 arch/arm/mach-exynos4/cpu.c                      |   10 ++++++++
 arch/arm/mach-exynos4/include/mach/entry-macro.S |    5 ++++
 arch/arm/mach-exynos4/include/mach/map.h         |    1 +
 arch/arm/mach-exynos4/platsmp.c                  |   27 +++++++++++++++++++++-
 4 files changed, 42 insertions(+), 1 deletions(-)
arch/arm/mach-exynos4/cpu.c +1 -0
index fa33294..40a866c 100644
@@ -16,6 +16,7 @@
 
 #include <asm/proc-fns.h>
 #include <asm/hardware/cache-l2x0.h>
+#include <asm/hardware/gic.h>
 
 #include <plat/cpu.h>
 #include <plat/clock.h>

arch/arm/mach-exynos4/cpu.c void __init exynos4_init_clocks(int xtal) · line 168

Quoted 9 lines
arch/arm/mach-exynos4/cpu.c +6 -0
@@ -159,11 +160,20 @@ void __init exynos4_init_clocks(int xtal)
 	exynos4_setup_clocks();
 }
 
+static void exynos4_gic_irq_eoi(struct irq_data *d)
+{
+	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
+
+	gic_data->cpu_base = S5P_VA_GIC_CPU +
+			    (EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());

Here, you're overwriting a field that is shared among *all* the interrupts in the system. What if an interrupt comes up on another CPU? If you look at the implementation of gic_eoi_irq(), you'll definitely see the race.

arch/arm/mach-exynos4/cpu.c void __init exynos4_init_clocks(int xtal) · line 176

Quoted 8 lines
arch/arm/mach-exynos4/cpu.c +3 -0
+}
+
 void __init exynos4_init_irq(void)
 {
 	int irq;
 
 	gic_init(0, IRQ_LOCALTIMER, S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+	gic_arch_extn.irq_eoi = exynos4_gic_irq_eoi;

And here you're abusing the GIC extension feature.

I've also had a look at -next, and this has been extended further to support 4412. The problem with that is without banking, you're painfully working around the GIC driver. At that stage, I wonder if you wouldn't be better off with a separate driver instead of abusing the existing one...

	M.
Signature · 1 line
Jazz is not dead. It just smells funny...
#11 lore raw

PATCH 5/7 ARM: EXYNOS4: Add support external GIC

Quoted 3 lines · Marc Zyngier

Hi Changhwan,

Hi Marc,

(Cc'ed Will Deacon and Russell King)

Quoted 44 lines · Changhwan Youn
Quoted 6 lines

For full support of power modes, this patch adds implementation external GIC on EXYNOS4.

External GIC of Exynos4 cannot support register banking so several interrupt related code for CPU1 should be different from that of CPU0.

I just realized that patch has made it to mainline... Unfortunately, it seems quite broken to me:

Quoted 6 lines
---
 arch/arm/mach-exynos4/cpu.c                      |   10 ++++++++
 arch/arm/mach-exynos4/include/mach/entry-macro.S |    5 ++++
 arch/arm/mach-exynos4/include/mach/map.h         |    1 +
 arch/arm/mach-exynos4/platsmp.c                  |   27

+++++++++++++++++++++-

Quoted 15 lines
 4 files changed, 42 insertions(+), 1 deletions(-)
arch/arm/mach-exynos4/cpu.c +1 -0
index fa33294..40a866c 100644
@@ -16,6 +16,7 @@
 
 #include <asm/proc-fns.h>
 #include <asm/hardware/cache-l2x0.h>
+#include <asm/hardware/gic.h>
 
 #include <plat/cpu.h>
 #include <plat/clock.h>

arch/arm/mach-exynos4/cpu.c void __init exynos4_init_clocks(int xtal) · line 168

Quoted 9 lines
arch/arm/mach-exynos4/cpu.c +6 -0
@@ -159,11 +160,20 @@ void __init exynos4_init_clocks(int xtal)
 	exynos4_setup_clocks();
 }
 
+static void exynos4_gic_irq_eoi(struct irq_data *d)
+{
+	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
+
+	gic_data->cpu_base = S5P_VA_GIC_CPU +
+			    (EXYNOS4_GIC_BANK_OFFSET *

smp_processor_id());

Quoted 5 lines

Here, you're overwriting a field that is shared among *all* the interrupts in the system. What if an interrupt comes up on another CPU? If you look at the implementation of gic_eoi_irq(), you'll definitely see the race.

Hmm...as you can see in git log, the EXYNOS4210 cannot support register banking in GIC so this is needed.

Quoted 11 lines

arch/arm/mach-exynos4/cpu.c void __init exynos4_init_clocks(int xtal) · line 176

Quoted 8 lines
arch/arm/mach-exynos4/cpu.c +3 -0
+}
+
 void __init exynos4_init_irq(void)
 {
 	int irq;
 
 	gic_init(0, IRQ_LOCALTIMER, S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+	gic_arch_extn.irq_eoi = exynos4_gic_irq_eoi;

And here you're abusing the GIC extension feature.

I think gic_arch_extn.irq_eoi can be overwritten in each architecture to support own specific extensions like in the EXYNOS4 case.

Quoted 4 lines

I've also had a look at -next, and this has been extended further to support 4412. The problem with that is without banking, you're painfully working around the GIC driver. At that stage, I wonder if you wouldn't be better off with a separate driver instead of abusing the existing

one...

Quoted 1 line

Well, in this case, you mean separate driver is better to us even though there is a gic driver in arch/arm/common? I don't think so because separate driver will probably have many duplicated codes and if common gic driver can support every silicons which have different version's gic it's better to us and should do.

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <[email protected]>, Senior Engineer, SW Solution Development Team, Samsung Electronics Co., Ltd.

#12 lore raw

PATCH 5/7 ARM: EXYNOS4: Add support external GIC

Quoted 52 lines · Kukjin Kim
Quoted 3 lines · Marc Zyngier

Hi Changhwan,

Hi Marc,

(Cc'ed Will Deacon and Russell King)

Quoted 44 lines · Changhwan Youn
Quoted 6 lines

For full support of power modes, this patch adds implementation external GIC on EXYNOS4.

External GIC of Exynos4 cannot support register banking so several interrupt related code for CPU1 should be different from that of CPU0.

I just realized that patch has made it to mainline... Unfortunately, it seems quite broken to me:

Quoted 6 lines
---
 arch/arm/mach-exynos4/cpu.c                      |   10 ++++++++
 arch/arm/mach-exynos4/include/mach/entry-macro.S |    5 ++++
 arch/arm/mach-exynos4/include/mach/map.h         |    1 +
 arch/arm/mach-exynos4/platsmp.c                  |   27

+++++++++++++++++++++-

Quoted 15 lines
 4 files changed, 42 insertions(+), 1 deletions(-)
arch/arm/mach-exynos4/cpu.c +1 -0
index fa33294..40a866c 100644
@@ -16,6 +16,7 @@
 
 #include <asm/proc-fns.h>
 #include <asm/hardware/cache-l2x0.h>
+#include <asm/hardware/gic.h>
 
 #include <plat/cpu.h>
 #include <plat/clock.h>

arch/arm/mach-exynos4/cpu.c void __init exynos4_init_clocks(int xtal) · line 168

Quoted 9 lines
arch/arm/mach-exynos4/cpu.c +6 -0
@@ -159,11 +160,20 @@ void __init exynos4_init_clocks(int xtal)
 	exynos4_setup_clocks();
 }
 
+static void exynos4_gic_irq_eoi(struct irq_data *d)
+{
+	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
+
+	gic_data->cpu_base = S5P_VA_GIC_CPU +
+			    (EXYNOS4_GIC_BANK_OFFSET *

smp_processor_id());

Quoted 7 lines
Quoted 5 lines

Here, you're overwriting a field that is shared among *all* the interrupts in the system. What if an interrupt comes up on another CPU? If you look at the implementation of gic_eoi_irq(), you'll definitely see the race.

Hmm...as you can see in git log, the EXYNOS4210 cannot support register banking in GIC so this is needed.

I don't dispute the need. I claim that the implementation is wrong, and will fail given the right timings.

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
arch/arm/mach-exynos4/cpu.c +2 -0
+}
+
 void __init exynos4_init_irq(void)
 {
 	int irq;
 
Quoted 7 lines
Quoted 5 lines

arch/arm/mach-exynos4/cpu.c void __init exynos4_init_clocks(int xtal) · line 176

Quoted 2 lines
arch/arm/mach-exynos4/cpu.c +1 -0
 	gic_init(0, IRQ_LOCALTIMER, S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+	gic_arch_extn.irq_eoi = exynos4_gic_irq_eoi;

And here you're abusing the GIC extension feature.

I think gic_arch_extn.irq_eoi can be overwritten in each architecture to support own specific extensions like in the EXYNOS4 case.

Sure. My point is you are diverting the GIC extension from its purpose, which is mostly to be able to control wake-up sources (as for example in the Tegra case). Here, you use this hooks to work around the fact that the GIC driver is written with banking in mind, which is quite a different thing.

Quoted 11 lines
Quoted 4 lines

I've also had a look at -next, and this has been extended further to support 4412. The problem with that is without banking, you're painfully working around the GIC driver. At that stage, I wonder if you wouldn't be better off with a separate driver instead of abusing the existing

one...

Quoted 1 line

Well, in this case, you mean separate driver is better to us even though there is a gic driver in arch/arm/common? I don't think so because separate driver will probably have many duplicated codes and if common gic driver can support every silicons which have different version's gic it's better to us and should do.

If you really insist on using the GIC common code, then I'd suggest to adapt it to your needs instead of working around the problem. What about making cpu_base a percpu field inside struct gic_chip_data? No hook abuse, and no race conditions. You could also do that for dist_base, as it looks to be required for the 4412.

Cheers,

	M.
Signature · 1 line
Jazz is not dead. It just smells funny...
#13 lore raw

PATCH 5/7 ARM: EXYNOS4: Add support external GIC

Quoted 96 lines · Marc Zyngier
Quoted 52 lines · Kukjin Kim
Quoted 3 lines · Marc Zyngier

Hi Changhwan,

Hi Marc,

(Cc'ed Will Deacon and Russell King)

Quoted 44 lines · Changhwan Youn
Quoted 6 lines

For full support of power modes, this patch adds implementation external GIC on EXYNOS4.

External GIC of Exynos4 cannot support register banking so several interrupt related code for CPU1 should be different from that of CPU0.

I just realized that patch has made it to mainline... Unfortunately, it seems quite broken to me:

Quoted 6 lines
---
 arch/arm/mach-exynos4/cpu.c                      |   10 ++++++++
 arch/arm/mach-exynos4/include/mach/entry-macro.S |    5 ++++
 arch/arm/mach-exynos4/include/mach/map.h         |    1 +
 arch/arm/mach-exynos4/platsmp.c                  |   27

+++++++++++++++++++++-

Quoted 15 lines
 4 files changed, 42 insertions(+), 1 deletions(-)
arch/arm/mach-exynos4/cpu.c +1 -0
index fa33294..40a866c 100644
@@ -16,6 +16,7 @@
 
 #include <asm/proc-fns.h>
 #include <asm/hardware/cache-l2x0.h>
+#include <asm/hardware/gic.h>
 
 #include <plat/cpu.h>
 #include <plat/clock.h>

arch/arm/mach-exynos4/cpu.c void __init exynos4_init_clocks(int xtal) · line 168

Quoted 9 lines
arch/arm/mach-exynos4/cpu.c +6 -0
@@ -159,11 +160,20 @@ void __init exynos4_init_clocks(int xtal)
 	exynos4_setup_clocks();
 }
 
+static void exynos4_gic_irq_eoi(struct irq_data *d)
+{
+	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
+
+	gic_data->cpu_base = S5P_VA_GIC_CPU +
+			    (EXYNOS4_GIC_BANK_OFFSET *

smp_processor_id());

Quoted 7 lines
Quoted 5 lines

Here, you're overwriting a field that is shared among *all* the interrupts in the system. What if an interrupt comes up on another CPU? If you look at the implementation of gic_eoi_irq(), you'll definitely see the race.

Hmm...as you can see in git log, the EXYNOS4210 cannot support register banking in GIC so this is needed.

I don't dispute the need. I claim that the implementation is wrong, and will fail given the right timings.

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
arch/arm/mach-exynos4/cpu.c +2 -0
+}
+
 void __init exynos4_init_irq(void)
 {
 	int irq;
 
Quoted 7 lines
Quoted 5 lines

arch/arm/mach-exynos4/cpu.c void __init exynos4_init_clocks(int xtal) · line 176

Quoted 2 lines
arch/arm/mach-exynos4/cpu.c +1 -0
 	gic_init(0, IRQ_LOCALTIMER, S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+	gic_arch_extn.irq_eoi = exynos4_gic_irq_eoi;

And here you're abusing the GIC extension feature.

I think gic_arch_extn.irq_eoi can be overwritten in each architecture to support own specific extensions like in the EXYNOS4 case.

Sure. My point is you are diverting the GIC extension from its purpose, which is mostly to be able to control wake-up sources (as for example in the Tegra case). Here, you use this hooks to work around the fact that the GIC driver is written with banking in mind, which is quite a different thing.

Quoted 11 lines
Quoted 4 lines

I've also had a look at -next, and this has been extended further to support 4412. The problem with that is without banking, you're painfully working around the GIC driver. At that stage, I wonder if you wouldn't be better off with a separate driver instead of abusing the existing

one...

Quoted 1 line

Well, in this case, you mean separate driver is better to us even though there is a gic driver in arch/arm/common? I don't think so because separate driver will probably have many duplicated codes and if common gic driver can support every silicons which have different version's gic it's better to us and should do.

Quoted 5 lines

If you really insist on using the GIC common code, then I'd suggest to adapt it to your needs instead of working around the problem. What about making cpu_base a percpu field inside struct gic_chip_data? No hook abuse, and no race conditions. You could also do that for dist_base, as it looks to be required for the 4412.

So to make my suggestion completely clear, here's a patch I'm now carrying in my tree. It's only been test compiled on EXYNOS4, but works nicely on my 11MP. It turns both dist_base and cpu_base into per-cpu variables, removes these callbacks, removes your private copy of gic_cpu_init, and makes struct gic_chip_data private again.

What do you think?

	M.
Signature · 1 line
Jazz is not dead. It just smells funny...
Quoted 1 line

From da57c3979543fcef47f1ae22b5224a1d7a96aa2d Mon Sep 17 00:00:00 2001

From: Marc Zyngier <[email protected]>
Date: Fri, 7 Oct 2011 10:23:31 +0100
Subject: [PATCH] ARM: gic: allow GIC to support non-banked setups

The GIC support code is heavily using the fact that hardware implementations are exposing banked registers. Unfortunately, it looks like at least one GIC implementation (EXYNOS4) offers both the distributor and the CPU interfaces at different addresses, depending on the CPU.

This problem is solved by turning the distributor and CPU interface addresses into per-cpu variables. The EXYNOS4 code is updated not to mess with the GIC internals while handling interrupts, and struct gic_chip_data is back to being private.

---
 arch/arm/common/gic.c               |   76 +++++++++++++++++++++++++++--------
 arch/arm/include/asm/hardware/gic.h |   17 +------
 arch/arm/mach-exynos4/cpu.c         |   14 ------
 arch/arm/mach-exynos4/platsmp.c     |   28 ++-----------
 4 files changed, 66 insertions(+), 69 deletions(-)
arch/arm/common/gic.c +59 -17
index b574931..c7521dd 100644
@@ -37,6 +37,20 @@
 #include <asm/mach/irq.h>
 #include <asm/hardware/gic.h>
 
+struct gic_chip_data {
+	unsigned int irq_offset;
+	void __percpu __iomem **dist_base;
+	void __percpu __iomem **cpu_base;
+#ifdef CONFIG_CPU_PM
+	u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)];
+	u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)];
+	u32 saved_spi_target[DIV_ROUND_UP(1020, 4)];
+	u32 __percpu *saved_ppi_enable;
+	u32 __percpu *saved_ppi_conf;
+#endif
+	unsigned int gic_irqs;
+};
+
 static DEFINE_RAW_SPINLOCK(irq_controller_lock);
 
 /* Address of GIC 0 CPU interface */
@@ -61,16 +75,26 @@ struct irq_chip gic_arch_extn = {
 
 static struct gic_chip_data gic_data[MAX_GIC_NR] __read_mostly;
 
+static inline void __iomem *gic_data_dist_base(struct gic_chip_data *data)
+{
+	return *__this_cpu_ptr(data->dist_base);
+}
+
 static inline void __iomem *gic_dist_base(struct irq_data *d)
 {
 	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
-	return gic_data->dist_base;
+	return gic_data_dist_base(gic_data);
+}
+
+static inline void __iomem *gic_data_cpu_base(struct gic_chip_data *data)
+{
+	return *__this_cpu_ptr(data->cpu_base);
 }
 
 static inline void __iomem *gic_cpu_base(struct irq_data *d)
 {
 	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
-	return gic_data->cpu_base;
+	return gic_data_cpu_base(gic_data);
 }
 
 static inline unsigned int gic_irq(struct irq_data *d)
@@ -243,7 +267,7 @@ static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
 	chained_irq_enter(chip, desc);
 
 	raw_spin_lock(&irq_controller_lock);
-	status = readl_relaxed(chip_data->cpu_base + GIC_CPU_INTACK);
+	status = readl_relaxed(gic_data_cpu_base(chip_data) + GIC_CPU_INTACK);
 	raw_spin_unlock(&irq_controller_lock);
 
 	gic_irq = (status & 0x3ff);
@@ -287,7 +311,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
 {
 	unsigned int gic_irqs, irq_limit, i;
 	u32 cpumask;
-	void __iomem *base = gic->dist_base;
+	void __iomem *base = gic_data_dist_base(gic);
 	u32 cpu = 0;
 	u32 nrppis = 0, ppi_base = 0;
 
@@ -380,8 +404,8 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
 
 static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
 {
-	void __iomem *dist_base = gic->dist_base;
-	void __iomem *base = gic->cpu_base;
+	void __iomem *dist_base = gic_data_dist_base(gic);
+	void __iomem *base = gic_data_cpu_base(gic);
 	int i;
 
 	/*
@@ -418,7 +442,7 @@ static void gic_dist_save(unsigned int gic_nr)
 		BUG();
 
 	gic_irqs = gic_data[gic_nr].gic_irqs;
-	dist_base = gic_data[gic_nr].dist_base;
+	dist_base = gic_data_dist_base(&gic_data[gic_nr]);
 
 	if (!dist_base)
 		return;
@@ -453,7 +477,7 @@ static void gic_dist_restore(unsigned int gic_nr)
 		BUG();
 
 	gic_irqs = gic_data[gic_nr].gic_irqs;
-	dist_base = gic_data[gic_nr].dist_base;
+	dist_base = gic_data_dist_base(&gic_data[gic_nr]);
 
 	if (!dist_base)
 		return;
@@ -489,8 +513,8 @@ static void gic_cpu_save(unsigned int gic_nr)
 	if (gic_nr >= MAX_GIC_NR)
 		BUG();
 
-	dist_base = gic_data[gic_nr].dist_base;
-	cpu_base = gic_data[gic_nr].cpu_base;
+	dist_base = gic_data_dist_base(&gic_data[gic_nr]);
+	cpu_base = gic_data_cpu_base(&gic_data[gic_nr]);
 
 	if (!dist_base || !cpu_base)
 		return;
@@ -515,8 +539,8 @@ static void gic_cpu_restore(unsigned int gic_nr)
 	if (gic_nr >= MAX_GIC_NR)
 		BUG();
 
-	dist_base = gic_data[gic_nr].dist_base;
-	cpu_base = gic_data[gic_nr].cpu_base;
+	dist_base = gic_data_dist_base(&gic_data[gic_nr]);
+	cpu_base = gic_data_cpu_base(&gic_data[gic_nr]);
 
 	if (!dist_base || !cpu_base)
 		return;
@@ -588,12 +612,24 @@ void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
 	void __iomem *dist_base, void __iomem *cpu_base)
 {
 	struct gic_chip_data *gic;
+	int cpu;
 
 	BUG_ON(gic_nr >= MAX_GIC_NR);
 
 	gic = &gic_data[gic_nr];
-	gic->dist_base = dist_base;
-	gic->cpu_base = cpu_base;
+	gic->dist_base = alloc_percpu(void __iomem *);
+	gic->cpu_base = alloc_percpu(void __iomem *);
+	if (WARN_ON(!gic->dist_base || !gic->cpu_base)) {
+		free_percpu(gic->dist_base);
+		free_percpu(gic->cpu_base);
+		return;
+	}
+
+	for_each_possible_cpu(cpu) {
+		*per_cpu_ptr(gic->dist_base, cpu) = dist_base;
+		*per_cpu_ptr(gic->cpu_base, cpu) = cpu_base;
+	}
+
 	gic->irq_offset = (irq_start - 1) & ~31;
 
 	if (gic_nr == 0)
@@ -605,11 +641,17 @@ void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
 	gic_pm_init(gic);
 }
 
-void __cpuinit gic_secondary_init(unsigned int gic_nr)
+void __cpuinit gic_secondary_init_base(unsigned int gic_nr,
+				       void __iomem *dist_base,
+				       void __iomem *cpu_base)
 {
 	BUG_ON(gic_nr >= MAX_GIC_NR);
 
-	gic_cpu_init(&gic_data[gic_nr]);
+	if (dist_base)
+		*__this_cpu_ptr(gic_data[gic_nr].dist_base) = dist_base;
+	if (cpu_base)
+		*__this_cpu_ptr(gic_data[gic_nr].cpu_base) = cpu_base;
+	gic_cpu_init(&gic_data[gic_nr]);	
 }
 
 #ifdef CONFIG_SMP
@@ -629,6 +671,6 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 	dsb();
 
 	/* this always happens on GIC0 */
-	writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
+	writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
 }
 #endif
arch/arm/include/asm/hardware/gic.h +3 -14
index 2b7ec2b..d45d78b 100644
@@ -36,24 +36,13 @@
 extern struct irq_chip gic_arch_extn;
 
 void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
-void gic_secondary_init(unsigned int);
+void gic_secondary_init_base(unsigned int, void __iomem *, void __iomem *);
 void gic_handle_irq(struct pt_regs *regs);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
 
-struct gic_chip_data {
-	unsigned int irq_offset;
-	void __iomem *dist_base;
-	void __iomem *cpu_base;
-#ifdef CONFIG_CPU_PM
-	u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)];
-	u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)];
-	u32 saved_spi_target[DIV_ROUND_UP(1020, 4)];
-	u32 __percpu *saved_ppi_enable;
-	u32 __percpu *saved_ppi_conf;
-#endif
-	unsigned int gic_irqs;
-};
+#define gic_secondary_init(n)	gic_secondary_init_base((n), NULL, NULL)
+
 #endif
 
 #endif
arch/arm/mach-exynos4/cpu.c +0 -14
index c682887..09e2760 100644
@@ -204,17 +204,6 @@ void __init exynos4_init_clocks(int xtal)
 	exynos4_setup_clocks();
 }
 
-static void exynos4_gic_irq_fix_base(struct irq_data *d)
-{
-	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
-
-	gic_data->cpu_base = S5P_VA_GIC_CPU +
-			    (gic_bank_offset * smp_processor_id());
-
-	gic_data->dist_base = S5P_VA_GIC_DIST +
-			    (gic_bank_offset * smp_processor_id());
-}
-
 void __init exynos4_init_irq(void)
 {
 	int irq;
@@ -222,9 +211,6 @@ void __init exynos4_init_irq(void)
 	gic_bank_offset = soc_is_exynos4412() ? 0x4000 : 0x8000;
 
 	gic_init(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
-	gic_arch_extn.irq_eoi = exynos4_gic_irq_fix_base;
-	gic_arch_extn.irq_unmask = exynos4_gic_irq_fix_base;
-	gic_arch_extn.irq_mask = exynos4_gic_irq_fix_base;
 
 	for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
 
arch/arm/mach-exynos4/platsmp.c +4 -24
index 56377d2..76cb2ba 100644
@@ -67,39 +67,19 @@ static void __iomem *scu_base_addr(void)
 
 static DEFINE_SPINLOCK(boot_lock);
 
-static void __cpuinit exynos4_gic_secondary_init(void)
+static void __cpuinit exynos4_secondary_init(unsigned int cpu)
 {
 	void __iomem *dist_base = S5P_VA_GIC_DIST +
-				(gic_bank_offset * smp_processor_id());
+				(gic_bank_offset * cpu_logical_map(cpu));
 	void __iomem *cpu_base = S5P_VA_GIC_CPU +
-				(gic_bank_offset * smp_processor_id());
-	int i;
-
-	/*
-	 * Deal with the banked PPI and SGI interrupts - disable all
-	 * PPI interrupts, ensure all SGI interrupts are enabled.
-	 */
-	__raw_writel(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR);
-	__raw_writel(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET);
+				(gic_bank_offset * cpu_logical_map(cpu));
 
 	/*
-	 * Set priority on PPI and SGI interrupts
-	 */
-	for (i = 0; i < 32; i += 4)
-		__raw_writel(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4);
-
-	__raw_writel(0xf0, cpu_base + GIC_CPU_PRIMASK);
-	__raw_writel(1, cpu_base + GIC_CPU_CTRL);
-}
-
-static void __cpuinit exynos4_secondary_init(unsigned int cpu)
-{
-	/*
 	 * if any interrupts are already enabled for the primary
 	 * core (e.g. timer irq), then they will not have been enabled
 	 * for us: do so
 	 */
-	exynos4_gic_secondary_init();
+	gic_secondary_init_base(0, dist_base, cpu_base);
 
 	/*
 	 * let the primary processor know we're out of the
Signature · 1 line
1.7.0.4
#14 lore raw

PATCH 5/7 ARM: EXYNOS4: Add support external GIC

Quoted 12 lines · Marc Zyngier
Quoted 10 lines · Marc Zyngier
Quoted 9 lines · Kukjin Kim
Quoted 3 lines · Marc Zyngier

Hi Changhwan,

Hi Marc,

(Cc'ed Will Deacon and Russell King)

Quoted 1 line · Changhwan Youn
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 6 lines

For full support of power modes, this patch adds implementation external GIC on EXYNOS4.

External GIC of Exynos4 cannot support register banking so several interrupt related code for CPU1 should be different from that of CPU0.

I just realized that patch has made it to mainline... Unfortunately,

it

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

seems quite broken to me:

Quoted 6 lines
---
 arch/arm/mach-exynos4/cpu.c                      |   10 ++++++++
 arch/arm/mach-exynos4/include/mach/entry-macro.S |    5 ++++
 arch/arm/mach-exynos4/include/mach/map.h         |    1 +
 arch/arm/mach-exynos4/platsmp.c                  |   27
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines

+++++++++++++++++++++-

Review

Quoted 3 lines
 4 files changed, 42 insertions(+), 1 deletions(-)
(quoted diff) +0 -0

b/arch/arm/mach-exynos4/cpu.c

Quoted 15 lines
Quoted 15 lines
Quoted 15 lines
Quoted 15 lines
Quoted 15 lines

index fa33294..40a866c 100644

arch/arm/mach-exynos4/cpu.c +1 -0
@@ -16,6 +16,7 @@
 
 #include <asm/proc-fns.h>
 #include <asm/hardware/cache-l2x0.h>
+#include <asm/hardware/gic.h>
 
 #include <plat/cpu.h>
 #include <plat/clock.h>
@@ -159,11 +160,20 @@ void __init exynos4_init_clocks(int xtal)
 	exynos4_setup_clocks();
 }
 
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

arch/arm/mach-exynos4/cpu.c void __init exynos4_init_clocks(int xtal)

Quoted 3 lines
arch/arm/mach-exynos4/cpu.c +3 -0
+static void exynos4_gic_irq_eoi(struct irq_data *d)
+{
+	struct gic_chip_data *gic_data =

irq_data_get_irq_chip_data(d);

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

arch/arm/mach-exynos4/cpu.c void __init exynos4_init_clocks(int xtal)

Quoted 3 lines
arch/arm/mach-exynos4/cpu.c +3 -0
+
+	gic_data->cpu_base = S5P_VA_GIC_CPU +
+			    (EXYNOS4_GIC_BANK_OFFSET *

smp_processor_id());

Here, you're overwriting a field that is shared among *all* the interrupts in the system. What if an interrupt comes up on another

CPU?

Quoted 9 lines
Quoted 9 lines
Quoted 5 lines
Quoted 3 lines

If you look at the implementation of gic_eoi_irq(), you'll definitely see the race.

Hmm...as you can see in git log, the EXYNOS4210 cannot support register banking in GIC so this is needed.

I don't dispute the need. I claim that the implementation is wrong, and will fail given the right timings.

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

arch/arm/mach-exynos4/cpu.c void __init exynos4_init_clocks(int xtal)

Quoted 7 lines
arch/arm/mach-exynos4/cpu.c +2 -0
+}
+
 void __init exynos4_init_irq(void)
 {
 	int irq;
 
 	gic_init(0, IRQ_LOCALTIMER, S5P_VA_GIC_DIST,

S5P_VA_GIC_CPU);

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 4 lines

arch/arm/mach-exynos4/cpu.c void __init exynos4_init_clocks(int xtal) · line 176

Quoted 1 line
arch/arm/mach-exynos4/cpu.c +1 -0
+	gic_arch_extn.irq_eoi = exynos4_gic_irq_eoi;

And here you're abusing the GIC extension feature.

I think gic_arch_extn.irq_eoi can be overwritten in each architecture

to

Quoted 10 lines
Quoted 10 lines
Quoted 1 line

support own specific extensions like in the EXYNOS4 case.

Sure. My point is you are diverting the GIC extension from its purpose, which is mostly to be able to control wake-up sources (as for example in the Tegra case). Here, you use this hooks to work around the fact that the GIC driver is written with banking in mind, which is quite a different thing.

Quoted 2 lines
Quoted 2 lines

I've also had a look at -next, and this has been extended further to support 4412. The problem with that is without banking, you're

painfully

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 2 lines

working around the GIC driver. At that stage, I wonder if you wouldn't be better off with a separate driver instead of abusing the existing

one...

Quoted 1 line

Well, in this case, you mean separate driver is better to us even

though

Quoted 1 line
Quoted 1 line
Quoted 1 line

there is a gic driver in arch/arm/common? I don't think so because

separate

Quoted 1 line
Quoted 1 line
Quoted 1 line

driver will probably have many duplicated codes and if common gic

driver can

Quoted 1 line
Quoted 1 line
Quoted 1 line

support every silicons which have different version's gic it's better

to us

Quoted 8 lines
Quoted 7 lines
Quoted 1 line

and should do.

If you really insist on using the GIC common code, then I'd suggest to adapt it to your needs instead of working around the problem. What about making cpu_base a percpu field inside struct gic_chip_data? No hook abuse, and no race conditions. You could also do that for dist_base, as it looks to be required for the 4412.

Quoted 7 lines

So to make my suggestion completely clear, here's a patch I'm now carrying in my tree. It's only been test compiled on EXYNOS4, but works nicely on my 11MP. It turns both dist_base and cpu_base into per-cpu variables, removes these callbacks, removes your private copy of gic_cpu_init, and makes struct gic_chip_data private again.

What do you think?

Let me check this soon. Actually I need to sort this out to test on my board with my git.

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <[email protected]>, Senior Engineer, SW Solution Development Team, Samsung Electronics Co., Ltd.

#15 lore raw

PATCH 5/7 ARM: EXYNOS4: Add support external GIC

In reply to Marc Zyngier

Hi Marc,

Quoted 7 lines · Marc Zyngier

So to make my suggestion completely clear, here's a patch I'm now carrying in my tree. It's only been test compiled on EXYNOS4, but works nicely on my 11MP. It turns both dist_base and cpu_base into per-cpu variables, removes these callbacks, removes your private copy of gic_cpu_init, and makes struct gic_chip_data private again.

What do you think?

This looks like the right sort of idea, although I'm deeply suspicious about per-cpu base addresses for the GIC distributor. It would be nice if the Samsung guys can elaborate on what's going on here. Few comments inline.

Quoted 32 lines

Subject: [PATCH] ARM: gic: allow GIC to support non-banked setups

The GIC support code is heavily using the fact that hardware implementations are exposing banked registers. Unfortunately, it looks like at least one GIC implementation (EXYNOS4) offers both the distributor and the CPU interfaces at different addresses, depending on the CPU.

This problem is solved by turning the distributor and CPU interface addresses into per-cpu variables. The EXYNOS4 code is updated not to mess with the GIC internals while handling interrupts, and struct gic_chip_data is back to being private.

---
 arch/arm/common/gic.c               |   76 +++++++++++++++++++++++++++--------
 arch/arm/include/asm/hardware/gic.h |   17 +------
 arch/arm/mach-exynos4/cpu.c         |   14 ------
 arch/arm/mach-exynos4/platsmp.c     |   28 ++-----------
 4 files changed, 66 insertions(+), 69 deletions(-)
arch/arm/common/gic.c +3 -0
index b574931..c7521dd 100644
@@ -37,6 +37,20 @@
 #include <asm/mach/irq.h>
 #include <asm/hardware/gic.h>
 
+struct gic_chip_data {
+	unsigned int irq_offset;
+	void __percpu __iomem **dist_base;

arch/arm/common/gic.c line 52

Quoted 10 lines
arch/arm/common/gic.c +10 -0
+	void __percpu __iomem **cpu_base;
+#ifdef CONFIG_CPU_PM
+	u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)];
+	u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)];
+	u32 saved_spi_target[DIV_ROUND_UP(1020, 4)];
+	u32 __percpu *saved_ppi_enable;
+	u32 __percpu *saved_ppi_conf;
+#endif
+	unsigned int gic_irqs;
+};

I think you can use DECLARE_PER_CPU(void __iomem *dist_base) etc. instead.

arch/arm/common/gic.c line 56

Quoted 4 lines
arch/arm/common/gic.c +4 -0
+static inline void __iomem *gic_data_dist_base(struct gic_chip_data *data)
+{
+	return *__this_cpu_ptr(data->dist_base);
+}

Then you can use __get_cpu_var here (same applies throughout).

arch/arm/common/gic.c

Quoted 5 lines
arch/arm/common/gic.c +2 -1
+static void __cpuinit exynos4_secondary_init(unsigned int cpu)
 {
 	void __iomem *dist_base = S5P_VA_GIC_DIST +
-				(gic_bank_offset * smp_processor_id());
+				(gic_bank_offset * cpu_logical_map(cpu));

Again, I'm deeply suspicious of this code :) Is there not a common memory alias for the distributor across all of the CPUs?

Will

#16 lore raw

PATCH 5/7 ARM: EXYNOS4: Add support external GIC

Quoted 9 lines · Will Deacon

Hi Marc,

Quoted 6 lines · Marc Zyngier

So to make my suggestion completely clear, here's a patch I'm now carrying in my tree. It's only been test compiled on EXYNOS4, but works nicely on my 11MP. It turns both dist_base and cpu_base into per-cpu variables, removes these callbacks, removes your private copy of gic_cpu_init, and makes struct gic_chip_data private again.

Quoted 5 lines
Quoted 1 line

What do you think?

This looks like the right sort of idea, although I'm deeply suspicious about per-cpu base addresses for the GIC distributor. It would be nice if the Samsung guys can elaborate on what's going on here. Few comments inline.

Yeah, this seem odd, specially as what's currently in mainline doesn't try to play tricks with the distributor. It looks like having a per-core distributor address is required for PPI usage on these SoCs, but the commit message is uninformative at best:

https://github.com/sfrothwell/linux-next/commit/637c2afa57ec9cd0ddc8879ea0cda4d8835ba71d#arch/arm/mach-exynos4/cpu.c

Again, comments from Samsung people would be much appreciated.

Quoted 29 lines
Quoted 29 lines

Subject: [PATCH] ARM: gic: allow GIC to support non-banked setups

The GIC support code is heavily using the fact that hardware implementations are exposing banked registers. Unfortunately, it looks like at least one GIC implementation (EXYNOS4) offers both the distributor and the CPU interfaces at different addresses, depending on the CPU.

This problem is solved by turning the distributor and CPU interface addresses into per-cpu variables. The EXYNOS4 code is updated not to mess with the GIC internals while handling interrupts, and struct gic_chip_data is back to being private.

---
 arch/arm/common/gic.c               |   76 +++++++++++++++++++++++++++--------
 arch/arm/include/asm/hardware/gic.h |   17 +------
 arch/arm/mach-exynos4/cpu.c         |   14 ------
 arch/arm/mach-exynos4/platsmp.c     |   28 ++-----------
 4 files changed, 66 insertions(+), 69 deletions(-)
arch/arm/common/gic.c +0 -0
index b574931..c7521dd 100644
@@ -37,6 +37,20 @@
 #include <asm/mach/irq.h>
 #include <asm/hardware/gic.h>
 
Quoted 15 lines

arch/arm/common/gic.c line 52

Quoted 13 lines
arch/arm/common/gic.c +13 -0
+struct gic_chip_data {
+	unsigned int irq_offset;
+	void __percpu __iomem **dist_base;
+	void __percpu __iomem **cpu_base;
+#ifdef CONFIG_CPU_PM
+	u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)];
+	u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)];
+	u32 saved_spi_target[DIV_ROUND_UP(1020, 4)];
+	u32 __percpu *saved_ppi_enable;
+	u32 __percpu *saved_ppi_conf;
+#endif
+	unsigned int gic_irqs;
+};

I think you can use DECLARE_PER_CPU(void __iomem *dist_base) etc. instead.

Unfortunately, you can't. That would be nice though... ;-)

Quoted 8 lines

arch/arm/common/gic.c line 56

Quoted 5 lines
arch/arm/common/gic.c +2 -1
+static void __cpuinit exynos4_secondary_init(unsigned int cpu)
 {
 	void __iomem *dist_base = S5P_VA_GIC_DIST +
-				(gic_bank_offset * smp_processor_id());
+				(gic_bank_offset * cpu_logical_map(cpu));

Again, I'm deeply suspicious of this code :) Is there not a common memory alias for the distributor across all of the CPUs?

Kukjin, could you please comment on the presence of a common memory region for the distributor? This seem quite odd...

Thanks,

	M.
Signature · 1 line
Jazz is not dead. It just smells funny...
#17 lore raw

PATCH 5/7 ARM: EXYNOS4: Add support external GIC

Dear Marc and Will,

Quoted 22 lines · Marc Zyngier
Quoted 9 lines · Will Deacon

Hi Marc,

Quoted 6 lines · Marc Zyngier

So to make my suggestion completely clear, here's a patch I'm now carrying in my tree. It's only been test compiled on EXYNOS4, but works nicely on my 11MP. It turns both dist_base and cpu_base into per-cpu variables, removes these callbacks, removes your private copy of gic_cpu_init, and makes struct gic_chip_data private again.

Quoted 5 lines
Quoted 1 line

What do you think?

This looks like the right sort of idea, although I'm deeply suspicious about per-cpu base addresses for the GIC distributor. It would be nice if the Samsung guys can elaborate on what's going on here. Few comments inline.

Yeah, this seem odd, specially as what's currently in mainline doesn't try to play tricks with the distributor. It looks like having a per-core distributor address is required for PPI usage on these SoCs, but the commit message is uninformative at best:

Quoted 4 lines

https://github.com/sfrothwell/linux-
next/commit/637c2afa57ec9cd0ddc8879ea0cda4d8835ba71d#arch/arm/mach-exynos4/cpu.c

Again, comments from Samsung people would be much appreciated.

Your guess is right.
Exynos4 cannot support register banking, which means every CPU has its own CPU base and Distributor base address.
Without the workaround I implemented, every CPU accesses the base address for CPU0 and thus the interrupts for other CPUs cannot be handled properly.

Quoted 56 lines
Quoted 29 lines
Quoted 29 lines

Subject: [PATCH] ARM: gic: allow GIC to support non-banked setups

The GIC support code is heavily using the fact that hardware implementations are exposing banked registers. Unfortunately, it looks like at least one GIC implementation (EXYNOS4) offers both the distributor and the CPU interfaces at different addresses, depending on the CPU.

This problem is solved by turning the distributor and CPU interface addresses into per-cpu variables. The EXYNOS4 code is updated not to mess with the GIC internals while handling interrupts, and struct gic_chip_data is back to being private.

---
 arch/arm/common/gic.c               |   76 +++++++++++++++++++++++++++--------
 arch/arm/include/asm/hardware/gic.h |   17 +------
 arch/arm/mach-exynos4/cpu.c         |   14 ------
 arch/arm/mach-exynos4/platsmp.c     |   28 ++-----------
 4 files changed, 66 insertions(+), 69 deletions(-)
arch/arm/common/gic.c +0 -0
index b574931..c7521dd 100644
@@ -37,6 +37,20 @@
 #include <asm/mach/irq.h>
 #include <asm/hardware/gic.h>
 
Quoted 15 lines

arch/arm/common/gic.c line 52

Quoted 13 lines
arch/arm/common/gic.c +13 -0
+struct gic_chip_data {
+	unsigned int irq_offset;
+	void __percpu __iomem **dist_base;
+	void __percpu __iomem **cpu_base;
+#ifdef CONFIG_CPU_PM
+	u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)];
+	u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)];
+	u32 saved_spi_target[DIV_ROUND_UP(1020, 4)];
+	u32 __percpu *saved_ppi_enable;
+	u32 __percpu *saved_ppi_conf;
+#endif
+	unsigned int gic_irqs;
+};

I think you can use DECLARE_PER_CPU(void __iomem *dist_base) etc. instead.

Unfortunately, you can't. That would be nice though... ;-)

Quoted 8 lines

arch/arm/common/gic.c line 56

Quoted 5 lines
arch/arm/common/gic.c +2 -1
+static void __cpuinit exynos4_secondary_init(unsigned int cpu)
 {
 	void __iomem *dist_base = S5P_VA_GIC_DIST +
-				(gic_bank_offset * smp_processor_id());
+				(gic_bank_offset * cpu_logical_map(cpu));

Again, I'm deeply suspicious of this code :) Is there not a common memory alias for the distributor across all of the CPUs?

Quoted 2 lines

Kukjin, could you please comment on the presence of a common memory region for the distributor? This seem quite odd...

Some registers in Distributor are banked for PPI and SGI support (banked interrupts). The register for pending and enable status of these interrupts are banked.

Marc, I think the approach in your patch is much better than mine if it doesn't hurt the performance of other platforms which use the common gic code.
I'll re-work the exynos4 interrupt code based on your patch though
I'm not sure that it's possible to be merged in merge window.

Kukjin, how do you think about this?

Quoted 11 lines

Thanks,

	M.

--
Jazz is not dead. It just smells funny...

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

#18 lore raw

PATCH 5/7 ARM: EXYNOS4: Add support external GIC

Hi Changwan,

Quoted 6 lines · Changhwan Youn
Quoted 2 lines

Kukjin, could you please comment on the presence of a common memory region for the distributor? This seem quite odd...

Some registers in Distributor are banked for PPI and SGI support (banked interrupts). The register for pending and enable status of these interrupts are banked.

Right, that explains it then.

Quoted 2 lines

Marc, I think the approach in your patch is much better than mine if it doesn't hurt the performance of other platforms which use the common gic code.

It probably doesn't hurt the general case too much (I expect a bit more pressure on the d-cache because of the per-cpu stuff, but nothing to be too worried about).

Quoted 2 lines

I'll re-work the exynos4 interrupt code based on your patch though I'm not sure that it's possible to be merged in merge window.

My main concern at the moment is that mainline is broken as far as EXYNOS4 is concerned (there's a race with the EOI hook), so that should get fixed first.

Cheers,

	M.
Signature · 1 line
Jazz is not dead. It just smells funny...
#19 lore raw

PATCH 5/7 ARM: EXYNOS4: Add support external GIC

Quoted 7 lines · Marc Zyngier

Hi Changwan,

Quoted 3 lines · Changhwan Youn
Quoted 2 lines

Kukjin, could you please comment on the presence of a common memory region for the distributor? This seem quite odd...

Quoted 8 lines
Quoted 1 line

Some registers in Distributor are banked for PPI and SGI support (banked

interrupts).

Quoted 2 lines

The register for pending and enable status of these interrupts are banked.

Right, that explains it then.

Quoted 1 line

Marc, I think the approach in your patch is much better than mine if it

doesn't hurt

Quoted 6 lines
Quoted 1 line

the performance of other platforms which use the common gic code.

It probably doesn't hurt the general case too much (I expect a bit more pressure on the d-cache because of the per-cpu stuff, but nothing to be too worried about).

Quoted 7 lines
Quoted 2 lines

I'll re-work the exynos4 interrupt code based on your patch though I'm not sure that it's possible to be merged in merge window.

My main concern at the moment is that mainline is broken as far as EXYNOS4 is concerned (there's a race with the EOI hook), so that should get fixed first.

Hi Marc,

OK. I agree with Will and your opinions and I think Changhwan can fix it as per your suggestion, but he needs fixed/updated regarding gic codes to avoid re-work and conflicts with others. So it would be better to us if he could fix it after merging your patches even probably at the end of upcoming merge window. I hope he can do it before v3.2-rc1.

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <[email protected]>, Senior Engineer, SW Solution Development Team, Samsung Electronics Co., Ltd.

#20 lore raw

PATCH 5/7 ARM: EXYNOS4: Add support external GIC

Quoted 30 lines · Kukjin Kim
Quoted 7 lines · Marc Zyngier

Hi Changwan,

Quoted 3 lines · Changhwan Youn
Quoted 2 lines

Kukjin, could you please comment on the presence of a common memory region for the distributor? This seem quite odd...

Quoted 8 lines
Quoted 1 line

Some registers in Distributor are banked for PPI and SGI support (banked

interrupts).

Quoted 2 lines

The register for pending and enable status of these interrupts are banked.

Right, that explains it then.

Quoted 1 line

Marc, I think the approach in your patch is much better than mine if it

doesn't hurt

Quoted 6 lines
Quoted 1 line

the performance of other platforms which use the common gic code.

It probably doesn't hurt the general case too much (I expect a bit more pressure on the d-cache because of the per-cpu stuff, but nothing to be too worried about).

Quoted 7 lines
Quoted 2 lines

I'll re-work the exynos4 interrupt code based on your patch though I'm not sure that it's possible to be merged in merge window.

My main concern at the moment is that mainline is broken as far as EXYNOS4 is concerned (there's a race with the EOI hook), so that should get fixed first.

Quoted 7 lines

Hi Marc,

OK. I agree with Will and your opinions and I think Changhwan can fix it as per your suggestion, but he needs fixed/updated regarding gic codes to avoid re-work and conflicts with others. So it would be better to us if he could fix it after merging your patches even probably at the end of upcoming merge window. I hope he can do it before v3.2-rc1.

Right. So this damned thing has made it to mainline in its full glory. Furthermore, the MCT code is also broken, as it uses the old PPI API (doesn't even compile).

Can we please fix this as soon as possible? I posted patches for both a while ago, with almost no reaction...

	M.
Signature · 1 line
Jazz is not dead. It just smells funny...
#21 lore raw

PATCH 5/7 ARM: EXYNOS4: Add support external GIC

Quoted 11 lines · Marc Zyngier
Quoted 9 lines · Kukjin Kim
Quoted 8 lines · Marc Zyngier

Hi Changwan,

Quoted 4 lines · Changhwan Youn
Quoted 2 lines

Kukjin, could you please comment on the presence of a common memory region for the distributor? This seem quite odd...

Some registers in Distributor are banked for PPI and SGI support

(banked

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

interrupts).

Quoted 2 lines

The register for pending and enable status of these interrupts are banked.

Right, that explains it then.

Quoted 1 line

Marc, I think the approach in your patch is much better than mine if

it

Quoted 10 lines
Quoted 10 lines

doesn't hurt

Quoted 9 lines
Quoted 1 line

the performance of other platforms which use the common gic code.

It probably doesn't hurt the general case too much (I expect a bit more pressure on the d-cache because of the per-cpu stuff, but nothing to be too worried about).

Quoted 2 lines

I'll re-work the exynos4 interrupt code based on your patch though I'm not sure that it's possible to be merged in merge window.

Quoted 7 lines
Quoted 7 lines
Quoted 4 lines

My main concern at the moment is that mainline is broken as far as EXYNOS4 is concerned (there's a race with the EOI hook), so that should get fixed first.

Hi Marc,

OK. I agree with Will and your opinions and I think Changhwan can fix it

as

Quoted 1 line
Quoted 1 line

per your suggestion, but he needs fixed/updated regarding gic codes to

avoid

Quoted 1 line
Quoted 1 line

re-work and conflicts with others. So it would be better to us if he

could

Quoted 1 line
Quoted 1 line

fix it after merging your patches even probably at the end of upcoming

merge

Quoted 8 lines
Quoted 1 line

window. I hope he can do it before v3.2-rc1.

Right. So this damned thing has made it to mainline in its full glory. Furthermore, the MCT code is also broken, as it uses the old PPI API (doesn't even compile).

Can we please fix this as soon as possible? I posted patches for both a while ago, with almost no reaction...

Yeah, should be fixed. Let me check again and if any updates, let you know.

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <[email protected]>, Senior Engineer, SW Solution Development Team, Samsung Electronics Co., Ltd.

#22 lore raw

PATCH 5/7 ARM: EXYNOS4: Add support external GIC

In reply to Marc Zyngier
Quoted 11 lines · Marc Zyngier
Quoted 9 lines · Will Deacon

Review

Quoted 5 lines · Marc Zyngier
(quoted diff) +2 -1
+static void __cpuinit exynos4_secondary_init(unsigned int cpu)
 {
 	void __iomem *dist_base = S5P_VA_GIC_DIST +
-				(gic_bank_offset * smp_processor_id());
+				(gic_bank_offset * cpu_logical_map(cpu));

Again, I'm deeply suspicious of this code :) Is there not a common memory alias for the distributor across all of the CPUs?

Quoted 2 lines

Kukjin, could you please comment on the presence of a common memory region for the distributor? This seem quite odd...

It's not odd when you consider that there's per-CPU registers within the GIC distributor as well (for the first 32 GIC IRQs) as the per-CPU GIC CPU interfaces.

#23 lore raw

PATCH 5/7 ARM: EXYNOS4: Add support external GIC

Quoted 12 lines · Russell King - ARM Linux
Quoted 11 lines · Marc Zyngier
Quoted 9 lines · Will Deacon

Review

Quoted 5 lines · Marc Zyngier
(quoted diff) +2 -1
+static void __cpuinit exynos4_secondary_init(unsigned int cpu)
 {
 	void __iomem *dist_base = S5P_VA_GIC_DIST +
-				(gic_bank_offset * smp_processor_id());
+				(gic_bank_offset * cpu_logical_map(cpu));

Again, I'm deeply suspicious of this code :) Is there not a common memory alias for the distributor across all of the CPUs?

Quoted 6 lines
Quoted 2 lines

Kukjin, could you please comment on the presence of a common memory region for the distributor? This seem quite odd...

It's not odd when you consider that there's per-CPU registers within the GIC distributor as well (for the first 32 GIC IRQs) as the per-CPU GIC CPU interfaces.

Agreed, but it is odd for those registers not to be banked in hardware. Marc and I spoke to some of the hardware chaps at ARM and they don't see this as a common setup in the future, so rather than litter the GIC driver with __percpu variables, we might be better off adding some extra platform callbacks to the set that we already have.

Will

#24 lore raw

PATCH 6/7 ARM: EXYNOS4: Remove clock event timers using ARM private timers

In reply to Changhwan Youn

External GIC cannot support PPI (Private Peripheral Interrupt) for ARM private timers. Thus MCT should be selected as clock event timers by default.

---
 arch/arm/mach-exynos4/Kconfig                    |    3 +-
 arch/arm/mach-exynos4/Makefile                   |    7 +-
 arch/arm/mach-exynos4/cpu.c                      |    2 +-
 arch/arm/mach-exynos4/include/mach/entry-macro.S |    6 -
 arch/arm/mach-exynos4/include/mach/irqs.h        |    2 -
 arch/arm/mach-exynos4/localtimer.c               |   26 --
 arch/arm/mach-exynos4/time.c                     |  303 ----------------------
 7 files changed, 4 insertions(+), 345 deletions(-)
 delete mode 100644 arch/arm/mach-exynos4/localtimer.c
 delete mode 100644 arch/arm/mach-exynos4/time.c
arch/arm/mach-exynos4/Kconfig +2 -1
index 1435fc3..0aca083 100644
@@ -16,7 +16,8 @@ config CPU_EXYNOS4210
 	  Enable EXYNOS4210 CPU support
 
 config EXYNOS4_MCT
-	bool "Kernel timer support by MCT"
+	bool
+	default y
 	help
 	  Use MCT (Multi Core Timer) as kernel timers
 
arch/arm/mach-exynos4/Makefile +1 -6
index 60fe5ec..c3c70ab 100644
@@ -20,12 +20,7 @@ obj-$(CONFIG_CPU_IDLE)		+= cpuidle.o
 
 obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o
 
-ifeq ($(CONFIG_EXYNOS4_MCT),y)
-obj-y				+= mct.o
-else
-obj-y				+= time.o
-obj-$(CONFIG_LOCAL_TIMERS)	+= localtimer.o
-endif
+obj-$(CONFIG_EXYNOS4_MCT)	+= mct.o
 
 obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
 
arch/arm/mach-exynos4/cpu.c +1 -1
index 40a866c..d153309 100644
@@ -172,7 +172,7 @@ void __init exynos4_init_irq(void)
 {
 	int irq;
 
-	gic_init(0, IRQ_LOCALTIMER, S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+	gic_init(0, IRQ_SPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
 	gic_arch_extn.irq_eoi = exynos4_gic_irq_eoi;
 
 	for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
arch/arm/mach-exynos4/include/mach/entry-macro.S +0 -6
index 4fad076..d7a1e28 100644
@@ -80,10 +80,4 @@
 		/* As above, this assumes that irqstat and base are preserved.. */
 
 		.macro test_for_ltirq, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		mov	\tmp, #0
-		cmp	\irqnr, #29
-		moveq	\tmp, #1
-		streq	\irqstat, [\base, #GIC_CPU_EOI]
-		cmp	\tmp, #0
 		.endm
arch/arm/mach-exynos4/include/mach/irqs.h +0 -2
index e497ea2..250427f 100644
@@ -19,8 +19,6 @@
 
 #define IRQ_PPI(x)		S5P_IRQ(x+16)
 
-#define IRQ_LOCALTIMER		IRQ_PPI(13)
-
 /* SPI: Shared Peripheral Interrupt */
 
 #define IRQ_SPI(x)		S5P_IRQ(x+32)
arch/arm/mach-exynos4/localtimer.c deleted +0 -26
deleted file mode 100644
index 6bf3d0a..0000000
@@ -1,26 +0,0 @@
-/* linux/arch/arm/mach-exynos4/localtimer.c
- *
- * Cloned from linux/arch/arm/mach-realview/localtimer.c
- *
- *  Copyright (C) 2002 ARM Ltd.
- *  All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/clockchips.h>
-
-#include <asm/irq.h>
-#include <asm/localtimer.h>
-
-/*
- * Setup the local clock events for a CPU.
- */
-int __cpuinit local_timer_setup(struct clock_event_device *evt)
-{
-	evt->irq = IRQ_LOCALTIMER;
-	twd_timer_setup(evt);
-	return 0;
-}
arch/arm/mach-exynos4/time.c deleted +0 -303

303 lines not on this page · raw message

Signature · 1 line
1.7.1
#25 lore raw

PATCH 7/7 ARM: EXYNOS4: Add chained enrty/exit function to uart interrupt handler

In reply to Changhwan Youn

This patch adds chained IRQ enter/exit functions to uart interrupt handler in order to function correctly on primary controllers with different methods of flow control.

---
 arch/arm/plat-samsung/irq-uart.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)
arch/arm/plat-samsung/irq-uart.c +7 -0
index 32582c0..8960eaf 100644
@@ -19,6 +19,8 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 
+#include <asm/mach/irq.h>
+
 #include <mach/map.h>
 #include <plat/irq-uart.h>
 #include <plat/regs-serial.h>
@@ -30,9 +32,12 @@
 static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc)
 {
 	struct s3c_uart_irq *uirq = desc->irq_data.handler_data;
+	struct irq_chip *chip = irq_get_chip(irq);
 	u32 pend = __raw_readl(uirq->regs + S3C64XX_UINTP);
 	int base = uirq->base_irq;
 
+	chained_irq_enter(chip, desc);
+
 	if (pend & (1 << 0))
 		generic_handle_irq(base);
 	if (pend & (1 << 1))
@@ -41,6 +46,8 @@ static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc)
 		generic_handle_irq(base + 2);
 	if (pend & (1 << 3))
 		generic_handle_irq(base + 3);
+
+	chained_irq_exit(chip, desc);
 }
 
 static void __init s3c_init_uart_irq(struct s3c_uart_irq *uirq)
Signature · 1 line
1.7.1
#26 lore raw

cover ARM: EXYNOS4: Adds External GIC

In reply to Changhwan Youn

Hi,

There are some boards which use the EVT0 chip. some SMDKV310 and Universal-C210.
With this changes, it can't use these boards.

Do you want to remove EVT0 based boards?

Thank you,
Kyungmin Park

Quoted 17 lines · Changhwan Youn

This patch adds implementation External GIC on EXYNOS4 SoC.

Note: need to update timer codes for supporting old type of EXYNOS4 SoCs.

[PATCH 1/7] ARM: EXYNOS4: Add external GIC io memory mapping
[PATCH 2/7] ARM: EXYNOS4: modify interrupt mappings for external GIC [PATCH 3/7] ARM: EXYNOS4: set the affinity of mct1 interrupt using IRQ_MCT_L1 [PATCH 4/7] ARM: GIC: move gic_chip_data structure declaration to header [PATCH 5/7] ARM: EXYNOS4: Add support external GIC
[PATCH 6/7] ARM: EXYNOS4: Remove clock event timers using ARM private timers [PATCH 7/7] ARM: EXYNOS4: Add chained enrty/exit function to uart interrupt handler --
To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in the body of a message to majordomo at vger.kernel.org
More majordomo info at ?http://vger.kernel.org/majordomo-info.html

#27 lore raw

cover ARM: EXYNOS4: Adds External GIC

In reply to Changhwan Youn
Quoted 9 lines · Changhwan Youn

This patch adds implementation External GIC on EXYNOS4 SoC.

Note: need to update timer codes for supporting old type of EXYNOS4 SoCs.

[PATCH 1/7] ARM: EXYNOS4: Add external GIC io memory mapping [PATCH 2/7] ARM: EXYNOS4: modify interrupt mappings for external GIC [PATCH 3/7] ARM: EXYNOS4: set the affinity of mct1 interrupt using

IRQ_MCT_L1

Quoted 3 lines

[PATCH 4/7] ARM: GIC: move gic_chip_data structure declaration to header [PATCH 5/7] ARM: EXYNOS4: Add support external GIC
[PATCH 6/7] ARM: EXYNOS4: Remove clock event timers using ARM private

timers

Quoted 1 line

[PATCH 7/7] ARM: EXYNOS4: Add chained enrty/exit function to uart

interrupt

Quoted 1 line

handler

OK, applied.
Thanks.

As a note, this is needed for to support upcoming other EXYNOS4 SoCs with current exynos4 mainline.

Best regards,
Kgene.
--
Kukjin Kim <[email protected]>, Senior Engineer, SW Solution Development Team, Samsung Electronics Co., Ltd.