All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V3 00/10] Introduce ACPI world to GICv3 & ITS irqchip
@ 2016-01-19 13:11 ` Tomasz Nowicki
  0 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-01-19 13:11 UTC (permalink / raw)
  To: marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm,
	Tomasz Nowicki

Patches base on Suravee's ACPI GICv2m support:
https://lkml.org/lkml/2015/12/10/475

The following git branch contains submitted patches along with
the useful patches from the test point of view (mainly ACPI ARM64 PCI support).
https://github.com/semihalf-nowicki-tomasz/linux.git (gicv3-its-acpi-v3)

Series has been tested on Cavium ThunderX server.

v2 -> v3
- rebased on top of 4.4
- fixes and improvements for redistributor init via GICC structures
- fixes as per kbuild reports

v1 -> v2
- rebased on top of 4.4-rc4
- use pci_msi_domain_get_msi_rid for requester ID to device ID translation

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 |  85 ++++++--
 drivers/irqchip/irq-gic-v3-its.c         | 143 +++++++++----
 drivers/irqchip/irq-gic-v3.c             | 344 ++++++++++++++++++++++++++-----
 drivers/pci/msi.c                        |   3 +
 include/linux/iort.h                     |  38 ++++
 include/linux/irqchip/arm-gic-v3.h       |   2 +-
 10 files changed, 845 insertions(+), 101 deletions(-)
 create mode 100644 drivers/acpi/iort.c
 create mode 100644 include/linux/iort.h

-- 
1.9.1


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

* [PATCH V3 00/10] Introduce ACPI world to GICv3 & ITS irqchip
@ 2016-01-19 13:11 ` Tomasz Nowicki
  0 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-01-19 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

Patches base on Suravee's ACPI GICv2m support:
https://lkml.org/lkml/2015/12/10/475

The following git branch contains submitted patches along with
the useful patches from the test point of view (mainly ACPI ARM64 PCI support).
https://github.com/semihalf-nowicki-tomasz/linux.git (gicv3-its-acpi-v3)

Series has been tested on Cavium ThunderX server.

v2 -> v3
- rebased on top of 4.4
- fixes and improvements for redistributor init via GICC structures
- fixes as per kbuild reports

v1 -> v2
- rebased on top of 4.4-rc4
- use pci_msi_domain_get_msi_rid for requester ID to device ID translation

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 |  85 ++++++--
 drivers/irqchip/irq-gic-v3-its.c         | 143 +++++++++----
 drivers/irqchip/irq-gic-v3.c             | 344 ++++++++++++++++++++++++++-----
 drivers/pci/msi.c                        |   3 +
 include/linux/iort.h                     |  38 ++++
 include/linux/irqchip/arm-gic-v3.h       |   2 +-
 10 files changed, 845 insertions(+), 101 deletions(-)
 create mode 100644 drivers/acpi/iort.c
 create mode 100644 include/linux/iort.h

-- 
1.9.1

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

* [PATCH V3 01/10] irqchip / GICv3: Refactor gic_of_init() for GICv3 driver
  2016-01-19 13:11 ` Tomasz Nowicki
@ 2016-01-19 13:11   ` Tomasz Nowicki
  -1 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-01-19 13:11 UTC (permalink / raw)
  To: marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm,
	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 d7be6dd..31205c7 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -811,59 +811,16 @@ static void gicv3_enable_quirks(void)
 #endif
 }
 
-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);
@@ -889,8 +846,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)) {
@@ -900,7 +857,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();
@@ -914,6 +873,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] 71+ messages in thread

* [PATCH V3 01/10] irqchip / GICv3: Refactor gic_of_init() for GICv3 driver
@ 2016-01-19 13:11   ` Tomasz Nowicki
  0 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-01-19 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

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 d7be6dd..31205c7 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -811,59 +811,16 @@ static void gicv3_enable_quirks(void)
 #endif
 }
 
-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);
@@ -889,8 +846,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)) {
@@ -900,7 +857,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();
@@ -914,6 +873,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] 71+ messages in thread

* [PATCH V3 02/10] irqchip / GICv3: Add ACPI support for GICv3+ initialization
  2016-01-19 13:11 ` Tomasz Nowicki
@ 2016-01-19 13:11   ` Tomasz Nowicki
  -1 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-01-19 13:11 UTC (permalink / raw)
  To: marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm,
	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 | 137 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 137 insertions(+)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 31205c7..2cada42 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -15,10 +15,12 @@
  * 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>
 #include <linux/interrupt.h>
+#include <linux/irqdomain.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -764,6 +766,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;
 }
 
@@ -951,3 +962,129 @@ 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_parse_madt_redist(struct acpi_subtable_header *header,
+			   const unsigned long end)
+{
+	struct acpi_madt_generic_redistributor *redist =
+			(struct acpi_madt_generic_redistributor *)header;
+	void __iomem *redist_base;
+	static int count = 0;
+
+	redist_base = ioremap(redist->base_address, redist->length);
+	if (!redist_base) {
+		pr_err("Couldn't map GICR region @%llx\n", redist->base_address);
+		return -ENOMEM;
+	}
+
+	redist_regs[count].phys_base = redist->base_address;
+	redist_regs[count].redist_base = redist_base;
+	count++;
+	return 0;
+}
+
+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_v4, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
+		     acpi_validate_gic_table, ACPI_MADT_GIC_VERSION_V4,
+		     gic_acpi_init);
+IRQCHIP_ACPI_DECLARE(gic_v3_or_v4, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
+		     acpi_validate_gic_table, ACPI_MADT_GIC_VERSION_NONE,
+		     gic_acpi_init);
+#endif
-- 
1.9.1

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

* [PATCH V3 02/10] irqchip / GICv3: Add ACPI support for GICv3+ initialization
@ 2016-01-19 13:11   ` Tomasz Nowicki
  0 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-01-19 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

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 | 137 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 137 insertions(+)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 31205c7..2cada42 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -15,10 +15,12 @@
  * 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>
 #include <linux/interrupt.h>
+#include <linux/irqdomain.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -764,6 +766,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;
 }
 
@@ -951,3 +962,129 @@ 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_parse_madt_redist(struct acpi_subtable_header *header,
+			   const unsigned long end)
+{
+	struct acpi_madt_generic_redistributor *redist =
+			(struct acpi_madt_generic_redistributor *)header;
+	void __iomem *redist_base;
+	static int count = 0;
+
+	redist_base = ioremap(redist->base_address, redist->length);
+	if (!redist_base) {
+		pr_err("Couldn't map GICR region @%llx\n", redist->base_address);
+		return -ENOMEM;
+	}
+
+	redist_regs[count].phys_base = redist->base_address;
+	redist_regs[count].redist_base = redist_base;
+	count++;
+	return 0;
+}
+
+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_v4, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
+		     acpi_validate_gic_table, ACPI_MADT_GIC_VERSION_V4,
+		     gic_acpi_init);
+IRQCHIP_ACPI_DECLARE(gic_v3_or_v4, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
+		     acpi_validate_gic_table, ACPI_MADT_GIC_VERSION_NONE,
+		     gic_acpi_init);
+#endif
-- 
1.9.1

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

* [PATCH V3 03/10] irqchip,GICv3,ACPI: Add redistributor support via GICC structures.
  2016-01-19 13:11 ` Tomasz Nowicki
@ 2016-01-19 13:11   ` Tomasz Nowicki
  -1 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-01-19 13:11 UTC (permalink / raw)
  To: marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm,
	Tomasz Nowicki

Following ACPI spec:
On systems supporting GICv3 and above, GICR Base Address in MADT GICC
structure holds the 64-bit physical address of the associated Redistributor.
If all of the GIC Redistributors are in the always-on power domain,
GICR structures should be used to describe the Redistributors instead,
and this field must be set to 0.

It means that we have two ways to initialize registirbutors map.
1. via GICD structure which can accommodate many redistributors as a region
2. via GICC which is able to describe single redistributor

This patch is going to add support for second option.
Considering redistributors, GICD and GICC subtables have be mutually
exclusive. While discovering and mapping redistributor, we need to know
its size in advance. For the GICC case, redistributor can be in
a power-domain that is off, thus we cannot relay on GICR TYPER register.
Therefore, we get GIC version from distributor register and map 2xSZ_64K
for GICv3 and 4xSZ_64K for GICv4.

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

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 2cada42..dd16a60 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -40,6 +40,7 @@
 struct redist_region {
 	void __iomem		*redist_base;
 	phys_addr_t		phys_base;
+	bool			single_redist;
 };
 
 struct gic_chip_data {
@@ -436,6 +437,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 {
@@ -964,8 +968,21 @@ out_unmap_dist:
 IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
 
 #ifdef CONFIG_ACPI
+static void __iomem *dist_base;
 static struct redist_region *redist_regs __initdata;
 static u32 nr_redist_regions __initdata;
+static bool single_redist;
+
+static void __init
+gic_acpi_register_redist(phys_addr_t phys_base, void __iomem *redist_base)
+{
+	static int count = 0;
+
+	redist_regs[count].phys_base = phys_base;
+	redist_regs[count].redist_base = redist_base;
+	redist_regs[count].single_redist = single_redist;
+	count++;
+}
 
 static int __init
 gic_acpi_parse_madt_redist(struct acpi_subtable_header *header,
@@ -974,7 +991,6 @@ gic_acpi_parse_madt_redist(struct acpi_subtable_header *header,
 	struct acpi_madt_generic_redistributor *redist =
 			(struct acpi_madt_generic_redistributor *)header;
 	void __iomem *redist_base;
-	static int count = 0;
 
 	redist_base = ioremap(redist->base_address, redist->length);
 	if (!redist_base) {
@@ -982,12 +998,49 @@ gic_acpi_parse_madt_redist(struct acpi_subtable_header *header,
 		return -ENOMEM;
 	}
 
-	redist_regs[count].phys_base = redist->base_address;
-	redist_regs[count].redist_base = redist_base;
-	count++;
+	gic_acpi_register_redist(redist->base_address, redist_base);
 	return 0;
 }
 
+static int __init
+gic_acpi_parse_madt_gicc(struct acpi_subtable_header *header,
+			 const unsigned long end)
+{
+	struct acpi_madt_generic_interrupt *gicc =
+				(struct acpi_madt_generic_interrupt *)header;
+	u32 reg = readl_relaxed(dist_base + GICD_PIDR2) & GIC_PIDR2_ARCH_MASK;
+	u32 size = reg == GIC_PIDR2_ARCH_GICv4 ? SZ_64K * 4 : SZ_64K * 2;
+	void __iomem *redist_base;
+
+	redist_base = ioremap(gicc->gicr_base_address, size);
+	if (!redist_base)
+		return -ENOMEM;
+
+	gic_acpi_register_redist(gicc->gicr_base_address, redist_base);
+	return 0;
+}
+
+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)
 {
@@ -995,6 +1048,46 @@ 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. It is not allowed
+	 * to mix redistributor description, GICR and GICC subtables have to be
+	 * mutually exclusive.
+	 */
+	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)
 {
@@ -1006,8 +1099,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;
 
@@ -1022,8 +1114,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;
@@ -1046,12 +1137,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] 71+ messages in thread

* [PATCH V3 03/10] irqchip, GICv3, ACPI: Add redistributor support via GICC structures.
@ 2016-01-19 13:11   ` Tomasz Nowicki
  0 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-01-19 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

Following ACPI spec:
On systems supporting GICv3 and above, GICR Base Address in MADT GICC
structure holds the 64-bit physical address of the associated Redistributor.
If all of the GIC Redistributors are in the always-on power domain,
GICR structures should be used to describe the Redistributors instead,
and this field must be set to 0.

It means that we have two ways to initialize registirbutors map.
1. via GICD structure which can accommodate many redistributors as a region
2. via GICC which is able to describe single redistributor

This patch is going to add support for second option.
Considering redistributors, GICD and GICC subtables have be mutually
exclusive. While discovering and mapping redistributor, we need to know
its size in advance. For the GICC case, redistributor can be in
a power-domain that is off, thus we cannot relay on GICR TYPER register.
Therefore, we get GIC version from distributor register and map 2xSZ_64K
for GICv3 and 4xSZ_64K for GICv4.

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

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 2cada42..dd16a60 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -40,6 +40,7 @@
 struct redist_region {
 	void __iomem		*redist_base;
 	phys_addr_t		phys_base;
+	bool			single_redist;
 };
 
 struct gic_chip_data {
@@ -436,6 +437,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 {
@@ -964,8 +968,21 @@ out_unmap_dist:
 IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
 
 #ifdef CONFIG_ACPI
+static void __iomem *dist_base;
 static struct redist_region *redist_regs __initdata;
 static u32 nr_redist_regions __initdata;
+static bool single_redist;
+
+static void __init
+gic_acpi_register_redist(phys_addr_t phys_base, void __iomem *redist_base)
+{
+	static int count = 0;
+
+	redist_regs[count].phys_base = phys_base;
+	redist_regs[count].redist_base = redist_base;
+	redist_regs[count].single_redist = single_redist;
+	count++;
+}
 
 static int __init
 gic_acpi_parse_madt_redist(struct acpi_subtable_header *header,
@@ -974,7 +991,6 @@ gic_acpi_parse_madt_redist(struct acpi_subtable_header *header,
 	struct acpi_madt_generic_redistributor *redist =
 			(struct acpi_madt_generic_redistributor *)header;
 	void __iomem *redist_base;
-	static int count = 0;
 
 	redist_base = ioremap(redist->base_address, redist->length);
 	if (!redist_base) {
@@ -982,12 +998,49 @@ gic_acpi_parse_madt_redist(struct acpi_subtable_header *header,
 		return -ENOMEM;
 	}
 
-	redist_regs[count].phys_base = redist->base_address;
-	redist_regs[count].redist_base = redist_base;
-	count++;
+	gic_acpi_register_redist(redist->base_address, redist_base);
 	return 0;
 }
 
+static int __init
+gic_acpi_parse_madt_gicc(struct acpi_subtable_header *header,
+			 const unsigned long end)
+{
+	struct acpi_madt_generic_interrupt *gicc =
+				(struct acpi_madt_generic_interrupt *)header;
+	u32 reg = readl_relaxed(dist_base + GICD_PIDR2) & GIC_PIDR2_ARCH_MASK;
+	u32 size = reg == GIC_PIDR2_ARCH_GICv4 ? SZ_64K * 4 : SZ_64K * 2;
+	void __iomem *redist_base;
+
+	redist_base = ioremap(gicc->gicr_base_address, size);
+	if (!redist_base)
+		return -ENOMEM;
+
+	gic_acpi_register_redist(gicc->gicr_base_address, redist_base);
+	return 0;
+}
+
+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)
 {
@@ -995,6 +1048,46 @@ 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. It is not allowed
+	 * to mix redistributor description, GICR and GICC subtables have to be
+	 * mutually exclusive.
+	 */
+	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)
 {
@@ -1006,8 +1099,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;
 
@@ -1022,8 +1114,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;
@@ -1046,12 +1137,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] 71+ messages in thread

* [PATCH V3 04/10] irqchip / GICv3: remove gic root node in ITS
  2016-01-19 13:11 ` Tomasz Nowicki
@ 2016-01-19 13:11   ` Tomasz Nowicki
  -1 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-01-19 13:11 UTC (permalink / raw)
  To: marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm

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 e23d1d1..7ca7f9a 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -97,7 +97,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))
@@ -1602,8 +1601,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] 71+ messages in thread

* [PATCH V3 04/10] irqchip / GICv3: remove gic root node in ITS
@ 2016-01-19 13:11   ` Tomasz Nowicki
  0 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-01-19 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

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 e23d1d1..7ca7f9a 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -97,7 +97,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))
@@ -1602,8 +1601,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] 71+ messages in thread

