aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/uv/uv_hub.h63
-rw-r--r--arch/x86/kernel/genx2apic_uv_x.c102
2 files changed, 164 insertions, 1 deletions
diff --git a/arch/x86/include/asm/uv/uv_hub.h b/arch/x86/include/asm/uv/uv_hub.h
index c6ad93e315c..400776dba9b 100644
--- a/arch/x86/include/asm/uv/uv_hub.h
+++ b/arch/x86/include/asm/uv/uv_hub.h
@@ -112,6 +112,16 @@
112 */ 112 */
113#define UV_MAX_NASID_VALUE (UV_MAX_NUMALINK_NODES * 2) 113#define UV_MAX_NASID_VALUE (UV_MAX_NUMALINK_NODES * 2)
114 114
115struct uv_scir_s {
116 struct timer_list timer;
117 unsigned long offset;
118 unsigned long last;
119 unsigned long idle_on;
120 unsigned long idle_off;
121 unsigned char state;
122 unsigned char enabled;
123};
124
115/* 125/*
116 * The following defines attributes of the HUB chip. These attributes are 126 * The following defines attributes of the HUB chip. These attributes are
117 * frequently referenced and are kept in the per-cpu data areas of each cpu. 127 * frequently referenced and are kept in the per-cpu data areas of each cpu.
@@ -130,7 +140,9 @@ struct uv_hub_info_s {
130 unsigned char blade_processor_id; 140 unsigned char blade_processor_id;
131 unsigned char m_val; 141 unsigned char m_val;
132 unsigned char n_val; 142 unsigned char n_val;
143 struct uv_scir_s scir;
133}; 144};
145
134DECLARE_PER_CPU(struct uv_hub_info_s, __uv_hub_info); 146DECLARE_PER_CPU(struct uv_hub_info_s, __uv_hub_info);
135#define uv_hub_info (&__get_cpu_var(__uv_hub_info)) 147#define uv_hub_info (&__get_cpu_var(__uv_hub_info))
136#define uv_cpu_hub_info(cpu) (&per_cpu(__uv_hub_info, cpu)) 148#define uv_cpu_hub_info(cpu) (&per_cpu(__uv_hub_info, cpu))
@@ -162,6 +174,30 @@ DECLARE_PER_CPU(struct uv_hub_info_s, __uv_hub_info);
162 174
163#define UV_APIC_PNODE_SHIFT 6 175#define UV_APIC_PNODE_SHIFT 6
164 176
177/* Local Bus from cpu's perspective */
178#define LOCAL_BUS_BASE 0x1c00000
179#define LOCAL_BUS_SIZE (4 * 1024 * 1024)
180
181/*
182 * System Controller Interface Reg
183 *
184 * Note there are NO leds on a UV system. This register is only
185 * used by the system controller to monitor system-wide operation.
186 * There are 64 regs per node. With Nahelem cpus (2 cores per node,
187 * 8 cpus per core, 2 threads per cpu) there are 32 cpu threads on
188 * a node.
189 *
190 * The window is located at top of ACPI MMR space
191 */
192#define SCIR_WINDOW_COUNT 64
193#define SCIR_LOCAL_MMR_BASE (LOCAL_BUS_BASE + \
194 LOCAL_BUS_SIZE - \
195 SCIR_WINDOW_COUNT)
196
197#define SCIR_CPU_HEARTBEAT 0x01 /* timer interrupt */
198#define SCIR_CPU_ACTIVITY 0x02 /* not idle */
199#define SCIR_CPU_HB_INTERVAL (HZ) /* once per second */
200
165/* 201/*
166 * Macros for converting between kernel virtual addresses, socket local physical 202 * Macros for converting between kernel virtual addresses, socket local physical
167 * addresses, and UV global physical addresses. 203 * addresses, and UV global physical addresses.
@@ -276,6 +312,16 @@ static inline void uv_write_local_mmr(unsigned long offset, unsigned long val)
276 *uv_local_mmr_address(offset) = val; 312 *uv_local_mmr_address(offset) = val;
277} 313}
278 314
315static inline unsigned char uv_read_local_mmr8(unsigned long offset)
316{
317 return *((unsigned char *)uv_local_mmr_address(offset));
318}
319
320static inline void uv_write_local_mmr8(unsigned long offset, unsigned char val)
321{
322 *((unsigned char *)uv_local_mmr_address(offset)) = val;
323}
324
279/* 325/*
280 * Structures and definitions for converting between cpu, node, pnode, and blade 326 * Structures and definitions for converting between cpu, node, pnode, and blade
281 * numbers. 327 * numbers.
@@ -350,5 +396,20 @@ static inline int uv_num_possible_blades(void)
350 return uv_possible_blades; 396 return uv_possible_blades;
351} 397}
352 398
353#endif /* _ASM_X86_UV_UV_HUB_H */ 399/* Update SCIR state */
400static inline void uv_set_scir_bits(unsigned char value)
401{
402 if (uv_hub_info->scir.state != value) {
403 uv_hub_info->scir.state = value;
404 uv_write_local_mmr8(uv_hub_info->scir.offset, value);
405 }
406}
407static inline void uv_set_cpu_scir_bits(int cpu, unsigned char value)
408{
409 if (uv_cpu_hub_info(cpu)->scir.state != value) {
410 uv_cpu_hub_info(cpu)->scir.state = value;
411 uv_write_local_mmr8(uv_cpu_hub_info(cpu)->scir.offset, value);
412 }
413}
354 414
415#endif /* _ASM_X86_UV_UV_HUB_H */
diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c
index dc6b4696152..84367d84bb1 100644
--- a/arch/x86/kernel/genx2apic_uv_x.c
+++ b/arch/x86/kernel/genx2apic_uv_x.c
@@ -10,6 +10,7 @@
10 10
11#include <linux/kernel.h> 11#include <linux/kernel.h>
12#include <linux/threads.h> 12#include <linux/threads.h>
13#include <linux/cpu.h>
13#include <linux/cpumask.h> 14#include <linux/cpumask.h>
14#include <linux/string.h> 15#include <linux/string.h>
15#include <linux/ctype.h> 16#include <linux/ctype.h>
@@ -18,6 +19,8 @@
18#include <linux/bootmem.h> 19#include <linux/bootmem.h>
19#include <linux/module.h> 20#include <linux/module.h>
20#include <linux/hardirq.h> 21#include <linux/hardirq.h>
22#include <linux/timer.h>
23#include <asm/current.h>
21#include <asm/smp.h> 24#include <asm/smp.h>
22#include <asm/ipi.h> 25#include <asm/ipi.h>
23#include <asm/genapic.h> 26#include <asm/genapic.h>
@@ -357,6 +360,103 @@ static __init void uv_rtc_init(void)
357} 360}
358 361
359/* 362/*
363 * percpu heartbeat timer
364 */
365static void uv_heartbeat(unsigned long ignored)
366{
367 struct timer_list *timer = &uv_hub_info->scir.timer;
368 unsigned char bits = uv_hub_info->scir.state;
369
370 /* flip heartbeat bit */
371 bits ^= SCIR_CPU_HEARTBEAT;
372
373 /* are we the idle thread? */
374 if (current->pid == 0)
375 bits &= ~SCIR_CPU_ACTIVITY;
376 else
377 bits |= SCIR_CPU_ACTIVITY;
378
379 /* update system controller interface reg */
380 uv_set_scir_bits(bits);
381
382 /* enable next timer period */
383 mod_timer(timer, jiffies + SCIR_CPU_HB_INTERVAL);
384}
385
386static void __cpuinit uv_heartbeat_enable(int cpu)
387{
388 if (!uv_cpu_hub_info(cpu)->scir.enabled) {
389 struct timer_list *timer = &uv_cpu_hub_info(cpu)->scir.timer;
390
391 uv_set_cpu_scir_bits(cpu, SCIR_CPU_HEARTBEAT|SCIR_CPU_ACTIVITY);
392 setup_timer(timer, uv_heartbeat, cpu);
393 timer->expires = jiffies + SCIR_CPU_HB_INTERVAL;
394 add_timer_on(timer, cpu);
395 uv_cpu_hub_info(cpu)->scir.enabled = 1;
396 }
397
398 /* check boot cpu */
399 if (!uv_cpu_hub_info(0)->scir.enabled)
400 uv_heartbeat_enable(0);
401}
402
403static void __cpuinit uv_heartbeat_disable(int cpu)
404{
405 if (uv_cpu_hub_info(cpu)->scir.enabled) {
406 uv_cpu_hub_info(cpu)->scir.enabled = 0;
407 del_timer(&uv_cpu_hub_info(cpu)->scir.timer);
408 }
409 uv_set_cpu_scir_bits(cpu, 0xff);
410}
411
412#ifdef CONFIG_HOTPLUG_CPU
413/*
414 * cpu hotplug notifier
415 */
416static __cpuinit int uv_scir_cpu_notify(struct notifier_block *self,
417 unsigned long action, void *hcpu)
418{
419 long cpu = (long)hcpu;
420
421 switch (action) {
422 case CPU_ONLINE:
423 uv_heartbeat_enable(cpu);
424 break;
425 case CPU_DOWN_PREPARE:
426 uv_heartbeat_disable(cpu);
427 break;
428 default:
429 break;
430 }
431 return NOTIFY_OK;
432}
433
434static __init void uv_scir_register_cpu_notifier(void)
435{
436 hotcpu_notifier(uv_scir_cpu_notify, 0);
437}
438
439#else /* !CONFIG_HOTPLUG_CPU */
440
441static __init void uv_scir_register_cpu_notifier(void)
442{
443}
444
445static __init int uv_init_heartbeat(void)
446{
447 int cpu;
448
449 if (is_uv_system())
450 for_each_online_cpu(cpu)
451 uv_heartbeat_enable(cpu);
452 return 0;
453}
454
455late_initcall(uv_init_heartbeat);
456
457#endif /* !CONFIG_HOTPLUG_CPU */
458
459/*
360 * Called on each cpu to initialize the per_cpu UV data area. 460 * Called on each cpu to initialize the per_cpu UV data area.
361 * ZZZ hotplug not supported yet 461 * ZZZ hotplug not supported yet
362 */ 462 */
@@ -452,6 +552,7 @@ void __init uv_system_init(void)
452 uv_cpu_hub_info(cpu)->gnode_upper = gnode_upper; 552 uv_cpu_hub_info(cpu)->gnode_upper = gnode_upper;
453 uv_cpu_hub_info(cpu)->global_mmr_base = mmr_base; 553 uv_cpu_hub_info(cpu)->global_mmr_base = mmr_base;
454 uv_cpu_hub_info(cpu)->coherency_domain_number = sn_coherency_id; 554 uv_cpu_hub_info(cpu)->coherency_domain_number = sn_coherency_id;
555 uv_cpu_hub_info(cpu)->scir.offset = SCIR_LOCAL_MMR_BASE + lcpu;
455 uv_node_to_blade[nid] = blade; 556 uv_node_to_blade[nid] = blade;
456 uv_cpu_to_blade[cpu] = blade; 557 uv_cpu_to_blade[cpu] = blade;
457 max_pnode = max(pnode, max_pnode); 558 max_pnode = max(pnode, max_pnode);
@@ -468,4 +569,5 @@ void __init uv_system_init(void)
468 map_mmioh_high(max_pnode); 569 map_mmioh_high(max_pnode);
469 570
470 uv_cpu_init(); 571 uv_cpu_init();
572 uv_scir_register_cpu_notifier();
471} 573}