diff options
| -rw-r--r-- | arch/x86/include/asm/uv/uv_hub.h | 21 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/x2apic_uv_x.c | 25 |
2 files changed, 41 insertions, 5 deletions
diff --git a/arch/x86/include/asm/uv/uv_hub.h b/arch/x86/include/asm/uv/uv_hub.h index bf6b88ef8eeb..e969f691cbfd 100644 --- a/arch/x86/include/asm/uv/uv_hub.h +++ b/arch/x86/include/asm/uv/uv_hub.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * SGI UV architectural definitions | 6 | * SGI UV architectural definitions |
| 7 | * | 7 | * |
| 8 | * Copyright (C) 2007-2008 Silicon Graphics, Inc. All rights reserved. | 8 | * Copyright (C) 2007-2010 Silicon Graphics, Inc. All rights reserved. |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | #ifndef _ASM_X86_UV_UV_HUB_H | 11 | #ifndef _ASM_X86_UV_UV_HUB_H |
| @@ -77,7 +77,8 @@ | |||
| 77 | * | 77 | * |
| 78 | * 1111110000000000 | 78 | * 1111110000000000 |
| 79 | * 5432109876543210 | 79 | * 5432109876543210 |
| 80 | * pppppppppplc0cch | 80 | * pppppppppplc0cch Nehalem-EX |
| 81 | * ppppppppplcc0cch Westmere-EX | ||
| 81 | * sssssssssss | 82 | * sssssssssss |
| 82 | * | 83 | * |
| 83 | * p = pnode bits | 84 | * p = pnode bits |
| @@ -148,12 +149,25 @@ struct uv_hub_info_s { | |||
| 148 | unsigned char m_val; | 149 | unsigned char m_val; |
| 149 | unsigned char n_val; | 150 | unsigned char n_val; |
| 150 | struct uv_scir_s scir; | 151 | struct uv_scir_s scir; |
| 152 | unsigned char apic_pnode_shift; | ||
| 151 | }; | 153 | }; |
| 152 | 154 | ||
| 153 | DECLARE_PER_CPU(struct uv_hub_info_s, __uv_hub_info); | 155 | DECLARE_PER_CPU(struct uv_hub_info_s, __uv_hub_info); |
| 154 | #define uv_hub_info (&__get_cpu_var(__uv_hub_info)) | 156 | #define uv_hub_info (&__get_cpu_var(__uv_hub_info)) |
| 155 | #define uv_cpu_hub_info(cpu) (&per_cpu(__uv_hub_info, cpu)) | 157 | #define uv_cpu_hub_info(cpu) (&per_cpu(__uv_hub_info, cpu)) |
| 156 | 158 | ||
| 159 | union uvh_apicid { | ||
| 160 | unsigned long v; | ||
| 161 | struct uvh_apicid_s { | ||
| 162 | unsigned long local_apic_mask : 24; | ||
| 163 | unsigned long local_apic_shift : 5; | ||
| 164 | unsigned long unused1 : 3; | ||
| 165 | unsigned long pnode_mask : 24; | ||
| 166 | unsigned long pnode_shift : 5; | ||
| 167 | unsigned long unused2 : 3; | ||
| 168 | } s; | ||
| 169 | }; | ||
| 170 | |||
| 157 | /* | 171 | /* |
| 158 | * Local & Global MMR space macros. | 172 | * Local & Global MMR space macros. |
| 159 | * Note: macros are intended to be used ONLY by inline functions | 173 | * Note: macros are intended to be used ONLY by inline functions |
| @@ -182,6 +196,7 @@ DECLARE_PER_CPU(struct uv_hub_info_s, __uv_hub_info); | |||
| 182 | #define UV_GLOBAL_MMR64_PNODE_BITS(p) \ | 196 | #define UV_GLOBAL_MMR64_PNODE_BITS(p) \ |
| 183 | (((unsigned long)(p)) << UV_GLOBAL_MMR64_PNODE_SHIFT) | 197 | (((unsigned long)(p)) << UV_GLOBAL_MMR64_PNODE_SHIFT) |
| 184 | 198 | ||
| 199 | #define UVH_APICID 0x002D0E00L | ||
| 185 | #define UV_APIC_PNODE_SHIFT 6 | 200 | #define UV_APIC_PNODE_SHIFT 6 |
| 186 | 201 | ||
| 187 | /* Local Bus from cpu's perspective */ | 202 | /* Local Bus from cpu's perspective */ |
| @@ -280,7 +295,7 @@ static inline void *uv_pnode_offset_to_vaddr(int pnode, unsigned long offset) | |||
| 280 | */ | 295 | */ |
| 281 | static inline int uv_apicid_to_pnode(int apicid) | 296 | static inline int uv_apicid_to_pnode(int apicid) |
| 282 | { | 297 | { |
| 283 | return (apicid >> UV_APIC_PNODE_SHIFT); | 298 | return (apicid >> uv_hub_info->apic_pnode_shift); |
| 284 | } | 299 | } |
| 285 | 300 | ||
| 286 | /* | 301 | /* |
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index f744f54cb248..0a2918eaab34 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * SGI UV APIC functions (note: not an Intel compatible APIC) | 6 | * SGI UV APIC functions (note: not an Intel compatible APIC) |
| 7 | * | 7 | * |
| 8 | * Copyright (C) 2007-2009 Silicon Graphics, Inc. All rights reserved. | 8 | * Copyright (C) 2007-2010 Silicon Graphics, Inc. All rights reserved. |
| 9 | */ | 9 | */ |
| 10 | #include <linux/cpumask.h> | 10 | #include <linux/cpumask.h> |
| 11 | #include <linux/hardirq.h> | 11 | #include <linux/hardirq.h> |
| @@ -41,6 +41,7 @@ DEFINE_PER_CPU(int, x2apic_extra_bits); | |||
| 41 | 41 | ||
| 42 | static enum uv_system_type uv_system_type; | 42 | static enum uv_system_type uv_system_type; |
| 43 | static u64 gru_start_paddr, gru_end_paddr; | 43 | static u64 gru_start_paddr, gru_end_paddr; |
| 44 | static union uvh_apicid uvh_apicid; | ||
| 44 | int uv_min_hub_revision_id; | 45 | int uv_min_hub_revision_id; |
| 45 | EXPORT_SYMBOL_GPL(uv_min_hub_revision_id); | 46 | EXPORT_SYMBOL_GPL(uv_min_hub_revision_id); |
| 46 | static DEFINE_SPINLOCK(uv_nmi_lock); | 47 | static DEFINE_SPINLOCK(uv_nmi_lock); |
| @@ -70,6 +71,22 @@ static int early_get_nodeid(void) | |||
| 70 | return node_id.s.node_id; | 71 | return node_id.s.node_id; |
| 71 | } | 72 | } |
| 72 | 73 | ||
| 74 | static int __init early_get_apic_pnode_shift(void) | ||
| 75 | { | ||
| 76 | unsigned long *mmr; | ||
| 77 | |||
| 78 | mmr = early_ioremap(UV_LOCAL_MMR_BASE | UVH_APICID, sizeof(*mmr)); | ||
| 79 | uvh_apicid.v = *mmr; | ||
| 80 | early_iounmap(mmr, sizeof(*mmr)); | ||
| 81 | if (!uvh_apicid.v) | ||
| 82 | /* | ||
| 83 | * Old bios, use default value | ||
| 84 | */ | ||
| 85 | uvh_apicid.s.pnode_shift = UV_APIC_PNODE_SHIFT; | ||
| 86 | |||
| 87 | return uvh_apicid.s.pnode_shift; | ||
| 88 | } | ||
| 89 | |||
| 73 | static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | 90 | static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id) |
| 74 | { | 91 | { |
| 75 | int nodeid; | 92 | int nodeid; |
| @@ -84,7 +101,7 @@ static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | |||
| 84 | uv_system_type = UV_X2APIC; | 101 | uv_system_type = UV_X2APIC; |
| 85 | else if (!strcmp(oem_table_id, "UVH")) { | 102 | else if (!strcmp(oem_table_id, "UVH")) { |
| 86 | __get_cpu_var(x2apic_extra_bits) = | 103 | __get_cpu_var(x2apic_extra_bits) = |
| 87 | nodeid << (UV_APIC_PNODE_SHIFT - 1); | 104 | nodeid << (early_get_apic_pnode_shift() - 1); |
| 88 | uv_system_type = UV_NON_UNIQUE_APIC; | 105 | uv_system_type = UV_NON_UNIQUE_APIC; |
| 89 | return 1; | 106 | return 1; |
| 90 | } | 107 | } |
| @@ -716,6 +733,10 @@ void __init uv_system_init(void) | |||
| 716 | int apicid = per_cpu(x86_cpu_to_apicid, cpu); | 733 | int apicid = per_cpu(x86_cpu_to_apicid, cpu); |
| 717 | 734 | ||
| 718 | nid = cpu_to_node(cpu); | 735 | nid = cpu_to_node(cpu); |
| 736 | /* | ||
| 737 | * apic_pnode_shift must be set before calling uv_apicid_to_pnode(); | ||
| 738 | */ | ||
| 739 | uv_cpu_hub_info(cpu)->apic_pnode_shift = uvh_apicid.s.pnode_shift; | ||
| 719 | pnode = uv_apicid_to_pnode(apicid); | 740 | pnode = uv_apicid_to_pnode(apicid); |
| 720 | blade = boot_pnode_to_blade(pnode); | 741 | blade = boot_pnode_to_blade(pnode); |
| 721 | lcpu = uv_blade_info[blade].nr_possible_cpus; | 742 | lcpu = uv_blade_info[blade].nr_possible_cpus; |
