]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.arch/x86_sgi-uv-scir.patch
Imported linux-2.6.27.39 suse/xen patches.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.arch / x86_sgi-uv-scir.patch
CommitLineData
2cb7cef9
BS
1From: Mike Travis <travis@sgi.com>
2Subject: SGI X86 UV: Provide a System Activity Indicator driver
3References: FATE304268 bnc#426066
4Patch-mainline: 2.6.28
5
6Signed-off-by: Thomas Renninger <trenn@suse.de>
7
8The SGI UV system has no LEDS but uses one of the system controller
9regs to indicate the online internal state of the cpu. There is a
10heartbeat bit indicating that the cpu is responding to interrupts,
11and an idle bit indicating whether the cpu has been more or less than
1250% idle each heartbeat period. The current period is one second.
13
14When a cpu panics, an error code is written by BIOS to this same reg.
15
16So the reg has been renamed the "System Controller Interface Reg".
17
18This patchset provides the following:
19
20 * x86_64: Add base functionality for writing to the specific SCIR's
21 for each cpu.
22
23 * idle: Add an idle callback to measure the idle "on" and "off" times.
24
25 * heartbeat: Invert "heartbeat" bit to indicate the cpu is "active".
26
27 * if hotplug enabled, all bits are set (0xff) when the cpu is disabled.
28
29Based on linux-2.6.tip/master.
30
31Signed-off-by: Mike Travis <travis@sgi.com>
32---
33 arch/x86/kernel/genx2apic_uv_x.c | 102 +++++++++++++++++++++++++++++++++++++++
34 include/asm-x86/uv/uv_hub.h | 63 ++++++++++++++++++++++++
35 2 files changed, 165 insertions(+)
36
37--- linux-2.6.27.orig/arch/x86/kernel/genx2apic_uv_x.c
38+++ linux-2.6.27/arch/x86/kernel/genx2apic_uv_x.c
39@@ -10,6 +10,7 @@
40
41 #include <linux/kernel.h>
42 #include <linux/threads.h>
43+#include <linux/cpu.h>
44 #include <linux/cpumask.h>
45 #include <linux/string.h>
46 #include <linux/kernel.h>
47@@ -19,6 +20,8 @@
48 #include <linux/bootmem.h>
49 #include <linux/module.h>
50 #include <linux/hardirq.h>
51+#include <linux/timer.h>
52+#include <asm/current.h>
53 #include <asm/smp.h>
54 #include <asm/ipi.h>
55 #include <asm/genapic.h>
56@@ -365,6 +368,104 @@ static __init void uv_rtc_init(void)
57 sn_rtc_cycles_per_second = ticks_per_sec;
58 }
59
60+/*
61+ * percpu heartbeat timer
62+ */
63+static void uv_heartbeat(unsigned long ignored)
64+{
65+ struct timer_list *timer = &uv_hub_info->scir.timer;
66+ unsigned char bits = uv_hub_info->scir.state;
67+
68+ /* flip heartbeat bit */
69+ bits ^= SCIR_CPU_HEARTBEAT;
70+
71+ /* are we the idle thread? */
72+ if (current->pid == 0)
73+ bits &= ~SCIR_CPU_ACTIVITY;
74+ else
75+ bits |= SCIR_CPU_ACTIVITY;
76+
77+ /* update system controller interface reg */
78+ uv_set_scir_bits(bits);
79+
80+ /* enable next timer period */
81+ mod_timer(timer, jiffies + SCIR_CPU_HB_INTERVAL);
82+}
83+
84+static void __cpuinit uv_heartbeat_enable(int cpu)
85+{
86+ if (!uv_cpu_hub_info(cpu)->scir.enabled) {
87+ struct timer_list *timer = &uv_cpu_hub_info(cpu)->scir.timer;
88+
89+ uv_set_cpu_scir_bits(cpu, SCIR_CPU_HEARTBEAT|SCIR_CPU_ACTIVITY);
90+ setup_timer(timer, uv_heartbeat, cpu);
91+ timer->expires = jiffies + SCIR_CPU_HB_INTERVAL;
92+ add_timer_on(timer, cpu);
93+ uv_cpu_hub_info(cpu)->scir.enabled = 1;
94+ }
95+
96+ /* check boot cpu */
97+ if (!uv_cpu_hub_info(0)->scir.enabled)
98+ uv_heartbeat_enable(0);
99+}
100+
101+#ifdef CONFIG_HOTPLUG_CPU
102+
103+static void __cpuinit uv_heartbeat_disable(int cpu)
104+{
105+ if (uv_cpu_hub_info(cpu)->scir.enabled) {
106+ uv_cpu_hub_info(cpu)->scir.enabled = 0;
107+ del_timer(&uv_cpu_hub_info(cpu)->scir.timer);
108+ }
109+ uv_set_cpu_scir_bits(cpu, 0xff);
110+}
111+
112+/*
113+ * cpu hotplug notifier
114+ */
115+static __cpuinit int uv_scir_cpu_notify(struct notifier_block *self,
116+ unsigned long action, void *hcpu)
117+{
118+ long cpu = (long)hcpu;
119+
120+ switch (action) {
121+ case CPU_ONLINE:
122+ uv_heartbeat_enable(cpu);
123+ break;
124+ case CPU_DOWN_PREPARE:
125+ uv_heartbeat_disable(cpu);
126+ break;
127+ default:
128+ break;
129+ }
130+ return NOTIFY_OK;
131+}
132+
133+static __init void uv_scir_register_cpu_notifier(void)
134+{
135+ hotcpu_notifier(uv_scir_cpu_notify, 0);
136+}
137+
138+#else /* !CONFIG_HOTPLUG_CPU */
139+
140+static __init void uv_scir_register_cpu_notifier(void)
141+{
142+}
143+
144+static __init int uv_init_heartbeat(void)
145+{
146+ int cpu;
147+
148+ if (is_uv_system())
149+ for_each_online_cpu(cpu)
150+ uv_heartbeat_enable(cpu);
151+ return 0;
152+}
153+
154+late_initcall(uv_init_heartbeat);
155+
156+#endif /* !CONFIG_HOTPLUG_CPU */
157+
158 static bool uv_system_inited;
159
160 void __init uv_system_init(void)
161@@ -443,6 +544,7 @@ void __init uv_system_init(void)
162 uv_cpu_hub_info(cpu)->gnode_upper = gnode_upper;
163 uv_cpu_hub_info(cpu)->global_mmr_base = mmr_base;
164 uv_cpu_hub_info(cpu)->coherency_domain_number = 0;/* ZZZ */
165+ uv_cpu_hub_info(cpu)->scir.offset = SCIR_LOCAL_MMR_BASE + lcpu;
166 uv_node_to_blade[nid] = blade;
167 uv_cpu_to_blade[cpu] = blade;
168 max_pnode = max(pnode, max_pnode);
169@@ -458,6 +560,7 @@ void __init uv_system_init(void)
170 map_config_high(max_pnode);
171 map_mmioh_high(max_pnode);
172 uv_system_inited = true;
173+ uv_scir_register_cpu_notifier();
174 }
175
176 /*
177--- linux-2.6.27.orig/include/asm-x86/uv/uv_hub.h
178+++ linux-2.6.27/include/asm-x86/uv/uv_hub.h
179@@ -13,6 +13,7 @@
180
181 #include <linux/numa.h>
182 #include <linux/percpu.h>
183+#include <linux/timer.h>
184 #include <asm/types.h>
185 #include <asm/percpu.h>
186
187@@ -112,6 +113,16 @@
188 */
189 #define UV_MAX_NASID_VALUE (UV_MAX_NUMALINK_NODES * 2)
190
191+struct uv_scir_s {
192+ struct timer_list timer;
193+ unsigned long offset;
194+ unsigned long last;
195+ unsigned long idle_on;
196+ unsigned long idle_off;
197+ unsigned char state;
198+ unsigned char enabled;
199+};
200+
201 /*
202 * The following defines attributes of the HUB chip. These attributes are
203 * frequently referenced and are kept in the per-cpu data areas of each cpu.
204@@ -130,7 +141,9 @@ struct uv_hub_info_s {
205 unsigned char blade_processor_id;
206 unsigned char m_val;
207 unsigned char n_val;
208+ struct uv_scir_s scir;
209 };
210+
211 DECLARE_PER_CPU(struct uv_hub_info_s, __uv_hub_info);
212 #define uv_hub_info (&__get_cpu_var(__uv_hub_info))
213 #define uv_cpu_hub_info(cpu) (&per_cpu(__uv_hub_info, cpu))
214@@ -162,6 +175,30 @@ DECLARE_PER_CPU(struct uv_hub_info_s, __
215
216 #define UV_APIC_PNODE_SHIFT 6
217
218+/* Local Bus from cpu's perspective */
219+#define LOCAL_BUS_BASE 0x1c00000
220+#define LOCAL_BUS_SIZE (4 * 1024 * 1024)
221+
222+/*
223+ * System Controller Interface Reg
224+ *
225+ * Note there are NO leds on a UV system. This register is only
226+ * used by the system controller to monitor system-wide operation.
227+ * There are 64 regs per node. With Nahelem cpus (2 cores per node,
228+ * 8 cpus per core, 2 threads per cpu) there are 32 cpu threads on
229+ * a node.
230+ *
231+ * The window is located at top of ACPI MMR space
232+ */
233+#define SCIR_WINDOW_COUNT 64
234+#define SCIR_LOCAL_MMR_BASE (LOCAL_BUS_BASE + \
235+ LOCAL_BUS_SIZE - \
236+ SCIR_WINDOW_COUNT)
237+
238+#define SCIR_CPU_HEARTBEAT 0x01 /* timer interrupt */
239+#define SCIR_CPU_ACTIVITY 0x02 /* not idle */
240+#define SCIR_CPU_HB_INTERVAL (HZ) /* once per second */
241+
242 /*
243 * Macros for converting between kernel virtual addresses, socket local physical
244 * addresses, and UV global physical addresses.
245@@ -276,6 +313,16 @@ static inline void uv_write_local_mmr(un
246 *uv_local_mmr_address(offset) = val;
247 }
248
249+static inline unsigned char uv_read_local_mmr8(unsigned long offset)
250+{
251+ return *((unsigned char *)uv_local_mmr_address(offset));
252+}
253+
254+static inline void uv_write_local_mmr8(unsigned long offset, unsigned char val)
255+{
256+ *((unsigned char *)uv_local_mmr_address(offset)) = val;
257+}
258+
259 /*
260 * Structures and definitions for converting between cpu, node, pnode, and blade
261 * numbers.
262@@ -350,5 +397,21 @@ static inline int uv_num_possible_blades
263 return uv_possible_blades;
264 }
265
266+/* Update SCIR state */
267+static inline void uv_set_scir_bits(unsigned char value)
268+{
269+ if (uv_hub_info->scir.state != value) {
270+ uv_hub_info->scir.state = value;
271+ uv_write_local_mmr8(uv_hub_info->scir.offset, value);
272+ }
273+}
274+static inline void uv_set_cpu_scir_bits(int cpu, unsigned char value)
275+{
276+ if (uv_cpu_hub_info(cpu)->scir.state != value) {
277+ uv_cpu_hub_info(cpu)->scir.state = value;
278+ uv_write_local_mmr8(uv_cpu_hub_info(cpu)->scir.offset, value);
279+ }
280+}
281+
282 #endif /* __ASM_X86_UV_HUB__ */
283