* [PATCH V3 05/10] irqchip, gicv3, its: Mark its_init() and its children as __init
  2016-01-19 13:11 ` Tomasz Nowicki
  (?)
@ 2016-01-19 13:11   ` Tomasz Nowicki
  -1 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-01-19 13:11 UTC (permalink / raw)
  To: marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, ddaney.cavm, Tomasz Nowicki, mw,
	linux-arm-kernel

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 7ca7f9a..2bbed18 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -669,7 +669,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);
 
@@ -1424,7 +1424,8 @@ static void its_enable_quirks(struct its_node *its)
 	gic_enable_quirks(iidr, its_quirks, its);
 }
 
-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;
@@ -1585,7 +1586,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] 71+ messages in thread

* [PATCH V3 05/10] irqchip, gicv3, its: Mark its_init() and its children as __init
@ 2016-01-19 13:11   ` Tomasz Nowicki
  0 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-01-19 13:11 UTC (permalink / raw)
  To: marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm,
	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 7ca7f9a..2bbed18 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -669,7 +669,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);
 
@@ -1424,7 +1424,8 @@ static void its_enable_quirks(struct its_node *its)
 	gic_enable_quirks(iidr, its_quirks, its);
 }
 
-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;
@@ -1585,7 +1586,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] 71+ messages in thread

* [PATCH V3 05/10] irqchip, gicv3, its: Mark its_init() and its children as __init
@ 2016-01-19 13:11   ` Tomasz Nowicki
  0 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-01-19 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

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 7ca7f9a..2bbed18 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -669,7 +669,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);
 
@@ -1424,7 +1424,8 @@ static void its_enable_quirks(struct its_node *its)
 	gic_enable_quirks(iidr, its_quirks, its);
 }
 
-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;
@@ -1585,7 +1586,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] 71+ messages in thread

* [PATCH V3 06/10] irqchip, GICv3, ITS: Refator ITS dt init code to prepare for ACPI.
  2016-01-19 13:11 ` Tomasz Nowicki
  (?)
@ 2016-01-19 13:11   ` Tomasz Nowicki
  -1 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-01-19 13:11 UTC (permalink / raw)
  To: marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, ddaney.cavm, Tomasz Nowicki, mw,
	linux-arm-kernel

Similarly to GICv3 core, we need to extract common code before adding
ACPI support. No functional changes.

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

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 2bbed18..fecb7a6 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -813,7 +813,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;
@@ -868,8 +868,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);
 			}
 		}
 
@@ -878,8 +878,8 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
 		if (alloc_pages > GITS_BASER_PAGES_MAX) {
 			alloc_pages = GITS_BASER_PAGES_MAX;
 			order = get_order(GITS_BASER_PAGES_MAX * psz);
-			pr_warn("%s: Device Table too large, reduce its page order to %u (%u pages)\n",
-				node_name, order, alloc_pages);
+			pr_warn("ITS@0x%lx: Device Table too large, reduce its page order to %u (%u pages)\n",
+				its->phys_base, order, alloc_pages);
 		}
 
 		base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
@@ -948,8 +948,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;
@@ -1424,10 +1424,11 @@ static void its_enable_quirks(struct its_node *its)
 	gic_enable_quirks(iidr, its_quirks, its);
 }
 
-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;
@@ -1435,33 +1436,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) {
@@ -1473,7 +1467,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);
@@ -1485,7 +1479,7 @@ static int __init its_probe(struct device_node *node,
 
 	its_enable_quirks(its);
 
-	err = its_alloc_tables(node->full_name, its);
+	err = its_alloc_tables(its);
 	if (err)
 		goto out_free_cmd;
 
@@ -1521,7 +1515,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);
@@ -1530,7 +1524,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);
@@ -1558,10 +1553,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);
@@ -1586,14 +1599,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 dd16a60..995b7251 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -832,7 +832,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;
@@ -872,10 +871,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 d5d798b..a40ed7d 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -332,7 +332,7 @@ struct rdists {
 struct irq_domain;
 struct device_node;
 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);
 
 static inline bool gic_enable_sre(void)
-- 
1.9.1

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

* [PATCH V3 06/10] irqchip, GICv3, ITS: Refator ITS dt init code to prepare for ACPI.
@ 2016-01-19 13:11   ` Tomasz Nowicki
  0 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-01-19 13:11 UTC (permalink / raw)
  To: marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm,
	Tomasz Nowicki

Similarly to GICv3 core, we need to extract common code before adding
ACPI support. No functional changes.

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

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 2bbed18..fecb7a6 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -813,7 +813,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;
@@ -868,8 +868,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);
 			}
 		}
 
@@ -878,8 +878,8 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
 		if (alloc_pages > GITS_BASER_PAGES_MAX) {
 			alloc_pages = GITS_BASER_PAGES_MAX;
 			order = get_order(GITS_BASER_PAGES_MAX * psz);
-			pr_warn("%s: Device Table too large, reduce its page order to %u (%u pages)\n",
-				node_name, order, alloc_pages);
+			pr_warn("ITS@0x%lx: Device Table too large, reduce its page order to %u (%u pages)\n",
+				its->phys_base, order, alloc_pages);
 		}
 
 		base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
@@ -948,8 +948,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;
@@ -1424,10 +1424,11 @@ static void its_enable_quirks(struct its_node *its)
 	gic_enable_quirks(iidr, its_quirks, its);
 }
 
-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;
@@ -1435,33 +1436,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) {
@@ -1473,7 +1467,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);
@@ -1485,7 +1479,7 @@ static int __init its_probe(struct device_node *node,
 
 	its_enable_quirks(its);
 
-	err = its_alloc_tables(node->full_name, its);
+	err = its_alloc_tables(its);
 	if (err)
 		goto out_free_cmd;
 
@@ -1521,7 +1515,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);
@@ -1530,7 +1524,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);
@@ -1558,10 +1553,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);
@@ -1586,14 +1599,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 dd16a60..995b7251 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -832,7 +832,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;
@@ -872,10 +871,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 d5d798b..a40ed7d 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -332,7 +332,7 @@ struct rdists {
 struct irq_domain;
 struct device_node;
 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);
 
 static inline bool gic_enable_sre(void)
-- 
1.9.1

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

* [PATCH V3 06/10] irqchip, GICv3, ITS: Refator ITS dt init code to prepare for ACPI.
@ 2016-01-19 13:11   ` Tomasz Nowicki
  0 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-01-19 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

Similarly to GICv3 core, we need to extract common code before adding
ACPI support. No functional changes.

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

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 2bbed18..fecb7a6 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -813,7 +813,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;
@@ -868,8 +868,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 at 0x%lx: Device Table too large, reduce its page order to %u\n",
+					its->phys_base, order);
 			}
 		}
 
@@ -878,8 +878,8 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
 		if (alloc_pages > GITS_BASER_PAGES_MAX) {
 			alloc_pages = GITS_BASER_PAGES_MAX;
 			order = get_order(GITS_BASER_PAGES_MAX * psz);
-			pr_warn("%s: Device Table too large, reduce its page order to %u (%u pages)\n",
-				node_name, order, alloc_pages);
+			pr_warn("ITS at 0x%lx: Device Table too large, reduce its page order to %u (%u pages)\n",
+				its->phys_base, order, alloc_pages);
 		}
 
 		base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
@@ -948,8 +948,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 at 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;
@@ -1424,10 +1424,11 @@ static void its_enable_quirks(struct its_node *its)
 	gic_enable_quirks(iidr, its_quirks, its);
 }
 
-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;
@@ -1435,33 +1436,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 at 0x%lx\n", (long)phys_base);
 
 	its = kzalloc(sizeof(*its), GFP_KERNEL);
 	if (!its) {
@@ -1473,7 +1467,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);
@@ -1485,7 +1479,7 @@ static int __init its_probe(struct device_node *node,
 
 	its_enable_quirks(its);
 
-	err = its_alloc_tables(node->full_name, its);
+	err = its_alloc_tables(its);
 	if (err)
 		goto out_free_cmd;
 
@@ -1521,7 +1515,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);
@@ -1530,7 +1524,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);
@@ -1558,10 +1553,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 at 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);
@@ -1586,14 +1599,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 dd16a60..995b7251 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -832,7 +832,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;
@@ -872,10 +871,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 d5d798b..a40ed7d 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -332,7 +332,7 @@ struct rdists {
 struct irq_domain;
 struct device_node;
 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);
 
 static inline bool gic_enable_sre(void)
-- 
1.9.1

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

* [PATCH V3 07/10] ARM64, ACPI, PCI: I/O Remapping Table (IORT) initial support.
  2016-01-19 13:11 ` Tomasz Nowicki
  (?)
@ 2016-01-19 13:11   ` Tomasz Nowicki
  -1 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-01-19 13:11 UTC (permalink / raw)
  To: marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, ddaney.cavm, Tomasz Nowicki, mw,
	linux-arm-kernel

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 5eef4cb..c3664be 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_DEBUGGER
 	bool "AML debugger interface (EXPERIMENTAL)"
 	select ACPI_DEBUG
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 675eaf3..96b3183 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -79,6 +79,7 @@ obj-$(CONFIG_ACPI_EC_DEBUGFS)	+= ec_sys.o
 obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
 obj-$(CONFIG_ACPI_BGRT)		+= bgrt.o
 obj-$(CONFIG_ACPI_CPPC_LIB)	+= cppc_acpi.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 4d7294e..90f00b1 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..92cde45
--- /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_IORT_TABLE
+
+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_IORT_TABLE */
+static inline int
+iort_find_pci_id(struct pci_dev *pdev, u32 req_id, u32 *dev_id)
+{ return -ENXIO; }
+#endif /* CONFIG_IORT_TABLE */
+
+#endif /* __IORT_H__ */
-- 
1.9.1

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

* [PATCH V3 07/10] ARM64, ACPI, PCI: I/O Remapping Table (IORT) initial support.
@ 2016-01-19 13:11   ` Tomasz Nowicki
  0 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-01-19 13:11 UTC (permalink / raw)
  To: marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm,
	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 5eef4cb..c3664be 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_DEBUGGER
 	bool "AML debugger interface (EXPERIMENTAL)"
 	select ACPI_DEBUG
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 675eaf3..96b3183 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -79,6 +79,7 @@ obj-$(CONFIG_ACPI_EC_DEBUGFS)	+= ec_sys.o
 obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
 obj-$(CONFIG_ACPI_BGRT)		+= bgrt.o
 obj-$(CONFIG_ACPI_CPPC_LIB)	+= cppc_acpi.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 4d7294e..90f00b1 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..92cde45
--- /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_IORT_TABLE
+
+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_IORT_TABLE */
+static inline int
+iort_find_pci_id(struct pci_dev *pdev, u32 req_id, u32 *dev_id)
+{ return -ENXIO; }
+#endif /* CONFIG_IORT_TABLE */
+
+#endif /* __IORT_H__ */
-- 
1.9.1

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

* [PATCH V3 07/10] ARM64, ACPI, PCI: I/O Remapping Table (IORT) initial support.
@ 2016-01-19 13:11   ` Tomasz Nowicki
  0 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-01-19 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

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 5eef4cb..c3664be 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_DEBUGGER
 	bool "AML debugger interface (EXPERIMENTAL)"
 	select ACPI_DEBUG
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 675eaf3..96b3183 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -79,6 +79,7 @@ obj-$(CONFIG_ACPI_EC_DEBUGFS)	+= ec_sys.o
 obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
 obj-$(CONFIG_ACPI_BGRT)		+= bgrt.o
 obj-$(CONFIG_ACPI_CPPC_LIB)	+= cppc_acpi.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 4d7294e..90f00b1 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..92cde45
--- /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_IORT_TABLE
+
+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_IORT_TABLE */
+static inline int
+iort_find_pci_id(struct pci_dev *pdev, u32 req_id, u32 *dev_id)
+{ return -ENXIO; }
+#endif /* CONFIG_IORT_TABLE */
+
+#endif /* __IORT_H__ */
-- 
1.9.1

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

* [PATCH V3 08/10] irqchip, gicv3, its: Probe ITS in the ACPI way.
  2016-01-19 13:11 ` Tomasz Nowicki
@ 2016-01-19 13:11   ` Tomasz Nowicki
  -1 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-01-19 13:11 UTC (permalink / raw)
  To: marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm,
	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 | 57 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 56 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index fecb7a6..42f378a 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -15,10 +15,13 @@
  * 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/irqdomain.h>
