From: tip-bot for Marc Zyngier <tipbot@zytor.com>
To: linux-tip-commits@vger.kernel.org
Cc: mingo@kernel.org, tglx@linutronix.de, marc.zyngier@arm.com,
Suravee.Suthikulpanit@amd.com, hpa@zytor.com, dhdang@apm.com,
linux-arm-kernel@lists.infradead.org, jason@lakedaemon.net,
linux-kernel@vger.kernel.org
Subject: [tip:irq/core] irqchip/gic-v2m: Add support for multiple MSI frames
Date: Thu, 15 Oct 2015 01:21:59 -0700 [thread overview]
Message-ID: <tip-a71225e204f5ba8b41e7bb100ca37c074861d5b1@git.kernel.org> (raw)
In-Reply-To: <1444822037-16983-3-git-send-email-marc.zyngier@arm.com>
Commit-ID: a71225e204f5ba8b41e7bb100ca37c074861d5b1
Gitweb: http://git.kernel.org/tip/a71225e204f5ba8b41e7bb100ca37c074861d5b1
Author: Marc Zyngier <marc.zyngier@arm.com>
AuthorDate: Wed, 14 Oct 2015 12:27:17 +0100
Committer: Thomas Gleixner <tglx@linutronix.de>
CommitDate: Thu, 15 Oct 2015 10:18:48 +0200
irqchip/gic-v2m: Add support for multiple MSI frames
The GICv2m driver is so far limited to a single MSI frame, but
nothing prevents an implementation from having several of them.
This patch expands the driver to enumerate all frames, keeping
the first one as the canonical identifier for the MSI domains.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Tested-by: Duc Dang <dhdang@apm.com>
Cc: <linux-arm-kernel@lists.infradead.org>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Jason Cooper <jason@lakedaemon.net>
Link: http://lkml.kernel.org/r/1444822037-16983-3-git-send-email-marc.zyngier@arm.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
drivers/irqchip/irq-gic-v2m.c | 124 ++++++++++++++++++++++++++----------------
1 file changed, 78 insertions(+), 46 deletions(-)
diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
index bf9b3c0..87f8d10 100644
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -50,8 +50,12 @@
/* List of flags for specific v2m implementation */
#define GICV2M_NEEDS_SPI_OFFSET 0x00000001
+static LIST_HEAD(v2m_nodes);
+static DEFINE_SPINLOCK(v2m_lock);
+
struct v2m_data {
- spinlock_t msi_cnt_lock;
+ struct list_head entry;
+ struct device_node *node;
struct resource res; /* GICv2m resource */
void __iomem *base; /* GICv2m virt address */
u32 spi_start; /* The SPI number that MSIs start */
@@ -158,27 +162,30 @@ static void gicv2m_unalloc_msi(struct v2m_data *v2m, unsigned int hwirq)
return;
}
- spin_lock(&v2m->msi_cnt_lock);
+ spin_lock(&v2m_lock);
__clear_bit(pos, v2m->bm);
- spin_unlock(&v2m->msi_cnt_lock);
+ spin_unlock(&v2m_lock);
}
static int gicv2m_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
unsigned int nr_irqs, void *args)
{
- struct v2m_data *v2m = domain->host_data;
+ struct v2m_data *v2m = NULL, *tmp;
int hwirq, offset, err = 0;
- spin_lock(&v2m->msi_cnt_lock);
- offset = find_first_zero_bit(v2m->bm, v2m->nr_spis);
- if (offset < v2m->nr_spis)
- __set_bit(offset, v2m->bm);
- else
- err = -ENOSPC;
- spin_unlock(&v2m->msi_cnt_lock);
+ spin_lock(&v2m_lock);
+ list_for_each_entry(tmp, &v2m_nodes, entry) {
+ offset = find_first_zero_bit(tmp->bm, tmp->nr_spis);
+ if (offset < tmp->nr_spis) {
+ __set_bit(offset, tmp->bm);
+ v2m = tmp;
+ break;
+ }
+ }
+ spin_unlock(&v2m_lock);
- if (err)
- return err;
+ if (!v2m)
+ return -ENOSPC;
hwirq = v2m->spi_start + offset;
@@ -239,12 +246,61 @@ static struct msi_domain_info gicv2m_pmsi_domain_info = {
.chip = &gicv2m_pmsi_irq_chip,
};
+static void gicv2m_teardown(void)
+{
+ struct v2m_data *v2m, *tmp;
+
+ list_for_each_entry_safe(v2m, tmp, &v2m_nodes, entry) {
+ list_del(&v2m->entry);
+ kfree(v2m->bm);
+ iounmap(v2m->base);
+ of_node_put(v2m->node);
+ kfree(v2m);
+ }
+}
+
+static int gicv2m_allocate_domains(struct irq_domain *parent)
+{
+ struct irq_domain *inner_domain, *pci_domain, *plat_domain;
+ struct v2m_data *v2m;
+
+ v2m = list_first_entry_or_null(&v2m_nodes, struct v2m_data, entry);
+ if (!v2m)
+ return 0;
+
+ inner_domain = irq_domain_create_tree(of_node_to_fwnode(v2m->node),
+ &gicv2m_domain_ops, v2m);
+ if (!inner_domain) {
+ pr_err("Failed to create GICv2m domain\n");
+ return -ENOMEM;
+ }
+
+ inner_domain->bus_token = DOMAIN_BUS_NEXUS;
+ inner_domain->parent = parent;
+ pci_domain = pci_msi_create_irq_domain(of_node_to_fwnode(v2m->node),
+ &gicv2m_msi_domain_info,
+ inner_domain);
+ plat_domain = platform_msi_create_irq_domain(of_node_to_fwnode(v2m->node),
+ &gicv2m_pmsi_domain_info,
+ inner_domain);
+ if (!pci_domain || !plat_domain) {
+ pr_err("Failed to create MSI domains\n");
+ if (plat_domain)
+ irq_domain_remove(plat_domain);
+ if (pci_domain)
+ irq_domain_remove(pci_domain);
+ irq_domain_remove(inner_domain);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
static int __init gicv2m_init_one(struct device_node *node,
struct irq_domain *parent)
{
int ret;
struct v2m_data *v2m;
- struct irq_domain *inner_domain, *pci_domain, *plat_domain;
v2m = kzalloc(sizeof(struct v2m_data), GFP_KERNEL);
if (!v2m) {
@@ -252,6 +308,9 @@ static int __init gicv2m_init_one(struct device_node *node,
return -ENOMEM;
}
+ INIT_LIST_HEAD(&v2m->entry);
+ v2m->node = node;
+
ret = of_address_to_resource(node, 0, &v2m->res);
if (ret) {
pr_err("Failed to allocate v2m resource.\n");
@@ -299,44 +358,13 @@ static int __init gicv2m_init_one(struct device_node *node,
goto err_iounmap;
}
- inner_domain = irq_domain_add_tree(node, &gicv2m_domain_ops, v2m);
- if (!inner_domain) {
- pr_err("Failed to create GICv2m domain\n");
- ret = -ENOMEM;
- goto err_free_bm;
- }
-
- inner_domain->bus_token = DOMAIN_BUS_NEXUS;
- inner_domain->parent = parent;
- pci_domain = pci_msi_create_irq_domain(of_node_to_fwnode(node),
- &gicv2m_msi_domain_info,
- inner_domain);
- plat_domain = platform_msi_create_irq_domain(of_node_to_fwnode(node),
- &gicv2m_pmsi_domain_info,
- inner_domain);
- if (!pci_domain || !plat_domain) {
- pr_err("Failed to create MSI domains\n");
- ret = -ENOMEM;
- goto err_free_domains;
- }
-
- spin_lock_init(&v2m->msi_cnt_lock);
-
+ list_add_tail(&v2m->entry, &v2m_nodes);
pr_info("Node %s: range[%#lx:%#lx], SPI[%d:%d]\n", node->name,
(unsigned long)v2m->res.start, (unsigned long)v2m->res.end,
v2m->spi_start, (v2m->spi_start + v2m->nr_spis));
return 0;
-err_free_domains:
- if (plat_domain)
- irq_domain_remove(plat_domain);
- if (pci_domain)
- irq_domain_remove(pci_domain);
- if (inner_domain)
- irq_domain_remove(inner_domain);
-err_free_bm:
- kfree(v2m->bm);
err_iounmap:
iounmap(v2m->base);
err_free_v2m:
@@ -366,5 +394,9 @@ int __init gicv2m_of_init(struct device_node *node, struct irq_domain *parent)
}
}
+ if (!ret)
+ ret = gicv2m_allocate_domains(parent);
+ if (ret)
+ gicv2m_teardown();
return ret;
}
prev parent reply other threads:[~2015-10-15 8:22 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-10-14 11:27 [PATCH v2 0/2] More GIC updates for Linux 4.4 Marc Zyngier
2015-10-14 11:27 ` [PATCH v2 1/2] irqchip/gic-v3: Fix translation of LPIs after conversion to irq_fwspec Marc Zyngier
2015-10-15 8:21 ` [tip:irq/core] " tip-bot for Marc Zyngier
2015-10-14 11:27 ` [PATCH v2 2/2] irqchip/gic-v2m: Add support for multiple MSI frames Marc Zyngier
2015-10-14 14:13 ` Suravee Suthikulanit
2015-10-14 15:28 ` Marc Zyngier
2015-10-14 15:30 ` Suravee Suthikulanit
2015-10-15 8:21 ` tip-bot for Marc Zyngier [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=tip-a71225e204f5ba8b41e7bb100ca37c074861d5b1@git.kernel.org \
--to=tipbot@zytor.com \
--cc=Suravee.Suthikulpanit@amd.com \
--cc=dhdang@apm.com \
--cc=hpa@zytor.com \
--cc=jason@lakedaemon.net \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-tip-commits@vger.kernel.org \
--cc=marc.zyngier@arm.com \
--cc=mingo@kernel.org \
--cc=tglx@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox