All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/8] Add self-probe infrastructure and stacked irqdomain support for ACPI based GICv2/3 init
@ 2015-07-10 10:45 ` Hanjun Guo
  0 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-10 10:45 UTC (permalink / raw)
  To: Marc Zyngier, Jason Cooper, Will Deacon, Catalin Marinas,
	Rafael J. Wysocki
  Cc: Thomas Gleixner, Jiang Liu, Lorenzo Pieralisi, Arnd Bergmann,
	Tomasz Nowicki, Grant Likely, Mark Brown, Wei Huang,
	linux-arm-kernel, linux-acpi, linux-kernel, linaro-acpi,
	Hanjun Guo

This patch set introduce self-probe infrastructure to init IRQ
controllers and stacked irqdomain support for ACPI based GICv2/3
init.

This patch set add its support for GIC verion which is introduced
in ACPI 6.0, based on that, we introduce the self-probe infrastructure,
the self-probe infrastructure for ACPI GIC init is similar as
IRQCHIP_DECLARE() and based on the GIC version support in ACPI
MADT table. we match the GIC version and GIC driver and load
it.

After the self-probe infrastructure is ready, I cleanuped the GICv2
code to use the framework.

Patch 4 implement the stacked irqdomain support for GICv2 based on
the model of mapping interrupt and device in ACPI.

Patch 5~8 are ACPI based GICv3 init.

Any comments are warmly welcomed.

v2->v3:
 - Introduced a mechanism to match the GSI with its irqdomain instead of
   referring to the acpi_irq_domain in previous version

 - Add finding GICR base address in GICC structures in GICv3 code.

 - Address the comments from Lorenzo and Marc

 - Rebased on top of 4.2-rc1, since ACPICA patches were pushed to
   4.2 by Rafael, I removed ACPICA patches in previous version.

v1->v2:
 - Remove the gicv2/v3 related driver code in drivers/irqchip/irq-gic-acpi.c
   which I was trying to consolidate them in one file, then arm-gic.h and
   arm-gic-v3.h will be used separately within parent driver only

 - Drop the gsi_mutex patch

 - Use the GIC version to match the GIC driver, then no need to test
   for the version in each driver

 - Move acpi_irq_init() to drivers/irqchip/irq-gic-acpi.c instead of
   in drivers/acpi/irq.c. maybe we need to rename acpi_irq_init() as
   acpi_gic_init() but I keep that name to accommodate of_irq_init(),
   any objections please let me know.

update from RFC version:
 - Consolidate all the GIC init code into drivers/irqchip/irq-gic-acpi.c


Hanjun Guo (6):
  irqchip / GIC: Add GIC version support in ACPI MADT
  ACPI / irqchip: Add self-probe infrastructure to initialize IRQ
    controller
  irqchip / GIC / ACPI: Use IRQCHIP_ACPI_DECLARE to simplify GICv2 init
    code
  irqchip / gic: Add stacked irqdomain support for ACPI based GICv2 init
  irqchip / GICv3: Add stacked irqdomain support for ACPI based init
  irqchip / gicv3 / ACPI: Add GICR support via GICC structures

Tomasz Nowicki (2):
  irqchip / GICv3: Refactor gic_of_init() for GICv3 driver
  irqchip / GICv3: Add ACPI support for GICv3+ initialization

 arch/arm64/Kconfig                   |   1 +
 arch/arm64/include/asm/acpi.h        |   1 -
 arch/arm64/include/asm/irq.h         |  13 --
 arch/arm64/kernel/acpi.c             |  25 --
 drivers/acpi/gsi.c                   |  78 +++++--
 drivers/irqchip/Kconfig              |   3 +
 drivers/irqchip/Makefile             |   1 +
 drivers/irqchip/irq-gic-acpi.c       | 171 ++++++++++++++
 drivers/irqchip/irq-gic-v3.c         | 427 ++++++++++++++++++++++++++++++-----
 drivers/irqchip/irq-gic.c            |  40 ++--
 include/asm-generic/vmlinux.lds.h    |  13 ++
 include/linux/acpi.h                 |  21 ++
 include/linux/acpi_irq.h             |   4 +-
 include/linux/irqchip.h              |  13 ++
 include/linux/irqchip/arm-gic-acpi.h |  10 +-
 include/linux/mod_devicetable.h      |   8 +
 16 files changed, 695 insertions(+), 134 deletions(-)
 create mode 100644 drivers/irqchip/irq-gic-acpi.c

-- 
1.9.1


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH v3 0/8] Add self-probe infrastructure and stacked irqdomain support for ACPI based GICv2/3 init
@ 2015-07-10 10:45 ` Hanjun Guo
  0 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-10 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

This patch set introduce self-probe infrastructure to init IRQ
controllers and stacked irqdomain support for ACPI based GICv2/3
init.

This patch set add its support for GIC verion which is introduced
in ACPI 6.0, based on that, we introduce the self-probe infrastructure,
the self-probe infrastructure for ACPI GIC init is similar as
IRQCHIP_DECLARE() and based on the GIC version support in ACPI
MADT table. we match the GIC version and GIC driver and load
it.

After the self-probe infrastructure is ready, I cleanuped the GICv2
code to use the framework.

Patch 4 implement the stacked irqdomain support for GICv2 based on
the model of mapping interrupt and device in ACPI.

Patch 5~8 are ACPI based GICv3 init.

Any comments are warmly welcomed.

v2->v3:
 - Introduced a mechanism to match the GSI with its irqdomain instead of
   referring to the acpi_irq_domain in previous version

 - Add finding GICR base address in GICC structures in GICv3 code.

 - Address the comments from Lorenzo and Marc

 - Rebased on top of 4.2-rc1, since ACPICA patches were pushed to
   4.2 by Rafael, I removed ACPICA patches in previous version.

v1->v2:
 - Remove the gicv2/v3 related driver code in drivers/irqchip/irq-gic-acpi.c
   which I was trying to consolidate them in one file, then arm-gic.h and
   arm-gic-v3.h will be used separately within parent driver only

 - Drop the gsi_mutex patch

 - Use the GIC version to match the GIC driver, then no need to test
   for the version in each driver

 - Move acpi_irq_init() to drivers/irqchip/irq-gic-acpi.c instead of
   in drivers/acpi/irq.c. maybe we need to rename acpi_irq_init() as
   acpi_gic_init() but I keep that name to accommodate of_irq_init(),
   any objections please let me know.

update from RFC version:
 - Consolidate all the GIC init code into drivers/irqchip/irq-gic-acpi.c


Hanjun Guo (6):
  irqchip / GIC: Add GIC version support in ACPI MADT
  ACPI / irqchip: Add self-probe infrastructure to initialize IRQ
    controller
  irqchip / GIC / ACPI: Use IRQCHIP_ACPI_DECLARE to simplify GICv2 init
    code
  irqchip / gic: Add stacked irqdomain support for ACPI based GICv2 init
  irqchip / GICv3: Add stacked irqdomain support for ACPI based init
  irqchip / gicv3 / ACPI: Add GICR support via GICC structures

Tomasz Nowicki (2):
  irqchip / GICv3: Refactor gic_of_init() for GICv3 driver
  irqchip / GICv3: Add ACPI support for GICv3+ initialization

 arch/arm64/Kconfig                   |   1 +
 arch/arm64/include/asm/acpi.h        |   1 -
 arch/arm64/include/asm/irq.h         |  13 --
 arch/arm64/kernel/acpi.c             |  25 --
 drivers/acpi/gsi.c                   |  78 +++++--
 drivers/irqchip/Kconfig              |   3 +
 drivers/irqchip/Makefile             |   1 +
 drivers/irqchip/irq-gic-acpi.c       | 171 ++++++++++++++
 drivers/irqchip/irq-gic-v3.c         | 427 ++++++++++++++++++++++++++++++-----
 drivers/irqchip/irq-gic.c            |  40 ++--
 include/asm-generic/vmlinux.lds.h    |  13 ++
 include/linux/acpi.h                 |  21 ++
 include/linux/acpi_irq.h             |   4 +-
 include/linux/irqchip.h              |  13 ++
 include/linux/irqchip/arm-gic-acpi.h |  10 +-
 include/linux/mod_devicetable.h      |   8 +
 16 files changed, 695 insertions(+), 134 deletions(-)
 create mode 100644 drivers/irqchip/irq-gic-acpi.c

-- 
1.9.1

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH v3 1/8] irqchip / GIC: Add GIC version support in ACPI MADT
  2015-07-10 10:45 ` Hanjun Guo
@ 2015-07-10 10:45   ` Hanjun Guo
  -1 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-10 10:45 UTC (permalink / raw)
  To: Marc Zyngier, Jason Cooper, Will Deacon, Catalin Marinas,
	Rafael J. Wysocki
  Cc: Thomas Gleixner, Jiang Liu, Lorenzo Pieralisi, Arnd Bergmann,
	Tomasz Nowicki, Grant Likely, Mark Brown, Wei Huang,
	linux-arm-kernel, linux-acpi, linux-kernel, linaro-acpi,
	Hanjun Guo

There is a field added in ACPI 6.0 MADT table to indicate the
GIC version, so parse the table to get its value for later use.

If GIC version presented in MADT is 0, we need to fallback to
hardware discovery to get the GIC version.

In ACPI MADT table there is no compatible strings to indicate
various irqchips and also ACPI doesn't support irqchips which
are not compatible with ARM GIC spec, so GIC version can be used
to load different GIC drivers which is needed for the later patch.

Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 arch/arm64/Kconfig                   |   1 +
 drivers/irqchip/Kconfig              |   3 +
 drivers/irqchip/Makefile             |   1 +
 drivers/irqchip/irq-gic-acpi.c       | 109 +++++++++++++++++++++++++++++++++++
 include/linux/irqchip/arm-gic-acpi.h |   1 +
 5 files changed, 115 insertions(+)
 create mode 100644 drivers/irqchip/irq-gic-acpi.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index a77d04f..b0cb9bb 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -16,6 +16,7 @@ config ARM64
 	select ARM_AMBA
 	select ARM_ARCH_TIMER
 	select ARM_GIC
+	select ARM_GIC_ACPI if ACPI
 	select AUDIT_ARCH_COMPAT_GENERIC
 	select ARM_GIC_V2M if PCI_MSI
 	select ARM_GIC_V3
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 120d815..557ec2f 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -47,6 +47,9 @@ config ARM_VIC_NR
 	  The maximum number of VICs available in the system, for
 	  power management.
 
+config ARM_GIC_ACPI
+	bool
+
 config ATMEL_AIC_IRQ
 	bool
 	select GENERIC_IRQ_CHIP
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index b8d4e96..90a7e44 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_ARM_GIC)			+= irq-gic.o irq-gic-common.o
 obj-$(CONFIG_ARM_GIC_V2M)		+= irq-gic-v2m.o
 obj-$(CONFIG_ARM_GIC_V3)		+= irq-gic-v3.o irq-gic-common.o
 obj-$(CONFIG_ARM_GIC_V3_ITS)		+= irq-gic-v3-its.o
+obj-$(CONFIG_ARM_GIC_ACPI)		+= irq-gic-acpi.o
 obj-$(CONFIG_ARM_NVIC)			+= irq-nvic.o
 obj-$(CONFIG_ARM_VIC)			+= irq-vic.o
 obj-$(CONFIG_ATMEL_AIC_IRQ)		+= irq-atmel-aic-common.o irq-atmel-aic.o
diff --git a/drivers/irqchip/irq-gic-acpi.c b/drivers/irqchip/irq-gic-acpi.c
new file mode 100644
index 0000000..6537b43
--- /dev/null
+++ b/drivers/irqchip/irq-gic-acpi.c
@@ -0,0 +1,109 @@
+/*
+ * ACPI based support for ARM GIC init
+ *
+ * Copyright (C) 2015, Linaro Ltd.
+ * 	Author: Hanjun Guo <hanjun.guo@linaro.org>
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt) "ACPI: GIC: " fmt
+
+#include <linux/acpi.h>
+#include <linux/init.h>
+#include <linux/irqchip/arm-gic-acpi.h>
+#include <linux/irqchip/arm-gic-v3.h>
+
+/* GIC version presented in MADT GIC distributor structure */
+static u8 gic_version __initdata = ACPI_MADT_GIC_VERSION_NONE;
+
+static phys_addr_t dist_phy_base __initdata;
+
+static int __init
+acpi_gic_parse_distributor(struct acpi_subtable_header *header,
+			   const unsigned long end)
+{
+	struct acpi_madt_generic_distributor *dist;
+
+	dist = (struct acpi_madt_generic_distributor *)header;
+
+	if (BAD_MADT_ENTRY(dist, end))
+		return -EINVAL;
+
+	gic_version = dist->version;
+	dist_phy_base = dist->base_address;
+	return 0;
+}
+
+static int __init
+match_gic_redist(struct acpi_subtable_header *header, const unsigned long end)
+{
+	return 0;
+}
+
+static bool __init acpi_gic_redist_is_present(void)
+{
+	int count;
+
+	/* scan MADT table to find if we have redistributor entries */
+	count  =  acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
+					match_gic_redist, 0);
+
+	/* that's true if we have at least one GIC redistributor entry */
+	return count > 0;
+}
+
+static int __init acpi_gic_version_init(void)
+{
+	int count;
+	u32 reg;
+	void __iomem *dist_base;
+
+	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
+				      acpi_gic_parse_distributor, 0);
+
+	if (count <= 0) {
+		pr_err("No valid GIC distributor entry exists\n");
+		return -ENODEV;
+	}
+
+	if (gic_version >= ACPI_MADT_GIC_VERSION_RESERVED) {
+		pr_err("Invalid GIC version %d in MADT\n", gic_version);
+		return -EINVAL;
+	}
+
+	/*
+	 * when the GIC version is 0, we fallback to hardware discovery.
+	 * this is also needed to keep compatiable with ACPI 5.1,
+	 * which has no gic_version field in distributor structure and
+	 * reserved as 0.
+	 *
+	 * For hardware discovery, the offset for GICv1/2 and GICv3/4 to
+	 * get the GIC version is different (0xFE8 for GICv1/2 and 0xFFE8
+	 * for GICv3/4), so we need to handle it separately.
+	 */
+	if (gic_version	== ACPI_MADT_GIC_VERSION_NONE) {
+		/* it's GICv3/v4 if redistributor is present */
+		if (acpi_gic_redist_is_present()) {
+			dist_base = ioremap(dist_phy_base,
+					    ACPI_GICV3_DIST_MEM_SIZE);
+			if (!dist_base)
+				return -ENOMEM;
+
+			reg = readl_relaxed(dist_base + GICD_PIDR2) &
+					    GIC_PIDR2_ARCH_MASK;
+			if (reg == GIC_PIDR2_ARCH_GICv3)
+				gic_version = ACPI_MADT_GIC_VERSION_V3;
+			else
+				gic_version = ACPI_MADT_GIC_VERSION_V4;
+
+			iounmap(dist_base);
+		} else {
+			gic_version = ACPI_MADT_GIC_VERSION_V2;
+		}
+	}
+
+	return 0;
+}
diff --git a/include/linux/irqchip/arm-gic-acpi.h b/include/linux/irqchip/arm-gic-acpi.h
index de3419e..13bc676 100644
--- a/include/linux/irqchip/arm-gic-acpi.h
+++ b/include/linux/irqchip/arm-gic-acpi.h
@@ -19,6 +19,7 @@
  */
 #define ACPI_GICV2_DIST_MEM_SIZE	(SZ_4K)
 #define ACPI_GIC_CPU_IF_MEM_SIZE	(SZ_8K)
+#define ACPI_GICV3_DIST_MEM_SIZE	(SZ_64K)
 
 struct acpi_table_header;
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 1/8] irqchip / GIC: Add GIC version support in ACPI MADT
@ 2015-07-10 10:45   ` Hanjun Guo
  0 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-10 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

There is a field added in ACPI 6.0 MADT table to indicate the
GIC version, so parse the table to get its value for later use.

If GIC version presented in MADT is 0, we need to fallback to
hardware discovery to get the GIC version.

In ACPI MADT table there is no compatible strings to indicate
various irqchips and also ACPI doesn't support irqchips which
are not compatible with ARM GIC spec, so GIC version can be used
to load different GIC drivers which is needed for the later patch.

Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 arch/arm64/Kconfig                   |   1 +
 drivers/irqchip/Kconfig              |   3 +
 drivers/irqchip/Makefile             |   1 +
 drivers/irqchip/irq-gic-acpi.c       | 109 +++++++++++++++++++++++++++++++++++
 include/linux/irqchip/arm-gic-acpi.h |   1 +
 5 files changed, 115 insertions(+)
 create mode 100644 drivers/irqchip/irq-gic-acpi.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index a77d04f..b0cb9bb 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -16,6 +16,7 @@ config ARM64
 	select ARM_AMBA
 	select ARM_ARCH_TIMER
 	select ARM_GIC
+	select ARM_GIC_ACPI if ACPI
 	select AUDIT_ARCH_COMPAT_GENERIC
 	select ARM_GIC_V2M if PCI_MSI
 	select ARM_GIC_V3
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 120d815..557ec2f 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -47,6 +47,9 @@ config ARM_VIC_NR
 	  The maximum number of VICs available in the system, for
 	  power management.
 
+config ARM_GIC_ACPI
+	bool
+
 config ATMEL_AIC_IRQ
 	bool
 	select GENERIC_IRQ_CHIP
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index b8d4e96..90a7e44 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_ARM_GIC)			+= irq-gic.o irq-gic-common.o
 obj-$(CONFIG_ARM_GIC_V2M)		+= irq-gic-v2m.o
 obj-$(CONFIG_ARM_GIC_V3)		+= irq-gic-v3.o irq-gic-common.o
 obj-$(CONFIG_ARM_GIC_V3_ITS)		+= irq-gic-v3-its.o
+obj-$(CONFIG_ARM_GIC_ACPI)		+= irq-gic-acpi.o
 obj-$(CONFIG_ARM_NVIC)			+= irq-nvic.o
 obj-$(CONFIG_ARM_VIC)			+= irq-vic.o
 obj-$(CONFIG_ATMEL_AIC_IRQ)		+= irq-atmel-aic-common.o irq-atmel-aic.o
diff --git a/drivers/irqchip/irq-gic-acpi.c b/drivers/irqchip/irq-gic-acpi.c
new file mode 100644
index 0000000..6537b43
--- /dev/null
+++ b/drivers/irqchip/irq-gic-acpi.c
@@ -0,0 +1,109 @@
+/*
+ * ACPI based support for ARM GIC init
+ *
+ * Copyright (C) 2015, Linaro Ltd.
+ * 	Author: Hanjun Guo <hanjun.guo@linaro.org>
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt) "ACPI: GIC: " fmt
+
+#include <linux/acpi.h>
+#include <linux/init.h>
+#include <linux/irqchip/arm-gic-acpi.h>
+#include <linux/irqchip/arm-gic-v3.h>
+
+/* GIC version presented in MADT GIC distributor structure */
+static u8 gic_version __initdata = ACPI_MADT_GIC_VERSION_NONE;
+
+static phys_addr_t dist_phy_base __initdata;
+
+static int __init
+acpi_gic_parse_distributor(struct acpi_subtable_header *header,
+			   const unsigned long end)
+{
+	struct acpi_madt_generic_distributor *dist;
+
+	dist = (struct acpi_madt_generic_distributor *)header;
+
+	if (BAD_MADT_ENTRY(dist, end))
+		return -EINVAL;
+
+	gic_version = dist->version;
+	dist_phy_base = dist->base_address;
+	return 0;
+}
+
+static int __init
+match_gic_redist(struct acpi_subtable_header *header, const unsigned long end)
+{
+	return 0;
+}
+
+static bool __init acpi_gic_redist_is_present(void)
+{
+	int count;
+
+	/* scan MADT table to find if we have redistributor entries */
+	count  =  acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
+					match_gic_redist, 0);
+
+	/* that's true if we have at least one GIC redistributor entry */
+	return count > 0;
+}
+
+static int __init acpi_gic_version_init(void)
+{
+	int count;
+	u32 reg;
+	void __iomem *dist_base;
+
+	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
+				      acpi_gic_parse_distributor, 0);
+
+	if (count <= 0) {
+		pr_err("No valid GIC distributor entry exists\n");
+		return -ENODEV;
+	}
+
+	if (gic_version >= ACPI_MADT_GIC_VERSION_RESERVED) {
+		pr_err("Invalid GIC version %d in MADT\n", gic_version);
+		return -EINVAL;
+	}
+
+	/*
+	 * when the GIC version is 0, we fallback to hardware discovery.
+	 * this is also needed to keep compatiable with ACPI 5.1,
+	 * which has no gic_version field in distributor structure and
+	 * reserved as 0.
+	 *
+	 * For hardware discovery, the offset for GICv1/2 and GICv3/4 to
+	 * get the GIC version is different (0xFE8 for GICv1/2 and 0xFFE8
+	 * for GICv3/4), so we need to handle it separately.
+	 */
+	if (gic_version	== ACPI_MADT_GIC_VERSION_NONE) {
+		/* it's GICv3/v4 if redistributor is present */
+		if (acpi_gic_redist_is_present()) {
+			dist_base = ioremap(dist_phy_base,
+					    ACPI_GICV3_DIST_MEM_SIZE);
+			if (!dist_base)
+				return -ENOMEM;
+
+			reg = readl_relaxed(dist_base + GICD_PIDR2) &
+					    GIC_PIDR2_ARCH_MASK;
+			if (reg == GIC_PIDR2_ARCH_GICv3)
+				gic_version = ACPI_MADT_GIC_VERSION_V3;
+			else
+				gic_version = ACPI_MADT_GIC_VERSION_V4;
+
+			iounmap(dist_base);
+		} else {
+			gic_version = ACPI_MADT_GIC_VERSION_V2;
+		}
+	}
+
+	return 0;
+}
diff --git a/include/linux/irqchip/arm-gic-acpi.h b/include/linux/irqchip/arm-gic-acpi.h
index de3419e..13bc676 100644
--- a/include/linux/irqchip/arm-gic-acpi.h
+++ b/include/linux/irqchip/arm-gic-acpi.h
@@ -19,6 +19,7 @@
  */
 #define ACPI_GICV2_DIST_MEM_SIZE	(SZ_4K)
 #define ACPI_GIC_CPU_IF_MEM_SIZE	(SZ_8K)
+#define ACPI_GICV3_DIST_MEM_SIZE	(SZ_64K)
 
 struct acpi_table_header;
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 2/8] ACPI / irqchip: Add self-probe infrastructure to initialize IRQ controller
  2015-07-10 10:45 ` Hanjun Guo
