[PATCH 11/11] irqchip / GICv3 / ACPI: Consolidate GICv3 ACPI related init code

Hanjun Guo hanjun.guo at linaro.org
Mon May 18 05:59:21 PDT 2015


Move GICv3 ACPI related init code in irq-gic.c to irq-gic-acpi.c,
this can make the ACPI related GIC init code slef-contained as GICV2
did.

Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
---
 drivers/irqchip/irq-gic-acpi.c     | 109 +++++++++++++++++++++++++++++
 drivers/irqchip/irq-gic-v3.c       | 140 ++-----------------------------------
 include/linux/irqchip/arm-gic-v3.h |  10 +++
 3 files changed, 123 insertions(+), 136 deletions(-)

diff --git a/drivers/irqchip/irq-gic-acpi.c b/drivers/irqchip/irq-gic-acpi.c
index 8463e48..75c4893 100644
--- a/drivers/irqchip/irq-gic-acpi.c
+++ b/drivers/irqchip/irq-gic-acpi.c
@@ -207,3 +207,112 @@ gic_v2_acpi_init(struct acpi_table_header *table)
 	return 0;
 }
 IRQCHIP_ACPI_DECLARE(gic_v2, ACPI_SIG_MADT, gic_v2_acpi_init);
+
+static struct redist_region *redist_regs __initdata;
+static u32 nr_redist_regions __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_v3_acpi_init(struct acpi_table_header *table)
+{
+	int count, i, err = 0;
+	void __iomem *dist_base;
+
+	if (acpi_gic_version() < ACPI_MADT_GIC_VER_V3)
+		return -ENODEV;
+
+	/* Get distributor base address */
+	count = acpi_parse_entries(ACPI_SIG_MADT,
+				sizeof(struct acpi_table_madt),
+				acpi_gic_parse_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 = gicv3_init_bases(dist_base, redist_regs, nr_redist_regions, 0, NULL);
+	if (err)
+		goto out_redist_unmap;
+
+	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_SIG_MADT, gic_v3_acpi_init);
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index e7f134e..a8382f4 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -36,11 +36,6 @@
 #include "irq-gic-common.h"
 #include "irqchip.h"
 
-struct redist_region {
-	void __iomem		*redist_base;
-	phys_addr_t		phys_base;
-};
-
 struct gic_chip_data {
 	void __iomem		*dist_base;
 	struct redist_region	*redist_regions;
@@ -773,7 +768,7 @@ 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,
+int __init gicv3_init_bases(void __iomem *dist_base,
 			    struct redist_region *rdist_regs,
 			    u32 nr_redist_regions,
 			    u64 redist_stride,
@@ -808,6 +803,7 @@ static int __init gic_init_bases(void __iomem *dist_base,
 		goto out_free;
 	}
 
+	set_acpi_core_irqdomain(gic_data.domain);
 	set_handle_irq(gic_handle_irq);
 
 	if (IS_ENABLED(CONFIG_ARM_GIC_V3_ITS) && gic_dist_supports_lpis())
@@ -827,7 +823,7 @@ out_free:
 	return err;
 }
 
-static int __init detect_distributor(void __iomem *dist_base)
+int __init detect_distributor(void __iomem *dist_base)
 {
 	u32 reg = readl_relaxed(dist_base + GICD_PIDR2) & GIC_PIDR2_ARCH_MASK;
 
@@ -887,7 +883,7 @@ 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;
 
-	err = gic_init_bases(dist_base, rdist_regs, nr_redist_regions,
+	err = gicv3_init_bases(dist_base, rdist_regs, nr_redist_regions,
 			     redist_stride, node);
 	if (!err)
 		return 0;
@@ -904,131 +900,3 @@ 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_v3_acpi_init(struct acpi_table_header *table)
-{
-	int count, i, err = 0;
-	void __iomem *dist_base;
-
-	if (acpi_gic_version() < ACPI_MADT_GIC_VER_V3)
-		return -ENODEV;
-
-	/* 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;
-
-	acpi_irq_domain = 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_SIG_MADT, gic_v3_acpi_init);
-#endif
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index ffbc034..37ef420 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -378,6 +378,11 @@ struct rdists {
 	u64			flags;
 };
 
+struct redist_region {
+	void __iomem            *redist_base;
+	phys_addr_t             phys_base;
+};
+
 static inline void gic_write_eoir(u64 irq)
 {
 	asm volatile("msr_s " __stringify(ICC_EOIR1_EL1) ", %0" : : "r" (irq));
@@ -389,6 +394,11 @@ int its_cpu_init(void);
 int its_init(struct device_node *node, struct rdists *rdists,
 	     struct irq_domain *domain);
 
+int gicv3_init_bases(void __iomem *dist_base, struct redist_region *rdist_regs,
+		     u32 nr_redist_regions, u64 redist_stride,
+		     struct device_node *node);
+
+int detect_distributor(void __iomem *dist_base);
 #endif
 
 #endif
-- 
1.9.1




More information about the linux-arm-kernel mailing list