[Arm-dev] [PATCH v1 63/87] GICv3, ITS: Isolate FDT related code, extract common functions.
Vadim Lomovtsev
Vadim.Lomovtsev at caviumnetworks.com
Thu Aug 13 13:19:00 UTC 2015
From: Tomasz Nowicki <tomasz.nowicki at linaro.org>
Signed-off-by: Tomasz Nowicki <tomasz.nowicki at linaro.org>
Signed-off-by: Robert Richter <rrichter at cavium.com>
Signed-off-by: Vadim Lomovtsev <Vadim.Lomovtsev at caviumnetworks.com>
---
drivers/irqchip/irq-gic-v3-its.c | 131 +++++++++++++++++++------------------
drivers/irqchip/irq-gic-v3.c | 4 +-
include/linux/irqchip/arm-gic-v3.h | 4 +-
3 files changed, 71 insertions(+), 68 deletions(-)
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index cb7f33d..3b7f352 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -99,7 +99,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))
@@ -888,8 +887,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);
}
}
@@ -898,8 +897,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);
@@ -966,9 +965,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;
}
@@ -1481,43 +1479,33 @@ static void its_check_capabilities(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;
@@ -1528,8 +1516,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);
@@ -1577,39 +1564,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:
@@ -1618,8 +1578,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)
@@ -1641,31 +1601,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;
}
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index db82724..d78589c 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -869,7 +869,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();
@@ -928,6 +928,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)
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 5bbd47c..2c8f0f5 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -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);
--
2.4.3
More information about the Arm-dev
mailing list