Skip to contentSkip to conversation

Consolidating GIC per-cpu interrupts

RFC PATCH Superseded Marc Zyngier 4 participants 11 messages Jul 21, 2011 – Aug 1, 2011

Subsystems (5)

v9 of 11 Superseded Latest is v11 →

lore
Share & tools
lore
#0 lore raw

v9 cover Consolidating GIC per-cpu interrupts

The current GIC per-cpu interrupts (aka PPIs) suffer from a number of problems:

- They use a completely separate scheme to handle the interrupts, mostly because the PPI concept doesn't really match the kernel view of an interrupt.
- PPIs can only be used by the timer code, unless we add more low-level assembly code.
- The local timer code can only be used by devices generating PPIs, and not SPIs.
- At least one platform (msm) has started implementing its own alternative scheme.
- Some low-level code gets duplicated, as usual...

As the previous solution which tried to map PPIs to normal interrupts has been proved to be buggy, I've opted to a much simpler scheme (based on Russell's input).

The proposed solution is to handle the interrupt using the same path as SPIs, with a common handler for all PPIs. Each PPI can be requested using gic_request_ppi(), similar to request_irq(). The local timer code is updated to reflect these changes.

Patches against next-20110721, tested on PB11MP. As this patch series is quite different from the previous one, I've dropped all previous acks from platform maintainers.

Marc Zyngier (4):
ARM: gic: consolidate PPI handling
ARM: gic: Add PPI registration interface
ARM: local timers: drop local_timer_ack()
ARM: gic: add compute_irqnr macro for exynos4

 arch/arm/common/gic.c                             |  150 +++++++++++++++++++--
 arch/arm/include/asm/entry-macro-multi.S          |    7 -
 arch/arm/include/asm/hardirq.h                    |    3 -
 arch/arm/include/asm/hardware/entry-macro-gic.S   |   22 +---
 arch/arm/include/asm/hardware/gic.h               |    5 +-
 arch/arm/include/asm/localtimer.h                 |   14 +-
 arch/arm/include/asm/smp.h                        |    5 -
 arch/arm/include/asm/smp_twd.h                    |    2 +-
 arch/arm/kernel/irq.c                             |    3 -
 arch/arm/kernel/smp.c                             |   33 +-----
 arch/arm/kernel/smp_twd.c                         |   32 +++--
 arch/arm/mach-exynos4/include/mach/entry-macro.S  |   61 +--------
 arch/arm/mach-exynos4/mct.c                       |    6 -
 arch/arm/mach-msm/board-msm8x60.c                 |   11 --
 arch/arm/mach-msm/include/mach/entry-macro-qgic.S |   73 +----------
 arch/arm/mach-msm/timer.c                         |   52 +++----
 arch/arm/mach-omap2/include/mach/entry-macro.S    |   14 +--
 arch/arm/mach-shmobile/entry-intc.S               |    3 -
 arch/arm/mach-shmobile/include/mach/entry-macro.S |    3 -
 19 files changed, 208 insertions(+), 291 deletions(-)
#1 lore raw

RFC PATCH v9 1/4 ARM: gic: consolidate PPI handling

PPI handling is a bit of an odd beast. It uses its own low level handling code and is hardwired to the local timers (hence lacking a registration interface).

Instead, switch the low handling to the normal SPI handling code.

This also allows the removal of some duplicated code.

Cc Kukjin Kim <[email protected]>
Cc David Brown <[email protected]>
Cc Bryan Huntsman <[email protected]>
Cc Tony Lindgren <[email protected]>
Cc Paul Mundt <[email protected]>
Cc Magnus Damm <[email protected]>
---
 arch/arm/common/gic.c                             |   72 +++++++++++++++++++-
 arch/arm/include/asm/entry-macro-multi.S          |    7 --
 arch/arm/include/asm/hardirq.h                    |    3 -
 arch/arm/include/asm/hardware/entry-macro-gic.S   |   19 +-----
 arch/arm/include/asm/localtimer.h                 |    6 +-
 arch/arm/include/asm/smp.h                        |    5 --
 arch/arm/kernel/irq.c                             |    3 -
 arch/arm/kernel/smp.c                             |   27 ++------
 arch/arm/mach-exynos4/include/mach/entry-macro.S  |    6 +--
 arch/arm/mach-msm/board-msm8x60.c                 |   11 ---
 arch/arm/mach-msm/include/mach/entry-macro-qgic.S |   73 +--------------------
 arch/arm/mach-omap2/include/mach/entry-macro.S    |   14 +----
 arch/arm/mach-shmobile/entry-intc.S               |    3 -
 arch/arm/mach-shmobile/include/mach/entry-macro.S |    3 -
 14 files changed, 83 insertions(+), 169 deletions(-)
arch/arm/common/gic.c +69 -3
index 23564ed..6a54c28 100644
@@ -28,10 +28,14 @@
 #include <linux/smp.h>
 #include <linux/cpumask.h>
 #include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/percpu.h>
+#include <linux/slab.h>
 
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
 #include <asm/hardware/gic.h>
+#include <asm/localtimer.h>
 
 static DEFINE_SPINLOCK(irq_controller_lock);
 
@@ -256,12 +260,33 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
 	irq_set_chained_handler(irq, gic_handle_cascade_irq);
 }
 
