All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V2 00/10] Introduce ACPI world to GICv3 & ITS irqchip
@ 2015-12-17 11:52 ` Tomasz Nowicki
  0 siblings, 0 replies; 62+ messages in thread
From: Tomasz Nowicki @ 2015-12-17 11:52 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

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

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 for test patches (mainly ACPI ARM64 PCI support).
https://github.com/semihalf-nowicki-tomasz/linux.git (gicv3-its-acpi-v2)

Series has been tested on Cavium ThunderX 1 socket server.

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         | 142 +++++++++----
 drivers/irqchip/irq-gic-v3.c             | 341 ++++++++++++++++++++++++++-----
 drivers/pci/msi.c                        |   3 +
 include/linux/iort.h                     |  38 ++++
 include/linux/irqchip/arm-gic-v3.h       |   2 +-
 10 files changed, 841 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] 62+ messages in thread

* [PATCH V2 00/10] Introduce ACPI world to GICv3 & ITS irqchip
@ 2015-12-17 11:52 ` Tomasz Nowicki
  0 siblings, 0 replies; 62+ messages in thread
From: Tomasz Nowicki @ 2015-12-17 11:52 UTC (permalink / raw)
  To: linux-arm-kernel

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

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 for test patches (mainly ACPI ARM64 PCI support).
https://github.com/semihalf-nowicki-tomasz/linux.git (gicv3-its-acpi-v2)

Series has been tested on Cavium ThunderX 1 socket server.

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         | 142 +++++++++----
 drivers/irqchip/irq-gic-v3.c             | 341 ++++++++++++++++++++++++++-----
 drivers/pci/msi.c                        |   3 +
 include/linux/iort.h                     |  38 ++++
 include/linux/irqchip/arm-gic-v3.h       |   2 +-
 10 files changed, 841 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] 62+ messages in thread

* [PATCH V2 01/10] irqchip / GICv3: Refactor gic_of_init() for GICv3 driver
  2015-12-17 11:52 ` Tomasz Nowicki
@ 2015-12-17 11:52   ` Tomasz Nowicki
  -1 siblings, 0 replies; 62+ messages in thread
From: Tomasz Nowicki @ 2015-12-17 11:52 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] 62+ messages in thread

* [PATCH V2 01/10] irqchip / GICv3: Refactor gic_of_init() for GICv3 driver
@ 2015-12-17 11:52   ` Tomasz Nowicki
  0 siblings, 0 replies; 62+ messages in thread
From: Tomasz Nowicki @ 2015-12-17 11:52 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] 62+ messages in thread

* [PATCH V2 02/10] irqchip / GICv3: Add ACPI support for GICv3+ initialization
  2015-12-17 11:52 ` Tomasz Nowicki
  (?)
@ 2015-12-17 11:52   ` Tomasz Nowicki
  -1 siblings, 0 replies; 62+ messages in thread
From: Tomasz Nowicki @ 2015-12-17 11:52 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

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

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

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

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

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 31205c7..c4b929c 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -15,6 +15,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/acpi.h>
 #include <linux/cpu.h>
 #include <linux/cpu_pm.h>
 #include <linux/delay.h>
@@ -764,6 +765,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 +961,135 @@ out_unmap_dist:
 }
 
 IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
+
+#ifdef CONFIG_ACPI
+static struct redist_region *redist_regs __initdata;
+static u32 nr_redist_regions __initdata;
+
+static int __init
+gic_acpi_register_redist(phys_addr_t phys_base, u64 size)
+{
+	void __iomem *redist_base;
+	static int count = 0;
+
+	redist_base = ioremap(phys_base, size);
+	if (!redist_base) {
+		pr_err("Couldn't map GICR region @%llx\n", phys_base);
+		return -ENOMEM;
+	}
+
+	redist_regs[count].phys_base = phys_base;
+	redist_regs[count++].redist_base = redist_base;
+	return 0;
+}
+
+static int __init
+gic_acpi_parse_madt_redist(struct acpi_subtable_header *header,
+			   const unsigned long end)
+{
+	struct acpi_madt_generic_redistributor *redist =
+			(struct acpi_madt_generic_redistributor *)header;
+
+	return gic_acpi_register_redist(redist->base_address, redist->length);
+}
+
+static int __init gic_acpi_match_gicr(struct acpi_subtable_header *header,
+				  const unsigned long end)
+{
+	/* Subtable presence means that redist exists, that's it */
+	return 0;
+}
+
+static bool __init acpi_validate_gic_table(struct acpi_subtable_header *header,
+					   struct acpi_probe_entry *ape)
+{
+	struct acpi_madt_generic_distributor *dist;
+	int count;
+
+	dist = (struct acpi_madt_generic_distributor *)header;
+	if (dist->version != ape->driver_data)
+		return false;
+
+	/* We need to do that exercise anyway, the sooner the better */
+	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
+				      gic_acpi_match_gicr, 0);
+	if (count <= 0)
+		return false;
+
+	nr_redist_regions = count;
+	return true;
+}
+
+#define ACPI_GICV3_DIST_MEM_SIZE (SZ_64K)
+
+static int __init
+gic_acpi_init(struct acpi_subtable_header *header, const unsigned long end)
+{
+	struct acpi_madt_generic_distributor *dist;
+	struct fwnode_handle *domain_handle;
+	void __iomem *dist_base;
+	int i, err, count;
+
+	/* Get distributor base address */
+	dist = (struct acpi_madt_generic_distributor *)header;
+	dist_base = ioremap(dist->base_address, ACPI_GICV3_DIST_MEM_SIZE);
+	if (!dist_base) {
+		pr_err("Unable to map GICD registers\n");
+		return -ENOMEM;
+	}
+
+	err = gic_validate_dist_version(dist_base);
+	if (err) {
+		pr_err("No distributor detected at @%p, giving up", dist_base);
+		goto out_dist_unmap;
+	}
+
+	redist_regs = kzalloc(sizeof(*redist_regs) * nr_redist_regions,
+			      GFP_KERNEL);
+	if (!redist_regs) {
+		err = -ENOMEM;
+		goto out_dist_unmap;
+	}
+
+	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
+				      gic_acpi_parse_madt_redist, 0);
+	if (count <= 0) {
+		err = -ENODEV;
+		goto out_redist_unmap;
+	}
+
+	domain_handle = irq_domain_alloc_fwnode(dist_base);
+	if (!domain_handle) {
+		err = -ENOMEM;
+		goto out_redist_unmap;
+	}
+
+	err = gic_init_bases(dist_base, redist_regs, nr_redist_regions, 0,
+			     domain_handle);
+	if (err)
+		goto out_fwhandle_free;
+
+	acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, domain_handle);
+	return 0;
+
+out_fwhandle_free:
+	irq_domain_free_fwnode(domain_handle);
+out_redist_unmap:
+	for (i = 0; i < nr_redist_regions; i++)
+		if (redist_regs[i].redist_base)
+			iounmap(redist_regs[i].redist_base);
+	kfree(redist_regs);
+out_dist_unmap:
+	iounmap(dist_base);
+	return err;
+}
+IRQCHIP_ACPI_DECLARE(gic_v3, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
+		     acpi_validate_gic_table, ACPI_MADT_GIC_VERSION_V3,
+		     gic_acpi_init);
+IRQCHIP_ACPI_DECLARE(gic_v3_maybe, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
+		     acpi_validate_gic_table, ACPI_MADT_GIC_VERSION_NONE,
+		     gic_acpi_init);
+IRQCHIP_ACPI_DECLARE(gic_v4, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
+		     acpi_validate_gic_table, ACPI_MADT_GIC_VERSION_V4,
+		     gic_acpi_init);
+#endif
-- 
1.9.1

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

* [PATCH V2 02/10] irqchip / GICv3: Add ACPI support for GICv3+ initialization
@ 2015-12-17 11:52   ` Tomasz Nowicki
  0 siblings, 0 replies; 62+ messages in thread
From: Tomasz Nowicki @ 2015-12-17 11:52 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 | 142 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 142 insertions(+)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 31205c7..c4b929c 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -15,6 +15,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/acpi.h>
 #include <linux/cpu.h>
 #include <linux/cpu_pm.h>
 #include <linux/delay.h>
@@ -764,6 +765,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 +961,135 @@ out_unmap_dist:
 }
 
 IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
+
+#ifdef CONFIG_ACPI
+static struct redist_region *redist_regs __initdata;
+static u32 nr_redist_regions __initdata;
+
+static int __init
+gic_acpi_register_redist(phys_addr_t phys_base, u64 size)
+{
+	void __iomem *redist_base;
+	static int count = 0;
+
+	redist_base = ioremap(phys_base, size);
+	if (!redist_base) {
+		pr_err("Couldn't map GICR region @%llx\n", phys_base);
+		return -ENOMEM;
+	}
+
+	redist_regs[count].phys_base = phys_base;
+	redist_regs[count++].redist_base = redist_base;
+	return 0;
+}
+
+static int __init
+gic_acpi_parse_madt_redist(struct acpi_subtable_header *header,
+			   const unsigned long end)
+{
+	struct acpi_madt_generic_redistributor *redist =
+			(struct acpi_madt_generic_redistributor *)header;
+
+	return gic_acpi_register_redist(redist->base_address, redist->length);
+}
+
+static int __init gic_acpi_match_gicr(struct acpi_subtable_header *header,
+				  const unsigned long end)
+{
+	/* Subtable presence means that redist exists, that's it */
+	return 0;
+}
+
+static bool __init acpi_validate_gic_table(struct acpi_subtable_header *header,
+					   struct acpi_probe_entry *ape)
+{
+	struct acpi_madt_generic_distributor *dist;
+	int count;
+
+	dist = (struct acpi_madt_generic_distributor *)header;
+	if (dist->version != ape->driver_data)
+		return false;
+
+	/* We need to do that exercise anyway, the sooner the better */
+	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
+				      gic_acpi_match_gicr, 0);
+	if (count <= 0)
+		return false;
+
+	nr_redist_regions = count;
+	return true;
+}
+
+#define ACPI_GICV3_DIST_MEM_SIZE (SZ_64K)
+
+static int __init
+gic_acpi_init(struct acpi_subtable_header *header, const unsigned long end)
+{
+	struct acpi_madt_generic_distributor *dist;
+	struct fwnode_handle *domain_handle;
+	void __iomem *dist_base;
+	int i, err, count;
+
+	/* Get distributor base address */
+	dist = (struct acpi_madt_generic_distributor *)header;
+	dist_base = ioremap(dist->base_address, ACPI_GICV3_DIST_MEM_SIZE);
+	if (!dist_base) {
+		pr_err("Unable to map GICD registers\n");
+		return -ENOMEM;
+	}
+
+	err = gic_validate_dist_version(dist_base);
+	if (err) {
+		pr_err("No distributor detected at @%p, giving up", dist_base);
+		goto out_dist_unmap;
+	}
+
+	redist_regs = kzalloc(sizeof(*redist_regs) * nr_redist_regions,
+			      GFP_KERNEL);
+	if (!redist_regs) {
+		err = -ENOMEM;
+		goto out_dist_unmap;
+	}
+
+	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
+				      gic_acpi_parse_madt_redist, 0);
+	if (count <= 0) {
+		err = -ENODEV;
+		goto out_redist_unmap;
+	}
+
+	domain_handle = irq_domain_alloc_fwnode(dist_base);
+	if (!domain_handle) {
+		err = -ENOMEM;
+		goto out_redist_unmap;
+	}
+
+	err = gic_init_bases(dist_base, redist_regs, nr_redist_regions, 0,
+			     domain_handle);
+	if (err)
+		goto out_fwhandle_free;
+
+	acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, domain_handle);
+	return 0;
+
+out_fwhandle_free:
+	irq_domain_free_fwnode(domain_handle);
+out_redist_unmap:
+	for (i = 0; i < nr_redist_regions; i++)
+		if (redist_regs[i].redist_base)
+			iounmap(redist_regs[i].redist_base);
+	kfree(redist_regs);
+out_dist_unmap:
+	iounmap(dist_base);
+	return err;
+}
+IRQCHIP_ACPI_DECLARE(gic_v3, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
+		     acpi_validate_gic_table, ACPI_MADT_GIC_VERSION_V3,
+		     gic_acpi_init);
+IRQCHIP_ACPI_DECLARE(gic_v3_maybe, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
+		     acpi_validate_gic_table, ACPI_MADT_GIC_VERSION_NONE,
+		     gic_acpi_init);
+IRQCHIP_ACPI_DECLARE(gic_v4, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
+		     acpi_validate_gic_table, ACPI_MADT_GIC_VERSION_V4,
+		     gic_acpi_init);
+#endif
-- 
1.9.1


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

