From 05ff3004d278b54760abd71530506d803182c71d Mon Sep 17 00:00:00 2001
From: Paul Mundt <lethal@linux-sh.org>
Date: Fri, 22 May 2009 01:28:33 +0900
Subject: sh: irq: Teach ipr and intc about dynamically allocating irq_descs.

This hooks in irq_to_desc_alloc_cpu() to the necessary code paths in the
intc and ipr controller registration paths. As these are the primary call
paths for all SH CPUs, this alone will make all CPUs sparse IRQ ready.

There is the added benefit now that each CPU contains specific IPR and
INTC tables, so only the vectors with interrupt sources backing them will
ever see an irq_desc instantiation. This effectively packs irq_desc
down to match the CPU, rather than padding NR_IRQS out to cover the valid
vector range.

Boards with extra sources will still have to fiddle with the nr_irqs
setting, but they can continue doing so through the machvec as before.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
---
 drivers/sh/intc.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

(limited to 'drivers/sh')

diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c
index 12d13d99b6f..098b767e9af 100644
--- a/drivers/sh/intc.c
+++ b/drivers/sh/intc.c
@@ -671,7 +671,7 @@ unsigned int intc_evt2irq(unsigned int vector)
 
 void __init register_intc_controller(struct intc_desc *desc)
 {
-	unsigned int i, k, smp;
+	unsigned int i, k, smp, cpu = smp_processor_id();
 	struct intc_desc_int *d;
 
 	d = alloc_bootmem(sizeof(*d));
@@ -770,11 +770,19 @@ void __init register_intc_controller(struct intc_desc *desc)
 	/* register the vectors one by one */
 	for (i = 0; i < desc->nr_vectors; i++) {
 		struct intc_vect *vect = desc->vectors + i;
+		unsigned int irq = evt2irq(vect->vect);
+		struct irq_desc *irq_desc;
 
 		if (!vect->enum_id)
 			continue;
 
-		intc_register_irq(desc, d, vect->enum_id, evt2irq(vect->vect));
+		irq_desc = irq_to_desc_alloc_cpu(irq, cpu);
+		if (unlikely(!irq_desc)) {
+			printk(KERN_INFO "can not get irq_desc for %d\n", irq);
+			continue;
+		}
+
+		intc_register_irq(desc, d, vect->enum_id, irq);
 	}
 }
 
-- 
cgit v1.2.3-70-g09d2


From 2f3ed17e010e8c0873094016f93c1afbb4adb666 Mon Sep 17 00:00:00 2001
From: Paul Mundt <lethal@linux-sh.org>
Date: Fri, 22 May 2009 13:47:52 +0900
Subject: sh: Wrap irq_to_desc_alloc_cpu() around CONFIG_SPARSE_IRQ
 temporarily.

irq_to_desc_alloc_cpu() has been renamed to irq_to_desc_alloc_node() in
-next, but as we can not presently enable SPARSE_IRQ without the early
irq_desc alloc patch, protect it with an ifdef until the interface has
settled and we are ready to enable it system-wide.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
---
 arch/sh/kernel/cpu/irq/ipr.c | 4 ++++
 drivers/sh/intc.c            | 5 ++++-
 2 files changed, 8 insertions(+), 1 deletion(-)

(limited to 'drivers/sh')

diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c
index fa0c8467a28..6ad40dbad88 100644
--- a/arch/sh/kernel/cpu/irq/ipr.c
+++ b/arch/sh/kernel/cpu/irq/ipr.c
@@ -59,17 +59,21 @@ void register_ipr_controller(struct ipr_desc *desc)
 
 	for (i = 0; i < desc->nr_irqs; i++) {
 		struct ipr_data *p = desc->ipr_data + i;
+#ifdef CONFIG_SPARSE_IRQ
 		struct irq_desc *irq_desc;
+#endif
 
 		BUG_ON(p->ipr_idx >= desc->nr_offsets);
 		BUG_ON(!desc->ipr_offsets[p->ipr_idx]);
 
+#ifdef CONFIG_SPARSE_IRQ
 		irq_desc = irq_to_desc_alloc_cpu(p->irq, smp_processor_id());
 		if (unlikely(!irq_desc)) {
 			printk(KERN_INFO "can not get irq_desc for %d\n",
 			       p->irq);
 			continue;
 		}
+#endif
 
 		disable_irq_nosync(p->irq);
 		set_irq_chip_and_handler_name(p->irq, &desc->chip,
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c
index 098b767e9af..caf06569404 100644
--- a/drivers/sh/intc.c
+++ b/drivers/sh/intc.c
@@ -771,16 +771,19 @@ void __init register_intc_controller(struct intc_desc *desc)
 	for (i = 0; i < desc->nr_vectors; i++) {
 		struct intc_vect *vect = desc->vectors + i;
 		unsigned int irq = evt2irq(vect->vect);
+#ifdef CONFIG_SPARSE_IRQ
 		struct irq_desc *irq_desc;
-
+#endif
 		if (!vect->enum_id)
 			continue;
 
+#ifdef CONFIG_SPARSE_IRQ
 		irq_desc = irq_to_desc_alloc_cpu(irq, cpu);
 		if (unlikely(!irq_desc)) {
 			printk(KERN_INFO "can not get irq_desc for %d\n", irq);
 			continue;
 		}
+#endif
 
 		intc_register_irq(desc, d, vect->enum_id, irq);
 	}
-- 
cgit v1.2.3-70-g09d2


From 54ff328b46e58568c4b3350c2fa3223ef862e5a4 Mon Sep 17 00:00:00 2001
From: Paul Mundt <lethal@linux-sh.org>
Date: Thu, 11 Jun 2009 10:33:09 +0300
Subject: sh: Tie sparseirq in to Kconfig.

Now that the dependent patches are merged, we are ready to enable
sparseirq support. This simply adds the Kconfig option, and then converts
from the _cpu to the _node allocation routines to follow the upstream
sparseirq API changes.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
---
 arch/sh/Kconfig              | 12 ++++++++++++
 arch/sh/kernel/cpu/irq/ipr.c |  7 ++-----
 drivers/sh/intc.c            | 10 ++++------
 3 files changed, 18 insertions(+), 11 deletions(-)

(limited to 'drivers/sh')

diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index b5629cdc37a..586cd045e2d 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -678,6 +678,18 @@ config GUSA_RB
 	  LLSC, this should be more efficient than the other alternative of
 	  disabling interrupts around the atomic sequence.
 
+config SPARSE_IRQ
+	bool "Support sparse irq numbering"
+	depends on EXPERIMENTAL
+	help
+	  This enables support for sparse irqs. This is useful in general
+	  as most CPUs have a fairly sparse array of IRQ vectors, which
+	  the irq_desc then maps directly on to. Systems with a high
+	  number of off-chip IRQs will want to treat this as
+	  experimental until they have been independently verified.
+
+	  If you don't know what to do here, say N.
+
 endmenu
 
 menu "Boot options"
diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c
index 6ad40dbad88..808d99a48ef 100644
--- a/arch/sh/kernel/cpu/irq/ipr.c
+++ b/arch/sh/kernel/cpu/irq/ipr.c
@@ -21,6 +21,7 @@
 #include <linux/module.h>
 #include <linux/io.h>
 #include <linux/interrupt.h>
+#include <linux/topology.h>
 
 static inline struct ipr_desc *get_ipr_desc(unsigned int irq)
 {
@@ -59,21 +60,17 @@ void register_ipr_controller(struct ipr_desc *desc)
 
 	for (i = 0; i < desc->nr_irqs; i++) {
 		struct ipr_data *p = desc->ipr_data + i;
-#ifdef CONFIG_SPARSE_IRQ
 		struct irq_desc *irq_desc;
-#endif
 
 		BUG_ON(p->ipr_idx >= desc->nr_offsets);
 		BUG_ON(!desc->ipr_offsets[p->ipr_idx]);
 
-#ifdef CONFIG_SPARSE_IRQ
-		irq_desc = irq_to_desc_alloc_cpu(p->irq, smp_processor_id());
+		irq_desc = irq_to_desc_alloc_node(p->irq, numa_node_id());
 		if (unlikely(!irq_desc)) {
 			printk(KERN_INFO "can not get irq_desc for %d\n",
 			       p->irq);
 			continue;
 		}
-#endif
 
 		disable_irq_nosync(p->irq);
 		set_irq_chip_and_handler_name(p->irq, &desc->chip,
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c
index caf06569404..d687a9b93d0 100644
--- a/drivers/sh/intc.c
+++ b/drivers/sh/intc.c
@@ -24,6 +24,7 @@
 #include <linux/sh_intc.h>
 #include <linux/sysdev.h>
 #include <linux/list.h>
+#include <linux/topology.h>
 
 #define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \
 	((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \
@@ -671,7 +672,7 @@ unsigned int intc_evt2irq(unsigned int vector)
 
 void __init register_intc_controller(struct intc_desc *desc)
 {
-	unsigned int i, k, smp, cpu = smp_processor_id();
+	unsigned int i, k, smp;
 	struct intc_desc_int *d;
 
 	d = alloc_bootmem(sizeof(*d));
@@ -771,19 +772,16 @@ void __init register_intc_controller(struct intc_desc *desc)
 	for (i = 0; i < desc->nr_vectors; i++) {
 		struct intc_vect *vect = desc->vectors + i;
 		unsigned int irq = evt2irq(vect->vect);
-#ifdef CONFIG_SPARSE_IRQ
 		struct irq_desc *irq_desc;
-#endif
+
 		if (!vect->enum_id)
 			continue;
 
-#ifdef CONFIG_SPARSE_IRQ
-		irq_desc = irq_to_desc_alloc_cpu(irq, cpu);
+		irq_desc = irq_to_desc_alloc_node(irq, numa_node_id());
 		if (unlikely(!irq_desc)) {
 			printk(KERN_INFO "can not get irq_desc for %d\n", irq);
 			continue;
 		}
-#endif
 
 		intc_register_irq(desc, d, vect->enum_id, irq);
 	}
-- 
cgit v1.2.3-70-g09d2


From 11b6aa9555d0c2f4d195695cd151e1fd07413387 Mon Sep 17 00:00:00 2001
From: Paul Mundt <lethal@linux-sh.org>
Date: Fri, 12 Jun 2009 01:34:12 +0300
Subject: sh: intc: alloc_bootmem() -> kzalloc() conversion.

Now that the slab allocators are available much earlier, this triggers a
the slab_is_available() warning when registering the interrupt
controller. Convert to kzalloc() with GFP_NOWAIT, as per the generic
changes.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
---
 drivers/sh/intc.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

(limited to 'drivers/sh')

diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c
index d687a9b93d0..3dd231a643b 100644
--- a/drivers/sh/intc.c
+++ b/drivers/sh/intc.c
@@ -20,7 +20,6 @@
 #include <linux/module.h>
 #include <linux/io.h>
 #include <linux/interrupt.h>
-#include <linux/bootmem.h>
 #include <linux/sh_intc.h>
 #include <linux/sysdev.h>
 #include <linux/list.h>
@@ -675,7 +674,7 @@ void __init register_intc_controller(struct intc_desc *desc)
 	unsigned int i, k, smp;
 	struct intc_desc_int *d;
 
-	d = alloc_bootmem(sizeof(*d));
+	d = kzalloc(sizeof(*d), GFP_NOWAIT);
 
 	INIT_LIST_HEAD(&d->list);
 	list_add(&d->list, &intc_list);
@@ -687,9 +686,9 @@ void __init register_intc_controller(struct intc_desc *desc)
 #if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
 	d->nr_reg += desc->ack_regs ? desc->nr_ack_regs : 0;
 #endif
-	d->reg = alloc_bootmem(d->nr_reg * sizeof(*d->reg));
+	d->reg = kzalloc(d->nr_reg * sizeof(*d->reg), GFP_NOWAIT);
 #ifdef CONFIG_SMP
-	d->smp = alloc_bootmem(d->nr_reg * sizeof(*d->smp));
+	d->smp = kzalloc(d->nr_reg * sizeof(*d->smp), GFP_NOWAIT);
 #endif
 	k = 0;
 
@@ -702,7 +701,7 @@ void __init register_intc_controller(struct intc_desc *desc)
 	}
 
 	if (desc->prio_regs) {
-		d->prio = alloc_bootmem(desc->nr_vectors * sizeof(*d->prio));
+		d->prio = kzalloc(desc->nr_vectors * sizeof(*d->prio), GFP_NOWAIT);
 
 		for (i = 0; i < desc->nr_prio_regs; i++) {
 			smp = IS_SMP(desc->prio_regs[i]);
@@ -712,7 +711,7 @@ void __init register_intc_controller(struct intc_desc *desc)
 	}
 
 	if (desc->sense_regs) {
-		d->sense = alloc_bootmem(desc->nr_vectors * sizeof(*d->sense));
+		d->sense = kzalloc(desc->nr_vectors * sizeof(*d->sense), GFP_NOWAIT);
 
 		for (i = 0; i < desc->nr_sense_regs; i++) {
 			k += save_reg(d, k, desc->sense_regs[i].reg, 0);
@@ -757,7 +756,7 @@ void __init register_intc_controller(struct intc_desc *desc)
 			vect2->enum_id = 0;
 
 			if (!intc_evt2irq_table)
-				intc_evt2irq_table = alloc_bootmem(NR_IRQS);
+				intc_evt2irq_table = kzalloc(NR_IRQS, GFP_NOWAIT);
 
 			if (!intc_evt2irq_table) {
 				pr_warning("intc: cannot allocate evt2irq!\n");
-- 
cgit v1.2.3-70-g09d2