[linux-yocto] [PATCH 08/78] arm/mach-axxia: fix error with IRQ type setting at startup

Paul Butler butler.paul at gmail.com
Tue Nov 19 20:22:44 PST 2013


From: David Mercado <david.mercado at windriver.com>

This patch fixes the errors reported by gic_set_type() when booting a
kernel that's configured for more cores than the simulator has enabled
(i.e., the DTS file has more cores enabled than cores enabled in the
simulator topology.xml file).  The driver now checks if a cpu is online
prior to attempting to set its IRQ type.

Signed-off-by: David Mercado <david.mercado at windriver.com>
---
 arch/arm/mach-axxia/axxia-gic.c | 47 +++++++++++++++++++++++------------------
 1 file changed, 27 insertions(+), 20 deletions(-)

diff --git a/arch/arm/mach-axxia/axxia-gic.c b/arch/arm/mach-axxia/axxia-gic.c
index c074f6c..f899188 100644
--- a/arch/arm/mach-axxia/axxia-gic.c
+++ b/arch/arm/mach-axxia/axxia-gic.c
@@ -310,7 +310,7 @@ static void gic_set_type_wrapper(void *data)
 static int gic_set_type(struct irq_data *d, unsigned int type)
 {
 #ifdef CONFIG_SMP
-	int i, nr_cluster_ids = ((nr_cpu_ids-1) / 4) + 1;
+	int i, cpu, nr_cluster_ids = ((nr_cpu_ids-1) / 4) + 1;
 	unsigned int gicirq = gic_irq(d);
 	u32 pcpu = cpu_logical_map(smp_processor_id());
 	struct gic_set_type_wrapper_struct data;
@@ -337,19 +337,23 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
 		if (i == (pcpu/4))
 			continue;
 
-		/*
-		 * We are running here with local interrupts
-		 * disabled. Temporarily re-enable them to
-		 * avoid possible deadlock when calling
-		 * smp_call_function_single().
-		 */
-		local_irq_enable();
-		smp_call_function_single((i * 4),
-			 gic_set_type_wrapper, &data, 1);
-		local_irq_disable();
-		if (data.status != 0)
-			printk(KERN_ERR "gic_set_type() error (%d)!\n",
-			       data.status);
+		/* Have the first cpu in each cluster execute this. */
+		cpu = i * 4;
+		if (cpu_online(cpu)) {
+			/*
+			 * We are running here with local interrupts
+			 * disabled. Temporarily re-enable them to
+			 * avoid possible deadlock when calling
+			 * smp_call_function_single().
+			 */
+			local_irq_enable();
+			smp_call_function_single(cpu, gic_set_type_wrapper,
+						 &data, 1);
+			local_irq_disable();
+			if (data.status != 0)
+				pr_err("Failed to set IRQ type for cpu%d\n",
+				       cpu);
+		}
 	}
 #endif
 	return _gic_set_type(d, type);
@@ -892,7 +896,7 @@ static void gic_notifier_wrapper(void *data)
 
 static int gic_notifier(struct notifier_block *self, unsigned long cmd,	void *v)
 {
-	int i;
+	int i, cpu;
 	struct gic_notifier_wrapper_struct data;
 	int nr_cluster_ids = ((nr_cpu_ids-1) / 4) + 1;
 	u32 pcpu = cpu_logical_map(smp_processor_id());
@@ -907,11 +911,14 @@ static int gic_notifier(struct notifier_block *self, unsigned long cmd,	void *v)
 			continue;
 
 		/* Have the first cpu in each cluster execute this. */
-		local_irq_enable(); /* Temporarily re-enable interrupts. */
-		smp_call_function_single((i * 4),
-					 gic_notifier_wrapper,
-					 &data, 0);
-		local_irq_disable();
+		cpu = i * 4;
+		if (cpu_online(cpu)) {
+			local_irq_enable();
+			smp_call_function_single(cpu,
+						 gic_notifier_wrapper,
+						 &data, 0);
+			local_irq_disable();
+		}
 	}
 
 	/* Execute on this cluster. */
-- 
1.8.4.3



More information about the linux-yocto mailing list