Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1293816 > unrolled thread
| Started by | Tomasz Nowicki <tn@semihalf.com> |
|---|---|
| First post | 2015-12-17 13:00 +0100 |
| Last post | 2015-12-17 13:50 +0100 |
| Articles | 10 — 3 participants |
Back to article view | Back to linux.kernel
[PATCH V2 00/10] Introduce ACPI world to GICv3 & ITS irqchip Tomasz Nowicki <tn@semihalf.com> - 2015-12-17 13:00 +0100
[PATCH V2 01/10] irqchip / GICv3: Refactor gic_of_init() for GICv3 driver Tomasz Nowicki <tn@semihalf.com> - 2015-12-17 13:00 +0100
[PATCH V2 09/10] acpi, gicv3, msi: Factor out code that might be reused for ACPI equivalent. Tomasz Nowicki <tn@semihalf.com> - 2015-12-17 13:00 +0100
[PATCH V2 06/10] irqchip/GICv3/ITS: Refator ITS dt init code to prepare for ACPI. Tomasz Nowicki <tn@semihalf.com> - 2015-12-17 13:00 +0100
Re: [PATCH V2 06/10] irqchip/GICv3/ITS: Refator ITS dt init code to prepare for ACPI. Hanjun Guo <guohanjun@huawei.com> - 2015-12-18 12:00 +0100
Re: [PATCH V2 06/10] irqchip/GICv3/ITS: Refator ITS dt init code to prepare for ACPI. Tomasz Nowicki <tn@semihalf.com> - 2015-12-18 12:20 +0100
[PATCH V2 02/10] irqchip / GICv3: Add ACPI support for GICv3+ initialization Tomasz Nowicki <tn@semihalf.com> - 2015-12-17 13:00 +0100
[PATCH V2 05/10] irqchip, gicv3, its: Mark its_init() and its children as __init Tomasz Nowicki <tn@semihalf.com> - 2015-12-17 13:00 +0100
[PATCH V2 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization. Tomasz Nowicki <tn@semihalf.com> - 2015-12-17 13:00 +0100
Re: [PATCH V2 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization. kbuild test robot <lkp@intel.com> - 2015-12-17 13:50 +0100
| From | Tomasz Nowicki <tn@semihalf.com> |
|---|---|
| Date | 2015-12-17 13:00 +0100 |
| Subject | [PATCH V2 00/10] Introduce ACPI world to GICv3 & ITS irqchip |
| Message-ID | <qGFnY-7mN-3@gated-at.bofh.it> |
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
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | Tomasz Nowicki <tn@semihalf.com> |
|---|---|
| Date | 2015-12-17 13:00 +0100 |
| Subject | [PATCH V2 01/10] irqchip / GICv3: Refactor gic_of_init() for GICv3 driver |
| Message-ID | <qGFnY-7mN-13@gated-at.bofh.it> |
| In reply to | #1293816 |
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
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Tomasz Nowicki <tn@semihalf.com> |
|---|---|
| Date | 2015-12-17 13:00 +0100 |
| Subject | [PATCH V2 09/10] acpi, gicv3, msi: Factor out code that might be reused for ACPI equivalent. |
| Message-ID | <qGFnY-7mN-15@gated-at.bofh.it> |
| In reply to | #1293816 |
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
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Tomasz Nowicki <tn@semihalf.com> |
|---|---|
| Date | 2015-12-17 13:00 +0100 |
| Subject | [PATCH V2 06/10] irqchip/GICv3/ITS: Refator ITS dt init code to prepare for ACPI. |
| Message-ID | <qGFnZ-7mN-19@gated-at.bofh.it> |
| In reply to | #1293816 |
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
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Hanjun Guo <guohanjun@huawei.com> |
|---|---|
| Date | 2015-12-18 12:00 +0100 |
| Subject | Re: [PATCH V2 06/10] irqchip/GICv3/ITS: Refator ITS dt init code to prepare for ACPI. |
| Message-ID | <qH0Vs-4xe-7@gated-at.bofh.it> |
| In reply to | #1293820 |
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 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Tomasz Nowicki <tn@semihalf.com> |
|---|---|
| Date | 2015-12-18 12:20 +0100 |
| Subject | Re: [PATCH V2 06/10] irqchip/GICv3/ITS: Refator ITS dt init code to prepare for ACPI. |
| Message-ID | <qH1eO-4T3-9@gated-at.bofh.it> |
| In reply to | #1294658 |
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 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Tomasz Nowicki <tn@semihalf.com> |
|---|---|
| Date | 2015-12-17 13:00 +0100 |
| Subject | [PATCH V2 02/10] irqchip / GICv3: Add ACPI support for GICv3+ initialization |
| Message-ID | <qGFnZ-7mN-23@gated-at.bofh.it> |
| In reply to | #1293816 |
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
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Tomasz Nowicki <tn@semihalf.com> |
|---|---|
| Date | 2015-12-17 13:00 +0100 |
| Subject | [PATCH V2 05/10] irqchip, gicv3, its: Mark its_init() and its children as __init |
| Message-ID | <qGFnZ-7mN-25@gated-at.bofh.it> |
| In reply to | #1293816 |
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
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Tomasz Nowicki <tn@semihalf.com> |
|---|---|
| Date | 2015-12-17 13:00 +0100 |
| Subject | [PATCH V2 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization. |
| Message-ID | <qGFnZ-7mN-27@gated-at.bofh.it> |
| In reply to | #1293816 |
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
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | kbuild test robot <lkp@intel.com> |
|---|---|
| Date | 2015-12-17 13:50 +0100 |
| Subject | Re: [PATCH V2 10/10] acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain initialization. |
| Message-ID | <qGGam-7Vm-13@gated-at.bofh.it> |
| In reply to | #1293823 |
[Multipart message — attachments visible in raw view] — view raw
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
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web