@ 2015-07-10 10:45   ` Hanjun Guo
  -1 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-10 10:45 UTC (permalink / raw)
  To: Marc Zyngier, Jason Cooper, Will Deacon, Catalin Marinas,
	Rafael J. Wysocki
  Cc: Thomas Gleixner, Jiang Liu, Lorenzo Pieralisi, Arnd Bergmann,
	Tomasz Nowicki, Grant Likely, Mark Brown, Wei Huang,
	linux-arm-kernel, linux-acpi, linux-kernel, linaro-acpi,
	Hanjun Guo

This self-probe infrastructure works in the similar way as OF,
but there is some different in the mechanism:

For DT, the init fn will be called once it finds compatible strings
in DT,  but for ACPI, we init irqchips by static tables, and in
static ACPI tables, there are no compatible strings to indicate
irqchips, but thanks to the GIC version presented in ACPI table,
we can call the corresponding GIC drivers matching the GIC version
with this framework.

This mechanism can also be used for clock declare and may also works
on x86 for some table parsing too.

Part of this patch is based on Tomasz Nowicki's work.

Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 drivers/irqchip/irq-gic-acpi.c    | 29 +++++++++++++++++++++++++++++
 include/asm-generic/vmlinux.lds.h | 13 +++++++++++++
 include/linux/acpi.h              | 16 ++++++++++++++++
 include/linux/irqchip.h           | 13 +++++++++++++
 include/linux/mod_devicetable.h   |  8 ++++++++
 5 files changed, 79 insertions(+)

diff --git a/drivers/irqchip/irq-gic-acpi.c b/drivers/irqchip/irq-gic-acpi.c
index 6537b43..e003a89 100644
--- a/drivers/irqchip/irq-gic-acpi.c
+++ b/drivers/irqchip/irq-gic-acpi.c
@@ -107,3 +107,32 @@ static int __init acpi_gic_version_init(void)
 
 	return 0;
 }
+
+/*
+ * This special acpi_table_id is the sentinel at the end of the
+ * acpi_table_id[] array of all irqchips. It is automatically placed at
+ * the end of the array by the linker, thanks to being part of a
+ * special section.
+ */
+static const struct acpi_table_id
+irqchip_acpi_match_end __used __section(__irqchip_acpi_table_end);
+
+extern struct acpi_table_id __irqchip_acpi_table[];
+
+void __init acpi_irqchip_init(void)
+{
+	struct acpi_table_id *id;
+
+	if (acpi_disabled)
+		return;
+
+	if (acpi_gic_version_init())
+		return;
+
+	/* scan the irqchip table to match the GIC version and its driver */
+	for (id = __irqchip_acpi_table; id->id[0]; id++) {
+		if (gic_version == (u8)id->driver_data)
+			acpi_table_parse(id->id,
+					 (acpi_tbl_table_handler)id->handler);
+	}
+}
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 8bd374d..625776c 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -181,6 +181,18 @@
 #define CPUIDLE_METHOD_OF_TABLES() OF_TABLE(CONFIG_CPU_IDLE, cpuidle_method)
 #define EARLYCON_OF_TABLES()	OF_TABLE(CONFIG_SERIAL_EARLYCON, earlycon)
 
+#ifdef CONFIG_ACPI
+#define ACPI_TABLE(name)						\
+	. = ALIGN(8);							\
+	VMLINUX_SYMBOL(__##name##_acpi_table) = .;			\
+	*(__##name##_acpi_table)					\
+	*(__##name##_acpi_table_end)
+
+#define IRQCHIP_ACPI_MATCH_TABLE()	ACPI_TABLE(irqchip)
+#else
+#define IRQCHIP_ACPI_MATCH_TABLE()
+#endif
+
 #define KERNEL_DTB()							\
 	STRUCT_ALIGN();							\
 	VMLINUX_SYMBOL(__dtb_start) = .;				\
@@ -516,6 +528,7 @@
 	CPUIDLE_METHOD_OF_TABLES()					\
 	KERNEL_DTB()							\
 	IRQCHIP_OF_MATCH_TABLE()					\
+	IRQCHIP_ACPI_MATCH_TABLE()					\
 	EARLYCON_TABLE()						\
 	EARLYCON_OF_TABLES()
 
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index c471dfc..7b058f0 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -811,4 +811,20 @@ static inline struct acpi_device *acpi_get_next_child(struct device *dev,
 
 #endif
 
+#ifdef CONFIG_ACPI
+#define ACPI_DECLARE(table, name, table_id, data, fn)			\
+	static const struct acpi_table_id __acpi_table_##name		\
+		__used __section(__##table##_acpi_table)		\
+		 = { .id = table_id,					\
+		     .handler = (void *)fn,				\
+		     .driver_data = data }
+#else
+#define ACPI_DECLARE(table, name, table_id, data, fn)			\
+	static const struct acpi_table_id __acpi_table_##name		\
+		__attribute__((unused))					\
+		 = { .id = table_id,					\
+		     .handler = (void *)fn,				\
+		     .driver_data = data }
+#endif
+
 #endif	/*_LINUX_ACPI_H*/
diff --git a/include/linux/irqchip.h b/include/linux/irqchip.h
index 6388873..6b66d3e 100644
--- a/include/linux/irqchip.h
+++ b/include/linux/irqchip.h
@@ -11,6 +11,7 @@
 #ifndef _LINUX_IRQCHIP_H
 #define _LINUX_IRQCHIP_H
 
+#include <linux/acpi.h>
 #include <linux/of.h>
 
 /*
@@ -25,6 +26,18 @@
  */
 #define IRQCHIP_DECLARE(name, compat, fn) OF_DECLARE_2(irqchip, name, compat, fn)
 
+/*
+ * This macro must be used by the different ARM GIC drivers to declare
+ * the association between their version and their initialization function.
+ *
+ * @name: name that must be unique accross all IRQCHIP_ACPI_DECLARE of the
+ * same file.
+ * @gic_version: version of GIC
+ * @fn: initialization function
+ */
+#define IRQCHIP_ACPI_DECLARE(name, gic_version, fn)	\
+	ACPI_DECLARE(irqchip, name, ACPI_SIG_MADT, gic_version, fn)
+
 #ifdef CONFIG_IRQCHIP
 void irqchip_init(void);
 #else
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 8183d66..c74855f 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -191,6 +191,14 @@ struct acpi_device_id {
 	kernel_ulong_t driver_data;
 };
 
+#define ACPI_TABLE_ID_LEN	5
+
+struct acpi_table_id {
+	__u8 id[ACPI_TABLE_ID_LEN];
+	const void *handler;
+	kernel_ulong_t driver_data;
+};
+
 #define PNP_ID_LEN	8
 #define PNP_MAX_DEVICES	8
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 2/8] ACPI / irqchip: Add self-probe infrastructure to initialize IRQ controller
@ 2015-07-10 10:45   ` Hanjun Guo
  0 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-10 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

This self-probe infrastructure works in the similar way as OF,
but there is some different in the mechanism:

For DT, the init fn will be called once it finds compatible strings
in DT,  but for ACPI, we init irqchips by static tables, and in
static ACPI tables, there are no compatible strings to indicate
irqchips, but thanks to the GIC version presented in ACPI table,
we can call the corresponding GIC drivers matching the GIC version
with this framework.

This mechanism can also be used for clock declare and may also works
on x86 for some table parsing too.

Part of this patch is based on Tomasz Nowicki's work.

Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 drivers/irqchip/irq-gic-acpi.c    | 29 +++++++++++++++++++++++++++++
 include/asm-generic/vmlinux.lds.h | 13 +++++++++++++
 include/linux/acpi.h              | 16 ++++++++++++++++
 include/linux/irqchip.h           | 13 +++++++++++++
 include/linux/mod_devicetable.h   |  8 ++++++++
 5 files changed, 79 insertions(+)

diff --git a/drivers/irqchip/irq-gic-acpi.c b/drivers/irqchip/irq-gic-acpi.c
index 6537b43..e003a89 100644
--- a/drivers/irqchip/irq-gic-acpi.c
+++ b/drivers/irqchip/irq-gic-acpi.c
@@ -107,3 +107,32 @@ static int __init acpi_gic_version_init(void)
 
 	return 0;
 }
+
+/*
+ * This special acpi_table_id is the sentinel at the end of the
+ * acpi_table_id[] array of all irqchips. It is automatically placed at
+ * the end of the array by the linker, thanks to being part of a
+ * special section.
+ */
+static const struct acpi_table_id
+irqchip_acpi_match_end __used __section(__irqchip_acpi_table_end);
+
+extern struct acpi_table_id __irqchip_acpi_table[];
+
+void __init acpi_irqchip_init(void)
+{
+	struct acpi_table_id *id;
+
+	if (acpi_disabled)
+		return;
+
+	if (acpi_gic_version_init())
+		return;
+
+	/* scan the irqchip table to match the GIC version and its driver */
+	for (id = __irqchip_acpi_table; id->id[0]; id++) {
+		if (gic_version == (u8)id->driver_data)
+			acpi_table_parse(id->id,
+					 (acpi_tbl_table_handler)id->handler);
+	}
+}
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 8bd374d..625776c 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -181,6 +181,18 @@
 #define CPUIDLE_METHOD_OF_TABLES() OF_TABLE(CONFIG_CPU_IDLE, cpuidle_method)
 #define EARLYCON_OF_TABLES()	OF_TABLE(CONFIG_SERIAL_EARLYCON, earlycon)
 