+#include <linux/iort.h>
 #include <linux/log2.h>
 #include <linux/mm.h>
 #include <linux/msi.h>
@@ -1272,6 +1275,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;
 	}
@@ -1594,6 +1602,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",	},
 	{},
@@ -1610,7 +1664,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] 71+ messages in thread

* [PATCH V3 08/10] irqchip, gicv3, its: Probe ITS in the ACPI way.
@ 2016-01-19 13:11   ` Tomasz Nowicki
  0 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-01-19 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

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 | 57 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 56 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index fecb7a6..42f378a 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -15,10 +15,13 @@
  * 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/irqdomain.h>
+#include <linux/iort.h>
 #include <linux/log2.h>
 #include <linux/mm.h>
 #include <linux/msi.h>
@@ -1272,6 +1275,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;
 	}
@@ -1594,6 +1602,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",	},
 	{},
@@ -1610,7 +1664,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] 71+ messages in thread

* [PATCH V3 09/10] acpi, gicv3, msi: Factor out code that might be reused for ACPI equivalent.
  2016-01-19 13:11 ` Tomasz Nowicki
@ 2016-01-19 13:11   ` Tomasz Nowicki
  -1 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-01-19 13:11 UTC (permalink / raw)
  To: marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm,
	Tomasz Nowicki

Firmware agnostic code lands in separate function which do necessary
domain initialization based on unique 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 aee60ed..06165cb 100644
--- a/drivers/irqchip/irq-gic-v3-its-pci-msi.c
+++ b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
@@ -106,34 +106,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] 71+ messages in thread

* [PATCH V3 09/10] acpi, gicv3, msi: Factor out code that might be reused for ACPI equivalent.
@ 2016-01-19 13:11   ` Tomasz Nowicki
  0 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-01-19 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

Firmware agnostic code lands in separate function which do necessary
domain initialization based on unique 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 aee60ed..06165cb 100644
--- a/drivers/irqchip/irq-gic-v3-its-pci-msi.c
+++ b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
@@ -106,34 +106,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] 71+ messages in thread

* [PATCH V3 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization.
  2016-01-19 13:11 ` Tomasz Nowicki
@ 2016-01-19 13:11   ` Tomasz Nowicki
  -1 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-01-19 13:11 UTC (permalink / raw)
  To: marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm,
	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 | 44 +++++++++++++++++++++++++++++++-
 drivers/irqchip/irq-gic-v3.c             |  3 +--
 drivers/pci/msi.c                        |  3 +++
 3 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its-pci-msi.c b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
index 06165cb..7f0a958 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>
@@ -143,10 +145,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 995b7251..fee635e 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -871,8 +871,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();
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 7eaa4c8..6ced37b 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -18,6 +18,7 @@
 #include <linux/smp.h>
 #include <linux/errno.h>
 #include <linux/io.h>
+#include <linux/iort.h>
 #include <linux/slab.h>
 #include <linux/irqdomain.h>
 #include <linux/of_irq.h>
@@ -1366,6 +1367,8 @@ u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, struct pci_dev *pdev)
 	of_node = irq_domain_get_of_node(domain);
 	if (of_node)
 		rid = of_msi_map_rid(&pdev->dev, of_node, rid);
+	else
+		iort_find_pci_id(pdev, rid, &rid);
 
 	return rid;
 }
-- 
1.9.1

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

