]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.31/patches.fixes/uv_setup_irq.diff
Add a patch to fix Intel E100 wake-on-lan problems.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.fixes / uv_setup_irq.diff
CommitLineData
6a930a95
BS
1From: Dean Nelson <dcn@sgi.com>
2Date: Thu, 2 Oct 2008 17:18:21 +0000 (-0500)
3Subject: x86, UV: add uv_setup_irq() and uv_teardown_irq() functions, v3
4X-Git-Tag: v2.6.28-rc1~80^2~27
5X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=4173a0e7371ece227559b44943c6fd456ee470d1
6References: bnc#442461
7
8x86, UV: add uv_setup_irq() and uv_teardown_irq() functions, v3
9
10Provide a means for UV interrupt MMRs to be setup with the message to be sent
11when an MSI is raised.
12
13Signed-off-by: Dean Nelson <dcn@sgi.com>
14Signed-off-by: Ingo Molnar <mingo@elte.hu>
15Acked-by: Bernhard Walle <bwalle@suse.de>
16
17---
18 arch/x86/kernel/Makefile | 2 -
19 arch/x86/kernel/io_apic_64.c | 68 +++++++++++++++++++++++++++++++++++++
20 arch/x86/kernel/uv_irq.c | 79 +++++++++++++++++++++++++++++++++++++++++++
21 include/asm-x86/uv/uv_irq.h | 36 +++++++++++++++++++
22 4 files changed, 184 insertions(+), 1 deletion(-)
23
24--- a/arch/x86/kernel/Makefile
25+++ b/arch/x86/kernel/Makefile
26@@ -106,7 +106,7 @@ ifeq ($(CONFIG_X86_64),y)
27 obj-y += uv_sysfs.o
28 obj-y += genx2apic_cluster.o
29 obj-y += genx2apic_phys.o
30- obj-y += bios_uv.o
31+ obj-y += bios_uv.o uv_irq.o
32 obj-$(CONFIG_X86_PM_TIMER) += pmtimer_64.o
33 obj-$(CONFIG_AUDIT) += audit_64.o
34
35--- a/arch/x86/kernel/io_apic_64.c
36+++ b/arch/x86/kernel/io_apic_64.c
37@@ -51,6 +51,8 @@
38 #include <asm/msidef.h>
39 #include <asm/hypertransport.h>
40 #include <asm/irq_remapping.h>
41+#include <asm/uv/uv_hub.h>
42+#include <asm/uv/uv_irq.h>
43
44 #include <mach_ipi.h>
45 #include <mach_apic.h>
46@@ -2787,6 +2789,72 @@ int arch_setup_ht_irq(unsigned int irq,
47 }
48 #endif /* CONFIG_HT_IRQ */
49
50+#ifdef CONFIG_X86_64
51+/*
52+ * Re-target the irq to the specified CPU and enable the specified MMR located
53+ * on the specified blade to allow the sending of MSIs to the specified CPU.
54+ */
55+int arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
56+ unsigned long mmr_offset)
57+{
58+ const cpumask_t *eligible_cpu = get_cpu_mask(cpu);
59+ struct irq_cfg *cfg;
60+ int mmr_pnode;
61+ unsigned long mmr_value;
62+ struct uv_IO_APIC_route_entry *entry;
63+ unsigned long flags;
64+ int err;
65+
66+ err = assign_irq_vector(irq, eligible_cpu);
67+ if (err != 0)
68+ return err;
69+
70+ spin_lock_irqsave(&vector_lock, flags);
71+ set_irq_chip_and_handler_name(irq, &uv_irq_chip, handle_percpu_irq,
72+ irq_name);
73+ spin_unlock_irqrestore(&vector_lock, flags);
74+
75+ cfg = &irq_cfg[irq];
76+
77+ mmr_value = 0;
78+ entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
79+ BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
80+
81+ entry->vector = cfg->vector;
82+ entry->delivery_mode = INT_DELIVERY_MODE;
83+ entry->dest_mode = INT_DEST_MODE;
84+ entry->polarity = 0;
85+ entry->trigger = 0;
86+ entry->mask = 0;
87+ entry->dest = cpu_mask_to_apicid(eligible_cpu);
88+
89+ mmr_pnode = uv_blade_to_pnode(mmr_blade);
90+ uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
91+
92+ return irq;
93+}
94+
95+/*
96+ * Disable the specified MMR located on the specified blade so that MSIs are
97+ * longer allowed to be sent.
98+ */
99+void arch_disable_uv_irq(int mmr_blade, unsigned long mmr_offset)
100+{
101+ unsigned long mmr_value;
102+ struct uv_IO_APIC_route_entry *entry;
103+ int mmr_pnode;
104+
105+ mmr_value = 0;
106+ entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
107+ BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
108+
109+ entry->mask = 1;
110+
111+ mmr_pnode = uv_blade_to_pnode(mmr_blade);
112+ uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
113+}
114+#endif /* CONFIG_X86_64 */
115+
116 /* --------------------------------------------------------------------------
117 ACPI-based IOAPIC Configuration
118 -------------------------------------------------------------------------- */
119--- /dev/null
120+++ b/arch/x86/kernel/uv_irq.c
121@@ -0,0 +1,79 @@
122+/*
123+ * This file is subject to the terms and conditions of the GNU General Public
124+ * License. See the file "COPYING" in the main directory of this archive
125+ * for more details.
126+ *
127+ * SGI UV IRQ functions
128+ *
129+ * Copyright (C) 2008 Silicon Graphics, Inc. All rights reserved.
130+ */
131+
132+#include <linux/module.h>
133+#include <linux/irq.h>
134+
135+#include <asm/apic.h>
136+#include <asm/uv/uv_irq.h>
137+
138+static void uv_noop(unsigned int irq)
139+{
140+}
141+
142+static unsigned int uv_noop_ret(unsigned int irq)
143+{
144+ return 0;
145+}
146+
147+static void uv_ack_apic(unsigned int irq)
148+{
149+ ack_APIC_irq();
150+}
151+
152+struct irq_chip uv_irq_chip = {
153+ .name = "UV-CORE",
154+ .startup = uv_noop_ret,
155+ .shutdown = uv_noop,
156+ .enable = uv_noop,
157+ .disable = uv_noop,
158+ .ack = uv_noop,
159+ .mask = uv_noop,
160+ .unmask = uv_noop,
161+ .eoi = uv_ack_apic,
162+ .end = uv_noop,
163+};
164+
165+/*
166+ * Set up a mapping of an available irq and vector, and enable the specified
167+ * MMR that defines the MSI that is to be sent to the specified CPU when an
168+ * interrupt is raised.
169+ */
170+int uv_setup_irq(char *irq_name, int cpu, int mmr_blade,
171+ unsigned long mmr_offset)
172+{
173+ int irq;
174+ int ret;
175+
176+ irq = create_irq();
177+ if (irq < 0)
178+ return -EBUSY;
179+
180+ ret = arch_enable_uv_irq(irq_name, irq, cpu, mmr_blade, mmr_offset);
181+ if (ret != irq)
182+ destroy_irq(irq);
183+
184+ return ret;
185+}
186+EXPORT_SYMBOL_GPL(uv_setup_irq);
187+
188+/*
189+ * Tear down a mapping of an irq and vector, and disable the specified MMR that
190+ * defined the MSI that was to be sent to the specified CPU when an interrupt
191+ * was raised.
192+ *
193+ * Set mmr_blade and mmr_offset to what was passed in on uv_setup_irq().
194+ */
195+void uv_teardown_irq(unsigned int irq, int mmr_blade, unsigned long mmr_offset)
196+{
197+ arch_disable_uv_irq(mmr_blade, mmr_offset);
198+ destroy_irq(irq);
199+}
200+EXPORT_SYMBOL_GPL(uv_teardown_irq);
201--- /dev/null
202+++ b/include/asm-x86/uv/uv_irq.h
203@@ -0,0 +1,36 @@
204+/*
205+ * This file is subject to the terms and conditions of the GNU General Public
206+ * License. See the file "COPYING" in the main directory of this archive
207+ * for more details.
208+ *
209+ * SGI UV IRQ definitions
210+ *
211+ * Copyright (C) 2008 Silicon Graphics, Inc. All rights reserved.
212+ */
213+
214+#ifndef _ASM_X86_UV_UV_IRQ_H
215+#define _ASM_X86_UV_UV_IRQ_H
216+
217+/* If a generic version of this structure gets defined, eliminate this one. */
218+struct uv_IO_APIC_route_entry {
219+ __u64 vector : 8,
220+ delivery_mode : 3,
221+ dest_mode : 1,
222+ delivery_status : 1,
223+ polarity : 1,
224+ __reserved_1 : 1,
225+ trigger : 1,
226+ mask : 1,
227+ __reserved_2 : 15,
228+ dest : 32;
229+};
230+
231+extern struct irq_chip uv_irq_chip;
232+
233+extern int arch_enable_uv_irq(char *, unsigned int, int, int, unsigned long);
234+extern void arch_disable_uv_irq(int, unsigned long);
235+
236+extern int uv_setup_irq(char *, int, int, unsigned long);
237+extern void uv_teardown_irq(unsigned int, int, unsigned long);
238+
239+#endif /* _ASM_X86_UV_UV_IRQ_H */