aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDean Nelson <dcn@sgi.com>2008-10-02 13:18:21 -0400
committerIngo Molnar <mingo@elte.hu>2008-10-16 10:53:12 -0400
commit4173a0e7371ece227559b44943c6fd456ee470d1 (patch)
treee9a6dd475bfc72b373c1db13c21c8d82591636ec
parent5f79f2f2ad39b5177c52ed08ffd066ea0c1da924 (diff)
x86, UV: add uv_setup_irq() and uv_teardown_irq() functions, v3
Provide a means for UV interrupt MMRs to be setup with the message to be sent when an MSI is raised. Signed-off-by: Dean Nelson <dcn@sgi.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--arch/x86/kernel/Makefile2
-rw-r--r--arch/x86/kernel/io_apic.c68
-rw-r--r--arch/x86/kernel/uv_irq.c77
-rw-r--r--include/asm-x86/uv/uv_irq.h36
4 files changed, 182 insertions, 1 deletions
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 45cecc59d89..acc0e8bf043 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -108,7 +108,7 @@ obj-$(CONFIG_MICROCODE) += microcode.o
108# 64 bit specific files 108# 64 bit specific files
109ifeq ($(CONFIG_X86_64),y) 109ifeq ($(CONFIG_X86_64),y)
110 obj-y += genapic_64.o genapic_flat_64.o genx2apic_uv_x.o tlb_uv.o 110 obj-y += genapic_64.o genapic_flat_64.o genx2apic_uv_x.o tlb_uv.o
111 obj-y += bios_uv.o 111 obj-y += bios_uv.o uv_irq.o
112 obj-y += genx2apic_cluster.o 112 obj-y += genx2apic_cluster.o
113 obj-y += genx2apic_phys.o 113 obj-y += genx2apic_phys.o
114 obj-$(CONFIG_X86_PM_TIMER) += pmtimer_64.o 114 obj-$(CONFIG_X86_PM_TIMER) += pmtimer_64.o
diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c
index 4ee270d3035..260c95a5e6d 100644
--- a/arch/x86/kernel/io_apic.c
+++ b/arch/x86/kernel/io_apic.c
@@ -58,6 +58,8 @@
58#include <asm/setup.h> 58#include <asm/setup.h>
59#include <asm/irq_remapping.h> 59#include <asm/irq_remapping.h>
60#include <asm/hpet.h> 60#include <asm/hpet.h>
61#include <asm/uv/uv_hub.h>
62#include <asm/uv/uv_irq.h>
61 63
62#include <mach_ipi.h> 64#include <mach_ipi.h>
63#include <mach_apic.h> 65#include <mach_apic.h>
@@ -3692,6 +3694,72 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
3692} 3694}
3693#endif /* CONFIG_HT_IRQ */ 3695#endif /* CONFIG_HT_IRQ */
3694 3696
3697#ifdef CONFIG_X86_64
3698/*
3699 * Re-target the irq to the specified CPU and enable the specified MMR located
3700 * on the specified blade to allow the sending of MSIs to the specified CPU.
3701 */
3702int arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
3703 unsigned long mmr_offset)
3704{
3705 const cpumask_t *eligible_cpu = get_cpu_mask(cpu);
3706 struct irq_cfg *cfg;
3707 int mmr_pnode;
3708 unsigned long mmr_value;
3709 struct uv_IO_APIC_route_entry *entry;
3710 unsigned long flags;
3711 int err;
3712
3713 err = assign_irq_vector(irq, *eligible_cpu);
3714 if (err != 0)
3715 return err;
3716
3717 spin_lock_irqsave(&vector_lock, flags);
3718 set_irq_chip_and_handler_name(irq, &uv_irq_chip, handle_percpu_irq,
3719 irq_name);
3720 spin_unlock_irqrestore(&vector_lock, flags);
3721
3722 cfg = irq_cfg(irq);
3723
3724 mmr_value = 0;
3725 entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
3726 BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
3727
3728 entry->vector = cfg->vector;
3729 entry->delivery_mode = INT_DELIVERY_MODE;
3730 entry->dest_mode = INT_DEST_MODE;
3731 entry->polarity = 0;
3732 entry->trigger = 0;
3733 entry->mask = 0;
3734 entry->dest = cpu_mask_to_apicid(*eligible_cpu);
3735
3736 mmr_pnode = uv_blade_to_pnode(mmr_blade);
3737 uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
3738
3739 return irq;
3740}
3741
3742/*
3743 * Disable the specified MMR located on the specified blade so that MSIs are
3744 * longer allowed to be sent.
3745 */
3746void arch_disable_uv_irq(int mmr_blade, unsigned long mmr_offset)
3747{
3748 unsigned long mmr_value;
3749 struct uv_IO_APIC_route_entry *entry;
3750 int mmr_pnode;
3751
3752 mmr_value = 0;
3753 entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
3754 BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
3755
3756 entry->mask = 1;
3757
3758 mmr_pnode = uv_blade_to_pnode(mmr_blade);
3759 uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
3760}
3761#endif /* CONFIG_X86_64 */
3762
3695int __init io_apic_get_redir_entries (int ioapic) 3763int __init io_apic_get_redir_entries (int ioapic)
3696{ 3764{
3697 union IO_APIC_reg_01 reg_01; 3765 union IO_APIC_reg_01 reg_01;
diff --git a/arch/x86/kernel/uv_irq.c b/arch/x86/kernel/uv_irq.c
new file mode 100644
index 00000000000..6bd26c91c30
--- /dev/null
+++ b/arch/x86/kernel/uv_irq.c
@@ -0,0 +1,77 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * SGI UV IRQ functions
7 *
8 * Copyright (C) 2008 Silicon Graphics, Inc. All rights reserved.
9 */
10
11#include <linux/module.h>
12#include <linux/irq.h>
13#include <asm/uv/uv_irq.h>
14
15static void uv_noop(unsigned int irq)
16{
17}
18
19static unsigned int uv_noop_ret(unsigned int irq)
20{
21 return 0;
22}
23
24static void uv_ack_apic(unsigned int irq)
25{
26 ack_APIC_irq();
27}
28
29struct irq_chip uv_irq_chip = {
30 .name = "UV-CORE",
31 .startup = uv_noop_ret,
32 .shutdown = uv_noop,
33 .enable = uv_noop,
34 .disable = uv_noop,
35 .ack = uv_noop,
36 .mask = uv_noop,
37 .unmask = uv_noop,
38 .eoi = uv_ack_apic,
39 .end = uv_noop,
40};
41
42/*
43 * Set up a mapping of an available irq and vector, and enable the specified
44 * MMR that defines the MSI that is to be sent to the specified CPU when an
45 * interrupt is raised.
46 */
47int uv_setup_irq(char *irq_name, int cpu, int mmr_blade,
48 unsigned long mmr_offset)
49{
50 int irq;
51 int ret;
52
53 irq = create_irq();
54 if (irq <= 0)
55 return -EBUSY;
56
57 ret = arch_enable_uv_irq(irq_name, irq, cpu, mmr_blade, mmr_offset);
58 if (ret != irq)
59 destroy_irq(irq);
60
61 return ret;
62}
63EXPORT_SYMBOL_GPL(uv_setup_irq);
64
65/*
66 * Tear down a mapping of an irq and vector, and disable the specified MMR that
67 * defined the MSI that was to be sent to the specified CPU when an interrupt
68 * was raised.
69 *
70 * Set mmr_blade and mmr_offset to what was passed in on uv_setup_irq().
71 */
72void uv_teardown_irq(unsigned int irq, int mmr_blade, unsigned long mmr_offset)
73{
74 arch_disable_uv_irq(mmr_blade, mmr_offset);
75 destroy_irq(irq);
76}
77EXPORT_SYMBOL_GPL(uv_teardown_irq);
diff --git a/include/asm-x86/uv/uv_irq.h b/include/asm-x86/uv/uv_irq.h
new file mode 100644
index 00000000000..8bf5f32da9c
--- /dev/null
+++ b/include/asm-x86/uv/uv_irq.h
@@ -0,0 +1,36 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * SGI UV IRQ definitions
7 *
8 * Copyright (C) 2008 Silicon Graphics, Inc. All rights reserved.
9 */
10
11#ifndef ASM_X86__UV__UV_IRQ_H
12#define ASM_X86__UV__UV_IRQ_H
13
14/* If a generic version of this structure gets defined, eliminate this one. */
15struct uv_IO_APIC_route_entry {
16 __u64 vector : 8,
17 delivery_mode : 3,
18 dest_mode : 1,
19 delivery_status : 1,
20 polarity : 1,
21 __reserved_1 : 1,
22 trigger : 1,
23 mask : 1,
24 __reserved_2 : 15,
25 dest : 32;
26};
27
28extern struct irq_chip uv_irq_chip;
29
30extern int arch_enable_uv_irq(char *, unsigned int, int, int, unsigned long);
31extern void arch_disable_uv_irq(int, unsigned long);
32
33extern int uv_setup_irq(char *, int, int, unsigned long);
34extern void uv_teardown_irq(unsigned int, int, unsigned long);
35
36#endif /* ASM_X86__UV__UV_IRQ_H */