Re: [PATCH v2] [ARM] gic: Unmask private interrupts on all cores during IRQ enable

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Russell,

Can you pull in this patch or let me know if you want something changed with it?

Thanks,
Stephen

On 11/03/2010 05:46 PM, Stephen Caudle wrote:
Some multi-core ARM chips designate a unique IRQ number for each core for
private peripheral interrupts (PPIs). Others designate a common IRQ number
for all cores. In the latter case, requesting/freeing private peripheral
interrupts currently unmasks/masks the interrupt for only the
executing core, respectively.

With this change, request_irq will unmask a PPI on all cores so a separate
call to enable_irq on the other cores is not required. Likewise, free_irq
will mask a PPI on the other cores. Also, shutdown is implemented instead
of disable to allow for lazy IRQ disabling.

Signed-off-by: Stephen Caudle<scaudle@xxxxxxxxxxxxxx>
---
  arch/arm/Kconfig      |    5 +++
  arch/arm/common/gic.c |   86 +++++++++++++++++++++++++++++++++++++++++++++++++
  2 files changed, 91 insertions(+), 0 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 30ddd06..7f11e31 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1153,6 +1153,11 @@ config SMP

  	  If you don't know what to do here, say N.

+config IRQ_PER_CPU
+	bool
+	depends on SMP
+	default n
+
  config HAVE_ARM_SCU
  	bool
  	depends on SMP
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 886daaf..937a33a 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -44,12 +44,25 @@ struct gic_chip_data {
  	unsigned int wakeup_irqs[32];
  	unsigned int enabled_irqs[32];
  #endif
+#ifdef CONFIG_IRQ_PER_CPU
+	struct call_single_data ppi_data[NR_CPUS];
+#endif
  };

  #ifndef MAX_GIC_NR
  #define MAX_GIC_NR	1
  #endif

+#ifdef CONFIG_IRQ_PER_CPU
+#ifndef GIC_PPI_FIRST
+#define GIC_PPI_FIRST	16
+#endif
+
+#ifndef GIC_PPI_LAST
+#define GIC_PPI_LAST	31
+#endif
+#endif
+
  static struct gic_chip_data gic_data[MAX_GIC_NR];

  static inline void __iomem *gic_dist_base(unsigned int irq)
@@ -272,6 +285,75 @@ static int gic_set_type(unsigned int irq, unsigned int type)
  	return 0;
  }

+#ifdef CONFIG_IRQ_PER_CPU
+static inline void gic_smp_call_function(struct call_single_data *data)
+{
+	int cpu;
+
+	/* Make sure data is visible */
+	smp_mb();
+
+	/*
+	 * Since this function is called with interrupts disabled,
+	 * smp_call_function can't be used here because it warns (even
+	 * if wait = 0) when interrupts are disabled.
+	 *
+	 * __smp_call_function_single doesn't warn when interrupts are
+	 * disabled and not waiting, so use it instead.
+	 */
+	for_each_online_cpu(cpu)
+		if (cpu != smp_processor_id())
+			__smp_call_function_single(cpu, data, 0);
+}
+
+static void gic_mask_ppi(void *info)
+{
+	struct irq_desc *desc = info;
+	gic_mask_irq(desc->irq);
+}
+
+static void gic_unmask_ppi(void *info)
+{
+	struct irq_desc *desc = info;
+	gic_unmask_irq(desc->irq);
+}
+
+static void gic_enable_irq(unsigned int irq)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+	struct gic_chip_data *gic_data = get_irq_chip_data(irq);
+	int cpu = smp_processor_id();
+
+	if (irq>= GIC_PPI_FIRST&&  irq<= GIC_PPI_LAST) {
+		gic_data->ppi_data[cpu].func = gic_unmask_ppi;
+		gic_data->ppi_data[cpu].info = desc;
+
+		/* Unmask PPIs on all cores during enable. */
+		gic_smp_call_function(&gic_data->ppi_data[cpu]);
+	}
+
+	desc->chip->unmask(irq);
+	desc->status&= ~IRQ_MASKED;
+}
+
+static void gic_shutdown_irq(unsigned int irq)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+	struct gic_chip_data *gic_data = get_irq_chip_data(irq);
+	int cpu = smp_processor_id();
+
+	if (irq>= GIC_PPI_FIRST&&  irq<= GIC_PPI_LAST) {
+		gic_data->ppi_data[cpu].func = gic_mask_ppi;
+		gic_data->ppi_data[cpu].info = desc;
+
+		/* Mask PPIs on all cores during disable. */
+		gic_smp_call_function(&gic_data->ppi_data[cpu]);
+	}
+
+	desc->chip->mask(irq);
+	desc->status |= IRQ_MASKED;
+}
+#endif

  static struct irq_chip gic_chip = {
  	.name		= "GIC",
@@ -283,6 +365,10 @@ static struct irq_chip gic_chip = {
  #endif
  	.set_type	= gic_set_type,
  	.set_wake	= gic_set_wake,
+#ifdef CONFIG_IRQ_PER_CPU
+	.enable		= gic_enable_irq,
+	.shutdown	= gic_shutdown_irq,
+#endif
  };

  void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)


--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [Linux for Sparc]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux