linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V1 00/10] Introduce ACPI world to GICv3 and ITS irqchips
@ 2015-10-15 14:05 Tomasz Nowicki
  2015-10-15 14:05 ` [PATCH V1 01/10] irqchip / GICv3: Refactor gic_of_init() for GICv3 driver Tomasz Nowicki
                   ` (9 more replies)
  0 siblings, 10 replies; 16+ messages in thread
From: Tomasz Nowicki @ 2015-10-15 14:05 UTC (permalink / raw)
  To: marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi, robert.richter
  Cc: will.deacon, Catalin.Marinas, hanjun.guo, graeme.gregory,
	linux-arm-kernel, linux-kernel, linux-acpi, ddaney.cavm,
	Suravee.Suthikulpanit, Tomasz Nowicki

These patches have been part of:
[PATCH v4 00/10] ACPI GIC Self-probing, GICv2m and GICv3 support
https://lkml.org/lkml/2015/7/29/234

Now patches address comments that came up during above series review and
take advantage of useful things like:
1. Making irqdmain independent from device node introduced by Marc:
[PATCH v2 00/17] Divorcing irqdomain and device_node
http://git.kernel.org/cgit/linux/kernel/git/maz/arm-platforms.git irq/irq-domain-fwnode-v2
2. Self-probe infrastructure for probing irqchip introduced by Marc:
[PATCH v3 0/7] Early ACPI probing infrastructure
https://lkml.org/lkml/2015/9/28/421
3. Early MADT sanity check introduced by Al:
[PATCH v5 0/5] Provide better MADT subtable sanity checks
https://lkml.org/lkml/2015/9/29/968

The following git branch contains the submitted patches along with
the pre-requsite patches (mainly for ARM64 PCI support for ACPI).
https://git.linaro.org/leg/acpi/acpi.git pci-acpi-upstream

This has been tested on Cavium ThunderX 1 socket board.

Hanjun Guo (1):
  irqchip / GICv3: remove gic root node in ITS

Tomasz Nowicki (9):
  irqchip / GICv3: Refactor gic_of_init() for GICv3 driver
  irqchip / GICv3: Add ACPI support for GICv3+ initialization
  irqchip,GICv3,ACPI: Add redistributor support via GICC structures.
  irqchip, gicv3, its: Mark its_init() and its children as __init
  irqchip/GICv3/ITS: Refator ITS dt init code to prepare for ACPI.
  ARM64, ACPI, PCI: I/O Remapping Table (IORT) initial support.
  irqchip, gicv3, its: Probe ITS in the ACPI way.
  acpi, gicv3, msi: Factor out code that might be reused for ACPI
    equivalent.
  acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain
    initialization.

 drivers/acpi/Kconfig                     |   3 +
 drivers/acpi/Makefile                    |   1 +
 drivers/acpi/iort.c                      | 326 +++++++++++++++++++++++++++++
 drivers/irqchip/Kconfig                  |   1 +
 drivers/irqchip/irq-gic-v3-its-pci-msi.c |  89 ++++++--
 drivers/irqchip/irq-gic-v3-its.c         | 138 +++++++++----
 drivers/irqchip/irq-gic-v3.c             | 339 ++++++++++++++++++++++++++-----
 include/linux/iort.h                     |  38 ++++
 include/linux/irqchip/arm-gic-v3.h       |   2 +-
 9 files changed, 838 insertions(+), 99 deletions(-)
 create mode 100644 drivers/acpi/iort.c
 create mode 100644 include/linux/iort.h

-- 
1.9.1


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

* [PATCH V1 01/10] irqchip / GICv3: Refactor gic_of_init() for GICv3 driver
  2015-10-15 14:05 [PATCH V1 00/10] Introduce ACPI world to GICv3 and ITS irqchips Tomasz Nowicki
@ 2015-10-15 14:05 ` Tomasz Nowicki
  2015-10-15 14:05 ` [PATCH V1 02/10] irqchip / GICv3: Add ACPI support for GICv3+ initialization Tomasz Nowicki
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Tomasz Nowicki @ 2015-10-15 14:05 UTC (permalink / raw)
  To: marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi, robert.richter
  Cc: will.deacon, Catalin.Marinas, hanjun.guo, graeme.gregory,
	linux-arm-kernel, linux-kernel, linux-acpi, ddaney.cavm,
	Suravee.Suthikulpanit, Tomasz Nowicki, Tomasz Nowicki

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 | 130 ++++++++++++++++++++++++++-----------------
 1 file changed, 78 insertions(+), 52 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 048f020c..e146e20 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -837,59 +837,16 @@ static const struct irq_domain_ops gic_irq_domain_ops = {
 	.free = gic_irq_domain_free,
 };
 
-static int __init gic_of_init(struct device_node *node, struct device_node *parent)
+static int __init gic_init_bases(void __iomem *dist_base,
+				 struct redist_region *rdist_regs,
+				 u32 nr_redist_regions,
+				 u64 redist_stride,
+				 struct fwnode_handle *handle)
 {
-	void __iomem *dist_base;
-	struct redist_region *rdist_regs;
-	u64 redist_stride;
-	u32 nr_redist_regions;
+	struct device_node *node;
 	u32 typer;
-	u32 reg;
 	int gic_irqs;
 	int err;
-	int i;
-
-	dist_base = of_iomap(node, 0);
-	if (!dist_base) {
-		pr_err("%s: unable to map gic dist registers\n",
-			node->full_name);
-		return -ENXIO;
-	}
-
-	reg = readl_relaxed(dist_base + GICD_PIDR2) & GIC_PIDR2_ARCH_MASK;
-	if (reg != GIC_PIDR2_ARCH_GICv3 && reg != GIC_PIDR2_ARCH_GICv4) {
-		pr_err("%s: no distributor detected, giving up\n",
-			node->full_name);
-		err = -ENODEV;
-		goto out_unmap_dist;
-	}
-
-	if (of_property_read_u32(node, "#redistributor-regions", &nr_redist_regions))
-		nr_redist_regions = 1;
-
-	rdist_regs = kzalloc(sizeof(*rdist_regs) * nr_redist_regions, GFP_KERNEL);
-	if (!rdist_regs) {
-		err = -ENOMEM;
-		goto out_unmap_dist;
-	}
-
-	for (i = 0; i < nr_redist_regions; i++) {
-		struct resource res;
-		int ret;
-
-		ret = of_address_to_resource(node, 1 + i, &res);
-		rdist_regs[i].redist_base = of_iomap(node, 1 + i);
-		if (ret || !rdist_regs[i].redist_base) {
-			pr_err("%s: couldn't map region %d\n",
-			       node->full_name, i);
-			err = -ENODEV;
-			goto out_unmap_rdist;
-		}
-		rdist_regs[i].phys_base = res.start;
-	}
-
-	if (of_property_read_u64(node, "redistributor-stride", &redist_stride))
-		redist_stride = 0;
 
 	if (!is_hyp_mode_available())
 		static_key_slow_dec(&supports_deactivate);
@@ -913,8 +870,8 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
 		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.domain = irq_domain_create_tree(handle, &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)) {
@@ -924,7 +881,9 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
 
 	set_handle_irq(gic_handle_irq);
 
-	if (IS_ENABLED(CONFIG_ARM_GIC_V3_ITS) && gic_dist_supports_lpis())
+	node = to_of_node(handle);
+	if (IS_ENABLED(CONFIG_ARM_GIC_V3_ITS) && gic_dist_supports_lpis() &&
+	    node) /* Temp hack to prevent ITS init for ACPI */
 		its_init(node, &gic_data.rdists, gic_data.domain);
 
 	gic_smp_init();
@@ -938,6 +897,73 @@ out_free:
 	if (gic_data.domain)
 		irq_domain_remove(gic_data.domain);
 	free_percpu(gic_data.rdists.rdist);
+	return err;
+}
+
+static int __init gic_validate_dist_version(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;
+}
+
+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;
+	int err, i;
+
+	dist_base = of_iomap(node, 0);
+	if (!dist_base) {
+		pr_err("%s: unable to map gic dist registers\n",
+			node->full_name);
+		return -ENXIO;
+	}
+
+	err = gic_validate_dist_version(dist_base);
+	if (err) {
+		pr_err("%s: no distributor detected, giving up\n",
+			node->full_name);
+		goto out_unmap_dist;
+	}
+
+	if (of_property_read_u32(node, "#redistributor-regions", &nr_redist_regions))
+		nr_redist_regions = 1;
+
+	rdist_regs = kzalloc(sizeof(*rdist_regs) * nr_redist_regions, GFP_KERNEL);
+	if (!rdist_regs) {
+		err = -ENOMEM;
+		goto out_unmap_dist;
+	}
+
+	for (i = 0; i < nr_redist_regions; i++) {
+		struct resource res;
+		int ret;
+
+		ret = of_address_to_resource(node, 1 + i, &res);
+		rdist_regs[i].redist_base = of_iomap(node, 1 + i);
+		if (ret || !rdist_regs[i].redist_base) {
+			pr_err("%s: couldn't map region %d\n",
+			       node->full_name, i);
+			err = -ENODEV;
+			goto out_unmap_rdist;
+		}
+		rdist_regs[i].phys_base = res.start;
+	}
+
+	if (of_property_read_u64(node, "redistributor-stride", &redist_stride))
+		redist_stride = 0;
+
+	err = gic_init_bases(dist_base, rdist_regs, nr_redist_regions,
+			     redist_stride, &node->fwnode);
+	if (!err)
+		return 0;
+
 out_unmap_rdist:
 	for (i = 0; i < nr_redist_regions; i++)
 		if (rdist_regs[i].redist_base)