+#ifdef CONFIG_ACPI
+#define ACPI_TABLE(name)						\
+	. = ALIGN(8);							\
+	VMLINUX_SYMBOL(__##name##_acpi_table) = .;			\
+	*(__##name##_acpi_table)					\
+	*(__##name##_acpi_table_end)
+
+#define IRQCHIP_ACPI_MATCH_TABLE()	ACPI_TABLE(irqchip)
+#else
+#define IRQCHIP_ACPI_MATCH_TABLE()
+#endif
+
 #define KERNEL_DTB()							\
 	STRUCT_ALIGN();							\
 	VMLINUX_SYMBOL(__dtb_start) = .;				\
@@ -516,6 +528,7 @@
 	CPUIDLE_METHOD_OF_TABLES()					\
 	KERNEL_DTB()							\
 	IRQCHIP_OF_MATCH_TABLE()					\
+	IRQCHIP_ACPI_MATCH_TABLE()					\
 	EARLYCON_TABLE()						\
 	EARLYCON_OF_TABLES()
 
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index c471dfc..7b058f0 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -811,4 +811,20 @@ static inline struct acpi_device *acpi_get_next_child(struct device *dev,
 
 #endif
 
+#ifdef CONFIG_ACPI
+#define ACPI_DECLARE(table, name, table_id, data, fn)			\
+	static const struct acpi_table_id __acpi_table_##name		\
+		__used __section(__##table##_acpi_table)		\
+		 = { .id = table_id,					\
+		     .handler = (void *)fn,				\
+		     .driver_data = data }
+#else
+#define ACPI_DECLARE(table, name, table_id, data, fn)			\
+	static const struct acpi_table_id __acpi_table_##name		\
+		__attribute__((unused))					\
+		 = { .id = table_id,					\
+		     .handler = (void *)fn,				\
+		     .driver_data = data }
+#endif
+
 #endif	/*_LINUX_ACPI_H*/
diff --git a/include/linux/irqchip.h b/include/linux/irqchip.h
index 6388873..6b66d3e 100644
--- a/include/linux/irqchip.h
+++ b/include/linux/irqchip.h
@@ -11,6 +11,7 @@
 #ifndef _LINUX_IRQCHIP_H
 #define _LINUX_IRQCHIP_H
 
+#include <linux/acpi.h>
 #include <linux/of.h>
 
 /*
@@ -25,6 +26,18 @@
  */
 #define IRQCHIP_DECLARE(name, compat, fn) OF_DECLARE_2(irqchip, name, compat, fn)
 
+/*
+ * This macro must be used by the different ARM GIC drivers to declare
+ * the association between their version and their initialization function.
+ *
+ * @name: name that must be unique accross all IRQCHIP_ACPI_DECLARE of the
+ * same file.
+ * @gic_version: version of GIC
+ * @fn: initialization function
+ */
+#define IRQCHIP_ACPI_DECLARE(name, gic_version, fn)	\
+	ACPI_DECLARE(irqchip, name, ACPI_SIG_MADT, gic_version, fn)
+
 #ifdef CONFIG_IRQCHIP
 void irqchip_init(void);
 #else
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 8183d66..c74855f 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -191,6 +191,14 @@ struct acpi_device_id {
 	kernel_ulong_t driver_data;
 };
 
+#define ACPI_TABLE_ID_LEN	5
+
+struct acpi_table_id {
+	__u8 id[ACPI_TABLE_ID_LEN];
+	const void *handler;
+	kernel_ulong_t driver_data;
+};
+
 #define PNP_ID_LEN	8
 #define PNP_MAX_DEVICES	8
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 3/8] irqchip / GIC / ACPI: Use IRQCHIP_ACPI_DECLARE to simplify GICv2 init code
  2015-07-10 10:45 ` Hanjun Guo
  (?)
@ 2015-07-10 10:45   ` Hanjun Guo
  -1 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-10 10:45 UTC (permalink / raw)
  To: Marc Zyngier, Jason Cooper, Will Deacon, Catalin Marinas,
	Rafael J. Wysocki
  Cc: Wei Huang, Lorenzo Pieralisi, Arnd Bergmann, linaro-acpi,
	linux-kernel, Tomasz Nowicki, linux-acpi, Mark Brown, Hanjun Guo,
	Grant Likely, Thomas Gleixner, Jiang Liu, linux-arm-kernel

As the ACPI self-probe infrastructure for irqchip is ready,
we use the infrastructure to simplify GICv2 init code.

acpi_irqchip_init() is renamed as acpi_irq_init() to replace
the previous hardcode version of acpi_irq_init() in asm/irq.h,
also cleanup the code which previously calling the GIC driver
manually in arch/arm64/kernel/acpi.c.

>From now on, GIC init calls reside in theirs drivers only.
This means the code becomes cleaner and it is not spread
outside irqchip driver.

Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 arch/arm64/include/asm/acpi.h        |  1 -
 arch/arm64/include/asm/irq.h         | 13 -------------
 arch/arm64/kernel/acpi.c             | 25 -------------------------
 drivers/irqchip/irq-gic-acpi.c       |  2 +-
 drivers/irqchip/irq-gic.c            |  3 ++-
 include/linux/acpi_irq.h             |  4 +++-
 include/linux/irqchip/arm-gic-acpi.h |  9 +--------
 7 files changed, 7 insertions(+), 50 deletions(-)

diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
index ed7e212..05656fc 100644
--- a/arch/arm64/include/asm/acpi.h
+++ b/arch/arm64/include/asm/acpi.h
@@ -12,7 +12,6 @@
 #ifndef _ASM_ACPI_H
 #define _ASM_ACPI_H
 
-#include <linux/irqchip/arm-gic-acpi.h>
 #include <linux/mm.h>
 #include <linux/psci.h>
 
diff --git a/arch/arm64/include/asm/irq.h b/arch/arm64/include/asm/irq.h
index bbb251b..94c5367 100644
--- a/arch/arm64/include/asm/irq.h
+++ b/arch/arm64/include/asm/irq.h
@@ -1,8 +1,6 @@
 #ifndef __ASM_IRQ_H
 #define __ASM_IRQ_H
 
-#include <linux/irqchip/arm-gic-acpi.h>
-
 #include <asm-generic/irq.h>
 
 struct pt_regs;
@@ -10,15 +8,4 @@ struct pt_regs;
 extern void migrate_irqs(void);
 extern void set_handle_irq(void (*handle_irq)(struct pt_regs *));
 
-static inline void acpi_irq_init(void)
-{
-	/*
-	 * Hardcode ACPI IRQ chip initialization to GICv2 for now.
-	 * Proper irqchip infrastructure will be implemented along with
-	 * incoming  GICv2m|GICv3|ITS bits.
-	 */
-	acpi_gic_init();
-}
-#define acpi_irq_init acpi_irq_init
-
 #endif
diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
index 19de753..d6463bb 100644
--- a/arch/arm64/kernel/acpi.c
+++ b/arch/arm64/kernel/acpi.c
@@ -205,28 +205,3 @@ void __init acpi_boot_table_init(void)
 			disable_acpi();
 	}
 }
-
-void __init acpi_gic_init(void)
-{
-	struct acpi_table_header *table;
-	acpi_status status;
-	acpi_size tbl_size;
-	int err;
-
-	if (acpi_disabled)
-		return;
-
-	status = acpi_get_table_with_size(ACPI_SIG_MADT, 0, &table, &tbl_size);
-	if (ACPI_FAILURE(status)) {
-		const char *msg = acpi_format_exception(status);
-
-		pr_err("Failed to get MADT table, %s\n", msg);
-		return;
-	}
-
-	err = gic_v2_acpi_init(table);
-	if (err)
-		pr_err("Failed to initialize GIC IRQ controller");
-
-	early_acpi_os_unmap_memory((char *)table, tbl_size);
-}
diff --git a/drivers/irqchip/irq-gic-acpi.c b/drivers/irqchip/irq-gic-acpi.c
index e003a89..b87a581 100644
--- a/drivers/irqchip/irq-gic-acpi.c
+++ b/drivers/irqchip/irq-gic-acpi.c
@@ -119,7 +119,7 @@ irqchip_acpi_match_end __used __section(__irqchip_acpi_table_end);
 
 extern struct acpi_table_id __irqchip_acpi_table[];
 
-void __init acpi_irqchip_init(void)
+void __init acpi_irq_init(void)
 {
 	struct acpi_table_id *id;
 
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 8d7e1c8..58a7112 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -1086,7 +1086,7 @@ gic_acpi_parse_madt_distributor(struct acpi_subtable_header *header,
 	return 0;
 }
 
-int __init
+static int __init
 gic_v2_acpi_init(struct acpi_table_header *table)
 {
 	void __iomem *cpu_base, *dist_base;
@@ -1142,4 +1142,5 @@ gic_v2_acpi_init(struct acpi_table_header *table)
 	acpi_irq_model = ACPI_IRQ_MODEL_GIC;
 	return 0;
 }
+IRQCHIP_ACPI_DECLARE(gic_v2, ACPI_MADT_GIC_VERSION_V2, gic_v2_acpi_init);
 #endif
diff --git a/include/linux/acpi_irq.h b/include/linux/acpi_irq.h
index f10c872..4c0e108 100644
--- a/include/linux/acpi_irq.h
+++ b/include/linux/acpi_irq.h
@@ -3,7 +3,9 @@
 
 #include <linux/irq.h>
 
-#ifndef acpi_irq_init
+#ifdef CONFIG_ACPI
+void acpi_irq_init(void);
+#else
 static inline void acpi_irq_init(void) { }
 #endif
 
diff --git a/include/linux/irqchip/arm-gic-acpi.h b/include/linux/irqchip/arm-gic-acpi.h
index 13bc676..56cd82c 100644
--- a/include/linux/irqchip/arm-gic-acpi.h
+++ b/include/linux/irqchip/arm-gic-acpi.h
@@ -21,12 +21,5 @@
 #define ACPI_GIC_CPU_IF_MEM_SIZE	(SZ_8K)
 #define ACPI_GICV3_DIST_MEM_SIZE	(SZ_64K)
 
-struct acpi_table_header;
-
-int gic_v2_acpi_init(struct acpi_table_header *table);
-void acpi_gic_init(void);
-#else
-static inline void acpi_gic_init(void) { }
-#endif
-
+#endif /* CONFIG_ACPI */
 #endif /* ARM_GIC_ACPI_H_ */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 3/8] irqchip / GIC / ACPI: Use IRQCHIP_ACPI_DECLARE to simplify GICv2 init code
@ 2015-07-10 10:45   ` Hanjun Guo
  0 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-10 10:45 UTC (permalink / raw)
  To: Marc Zyngier, Jason Cooper, Will Deacon, Catalin Marinas,
	Rafael J. Wysocki
  Cc: Thomas Gleixner, Jiang Liu, Lorenzo Pieralisi, Arnd Bergmann,
	Tomasz Nowicki, Grant Likely, Mark Brown, Wei Huang,
	linux-arm-kernel, linux-acpi, linux-kernel, linaro-acpi,
	Hanjun Guo

As the ACPI self-probe infrastructure for irqchip is ready,
we use the infrastructure to simplify GICv2 init code.

acpi_irqchip_init() is renamed as acpi_irq_init() to replace
the previous hardcode version of acpi_irq_init() in asm/irq.h,
also cleanup the code which previously calling the GIC driver
manually in arch/arm64/kernel/acpi.c.

>From now on, GIC init calls reside in theirs drivers only.
This means the code becomes cleaner and it is not spread
outside irqchip driver.

Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 arch/arm64/include/asm/acpi.h        |  1 -
 arch/arm64/include/asm/irq.h         | 13 -------------
 arch/arm64/kernel/acpi.c             | 25 -------------------------
 drivers/irqchip/irq-gic-acpi.c       |  2 +-
 drivers/irqchip/irq-gic.c            |  3 ++-
 include/linux/acpi_irq.h             |  4 +++-
 include/linux/irqchip/arm-gic-acpi.h |  9 +--------
 7 files changed, 7 insertions(+), 50 deletions(-)

diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
index ed7e212..05656fc 100644
--- a/arch/arm64/include/asm/acpi.h
+++ b/arch/arm64/include/asm/acpi.h
@@ -12,7 +12,6 @@
 #ifndef _ASM_ACPI_H
 #define _ASM_ACPI_H
 
-#include <linux/irqchip/arm-gic-acpi.h>
 #include <linux/mm.h>
 #include <linux/psci.h>
 
diff --git a/arch/arm64/include/asm/irq.h b/arch/arm64/include/asm/irq.h
index bbb251b..94c5367 100644
--- a/arch/arm64/include/asm/irq.h
+++ b/arch/arm64/include/asm/irq.h
@@ -1,8 +1,6 @@
 #ifndef __ASM_IRQ_H
 #define __ASM_IRQ_H
 
-#include <linux/irqchip/arm-gic-acpi.h>
-
 #include <asm-generic/irq.h>
 
 struct pt_regs;
@@ -10,15 +8,4 @@ struct pt_regs;
 extern void migrate_irqs(void);
 extern void set_handle_irq(void (*handle_irq)(struct pt_regs *));
 
-static inline void acpi_irq_init(void)
-{
-	/*
-	 * Hardcode ACPI IRQ chip initialization to GICv2 for now.
-	 * Proper irqchip infrastructure will be implemented along with
-	 * incoming  GICv2m|GICv3|ITS bits.
-	 */
-	acpi_gic_init();
-}
-#define acpi_irq_init acpi_irq_init
-
 #endif
diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
index 19de753..d6463bb 100644
--- a/arch/arm64/kernel/acpi.c
+++ b/arch/arm64/kernel/acpi.c
@@ -205,28 +205,3 @@ void __init acpi_boot_table_init(void)
 			disable_acpi();
 	}
 }
-
-void __init acpi_gic_init(void)
-{
-	struct acpi_table_header *table;
-	acpi_status status;
-	acpi_size tbl_size;
-	int err;
-
-	if (acpi_disabled)
-		return;
-
-	status = acpi_get_table_with_size(ACPI_SIG_MADT, 0, &table, &tbl_size);
-	if (ACPI_FAILURE(status)) {
-		const char *msg = acpi_format_exception(status);
-
-		pr_err("Failed to get MADT table, %s\n", msg);
-		return;
-	}
-
-	err = gic_v2_acpi_init(table);
-	if (err)
-		pr_err("Failed to initialize GIC IRQ controller");
-
-	early_acpi_os_unmap_memory((char *)table, tbl_size);
-}
diff --git a/drivers/irqchip/irq-gic-acpi.c b/drivers/irqchip/irq-gic-acpi.c
index e003a89..b87a581 100644
--- a/drivers/irqchip/irq-gic-acpi.c
+++ b/drivers/irqchip/irq-gic-acpi.c
@@ -119,7 +119,7 @@ irqchip_acpi_match_end __used __section(__irqchip_acpi_table_end);
 
 extern struct acpi_table_id __irqchip_acpi_table[];
 
-void __init acpi_irqchip_init(void)
+void __init acpi_irq_init(void)
 {
 	struct acpi_table_id *id;
 
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 8d7e1c8..58a7112 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -1086,7 +1086,7 @@ gic_acpi_parse_madt_distributor(struct acpi_subtable_header *header,
 	return 0;
 }
 
-int __init
+static int __init
 gic_v2_acpi_init(struct acpi_table_header *table)
 {
 	void __iomem *cpu_base, *dist_base;
@@ -1142,4 +1142,5 @@ gic_v2_acpi_init(struct acpi_table_header *table)
 	acpi_irq_model = ACPI_IRQ_MODEL_GIC;
 	return 0;
 }
+IRQCHIP_ACPI_DECLARE(gic_v2, ACPI_MADT_GIC_VERSION_V2, gic_v2_acpi_init);
 #endif
diff --git a/include/linux/acpi_irq.h b/include/linux/acpi_irq.h
index f10c872..4c0e108 100644
--- a/include/linux/acpi_irq.h
+++ b/include/linux/acpi_irq.h
@@ -3,7 +3,9 @@
 
 #include <linux/irq.h>
 
-#ifndef acpi_irq_init
+#ifdef CONFIG_ACPI
+void acpi_irq_init(void);
+#else
 static inline void acpi_irq_init(void) { }
 #endif
 
diff --git a/include/linux/irqchip/arm-gic-acpi.h b/include/linux/irqchip/arm-gic-acpi.h
index 13bc676..56cd82c 100644
--- a/include/linux/irqchip/arm-gic-acpi.h
+++ b/include/linux/irqchip/arm-gic-acpi.h
@@ -21,12 +21,5 @@
 #define ACPI_GIC_CPU_IF_MEM_SIZE	(SZ_8K)
 #define ACPI_GICV3_DIST_MEM_SIZE	(SZ_64K)
 
-struct acpi_table_header;
-
-int gic_v2_acpi_init(struct acpi_table_header *table);
-void acpi_gic_init(void);
-#else
-static inline void acpi_gic_init(void) { }
-#endif
-
+#endif /* CONFIG_ACPI */
 #endif /* ARM_GIC_ACPI_H_ */
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 3/8] irqchip / GIC / ACPI: Use IRQCHIP_ACPI_DECLARE to simplify GICv2 init code
@ 2015-07-10 10:45   ` Hanjun Guo
  0 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-10 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

As the ACPI self-probe infrastructure for irqchip is ready,
we use the infrastructure to simplify GICv2 init code.

acpi_irqchip_init() is renamed as acpi_irq_init() to replace
the previous hardcode version of acpi_irq_init() in asm/irq.h,
also cleanup the code which previously calling the GIC driver
manually in arch/arm64/kernel/acpi.c.

>From now on, GIC init calls reside in theirs drivers only.
This means the code becomes cleaner and it is not spread
outside irqchip driver.

Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 arch/arm64/include/asm/acpi.h        |  1 -
 arch/arm64/include/asm/irq.h         | 13 -------------
 arch/arm64/kernel/acpi.c             | 25 -------------------------
 drivers/irqchip/irq-gic-acpi.c       |  2 +-
 drivers/irqchip/irq-gic.c            |  3 ++-
 include/linux/acpi_irq.h             |  4 +++-
 include/linux/irqchip/arm-gic-acpi.h |  9 +--------
 7 files changed, 7 insertions(+), 50 deletions(-)

diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
index ed7e212..05656fc 100644
--- a/arch/arm64/include/asm/acpi.h
+++ b/arch/arm64/include/asm/acpi.h
@@ -12,7 +12,6 @@
 #ifndef _ASM_ACPI_H
 #define _ASM_ACPI_H
 
-#include <linux/irqchip/arm-gic-acpi.h>
 #include <linux/mm.h>
 #include <linux/psci.h>
 
diff --git a/arch/arm64/include/asm/irq.h b/arch/arm64/include/asm/irq.h
index bbb251b..94c5367 100644
--- a/arch/arm64/include/asm/irq.h
+++ b/arch/arm64/include/asm/irq.h
@@ -1,8 +1,6 @@
 #ifndef __ASM_IRQ_H
 #define __ASM_IRQ_H
 
-#include <linux/irqchip/arm-gic-acpi.h>
-
 #include <asm-generic/irq.h>
 
 struct pt_regs;
@@ -10,15 +8,4 @@ struct pt_regs;
 extern void migrate_irqs(void);
 extern void set_handle_irq(void (*handle_irq)(struct pt_regs *));
 
-static inline void acpi_irq_init(void)
-{
-	/*
-	 * Hardcode ACPI IRQ chip initialization to GICv2 for now.
-	 * Proper irqchip infrastructure will be implemented along with
-	 * incoming  GICv2m|GICv3|ITS bits.
-	 */
-	acpi_gic_init();
-}
-#define acpi_irq_init acpi_irq_init
-
 #endif
diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
index 19de753..d6463bb 100644
--- a/arch/arm64/kernel/acpi.c
+++ b/arch/arm64/kernel/acpi.c
@@ -205,28 +205,3 @@ void __init acpi_boot_table_init(void)
 			disable_acpi();
 	}
 }
-
-void __init acpi_gic_init(void)
-{
-	struct acpi_table_header *table;
-	acpi_status status;
-	acpi_size tbl_size;
-	int err;
-
-	if (acpi_disabled)
-		return;
-
-	status = acpi_get_table_with_size(ACPI_SIG_MADT, 0, &table, &tbl_size);
-	if (ACPI_FAILURE(status)) {
-		const char *msg = acpi_format_exception(status);
-
-		pr_err("Failed to get MADT table, %s\n", msg);
-		return;
-	}
-
-	err = gic_v2_acpi_init(table);
-	if (err)
-		pr_err("Failed to initialize GIC IRQ controller");
-
-	early_acpi_os_unmap_memory((char *)table, tbl_size);
-}
diff --git a/drivers/irqchip/irq-gic-acpi.c b/drivers/irqchip/irq-gic-acpi.c
index e003a89..b87a581 100644
--- a/drivers/irqchip/irq-gic-acpi.c
+++ b/drivers/irqchip/irq-gic-acpi.c
@@ -119,7 +119,7 @@ irqchip_acpi_match_end __used __section(__irqchip_acpi_table_end);
 
 extern struct acpi_table_id __irqchip_acpi_table[];
 
-void __init acpi_irqchip_init(void)
+void __init acpi_irq_init(void)
 {
 	struct acpi_table_id *id;
 
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 8d7e1c8..58a7112 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -1086,7 +1086,7 @@ gic_acpi_parse_madt_distributor(struct acpi_subtable_header *header,
 	return 0;
 }
 
-int __init
+static int __init
 gic_v2_acpi_init(struct acpi_table_header *table)
 {
 	void __iomem *cpu_base, *dist_base;
@@ -1142,4 +1142,5 @@ gic_v2_acpi_init(struct acpi_table_header *table)
 	acpi_irq_model = ACPI_IRQ_MODEL_GIC;
 	return 0;
 }
+IRQCHIP_ACPI_DECLARE(gic_v2, ACPI_MADT_GIC_VERSION_V2, gic_v2_acpi_init);
 #endif
diff --git a/include/linux/acpi_irq.h b/include/linux/acpi_irq.h
index f10c872..4c0e108 100644
--- a/include/linux/acpi_irq.h
+++ b/include/linux/acpi_irq.h
@@ -3,7 +3,9 @@
 
 #include <linux/irq.h>
 
-#ifndef acpi_irq_init
+#ifdef CONFIG_ACPI
+void acpi_irq_init(void);
+#else
 static inline void acpi_irq_init(void) { }
 #endif
 
diff --git a/include/linux/irqchip/arm-gic-acpi.h b/include/linux/irqchip/arm-gic-acpi.h
index 13bc676..56cd82c 100644
--- a/include/linux/irqchip/arm-gic-acpi.h
+++ b/include/linux/irqchip/arm-gic-acpi.h
@@ -21,12 +21,5 @@
 #define ACPI_GIC_CPU_IF_MEM_SIZE	(SZ_8K)
 #define ACPI_GICV3_DIST_MEM_SIZE	(SZ_64K)
 
-struct acpi_table_header;
-
-int gic_v2_acpi_init(struct acpi_table_header *table);
-void acpi_gic_init(void);
-#else
-static inline void acpi_gic_init(void) { }
-#endif
-
+#endif /* CONFIG_ACPI */
 #endif /* ARM_GIC_ACPI_H_ */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 4/8] irqchip / gic: Add stacked irqdomain support for ACPI based GICv2 init
  2015-07-10 10:45 ` Hanjun Guo
  (?)
@ 2015-07-10 10:45   ` Hanjun Guo
  -1 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-10 10:45 UTC (permalink / raw)
  To: Marc Zyngier, Jason Cooper, Will Deacon, Catalin Marinas,
	Rafael J. Wysocki
  Cc: Thomas Gleixner, Jiang Liu, Lorenzo Pieralisi, Arnd Bergmann,
	Tomasz Nowicki, Grant Likely, Mark Brown, Wei Huang,
	linux-arm-kernel, linux-acpi, linux-kernel, linaro-acpi,
	Hanjun Guo

For now, ACPI based GICv2 is using the irq_default_domain as the
ACPI core domain which is not scalable, also we don't support
stacked irq domains in ACPI, this patch is trying to implement that.

Firstly, we need to find the irqdomain with GSI, because we use
different model of mapping interrupt with device in ACPI than DT,
in DT, we using the interrupt parent property to get the device
node of irqchip for devices, that's why we need the matching function
that match the device node with the one associated with the irqdomain.
But for ACPI, we only can get the GSI which the device is using, no
interrupt parent will be specified, then we need a mechanism to find
GSI's (also the device's) irqdomain to make the code scalable.

Thanks to the usage of GSI, it is a flat hwirq number which is unique
in the system, then we can get its associated irq domain by matching
the GSI supported by this irqchip (see drawings below), then we can
live without the token pointer matching the interrupt controller as
DT did.

                  ------------      ---> gsi_base0
                 |            |
                 |            |
  irqdomain <----| irqchip 0  |
                 |            |
                 |            |
                 |____________|     ---> gsi_end0

                  ------------      ---> gsi_base1 (probably gsi_end0+1)
                 |            |
                 |            |
  irqdomain <----| irqchip 1  |
                 |            |
                 |            |
                 |____________|     ---> gsi_end1

                  .....

if a device is using GSI n, then we can find GSI's irqdomain by matching
gsi_base <= n <= gsi_end.

For GIC, we only have one GICD, but the above model still valid. GICD
structure in ACPI MADT defines System Vector Base in the GICD entry,
which means the global system interrupt number where this GIC
Distributor’s interrupt inputs start, then we can get the hwirq numbers
supported by reading the register, so we can explictly get the GSI's
associated irqdomain if the GSI is within the range of hwirq supported
by this GICD.

Secondly, pass the GSI as the arg for domain's ops alloc() function
when register the GSI, then we can take advantage of stacked irqdomains.

Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 drivers/acpi/gsi.c        | 78 ++++++++++++++++++++++++++++++++++++++---------
 drivers/irqchip/irq-gic.c | 37 +++++++++++++---------
 include/linux/acpi.h      |  5 +++
 3 files changed, 90 insertions(+), 30 deletions(-)

diff --git a/drivers/acpi/gsi.c b/drivers/acpi/gsi.c
index 38208f2..ba7de7f 100644
--- a/drivers/acpi/gsi.c
+++ b/drivers/acpi/gsi.c
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2015 ARM Ltd.
  * Author: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+ *         Hanjun Guo <hanjun.guo@linaro.org> for stacked irqdomains support
  *
  * 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
@@ -14,6 +15,54 @@
 
 enum acpi_irq_model_id acpi_irq_model;
 
+struct gsi_cfg_data {
+	struct list_head list;
+	u32 gsi_base;
+	u32 gsi_end;
+	struct irq_domain *domain;
+};
+
+static LIST_HEAD(gsi_cfg_data_list);
+static DEFINE_MUTEX(gsi_mutex);
+
+/* Init the gsi cfg data which is called by irqchip drivers */
+int gsi_cfg_data_add(struct irq_domain *domain, u32 gsi_base, u32 gsi_end)
+{
+	struct gsi_cfg_data *data;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->domain = domain;
+	data->gsi_base = gsi_base;
+	data->gsi_end = gsi_end;
+
+	mutex_lock(&gsi_mutex);
+	list_add(&data->list, &gsi_cfg_data_list);
+	mutex_unlock(&gsi_mutex);
+
+	return 0;
+}
+
+/* Find irqdomain with GSI (hwirq number) */
+static struct irq_domain *acpi_find_irqdomain(u32 gsi)
+{
+	struct gsi_cfg_data *data;
+	struct irq_domain *domain = NULL;
+
+	mutex_lock(&gsi_mutex);
+	list_for_each_entry(data, &gsi_cfg_data_list, list) {
+		if (gsi >= data->gsi_base && gsi <= data->gsi_end) {
+			domain = data->domain;
+			break;
+		}
+	}
+	mutex_unlock(&gsi_mutex);
+
+	return domain;
+}
+
 static unsigned int acpi_gsi_get_irq_type(int trigger, int polarity)
 {
 	switch (polarity) {
@@ -45,12 +94,9 @@ static unsigned int acpi_gsi_get_irq_type(int trigger, int polarity)
  */
 int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
 {
-	/*
-	 * Only default domain is supported at present, always find
-	 * the mapping corresponding to default domain by passing NULL
-	 * as irq_domain parameter
-	 */
-	*irq = irq_find_mapping(NULL, gsi);
+	struct irq_domain *domain = acpi_find_irqdomain(gsi);
+
+	*irq = irq_find_mapping(domain, gsi);
 	/*
 	 * *irq == 0 means no mapping, that should
 	 * be reported as a failure
@@ -72,16 +118,17 @@ EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
 int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
 		      int polarity)
 {
-	unsigned int irq;
+	int irq;
 	unsigned int irq_type = acpi_gsi_get_irq_type(trigger, polarity);
+	struct irq_domain *domain = acpi_find_irqdomain(gsi);
 
-	/*
-	 * There is no way at present to look-up the IRQ domain on ACPI,
-	 * hence always create mapping referring to the default domain
-	 * by passing NULL as irq_domain parameter
-	 */
-	irq = irq_create_mapping(NULL, gsi);
-	if (!irq)
+	irq = irq_find_mapping(domain, gsi);
+	if (irq > 0)
+		return irq;
+
+	/* pass gsi as the hwirq num and get it in the domain's alloc() ops */
+	irq = irq_domain_alloc_irqs(domain, 1, dev_to_node(dev), &gsi);
+	if (irq <= 0)
 		return -EINVAL;
 
 	/* Set irq type if specified and different than the current one */
@@ -98,7 +145,8 @@ EXPORT_SYMBOL_GPL(acpi_register_gsi);
  */
 void acpi_unregister_gsi(u32 gsi)
 {
-	int irq = irq_find_mapping(NULL, gsi);
+	struct irq_domain *domain = acpi_find_irqdomain(gsi);
+	int irq = irq_find_mapping(domain, gsi);
 
 	irq_dispose_mapping(irq);
 }
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 58a7112..39c1b0d 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -852,15 +852,22 @@ static struct notifier_block gic_cpu_notifier = {
 static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 				unsigned int nr_irqs, void *arg)
 {
-	int i, ret;
+	int i;
 	irq_hw_number_t hwirq;
-	unsigned int type = IRQ_TYPE_NONE;
-	struct of_phandle_args *irq_data = arg;
 
-	ret = gic_irq_domain_xlate(domain, irq_data->np, irq_data->args,
-				   irq_data->args_count, &hwirq, &type);
-	if (ret)
-		return ret;
+	if (acpi_disabled) {	/* DT case */
+		int ret;
+		unsigned int type = IRQ_TYPE_NONE;
+		struct of_phandle_args *irq_data = arg;
+
+		ret = gic_irq_domain_xlate(domain, irq_data->np,
+					irq_data->args,
+					irq_data->args_count, &hwirq, &type);
+		if (ret)
+			return ret;
+	} else {	/* ACPI case */
+		hwirq = (irq_hw_number_t)*(u32 *)arg;
+	}
 
 	for (i = 0; i < nr_irqs; i++)
 		gic_irq_domain_map(domain, virq + i, hwirq + i);
@@ -946,11 +953,11 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
 		gic_irqs = 1020;
 	gic->gic_irqs = gic_irqs;
 
-	if (node) {		/* DT case */
+	if (node || !acpi_disabled) {	/* DT or ACPI case */
 		gic->domain = irq_domain_add_linear(node, gic_irqs,
 						    &gic_irq_domain_hierarchy_ops,
 						    gic);
-	} else {		/* Non-DT case */
+	} else {		/* Non-DT and Non-ACPI case */
 		/*
 		 * For primary GICs, skip over SGIs.
 		 * For secondary GICs, skip over PPIs, too.
@@ -1044,6 +1051,7 @@ IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init);
 
 #ifdef CONFIG_ACPI
 static phys_addr_t dist_phy_base, cpu_phy_base __initdata;
+static u32 gsi_base __initdata;
 
 static int __init
 gic_acpi_parse_madt_cpu(struct acpi_subtable_header *header,
@@ -1082,6 +1090,7 @@ gic_acpi_parse_madt_distributor(struct acpi_subtable_header *header,
 	if (BAD_MADT_ENTRY(dist, end))
 		return -EINVAL;
 
+	gsi_base = dist->global_irq_base;
 	dist_phy_base = dist->base_address;
 	return 0;
 }
@@ -1131,13 +1140,11 @@ gic_v2_acpi_init(struct acpi_table_header *table)
 		return -ENOMEM;
 	}
 
-	/*
-	 * Initialize zero GIC instance (no multi-GIC support). Also, set GIC
-	 * as default IRQ domain to allow for GSI registration and GSI to IRQ
-	 * number translation (see acpi_register_gsi() and acpi_gsi_to_irq()).
-	 */
 	gic_init_bases(0, -1, dist_base, cpu_base, 0, NULL);
-	irq_set_default_host(gic_data[0].domain);
+
+	/* since we have only one GICD, we can safely use gic_data[0] here */
+	gsi_cfg_data_add(gic_data[0].domain, gsi_base,
+			 gsi_base + gic_data[0].gic_irqs);
 
 	acpi_irq_model = ACPI_IRQ_MODEL_GIC;
 	return 0;
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 7b058f0..6e84714 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -204,6 +204,11 @@ extern int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity);
  */
 void acpi_unregister_gsi (u32 gsi);
 
+#ifdef CONFIG_ACPI_GENERIC_GSI
+struct irq_domain;
+int gsi_cfg_data_add(struct irq_domain *domain, u32 gsi_base, u32 gsi_end);
+#endif
+
 struct pci_dev;
 
 int acpi_pci_irq_enable (struct pci_dev *dev);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 4/8] irqchip / gic: Add stacked irqdomain support for ACPI based GICv2 init
@ 2015-07-10 10:45   ` Hanjun Guo
  0 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-10 10:45 UTC (permalink / raw)
  To: Marc Zyngier, Jason Cooper, Will Deacon, Catalin Marinas,
	Rafael J. Wysocki
  Cc: Thomas Gleixner, Jiang Liu, Lorenzo Pieralisi, Arnd Bergmann,
	Tomasz Nowicki, Grant Likely, Mark Brown, Wei Huang,
	linux-arm-kernel, linux-acpi, linux-kernel, linaro-acpi,
	Hanjun Guo

For now, ACPI based GICv2 is using the irq_default_domain as the
ACPI core domain which is not scalable, also we don't support
stacked irq domains in ACPI, this patch is trying to implement that.

Firstly, we need to find the irqdomain with GSI, because we use
different model of mapping interrupt with device in ACPI than DT,
in DT, we using the interrupt parent property to get the device
node of irqchip for devices, that's why we need the matching function
that match the device node with the one associated with the irqdomain.
But for ACPI, we only can get the GSI which the device is using, no
interrupt parent will be specified, then we need a mechanism to find
GSI's (also the device's) irqdomain to make the code scalable.

Thanks to the usage of GSI, it is a flat hwirq number which is unique
in the system, then we can get its associated irq domain by matching
the GSI supported by this irqchip (see drawings below), then we can
live without the token pointer matching the interrupt controller as
DT did.

                  ------------      ---> gsi_base0
                 |            |
                 |            |
  irqdomain <----| irqchip 0  |
                 |            |
                 |            |
                 |____________|     ---> gsi_end0

                  ------------      ---> gsi_base1 (probably gsi_end0+1)
                 |            |
                 |            |
  irqdomain <----| irqchip 1  |
                 |            |
                 |            |
                 |____________|     ---> gsi_end1

                  .....

if a device is using GSI n, then we can find GSI's irqdomain by matching
gsi_base <= n <= gsi_end.

For GIC, we only have one GICD, but the above model still valid. GICD
structure in ACPI MADT defines System Vector Base in the GICD entry,
which means the global system interrupt number where this GIC
Distributor’s interrupt inputs start, then we can get the hwirq numbers
supported by reading the register, so we can explictly get the GSI's
associated irqdomain if the GSI is within the range of hwirq supported
by this GICD.

Secondly, pass the GSI as the arg for domain's ops alloc() function
when register the GSI, then we can take advantage of stacked irqdomains.

Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 drivers/acpi/gsi.c        | 78 ++++++++++++++++++++++++++++++++++++++---------
 drivers/irqchip/irq-gic.c | 37 +++++++++++++---------
 include/linux/acpi.h      |  5 +++
 3 files changed, 90 insertions(+), 30 deletions(-)

diff --git a/drivers/acpi/gsi.c b/drivers/acpi/gsi.c
index 38208f2..ba7de7f 100644
--- a/drivers/acpi/gsi.c
+++ b/drivers/acpi/gsi.c
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2015 ARM Ltd.
  * Author: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+ *         Hanjun Guo <hanjun.guo@linaro.org> for stacked irqdomains support
  *
  * 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
@@ -14,6 +15,54 @@
 
 enum acpi_irq_model_id acpi_irq_model;
 
+struct gsi_cfg_data {
+	struct list_head list;
+	u32 gsi_base;
+	u32 gsi_end;
+	struct irq_domain *domain;
+};
+
+static LIST_HEAD(gsi_cfg_data_list);
+static DEFINE_MUTEX(gsi_mutex);
+
+/* Init the gsi cfg data which is called by irqchip drivers */
+int gsi_cfg_data_add(struct irq_domain *domain, u32 gsi_base, u32 gsi_end)
+{
+	struct gsi_cfg_data *data;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->domain = domain;
+	data->gsi_base = gsi_base;
+	data->gsi_end = gsi_end;
+
+	mutex_lock(&gsi_mutex);
+	list_add(&data->list, &gsi_cfg_data_list);
+	mutex_unlock(&gsi_mutex);
+
+	return 0;
+}
+
+/* Find irqdomain with GSI (hwirq number) */
+static struct irq_domain *acpi_find_irqdomain(u32 gsi)
+{
+	struct gsi_cfg_data *data;
+	struct irq_domain *domain = NULL;
+
+	mutex_lock(&gsi_mutex);
+	list_for_each_entry(data, &gsi_cfg_data_list, list) {
+		if (gsi >= data->gsi_base && gsi <= data->gsi_end) {
+			domain = data->domain;
+			break;
+		}
+	}
+	mutex_unlock(&gsi_mutex);
+
+	return domain;
+}
+
 static unsigned int acpi_gsi_get_irq_type(int trigger, int polarity)
 {
 	switch (polarity) {
@@ -45,12 +94,9 @@ static unsigned int acpi_gsi_get_irq_type(int trigger, int polarity)
  */
 int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
 {
-	/*
-	 * Only default domain is supported at present, always find
-	 * the mapping corresponding to default domain by passing NULL
-	 * as irq_domain parameter
-	 */
-	*irq = irq_find_mapping(NULL, gsi);
+	struct irq_domain *domain = acpi_find_irqdomain(gsi);
+
+	*irq = irq_find_mapping(domain, gsi);
 	/*
 	 * *irq == 0 means no mapping, that should
 	 * be reported as a failure
@@ -72,16 +118,17 @@ EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
 int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
 		      int polarity)
 {
-	unsigned int irq;
+	int irq;
 	unsigned int irq_type = acpi_gsi_get_irq_type(trigger, polarity);
+	struct irq_domain *domain = acpi_find_irqdomain(gsi);
 
-	/*
-	 * There is no way at present to look-up the IRQ domain on ACPI,
-	 * hence always create mapping referring to the default domain
-	 * by passing NULL as irq_domain parameter
-	 */
-	irq = irq_create_mapping(NULL, gsi);
-	if (!irq)
+	irq = irq_find_mapping(domain, gsi);
+	if (irq > 0)
+		return irq;
+
+	/* pass gsi as the hwirq num and get it in the domain's alloc() ops */
+	irq = irq_domain_alloc_irqs(domain, 1, dev_to_node(dev), &gsi);
+	if (irq <= 0)
 		return -EINVAL;
 
 	/* Set irq type if specified and different than the current one */
@@ -98,7 +145,8 @@ EXPORT_SYMBOL_GPL(acpi_register_gsi);
  */
 void acpi_unregister_gsi(u32 gsi)
 {
-	int irq = irq_find_mapping(NULL, gsi);
+	struct irq_domain *domain = acpi_find_irqdomain(gsi);
+	int irq = irq_find_mapping(domain, gsi);
 
 	irq_dispose_mapping(irq);
 }
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 58a7112..39c1b0d 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -852,15 +852,22 @@ static struct notifier_block gic_cpu_notifier = {
 static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 				unsigned int nr_irqs, void *arg)
 {
-	int i, ret;
+	int i;
 	irq_hw_number_t hwirq;
-	unsigned int type = IRQ_TYPE_NONE;
-	struct of_phandle_args *irq_data = arg;
 
-	ret = gic_irq_domain_xlate(domain, irq_data->np, irq_data->args,
-				   irq_data->args_count, &hwirq, &type);
-	if (ret)
-		return ret;
+	if (acpi_disabled) {	/* DT case */
+		int ret;
+		unsigned int type = IRQ_TYPE_NONE;
+		struct of_phandle_args *irq_data = arg;
+
+		ret = gic_irq_domain_xlate(domain, irq_data->np,
+					irq_data->args,
+					irq_data->args_count, &hwirq, &type);
+		if (ret)
+			return ret;
+	} else {	/* ACPI case */
+		hwirq = (irq_hw_number_t)*(u32 *)arg;
+	}
 
 	for (i = 0; i < nr_irqs; i++)
 		gic_irq_domain_map(domain, virq + i, hwirq + i);
@@ -946,11 +953,11 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
 		gic_irqs = 1020;
 	gic->gic_irqs = gic_irqs;
 
-	if (node) {		/* DT case */
+	if (node || !acpi_disabled) {	/* DT or ACPI case */
 		gic->domain = irq_domain_add_linear(node, gic_irqs,
 						    &gic_irq_domain_hierarchy_ops,
 						    gic);
-	} else {		/* Non-DT case */
+	} else {		/* Non-DT and Non-ACPI case */
 		/*
 		 * For primary GICs, skip over SGIs.
 		 * For secondary GICs, skip over PPIs, too.
@@ -1044,6 +1051,7 @@ IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init);
 
 #ifdef CONFIG_ACPI
 static phys_addr_t dist_phy_base, cpu_phy_base __initdata;
+static u32 gsi_base __initdata;
 
 static int __init
 gic_acpi_parse_madt_cpu(struct acpi_subtable_header *header,
@@ -1082,6 +1090,7 @@ gic_acpi_parse_madt_distributor(struct acpi_subtable_header *header,
 	if (BAD_MADT_ENTRY(dist, end))
 		return -EINVAL;
 
+	gsi_base = dist->global_irq_base;
 	dist_phy_base = dist->base_address;
 	return 0;
 }
@@ -1131,13 +1140,11 @@ gic_v2_acpi_init(struct acpi_table_header *table)
 		return -ENOMEM;
 	}
 
-	/*
-	 * Initialize zero GIC instance (no multi-GIC support). Also, set GIC
-	 * as default IRQ domain to allow for GSI registration and GSI to IRQ
-	 * number translation (see acpi_register_gsi() and acpi_gsi_to_irq()).
-	 */
 	gic_init_bases(0, -1, dist_base, cpu_base, 0, NULL);
-	irq_set_default_host(gic_data[0].domain);
+
+	/* since we have only one GICD, we can safely use gic_data[0] here */
+	gsi_cfg_data_add(gic_data[0].domain, gsi_base,
+			 gsi_base + gic_data[0].gic_irqs);
 
 	acpi_irq_model = ACPI_IRQ_MODEL_GIC;
 	return 0;
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 7b058f0..6e84714 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -204,6 +204,11 @@ extern int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity);
  */
 void acpi_unregister_gsi (u32 gsi);
 
+#ifdef CONFIG_ACPI_GENERIC_GSI
+struct irq_domain;
+int gsi_cfg_data_add(struct irq_domain *domain, u32 gsi_base, u32 gsi_end);
+#endif
+
 struct pci_dev;
 
 int acpi_pci_irq_enable (struct pci_dev *dev);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 4/8] irqchip / gic: Add stacked irqdomain support for ACPI based GICv2 init
@ 2015-07-10 10:45   ` Hanjun Guo
  0 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-10 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

For now, ACPI based GICv2 is using the irq_default_domain as the
ACPI core domain which is not scalable, also we don't support
stacked irq domains in ACPI, this patch is trying to implement that.

Firstly, we need to find the irqdomain with GSI, because we use
different model of mapping interrupt with device in ACPI than DT,
in DT, we using the interrupt parent property to get the device
node of irqchip for devices, that's why we need the matching function
that match the device node with the one associated with the irqdomain.
But for ACPI, we only can get the GSI which the device is using, no
interrupt parent will be specified, then we need a mechanism to find
GSI's (also the device's) irqdomain to make the code scalable.

Thanks to the usage of GSI, it is a flat hwirq number which is unique
in the system, then we can get its associated irq domain by matching
the GSI supported by this irqchip (see drawings below), then we can
live without the token pointer matching the interrupt controller as
DT did.

                  ------------      ---> gsi_base0
                 |            |
                 |            |
  irqdomain <----| irqchip 0  |
                 |            |
                 |            |
                 |____________|     ---> gsi_end0

                  ------------      ---> gsi_base1 (probably gsi_end0+1)
                 |            |
                 |            |
  irqdomain <----| irqchip 1  |
                 |            |
                 |            |
                 |____________|     ---> gsi_end1

                  .....

if a device is using GSI n, then we can find GSI's irqdomain by matching
gsi_base <= n <= gsi_end.

For GIC, we only have one GICD, but the above model still valid. GICD
structure in ACPI MADT defines System Vector Base in the GICD entry,
which means the global system interrupt number where this GIC
Distributor?s interrupt inputs start, then we can get the hwirq numbers
supported by reading the register, so we can explictly get the GSI's
associated irqdomain if the GSI is within the range of hwirq supported
by this GICD.

Secondly, pass the GSI as the arg for domain's ops alloc() function
when register the GSI, then we can take advantage of stacked irqdomains.

Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 drivers/acpi/gsi.c        | 78 ++++++++++++++++++++++++++++++++++++++---------
 drivers/irqchip/irq-gic.c | 37 +++++++++++++---------
 include/linux/acpi.h      |  5 +++
 3 files changed, 90 insertions(+), 30 deletions(-)

diff --git a/drivers/acpi/gsi.c b/drivers/acpi/gsi.c
index 38208f2..ba7de7f 100644
--- a/drivers/acpi/gsi.c
+++ b/drivers/acpi/gsi.c
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2015 ARM Ltd.
  * Author: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+ *         Hanjun Guo <hanjun.guo@linaro.org> for stacked irqdomains support
  *
  * 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
@@ -14,6 +15,54 @@
 
 enum acpi_irq_model_id acpi_irq_model;
 
+struct gsi_cfg_data {
+	struct list_head list;
+	u32 gsi_base;
+	u32 gsi_end;
+	struct irq_domain *domain;
+};
+
+static LIST_HEAD(gsi_cfg_data_list);
+static DEFINE_MUTEX(gsi_mutex);
+
+/* Init the gsi cfg data which is called by irqchip drivers */
+int gsi_cfg_data_add(struct irq_domain *domain, u32 gsi_base, u32 gsi_end)
+{
+	struct gsi_cfg_data *data;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->domain = domain;
+	data->gsi_base = gsi_base;
+	data->gsi_end = gsi_end;
+
+	mutex_lock(&gsi_mutex);
+	list_add(&data->list, &gsi_cfg_data_list);
+	mutex_unlock(&gsi_mutex);
+
+	return 0;
+}
+
+/* Find irqdomain with GSI (hwirq number) */
+static struct irq_domain *acpi_find_irqdomain(u32 gsi)
+{
+	struct gsi_cfg_data *data;
+	struct irq_domain *domain = NULL;
+
+	mutex_lock(&gsi_mutex);
+	list_for_each_entry(data, &gsi_cfg_data_list, list) {
+		if (gsi >= data->gsi_base && gsi <= data->gsi_end) {
+			domain = data->domain;
+			break;
+		}
+	}
+	mutex_unlock(&gsi_mutex);
+
+	return domain;
+}
+
 static unsigned int acpi_gsi_get_irq_type(int trigger, int polarity)
 {
 	switch (polarity) {
@@ -45,12 +94,9 @@ static unsigned int acpi_gsi_get_irq_type(int trigger, int polarity)
  */
 int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
 {
-	/*
-	 * Only default domain is supported at present, always find
-	 * the mapping corresponding to default domain by passing NULL
-	 * as irq_domain parameter
-	 */
-	*irq = irq_find_mapping(NULL, gsi);
+	struct irq_domain *domain = acpi_find_irqdomain(gsi);
+
+	*irq = irq_find_mapping(domain, gsi);
 	/*
 	 * *irq == 0 means no mapping, that should
 	 * be reported as a failure
@@ -72,16 +118,17 @@ EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
 int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
 		      int polarity)
 {
-	unsigned int irq;
+	int irq;
 	unsigned int irq_type = acpi_gsi_get_irq_type(trigger, polarity);
+	struct irq_domain *domain = acpi_find_irqdomain(gsi);
 
-	/*
-	 * There is no way at present to look-up the IRQ domain on ACPI,
-	 * hence always create mapping referring to the default domain
-	 * by passing NULL as irq_domain parameter
-	 */
-	irq = irq_create_mapping(NULL, gsi);
-	if (!irq)
+	irq = irq_find_mapping(domain, gsi);
+	if (irq > 0)
+		return irq;
+
+	/* pass gsi as the hwirq num and get it in the domain's alloc() ops */
+	irq = irq_domain_alloc_irqs(domain, 1, dev_to_node(dev), &gsi);
+	if (irq <= 0)
 		return -EINVAL;
 
 	/* Set irq type if specified and different than the current one */
@@ -98,7 +145,8 @@ EXPORT_SYMBOL_GPL(acpi_register_gsi);
  */
 void acpi_unregister_gsi(u32 gsi)
 {
-	int irq = irq_find_mapping(NULL, gsi);
+	struct irq_domain *domain = acpi_find_irqdomain(gsi);
+	int irq = irq_find_mapping(domain, gsi);
 
 	irq_dispose_mapping(irq);
 }
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 58a7112..39c1b0d 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -852,15 +852,22 @@ static struct notifier_block gic_cpu_notifier = {
 static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 				unsigned int nr_irqs, void *arg)
 {
-	int i, ret;
+	int i;
 	irq_hw_number_t hwirq;
-	unsigned int type = IRQ_TYPE_NONE;
-	struct of_phandle_args *irq_data = arg;
 
-	ret = gic_irq_domain_xlate(domain, irq_data->np, irq_data->args,
-				   irq_data->args_count, &hwirq, &type);
-	if (ret)
-		return ret;
+	if (acpi_disabled) {	/* DT case */
+		int ret;
+		unsigned int type = IRQ_TYPE_NONE;
+		struct of_phandle_args *irq_data = arg;
+
+		ret = gic_irq_domain_xlate(domain, irq_data->np,
+					irq_data->args,
+					irq_data->args_count, &hwirq, &type);
+		if (ret)
+			return ret;
+	} else {	/* ACPI case */
+		hwirq = (irq_hw_number_t)*(u32 *)arg;
+	}
 
 	for (i = 0; i < nr_irqs; i++)
 		gic_irq_domain_map(domain, virq + i, hwirq + i);
@@ -946,11 +953,11 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
 		gic_irqs = 1020;
 	gic->gic_irqs = gic_irqs;
 
-	if (node) {		/* DT case */
+	if (node || !acpi_disabled) {	/* DT or ACPI case */
 		gic->domain = irq_domain_add_linear(node, gic_irqs,
 						    &gic_irq_domain_hierarchy_ops,
 						    gic);
-	} else {		/* Non-DT case */
+	} else {		/* Non-DT and Non-ACPI case */
 		/*
 		 * For primary GICs, skip over SGIs.
 		 * For secondary GICs, skip over PPIs, too.
@@ -1044,6 +1051,7 @@ IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init);
 
 #ifdef CONFIG_ACPI
 static phys_addr_t dist_phy_base, cpu_phy_base __initdata;
+static u32 gsi_base __initdata;
 
 static int __init
 gic_acpi_parse_madt_cpu(struct acpi_subtable_header *header,
@@ -1082,6 +1090,7 @@ gic_acpi_parse_madt_distributor(struct acpi_subtable_header *header,
 	if (BAD_MADT_ENTRY(dist, end))
 		return -EINVAL;
 
+	gsi_base = dist->global_irq_base;
 	dist_phy_base = dist->base_address;
 	return 0;
 }
@@ -1131,13 +1140,11 @@ gic_v2_acpi_init(struct acpi_table_header *table)
 		return -ENOMEM;
 	}
 
-	/*
-	 * Initialize zero GIC instance (no multi-GIC support). Also, set GIC
-	 * as default IRQ domain to allow for GSI registration and GSI to IRQ
-	 * number translation (see acpi_register_gsi() and acpi_gsi_to_irq()).
-	 */
 	gic_init_bases(0, -1, dist_base, cpu_base, 0, NULL);
-	irq_set_default_host(gic_data[0].domain);
+
+	/* since we have only one GICD, we can safely use gic_data[0] here */
+	gsi_cfg_data_add(gic_data[0].domain, gsi_base,
+			 gsi_base + gic_data[0].gic_irqs);
 
 	acpi_irq_model = ACPI_IRQ_MODEL_GIC;
 	return 0;
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 7b058f0..6e84714 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -204,6 +204,11 @@ extern int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity);
  */
 void acpi_unregister_gsi (u32 gsi);
 
+#ifdef CONFIG_ACPI_GENERIC_GSI
+struct irq_domain;
+int gsi_cfg_data_add(struct irq_domain *domain, u32 gsi_base, u32 gsi_end);
+#endif
+
 struct pci_dev;
 
 int acpi_pci_irq_enable (struct pci_dev *dev);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 5/8] irqchip / GICv3: Refactor gic_of_init() for GICv3 driver
  2015-07-10 10:45 ` Hanjun Guo
@ 2015-07-10 10:45   ` Hanjun Guo
  -1 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-10 10:45 UTC (permalink / raw)
  To: Marc Zyngier, Jason Cooper, Will Deacon, Catalin Marinas,
	Rafael J. Wysocki
  Cc: Thomas Gleixner, Jiang Liu, Lorenzo Pieralisi, Arnd Bergmann,
	Tomasz Nowicki, Grant Likely, Mark Brown, Wei Huang,
	linux-arm-kernel, linux-acpi, linux-kernel, linaro-acpi,
	Hanjun Guo

From: Tomasz Nowicki <tomasz.nowicki@linaro.org>

Isolate hardware abstraction (FDT) code to gic_of_init().
Rest of the logic goes to gic_init_bases() and expects well
defined data to initialize GIC properly. The same solution
is used for GICv2 driver.

This is needed for ACPI initialization later.

Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 drivers/irqchip/irq-gic-v3.c | 105 +++++++++++++++++++++++++------------------
 1 file changed, 61 insertions(+), 44 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index c52f7ba..aeba1cc 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -766,17 +766,69 @@ static const struct irq_domain_ops gic_irq_domain_ops = {
 	.free = gic_irq_domain_free,
 };
 
+static int __init gic_init_bases(void __iomem *dist_base,
+			    struct redist_region *rdist_regs,
+			    u32 nr_redist_regions,
+			    u64 redist_stride,
+			    struct device_node *node)
+{
+	u32 typer;
+	int gic_irqs;
+	int err;
+
+	gic_data.dist_base = dist_base;
+	gic_data.redist_regions = rdist_regs;
+	gic_data.nr_redist_regions = nr_redist_regions;
+	gic_data.redist_stride = redist_stride;
+
+	/*
+	 * Find out how many interrupts are supported.
+	 * The GIC only supports up to 1020 interrupt sources (SGI+PPI+SPI)
+	 */
+	typer = readl_relaxed(gic_data.dist_base + GICD_TYPER);
+	gic_data.rdists.id_bits = GICD_TYPER_ID_BITS(typer);
+	gic_irqs = GICD_TYPER_IRQS(typer);
+	if (gic_irqs > 1020)
+		gic_irqs = 1020;
+	gic_data.irq_nr = gic_irqs;
+
+	gic_data.domain = irq_domain_add_tree(node, &gic_irq_domain_ops,
+					      &gic_data);
+	gic_data.rdists.rdist = alloc_percpu(typeof(*gic_data.rdists.rdist));
+
+	if (WARN_ON(!gic_data.domain) || WARN_ON(!gic_data.rdists.rdist)) {
+		err = -ENOMEM;
+		goto out_free;
+	}
+
+	set_handle_irq(gic_handle_irq);
+
+	if (IS_ENABLED(CONFIG_ARM_GIC_V3_ITS) && gic_dist_supports_lpis())
+		its_init(node, &gic_data.rdists, gic_data.domain);
+
+	gic_smp_init();
+	gic_dist_init();
+	gic_cpu_init();
+	gic_cpu_pm_init();
+
+	return 0;
+
+out_free:
+	if (gic_data.domain)
+		irq_domain_remove(gic_data.domain);
+	free_percpu(gic_data.rdists.rdist);
+	return err;
+}
+
+#ifdef CONFIG_OF
 static int __init gic_of_init(struct device_node *node, struct device_node *parent)
 {
 	void __iomem *dist_base;
 	struct redist_region *rdist_regs;
 	u64 redist_stride;
 	u32 nr_redist_regions;
-	u32 typer;
 	u32 reg;
-	int gic_irqs;
-	int err;
-	int i;
+	int err, i;
 
 	dist_base = of_iomap(node, 0);
 	if (!dist_base) {
@@ -820,47 +872,11 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
 	if (of_property_read_u64(node, "redistributor-stride", &redist_stride))
 		redist_stride = 0;
 
-	gic_data.dist_base = dist_base;
-	gic_data.redist_regions = rdist_regs;
-	gic_data.nr_redist_regions = nr_redist_regions;
-	gic_data.redist_stride = redist_stride;
-
-	/*
-	 * Find out how many interrupts are supported.
-	 * The GIC only supports up to 1020 interrupt sources (SGI+PPI+SPI)
-	 */
-	typer = readl_relaxed(gic_data.dist_base + GICD_TYPER);
-	gic_data.rdists.id_bits = GICD_TYPER_ID_BITS(typer);
-	gic_irqs = GICD_TYPER_IRQS(typer);
-	if (gic_irqs > 1020)
-		gic_irqs = 1020;
-	gic_data.irq_nr = gic_irqs;
+	err = gic_init_bases(dist_base, rdist_regs, nr_redist_regions,
+			     redist_stride, node);
+	if (!err)
+		return 0;
 
-	gic_data.domain = irq_domain_add_tree(node, &gic_irq_domain_ops,
-					      &gic_data);
-	gic_data.rdists.rdist = alloc_percpu(typeof(*gic_data.rdists.rdist));
-
-	if (WARN_ON(!gic_data.domain) || WARN_ON(!gic_data.rdists.rdist)) {
-		err = -ENOMEM;
-		goto out_free;
-	}
-
-	set_handle_irq(gic_handle_irq);
-
-	if (IS_ENABLED(CONFIG_ARM_GIC_V3_ITS) && gic_dist_supports_lpis())
-		its_init(node, &gic_data.rdists, gic_data.domain);
-
-	gic_smp_init();
-	gic_dist_init();
-	gic_cpu_init();
-	gic_cpu_pm_init();
-
-	return 0;
-
-out_free:
-	if (gic_data.domain)
-		irq_domain_remove(gic_data.domain);
-	free_percpu(gic_data.rdists.rdist);
 out_unmap_rdist:
 	for (i = 0; i < nr_redist_regions; i++)
 		if (rdist_regs[i].redist_base)
@@ -872,3 +888,4 @@ out_unmap_dist:
 }
 
 IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
+#endif
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 5/8] irqchip / GICv3: Refactor gic_of_init() for GICv3 driver
@ 2015-07-10 10:45   ` Hanjun Guo
  0 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-10 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

From: Tomasz Nowicki <tomasz.nowicki@linaro.org>

Isolate hardware abstraction (FDT) code to gic_of_init().
Rest of the logic goes to gic_init_bases() and expects well
defined data to initialize GIC properly. The same solution
is used for GICv2 driver.

This is needed for ACPI initialization later.

Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 drivers/irqchip/irq-gic-v3.c | 105 +++++++++++++++++++++++++------------------
 1 file changed, 61 insertions(+), 44 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index c52f7ba..aeba1cc 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -766,17 +766,69 @@ static const struct irq_domain_ops gic_irq_domain_ops = {
 	.free = gic_irq_domain_free,
 };
 
+static int __init gic_init_bases(void __iomem *dist_base,
+			    struct redist_region *rdist_regs,
+			    u32 nr_redist_regions,
+			    u64 redist_stride,
+			    struct device_node *node)
+{
+	u32 typer;
+	int gic_irqs;
+	int err;
+
+	gic_data.dist_base = dist_base;
+	gic_data.redist_regions = rdist_regs;
+	gic_data.nr_redist_regions = nr_redist_regions;
+	gic_data.redist_stride = redist_stride;
+
+	/*
+	 * Find out how many interrupts are supported.
+	 * The GIC only supports up to 1020 interrupt sources (SGI+PPI+SPI)
+	 */
+	typer = readl_relaxed(gic_data.dist_base + GICD_TYPER);
+	gic_data.rdists.id_bits = GICD_TYPER_ID_BITS(typer);
+	gic_irqs = GICD_TYPER_IRQS(typer);
+	if (gic_irqs > 1020)
+		gic_irqs = 1020;
+	gic_data.irq_nr = gic_irqs;
+
+	gic_data.domain = irq_domain_add_tree(node, &gic_irq_domain_ops,
+					      &gic_data);
+	gic_data.rdists.rdist = alloc_percpu(typeof(*gic_data.rdists.rdist));
+
+	if (WARN_ON(!gic_data.domain) || WARN_ON(!gic_data.rdists.rdist)) {
+		err = -ENOMEM;
+		goto out_free;
+	}
+
+	set_handle_irq(gic_handle_irq);
+
+	if (IS_ENABLED(CONFIG_ARM_GIC_V3_ITS) && gic_dist_supports_lpis())
+		its_init(node, &gic_data.rdists, gic_data.domain);
+
+	gic_smp_init();
+	gic_dist_init();
+	gic_cpu_init();
+	gic_cpu_pm_init();
+
+	return 0;
+
+out_free:
+	if (gic_data.domain)
+		irq_domain_remove(gic_data.domain);
+	free_percpu(gic_data.rdists.rdist);
+	return err;
+}
+
+#ifdef CONFIG_OF
 static int __init gic_of_init(struct device_node *node, struct device_node *parent)
 {
 	void __iomem *dist_base;
 	struct redist_region *rdist_regs;
 	u64 redist_stride;
 	u32 nr_redist_regions;
-	u32 typer;
 	u32 reg;
-	int gic_irqs;
-	int err;
-	int i;
+	int err, i;
 
 	dist_base = of_iomap(node, 0);
 	if (!dist_base) {
@@ -820,47 +872,11 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
 	if (of_property_read_u64(node, "redistributor-stride", &redist_stride))
 		redist_stride = 0;
 
-	gic_data.dist_base = dist_base;
-	gic_data.redist_regions = rdist_regs;
-	gic_data.nr_redist_regions = nr_redist_regions;
-	gic_data.redist_stride = redist_stride;
-
-	/*
-	 * Find out how many interrupts are supported.
-	 * The GIC only supports up to 1020 interrupt sources (SGI+PPI+SPI)
-	 */
-	typer = readl_relaxed(gic_data.dist_base + GICD_TYPER);
-	gic_data.rdists.id_bits = GICD_TYPER_ID_BITS(typer);
-	gic_irqs = GICD_TYPER_IRQS(typer);
-	if (gic_irqs > 1020)
-		gic_irqs = 1020;
-	gic_data.irq_nr = gic_irqs;
+	err = gic_init_bases(dist_base, rdist_regs, nr_redist_regions,
+			     redist_stride, node);
+	if (!err)
+		return 0;
 
-	gic_data.domain = irq_domain_add_tree(node, &gic_irq_domain_ops,
-					      &gic_data);
-	gic_data.rdists.rdist = alloc_percpu(typeof(*gic_data.rdists.rdist));
-
-	if (WARN_ON(!gic_data.domain) || WARN_ON(!gic_data.rdists.rdist)) {
-		err = -ENOMEM;
-		goto out_free;
-	}
-
-	set_handle_irq(gic_handle_irq);
-
-	if (IS_ENABLED(CONFIG_ARM_GIC_V3_ITS) && gic_dist_supports_lpis())
-		its_init(node, &gic_data.rdists, gic_data.domain);
-
-	gic_smp_init();
-	gic_dist_init();
-	gic_cpu_init();
-	gic_cpu_pm_init();
-
-	return 0;
-
-out_free:
-	if (gic_data.domain)
-		irq_domain_remove(gic_data.domain);
-	free_percpu(gic_data.rdists.rdist);
 out_unmap_rdist:
 	for (i = 0; i < nr_redist_regions; i++)
 		if (rdist_regs[i].redist_base)
@@ -872,3 +888,4 @@ out_unmap_dist:
 }
 
 IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
+#endif
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 6/8] irqchip / GICv3: Add ACPI support for GICv3+ initialization
  2015-07-10 10:45 ` Hanjun Guo
@ 2015-07-10 10:45   ` Hanjun Guo
  -1 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-10 10:45 UTC (permalink / raw)
  To: Marc Zyngier, Jason Cooper, Will Deacon, Catalin Marinas,
	Rafael J. Wysocki
  Cc: Thomas Gleixner, Jiang Liu, Lorenzo Pieralisi, Arnd Bergmann,
	Tomasz Nowicki, Grant Likely, Mark Brown, Wei Huang,
	linux-arm-kernel, linux-acpi, linux-kernel, linaro-acpi,
	Hanjun Guo

From: Tomasz Nowicki <tomasz.nowicki@linaro.org>

With the refator of gic_of_init(), GICv3/4 can be initialized
by gic_init_bases() with gic distributor base address and gic
redistributor region(s).

So get the redistributor region base addresses from MADT GIC
redistributor subtable, and the distributor base address from
GICD subtable to init GICv3 irqchip in ACPI way.

Note: GIC redistributor base address may also be provided in
GICC structures on systems supporting GICv3 and above if the GIC
Redistributors are not in the always-on power domain, this
patch didn't implement such feature yet.

Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org>
[hj: Rework this patch and fix multi issues]
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 drivers/irqchip/irq-gic-v3.c | 144 +++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 140 insertions(+), 4 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index aeba1cc..7b5bde3 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -15,6 +15,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/acpi.h>
 #include <linux/cpu.h>
 #include <linux/cpu_pm.h>
 #include <linux/delay.h>
@@ -25,6 +26,7 @@
 #include <linux/percpu.h>
 #include <linux/slab.h>
 
+#include <linux/irqchip/arm-gic-acpi.h>
 #include <linux/irqchip/arm-gic-v3.h>
 
 #include <asm/cputype.h>
@@ -820,6 +822,16 @@ out_free:
 	return err;
 }
 
+static int __init detect_distributor(void __iomem *dist_base)
+{
+	u32 reg = readl_relaxed(dist_base + GICD_PIDR2) & GIC_PIDR2_ARCH_MASK;
+
+	if (reg != GIC_PIDR2_ARCH_GICv3 && reg != GIC_PIDR2_ARCH_GICv4)
+		return -ENODEV;
+
+	return 0;
+}
+
 #ifdef CONFIG_OF
 static int __init gic_of_init(struct device_node *node, struct device_node *parent)
 {
@@ -827,7 +839,6 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
 	struct redist_region *rdist_regs;
 	u64 redist_stride;
 	u32 nr_redist_regions;
-	u32 reg;
 	int err, i;
 
 	dist_base = of_iomap(node, 0);
@@ -837,11 +848,10 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
 		return -ENXIO;
 	}
 
-	reg = readl_relaxed(dist_base + GICD_PIDR2) & GIC_PIDR2_ARCH_MASK;
-	if (reg != GIC_PIDR2_ARCH_GICv3 && reg != GIC_PIDR2_ARCH_GICv4) {
+	err = detect_distributor(dist_base);
+	if (err) {
 		pr_err("%s: no distributor detected, giving up\n",
 			node->full_name);
-		err = -ENODEV;
 		goto out_unmap_dist;
 	}
 
@@ -889,3 +899,129 @@ out_unmap_dist:
 
 IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
 #endif
+
+#ifdef CONFIG_ACPI
+static struct redist_region *redist_regs __initdata;
+static u32 nr_redist_regions __initdata;
+static phys_addr_t dist_phy_base __initdata;
+
+static int __init
+gic_acpi_register_redist(u64 phys_base, u64 size)
+{
+	struct redist_region *redist_regs_new;
+	void __iomem *redist_base;
+
+	redist_regs_new = krealloc(redist_regs,
+				   sizeof(*redist_regs) * (nr_redist_regions + 1),
+				   GFP_KERNEL);
+	if (!redist_regs_new) {
+		pr_err("Couldn't allocate resource for GICR region\n");
+		return -ENOMEM;
+	}
+
+	redist_regs = redist_regs_new;
+
+	redist_base = ioremap(phys_base, size);
+	if (!redist_base) {
+		pr_err("Couldn't map GICR region @%llx\n", phys_base);
+		return -ENOMEM;
+	}
+
+	redist_regs[nr_redist_regions].phys_base = phys_base;
+	redist_regs[nr_redist_regions].redist_base = redist_base;
+	nr_redist_regions++;
+	return 0;
+}
+
+static int __init
+gic_acpi_parse_madt_redist(struct acpi_subtable_header *header,
+			const unsigned long end)
+{
+	struct acpi_madt_generic_redistributor *redist;
+
+	if (BAD_MADT_ENTRY(header, end))
+		return -EINVAL;
+
+	redist = (struct acpi_madt_generic_redistributor *)header;
+	if (!redist->base_address)
+		return -EINVAL;
+
+	return gic_acpi_register_redist(redist->base_address, redist->length);
+}
+
+static int __init
+gic_acpi_parse_madt_distributor(struct acpi_subtable_header *header,
+				const unsigned long end)
+{
+	struct acpi_madt_generic_distributor *dist;
+
+	dist = (struct acpi_madt_generic_distributor *)header;
+
+	if (BAD_MADT_ENTRY(dist, end))
+		return -EINVAL;
+
+	dist_phy_base = dist->base_address;
+	return 0;
+}
+
+static int __init
+gic_acpi_init(struct acpi_table_header *table)
+{
+	int count, i, err = 0;
+	void __iomem *dist_base;
+
+	/* Get distributor base address */
+	count = acpi_parse_entries(ACPI_SIG_MADT,
+				sizeof(struct acpi_table_madt),
+				gic_acpi_parse_madt_distributor, table,
+				ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, 0);
+	if (count <= 0) {
+		pr_err("No valid GICD entry exist\n");
+		return -EINVAL;
+	} else if (count > 1) {
+		pr_err("More than one GICD entry detected\n");
+		return -EINVAL;
+	}
+
+	dist_base = ioremap(dist_phy_base, ACPI_GICV3_DIST_MEM_SIZE);
+	if (!dist_base) {
+		pr_err("Unable to map GICD registers\n");
+		return -ENOMEM;
+	}
+
+	err = detect_distributor(dist_base);
+	if (err) {
+		pr_err("No distributor detected at @%p, giving up", dist_base);
+		goto out_dist_unmap;
+	}
+
+	/* Collect redistributor base addresses */
+	count = acpi_parse_entries(ACPI_SIG_MADT,
+			sizeof(struct acpi_table_madt),
+			gic_acpi_parse_madt_redist, table,
+			ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR, 0);
+	if (count <= 0) {
+		pr_info("No valid GICR entries exist\n");
+		err = -EINVAL;
+		goto out_redist_unmap;
+	}
+
+	err = gic_init_bases(dist_base, redist_regs, nr_redist_regions, 0, NULL);
+	if (err)
+		goto out_redist_unmap;
+
+	irq_set_default_host(gic_data.domain);
+	return 0;
+
+out_redist_unmap:
+	for (i = 0; i < nr_redist_regions; i++)
+		if (redist_regs[i].redist_base)
+			iounmap(redist_regs[i].redist_base);
+	kfree(redist_regs);
+out_dist_unmap:
+	iounmap(dist_base);
+	return err;
+}
+IRQCHIP_ACPI_DECLARE(gic_v3, ACPI_MADT_GIC_VERSION_V3, gic_acpi_init);
+IRQCHIP_ACPI_DECLARE(gic_v4, ACPI_MADT_GIC_VERSION_V4, gic_acpi_init);
+#endif
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 6/8] irqchip / GICv3: Add ACPI support for GICv3+ initialization
@ 2015-07-10 10:45   ` Hanjun Guo
  0 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-10 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

From: Tomasz Nowicki <tomasz.nowicki@linaro.org>

With the refator of gic_of_init(), GICv3/4 can be initialized
by gic_init_bases() with gic distributor base address and gic
redistributor region(s).

So get the redistributor region base addresses from MADT GIC
redistributor subtable, and the distributor base address from
GICD subtable to init GICv3 irqchip in ACPI way.

Note: GIC redistributor base address may also be provided in
GICC structures on systems supporting GICv3 and above if the GIC
Redistributors are not in the always-on power domain, this
patch didn't implement such feature yet.

Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org>
[hj: Rework this patch and fix multi issues]
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 drivers/irqchip/irq-gic-v3.c | 144 +++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 140 insertions(+), 4 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index aeba1cc..7b5bde3 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -15,6 +15,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/acpi.h>
 #include <linux/cpu.h>
 #include <linux/cpu_pm.h>
 #include <linux/delay.h>
@@ -25,6 +26,7 @@
 #include <linux/percpu.h>
 #include <linux/slab.h>
 
+#include <linux/irqchip/arm-gic-acpi.h>
 #include <linux/irqchip/arm-gic-v3.h>
 
 #include <asm/cputype.h>
@@ -820,6 +822,16 @@ out_free:
 	return err;
 }
 
+static int __init detect_distributor(void __iomem *dist_base)
+{
+	u32 reg = readl_relaxed(dist_base + GICD_PIDR2) & GIC_PIDR2_ARCH_MASK;
+
+	if (reg != GIC_PIDR2_ARCH_GICv3 && reg != GIC_PIDR2_ARCH_GICv4)
+		return -ENODEV;
+
+	return 0;
+}
+
 #ifdef CONFIG_OF
 static int __init gic_of_init(struct device_node *node, struct device_node *parent)
 {
@@ -827,7 +839,6 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
 	struct redist_region *rdist_regs;
 	u64 redist_stride;
 	u32 nr_redist_regions;
-	u32 reg;
 	int err, i;
 
 	dist_base = of_iomap(node, 0);
@@ -837,11 +848,10 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
 		return -ENXIO;
 	}
 
-	reg = readl_relaxed(dist_base + GICD_PIDR2) & GIC_PIDR2_ARCH_MASK;
-	if (reg != GIC_PIDR2_ARCH_GICv3 && reg != GIC_PIDR2_ARCH_GICv4) {
+	err = detect_distributor(dist_base);
+	if (err) {
 		pr_err("%s: no distributor detected, giving up\n",
 			node->full_name);
-		err = -ENODEV;
 		goto out_unmap_dist;
 	}
 
@@ -889,3 +899,129 @@ out_unmap_dist:
 
 IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
 #endif
+
+#ifdef CONFIG_ACPI
+static struct redist_region *redist_regs __initdata;
+static u32 nr_redist_regions __initdata;
+static phys_addr_t dist_phy_base __initdata;
+
+static int __init
+gic_acpi_register_redist(u64 phys_base, u64 size)
+{
+	struct redist_region *redist_regs_new;
+	void __iomem *redist_base;
+
+	redist_regs_new = krealloc(redist_regs,
+				   sizeof(*redist_regs) * (nr_redist_regions + 1),
+				   GFP_KERNEL);
+	if (!redist_regs_new) {
+		pr_err("Couldn't allocate resource for GICR region\n");
+		return -ENOMEM;
+	}
+
+	redist_regs = redist_regs_new;
+
+	redist_base = ioremap(phys_base, size);
+	if (!redist_base) {
+		pr_err("Couldn't map GICR region @%llx\n", phys_base);
+		return -ENOMEM;
+	}
+
+	redist_regs[nr_redist_regions].phys_base = phys_base;
+	redist_regs[nr_redist_regions].redist_base = redist_base;
+	nr_redist_regions++;
+	return 0;
+}
+
+static int __init
+gic_acpi_parse_madt_redist(struct acpi_subtable_header *header,
+			const unsigned long end)
+{
+	struct acpi_madt_generic_redistributor *redist;
+
+	if (BAD_MADT_ENTRY(header, end))
+		return -EINVAL;
+
+	redist = (struct acpi_madt_generic_redistributor *)header;
+	if (!redist->base_address)
+		return -EINVAL;
+
+	return gic_acpi_register_redist(redist->base_address, redist->length);
+}
+
+static int __init
+gic_acpi_parse_madt_distributor(struct acpi_subtable_header *header,
+				const unsigned long end)
+{
+	struct acpi_madt_generic_distributor *dist;
+
+	dist = (struct acpi_madt_generic_distributor *)header;
+
+	if (BAD_MADT_ENTRY(dist, end))
+		return -EINVAL;
+
+	dist_phy_base = dist->base_address;
+	return 0;
+}
+
+static int __init
+gic_acpi_init(struct acpi_table_header *table)
+{
+	int count, i, err = 0;
+	void __iomem *dist_base;
+
+	/* Get distributor base address */
+	count = acpi_parse_entries(ACPI_SIG_MADT,
+				sizeof(struct acpi_table_madt),
+				gic_acpi_parse_madt_distributor, table,
+				ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, 0);
+	if (count <= 0) {
+		pr_err("No valid GICD entry exist\n");
+		return -EINVAL;
+	} else if (count > 1) {
+		pr_err("More than one GICD entry detected\n");
+		return -EINVAL;
+	}
+
+	dist_base = ioremap(dist_phy_base, ACPI_GICV3_DIST_MEM_SIZE);
+	if (!dist_base) {
+		pr_err("Unable to map GICD registers\n");
+		return -ENOMEM;
+	}
+
+	err = detect_distributor(dist_base);
+	if (err) {
+		pr_err("No distributor detected at @%p, giving up", dist_base);
+		goto out_dist_unmap;
+	}
+
+	/* Collect redistributor base addresses */
+	count = acpi_parse_entries(ACPI_SIG_MADT,
+			sizeof(struct acpi_table_madt),
+			gic_acpi_parse_madt_redist, table,
+			ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR, 0);
+	if (count <= 0) {
+		pr_info("No valid GICR entries exist\n");
+		err = -EINVAL;
+		goto out_redist_unmap;
+	}
+
+	err = gic_init_bases(dist_base, redist_regs, nr_redist_regions, 0, NULL);
+	if (err)
+		goto out_redist_unmap;
+
+	irq_set_default_host(gic_data.domain);
+	return 0;
+
+out_redist_unmap:
+	for (i = 0; i < nr_redist_regions; i++)
+		if (redist_regs[i].redist_base)
+			iounmap(redist_regs[i].redist_base);
+	kfree(redist_regs);
+out_dist_unmap:
+	iounmap(dist_base);
+	return err;
+}
+IRQCHIP_ACPI_DECLARE(gic_v3, ACPI_MADT_GIC_VERSION_V3, gic_acpi_init);
+IRQCHIP_ACPI_DECLARE(gic_v4, ACPI_MADT_GIC_VERSION_V4, gic_acpi_init);
+#endif
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 7/8] irqchip / GICv3: Add stacked irqdomain support for ACPI based init
  2015-07-10 10:45 ` Hanjun Guo
@ 2015-07-10 10:45   ` Hanjun Guo
  -1 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-10 10:45 UTC (permalink / raw)
  To: Marc Zyngier, Jason Cooper, Will Deacon, Catalin Marinas,
	Rafael J. Wysocki
  Cc: Thomas Gleixner, Jiang Liu, Lorenzo Pieralisi, Arnd Bergmann,
	Tomasz Nowicki, Grant Likely, Mark Brown, Wei Huang,
	linux-arm-kernel, linux-acpi, linux-kernel, linaro-acpi,
	Hanjun Guo

Similar as stacked domain support for ACPI based GICv2 init, let
acpi_irq_domain point to the core domain of GICv3 and pass the
gsi as the arg to support stacked irqdomain.

Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 drivers/irqchip/irq-gic-v3.c | 24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 7b5bde3..91d2f9a 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -734,15 +734,21 @@ static int gic_irq_domain_xlate(struct irq_domain *d,
 static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 				unsigned int nr_irqs, void *arg)
 {
-	int i, ret;
+	int i;
 	irq_hw_number_t hwirq;
-	unsigned int type = IRQ_TYPE_NONE;
-	struct of_phandle_args *irq_data = arg;
 
-	ret = gic_irq_domain_xlate(domain, irq_data->np, irq_data->args,
-				   irq_data->args_count, &hwirq, &type);
-	if (ret)
-		return ret;
+	if (acpi_disabled) {	/* DT case */
+		int ret;
+		unsigned int type = IRQ_TYPE_NONE;
+		struct of_phandle_args *irq_data = arg;
+
+		ret = gic_irq_domain_xlate(domain, irq_data->np, irq_data->args,
+					   irq_data->args_count, &hwirq, &type);
+		if (ret)
+			return ret;
+	} else {	/* ACPI case */
+		hwirq = (irq_hw_number_t)*(u32 *)arg;
+	}
 
 	for (i = 0; i < nr_irqs; i++)
 		gic_irq_domain_map(domain, virq + i, hwirq + i);
@@ -904,6 +910,7 @@ IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
 static struct redist_region *redist_regs __initdata;
 static u32 nr_redist_regions __initdata;
 static phys_addr_t dist_phy_base __initdata;
+static u32 gsi_base __initdata;
 
 static int __init
 gic_acpi_register_redist(u64 phys_base, u64 size)
@@ -961,6 +968,7 @@ gic_acpi_parse_madt_distributor(struct acpi_subtable_header *header,
 		return -EINVAL;
 
 	dist_phy_base = dist->base_address;
+	gsi_base = dist->global_irq_base;
 	return 0;
 }
 
@@ -1010,7 +1018,7 @@ gic_acpi_init(struct acpi_table_header *table)
 	if (err)
 		goto out_redist_unmap;
 
-	irq_set_default_host(gic_data.domain);
+	gsi_cfg_data_add(gic_data.domain, gsi_base, gsi_base + gic_data.irq_nr);
 	return 0;
 
 out_redist_unmap:
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 7/8] irqchip / GICv3: Add stacked irqdomain support for ACPI based init
@ 2015-07-10 10:45   ` Hanjun Guo
  0 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-10 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

Similar as stacked domain support for ACPI based GICv2 init, let
acpi_irq_domain point to the core domain of GICv3 and pass the
gsi as the arg to support stacked irqdomain.

Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 drivers/irqchip/irq-gic-v3.c | 24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 7b5bde3..91d2f9a 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -734,15 +734,21 @@ static int gic_irq_domain_xlate(struct irq_domain *d,
 static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 				unsigned int nr_irqs, void *arg)
 {
-	int i, ret;
+	int i;
 	irq_hw_number_t hwirq;
-	unsigned int type = IRQ_TYPE_NONE;
-	struct of_phandle_args *irq_data = arg;
 
-	ret = gic_irq_domain_xlate(domain, irq_data->np, irq_data->args,
-				   irq_data->args_count, &hwirq, &type);
-	if (ret)
-		return ret;
+	if (acpi_disabled) {	/* DT case */
+		int ret;
+		unsigned int type = IRQ_TYPE_NONE;
+		struct of_phandle_args *irq_data = arg;
+
+		ret = gic_irq_domain_xlate(domain, irq_data->np, irq_data->args,
+					   irq_data->args_count, &hwirq, &type);
+		if (ret)
+			return ret;
+	} else {	/* ACPI case */
+		hwirq = (irq_hw_number_t)*(u32 *)arg;
+	}
 
 	for (i = 0; i < nr_irqs; i++)
 		gic_irq_domain_map(domain, virq + i, hwirq + i);
@@ -904,6 +910,7 @@ IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
 static struct redist_region *redist_regs __initdata;
 static u32 nr_redist_regions __initdata;
 static phys_addr_t dist_phy_base __initdata;
+static u32 gsi_base __initdata;
 
 static int __init
 gic_acpi_register_redist(u64 phys_base, u64 size)
@@ -961,6 +968,7 @@ gic_acpi_parse_madt_distributor(struct acpi_subtable_header *header,
 		return -EINVAL;
 
 	dist_phy_base = dist->base_address;
+	gsi_base = dist->global_irq_base;
 	return 0;
 }
 
@@ -1010,7 +1018,7 @@ gic_acpi_init(struct acpi_table_header *table)
 	if (err)
 		goto out_redist_unmap;
 
-	irq_set_default_host(gic_data.domain);
+	gsi_cfg_data_add(gic_data.domain, gsi_base, gsi_base + gic_data.irq_nr);
 	return 0;
 
 out_redist_unmap:
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 8/8] irqchip / gicv3 / ACPI: Add GICR support via GICC structures
  2015-07-10 10:45 ` Hanjun Guo
@ 2015-07-10 10:45   ` Hanjun Guo
  -1 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-10 10:45 UTC (permalink / raw)
  To: Marc Zyngier, Jason Cooper, Will Deacon, Catalin Marinas,
	Rafael J. Wysocki
  Cc: Thomas Gleixner, Jiang Liu, Lorenzo Pieralisi, Arnd Bergmann,
	Tomasz Nowicki, Grant Likely, Mark Brown, Wei Huang,
	linux-arm-kernel, linux-acpi, linux-kernel, linaro-acpi,
	Hanjun Guo

On systems supporting GICv3 and above, the field of GICR Base
Address holds the 64-bit physical address of the associated
Redistributor if the GIC Redistributors are not in the always-on
power domain, so instead of init GICR regions via GIC redistributor
stricture, init it with GICR base address in GICC structures.

Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 drivers/irqchip/irq-gic-acpi.c       |  35 ++++++-
 drivers/irqchip/irq-gic-v3.c         | 180 ++++++++++++++++++++++++++++++++---
 include/linux/irqchip/arm-gic-acpi.h |   2 +
 3 files changed, 203 insertions(+), 14 deletions(-)

diff --git a/drivers/irqchip/irq-gic-acpi.c b/drivers/irqchip/irq-gic-acpi.c
index b87a581..792e5ea 100644
--- a/drivers/irqchip/irq-gic-acpi.c
+++ b/drivers/irqchip/irq-gic-acpi.c
@@ -21,6 +21,11 @@ static u8 gic_version __initdata = ACPI_MADT_GIC_VERSION_NONE;
 
 static phys_addr_t dist_phy_base __initdata;
 
+u8 __init acpi_gic_version(void)
+{
+	return gic_version;
+}
+
 static int __init
 acpi_gic_parse_distributor(struct acpi_subtable_header *header,
 			   const unsigned long end)
@@ -38,6 +43,27 @@ acpi_gic_parse_distributor(struct acpi_subtable_header *header,
 }
 
 static int __init
+gic_acpi_parse_madt_gicc(struct acpi_subtable_header *header,
+			 const unsigned long end)
+{
+	struct acpi_madt_generic_interrupt *gicc;
+
+	gicc = (struct acpi_madt_generic_interrupt *)header;
+
+	if (BAD_MADT_ENTRY(gicc, end))
+		return -EINVAL;
+
+	/*
+	 * If GICC is enabled but has no valid gicr base address, then it
+	 * means GICR is not presented via GICC
+	 */
+	if ((gicc->flags & ACPI_MADT_ENABLED) && !gicc->gicr_base_address)
+		return -ENODEV;
+
+	return 0;
+}
+
+static int __init
 match_gic_redist(struct acpi_subtable_header *header, const unsigned long end)
 {
 	return 0;
@@ -51,7 +77,14 @@ static bool __init acpi_gic_redist_is_present(void)
 	count  =  acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
 					match_gic_redist, 0);
 
-	/* that's true if we have at least one GIC redistributor entry */
+	/* has at least one GIC redistributor entry */
+	if (count > 0)
+		return true;
+
+	/* else try to find GICR base in GICC entries */
+	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
+				      gic_acpi_parse_madt_gicc, 0);
+
 	return count > 0;
 }
 
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 91d2f9a..fd617d6 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -389,9 +389,8 @@ static void __init gic_dist_init(void)
 		writeq_relaxed(affinity, base + GICD_IROUTER + i * 8);
 }
 
-static int gic_populate_rdist(void)
+static int gic_populate_rdist_with_regions(u64 mpidr)
 {
-	u64 mpidr = cpu_logical_map(smp_processor_id());
 	u64 typer;
 	u32 aff;
 	int i;
@@ -439,6 +438,34 @@ static int gic_populate_rdist(void)
 		} while (!(typer & GICR_TYPER_LAST));
 	}
 
+	return -ENODEV;
+}
+
+#ifdef CONFIG_ACPI
+/*
+ * Populate redist when GIC redistributor address is presented in ACPI
+ * MADT GICC entries
+ */
+static int gic_populate_rdist_with_gicr_base(u64 mpidr);
+#else
+static inline int gic_populate_rdist_with_gicr_base(u64 mpidr)
+{
+	return -ENODEV;
+}
+#endif
+
+static int gic_populate_rdist(void)
+{
+	u64 mpidr = cpu_logical_map(smp_processor_id());
+
+	if (!gic_data.nr_redist_regions) {
+		if (!gic_populate_rdist_with_gicr_base(mpidr))
+			return 0;
+	} else {
+		if (!gic_populate_rdist_with_regions(mpidr))
+			return 0;
+	}
+
 	/* We couldn't even deal with ourselves... */
 	WARN(true, "CPU%d: mpidr %llx has no re-distributor!\n",
 	     smp_processor_id(), (unsigned long long)mpidr);
@@ -907,6 +934,16 @@ IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
 #endif
 
 #ifdef CONFIG_ACPI
+
+struct acpi_gicc_redist {
+	struct list_head list;
+	u64 mpidr;
+	phys_addr_t phys_base;
+	void __iomem *redist_base;
+};
+
+static LIST_HEAD(redist_list);
+
 static struct redist_region *redist_regs __initdata;
 static u32 nr_redist_regions __initdata;
 static phys_addr_t dist_phy_base __initdata;
@@ -940,6 +977,17 @@ gic_acpi_register_redist(u64 phys_base, u64 size)
 	return 0;
 }
 
+static void __init
+gic_acpi_release_redist_regions(void)
+{
+	int i;
+
+	for (i = 0; i < nr_redist_regions; i++)
+		if (redist_regs[i].redist_base)
+			iounmap(redist_regs[i].redist_base);
+	kfree(redist_regs);
+}
+
 static int __init
 gic_acpi_parse_madt_redist(struct acpi_subtable_header *header,
 			const unsigned long end)
@@ -973,10 +1021,101 @@ gic_acpi_parse_madt_distributor(struct acpi_subtable_header *header,
 }
 
 static int __init
+gic_acpi_add_gicc_redist(phys_addr_t phys_base, u64 mpidr)
+{
+	struct acpi_gicc_redist *redist;
+
+	redist = kzalloc(sizeof(*redist), GFP_KERNEL);
+	if (!redist)
+		return -ENOMEM;
+
+	redist->mpidr = mpidr;
+	redist->phys_base = phys_base;
+
+	if (acpi_gic_version() == ACPI_MADT_GIC_VERSION_V3)
+		/* RD_base + SGI_base */
+		redist->redist_base = ioremap(phys_base, 2 * SZ_64K);
+	else
+		/*
+		 * RD_base + SGI_base + VLPI_base,
+		 * we don't map reserved page as it's buggy to access it
+		 */
+		redist->redist_base = ioremap(phys_base, 3 * SZ_64K);
+
+	if (!redist->redist_base) {
+		kfree(redist);
+		return -ENOMEM;
+	}
+
+	list_add(&redist->list, &redist_list);
+	return 0;
+}
+
+static void __init
+gic_acpi_release_gicc_redist(void)
+{
+	struct acpi_gicc_redist *redist, *t;
+
+	list_for_each_entry_safe(redist, t, &redist_list, list) {
+		list_del(&redist->list);
+		iounmap(redist->redist_base);
+		kfree(redist);
+	}
+}
+
+static int __init
+gic_acpi_parse_madt_gicc(struct acpi_subtable_header *header,
+			 const unsigned long end)
+{
+	struct acpi_madt_generic_interrupt *gicc;
+
+	gicc = (struct acpi_madt_generic_interrupt *)header;
+
+	if (BAD_MADT_ENTRY(gicc, end))
+		return -EINVAL;
+
+	if (!(gicc->flags & ACPI_MADT_ENABLED))
+		return -ENODEV;
+
+	return gic_acpi_add_gicc_redist(gicc->gicr_base_address,
+					gicc->arm_mpidr);
+}
+
+static int gic_populate_rdist_with_gicr_base(u64 mpidr)
+{
+	struct acpi_gicc_redist *redist;
+	void __iomem *ptr;
+	u32 reg;
+
+	list_for_each_entry(redist, &redist_list, list) {
+		if (redist->mpidr != mpidr)
+			continue;
+
+		ptr = redist->redist_base;
+		reg = readl_relaxed(ptr + GICR_PIDR2) & GIC_PIDR2_ARCH_MASK;
+		if (reg != GIC_PIDR2_ARCH_GICv3 && reg != GIC_PIDR2_ARCH_GICv4) {
+			pr_warn("No redistributor present @%p\n", ptr);
+			return -ENODEV;
+		}
+
+		gic_data_rdist_rd_base() = ptr;
+		gic_data_rdist()->phys_base = redist->phys_base;
+		pr_info("CPU%d: found redistributor %llx phys base:%pa\n",
+			smp_processor_id(),
+			(unsigned long long)mpidr,
+			&gic_data_rdist()->phys_base);
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
+static int __init
 gic_acpi_init(struct acpi_table_header *table)
 {
-	int count, i, err = 0;
+	int count, err = 0;
 	void __iomem *dist_base;
+	bool no_gicr_entries = false;
 
 	/* Get distributor base address */
 	count = acpi_parse_entries(ACPI_SIG_MADT,
@@ -1003,29 +1142,44 @@ gic_acpi_init(struct acpi_table_header *table)
 		goto out_dist_unmap;
 	}
 
-	/* Collect redistributor base addresses */
+	/* Collect redistributor base addresses in GICR entries */
 	count = acpi_parse_entries(ACPI_SIG_MADT,
 			sizeof(struct acpi_table_madt),
 			gic_acpi_parse_madt_redist, table,
 			ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR, 0);
 	if (count <= 0) {
-		pr_info("No valid GICR entries exist\n");
-		err = -EINVAL;
-		goto out_redist_unmap;
+		pr_info("No valid GICR entries exist, try GICC entries\n");
+		gic_acpi_release_redist_regions();
+		no_gicr_entries = true;
+	} else {
+		goto init_base;
 	}
 
+	/* Collect redistributor base addresses in GICC entries */
+	count = acpi_parse_entries(ACPI_SIG_MADT,
+			sizeof(struct acpi_table_madt),
+			gic_acpi_parse_madt_gicc, table,
+			ACPI_MADT_TYPE_GENERIC_INTERRUPT, 0);
+	if (count <= 0) {
+		pr_info("No valid GICC entries exist\n");
+		goto out_release_redist;
+	}
+
+init_base:
 	err = gic_init_bases(dist_base, redist_regs, nr_redist_regions, 0, NULL);
 	if (err)
-		goto out_redist_unmap;
+		goto out_release_redist;
 
 	gsi_cfg_data_add(gic_data.domain, gsi_base, gsi_base + gic_data.irq_nr);
 	return 0;
 
-out_redist_unmap:
-	for (i = 0; i < nr_redist_regions; i++)
-		if (redist_regs[i].redist_base)
-			iounmap(redist_regs[i].redist_base);
-	kfree(redist_regs);
+out_release_redist:
+	if (no_gicr_entries) {
+		if (!list_empty(&redist_list))
+			gic_acpi_release_gicc_redist();
+	} else {
+		gic_acpi_release_redist_regions();
+	}
 out_dist_unmap:
 	iounmap(dist_base);
 	return err;
diff --git a/include/linux/irqchip/arm-gic-acpi.h b/include/linux/irqchip/arm-gic-acpi.h
index 56cd82c..0d43f515 100644
--- a/include/linux/irqchip/arm-gic-acpi.h
+++ b/include/linux/irqchip/arm-gic-acpi.h
@@ -21,5 +21,7 @@
 #define ACPI_GIC_CPU_IF_MEM_SIZE	(SZ_8K)
 #define ACPI_GICV3_DIST_MEM_SIZE	(SZ_64K)
 
+u8 acpi_gic_version(void);
+
 #endif /* CONFIG_ACPI */
 #endif /* ARM_GIC_ACPI_H_ */
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 8/8] irqchip / gicv3 / ACPI: Add GICR support via GICC structures
@ 2015-07-10 10:45   ` Hanjun Guo
  0 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-10 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

On systems supporting GICv3 and above, the field of GICR Base
Address holds the 64-bit physical address of the associated
Redistributor if the GIC Redistributors are not in the always-on
power domain, so instead of init GICR regions via GIC redistributor
stricture, init it with GICR base address in GICC structures.

Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 drivers/irqchip/irq-gic-acpi.c       |  35 ++++++-
 drivers/irqchip/irq-gic-v3.c         | 180 ++++++++++++++++++++++++++++++++---
 include/linux/irqchip/arm-gic-acpi.h |   2 +
 3 files changed, 203 insertions(+), 14 deletions(-)

diff --git a/drivers/irqchip/irq-gic-acpi.c b/drivers/irqchip/irq-gic-acpi.c
index b87a581..792e5ea 100644
--- a/drivers/irqchip/irq-gic-acpi.c
+++ b/drivers/irqchip/irq-gic-acpi.c
@@ -21,6 +21,11 @@ static u8 gic_version __initdata = ACPI_MADT_GIC_VERSION_NONE;
 
 static phys_addr_t dist_phy_base __initdata;
 
+u8 __init acpi_gic_version(void)
+{
+	return gic_version;
+}
+
 static int __init
 acpi_gic_parse_distributor(struct acpi_subtable_header *header,
 			   const unsigned long end)
@@ -38,6 +43,27 @@ acpi_gic_parse_distributor(struct acpi_subtable_header *header,
 }
 
 static int __init
+gic_acpi_parse_madt_gicc(struct acpi_subtable_header *header,
+			 const unsigned long end)
+{
+	struct acpi_madt_generic_interrupt *gicc;
+
+	gicc = (struct acpi_madt_generic_interrupt *)header;
+
+	if (BAD_MADT_ENTRY(gicc, end))
+		return -EINVAL;
+
+	/*
+	 * If GICC is enabled but has no valid gicr base address, then it
+	 * means GICR is not presented via GICC
+	 */
+	if ((gicc->flags & ACPI_MADT_ENABLED) && !gicc->gicr_base_address)
+		return -ENODEV;
+
+	return 0;
+}
+
+static int __init
 match_gic_redist(struct acpi_subtable_header *header, const unsigned long end)
 {
 	return 0;
@@ -51,7 +77,14 @@ static bool __init acpi_gic_redist_is_present(void)
 	count  =  acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
 					match_gic_redist, 0);
 
-	/* that's true if we have at least one GIC redistributor entry */
+	/* has at least one GIC redistributor entry */
+	if (count > 0)
+		return true;
+
+	/* else try to find GICR base in GICC entries */
+	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
+				      gic_acpi_parse_madt_gicc, 0);
+
 	return count > 0;
 }
 
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 91d2f9a..fd617d6 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -389,9 +389,8 @@ static void __init gic_dist_init(void)
 		writeq_relaxed(affinity, base + GICD_IROUTER + i * 8);
 }
 
-static int gic_populate_rdist(void)
+static int gic_populate_rdist_with_regions(u64 mpidr)
 {
-	u64 mpidr = cpu_logical_map(smp_processor_id());
 	u64 typer;
 	u32 aff;
 	int i;
@@ -439,6 +438,34 @@ static int gic_populate_rdist(void)
 		} while (!(typer & GICR_TYPER_LAST));
 	}
 
+	return -ENODEV;
+}
+
+#ifdef CONFIG_ACPI
+/*
+ * Populate redist when GIC redistributor address is presented in ACPI
+ * MADT GICC entries
+ */
+static int gic_populate_rdist_with_gicr_base(u64 mpidr);
+#else
+static inline int gic_populate_rdist_with_gicr_base(u64 mpidr)
+{
+	return -ENODEV;
+}
+#endif
+
+static int gic_populate_rdist(void)
+{
+	u64 mpidr = cpu_logical_map(smp_processor_id());
+
+	if (!gic_data.nr_redist_regions) {
+		if (!gic_populate_rdist_with_gicr_base(mpidr))
+			return 0;
+	} else {
+		if (!gic_populate_rdist_with_regions(mpidr))
+			return 0;
+	}
+
 	/* We couldn't even deal with ourselves... */
 	WARN(true, "CPU%d: mpidr %llx has no re-distributor!\n",
 	     smp_processor_id(), (unsigned long long)mpidr);
@@ -907,6 +934,16 @@ IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
 #endif
 
 #ifdef CONFIG_ACPI
+
+struct acpi_gicc_redist {
+	struct list_head list;
+	u64 mpidr;
+	phys_addr_t phys_base;
+	void __iomem *redist_base;
+};
+
+static LIST_HEAD(redist_list);
+
 static struct redist_region *redist_regs __initdata;
 static u32 nr_redist_regions __initdata;
 static phys_addr_t dist_phy_base __initdata;
@@ -940,6 +977,17 @@ gic_acpi_register_redist(u64 phys_base, u64 size)
 	return 0;
 }
 
+static void __init
+gic_acpi_release_redist_regions(void)
+{
+	int i;
+
+	for (i = 0; i < nr_redist_regions; i++)
+		if (redist_regs[i].redist_base)
+			iounmap(redist_regs[i].redist_base);
+	kfree(redist_regs);
+}
+
 static int __init
 gic_acpi_parse_madt_redist(struct acpi_subtable_header *header,
 			const unsigned long end)
@@ -973,10 +1021,101 @@ gic_acpi_parse_madt_distributor(struct acpi_subtable_header *header,
 }
 
 static int __init
+gic_acpi_add_gicc_redist(phys_addr_t phys_base, u64 mpidr)
+{
+	struct acpi_gicc_redist *redist;
+
+	redist = kzalloc(sizeof(*redist), GFP_KERNEL);
+	if (!redist)
+		return -ENOMEM;
+
+	redist->mpidr = mpidr;
+	redist->phys_base = phys_base;
+
+	if (acpi_gic_version() == ACPI_MADT_GIC_VERSION_V3)
+		/* RD_base + SGI_base */
+		redist->redist_base = ioremap(phys_base, 2 * SZ_64K);
+	else
+		/*
+		 * RD_base + SGI_base + VLPI_base,
+		 * we don't map reserved page as it's buggy to access it
+		 */
+		redist->redist_base = ioremap(phys_base, 3 * SZ_64K);
+
+	if (!redist->redist_base) {
+		kfree(redist);
+		return -ENOMEM;
+	}
+
+	list_add(&redist->list, &redist_list);
+	return 0;
+}
+
+static void __init
+gic_acpi_release_gicc_redist(void)
+{
+	struct acpi_gicc_redist *redist, *t;
+
+	list_for_each_entry_safe(redist, t, &redist_list, list) {
+		list_del(&redist->list);
+		iounmap(redist->redist_base);
+		kfree(redist);
+	}
+}
+
+static int __init
+gic_acpi_parse_madt_gicc(struct acpi_subtable_header *header,
+			 const unsigned long end)
+{
+	struct acpi_madt_generic_interrupt *gicc;
+
+	gicc = (struct acpi_madt_generic_interrupt *)header;
+
+	if (BAD_MADT_ENTRY(gicc, end))
+		return -EINVAL;
+
+	if (!(gicc->flags & ACPI_MADT_ENABLED))
+		return -ENODEV;
+
+	return gic_acpi_add_gicc_redist(gicc->gicr_base_address,
+					gicc->arm_mpidr);
+}
+
+static int gic_populate_rdist_with_gicr_base(u64 mpidr)
+{
+	struct acpi_gicc_redist *redist;
+	void __iomem *ptr;
+	u32 reg;
+
+	list_for_each_entry(redist, &redist_list, list) {
+		if (redist->mpidr != mpidr)
+			continue;
+
+		ptr = redist->redist_base;
+		reg = readl_relaxed(ptr + GICR_PIDR2) & GIC_PIDR2_ARCH_MASK;
+		if (reg != GIC_PIDR2_ARCH_GICv3 && reg != GIC_PIDR2_ARCH_GICv4) {
+			pr_warn("No redistributor present @%p\n", ptr);
+			return -ENODEV;
+		}
+
+		gic_data_rdist_rd_base() = ptr;
+		gic_data_rdist()->phys_base = redist->phys_base;
+		pr_info("CPU%d: found redistributor %llx phys base:%pa\n",
+			smp_processor_id(),
+			(unsigned long long)mpidr,
+			&gic_data_rdist()->phys_base);
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
+static int __init
 gic_acpi_init(struct acpi_table_header *table)
 {
-	int count, i, err = 0;
+	int count, err = 0;
 	void __iomem *dist_base;
+	bool no_gicr_entries = false;
 
 	/* Get distributor base address */
 	count = acpi_parse_entries(ACPI_SIG_MADT,
@@ -1003,29 +1142,44 @@ gic_acpi_init(struct acpi_table_header *table)
 		goto out_dist_unmap;
 	}
 
-	/* Collect redistributor base addresses */
+	/* Collect redistributor base addresses in GICR entries */
 	count = acpi_parse_entries(ACPI_SIG_MADT,
 			sizeof(struct acpi_table_madt),
 			gic_acpi_parse_madt_redist, table,
 			ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR, 0);
 	if (count <= 0) {
-		pr_info("No valid GICR entries exist\n");
-		err = -EINVAL;
-		goto out_redist_unmap;
+		pr_info("No valid GICR entries exist, try GICC entries\n");
+		gic_acpi_release_redist_regions();
+		no_gicr_entries = true;
+	} else {
+		goto init_base;
 	}
 
+	/* Collect redistributor base addresses in GICC entries */
+	count = acpi_parse_entries(ACPI_SIG_MADT,
+			sizeof(struct acpi_table_madt),
+			gic_acpi_parse_madt_gicc, table,
+			ACPI_MADT_TYPE_GENERIC_INTERRUPT, 0);
+	if (count <= 0) {
+		pr_info("No valid GICC entries exist\n");
+		goto out_release_redist;
+	}
+
+init_base:
 	err = gic_init_bases(dist_base, redist_regs, nr_redist_regions, 0, NULL);
 	if (err)
-		goto out_redist_unmap;
+		goto out_release_redist;
 
 	gsi_cfg_data_add(gic_data.domain, gsi_base, gsi_base + gic_data.irq_nr);
 	return 0;
 
-out_redist_unmap:
-	for (i = 0; i < nr_redist_regions; i++)
-		if (redist_regs[i].redist_base)
-			iounmap(redist_regs[i].redist_base);
-	kfree(redist_regs);
+out_release_redist:
+	if (no_gicr_entries) {
+		if (!list_empty(&redist_list))
+			gic_acpi_release_gicc_redist();
+	} else {
+		gic_acpi_release_redist_regions();
+	}
 out_dist_unmap:
 	iounmap(dist_base);
 	return err;
diff --git a/include/linux/irqchip/arm-gic-acpi.h b/include/linux/irqchip/arm-gic-acpi.h
index 56cd82c..0d43f515 100644
--- a/include/linux/irqchip/arm-gic-acpi.h
+++ b/include/linux/irqchip/arm-gic-acpi.h
@@ -21,5 +21,7 @@
 #define ACPI_GIC_CPU_IF_MEM_SIZE	(SZ_8K)
 #define ACPI_GICV3_DIST_MEM_SIZE	(SZ_64K)
 
+u8 acpi_gic_version(void);
+
 #endif /* CONFIG_ACPI */
 #endif /* ARM_GIC_ACPI_H_ */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* Re: [Linaro-acpi] [PATCH v3 0/8] Add self-probe infrastructure and stacked irqdomain support for ACPI based GICv2/3 init
  2015-07-10 10:45 ` Hanjun Guo
  (?)
@ 2015-07-17 23:09   ` Timur Tabi
  -1 siblings, 0 replies; 44+ messages in thread
From: Timur Tabi @ 2015-07-17 23:09 UTC (permalink / raw)
  To: Hanjun Guo
  Cc: Marc Zyngier, Jason Cooper, Will Deacon, Catalin Marinas,
	Rafael J. Wysocki, Wei Huang, Arnd Bergmann, linaro-acpi, lkml,
	linux-acpi, Mark Brown, Thomas Gleixner, Jiang Liu,
	linux-arm-kernel

On Fri, Jul 10, 2015 at 5:45 AM, Hanjun Guo <hanjun.guo@linaro.org> wrote:
> This patch set introduce self-probe infrastructure to init IRQ
> controllers and stacked irqdomain support for ACPI based GICv2/3
> init.
>
> This patch set add its support for GIC verion which is introduced
> in ACPI 6.0, based on that, we introduce the self-probe infrastructure,
> the self-probe infrastructure for ACPI GIC init is similar as
> IRQCHIP_DECLARE() and based on the GIC version support in ACPI
> MADT table. we match the GIC version and GIC driver and load
> it.
>
> After the self-probe infrastructure is ready, I cleanuped the GICv2
> code to use the framework.
>
> Patch 4 implement the stacked irqdomain support for GICv2 based on
> the model of mapping interrupt and device in ACPI.
>
> Patch 5~8 are ACPI based GICv3 init.

All eight patches:

Tested-by: Timur Tabi <timur@codeaurora.org>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Linaro-acpi] [PATCH v3 0/8] Add self-probe infrastructure and stacked irqdomain support for ACPI based GICv2/3 init
@ 2015-07-17 23:09   ` Timur Tabi
  0 siblings, 0 replies; 44+ messages in thread
From: Timur Tabi @ 2015-07-17 23:09 UTC (permalink / raw)
  To: Hanjun Guo
  Cc: Marc Zyngier, Jason Cooper, Will Deacon, Catalin Marinas,
	Rafael J. Wysocki, Wei Huang, Arnd Bergmann, linaro-acpi, lkml,
	linux-acpi, Mark Brown, Thomas Gleixner, Jiang Liu,
	linux-arm-kernel

On Fri, Jul 10, 2015 at 5:45 AM, Hanjun Guo <hanjun.guo@linaro.org> wrote:
> This patch set introduce self-probe infrastructure to init IRQ
> controllers and stacked irqdomain support for ACPI based GICv2/3
> init.
>
> This patch set add its support for GIC verion which is introduced
> in ACPI 6.0, based on that, we introduce the self-probe infrastructure,
> the self-probe infrastructure for ACPI GIC init is similar as
> IRQCHIP_DECLARE() and based on the GIC version support in ACPI
> MADT table. we match the GIC version and GIC driver and load
> it.
>
> After the self-probe infrastructure is ready, I cleanuped the GICv2
> code to use the framework.
>
> Patch 4 implement the stacked irqdomain support for GICv2 based on
> the model of mapping interrupt and device in ACPI.
>
> Patch 5~8 are ACPI based GICv3 init.

All eight patches:

Tested-by: Timur Tabi <timur@codeaurora.org>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [Linaro-acpi] [PATCH v3 0/8] Add self-probe infrastructure and stacked irqdomain support for ACPI based GICv2/3 init
@ 2015-07-17 23:09   ` Timur Tabi
  0 siblings, 0 replies; 44+ messages in thread
From: Timur Tabi @ 2015-07-17 23:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jul 10, 2015 at 5:45 AM, Hanjun Guo <hanjun.guo@linaro.org> wrote:
> This patch set introduce self-probe infrastructure to init IRQ
> controllers and stacked irqdomain support for ACPI based GICv2/3
> init.
>
> This patch set add its support for GIC verion which is introduced
> in ACPI 6.0, based on that, we introduce the self-probe infrastructure,
> the self-probe infrastructure for ACPI GIC init is similar as
> IRQCHIP_DECLARE() and based on the GIC version support in ACPI
> MADT table. we match the GIC version and GIC driver and load
> it.
>
> After the self-probe infrastructure is ready, I cleanuped the GICv2
> code to use the framework.
>
> Patch 4 implement the stacked irqdomain support for GICv2 based on
> the model of mapping interrupt and device in ACPI.
>
> Patch 5~8 are ACPI based GICv3 init.

All eight patches:

Tested-by: Timur Tabi <timur@codeaurora.org>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v3 2/8] ACPI / irqchip: Add self-probe infrastructure to initialize IRQ controller
  2015-07-10 10:45   ` Hanjun Guo
  (?)
@ 2015-07-17 23:15     ` Timur Tabi
  -1 siblings, 0 replies; 44+ messages in thread
From: Timur Tabi @ 2015-07-17 23:15 UTC (permalink / raw)
  To: Hanjun Guo
  Cc: Marc Zyngier, Jason Cooper, Will Deacon, Catalin Marinas,
	Rafael J. Wysocki, Wei Huang, Lorenzo Pieralisi, Arnd Bergmann,
	linaro-acpi, lkml, Tomasz Nowicki, linux-acpi, Mark Brown,
	Grant Likely, Thomas Gleixner, Jiang Liu, linux-arm-kernel

On Fri, Jul 10, 2015 at 5:45 AM, Hanjun Guo <hanjun.guo@linaro.org> wrote:

> +void __init acpi_irqchip_init(void)
> +{
> +       struct acpi_table_id *id;
> +
> +       if (acpi_disabled)
> +               return;
> +
> +       if (acpi_gic_version_init())
> +               return;
> +
> +       /* scan the irqchip table to match the GIC version and its driver */
> +       for (id = __irqchip_acpi_table; id->id[0]; id++) {
> +               if (gic_version == (u8)id->driver_data)
> +                       acpi_table_parse(id->id,
> +                                        (acpi_tbl_table_handler)id->handler);
> +       }

Should we display an error message if we don't find a matching table?
That can happen if the ACPI tables shows a GIC version number that is
not listed in __irqchip_acpi_table[]?

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v3 2/8] ACPI / irqchip: Add self-probe infrastructure to initialize IRQ controller
@ 2015-07-17 23:15     ` Timur Tabi
  0 siblings, 0 replies; 44+ messages in thread
From: Timur Tabi @ 2015-07-17 23:15 UTC (permalink / raw)
  To: Hanjun Guo
  Cc: Marc Zyngier, Jason Cooper, Will Deacon, Catalin Marinas,
	Rafael J. Wysocki, Wei Huang, Lorenzo Pieralisi, Arnd Bergmann,
	linaro-acpi, lkml, Tomasz Nowicki, linux-acpi, Mark Brown,
	Grant Likely, Thomas Gleixner, Jiang Liu, linux-arm-kernel

On Fri, Jul 10, 2015 at 5:45 AM, Hanjun Guo <hanjun.guo@linaro.org> wrote:

> +void __init acpi_irqchip_init(void)
> +{
> +       struct acpi_table_id *id;
> +
> +       if (acpi_disabled)
> +               return;
> +
> +       if (acpi_gic_version_init())
> +               return;
> +
> +       /* scan the irqchip table to match the GIC version and its driver */
> +       for (id = __irqchip_acpi_table; id->id[0]; id++) {
> +               if (gic_version == (u8)id->driver_data)
> +                       acpi_table_parse(id->id,
> +                                        (acpi_tbl_table_handler)id->handler);
> +       }

Should we display an error message if we don't find a matching table?
That can happen if the ACPI tables shows a GIC version number that is
not listed in __irqchip_acpi_table[]?

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH v3 2/8] ACPI / irqchip: Add self-probe infrastructure to initialize IRQ controller
@ 2015-07-17 23:15     ` Timur Tabi
  0 siblings, 0 replies; 44+ messages in thread
From: Timur Tabi @ 2015-07-17 23:15 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jul 10, 2015 at 5:45 AM, Hanjun Guo <hanjun.guo@linaro.org> wrote:

> +void __init acpi_irqchip_init(void)
> +{
> +       struct acpi_table_id *id;
> +
> +       if (acpi_disabled)
> +               return;
> +
> +       if (acpi_gic_version_init())
> +               return;
> +
> +       /* scan the irqchip table to match the GIC version and its driver */
> +       for (id = __irqchip_acpi_table; id->id[0]; id++) {
> +               if (gic_version == (u8)id->driver_data)
> +                       acpi_table_parse(id->id,
> +                                        (acpi_tbl_table_handler)id->handler);
> +       }

Should we display an error message if we don't find a matching table?
That can happen if the ACPI tables shows a GIC version number that is
not listed in __irqchip_acpi_table[]?

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Linaro-acpi] [PATCH v3 0/8] Add self-probe infrastructure and stacked irqdomain support for ACPI based GICv2/3 init
  2015-07-17 23:09   ` Timur Tabi
  (?)
@ 2015-07-20  9:06     ` Hanjun Guo
  -1 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-20  9:06 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Marc Zyngier, Jason Cooper, Will Deacon, Catalin Marinas,
	Rafael J. Wysocki, Wei Huang, Arnd Bergmann, linaro-acpi, lkml,
	linux-acpi, Mark Brown, Thomas Gleixner, Jiang Liu,
	linux-arm-kernel

Hi Timur,

On 07/18/2015 07:09 AM, Timur Tabi wrote:
> On Fri, Jul 10, 2015 at 5:45 AM, Hanjun Guo <hanjun.guo@linaro.org> wrote:
>> This patch set introduce self-probe infrastructure to init IRQ
>> controllers and stacked irqdomain support for ACPI based GICv2/3
>> init.
>>
>> This patch set add its support for GIC verion which is introduced
>> in ACPI 6.0, based on that, we introduce the self-probe infrastructure,
>> the self-probe infrastructure for ACPI GIC init is similar as
>> IRQCHIP_DECLARE() and based on the GIC version support in ACPI
>> MADT table. we match the GIC version and GIC driver and load
>> it.
>>
>> After the self-probe infrastructure is ready, I cleanuped the GICv2
>> code to use the framework.
>>
>> Patch 4 implement the stacked irqdomain support for GICv2 based on
>> the model of mapping interrupt and device in ACPI.
>>
>> Patch 5~8 are ACPI based GICv3 init.
>
> All eight patches:
>
> Tested-by: Timur Tabi <timur@codeaurora.org>

Wonderful, Thanks a lot!

I got a question, do you test GICv3 in this patch set too?
if yes, that will be really great!

Just let you know, I'm still working on this patch set to try
to address Marc's comments (unify DT and ACPI to match the domain),
I'm not sure if any obstacles ahead, I will let you know the progress.

Regards
Hanjun

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Linaro-acpi] [PATCH v3 0/8] Add self-probe infrastructure and stacked irqdomain support for ACPI based GICv2/3 init
@ 2015-07-20  9:06     ` Hanjun Guo
  0 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-20  9:06 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Marc Zyngier, Jason Cooper, Will Deacon, Catalin Marinas,
	Rafael J. Wysocki, Wei Huang, Arnd Bergmann, linaro-acpi, lkml,
	linux-acpi, Mark Brown, Thomas Gleixner, Jiang Liu,
	linux-arm-kernel

Hi Timur,

On 07/18/2015 07:09 AM, Timur Tabi wrote:
> On Fri, Jul 10, 2015 at 5:45 AM, Hanjun Guo <hanjun.guo@linaro.org> wrote:
>> This patch set introduce self-probe infrastructure to init IRQ
>> controllers and stacked irqdomain support for ACPI based GICv2/3
>> init.
>>
>> This patch set add its support for GIC verion which is introduced
>> in ACPI 6.0, based on that, we introduce the self-probe infrastructure,
>> the self-probe infrastructure for ACPI GIC init is similar as
>> IRQCHIP_DECLARE() and based on the GIC version support in ACPI
>> MADT table. we match the GIC version and GIC driver and load
>> it.
>>
>> After the self-probe infrastructure is ready, I cleanuped the GICv2
>> code to use the framework.
>>
>> Patch 4 implement the stacked irqdomain support for GICv2 based on
>> the model of mapping interrupt and device in ACPI.
>>
>> Patch 5~8 are ACPI based GICv3 init.
>
> All eight patches:
>
> Tested-by: Timur Tabi <timur@codeaurora.org>

Wonderful, Thanks a lot!

I got a question, do you test GICv3 in this patch set too?
if yes, that will be really great!

Just let you know, I'm still working on this patch set to try
to address Marc's comments (unify DT and ACPI to match the domain),
I'm not sure if any obstacles ahead, I will let you know the progress.

Regards
Hanjun

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [Linaro-acpi] [PATCH v3 0/8] Add self-probe infrastructure and stacked irqdomain support for ACPI based GICv2/3 init
@ 2015-07-20  9:06     ` Hanjun Guo
  0 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-20  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Timur,

On 07/18/2015 07:09 AM, Timur Tabi wrote:
> On Fri, Jul 10, 2015 at 5:45 AM, Hanjun Guo <hanjun.guo@linaro.org> wrote:
>> This patch set introduce self-probe infrastructure to init IRQ
>> controllers and stacked irqdomain support for ACPI based GICv2/3
>> init.
>>
>> This patch set add its support for GIC verion which is introduced
>> in ACPI 6.0, based on that, we introduce the self-probe infrastructure,
>> the self-probe infrastructure for ACPI GIC init is similar as
>> IRQCHIP_DECLARE() and based on the GIC version support in ACPI
>> MADT table. we match the GIC version and GIC driver and load
>> it.
>>
>> After the self-probe infrastructure is ready, I cleanuped the GICv2
>> code to use the framework.
>>
>> Patch 4 implement the stacked irqdomain support for GICv2 based on
>> the model of mapping interrupt and device in ACPI.
>>
>> Patch 5~8 are ACPI based GICv3 init.
>
> All eight patches:
>
> Tested-by: Timur Tabi <timur@codeaurora.org>

Wonderful, Thanks a lot!

I got a question, do you test GICv3 in this patch set too?
if yes, that will be really great!

Just let you know, I'm still working on this patch set to try
to address Marc's comments (unify DT and ACPI to match the domain),
I'm not sure if any obstacles ahead, I will let you know the progress.

Regards
Hanjun

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v3 2/8] ACPI / irqchip: Add self-probe infrastructure to initialize IRQ controller
  2015-07-17 23:15     ` Timur Tabi
  (?)
@ 2015-07-20  9:32       ` Hanjun Guo
  -1 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-20  9:32 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Marc Zyngier, Jason Cooper, Will Deacon, Catalin Marinas,
	Rafael J. Wysocki, Wei Huang, Lorenzo Pieralisi, Arnd Bergmann,
	linaro-acpi, lkml, Tomasz Nowicki, linux-acpi, Mark Brown,
	Grant Likely, Thomas Gleixner, Jiang Liu, linux-arm-kernel

On 07/18/2015 07:15 AM, Timur Tabi wrote:
> On Fri, Jul 10, 2015 at 5:45 AM, Hanjun Guo <hanjun.guo@linaro.org> wrote:
>
>> +void __init acpi_irqchip_init(void)
>> +{
>> +       struct acpi_table_id *id;
>> +
>> +       if (acpi_disabled)
>> +               return;
>> +
>> +       if (acpi_gic_version_init())
>> +               return;
>> +
>> +       /* scan the irqchip table to match the GIC version and its driver */
>> +       for (id = __irqchip_acpi_table; id->id[0]; id++) {
>> +               if (gic_version == (u8)id->driver_data)
>> +                       acpi_table_parse(id->id,
>> +                                        (acpi_tbl_table_handler)id->handler);
>> +       }
>
> Should we display an error message if we don't find a matching table?
> That can happen if the ACPI tables shows a GIC version number that is
> not listed in __irqchip_acpi_table[]?

Hmm, did you get the error message like: "Invalid GIC version 5 in
MADT"? or just use ACPI_MADT_GIC_VERSION_V1 as the gic_version? if
the later one, it will show everything is fine, but failed to probe
the GIC.

I agree with you that we need to print some error message here,
I will update my patch.

Thanks
Hanjun

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v3 2/8] ACPI / irqchip: Add self-probe infrastructure to initialize IRQ controller
@ 2015-07-20  9:32       ` Hanjun Guo
  0 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-20  9:32 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Marc Zyngier, Jason Cooper, Will Deacon, Catalin Marinas,
	Rafael J. Wysocki, Wei Huang, Lorenzo Pieralisi, Arnd Bergmann,
	linaro-acpi, lkml, Tomasz Nowicki, linux-acpi, Mark Brown,
	Grant Likely, Thomas Gleixner, Jiang Liu, linux-arm-kernel

On 07/18/2015 07:15 AM, Timur Tabi wrote:
> On Fri, Jul 10, 2015 at 5:45 AM, Hanjun Guo <hanjun.guo@linaro.org> wrote:
>
>> +void __init acpi_irqchip_init(void)
>> +{
>> +       struct acpi_table_id *id;
>> +
>> +       if (acpi_disabled)
>> +               return;
>> +
>> +       if (acpi_gic_version_init())
>> +               return;
>> +
>> +       /* scan the irqchip table to match the GIC version and its driver */
>> +       for (id = __irqchip_acpi_table; id->id[0]; id++) {
>> +               if (gic_version == (u8)id->driver_data)
>> +                       acpi_table_parse(id->id,
>> +                                        (acpi_tbl_table_handler)id->handler);
>> +       }
>
> Should we display an error message if we don't find a matching table?
> That can happen if the ACPI tables shows a GIC version number that is
> not listed in __irqchip_acpi_table[]?

Hmm, did you get the error message like: "Invalid GIC version 5 in
MADT"? or just use ACPI_MADT_GIC_VERSION_V1 as the gic_version? if
the later one, it will show everything is fine, but failed to probe
the GIC.

I agree with you that we need to print some error message here,
I will update my patch.

Thanks
Hanjun

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH v3 2/8] ACPI / irqchip: Add self-probe infrastructure to initialize IRQ controller
@ 2015-07-20  9:32       ` Hanjun Guo
  0 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-20  9:32 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/18/2015 07:15 AM, Timur Tabi wrote:
> On Fri, Jul 10, 2015 at 5:45 AM, Hanjun Guo <hanjun.guo@linaro.org> wrote:
>
>> +void __init acpi_irqchip_init(void)
>> +{
>> +       struct acpi_table_id *id;
>> +
>> +       if (acpi_disabled)
>> +               return;
>> +
>> +       if (acpi_gic_version_init())
>> +               return;
>> +
>> +       /* scan the irqchip table to match the GIC version and its driver */
>> +       for (id = __irqchip_acpi_table; id->id[0]; id++) {
>> +               if (gic_version == (u8)id->driver_data)
>> +                       acpi_table_parse(id->id,
>> +                                        (acpi_tbl_table_handler)id->handler);
>> +       }
>
> Should we display an error message if we don't find a matching table?
> That can happen if the ACPI tables shows a GIC version number that is
> not listed in __irqchip_acpi_table[]?

Hmm, did you get the error message like: "Invalid GIC version 5 in
MADT"? or just use ACPI_MADT_GIC_VERSION_V1 as the gic_version? if
the later one, it will show everything is fine, but failed to probe
the GIC.

I agree with you that we need to print some error message here,
I will update my patch.

Thanks
Hanjun

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Linaro-acpi] [PATCH v3 0/8] Add self-probe infrastructure and stacked irqdomain support for ACPI based GICv2/3 init
  2015-07-20  9:06     ` Hanjun Guo
  (?)
@ 2015-07-20 12:06       ` Timur Tabi
  -1 siblings, 0 replies; 44+ messages in thread
From: Timur Tabi @ 2015-07-20 12:06 UTC (permalink / raw)
  To: Hanjun Guo
  Cc: Marc Zyngier, Jason Cooper, Will Deacon, Catalin Marinas,
	Rafael J. Wysocki, Wei Huang, Arnd Bergmann, linaro-acpi, lkml,
	linux-acpi, Mark Brown, Thomas Gleixner, Jiang Liu,
	linux-arm-kernel

Hanjun Guo wrote:

> I got a question, do you test GICv3 in this patch set too?
> if yes, that will be really great!

Yes, I specifically tested GICv3 on an ACPI-only system.

> Just let you know, I'm still working on this patch set to try
> to address Marc's comments (unify DT and ACPI to match the domain),
> I'm not sure if any obstacles ahead, I will let you know the progress.

Just CC me on all patches, and I will test each version.

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Linaro-acpi] [PATCH v3 0/8] Add self-probe infrastructure and stacked irqdomain support for ACPI based GICv2/3 init
@ 2015-07-20 12:06       ` Timur Tabi
  0 siblings, 0 replies; 44+ messages in thread
From: Timur Tabi @ 2015-07-20 12:06 UTC (permalink / raw)
  To: Hanjun Guo
  Cc: Marc Zyngier, Jason Cooper, Will Deacon, Catalin Marinas,
	Rafael J. Wysocki, Wei Huang, Arnd Bergmann, linaro-acpi, lkml,
	linux-acpi, Mark Brown, Thomas Gleixner, Jiang Liu,
	linux-arm-kernel

Hanjun Guo wrote:

> I got a question, do you test GICv3 in this patch set too?
> if yes, that will be really great!

Yes, I specifically tested GICv3 on an ACPI-only system.

> Just let you know, I'm still working on this patch set to try
> to address Marc's comments (unify DT and ACPI to match the domain),
> I'm not sure if any obstacles ahead, I will let you know the progress.

Just CC me on all patches, and I will test each version.

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [Linaro-acpi] [PATCH v3 0/8] Add self-probe infrastructure and stacked irqdomain support for ACPI based GICv2/3 init
@ 2015-07-20 12:06       ` Timur Tabi
  0 siblings, 0 replies; 44+ messages in thread
