]> xenbits.xensource.com Git - people/julieng/linux-arm.git/commitdiff
GICv3, ITS: Isolate FDT related code, extract common functions.
authorTomasz Nowicki <tomasz.nowicki@linaro.org>
Mon, 24 Nov 2014 17:53:53 +0000 (18:53 +0100)
committerJulien Grall <julien.grall@citrix.com>
Mon, 28 Sep 2015 11:05:19 +0000 (12:05 +0100)
Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org>
Signed-off-by: Robert Richter <rrichter@cavium.com>
Signed-off-by: Vadim Lomovtsev <Vadim.Lomovtsev@caviumnetworks.com>
drivers/irqchip/irq-gic-v3-its.c
drivers/irqchip/irq-gic-v3.c
include/linux/irqchip/arm-gic-v3.h

index 187692fd9f618d3e3cf6b490469e59a1ab81508c..648487ce49f7a1d9b22b6ac92a9d6669e058b991 100644 (file)
@@ -101,7 +101,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))
@@ -897,8 +896,8 @@ static int its_alloc_tables(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",
-                                       its->msi_chip.of_node->full_name, order);
+                               pr_warn("ITS: Device Table too large, reduce its page order to %u\n",
+                                       order);
                        }
                }
 
@@ -907,8 +906,8 @@ static int its_alloc_tables(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",
-                               its->msi_chip.of_node->full_name, order, alloc_pages);
+                       pr_warn("ITS: Device Table too large, reduce its page order to %u (%u pages)\n",
+                               order, alloc_pages);
                }
 
                base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
@@ -975,9 +974,8 @@ retry_baser:
                }
 
                if (val != tmp) {
-                       pr_err("ITS: %s: GITS_BASER%d doesn't stick: %lx %lx\n",
-                              its->msi_chip.of_node->full_name, i,
-                              (unsigned long) val, (unsigned long) tmp);
+                       pr_err("ITS: GITS_BASER%d doesn't stick: %lx %lx\n",
+                               i, (unsigned long)val, (unsigned long)tmp);
                        err = -ENXIO;
                        goto out_free;
                }
@@ -1521,43 +1519,33 @@ static void its_enable_quirks(struct its_node *its)
        gic_check_capabilities(iidr, its_errata, its);
 }
 
-static int its_probe(struct device_node *node, struct irq_domain *parent)
+static struct its_node *its_probe(unsigned long phys_base, unsigned long size)
 {
-       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(phys_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 NULL;
        }
 
        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("ITS: Failed to quiesce, giving up: %d\n", err);
                goto out_unmap;
        }
 
-       pr_info("ITS: %s\n", node->full_name);
-
        its = kzalloc(sizeof(*its), GFP_KERNEL);
        if (!its) {
                err = -ENOMEM;
@@ -1568,8 +1556,7 @@ static int its_probe(struct device_node *node, struct irq_domain *parent)
        INIT_LIST_HEAD(&its->entry);
        INIT_LIST_HEAD(&its->its_device_list);
        its->base = its_base;
-       its->phys_base = res.start;
-       its->msi_chip.of_node = node;
+       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);
@@ -1617,39 +1604,12 @@ static int its_probe(struct device_node *node, struct irq_domain *parent)
        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 (err)
-                       goto out_free_domains;
-       }
-
        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:
@@ -1658,8 +1618,8 @@ out_free_its:
        kfree(its);
 out_unmap:
        iounmap(its_base);
-       pr_err("ITS: failed probing %s (%d)\n", node->full_name, err);
-       return err;
+       pr_err("ITS: failed probing (%d)\n", err);
+       return NULL;
 }
 
 static bool gic_rdists_supports_plpis(void)
@@ -1681,31 +1641,72 @@ int its_cpu_init(void)
        return 0;
 }
 
+static int its_init_domain(struct device_node *node, struct its_node *its)
+{
+       its->domain = irq_domain_add_tree(NULL, &its_domain_ops, its);
+       if (!its->domain)
+               return -ENOMEM;
+
+       its->msi_chip.domain = pci_msi_create_irq_domain(node,
+                                                       &its_pci_msi_domain_info,
+                                                       its->domain);
+       if (!its->msi_chip.domain) {
+               irq_domain_remove(its->domain);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
 static struct of_device_id its_device_id[] = {
        {       .compatible     = "arm,gic-v3-its",     },
        {},
 };
 
-int its_init(struct device_node *node, struct rdists *rdists,
-            struct irq_domain *parent_domain)
+void its_of_probe(struct device_node *node)
 {
        struct device_node *np;
+       struct its_node *its;
+       struct resource res;
 
        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);
+               if (of_address_to_resource(np, 0, &res)) {
+                       pr_warn("%s: no regs?\n", node->full_name);
+                       continue;
+               }
+
+               pr_info("ITS: %s\n", np->full_name);
+               its = its_probe(res.start, resource_size(&res));
+               if (!its)
+                       continue;
+
+               its->msi_chip.of_node = np;
+               if (of_property_read_bool(its->msi_chip.of_node, "msi-controller")) {
+                       if (its_init_domain(np, its))
+                               continue;
+
+                       of_pci_msi_chip_add(&its->msi_chip);
+               }
        }
+}
+
+void its_init(struct rdists *rdists, struct irq_domain *domain)
+{
+       struct its_node *its;
 
-       if (list_empty(&its_nodes)) {
-               pr_warn("ITS: No ITS available, not enabling LPIs\n");
-               return -ENXIO;
+       if (list_empty(&its_nodes))
+               pr_info("ITS: No ITS available, not enabling LPIs\n");
+
+       spin_lock(&its_lock);
+       list_for_each_entry(its, &its_nodes, entry) {
+               if (its->domain)
+                       its->domain->parent = domain;
        }
+       spin_unlock(&its_lock);
 
        gic_rdists = rdists;
-       gic_root_node = node;
 
        its_alloc_lpi_tables();
        its_lpi_init(rdists->id_bits);
-
-       return 0;
 }
index b68885f9df5295609024e6479c579fad6e79fa31..398481a1f63b8a994b40d9db3fb815592c6a2f64 100644 (file)
@@ -860,7 +860,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())
-               its_init(node, &gic_data.rdists, gic_data.domain);
+               its_init(&gic_data.rdists, gic_data.domain);
 
        gic_smp_init();
        gic_dist_init();
@@ -919,6 +919,8 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
        if (of_property_read_u64(node, "redistributor-stride", &redist_stride))
                redist_stride = 0;
 
+       its_of_probe(node);
+
        err = gic_init_bases(dist_base, rdist_regs, nr_redist_regions,
                             redist_stride, node);
        if (!err)
index 5bbd47c8adaadd0935e38c93665733670d6fa805..2c8f0f52bae1944d0b4f86828b37c7f793070748 100644 (file)
@@ -399,8 +399,8 @@ static inline void gic_write_eoir(u64 irq)
 
 struct irq_domain;
 int its_cpu_init(void);
-int its_init(struct device_node *node, struct rdists *rdists,
-            struct irq_domain *domain);
+void its_init(struct rdists *rdists, struct irq_domain *domain);
+void its_of_probe(struct device_node *node);
 
 typedef u32 (*its_pci_requester_id_t)(struct pci_dev *, u16);
 void set_its_pci_requester_id(its_pci_requester_id_t fn);