* [PATCH V2 02/10] irqchip / GICv3: Add ACPI support for GICv3+ initialization
@ 2015-12-17 11:52   ` Tomasz Nowicki
  0 siblings, 0 replies; 62+ messages in thread
From: Tomasz Nowicki @ 2015-12-17 11:52 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 | 142 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 142 insertions(+)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 31205c7..c4b929c 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -15,6 +15,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/acpi.h>
 #include <linux/cpu.h>
 #include <linux/cpu_pm.h>
 #include <linux/delay.h>
@@ -764,6 +765,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 +961,135 @@ out_unmap_dist:
 }
 
 IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
+
+#ifdef CONFIG_ACPI
+static struct redist_region *redist_regs __initdata;
+static u32 nr_redist_regions __initdata;
+
+static int __init
+gic_acpi_register_redist(phys_addr_t phys_base, u64 size)
+{
+	void __iomem *redist_base;
+	static int count = 0;
+
+	redist_base = ioremap(phys_base, size);
+	if (!redist_base) {
+		pr_err("Couldn't map GICR region @%llx\n", phys_base);
+		return -ENOMEM;
+	}
+
+	redist_regs[count].phys_base = phys_base;
+	redist_regs[count++].redist_base = redist_base;
+	return 0;
+}
+
+static int __init
+gic_acpi_parse_madt_redist(struct acpi_subtable_header *header,
+			   const unsigned long end)
+{
+	struct acpi_madt_generic_redistributor *redist =
+			(struct acpi_madt_generic_redistributor *)header;
+
+	return gic_acpi_register_redist(redist->base_address, redist->length);
+}
+
+static int __init gic_acpi_match_gicr(struct acpi_subtable_header *header,
+				  const unsigned long end)
+{
+	/* Subtable presence means that redist exists, that's it */
+	return 0;
+}
+
+static bool __init acpi_validate_gic_table(struct acpi_subtable_header *header,
+					   struct acpi_probe_entry *ape)
+{
+	struct acpi_madt_generic_distributor *dist;
+	int count;
+
+	dist = (struct acpi_madt_generic_distributor *)header;
+	if (dist->version != ape->driver_data)
+		return false;
+
+	/* We need to do that exercise anyway, the sooner the better */
+	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
+				      gic_acpi_match_gicr, 0);
+	if (count <= 0)
+		return false;
+
+	nr_redist_regions = count;
+	return true;
+}
+
+#define ACPI_GICV3_DIST_MEM_SIZE (SZ_64K)
+
+static int __init
+gic_acpi_init(struct acpi_subtable_header *header, const unsigned long end)
+{
+	struct acpi_madt_generic_distributor *dist;
+	struct fwnode_handle *domain_handle;
+	void __iomem *dist_base;
+	int i, err, count;
+
+	/* Get distributor base address */
+	dist = (struct acpi_madt_generic_distributor *)header;
+	dist_base = ioremap(dist->base_address, ACPI_GICV3_DIST_MEM_SIZE);
+	if (!dist_base) {
+		pr_err("Unable to map GICD registers\n");
+		return -ENOMEM;
+	}
+
+	err = gic_validate_dist_version(dist_base);
+	if (err) {
+		pr_err("No distributor detected at @%p, giving up", dist_base);
+		goto out_dist_unmap;
+	}
+
+	redist_regs = kzalloc(sizeof(*redist_regs) * nr_redist_regions,
+			      GFP_KERNEL);
+	if (!redist_regs) {
+		err = -ENOMEM;
+		goto out_dist_unmap;
+	}
+
+	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
+				      gic_acpi_parse_madt_redist, 0);
+	if (count <= 0) {
+		err = -ENODEV;
+		goto out_redist_unmap;
+	}
+
+	domain_handle = irq_domain_alloc_fwnode(dist_base);
+	if (!domain_handle) {
+		err = -ENOMEM;
+		goto out_redist_unmap;
+	}
+
+	err = gic_init_bases(dist_base, redist_regs, nr_redist_regions, 0,
+			     domain_handle);
+	if (err)
+		goto out_fwhandle_free;
+
+	acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, domain_handle);
+	return 0;
+
+out_fwhandle_free:
+	irq_domain_free_fwnode(domain_handle);
+out_redist_unmap:
+	for (i = 0; i < nr_redist_regions; i++)
+		if (redist_regs[i].redist_base)
+			iounmap(redist_regs[i].redist_base);
+	kfree(redist_regs);
+out_dist_unmap:
+	iounmap(dist_base);
+	return err;
+}
+IRQCHIP_ACPI_DECLARE(gic_v3, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
+		     acpi_validate_gic_table, ACPI_MADT_GIC_VERSION_V3,
+		     gic_acpi_init);
+IRQCHIP_ACPI_DECLARE(gic_v3_maybe, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
+		     acpi_validate_gic_table, ACPI_MADT_GIC_VERSION_NONE,
+		     gic_acpi_init);
+IRQCHIP_ACPI_DECLARE(gic_v4, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
+		     acpi_validate_gic_table, ACPI_MADT_GIC_VERSION_V4,
+		     gic_acpi_init);
+#endif
-- 
1.9.1

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

* [PATCH V2 03/10] irqchip,GICv3,ACPI: Add redistributor support via GICC structures.
  2015-12-17 11:52 ` Tomasz Nowicki
@ 2015-12-17 11:52   ` Tomasz Nowicki
  -1 siblings, 0 replies; 62+ messages in thread
From: Tomasz Nowicki @ 2015-12-17 11:52 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

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

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

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index c4b929c..0528e82 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -39,6 +39,7 @@
 struct redist_region {
 	void __iomem		*redist_base;
 	phys_addr_t		phys_base;
+	bool			single_redist;
 };
 
 struct gic_chip_data {
@@ -435,6 +436,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 {
@@ -965,6 +969,7 @@ IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
 #ifdef CONFIG_ACPI
 static struct redist_region *redist_regs __initdata;
 static u32 nr_redist_regions __initdata;
+static bool single_redist;
 
 static int __init
 gic_acpi_register_redist(phys_addr_t phys_base, u64 size)
@@ -979,7 +984,8 @@ gic_acpi_register_redist(phys_addr_t phys_base, u64 size)
 	}
 
 	redist_regs[count].phys_base = phys_base;
-	redist_regs[count++].redist_base = redist_base;
+	redist_regs[count].redist_base = redist_base;
+	redist_regs[count++].single_redist = single_redist;
 	return 0;
 }
 
@@ -993,6 +999,48 @@ gic_acpi_parse_madt_redist(struct acpi_subtable_header *header,
 	return gic_acpi_register_redist(redist->base_address, redist->length);
 }
 
+static int __init
+gic_acpi_parse_madt_gicc(struct acpi_subtable_header *header,
+			 const unsigned long end)
+{
+	struct acpi_madt_generic_interrupt *gicc;
+	void __iomem *redist_base;
+	u64 typer;
+	u32 size;
+
+	gicc = (struct acpi_madt_generic_interrupt *)header;
+	redist_base = ioremap(gicc->gicr_base_address, SZ_64K * 2);
+	if (!redist_base)
+		return -ENOMEM;
+
+	typer = readq_relaxed(redist_base + GICR_TYPER);
+	/* don't map reserved page as it's buggy to access it */
+	size = (typer & GICR_TYPER_VLPIS) ? SZ_64K * 3 : SZ_64K * 2;
+	iounmap(redist_base);
+	return gic_acpi_register_redist(gicc->gicr_base_address, size);
+}
+
+static int __init gic_acpi_collect_gicr_base(void)
+{
+	acpi_tbl_entry_handler redist_parser;
+	enum acpi_madt_type type;
+
+	if (single_redist) {
+		type = ACPI_MADT_TYPE_GENERIC_INTERRUPT;
+		redist_parser = gic_acpi_parse_madt_gicc;
+	} else {
+		type = ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR;
+		redist_parser = gic_acpi_parse_madt_redist;
+	}
+
+	/* Collect redistributor base addresses in GICR entries */
+	if (acpi_table_parse_madt(type, redist_parser, 0) > 0)
+		return 0;
+
+	pr_info("No valid GICR entries exist\n");
+	return -ENODEV;
+}
+
 static int __init gic_acpi_match_gicr(struct acpi_subtable_header *header,
 				  const unsigned long end)
 {
@@ -1000,6 +1048,42 @@ static int __init gic_acpi_match_gicr(struct acpi_subtable_header *header,
 	return 0;
 }
 
+static int __init gic_acpi_match_gicc(struct acpi_subtable_header *header,
+				      const unsigned long end)
+{
+	struct acpi_madt_generic_interrupt *gicc =
+				(struct acpi_madt_generic_interrupt *)header;
+
+	/*
+	 * If GICC is enabled and has valid gicr base address, then it means
+	 * GICR base is presented via GICC
+	 */
+	if ((gicc->flags & ACPI_MADT_ENABLED) && gicc->gicr_base_address)
+		return 0;
+
+	return -ENODEV;
+}
+
+static int __init gic_acpi_count_gicr_regions(void)
+{
+	int count;
+
+	/* Count how many redistributor regions we have */
+	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
+				      gic_acpi_match_gicr, 0);
+	if (count > 0) {
+		single_redist = false;
+		return count;
+	}
+
+	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
+				      gic_acpi_match_gicc, 0);
+	if (count > 0)
+		single_redist = true;
+
+	return count;
+}
+
 static bool __init acpi_validate_gic_table(struct acpi_subtable_header *header,
 					   struct acpi_probe_entry *ape)
 {
@@ -1011,8 +1095,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;
 
@@ -1028,7 +1111,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;
@@ -1051,12 +1134,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] 62+ messages in thread

* [PATCH V2 03/10] irqchip, GICv3, ACPI: Add redistributor support via GICC structures.
@ 2015-12-17 11:52   ` Tomasz Nowicki
  0 siblings, 0 replies; 62+ messages in thread
From: Tomasz Nowicki @ 2015-12-17 11:52 UTC (permalink / raw)
  To: linux-arm-kernel

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

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

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index c4b929c..0528e82 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -39,6 +39,7 @@
 struct redist_region {
 	void __iomem		*redist_base;
 	phys_addr_t		phys_base;
+	bool			single_redist;
 };
 
 struct gic_chip_data {
@@ -435,6 +436,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 {
@@ -965,6 +969,7 @@ IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
 #ifdef CONFIG_ACPI
 static struct redist_region *redist_regs __initdata;
 static u32 nr_redist_regions __initdata;
+static bool single_redist;
 
 static int __init
 gic_acpi_register_redist(phys_addr_t phys_base, u64 size)
@@ -979,7 +984,8 @@ gic_acpi_register_redist(phys_addr_t phys_base, u64 size)
 	}
 
 	redist_regs[count].phys_base = phys_base;
-	redist_regs[count++].redist_base = redist_base;
+	redist_regs[count].redist_base = redist_base;
+	redist_regs[count++].single_redist = single_redist;
 	return 0;
 }
 
@@ -993,6 +999,48 @@ gic_acpi_parse_madt_redist(struct acpi_subtable_header *header,
 	return gic_acpi_register_redist(redist->base_address, redist->length);
 }
 
+static int __init
+gic_acpi_parse_madt_gicc(struct acpi_subtable_header *header,
+			 const unsigned long end)
+{
+	struct acpi_madt_generic_interrupt *gicc;
+	void __iomem *redist_base;
+	u64 typer;
+	u32 size;
+
+	gicc = (struct acpi_madt_generic_interrupt *)header;
+	redist_base = ioremap(gicc->gicr_base_address, SZ_64K * 2);
+	if (!redist_base)
+		return -ENOMEM;
+
+	typer = readq_relaxed(redist_base + GICR_TYPER);
+	/* don't map reserved page as it's buggy to access it */
+	size = (typer & GICR_TYPER_VLPIS) ? SZ_64K * 3 : SZ_64K * 2;
+	iounmap(redist_base);
+	return gic_acpi_register_redist(gicc->gicr_base_address, size);
+}
+
+static int __init gic_acpi_collect_gicr_base(void)
+{
+	acpi_tbl_entry_handler redist_parser;
+	enum acpi_madt_type type;
+
+	if (single_redist) {
+		type = ACPI_MADT_TYPE_GENERIC_INTERRUPT;
+		redist_parser = gic_acpi_parse_madt_gicc;
+	} else {
+		type = ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR;
+		redist_parser = gic_acpi_parse_madt_redist;
+	}
+
+	/* Collect redistributor base addresses in GICR entries */
+	if (acpi_table_parse_madt(type, redist_parser, 0) > 0)
+		return 0;
+
+	pr_info("No valid GICR entries exist\n");
+	return -ENODEV;
+}
+
 static int __init gic_acpi_match_gicr(struct acpi_subtable_header *header,
 				  const unsigned long end)
 {
@@ -1000,6 +1048,42 @@ static int __init gic_acpi_match_gicr(struct acpi_subtable_header *header,
 	return 0;
 }
 
+static int __init gic_acpi_match_gicc(struct acpi_subtable_header *header,
+				      const unsigned long end)
+{
+	struct acpi_madt_generic_interrupt *gicc =
+				(struct acpi_madt_generic_interrupt *)header;
+
+	/*
+	 * If GICC is enabled and has valid gicr base address, then it means
+	 * GICR base is presented via GICC
+	 */
+	if ((gicc->flags & ACPI_MADT_ENABLED) && gicc->gicr_base_address)
+		return 0;
+
+	return -ENODEV;
+}
+
+static int __init gic_acpi_count_gicr_regions(void)
+{
+	int count;
+
+	/* Count how many redistributor regions we have */
+	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
+				      gic_acpi_match_gicr, 0);
+	if (count > 0) {
+		single_redist = false;
+		return count;
+	}
+
+	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
+				      gic_acpi_match_gicc, 0);
+	if (count > 0)
+		single_redist = true;
+
+	return count;
+}
+
 static bool __init acpi_validate_gic_table(struct acpi_subtable_header *header,
 					   struct acpi_probe_entry *ape)
 {
@@ -1011,8 +1095,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;
 
@@ -1028,7 +1111,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;
@@ -1051,12 +1134,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] 62+ messages in thread

* [PATCH V2 04/10] irqchip / GICv3: remove gic root node in ITS
  2015-12-17 11:52 ` Tomasz Nowicki
  (?)
@ 2015-12-17 11:52   ` Tomasz Nowicki
  -1 siblings, 0 replies; 62+ messages in thread
From: Tomasz Nowicki @ 2015-12-17 11:52 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, mw, 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] 62+ messages in thread

* [PATCH V2 04/10] irqchip / GICv3: remove gic root node in ITS
@ 2015-12-17 11:52   ` Tomasz Nowicki
  0 siblings, 0 replies; 62+ messages in thread
From: Tomasz Nowicki @ 2015-12-17 11:52 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] 62+ messages in thread

* [PATCH V2 04/10] irqchip / GICv3: remove gic root node in ITS
@ 2015-12-17 11:52   ` Tomasz Nowicki
  0 siblings, 0 replies; 62+ messages in thread
From: Tomasz Nowicki @ 2015-12-17 11:52 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] 62+ messages in thread

* [PATCH V2 05/10] irqchip, gicv3, its: Mark its_init() and its children as __init
  2015-12-17 11:52 ` Tomasz Nowicki
@ 2015-12-17 11:52   ` Tomasz Nowicki
  -1 siblings, 0 replies; 62+ messages in thread
From: Tomasz Nowicki @ 2015-12-17 11:52 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] 62+ messages in thread

* [PATCH V2 05/10] irqchip, gicv3, its: Mark its_init() and its children as __init
@ 2015-12-17 11:52   ` Tomasz Nowicki
  0 siblings, 0 replies; 62+ messages in thread
From: Tomasz Nowicki @ 2015-12-17 11:52 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] 62+ messages in thread

* [PATCH V2 06/10] irqchip/GICv3/ITS: Refator ITS dt init code to prepare for ACPI.
  2015-12-17 11:52 ` Tomasz Nowicki