+static unsigned int gic_nr_ppis, gic_ppi_base;
+
+#define PPI_IRQACT(nr)						\
+	{							\
+		.handler	= percpu_timer_handler,		\
+		.flags		= IRQF_PERCPU | IRQF_TIMER,	\
+		.irq		= nr,				\
+		.name		= "PPI-" # nr,			\
+	}
+
+static struct irqaction ppi_irqaction_template[16] __initdata = {
+	PPI_IRQACT(0),  PPI_IRQACT(1),  PPI_IRQACT(2),  PPI_IRQACT(3),
+	PPI_IRQACT(4),  PPI_IRQACT(5),  PPI_IRQACT(6),  PPI_IRQACT(7),
+	PPI_IRQACT(8),  PPI_IRQACT(9),  PPI_IRQACT(10), PPI_IRQACT(11),
+	PPI_IRQACT(12), PPI_IRQACT(13), PPI_IRQACT(14), PPI_IRQACT(15),
+};
+
+static struct irqaction *ppi_irqaction;
+
 static void __init gic_dist_init(struct gic_chip_data *gic,
 	unsigned int irq_start)
 {
 	unsigned int gic_irqs, irq_limit, i;
 	void __iomem *base = gic->dist_base;
 	u32 cpumask = 1 << smp_processor_id();
+	u32 dist_ctr, nrcpus;
+	u32 nrppis = 0, ppi_base = 0;
 
 	cpumask |= cpumask << 8;
 	cpumask |= cpumask << 16;
@@ -272,11 +297,38 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
 	 * Find out how many interrupts are supported.
 	 * The GIC only supports up to 1020 interrupt sources.
 	 */
-	gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f;
-	gic_irqs = (gic_irqs + 1) * 32;
+	dist_ctr = readl_relaxed(base + GIC_DIST_CTR);
+	gic_irqs = ((dist_ctr & 0x1f) + 1) * 32;
 	if (gic_irqs > 1020)
 		gic_irqs = 1020;
 
+	/* Find out how many CPUs are supported (8 max). */
+	nrcpus = ((dist_ctr >> 5) & 7) + 1;
+
+	/*
+	 * Nobody would be insane enough to use PPIs on a secondary
+	 * GIC, right?
+	 */
+	if (gic == &gic_data[0]) {
+		nrppis = 16 - (irq_start & 15);
+		ppi_base = gic->irq_offset + 32 - nrppis;
+		ppi_irqaction = kzalloc(sizeof(*ppi_irqaction) * nrppis,
+					 GFP_KERNEL);
+		if (!ppi_irqaction) {
+			pr_err("GIC: Can't allocate PPI memory");
+			nrppis = 0;
+			ppi_base = 0;
+		}
+
+		for (i = 0; i < nrppis; i++)
+			ppi_irqaction[i] = ppi_irqaction_template[i + (ppi_base & 15)];
+		gic_nr_ppis = nrppis;
+		gic_ppi_base = ppi_base;
+	}
+
+	pr_info("Configuring GIC with %d sources (%d PPIs)\n",
+		gic_irqs, (gic == &gic_data[0]) ? nrppis : 0);
+
 	/*
 	 * Set all global interrupts to be level triggered, active low.
 	 */
@@ -312,7 +364,21 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
 	/*
 	 * Setup the Linux IRQ subsystem.
 	 */
-	for (i = irq_start; i < irq_limit; i++) {
+	for (i = 0; i < nrppis; i++) {
+		int ppi = i + ppi_base;
+		int err;
+
+		irq_set_chip_and_handler(ppi, &gic_chip, handle_percpu_irq);
+		irq_set_chip_data(ppi, gic);
+		irq_set_status_flags(ppi, IRQ_NOAUTOEN | IRQ_NOPROBE);
+
+		err = setup_irq(ppi, &ppi_irqaction[i]);
+		if (err)
+			pr_err("GIC: can't setup IRQ%d PPI%d (%d)\n",
+			       i, ppi, err);
+	}
+
+	for (i = irq_start + nrppis; i < irq_limit; i++) {
 		irq_set_chip_and_handler(i, &gic_chip, handle_fasteoi_irq);
 		irq_set_chip_data(i, gic);
 		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
arch/arm/include/asm/entry-macro-multi.S +0 -7
index 2f1e209..88d6181 100644
@@ -25,13 +25,6 @@
 	movne	r1, sp
 	adrne	lr, BSYM(1b)
 	bne	do_IPI
-
-#ifdef CONFIG_LOCAL_TIMERS
-	test_for_ltirq r0, r2, r6, lr
-	movne	r0, sp
-	adrne	lr, BSYM(1b)
-	bne	do_local_timer
-#endif
 #endif
 9997:
 	.endm
arch/arm/include/asm/hardirq.h +0 -3
index 89ad180..ddf07a9 100644
@@ -9,9 +9,6 @@
 
 typedef struct {
 	unsigned int __softirq_pending;
-#ifdef CONFIG_LOCAL_TIMERS
-	unsigned int local_timer_irqs;
-#endif
 #ifdef CONFIG_SMP
 	unsigned int ipi_irqs[NR_IPI];
 #endif
arch/arm/include/asm/hardware/entry-macro-gic.S +2 -17
index c115b82..74ebc80 100644
@@ -22,15 +22,11 @@
  * interrupt controller spec.  To wit:
  *
  * Interrupts 0-15 are IPI
- * 16-28 are reserved
- * 29-31 are local.  We allow 30 to be used for the watchdog.
+ * 16-31 are local.  We allow 30 to be used for the watchdog.
  * 32-1020 are global
  * 1021-1022 are reserved
  * 1023 is "spurious" (no interrupt)
  *
- * For now, we ignore all local interrupts so only return an interrupt if it's
- * between 30 and 1020.  The test_for_ipi routine below will pick up on IPIs.
- *
  * A simple read from the controller will tell us the number of the highest
  * priority enabled interrupt.  We then just need to check whether it is in the
  * valid range for an IRQ (30-1020 inclusive).
@@ -43,7 +39,7 @@
 
 	ldr	\tmp, =1021
 	bic     \irqnr, \irqstat, #0x1c00
-	cmp     \irqnr, #29
+	cmp     \irqnr, #15
 	cmpcc	\irqnr, \irqnr
 	cmpne	\irqnr, \tmp
 	cmpcs	\irqnr, \irqnr
@@ -62,14 +58,3 @@
 	strcc	\irqstat, [\base, #GIC_CPU_EOI]
 	cmpcs	\irqnr, \irqnr
 	.endm
-
-/* 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/include/asm/localtimer.h +4 -2
index 080d74f..e3663f7 100644
@@ -10,6 +10,8 @@
 #ifndef __ASM_ARM_LOCALTIMER_H
 #define __ASM_ARM_LOCALTIMER_H
 
+#include <linux/interrupt.h>
+
 struct clock_event_device;
 
 /*
@@ -18,9 +20,9 @@ struct clock_event_device;
 void percpu_timer_setup(void);
 
 /*
- * Called from assembly, this is the local timer IRQ handler
+ * Per-cpu timer IRQ handler
  */
-asmlinkage void do_local_timer(struct pt_regs *);
+irqreturn_t percpu_timer_handler(int irq, void *dev_id);
 
 
 #ifdef CONFIG_LOCAL_TIMERS
arch/arm/include/asm/smp.h +0 -5
index e42d96a..73ec155 100644
@@ -88,9 +88,4 @@ extern void platform_cpu_enable(unsigned int cpu);
 extern void arch_send_call_function_single_ipi(int cpu);
 extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
 
-/*
- * show local interrupt info
- */
-extern void show_local_irqs(struct seq_file *, int);
-
 #endif /* ifndef __ASM_ARM_SMP_H */
arch/arm/kernel/irq.c +0 -3
index dbc1f41..bf1a5cd 100644
@@ -59,9 +59,6 @@ int arch_show_interrupts(struct seq_file *p, int prec)
 #ifdef CONFIG_SMP
 	show_ipi_list(p, prec);
 #endif
-#ifdef CONFIG_LOCAL_TIMERS
-	show_local_irqs(p, prec);
-#endif
 	seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);
 	return 0;
 }
arch/arm/kernel/smp.c +5 -22
index 167e3cb..c213f6a 100644
@@ -437,10 +437,6 @@ u64 smp_irq_stat_cpu(unsigned int cpu)
 	for (i = 0; i < NR_IPI; i++)
 		sum += __get_irq_stat(cpu, ipi_irqs[i]);
 
-#ifdef CONFIG_LOCAL_TIMERS
-	sum += __get_irq_stat(cpu, local_timer_irqs);
-#endif
-
 	return sum;
 }
 
@@ -458,29 +454,16 @@ static void ipi_timer(void)
 }
 
 #ifdef CONFIG_LOCAL_TIMERS
-asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs)
+irqreturn_t percpu_timer_handler(int irq, void *dev_id)
 {
-	struct pt_regs *old_regs = set_irq_regs(regs);
-	int cpu = smp_processor_id();
+	struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent);
 
 	if (local_timer_ack()) {
-		__inc_irq_stat(cpu, local_timer_irqs);
-		ipi_timer();
+		evt->event_handler(evt);
+		return IRQ_HANDLED;
 	}
 