-- 
1.9.1


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

* [PATCH V1 02/10] irqchip / GICv3: Add ACPI support for GICv3+ initialization
  2015-10-15 14:05 [PATCH V1 00/10] Introduce ACPI world to GICv3 and ITS irqchips Tomasz Nowicki
  2015-10-15 14:05 ` [PATCH V1 01/10] irqchip / GICv3: Refactor gic_of_init() for GICv3 driver Tomasz Nowicki
@ 2015-10-15 14:05 ` Tomasz Nowicki
  2015-10-15 14:05 ` [PATCH V1 03/10] irqchip,GICv3,ACPI: Add redistributor support via GICC structures Tomasz Nowicki
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Tomasz Nowicki @ 2015-10-15 14:05 UTC (permalink / raw)
  To: marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi, robert.richter
  Cc: will.deacon, Catalin.Marinas, hanjun.guo, graeme.gregory,
	linux-arm-kernel, linux-kernel, linux-acpi, ddaney.cavm,
	Suravee.Suthikulpanit, Tomasz Nowicki

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.
Also, ACPI ITS initialization will be added in the following patches.

Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 drivers/irqchip/irq-gic-v3.c | 142 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 142 insertions(+)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index e146e20..0da887c 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>
@@ -798,6 +799,15 @@ static int gic_irq_domain_translate(struct irq_domain *d,
 		return 0;
 	}
 
+	if (is_fwnode_irqchip(fwspec->fwnode)) {
+		if(fwspec->param_count != 2)
+			return -EINVAL;
+
+		*hwirq = fwspec->param[0];
+		*type = fwspec->param[1];
+		return 0;
+	}
+
 	return -EINVAL;
 }
 
@@ -975,3 +985,135 @@ out_unmap_dist:
 }
 
 IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
+
+#ifdef CONFIG_ACPI
+static struct redist_region *redist_regs __initdata;
+static u32 nr_redist_regions __initdata;
+
+static int __init
+gic_acpi_register_redist(phys_addr_t phys_base, u64 size)
+{
+	void __iomem *redist_base;
+	static int count = 0;
+
+	redist_base = ioremap(phys_base, size);
+	if (!redist_base) {
+		pr_err("Couldn't map GICR region @%llx\n", phys_base);
+		return -ENOMEM;
+	}
+
+	redist_regs[count].phys_base = phys_base;
+	redist_regs[count++].redist_base = redist_base;
+	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 =
+			(struct acpi_madt_generic_redistributor *)header;
+
+	return gic_acpi_register_redist(redist->base_address, redist->length);
+}
+
+static int __init gic_acpi_match_gicr(struct acpi_subtable_header *header,
+				  const unsigned long end)
+{
+	/* Subtable presence means that redist exists, that's it */
+	return 0;
+}
+
+static bool __init acpi_validate_gic_table(struct acpi_subtable_header *header,
+					   struct acpi_probe_entry *ape)
+{
+	struct acpi_madt_generic_distributor *dist;
+	int count;
+
+	dist = (struct acpi_madt_generic_distributor *)header;
+	if (dist->version != ape->driver_data)
+		return false;
+
+	/* We need to do that exercise anyway, the sooner the better */
+	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
+				      gic_acpi_match_gicr, 0);
+	if (count <= 0)
+		return false;
+
+	nr_redist_regions = count;
+	return true;
+}
+
+#define ACPI_GICV3_DIST_MEM_SIZE (SZ_64K)
+
+static int __init
+gic_acpi_init(struct acpi_subtable_header *header, const unsigned long end)
+{
+	struct acpi_madt_generic_distributor *dist;
+	struct fwnode_handle *domain_handle;
+	void __iomem *dist_base;
+	int i, err, count;
+
+	/* Get distributor base address */
+	dist = (struct acpi_madt_generic_distributor *)header;
+	dist_base = ioremap(dist->base_address, ACPI_GICV3_DIST_MEM_SIZE);
+	if (!dist_base) {
+		pr_err("Unable to map GICD registers\n");
+		return -ENOMEM;
+	}
+
+	err = gic_validate_dist_version(dist_base);
+	if (err) {
+		pr_err("No distributor detected at @%p, giving up", dist_base);
+		goto out_dist_unmap;
+	}
+
+	redist_regs = kzalloc(sizeof(*redist_regs) * nr_redist_regions,
+			      GFP_KERNEL);
+	if (!redist_regs) {
+		err = -ENOMEM;
+		goto out_dist_unmap;
+	}
+
+	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
+				      gic_acpi_parse_madt_redist, 0);
+	if (count <= 0) {
+		err = -ENODEV;
+		goto out_redist_unmap;
+	}
+
+	domain_handle = irq_domain_alloc_fwnode(dist_base);
+	if (!domain_handle) {
+		err = -ENOMEM;
+		goto out_redist_unmap;
+	}
+
+	err = gic_init_bases(dist_base, redist_regs, nr_redist_regions, 0,
+			     domain_handle);
+	if (err)
+		goto out_fwhandle_free;
+
+	acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, domain_handle);
+	return 0;
+
+out_fwhandle_free:
+	irq_domain_free_fwnode(domain_handle);
+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_TYPE_GENERIC_DISTRIBUTOR,
+		     acpi_validate_gic_table, ACPI_MADT_GIC_VERSION_V3,
+		     gic_acpi_init);
+IRQCHIP_ACPI_DECLARE(gic_v3_maybe, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
+		     acpi_validate_gic_table, ACPI_MADT_GIC_VERSION_NONE,
+		     gic_acpi_init);
+IRQCHIP_ACPI_DECLARE(gic_v4, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
+		     acpi_validate_gic_table, ACPI_MADT_GIC_VERSION_V4,
+		     gic_acpi_init);
+#endif
-- 
1.9.1


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

* [PATCH V1 03/10] irqchip,GICv3,ACPI: Add redistributor support via GICC structures.
  2015-10-15 14:05 [PATCH V1 00/10] Introduce ACPI world to GICv3 and ITS irqchips Tomasz Nowicki
  2015-10-15 14:05 ` [PATCH V1 01/10] irqchip / GICv3: Refactor gic_of_init() for GICv3 driver Tomasz Nowicki
  2015-10-15 14:05 ` [PATCH V1 02/10] irqchip / GICv3: Add ACPI support for GICv3+ initialization Tomasz Nowicki
@ 2015-10-15 14:05 ` Tomasz Nowicki
  2015-10-15 14:05 ` [PATCH V1 04/10] irqchip / GICv3: remove gic root node in ITS Tomasz Nowicki
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Tomasz Nowicki @ 2015-10-15 14:05 UTC (permalink / raw)
  To: marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi, robert.richter
  Cc: will.deacon, Catalin.Marinas, hanjun.guo, graeme.gregory,
	linux-arm-kernel, linux-kernel, linux-acpi, ddaney.cavm,
	Suravee.Suthikulpanit, Tomasz Nowicki

On systems supporting GICv3 and above, in MADT GICC structures, 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 structure(s), init it with GICR base address in GICC
structures in that case.

Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
---
 drivers/irqchip/irq-gic-v3.c | 98 ++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 89 insertions(+), 9 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 0da887c..b27a543 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -39,6 +39,7 @@
 struct redist_region {
 	void __iomem		*redist_base;
 	phys_addr_t		phys_base;
+	bool			single_redist;
 };
 
 struct gic_chip_data {
@@ -476,6 +477,9 @@ static int gic_populate_rdist(void)
 				return 0;
 			}
 
+			if (gic_data.redist_regions[i].single_redist)
+				break;
+
 			if (gic_data.redist_stride) {
 				ptr += gic_data.redist_stride;
 			} else {
@@ -989,6 +993,7 @@ IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
 #ifdef CONFIG_ACPI
 static struct redist_region *redist_regs __initdata;
 static u32 nr_redist_regions __initdata;
+static bool single_redist;
 
 static int __init
 gic_acpi_register_redist(phys_addr_t phys_base, u64 size)
@@ -1003,7 +1008,8 @@ gic_acpi_register_redist(phys_addr_t phys_base, u64 size)
 	}
 
 	redist_regs[count].phys_base = phys_base;
-	redist_regs[count++].redist_base = redist_base;
+	redist_regs[count].redist_base = redist_base;
+	redist_regs[count++].single_redist = single_redist;
 	return 0;
 }
 
@@ -1017,6 +1023,48 @@ gic_acpi_parse_madt_redist(struct acpi_subtable_header *header,
 	return gic_acpi_register_redist(redist->base_address, redist->length);
 }
 
+static int __init
+gic_acpi_parse_madt_gicc(struct acpi_subtable_header *header,
+			 const unsigned long end)
+{
+	struct acpi_madt_generic_interrupt *gicc;
+	void __iomem *redist_base;
+	u64 typer;
+	u32 size;
+
+	gicc = (struct acpi_madt_generic_interrupt *)header;
+	redist_base = ioremap(gicc->gicr_base_address, SZ_64K * 2);
+	if (!redist_base)
+		return -ENOMEM;
+
+	typer = readq_relaxed(redist_base + GICR_TYPER);
+	/* don't map reserved page as it's buggy to access it */
+	size = (typer & GICR_TYPER_VLPIS) ? SZ_64K * 3 : SZ_64K * 2;
+	iounmap(redist_base);
+	return gic_acpi_register_redist(gicc->gicr_base_address, size);
+}
+
+static int __init gic_acpi_collect_gicr_base(void)
+{
+	acpi_tbl_entry_handler redist_parser;
+	enum acpi_madt_type type;
+
+	if (single_redist) {
+		type = ACPI_MADT_TYPE_GENERIC_INTERRUPT;
+		redist_parser = gic_acpi_parse_madt_gicc;
+	} else {
+		type = ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR;
+		redist_parser = gic_acpi_parse_madt_redist;
+	}
+
+	/* Collect redistributor base addresses in GICR entries */
+	if (acpi_table_parse_madt(type, redist_parser, 0) > 0)
+		return 0;
+
+	pr_info("No valid GICR entries exist\n");
+	return -ENODEV;
+}
+
 static int __init gic_acpi_match_gicr(struct acpi_subtable_header *header,
 				  const unsigned long end)
 {
@@ -1024,6 +1072,42 @@ static int __init gic_acpi_match_gicr(struct acpi_subtable_header *header,
 	return 0;
 }
 
+static int __init gic_acpi_match_gicc(struct acpi_subtable_header *header,
+				      const unsigned long end)
+{
+	struct acpi_madt_generic_interrupt *gicc =
+				(struct acpi_madt_generic_interrupt *)header;
+
+	/*
+	 * If GICC is enabled and has valid gicr base address, then it means
+	 * GICR base is presented via GICC
+	 */
+	if ((gicc->flags & ACPI_MADT_ENABLED) && gicc->gicr_base_address)
+		return 0;
+
+	return -ENODEV;
+}
+
+static int __init gic_acpi_count_gicr_regions(void)
+{
+	int count;
+
+	/* Count how many redistributor regions we have */
+	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
+				      gic_acpi_match_gicr, 0);
+	if (count > 0) {
+		single_redist = false;
+		return count;
+	}
+
+	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
+				      gic_acpi_match_gicc, 0);
+	if (count > 0)
+		single_redist = true;
+
+	return count;
+}
+
 static bool __init acpi_validate_gic_table(struct acpi_subtable_header *header,
 					   struct acpi_probe_entry *ape)
 {
@@ -1035,8 +1119,7 @@ static bool __init acpi_validate_gic_table(struct acpi_subtable_header *header,
 		return false;
 
 	/* We need to do that exercise anyway, the sooner the better */
-	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
-				      gic_acpi_match_gicr, 0);
+	count = gic_acpi_count_gicr_regions();
 	if (count <= 0)
 		return false;
 
@@ -1052,7 +1135,7 @@ gic_acpi_init(struct acpi_subtable_header *header, const unsigned long end)
 	struct acpi_madt_generic_distributor *dist;
 	struct fwnode_handle *domain_handle;
 	void __iomem *dist_base;
-	int i, err, count;
+	int i, err;
 
 	/* Get distributor base address */
 	dist = (struct acpi_madt_generic_distributor *)header;
@@ -1075,12 +1158,9 @@ gic_acpi_init(struct acpi_subtable_header *header, const unsigned long end)
 		goto out_dist_unmap;
 	}
 
-	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
-				      gic_acpi_parse_madt_redist, 0);
-	if (count <= 0) {
-		err = -ENODEV;
+	err = gic_acpi_collect_gicr_base();
+	if (err)
 		goto out_redist_unmap;
-	}
 
 	domain_handle = irq_domain_alloc_fwnode(dist_base);
 	if (!domain_handle) {
-- 
1.9.1


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

* [PATCH V1 04/10] irqchip / GICv3: remove gic root node in ITS
  2015-10-15 14:05 [PATCH V1 00/10] Introduce ACPI world to GICv3 and ITS irqchips Tomasz Nowicki
                   ` (2 preceding siblings ...)
  2015-10-15 14:05 ` [PATCH V1 03/10] irqchip,GICv3,ACPI: Add redistributor support via GICC structures Tomasz Nowicki
@ 2015-10-15 14:05 ` Tomasz Nowicki
  2015-10-15 14:05 ` [PATCH V1 05/10] irqchip, gicv3, its: Mark its_init() and its children as __init Tomasz Nowicki
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Tomasz Nowicki @ 2015-10-15 14:05 UTC (permalink / raw)
  To: marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi, robert.richter
  Cc: will.deacon, Catalin.Marinas, hanjun.guo, graeme.gregory,
	linux-arm-kernel, linux-kernel, linux-acpi, ddaney.cavm,
	Suravee.Suthikulpanit

From: Hanjun Guo <hanjun.guo@linaro.org>

The gic_root_node defined in ITS driver is not actually
used, and the ITS driver seems will not use it in the
future, so just remove it.

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

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index f0d64e4..9640e4d 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -94,7 +94,6 @@ struct its_device {
 
 static LIST_HEAD(its_nodes);
 static DEFINE_SPINLOCK(its_lock);
-static struct device_node *gic_root_node;
 static struct rdists *gic_rdists;
 
 #define gic_data_rdist()		(raw_cpu_ptr(gic_rdists->rdist))
@@ -1549,8 +1548,6 @@ int its_init(struct device_node *node, struct rdists *rdists,
 	}
 
 	gic_rdists = rdists;
-	gic_root_node = node;
-
 	its_alloc_lpi_tables();
 	its_lpi_init(rdists->id_bits);
 
-- 
1.9.1


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

* [PATCH V1 05/10] irqchip, gicv3, its: Mark its_init() and its children as __init
  2015-10-15 14:05 [PATCH V1 00/10] Introduce ACPI world to GICv3 and ITS irqchips Tomasz Nowicki
                   ` (3 preceding siblings ...)
  2015-10-15 14:05 ` [PATCH V1 04/10] irqchip / GICv3: remove gic root node in ITS Tomasz Nowicki
@ 2015-10-15 14:05 ` Tomasz Nowicki
  2015-10-15 14:05 ` [PATCH V1 06/10] irqchip/GICv3/ITS: Refator ITS dt init code to prepare for ACPI Tomasz Nowicki
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Tomasz Nowicki @ 2015-10-15 14:05 UTC (permalink / raw)
  To: marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi, robert.richter
  Cc: will.deacon, Catalin.Marinas, hanjun.guo, graeme.gregory,
	linux-arm-kernel, linux-kernel, linux-acpi, ddaney.cavm,
	Suravee.Suthikulpanit, Tomasz Nowicki

gicv3_init_bases() is the only caller for its_init(),
also it is a __init function, so mark its_init() as __init too,
then recursively mark the functions called as __init.

This will help to introduce ITS initialization using ACPI tables as
we will use acpi_table_parse_entries family functions there which
belong to __init section as well.

Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
---
 drivers/irqchip/irq-gic-v3-its.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 9640e4d..7a1a682 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -666,7 +666,7 @@ static int its_chunk_to_lpi(int chunk)
 	return (chunk << IRQS_PER_CHUNK_SHIFT) + 8192;
 }
 
-static int its_lpi_init(u32 id_bits)
+static int __init its_lpi_init(u32 id_bits)
 {
 	lpi_chunks = its_lpi_to_chunk(1UL << id_bits);
 
@@ -1373,7 +1373,8 @@ static int its_force_quiescent(void __iomem *base)
 	}
 }
 
-static int its_probe(struct device_node *node, struct irq_domain *parent)
+static int __init its_probe(struct device_node *node,
+			    struct irq_domain *parent)
 {
 	struct resource res;
 	struct its_node *its;
@@ -1532,7 +1533,7 @@ static struct of_device_id its_device_id[] = {
 	{},
 };
 
-int its_init(struct device_node *node, struct rdists *rdists,
+int __init its_init(struct device_node *node, struct rdists *rdists,
 	     struct irq_domain *parent_domain)
 {
 	struct device_node *np;
-- 
1.9.1


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

* [PATCH V1 06/10] irqchip/GICv3/ITS: Refator ITS dt init code to prepare for ACPI.
  2015-10-15 14:05 [PATCH V1 00/10] Introduce ACPI world to GICv3 and ITS irqchips Tomasz Nowicki
                   ` (4 preceding siblings ...)
  2015-10-15 14:05 ` [PATCH V1 05/10] irqchip, gicv3, its: Mark its_init() and its children as __init Tomasz Nowicki
@ 2015-10-15 14:05 ` Tomasz Nowicki
  2015-10-15 14:05 ` [PATCH V1 07/10] ARM64, ACPI, PCI: I/O Remapping Table (IORT) initial support Tomasz Nowicki
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Tomasz Nowicki @ 2015-10-15 14:05 UTC (permalink / raw)
  To: marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi, robert.richter
  Cc: will.deacon, Catalin.Marinas, hanjun.guo, graeme.gregory,
	linux-arm-kernel, linux-kernel, linux-acpi, ddaney.cavm,
	Suravee.Suthikulpanit, Tomasz Nowicki

Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
---
 drivers/irqchip/irq-gic-v3-its.c   | 78 +++++++++++++++++++++++---------------
 drivers/irqchip/irq-gic-v3.c       |  6 +--
 include/linux/irqchip/arm-gic-v3.h |  2 +-
 3 files changed, 50 insertions(+), 36 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 7a1a682..25926f2 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -810,7 +810,7 @@ static void its_free_tables(struct its_node *its)
 	}
 }
 
-static int its_alloc_tables(const char *node_name, struct its_node *its)
+static int its_alloc_tables(struct its_node *its)
 {
 	int err;
 	int i;
@@ -852,8 +852,8 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
 				    order);
 			if (order >= MAX_ORDER) {
 				order = MAX_ORDER - 1;
-				pr_warn("%s: Device Table too large, reduce its page order to %u\n",
-					node_name, order);
+				pr_warn("ITS@0x%lx: Device Table too large, reduce its page order to %u\n",
+					its->phys_base, order);
 			}
 		}
 
@@ -924,8 +924,8 @@ retry_baser:
 		}
 
 		if (val != tmp) {
-			pr_err("ITS: %s: GITS_BASER%d doesn't stick: %lx %lx\n",
-			       node_name, i,
+			pr_err("ITS@0x%lx: GITS_BASER%d doesn't stick: %lx %lx\n",
+			       its->phys_base, i,
 			       (unsigned long) val, (unsigned long) tmp);
 			err = -ENXIO;
 			goto out_free;
@@ -1373,10 +1373,11 @@ static int its_force_quiescent(void __iomem *base)
 	}
 }
 
-static int __init its_probe(struct device_node *node,
-			    struct irq_domain *parent)
+static int __init its_probe_one(phys_addr_t phys_base, unsigned long size,
+				struct irq_domain *parent,
+				bool is_msi_controller,
+				struct fwnode_handle *handler)
 {
-	struct resource res;
 	struct its_node *its;
 	void __iomem *its_base;
 	struct irq_domain *inner_domain;
@@ -1384,33 +1385,26 @@ static int __init its_probe(struct device_node *node,
 	u64 baser, tmp;
 	int err;
 
-	err = of_address_to_resource(node, 0, &res);
-	if (err) {
-		pr_warn("%s: no regs?\n", node->full_name);
-		return -ENXIO;
-	}
-
-	its_base = ioremap(res.start, resource_size(&res));
+	its_base = ioremap(phys_base, size);
 	if (!its_base) {
-		pr_warn("%s: unable to map registers\n", node->full_name);
+		pr_warn("Unable to map ITS registers\n");
 		return -ENOMEM;
 	}
 
 	val = readl_relaxed(its_base + GITS_PIDR2) & GIC_PIDR2_ARCH_MASK;
 	if (val != 0x30 && val != 0x40) {
-		pr_warn("%s: no ITS detected, giving up\n", node->full_name);
+		pr_warn("No ITS detected, giving up\n");
 		err = -ENODEV;
 		goto out_unmap;
 	}
 
 	err = its_force_quiescent(its_base);
 	if (err) {
-		pr_warn("%s: failed to quiesce, giving up\n",
-			node->full_name);
+		pr_warn("Failed to quiesce, giving up\n");
 		goto out_unmap;
 	}
 
-	pr_info("ITS: %s\n", node->full_name);
+	pr_info("ITS@0x%lx\n", (long)phys_base);
 
 	its = kzalloc(sizeof(*its), GFP_KERNEL);
 	if (!its) {
@@ -1422,7 +1416,7 @@ static int __init its_probe(struct device_node *node,
 	INIT_LIST_HEAD(&its->entry);
 	INIT_LIST_HEAD(&its->its_device_list);
 	its->base = its_base;
-	its->phys_base = res.start;
+	its->phys_base = phys_base;
 	its->ite_size = ((readl_relaxed(its_base + GITS_TYPER) >> 4) & 0xf) + 1;
 
 	its->cmd_base = kzalloc(ITS_CMD_QUEUE_SZ, GFP_KERNEL);
@@ -1432,7 +1426,7 @@ static int __init its_probe(struct device_node *node,
 	}
 	its->cmd_write = its->cmd_base;
 
-	err = its_alloc_tables(node->full_name, its);
+	err = its_alloc_tables(its);
 	if (err)
 		goto out_free_cmd;
 
@@ -1468,7 +1462,7 @@ static int __init its_probe(struct device_node *node,
 	writeq_relaxed(0, its->base + GITS_CWRITER);
 	writel_relaxed(GITS_CTLR_ENABLE, its->base + GITS_CTLR);
 
-	if (of_property_read_bool(node, "msi-controller")) {
+	if (is_msi_controller) {
 		struct msi_domain_info *info;
 
 		info = kzalloc(sizeof(*info), GFP_KERNEL);
@@ -1477,7 +1471,8 @@ static int __init its_probe(struct device_node *node,
 			goto out_free_tables;
 		}
 
-		inner_domain = irq_domain_add_tree(node, &its_domain_ops, its);
+		inner_domain = irq_domain_create_tree(handler, &its_domain_ops,
+						      its);
 		if (!inner_domain) {
 			err = -ENOMEM;
 			kfree(info);
@@ -1505,10 +1500,28 @@ out_free_its:
 	kfree(its);
 out_unmap:
 	iounmap(its_base);
-	pr_err("ITS: failed probing %s (%d)\n", node->full_name, err);
+	pr_err("ITS@0x%lx: failed probing (%d)\n", (long)phys_base, err);
 	return err;
 }
 
+static int __init
+its_of_probe(struct device_node *node, struct irq_domain *parent)
+{
+	struct resource res;
+	bool is_msi_controller = false;
+
+	if (of_address_to_resource(node, 0, &res)) {
+		pr_warn("%s: no regs?\n", node->full_name);
+		return -ENXIO;
+	}
+
+	if (of_property_read_bool(node, "msi-controller"))
+		is_msi_controller = true;
+
+	return its_probe_one(res.start, resource_size(&res), parent,
+			    is_msi_controller, &node->fwnode);
+}
+
 static bool gic_rdists_supports_plpis(void)
 {
 	return !!(readl_relaxed(gic_data_rdist_rd_base() + GICR_TYPER) & GICR_TYPER_PLPIS);
@@ -1533,14 +1546,17 @@ static struct of_device_id its_device_id[] = {
 	{},
 };
 
-int __init its_init(struct device_node *node, struct rdists *rdists,
-	     struct irq_domain *parent_domain)
+int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
+		    struct irq_domain *parent_domain)
 {
-	struct device_node *np;
+	struct device_node *np, *of_node;
 
-	for (np = of_find_matching_node(node, its_device_id); np;
-	     np = of_find_matching_node(np, its_device_id)) {
-		its_probe(np, parent_domain);
+	of_node = to_of_node(handle);
+	if (of_node) {
+		for (np = of_find_matching_node(of_node, its_device_id); np;
+		     np = of_find_matching_node(np, its_device_id)) {
+			its_of_probe(np, parent_domain);
+		}
 	}
 
 	if (list_empty(&its_nodes)) {
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index b27a543..27a6b79 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -857,7 +857,6 @@ static int __init gic_init_bases(void __iomem *dist_base,
 				 u64 redist_stride,
 				 struct fwnode_handle *handle)
 {
-	struct device_node *node;
 	u32 typer;
 	int gic_irqs;
 	int err;
@@ -895,10 +894,9 @@ static int __init gic_init_bases(void __iomem *dist_base,
 
 	set_handle_irq(gic_handle_irq);
 
-	node = to_of_node(handle);
 	if (IS_ENABLED(CONFIG_ARM_GIC_V3_ITS) && gic_dist_supports_lpis() &&
-	    node) /* Temp hack to prevent ITS init for ACPI */
-		its_init(node, &gic_data.rdists, gic_data.domain);
+	    to_of_node(handle)) /* Temp hack to prevent ITS init for ACPI */
+		its_init(handle, &gic_data.rdists, gic_data.domain);
 
 	gic_smp_init();
 	gic_dist_init();
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 9eeeb95..7541c11 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -399,7 +399,7 @@ static inline void gic_write_dir(u64 irq)
 
 struct irq_domain;
 int its_cpu_init(void);
-int its_init(struct device_node *node, struct rdists *rdists,
+int its_init(struct fwnode_handle *handle, struct rdists *rdists,
 	     struct irq_domain *domain);
 
 #endif
-- 
1.9.1


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

* [PATCH V1 07/10] ARM64, ACPI, PCI: I/O Remapping Table (IORT) initial support.
  2015-10-15 14:05 [PATCH V1 00/10] Introduce ACPI world to GICv3 and ITS irqchips Tomasz Nowicki
                   ` (5 preceding siblings ...)
  2015-10-15 14:05 ` [PATCH V1 06/10] irqchip/GICv3/ITS: Refator ITS dt init code to prepare for ACPI Tomasz Nowicki
@ 2015-10-15 14:05 ` Tomasz Nowicki
  2015-10-15 14:05 ` [PATCH V1 08/10] irqchip, gicv3, its: Probe ITS in the ACPI way Tomasz Nowicki
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Tomasz Nowicki @ 2015-10-15 14:05 UTC (permalink / raw)
  To: marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi, robert.richter
  Cc: will.deacon, Catalin.Marinas, hanjun.guo, graeme.gregory,
	linux-arm-kernel, linux-kernel, linux-acpi, ddaney.cavm,
	Suravee.Suthikulpanit, Tomasz Nowicki

IORT shows representation of IO topology for ARM based systems.
It describes how various components are connected together on
parent-child basis e.g. PCI RC -> SMMU -> ITS.

Initial support allows to:
- register ITS MSI chip along with ITS translation ID and domain token
- find registered domain token based on ITS translation ID
- find registered domain token corresponding to given PCI device
- find PCI device DeviceID based on its RequesterID

Additional features like:
- devices to SMMU binding
- finding platform device DeviceID based on its RequesterID
will be added in next series.

Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
---
 drivers/acpi/Kconfig    |   3 +
 drivers/acpi/Makefile   |   1 +
 drivers/acpi/iort.c     | 326 ++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/irqchip/Kconfig |   1 +
 include/linux/iort.h    |  38 ++++++
 5 files changed, 369 insertions(+)
 create mode 100644 drivers/acpi/iort.c
 create mode 100644 include/linux/iort.h

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 5d1015c..8d2b2bd 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -57,6 +57,9 @@ config ACPI_SYSTEM_POWER_STATES_SUPPORT
 config ACPI_CCA_REQUIRED
 	bool
 
+config IORT_TABLE
+	bool
+
 config ACPI_SLEEP
 	bool
 	depends on SUSPEND || HIBERNATION
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index b5e7cd8..962f98e 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -78,6 +78,7 @@ obj-$(CONFIG_ACPI_HED)		+= hed.o
 obj-$(CONFIG_ACPI_EC_DEBUGFS)	+= ec_sys.o
 obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
 obj-$(CONFIG_ACPI_BGRT)		+= bgrt.o
+obj-$(CONFIG_IORT_TABLE) 	+= iort.o
 
 # processor has its own "processor." module_param namespace
 processor-y			:= processor_driver.o
diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
new file mode 100644
index 0000000..13efc5f
--- /dev/null
+++ b/drivers/acpi/iort.c
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2015, Linaro Ltd.
+ *	Author: Tomasz Nowicki <tomasz.nowicki@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * This file implements early detection/parsing of I/O mapping
+ * reported to OS through firmware via I/O Remapping Table (IORT)
+ * IORT document number: ARM DEN 0049A
+ */
+
+#define pr_fmt(fmt)	"ACPI: IORT: " fmt
+
+#include <linux/export.h>
+#include <linux/iort.h>
+#include <linux/irqdomain.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+
+struct iort_its_msi_chip {
+	struct list_head	list;
+	struct fwnode_handle	*fw_node;
+	u32			translation_id;
+};
+
+typedef acpi_status (*iort_find_node_callback)
+	(struct acpi_iort_node *node, void *context);
+
+/* Root pointer to the mapped IORT table */
+static struct acpi_table_header *iort_table;
+
+static LIST_HEAD(iort_msi_chip_list);
+
+/**
+ * iort_register_domain_token() - register domain token and related ITS ID
+ * 				  to the list from where we can get it back
+ * 				  later on.
+ * @translation_id: ITS ID
+ * @token: domain token
+ *
+ * Returns: 0 on success, -ENOMEM if not memory when allocating list element.
+ */
+int iort_register_domain_token(int trans_id, struct fwnode_handle *fw_node)
+{
+	struct iort_its_msi_chip *its_msi_chip;
+
+	its_msi_chip = kzalloc(sizeof(*its_msi_chip), GFP_KERNEL);
+	if (!its_msi_chip)
+		return -ENOMEM;
+
+	its_msi_chip->fw_node = fw_node;
+	its_msi_chip->translation_id = trans_id;
+
+	list_add(&its_msi_chip->list, &iort_msi_chip_list);
+	return 0;
+}
+
+/**
+ * iort_find_its_domain_token() - find domain token based on given ITS ID.
+ * @translation_id: ITS ID
+ *
+ * Returns: domain token when find on the list, NULL otherwise.
+ */
+struct fwnode_handle *iort_find_its_domain_token(int trans_id)
+{
+	struct iort_its_msi_chip *its_msi_chip;
+
+	list_for_each_entry(its_msi_chip, &iort_msi_chip_list, list) {
+		if (its_msi_chip->translation_id == trans_id)
+			return its_msi_chip->fw_node;
+	}
+
+	return NULL;
+}
+
+static struct acpi_iort_node *
+iort_scan_node(enum acpi_iort_node_type type,
+	       iort_find_node_callback callback, void *context)
+{
+	struct acpi_iort_node *iort_node, *iort_end;
+	struct acpi_table_iort *iort;
+	int i;
+
+	if (!iort_table)
+		return NULL;
+
+	/*
+	 * iort_table and iort both point to the start of IORT table, but
+	 * have different struct types
+	 */
+	iort = (struct acpi_table_iort *)iort_table;
+
+	/* Get the first IORT node */
+	iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort,
+				 iort->node_offset);
+	iort_end = ACPI_ADD_PTR(struct acpi_iort_node, iort_table,
+				iort_table->length);
+
+	for (i = 0; i < iort->node_count; i++) {
+		if (iort_node >= iort_end) {
+			pr_err("iort node pointer overflows, bad table\n");
+			return NULL;
+		}
+
+		if (iort_node->type == type) {
+			if (ACPI_SUCCESS(callback(iort_node, context)))
+				return iort_node;
+		}
+
+		iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort_node,
+					 iort_node->length);
+	}
+
+	return NULL;
+}
+
+static struct acpi_iort_node *iort_find_parent_node(struct acpi_iort_node *node)
+{
+	struct acpi_iort_id_mapping *id;
+
+	if (!node || !node->mapping_offset || !node->mapping_count)
+		return NULL;
+
+	id = ACPI_ADD_PTR(struct acpi_iort_id_mapping, node,
+			      node->mapping_offset);
+	/* Firmware bug! */
+	if (!id->output_reference) {
+		pr_err(FW_BUG "[node %p type %d] ID map has NULL parent reference\n",
+		       node, node->type);
+		return NULL;
+	}
+
+	node = ACPI_ADD_PTR(struct acpi_iort_node, iort_table,
+			    id->output_reference);
+	return node;
+}
+
+static acpi_status
+iort_find_dev_callback(struct acpi_iort_node *node, void *context)
+{
+	struct acpi_iort_root_complex *pci_rc;
+	struct device *dev = context;
+	struct pci_bus *bus;
+
+	switch (node->type) {
+	case ACPI_IORT_NODE_PCI_ROOT_COMPLEX:
+		bus = to_pci_bus(dev);
+		pci_rc = (struct acpi_iort_root_complex *)node->node_data;
+
+		/*
+		 * It is assumed that PCI segment numbers have a one-to-one
+		 * mapping with root complexes. Each segment number can
+		 * represent only one root complex.
+		 */
+		if (pci_rc->pci_segment_number == pci_domain_nr(bus))
+			return AE_OK;
+
+		break;
+	}
+
+	return AE_NOT_FOUND;
+}
+
+/**
+ * iort_pci_find_its_id() - find the ITS identifier based on specified device.
+ * @dev: device
+ * @idx: index of the ITS identifier list
+ * @its_id: ITS identifier
+ *
+ * Returns: 0 on success, appropriate error value otherwise
+ */
+static int
+iort_pci_find_its_id(struct device *dev, unsigned int idx, int *its_id)
+{
+	struct acpi_iort_its_group *its;
+	struct acpi_iort_node *node;
+
+	node = iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX,
+			      iort_find_dev_callback, dev);
+	if (!node) {
+		pr_err("can't find node related to %s device\n", dev_name(dev));
+		return -ENXIO;
+	}
+
+	/* Go upstream until find its parent ITS node */
+	while (node->type != ACPI_IORT_NODE_ITS_GROUP) {
+		node = iort_find_parent_node(node);
+		if (!node)
+			return -ENXIO;
+	}
+
+	/* Move to ITS specific data */
+	its = (struct acpi_iort_its_group *)node->node_data;
+	if (idx > its->its_count) {
+		pr_err("requested ITS ID index [%d] is greater than available ITS count [%d]\n",
+		       idx, its->its_count);
+		return -ENXIO;
+	}
+
+	*its_id = its->identifiers[idx];
+	return 0;
+}
+
+
+/**
+ * iort_find_pci_domain_token() - find registered domain token related to
+ * 				  PCI device
+ * @dev: device
+ *
+ * Returns: domain token on success, NULL otherwise
+ */
+struct fwnode_handle *iort_find_pci_domain_token(struct device *dev)
+{
+	static struct fwnode_handle *domain_handle;
+	int its_id;
+
+	if (iort_pci_find_its_id(dev, 0, &its_id))
+		return NULL;
+
+	domain_handle = iort_find_its_domain_token(its_id);
+	if (!domain_handle)
+		return NULL;
+
+	return domain_handle;
+}
+
+static int
+iort_translate_dev_to_devid(struct acpi_iort_node *node, u32 req_id,
+			    u32 *dev_id)
+{
+	u32 curr_id = req_id;
+
+	if (!node)
+		return -EINVAL;
+
+	/* Go upstream */
+	while (node->type != ACPI_IORT_NODE_ITS_GROUP) {
+		struct acpi_iort_id_mapping *id;
+		int i, found = 0;
+
+		/* Exit when no mapping array */
+		if (!node->mapping_offset || !node->mapping_count)
+			return -EINVAL;
+
+		id = ACPI_ADD_PTR(struct acpi_iort_id_mapping, node,
+				  node->mapping_offset);
+
+		for (i = 0, found = 0; i < node->mapping_count; i++, id++) {
+			/*
+			 * Single mapping is not translation rule,
+			 * lets move on for this case
+			 */
+			if (id->flags & ACPI_IORT_ID_SINGLE_MAPPING)
+				continue;
+
+			if (curr_id < id->input_base ||
+			    (curr_id > id->input_base + id->id_count))
+				continue;
+
+			curr_id = id->output_base + (curr_id - id->input_base);
+			found = 1;
+			break;
+		}
+
+		if (!found)
+			return -ENXIO;
+
+		node = iort_find_parent_node(node);
+		if (!node)
+			return -ENXIO;
+	}
+
+	*dev_id = curr_id;
+	return 0;
+}
+
+/**
+ * iort_find_pci_id() - find PCI device ID based on requester ID
+ * @dev: device
+ * @req_id: requester ID
+ * @dev_id: device ID
+ *
+ * Returns: 0 on success, appropriate error value otherwise
+ */
+int iort_find_pci_id(struct pci_dev *pdev, u32 req_id, u32 *dev_id)
+{
+	struct pci_bus *bus = pdev->bus;
+	struct acpi_iort_node *node;
+	int err;
+
+	node = iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX,
+			      iort_find_dev_callback, &bus->dev);
+	if (!node) {
+		pr_err("can't find node related to %s device\n",
+		       dev_name(&pdev->dev));
+		return -ENXIO;
+	}
+
+	err = iort_translate_dev_to_devid(node, req_id, dev_id);
+	return err;
+}
+
+static int __init iort_table_detect(void)
+{
+	acpi_status status;
+
+	if (acpi_disabled)
+		return -ENODEV;
+
+	status = acpi_get_table(ACPI_SIG_IORT, 0, &iort_table);
+	if (ACPI_FAILURE(status)) {
+		const char *msg = acpi_format_exception(status);
+		pr_err("Failed to get table, %s\n", msg);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+arch_initcall(iort_table_detect);
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 27b52c8..67a8da56 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -26,6 +26,7 @@ config ARM_GIC_V3
 config ARM_GIC_V3_ITS
 	bool
 	select PCI_MSI_IRQ_DOMAIN
+	select IORT_TABLE if ACPI
 
 config ARM_NVIC
 	bool
diff --git a/include/linux/iort.h b/include/linux/iort.h
new file mode 100644
index 0000000..783e8d6
--- /dev/null
+++ b/include/linux/iort.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015, Linaro Ltd.
+ *	Author: Tomasz Nowicki <tomasz.nowicki@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef __IORT_H__
+#define __IORT_H__
+
+#include <linux/acpi.h>
+
+#ifdef CONFIG_ACPI
+
+struct fwnode_handle;
+
+int iort_register_domain_token(int trans_id, struct fwnode_handle *fw_node);
+struct fwnode_handle *iort_find_its_domain_token(int trans_id);
+struct fwnode_handle *iort_find_pci_domain_token(struct device *dev);
+int iort_find_pci_id(struct pci_dev *pdev, u32 req_id, u32 *dev_id);
+#else /* CONFIG_ACPI */
+static inline int
+iort_find_pci_id(struct pci_dev *pdev, u32 req_id, u32 *dev_id)
+{ return -ENXIO; }
+#endif /* CONFIG_ACPI */
+
+#endif /* __IORT_H__ */
-- 
1.9.1


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

* [PATCH V1 08/10] irqchip, gicv3, its: Probe ITS in the ACPI way.
  2015-10-15 14:05 [PATCH V1 00/10] Introduce ACPI world to GICv3 and ITS irqchips Tomasz Nowicki
                   ` (6 preceding siblings ...)
  2015-10-15 14:05 ` [PATCH V1 07/10] ARM64, ACPI, PCI: I/O Remapping Table (IORT) initial support Tomasz Nowicki
@ 2015-10-15 14:05 ` Tomasz Nowicki
  2015-10-15 14:05 ` [PATCH V1 09/10] acpi, gicv3, msi: Factor out code that might be reused for ACPI equivalent Tomasz Nowicki
  2015-10-15 14:05 ` [PATCH V1 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization Tomasz Nowicki
  9 siblings, 0 replies; 16+ messages in thread
From: Tomasz Nowicki @ 2015-10-15 14:05 UTC (permalink / raw)
  To: marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi, robert.richter
  Cc: will.deacon, Catalin.Marinas, hanjun.guo, graeme.gregory,
	linux-arm-kernel, linux-kernel, linux-acpi, ddaney.cavm,
	Suravee.Suthikulpanit, Tomasz Nowicki

Since we prepared ITS for being initialized different that via DT,
it is now possible to parse MADT and pass mandatory info to
firmware-agnostic ITS init call.

Note that we are using here IORT lib to keep track of allocated
domain handler which will be used to build PCI MSI domain on top
in the later patches.

Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 drivers/irqchip/irq-gic-v3-its.c | 56 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 55 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 25926f2..061af36 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -15,10 +15,12 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/acpi.h>
 #include <linux/bitmap.h>
 #include <linux/cpu.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/iort.h>
 #include <linux/log2.h>
 #include <linux/mm.h>
 #include <linux/msi.h>
@@ -1248,6 +1250,11 @@ static int its_irq_gic_domain_alloc(struct irq_domain *domain,
 		fwspec.param[0] = GIC_IRQ_TYPE_LPI;
 		fwspec.param[1] = hwirq;
 		fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
+	} else if (is_fwnode_irqchip(domain->parent->fwnode)) {
+		fwspec.fwnode = domain->parent->fwnode;
+		fwspec.param_count = 2;
+		fwspec.param[0] = hwirq;
+		fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
 	} else {
 		return -EINVAL;
 	}
@@ -1541,6 +1548,52 @@ int its_cpu_init(void)
 	return 0;
 }
 