* [PATCH V3 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization.
@ 2016-01-19 13:11   ` Tomasz Nowicki
  0 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-01-19 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

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 | 44 +++++++++++++++++++++++++++++++-
 drivers/irqchip/irq-gic-v3.c             |  3 +--
 drivers/pci/msi.c                        |  3 +++
 3 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its-pci-msi.c b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
index 06165cb..7f0a958 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>
@@ -143,10 +145,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 at 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 at 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 995b7251..fee635e 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -871,8 +871,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();
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 7eaa4c8..6ced37b 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -18,6 +18,7 @@
 #include <linux/smp.h>
 #include <linux/errno.h>
 #include <linux/io.h>
+#include <linux/iort.h>
 #include <linux/slab.h>
 #include <linux/irqdomain.h>
 #include <linux/of_irq.h>
@@ -1366,6 +1367,8 @@ u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, struct pci_dev *pdev)
 	of_node = irq_domain_get_of_node(domain);
 	if (of_node)
 		rid = of_msi_map_rid(&pdev->dev, of_node, rid);
+	else
+		iort_find_pci_id(pdev, rid, &rid);
 
 	return rid;
 }
-- 
1.9.1

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

* Re: [PATCH V3 08/10] irqchip, gicv3, its: Probe ITS in the ACPI way.
  2016-01-19 13:11   ` Tomasz Nowicki
  (?)
@ 2016-01-19 18:04     ` kbuild test robot
  -1 siblings, 0 replies; 71+ messages in thread
From: kbuild test robot @ 2016-01-19 18:04 UTC (permalink / raw)
  Cc: kbuild-all, marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit,
	mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm,
	Tomasz Nowicki

[-- Attachment #1: Type: text/plain, Size: 1661 bytes --]

Hi Tomasz,

[auto build test ERROR on v4.4-rc8]
[cannot apply to tip/irq/core next-20160119]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Tomasz-Nowicki/Introduce-ACPI-world-to-GICv3-ITS-irqchip/20160119-211652
config: arm64-allmodconfig (attached as .config)
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm64 

All errors (new ones prefixed by >>):

   drivers/irqchip/irq-gic-v3-its.c: In function 'its_irq_gic_domain_alloc':
>> drivers/irqchip/irq-gic-v3-its.c:1278:2: error: implicit declaration of function 'is_fwnode_irqchip' [-Werror=implicit-function-declaration]
     } else if (is_fwnode_irqchip(domain->parent->fwnode)) {
     ^
   cc1: some warnings being treated as errors

vim +/is_fwnode_irqchip +1278 drivers/irqchip/irq-gic-v3-its.c

  1272		if (irq_domain_get_of_node(domain->parent)) {
  1273			fwspec.fwnode = domain->parent->fwnode;
  1274			fwspec.param_count = 3;
  1275			fwspec.param[0] = GIC_IRQ_TYPE_LPI;
  1276			fwspec.param[1] = hwirq;
  1277			fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
> 1278		} else if (is_fwnode_irqchip(domain->parent->fwnode)) {
  1279			fwspec.fwnode = domain->parent->fwnode;
  1280			fwspec.param_count = 2;
  1281			fwspec.param[0] = hwirq;

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 46675 bytes --]

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

* Re: [PATCH V3 08/10] irqchip, gicv3, its: Probe ITS in the ACPI way.
@ 2016-01-19 18:04     ` kbuild test robot
  0 siblings, 0 replies; 71+ messages in thread
From: kbuild test robot @ 2016-01-19 18:04 UTC (permalink / raw)
  To: Tomasz Nowicki
  Cc: kbuild-all, marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit,
	mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm,
	Tomasz Nowicki

[-- Attachment #1: Type: text/plain, Size: 1661 bytes --]

Hi Tomasz,

[auto build test ERROR on v4.4-rc8]
[cannot apply to tip/irq/core next-20160119]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Tomasz-Nowicki/Introduce-ACPI-world-to-GICv3-ITS-irqchip/20160119-211652
config: arm64-allmodconfig (attached as .config)
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm64 

All errors (new ones prefixed by >>):

   drivers/irqchip/irq-gic-v3-its.c: In function 'its_irq_gic_domain_alloc':
>> drivers/irqchip/irq-gic-v3-its.c:1278:2: error: implicit declaration of function 'is_fwnode_irqchip' [-Werror=implicit-function-declaration]
     } else if (is_fwnode_irqchip(domain->parent->fwnode)) {
     ^
   cc1: some warnings being treated as errors

vim +/is_fwnode_irqchip +1278 drivers/irqchip/irq-gic-v3-its.c

  1272		if (irq_domain_get_of_node(domain->parent)) {
  1273			fwspec.fwnode = domain->parent->fwnode;
  1274			fwspec.param_count = 3;
  1275			fwspec.param[0] = GIC_IRQ_TYPE_LPI;
  1276			fwspec.param[1] = hwirq;
  1277			fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
> 1278		} else if (is_fwnode_irqchip(domain->parent->fwnode)) {
  1279			fwspec.fwnode = domain->parent->fwnode;
  1280			fwspec.param_count = 2;
  1281			fwspec.param[0] = hwirq;

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 46675 bytes --]

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

* [PATCH V3 08/10] irqchip, gicv3, its: Probe ITS in the ACPI way.
@ 2016-01-19 18:04     ` kbuild test robot
  0 siblings, 0 replies; 71+ messages in thread
From: kbuild test robot @ 2016-01-19 18:04 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Tomasz,

[auto build test ERROR on v4.4-rc8]
[cannot apply to tip/irq/core next-20160119]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Tomasz-Nowicki/Introduce-ACPI-world-to-GICv3-ITS-irqchip/20160119-211652
config: arm64-allmodconfig (attached as .config)
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm64 

All errors (new ones prefixed by >>):

   drivers/irqchip/irq-gic-v3-its.c: In function 'its_irq_gic_domain_alloc':
>> drivers/irqchip/irq-gic-v3-its.c:1278:2: error: implicit declaration of function 'is_fwnode_irqchip' [-Werror=implicit-function-declaration]
     } else if (is_fwnode_irqchip(domain->parent->fwnode)) {
     ^
   cc1: some warnings being treated as errors

vim +/is_fwnode_irqchip +1278 drivers/irqchip/irq-gic-v3-its.c

  1272		if (irq_domain_get_of_node(domain->parent)) {
  1273			fwspec.fwnode = domain->parent->fwnode;
  1274			fwspec.param_count = 3;
  1275			fwspec.param[0] = GIC_IRQ_TYPE_LPI;
  1276			fwspec.param[1] = hwirq;
  1277			fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
> 1278		} else if (is_fwnode_irqchip(domain->parent->fwnode)) {
  1279			fwspec.fwnode = domain->parent->fwnode;
  1280			fwspec.param_count = 2;
  1281			fwspec.param[0] = hwirq;

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/octet-stream
Size: 46675 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160120/3b84bc2b/attachment-0001.obj>

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

* Re: [PATCH V3 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization.
  2016-01-19 13:11   ` Tomasz Nowicki
  (?)
@ 2016-01-19 18:26     ` kbuild test robot
  -1 siblings, 0 replies; 71+ messages in thread
From: kbuild test robot @ 2016-01-19 18:26 UTC (permalink / raw)
  Cc: kbuild-all, marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit,
	mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm,
	Tomasz Nowicki

[-- Attachment #1: Type: text/plain, Size: 1572 bytes --]

Hi Tomasz,

[auto build test ERROR on v4.4-rc8]
[cannot apply to tip/irq/core next-20160119]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Tomasz-Nowicki/Introduce-ACPI-world-to-GICv3-ITS-irqchip/20160119-211652
config: arm64-allmodconfig (attached as .config)
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm64 

All errors (new ones prefixed by >>):

   drivers/irqchip/irq-gic-v3-its-pci-msi.c: In function 'its_pci_msi_parse_madt':
>> drivers/irqchip/irq-gic-v3-its-pci-msi.c:168:2: error: implicit declaration of function 'pci_msi_register_fwnode_provider' [-Werror=implicit-function-declaration]
     pci_msi_register_fwnode_provider(&iort_find_pci_domain_token);
     ^
   cc1: some warnings being treated as errors

vim +/pci_msi_register_fwnode_provider +168 drivers/irqchip/irq-gic-v3-its-pci-msi.c

   162			return 0;
   163		}
   164	
   165		if (its_pci_msi_init_one(domain_handle))
   166			return 0;
   167	
 > 168		pci_msi_register_fwnode_provider(&iort_find_pci_domain_token);
   169		pr_info("PCI/MSI: ITS@0x%lx domain created\n",
   170			(long)its_entry->base_address);
   171		return 0;

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 46675 bytes --]

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

* Re: [PATCH V3 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization.
@ 2016-01-19 18:26     ` kbuild test robot
  0 siblings, 0 replies; 71+ messages in thread
From: kbuild test robot @ 2016-01-19 18:26 UTC (permalink / raw)
  To: Tomasz Nowicki
  Cc: kbuild-all, marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit,
	mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm,
	Tomasz Nowicki

[-- Attachment #1: Type: text/plain, Size: 1572 bytes --]

Hi Tomasz,

[auto build test ERROR on v4.4-rc8]
[cannot apply to tip/irq/core next-20160119]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Tomasz-Nowicki/Introduce-ACPI-world-to-GICv3-ITS-irqchip/20160119-211652
config: arm64-allmodconfig (attached as .config)
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm64 

All errors (new ones prefixed by >>):

   drivers/irqchip/irq-gic-v3-its-pci-msi.c: In function 'its_pci_msi_parse_madt':
>> drivers/irqchip/irq-gic-v3-its-pci-msi.c:168:2: error: implicit declaration of function 'pci_msi_register_fwnode_provider' [-Werror=implicit-function-declaration]
     pci_msi_register_fwnode_provider(&iort_find_pci_domain_token);
     ^
   cc1: some warnings being treated as errors

vim +/pci_msi_register_fwnode_provider +168 drivers/irqchip/irq-gic-v3-its-pci-msi.c

   162			return 0;
   163		}
   164	
   165		if (its_pci_msi_init_one(domain_handle))
   166			return 0;
   167	
 > 168		pci_msi_register_fwnode_provider(&iort_find_pci_domain_token);
   169		pr_info("PCI/MSI: ITS@0x%lx domain created\n",
   170			(long)its_entry->base_address);
   171		return 0;

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 46675 bytes --]

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

* [PATCH V3 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization.
@ 2016-01-19 18:26     ` kbuild test robot
  0 siblings, 0 replies; 71+ messages in thread
From: kbuild test robot @ 2016-01-19 18:26 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Tomasz,

[auto build test ERROR on v4.4-rc8]
[cannot apply to tip/irq/core next-20160119]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Tomasz-Nowicki/Introduce-ACPI-world-to-GICv3-ITS-irqchip/20160119-211652
config: arm64-allmodconfig (attached as .config)
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm64 

All errors (new ones prefixed by >>):

   drivers/irqchip/irq-gic-v3-its-pci-msi.c: In function 'its_pci_msi_parse_madt':
>> drivers/irqchip/irq-gic-v3-its-pci-msi.c:168:2: error: implicit declaration of function 'pci_msi_register_fwnode_provider' [-Werror=implicit-function-declaration]
     pci_msi_register_fwnode_provider(&iort_find_pci_domain_token);
     ^
   cc1: some warnings being treated as errors

vim +/pci_msi_register_fwnode_provider +168 drivers/irqchip/irq-gic-v3-its-pci-msi.c

   162			return 0;
   163		}
   164	
   165		if (its_pci_msi_init_one(domain_handle))
   166			return 0;
   167	
 > 168		pci_msi_register_fwnode_provider(&iort_find_pci_domain_token);
   169		pr_info("PCI/MSI: ITS at 0x%lx domain created\n",
   170			(long)its_entry->base_address);
   171		return 0;

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/octet-stream
Size: 46675 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160120/7b83b434/attachment-0001.obj>

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

* Re: [PATCH V3 00/10] Introduce ACPI world to GICv3 & ITS irqchip
  2016-01-19 13:11 ` Tomasz Nowicki
@ 2016-01-22 21:56   ` Christopher Covington
  -1 siblings, 0 replies; 71+ messages in thread
From: Christopher Covington @ 2016-01-22 21:56 UTC (permalink / raw)
  To: Tomasz Nowicki, marc.zyngier, tglx, jason, rjw,
	lorenzo.pieralisi, robert.richter, shijie.huang, guohanjun,
	Suravee.Suthikulpanit
  Cc: graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, ddaney.cavm, mw, linux-arm-kernel

On 01/19/16 08:11, Tomasz Nowicki wrote:
> Patches base on Suravee's ACPI GICv2m support:
> https://lkml.org/lkml/2015/12/10/475
> 
> The following git branch contains submitted patches along with
> the useful patches from the test point of view (mainly ACPI ARM64 PCI support).
> https://github.com/semihalf-nowicki-tomasz/linux.git (gicv3-its-acpi-v3)
> 
> Series has been tested on Cavium ThunderX server.

Thanks Tomasz. Looks good on my Qualcomm Technologies QDF2xxx server.

Tested-by: Christopher Covington <cov@codeaurora.org>

-- 
Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* [PATCH V3 00/10] Introduce ACPI world to GICv3 & ITS irqchip
@ 2016-01-22 21:56   ` Christopher Covington
  0 siblings, 0 replies; 71+ messages in thread
From: Christopher Covington @ 2016-01-22 21:56 UTC (permalink / raw)
  To: linux-arm-kernel

On 01/19/16 08:11, Tomasz Nowicki wrote:
> Patches base on Suravee's ACPI GICv2m support:
> https://lkml.org/lkml/2015/12/10/475
> 
> The following git branch contains submitted patches along with
> the useful patches from the test point of view (mainly ACPI ARM64 PCI support).
> https://github.com/semihalf-nowicki-tomasz/linux.git (gicv3-its-acpi-v3)
> 
> Series has been tested on Cavium ThunderX server.

Thanks Tomasz. Looks good on my Qualcomm Technologies QDF2xxx server.

Tested-by: Christopher Covington <cov@codeaurora.org>

-- 
Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH V3 00/10] Introduce ACPI world to GICv3 & ITS irqchip
  2016-01-19 13:11 ` Tomasz Nowicki
  (?)
@ 2016-01-22 23:06   ` Robert Richter
  -1 siblings, 0 replies; 71+ messages in thread
From: Robert Richter @ 2016-01-22 23:06 UTC (permalink / raw)
  To: Tomasz Nowicki
  Cc: lorenzo.pieralisi, ddaney.cavm, jason, graeme.gregory,
	marc.zyngier, Catalin.Marinas, rjw, linux-kernel, will.deacon,
	linux-acpi, hanjun.guo, Suravee.Suthikulpanit, guohanjun,
	shijie.huang, tglx, mw, linux-arm-kernel

On 19.01.16 14:11:13, Tomasz Nowicki wrote:
> Patches base on Suravee's ACPI GICv2m support:
> https://lkml.org/lkml/2015/12/10/475
> 
> The following git branch contains submitted patches along with
> the useful patches from the test point of view (mainly ACPI ARM64 PCI support).
> https://github.com/semihalf-nowicki-tomasz/linux.git (gicv3-its-acpi-v3)
> 
> Series has been tested on Cavium ThunderX server.
> 
> v2 -> v3
> - rebased on top of 4.4
> - fixes and improvements for redistributor init via GICC structures
> - fixes as per kbuild reports
> 
> v1 -> v2
> - rebased on top of 4.4-rc4
> - use pci_msi_domain_get_msi_rid for requester ID to device ID translation
> 
> 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 |  85 ++++++--
>  drivers/irqchip/irq-gic-v3-its.c         | 143 +++++++++----
>  drivers/irqchip/irq-gic-v3.c             | 344 ++++++++++++++++++++++++++-----
>  drivers/pci/msi.c                        |   3 +
>  include/linux/iort.h                     |  38 ++++
>  include/linux/irqchip/arm-gic-v3.h       |   2 +-
>  10 files changed, 845 insertions(+), 101 deletions(-)
>  create mode 100644 drivers/acpi/iort.c
>  create mode 100644 include/linux/iort.h

Tested on various ThunderX single and dual node systems.

Tested-by: Robert Richter <rrichter@cavium.com>

Thanks Tomasz,

-Robert

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

* Re: [PATCH V3 00/10] Introduce ACPI world to GICv3 & ITS irqchip
@ 2016-01-22 23:06   ` Robert Richter
  0 siblings, 0 replies; 71+ messages in thread
From: Robert Richter @ 2016-01-22 23:06 UTC (permalink / raw)
  To: Tomasz Nowicki
  Cc: marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi, shijie.huang,
	guohanjun, Suravee.Suthikulpanit, mw, graeme.gregory,
	Catalin.Marinas, will.deacon, linux-kernel, linux-acpi,
	hanjun.guo, linux-arm-kernel, ddaney.cavm

On 19.01.16 14:11:13, Tomasz Nowicki wrote:
> Patches base on Suravee's ACPI GICv2m support:
> https://lkml.org/lkml/2015/12/10/475
> 
> The following git branch contains submitted patches along with
> the useful patches from the test point of view (mainly ACPI ARM64 PCI support).
> https://github.com/semihalf-nowicki-tomasz/linux.git (gicv3-its-acpi-v3)
> 
> Series has been tested on Cavium ThunderX server.
> 
> v2 -> v3
> - rebased on top of 4.4
> - fixes and improvements for redistributor init via GICC structures
> - fixes as per kbuild reports
> 
> v1 -> v2
> - rebased on top of 4.4-rc4
> - use pci_msi_domain_get_msi_rid for requester ID to device ID translation
> 
> 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 |  85 ++++++--
>  drivers/irqchip/irq-gic-v3-its.c         | 143 +++++++++----
>  drivers/irqchip/irq-gic-v3.c             | 344 ++++++++++++++++++++++++++-----
>  drivers/pci/msi.c                        |   3 +
>  include/linux/iort.h                     |  38 ++++
>  include/linux/irqchip/arm-gic-v3.h       |   2 +-
>  10 files changed, 845 insertions(+), 101 deletions(-)
>  create mode 100644 drivers/acpi/iort.c
>  create mode 100644 include/linux/iort.h

Tested on various ThunderX single and dual node systems.

Tested-by: Robert Richter <rrichter@cavium.com>

Thanks Tomasz,

-Robert

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

* [PATCH V3 00/10] Introduce ACPI world to GICv3 & ITS irqchip
@ 2016-01-22 23:06   ` Robert Richter
  0 siblings, 0 replies; 71+ messages in thread
From: Robert Richter @ 2016-01-22 23:06 UTC (permalink / raw)
  To: linux-arm-kernel

On 19.01.16 14:11:13, Tomasz Nowicki wrote:
> Patches base on Suravee's ACPI GICv2m support:
> https://lkml.org/lkml/2015/12/10/475
> 
> The following git branch contains submitted patches along with
> the useful patches from the test point of view (mainly ACPI ARM64 PCI support).
> https://github.com/semihalf-nowicki-tomasz/linux.git (gicv3-its-acpi-v3)
> 
> Series has been tested on Cavium ThunderX server.
> 
> v2 -> v3
> - rebased on top of 4.4
> - fixes and improvements for redistributor init via GICC structures
> - fixes as per kbuild reports
> 
> v1 -> v2
> - rebased on top of 4.4-rc4
> - use pci_msi_domain_get_msi_rid for requester ID to device ID translation
> 
> 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 |  85 ++++++--
>  drivers/irqchip/irq-gic-v3-its.c         | 143 +++++++++----
>  drivers/irqchip/irq-gic-v3.c             | 344 ++++++++++++++++++++++++++-----
>  drivers/pci/msi.c                        |   3 +
>  include/linux/iort.h                     |  38 ++++
>  include/linux/irqchip/arm-gic-v3.h       |   2 +-
>  10 files changed, 845 insertions(+), 101 deletions(-)
>  create mode 100644 drivers/acpi/iort.c
>  create mode 100644 include/linux/iort.h

Tested on various ThunderX single and dual node systems.

Tested-by: Robert Richter <rrichter@cavium.com>

Thanks Tomasz,

-Robert

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

* Re: [PATCH V3 00/10] Introduce ACPI world to GICv3 & ITS irqchip
  2016-01-19 13:11 ` Tomasz Nowicki
@ 2016-02-10  8:55   ` Tomasz Nowicki
  -1 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-02-10  8:55 UTC (permalink / raw)
  To: marc.zyngier, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm

On 19.01.2016 14:11, Tomasz Nowicki wrote:
> Patches base on Suravee's ACPI GICv2m support:
> https://lkml.org/lkml/2015/12/10/475
>
> The following git branch contains submitted patches along with
> the useful patches from the test point of view (mainly ACPI ARM64 PCI support).
> https://github.com/semihalf-nowicki-tomasz/linux.git (gicv3-its-acpi-v3)
>

Hi Marc,

Can you please have a look at this series. I think your previous 
concerns have been addressed.

Tomasz

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

* [PATCH V3 00/10] Introduce ACPI world to GICv3 & ITS irqchip
@ 2016-02-10  8:55   ` Tomasz Nowicki
  0 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-02-10  8:55 UTC (permalink / raw)
  To: linux-arm-kernel

On 19.01.2016 14:11, Tomasz Nowicki wrote:
> Patches base on Suravee's ACPI GICv2m support:
> https://lkml.org/lkml/2015/12/10/475
>
> The following git branch contains submitted patches along with
> the useful patches from the test point of view (mainly ACPI ARM64 PCI support).
> https://github.com/semihalf-nowicki-tomasz/linux.git (gicv3-its-acpi-v3)
>

Hi Marc,

Can you please have a look at this series. I think your previous 
concerns have been addressed.

Tomasz

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

* Re: [PATCH V3 01/10] irqchip / GICv3: Refactor gic_of_init() for GICv3 driver
  2016-01-19 13:11   ` Tomasz Nowicki
@ 2016-02-10  9:50     ` Marc Zyngier
  -1 siblings, 0 replies; 71+ messages in thread
From: Marc Zyngier @ 2016-02-10  9:50 UTC (permalink / raw)
  To: Tomasz Nowicki, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm,
	Tomasz Nowicki

On 19/01/16 13:11, Tomasz Nowicki wrote:
> 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>

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

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

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

* [PATCH V3 01/10] irqchip / GICv3: Refactor gic_of_init() for GICv3 driver
@ 2016-02-10  9:50     ` Marc Zyngier
  0 siblings, 0 replies; 71+ messages in thread
From: Marc Zyngier @ 2016-02-10  9:50 UTC (permalink / raw)
  To: linux-arm-kernel

On 19/01/16 13:11, Tomasz Nowicki wrote:
> 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>

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

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

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

* Re: [PATCH V3 02/10] irqchip / GICv3: Add ACPI support for GICv3+ initialization
  2016-01-19 13:11   ` Tomasz Nowicki
@ 2016-02-10  9:55     ` Marc Zyngier
  -1 siblings, 0 replies; 71+ messages in thread
From: Marc Zyngier @ 2016-02-10  9:55 UTC (permalink / raw)
  To: Tomasz Nowicki, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm

On 19/01/16 13:11, Tomasz Nowicki wrote:
> 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>

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

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

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

* [PATCH V3 02/10] irqchip / GICv3: Add ACPI support for GICv3+ initialization
@ 2016-02-10  9:55     ` Marc Zyngier
  0 siblings, 0 replies; 71+ messages in thread
From: Marc Zyngier @ 2016-02-10  9:55 UTC (permalink / raw)
  To: linux-arm-kernel

On 19/01/16 13:11, Tomasz Nowicki wrote:
> 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>

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

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

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

* Re: [PATCH V3 03/10] irqchip,GICv3,ACPI: Add redistributor support via GICC structures.
  2016-01-19 13:11   ` [PATCH V3 03/10] irqchip, GICv3, ACPI: " Tomasz Nowicki
@ 2016-02-10 10:16     ` Marc Zyngier
  -1 siblings, 0 replies; 71+ messages in thread
From: Marc Zyngier @ 2016-02-10 10:16 UTC (permalink / raw)
  To: Tomasz Nowicki, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm

On 19/01/16 13:11, Tomasz Nowicki wrote:
> Following ACPI spec:
> On systems supporting GICv3 and above, GICR Base Address in MADT GICC
> structure holds the 64-bit physical address of the associated Redistributor.
> If all of the GIC Redistributors are in the always-on power domain,
> GICR structures should be used to describe the Redistributors instead,
> and this field must be set to 0.
> 
> It means that we have two ways to initialize registirbutors map.
> 1. via GICD structure which can accommodate many redistributors as a region
> 2. via GICC which is able to describe single redistributor
> 
> This patch is going to add support for second option.
> Considering redistributors, GICD and GICC subtables have be mutually
> exclusive. While discovering and mapping redistributor, we need to know
> its size in advance. For the GICC case, redistributor can be in
> a power-domain that is off, thus we cannot relay on GICR TYPER register.
> Therefore, we get GIC version from distributor register and map 2xSZ_64K
> for GICv3 and 4xSZ_64K for GICv4.
> 
> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
> Signed-off-by: Tomasz Nowicki <tn@semihalf.com>

This is incredibly convoluted, but I'm not sure there is a better way
given the current ACPI API. Still, it hurts.

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

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

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

* [PATCH V3 03/10] irqchip,GICv3,ACPI: Add redistributor support via GICC structures.
@ 2016-02-10 10:16     ` Marc Zyngier
  0 siblings, 0 replies; 71+ messages in thread
From: Marc Zyngier @ 2016-02-10 10:16 UTC (permalink / raw)
  To: linux-arm-kernel

On 19/01/16 13:11, Tomasz Nowicki wrote:
> Following ACPI spec:
> On systems supporting GICv3 and above, GICR Base Address in MADT GICC
> structure holds the 64-bit physical address of the associated Redistributor.
> If all of the GIC Redistributors are in the always-on power domain,
> GICR structures should be used to describe the Redistributors instead,
> and this field must be set to 0.
> 
> It means that we have two ways to initialize registirbutors map.
> 1. via GICD structure which can accommodate many redistributors as a region
> 2. via GICC which is able to describe single redistributor
> 
> This patch is going to add support for second option.
> Considering redistributors, GICD and GICC subtables have be mutually
> exclusive. While discovering and mapping redistributor, we need to know
> its size in advance. For the GICC case, redistributor can be in
> a power-domain that is off, thus we cannot relay on GICR TYPER register.
> Therefore, we get GIC version from distributor register and map 2xSZ_64K
> for GICv3 and 4xSZ_64K for GICv4.
> 
> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
> Signed-off-by: Tomasz Nowicki <tn@semihalf.com>

This is incredibly convoluted, but I'm not sure there is a better way
given the current ACPI API. Still, it hurts.

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

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

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

* Re: [PATCH V3 00/10] Introduce ACPI world to GICv3 & ITS irqchip
  2016-02-10  8:55   ` Tomasz Nowicki
  (?)
@ 2016-02-10 10:19     ` Marc Zyngier
  -1 siblings, 0 replies; 71+ messages in thread
From: Marc Zyngier @ 2016-02-10 10:19 UTC (permalink / raw)
  To: Tomasz Nowicki, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, ddaney.cavm, mw, linux-arm-kernel

Thomasz,

On 10/02/16 08:55, Tomasz Nowicki wrote:
> On 19.01.2016 14:11, Tomasz Nowicki wrote:
>> Patches base on Suravee's ACPI GICv2m support:
>> https://lkml.org/lkml/2015/12/10/475
>>
>> The following git branch contains submitted patches along with
>> the useful patches from the test point of view (mainly ACPI ARM64 PCI support).
>> https://github.com/semihalf-nowicki-tomasz/linux.git (gicv3-its-acpi-v3)
>>
> 
> Hi Marc,
> 
> Can you please have a look at this series. I think your previous 
> concerns have been addressed.

I've just acked the first 3 patches, which I believe are good to go.

The ITS support is a separate thing, mostly because it introduces a
completely new infrastructure (IORT). I'll review that separately (no
need to resend the patches though).

