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