diff options
author | Marc Zyngier <marc.zyngier@arm.com> | 2015-07-28 14:46:21 +0100 |
---|---|---|
committer | Alex Shi <alex.shi@linaro.org> | 2015-10-15 16:15:22 +0800 |
commit | c503090f604310814345424a58ba9add452d0336 (patch) | |
tree | 831feb8053e9b552b8f4a02434c72b751c72f8e3 /drivers/irqchip/irq-gic-v3-its.c | |
parent | 4779562135562c62de3a2b3dd2bbc915bd39c4bd (diff) |
irqchip/gicv3-its: Make the PCI/MSI code standalone
We can now lookup the base ITS domain, making it possible to
initialize the PCI/MSI code independently from the main ITS
subsystem.
This allows us to remove all the previously add hooks.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Cc: <linux-arm-kernel@lists.infradead.org>
Cc: Yijing Wang <wangyijing@huawei.com>
Cc: Ma Jun <majun258@huawei.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Duc Dang <dhdang@apm.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Jiang Liu <jiang.liu@linux.intel.com>
Cc: Jason Cooper <jason@lakedaemon.net>
Link: http://lkml.kernel.org/r/1438091186-10244-15-git-send-email-marc.zyngier@arm.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
(cherry picked from commit 54456db9a23753b87ce4d49adabe7da853bf13a2)
Signed-off-by: Alex Shi <alex.shi@linaro.org>
Diffstat (limited to 'drivers/irqchip/irq-gic-v3-its.c')
-rw-r--r-- | drivers/irqchip/irq-gic-v3-its.c | 48 |
1 files changed, 32 insertions, 16 deletions
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 9a7d00d220ee..42b137ed3bea 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -60,7 +60,6 @@ struct its_collection { struct its_node { raw_spinlock_t lock; struct list_head entry; - struct irq_domain *domain; void __iomem *base; unsigned long phys_base; struct its_cmd_block *cmd_base; @@ -1188,13 +1187,25 @@ static int its_alloc_device_irq(struct its_device *dev, irq_hw_number_t *hwirq) return 0; } -int its_msi_prepare(struct irq_domain *domain, u32 dev_id, - int nvec, msi_alloc_info_t *info) +static int its_msi_prepare(struct irq_domain *domain, struct device *dev, + int nvec, msi_alloc_info_t *info) { struct its_node *its; struct its_device *its_dev; + struct msi_domain_info *msi_info; + u32 dev_id; + + /* + * We ignore "dev" entierely, and rely on the dev_id that has + * been passed via the scratchpad. This limits this domain's + * usefulness to upper layers that definitely know that they + * are built on top of the ITS. + */ + dev_id = info->scratchpad[0].ul; + + msi_info = msi_get_domain_info(domain); + its = msi_info->data; - its = domain->parent->host_data; its_dev = its_find_device(its, dev_id); if (its_dev) { /* @@ -1216,6 +1227,10 @@ out: return 0; } +static struct msi_domain_ops its_msi_domain_ops = { + .msi_prepare = its_msi_prepare, +}; + static int its_irq_gic_domain_alloc(struct irq_domain *domain, unsigned int virq, irq_hw_number_t hwirq) @@ -1354,7 +1369,7 @@ static int its_probe(struct device_node *node, struct irq_domain *parent) struct resource res; struct its_node *its; void __iomem *its_base; - struct irq_domain *inner_domain = NULL; + struct irq_domain *inner_domain; u32 val; u64 baser, tmp; int err; @@ -1444,20 +1459,26 @@ static int its_probe(struct device_node *node, struct irq_domain *parent) writel_relaxed(GITS_CTLR_ENABLE, its->base + GITS_CTLR); if (of_property_read_bool(node, "msi-controller")) { + struct msi_domain_info *info; + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) { + err = -ENOMEM; + goto out_free_tables; + } + inner_domain = irq_domain_add_tree(node, &its_domain_ops, its); if (!inner_domain) { err = -ENOMEM; + kfree(info); goto out_free_tables; } inner_domain->parent = parent; inner_domain->bus_token = DOMAIN_BUS_NEXUS; - - its->domain = its_pci_msi_alloc_domain(node, inner_domain); - if (!its->domain) { - err = -ENOMEM; - goto out_free_domains; - } + info->ops = &its_msi_domain_ops; + info->data = its; + inner_domain->host_data = info; } spin_lock(&its_lock); @@ -1466,11 +1487,6 @@ static int its_probe(struct device_node *node, struct irq_domain *parent) return 0; -out_free_domains: - if (its->domain) - irq_domain_remove(its->domain); - if (inner_domain) - irq_domain_remove(inner_domain); out_free_tables: its_free_tables(its); out_free_cmd: |