-	set_irq_regs(old_regs);
-}
-
-void show_local_irqs(struct seq_file *p, int prec)
-{
-	unsigned int cpu;
-
-	seq_printf(p, "%*s: ", prec, "LOC");
-
-	for_each_present_cpu(cpu)
-		seq_printf(p, "%10u ", __get_irq_stat(cpu, local_timer_irqs));
-
-	seq_printf(p, " Local timer interrupts\n");
+	return IRQ_NONE;
 }
 #endif
 
arch/arm/mach-exynos4/include/mach/entry-macro.S +1 -5
index d7a1e28..807d05d 100644
@@ -55,7 +55,7 @@
 
 		bic     \irqnr, \irqstat, #0x1c00
 
-		cmp     \irqnr, #29
+		cmp     \irqnr, #15
 		cmpcc	\irqnr, \irqnr
 		cmpne	\irqnr, \tmp
 		cmpcs	\irqnr, \irqnr
@@ -77,7 +77,3 @@
 		cmpcs	\irqnr, \irqnr
 		.endm
 
-		/* As above, this assumes that irqstat and base are preserved.. */
-
-		.macro test_for_ltirq, irqnr, irqstat, base, tmp
-		.endm
arch/arm/mach-msm/board-msm8x60.c +0 -11
index 98c47ce..990e036 100644
@@ -42,8 +42,6 @@ static struct platform_device *devices[] __initdata = {
 
 static void __init msm8x60_init_irq(void)
 {
-	unsigned int i;
-
 	gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
 		 (void *)MSM_QGIC_CPU_BASE);
 
@@ -55,15 +53,6 @@ static void __init msm8x60_init_irq(void)
 	 */
 	if (!machine_is_msm8x60_sim())
 		writel(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
-
-	/* FIXME: Not installing AVS_SVICINT and AVS_SVICINTSWDONE yet
-	 * as they are configured as level, which does not play nice with
-	 * handle_percpu_irq.
-	 */
-	for (i = GIC_PPI_START; i < GIC_SPI_START; i++) {
-		if (i != AVS_SVICINT && i != AVS_SVICINTSWDONE)
-			irq_set_handler(i, handle_percpu_irq);
-	}
 }
 
 static void __init msm8x60_init(void)
arch/arm/mach-msm/include/mach/entry-macro-qgic.S +1 -72

82 lines not on this page · raw message

arch/arm/mach-omap2/include/mach/entry-macro.S +1 -13
index ceb8b7e..feb90a1 100644
@@ -78,7 +78,7 @@
 4401:		ldr     \irqstat, [\base, #GIC_CPU_INTACK]
 		ldr     \tmp, =1021
 		bic     \irqnr, \irqstat, #0x1c00
-		cmp     \irqnr, #29
+		cmp     \irqnr, #15
 		cmpcc   \irqnr, \irqnr
 		cmpne   \irqnr, \tmp
 		cmpcs   \irqnr, \irqnr
@@ -101,18 +101,6 @@
 		it	cs
 		cmpcs	\irqnr, \irqnr
 		.endm
-
-		/* 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
-		itt	eq
-		moveq	\tmp, #1
-		streq	\irqstat, [\base, #GIC_CPU_EOI]
-		cmp	\tmp, #0
-		.endm
 #endif	/* CONFIG_SMP */
 
 #else	/* MULTI_OMAP2 */
arch/arm/mach-shmobile/entry-intc.S +0 -3
index cac0a7a..1a1c00c 100644
@@ -51,7 +51,4 @@
 	.macro  test_for_ipi, irqnr, irqstat, base, tmp
 	.endm
 
-	.macro  test_for_ltirq, irqnr, irqstat, base, tmp
-	.endm
-
 	arch_irq_handler shmobile_handle_irq_intc
arch/arm/mach-shmobile/include/mach/entry-macro.S +0 -3
index d791f10..8d4a416 100644
@@ -27,8 +27,5 @@
 	.macro  test_for_ipi, irqnr, irqstat, base, tmp
 	.endm
 
-	.macro  test_for_ltirq, irqnr, irqstat, base, tmp
-	.endm
-
 	.macro  arch_ret_to_user, tmp1, tmp2
 	.endm
Signature · 1 line
1.7.0.4
#2 lore raw

RFC PATCH v9 1/4 ARM: gic: consolidate PPI handling

arch/arm/common/gic.c void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) · line 267

Quoted 9 lines · Marc Zyngier
arch/arm/common/gic.c +5 -0
@@ -256,12 +260,33 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
 	irq_set_chained_handler(irq, gic_handle_cascade_irq);
 }
 
+static unsigned int gic_nr_ppis, gic_ppi_base;
+
+#define PPI_IRQACT(nr)						\
+	{							\
+		.handler	= percpu_timer_handler,		\

Won't this break on non-SMP non-localtimer builds?

Quoted 11 lines
arch/arm/common/gic.c +11 -0
+		.flags		= IRQF_PERCPU | IRQF_TIMER,	\
+		.irq		= nr,				\
+		.name		= "PPI-" # nr,			\
+	}
+
+static struct irqaction ppi_irqaction_template[16] __initdata = {
+	PPI_IRQACT(0),  PPI_IRQACT(1),  PPI_IRQACT(2),  PPI_IRQACT(3),
+	PPI_IRQACT(4),  PPI_IRQACT(5),  PPI_IRQACT(6),  PPI_IRQACT(7),
+	PPI_IRQACT(8),  PPI_IRQACT(9),  PPI_IRQACT(10), PPI_IRQACT(11),
+	PPI_IRQACT(12), PPI_IRQACT(13), PPI_IRQACT(14), PPI_IRQACT(15),
+};

arch/arm/common/gic.c void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) · line 288

Quoted 10 lines
arch/arm/common/gic.c +4 -0
+
+static struct irqaction *ppi_irqaction;
+
 static void __init gic_dist_init(struct gic_chip_data *gic,
 	unsigned int irq_start)
 {
 	unsigned int gic_irqs, irq_limit, i;
 	void __iomem *base = gic->dist_base;
 	u32 cpumask = 1 << smp_processor_id();
+	u32 dist_ctr, nrcpus;

nrcpus doesn't seem to be used. With that eliminated, dist_ctr doesn't seem to have much purpose.

arch/arm/common/gic.c void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) · line 289

Quoted 1 line
arch/arm/common/gic.c +1 -0
+	u32 nrppis = 0, ppi_base = 0;

Might be better to move this inside the "if (gic == &gic_data[0]) {" block, along with the printk too.

Quoted 6 lines
arch/arm/common/gic.c +0 -0
 	cpumask |= cpumask << 8;
 	cpumask |= cpumask << 16;
@@ -272,11 +297,38 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
 	 * Find out how many interrupts are supported.
 	 * The GIC only supports up to 1020 interrupt sources.

arch/arm/common/gic.c static void __init gic_dist_init(struct gic_chip_data *gic, · line 306

Quoted 10 lines
arch/arm/common/gic.c +4 -2
 	 */
-	gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f;
-	gic_irqs = (gic_irqs + 1) * 32;
+	dist_ctr = readl_relaxed(base + GIC_DIST_CTR);
+	gic_irqs = ((dist_ctr & 0x1f) + 1) * 32;
 	if (gic_irqs > 1020)
 		gic_irqs = 1020;
 
+	/* Find out how many CPUs are supported (8 max). */
+	nrcpus = ((dist_ctr >> 5) & 7) + 1;

As mentioned above, the above change can be killed because it doesn't alter anything which is used.

Quoted 10 lines
arch/arm/common/gic.c +10 -0
+
+	/*
+	 * Nobody would be insane enough to use PPIs on a secondary
+	 * GIC, right?
+	 */
+	if (gic == &gic_data[0]) {
+		nrppis = 16 - (irq_start & 15);
+		ppi_base = gic->irq_offset + 32 - nrppis;
+		ppi_irqaction = kzalloc(sizeof(*ppi_irqaction) * nrppis,
+					 GFP_KERNEL);

arch/arm/common/gic.c static void __init gic_dist_init(struct gic_chip_data *gic, · line 326

Quoted 10 lines
arch/arm/common/gic.c +10 -0
+		if (!ppi_irqaction) {
+			pr_err("GIC: Can't allocate PPI memory");
+			nrppis = 0;
+			ppi_base = 0;
+		}
+
+		for (i = 0; i < nrppis; i++)
+			ppi_irqaction[i] = ppi_irqaction_template[i + (ppi_base & 15)];
+		gic_nr_ppis = nrppis;
+		gic_ppi_base = ppi_base;

Would:

		ppi_irqaction = kmemdup(ppi_irqaction_template,
					sizeof(*ppi_irqaction) * nrppis,
					GFP_KERNEL);
		if (ppi_irqaction) {
			gic_nr_ppis = nrppis;
			gic_ppi_base = ppi_base;
		}

be a shorter way to write what you have above?

#3 lore raw

RFC PATCH v9 1/4 ARM: gic: consolidate PPI handling

Quoted 5 lines · Russell King - ARM Linux
Quoted 4 lines · Marc Zyngier
arch/arm/common/gic.c +0 -0
@@ -256,12 +260,33 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
 	irq_set_chained_handler(irq, gic_handle_cascade_irq);
 }
 
Quoted 7 lines

arch/arm/common/gic.c void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) · line 267

Quoted 5 lines
arch/arm/common/gic.c +5 -0
+static unsigned int gic_nr_ppis, gic_ppi_base;
+
+#define PPI_IRQACT(nr)						\
+	{							\
+		.handler	= percpu_timer_handler,		\

Won't this break on non-SMP non-localtimer builds?

Good point. I'd probably need to #ifdef that (as it was #ifdef'ed in the original code), and remove it in patch #2.

Quoted 44 lines
Quoted 11 lines
arch/arm/common/gic.c +11 -0
+		.flags		= IRQF_PERCPU | IRQF_TIMER,	\
+		.irq		= nr,				\
+		.name		= "PPI-" # nr,			\
+	}
+
+static struct irqaction ppi_irqaction_template[16] __initdata = {
+	PPI_IRQACT(0),  PPI_IRQACT(1),  PPI_IRQACT(2),  PPI_IRQACT(3),
+	PPI_IRQACT(4),  PPI_IRQACT(5),  PPI_IRQACT(6),  PPI_IRQACT(7),
+	PPI_IRQACT(8),  PPI_IRQACT(9),  PPI_IRQACT(10), PPI_IRQACT(11),
+	PPI_IRQACT(12), PPI_IRQACT(13), PPI_IRQACT(14), PPI_IRQACT(15),
+};