Thanks,

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

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

* Re: [PATCH V3 00/10] Introduce ACPI world to GICv3 & ITS irqchip
@ 2016-02-10 10:19     ` Marc Zyngier
  0 siblings, 0 replies; 71+ messages in thread
From: Marc Zyngier @ 2016-02-10 10:19 UTC (permalink / raw)
  To: Tomasz Nowicki, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm

Thomasz,

On 10/02/16 08:55, Tomasz Nowicki wrote:
> On 19.01.2016 14:11, Tomasz Nowicki wrote:
>> Patches base on Suravee's ACPI GICv2m support:
>> https://lkml.org/lkml/2015/12/10/475
>>
>> The following git branch contains submitted patches along with
>> the useful patches from the test point of view (mainly ACPI ARM64 PCI support).
>> https://github.com/semihalf-nowicki-tomasz/linux.git (gicv3-its-acpi-v3)
>>
> 
> Hi Marc,
> 
> Can you please have a look at this series. I think your previous 
> concerns have been addressed.

I've just acked the first 3 patches, which I believe are good to go.

The ITS support is a separate thing, mostly because it introduces a
completely new infrastructure (IORT). I'll review that separately (no
need to resend the patches though).

Thanks,

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

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

* [PATCH V3 00/10] Introduce ACPI world to GICv3 & ITS irqchip
@ 2016-02-10 10:19     ` Marc Zyngier
  0 siblings, 0 replies; 71+ messages in thread
From: Marc Zyngier @ 2016-02-10 10:19 UTC (permalink / raw)
  To: linux-arm-kernel

Thomasz,

On 10/02/16 08:55, Tomasz Nowicki wrote:
> On 19.01.2016 14:11, Tomasz Nowicki wrote:
>> Patches base on Suravee's ACPI GICv2m support:
>> https://lkml.org/lkml/2015/12/10/475
>>
>> The following git branch contains submitted patches along with
>> the useful patches from the test point of view (mainly ACPI ARM64 PCI support).
>> https://github.com/semihalf-nowicki-tomasz/linux.git (gicv3-its-acpi-v3)
>>
> 
> Hi Marc,
> 
> Can you please have a look at this series. I think your previous 
> concerns have been addressed.

I've just acked the first 3 patches, which I believe are good to go.

The ITS support is a separate thing, mostly because it introduces a
completely new infrastructure (IORT). I'll review that separately (no
need to resend the patches though).

Thanks,

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

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

* Re: [PATCH V3 04/10] irqchip / GICv3: remove gic root node in ITS
  2016-01-19 13:11   ` Tomasz Nowicki
@ 2016-02-10 10:25     ` Marc Zyngier
  -1 siblings, 0 replies; 71+ messages in thread
From: Marc Zyngier @ 2016-02-10 10:25 UTC (permalink / raw)
  To: Tomasz Nowicki, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm

On 19/01/16 13:11, Tomasz Nowicki wrote:
> 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>

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

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

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

* [PATCH V3 04/10] irqchip / GICv3: remove gic root node in ITS
@ 2016-02-10 10:25     ` Marc Zyngier
  0 siblings, 0 replies; 71+ messages in thread
From: Marc Zyngier @ 2016-02-10 10:25 UTC (permalink / raw)
  To: linux-arm-kernel

On 19/01/16 13:11, Tomasz Nowicki wrote:
> 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>

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

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

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

* Re: [PATCH V3 05/10] irqchip, gicv3, its: Mark its_init() and its children as __init
  2016-01-19 13:11   ` Tomasz Nowicki
@ 2016-02-10 10:30     ` Marc Zyngier
  -1 siblings, 0 replies; 71+ messages in thread
From: Marc Zyngier @ 2016-02-10 10:30 UTC (permalink / raw)
  To: Tomasz Nowicki, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm

On 19/01/16 13:11, Tomasz Nowicki wrote:
> 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>

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

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

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

* [PATCH V3 05/10] irqchip, gicv3, its: Mark its_init() and its children as __init
@ 2016-02-10 10:30     ` Marc Zyngier
  0 siblings, 0 replies; 71+ messages in thread
From: Marc Zyngier @ 2016-02-10 10:30 UTC (permalink / raw)
  To: linux-arm-kernel

On 19/01/16 13:11, Tomasz Nowicki wrote:
> 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>

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

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

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

* Re: [PATCH V3 06/10] irqchip, GICv3, ITS: Refator ITS dt init code to prepare for ACPI.
  2016-01-19 13:11   ` Tomasz Nowicki
@ 2016-02-10 10:47     ` Marc Zyngier
  -1 siblings, 0 replies; 71+ messages in thread
From: Marc Zyngier @ 2016-02-10 10:47 UTC (permalink / raw)
  To: Tomasz Nowicki, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm

On 19/01/16 13:11, Tomasz Nowicki wrote:
> Similarly to GICv3 core, we need to extract common code before adding
> ACPI support. No functional changes.
> 
> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
> Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
> ---
>  drivers/irqchip/irq-gic-v3-its.c   | 82 +++++++++++++++++++++++---------------
>  drivers/irqchip/irq-gic-v3.c       |  6 +--
>  include/linux/irqchip/arm-gic-v3.h |  2 +-
>  3 files changed, 52 insertions(+), 38 deletions(-)
> 
> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
> index 2bbed18..fecb7a6 100644
> --- a/drivers/irqchip/irq-gic-v3-its.c
> +++ b/drivers/irqchip/irq-gic-v3-its.c
> @@ -813,7 +813,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;
> @@ -868,8 +868,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);
>  			}
>  		}
>  
> @@ -878,8 +878,8 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
>  		if (alloc_pages > GITS_BASER_PAGES_MAX) {
>  			alloc_pages = GITS_BASER_PAGES_MAX;
>  			order = get_order(GITS_BASER_PAGES_MAX * psz);
> -			pr_warn("%s: Device Table too large, reduce its page order to %u (%u pages)\n",
> -				node_name, order, alloc_pages);
> +			pr_warn("ITS@0x%lx: Device Table too large, reduce its page order to %u (%u pages)\n",
> +				its->phys_base, order, alloc_pages);
>  		}
>  
>  		base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
> @@ -948,8 +948,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;
> @@ -1424,10 +1424,11 @@ static void its_enable_quirks(struct its_node *its)
>  	gic_enable_quirks(iidr, its_quirks, its);
>  }
>  
> -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,

I really question the fact that you are keeping this msi_controller
thing. Let's face it: if this is not an MSI controller, then the whole
thing is absolutely pointless.

So I'd rather you simplify the whole in a separate patch, and just don't
bother initializing the ITS if it cannot be used for MSIs.

> +				struct fwnode_handle *handler)
>  {
> -	struct resource res;
>  	struct its_node *its;
>  	void __iomem *its_base;
>  	struct irq_domain *inner_domain;
> @@ -1435,33 +1436,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");

There is some value in at least displaying the base address - think of
people writing their DT or ACPI tables. Please do not blindly remove
debugging information which is often useful on a system with multiple ITS.

>  		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) {
> @@ -1473,7 +1467,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);
> @@ -1485,7 +1479,7 @@ static int __init its_probe(struct device_node *node,
>  
>  	its_enable_quirks(its);
>  
> -	err = its_alloc_tables(node->full_name, its);
> +	err = its_alloc_tables(its);
>  	if (err)
>  		goto out_free_cmd;
>  
> @@ -1521,7 +1515,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);
> @@ -1530,7 +1524,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);
> @@ -1558,10 +1553,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;

This is where you should return early, with a message saying that this
ITS is being ignored if it doesn't have the msi-controller property.

> +
> +	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);
> @@ -1586,14 +1599,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 dd16a60..995b7251 100644
> --- a/drivers/irqchip/irq-gic-v3.c
> +++ b/drivers/irqchip/irq-gic-v3.c
> @@ -832,7 +832,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;
> @@ -872,10 +871,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 d5d798b..a40ed7d 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -332,7 +332,7 @@ struct rdists {
>  struct irq_domain;
>  struct device_node;
>  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);
>  
>  static inline bool gic_enable_sre(void)
> 

Thanks,

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

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

* [PATCH V3 06/10] irqchip, GICv3, ITS: Refator ITS dt init code to prepare for ACPI.
@ 2016-02-10 10:47     ` Marc Zyngier
  0 siblings, 0 replies; 71+ messages in thread
From: Marc Zyngier @ 2016-02-10 10:47 UTC (permalink / raw)
  To: linux-arm-kernel

On 19/01/16 13:11, Tomasz Nowicki wrote:
> Similarly to GICv3 core, we need to extract common code before adding
> ACPI support. No functional changes.
> 
> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
> Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
> ---
>  drivers/irqchip/irq-gic-v3-its.c   | 82 +++++++++++++++++++++++---------------
>  drivers/irqchip/irq-gic-v3.c       |  6 +--
>  include/linux/irqchip/arm-gic-v3.h |  2 +-
>  3 files changed, 52 insertions(+), 38 deletions(-)
> 
> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
> index 2bbed18..fecb7a6 100644
> --- a/drivers/irqchip/irq-gic-v3-its.c
> +++ b/drivers/irqchip/irq-gic-v3-its.c
> @@ -813,7 +813,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;
> @@ -868,8 +868,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 at 0x%lx: Device Table too large, reduce its page order to %u\n",
> +					its->phys_base, order);
>  			}
>  		}
>  
> @@ -878,8 +878,8 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
>  		if (alloc_pages > GITS_BASER_PAGES_MAX) {
>  			alloc_pages = GITS_BASER_PAGES_MAX;
>  			order = get_order(GITS_BASER_PAGES_MAX * psz);
> -			pr_warn("%s: Device Table too large, reduce its page order to %u (%u pages)\n",
> -				node_name, order, alloc_pages);
> +			pr_warn("ITS at 0x%lx: Device Table too large, reduce its page order to %u (%u pages)\n",
> +				its->phys_base, order, alloc_pages);
>  		}
>  
>  		base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
> @@ -948,8 +948,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 at 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;
> @@ -1424,10 +1424,11 @@ static void its_enable_quirks(struct its_node *its)
>  	gic_enable_quirks(iidr, its_quirks, its);
>  }
>  
> -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,

I really question the fact that you are keeping this msi_controller
thing. Let's face it: if this is not an MSI controller, then the whole
thing is absolutely pointless.

So I'd rather you simplify the whole in a separate patch, and just don't
bother initializing the ITS if it cannot be used for MSIs.

> +				struct fwnode_handle *handler)
>  {
> -	struct resource res;
>  	struct its_node *its;
>  	void __iomem *its_base;
>  	struct irq_domain *inner_domain;
> @@ -1435,33 +1436,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");

There is some value in at least displaying the base address - think of
people writing their DT or ACPI tables. Please do not blindly remove
debugging information which is often useful on a system with multiple ITS.

>  		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 at 0x%lx\n", (long)phys_base);
>  
>  	its = kzalloc(sizeof(*its), GFP_KERNEL);
>  	if (!its) {
> @@ -1473,7 +1467,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);
> @@ -1485,7 +1479,7 @@ static int __init its_probe(struct device_node *node,
>  
>  	its_enable_quirks(its);
>  
> -	err = its_alloc_tables(node->full_name, its);
> +	err = its_alloc_tables(its);
>  	if (err)
>  		goto out_free_cmd;
>  
> @@ -1521,7 +1515,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);
> @@ -1530,7 +1524,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);
> @@ -1558,10 +1553,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 at 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;

This is where you should return early, with a message saying that this
ITS is being ignored if it doesn't have the msi-controller property.

> +
> +	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);
> @@ -1586,14 +1599,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 dd16a60..995b7251 100644
> --- a/drivers/irqchip/irq-gic-v3.c
> +++ b/drivers/irqchip/irq-gic-v3.c
> @@ -832,7 +832,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;
> @@ -872,10 +871,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 d5d798b..a40ed7d 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -332,7 +332,7 @@ struct rdists {
>  struct irq_domain;
>  struct device_node;
>  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);
>  
>  static inline bool gic_enable_sre(void)
> 

Thanks,

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

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

* Re: [PATCH V3 08/10] irqchip, gicv3, its: Probe ITS in the ACPI way.
  2016-01-19 13:11   ` Tomasz Nowicki
@ 2016-02-10 11:46     ` Marc Zyngier
  -1 siblings, 0 replies; 71+ messages in thread
From: Marc Zyngier @ 2016-02-10 11:46 UTC (permalink / raw)
  To: Tomasz Nowicki, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm

On 19/01/16 13:11, Tomasz Nowicki wrote:
> 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 | 57 +++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 56 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
> index fecb7a6..42f378a 100644
> --- a/drivers/irqchip/irq-gic-v3-its.c
> +++ b/drivers/irqchip/irq-gic-v3-its.c
> @@ -15,10 +15,13 @@
>   * 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/irqdomain.h>
> +#include <linux/iort.h>
>  #include <linux/log2.h>
>  #include <linux/mm.h>
>  #include <linux/msi.h>
> @@ -1272,6 +1275,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;
>  	}
> @@ -1594,6 +1602,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");

-ECOPYPASTE.

> +		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);

And what if this fails?

> +	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",	},
>  	{},
> @@ -1610,7 +1664,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);

Missing braces.

>  
>  	if (list_empty(&its_nodes)) {
>  		pr_warn("ITS: No ITS available, not enabling LPIs\n");
> 

Thanks,

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

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

* [PATCH V3 08/10] irqchip, gicv3, its: Probe ITS in the ACPI way.
@ 2016-02-10 11:46     ` Marc Zyngier
  0 siblings, 0 replies; 71+ messages in thread
From: Marc Zyngier @ 2016-02-10 11:46 UTC (permalink / raw)
  To: linux-arm-kernel

On 19/01/16 13:11, Tomasz Nowicki wrote:
> 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 | 57 +++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 56 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
> index fecb7a6..42f378a 100644
> --- a/drivers/irqchip/irq-gic-v3-its.c
> +++ b/drivers/irqchip/irq-gic-v3-its.c
> @@ -15,10 +15,13 @@
>   * 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/irqdomain.h>
> +#include <linux/iort.h>
>  #include <linux/log2.h>
>  #include <linux/mm.h>
>  #include <linux/msi.h>
> @@ -1272,6 +1275,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;
>  	}
> @@ -1594,6 +1602,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");

-ECOPYPASTE.

> +		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);

And what if this fails?

> +	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",	},
>  	{},
> @@ -1610,7 +1664,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);

Missing braces.

>  
>  	if (list_empty(&its_nodes)) {
>  		pr_warn("ITS: No ITS available, not enabling LPIs\n");
> 

Thanks,

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

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

* Re: [PATCH V3 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization.
  2016-01-19 13:11   ` Tomasz Nowicki
@ 2016-02-10 12:02     ` Marc Zyngier
  -1 siblings, 0 replies; 71+ messages in thread
From: Marc Zyngier @ 2016-02-10 12:02 UTC (permalink / raw)
  To: Tomasz Nowicki, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm

On 19/01/16 13:11, 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 | 44 +++++++++++++++++++++++++++++++-
>  drivers/irqchip/irq-gic-v3.c             |  3 +--
>  drivers/pci/msi.c                        |  3 +++
>  3 files changed, 47 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/irqchip/irq-gic-v3-its-pci-msi.c b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
> index 06165cb..7f0a958 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>
> @@ -143,10 +145,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);

I'm a bit worried by this. You are registering this for each and every
ITS that gets probed (useless, but why not). But also, you're using a
hook that is designed to work at the bus level, without caring for the
actual PCI devices. That's fine for something like GICv2m, which exposes
a single domain, but I can't picture how this works when you have
devices sitting behind a single RC that talk to different ITSs.

My understanding is that IORT was behaving in a similar way the msi-map
property works, so I'm a bit puzzled here.

Can you please shed some light on that?

Thanks,

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

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

* [PATCH V3 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization.
@ 2016-02-10 12:02     ` Marc Zyngier
  0 siblings, 0 replies; 71+ messages in thread
From: Marc Zyngier @ 2016-02-10 12:02 UTC (permalink / raw)
  To: linux-arm-kernel

On 19/01/16 13:11, 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 | 44 +++++++++++++++++++++++++++++++-
>  drivers/irqchip/irq-gic-v3.c             |  3 +--
>  drivers/pci/msi.c                        |  3 +++
>  3 files changed, 47 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/irqchip/irq-gic-v3-its-pci-msi.c b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
> index 06165cb..7f0a958 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>
> @@ -143,10 +145,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 at 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);

I'm a bit worried by this. You are registering this for each and every
ITS that gets probed (useless, but why not). But also, you're using a
hook that is designed to work at the bus level, without caring for the
actual PCI devices. That's fine for something like GICv2m, which exposes
a single domain, but I can't picture how this works when you have
devices sitting behind a single RC that talk to different ITSs.

My understanding is that IORT was behaving in a similar way the msi-map
property works, so I'm a bit puzzled here.

Can you please shed some light on that?

Thanks,

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

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

* Re: [PATCH V3 00/10] Introduce ACPI world to GICv3 & ITS irqchip
  2016-01-19 13:11 ` Tomasz Nowicki
@ 2016-02-11 11:47   ` Marc Zyngier
  -1 siblings, 0 replies; 71+ messages in thread
From: Marc Zyngier @ 2016-02-11 11:47 UTC (permalink / raw)
  To: Tomasz Nowicki, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm

Thomas, Hanjun,

On 19/01/16 13:11, Tomasz Nowicki wrote:
> Patches base on Suravee's ACPI GICv2m support:
> https://lkml.org/lkml/2015/12/10/475
> 
> The following git branch contains submitted patches along with
> the useful patches from the test point of view (mainly ACPI ARM64 PCI support).
> https://github.com/semihalf-nowicki-tomasz/linux.git (gicv3-its-acpi-v3)
> 
> Series has been tested on Cavium ThunderX server.
> 
> v2 -> v3
> - rebased on top of 4.4
> - fixes and improvements for redistributor init via GICC structures
> - fixes as per kbuild reports
> 
> v1 -> v2
> - rebased on top of 4.4-rc4
> - use pci_msi_domain_get_msi_rid for requester ID to device ID translation
> 
> 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 |  85 ++++++--
>  drivers/irqchip/irq-gic-v3-its.c         | 143 +++++++++----
>  drivers/irqchip/irq-gic-v3.c             | 344 ++++++++++++++++++++++++++-----
>  drivers/pci/msi.c                        |   3 +
>  include/linux/iort.h                     |  38 ++++
>  include/linux/irqchip/arm-gic-v3.h       |   2 +-
>  10 files changed, 845 insertions(+), 101 deletions(-)
>  create mode 100644 drivers/acpi/iort.c
>  create mode 100644 include/linux/iort.h
> 

I've so far queued the first 5 patches of this series (basic ACPI
support for GICv3 and associated cleanups). The rest needs additional
discussion (see my comments on patch 10), and requires some form of Ack
from the ACPI maintainers (at least for patch 7).

Thanks,

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

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

* [PATCH V3 00/10] Introduce ACPI world to GICv3 & ITS irqchip
@ 2016-02-11 11:47   ` Marc Zyngier
  0 siblings, 0 replies; 71+ messages in thread
From: Marc Zyngier @ 2016-02-11 11:47 UTC (permalink / raw)
  To: linux-arm-kernel

Thomas, Hanjun,

On 19/01/16 13:11, Tomasz Nowicki wrote:
> Patches base on Suravee's ACPI GICv2m support:
> https://lkml.org/lkml/2015/12/10/475
> 
> The following git branch contains submitted patches along with
> the useful patches from the test point of view (mainly ACPI ARM64 PCI support).
> https://github.com/semihalf-nowicki-tomasz/linux.git (gicv3-its-acpi-v3)
> 
> Series has been tested on Cavium ThunderX server.
> 
> v2 -> v3
> - rebased on top of 4.4
> - fixes and improvements for redistributor init via GICC structures
> - fixes as per kbuild reports
> 
> v1 -> v2
> - rebased on top of 4.4-rc4
> - use pci_msi_domain_get_msi_rid for requester ID to device ID translation
> 
> 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 |  85 ++++++--
>  drivers/irqchip/irq-gic-v3-its.c         | 143 +++++++++----
>  drivers/irqchip/irq-gic-v3.c             | 344 ++++++++++++++++++++++++++-----
>  drivers/pci/msi.c                        |   3 +
>  include/linux/iort.h                     |  38 ++++
>  include/linux/irqchip/arm-gic-v3.h       |   2 +-
>  10 files changed, 845 insertions(+), 101 deletions(-)
>  create mode 100644 drivers/acpi/iort.c
>  create mode 100644 include/linux/iort.h
> 

I've so far queued the first 5 patches of this series (basic ACPI
support for GICv3 and associated cleanups). The rest needs additional
discussion (see my comments on patch 10), and requires some form of Ack
from the ACPI maintainers (at least for patch 7).

Thanks,

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

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

* Re: [PATCH V3 00/10] Introduce ACPI world to GICv3 & ITS irqchip
  2016-02-11 11:47   ` Marc Zyngier
@ 2016-02-11 14:02     ` Tomasz Nowicki
  -1 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-02-11 14:02 UTC (permalink / raw)
  To: Marc Zyngier, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm

On 11.02.2016 12:47, Marc Zyngier wrote:
> Thomas, Hanjun,
>
> On 19/01/16 13:11, Tomasz Nowicki wrote:
>> Patches base on Suravee's ACPI GICv2m support:
>> https://lkml.org/lkml/2015/12/10/475
>>
>> The following git branch contains submitted patches along with
>> the useful patches from the test point of view (mainly ACPI ARM64 PCI support).
>> https://github.com/semihalf-nowicki-tomasz/linux.git (gicv3-its-acpi-v3)
>>
>> Series has been tested on Cavium ThunderX server.
>>
>> v2 -> v3
>> - rebased on top of 4.4
>> - fixes and improvements for redistributor init via GICC structures
>> - fixes as per kbuild reports
>>
>> v1 -> v2
>> - rebased on top of 4.4-rc4
>> - use pci_msi_domain_get_msi_rid for requester ID to device ID translation
>>
>> 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 |  85 ++++++--
>>   drivers/irqchip/irq-gic-v3-its.c         | 143 +++++++++----
>>   drivers/irqchip/irq-gic-v3.c             | 344 ++++++++++++++++++++++++++-----
>>   drivers/pci/msi.c                        |   3 +
>>   include/linux/iort.h                     |  38 ++++
>>   include/linux/irqchip/arm-gic-v3.h       |   2 +-
>>   10 files changed, 845 insertions(+), 101 deletions(-)
>>   create mode 100644 drivers/acpi/iort.c
>>   create mode 100644 include/linux/iort.h
>>
>
> I've so far queued the first 5 patches of this series (basic ACPI
> support for GICv3 and associated cleanups). The rest needs additional
> discussion (see my comments on patch 10), and requires some form of Ack
> from the ACPI maintainers (at least for patch 7).
>
Thanks Marc!

I will respond to the rest of your comments shortly.

Tomasz

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

* [PATCH V3 00/10] Introduce ACPI world to GICv3 & ITS irqchip
@ 2016-02-11 14:02     ` Tomasz Nowicki
  0 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-02-11 14:02 UTC (permalink / raw)
  To: linux-arm-kernel

On 11.02.2016 12:47, Marc Zyngier wrote:
> Thomas, Hanjun,
>
> On 19/01/16 13:11, Tomasz Nowicki wrote:
>> Patches base on Suravee's ACPI GICv2m support:
>> https://lkml.org/lkml/2015/12/10/475
>>
>> The following git branch contains submitted patches along with
>> the useful patches from the test point of view (mainly ACPI ARM64 PCI support).
>> https://github.com/semihalf-nowicki-tomasz/linux.git (gicv3-its-acpi-v3)
>>
>> Series has been tested on Cavium ThunderX server.
>>
>> v2 -> v3
>> - rebased on top of 4.4
>> - fixes and improvements for redistributor init via GICC structures
>> - fixes as per kbuild reports
>>
>> v1 -> v2
>> - rebased on top of 4.4-rc4
>> - use pci_msi_domain_get_msi_rid for requester ID to device ID translation
>>
>> 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 |  85 ++++++--
>>   drivers/irqchip/irq-gic-v3-its.c         | 143 +++++++++----
>>   drivers/irqchip/irq-gic-v3.c             | 344 ++++++++++++++++++++++++++-----
>>   drivers/pci/msi.c                        |   3 +
>>   include/linux/iort.h                     |  38 ++++
>>   include/linux/irqchip/arm-gic-v3.h       |   2 +-
>>   10 files changed, 845 insertions(+), 101 deletions(-)
>>   create mode 100644 drivers/acpi/iort.c
>>   create mode 100644 include/linux/iort.h
>>
>
> I've so far queued the first 5 patches of this series (basic ACPI
> support for GICv3 and associated cleanups). The rest needs additional
> discussion (see my comments on patch 10), and requires some form of Ack
> from the ACPI maintainers (at least for patch 7).
>
Thanks Marc!

I will respond to the rest of your comments shortly.

Tomasz

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

* Re: [PATCH V3 06/10] irqchip, GICv3, ITS: Refator ITS dt init code to prepare for ACPI.
  2016-02-10 10:47     ` Marc Zyngier
