From: Jiang Liu <jiang.liu@linux.intel.com>
To: Benjamin Herrenschmidt <benh@kernel.crashing.org>,
Thomas Gleixner <tglx@linutronix.de>,
Ingo Molnar <mingo@redhat.com>, "H. Peter Anvin" <hpa@zytor.com>,
"Rafael J. Wysocki" <rjw@rjwysocki.net>,
Bjorn Helgaas <bhelgaas@google.com>,
Randy Dunlap <rdunlap@infradead.org>,
Yinghai Lu <yinghai@kernel.org>, Borislav Petkov <bp@alien8.de>,
Grant Likely <grant.likely@linaro.org>,
Marc Zyngier <marc.zyngier@arm.com>,
Yingjoe Chen <yingjoe.chen@mediatek.com>,
x86@kernel.org, Matthias Brugger <matthias.bgg@gmail.com>,
Jiang Liu <jiang.liu@linux.intel.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>,
Andrew Morton <akpm@linux-foundation.org>,
Tony Luck <tony.luck@intel.com>, Joerg Roedel <joro@8bytes.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org,
linux-acpi@vger.kernel.org, linux-arm-kernel@lists.infradead.org
Subject: [Patch Part2 v4 31/31] x86, uv: Use hierarchy irqdomain to manage UV interrupts
Date: Tue, 4 Nov 2014 20:02:05 +0800 [thread overview]
Message-ID: <1415102525-9898-32-git-send-email-jiang.liu@linux.intel.com> (raw)
In-Reply-To: <1415102525-9898-1-git-send-email-jiang.liu@linux.intel.com>
Enhance UV code to support hierarchy irqdomain, it helps to make
the architecture more clear.
We should construct hwirq based on mmr_blade and mmr_offset, but
mmr_offset is type of unsigned long, it may exceed the range of
irq_hw_number_t. So help about the way to construct hwirq based
on mmr_blade and mmr_offset is welcomed!
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
arch/x86/include/asm/hw_irq.h | 9 ++
arch/x86/platform/uv/uv_irq.c | 288 ++++++++++++++++-------------------------
2 files changed, 120 insertions(+), 177 deletions(-)
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h
index f54e78023218..e0c3332832e7 100644
--- a/arch/x86/include/asm/hw_irq.h
+++ b/arch/x86/include/asm/hw_irq.h
@@ -123,6 +123,7 @@ enum irq_alloc_type {
X86_IRQ_ALLOC_TYPE_MSI,
X86_IRQ_ALLOC_TYPE_MSIX,
X86_IRQ_ALLOC_TYPE_DMAR,
+ X86_IRQ_ALLOC_TYPE_UV,
};
struct irq_alloc_info {
@@ -167,6 +168,14 @@ struct irq_alloc_info {
void *ht_update;
};
#endif
+#ifdef CONFIG_X86_UV
+ struct {
+ int uv_limit;
+ int uv_blade;
+ unsigned long uv_offset;
+ char *uv_name;
+ };
+#endif
};
};
diff --git a/arch/x86/platform/uv/uv_irq.c b/arch/x86/platform/uv/uv_irq.c
index 474912d03f40..50c18bcb7f40 100644
--- a/arch/x86/platform/uv/uv_irq.c
+++ b/arch/x86/platform/uv/uv_irq.c
@@ -19,17 +19,31 @@
#include <asm/uv/uv_hub.h>
/* MMR offset and pnode of hub sourcing interrupts for a given irq */
-struct uv_irq_2_mmr_pnode{
- struct rb_node list;
+struct uv_irq_2_mmr_pnode {
unsigned long offset;
int pnode;
- int irq;
};
-static DEFINE_SPINLOCK(uv_irq_lock);
-static struct rb_root uv_irq_root;
+static void uv_program_mmr(struct irq_cfg *cfg, struct uv_irq_2_mmr_pnode *info)
+{
+ unsigned long mmr_value;
+ struct uv_IO_APIC_route_entry *entry;
+
+ BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) !=
+ sizeof(unsigned long));
+
+ mmr_value = 0;
+ entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
+ entry->vector = cfg->vector;
+ entry->delivery_mode = apic->irq_delivery_mode;
+ entry->dest_mode = apic->irq_dest_mode;
+ entry->polarity = 0;
+ entry->trigger = 0;
+ entry->mask = 0;
+ entry->dest = cfg->dest_apicid;
-static int uv_set_irq_affinity(struct irq_data *, const struct cpumask *, bool);
+ uv_write_global_mmr64(info->pnode, info->offset, mmr_value);
+}
static void uv_noop(struct irq_data *data) { }
@@ -38,6 +52,24 @@ static void uv_ack_apic(struct irq_data *data)
ack_APIC_irq();
}
+static int
+uv_set_irq_affinity(struct irq_data *data, const struct cpumask *mask,
+ bool force)
+{
+ struct irq_data *parent = data->parent_data;
+ struct irq_cfg *cfg = irqd_cfg(data);
+ int ret;
+
+ ret = parent->chip->irq_set_affinity(parent, mask, force);
+ if (ret >= 0) {
+ uv_program_mmr(cfg, data->chip_data);
+ if (cfg->move_in_progress)
+ send_cleanup_vector(cfg);
+ }
+
+ return ret;
+}
+
static struct irq_chip uv_irq_chip = {
.name = "UV-CORE",
.irq_mask = uv_noop,
@@ -46,179 +78,104 @@ static struct irq_chip uv_irq_chip = {
.irq_set_affinity = uv_set_irq_affinity,
};
-/*
- * Add offset and pnode information of the hub sourcing interrupts to the
- * rb tree for a specific irq.
- */
-static int uv_set_irq_2_mmr_info(int irq, unsigned long offset, unsigned blade)
+static int uv_domain_alloc(struct irq_domain *domain, unsigned int virq,
+ unsigned int nr_irqs, void *arg)
{
- struct rb_node **link = &uv_irq_root.rb_node;
- struct rb_node *parent = NULL;
- struct uv_irq_2_mmr_pnode *n;
- struct uv_irq_2_mmr_pnode *e;
- unsigned long irqflags;
-
- n = kmalloc_node(sizeof(struct uv_irq_2_mmr_pnode), GFP_KERNEL,
- uv_blade_to_memory_nid(blade));
- if (!n)
+ struct uv_irq_2_mmr_pnode *chip_data;
+ struct irq_alloc_info *info = arg;
+ struct irq_data *irq_data = irq_domain_get_irq_data(domain, virq);
+ int ret;
+
+ if (nr_irqs > 1 || !info || info->type != X86_IRQ_ALLOC_TYPE_UV)
+ return -EINVAL;
+
+ chip_data = kmalloc_node(sizeof(*chip_data), GFP_KERNEL,
+ irq_data->node);
+ if (!chip_data)
return -ENOMEM;
- n->irq = irq;
- n->offset = offset;
- n->pnode = uv_blade_to_pnode(blade);
- spin_lock_irqsave(&uv_irq_lock, irqflags);
- /* Find the right place in the rbtree: */
- while (*link) {
- parent = *link;
- e = rb_entry(parent, struct uv_irq_2_mmr_pnode, list);
-
- if (unlikely(irq == e->irq)) {
- /* irq entry exists */
- e->pnode = uv_blade_to_pnode(blade);
- e->offset = offset;
- spin_unlock_irqrestore(&uv_irq_lock, irqflags);
- kfree(n);
- return 0;
- }
-
- if (irq < e->irq)
- link = &(*link)->rb_left;
+ ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, arg);
+ if (ret >= 0) {
+ if (info->uv_limit == UV_AFFINITY_CPU)
+ irq_set_status_flags(virq, IRQ_NO_BALANCING);
else
- link = &(*link)->rb_right;
+ irq_set_status_flags(virq, IRQ_MOVE_PCNTXT);
+
+ chip_data->pnode = uv_blade_to_pnode(info->uv_blade);
+ chip_data->offset = info->uv_offset;
+ irq_domain_set_hwirq_and_chip(domain, virq, virq,
+ &uv_irq_chip, chip_data);
+ __irq_set_handler(virq, handle_percpu_irq, 0, info->uv_name);
+ } else {
+ kfree(chip_data);
}
- /* Insert the node into the rbtree. */
- rb_link_node(&n->list, parent, link);
- rb_insert_color(&n->list, &uv_irq_root);
-
- spin_unlock_irqrestore(&uv_irq_lock, irqflags);
- return 0;
+ return ret;
}
-/* Retrieve offset and pnode information from the rb tree for a specific irq */
-int uv_irq_2_mmr_info(int irq, unsigned long *offset, int *pnode)
+static void uv_domain_free(struct irq_domain *domain, unsigned int virq,
+ unsigned int nr_irqs)
{
- struct uv_irq_2_mmr_pnode *e;
- struct rb_node *n;
- unsigned long irqflags;
-
- spin_lock_irqsave(&uv_irq_lock, irqflags);
- n = uv_irq_root.rb_node;
- while (n) {
- e = rb_entry(n, struct uv_irq_2_mmr_pnode, list);
-
- if (e->irq == irq) {
- *offset = e->offset;
- *pnode = e->pnode;
- spin_unlock_irqrestore(&uv_irq_lock, irqflags);
- return 0;
- }
-
- if (irq < e->irq)
- n = n->rb_left;
- else
- n = n->rb_right;
- }
- spin_unlock_irqrestore(&uv_irq_lock, irqflags);
- return -1;
+ struct irq_data *irq_data = irq_domain_get_irq_data(domain, virq);
+
+ BUG_ON(nr_irqs != 1);
+ kfree(irq_data->chip_data);
+ irq_clear_status_flags(virq, IRQ_MOVE_PCNTXT);
+ irq_clear_status_flags(virq, IRQ_NO_BALANCING);
+ irq_domain_free_irqs_top(domain, virq, nr_irqs);
}
/*
* Re-target the irq to the specified CPU and enable the specified MMR located
* on the specified blade to allow the sending of MSIs to the specified CPU.
*/
-static int
-arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
- unsigned long mmr_offset, int limit)
+static int uv_domain_activate(struct irq_domain *domain,
+ struct irq_data *irq_data)
{
- struct irq_cfg *cfg = irq_cfg(irq);
- unsigned long mmr_value;
- struct uv_IO_APIC_route_entry *entry;
- int mmr_pnode;
-
- BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) !=
- sizeof(unsigned long));
-
- if (limit == UV_AFFINITY_CPU)
- irq_set_status_flags(irq, IRQ_NO_BALANCING);
- else
- irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
-
- irq_set_chip_and_handler_name(irq, &uv_irq_chip, handle_percpu_irq,
- irq_name);
+ uv_program_mmr(irqd_cfg(irq_data), irq_data->chip_data);
- mmr_value = 0;
- entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
- entry->vector = cfg->vector;
- entry->delivery_mode = apic->irq_delivery_mode;
- entry->dest_mode = apic->irq_dest_mode;
- entry->polarity = 0;
- entry->trigger = 0;
- entry->mask = 0;
- entry->dest = cfg->dest_apicid;
-
- mmr_pnode = uv_blade_to_pnode(mmr_blade);
- uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
-
- if (cfg->move_in_progress)
- send_cleanup_vector(cfg);
-
- return irq;
+ return 0;
}
/*
* Disable the specified MMR located on the specified blade so that MSIs are
* longer allowed to be sent.
*/
-static void arch_disable_uv_irq(int mmr_pnode, unsigned long mmr_offset)
+static int uv_domain_deactivate(struct irq_domain *domain,
+ struct irq_data *irq_data)
{
unsigned long mmr_value;
struct uv_IO_APIC_route_entry *entry;
- BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) !=
- sizeof(unsigned long));
-
mmr_value = 0;
entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
entry->mask = 1;
+ uv_program_mmr(irqd_cfg(irq_data), irq_data->chip_data);
- uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
+ return 0;
}
-static int
-uv_set_irq_affinity(struct irq_data *data, const struct cpumask *mask,
- bool force)
-{
- struct irq_cfg *cfg = irqd_cfg(data);
- unsigned int dest;
- unsigned long mmr_value, mmr_offset;
- struct uv_IO_APIC_route_entry *entry;
- int mmr_pnode;
-
- if (apic_set_affinity(data, mask, &dest))
- return -1;
-
- mmr_value = 0;
- entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
-
- entry->vector = cfg->vector;
- entry->delivery_mode = apic->irq_delivery_mode;
- entry->dest_mode = apic->irq_dest_mode;
- entry->polarity = 0;
- entry->trigger = 0;
- entry->mask = 0;
- entry->dest = dest;
-
- /* Get previously stored MMR and pnode of hub sourcing interrupts */
- if (uv_irq_2_mmr_info(data->irq, &mmr_offset, &mmr_pnode))
- return -1;
-
- uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
+static struct irq_domain_ops uv_domain_ops = {
+ .alloc = uv_domain_alloc,
+ .free = uv_domain_free,
+ .activate = uv_domain_activate,
+ .deactivate = uv_domain_deactivate,
+};
- if (cfg->move_in_progress)
- send_cleanup_vector(cfg);
+static struct irq_domain *uv_get_irq_domain(void)
+{
+ static struct irq_domain *uv_domain;
+ static DEFINE_MUTEX(uv_lock);
+
+ mutex_lock(&uv_lock);
+ if (uv_domain == NULL) {
+ uv_domain = irq_domain_add_tree(NULL, &uv_domain_ops, NULL);
+ if (uv_domain)
+ uv_domain->parent = x86_vector_domain;
+ }
+ mutex_unlock(&uv_lock);
- return IRQ_SET_MASK_OK_NOCOPY;
+ return uv_domain;
}
/*
@@ -229,23 +186,20 @@ uv_set_irq_affinity(struct irq_data *data, const struct cpumask *mask,
int uv_setup_irq(char *irq_name, int cpu, int mmr_blade,
unsigned long mmr_offset, int limit)
{
- int ret, irq;
struct irq_alloc_info info;
+ struct irq_domain *domain = uv_get_irq_domain();
+
+ if (!domain)
+ return -ENOMEM;
init_irq_alloc_info(&info, cpumask_of(cpu));
- irq = irq_domain_alloc_irqs(NULL, 1, uv_blade_to_memory_nid(mmr_blade),
- &info);
- if (irq <= 0)
- return -EBUSY;
-
- ret = arch_enable_uv_irq(irq_name, irq, cpu, mmr_blade, mmr_offset,
- limit);
- if (ret == irq)
- uv_set_irq_2_mmr_info(irq, mmr_offset, mmr_blade);
- else
- irq_domain_free_irqs(irq, 1);
+ info.uv_limit = limit;
+ info.uv_blade = mmr_blade;
+ info.uv_offset = mmr_offset;
+ info.uv_name = irq_name;
- return ret;
+ return irq_domain_alloc_irqs(domain, 1,
+ uv_blade_to_memory_nid(mmr_blade), &info);
}
EXPORT_SYMBOL_GPL(uv_setup_irq);
@@ -258,26 +212,6 @@ EXPORT_SYMBOL_GPL(uv_setup_irq);
*/
void uv_teardown_irq(unsigned int irq)
{
- struct uv_irq_2_mmr_pnode *e;
- struct rb_node *n;
- unsigned long irqflags;
-
- spin_lock_irqsave(&uv_irq_lock, irqflags);
- n = uv_irq_root.rb_node;
- while (n) {
- e = rb_entry(n, struct uv_irq_2_mmr_pnode, list);
- if (e->irq == irq) {
- arch_disable_uv_irq(e->pnode, e->offset);
- rb_erase(n, &uv_irq_root);
- kfree(e);
- break;
- }
- if (irq < e->irq)
- n = n->rb_left;
- else
- n = n->rb_right;
- }
- spin_unlock_irqrestore(&uv_irq_lock, irqflags);
irq_domain_free_irqs(irq, 1);
}
EXPORT_SYMBOL_GPL(uv_teardown_irq);
--
1.7.10.4
WARNING: multiple messages have this Message-ID (diff)
From: jiang.liu@linux.intel.com (Jiang Liu)
To: linux-arm-kernel@lists.infradead.org
Subject: [Patch Part2 v4 31/31] x86, uv: Use hierarchy irqdomain to manage UV interrupts
Date: Tue, 4 Nov 2014 20:02:05 +0800 [thread overview]
Message-ID: <1415102525-9898-32-git-send-email-jiang.liu@linux.intel.com> (raw)
In-Reply-To: <1415102525-9898-1-git-send-email-jiang.liu@linux.intel.com>
Enhance UV code to support hierarchy irqdomain, it helps to make
the architecture more clear.
We should construct hwirq based on mmr_blade and mmr_offset, but
mmr_offset is type of unsigned long, it may exceed the range of
irq_hw_number_t. So help about the way to construct hwirq based
on mmr_blade and mmr_offset is welcomed!
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
arch/x86/include/asm/hw_irq.h | 9 ++
arch/x86/platform/uv/uv_irq.c | 288 ++++++++++++++++-------------------------
2 files changed, 120 insertions(+), 177 deletions(-)
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h
index f54e78023218..e0c3332832e7 100644
--- a/arch/x86/include/asm/hw_irq.h
+++ b/arch/x86/include/asm/hw_irq.h
@@ -123,6 +123,7 @@ enum irq_alloc_type {
X86_IRQ_ALLOC_TYPE_MSI,
X86_IRQ_ALLOC_TYPE_MSIX,
X86_IRQ_ALLOC_TYPE_DMAR,
+ X86_IRQ_ALLOC_TYPE_UV,
};
struct irq_alloc_info {
@@ -167,6 +168,14 @@ struct irq_alloc_info {
void *ht_update;
};
#endif
+#ifdef CONFIG_X86_UV
+ struct {
+ int uv_limit;
+ int uv_blade;
+ unsigned long uv_offset;
+ char *uv_name;
+ };
+#endif
};
};
diff --git a/arch/x86/platform/uv/uv_irq.c b/arch/x86/platform/uv/uv_irq.c
index 474912d03f40..50c18bcb7f40 100644
--- a/arch/x86/platform/uv/uv_irq.c
+++ b/arch/x86/platform/uv/uv_irq.c
@@ -19,17 +19,31 @@
#include <asm/uv/uv_hub.h>
/* MMR offset and pnode of hub sourcing interrupts for a given irq */
-struct uv_irq_2_mmr_pnode{
- struct rb_node list;
+struct uv_irq_2_mmr_pnode {
unsigned long offset;
int pnode;
- int irq;
};
-static DEFINE_SPINLOCK(uv_irq_lock);
-static struct rb_root uv_irq_root;
+static void uv_program_mmr(struct irq_cfg *cfg, struct uv_irq_2_mmr_pnode *info)
+{
+ unsigned long mmr_value;
+ struct uv_IO_APIC_route_entry *entry;
+
+ BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) !=
+ sizeof(unsigned long));
+
+ mmr_value = 0;
+ entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
+ entry->vector = cfg->vector;
+ entry->delivery_mode = apic->irq_delivery_mode;
+ entry->dest_mode = apic->irq_dest_mode;
+ entry->polarity = 0;
+ entry->trigger = 0;
+ entry->mask = 0;
+ entry->dest = cfg->dest_apicid;
-static int uv_set_irq_affinity(struct irq_data *, const struct cpumask *, bool);
+ uv_write_global_mmr64(info->pnode, info->offset, mmr_value);
+}
static void uv_noop(struct irq_data *data) { }
@@ -38,6 +52,24 @@ static void uv_ack_apic(struct irq_data *data)
ack_APIC_irq();
}
+static int
+uv_set_irq_affinity(struct irq_data *data, const struct cpumask *mask,
+ bool force)
+{
+ struct irq_data *parent = data->parent_data;
+ struct irq_cfg *cfg = irqd_cfg(data);
+ int ret;
+
+ ret = parent->chip->irq_set_affinity(parent, mask, force);
+ if (ret >= 0) {
+ uv_program_mmr(cfg, data->chip_data);
+ if (cfg->move_in_progress)
+ send_cleanup_vector(cfg);
+ }
+
+ return ret;
+}
+
static struct irq_chip uv_irq_chip = {
.name = "UV-CORE",
.irq_mask = uv_noop,
@@ -46,179 +78,104 @@ static struct irq_chip uv_irq_chip = {
.irq_set_affinity = uv_set_irq_affinity,
};
-/*
- * Add offset and pnode information of the hub sourcing interrupts to the
- * rb tree for a specific irq.
- */
-static int uv_set_irq_2_mmr_info(int irq, unsigned long offset, unsigned blade)
+static int uv_domain_alloc(struct irq_domain *domain, unsigned int virq,
+ unsigned int nr_irqs, void *arg)
{
- struct rb_node **link = &uv_irq_root.rb_node;
- struct rb_node *parent = NULL;
- struct uv_irq_2_mmr_pnode *n;
- struct uv_irq_2_mmr_pnode *e;
- unsigned long irqflags;
-
- n = kmalloc_node(sizeof(struct uv_irq_2_mmr_pnode), GFP_KERNEL,
- uv_blade_to_memory_nid(blade));
- if (!n)
+ struct uv_irq_2_mmr_pnode *chip_data;
+ struct irq_alloc_info *info = arg;
+ struct irq_data *irq_data = irq_domain_get_irq_data(domain, virq);
+ int ret;
+
+ if (nr_irqs > 1 || !info || info->type != X86_IRQ_ALLOC_TYPE_UV)
+ return -EINVAL;
+
+ chip_data = kmalloc_node(sizeof(*chip_data), GFP_KERNEL,
+ irq_data->node);
+ if (!chip_data)
return -ENOMEM;
- n->irq = irq;
- n->offset = offset;
- n->pnode = uv_blade_to_pnode(blade);
- spin_lock_irqsave(&uv_irq_lock, irqflags);
- /* Find the right place in the rbtree: */
- while (*link) {
- parent = *link;
- e = rb_entry(parent, struct uv_irq_2_mmr_pnode, list);
-
- if (unlikely(irq == e->irq)) {
- /* irq entry exists */
- e->pnode = uv_blade_to_pnode(blade);
- e->offset = offset;
- spin_unlock_irqrestore(&uv_irq_lock, irqflags);
- kfree(n);
- return 0;
- }
-
- if (irq < e->irq)
- link = &(*link)->rb_left;
+ ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, arg);
+ if (ret >= 0) {
+ if (info->uv_limit == UV_AFFINITY_CPU)
+ irq_set_status_flags(virq, IRQ_NO_BALANCING);
else
- link = &(*link)->rb_right;
+ irq_set_status_flags(virq, IRQ_MOVE_PCNTXT);
+
+ chip_data->pnode = uv_blade_to_pnode(info->uv_blade);
+ chip_data->offset = info->uv_offset;
+ irq_domain_set_hwirq_and_chip(domain, virq, virq,
+ &uv_irq_chip, chip_data);
+ __irq_set_handler(virq, handle_percpu_irq, 0, info->uv_name);
+ } else {
+ kfree(chip_data);
}
- /* Insert the node into the rbtree. */
- rb_link_node(&n->list, parent, link);
- rb_insert_color(&n->list, &uv_irq_root);
-
- spin_unlock_irqrestore(&uv_irq_lock, irqflags);
- return 0;
+ return ret;
}
-/* Retrieve offset and pnode information from the rb tree for a specific irq */
-int uv_irq_2_mmr_info(int irq, unsigned long *offset, int *pnode)
+static void uv_domain_free(struct irq_domain *domain, unsigned int virq,
+ unsigned int nr_irqs)
{
- struct uv_irq_2_mmr_pnode *e;
- struct rb_node *n;
- unsigned long irqflags;
-
- spin_lock_irqsave(&uv_irq_lock, irqflags);
- n = uv_irq_root.rb_node;
- while (n) {
- e = rb_entry(n, struct uv_irq_2_mmr_pnode, list);
-
- if (e->irq == irq) {
- *offset = e->offset;
- *pnode = e->pnode;
- spin_unlock_irqrestore(&uv_irq_lock, irqflags);
- return 0;
- }
-
- if (irq < e->irq)
- n = n->rb_left;
- else
- n = n->rb_right;
- }
- spin_unlock_irqrestore(&uv_irq_lock, irqflags);
- return -1;
+ struct irq_data *irq_data = irq_domain_get_irq_data(domain, virq);
+
+ BUG_ON(nr_irqs != 1);
+ kfree(irq_data->chip_data);
+ irq_clear_status_flags(virq, IRQ_MOVE_PCNTXT);
+ irq_clear_status_flags(virq, IRQ_NO_BALANCING);
+ irq_domain_free_irqs_top(domain, virq, nr_irqs);
}
/*
* Re-target the irq to the specified CPU and enable the specified MMR located
* on the specified blade to allow the sending of MSIs to the specified CPU.
*/
-static int
-arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
- unsigned long mmr_offset, int limit)
+static int uv_domain_activate(struct irq_domain *domain,
+ struct irq_data *irq_data)
{
- struct irq_cfg *cfg = irq_cfg(irq);
- unsigned long mmr_value;
- struct uv_IO_APIC_route_entry *entry;
- int mmr_pnode;
-
- BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) !=
- sizeof(unsigned long));
-
- if (limit == UV_AFFINITY_CPU)
- irq_set_status_flags(irq, IRQ_NO_BALANCING);
- else
- irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
-
- irq_set_chip_and_handler_name(irq, &uv_irq_chip, handle_percpu_irq,
- irq_name);
+ uv_program_mmr(irqd_cfg(irq_data), irq_data->chip_data);
- mmr_value = 0;
- entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
- entry->vector = cfg->vector;
- entry->delivery_mode = apic->irq_delivery_mode;
- entry->dest_mode = apic->irq_dest_mode;
- entry->polarity = 0;
- entry->trigger = 0;
- entry->mask = 0;
- entry->dest = cfg->dest_apicid;
-
- mmr_pnode = uv_blade_to_pnode(mmr_blade);
- uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
-
- if (cfg->move_in_progress)
- send_cleanup_vector(cfg);
-
- return irq;
+ return 0;
}
/*
* Disable the specified MMR located on the specified blade so that MSIs are
* longer allowed to be sent.
*/
-static void arch_disable_uv_irq(int mmr_pnode, unsigned long mmr_offset)
+static int uv_domain_deactivate(struct irq_domain *domain,
+ struct irq_data *irq_data)
{
unsigned long mmr_value;
struct uv_IO_APIC_route_entry *entry;
- BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) !=
- sizeof(unsigned long));
-
mmr_value = 0;
entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
entry->mask = 1;
+ uv_program_mmr(irqd_cfg(irq_data), irq_data->chip_data);
- uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
+ return 0;
}
-static int
-uv_set_irq_affinity(struct irq_data *data, const struct cpumask *mask,
- bool force)
-{
- struct irq_cfg *cfg = irqd_cfg(data);
- unsigned int dest;
- unsigned long mmr_value, mmr_offset;
- struct uv_IO_APIC_route_entry *entry;
- int mmr_pnode;
-
- if (apic_set_affinity(data, mask, &dest))
- return -1;
-
- mmr_value = 0;
- entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
-
- entry->vector = cfg->vector;
- entry->delivery_mode = apic->irq_delivery_mode;
- entry->dest_mode = apic->irq_dest_mode;
- entry->polarity = 0;
- entry->trigger = 0;
- entry->mask = 0;
- entry->dest = dest;
-
- /* Get previously stored MMR and pnode of hub sourcing interrupts */
- if (uv_irq_2_mmr_info(data->irq, &mmr_offset, &mmr_pnode))
- return -1;
-
- uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
+static struct irq_domain_ops uv_domain_ops = {
+ .alloc = uv_domain_alloc,
+ .free = uv_domain_free,
+ .activate = uv_domain_activate,
+ .deactivate = uv_domain_deactivate,
+};
- if (cfg->move_in_progress)
- send_cleanup_vector(cfg);
+static struct irq_domain *uv_get_irq_domain(void)
+{
+ static struct irq_domain *uv_domain;
+ static DEFINE_MUTEX(uv_lock);
+
+ mutex_lock(&uv_lock);
+ if (uv_domain == NULL) {
+ uv_domain = irq_domain_add_tree(NULL, &uv_domain_ops, NULL);
+ if (uv_domain)
+ uv_domain->parent = x86_vector_domain;
+ }
+ mutex_unlock(&uv_lock);
- return IRQ_SET_MASK_OK_NOCOPY;
+ return uv_domain;
}
/*
@@ -229,23 +186,20 @@ uv_set_irq_affinity(struct irq_data *data, const struct cpumask *mask,
int uv_setup_irq(char *irq_name, int cpu, int mmr_blade,
unsigned long mmr_offset, int limit)
{
- int ret, irq;
struct irq_alloc_info info;
+ struct irq_domain *domain = uv_get_irq_domain();
+
+ if (!domain)
+ return -ENOMEM;
init_irq_alloc_info(&info, cpumask_of(cpu));
- irq = irq_domain_alloc_irqs(NULL, 1, uv_blade_to_memory_nid(mmr_blade),
- &info);
- if (irq <= 0)
- return -EBUSY;
-
- ret = arch_enable_uv_irq(irq_name, irq, cpu, mmr_blade, mmr_offset,
- limit);
- if (ret == irq)
- uv_set_irq_2_mmr_info(irq, mmr_offset, mmr_blade);
- else
- irq_domain_free_irqs(irq, 1);
+ info.uv_limit = limit;
+ info.uv_blade = mmr_blade;
+ info.uv_offset = mmr_offset;
+ info.uv_name = irq_name;
- return ret;
+ return irq_domain_alloc_irqs(domain, 1,
+ uv_blade_to_memory_nid(mmr_blade), &info);
}
EXPORT_SYMBOL_GPL(uv_setup_irq);
@@ -258,26 +212,6 @@ EXPORT_SYMBOL_GPL(uv_setup_irq);
*/
void uv_teardown_irq(unsigned int irq)
{
- struct uv_irq_2_mmr_pnode *e;
- struct rb_node *n;
- unsigned long irqflags;
-
- spin_lock_irqsave(&uv_irq_lock, irqflags);
- n = uv_irq_root.rb_node;
- while (n) {
- e = rb_entry(n, struct uv_irq_2_mmr_pnode, list);
- if (e->irq == irq) {
- arch_disable_uv_irq(e->pnode, e->offset);
- rb_erase(n, &uv_irq_root);
- kfree(e);
- break;
- }
- if (irq < e->irq)
- n = n->rb_left;
- else
- n = n->rb_right;
- }
- spin_unlock_irqrestore(&uv_irq_lock, irqflags);
irq_domain_free_irqs(irq, 1);
}
EXPORT_SYMBOL_GPL(uv_teardown_irq);
--
1.7.10.4
next prev parent reply other threads:[~2014-11-04 12:02 UTC|newest]
Thread overview: 157+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-11-04 12:01 [Patch Part2 v4 00/31] Enable hierarchy irqdomian on x86 platforms Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:01 ` [Patch Part2 v4 01/31] irqdomain: Introduce new interfaces to support hierarchy irqdomains Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-05 23:48 ` Thomas Gleixner
2014-11-05 23:48 ` Thomas Gleixner
2014-11-06 6:09 ` Jiang Liu
2014-11-06 6:09 ` Jiang Liu
2014-11-04 12:01 ` [Patch Part2 v4 02/31] irqdomain: Do irq_find_mapping and set_type for hierarchy irqdomain in case OF Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:01 ` [Patch Part2 v4 03/31] genirq: Introduce helper functions to support stacked irq_chip Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:01 ` [Patch Part2 v4 04/31] genirq: Introduce irq_chip.irq_compose_msi_msg() to support stacked irqchip Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:01 ` [Patch Part2 v4 05/31] genirq: Add IRQ_SET_MASK_OK_DONE " Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:01 ` [Patch Part2 v4 06/31] x86, irq: Save destination CPU ID in irq_cfg Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:01 ` [Patch Part2 v4 07/31] x86, irq: Use hierarchy irqdomain to manage CPU interrupt vectors Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:01 ` [Patch Part2 v4 08/31] x86, hpet: Use new irqdomain interfaces to allocate/free IRQ Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:01 ` [Patch Part2 v4 09/31] x86, MSI: " Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:01 ` [Patch Part2 v4 10/31] x86, uv: " Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:01 ` [Patch Part2 v4 11/31] x86, htirq: " Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:01 ` [Patch Part2 v4 13/31] x86: irq_remapping: Introduce new interfaces to support hierarchy irqdomain Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-06 11:43 ` Yijing Wang
2014-11-06 11:43 ` Yijing Wang
2014-11-06 11:43 ` Yijing Wang
[not found] ` <1415102525-9898-1-git-send-email-jiang.liu-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
2014-11-04 12:01 ` [Patch Part2 v4 12/31] x86, dmar: Use new irqdomain interfaces to allocate/free IRQ Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:01 ` [Patch Part2 v4 14/31] iommu/vt-d: Change prototypes to prepare for enabling hierarchy irqdomain Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:01 ` [Patch Part2 v4 15/31] iommu/vt-d: Enhance Intel IR driver to suppport " Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:01 ` [Patch Part2 v4 16/31] iommu/amd: Enhance AMD " Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:01 ` [Patch Part2 v4 19/31] PCI/MSI: Simplify PCI MSI code by initializing msi_desc.nvec_used earlier Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:01 ` Jiang Liu
[not found] ` <1415102525-9898-20-git-send-email-jiang.liu-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
2014-11-05 22:35 ` Bjorn Helgaas
2014-11-05 22:35 ` Bjorn Helgaas
2014-11-05 22:35 ` Bjorn Helgaas
2014-11-04 12:01 ` [Patch Part2 v4 22/31] x86, PCI, MSI: Use hierarchy irqdomain to manage MSI interrupts Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:01 ` [Patch Part2 v4 24/31] iommu/vt-d: Clean up unused MSI related code Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:02 ` [Patch Part2 v4 26/31] x86: irq_remapping: " Jiang Liu
2014-11-04 12:02 ` Jiang Liu
2014-11-04 12:02 ` Jiang Liu
2014-11-04 12:02 ` [Patch Part2 v4 28/31] iommu/vt-d: Refine the interfaces to create IRQ for DMAR unit Jiang Liu
2014-11-04 12:02 ` Jiang Liu
2014-11-04 12:02 ` Jiang Liu
2014-11-04 12:02 ` Jiang Liu
2014-11-04 12:01 ` [Patch Part2 v4 17/31] x86, hpet: Enhance HPET IRQ to support hierarchy irqdomain Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:01 ` [Patch Part2 v4 18/31] PCI/MSI, trivial: Fix minor syntax issues according to coding styles Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-05 22:10 ` Bjorn Helgaas
2014-11-05 22:10 ` Bjorn Helgaas
2014-11-05 22:10 ` Bjorn Helgaas
2014-11-05 22:10 ` Bjorn Helgaas
2014-11-04 12:01 ` [Patch Part2 v4 20/31] PCI/MSI: Kill redundant calling for irq_set_msi_desc() for MSIx interrupts Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-05 22:45 ` Bjorn Helgaas
2014-11-05 22:45 ` Bjorn Helgaas
2014-11-06 1:32 ` Yijing Wang
2014-11-06 1:32 ` Yijing Wang
2014-11-06 1:32 ` Yijing Wang
2014-11-06 4:04 ` Bjorn Helgaas
2014-11-06 4:04 ` Bjorn Helgaas
2014-11-06 4:04 ` Bjorn Helgaas
2014-11-06 4:31 ` Jiang Liu
2014-11-06 4:31 ` Jiang Liu
2014-11-04 12:01 ` [Patch Part2 v4 21/31] PCI/MSI: enhance PCI MSI core to support hierarchy irqdomain Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-05 23:09 ` Bjorn Helgaas
2014-11-05 23:09 ` Bjorn Helgaas
2014-11-05 23:09 ` Bjorn Helgaas
2014-11-06 1:58 ` Yijing Wang
2014-11-06 1:58 ` Yijing Wang
2014-11-06 1:58 ` Yijing Wang
2014-11-06 4:10 ` Bjorn Helgaas
2014-11-06 4:10 ` Bjorn Helgaas
2014-11-06 4:10 ` Bjorn Helgaas
2014-11-06 4:54 ` Yijing Wang
2014-11-06 4:54 ` Yijing Wang
2014-11-06 4:54 ` Yijing Wang
2014-11-06 5:06 ` Jiang Liu
2014-11-06 5:06 ` Jiang Liu
2014-11-06 5:42 ` Yijing Wang
2014-11-06 5:42 ` Yijing Wang
2014-11-06 5:42 ` Yijing Wang
2014-11-06 4:58 ` Jiang Liu
2014-11-06 4:58 ` Jiang Liu
2014-11-06 4:58 ` Jiang Liu
2014-11-06 5:28 ` Bjorn Helgaas
2014-11-06 5:28 ` Bjorn Helgaas
2014-11-06 5:28 ` Bjorn Helgaas
2014-11-06 10:01 ` Thomas Gleixner
2014-11-06 10:01 ` Thomas Gleixner
2014-11-06 10:01 ` Thomas Gleixner
2014-11-06 10:30 ` Thomas Gleixner
2014-11-06 10:30 ` Thomas Gleixner
2014-11-06 10:30 ` Thomas Gleixner
2014-11-06 11:41 ` Jiang Liu
2014-11-06 11:41 ` Jiang Liu
2014-11-06 11:41 ` Jiang Liu
2014-11-06 11:59 ` Thomas Gleixner
2014-11-06 11:59 ` Thomas Gleixner
2014-11-06 11:59 ` Thomas Gleixner
2014-11-04 12:01 ` [Patch Part2 v4 23/31] x86, irq: Directly call native_compose_msi_msg() for DMAR IRQ Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:01 ` [Patch Part2 v4 25/31] iommu/amd: Clean up unused MSI related code Jiang Liu
2014-11-04 12:01 ` Jiang Liu
2014-11-04 12:02 ` [Patch Part2 v4 27/31] x86, irq: Clean up unused MSI related code and interfaces Jiang Liu
2014-11-04 12:02 ` Jiang Liu
2014-11-04 12:02 ` [Patch Part2 v4 29/31] x86, irq: Use hierarchy irqdomain to manage DMAR interrupts Jiang Liu
2014-11-04 12:02 ` Jiang Liu
2014-11-04 12:02 ` [Patch Part2 v4 30/31] x86, htirq: Use hierarchy irqdomain to manage Hypertransport interrupts Jiang Liu
2014-11-04 12:02 ` Jiang Liu
2014-11-04 12:02 ` Jiang Liu [this message]
2014-11-04 12:02 ` [Patch Part2 v4 31/31] x86, uv: Use hierarchy irqdomain to manage UV interrupts Jiang Liu
2014-11-04 14:47 ` [Patch Part2 v4 00/31] Enable hierarchy irqdomian on x86 platforms Joerg Roedel
2014-11-04 14:47 ` Joerg Roedel
2014-11-04 15:12 ` Jiang Liu
2014-11-04 15:12 ` Jiang Liu
2014-11-04 15:32 ` Joerg Roedel
2014-11-04 15:32 ` Joerg Roedel
2014-11-05 8:51 ` Joerg Roedel
2014-11-05 8:51 ` Joerg Roedel
2014-11-05 9:04 ` Jiang Liu
2014-11-05 9:04 ` Jiang Liu
2014-11-05 9:41 ` Jiang Liu
2014-11-05 9:41 ` Jiang Liu
2014-11-05 9:58 ` Joerg Roedel
2014-11-05 9:58 ` Joerg Roedel
2014-11-05 10:28 ` Jiang Liu
2014-11-05 10:28 ` Jiang Liu
2014-11-05 11:10 ` Joerg Roedel
2014-11-05 11:10 ` Joerg Roedel
2014-11-06 13:07 ` Joerg Roedel
2014-11-06 13:07 ` Joerg Roedel
2014-11-06 13:35 ` Jiang Liu
2014-11-06 13:35 ` Jiang Liu
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=1415102525-9898-32-git-send-email-jiang.liu@linux.intel.com \
--to=jiang.liu@linux.intel.com \
--cc=akpm@linux-foundation.org \
--cc=benh@kernel.crashing.org \
--cc=bhelgaas@google.com \
--cc=bp@alien8.de \
--cc=grant.likely@linaro.org \
--cc=gregkh@linuxfoundation.org \
--cc=hpa@zytor.com \
--cc=joro@8bytes.org \
--cc=konrad.wilk@oracle.com \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=marc.zyngier@arm.com \
--cc=matthias.bgg@gmail.com \
--cc=mingo@redhat.com \
--cc=rdunlap@infradead.org \
--cc=rjw@rjwysocki.net \
--cc=tglx@linutronix.de \
--cc=tony.luck@intel.com \
--cc=x86@kernel.org \
--cc=yinghai@kernel.org \
--cc=yingjoe.chen@mediatek.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.