arch/arm/common/gic.c void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) · line 288

Quoted 10 lines
arch/arm/common/gic.c +4 -0
+
+static struct irqaction *ppi_irqaction;
+
 static void __init gic_dist_init(struct gic_chip_data *gic,
 	unsigned int irq_start)
 {
 	unsigned int gic_irqs, irq_limit, i;
 	void __iomem *base = gic->dist_base;
 	u32 cpumask = 1 << smp_processor_id();
+	u32 dist_ctr, nrcpus;

nrcpus doesn't seem to be used. With that eliminated, dist_ctr doesn't seem to have much purpose.

arch/arm/common/gic.c void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) · line 289

Quoted 1 line
arch/arm/common/gic.c +1 -0
+	u32 nrppis = 0, ppi_base = 0;

Might be better to move this inside the "if (gic == &gic_data[0]) {" block, along with the printk too.

Quoted 14 lines
arch/arm/common/gic.c +2 -2
 	cpumask |= cpumask << 8;
 	cpumask |= cpumask << 16;
@@ -272,11 +297,38 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
 	 * Find out how many interrupts are supported.
 	 * The GIC only supports up to 1020 interrupt sources.
 	 */
-	gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f;
-	gic_irqs = (gic_irqs + 1) * 32;
+	dist_ctr = readl_relaxed(base + GIC_DIST_CTR);
+	gic_irqs = ((dist_ctr & 0x1f) + 1) * 32;
 	if (gic_irqs > 1020)
 		gic_irqs = 1020;
 
Quoted 5 lines