@ 2016-02-12 10:10       ` Tomasz Nowicki
  -1 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-02-12 10:10 UTC (permalink / raw)
  To: Marc Zyngier, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm

On 10.02.2016 11:47, Marc Zyngier wrote:
> On 19/01/16 13:11, Tomasz Nowicki wrote:
>> Similarly to GICv3 core, we need to extract common code before adding
>> ACPI support. No functional changes.
>>
>> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
>> Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
>> ---
>>   drivers/irqchip/irq-gic-v3-its.c   | 82 +++++++++++++++++++++++---------------
>>   drivers/irqchip/irq-gic-v3.c       |  6 +--
>>   include/linux/irqchip/arm-gic-v3.h |  2 +-
>>   3 files changed, 52 insertions(+), 38 deletions(-)
>>
>> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c

[..]

>> -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,
>
> I really question the fact that you are keeping this msi_controller
> thing. Let's face it: if this is not an MSI controller, then the whole
> thing is absolutely pointless.
>
> So I'd rather you simplify the whole in a separate patch, and just don't
> bother initializing the ITS if it cannot be used for MSIs.
>
>> +				struct fwnode_handle *handler)
>>   {
>> -	struct resource res;
>>   	struct its_node *its;
>>   	void __iomem *its_base;
>>   	struct irq_domain *inner_domain;
>> @@ -1435,33 +1436,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");
>
> There is some value in at least displaying the base address - think of
> people writing their DT or ACPI tables. Please do not blindly remove
> debugging information which is often useful on a system with multiple ITS.

Yes, base address is helpful with multi ITS.

>
>>   		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) {
>> @@ -1473,7 +1467,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);
>> @@ -1485,7 +1479,7 @@ static int __init its_probe(struct device_node *node,
>>
>>   	its_enable_quirks(its);
>>
>> -	err = its_alloc_tables(node->full_name, its);
>> +	err = its_alloc_tables(its);
>>   	if (err)
>>   		goto out_free_cmd;
>>
>> @@ -1521,7 +1515,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);
>> @@ -1530,7 +1524,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);
>> @@ -1558,10 +1553,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;
>
> This is where you should return early, with a message saying that this
> ITS is being ignored if it doesn't have the msi-controller property.

Agree, will do.

Thanks,
Tomasz

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

* [PATCH V3 06/10] irqchip, GICv3, ITS: Refator ITS dt init code to prepare for ACPI.
@ 2016-02-12 10:10       ` Tomasz Nowicki
  0 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-02-12 10:10 UTC (permalink / raw)
  To: linux-arm-kernel

On 10.02.2016 11:47, Marc Zyngier wrote:
> On 19/01/16 13:11, Tomasz Nowicki wrote:
>> Similarly to GICv3 core, we need to extract common code before adding
>> ACPI support. No functional changes.
>>
>> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
>> Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
>> ---
>>   drivers/irqchip/irq-gic-v3-its.c   | 82 +++++++++++++++++++++++---------------
>>   drivers/irqchip/irq-gic-v3.c       |  6 +--
>>   include/linux/irqchip/arm-gic-v3.h |  2 +-
>>   3 files changed, 52 insertions(+), 38 deletions(-)
>>
>> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c

[..]

>> -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,
>
> I really question the fact that you are keeping this msi_controller
> thing. Let's face it: if this is not an MSI controller, then the whole
> thing is absolutely pointless.
>
> So I'd rather you simplify the whole in a separate patch, and just don't
> bother initializing the ITS if it cannot be used for MSIs.
>
>> +				struct fwnode_handle *handler)
>>   {
>> -	struct resource res;
>>   	struct its_node *its;
>>   	void __iomem *its_base;
>>   	struct irq_domain *inner_domain;
>> @@ -1435,33 +1436,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");
>
> There is some value in at least displaying the base address - think of
> people writing their DT or ACPI tables. Please do not blindly remove
> debugging information which is often useful on a system with multiple ITS.

Yes, base address is helpful with multi ITS.

>
>>   		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 at 0x%lx\n", (long)phys_base);
>>
>>   	its = kzalloc(sizeof(*its), GFP_KERNEL);
>>   	if (!its) {
>> @@ -1473,7 +1467,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);
>> @@ -1485,7 +1479,7 @@ static int __init its_probe(struct device_node *node,
>>
>>   	its_enable_quirks(its);
>>
>> -	err = its_alloc_tables(node->full_name, its);
>> +	err = its_alloc_tables(its);
>>   	if (err)
>>   		goto out_free_cmd;
>>
>> @@ -1521,7 +1515,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);
>> @@ -1530,7 +1524,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);
>> @@ -1558,10 +1553,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 at 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;
>
> This is where you should return early, with a message saying that this
> ITS is being ignored if it doesn't have the msi-controller property.

Agree, will do.

Thanks,
Tomasz

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

* Re: [PATCH V3 08/10] irqchip, gicv3, its: Probe ITS in the ACPI way.
  2016-02-10 11:46     ` Marc Zyngier
@ 2016-02-12 10:14       ` Tomasz Nowicki
  -1 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-02-12 10:14 UTC (permalink / raw)
  To: Marc Zyngier, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm

On 10.02.2016 12:46, Marc Zyngier wrote:
> On 19/01/16 13:11, Tomasz Nowicki wrote:
>> 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 | 57 +++++++++++++++++++++++++++++++++++++++-
>>   1 file changed, 56 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
>> index fecb7a6..42f378a 100644
>> --- a/drivers/irqchip/irq-gic-v3-its.c
>> +++ b/drivers/irqchip/irq-gic-v3-its.c
>> @@ -15,10 +15,13 @@
>>    * 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/irqdomain.h>
>> +#include <linux/iort.h>
>>   #include <linux/log2.h>
>>   #include <linux/mm.h>
>>   #include <linux/msi.h>
>> @@ -1272,6 +1275,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;
>>   	}
>> @@ -1594,6 +1602,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");
>
> -ECOPYPASTE.
>
>> +		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);
>
> And what if this fails?
>
>> +	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",	},
>>   	{},
>> @@ -1610,7 +1664,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);
>
> Missing braces.
>

Right, I will address all your comments in the next ITS-only series.

Tomasz

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

* [PATCH V3 08/10] irqchip, gicv3, its: Probe ITS in the ACPI way.
@ 2016-02-12 10:14       ` Tomasz Nowicki
  0 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-02-12 10:14 UTC (permalink / raw)
  To: linux-arm-kernel

On 10.02.2016 12:46, Marc Zyngier wrote:
> On 19/01/16 13:11, Tomasz Nowicki wrote:
>> 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 | 57 +++++++++++++++++++++++++++++++++++++++-
>>   1 file changed, 56 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
>> index fecb7a6..42f378a 100644
>> --- a/drivers/irqchip/irq-gic-v3-its.c
>> +++ b/drivers/irqchip/irq-gic-v3-its.c
>> @@ -15,10 +15,13 @@
>>    * 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/irqdomain.h>
>> +#include <linux/iort.h>
>>   #include <linux/log2.h>
>>   #include <linux/mm.h>
>>   #include <linux/msi.h>
>> @@ -1272,6 +1275,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;
>>   	}
>> @@ -1594,6 +1602,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");
>
> -ECOPYPASTE.
>
>> +		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);
>
> And what if this fails?
>
>> +	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",	},
>>   	{},
>> @@ -1610,7 +1664,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);
>
> Missing braces.
>

Right, I will address all your comments in the next ITS-only series.

Tomasz

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

* Re: [PATCH V3 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization.
  2016-02-10 12:02     ` Marc Zyngier
@ 2016-02-12 12:26       ` Tomasz Nowicki
  -1 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-02-12 12:26 UTC (permalink / raw)
  To: Marc Zyngier, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit,
	Charles Garcia-Tobin
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm

+ Charles

On 10.02.2016 13:02, Marc Zyngier wrote:
> On 19/01/16 13:11, 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 | 44 +++++++++++++++++++++++++++++++-
>>   drivers/irqchip/irq-gic-v3.c             |  3 +--
>>   drivers/pci/msi.c                        |  3 +++
>>   3 files changed, 47 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/irqchip/irq-gic-v3-its-pci-msi.c b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
>> index 06165cb..7f0a958 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>
>> @@ -143,10 +145,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);
>
> I'm a bit worried by this. You are registering this for each and every
> ITS that gets probed (useless, but why not). But also, you're using a
> hook that is designed to work at the bus level, without caring for the
> actual PCI devices. That's fine for something like GICv2m, which exposes
> a single domain, but I can't picture how this works when you have
> devices sitting behind a single RC that talk to different ITSs.
>
> My understanding is that IORT was behaving in a similar way the msi-map
> property works, so I'm a bit puzzled here.
>
> Can you please shed some light on that?
>

I see your point now. It is possible to describe such case in IORT, for 
example:

********************************************
RC0 node:
---------------
Mapping 0:
<input ID range> -> <output ID range>
<0:100> -> <0:100>
parent -> ITS0
---------------
Mapping 1:
<input ID range> -> <output ID range>
<101:200> -> <101:200>
parent -> ITS1
---------------
********************************************

So for this scenario I cannot use pci_host_bridge_acpi_msi_domain() to 
find IRQ domain based on bus device (unless there is only one ITS bound 
to e.g. RC), I should rather add ACPI implementation to 
pci_msi_get_device_domain on per-device MSI basis. Do you agree?

BTW. I should have put IORT specification link to changelog:
http://infocenter.arm.com/help/topic/com.arm.doc.den0049a/DEN0049A_IO_Remapping_Table.pdf

Thanks,
Tomasz

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

* [PATCH V3 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization.
@ 2016-02-12 12:26       ` Tomasz Nowicki
  0 siblings, 0 replies; 71+ messages in thread
From: Tomasz Nowicki @ 2016-02-12 12:26 UTC (permalink / raw)
  To: linux-arm-kernel

+ Charles

On 10.02.2016 13:02, Marc Zyngier wrote:
> On 19/01/16 13:11, 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 | 44 +++++++++++++++++++++++++++++++-
>>   drivers/irqchip/irq-gic-v3.c             |  3 +--
>>   drivers/pci/msi.c                        |  3 +++
>>   3 files changed, 47 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/irqchip/irq-gic-v3-its-pci-msi.c b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
>> index 06165cb..7f0a958 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>
>> @@ -143,10 +145,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 at 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);
>
> I'm a bit worried by this. You are registering this for each and every
> ITS that gets probed (useless, but why not). But also, you're using a
> hook that is designed to work at the bus level, without caring for the
> actual PCI devices. That's fine for something like GICv2m, which exposes
> a single domain, but I can't picture how this works when you have
> devices sitting behind a single RC that talk to different ITSs.
>
> My understanding is that IORT was behaving in a similar way the msi-map
> property works, so I'm a bit puzzled here.
>
> Can you please shed some light on that?
>

I see your point now. It is possible to describe such case in IORT, for 
example:

********************************************
RC0 node:
---------------
Mapping 0:
<input ID range> -> <output ID range>
<0:100> -> <0:100>
parent -> ITS0
---------------
Mapping 1:
<input ID range> -> <output ID range>
<101:200> -> <101:200>
parent -> ITS1
---------------
********************************************

So for this scenario I cannot use pci_host_bridge_acpi_msi_domain() to 
find IRQ domain based on bus device (unless there is only one ITS bound 
to e.g. RC), I should rather add ACPI implementation to 
pci_msi_get_device_domain on per-device MSI basis. Do you agree?

BTW. I should have put IORT specification link to changelog:
http://infocenter.arm.com/help/topic/com.arm.doc.den0049a/DEN0049A_IO_Remapping_Table.pdf

Thanks,
Tomasz

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

* Re: [PATCH V3 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization.
  2016-02-12 12:26       ` Tomasz Nowicki
@ 2016-02-12 13:22         ` Marc Zyngier
  -1 siblings, 0 replies; 71+ messages in thread
From: Marc Zyngier @ 2016-02-12 13:22 UTC (permalink / raw)
  To: Tomasz Nowicki, tglx, jason, rjw, lorenzo.pieralisi,
	robert.richter, shijie.huang, guohanjun, Suravee.Suthikulpanit,
	Charles Garcia-Tobin
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, hanjun.guo, linux-arm-kernel, ddaney.cavm

On 12/02/16 12:26, Tomasz Nowicki wrote:
> + Charles
> 
> On 10.02.2016 13:02, Marc Zyngier wrote:
>> On 19/01/16 13:11, 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 | 44 +++++++++++++++++++++++++++++++-
>>>   drivers/irqchip/irq-gic-v3.c             |  3 +--
>>>   drivers/pci/msi.c                        |  3 +++
>>>   3 files changed, 47 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/irqchip/irq-gic-v3-its-pci-msi.c b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
>>> index 06165cb..7f0a958 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>
>>> @@ -143,10 +145,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);
>>
>> I'm a bit worried by this. You are registering this for each and every
>> ITS that gets probed (useless, but why not). But also, you're using a
>> hook that is designed to work at the bus level, without caring for the
>> actual PCI devices. That's fine for something like GICv2m, which exposes
>> a single domain, but I can't picture how this works when you have
>> devices sitting behind a single RC that talk to different ITSs.
>>
>> My understanding is that IORT was behaving in a similar way the msi-map
>> property works, so I'm a bit puzzled here.
>>
>> Can you please shed some light on that?
>>
> 
> I see your point now. It is possible to describe such case in IORT, for 
> example:
> 
> ********************************************
> RC0 node:
> ---------------
> Mapping 0:
> <input ID range> -> <output ID range>
> <0:100> -> <0:100>
> parent -> ITS0
> ---------------
> Mapping 1:
> <input ID range> -> <output ID range>
> <101:200> -> <101:200>
> parent -> ITS1
> ---------------
> ********************************************
> 
> So for this scenario I cannot use pci_host_bridge_acpi_msi_domain() to 
> find IRQ domain based on bus device (unless there is only one ITS bound 
> to e.g. RC), I should rather add ACPI implementation to 
> pci_msi_get_device_domain on per-device MSI basis. Do you agree?