+#ifdef CONFIG_ACPI
+
+#define ACPI_GICV3_ITS_MEM_SIZE (2 * SZ_64K)
+
+static struct irq_domain *its_parent __initdata;
+
+static int __init
+gic_acpi_parse_madt_its(struct acpi_subtable_header *header,
+			const unsigned long end)
+{
+	struct acpi_madt_generic_translator *its_entry;
+	struct fwnode_handle *domain_handle;
+	int err;
+
+	its_entry = (struct acpi_madt_generic_translator *)header;
+	domain_handle = irq_domain_alloc_fwnode((void *)its_entry->base_address);
+	if (!domain_handle) {
+		pr_err("Unable to allocate GICv2m domain token\n");
+		return -ENOMEM;
+	}
+
+	/* ITS works as msi controller in ACPI case */
+	err = its_probe_one(its_entry->base_address, ACPI_GICV3_ITS_MEM_SIZE,
+			    its_parent, true, domain_handle);
+	if (err) {
+		irq_domain_free_fwnode(domain_handle);
+		return err;
+	}
+	iort_register_domain_token(its_entry->translation_id, domain_handle);
+	return 0;
+}
+
+void __init its_acpi_probe(struct irq_domain *parent_domain)
+{
+	int count;
+
+	its_parent = parent_domain;
+	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_TRANSLATOR,
+				      gic_acpi_parse_madt_its, 0);
+	if (count <= 0)
+		pr_info("No valid GIC ITS entries exist\n");
+}
+#else
+static inline void __init its_acpi_probe(struct irq_domain *parent_domain) { }
+#endif
+
 static struct of_device_id its_device_id[] = {
 	{	.compatible	= "arm,gic-v3-its",	},
 	{},
@@ -1557,7 +1610,8 @@ int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
 		     np = of_find_matching_node(np, its_device_id)) {
 			its_of_probe(np, parent_domain);
 		}