From: Timur Tabi @ 2015-07-20 12:06 UTC (permalink / raw)
  To: linux-arm-kernel

Hanjun Guo wrote:

> I got a question, do you test GICv3 in this patch set too?
> if yes, that will be really great!

Yes, I specifically tested GICv3 on an ACPI-only system.

> Just let you know, I'm still working on this patch set to try
> to address Marc's comments (unify DT and ACPI to match the domain),
> I'm not sure if any obstacles ahead, I will let you know the progress.

Just CC me on all patches, and I will test each version.

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v3 2/8] ACPI / irqchip: Add self-probe infrastructure to initialize IRQ controller
  2015-07-20  9:32       ` Hanjun Guo
  (?)
@ 2015-07-20 12:12         ` Timur Tabi
  -1 siblings, 0 replies; 44+ messages in thread
From: Timur Tabi @ 2015-07-20 12:12 UTC (permalink / raw)
  To: Hanjun Guo
  Cc: Marc Zyngier, Jason Cooper, Will Deacon, Catalin Marinas,
	Rafael J. Wysocki, Wei Huang, Lorenzo Pieralisi, Arnd Bergmann,
	linaro-acpi, lkml, Tomasz Nowicki, linux-acpi, Mark Brown,
	Grant Likely, Thomas Gleixner, Jiang Liu, linux-arm-kernel

