On 16 June 2015 at 09:09, Hanjun Guo hanjun.guo@linaro.org wrote:
Refactor ITS init code to prepare for ACPI
Signed-off-by: Hanjun Guo hanjun.guo@linaro.org
drivers/irqchip/irq-gic-v3-its.c | 126 +++++++++++++++++++++++++-------------- 1 file changed, 80 insertions(+), 46 deletions(-)
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 6964bf8..c3652cd 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -1374,44 +1374,71 @@ static int its_force_quiescent(void __iomem *base) } }
-static int __init its_probe(struct device_node *node,
struct irq_domain *parent)
+static int __init its_init_domain(struct device_node *node, struct its_node *its,
struct irq_domain *parent)
+{
int err;
its->domain = irq_domain_add_tree(NULL, &its_domain_ops, its);
if (!its->domain)
return -ENOMEM;
its->domain->parent = parent;
its->msi_chip.domain = pci_msi_create_irq_domain(node,
&its_pci_msi_domain_info,
its->domain);
if (!its->msi_chip.domain) {
err = -ENOMEM;
goto out_free_domains;
}
if (its->msi_chip.of_node) {
err = of_pci_msi_chip_add(&its->msi_chip);
if (err)
goto out_free_domains;
}
return 0;
+out_free_domains:
if (its->msi_chip.domain)
irq_domain_remove(its->msi_chip.domain);
if (its->domain)
irq_domain_remove(its->domain);
return err;
+}
+struct its_node * __init its_probe(phys_addr_t phy_base, unsigned long size,
struct device_node *node,
struct irq_domain *parent,
bool is_msi_controller)
{
struct resource res; struct its_node *its; void __iomem *its_base; u32 val; 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(phy_base, size); if (!its_base) {
pr_warn("%s: unable to map registers\n", node->full_name);
return -ENOMEM;
pr_warn("Unable to map registers\n");
return ERR_PTR(-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);
its = kzalloc(sizeof(*its), GFP_KERNEL); if (!its) { err = -ENOMEM;
@@ -1422,7 +1449,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 = phy_base; its->msi_chip.of_node = node; its->ite_size = ((readl_relaxed(its_base + GITS_TYPER) >> 4) & 0xf) + 1;
@@ -1469,39 +1496,18 @@ 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(its->msi_chip.of_node, "msi-controller")) {
its->domain = irq_domain_add_tree(NULL, &its_domain_ops, its);
if (!its->domain) {
err = -ENOMEM;
goto out_free_tables;
}
its->domain->parent = parent;
its->msi_chip.domain = pci_msi_create_irq_domain(node,
&its_pci_msi_domain_info,
its->domain);
if (!its->msi_chip.domain) {
err = -ENOMEM;
goto out_free_domains;
}
err = of_pci_msi_chip_add(&its->msi_chip);
if (is_msi_controller) {
err = its_init_domain(node, its, parent); if (err)
goto out_free_domains;
goto out_free_tables; } spin_lock(&its_lock); list_add(&its->entry, &its_nodes); spin_unlock(&its_lock);
return 0;
return its;
-out_free_domains:
if (its->msi_chip.domain)
irq_domain_remove(its->msi_chip.domain);
if (its->domain)
irq_domain_remove(its->domain);
out_free_tables: its_free_tables(its); out_free_cmd: @@ -1510,8 +1516,36 @@ out_free_its: kfree(its); out_unmap: iounmap(its_base);
pr_err("ITS: failed probing %s (%d)\n", node->full_name, err);
return err;
return ERR_PTR(err);
+}
+static int __init its_of_probe(struct device_node *node,
struct irq_domain *parent)
+{
struct resource res;
struct its_node *its;
int err;
bool is_msi_controller = false;
err = of_address_to_resource(node, 0, &res);
if (err) {
pr_warn("%s: no regs?\n", node->full_name);
return -ENXIO;
}
if (of_property_read_bool(node, "msi-controller"))
is_msi_controller = true;
its = its_probe(res.start, resource_size(&res), node, parent,
is_msi_controller);
Still grokking, but I think we're passing the DT node pointer around too much. It could probably be split up cleaner such that its_probe() is independent of ACPI or DT, but I'll need to get more surrounding context to be sure.
if (IS_ERR(its)) {
err = PTR_ERR(its);
pr_err("ITS: failed probing %s (%d)\n", node->full_name, err);
return err;
}
pr_info("ITS: %s\n", node->full_name);
return 0;
}
static bool gic_rdists_supports_plpis(void) @@ -1545,7 +1579,7 @@ int __init its_init(struct device_node *node, struct rdists *rdists,
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);
its_of_probe(np, parent_domain); } if (list_empty(&its_nodes)) {
-- 1.9.1
Linaro-acpi mailing list Linaro-acpi@lists.linaro.org https://lists.linaro.org/mailman/listinfo/linaro-acpi