arch/arm/common/gic.c static void __init gic_dist_init(struct gic_chip_data *gic, · line 306

Quoted 2 lines
arch/arm/common/gic.c +2 -0
+	/* Find out how many CPUs are supported (8 max). */
+	nrcpus = ((dist_ctr >> 5) & 7) + 1;

As mentioned above, the above change can be killed because it doesn't alter anything which is used.

Actually, all this really belongs to patch #2. Will move it there.

Quoted 30 lines
Quoted 10 lines
arch/arm/common/gic.c +10 -0
+
+	/*
+	 * Nobody would be insane enough to use PPIs on a secondary
+	 * GIC, right?
+	 */
+	if (gic == &gic_data[0]) {
+		nrppis = 16 - (irq_start & 15);
+		ppi_base = gic->irq_offset + 32 - nrppis;
+		ppi_irqaction = kzalloc(sizeof(*ppi_irqaction) * nrppis,
+					 GFP_KERNEL);

arch/arm/common/gic.c static void __init gic_dist_init(struct gic_chip_data *gic, · line 326

Quoted 10 lines
arch/arm/common/gic.c +10 -0
+		if (!ppi_irqaction) {
+			pr_err("GIC: Can't allocate PPI memory");
+			nrppis = 0;
+			ppi_base = 0;
+		}
+
+		for (i = 0; i < nrppis; i++)
+			ppi_irqaction[i] = ppi_irqaction_template[i + (ppi_base & 15)];
+		gic_nr_ppis = nrppis;
+		gic_ppi_base = ppi_base;

Would:

		ppi_irqaction = kmemdup(ppi_irqaction_template,
					sizeof(*ppi_irqaction) * nrppis,
					GFP_KERNEL);
		if (ppi_irqaction) {
			gic_nr_ppis = nrppis;
			gic_ppi_base = ppi_base;
		}
Quoted 1 line

be a shorter way to write what you have above?

Indeed. Will fix that in the next version.

Thanks for reviewing.

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

RFC PATCH v9 2/4 ARM: gic: Add PPI registration interface

In reply to Marc Zyngier

This patch makes it possible to request (and free) a PPI. It thus makes it useable for more than just the local timers.

Update TWD and MSM timers to use that functionnality.

Based on an earlier patch by Russell King.

---
 arch/arm/common/gic.c               |   82 +++++++++++++++++++++++++++++-----
 arch/arm/include/asm/hardware/gic.h |    5 ++-
 arch/arm/include/asm/localtimer.h   |    7 +++-
 arch/arm/include/asm/smp_twd.h      |    1 +
 arch/arm/kernel/smp.c               |    4 +-
 arch/arm/kernel/smp_twd.c           |   17 ++++++-
 arch/arm/mach-msm/timer.c           |   52 +++++++++++-----------
 7 files changed, 124 insertions(+), 44 deletions(-)
arch/arm/common/gic.c +70 -12
index 6a54c28..30ee245 100644
@@ -35,7 +35,6 @@
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
 #include <asm/hardware/gic.h>
-#include <asm/localtimer.h>
 
 static DEFINE_SPINLOCK(irq_controller_lock);
 
@@ -260,11 +259,29 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
 	irq_set_chained_handler(irq, gic_handle_cascade_irq);
 }
 
+struct gic_action {
+	irq_handler_t handler;
+	void *data;
+};
+
+static DEFINE_PER_CPU(struct gic_action *, gic_ppi_action);
 static unsigned int gic_nr_ppis, gic_ppi_base;
 
+static irqreturn_t gic_ppi_handler(int irq, void *dev_id)
+{
+	unsigned int ppi = irq - gic_ppi_base;
+	struct gic_action *act;
+
+	act = &__get_cpu_var(gic_ppi_action)[ppi];
+	if (likely(act->handler))
+		return act->handler(irq, act->data);
+
+	return IRQ_NONE;
+}
+
 #define PPI_IRQACT(nr)						\
 	{							\
-		.handler	= percpu_timer_handler,		\
+		.handler	= gic_ppi_handler,		\
 		.flags		= IRQF_PERCPU | IRQF_TIMER,	\
 		.irq		= nr,				\
 		.name		= "PPI-" # nr,			\
@@ -322,6 +339,14 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
 
 		for (i = 0; i < nrppis; i++)
 			ppi_irqaction[i] = ppi_irqaction_template[i + (ppi_base & 15)];
+		for (i = 0; i < nrcpus; i++) {
+			struct gic_action **ppiacts;
+
+			ppiacts = &per_cpu(gic_ppi_action, i);
+			*ppiacts = kzalloc(sizeof(*gic_ppi_action) * nrppis, GFP_KERNEL);
+			if (!*ppiacts)
+				pr_err("GIC: Can't allocate PPI CPU%d memory", i);
+		}
 		gic_nr_ppis = nrppis;
 		gic_ppi_base = ppi_base;
 	}
@@ -387,6 +412,49 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
 	writel_relaxed(1, base + GIC_DIST_CTRL);
 }
 
+int gic_request_ppi(unsigned int irq, irq_handler_t handler, void *data)
+{
+	struct gic_action *act;
+	unsigned long flags;
+	unsigned int ppi = irq - gic_ppi_base;
+	int ret = -EBUSY;
+
+	if (ppi >= gic_nr_ppis)
+		return -EINVAL;
+
+	local_irq_save(flags);
+	act = &__get_cpu_var(gic_ppi_action)[ppi];
+	if (!act->handler) {
+		act->handler = handler;
+		act->data = data;
+
+		gic_unmask_irq(irq_get_irq_data(irq));
+		ret = 0;
+	}
+	local_irq_restore(flags);
+
+	return ret;
+}
+
+void gic_free_ppi(unsigned int irq, void *data)
+{
+	struct gic_action *act;
+	unsigned long flags;
+	unsigned int ppi = irq - gic_ppi_base;
+
+	if (ppi >= gic_nr_ppis)
+		return;
+
+	local_irq_save(flags);
+	act = &__get_cpu_var(gic_ppi_action)[ppi];
+	if (act->data == data) {
+		gic_mask_irq(irq_get_irq_data(irq));
+		act->handler = NULL;
+		act->data = NULL;
+	}
+	local_irq_restore(flags);
+}
+
 static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
 {
 	void __iomem *dist_base = gic->dist_base;
@@ -436,16 +504,6 @@ void __cpuinit gic_secondary_init(unsigned int gic_nr)
 	gic_cpu_init(&gic_data[gic_nr]);
 }
 
-void __cpuinit gic_enable_ppi(unsigned int irq)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	irq_set_status_flags(irq, IRQ_NOPROBE);
-	gic_unmask_irq(irq_get_irq_data(irq));
-	local_irq_restore(flags);
-}
-
 #ifdef CONFIG_SMP
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 {
arch/arm/include/asm/hardware/gic.h +4 -1
index 435d3f8..b37780f 100644
@@ -33,6 +33,8 @@
 #define GIC_DIST_SOFTINT		0xf00
 
 #ifndef __ASSEMBLY__
+#include <linux/interrupt.h>
+
 extern void __iomem *gic_cpu_base_addr;
 extern struct irq_chip gic_arch_extn;
 
@@ -40,7 +42,8 @@ void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
 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);
+int gic_request_ppi(unsigned int irq, irq_handler_t handler, void *data);
+void gic_free_ppi(unsigned int irq, void *data);
 
 struct gic_chip_data {
 	unsigned int irq_offset;
arch/arm/include/asm/localtimer.h +6 -1
index e3663f7..9b0dfbb 100644
@@ -24,7 +24,6 @@ void percpu_timer_setup(void);
  */
 irqreturn_t percpu_timer_handler(int irq, void *dev_id);
 
-
 #ifdef CONFIG_LOCAL_TIMERS
 
 #ifdef CONFIG_HAVE_ARM_TWD
@@ -32,6 +31,7 @@ irqreturn_t percpu_timer_handler(int irq, void *dev_id);
 #include "smp_twd.h"
 
 #define local_timer_ack()	twd_timer_ack()
+#define local_timer_stop(c)	twd_timer_stop((c))
 
 #else
 
@@ -41,6 +41,11 @@ irqreturn_t percpu_timer_handler(int irq, void *dev_id);
  */
 int local_timer_ack(void);
 
+/*
+ * Stop the local timer
+ */
+void local_timer_stop(struct clock_event_device *);
+
 #endif
 
 /*
arch/arm/include/asm/smp_twd.h +1 -0
index fed9981..6923037 100644
@@ -24,5 +24,6 @@ extern void __iomem *twd_base;
 
 int twd_timer_ack(void);
 void twd_timer_setup(struct clock_event_device *);
+void twd_timer_stop(struct clock_event_device *);
 
 #endif
arch/arm/kernel/smp.c +2 -2
index c213f6a..9bcdbba 100644
@@ -456,7 +456,7 @@ static void ipi_timer(void)
 #ifdef CONFIG_LOCAL_TIMERS
 irqreturn_t percpu_timer_handler(int irq, void *dev_id)
 {
-	struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent);
+	struct clock_event_device *evt = dev_id;
 
 	if (local_timer_ack()) {
 		evt->event_handler(evt);
@@ -517,7 +517,7 @@ static void percpu_timer_stop(void)
 	unsigned int cpu = smp_processor_id();
 	struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
 
-	evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
+	local_timer_stop(evt);
 }
 #endif
 
arch/arm/kernel/smp_twd.c +15 -2
index 2c277d4..b2c4543 100644
@@ -19,6 +19,7 @@
 #include <linux/io.h>
 
 #include <asm/smp_twd.h>
+#include <asm/localtimer.h>
 #include <asm/hardware/gic.h>
 
 /* set up by the platform code */
@@ -80,6 +81,12 @@ int twd_timer_ack(void)
 	return 0;
 }
 