Hanjun Guo wrote:
>> Should we display an error message if we don't find a matching table?
>> That can happen if the ACPI tables shows a GIC version number that is
>> not listed in __irqchip_acpi_table[]?
>
> Hmm, did you get the error message like: "Invalid GIC version 5 in
> MADT"? or just use ACPI_MADT_GIC_VERSION_V1 as the gic_version? if
> the later one, it will show everything is fine, but failed to probe
> the GIC.

We had a bug in our ACPI tables that listed the GIC version as 1, and it 
failed to probe and then the kernel panicked.  It took me a while to 
figure out what was wrong, so I think it should print an error message 
that says that version X is unsupported.


-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v3 2/8] ACPI / irqchip: Add self-probe infrastructure to initialize IRQ controller
@ 2015-07-20 12:12         ` Timur Tabi
  0 siblings, 0 replies; 44+ messages in thread
From: Timur Tabi @ 2015-07-20 12:12 UTC (permalink / raw)
  To: Hanjun Guo
  Cc: Marc Zyngier, Jason Cooper, Will Deacon, Catalin Marinas,
	Rafael J. Wysocki, Wei Huang, Lorenzo Pieralisi, Arnd Bergmann,
	linaro-acpi, lkml, Tomasz Nowicki, linux-acpi, Mark Brown,
	Grant Likely, Thomas Gleixner, Jiang Liu, linux-arm-kernel

Hanjun Guo wrote:
>> Should we display an error message if we don't find a matching table?
>> That can happen if the ACPI tables shows a GIC version number that is
>> not listed in __irqchip_acpi_table[]?
>
> Hmm, did you get the error message like: "Invalid GIC version 5 in
> MADT"? or just use ACPI_MADT_GIC_VERSION_V1 as the gic_version? if
> the later one, it will show everything is fine, but failed to probe
> the GIC.

We had a bug in our ACPI tables that listed the GIC version as 1, and it 
failed to probe and then the kernel panicked.  It took me a while to 
figure out what was wrong, so I think it should print an error message 
that says that version X is unsupported.


-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH v3 2/8] ACPI / irqchip: Add self-probe infrastructure to initialize IRQ controller
@ 2015-07-20 12:12         ` Timur Tabi
  0 siblings, 0 replies; 44+ messages in thread