@ 2015-12-17 11:52   ` Tomasz Nowicki
  -1 siblings, 0 replies; 62+ messages in thread
From: Tomasz Nowicki @ 2015-12-17 11:52 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

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 0528e82..1f3d761 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -831,7 +831,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;
@@ -871,10 +870,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 c9ae0c6..6739fd3 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -331,7 +331,7 @@ struct rdists {
 
 struct irq_domain;
 int its_cpu_init(void);
-int its_init(struct device_node *node, struct rdists *rdists,
+int its_init(struct fwnode_handle *handle, struct rdists *rdists,
 	     struct irq_domain *domain);
 
 static inline bool gic_enable_sre(void)
-- 
1.9.1

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

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

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 0528e82..1f3d761 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -831,7 +831,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;
@@ -871,10 +870,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 c9ae0c6..6739fd3 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -331,7 +331,7 @@ struct rdists {
 
 struct irq_domain;
 int its_cpu_init(void);
-int its_init(struct device_node *node, struct rdists *rdists,
+int its_init(struct fwnode_handle *handle, struct rdists *rdists,
 	     struct irq_domain *domain);
 
 static inline bool gic_enable_sre(void)
-- 
1.9.1

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

* [PATCH V2 07/10] ARM64, ACPI, PCI: I/O Remapping Table (IORT) initial support.
  2015-12-17 11:52 ` Tomasz Nowicki
@ 2015-12-17 11:52   ` Tomasz Nowicki
  -1 siblings, 0 replies; 62+ messages in thread
From: Tomasz Nowicki @ 2015-12-17 11:52 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>

Conflicts:
	drivers/acpi/Kconfig
---
 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..783e8d6
--- /dev/null
+++ b/include/linux/iort.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015, Linaro Ltd.
+ *	Author: Tomasz Nowicki <tomasz.nowicki@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef __IORT_H__
+#define __IORT_H__
+
+#include <linux/acpi.h>
+
+#ifdef CONFIG_ACPI
+
+struct fwnode_handle;
+
+int iort_register_domain_token(int trans_id, struct fwnode_handle *fw_node);
+struct fwnode_handle *iort_find_its_domain_token(int trans_id);
+struct fwnode_handle *iort_find_pci_domain_token(struct device *dev);
+int iort_find_pci_id(struct pci_dev *pdev, u32 req_id, u32 *dev_id);
+#else /* CONFIG_ACPI */
+static inline int
+iort_find_pci_id(struct pci_dev *pdev, u32 req_id, u32 *dev_id)
+{ return -ENXIO; }
+#endif /* CONFIG_ACPI */
+
+#endif /* __IORT_H__ */
-- 
1.9.1

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

* [PATCH V2 07/10] ARM64, ACPI, PCI: I/O Remapping Table (IORT) initial support.
@ 2015-12-17 11:52   ` Tomasz Nowicki
  0 siblings, 0 replies; 62+ messages in thread
From: Tomasz Nowicki @ 2015-12-17 11:52 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>

Conflicts:
	drivers/acpi/Kconfig
---
 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..783e8d6
--- /dev/null
+++ b/include/linux/iort.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015, Linaro Ltd.
+ *	Author: Tomasz Nowicki <tomasz.nowicki@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef __IORT_H__
+#define __IORT_H__
+
+#include <linux/acpi.h>
+
+#ifdef CONFIG_ACPI
+
+struct fwnode_handle;
+
+int iort_register_domain_token(int trans_id, struct fwnode_handle *fw_node);
+struct fwnode_handle *iort_find_its_domain_token(int trans_id);
+struct fwnode_handle *iort_find_pci_domain_token(struct device *dev);
+int iort_find_pci_id(struct pci_dev *pdev, u32 req_id, u32 *dev_id);
+#else /* CONFIG_ACPI */
+static inline int
+iort_find_pci_id(struct pci_dev *pdev, u32 req_id, u32 *dev_id)
+{ return -ENXIO; }
+#endif /* CONFIG_ACPI */
+
+#endif /* __IORT_H__ */
-- 
1.9.1

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

* [PATCH V2 08/10] irqchip, gicv3, its: Probe ITS in the ACPI way.
  2015-12-17 11:52 ` Tomasz Nowicki
@ 2015-12-17 11:52   ` Tomasz Nowicki
  -1 siblings, 0 replies; 62+ messages in thread
From: Tomasz Nowicki @ 2015-12-17 11:52 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 | 56 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 55 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index fecb7a6..2adb220 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -15,10 +15,12 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/acpi.h>
 #include <linux/bitmap.h>
 #include <linux/cpu.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/iort.h>
 #include <linux/log2.h>
 #include <linux/mm.h>
 #include <linux/msi.h>
@@ -1272,6 +1274,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 +1601,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 +1663,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] 62+ messages in thread

* [PATCH V2 08/10] irqchip, gicv3, its: Probe ITS in the ACPI way.
@ 2015-12-17 11:52   ` Tomasz Nowicki
  0 siblings, 0 replies; 62+ messages in thread
From: Tomasz Nowicki @ 2015-12-17 11:52 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 | 56 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 55 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index fecb7a6..2adb220 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -15,10 +15,12 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/acpi.h>
 #include <linux/bitmap.h>
 #include <linux/cpu.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/iort.h>
 #include <linux/log2.h>
 #include <linux/mm.h>
 #include <linux/msi.h>
@@ -1272,6 +1274,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 +1601,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 +1663,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] 62+ messages in thread

* [PATCH V2 09/10] acpi, gicv3, msi: Factor out code that might be reused for ACPI equivalent.
  2015-12-17 11:52 ` Tomasz Nowicki
@ 2015-12-17 11:52   ` Tomasz Nowicki
  -1 siblings, 0 replies; 62+ messages in thread
From: Tomasz Nowicki @ 2015-12-17 11:52 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] 62+ messages in thread

* [PATCH V2 09/10] acpi, gicv3, msi: Factor out code that might be reused for ACPI equivalent.
@ 2015-12-17 11:52   ` Tomasz Nowicki
  0 siblings, 0 replies; 62+ messages in thread
From: Tomasz Nowicki @ 2015-12-17 11:52 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] 62+ messages in thread

* [PATCH V2 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization.
  2015-12-17 11:52 ` Tomasz Nowicki
@ 2015-12-17 11:52   ` Tomasz Nowicki
  -1 siblings, 0 replies; 62+ messages in thread
From: Tomasz Nowicki @ 2015-12-17 11:52 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 1f3d761..1c9cd5c 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -870,8 +870,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 53e4632..0393114 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] 62+ messages in thread

* [PATCH V2 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization.
@ 2015-12-17 11:52   ` Tomasz Nowicki
  0 siblings, 0 replies; 62+ messages in thread
From: Tomasz Nowicki @ 2015-12-17 11:52 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 1f3d761..1c9cd5c 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -870,8 +870,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 53e4632..0393114 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] 62+ messages in thread

* Re: [PATCH V2 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization.
  2015-12-17 11:52   ` Tomasz Nowicki
  (?)
@ 2015-12-17 12:46     ` kbuild test robot
  -1 siblings, 0 replies; 62+ messages in thread
From: kbuild test robot @ 2015-12-17 12:46 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: 729 bytes --]

Hi Tomasz,

[auto build test ERROR on v4.4-rc4]
[also build test ERROR on next-20151217]
[cannot apply to tip/irq/core v4.4-rc5]

url:    https://github.com/0day-ci/linux/commits/Tomasz-Nowicki/Introduce-ACPI-world-to-GICv3-ITS-irqchip/20151217-195910
config: i386-randconfig-s1-12171706 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

   drivers/built-in.o: In function `pci_msi_domain_get_msi_rid':
>> (.text+0x3175d): undefined reference to `iort_find_pci_id'

---
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: 24633 bytes --]

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

* Re: [PATCH V2 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization.
@ 2015-12-17 12:46     ` kbuild test robot
  0 siblings, 0 replies; 62+ messages in thread
From: kbuild test robot @ 2015-12-17 12:46 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: 729 bytes --]

Hi Tomasz,

[auto build test ERROR on v4.4-rc4]
[also build test ERROR on next-20151217]
[cannot apply to tip/irq/core v4.4-rc5]

url:    https://github.com/0day-ci/linux/commits/Tomasz-Nowicki/Introduce-ACPI-world-to-GICv3-ITS-irqchip/20151217-195910
config: i386-randconfig-s1-12171706 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

   drivers/built-in.o: In function `pci_msi_domain_get_msi_rid':
>> (.text+0x3175d): undefined reference to `iort_find_pci_id'

---
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: 24633 bytes --]

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

* [PATCH V2 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization.
@ 2015-12-17 12:46     ` kbuild test robot
  0 siblings, 0 replies; 62+ messages in thread
From: kbuild test robot @ 2015-12-17 12:46 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Tomasz,

[auto build test ERROR on v4.4-rc4]
[also build test ERROR on next-20151217]
[cannot apply to tip/irq/core v4.4-rc5]

url:    https://github.com/0day-ci/linux/commits/Tomasz-Nowicki/Introduce-ACPI-world-to-GICv3-ITS-irqchip/20151217-195910
config: i386-randconfig-s1-12171706 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

   drivers/built-in.o: In function `pci_msi_domain_get_msi_rid':
>> (.text+0x3175d): undefined reference to `iort_find_pci_id'

---
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: 24633 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20151217/1659c2ca/attachment-0001.obj>

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

* Re: [PATCH V2 07/10] ARM64, ACPI, PCI: I/O Remapping Table (IORT) initial support.
  2015-12-17 11:52   ` Tomasz Nowicki
@ 2015-12-17 13:24     ` Tomasz Nowicki
  -1 siblings, 0 replies; 62+ messages in thread
From: Tomasz Nowicki @ 2015-12-17 13:24 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 17.12.2015 12:52, Tomasz Nowicki wrote:
> 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>
>
> Conflicts:
> 	drivers/acpi/Kconfig

Sorry for ^^^^ git rebase leftover.

> ---
>   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/include/linux/iort.h b/include/linux/iort.h
> new file mode 100644
> index 0000000..783e8d6
> --- /dev/null
> +++ b/include/linux/iort.h
> @@ -0,0 +1,38 @@
> +/*
> + * Copyright (C) 2015, Linaro Ltd.
> + *	Author: Tomasz Nowicki <tomasz.nowicki@linaro.org>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
> + * Place - Suite 330, Boston, MA 02111-1307 USA.
> + */
> +
> +#ifndef __IORT_H__
> +#define __IORT_H__
> +
> +#include <linux/acpi.h>
> +
> +#ifdef CONFIG_ACPI
> +

As per kbuild test report, this has to be:
#ifdef CONFIG_IORT_TABLE

Will be fixed in the next version.

Regards,
Tomasz

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

* [PATCH V2 07/10] ARM64, ACPI, PCI: I/O Remapping Table (IORT) initial support.
@ 2015-12-17 13:24     ` Tomasz Nowicki
  0 siblings, 0 replies; 62+ messages in thread
From: Tomasz Nowicki @ 2015-12-17 13:24 UTC (permalink / raw)
  To: linux-arm-kernel

On 17.12.2015 12:52, Tomasz Nowicki wrote:
> 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>
>
> Conflicts:
> 	drivers/acpi/Kconfig

Sorry for ^^^^ git rebase leftover.

> ---
>   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/include/linux/iort.h b/include/linux/iort.h
> new file mode 100644
> index 0000000..783e8d6
> --- /dev/null
> +++ b/include/linux/iort.h
> @@ -0,0 +1,38 @@
> +/*
> + * Copyright (C) 2015, Linaro Ltd.
> + *	Author: Tomasz Nowicki <tomasz.nowicki@linaro.org>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
> + * Place - Suite 330, Boston, MA 02111-1307 USA.
> + */
> +
> +#ifndef __IORT_H__
> +#define __IORT_H__
> +
> +#include <linux/acpi.h>
> +
> +#ifdef CONFIG_ACPI
> +

As per kbuild test report, this has to be:
#ifdef CONFIG_IORT_TABLE

Will be fixed in the next version.

Regards,
Tomasz

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

* Re: [PATCH V2 02/10] irqchip / GICv3: Add ACPI support for GICv3+ initialization
  2015-12-17 11:52   ` Tomasz Nowicki
  (?)
@ 2015-12-17 13:44     ` kbuild test robot
  -1 siblings, 0 replies; 62+ messages in thread
From: kbuild test robot @ 2015-12-17 13:44 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: 1353 bytes --]

Hi Tomasz,

[auto build test ERROR on v4.4-rc4]
[also build test ERROR on next-20151217]
[cannot apply to tip/irq/core v4.4-rc5]

url:    https://github.com/0day-ci/linux/commits/Tomasz-Nowicki/Introduce-ACPI-world-to-GICv3-ITS-irqchip/20151217-195910
config: arm-allyesconfig (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=arm 

All errors (new ones prefixed by >>):

   drivers/irqchip/irq-gic-v3.c: In function 'gic_irq_domain_translate':
>> drivers/irqchip/irq-gic-v3.c:768:2: error: implicit declaration of function 'is_fwnode_irqchip' [-Werror=implicit-function-declaration]
     if (is_fwnode_irqchip(fwspec->fwnode)) {
     ^
   cc1: some warnings being treated as errors

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

   762			}
   763	
   764			*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
   765			return 0;
   766		}
   767	
 > 768		if (is_fwnode_irqchip(fwspec->fwnode)) {
   769			if(fwspec->param_count != 2)
   770				return -EINVAL;
   771	

---
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: 53975 bytes --]

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