+void twd_timer_stop(struct clock_event_device *clk)
+{
+	twd_set_mode(CLOCK_EVT_MODE_UNUSED, clk);
+	gic_free_ppi(clk->irq, clk);
+}
+
 static void __cpuinit twd_calibrate_rate(void)
 {
 	unsigned long count;
@@ -124,6 +131,8 @@ static void __cpuinit twd_calibrate_rate(void)
  */
 void __cpuinit twd_timer_setup(struct clock_event_device *clk)
 {
+	int err;
+
 	twd_calibrate_rate();
 
 	clk->name = "local_timer";
@@ -137,8 +146,12 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk)
 	clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk);
 	clk->min_delta_ns = clockevent_delta2ns(0xf, clk);
 
-	/* Make sure our local interrupt controller has this enabled */
-	gic_enable_ppi(clk->irq);
+	err = gic_request_ppi(clk->irq, percpu_timer_handler, clk);
+	if (err) {
+		pr_err("%s: can't register interrupt %d on cpu %d (%d)\n",
+		       clk->name, clk->irq, smp_processor_id(), err);
+		return;
+	}
 
 	clockevents_register_device(clk);
 }
arch/arm/mach-msm/timer.c +26 -26

115 lines not on this page · raw message

Signature · 1 line
1.7.0.4
#5 lore raw

RFC PATCH v9 2/4 ARM: gic: Add PPI registration interface

arch/arm/mach-msm/timer.c int __cpuinit local_timer_setup(struct clock_event_device *evt) · line 292

Quoted 8 lines · Marc Zyngier
arch/arm/mach-msm/timer.c +1 -3
@@ -298,14 +289,23 @@ int __cpuinit local_timer_setup(struct clock_event_device *evt)
 		clockevent_delta2ns(0xf0000000 >> clock->shift, evt);
 	evt->min_delta_ns = clockevent_delta2ns(4, evt);
 
-	local_clock_event = evt;
-
-	gic_enable_ppi(clock->irq.irq);
+	res = git_request_ppi(evt->irq, msm_timer_interrupt, evt);

Typo, should be gic_request_ppi.

Jeff

Signature · 2 lines
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
#6 lore raw

RFC PATCH v9 2/4 ARM: gic: Add PPI registration interface

Quoted 11 lines · Jeff Ohlstein

arch/arm/mach-msm/timer.c int __cpuinit local_timer_setup(struct clock_event_device *evt) · line 292

Quoted 8 lines · Marc Zyngier
arch/arm/mach-msm/timer.c +1 -3
@@ -298,14 +289,23 @@ int __cpuinit local_timer_setup(struct clock_event_device *evt)
 		clockevent_delta2ns(0xf0000000 >> clock->shift, evt);
 	evt->min_delta_ns = clockevent_delta2ns(4, evt);
 
-	local_clock_event = evt;
-
-	gic_enable_ppi(clock->irq.irq);
+	res = git_request_ppi(evt->irq, msm_timer_interrupt, evt);

Typo, should be gic_request_ppi.

Doh... Thanks for noticing this.

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

RFC PATCH v9 3/4 ARM: local timers: drop local_timer_ack()

In reply to Marc Zyngier

Only TWD uses local_timer_ack() to perform something useful. Make it the real (private) interrupt handler, remove the common interrupt handler as well as the useless stubs from MCT and MSM.

Cc Kukjin Kim <[email protected]>
Cc David Brown <[email protected]>
---
 arch/arm/include/asm/localtimer.h |    7 -------
 arch/arm/include/asm/smp_twd.h    |    1 -
 arch/arm/kernel/smp.c             |   14 --------------
 arch/arm/kernel/smp_twd.c         |   17 +++++++----------
 arch/arm/mach-exynos4/mct.c       |    6 ------
 arch/arm/mach-msm/timer.c         |    6 ------
 6 files changed, 7 insertions(+), 44 deletions(-)
arch/arm/include/asm/localtimer.h +0 -7
index 9b0dfbb..12ce9f8 100644
@@ -30,18 +30,11 @@ irqreturn_t percpu_timer_handler(int irq, void *dev_id);
 
 #include "smp_twd.h"
 
-#define local_timer_ack()	twd_timer_ack()
 #define local_timer_stop(c)	twd_timer_stop((c))
 
 #else
 
 /*
- * Platform provides this to acknowledge a local timer IRQ.
- * Returns true if the local timer IRQ is to be processed.
- */
-int local_timer_ack(void);
-
-/*
  * Stop the local timer
  */
 void local_timer_stop(struct clock_event_device *);
arch/arm/include/asm/smp_twd.h +0 -1
index 6923037..ef9ffba 100644
@@ -22,7 +22,6 @@ struct clock_event_device;
 
 extern void __iomem *twd_base;
 