From: Timur Tabi @ 2015-07-20 12:12 UTC (permalink / raw)
  To: linux-arm-kernel

Hanjun Guo wrote:
>> Should we display an error message if we don't find a matching table?
>> That can happen if the ACPI tables shows a GIC version number that is
>> not listed in __irqchip_acpi_table[]?
>
> Hmm, did you get the error message like: "Invalid GIC version 5 in
> MADT"? or just use ACPI_MADT_GIC_VERSION_V1 as the gic_version? if
> the later one, it will show everything is fine, but failed to probe
> the GIC.

We had a bug in our ACPI tables that listed the GIC version as 1, and it 
failed to probe and then the kernel panicked.  It took me a while to 
figure out what was wrong, so I think it should print an error message 
that says that version X is unsupported.


-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v3 2/8] ACPI / irqchip: Add self-probe infrastructure to initialize IRQ controller
  2015-07-20 12:12         ` Timur Tabi
  (?)
@ 2015-07-20 12:48           ` Hanjun Guo
  -1 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-20 12:48 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Marc Zyngier, Jason Cooper, Will Deacon, Catalin Marinas,
	Rafael J. Wysocki, Wei Huang, Lorenzo Pieralisi, Arnd Bergmann,
	linaro-acpi, lkml, Tomasz Nowicki, linux-acpi, Mark Brown,
	Grant Likely, Thomas Gleixner, Jiang Liu, linux-arm-kernel