* Re: [PATCH V2 02/10] irqchip / GICv3: Add ACPI support for GICv3+ initialization
@ 2015-12-17 13:44     ` kbuild test robot
  0 siblings, 0 replies; 62+ messages in thread
From: kbuild test robot @ 2015-12-17 13:44 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: 1353 bytes --]

Hi Tomasz,

[auto build test ERROR on v4.4-rc4]
[also build test ERROR on next-20151217]
[cannot apply to tip/irq/core v4.4-rc5]

url:    https://github.com/0day-ci/linux/commits/Tomasz-Nowicki/Introduce-ACPI-world-to-GICv3-ITS-irqchip/20151217-195910
config: arm-allyesconfig (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=arm 

All errors (new ones prefixed by >>):

   drivers/irqchip/irq-gic-v3.c: In function 'gic_irq_domain_translate':
>> drivers/irqchip/irq-gic-v3.c:768:2: error: implicit declaration of function 'is_fwnode_irqchip' [-Werror=implicit-function-declaration]
     if (is_fwnode_irqchip(fwspec->fwnode)) {
     ^
   cc1: some warnings being treated as errors

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

   762			}
   763	
   764			*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
   765			return 0;
   766		}
   767	
 > 768		if (is_fwnode_irqchip(fwspec->fwnode)) {
   769			if(fwspec->param_count != 2)
   770				return -EINVAL;
   771	

---
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: 53975 bytes --]

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

* [PATCH V2 02/10] irqchip / GICv3: Add ACPI support for GICv3+ initialization
@ 2015-12-17 13:44     ` kbuild test robot
  0 siblings, 0 replies; 62+ messages in thread
From: kbuild test robot @ 2015-12-17 13:44 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Tomasz,

[auto build test ERROR on v4.4-rc4]
[also build test ERROR on next-20151217]
[cannot apply to tip/irq/core v4.4-rc5]

url:    https://github.com/0day-ci/linux/commits/Tomasz-Nowicki/Introduce-ACPI-world-to-GICv3-ITS-irqchip/20151217-195910
config: arm-allyesconfig (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=arm 

All errors (new ones prefixed by >>):

   drivers/irqchip/irq-gic-v3.c: In function 'gic_irq_domain_translate':
>> drivers/irqchip/irq-gic-v3.c:768:2: error: implicit declaration of function 'is_fwnode_irqchip' [-Werror=implicit-function-declaration]
     if (is_fwnode_irqchip(fwspec->fwnode)) {
     ^
   cc1: some warnings being treated as errors

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

   762			}
   763	
   764			*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
   765			return 0;
   766		}
   767	
 > 768		if (is_fwnode_irqchip(fwspec->fwnode)) {
   769			if(fwspec->param_count != 2)
   770				return -EINVAL;
   771	

---
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: 53975 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20151217/e540faaf/attachment-0001.obj>

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

* Re: [PATCH V2 02/10] irqchip / GICv3: Add ACPI support for GICv3+ initialization
  2015-12-17 13:44     ` kbuild test robot
@ 2015-12-17 15:12       ` Tomasz Nowicki
  -1 siblings, 0 replies; 62+ messages in thread
From: Tomasz Nowicki @ 2015-12-17 15:12 UTC (permalink / raw)
  To: kbuild test robot
  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

On 17.12.2015 14:44, kbuild test robot wrote:
> Hi Tomasz,
>
> [auto build test ERROR on v4.4-rc4]
> [also build test ERROR on next-20151217]
> [cannot apply to tip/irq/core v4.4-rc5]
>
> url:    https://github.com/0day-ci/linux/commits/Tomasz-Nowicki/Introduce-ACPI-world-to-GICv3-ITS-irqchip/20151217-195910
> config: arm-allyesconfig (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=arm
>
> All errors (new ones prefixed by >>):
>
>     drivers/irqchip/irq-gic-v3.c: In function 'gic_irq_domain_translate':
>>> drivers/irqchip/irq-gic-v3.c:768:2: error: implicit declaration of function 'is_fwnode_irqchip' [-Werror=implicit-function-declaration]
>       if (is_fwnode_irqchip(fwspec->fwnode)) {
>       ^
>     cc1: some warnings being treated as errors
>
> vim +/is_fwnode_irqchip +768 drivers/irqchip/irq-gic-v3.c
>
>     762			}
>     763	
>     764			*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
>     765			return 0;
>     766		}
>     767	
>   > 768		if (is_fwnode_irqchip(fwspec->fwnode)) {
>     769			if(fwspec->param_count != 2)
>     770				return -EINVAL;
>     771	
>

It is because I missed irqdomain.h header for irq-gic-v3.c and 
irq-gic-v3-its.c files. Fixed in version 3.

Tomasz

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

* [PATCH V2 02/10] irqchip / GICv3: Add ACPI support for GICv3+ initialization
@ 2015-12-17 15:12       ` Tomasz Nowicki
  0 siblings, 0 replies; 62+ messages in thread
From: Tomasz Nowicki @ 2015-12-17 15:12 UTC (permalink / raw)
  To: linux-arm-kernel

On 17.12.2015 14:44, kbuild test robot wrote:
> Hi Tomasz,
>
> [auto build test ERROR on v4.4-rc4]
> [also build test ERROR on next-20151217]
> [cannot apply to tip/irq/core v4.4-rc5]
>
> url:    https://github.com/0day-ci/linux/commits/Tomasz-Nowicki/Introduce-ACPI-world-to-GICv3-ITS-irqchip/20151217-195910
> config: arm-allyesconfig (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=arm
>
> All errors (new ones prefixed by >>):
>
>     drivers/irqchip/irq-gic-v3.c: In function 'gic_irq_domain_translate':
>>> drivers/irqchip/irq-gic-v3.c:768:2: error: implicit declaration of function 'is_fwnode_irqchip' [-Werror=implicit-function-declaration]
>       if (is_fwnode_irqchip(fwspec->fwnode)) {
>       ^
>     cc1: some warnings being treated as errors
>
> vim +/is_fwnode_irqchip +768 drivers/irqchip/irq-gic-v3.c
>
>     762			}
>     763	
>     764			*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
>     765			return 0;
>     766		}
>     767	
>   > 768		if (is_fwnode_irqchip(fwspec->fwnode)) {
>     769			if(fwspec->param_count != 2)
>     770				return -EINVAL;
>     771	
>

It is because I missed irqdomain.h header for irq-gic-v3.c and 
irq-gic-v3-its.c files. Fixed in version 3.

Tomasz

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

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

On 2015/12/17 19:52, Tomasz Nowicki wrote:
> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
> Signed-off-by: Tomasz Nowicki <tn@semihalf.com>

Missing change log here?

Thanks
Hanjun

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

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

On 2015/12/17 19:52, Tomasz Nowicki wrote:
> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
> Signed-off-by: Tomasz Nowicki <tn@semihalf.com>

Missing change log here?

Thanks
Hanjun


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

* [PATCH V2 06/10] irqchip/GICv3/ITS: Refator ITS dt init code to prepare for ACPI.
@ 2015-12-18 10:57     ` Hanjun Guo
  0 siblings, 0 replies; 62+ messages in thread
From: Hanjun Guo @ 2015-12-18 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

On 2015/12/17 19:52, Tomasz Nowicki wrote:
> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
> Signed-off-by: Tomasz Nowicki <tn@semihalf.com>

Missing change log here?

Thanks
Hanjun

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

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

On 18.12.2015 11:57, Hanjun Guo wrote:
> On 2015/12/17 19:52, Tomasz Nowicki wrote:
>> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
>> Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
>
> Missing change log here?
>
I think that subject explains patch changes, if not I will add more 
detailed description, let me know.

Tomasz

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

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

On 18.12.2015 11:57, Hanjun Guo wrote:
> On 2015/12/17 19:52, Tomasz Nowicki wrote:
>> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
>> Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
>
> Missing change log here?
>
I think that subject explains patch changes, if not I will add more 
detailed description, let me know.

Tomasz

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

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

On 2015/12/17 19:52, Tomasz Nowicki wrote:
> +++ b/include/linux/iort.h
> @@ -0,0 +1,38 @@
> +/*
> + * Copyright (C) 2015, Linaro Ltd.
> + *	Author: Tomasz Nowicki <tomasz.nowicki@linaro.org>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
> + * Place - Suite 330, Boston, MA 02111-1307 USA.
> + */
> +
> +#ifndef __IORT_H__
> +#define __IORT_H__
> +
> +#include <linux/acpi.h>
> +
> +#ifdef CONFIG_ACPI

I think we need use CONFIG_IORT_TABLE here, or the code will be compiled
error on no-ARM64 platform, and it will lead to undefined function, just as
the kbuild test robot pointed out:

All errors (new ones prefixed by >>):

   drivers/built-in.o: In function `pci_msi_domain_get_msi_rid':

>> (.text+0x3175d): undefined reference to `iort_find_pci_id'


Thanks
Hanjun
> +
> +struct fwnode_handle;
> +
> +int iort_register_domain_token(int trans_id, struct fwnode_handle *fw_node);
> +struct fwnode_handle *iort_find_its_domain_token(int trans_id);
> +struct fwnode_handle *iort_find_pci_domain_token(struct device *dev);
> +int iort_find_pci_id(struct pci_dev *pdev, u32 req_id, u32 *dev_id);
> +#else /* CONFIG_ACPI */
> +static inline int
> +iort_find_pci_id(struct pci_dev *pdev, u32 req_id, u32 *dev_id)
> +{ return -ENXIO; }
> +#endif /* CONFIG_ACPI */
> +
> +#endif /* __IORT_H__ */

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

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

On 2015/12/17 19:52, Tomasz Nowicki wrote:
> +++ b/include/linux/iort.h
> @@ -0,0 +1,38 @@
> +/*
> + * Copyright (C) 2015, Linaro Ltd.
> + *	Author: Tomasz Nowicki <tomasz.nowicki@linaro.org>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
> + * Place - Suite 330, Boston, MA 02111-1307 USA.
> + */
> +
> +#ifndef __IORT_H__
> +#define __IORT_H__
> +
> +#include <linux/acpi.h>
> +
> +#ifdef CONFIG_ACPI

I think we need use CONFIG_IORT_TABLE here, or the code will be compiled
error on no-ARM64 platform, and it will lead to undefined function, just as
the kbuild test robot pointed out:

All errors (new ones prefixed by >>):

   drivers/built-in.o: In function `pci_msi_domain_get_msi_rid':

>> (.text+0x3175d): undefined reference to `iort_find_pci_id'


Thanks
Hanjun
> +
> +struct fwnode_handle;
> +
> +int iort_register_domain_token(int trans_id, struct fwnode_handle *fw_node);
> +struct fwnode_handle *iort_find_its_domain_token(int trans_id);
> +struct fwnode_handle *iort_find_pci_domain_token(struct device *dev);
> +int iort_find_pci_id(struct pci_dev *pdev, u32 req_id, u32 *dev_id);
> +#else /* CONFIG_ACPI */
> +static inline int
> +iort_find_pci_id(struct pci_dev *pdev, u32 req_id, u32 *dev_id)
> +{ return -ENXIO; }
> +#endif /* CONFIG_ACPI */
> +
> +#endif /* __IORT_H__ */



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

* [PATCH V2 07/10] ARM64, ACPI, PCI: I/O Remapping Table (IORT) initial support.
@ 2015-12-18 11:18     ` Hanjun Guo
  0 siblings, 0 replies; 62+ messages in thread
From: Hanjun Guo @ 2015-12-18 11:18 UTC (permalink / raw)
  To: linux-arm-kernel

On 2015/12/17 19:52, Tomasz Nowicki wrote:
> +++ b/include/linux/iort.h
> @@ -0,0 +1,38 @@
> +/*
> + * Copyright (C) 2015, Linaro Ltd.
> + *	Author: Tomasz Nowicki <tomasz.nowicki@linaro.org>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
> + * Place - Suite 330, Boston, MA 02111-1307 USA.
> + */
> +
> +#ifndef __IORT_H__
> +#define __IORT_H__
> +
> +#include <linux/acpi.h>
> +
> +#ifdef CONFIG_ACPI

I think we need use CONFIG_IORT_TABLE here, or the code will be compiled
error on no-ARM64 platform, and it will lead to undefined function, just as
the kbuild test robot pointed out:

All errors (new ones prefixed by >>):

   drivers/built-in.o: In function `pci_msi_domain_get_msi_rid':

>> (.text+0x3175d): undefined reference to `iort_find_pci_id'


Thanks
Hanjun
> +
> +struct fwnode_handle;
> +
> +int iort_register_domain_token(int trans_id, struct fwnode_handle *fw_node);
> +struct fwnode_handle *iort_find_its_domain_token(int trans_id);
> +struct fwnode_handle *iort_find_pci_domain_token(struct device *dev);
> +int iort_find_pci_id(struct pci_dev *pdev, u32 req_id, u32 *dev_id);
> +#else /* CONFIG_ACPI */
> +static inline int
> +iort_find_pci_id(struct pci_dev *pdev, u32 req_id, u32 *dev_id)
> +{ return -ENXIO; }
> +#endif /* CONFIG_ACPI */
> +
> +#endif /* __IORT_H__ */

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

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

On 2015/12/17 21:24, Tomasz Nowicki wrote:
> On 17.12.2015 12:52, Tomasz Nowicki wrote:
>> 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>
>>
>> Conflicts:
>>     drivers/acpi/Kconfig
>
> Sorry for ^^^^ git rebase leftover.
>
>> ---
>>   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/include/linux/iort.h b/include/linux/iort.h
>> new file mode 100644
>> index 0000000..783e8d6
>> --- /dev/null
>> +++ b/include/linux/iort.h
>> @@ -0,0 +1,38 @@
>> +/*
>> + * Copyright (C) 2015, Linaro Ltd.
>> + *    Author: Tomasz Nowicki <tomasz.nowicki@linaro.org>
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms and conditions of the GNU General Public License,
>> + * version 2, as published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope it will be useful, but WITHOUT
>> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
>> + * more details.
>> + *
>> + * You should have received a copy of the GNU General Public License along with
>> + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
>> + * Place - Suite 330, Boston, MA 02111-1307 USA.
>> + */
>> +
>> +#ifndef __IORT_H__
>> +#define __IORT_H__
>> +
>> +#include <linux/acpi.h>
>> +
>> +#ifdef CONFIG_ACPI
>> +
>
> As per kbuild test report, this has to be:
> #ifdef CONFIG_IORT_TABLE
>
> Will be fixed in the next version.

Sorry, I should notice this email before I comment on this patch
as you already find the way to fix it.

Thanks
Hanjun

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

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

On 2015/12/17 21:24, Tomasz Nowicki wrote:
> On 17.12.2015 12:52, Tomasz Nowicki wrote:
>> 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>
>>
>> Conflicts:
>>     drivers/acpi/Kconfig
>
> Sorry for ^^^^ git rebase leftover.
>
>> ---
>>   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/include/linux/iort.h b/include/linux/iort.h
>> new file mode 100644
>> index 0000000..783e8d6
>> --- /dev/null
>> +++ b/include/linux/iort.h
>> @@ -0,0 +1,38 @@
>> +/*
>> + * Copyright (C) 2015, Linaro Ltd.
>> + *    Author: Tomasz Nowicki <tomasz.nowicki@linaro.org>
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms and conditions of the GNU General Public License,
>> + * version 2, as published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope it will be useful, but WITHOUT
>> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
>> + * more details.
>> + *
>> + * You should have received a copy of the GNU General Public License along with
>> + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
>> + * Place - Suite 330, Boston, MA 02111-1307 USA.
>> + */
>> +
>> +#ifndef __IORT_H__
>> +#define __IORT_H__
>> +
>> +#include <linux/acpi.h>
>> +
>> +#ifdef CONFIG_ACPI
>> +
>
> As per kbuild test report, this has to be:
> #ifdef CONFIG_IORT_TABLE
>
> Will be fixed in the next version.

Sorry, I should notice this email before I comment on this patch
as you already find the way to fix it.

Thanks
Hanjun


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

* [PATCH V2 07/10] ARM64, ACPI, PCI: I/O Remapping Table (IORT) initial support.
@ 2015-12-18 12:11       ` Hanjun Guo
  0 siblings, 0 replies; 62+ messages in thread
From: Hanjun Guo @ 2015-12-18 12:11 UTC (permalink / raw)
  To: linux-arm-kernel

On 2015/12/17 21:24, Tomasz Nowicki wrote:
> On 17.12.2015 12:52, Tomasz Nowicki wrote:
>> 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>
>>
>> Conflicts:
>>     drivers/acpi/Kconfig
>
> Sorry for ^^^^ git rebase leftover.
>
>> ---
>>   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/include/linux/iort.h b/include/linux/iort.h
>> new file mode 100644
>> index 0000000..783e8d6
>> --- /dev/null
>> +++ b/include/linux/iort.h
>> @@ -0,0 +1,38 @@
>> +/*
>> + * Copyright (C) 2015, Linaro Ltd.
>> + *    Author: Tomasz Nowicki <tomasz.nowicki@linaro.org>
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms and conditions of the GNU General Public License,
>> + * version 2, as published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope it will be useful, but WITHOUT
>> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
>> + * more details.
>> + *
>> + * You should have received a copy of the GNU General Public License along with
>> + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
>> + * Place - Suite 330, Boston, MA 02111-1307 USA.
>> + */
>> +
>> +#ifndef __IORT_H__
>> +#define __IORT_H__
>> +
>> +#include <linux/acpi.h>
>> +
>> +#ifdef CONFIG_ACPI
>> +
>
> As per kbuild test report, this has to be:
> #ifdef CONFIG_IORT_TABLE
>
> Will be fixed in the next version.

Sorry, I should notice this email before I comment on this patch
as you already find the way to fix it.

Thanks
Hanjun

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

* Re: [PATCH V2 03/10] irqchip,GICv3,ACPI: Add redistributor support via GICC structures.
  2015-12-17 11:52   ` [PATCH V2 03/10] irqchip, GICv3, ACPI: " Tomasz Nowicki
@ 2016-01-12 12:03     ` Marc Zyngier
  -1 siblings, 0 replies; 62+ messages in thread
From: Marc Zyngier @ 2016-01-12 12:03 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 17/12/15 11:52, Tomasz Nowicki wrote:
> On systems supporting GICv3 and above, in MADT GICC structures, the
> field of GICR Base Address holds the 64-bit physical address of the
> associated Redistributor if the GIC Redistributors are not in the
> always-on power domain, so instead of init GICR regions via GIC
> redistributor structure(s), init it with GICR base address in GICC
> structures in that case.
> 
> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
> Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
> ---
>  drivers/irqchip/irq-gic-v3.c | 98 ++++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 89 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
> index c4b929c..0528e82 100644
> --- a/drivers/irqchip/irq-gic-v3.c
> +++ b/drivers/irqchip/irq-gic-v3.c
> @@ -39,6 +39,7 @@
>  struct redist_region {
>  	void __iomem		*redist_base;
>  	phys_addr_t		phys_base;
> +	bool			single_redist;
>  };
>  
>  struct gic_chip_data {
> @@ -435,6 +436,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 {
> @@ -965,6 +969,7 @@ IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
>  #ifdef CONFIG_ACPI
>  static struct redist_region *redist_regs __initdata;
>  static u32 nr_redist_regions __initdata;
> +static bool single_redist;
>  
>  static int __init
>  gic_acpi_register_redist(phys_addr_t phys_base, u64 size)
> @@ -979,7 +984,8 @@ gic_acpi_register_redist(phys_addr_t phys_base, u64 size)
>  	}
>  
>  	redist_regs[count].phys_base = phys_base;
> -	redist_regs[count++].redist_base = redist_base;
> +	redist_regs[count].redist_base = redist_base;

nit: move the count++ out of the access in the previous patch, this will
make this series a bit easier to follow.

> +	redist_regs[count++].single_redist = single_redist;

What is that single_redist for? Is that because you can't rely on
GICR_TYPER.Last?

>  	return 0;
>  }
>  
> @@ -993,6 +999,48 @@ gic_acpi_parse_madt_redist(struct acpi_subtable_header *header,
>  	return gic_acpi_register_redist(redist->base_address, redist->length);
>  }
>  
> +static int __init
> +gic_acpi_parse_madt_gicc(struct acpi_subtable_header *header,
> +			 const unsigned long end)
> +{
> +	struct acpi_madt_generic_interrupt *gicc;
> +	void __iomem *redist_base;
> +	u64 typer;
> +	u32 size;
> +
> +	gicc = (struct acpi_madt_generic_interrupt *)header;
> +	redist_base = ioremap(gicc->gicr_base_address, SZ_64K * 2);
> +	if (!redist_base)
> +		return -ENOMEM;
> +
> +	typer = readq_relaxed(redist_base + GICR_TYPER);
> +	/* don't map reserved page as it's buggy to access it */
> +	size = (typer & GICR_TYPER_VLPIS) ? SZ_64K * 3 : SZ_64K * 2;
> +	iounmap(redist_base);

What a mess. If you discover a !VLPIS redistributor, why do you have to
unmap it to remap it again? Also, please map the whole region for the
redistributor as we have on the DT side (4 64kB pages for VLPIS capable
redistributors).

Also, the spec says:

"On systems supporting GICv3 and above, this field 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."

which triggers two questions:
- Can you access always the GICR_TYPER register without waking the
redistributor up?
- How do you cope with situations where some redistributors are in the
always-on domain, and some are not?

> +	return gic_acpi_register_redist(gicc->gicr_base_address, size);
> +}
> +
> +static int __init gic_acpi_collect_gicr_base(void)
> +{
> +	acpi_tbl_entry_handler redist_parser;
> +	enum acpi_madt_type type;
> +
> +	if (single_redist) {
> +		type = ACPI_MADT_TYPE_GENERIC_INTERRUPT;
> +		redist_parser = gic_acpi_parse_madt_gicc;
> +	} else {
> +		type = ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR;
> +		redist_parser = gic_acpi_parse_madt_redist;
> +	}
> +
> +	/* Collect redistributor base addresses in GICR entries */
> +	if (acpi_table_parse_madt(type, redist_parser, 0) > 0)
> +		return 0;
> +
> +	pr_info("No valid GICR entries exist\n");
> +	return -ENODEV;
> +}
> +
>  static int __init gic_acpi_match_gicr(struct acpi_subtable_header *header,
>  				  const unsigned long end)
>  {
> @@ -1000,6 +1048,42 @@ static int __init gic_acpi_match_gicr(struct acpi_subtable_header *header,
>  	return 0;
>  }
>  
> +static int __init gic_acpi_match_gicc(struct acpi_subtable_header *header,
> +				      const unsigned long end)
> +{
> +	struct acpi_madt_generic_interrupt *gicc =
> +				(struct acpi_madt_generic_interrupt *)header;
> +
> +	/*
> +	 * If GICC is enabled and has valid gicr base address, then it means
> +	 * GICR base is presented via GICC
> +	 */
> +	if ((gicc->flags & ACPI_MADT_ENABLED) && gicc->gicr_base_address)
> +		return 0;
> +
> +	return -ENODEV;
> +}
> +
> +static int __init gic_acpi_count_gicr_regions(void)
> +{
> +	int count;
> +
> +	/* Count how many redistributor regions we have */
> +	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
> +				      gic_acpi_match_gicr, 0);
> +	if (count > 0) {
> +		single_redist = false;
> +		return count;
> +	}
> +
> +	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
> +				      gic_acpi_match_gicc, 0);
> +	if (count > 0)
> +		single_redist = true;
> +
> +	return count;
> +}
> +

Here, you seem to consider GICR and GICC tables to be mutually
exclusive. I don't think the spec says so.

>  static bool __init acpi_validate_gic_table(struct acpi_subtable_header *header,
>  					   struct acpi_probe_entry *ape)
>  {
> @@ -1011,8 +1095,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;
>  
> @@ -1028,7 +1111,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;
> @@ -1051,12 +1134,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) {
> 

Thanks,

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

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

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

On 17/12/15 11:52, Tomasz Nowicki wrote:
> On systems supporting GICv3 and above, in MADT GICC structures, the
> field of GICR Base Address holds the 64-bit physical address of the
> associated Redistributor if the GIC Redistributors are not in the
> always-on power domain, so instead of init GICR regions via GIC
> redistributor structure(s), init it with GICR base address in GICC
> structures in that case.
> 
> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
> Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
> ---
>  drivers/irqchip/irq-gic-v3.c | 98 ++++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 89 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
> index c4b929c..0528e82 100644
> --- a/drivers/irqchip/irq-gic-v3.c
> +++ b/drivers/irqchip/irq-gic-v3.c
> @@ -39,6 +39,7 @@
>  struct redist_region {
>  	void __iomem		*redist_base;
>  	phys_addr_t		phys_base;
> +	bool			single_redist;
>  };
>  
>  struct gic_chip_data {
> @@ -435,6 +436,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 {
> @@ -965,6 +969,7 @@ IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
>  #ifdef CONFIG_ACPI
>  static struct redist_region *redist_regs __initdata;
>  static u32 nr_redist_regions __initdata;
> +static bool single_redist;
>  
>  static int __init
>  gic_acpi_register_redist(phys_addr_t phys_base, u64 size)
> @@ -979,7 +984,8 @@ gic_acpi_register_redist(phys_addr_t phys_base, u64 size)
>  	}
>  
>  	redist_regs[count].phys_base = phys_base;
> -	redist_regs[count++].redist_base = redist_base;
> +	redist_regs[count].redist_base = redist_base;

nit: move the count++ out of the access in the previous patch, this will
make this series a bit easier to follow.

> +	redist_regs[count++].single_redist = single_redist;

What is that single_redist for? Is that because you can't rely on
GICR_TYPER.Last?

>  	return 0;
>  }
>  
> @@ -993,6 +999,48 @@ gic_acpi_parse_madt_redist(struct acpi_subtable_header *header,
>  	return gic_acpi_register_redist(redist->base_address, redist->length);
>  }
>  
> +static int __init
> +gic_acpi_parse_madt_gicc(struct acpi_subtable_header *header,
> +			 const unsigned long end)
> +{
> +	struct acpi_madt_generic_interrupt *gicc;
> +	void __iomem *redist_base;
> +	u64 typer;
> +	u32 size;
> +
> +	gicc = (struct acpi_madt_generic_interrupt *)header;
> +	redist_base = ioremap(gicc->gicr_base_address, SZ_64K * 2);
> +	if (!redist_base)
> +		return -ENOMEM;
> +
> +	typer = readq_relaxed(redist_base + GICR_TYPER);
> +	/* don't map reserved page as it's buggy to access it */
> +	size = (typer & GICR_TYPER_VLPIS) ? SZ_64K * 3 : SZ_64K * 2;
> +	iounmap(redist_base);

What a mess. If you discover a !VLPIS redistributor, why do you have to
unmap it to remap it again? Also, please map the whole region for the
redistributor as we have on the DT side (4 64kB pages for VLPIS capable
redistributors).

Also, the spec says:

"On systems supporting GICv3 and above, this field 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."

which triggers two questions:
- Can you access always the GICR_TYPER register without waking the
redistributor up?
- How do you cope with situations where some redistributors are in the
always-on domain, and some are not?

> +	return gic_acpi_register_redist(gicc->gicr_base_address, size);
> +}
> +
> +static int __init gic_acpi_collect_gicr_base(void)
> +{
> +	acpi_tbl_entry_handler redist_parser;
> +	enum acpi_madt_type type;
> +
> +	if (single_redist) {
> +		type = ACPI_MADT_TYPE_GENERIC_INTERRUPT;
> +		redist_parser = gic_acpi_parse_madt_gicc;
> +	} else {
> +		type = ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR;
> +		redist_parser = gic_acpi_parse_madt_redist;
> +	}
> +
> +	/* Collect redistributor base addresses in GICR entries */
> +	if (acpi_table_parse_madt(type, redist_parser, 0) > 0)
> +		return 0;
> +
> +	pr_info("No valid GICR entries exist\n");
> +	return -ENODEV;
> +}
> +
>  static int __init gic_acpi_match_gicr(struct acpi_subtable_header *header,
>  				  const unsigned long end)
>  {
> @@ -1000,6 +1048,42 @@ static int __init gic_acpi_match_gicr(struct acpi_subtable_header *header,
>  	return 0;
>  }
>  
> +static int __init gic_acpi_match_gicc(struct acpi_subtable_header *header,
> +				      const unsigned long end)
> +{
> +	struct acpi_madt_generic_interrupt *gicc =
> +				(struct acpi_madt_generic_interrupt *)header;
> +
> +	/*
> +	 * If GICC is enabled and has valid gicr base address, then it means
> +	 * GICR base is presented via GICC
> +	 */
> +	if ((gicc->flags & ACPI_MADT_ENABLED) && gicc->gicr_base_address)
> +		return 0;
> +
> +	return -ENODEV;
> +}
> +
> +static int __init gic_acpi_count_gicr_regions(void)
> +{
> +	int count;
> +
> +	/* Count how many redistributor regions we have */
> +	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
> +				      gic_acpi_match_gicr, 0);
> +	if (count > 0) {
> +		single_redist = false;
> +		return count;
> +	}
> +
> +	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
> +				      gic_acpi_match_gicc, 0);
> +	if (count > 0)
> +		single_redist = true;
> +
> +	return count;
> +}
> +

Here, you seem to consider GICR and GICC tables to be mutually
exclusive. I don't think the spec says so.

>  static bool __init acpi_validate_gic_table(struct acpi_subtable_header *header,
>  					   struct acpi_probe_entry *ape)
>  {
> @@ -1011,8 +1095,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;
>  
> @@ -1028,7 +1111,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;
> @@ -1051,12 +1134,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) {
> 

Thanks,

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

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

* Re: [PATCH V2 03/10] irqchip,GICv3,ACPI: Add redistributor support via GICC structures.
  2016-01-12 12:03     ` Marc Zyngier
@ 2016-01-12 15:05       ` Hanjun Guo
  -1 siblings, 0 replies; 62+ messages in thread
From: Hanjun Guo @ 2016-01-12 15:05 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 01/12/2016 08:03 PM, Marc Zyngier wrote:
> On 17/12/15 11:52, Tomasz Nowicki wrote:
>> On systems supporting GICv3 and above, in MADT GICC structures, the
>> field of GICR Base Address holds the 64-bit physical address of the
>> associated Redistributor if the GIC Redistributors are not in the
>> always-on power domain, so instead of init GICR regions via GIC
>> redistributor structure(s), init it with GICR base address in GICC
>> structures in that case.
>>
>> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
>> Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
>> ---
>>   drivers/irqchip/irq-gic-v3.c | 98 ++++++++++++++++++++++++++++++++++++++++----
>>   1 file changed, 89 insertions(+), 9 deletions(-)
>>
>> diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
>> index c4b929c..0528e82 100644
>> --- a/drivers/irqchip/irq-gic-v3.c
>> +++ b/drivers/irqchip/irq-gic-v3.c
>> @@ -39,6 +39,7 @@
>>   struct redist_region {
>>   	void __iomem		*redist_base;
>>   	phys_addr_t		phys_base;
>> +	bool			single_redist;
>>   };
>>
>>   struct gic_chip_data {
>> @@ -435,6 +436,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 {
>> @@ -965,6 +969,7 @@ IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
>>   #ifdef CONFIG_ACPI
>>   static struct redist_region *redist_regs __initdata;
>>   static u32 nr_redist_regions __initdata;
>> +static bool single_redist;
>>
>>   static int __init
>>   gic_acpi_register_redist(phys_addr_t phys_base, u64 size)
>> @@ -979,7 +984,8 @@ gic_acpi_register_redist(phys_addr_t phys_base, u64 size)
>>   	}
>>
>>   	redist_regs[count].phys_base = phys_base;
>> -	redist_regs[count++].redist_base = redist_base;
>> +	redist_regs[count].redist_base = redist_base;
>
> nit: move the count++ out of the access in the previous patch, this will
> make this series a bit easier to follow.

OK.

>
>> +	redist_regs[count++].single_redist = single_redist;
>
> What is that single_redist for? Is that because you can't rely on
> GICR_TYPER.Last?

Yes, there is no GICR_TYPER.Last bit for some redistributors,
as it's valid for redistributor regions.

>
>>   	return 0;
>>   }
>>
>> @@ -993,6 +999,48 @@ gic_acpi_parse_madt_redist(struct acpi_subtable_header *header,
>>   	return gic_acpi_register_redist(redist->base_address, redist->length);
>>   }
>>
>> +static int __init
>> +gic_acpi_parse_madt_gicc(struct acpi_subtable_header *header,
>> +			 const unsigned long end)
>> +{
>> +	struct acpi_madt_generic_interrupt *gicc;
>> +	void __iomem *redist_base;
>> +	u64 typer;
>> +	u32 size;
>> +
>> +	gicc = (struct acpi_madt_generic_interrupt *)header;
>> +	redist_base = ioremap(gicc->gicr_base_address, SZ_64K * 2);
>> +	if (!redist_base)
>> +		return -ENOMEM;
>> +
>> +	typer = readq_relaxed(redist_base + GICR_TYPER);
>> +	/* don't map reserved page as it's buggy to access it */
>> +	size = (typer & GICR_TYPER_VLPIS) ? SZ_64K * 3 : SZ_64K * 2;
>> +	iounmap(redist_base);
>
> What a mess. If you discover a !VLPIS redistributor, why do you have to
> unmap it to remap it again? Also, please map the whole region for the

I think I missed something here, I didn't know it's GICv3 or v4, I need
to check the GICR_TYPER first, then decide map 2 or 4 SZ_64K pages.

> redistributor as we have on the DT side (4 64kB pages for VLPIS capable
> redistributors).
>
> Also, the spec says:
>
> "On systems supporting GICv3 and above, this field 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."
>
> which triggers two questions:
> - Can you access always the GICR_TYPER register without waking the
> redistributor up?

I missed this part, can you suggest how can we do that? accessing some
register before access to redistributor?

> - How do you cope with situations where some redistributors are in the
> always-on domain, and some are not?

I'm not sure if there is such hardware, if yes, do we need to fix
the spec first?

>
>> +	return gic_acpi_register_redist(gicc->gicr_base_address, size);
>> +}
>> +
>> +static int __init gic_acpi_collect_gicr_base(void)
>> +{
>> +	acpi_tbl_entry_handler redist_parser;
>> +	enum acpi_madt_type type;
>> +
>> +	if (single_redist) {
>> +		type = ACPI_MADT_TYPE_GENERIC_INTERRUPT;
>> +		redist_parser = gic_acpi_parse_madt_gicc;
>> +	} else {
>> +		type = ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR;
>> +		redist_parser = gic_acpi_parse_madt_redist;
>> +	}
>> +
>> +	/* Collect redistributor base addresses in GICR entries */
>> +	if (acpi_table_parse_madt(type, redist_parser, 0) > 0)
>> +		return 0;
>> +
>> +	pr_info("No valid GICR entries exist\n");
>> +	return -ENODEV;
>> +}
>> +
>>   static int __init gic_acpi_match_gicr(struct acpi_subtable_header *header,
>>   				  const unsigned long end)
>>   {
>> @@ -1000,6 +1048,42 @@ static int __init gic_acpi_match_gicr(struct acpi_subtable_header *header,
>>   	return 0;
>>   }
>>
>> +static int __init gic_acpi_match_gicc(struct acpi_subtable_header *header,
>> +				      const unsigned long end)
>> +{
>> +	struct acpi_madt_generic_interrupt *gicc =
>> +				(struct acpi_madt_generic_interrupt *)header;
>> +
>> +	/*
>> +	 * If GICC is enabled and has valid gicr base address, then it means
>> +	 * GICR base is presented via GICC
>> +	 */
>> +	if ((gicc->flags & ACPI_MADT_ENABLED) && gicc->gicr_base_address)
>> +		return 0;
>> +
>> +	return -ENODEV;
>> +}
>> +
>> +static int __init gic_acpi_count_gicr_regions(void)
>> +{
>> +	int count;
>> +
>> +	/* Count how many redistributor regions we have */
>> +	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
>> +				      gic_acpi_match_gicr, 0);
>> +	if (count > 0) {
>> +		single_redist = false;
>> +		return count;
>> +	}
>> +
>> +	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
>> +				      gic_acpi_match_gicc, 0);
>> +	if (count > 0)
>> +		single_redist = true;
>> +
>> +	return count;
>> +}
>> +
>
> Here, you seem to consider GICR and GICC tables to be mutually
> exclusive. I don't think the spec says so.

Good question, I will ask Charles first about it.

Thanks
Hanjun

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

* [PATCH V2 03/10] irqchip,GICv3,ACPI: Add redistributor support via GICC structures.
@ 2016-01-12 15:05       ` Hanjun Guo
  0 siblings, 0 replies; 62+ messages in thread
From: Hanjun Guo @ 2016-01-12 15:05 UTC (permalink / raw)
  To: linux-arm-kernel

On 01/12/2016 08:03 PM, Marc Zyngier wrote:
> On 17/12/15 11:52, Tomasz Nowicki wrote:
>> On systems supporting GICv3 and above, in MADT GICC structures, the
>> field of GICR Base Address holds the 64-bit physical address of the
>> associated Redistributor if the GIC Redistributors are not in the
>> always-on power domain, so instead of init GICR regions via GIC
>> redistributor structure(s), init it with GICR base address in GICC
>> structures in that case.
>>
>> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
>> Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
>> ---
>>   drivers/irqchip/irq-gic-v3.c | 98 ++++++++++++++++++++++++++++++++++++++++----
>>   1 file changed, 89 insertions(+), 9 deletions(-)
>>
>> diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
>> index c4b929c..0528e82 100644
>> --- a/drivers/irqchip/irq-gic-v3.c
>> +++ b/drivers/irqchip/irq-gic-v3.c
>> @@ -39,6 +39,7 @@
>>   struct redist_region {
>>   	void __iomem		*redist_base;
>>   	phys_addr_t		phys_base;
>> +	bool			single_redist;
>>   };
>>
>>   struct gic_chip_data {
>> @@ -435,6 +436,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 {
>> @@ -965,6 +969,7 @@ IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
>>   #ifdef CONFIG_ACPI
>>   static struct redist_region *redist_regs __initdata;
>>   static u32 nr_redist_regions __initdata;
>> +static bool single_redist;
>>
>>   static int __init
>>   gic_acpi_register_redist(phys_addr_t phys_base, u64 size)
>> @@ -979,7 +984,8 @@ gic_acpi_register_redist(phys_addr_t phys_base, u64 size)
>>   	}
>>
>>   	redist_regs[count].phys_base = phys_base;
>> -	redist_regs[count++].redist_base = redist_base;
>> +	redist_regs[count].redist_base = redist_base;
>
> nit: move the count++ out of the access in the previous patch, this will
> make this series a bit easier to follow.

OK.

>
>> +	redist_regs[count++].single_redist = single_redist;
>
> What is that single_redist for? Is that because you can't rely on
> GICR_TYPER.Last?

Yes, there is no GICR_TYPER.Last bit for some redistributors,
as it's valid for redistributor regions.

>
>>   	return 0;
>>   }
>>
>> @@ -993,6 +999,48 @@ gic_acpi_parse_madt_redist(struct acpi_subtable_header *header,
>>   	return gic_acpi_register_redist(redist->base_address, redist->length);
>>   }
>>
>> +static int __init
>> +gic_acpi_parse_madt_gicc(struct acpi_subtable_header *header,
>> +			 const unsigned long end)
>> +{
>> +	struct acpi_madt_generic_interrupt *gicc;
>> +	void __iomem *redist_base;
>> +	u64 typer;
>> +	u32 size;
>> +
>> +	gicc = (struct acpi_madt_generic_interrupt *)header;
>> +	redist_base = ioremap(gicc->gicr_base_address, SZ_64K * 2);
>> +	if (!redist_base)
>> +		return -ENOMEM;
>> +
>> +	typer = readq_relaxed(redist_base + GICR_TYPER);
>> +	/* don't map reserved page as it's buggy to access it */
>> +	size = (typer & GICR_TYPER_VLPIS) ? SZ_64K * 3 : SZ_64K * 2;
>> +	iounmap(redist_base);
>
> What a mess. If you discover a !VLPIS redistributor, why do you have to
> unmap it to remap it again? Also, please map the whole region for the

I think I missed something here, I didn't know it's GICv3 or v4, I need
to check the GICR_TYPER first, then decide map 2 or 4 SZ_64K pages.

> redistributor as we have on the DT side (4 64kB pages for VLPIS capable
> redistributors).
>
> Also, the spec says:
>
> "On systems supporting GICv3 and above, this field 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."
>
> which triggers two questions:
> - Can you access always the GICR_TYPER register without waking the
> redistributor up?

I missed this part, can you suggest how can we do that? accessing some
register before access to redistributor?

> - How do you cope with situations where some redistributors are in the
> always-on domain, and some are not?

I'm not sure if there is such hardware, if yes, do we need to fix
the spec first?

>
>> +	return gic_acpi_register_redist(gicc->gicr_base_address, size);
>> +}
>> +
>> +static int __init gic_acpi_collect_gicr_base(void)
>> +{
>> +	acpi_tbl_entry_handler redist_parser;
>> +	enum acpi_madt_type type;
>> +
>> +	if (single_redist) {
>> +		type = ACPI_MADT_TYPE_GENERIC_INTERRUPT;
>> +		redist_parser = gic_acpi_parse_madt_gicc;
>> +	} else {
>> +		type = ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR;
>> +		redist_parser = gic_acpi_parse_madt_redist;
>> +	}
>> +
>> +	/* Collect redistributor base addresses in GICR entries */
>> +	if (acpi_table_parse_madt(type, redist_parser, 0) > 0)
>> +		return 0;
>> +
>> +	pr_info("No valid GICR entries exist\n");
>> +	return -ENODEV;
>> +}
>> +
>>   static int __init gic_acpi_match_gicr(struct acpi_subtable_header *header,
>>   				  const unsigned long end)
>>   {
>> @@ -1000,6 +1048,42 @@ static int __init gic_acpi_match_gicr(struct acpi_subtable_header *header,
>>   	return 0;
>>   }
>>
>> +static int __init gic_acpi_match_gicc(struct acpi_subtable_header *header,
>> +				      const unsigned long end)
>> +{
>> +	struct acpi_madt_generic_interrupt *gicc =
>> +				(struct acpi_madt_generic_interrupt *)header;
>> +
>> +	/*
>> +	 * If GICC is enabled and has valid gicr base address, then it means
>> +	 * GICR base is presented via GICC
>> +	 */
>> +	if ((gicc->flags & ACPI_MADT_ENABLED) && gicc->gicr_base_address)
>> +		return 0;
>> +
>> +	return -ENODEV;
>> +}
>> +
>> +static int __init gic_acpi_count_gicr_regions(void)
>> +{
>> +	int count;
>> +
>> +	/* Count how many redistributor regions we have */
>> +	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
>> +				      gic_acpi_match_gicr, 0);
>> +	if (count > 0) {
>> +		single_redist = false;
>> +		return count;
>> +	}
>> +
>> +	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
>> +				      gic_acpi_match_gicc, 0);
>> +	if (count > 0)
>> +		single_redist = true;
>> +
>> +	return count;
>> +}
>> +
>
> Here, you seem to consider GICR and GICC tables to be mutually
> exclusive. I don't think the spec says so.

Good question, I will ask Charles first about it.

Thanks
Hanjun

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

* Re: [PATCH V2 03/10] irqchip,GICv3,ACPI: Add redistributor support via GICC structures.
  2016-01-12 15:05       ` Hanjun Guo
@ 2016-01-12 16:16         ` Marc Zyngier
  -1 siblings, 0 replies; 62+ messages in thread
From: Marc Zyngier @ 2016-01-12 16:16 UTC (permalink / raw)
  To: Hanjun Guo, 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 12/01/16 15:05, Hanjun Guo wrote:
> On 01/12/2016 08:03 PM, Marc Zyngier wrote:
>> On 17/12/15 11:52, Tomasz Nowicki wrote:
>>> On systems supporting GICv3 and above, in MADT GICC structures, the
>>> field of GICR Base Address holds the 64-bit physical address of the
>>> associated Redistributor if the GIC Redistributors are not in the
>>> always-on power domain, so instead of init GICR regions via GIC
>>> redistributor structure(s), init it with GICR base address in GICC
>>> structures in that case.
>>>
>>> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
>>> Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
>>> ---
>>>   drivers/irqchip/irq-gic-v3.c | 98 ++++++++++++++++++++++++++++++++++++++++----
>>>   1 file changed, 89 insertions(+), 9 deletions(-)
>>>
>>> diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
>>> index c4b929c..0528e82 100644
>>> --- a/drivers/irqchip/irq-gic-v3.c
>>> +++ b/drivers/irqchip/irq-gic-v3.c
>>> @@ -39,6 +39,7 @@
>>>   struct redist_region {
>>>   	void __iomem		*redist_base;
>>>   	phys_addr_t		phys_base;
>>> +	bool			single_redist;
>>>   };
>>>
>>>   struct gic_chip_data {
>>> @@ -435,6 +436,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 {
>>> @@ -965,6 +969,7 @@ IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
>>>   #ifdef CONFIG_ACPI
>>>   static struct redist_region *redist_regs __initdata;
>>>   static u32 nr_redist_regions __initdata;
>>> +static bool single_redist;
>>>
>>>   static int __init
>>>   gic_acpi_register_redist(phys_addr_t phys_base, u64 size)
>>> @@ -979,7 +984,8 @@ gic_acpi_register_redist(phys_addr_t phys_base, u64 size)
>>>   	}
>>>
>>>   	redist_regs[count].phys_base = phys_base;
>>> -	redist_regs[count++].redist_base = redist_base;
>>> +	redist_regs[count].redist_base = redist_base;
>>
>> nit: move the count++ out of the access in the previous patch, this will
>> make this series a bit easier to follow.
> 
> OK.
> 
>>
>>> +	redist_regs[count++].single_redist = single_redist;
>>
>> What is that single_redist for? Is that because you can't rely on
>> GICR_TYPER.Last?
> 
> Yes, there is no GICR_TYPER.Last bit for some redistributors,
> as it's valid for redistributor regions.
> 
>>
>>>   	return 0;
>>>   }
>>>
>>> @@ -993,6 +999,48 @@ gic_acpi_parse_madt_redist(struct acpi_subtable_header *header,
>>>   	return gic_acpi_register_redist(redist->base_address, redist->length);
>>>   }
>>>
>>> +static int __init
>>> +gic_acpi_parse_madt_gicc(struct acpi_subtable_header *header,
>>> +			 const unsigned long end)
>>> +{
>>> +	struct acpi_madt_generic_interrupt *gicc;
>>> +	void __iomem *redist_base;
>>> +	u64 typer;
>>> +	u32 size;
>>> +
>>> +	gicc = (struct acpi_madt_generic_interrupt *)header;
>>> +	redist_base = ioremap(gicc->gicr_base_address, SZ_64K * 2);
>>> +	if (!redist_base)
>>> +		return -ENOMEM;
>>> +
>>> +	typer = readq_relaxed(redist_base + GICR_TYPER);
>>> +	/* don't map reserved page as it's buggy to access it */
>>> +	size = (typer & GICR_TYPER_VLPIS) ? SZ_64K * 3 : SZ_64K * 2;
>>> +	iounmap(redist_base);
>>
>> What a mess. If you discover a !VLPIS redistributor, why do you have to
>> unmap it to remap it again? Also, please map the whole region for the
> 
> I think I missed something here, I didn't know it's GICv3 or v4, I need
> to check the GICR_TYPER first, then decide map 2 or 4 SZ_64K pages.

But if you find out it is a v3, you already have it mapped, so why unmap
and then remap in this case?

> 
>> redistributor as we have on the DT side (4 64kB pages for VLPIS capable
>> redistributors).
>>
>> Also, the spec says:
>>
>> "On systems supporting GICv3 and above, this field 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."
>>
>> which triggers two questions:
>> - Can you access always the GICR_TYPER register without waking the
>> redistributor up?
> 
> I missed this part, can you suggest how can we do that? accessing some
> register before access to redistributor?

This redistributor may be in a power-domain that is off. Are you
guaranteed that you can access GICR_TYPER even when it is off?

> 
>> - How do you cope with situations where some redistributors are in the
>> always-on domain, and some are not?
> 
> I'm not sure if there is such hardware, if yes, do we need to fix
> the spec first?

It is something that should definitely be clarified. Can we end-up in a
situation where some redistributors are described via the GICR
structure, and some via the GICC structure? The spec is a bit ambiguous.

>>
>>> +	return gic_acpi_register_redist(gicc->gicr_base_address, size);
>>> +}
>>> +
>>> +static int __init gic_acpi_collect_gicr_base(void)
>>> +{
>>> +	acpi_tbl_entry_handler redist_parser;
>>> +	enum acpi_madt_type type;
>>> +
>>> +	if (single_redist) {
>>> +		type = ACPI_MADT_TYPE_GENERIC_INTERRUPT;
>>> +		redist_parser = gic_acpi_parse_madt_gicc;
>>> +	} else {
>>> +		type = ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR;
>>> +		redist_parser = gic_acpi_parse_madt_redist;
>>> +	}
>>> +
>>> +	/* Collect redistributor base addresses in GICR entries */
>>> +	if (acpi_table_parse_madt(type, redist_parser, 0) > 0)
>>> +		return 0;
>>> +
>>> +	pr_info("No valid GICR entries exist\n");
>>> +	return -ENODEV;
>>> +}
>>> +
>>>   static int __init gic_acpi_match_gicr(struct acpi_subtable_header *header,
>>>   				  const unsigned long end)
>>>   {
>>> @@ -1000,6 +1048,42 @@ static int __init gic_acpi_match_gicr(struct acpi_subtable_header *header,
>>>   	return 0;
>>>   }
>>>
>>> +static int __init gic_acpi_match_gicc(struct acpi_subtable_header *header,
>>> +				      const unsigned long end)
>>> +{
>>> +	struct acpi_madt_generic_interrupt *gicc =
>>> +				(struct acpi_madt_generic_interrupt *)header;
>>> +
>>> +	/*
>>> +	 * If GICC is enabled and has valid gicr base address, then it means
>>> +	 * GICR base is presented via GICC
>>> +	 */
>>> +	if ((gicc->flags & ACPI_MADT_ENABLED) && gicc->gicr_base_address)
>>> +		return 0;
>>> +
>>> +	return -ENODEV;
>>> +}
>>> +
>>> +static int __init gic_acpi_count_gicr_regions(void)
>>> +{
>>> +	int count;
>>> +
>>> +	/* Count how many redistributor regions we have */
>>> +	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
>>> +				      gic_acpi_match_gicr, 0);
>>> +	if (count > 0) {
>>> +		single_redist = false;
>>> +		return count;
>>> +	}
>>> +
>>> +	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
>>> +				      gic_acpi_match_gicc, 0);
>>> +	if (count > 0)
>>> +		single_redist = true;
>>> +
>>> +	return count;
>>> +}
>>> +
>>
>> Here, you seem to consider GICR and GICC tables to be mutually
>> exclusive. I don't think the spec says so.
> 
> Good question, I will ask Charles first about it.

I just did, and he agreed that the spec is ambiguous - but that your
interpretation is probably the correct one. It would be good fix it though.

Thanks,

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

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

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

On 12/01/16 15:05, Hanjun Guo wrote:
> On 01/12/2016 08:03 PM, Marc Zyngier wrote:
>> On 17/12/15 11:52, Tomasz Nowicki wrote:
>>> On systems supporting GICv3 and above, in MADT GICC structures, the
>>> field of GICR Base Address holds the 64-bit physical address of the
>>> associated Redistributor if the GIC Redistributors are not in the
>>> always-on power domain, so instead of init GICR regions via GIC
>>> redistributor structure(s), init it with GICR base address in GICC
>>> structures in that case.
>>>
>>> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
>>> Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
>>> ---
>>>   drivers/irqchip/irq-gic-v3.c | 98 ++++++++++++++++++++++++++++++++++++++++----
>>>   1 file changed, 89 insertions(+), 9 deletions(-)
>>>
>>> diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
>>> index c4b929c..0528e82 100644
>>> --- a/drivers/irqchip/irq-gic-v3.c
>>> +++ b/drivers/irqchip/irq-gic-v3.c
>>> @@ -39,6 +39,7 @@
>>>   struct redist_region {
>>>   	void __iomem		*redist_base;
>>>   	phys_addr_t		phys_base;
>>> +	bool			single_redist;
>>>   };
>>>
>>>   struct gic_chip_data {
>>> @@ -435,6 +436,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 {
>>> @@ -965,6 +969,7 @@ IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
>>>   #ifdef CONFIG_ACPI
>>>   static struct redist_region *redist_regs __initdata;
>>>   static u32 nr_redist_regions __initdata;
>>> +static bool single_redist;
>>>
>>>   static int __init
>>>   gic_acpi_register_redist(phys_addr_t phys_base, u64 size)
>>> @@ -979,7 +984,8 @@ gic_acpi_register_redist(phys_addr_t phys_base, u64 size)
>>>   	}
>>>
>>>   	redist_regs[count].phys_base = phys_base;
>>> -	redist_regs[count++].redist_base = redist_base;
>>> +	redist_regs[count].redist_base = redist_base;
>>
>> nit: move the count++ out of the access in the previous patch, this will
>> make this series a bit easier to follow.
> 
> OK.
> 
>>
>>> +	redist_regs[count++].single_redist = single_redist;
>>
>> What is that single_redist for? Is that because you can't rely on
>> GICR_TYPER.Last?
> 
> Yes, there is no GICR_TYPER.Last bit for some redistributors,
> as it's valid for redistributor regions.
> 
>>
>>>   	return 0;
>>>   }
>>>
>>> @@ -993,6 +999,48 @@ gic_acpi_parse_madt_redist(struct acpi_subtable_header *header,
>>>   	return gic_acpi_register_redist(redist->base_address, redist->length);
>>>   }
>>>
>>> +static int __init
>>> +gic_acpi_parse_madt_gicc(struct acpi_subtable_header *header,
>>> +			 const unsigned long end)
>>> +{
>>> +	struct acpi_madt_generic_interrupt *gicc;
>>> +	void __iomem *redist_base;
>>> +	u64 typer;
>>> +	u32 size;
>>> +
>>> +	gicc = (struct acpi_madt_generic_interrupt *)header;
>>> +	redist_base = ioremap(gicc->gicr_base_address, SZ_64K * 2);
>>> +	if (!redist_base)
>>> +		return -ENOMEM;
>>> +
>>> +	typer = readq_relaxed(redist_base + GICR_TYPER);
>>> +	/* don't map reserved page as it's buggy to access it */
>>> +	size = (typer & GICR_TYPER_VLPIS) ? SZ_64K * 3 : SZ_64K * 2;
>>> +	iounmap(redist_base);
>>
>> What a mess. If you discover a !VLPIS redistributor, why do you have to
>> unmap it to remap it again? Also, please map the whole region for the
> 
> I think I missed something here, I didn't know it's GICv3 or v4, I need
> to check the GICR_TYPER first, then decide map 2 or 4 SZ_64K pages.

But if you find out it is a v3, you already have it mapped, so why unmap
and then remap in this case?

> 
>> redistributor as we have on the DT side (4 64kB pages for VLPIS capable
>> redistributors).
>>
>> Also, the spec says:
>>
>> "On systems supporting GICv3 and above, this field 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."
>>
>> which triggers two questions:
>> - Can you access always the GICR_TYPER register without waking the
>> redistributor up?
> 
> I missed this part, can you suggest how can we do that? accessing some
> register before access to redistributor?

This redistributor may be in a power-domain that is off. Are you
guaranteed that you can access GICR_TYPER even when it is off?

> 
>> - How do you cope with situations where some redistributors are in the
>> always-on domain, and some are not?
> 
> I'm not sure if there is such hardware, if yes, do we need to fix
> the spec first?

It is something that should definitely be clarified. Can we end-up in a
situation where some redistributors are described via the GICR
structure, and some via the GICC structure? The spec is a bit ambiguous.

>>
>>> +	return gic_acpi_register_redist(gicc->gicr_base_address, size);
>>> +}
>>> +
>>> +static int __init gic_acpi_collect_gicr_base(void)
>>> +{
>>> +	acpi_tbl_entry_handler redist_parser;
>>> +	enum acpi_madt_type type;
>>> +
>>> +	if (single_redist) {
>>> +		type = ACPI_MADT_TYPE_GENERIC_INTERRUPT;
>>> +		redist_parser = gic_acpi_parse_madt_gicc;
>>> +	} else {
>>> +		type = ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR;
>>> +		redist_parser = gic_acpi_parse_madt_redist;
>>> +	}
>>> +
>>> +	/* Collect redistributor base addresses in GICR entries */
>>> +	if (acpi_table_parse_madt(type, redist_parser, 0) > 0)
>>> +		return 0;
>>> +
>>> +	pr_info("No valid GICR entries exist\n");
>>> +	return -ENODEV;
>>> +}
>>> +
>>>   static int __init gic_acpi_match_gicr(struct acpi_subtable_header *header,
>>>   				  const unsigned long end)
>>>   {
>>> @@ -1000,6 +1048,42 @@ static int __init gic_acpi_match_gicr(struct acpi_subtable_header *header,
>>>   	return 0;
>>>   }
>>>
>>> +static int __init gic_acpi_match_gicc(struct acpi_subtable_header *header,
>>> +				      const unsigned long end)
>>> +{
>>> +	struct acpi_madt_generic_interrupt *gicc =
>>> +				(struct acpi_madt_generic_interrupt *)header;
>>> +
>>> +	/*
>>> +	 * If GICC is enabled and has valid gicr base address, then it means
>>> +	 * GICR base is presented via GICC
>>> +	 */
>>> +	if ((gicc->flags & ACPI_MADT_ENABLED) && gicc->gicr_base_address)
>>> +		return 0;
>>> +
>>> +	return -ENODEV;
>>> +}
>>> +
>>> +static int __init gic_acpi_count_gicr_regions(void)
>>> +{
>>> +	int count;
>>> +
>>> +	/* Count how many redistributor regions we have */
>>> +	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
>>> +				      gic_acpi_match_gicr, 0);
>>> +	if (count > 0) {
>>> +		single_redist = false;
>>> +		return count;
>>> +	}
>>> +
>>> +	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
>>> +				      gic_acpi_match_gicc, 0);
>>> +	if (count > 0)
>>> +		single_redist = true;
>>> +
>>> +	return count;
>>> +}
>>> +
>>
>> Here, you seem to consider GICR and GICC tables to be mutually
>> exclusive. I don't think the spec says so.
> 
> Good question, I will ask Charles first about it.

I just did, and he agreed that the spec is ambiguous - but that your
interpretation is probably the correct one. It would be good fix it though.

Thanks,

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

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

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

On 12.01.2016 13:03, Marc Zyngier wrote:

 > +	typer = readq_relaxed(redist_base + GICR_TYPER);
 > +	/* don't map reserved page as it's buggy to access it */
 > +	size = (typer & GICR_TYPER_VLPIS) ? SZ_64K * 3 : SZ_64K * 2;

[...]

> Also, please map the whole region for the
> redistributor as we have on the DT side (4 64kB pages for VLPIS capable
> redistributors).

Hanjun, is it something you had problem with?

Tomasz

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

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

On 12.01.2016 13:03, Marc Zyngier wrote:

 > +	typer = readq_relaxed(redist_base + GICR_TYPER);
 > +	/* don't map reserved page as it's buggy to access it */
 > +	size = (typer & GICR_TYPER_VLPIS) ? SZ_64K * 3 : SZ_64K * 2;

[...]

> Also, please map the whole region for the
> redistributor as we have on the DT side (4 64kB pages for VLPIS capable
> redistributors).

Hanjun, is it something you had problem with?

Tomasz

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

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

On 12.01.2016 13:03, Marc Zyngier wrote:

 > +	typer = readq_relaxed(redist_base + GICR_TYPER);
 > +	/* don't map reserved page as it's buggy to access it */
 > +	size = (typer & GICR_TYPER_VLPIS) ? SZ_64K * 3 : SZ_64K * 2;

[...]

> Also, please map the whole region for the
> redistributor as we have on the DT side (4 64kB pages for VLPIS capable
> redistributors).

Hanjun, is it something you had problem with?

Tomasz

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

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

On 12.01.2016 17:16, Marc Zyngier wrote:
>>> >>Also, the spec says:
>>> >>
>>> >>"On systems supporting GICv3 and above, this field 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."
>>> >>
>>> >>which triggers two questions:
>>> >>- Can you access always the GICR_TYPER register without waking the
>>> >>redistributor up?
>> >
>> >I missed this part, can you suggest how can we do that? accessing some
>> >register before access to redistributor?
> This redistributor may be in a power-domain that is off. Are you
> guaranteed that you can access GICR_TYPER even when it is off?
>
>> >
>>> >>- How do you cope with situations where some redistributors are in the
>>> >>always-on domain, and some are not?
>> >
>> >I'm not sure if there is such hardware, if yes, do we need to fix
>> >the spec first?
> It is something that should definitely be clarified. Can we end-up in a
> situation where some redistributors are described via the GICR
> structure, and some via the GICC structure? The spec is a bit ambiguous.
>

To recap:
1. GICR and GICC subtables should be mutually exclusive, but ACPI spec 
should be clear about this.
2. We need to know if we can access GICR_TYPER without waking the 
redistributor up.

Tirumalesh, can you please advice?

Tomasz

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

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

On 12.01.2016 17:16, Marc Zyngier wrote:
>>> >>Also, the spec says:
>>> >>
>>> >>"On systems supporting GICv3 and above, this field 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."
>>> >>
>>> >>which triggers two questions:
>>> >>- Can you access always the GICR_TYPER register without waking the
>>> >>redistributor up?
>> >
>> >I missed this part, can you suggest how can we do that? accessing some
>> >register before access to redistributor?
> This redistributor may be in a power-domain that is off. Are you
> guaranteed that you can access GICR_TYPER even when it is off?
>
>> >
>>> >>- How do you cope with situations where some redistributors are in the
>>> >>always-on domain, and some are not?
>> >
>> >I'm not sure if there is such hardware, if yes, do we need to fix
>> >the spec first?
> It is something that should definitely be clarified. Can we end-up in a
> situation where some redistributors are described via the GICR
> structure, and some via the GICC structure? The spec is a bit ambiguous.
>

To recap:
1. GICR and GICC subtables should be mutually exclusive, but ACPI spec 
should be clear about this.
2. We need to know if we can access GICR_TYPER without waking the 
redistributor up.

Tirumalesh, can you please advice?

Tomasz

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

* Re: [PATCH V2 03/10] irqchip,GICv3,ACPI: Add redistributor support via GICC structures.
  2016-01-12 16:45       ` Tomasz Nowicki
@ 2016-01-13  1:52         ` Hanjun Guo
  -1 siblings, 0 replies; 62+ messages in thread
From: Hanjun Guo @ 2016-01-13  1:52 UTC (permalink / raw)
  To: Tomasz Nowicki, 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, linux-arm-kernel, ddaney.cavm



On 2016/1/13 0:45, Tomasz Nowicki wrote:
> On 12.01.2016 13:03, Marc Zyngier wrote:
>
>  > +    typer = readq_relaxed(redist_base + GICR_TYPER);
>  > +    /* don't map reserved page as it's buggy to access it */
>  > +    size = (typer & GICR_TYPER_VLPIS) ? SZ_64K * 3 : SZ_64K * 2;
>
> [...]
>
>> Also, please map the whole region for the
>> redistributor as we have on the DT side (4 64kB pages for VLPIS capable
>> redistributors).
>
> Hanjun, is it something you had problem with?

Yes, for D02, it use 3 64kB pages for GICv4, it removed the reserved
page. In DT case, it has "stride" binding so it can support no standard
cases, seems that we can introduce "stride" for ACPI too.

Thanks
Hanjun

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

* [PATCH V2 03/10] irqchip,GICv3,ACPI: Add redistributor support via GICC structures.
@ 2016-01-13  1:52         ` Hanjun Guo
  0 siblings, 0 replies; 62+ messages in thread
From: Hanjun Guo @ 2016-01-13  1:52 UTC (permalink / raw)
  To: linux-arm-kernel



On 2016/1/13 0:45, Tomasz Nowicki wrote:
> On 12.01.2016 13:03, Marc Zyngier wrote:
>
>  > +    typer = readq_relaxed(redist_base + GICR_TYPER);
>  > +    /* don't map reserved page as it's buggy to access it */
>  > +    size = (typer & GICR_TYPER_VLPIS) ? SZ_64K * 3 : SZ_64K * 2;
>
> [...]
>
>> Also, please map the whole region for the
>> redistributor as we have on the DT side (4 64kB pages for VLPIS capable
>> redistributors).
>
> Hanjun, is it something you had problem with?

Yes, for D02, it use 3 64kB pages for GICv4, it removed the reserved
page. In DT case, it has "stride" binding so it can support no standard
cases, seems that we can introduce "stride" for ACPI too.

Thanks
Hanjun

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

* Re: [PATCH V2 03/10] irqchip,GICv3,ACPI: Add redistributor support via GICC structures.
  2016-01-13  1:52         ` Hanjun Guo
@ 2016-01-13  8:35           ` Marc Zyngier
  -1 siblings, 0 replies; 62+ messages in thread
From: Marc Zyngier @ 2016-01-13  8:35 UTC (permalink / raw)
  To: Hanjun Guo, 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 13/01/16 01:52, Hanjun Guo wrote:
> 
> 
> On 2016/1/13 0:45, Tomasz Nowicki wrote:
>> On 12.01.2016 13:03, Marc Zyngier wrote:
>>
>>  > +    typer = readq_relaxed(redist_base + GICR_TYPER);
>>  > +    /* don't map reserved page as it's buggy to access it */
>>  > +    size = (typer & GICR_TYPER_VLPIS) ? SZ_64K * 3 : SZ_64K * 2;
>>
>> [...]
>>
>>> Also, please map the whole region for the
>>> redistributor as we have on the DT side (4 64kB pages for VLPIS capable
>>> redistributors).
>>
>> Hanjun, is it something you had problem with?
> 
> Yes, for D02, it use 3 64kB pages for GICv4, it removed the reserved
> page. In DT case, it has "stride" binding so it can support no standard
> cases, seems that we can introduce "stride" for ACPI too.

I don't think there is any need for that, assuming this system only
exposes its redistributors via the ACPI GICC structure. In which case, I
don't think it hurts to have overlapping mappings: For redistributors A
and B, we never touch A[3] (the reserved page), but we will access B[0].

Thanks,

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

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

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

On 13/01/16 01:52, Hanjun Guo wrote:
> 
> 
> On 2016/1/13 0:45, Tomasz Nowicki wrote:
>> On 12.01.2016 13:03, Marc Zyngier wrote:
>>
>>  > +    typer = readq_relaxed(redist_base + GICR_TYPER);
>>  > +    /* don't map reserved page as it's buggy to access it */
>>  > +    size = (typer & GICR_TYPER_VLPIS) ? SZ_64K * 3 : SZ_64K * 2;
>>
>> [...]
>>
>>> Also, please map the whole region for the
>>> redistributor as we have on the DT side (4 64kB pages for VLPIS capable
>>> redistributors).
>>
>> Hanjun, is it something you had problem with?
> 
> Yes, for D02, it use 3 64kB pages for GICv4, it removed the reserved
> page. In DT case, it has "stride" binding so it can support no standard
> cases, seems that we can introduce "stride" for ACPI too.

I don't think there is any need for that, assuming this system only
exposes its redistributors via the ACPI GICC structure. In which case, I
don't think it hurts to have overlapping mappings: For redistributors A
and B, we never touch A[3] (the reserved page), but we will access B[0].

Thanks,

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

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

* Re: [PATCH V2 03/10] irqchip,GICv3,ACPI: Add redistributor support via GICC structures.
  2016-01-13  8:35           ` Marc Zyngier
@ 2016-01-13  9:15             ` Hanjun Guo
  -1 siblings, 0 replies; 62+ messages in thread
From: Hanjun Guo @ 2016-01-13  9:15 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/1/13 16:35, Marc Zyngier wrote:
> On 13/01/16 01:52, Hanjun Guo wrote:
>>
>>
>> On 2016/1/13 0:45, Tomasz Nowicki wrote:
>>> On 12.01.2016 13:03, Marc Zyngier wrote:
>>>
>>>   > +    typer = readq_relaxed(redist_base + GICR_TYPER);
>>>   > +    /* don't map reserved page as it's buggy to access it */
>>>   > +    size = (typer & GICR_TYPER_VLPIS) ? SZ_64K * 3 : SZ_64K * 2;
>>>
>>> [...]
>>>
>>>> Also, please map the whole region for the
>>>> redistributor as we have on the DT side (4 64kB pages for VLPIS capable
>>>> redistributors).
>>>
>>> Hanjun, is it something you had problem with?
>>
>> Yes, for D02, it use 3 64kB pages for GICv4, it removed the reserved
>> page. In DT case, it has "stride" binding so it can support no standard
>> cases, seems that we can introduce "stride" for ACPI too.
>
> I don't think there is any need for that, assuming this system only
> exposes its redistributors via the ACPI GICC structure. In which case, I
> don't think it hurts to have overlapping mappings: For redistributors A
> and B, we never touch A[3] (the reserved page), but we will access B[0].

I think so, thanks for the clarify. I think we need to clarify the spec
first and interpret it in the right way.

Thanks
Hanjun

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

* [PATCH V2 03/10] irqchip,GICv3,ACPI: Add redistributor support via GICC structures.
@ 2016-01-13  9:15             ` Hanjun Guo
  0 siblings, 0 replies; 62+ messages in thread
From: Hanjun Guo @ 2016-01-13  9:15 UTC (permalink / raw)
  To: linux-arm-kernel

On 2016/1/13 16:35, Marc Zyngier wrote:
> On 13/01/16 01:52, Hanjun Guo wrote:
>>
>>
>> On 2016/1/13 0:45, Tomasz Nowicki wrote:
>>> On 12.01.2016 13:03, Marc Zyngier wrote:
>>>
>>>   > +    typer = readq_relaxed(redist_base + GICR_TYPER);
>>>   > +    /* don't map reserved page as it's buggy to access it */
>>>   > +    size = (typer & GICR_TYPER_VLPIS) ? SZ_64K * 3 : SZ_64K * 2;
>>>
>>> [...]
>>>
>>>> Also, please map the whole region for the
>>>> redistributor as we have on the DT side (4 64kB pages for VLPIS capable
>>>> redistributors).
>>>
>>> Hanjun, is it something you had problem with?
>>
>> Yes, for D02, it use 3 64kB pages for GICv4, it removed the reserved
>> page. In DT case, it has "stride" binding so it can support no standard
>> cases, seems that we can introduce "stride" for ACPI too.
>
> I don't think there is any need for that, assuming this system only
> exposes its redistributors via the ACPI GICC structure. In which case, I
> don't think it hurts to have overlapping mappings: For redistributors A
> and B, we never touch A[3] (the reserved page), but we will access B[0].

I think so, thanks for the clarify. I think we need to clarify the spec
first and interpret it in the right way.

Thanks
Hanjun

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

end of thread, other threads:[~2016-01-13  9:16 UTC | newest]

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

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.