That's what I was angling for, having had that in mind when writing that
particular piece of code (see 54fa97eeb for the rational).

You should also split the plugging of IORT into the MSI layer from the
ITS driver (last hunk of this patch).

Thanks,

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

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

* [PATCH V3 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization.
@ 2016-02-12 13:22         ` Marc Zyngier
  0 siblings, 0 replies; 71+ messages in thread
From: Marc Zyngier @ 2016-02-12 13:22 UTC (permalink / raw)
  To: linux-arm-kernel

On 12/02/16 12:26, Tomasz Nowicki wrote:
> + Charles
> 
> On 10.02.2016 13:02, Marc Zyngier wrote:
>> On 19/01/16 13:11, 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 | 44 +++++++++++++++++++++++++++++++-
>>>   drivers/irqchip/irq-gic-v3.c             |  3 +--
>>>   drivers/pci/msi.c                        |  3 +++
>>>   3 files changed, 47 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/irqchip/irq-gic-v3-its-pci-msi.c b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
>>> index 06165cb..7f0a958 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>
>>> @@ -143,10 +145,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 at 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);
>>
>> I'm a bit worried by this. You are registering this for each and every
>> ITS that gets probed (useless, but why not). But also, you're using a
>> hook that is designed to work at the bus level, without caring for the
>> actual PCI devices. That's fine for something like GICv2m, which exposes
>> a single domain, but I can't picture how this works when you have
>> devices sitting behind a single RC that talk to different ITSs.
>>
>> My understanding is that IORT was behaving in a similar way the msi-map
>> property works, so I'm a bit puzzled here.
>>
>> Can you please shed some light on that?
>>
> 
> I see your point now. It is possible to describe such case in IORT, for 
> example:
> 
> ********************************************
> RC0 node:
> ---------------
> Mapping 0:
> <input ID range> -> <output ID range>
> <0:100> -> <0:100>
> parent -> ITS0
> ---------------
> Mapping 1:
> <input ID range> -> <output ID range>
> <101:200> -> <101:200>
> parent -> ITS1
> ---------------
> ********************************************
> 
> So for this scenario I cannot use pci_host_bridge_acpi_msi_domain() to 
> find IRQ domain based on bus device (unless there is only one ITS bound 
> to e.g. RC), I should rather add ACPI implementation to 
> pci_msi_get_device_domain on per-device MSI basis. Do you agree?

That's what I was angling for, having had that in mind when writing that
particular piece of code (see 54fa97eeb for the rational).

You should also split the plugging of IORT into the MSI layer from the
ITS driver (last hunk of this patch).

Thanks,

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

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

* Re: [PATCH V3 06/10] irqchip, GICv3, ITS: Refator ITS dt init code to prepare for ACPI.
  2016-02-10 10:47     ` Marc Zyngier
@ 2016-02-14  8:06       ` Hanjun Guo
  -1 siblings, 0 replies; 71+ messages in thread
From: Hanjun Guo @ 2016-02-14  8:06 UTC (permalink / raw)
  To: Marc Zyngier, Tomasz Nowicki, tglx, jason, rjw,
	lorenzo.pieralisi, robert.richter, shijie.huang, guohanjun,
	Suravee.Suthikulpanit
  Cc: mw, graeme.gregory, Catalin.Marinas, will.deacon, linux-kernel,
	linux-acpi, linux-arm-kernel, ddaney.cavm

On 2016/2/10 18:47, Marc Zyngier wrote:
> On 19/01/16 13:11, Tomasz Nowicki wrote:
>> Similarly to GICv3 core, we need to extract common code before adding
>> ACPI support. No functional changes.
>>
>> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
>> Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
>> ---
>>   drivers/irqchip/irq-gic-v3-its.c   | 82 +++++++++++++++++++++++---------------
>>   drivers/irqchip/irq-gic-v3.c       |  6 +--
>>   include/linux/irqchip/arm-gic-v3.h |  2 +-
>>   3 files changed, 52 insertions(+), 38 deletions(-)
>>
>> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
>> index 2bbed18..fecb7a6 100644
>> --- a/drivers/irqchip/irq-gic-v3-its.c
>> +++ b/drivers/irqchip/irq-gic-v3-its.c
>> @@ -813,7 +813,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;
>> @@ -868,8 +868,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);
>>   			}
>>   		}
>>
>> @@ -878,8 +878,8 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
>>   		if (alloc_pages > GITS_BASER_PAGES_MAX) {
>>   			alloc_pages = GITS_BASER_PAGES_MAX;
>>   			order = get_order(GITS_BASER_PAGES_MAX * psz);
>> -			pr_warn("%s: Device Table too large, reduce its page order to %u (%u pages)\n",
>> -				node_name, order, alloc_pages);
>> +			pr_warn("ITS@0x%lx: Device Table too large, reduce its page order to %u (%u pages)\n",
>> +				its->phys_base, order, alloc_pages);
>>   		}
>>
>>   		base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
>> @@ -948,8 +948,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;
>> @@ -1424,10 +1424,11 @@ static void its_enable_quirks(struct its_node *its)
>>   	gic_enable_quirks(iidr, its_quirks, its);
>>   }
>>
>> -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,
>
> I really question the fact that you are keeping this msi_controller
> thing. Let's face it: if this is not an MSI controller, then the whole
> thing is absolutely pointless.
>
> So I'd rather you simplify the whole in a separate patch, and just don't
> bother initializing the ITS if it cannot be used for MSIs.

Agree, that will simplify the code a lot.

Thanks
Hanjun

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

* [PATCH V3 06/10] irqchip, GICv3, ITS: Refator ITS dt init code to prepare for ACPI.
@ 2016-02-14  8:06       ` Hanjun Guo
  0 siblings, 0 replies; 71+ messages in thread
From: Hanjun Guo @ 2016-02-14  8:06 UTC (permalink / raw)
  To: linux-arm-kernel

On 2016/2/10 18:47, Marc Zyngier wrote:
> On 19/01/16 13:11, Tomasz Nowicki wrote:
>> Similarly to GICv3 core, we need to extract common code before adding
>> ACPI support. No functional changes.
>>
>> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
>> Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
>> ---
>>   drivers/irqchip/irq-gic-v3-its.c   | 82 +++++++++++++++++++++++---------------
>>   drivers/irqchip/irq-gic-v3.c       |  6 +--
>>   include/linux/irqchip/arm-gic-v3.h |  2 +-
>>   3 files changed, 52 insertions(+), 38 deletions(-)
>>
>> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
>> index 2bbed18..fecb7a6 100644
>> --- a/drivers/irqchip/irq-gic-v3-its.c
>> +++ b/drivers/irqchip/irq-gic-v3-its.c
>> @@ -813,7 +813,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;
>> @@ -868,8 +868,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 at 0x%lx: Device Table too large, reduce its page order to %u\n",
>> +					its->phys_base, order);
>>   			}
>>   		}
>>
>> @@ -878,8 +878,8 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
>>   		if (alloc_pages > GITS_BASER_PAGES_MAX) {
>>   			alloc_pages = GITS_BASER_PAGES_MAX;
>>   			order = get_order(GITS_BASER_PAGES_MAX * psz);
>> -			pr_warn("%s: Device Table too large, reduce its page order to %u (%u pages)\n",
>> -				node_name, order, alloc_pages);
>> +			pr_warn("ITS at 0x%lx: Device Table too large, reduce its page order to %u (%u pages)\n",
>> +				its->phys_base, order, alloc_pages);
>>   		}
>>
>>   		base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
>> @@ -948,8 +948,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 at 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;
>> @@ -1424,10 +1424,11 @@ static void its_enable_quirks(struct its_node *its)
>>   	gic_enable_quirks(iidr, its_quirks, its);
>>   }
>>
>> -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,
>
> I really question the fact that you are keeping this msi_controller
> thing. Let's face it: if this is not an MSI controller, then the whole
> thing is absolutely pointless.
>
> So I'd rather you simplify the whole in a separate patch, and just don't
> bother initializing the ITS if it cannot be used for MSIs.

Agree, that will simplify the code a lot.

Thanks
Hanjun

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

end of thread, other threads:[~2016-02-14  8:06 UTC | newest]

Thread overview: 71+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-19 13:11 [PATCH V3 00/10] Introduce ACPI world to GICv3 & ITS irqchip Tomasz Nowicki
2016-01-19 13:11 ` Tomasz Nowicki
2016-01-19 13:11 ` [PATCH V3 01/10] irqchip / GICv3: Refactor gic_of_init() for GICv3 driver Tomasz Nowicki
2016-01-19 13:11   ` Tomasz Nowicki
2016-02-10  9:50   ` Marc Zyngier
2016-02-10  9:50     ` Marc Zyngier
2016-01-19 13:11 ` [PATCH V3 02/10] irqchip / GICv3: Add ACPI support for GICv3+ initialization Tomasz Nowicki
2016-01-19 13:11   ` Tomasz Nowicki
2016-02-10  9:55   ` Marc Zyngier
2016-02-10  9:55     ` Marc Zyngier
2016-01-19 13:11 ` [PATCH V3 03/10] irqchip,GICv3,ACPI: Add redistributor support via GICC structures Tomasz Nowicki
2016-01-19 13:11   ` [PATCH V3 03/10] irqchip, GICv3, ACPI: " Tomasz Nowicki
2016-02-10 10:16   ` [PATCH V3 03/10] irqchip,GICv3,ACPI: " Marc Zyngier
2016-02-10 10:16     ` Marc Zyngier
2016-01-19 13:11 ` [PATCH V3 04/10] irqchip / GICv3: remove gic root node in ITS Tomasz Nowicki
2016-01-19 13:11   ` Tomasz Nowicki
2016-02-10 10:25   ` Marc Zyngier
2016-02-10 10:25     ` Marc Zyngier
2016-01-19 13:11 ` [PATCH V3 05/10] irqchip, gicv3, its: Mark its_init() and its children as __init Tomasz Nowicki
2016-01-19 13:11   ` Tomasz Nowicki
2016-01-19 13:11   ` Tomasz Nowicki
2016-02-10 10:30   ` Marc Zyngier
2016-02-10 10:30     ` Marc Zyngier
2016-01-19 13:11 ` [PATCH V3 06/10] irqchip, GICv3, ITS: Refator ITS dt init code to prepare for ACPI Tomasz Nowicki
2016-01-19 13:11   ` Tomasz Nowicki
2016-01-19 13:11   ` Tomasz Nowicki
2016-02-10 10:47   ` Marc Zyngier
2016-02-10 10:47     ` Marc Zyngier
2016-02-12 10:10     ` Tomasz Nowicki
2016-02-12 10:10       ` Tomasz Nowicki
2016-02-14  8:06     ` Hanjun Guo
2016-02-14  8:06       ` Hanjun Guo
2016-01-19 13:11 ` [PATCH V3 07/10] ARM64, ACPI, PCI: I/O Remapping Table (IORT) initial support Tomasz Nowicki
2016-01-19 13:11   ` Tomasz Nowicki
2016-01-19 13:11   ` Tomasz Nowicki
2016-01-19 13:11 ` [PATCH V3 08/10] irqchip, gicv3, its: Probe ITS in the ACPI way Tomasz Nowicki
2016-01-19 13:11   ` Tomasz Nowicki
2016-01-19 18:04   ` kbuild test robot
2016-01-19 18:04     ` kbuild test robot
2016-01-19 18:04     ` kbuild test robot
2016-02-10 11:46   ` Marc Zyngier
2016-02-10 11:46     ` Marc Zyngier
2016-02-12 10:14     ` Tomasz Nowicki
2016-02-12 10:14       ` Tomasz Nowicki
2016-01-19 13:11 ` [PATCH V3 09/10] acpi, gicv3, msi: Factor out code that might be reused for ACPI equivalent Tomasz Nowicki
2016-01-19 13:11   ` Tomasz Nowicki
2016-01-19 13:11 ` [PATCH V3 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization Tomasz Nowicki
2016-01-19 13:11   ` Tomasz Nowicki
2016-01-19 18:26   ` kbuild test robot
2016-01-19 18:26     ` kbuild test robot
2016-01-19 18:26     ` kbuild test robot
2016-02-10 12:02   ` Marc Zyngier
2016-02-10 12:02     ` Marc Zyngier
2016-02-12 12:26     ` Tomasz Nowicki
2016-02-12 12:26       ` Tomasz Nowicki
2016-02-12 13:22       ` Marc Zyngier
2016-02-12 13:22         ` Marc Zyngier
2016-01-22 21:56 ` [PATCH V3 00/10] Introduce ACPI world to GICv3 & ITS irqchip Christopher Covington
2016-01-22 21:56   ` Christopher Covington
2016-01-22 23:06 ` Robert Richter
2016-01-22 23:06   ` Robert Richter
2016-01-22 23:06   ` Robert Richter
2016-02-10  8:55 ` Tomasz Nowicki
2016-02-10  8:55   ` Tomasz Nowicki
2016-02-10 10:19   ` Marc Zyngier
2016-02-10 10:19     ` Marc Zyngier
2016-02-10 10:19     ` Marc Zyngier
2016-02-11 11:47 ` Marc Zyngier
2016-02-11 11:47   ` Marc Zyngier
2016-02-11 14:02   ` Tomasz Nowicki
2016-02-11 14:02     ` Tomasz Nowicki

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.