On 07/20/2015 08:12 PM, Timur Tabi wrote:
> Hanjun Guo wrote:
>>> Should we display an error message if we don't find a matching table?
>>> That can happen if the ACPI tables shows a GIC version number that is
>>> not listed in __irqchip_acpi_table[]?
>>
>> Hmm, did you get the error message like: "Invalid GIC version 5 in
>> MADT"? or just use ACPI_MADT_GIC_VERSION_V1 as the gic_version? if
>> the later one, it will show everything is fine, but failed to probe
>> the GIC.
>
> We had a bug in our ACPI tables that listed the GIC version as 1, and it
> failed to probe and then the kernel panicked.  It took me a while to
> figure out what was wrong, so I think it should print an error message
> that says that version X is unsupported.

OK, will do in next version, thanks for testing those patches!

Hanjun

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v3 2/8] ACPI / irqchip: Add self-probe infrastructure to initialize IRQ controller
@ 2015-07-20 12:48           ` Hanjun Guo
  0 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-20 12:48 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Marc Zyngier, Jason Cooper, Will Deacon, Catalin Marinas,
	Rafael J. Wysocki, Wei Huang, Lorenzo Pieralisi, Arnd Bergmann,
	linaro-acpi, lkml, Tomasz Nowicki, linux-acpi, Mark Brown,
	Grant Likely, Thomas Gleixner, Jiang Liu, linux-arm-kernel

On 07/20/2015 08:12 PM, Timur Tabi wrote:
> Hanjun Guo wrote:
>>> Should we display an error message if we don't find a matching table?
>>> That can happen if the ACPI tables shows a GIC version number that is
>>> not listed in __irqchip_acpi_table[]?
>>
>> Hmm, did you get the error message like: "Invalid GIC version 5 in
>> MADT"? or just use ACPI_MADT_GIC_VERSION_V1 as the gic_version? if
>> the later one, it will show everything is fine, but failed to probe
>> the GIC.
>
> We had a bug in our ACPI tables that listed the GIC version as 1, and it
> failed to probe and then the kernel panicked.  It took me a while to
> figure out what was wrong, so I think it should print an error message
> that says that version X is unsupported.

OK, will do in next version, thanks for testing those patches!

Hanjun

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH v3 2/8] ACPI / irqchip: Add self-probe infrastructure to initialize IRQ controller
@ 2015-07-20 12:48           ` Hanjun Guo
  0 siblings, 0 replies; 44+ messages in thread