-int twd_timer_ack(void);
 void twd_timer_setup(struct clock_event_device *);
 void twd_timer_stop(struct clock_event_device *);
 
arch/arm/kernel/smp.c +0 -14
index 9bcdbba..882ab49 100644
@@ -453,20 +453,6 @@ static void ipi_timer(void)
 	irq_exit();
 }
 
-#ifdef CONFIG_LOCAL_TIMERS
-irqreturn_t percpu_timer_handler(int irq, void *dev_id)
-{
-	struct clock_event_device *evt = dev_id;
-
-	if (local_timer_ack()) {
-		evt->event_handler(evt);
-		return IRQ_HANDLED;
-	}
-
-	return IRQ_NONE;
-}
-#endif
-
 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
 static void smp_timer_broadcast(const struct cpumask *mask)
 {
arch/arm/kernel/smp_twd.c +7 -10
index b2c4543..1ad69f8 100644
@@ -65,20 +65,17 @@ static int twd_set_next_event(unsigned long evt,
 	return 0;
 }
 
-/*
- * local_timer_ack: checks for a local timer interrupt.
- *
- * If a local timer interrupt has occurred, acknowledge and return 1.
- * Otherwise, return 0.
- */
-int twd_timer_ack(void)
+static irqreturn_t twd_timer_handler(int irq, void *dev_id)
 {
+	struct clock_event_device *clk = dev_id;
+
 	if (__raw_readl(twd_base + TWD_TIMER_INTSTAT)) {
 		__raw_writel(1, twd_base + TWD_TIMER_INTSTAT);
-		return 1;
+		clk->event_handler(clk);
+		return IRQ_HANDLED;
 	}
 
-	return 0;
+	return IRQ_NONE;
 }
 
 void twd_timer_stop(struct clock_event_device *clk)
@@ -146,7 +143,7 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk)
 	clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk);
 	clk->min_delta_ns = clockevent_delta2ns(0xf, clk);
 
-	err = gic_request_ppi(clk->irq, percpu_timer_handler, clk);
+	err = gic_request_ppi(clk->irq, twd_timer_handler, clk);
 	if (err) {
 		pr_err("%s: can't register interrupt %d on cpu %d (%d)\n",
 		       clk->name, clk->irq, smp_processor_id(), err);
arch/arm/mach-exynos4/mct.c +0 -6
index 1ae059b..194fc6d 100644
@@ -393,12 +393,6 @@ void __cpuinit local_timer_setup(struct clock_event_device *evt)
 {
 	exynos4_mct_tick_init(evt);
 }
-
-int local_timer_ack(void)
-{
-	return 0;
-}
-
 #endif /* CONFIG_LOCAL_TIMERS */
 
 static void __init exynos4_timer_resources(void)
arch/arm/mach-msm/timer.c +0 -6
index 0f49b5c..02f03f4 100644
@@ -305,12 +305,6 @@ void local_timer_stop(struct clock_event_device *evt)
 	evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
 	gic_free_ppi(evt->irq, evt);
 }
-
-inline int local_timer_ack(void)
-{
-	return 1;
-}
-
 #endif
 
 struct sys_timer msm_timer = {
Signature · 1 line
1.7.0.4
#8 lore raw

RFC PATCH v9 4/4 ARM: gic: add compute_irqnr macro for exynos4

In reply to Marc Zyngier

exynos4 has a full copy of entry-macro-gic.S, just for the sake of an offset added to the IRQ number read from the GIC.

Add a compute_irqnr macro to entry-macro-gic.S so that any platform can add it's own hook without having to copy the whole file again.

---
 arch/arm/include/asm/hardware/entry-macro-gic.S  |    3 +
 arch/arm/mach-exynos4/include/mach/entry-macro.S |   57 +++-------------------
 2 files changed, 10 insertions(+), 50 deletions(-)
arch/arm/include/asm/hardware/entry-macro-gic.S +3 -0
index 74ebc80..fbb50dc 100644
@@ -43,6 +43,9 @@
 	cmpcc	\irqnr, \irqnr
 	cmpne	\irqnr, \tmp
 	cmpcs	\irqnr, \irqnr
+#ifdef HAVE_GIC_BASE_OFFSET
+	compute_irqnr	\irqnr, \tmp
+#endif
 	.endm
 
 /* We assume that irqstat (the raw value of the IRQ acknowledge
arch/arm/mach-exynos4/include/mach/entry-macro.S +7 -50

75 lines not on this page · raw message

Signature · 1 line
1.7.0.4
#9 lore raw

v9 cover Consolidating GIC per-cpu interrupts

In reply to Marc Zyngier
Quoted 3 lines · Marc Zyngier

The current GIC per-cpu interrupts (aka PPIs) suffer from a number of problems:

[snip]

Quoted 4 lines

Patches against next-20110721, tested on PB11MP. As this patch series is quite different from the previous one, I've dropped all previous acks from platform maintainers.

I tried this out the other day and it didn't work. The setup_irq() calls in msm timer code fails and then we calibrate delay forever. I haven't looked further.

Signature · 2 lines
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
#10 lore raw

v9 cover Consolidating GIC per-cpu interrupts

Quoted 6 lines · Stephen Boyd
Quoted 3 lines · Marc Zyngier

The current GIC per-cpu interrupts (aka PPIs) suffer from a number of problems:

[snip]

Quoted 1 line
Quoted 7 lines
Quoted 3 lines

Patches against next-20110721, tested on PB11MP. As this patch series is quite different from the previous one, I've dropped all previous acks from platform maintainers.

I tried this out the other day and it didn't work. The setup_irq() calls in msm timer code fails and then we calibrate delay forever. I haven't looked further.

Ah, of course. Need to do a gic_request_ppi() on CPU0's timer instead of request_irq(), but only on msm8x60/msm8960. Not very nice.

I'll update the patches and repost them later today.

Cheers,

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