-	}
+	} else
+		its_acpi_probe(parent_domain);
 
 	if (list_empty(&its_nodes)) {
 		pr_warn("ITS: No ITS available, not enabling LPIs\n");
-- 
1.9.1


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

* [PATCH V1 09/10] acpi, gicv3, msi: Factor out code that might be reused for ACPI equivalent.
  2015-10-15 14:05 [PATCH V1 00/10] Introduce ACPI world to GICv3 and ITS irqchips Tomasz Nowicki
                   ` (7 preceding siblings ...)
  2015-10-15 14:05 ` [PATCH V1 08/10] irqchip, gicv3, its: Probe ITS in the ACPI way Tomasz Nowicki
@ 2015-10-15 14:05 ` Tomasz Nowicki
  2015-10-15 14:05 ` [PATCH V1 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization Tomasz Nowicki
  9 siblings, 0 replies; 16+ messages in thread
From: Tomasz Nowicki @ 2015-10-15 14:05 UTC (permalink / raw)
  To: marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi, robert.richter
  Cc: will.deacon, Catalin.Marinas, hanjun.guo, graeme.gregory,
	linux-arm-kernel, linux-kernel, linux-acpi, ddaney.cavm,
	Suravee.Suthikulpanit, Tomasz Nowicki

Firmware agnostic code lands in separate function which do necessary
domain initialization based on unequal domain handler.

Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
---
 drivers/irqchip/irq-gic-v3-its-pci-msi.c | 43 +++++++++++++++++++++-----------
 1 file changed, 28 insertions(+), 15 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its-pci-msi.c b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
index 693c2f9..cfd35da 100644
--- a/drivers/irqchip/irq-gic-v3-its-pci-msi.c
+++ b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
@@ -108,34 +108,47 @@ static struct of_device_id its_device_id[] = {
 	{},
 };
 
-static int __init its_pci_msi_init(void)
+static int __init its_pci_msi_init_one(struct fwnode_handle *handle)
 {
-	struct device_node *np;
 	struct irq_domain *parent;
 
+	parent = irq_find_matching_fwnode(handle, DOMAIN_BUS_NEXUS);
+	if (!parent || !msi_get_domain_info(parent)) {
+		pr_err("Unable to locate ITS domain\n");
+		return -ENXIO;
+	}
+
+	if (!pci_msi_create_irq_domain(handle, &its_pci_msi_domain_info,
+				       parent)) {
+		pr_err("Unable to create PCI domain\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static int __init its_pci_of_msi_init(void)
+{
+	struct device_node *np;
+
 	for (np = of_find_matching_node(NULL, its_device_id); np;
 	     np = of_find_matching_node(np, its_device_id)) {
 		if (!of_property_read_bool(np, "msi-controller"))
 			continue;
 
-		parent = irq_find_matching_host(np, DOMAIN_BUS_NEXUS);
-		if (!parent || !msi_get_domain_info(parent)) {
-			pr_err("%s: unable to locate ITS domain\n",
-			       np->full_name);
+		if (its_pci_msi_init_one(of_node_to_fwnode(np)))
 			continue;
-		}
-
-		if (!pci_msi_create_irq_domain(of_node_to_fwnode(np),
-					       &its_pci_msi_domain_info,
-					       parent)) {
-			pr_err("%s: unable to create PCI domain\n",
-			       np->full_name);
-			continue;
-		}
 
 		pr_info("PCI/MSI: %s domain created\n", np->full_name);
 	}
 
 	return 0;
 }
+
+static int __init its_pci_msi_init(void)
+{
+	its_pci_of_msi_init();
+	return 0;
+}
+
 early_initcall(its_pci_msi_init);
-- 
1.9.1


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

* [PATCH V1 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization.
  2015-10-15 14:05 [PATCH V1 00/10] Introduce ACPI world to GICv3 and ITS irqchips Tomasz Nowicki
                   ` (8 preceding siblings ...)
  2015-10-15 14:05 ` [PATCH V1 09/10] acpi, gicv3, msi: Factor out code that might be reused for ACPI equivalent Tomasz Nowicki
@ 2015-10-15 14:05 ` Tomasz Nowicki
  2015-10-24 10:20   ` Hanjun Guo
  9 siblings, 1 reply; 16+ messages in thread
From: Tomasz Nowicki @ 2015-10-15 14:05 UTC (permalink / raw)
  To: marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi, robert.richter
  Cc: will.deacon, Catalin.Marinas, hanjun.guo, graeme.gregory,
	linux-arm-kernel, linux-kernel, linux-acpi, ddaney.cavm,
	Suravee.Suthikulpanit, Tomasz Nowicki

After refactoring DT code, we let ACPI to build ITS PCI MSI domain
and do requester ID to device ID translation using IORT table.

We have now full PCI MSI domain stack, thus we can enable ITS initialization
from GICv3 core driver for ACPI scenario.

Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
---
 drivers/irqchip/irq-gic-v3-its-pci-msi.c | 48 ++++++++++++++++++++++++++++++--
 drivers/irqchip/irq-gic-v3.c             |  3 +-
 2 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its-pci-msi.c b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
index cfd35da..09ae2d8 100644
--- a/drivers/irqchip/irq-gic-v3-its-pci-msi.c
+++ b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
@@ -15,6 +15,8 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/acpi.h>
+#include <linux/iort.h>
 #include <linux/msi.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
@@ -59,8 +61,10 @@ static int its_pci_msi_vec_count(struct pci_dev *pdev)
 static int its_get_pci_alias(struct pci_dev *pdev, u16 alias, void *data)
 {
 	struct its_pci_alias *dev_alias = data;
+	u32 dev_id;
 
-	dev_alias->dev_id = alias;
+	dev_alias->dev_id = iort_find_pci_id(pdev, alias, &dev_id) == 0 ?
+								dev_id : alias;
 	if (pdev != dev_alias->pdev)
 		dev_alias->count += its_pci_msi_vec_count(pdev);
 
@@ -145,10 +149,50 @@ static int __init its_pci_of_msi_init(void)
 	return 0;
 }
 
+#ifdef CONFIG_ACPI
+
+static int __init
+its_pci_msi_parse_madt(struct acpi_subtable_header *header,
+		    const unsigned long end)
+{
+	struct acpi_madt_generic_translator *its_entry;
+	struct fwnode_handle *domain_handle;
+
+	its_entry = (struct acpi_madt_generic_translator *)header;
+	domain_handle = iort_find_its_domain_token(its_entry->translation_id);
+	if (!domain_handle) {
+		pr_err("ITS@0x%lx: Unable to locate ITS domain handle\n",
+		       (long)its_entry->base_address);
+		return 0;
+	}
+
+	if (its_pci_msi_init_one(domain_handle))
+		return 0;
+
+	pci_msi_register_fwnode_provider(&iort_find_pci_domain_token);
+	pr_info("PCI/MSI: ITS@0x%lx domain created\n",
+		(long)its_entry->base_address);
+	return 0;
+}
+
+static int __init its_pci_acpi_msi_init(void)
+{
+	acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_TRANSLATOR,
+			      its_pci_msi_parse_madt, 0);
+	return 0;
+}
+#else
+inline static int __init its_pci_acpi_msi_init(void)
+{
+	return 0;
+}
+#endif
+
 static int __init its_pci_msi_init(void)
 {
 	its_pci_of_msi_init();
+	its_pci_acpi_msi_init();
+
 	return 0;
 }
-
 early_initcall(its_pci_msi_init);
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 27a6b79..b498947 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -894,8 +894,7 @@ static int __init gic_init_bases(void __iomem *dist_base,
 
 	set_handle_irq(gic_handle_irq);
 
-	if (IS_ENABLED(CONFIG_ARM_GIC_V3_ITS) && gic_dist_supports_lpis() &&
-	    to_of_node(handle)) /* Temp hack to prevent ITS init for ACPI */
+	if (IS_ENABLED(CONFIG_ARM_GIC_V3_ITS) && gic_dist_supports_lpis())
 		its_init(handle, &gic_data.rdists, gic_data.domain);
 
 	gic_smp_init();
-- 
1.9.1


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

* Re: [PATCH V1 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization.
  2015-10-15 14:05 ` [PATCH V1 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization Tomasz Nowicki
@ 2015-10-24 10:20   ` Hanjun Guo
  2015-10-24 13:58     ` Tomasz Nowicki
  0 siblings, 1 reply; 16+ messages in thread
From: Hanjun Guo @ 2015-10-24 10:20 UTC (permalink / raw)
  To: Tomasz Nowicki, marc.zyngier, tglx, jason, rjw,
	lorenzo.pieralisi, robert.richter
  Cc: will.deacon, Catalin.Marinas, hanjun.guo, graeme.gregory,
	linux-arm-kernel, linux-kernel, linux-acpi, ddaney.cavm,
	Suravee.Suthikulpanit

On 2015/10/15 22:05, Tomasz Nowicki wrote:
> After refactoring DT code, we let ACPI to build ITS PCI MSI domain
> and do requester ID to device ID translation using IORT table.
>
> We have now full PCI MSI domain stack, thus we can enable ITS initialization
> from GICv3 core driver for ACPI scenario.
>
> Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
> ---
>  drivers/irqchip/irq-gic-v3-its-pci-msi.c | 48 ++++++++++++++++++++++++++++++--
>  drivers/irqchip/irq-gic-v3.c             |  3 +-
>  2 files changed, 47 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/irqchip/irq-gic-v3-its-pci-msi.c b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
> index cfd35da..09ae2d8 100644
> --- a/drivers/irqchip/irq-gic-v3-its-pci-msi.c
> +++ b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
> @@ -15,6 +15,8 @@
>   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>   */
>  
> +#include <linux/acpi.h>
> +#include <linux/iort.h>
>  #include <linux/msi.h>
>  #include <linux/of.h>
>  #include <linux/of_irq.h>
> @@ -59,8 +61,10 @@ static int its_pci_msi_vec_count(struct pci_dev *pdev)
>  static int its_get_pci_alias(struct pci_dev *pdev, u16 alias, void *data)
>  {
>  	struct its_pci_alias *dev_alias = data;
> +	u32 dev_id;
>  
> -	dev_alias->dev_id = alias;
> +	dev_alias->dev_id = iort_find_pci_id(pdev, alias, &dev_id) == 0 ?
> +								dev_id : alias;

Hi tomasz, I think we need to re work this patch on top of tip/irq/core
which has support for "msi-map" and "mai-parent" property support.

Thanks
Hanjun


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

* Re: [PATCH V1 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization.
  2015-10-24 10:20   ` Hanjun Guo
@ 2015-10-24 13:58     ` Tomasz Nowicki
  2015-11-17  7:11       ` Huang Shijie
  0 siblings, 1 reply; 16+ messages in thread
From: Tomasz Nowicki @ 2015-10-24 13:58 UTC (permalink / raw)
  To: Hanjun Guo, Tomasz Nowicki, marc.zyngier, tglx, jason, rjw,
	lorenzo.pieralisi, robert.richter
  Cc: will.deacon, Catalin.Marinas, hanjun.guo, graeme.gregory,
	linux-arm-kernel, linux-kernel, linux-acpi, ddaney.cavm,
	Suravee.Suthikulpanit

On 10/24/2015 12:20 PM, Hanjun Guo wrote:
> On 2015/10/15 22:05, Tomasz Nowicki wrote:
>> After refactoring DT code, we let ACPI to build ITS PCI MSI domain
>> and do requester ID to device ID translation using IORT table.
>>
>> We have now full PCI MSI domain stack, thus we can enable ITS initialization
>> from GICv3 core driver for ACPI scenario.
>>
>> Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
>> ---
>>   drivers/irqchip/irq-gic-v3-its-pci-msi.c | 48 ++++++++++++++++++++++++++++++--
>>   drivers/irqchip/irq-gic-v3.c             |  3 +-
>>   2 files changed, 47 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/irqchip/irq-gic-v3-its-pci-msi.c b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
>> index cfd35da..09ae2d8 100644
>> --- a/drivers/irqchip/irq-gic-v3-its-pci-msi.c
>> +++ b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
>> @@ -15,6 +15,8 @@
>>    * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>>    */
>>
>> +#include <linux/acpi.h>
>> +#include <linux/iort.h>
>>   #include <linux/msi.h>
>>   #include <linux/of.h>
>>   #include <linux/of_irq.h>
>> @@ -59,8 +61,10 @@ static int its_pci_msi_vec_count(struct pci_dev *pdev)
>>   static int its_get_pci_alias(struct pci_dev *pdev, u16 alias, void *data)
>>   {
>>   	struct its_pci_alias *dev_alias = data;
>> +	u32 dev_id;
>>
>> -	dev_alias->dev_id = alias;
>> +	dev_alias->dev_id = iort_find_pci_id(pdev, alias, &dev_id) == 0 ?
>> +								dev_id : alias;
>
> Hi tomasz, I think we need to re work this patch on top of tip/irq/core
> which has support for "msi-map" and "mai-parent" property support.
>

Indeed, I will rebase after some more comments related to other patches 
in this series.

Tomasz

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

* Re: [PATCH V1 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization.
  2015-10-24 13:58     ` Tomasz Nowicki
@ 2015-11-17  7:11       ` Huang Shijie
  2015-11-17  9:03         ` Hanjun Guo
  0 siblings, 1 reply; 16+ messages in thread
From: Huang Shijie @ 2015-11-17  7:11 UTC (permalink / raw)
  To: Tomasz Nowicki
  Cc: Hanjun Guo, Tomasz Nowicki, marc.zyngier, tglx, jason, rjw,
	lorenzo.pieralisi, robert.richter, Suravee.Suthikulpanit,
	graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, ddaney.cavm, linux-arm-kernel

On Sat, Oct 24, 2015 at 03:58:17PM +0200, Tomasz Nowicki wrote:
Hi Tomasz,
> 
> Indeed, I will rebase after some more comments related to other patches in
> this series.
> 
Do you have any update about this patch set?
I want to test this patch set, but I met the fail when I git-am this
patch set to linux-next tree.

thanks
Huang Shijie


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

* Re: [PATCH V1 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization.
  2015-11-17  7:11       ` Huang Shijie
@ 2015-11-17  9:03         ` Hanjun Guo
  2015-11-17  9:30           ` Huang Shijie
  0 siblings, 1 reply; 16+ messages in thread
From: Hanjun Guo @ 2015-11-17  9:03 UTC (permalink / raw)
  To: Huang Shijie, Tomasz Nowicki
  Cc: Tomasz Nowicki, marc.zyngier, tglx, jason, rjw,
	lorenzo.pieralisi, robert.richter, Suravee.Suthikulpanit,
	graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, ddaney.cavm, linux-arm-kernel

Hi Shijie,

On 2015/11/17 15:11, Huang Shijie wrote:
> On Sat, Oct 24, 2015 at 03:58:17PM +0200, Tomasz Nowicki wrote:
> Hi Tomasz,
>> Indeed, I will rebase after some more comments related to other patches in
>> this series.
>>
> Do you have any update about this patch set?
> I want to test this patch set, but I met the fail when I git-am this
> patch set to linux-next tree.

you can pull from git://git.linaro.org/leg/acpi/acpi.git, branch topic-pci

Thanks
Hanjun


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

* Re: [PATCH V1 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization.
  2015-11-17  9:03         ` Hanjun Guo
@ 2015-11-17  9:30           ` Huang Shijie
  0 siblings, 0 replies; 16+ messages in thread
From: Huang Shijie @ 2015-11-17  9:30 UTC (permalink / raw)
  To: Hanjun Guo
  Cc: Tomasz Nowicki, Tomasz Nowicki, marc.zyngier, tglx, jason, rjw,
	lorenzo.pieralisi, robert.richter, Suravee.Suthikulpanit,
	graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, ddaney.cavm, linux-arm-kernel

On Tue, Nov 17, 2015 at 05:03:39PM +0800, Hanjun Guo wrote:
Hi Hanjun,
> Hi Shijie,
> 
> On 2015/11/17 15:11, Huang Shijie wrote:
> > On Sat, Oct 24, 2015 at 03:58:17PM +0200, Tomasz Nowicki wrote:
> > Hi Tomasz,
> >> Indeed, I will rebase after some more comments related to other patches in
> >> this series.
> >>
> > Do you have any update about this patch set?
> > I want to test this patch set, but I met the fail when I git-am this
> > patch set to linux-next tree.
> 
> you can pull from git://git.linaro.org/leg/acpi/acpi.git, branch topic-pci
okay, I will do that.

thanks
Huang Shijie


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

end of thread, other threads:[~2015-11-17  9:31 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-15 14:05 [PATCH V1 00/10] Introduce ACPI world to GICv3 and ITS irqchips Tomasz Nowicki
2015-10-15 14:05 ` [PATCH V1 01/10] irqchip / GICv3: Refactor gic_of_init() for GICv3 driver Tomasz Nowicki
2015-10-15 14:05 ` [PATCH V1 02/10] irqchip / GICv3: Add ACPI support for GICv3+ initialization Tomasz Nowicki
2015-10-15 14:05 ` [PATCH V1 03/10] irqchip,GICv3,ACPI: Add redistributor support via GICC structures Tomasz Nowicki
2015-10-15 14:05 ` [PATCH V1 04/10] irqchip / GICv3: remove gic root node in ITS Tomasz Nowicki
2015-10-15 14:05 ` [PATCH V1 05/10] irqchip, gicv3, its: Mark its_init() and its children as __init Tomasz Nowicki
2015-10-15 14:05 ` [PATCH V1 06/10] irqchip/GICv3/ITS: Refator ITS dt init code to prepare for ACPI Tomasz Nowicki
2015-10-15 14:05 ` [PATCH V1 07/10] ARM64, ACPI, PCI: I/O Remapping Table (IORT) initial support Tomasz Nowicki
2015-10-15 14:05 ` [PATCH V1 08/10] irqchip, gicv3, its: Probe ITS in the ACPI way Tomasz Nowicki
2015-10-15 14:05 ` [PATCH V1 09/10] acpi, gicv3, msi: Factor out code that might be reused for ACPI equivalent Tomasz Nowicki
2015-10-15 14:05 ` [PATCH V1 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization Tomasz Nowicki
2015-10-24 10:20   ` Hanjun Guo
2015-10-24 13:58     ` Tomasz Nowicki
2015-11-17  7:11       ` Huang Shijie
2015-11-17  9:03         ` Hanjun Guo
2015-11-17  9:30           ` Huang Shijie

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).