From: Hanjun Guo @ 2015-07-20 12:48 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/20/2015 08:12 PM, Timur Tabi wrote:
> Hanjun Guo wrote:
>>> Should we display an error message if we don't find a matching table?
>>> That can happen if the ACPI tables shows a GIC version number that is
>>> not listed in __irqchip_acpi_table[]?
>>
>> Hmm, did you get the error message like: "Invalid GIC version 5 in
>> MADT"? or just use ACPI_MADT_GIC_VERSION_V1 as the gic_version? if
>> the later one, it will show everything is fine, but failed to probe
>> the GIC.
>
> We had a bug in our ACPI tables that listed the GIC version as 1, and it
> failed to probe and then the kernel panicked.  It took me a while to
> figure out what was wrong, so I think it should print an error message
> that says that version X is unsupported.

OK, will do in next version, thanks for testing those patches!

Hanjun

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v3 4/8] irqchip / gic: Add stacked irqdomain support for ACPI based GICv2 init
  2015-07-10 10:45   ` Hanjun Guo
  (?)
@ 2015-07-20 17:45     ` Marc Zyngier
  -1 siblings, 0 replies; 44+ messages in thread
From: Marc Zyngier @ 2015-07-20 17:45 UTC (permalink / raw)
  To: Hanjun Guo, Jason Cooper, Will Deacon, Catalin Marinas,
	Rafael J. Wysocki
  Cc: Thomas Gleixner, Jiang Liu, Lorenzo Pieralisi, Arnd Bergmann,
	Tomasz Nowicki, grant.likely, Mark Brown, Wei Huang,
	linux-arm-kernel, linux-acpi, linux-kernel, linaro-acpi

On 10/07/15 11:45, Hanjun Guo wrote:
> For now, ACPI based GICv2 is using the irq_default_domain as the
> ACPI core domain which is not scalable, also we don't support
> stacked irq domains in ACPI, this patch is trying to implement that.
> 
> Firstly, we need to find the irqdomain with GSI, because we use
> different model of mapping interrupt with device in ACPI than DT,
> in DT, we using the interrupt parent property to get the device
> node of irqchip for devices, that's why we need the matching function
> that match the device node with the one associated with the irqdomain.
> But for ACPI, we only can get the GSI which the device is using, no
> interrupt parent will be specified, then we need a mechanism to find
> GSI's (also the device's) irqdomain to make the code scalable.
> 
> Thanks to the usage of GSI, it is a flat hwirq number which is unique
> in the system, then we can get its associated irq domain by matching
> the GSI supported by this irqchip (see drawings below), then we can
> live without the token pointer matching the interrupt controller as
> DT did.
> 
>                   ------------      ---> gsi_base0
>                  |            |
>                  |            |
>   irqdomain <----| irqchip 0  |
>                  |            |
>                  |            |
>                  |____________|     ---> gsi_end0
> 
>                   ------------      ---> gsi_base1 (probably gsi_end0+1)
>                  |            |
>                  |            |
>   irqdomain <----| irqchip 1  |
>                  |            |
>                  |            |
>                  |____________|     ---> gsi_end1
> 
>                   .....
> 
> if a device is using GSI n, then we can find GSI's irqdomain by matching
> gsi_base <= n <= gsi_end.
> 
> For GIC, we only have one GICD, but the above model still valid. GICD
> structure in ACPI MADT defines System Vector Base in the GICD entry,
> which means the global system interrupt number where this GIC
> Distributor’s interrupt inputs start, then we can get the hwirq numbers
> supported by reading the register, so we can explictly get the GSI's
> associated irqdomain if the GSI is within the range of hwirq supported
> by this GICD.
> 
> Secondly, pass the GSI as the arg for domain's ops alloc() function
> when register the GSI, then we can take advantage of stacked irqdomains.

I'm sorry, but this doesn't make much sense to me.

This patch doesn't only convert GICv2 ACPI support to stacked domains,
it adds a whole new concept of "banks of wired interrupts".

Why do we need this? How relevant is that to making the ACPI code
stacked-domain aware? As far as I understand, only SPIs provided by the
GIC can be expressed as a GSI. And you can only have one GIC.

I'm more and more puzzled by this series.

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

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v3 4/8] irqchip / gic: Add stacked irqdomain support for ACPI based GICv2 init
@ 2015-07-20 17:45     ` Marc Zyngier
  0 siblings, 0 replies; 44+ messages in thread
From: Marc Zyngier @ 2015-07-20 17:45 UTC (permalink / raw)
  To: Hanjun Guo, Jason Cooper, Will Deacon, Catalin Marinas,
	Rafael J. Wysocki
  Cc: Thomas Gleixner, Jiang Liu, Lorenzo Pieralisi, Arnd Bergmann,
	Tomasz Nowicki, grant.likely, Mark Brown, Wei Huang,
	linux-arm-kernel, linux-acpi, linux-kernel, linaro-acpi

On 10/07/15 11:45, Hanjun Guo wrote:
> For now, ACPI based GICv2 is using the irq_default_domain as the
> ACPI core domain which is not scalable, also we don't support
> stacked irq domains in ACPI, this patch is trying to implement that.
> 
> Firstly, we need to find the irqdomain with GSI, because we use
> different model of mapping interrupt with device in ACPI than DT,
> in DT, we using the interrupt parent property to get the device
> node of irqchip for devices, that's why we need the matching function
> that match the device node with the one associated with the irqdomain.
> But for ACPI, we only can get the GSI which the device is using, no
> interrupt parent will be specified, then we need a mechanism to find
> GSI's (also the device's) irqdomain to make the code scalable.
> 
> Thanks to the usage of GSI, it is a flat hwirq number which is unique
> in the system, then we can get its associated irq domain by matching
> the GSI supported by this irqchip (see drawings below), then we can
> live without the token pointer matching the interrupt controller as
> DT did.
> 
>                   ------------      ---> gsi_base0
>                  |            |
>                  |            |
>   irqdomain <----| irqchip 0  |
>                  |            |
>                  |            |
>                  |____________|     ---> gsi_end0
> 
>                   ------------      ---> gsi_base1 (probably gsi_end0+1)
>                  |            |
>                  |            |
>   irqdomain <----| irqchip 1  |
>                  |            |
>                  |            |
>                  |____________|     ---> gsi_end1
> 
>                   .....
> 
> if a device is using GSI n, then we can find GSI's irqdomain by matching
> gsi_base <= n <= gsi_end.
> 
> For GIC, we only have one GICD, but the above model still valid. GICD
> structure in ACPI MADT defines System Vector Base in the GICD entry,
> which means the global system interrupt number where this GIC
> Distributor’s interrupt inputs start, then we can get the hwirq numbers
> supported by reading the register, so we can explictly get the GSI's
> associated irqdomain if the GSI is within the range of hwirq supported
> by this GICD.
> 
> Secondly, pass the GSI as the arg for domain's ops alloc() function
> when register the GSI, then we can take advantage of stacked irqdomains.

I'm sorry, but this doesn't make much sense to me.

This patch doesn't only convert GICv2 ACPI support to stacked domains,
it adds a whole new concept of "banks of wired interrupts".

Why do we need this? How relevant is that to making the ACPI code
stacked-domain aware? As far as I understand, only SPIs provided by the
GIC can be expressed as a GSI. And you can only have one GIC.

I'm more and more puzzled by this series.

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

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH v3 4/8] irqchip / gic: Add stacked irqdomain support for ACPI based GICv2 init
@ 2015-07-20 17:45     ` Marc Zyngier
  0 siblings, 0 replies; 44+ messages in thread
From: Marc Zyngier @ 2015-07-20 17:45 UTC (permalink / raw)
  To: linux-arm-kernel

On 10/07/15 11:45, Hanjun Guo wrote:
> For now, ACPI based GICv2 is using the irq_default_domain as the
> ACPI core domain which is not scalable, also we don't support
> stacked irq domains in ACPI, this patch is trying to implement that.
> 
> Firstly, we need to find the irqdomain with GSI, because we use
> different model of mapping interrupt with device in ACPI than DT,
> in DT, we using the interrupt parent property to get the device
> node of irqchip for devices, that's why we need the matching function
> that match the device node with the one associated with the irqdomain.
> But for ACPI, we only can get the GSI which the device is using, no
> interrupt parent will be specified, then we need a mechanism to find
> GSI's (also the device's) irqdomain to make the code scalable.
> 
> Thanks to the usage of GSI, it is a flat hwirq number which is unique
> in the system, then we can get its associated irq domain by matching
> the GSI supported by this irqchip (see drawings below), then we can
> live without the token pointer matching the interrupt controller as
> DT did.
> 
>                   ------------      ---> gsi_base0
>                  |            |
>                  |            |
>   irqdomain <----| irqchip 0  |
>                  |            |
>                  |            |
>                  |____________|     ---> gsi_end0
> 
>                   ------------      ---> gsi_base1 (probably gsi_end0+1)
>                  |            |
>                  |            |
>   irqdomain <----| irqchip 1  |
>                  |            |
>                  |            |
>                  |____________|     ---> gsi_end1
> 
>                   .....
> 
> if a device is using GSI n, then we can find GSI's irqdomain by matching
> gsi_base <= n <= gsi_end.
> 
> For GIC, we only have one GICD, but the above model still valid. GICD
> structure in ACPI MADT defines System Vector Base in the GICD entry,
> which means the global system interrupt number where this GIC
> Distributor?s interrupt inputs start, then we can get the hwirq numbers
> supported by reading the register, so we can explictly get the GSI's
> associated irqdomain if the GSI is within the range of hwirq supported
> by this GICD.
> 
> Secondly, pass the GSI as the arg for domain's ops alloc() function
> when register the GSI, then we can take advantage of stacked irqdomains.

I'm sorry, but this doesn't make much sense to me.

This patch doesn't only convert GICv2 ACPI support to stacked domains,
it adds a whole new concept of "banks of wired interrupts".

Why do we need this? How relevant is that to making the ACPI code
stacked-domain aware? As far as I understand, only SPIs provided by the
GIC can be expressed as a GSI. And you can only have one GIC.

I'm more and more puzzled by this series.

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

^ permalink raw reply	[flat|nested] 44+ messages in thread

end of thread, other threads:[~2015-07-20 17:45 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-10 10:45 [PATCH v3 0/8] Add self-probe infrastructure and stacked irqdomain support for ACPI based GICv2/3 init Hanjun Guo
2015-07-10 10:45 ` Hanjun Guo
2015-07-10 10:45 ` [PATCH v3 1/8] irqchip / GIC: Add GIC version support in ACPI MADT Hanjun Guo
2015-07-10 10:45   ` Hanjun Guo
2015-07-10 10:45 ` [PATCH v3 2/8] ACPI / irqchip: Add self-probe infrastructure to initialize IRQ controller Hanjun Guo
2015-07-10 10:45   ` Hanjun Guo
2015-07-17 23:15   ` Timur Tabi
2015-07-17 23:15     ` Timur Tabi
2015-07-17 23:15     ` Timur Tabi
2015-07-20  9:32     ` Hanjun Guo
2015-07-20  9:32       ` Hanjun Guo
2015-07-20  9:32       ` Hanjun Guo
2015-07-20 12:12       ` Timur Tabi
2015-07-20 12:12         ` Timur Tabi
2015-07-20 12:12         ` Timur Tabi
2015-07-20 12:48         ` Hanjun Guo
2015-07-20 12:48           ` Hanjun Guo
2015-07-20 12:48           ` Hanjun Guo
2015-07-10 10:45 ` [PATCH v3 3/8] irqchip / GIC / ACPI: Use IRQCHIP_ACPI_DECLARE to simplify GICv2 init code Hanjun Guo
2015-07-10 10:45   ` Hanjun Guo
2015-07-10 10:45   ` Hanjun Guo
2015-07-10 10:45 ` [PATCH v3 4/8] irqchip / gic: Add stacked irqdomain support for ACPI based GICv2 init Hanjun Guo
2015-07-10 10:45   ` Hanjun Guo
2015-07-10 10:45   ` Hanjun Guo
2015-07-20 17:45   ` Marc Zyngier
2015-07-20 17:45     ` Marc Zyngier
2015-07-20 17:45     ` Marc Zyngier
2015-07-10 10:45 ` [PATCH v3 5/8] irqchip / GICv3: Refactor gic_of_init() for GICv3 driver Hanjun Guo
2015-07-10 10:45   ` Hanjun Guo
2015-07-10 10:45 ` [PATCH v3 6/8] irqchip / GICv3: Add ACPI support for GICv3+ initialization Hanjun Guo
2015-07-10 10:45   ` Hanjun Guo
2015-07-10 10:45 ` [PATCH v3 7/8] irqchip / GICv3: Add stacked irqdomain support for ACPI based init Hanjun Guo
2015-07-10 10:45   ` Hanjun Guo
2015-07-10 10:45 ` [PATCH v3 8/8] irqchip / gicv3 / ACPI: Add GICR support via GICC structures Hanjun Guo
2015-07-10 10:45   ` Hanjun Guo
2015-07-17 23:09 ` [Linaro-acpi] [PATCH v3 0/8] Add self-probe infrastructure and stacked irqdomain support for ACPI based GICv2/3 init Timur Tabi
2015-07-17 23:09   ` Timur Tabi
2015-07-17 23:09   ` Timur Tabi
2015-07-20  9:06   ` Hanjun Guo
2015-07-20  9:06     ` Hanjun Guo
2015-07-20  9:06     ` Hanjun Guo
2015-07-20 12:06     ` Timur Tabi
2015-07-20 12:06       ` Timur Tabi
2015-07-20 12:06       ` Timur Tabi

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.