.. | .. |
---|
5 | 5 | * |
---|
6 | 6 | * SGI UV APIC functions (note: not an Intel compatible APIC) |
---|
7 | 7 | * |
---|
| 8 | + * (C) Copyright 2020 Hewlett Packard Enterprise Development LP |
---|
8 | 9 | * Copyright (C) 2007-2014 Silicon Graphics, Inc. All rights reserved. |
---|
9 | 10 | */ |
---|
10 | | -#include <linux/cpumask.h> |
---|
11 | | -#include <linux/hardirq.h> |
---|
12 | | -#include <linux/proc_fs.h> |
---|
13 | | -#include <linux/threads.h> |
---|
14 | | -#include <linux/kernel.h> |
---|
15 | | -#include <linux/export.h> |
---|
16 | | -#include <linux/string.h> |
---|
17 | | -#include <linux/ctype.h> |
---|
18 | | -#include <linux/sched.h> |
---|
19 | | -#include <linux/timer.h> |
---|
20 | | -#include <linux/slab.h> |
---|
21 | | -#include <linux/cpu.h> |
---|
22 | | -#include <linux/init.h> |
---|
23 | | -#include <linux/io.h> |
---|
24 | | -#include <linux/pci.h> |
---|
25 | | -#include <linux/kdebug.h> |
---|
26 | | -#include <linux/delay.h> |
---|
27 | 11 | #include <linux/crash_dump.h> |
---|
28 | | -#include <linux/reboot.h> |
---|
| 12 | +#include <linux/cpuhotplug.h> |
---|
| 13 | +#include <linux/cpumask.h> |
---|
| 14 | +#include <linux/proc_fs.h> |
---|
29 | 15 | #include <linux/memory.h> |
---|
| 16 | +#include <linux/export.h> |
---|
| 17 | +#include <linux/pci.h> |
---|
| 18 | +#include <linux/acpi.h> |
---|
| 19 | +#include <linux/efi.h> |
---|
30 | 20 | |
---|
| 21 | +#include <asm/e820/api.h> |
---|
31 | 22 | #include <asm/uv/uv_mmrs.h> |
---|
32 | 23 | #include <asm/uv/uv_hub.h> |
---|
33 | | -#include <asm/current.h> |
---|
34 | | -#include <asm/pgtable.h> |
---|
35 | 24 | #include <asm/uv/bios.h> |
---|
36 | 25 | #include <asm/uv/uv.h> |
---|
37 | 26 | #include <asm/apic.h> |
---|
38 | | -#include <asm/e820/api.h> |
---|
39 | | -#include <asm/ipi.h> |
---|
40 | | -#include <asm/smp.h> |
---|
41 | | -#include <asm/x86_init.h> |
---|
42 | | -#include <asm/nmi.h> |
---|
43 | | - |
---|
44 | | -DEFINE_PER_CPU(int, x2apic_extra_bits); |
---|
45 | 27 | |
---|
46 | 28 | static enum uv_system_type uv_system_type; |
---|
47 | | -static bool uv_hubless_system; |
---|
| 29 | +static int uv_hubbed_system; |
---|
| 30 | +static int uv_hubless_system; |
---|
48 | 31 | static u64 gru_start_paddr, gru_end_paddr; |
---|
49 | | -static u64 gru_dist_base, gru_first_node_paddr = -1LL, gru_last_node_paddr; |
---|
50 | | -static u64 gru_dist_lmask, gru_dist_umask; |
---|
51 | 32 | static union uvh_apicid uvh_apicid; |
---|
| 33 | +static int uv_node_id; |
---|
52 | 34 | |
---|
53 | | -/* Information derived from CPUID: */ |
---|
| 35 | +/* Unpack AT/OEM/TABLE ID's to be NULL terminated strings */ |
---|
| 36 | +static u8 uv_archtype[UV_AT_SIZE + 1]; |
---|
| 37 | +static u8 oem_id[ACPI_OEM_ID_SIZE + 1]; |
---|
| 38 | +static u8 oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1]; |
---|
| 39 | + |
---|
| 40 | +/* Information derived from CPUID and some UV MMRs */ |
---|
54 | 41 | static struct { |
---|
55 | 42 | unsigned int apicid_shift; |
---|
56 | 43 | unsigned int apicid_mask; |
---|
57 | | - unsigned int socketid_shift; /* aka pnode_shift for UV1/2/3 */ |
---|
| 44 | + unsigned int socketid_shift; /* aka pnode_shift for UV2/3 */ |
---|
58 | 45 | unsigned int pnode_mask; |
---|
| 46 | + unsigned int nasid_shift; |
---|
59 | 47 | unsigned int gpa_shift; |
---|
60 | 48 | unsigned int gnode_shift; |
---|
| 49 | + unsigned int m_skt; |
---|
| 50 | + unsigned int n_skt; |
---|
61 | 51 | } uv_cpuid; |
---|
62 | 52 | |
---|
63 | | -int uv_min_hub_revision_id; |
---|
64 | | -EXPORT_SYMBOL_GPL(uv_min_hub_revision_id); |
---|
65 | | - |
---|
66 | | -unsigned int uv_apicid_hibits; |
---|
67 | | -EXPORT_SYMBOL_GPL(uv_apicid_hibits); |
---|
| 53 | +static int uv_min_hub_revision_id; |
---|
68 | 54 | |
---|
69 | 55 | static struct apic apic_x2apic_uv_x; |
---|
70 | 56 | static struct uv_hub_info_s uv_hub_info_node0; |
---|
.. | .. |
---|
97 | 83 | |
---|
98 | 84 | static inline bool is_GRU_range(u64 start, u64 end) |
---|
99 | 85 | { |
---|
100 | | - if (gru_dist_base) { |
---|
101 | | - u64 su = start & gru_dist_umask; /* Upper (incl pnode) bits */ |
---|
102 | | - u64 sl = start & gru_dist_lmask; /* Base offset bits */ |
---|
103 | | - u64 eu = end & gru_dist_umask; |
---|
104 | | - u64 el = end & gru_dist_lmask; |
---|
| 86 | + if (!gru_start_paddr) |
---|
| 87 | + return false; |
---|
105 | 88 | |
---|
106 | | - /* Must reside completely within a single GRU range: */ |
---|
107 | | - return (sl == gru_dist_base && el == gru_dist_base && |
---|
108 | | - su >= gru_first_node_paddr && |
---|
109 | | - su <= gru_last_node_paddr && |
---|
110 | | - eu == su); |
---|
111 | | - } else { |
---|
112 | | - return start >= gru_start_paddr && end <= gru_end_paddr; |
---|
113 | | - } |
---|
| 89 | + return start >= gru_start_paddr && end <= gru_end_paddr; |
---|
114 | 90 | } |
---|
115 | 91 | |
---|
116 | 92 | static bool uv_is_untracked_pat_range(u64 start, u64 end) |
---|
.. | .. |
---|
118 | 94 | return is_ISA_range(start, end) || is_GRU_range(start, end); |
---|
119 | 95 | } |
---|
120 | 96 | |
---|
121 | | -static int __init early_get_pnodeid(void) |
---|
| 97 | +static void __init early_get_pnodeid(void) |
---|
122 | 98 | { |
---|
123 | | - union uvh_node_id_u node_id; |
---|
124 | | - union uvh_rh_gam_config_mmr_u m_n_config; |
---|
125 | 99 | int pnode; |
---|
126 | 100 | |
---|
127 | | - /* Currently, all blades have same revision number */ |
---|
128 | | - node_id.v = uv_early_read_mmr(UVH_NODE_ID); |
---|
129 | | - m_n_config.v = uv_early_read_mmr(UVH_RH_GAM_CONFIG_MMR); |
---|
130 | | - uv_min_hub_revision_id = node_id.s.revision; |
---|
| 101 | + uv_cpuid.m_skt = 0; |
---|
| 102 | + if (UVH_RH10_GAM_ADDR_MAP_CONFIG) { |
---|
| 103 | + union uvh_rh10_gam_addr_map_config_u m_n_config; |
---|
131 | 104 | |
---|
132 | | - switch (node_id.s.part_number) { |
---|
133 | | - case UV2_HUB_PART_NUMBER: |
---|
134 | | - case UV2_HUB_PART_NUMBER_X: |
---|
135 | | - uv_min_hub_revision_id += UV2_HUB_REVISION_BASE - 1; |
---|
136 | | - break; |
---|
137 | | - case UV3_HUB_PART_NUMBER: |
---|
138 | | - case UV3_HUB_PART_NUMBER_X: |
---|
139 | | - uv_min_hub_revision_id += UV3_HUB_REVISION_BASE; |
---|
140 | | - break; |
---|
| 105 | + m_n_config.v = uv_early_read_mmr(UVH_RH10_GAM_ADDR_MAP_CONFIG); |
---|
| 106 | + uv_cpuid.n_skt = m_n_config.s.n_skt; |
---|
| 107 | + uv_cpuid.nasid_shift = 0; |
---|
| 108 | + } else if (UVH_RH_GAM_ADDR_MAP_CONFIG) { |
---|
| 109 | + union uvh_rh_gam_addr_map_config_u m_n_config; |
---|
141 | 110 | |
---|
142 | | - /* Update: UV4A has only a modified revision to indicate HUB fixes */ |
---|
143 | | - case UV4_HUB_PART_NUMBER: |
---|
144 | | - uv_min_hub_revision_id += UV4_HUB_REVISION_BASE - 1; |
---|
145 | | - uv_cpuid.gnode_shift = 2; /* min partition is 4 sockets */ |
---|
146 | | - break; |
---|
| 111 | + m_n_config.v = uv_early_read_mmr(UVH_RH_GAM_ADDR_MAP_CONFIG); |
---|
| 112 | + uv_cpuid.n_skt = m_n_config.s.n_skt; |
---|
| 113 | + if (is_uv(UV3)) |
---|
| 114 | + uv_cpuid.m_skt = m_n_config.s3.m_skt; |
---|
| 115 | + if (is_uv(UV2)) |
---|
| 116 | + uv_cpuid.m_skt = m_n_config.s2.m_skt; |
---|
| 117 | + uv_cpuid.nasid_shift = 1; |
---|
| 118 | + } else { |
---|
| 119 | + unsigned long GAM_ADDR_MAP_CONFIG = 0; |
---|
| 120 | + |
---|
| 121 | + WARN(GAM_ADDR_MAP_CONFIG == 0, |
---|
| 122 | + "UV: WARN: GAM_ADDR_MAP_CONFIG is not available\n"); |
---|
| 123 | + uv_cpuid.n_skt = 0; |
---|
| 124 | + uv_cpuid.nasid_shift = 0; |
---|
147 | 125 | } |
---|
148 | 126 | |
---|
149 | | - uv_hub_info->hub_revision = uv_min_hub_revision_id; |
---|
150 | | - uv_cpuid.pnode_mask = (1 << m_n_config.s.n_skt) - 1; |
---|
151 | | - pnode = (node_id.s.node_id >> 1) & uv_cpuid.pnode_mask; |
---|
| 127 | + if (is_uv(UV4|UVY)) |
---|
| 128 | + uv_cpuid.gnode_shift = 2; /* min partition is 4 sockets */ |
---|
| 129 | + |
---|
| 130 | + uv_cpuid.pnode_mask = (1 << uv_cpuid.n_skt) - 1; |
---|
| 131 | + pnode = (uv_node_id >> uv_cpuid.nasid_shift) & uv_cpuid.pnode_mask; |
---|
152 | 132 | uv_cpuid.gpa_shift = 46; /* Default unless changed */ |
---|
153 | 133 | |
---|
154 | | - pr_info("UV: rev:%d part#:%x nodeid:%04x n_skt:%d pnmsk:%x pn:%x\n", |
---|
155 | | - node_id.s.revision, node_id.s.part_number, node_id.s.node_id, |
---|
156 | | - m_n_config.s.n_skt, uv_cpuid.pnode_mask, pnode); |
---|
157 | | - return pnode; |
---|
| 134 | + pr_info("UV: n_skt:%d pnmsk:%x pn:%x\n", |
---|
| 135 | + uv_cpuid.n_skt, uv_cpuid.pnode_mask, pnode); |
---|
| 136 | +} |
---|
| 137 | + |
---|
| 138 | +/* Running on a UV Hubbed system, determine which UV Hub Type it is */ |
---|
| 139 | +static int __init early_set_hub_type(void) |
---|
| 140 | +{ |
---|
| 141 | + union uvh_node_id_u node_id; |
---|
| 142 | + |
---|
| 143 | + /* |
---|
| 144 | + * The NODE_ID MMR is always at offset 0. |
---|
| 145 | + * Contains the chip part # + revision. |
---|
| 146 | + * Node_id field started with 15 bits, |
---|
| 147 | + * ... now 7 but upper 8 are masked to 0. |
---|
| 148 | + * All blades/nodes have the same part # and hub revision. |
---|
| 149 | + */ |
---|
| 150 | + node_id.v = uv_early_read_mmr(UVH_NODE_ID); |
---|
| 151 | + uv_node_id = node_id.sx.node_id; |
---|
| 152 | + |
---|
| 153 | + switch (node_id.s.part_number) { |
---|
| 154 | + |
---|
| 155 | + case UV5_HUB_PART_NUMBER: |
---|
| 156 | + uv_min_hub_revision_id = node_id.s.revision |
---|
| 157 | + + UV5_HUB_REVISION_BASE; |
---|
| 158 | + uv_hub_type_set(UV5); |
---|
| 159 | + break; |
---|
| 160 | + |
---|
| 161 | + /* UV4/4A only have a revision difference */ |
---|
| 162 | + case UV4_HUB_PART_NUMBER: |
---|
| 163 | + uv_min_hub_revision_id = node_id.s.revision |
---|
| 164 | + + UV4_HUB_REVISION_BASE - 1; |
---|
| 165 | + uv_hub_type_set(UV4); |
---|
| 166 | + if (uv_min_hub_revision_id == UV4A_HUB_REVISION_BASE) |
---|
| 167 | + uv_hub_type_set(UV4|UV4A); |
---|
| 168 | + break; |
---|
| 169 | + |
---|
| 170 | + case UV3_HUB_PART_NUMBER: |
---|
| 171 | + case UV3_HUB_PART_NUMBER_X: |
---|
| 172 | + uv_min_hub_revision_id = node_id.s.revision |
---|
| 173 | + + UV3_HUB_REVISION_BASE; |
---|
| 174 | + uv_hub_type_set(UV3); |
---|
| 175 | + break; |
---|
| 176 | + |
---|
| 177 | + case UV2_HUB_PART_NUMBER: |
---|
| 178 | + case UV2_HUB_PART_NUMBER_X: |
---|
| 179 | + uv_min_hub_revision_id = node_id.s.revision |
---|
| 180 | + + UV2_HUB_REVISION_BASE - 1; |
---|
| 181 | + uv_hub_type_set(UV2); |
---|
| 182 | + break; |
---|
| 183 | + |
---|
| 184 | + default: |
---|
| 185 | + return 0; |
---|
| 186 | + } |
---|
| 187 | + |
---|
| 188 | + pr_info("UV: part#:%x rev:%d rev_id:%d UVtype:0x%x\n", |
---|
| 189 | + node_id.s.part_number, node_id.s.revision, |
---|
| 190 | + uv_min_hub_revision_id, is_uv(~0)); |
---|
| 191 | + |
---|
| 192 | + return 1; |
---|
158 | 193 | } |
---|
159 | 194 | |
---|
160 | 195 | static void __init uv_tsc_check_sync(void) |
---|
.. | .. |
---|
163 | 198 | int sync_state; |
---|
164 | 199 | int mmr_shift; |
---|
165 | 200 | char *state; |
---|
166 | | - bool valid; |
---|
167 | 201 | |
---|
168 | | - /* Accommodate different UV arch BIOSes */ |
---|
| 202 | + /* UV5 guarantees synced TSCs; do not zero TSC_ADJUST */ |
---|
| 203 | + if (!is_uv(UV2|UV3|UV4)) { |
---|
| 204 | + mark_tsc_async_resets("UV5+"); |
---|
| 205 | + return; |
---|
| 206 | + } |
---|
| 207 | + |
---|
| 208 | + /* UV2,3,4, UV BIOS TSC sync state available */ |
---|
169 | 209 | mmr = uv_early_read_mmr(UVH_TSC_SYNC_MMR); |
---|
170 | 210 | mmr_shift = |
---|
171 | | - is_uv1_hub() ? 0 : |
---|
172 | 211 | is_uv2_hub() ? UVH_TSC_SYNC_SHIFT_UV2K : UVH_TSC_SYNC_SHIFT; |
---|
173 | | - if (mmr_shift) |
---|
174 | | - sync_state = (mmr >> mmr_shift) & UVH_TSC_SYNC_MASK; |
---|
175 | | - else |
---|
176 | | - sync_state = 0; |
---|
| 212 | + sync_state = (mmr >> mmr_shift) & UVH_TSC_SYNC_MASK; |
---|
177 | 213 | |
---|
| 214 | + /* Check if TSC is valid for all sockets */ |
---|
178 | 215 | switch (sync_state) { |
---|
179 | 216 | case UVH_TSC_SYNC_VALID: |
---|
180 | 217 | state = "in sync"; |
---|
181 | | - valid = true; |
---|
| 218 | + mark_tsc_async_resets("UV BIOS"); |
---|
182 | 219 | break; |
---|
183 | 220 | |
---|
184 | | - case UVH_TSC_SYNC_INVALID: |
---|
185 | | - state = "unstable"; |
---|
186 | | - valid = false; |
---|
| 221 | + /* If BIOS state unknown, don't do anything */ |
---|
| 222 | + case UVH_TSC_SYNC_UNKNOWN: |
---|
| 223 | + state = "unknown"; |
---|
187 | 224 | break; |
---|
| 225 | + |
---|
| 226 | + /* Otherwise, BIOS indicates problem with TSC */ |
---|
188 | 227 | default: |
---|
189 | | - state = "unknown: assuming valid"; |
---|
190 | | - valid = true; |
---|
| 228 | + state = "unstable"; |
---|
| 229 | + mark_tsc_unstable("UV BIOS"); |
---|
191 | 230 | break; |
---|
192 | 231 | } |
---|
193 | 232 | pr_info("UV: TSC sync state from BIOS:0%d(%s)\n", sync_state, state); |
---|
194 | | - |
---|
195 | | - /* Mark flag that says TSC != 0 is valid for socket 0 */ |
---|
196 | | - if (valid) |
---|
197 | | - mark_tsc_async_resets("UV BIOS"); |
---|
198 | | - else |
---|
199 | | - mark_tsc_unstable("UV BIOS"); |
---|
200 | 233 | } |
---|
| 234 | + |
---|
| 235 | +/* Selector for (4|4A|5) structs */ |
---|
| 236 | +#define uvxy_field(sname, field, undef) ( \ |
---|
| 237 | + is_uv(UV4A) ? sname.s4a.field : \ |
---|
| 238 | + is_uv(UV4) ? sname.s4.field : \ |
---|
| 239 | + is_uv(UV3) ? sname.s3.field : \ |
---|
| 240 | + undef) |
---|
201 | 241 | |
---|
202 | 242 | /* [Copied from arch/x86/kernel/cpu/topology.c:detect_extended_topology()] */ |
---|
203 | 243 | |
---|
.. | .. |
---|
252 | 292 | pr_info("UV: socketid_shift:%d pnode_mask:0x%x\n", uv_cpuid.socketid_shift, uv_cpuid.pnode_mask); |
---|
253 | 293 | } |
---|
254 | 294 | |
---|
255 | | -/* |
---|
256 | | - * Add an extra bit as dictated by bios to the destination apicid of |
---|
257 | | - * interrupts potentially passing through the UV HUB. This prevents |
---|
258 | | - * a deadlock between interrupts and IO port operations. |
---|
259 | | - */ |
---|
260 | | -static void __init uv_set_apicid_hibit(void) |
---|
| 295 | +static void __init uv_stringify(int len, char *to, char *from) |
---|
261 | 296 | { |
---|
262 | | - union uv1h_lb_target_physical_apic_id_mask_u apicid_mask; |
---|
| 297 | + /* Relies on 'to' being NULL chars so result will be NULL terminated */ |
---|
| 298 | + strncpy(to, from, len-1); |
---|
263 | 299 | |
---|
264 | | - if (is_uv1_hub()) { |
---|
265 | | - apicid_mask.v = uv_early_read_mmr(UV1H_LB_TARGET_PHYSICAL_APIC_ID_MASK); |
---|
266 | | - uv_apicid_hibits = apicid_mask.s1.bit_enables & UV_APICID_HIBIT_MASK; |
---|
267 | | - } |
---|
| 300 | + /* Trim trailing spaces */ |
---|
| 301 | + (void)strim(to); |
---|
268 | 302 | } |
---|
269 | 303 | |
---|
270 | | -static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id) |
---|
| 304 | +/* Find UV arch type entry in UVsystab */ |
---|
| 305 | +static unsigned long __init early_find_archtype(struct uv_systab *st) |
---|
271 | 306 | { |
---|
272 | | - int pnodeid; |
---|
273 | | - int uv_apic; |
---|
| 307 | + int i; |
---|
274 | 308 | |
---|
275 | | - if (strncmp(oem_id, "SGI", 3) != 0) { |
---|
276 | | - if (strncmp(oem_id, "NSGI", 4) == 0) { |
---|
277 | | - uv_hubless_system = true; |
---|
278 | | - pr_info("UV: OEM IDs %s/%s, HUBLESS\n", |
---|
279 | | - oem_id, oem_table_id); |
---|
280 | | - } |
---|
| 309 | + for (i = 0; st->entry[i].type != UV_SYSTAB_TYPE_UNUSED; i++) { |
---|
| 310 | + unsigned long ptr = st->entry[i].offset; |
---|
| 311 | + |
---|
| 312 | + if (!ptr) |
---|
| 313 | + continue; |
---|
| 314 | + ptr += (unsigned long)st; |
---|
| 315 | + if (st->entry[i].type == UV_SYSTAB_TYPE_ARCH_TYPE) |
---|
| 316 | + return ptr; |
---|
| 317 | + } |
---|
| 318 | + return 0; |
---|
| 319 | +} |
---|
| 320 | + |
---|
| 321 | +/* Validate UV arch type field in UVsystab */ |
---|
| 322 | +static int __init decode_arch_type(unsigned long ptr) |
---|
| 323 | +{ |
---|
| 324 | + struct uv_arch_type_entry *uv_ate = (struct uv_arch_type_entry *)ptr; |
---|
| 325 | + int n = strlen(uv_ate->archtype); |
---|
| 326 | + |
---|
| 327 | + if (n > 0 && n < sizeof(uv_ate->archtype)) { |
---|
| 328 | + pr_info("UV: UVarchtype received from BIOS\n"); |
---|
| 329 | + uv_stringify(sizeof(uv_archtype), uv_archtype, uv_ate->archtype); |
---|
| 330 | + return 1; |
---|
| 331 | + } |
---|
| 332 | + return 0; |
---|
| 333 | +} |
---|
| 334 | + |
---|
| 335 | +/* Determine if UV arch type entry might exist in UVsystab */ |
---|
| 336 | +static int __init early_get_arch_type(void) |
---|
| 337 | +{ |
---|
| 338 | + unsigned long uvst_physaddr, uvst_size, ptr; |
---|
| 339 | + struct uv_systab *st; |
---|
| 340 | + u32 rev; |
---|
| 341 | + int ret; |
---|
| 342 | + |
---|
| 343 | + uvst_physaddr = get_uv_systab_phys(0); |
---|
| 344 | + if (!uvst_physaddr) |
---|
| 345 | + return 0; |
---|
| 346 | + |
---|
| 347 | + st = early_memremap_ro(uvst_physaddr, sizeof(struct uv_systab)); |
---|
| 348 | + if (!st) { |
---|
| 349 | + pr_err("UV: Cannot access UVsystab, remap failed\n"); |
---|
| 350 | + return 0; |
---|
| 351 | + } |
---|
| 352 | + |
---|
| 353 | + rev = st->revision; |
---|
| 354 | + if (rev < UV_SYSTAB_VERSION_UV5) { |
---|
| 355 | + early_memunmap(st, sizeof(struct uv_systab)); |
---|
| 356 | + return 0; |
---|
| 357 | + } |
---|
| 358 | + |
---|
| 359 | + uvst_size = st->size; |
---|
| 360 | + early_memunmap(st, sizeof(struct uv_systab)); |
---|
| 361 | + st = early_memremap_ro(uvst_physaddr, uvst_size); |
---|
| 362 | + if (!st) { |
---|
| 363 | + pr_err("UV: Cannot access UVarchtype, remap failed\n"); |
---|
| 364 | + return 0; |
---|
| 365 | + } |
---|
| 366 | + |
---|
| 367 | + ptr = early_find_archtype(st); |
---|
| 368 | + if (!ptr) { |
---|
| 369 | + early_memunmap(st, uvst_size); |
---|
| 370 | + return 0; |
---|
| 371 | + } |
---|
| 372 | + |
---|
| 373 | + ret = decode_arch_type(ptr); |
---|
| 374 | + early_memunmap(st, uvst_size); |
---|
| 375 | + return ret; |
---|
| 376 | +} |
---|
| 377 | + |
---|
| 378 | +static int __init uv_set_system_type(char *_oem_id, char *_oem_table_id) |
---|
| 379 | +{ |
---|
| 380 | + /* Save OEM_ID passed from ACPI MADT */ |
---|
| 381 | + uv_stringify(sizeof(oem_id), oem_id, _oem_id); |
---|
| 382 | + |
---|
| 383 | + /* Check if BIOS sent us a UVarchtype */ |
---|
| 384 | + if (!early_get_arch_type()) |
---|
| 385 | + |
---|
| 386 | + /* If not use OEM ID for UVarchtype */ |
---|
| 387 | + uv_stringify(sizeof(uv_archtype), uv_archtype, oem_id); |
---|
| 388 | + |
---|
| 389 | + /* Check if not hubbed */ |
---|
| 390 | + if (strncmp(uv_archtype, "SGI", 3) != 0) { |
---|
| 391 | + |
---|
| 392 | + /* (Not hubbed), check if not hubless */ |
---|
| 393 | + if (strncmp(uv_archtype, "NSGI", 4) != 0) |
---|
| 394 | + |
---|
| 395 | + /* (Not hubless), not a UV */ |
---|
| 396 | + return 0; |
---|
| 397 | + |
---|
| 398 | + /* Is UV hubless system */ |
---|
| 399 | + uv_hubless_system = 0x01; |
---|
| 400 | + |
---|
| 401 | + /* UV5 Hubless */ |
---|
| 402 | + if (strncmp(uv_archtype, "NSGI5", 5) == 0) |
---|
| 403 | + uv_hubless_system |= 0x20; |
---|
| 404 | + |
---|
| 405 | + /* UV4 Hubless: CH */ |
---|
| 406 | + else if (strncmp(uv_archtype, "NSGI4", 5) == 0) |
---|
| 407 | + uv_hubless_system |= 0x10; |
---|
| 408 | + |
---|
| 409 | + /* UV3 Hubless: UV300/MC990X w/o hub */ |
---|
| 410 | + else |
---|
| 411 | + uv_hubless_system |= 0x8; |
---|
| 412 | + |
---|
| 413 | + /* Copy APIC type */ |
---|
| 414 | + uv_stringify(sizeof(oem_table_id), oem_table_id, _oem_table_id); |
---|
| 415 | + |
---|
| 416 | + pr_info("UV: OEM IDs %s/%s, SystemType %d, HUBLESS ID %x\n", |
---|
| 417 | + oem_id, oem_table_id, uv_system_type, uv_hubless_system); |
---|
281 | 418 | return 0; |
---|
282 | 419 | } |
---|
283 | 420 | |
---|
.. | .. |
---|
286 | 423 | return 0; |
---|
287 | 424 | } |
---|
288 | 425 | |
---|
289 | | - /* Set up early hub type field in uv_hub_info for Node 0 */ |
---|
290 | | - uv_cpu_info->p_uv_hub_info = &uv_hub_info_node0; |
---|
291 | | - |
---|
292 | | - /* |
---|
293 | | - * Determine UV arch type. |
---|
294 | | - * SGI: UV100/1000 |
---|
295 | | - * SGI2: UV2000/3000 |
---|
296 | | - * SGI3: UV300 (truncated to 4 chars because of different varieties) |
---|
297 | | - * SGI4: UV400 (truncated to 4 chars because of different varieties) |
---|
298 | | - */ |
---|
| 426 | + /* Set hubbed type if true */ |
---|
299 | 427 | uv_hub_info->hub_revision = |
---|
300 | | - !strncmp(oem_id, "SGI4", 4) ? UV4_HUB_REVISION_BASE : |
---|
301 | | - !strncmp(oem_id, "SGI3", 4) ? UV3_HUB_REVISION_BASE : |
---|
302 | | - !strcmp(oem_id, "SGI2") ? UV2_HUB_REVISION_BASE : |
---|
303 | | - !strcmp(oem_id, "SGI") ? UV1_HUB_REVISION_BASE : 0; |
---|
| 428 | + !strncmp(uv_archtype, "SGI5", 4) ? UV5_HUB_REVISION_BASE : |
---|
| 429 | + !strncmp(uv_archtype, "SGI4", 4) ? UV4_HUB_REVISION_BASE : |
---|
| 430 | + !strncmp(uv_archtype, "SGI3", 4) ? UV3_HUB_REVISION_BASE : |
---|
| 431 | + !strcmp(uv_archtype, "SGI2") ? UV2_HUB_REVISION_BASE : 0; |
---|
304 | 432 | |
---|
305 | | - if (uv_hub_info->hub_revision == 0) |
---|
306 | | - goto badbios; |
---|
| 433 | + switch (uv_hub_info->hub_revision) { |
---|
| 434 | + case UV5_HUB_REVISION_BASE: |
---|
| 435 | + uv_hubbed_system = 0x21; |
---|
| 436 | + uv_hub_type_set(UV5); |
---|
| 437 | + break; |
---|
307 | 438 | |
---|
308 | | - pnodeid = early_get_pnodeid(); |
---|
309 | | - early_get_apic_socketid_shift(); |
---|
| 439 | + case UV4_HUB_REVISION_BASE: |
---|
| 440 | + uv_hubbed_system = 0x11; |
---|
| 441 | + uv_hub_type_set(UV4); |
---|
| 442 | + break; |
---|
310 | 443 | |
---|
311 | | - x86_platform.is_untracked_pat_range = uv_is_untracked_pat_range; |
---|
312 | | - x86_platform.nmi_init = uv_nmi_init; |
---|
| 444 | + case UV3_HUB_REVISION_BASE: |
---|
| 445 | + uv_hubbed_system = 0x9; |
---|
| 446 | + uv_hub_type_set(UV3); |
---|
| 447 | + break; |
---|
313 | 448 | |
---|
314 | | - if (!strcmp(oem_table_id, "UVX")) { |
---|
315 | | - /* This is the most common hardware variant: */ |
---|
316 | | - uv_system_type = UV_X2APIC; |
---|
317 | | - uv_apic = 0; |
---|
| 449 | + case UV2_HUB_REVISION_BASE: |
---|
| 450 | + uv_hubbed_system = 0x5; |
---|
| 451 | + uv_hub_type_set(UV2); |
---|
| 452 | + break; |
---|
318 | 453 | |
---|
319 | | - } else if (!strcmp(oem_table_id, "UVH")) { |
---|
320 | | - /* Only UV1 systems: */ |
---|
321 | | - uv_system_type = UV_NON_UNIQUE_APIC; |
---|
322 | | - x86_platform.legacy.warm_reset = 0; |
---|
323 | | - __this_cpu_write(x2apic_extra_bits, pnodeid << uvh_apicid.s.pnode_shift); |
---|
324 | | - uv_set_apicid_hibit(); |
---|
325 | | - uv_apic = 1; |
---|
326 | | - |
---|
327 | | - } else if (!strcmp(oem_table_id, "UVL")) { |
---|
328 | | - /* Only used for very small systems: */ |
---|
329 | | - uv_system_type = UV_LEGACY_APIC; |
---|
330 | | - uv_apic = 0; |
---|
331 | | - |
---|
332 | | - } else { |
---|
333 | | - goto badbios; |
---|
| 454 | + default: |
---|
| 455 | + return 0; |
---|
334 | 456 | } |
---|
335 | 457 | |
---|
336 | | - pr_info("UV: OEM IDs %s/%s, System/HUB Types %d/%d, uv_apic %d\n", oem_id, oem_table_id, uv_system_type, uv_min_hub_revision_id, uv_apic); |
---|
| 458 | + /* Get UV hub chip part number & revision */ |
---|
| 459 | + early_set_hub_type(); |
---|
| 460 | + |
---|
| 461 | + /* Other UV setup functions */ |
---|
| 462 | + early_get_pnodeid(); |
---|
| 463 | + early_get_apic_socketid_shift(); |
---|
| 464 | + x86_platform.is_untracked_pat_range = uv_is_untracked_pat_range; |
---|
| 465 | + x86_platform.nmi_init = uv_nmi_init; |
---|
337 | 466 | uv_tsc_check_sync(); |
---|
338 | 467 | |
---|
339 | | - return uv_apic; |
---|
| 468 | + return 1; |
---|
| 469 | +} |
---|
| 470 | + |
---|
| 471 | +/* Called early to probe for the correct APIC driver */ |
---|
| 472 | +static int __init uv_acpi_madt_oem_check(char *_oem_id, char *_oem_table_id) |
---|
| 473 | +{ |
---|
| 474 | + /* Set up early hub info fields for Node 0 */ |
---|
| 475 | + uv_cpu_info->p_uv_hub_info = &uv_hub_info_node0; |
---|
| 476 | + |
---|
| 477 | + /* If not UV, return. */ |
---|
| 478 | + if (uv_set_system_type(_oem_id, _oem_table_id) == 0) |
---|
| 479 | + return 0; |
---|
| 480 | + |
---|
| 481 | + /* Save and Decode OEM Table ID */ |
---|
| 482 | + uv_stringify(sizeof(oem_table_id), oem_table_id, _oem_table_id); |
---|
| 483 | + |
---|
| 484 | + /* This is the most common hardware variant, x2apic mode */ |
---|
| 485 | + if (!strcmp(oem_table_id, "UVX")) |
---|
| 486 | + uv_system_type = UV_X2APIC; |
---|
| 487 | + |
---|
| 488 | + /* Only used for very small systems, usually 1 chassis, legacy mode */ |
---|
| 489 | + else if (!strcmp(oem_table_id, "UVL")) |
---|
| 490 | + uv_system_type = UV_LEGACY_APIC; |
---|
| 491 | + |
---|
| 492 | + else |
---|
| 493 | + goto badbios; |
---|
| 494 | + |
---|
| 495 | + pr_info("UV: OEM IDs %s/%s, System/UVType %d/0x%x, HUB RevID %d\n", |
---|
| 496 | + oem_id, oem_table_id, uv_system_type, is_uv(UV_ANY), |
---|
| 497 | + uv_min_hub_revision_id); |
---|
| 498 | + |
---|
| 499 | + return 0; |
---|
340 | 500 | |
---|
341 | 501 | badbios: |
---|
342 | | - pr_err("UV: OEM_ID:%s OEM_TABLE_ID:%s\n", oem_id, oem_table_id); |
---|
343 | | - pr_err("Current BIOS not supported, update kernel and/or BIOS\n"); |
---|
| 502 | + pr_err("UV: UVarchtype:%s not supported\n", uv_archtype); |
---|
344 | 503 | BUG(); |
---|
345 | 504 | } |
---|
346 | 505 | |
---|
.. | .. |
---|
355 | 514 | } |
---|
356 | 515 | EXPORT_SYMBOL_GPL(is_uv_system); |
---|
357 | 516 | |
---|
358 | | -int is_uv_hubless(void) |
---|
| 517 | +int is_uv_hubbed(int uvtype) |
---|
359 | 518 | { |
---|
360 | | - return uv_hubless_system; |
---|
| 519 | + return (uv_hubbed_system & uvtype); |
---|
361 | 520 | } |
---|
362 | | -EXPORT_SYMBOL_GPL(is_uv_hubless); |
---|
| 521 | +EXPORT_SYMBOL_GPL(is_uv_hubbed); |
---|
| 522 | + |
---|
| 523 | +static int is_uv_hubless(int uvtype) |
---|
| 524 | +{ |
---|
| 525 | + return (uv_hubless_system & uvtype); |
---|
| 526 | +} |
---|
363 | 527 | |
---|
364 | 528 | void **__uv_hub_info_list; |
---|
365 | 529 | EXPORT_SYMBOL_GPL(__uv_hub_info_list); |
---|
.. | .. |
---|
386 | 550 | static __initdata struct uv_gam_range_s *_gr_table; |
---|
387 | 551 | |
---|
388 | 552 | #define SOCK_EMPTY ((unsigned short)~0) |
---|
389 | | - |
---|
390 | | -extern int uv_hub_info_version(void) |
---|
391 | | -{ |
---|
392 | | - return UV_HUB_INFO_VERSION; |
---|
393 | | -} |
---|
394 | | -EXPORT_SYMBOL(uv_hub_info_version); |
---|
395 | 553 | |
---|
396 | 554 | /* Default UV memory block size is 2GB */ |
---|
397 | 555 | static unsigned long mem_block_size __initdata = (2UL << 30); |
---|
.. | .. |
---|
539 | 697 | int pnode; |
---|
540 | 698 | |
---|
541 | 699 | pnode = uv_apicid_to_pnode(phys_apicid); |
---|
542 | | - phys_apicid |= uv_apicid_hibits; |
---|
543 | 700 | |
---|
544 | 701 | val = (1UL << UVH_IPI_INT_SEND_SHFT) | |
---|
545 | 702 | (phys_apicid << UVH_IPI_INT_APIC_ID_SHFT) | |
---|
.. | .. |
---|
560 | 717 | |
---|
561 | 718 | static void uv_send_IPI_one(int cpu, int vector) |
---|
562 | 719 | { |
---|
563 | | - unsigned long apicid; |
---|
564 | | - int pnode; |
---|
| 720 | + unsigned long apicid = per_cpu(x86_cpu_to_apicid, cpu); |
---|
| 721 | + int pnode = uv_apicid_to_pnode(apicid); |
---|
| 722 | + unsigned long dmode, val; |
---|
565 | 723 | |
---|
566 | | - apicid = per_cpu(x86_cpu_to_apicid, cpu); |
---|
567 | | - pnode = uv_apicid_to_pnode(apicid); |
---|
568 | | - uv_hub_send_ipi(pnode, apicid, vector); |
---|
| 724 | + if (vector == NMI_VECTOR) |
---|
| 725 | + dmode = dest_NMI; |
---|
| 726 | + else |
---|
| 727 | + dmode = dest_Fixed; |
---|
| 728 | + |
---|
| 729 | + val = (1UL << UVH_IPI_INT_SEND_SHFT) | |
---|
| 730 | + (apicid << UVH_IPI_INT_APIC_ID_SHFT) | |
---|
| 731 | + (dmode << UVH_IPI_INT_DELIVERY_MODE_SHFT) | |
---|
| 732 | + (vector << UVH_IPI_INT_VECTOR_SHFT); |
---|
| 733 | + |
---|
| 734 | + uv_write_global_mmr64(pnode, UVH_IPI_INT, val); |
---|
569 | 735 | } |
---|
570 | 736 | |
---|
571 | 737 | static void uv_send_IPI_mask(const struct cpumask *mask, int vector) |
---|
.. | .. |
---|
619 | 785 | |
---|
620 | 786 | static u32 apic_uv_calc_apicid(unsigned int cpu) |
---|
621 | 787 | { |
---|
622 | | - return apic_default_calc_apicid(cpu) | uv_apicid_hibits; |
---|
| 788 | + return apic_default_calc_apicid(cpu); |
---|
623 | 789 | } |
---|
624 | 790 | |
---|
625 | | -static unsigned int x2apic_get_apic_id(unsigned long x) |
---|
| 791 | +static unsigned int x2apic_get_apic_id(unsigned long id) |
---|
626 | 792 | { |
---|
627 | | - unsigned int id; |
---|
628 | | - |
---|
629 | | - WARN_ON(preemptible() && num_online_cpus() > 1); |
---|
630 | | - id = x | __this_cpu_read(x2apic_extra_bits); |
---|
631 | | - |
---|
632 | 793 | return id; |
---|
633 | 794 | } |
---|
634 | 795 | |
---|
635 | 796 | static u32 set_apic_id(unsigned int id) |
---|
636 | 797 | { |
---|
637 | | - /* CHECKME: Do we need to mask out the xapic extra bits? */ |
---|
638 | 798 | return id; |
---|
639 | 799 | } |
---|
640 | 800 | |
---|
.. | .. |
---|
706 | 866 | .safe_wait_icr_idle = native_safe_x2apic_wait_icr_idle, |
---|
707 | 867 | }; |
---|
708 | 868 | |
---|
709 | | -static void set_x2apic_extra_bits(int pnode) |
---|
710 | | -{ |
---|
711 | | - __this_cpu_write(x2apic_extra_bits, pnode << uvh_apicid.s.pnode_shift); |
---|
712 | | -} |
---|
713 | | - |
---|
714 | 869 | #define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_LENGTH 3 |
---|
715 | | -#define DEST_SHIFT UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR_DEST_BASE_SHFT |
---|
| 870 | +#define DEST_SHIFT UVXH_RH_GAM_ALIAS_0_REDIRECT_CONFIG_DEST_BASE_SHFT |
---|
716 | 871 | |
---|
717 | 872 | static __init void get_lowmem_redirect(unsigned long *base, unsigned long *size) |
---|
718 | 873 | { |
---|
719 | | - union uvh_rh_gam_alias210_overlay_config_2_mmr_u alias; |
---|
720 | | - union uvh_rh_gam_alias210_redirect_config_2_mmr_u redirect; |
---|
| 874 | + union uvh_rh_gam_alias_2_overlay_config_u alias; |
---|
| 875 | + union uvh_rh_gam_alias_2_redirect_config_u redirect; |
---|
721 | 876 | unsigned long m_redirect; |
---|
722 | 877 | unsigned long m_overlay; |
---|
723 | 878 | int i; |
---|
.. | .. |
---|
725 | 880 | for (i = 0; i < UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_LENGTH; i++) { |
---|
726 | 881 | switch (i) { |
---|
727 | 882 | case 0: |
---|
728 | | - m_redirect = UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR; |
---|
729 | | - m_overlay = UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR; |
---|
| 883 | + m_redirect = UVH_RH_GAM_ALIAS_0_REDIRECT_CONFIG; |
---|
| 884 | + m_overlay = UVH_RH_GAM_ALIAS_0_OVERLAY_CONFIG; |
---|
730 | 885 | break; |
---|
731 | 886 | case 1: |
---|
732 | | - m_redirect = UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR; |
---|
733 | | - m_overlay = UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR; |
---|
| 887 | + m_redirect = UVH_RH_GAM_ALIAS_1_REDIRECT_CONFIG; |
---|
| 888 | + m_overlay = UVH_RH_GAM_ALIAS_1_OVERLAY_CONFIG; |
---|
734 | 889 | break; |
---|
735 | 890 | case 2: |
---|
736 | | - m_redirect = UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR; |
---|
737 | | - m_overlay = UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR; |
---|
| 891 | + m_redirect = UVH_RH_GAM_ALIAS_2_REDIRECT_CONFIG; |
---|
| 892 | + m_overlay = UVH_RH_GAM_ALIAS_2_OVERLAY_CONFIG; |
---|
738 | 893 | break; |
---|
739 | 894 | } |
---|
740 | 895 | alias.v = uv_read_local_mmr(m_overlay); |
---|
.. | .. |
---|
749 | 904 | } |
---|
750 | 905 | |
---|
751 | 906 | enum map_type {map_wb, map_uc}; |
---|
| 907 | +static const char * const mt[] = { "WB", "UC" }; |
---|
752 | 908 | |
---|
753 | 909 | static __init void map_high(char *id, unsigned long base, int pshift, int bshift, int max_pnode, enum map_type map_type) |
---|
754 | 910 | { |
---|
.. | .. |
---|
760 | 916 | pr_info("UV: Map %s_HI base address NULL\n", id); |
---|
761 | 917 | return; |
---|
762 | 918 | } |
---|
763 | | - pr_debug("UV: Map %s_HI 0x%lx - 0x%lx\n", id, paddr, paddr + bytes); |
---|
764 | 919 | if (map_type == map_uc) |
---|
765 | 920 | init_extra_mapping_uc(paddr, bytes); |
---|
766 | 921 | else |
---|
767 | 922 | init_extra_mapping_wb(paddr, bytes); |
---|
768 | | -} |
---|
769 | 923 | |
---|
770 | | -static __init void map_gru_distributed(unsigned long c) |
---|
771 | | -{ |
---|
772 | | - union uvh_rh_gam_gru_overlay_config_mmr_u gru; |
---|
773 | | - u64 paddr; |
---|
774 | | - unsigned long bytes; |
---|
775 | | - int nid; |
---|
776 | | - |
---|
777 | | - gru.v = c; |
---|
778 | | - |
---|
779 | | - /* Only base bits 42:28 relevant in dist mode */ |
---|
780 | | - gru_dist_base = gru.v & 0x000007fff0000000UL; |
---|
781 | | - if (!gru_dist_base) { |
---|
782 | | - pr_info("UV: Map GRU_DIST base address NULL\n"); |
---|
783 | | - return; |
---|
784 | | - } |
---|
785 | | - |
---|
786 | | - bytes = 1UL << UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT; |
---|
787 | | - gru_dist_lmask = ((1UL << uv_hub_info->m_val) - 1) & ~(bytes - 1); |
---|
788 | | - gru_dist_umask = ~((1UL << uv_hub_info->m_val) - 1); |
---|
789 | | - gru_dist_base &= gru_dist_lmask; /* Clear bits above M */ |
---|
790 | | - |
---|
791 | | - for_each_online_node(nid) { |
---|
792 | | - paddr = ((u64)uv_node_to_pnode(nid) << uv_hub_info->m_val) | |
---|
793 | | - gru_dist_base; |
---|
794 | | - init_extra_mapping_wb(paddr, bytes); |
---|
795 | | - gru_first_node_paddr = min(paddr, gru_first_node_paddr); |
---|
796 | | - gru_last_node_paddr = max(paddr, gru_last_node_paddr); |
---|
797 | | - } |
---|
798 | | - |
---|
799 | | - /* Save upper (63:M) bits of address only for is_GRU_range */ |
---|
800 | | - gru_first_node_paddr &= gru_dist_umask; |
---|
801 | | - gru_last_node_paddr &= gru_dist_umask; |
---|
802 | | - |
---|
803 | | - pr_debug("UV: Map GRU_DIST base 0x%016llx 0x%016llx - 0x%016llx\n", gru_dist_base, gru_first_node_paddr, gru_last_node_paddr); |
---|
| 924 | + pr_info("UV: Map %s_HI 0x%lx - 0x%lx %s (%d segments)\n", |
---|
| 925 | + id, paddr, paddr + bytes, mt[map_type], max_pnode + 1); |
---|
804 | 926 | } |
---|
805 | 927 | |
---|
806 | 928 | static __init void map_gru_high(int max_pnode) |
---|
807 | 929 | { |
---|
808 | | - union uvh_rh_gam_gru_overlay_config_mmr_u gru; |
---|
809 | | - int shift = UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT; |
---|
810 | | - unsigned long mask = UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_MASK; |
---|
811 | | - unsigned long base; |
---|
| 930 | + union uvh_rh_gam_gru_overlay_config_u gru; |
---|
| 931 | + unsigned long mask, base; |
---|
| 932 | + int shift; |
---|
812 | 933 | |
---|
813 | | - gru.v = uv_read_local_mmr(UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR); |
---|
814 | | - if (!gru.s.enable) { |
---|
815 | | - pr_info("UV: GRU disabled\n"); |
---|
| 934 | + if (UVH_RH_GAM_GRU_OVERLAY_CONFIG) { |
---|
| 935 | + gru.v = uv_read_local_mmr(UVH_RH_GAM_GRU_OVERLAY_CONFIG); |
---|
| 936 | + shift = UVH_RH_GAM_GRU_OVERLAY_CONFIG_BASE_SHFT; |
---|
| 937 | + mask = UVH_RH_GAM_GRU_OVERLAY_CONFIG_BASE_MASK; |
---|
| 938 | + } else if (UVH_RH10_GAM_GRU_OVERLAY_CONFIG) { |
---|
| 939 | + gru.v = uv_read_local_mmr(UVH_RH10_GAM_GRU_OVERLAY_CONFIG); |
---|
| 940 | + shift = UVH_RH10_GAM_GRU_OVERLAY_CONFIG_BASE_SHFT; |
---|
| 941 | + mask = UVH_RH10_GAM_GRU_OVERLAY_CONFIG_BASE_MASK; |
---|
| 942 | + } else { |
---|
| 943 | + pr_err("UV: GRU unavailable (no MMR)\n"); |
---|
816 | 944 | return; |
---|
817 | 945 | } |
---|
818 | 946 | |
---|
819 | | - /* Only UV3 has distributed GRU mode */ |
---|
820 | | - if (is_uv3_hub() && gru.s3.mode) { |
---|
821 | | - map_gru_distributed(gru.v); |
---|
| 947 | + if (!gru.s.enable) { |
---|
| 948 | + pr_info("UV: GRU disabled (by BIOS)\n"); |
---|
822 | 949 | return; |
---|
823 | 950 | } |
---|
824 | 951 | |
---|
.. | .. |
---|
830 | 957 | |
---|
831 | 958 | static __init void map_mmr_high(int max_pnode) |
---|
832 | 959 | { |
---|
833 | | - union uvh_rh_gam_mmr_overlay_config_mmr_u mmr; |
---|
834 | | - int shift = UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_SHFT; |
---|
| 960 | + unsigned long base; |
---|
| 961 | + int shift; |
---|
| 962 | + bool enable; |
---|
835 | 963 | |
---|
836 | | - mmr.v = uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR); |
---|
837 | | - if (mmr.s.enable) |
---|
838 | | - map_high("MMR", mmr.s.base, shift, shift, max_pnode, map_uc); |
---|
| 964 | + if (UVH_RH10_GAM_MMR_OVERLAY_CONFIG) { |
---|
| 965 | + union uvh_rh10_gam_mmr_overlay_config_u mmr; |
---|
| 966 | + |
---|
| 967 | + mmr.v = uv_read_local_mmr(UVH_RH10_GAM_MMR_OVERLAY_CONFIG); |
---|
| 968 | + enable = mmr.s.enable; |
---|
| 969 | + base = mmr.s.base; |
---|
| 970 | + shift = UVH_RH10_GAM_MMR_OVERLAY_CONFIG_BASE_SHFT; |
---|
| 971 | + } else if (UVH_RH_GAM_MMR_OVERLAY_CONFIG) { |
---|
| 972 | + union uvh_rh_gam_mmr_overlay_config_u mmr; |
---|
| 973 | + |
---|
| 974 | + mmr.v = uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG); |
---|
| 975 | + enable = mmr.s.enable; |
---|
| 976 | + base = mmr.s.base; |
---|
| 977 | + shift = UVH_RH_GAM_MMR_OVERLAY_CONFIG_BASE_SHFT; |
---|
| 978 | + } else { |
---|
| 979 | + pr_err("UV:%s:RH_GAM_MMR_OVERLAY_CONFIG MMR undefined?\n", |
---|
| 980 | + __func__); |
---|
| 981 | + return; |
---|
| 982 | + } |
---|
| 983 | + |
---|
| 984 | + if (enable) |
---|
| 985 | + map_high("MMR", base, shift, shift, max_pnode, map_uc); |
---|
839 | 986 | else |
---|
840 | 987 | pr_info("UV: MMR disabled\n"); |
---|
841 | 988 | } |
---|
842 | 989 | |
---|
843 | | -/* UV3/4 have identical MMIOH overlay configs, UV4A is slightly different */ |
---|
844 | | -static __init void map_mmioh_high_uv34(int index, int min_pnode, int max_pnode) |
---|
845 | | -{ |
---|
846 | | - unsigned long overlay; |
---|
847 | | - unsigned long mmr; |
---|
848 | | - unsigned long base; |
---|
849 | | - unsigned long nasid_mask; |
---|
850 | | - unsigned long m_overlay; |
---|
851 | | - int i, n, shift, m_io, max_io; |
---|
852 | | - int nasid, lnasid, fi, li; |
---|
853 | | - char *id; |
---|
| 990 | +/* Arch specific ENUM cases */ |
---|
| 991 | +enum mmioh_arch { |
---|
| 992 | + UV2_MMIOH = -1, |
---|
| 993 | + UVY_MMIOH0, UVY_MMIOH1, |
---|
| 994 | + UVX_MMIOH0, UVX_MMIOH1, |
---|
| 995 | +}; |
---|
854 | 996 | |
---|
855 | | - if (index == 0) { |
---|
856 | | - id = "MMIOH0"; |
---|
857 | | - m_overlay = UVH_RH_GAM_MMIOH_OVERLAY_CONFIG0_MMR; |
---|
858 | | - overlay = uv_read_local_mmr(m_overlay); |
---|
859 | | - base = overlay & UVH_RH_GAM_MMIOH_OVERLAY_CONFIG0_MMR_BASE_MASK; |
---|
860 | | - mmr = UVH_RH_GAM_MMIOH_REDIRECT_CONFIG0_MMR; |
---|
861 | | - m_io = (overlay & UVH_RH_GAM_MMIOH_OVERLAY_CONFIG0_MMR_M_IO_MASK) |
---|
862 | | - >> UVH_RH_GAM_MMIOH_OVERLAY_CONFIG0_MMR_M_IO_SHFT; |
---|
863 | | - shift = UVH_RH_GAM_MMIOH_OVERLAY_CONFIG0_MMR_M_IO_SHFT; |
---|
864 | | - n = UVH_RH_GAM_MMIOH_REDIRECT_CONFIG0_MMR_DEPTH; |
---|
865 | | - nasid_mask = UVH_RH_GAM_MMIOH_REDIRECT_CONFIG0_MMR_NASID_MASK; |
---|
866 | | - } else { |
---|
867 | | - id = "MMIOH1"; |
---|
868 | | - m_overlay = UVH_RH_GAM_MMIOH_OVERLAY_CONFIG1_MMR; |
---|
869 | | - overlay = uv_read_local_mmr(m_overlay); |
---|
870 | | - base = overlay & UVH_RH_GAM_MMIOH_OVERLAY_CONFIG1_MMR_BASE_MASK; |
---|
871 | | - mmr = UVH_RH_GAM_MMIOH_REDIRECT_CONFIG1_MMR; |
---|
872 | | - m_io = (overlay & UVH_RH_GAM_MMIOH_OVERLAY_CONFIG1_MMR_M_IO_MASK) |
---|
873 | | - >> UVH_RH_GAM_MMIOH_OVERLAY_CONFIG1_MMR_M_IO_SHFT; |
---|
874 | | - shift = UVH_RH_GAM_MMIOH_OVERLAY_CONFIG1_MMR_M_IO_SHFT; |
---|
875 | | - n = UVH_RH_GAM_MMIOH_REDIRECT_CONFIG1_MMR_DEPTH; |
---|
876 | | - nasid_mask = UVH_RH_GAM_MMIOH_REDIRECT_CONFIG1_MMR_NASID_MASK; |
---|
| 997 | +/* Calculate and Map MMIOH Regions */ |
---|
| 998 | +static void __init calc_mmioh_map(enum mmioh_arch index, |
---|
| 999 | + int min_pnode, int max_pnode, |
---|
| 1000 | + int shift, unsigned long base, int m_io, int n_io) |
---|
| 1001 | +{ |
---|
| 1002 | + unsigned long mmr, nasid_mask; |
---|
| 1003 | + int nasid, min_nasid, max_nasid, lnasid, mapped; |
---|
| 1004 | + int i, fi, li, n, max_io; |
---|
| 1005 | + char id[8]; |
---|
| 1006 | + |
---|
| 1007 | + /* One (UV2) mapping */ |
---|
| 1008 | + if (index == UV2_MMIOH) { |
---|
| 1009 | + strncpy(id, "MMIOH", sizeof(id)); |
---|
| 1010 | + max_io = max_pnode; |
---|
| 1011 | + mapped = 0; |
---|
| 1012 | + goto map_exit; |
---|
877 | 1013 | } |
---|
878 | | - pr_info("UV: %s overlay 0x%lx base:0x%lx m_io:%d\n", id, overlay, base, m_io); |
---|
879 | | - if (!(overlay & UVH_RH_GAM_MMIOH_OVERLAY_CONFIG0_MMR_ENABLE_MASK)) { |
---|
880 | | - pr_info("UV: %s disabled\n", id); |
---|
| 1014 | + |
---|
| 1015 | + /* small and large MMIOH mappings */ |
---|
| 1016 | + switch (index) { |
---|
| 1017 | + case UVY_MMIOH0: |
---|
| 1018 | + mmr = UVH_RH10_GAM_MMIOH_REDIRECT_CONFIG0; |
---|
| 1019 | + nasid_mask = UVH_RH10_GAM_MMIOH_OVERLAY_CONFIG0_BASE_MASK; |
---|
| 1020 | + n = UVH_RH10_GAM_MMIOH_REDIRECT_CONFIG0_DEPTH; |
---|
| 1021 | + min_nasid = min_pnode; |
---|
| 1022 | + max_nasid = max_pnode; |
---|
| 1023 | + mapped = 1; |
---|
| 1024 | + break; |
---|
| 1025 | + case UVY_MMIOH1: |
---|
| 1026 | + mmr = UVH_RH10_GAM_MMIOH_REDIRECT_CONFIG1; |
---|
| 1027 | + nasid_mask = UVH_RH10_GAM_MMIOH_OVERLAY_CONFIG1_BASE_MASK; |
---|
| 1028 | + n = UVH_RH10_GAM_MMIOH_REDIRECT_CONFIG1_DEPTH; |
---|
| 1029 | + min_nasid = min_pnode; |
---|
| 1030 | + max_nasid = max_pnode; |
---|
| 1031 | + mapped = 1; |
---|
| 1032 | + break; |
---|
| 1033 | + case UVX_MMIOH0: |
---|
| 1034 | + mmr = UVH_RH_GAM_MMIOH_REDIRECT_CONFIG0; |
---|
| 1035 | + nasid_mask = UVH_RH_GAM_MMIOH_OVERLAY_CONFIG0_BASE_MASK; |
---|
| 1036 | + n = UVH_RH_GAM_MMIOH_REDIRECT_CONFIG0_DEPTH; |
---|
| 1037 | + min_nasid = min_pnode * 2; |
---|
| 1038 | + max_nasid = max_pnode * 2; |
---|
| 1039 | + mapped = 1; |
---|
| 1040 | + break; |
---|
| 1041 | + case UVX_MMIOH1: |
---|
| 1042 | + mmr = UVH_RH_GAM_MMIOH_REDIRECT_CONFIG1; |
---|
| 1043 | + nasid_mask = UVH_RH_GAM_MMIOH_OVERLAY_CONFIG1_BASE_MASK; |
---|
| 1044 | + n = UVH_RH_GAM_MMIOH_REDIRECT_CONFIG1_DEPTH; |
---|
| 1045 | + min_nasid = min_pnode * 2; |
---|
| 1046 | + max_nasid = max_pnode * 2; |
---|
| 1047 | + mapped = 1; |
---|
| 1048 | + break; |
---|
| 1049 | + default: |
---|
| 1050 | + pr_err("UV:%s:Invalid mapping type:%d\n", __func__, index); |
---|
881 | 1051 | return; |
---|
882 | 1052 | } |
---|
883 | 1053 | |
---|
884 | | - /* Convert to NASID: */ |
---|
885 | | - min_pnode *= 2; |
---|
886 | | - max_pnode *= 2; |
---|
887 | | - max_io = lnasid = fi = li = -1; |
---|
| 1054 | + /* enum values chosen so (index mod 2) is MMIOH 0/1 (low/high) */ |
---|
| 1055 | + snprintf(id, sizeof(id), "MMIOH%d", index%2); |
---|
888 | 1056 | |
---|
| 1057 | + max_io = lnasid = fi = li = -1; |
---|
889 | 1058 | for (i = 0; i < n; i++) { |
---|
890 | 1059 | unsigned long m_redirect = mmr + i * 8; |
---|
891 | 1060 | unsigned long redirect = uv_read_local_mmr(m_redirect); |
---|
.. | .. |
---|
895 | 1064 | pr_info("UV: %s redirect base 0x%lx(@0x%lx) 0x%04x\n", |
---|
896 | 1065 | id, redirect, m_redirect, nasid); |
---|
897 | 1066 | |
---|
898 | | - /* Invalid NASID: */ |
---|
899 | | - if (nasid < min_pnode || max_pnode < nasid) |
---|
| 1067 | + /* Invalid NASID check */ |
---|
| 1068 | + if (nasid < min_nasid || max_nasid < nasid) { |
---|
| 1069 | + pr_err("UV:%s:Invalid NASID:%x (range:%x..%x)\n", |
---|
| 1070 | + __func__, index, min_nasid, max_nasid); |
---|
900 | 1071 | nasid = -1; |
---|
| 1072 | + } |
---|
901 | 1073 | |
---|
902 | 1074 | if (nasid == lnasid) { |
---|
903 | 1075 | li = i; |
---|
.. | .. |
---|
920 | 1092 | } |
---|
921 | 1093 | addr1 = (base << shift) + f * (1ULL << m_io); |
---|
922 | 1094 | addr2 = (base << shift) + (l + 1) * (1ULL << m_io); |
---|
923 | | - pr_info("UV: %s[%03d..%03d] NASID 0x%04x ADDR 0x%016lx - 0x%016lx\n", id, fi, li, lnasid, addr1, addr2); |
---|
| 1095 | + pr_info("UV: %s[%03d..%03d] NASID 0x%04x ADDR 0x%016lx - 0x%016lx\n", |
---|
| 1096 | + id, fi, li, lnasid, addr1, addr2); |
---|
924 | 1097 | if (max_io < l) |
---|
925 | 1098 | max_io = l; |
---|
926 | 1099 | } |
---|
.. | .. |
---|
928 | 1101 | lnasid = nasid; |
---|
929 | 1102 | } |
---|
930 | 1103 | |
---|
931 | | - pr_info("UV: %s base:0x%lx shift:%d M_IO:%d MAX_IO:%d\n", id, base, shift, m_io, max_io); |
---|
| 1104 | +map_exit: |
---|
| 1105 | + pr_info("UV: %s base:0x%lx shift:%d m_io:%d max_io:%d max_pnode:0x%x\n", |
---|
| 1106 | + id, base, shift, m_io, max_io, max_pnode); |
---|
932 | 1107 | |
---|
933 | | - if (max_io >= 0) |
---|
| 1108 | + if (max_io >= 0 && !mapped) |
---|
934 | 1109 | map_high(id, base, shift, m_io, max_io, map_uc); |
---|
935 | 1110 | } |
---|
936 | 1111 | |
---|
937 | 1112 | static __init void map_mmioh_high(int min_pnode, int max_pnode) |
---|
938 | 1113 | { |
---|
939 | | - union uvh_rh_gam_mmioh_overlay_config_mmr_u mmioh; |
---|
940 | | - unsigned long mmr, base; |
---|
941 | | - int shift, enable, m_io, n_io; |
---|
| 1114 | + /* UVY flavor */ |
---|
| 1115 | + if (UVH_RH10_GAM_MMIOH_OVERLAY_CONFIG0) { |
---|
| 1116 | + union uvh_rh10_gam_mmioh_overlay_config0_u mmioh0; |
---|
| 1117 | + union uvh_rh10_gam_mmioh_overlay_config1_u mmioh1; |
---|
942 | 1118 | |
---|
943 | | - if (is_uv3_hub() || is_uv4_hub()) { |
---|
944 | | - /* Map both MMIOH regions: */ |
---|
945 | | - map_mmioh_high_uv34(0, min_pnode, max_pnode); |
---|
946 | | - map_mmioh_high_uv34(1, min_pnode, max_pnode); |
---|
| 1119 | + mmioh0.v = uv_read_local_mmr(UVH_RH10_GAM_MMIOH_OVERLAY_CONFIG0); |
---|
| 1120 | + if (unlikely(mmioh0.s.enable == 0)) |
---|
| 1121 | + pr_info("UV: MMIOH0 disabled\n"); |
---|
| 1122 | + else |
---|
| 1123 | + calc_mmioh_map(UVY_MMIOH0, min_pnode, max_pnode, |
---|
| 1124 | + UVH_RH10_GAM_MMIOH_OVERLAY_CONFIG0_BASE_SHFT, |
---|
| 1125 | + mmioh0.s.base, mmioh0.s.m_io, mmioh0.s.n_io); |
---|
| 1126 | + |
---|
| 1127 | + mmioh1.v = uv_read_local_mmr(UVH_RH10_GAM_MMIOH_OVERLAY_CONFIG1); |
---|
| 1128 | + if (unlikely(mmioh1.s.enable == 0)) |
---|
| 1129 | + pr_info("UV: MMIOH1 disabled\n"); |
---|
| 1130 | + else |
---|
| 1131 | + calc_mmioh_map(UVY_MMIOH1, min_pnode, max_pnode, |
---|
| 1132 | + UVH_RH10_GAM_MMIOH_OVERLAY_CONFIG1_BASE_SHFT, |
---|
| 1133 | + mmioh1.s.base, mmioh1.s.m_io, mmioh1.s.n_io); |
---|
| 1134 | + return; |
---|
| 1135 | + } |
---|
| 1136 | + /* UVX flavor */ |
---|
| 1137 | + if (UVH_RH_GAM_MMIOH_OVERLAY_CONFIG0) { |
---|
| 1138 | + union uvh_rh_gam_mmioh_overlay_config0_u mmioh0; |
---|
| 1139 | + union uvh_rh_gam_mmioh_overlay_config1_u mmioh1; |
---|
| 1140 | + |
---|
| 1141 | + mmioh0.v = uv_read_local_mmr(UVH_RH_GAM_MMIOH_OVERLAY_CONFIG0); |
---|
| 1142 | + if (unlikely(mmioh0.s.enable == 0)) |
---|
| 1143 | + pr_info("UV: MMIOH0 disabled\n"); |
---|
| 1144 | + else { |
---|
| 1145 | + unsigned long base = uvxy_field(mmioh0, base, 0); |
---|
| 1146 | + int m_io = uvxy_field(mmioh0, m_io, 0); |
---|
| 1147 | + int n_io = uvxy_field(mmioh0, n_io, 0); |
---|
| 1148 | + |
---|
| 1149 | + calc_mmioh_map(UVX_MMIOH0, min_pnode, max_pnode, |
---|
| 1150 | + UVH_RH_GAM_MMIOH_OVERLAY_CONFIG0_BASE_SHFT, |
---|
| 1151 | + base, m_io, n_io); |
---|
| 1152 | + } |
---|
| 1153 | + |
---|
| 1154 | + mmioh1.v = uv_read_local_mmr(UVH_RH_GAM_MMIOH_OVERLAY_CONFIG1); |
---|
| 1155 | + if (unlikely(mmioh1.s.enable == 0)) |
---|
| 1156 | + pr_info("UV: MMIOH1 disabled\n"); |
---|
| 1157 | + else { |
---|
| 1158 | + unsigned long base = uvxy_field(mmioh1, base, 0); |
---|
| 1159 | + int m_io = uvxy_field(mmioh1, m_io, 0); |
---|
| 1160 | + int n_io = uvxy_field(mmioh1, n_io, 0); |
---|
| 1161 | + |
---|
| 1162 | + calc_mmioh_map(UVX_MMIOH1, min_pnode, max_pnode, |
---|
| 1163 | + UVH_RH_GAM_MMIOH_OVERLAY_CONFIG1_BASE_SHFT, |
---|
| 1164 | + base, m_io, n_io); |
---|
| 1165 | + } |
---|
947 | 1166 | return; |
---|
948 | 1167 | } |
---|
949 | 1168 | |
---|
950 | | - if (is_uv1_hub()) { |
---|
951 | | - mmr = UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR; |
---|
952 | | - shift = UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_BASE_SHFT; |
---|
953 | | - mmioh.v = uv_read_local_mmr(mmr); |
---|
954 | | - enable = !!mmioh.s1.enable; |
---|
955 | | - base = mmioh.s1.base; |
---|
956 | | - m_io = mmioh.s1.m_io; |
---|
957 | | - n_io = mmioh.s1.n_io; |
---|
958 | | - } else if (is_uv2_hub()) { |
---|
959 | | - mmr = UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR; |
---|
960 | | - shift = UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_BASE_SHFT; |
---|
961 | | - mmioh.v = uv_read_local_mmr(mmr); |
---|
962 | | - enable = !!mmioh.s2.enable; |
---|
963 | | - base = mmioh.s2.base; |
---|
964 | | - m_io = mmioh.s2.m_io; |
---|
965 | | - n_io = mmioh.s2.n_io; |
---|
966 | | - } else { |
---|
967 | | - return; |
---|
968 | | - } |
---|
| 1169 | + /* UV2 flavor */ |
---|
| 1170 | + if (UVH_RH_GAM_MMIOH_OVERLAY_CONFIG) { |
---|
| 1171 | + union uvh_rh_gam_mmioh_overlay_config_u mmioh; |
---|
969 | 1172 | |
---|
970 | | - if (enable) { |
---|
971 | | - max_pnode &= (1 << n_io) - 1; |
---|
972 | | - pr_info("UV: base:0x%lx shift:%d N_IO:%d M_IO:%d max_pnode:0x%x\n", base, shift, m_io, n_io, max_pnode); |
---|
973 | | - map_high("MMIOH", base, shift, m_io, max_pnode, map_uc); |
---|
974 | | - } else { |
---|
975 | | - pr_info("UV: MMIOH disabled\n"); |
---|
| 1173 | + mmioh.v = uv_read_local_mmr(UVH_RH_GAM_MMIOH_OVERLAY_CONFIG); |
---|
| 1174 | + if (unlikely(mmioh.s2.enable == 0)) |
---|
| 1175 | + pr_info("UV: MMIOH disabled\n"); |
---|
| 1176 | + else |
---|
| 1177 | + calc_mmioh_map(UV2_MMIOH, min_pnode, max_pnode, |
---|
| 1178 | + UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_BASE_SHFT, |
---|
| 1179 | + mmioh.s2.base, mmioh.s2.m_io, mmioh.s2.n_io); |
---|
| 1180 | + return; |
---|
976 | 1181 | } |
---|
977 | 1182 | } |
---|
978 | 1183 | |
---|
979 | 1184 | static __init void map_low_mmrs(void) |
---|
980 | 1185 | { |
---|
981 | | - init_extra_mapping_uc(UV_GLOBAL_MMR32_BASE, UV_GLOBAL_MMR32_SIZE); |
---|
982 | | - init_extra_mapping_uc(UV_LOCAL_MMR_BASE, UV_LOCAL_MMR_SIZE); |
---|
| 1186 | + if (UV_GLOBAL_MMR32_BASE) |
---|
| 1187 | + init_extra_mapping_uc(UV_GLOBAL_MMR32_BASE, UV_GLOBAL_MMR32_SIZE); |
---|
| 1188 | + |
---|
| 1189 | + if (UV_LOCAL_MMR_BASE) |
---|
| 1190 | + init_extra_mapping_uc(UV_LOCAL_MMR_BASE, UV_LOCAL_MMR_SIZE); |
---|
983 | 1191 | } |
---|
984 | 1192 | |
---|
985 | 1193 | static __init void uv_rtc_init(void) |
---|
.. | .. |
---|
999 | 1207 | } |
---|
1000 | 1208 | } |
---|
1001 | 1209 | |
---|
1002 | | -/* |
---|
1003 | | - * percpu heartbeat timer |
---|
1004 | | - */ |
---|
1005 | | -static void uv_heartbeat(struct timer_list *timer) |
---|
1006 | | -{ |
---|
1007 | | - unsigned char bits = uv_scir_info->state; |
---|
1008 | | - |
---|
1009 | | - /* Flip heartbeat bit: */ |
---|
1010 | | - bits ^= SCIR_CPU_HEARTBEAT; |
---|
1011 | | - |
---|
1012 | | - /* Is this CPU idle? */ |
---|
1013 | | - if (idle_cpu(raw_smp_processor_id())) |
---|
1014 | | - bits &= ~SCIR_CPU_ACTIVITY; |
---|
1015 | | - else |
---|
1016 | | - bits |= SCIR_CPU_ACTIVITY; |
---|
1017 | | - |
---|
1018 | | - /* Update system controller interface reg: */ |
---|
1019 | | - uv_set_scir_bits(bits); |
---|
1020 | | - |
---|
1021 | | - /* Enable next timer period: */ |
---|
1022 | | - mod_timer(timer, jiffies + SCIR_CPU_HB_INTERVAL); |
---|
1023 | | -} |
---|
1024 | | - |
---|
1025 | | -static int uv_heartbeat_enable(unsigned int cpu) |
---|
1026 | | -{ |
---|
1027 | | - while (!uv_cpu_scir_info(cpu)->enabled) { |
---|
1028 | | - struct timer_list *timer = &uv_cpu_scir_info(cpu)->timer; |
---|
1029 | | - |
---|
1030 | | - uv_set_cpu_scir_bits(cpu, SCIR_CPU_HEARTBEAT|SCIR_CPU_ACTIVITY); |
---|
1031 | | - timer_setup(timer, uv_heartbeat, TIMER_PINNED); |
---|
1032 | | - timer->expires = jiffies + SCIR_CPU_HB_INTERVAL; |
---|
1033 | | - add_timer_on(timer, cpu); |
---|
1034 | | - uv_cpu_scir_info(cpu)->enabled = 1; |
---|
1035 | | - |
---|
1036 | | - /* Also ensure that boot CPU is enabled: */ |
---|
1037 | | - cpu = 0; |
---|
1038 | | - } |
---|
1039 | | - return 0; |
---|
1040 | | -} |
---|
1041 | | - |
---|
1042 | | -#ifdef CONFIG_HOTPLUG_CPU |
---|
1043 | | -static int uv_heartbeat_disable(unsigned int cpu) |
---|
1044 | | -{ |
---|
1045 | | - if (uv_cpu_scir_info(cpu)->enabled) { |
---|
1046 | | - uv_cpu_scir_info(cpu)->enabled = 0; |
---|
1047 | | - del_timer(&uv_cpu_scir_info(cpu)->timer); |
---|
1048 | | - } |
---|
1049 | | - uv_set_cpu_scir_bits(cpu, 0xff); |
---|
1050 | | - return 0; |
---|
1051 | | -} |
---|
1052 | | - |
---|
1053 | | -static __init void uv_scir_register_cpu_notifier(void) |
---|
1054 | | -{ |
---|
1055 | | - cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "x86/x2apic-uvx:online", |
---|
1056 | | - uv_heartbeat_enable, uv_heartbeat_disable); |
---|
1057 | | -} |
---|
1058 | | - |
---|
1059 | | -#else /* !CONFIG_HOTPLUG_CPU */ |
---|
1060 | | - |
---|
1061 | | -static __init void uv_scir_register_cpu_notifier(void) |
---|
1062 | | -{ |
---|
1063 | | -} |
---|
1064 | | - |
---|
1065 | | -static __init int uv_init_heartbeat(void) |
---|
1066 | | -{ |
---|
1067 | | - int cpu; |
---|
1068 | | - |
---|
1069 | | - if (is_uv_system()) { |
---|
1070 | | - for_each_online_cpu(cpu) |
---|
1071 | | - uv_heartbeat_enable(cpu); |
---|
1072 | | - } |
---|
1073 | | - |
---|
1074 | | - return 0; |
---|
1075 | | -} |
---|
1076 | | - |
---|
1077 | | -late_initcall(uv_init_heartbeat); |
---|
1078 | | - |
---|
1079 | | -#endif /* !CONFIG_HOTPLUG_CPU */ |
---|
1080 | | - |
---|
1081 | 1210 | /* Direct Legacy VGA I/O traffic to designated IOH */ |
---|
1082 | | -int uv_set_vga_state(struct pci_dev *pdev, bool decode, unsigned int command_bits, u32 flags) |
---|
| 1211 | +static int uv_set_vga_state(struct pci_dev *pdev, bool decode, unsigned int command_bits, u32 flags) |
---|
1083 | 1212 | { |
---|
1084 | 1213 | int domain, bus, rc; |
---|
1085 | 1214 | |
---|
.. | .. |
---|
1108 | 1237 | return; |
---|
1109 | 1238 | |
---|
1110 | 1239 | uv_hub_info->nr_online_cpus++; |
---|
1111 | | - |
---|
1112 | | - if (get_uv_system_type() == UV_NON_UNIQUE_APIC) |
---|
1113 | | - set_x2apic_extra_bits(uv_hub_info->pnode); |
---|
1114 | 1240 | } |
---|
1115 | 1241 | |
---|
1116 | 1242 | struct mn { |
---|
.. | .. |
---|
1120 | 1246 | unsigned char n_lshift; |
---|
1121 | 1247 | }; |
---|
1122 | 1248 | |
---|
| 1249 | +/* Initialize caller's MN struct and fill in values */ |
---|
1123 | 1250 | static void get_mn(struct mn *mnp) |
---|
1124 | 1251 | { |
---|
1125 | | - union uvh_rh_gam_config_mmr_u m_n_config; |
---|
1126 | | - union uv3h_gr0_gam_gr_config_u m_gr_config; |
---|
1127 | | - |
---|
1128 | | - /* Make sure the whole structure is well initialized: */ |
---|
1129 | 1252 | memset(mnp, 0, sizeof(*mnp)); |
---|
1130 | | - |
---|
1131 | | - m_n_config.v = uv_read_local_mmr(UVH_RH_GAM_CONFIG_MMR); |
---|
1132 | | - mnp->n_val = m_n_config.s.n_skt; |
---|
1133 | | - |
---|
1134 | | - if (is_uv4_hub()) { |
---|
| 1253 | + mnp->n_val = uv_cpuid.n_skt; |
---|
| 1254 | + if (is_uv(UV4|UVY)) { |
---|
1135 | 1255 | mnp->m_val = 0; |
---|
1136 | 1256 | mnp->n_lshift = 0; |
---|
1137 | 1257 | } else if (is_uv3_hub()) { |
---|
1138 | | - mnp->m_val = m_n_config.s3.m_skt; |
---|
1139 | | - m_gr_config.v = uv_read_local_mmr(UV3H_GR0_GAM_GR_CONFIG); |
---|
| 1258 | + union uvyh_gr0_gam_gr_config_u m_gr_config; |
---|
| 1259 | + |
---|
| 1260 | + mnp->m_val = uv_cpuid.m_skt; |
---|
| 1261 | + m_gr_config.v = uv_read_local_mmr(UVH_GR0_GAM_GR_CONFIG); |
---|
1140 | 1262 | mnp->n_lshift = m_gr_config.s3.m_skt; |
---|
1141 | 1263 | } else if (is_uv2_hub()) { |
---|
1142 | | - mnp->m_val = m_n_config.s2.m_skt; |
---|
| 1264 | + mnp->m_val = uv_cpuid.m_skt; |
---|
1143 | 1265 | mnp->n_lshift = mnp->m_val == 40 ? 40 : 39; |
---|
1144 | | - } else if (is_uv1_hub()) { |
---|
1145 | | - mnp->m_val = m_n_config.s1.m_skt; |
---|
1146 | | - mnp->n_lshift = mnp->m_val; |
---|
1147 | 1266 | } |
---|
1148 | 1267 | mnp->m_shift = mnp->m_val ? 64 - mnp->m_val : 0; |
---|
1149 | 1268 | } |
---|
1150 | 1269 | |
---|
1151 | | -void __init uv_init_hub_info(struct uv_hub_info_s *hi) |
---|
| 1270 | +static void __init uv_init_hub_info(struct uv_hub_info_s *hi) |
---|
1152 | 1271 | { |
---|
1153 | | - union uvh_node_id_u node_id; |
---|
1154 | 1272 | struct mn mn; |
---|
1155 | 1273 | |
---|
1156 | 1274 | get_mn(&mn); |
---|
.. | .. |
---|
1163 | 1281 | hi->m_shift = mn.m_shift; |
---|
1164 | 1282 | hi->n_lshift = mn.n_lshift ? mn.n_lshift : 0; |
---|
1165 | 1283 | hi->hub_revision = uv_hub_info->hub_revision; |
---|
| 1284 | + hi->hub_type = uv_hub_info->hub_type; |
---|
1166 | 1285 | hi->pnode_mask = uv_cpuid.pnode_mask; |
---|
| 1286 | + hi->nasid_shift = uv_cpuid.nasid_shift; |
---|
1167 | 1287 | hi->min_pnode = _min_pnode; |
---|
1168 | 1288 | hi->min_socket = _min_socket; |
---|
1169 | 1289 | hi->pnode_to_socket = _pnode_to_socket; |
---|
.. | .. |
---|
1172 | 1292 | hi->gr_table_len = _gr_table_len; |
---|
1173 | 1293 | hi->gr_table = _gr_table; |
---|
1174 | 1294 | |
---|
1175 | | - node_id.v = uv_read_local_mmr(UVH_NODE_ID); |
---|
1176 | 1295 | uv_cpuid.gnode_shift = max_t(unsigned int, uv_cpuid.gnode_shift, mn.n_val); |
---|
1177 | | - hi->gnode_extra = (node_id.s.node_id & ~((1 << uv_cpuid.gnode_shift) - 1)) >> 1; |
---|
| 1296 | + hi->gnode_extra = (uv_node_id & ~((1 << uv_cpuid.gnode_shift) - 1)) >> 1; |
---|
1178 | 1297 | if (mn.m_val) |
---|
1179 | 1298 | hi->gnode_upper = (u64)hi->gnode_extra << mn.m_val; |
---|
1180 | 1299 | |
---|
.. | .. |
---|
1186 | 1305 | hi->gpa_shift = uv_gp_table->gpa_shift; |
---|
1187 | 1306 | hi->gpa_mask = (1UL << hi->gpa_shift) - 1; |
---|
1188 | 1307 | } else { |
---|
1189 | | - hi->global_mmr_base = uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR) & ~UV_MMR_ENABLE; |
---|
| 1308 | + hi->global_mmr_base = |
---|
| 1309 | + uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG) & |
---|
| 1310 | + ~UV_MMR_ENABLE; |
---|
1190 | 1311 | hi->global_mmr_shift = _UV_GLOBAL_MMR64_PNODE_SHIFT; |
---|
1191 | 1312 | } |
---|
1192 | 1313 | |
---|
.. | .. |
---|
1197 | 1318 | /* Show system specific info: */ |
---|
1198 | 1319 | pr_info("UV: N:%d M:%d m_shift:%d n_lshift:%d\n", hi->n_val, hi->m_val, hi->m_shift, hi->n_lshift); |
---|
1199 | 1320 | pr_info("UV: gpa_mask/shift:0x%lx/%d pnode_mask:0x%x apic_pns:%d\n", hi->gpa_mask, hi->gpa_shift, hi->pnode_mask, hi->apic_pnode_shift); |
---|
1200 | | - pr_info("UV: mmr_base/shift:0x%lx/%ld gru_base/shift:0x%lx/%ld\n", hi->global_mmr_base, hi->global_mmr_shift, hi->global_gru_base, hi->global_gru_shift); |
---|
| 1321 | + pr_info("UV: mmr_base/shift:0x%lx/%ld\n", hi->global_mmr_base, hi->global_mmr_shift); |
---|
| 1322 | + if (hi->global_gru_base) |
---|
| 1323 | + pr_info("UV: gru_base/shift:0x%lx/%ld\n", |
---|
| 1324 | + hi->global_gru_base, hi->global_gru_shift); |
---|
| 1325 | + |
---|
1201 | 1326 | pr_info("UV: gnode_upper:0x%lx gnode_extra:0x%x\n", hi->gnode_upper, hi->gnode_extra); |
---|
1202 | 1327 | } |
---|
1203 | 1328 | |
---|
.. | .. |
---|
1269 | 1394 | pr_info("UV: GRT: %d entries, sockets(min:%x,max:%x) pnodes(min:%x,max:%x)\n", index, _min_socket, _max_socket, _min_pnode, _max_pnode); |
---|
1270 | 1395 | } |
---|
1271 | 1396 | |
---|
| 1397 | +/* Walk through UVsystab decoding the fields */ |
---|
1272 | 1398 | static int __init decode_uv_systab(void) |
---|
1273 | 1399 | { |
---|
1274 | 1400 | struct uv_systab *st; |
---|
1275 | 1401 | int i; |
---|
1276 | 1402 | |
---|
1277 | | - if (uv_hub_info->hub_revision < UV4_HUB_REVISION_BASE) |
---|
1278 | | - return 0; /* No extended UVsystab required */ |
---|
1279 | | - |
---|
| 1403 | + /* Get mapped UVsystab pointer */ |
---|
1280 | 1404 | st = uv_systab; |
---|
| 1405 | + |
---|
| 1406 | + /* If UVsystab is version 1, there is no extended UVsystab */ |
---|
| 1407 | + if (st && st->revision == UV_SYSTAB_VERSION_1) |
---|
| 1408 | + return 0; |
---|
| 1409 | + |
---|
1281 | 1410 | if ((!st) || (st->revision < UV_SYSTAB_VERSION_UV4_LATEST)) { |
---|
1282 | 1411 | int rev = st ? st->revision : 0; |
---|
1283 | 1412 | |
---|
1284 | | - pr_err("UV: BIOS UVsystab version(%x) mismatch, expecting(%x)\n", rev, UV_SYSTAB_VERSION_UV4_LATEST); |
---|
1285 | | - pr_err("UV: Cannot support UV operations, switching to generic PC\n"); |
---|
| 1413 | + pr_err("UV: BIOS UVsystab mismatch, (%x < %x)\n", |
---|
| 1414 | + rev, UV_SYSTAB_VERSION_UV4_LATEST); |
---|
| 1415 | + pr_err("UV: Does not support UV, switch to non-UV x86_64\n"); |
---|
1286 | 1416 | uv_system_type = UV_NONE; |
---|
1287 | 1417 | |
---|
1288 | 1418 | return -EINVAL; |
---|
.. | .. |
---|
1294 | 1424 | if (!ptr) |
---|
1295 | 1425 | continue; |
---|
1296 | 1426 | |
---|
1297 | | - ptr = ptr + (unsigned long)st; |
---|
| 1427 | + /* point to payload */ |
---|
| 1428 | + ptr += (unsigned long)st; |
---|
1298 | 1429 | |
---|
1299 | 1430 | switch (st->entry[i].type) { |
---|
1300 | 1431 | case UV_SYSTAB_TYPE_GAM_PARAMS: |
---|
.. | .. |
---|
1304 | 1435 | case UV_SYSTAB_TYPE_GAM_RNG_TBL: |
---|
1305 | 1436 | decode_gam_rng_tbl(ptr); |
---|
1306 | 1437 | break; |
---|
| 1438 | + |
---|
| 1439 | + case UV_SYSTAB_TYPE_ARCH_TYPE: |
---|
| 1440 | + /* already processed in early startup */ |
---|
| 1441 | + break; |
---|
| 1442 | + |
---|
| 1443 | + default: |
---|
| 1444 | + pr_err("UV:%s:Unrecognized UV_SYSTAB_TYPE:%d, skipped\n", |
---|
| 1445 | + __func__, st->entry[i].type); |
---|
| 1446 | + break; |
---|
1307 | 1447 | } |
---|
1308 | 1448 | } |
---|
1309 | 1449 | return 0; |
---|
1310 | 1450 | } |
---|
1311 | 1451 | |
---|
1312 | | -/* |
---|
1313 | | - * Set up physical blade translations from UVH_NODE_PRESENT_TABLE |
---|
1314 | | - * .. NB: UVH_NODE_PRESENT_TABLE is going away, |
---|
1315 | | - * .. being replaced by GAM Range Table |
---|
1316 | | - */ |
---|
| 1452 | +/* Set up physical blade translations from UVH_NODE_PRESENT_TABLE */ |
---|
1317 | 1453 | static __init void boot_init_possible_blades(struct uv_hub_info_s *hub_info) |
---|
1318 | 1454 | { |
---|
| 1455 | + unsigned long np; |
---|
1319 | 1456 | int i, uv_pb = 0; |
---|
1320 | 1457 | |
---|
1321 | | - pr_info("UV: NODE_PRESENT_DEPTH = %d\n", UVH_NODE_PRESENT_TABLE_DEPTH); |
---|
1322 | | - for (i = 0; i < UVH_NODE_PRESENT_TABLE_DEPTH; i++) { |
---|
1323 | | - unsigned long np; |
---|
1324 | | - |
---|
1325 | | - np = uv_read_local_mmr(UVH_NODE_PRESENT_TABLE + i * 8); |
---|
1326 | | - if (np) |
---|
| 1458 | + if (UVH_NODE_PRESENT_TABLE) { |
---|
| 1459 | + pr_info("UV: NODE_PRESENT_DEPTH = %d\n", |
---|
| 1460 | + UVH_NODE_PRESENT_TABLE_DEPTH); |
---|
| 1461 | + for (i = 0; i < UVH_NODE_PRESENT_TABLE_DEPTH; i++) { |
---|
| 1462 | + np = uv_read_local_mmr(UVH_NODE_PRESENT_TABLE + i * 8); |
---|
1327 | 1463 | pr_info("UV: NODE_PRESENT(%d) = 0x%016lx\n", i, np); |
---|
1328 | | - |
---|
| 1464 | + uv_pb += hweight64(np); |
---|
| 1465 | + } |
---|
| 1466 | + } |
---|
| 1467 | + if (UVH_NODE_PRESENT_0) { |
---|
| 1468 | + np = uv_read_local_mmr(UVH_NODE_PRESENT_0); |
---|
| 1469 | + pr_info("UV: NODE_PRESENT_0 = 0x%016lx\n", np); |
---|
| 1470 | + uv_pb += hweight64(np); |
---|
| 1471 | + } |
---|
| 1472 | + if (UVH_NODE_PRESENT_1) { |
---|
| 1473 | + np = uv_read_local_mmr(UVH_NODE_PRESENT_1); |
---|
| 1474 | + pr_info("UV: NODE_PRESENT_1 = 0x%016lx\n", np); |
---|
1329 | 1475 | uv_pb += hweight64(np); |
---|
1330 | 1476 | } |
---|
1331 | 1477 | if (uv_possible_blades != uv_pb) |
---|
1332 | 1478 | uv_possible_blades = uv_pb; |
---|
| 1479 | + |
---|
| 1480 | + pr_info("UV: number nodes/possible blades %d\n", uv_pb); |
---|
1333 | 1481 | } |
---|
1334 | 1482 | |
---|
1335 | 1483 | static void __init build_socket_tables(void) |
---|
.. | .. |
---|
1344 | 1492 | size_t bytes; |
---|
1345 | 1493 | |
---|
1346 | 1494 | if (!gre) { |
---|
1347 | | - if (is_uv1_hub() || is_uv2_hub() || is_uv3_hub()) { |
---|
| 1495 | + if (is_uv2_hub() || is_uv3_hub()) { |
---|
1348 | 1496 | pr_info("UV: No UVsystab socket table, ignoring\n"); |
---|
1349 | 1497 | return; |
---|
1350 | 1498 | } |
---|
1351 | | - pr_crit("UV: Error: UVsystab address translations not available!\n"); |
---|
| 1499 | + pr_err("UV: Error: UVsystab address translations not available!\n"); |
---|
1352 | 1500 | BUG(); |
---|
1353 | 1501 | } |
---|
1354 | 1502 | |
---|
.. | .. |
---|
1390 | 1538 | } |
---|
1391 | 1539 | |
---|
1392 | 1540 | /* Set socket -> node values: */ |
---|
1393 | | - lnid = -1; |
---|
| 1541 | + lnid = NUMA_NO_NODE; |
---|
1394 | 1542 | for_each_present_cpu(cpu) { |
---|
1395 | 1543 | int nid = cpu_to_node(cpu); |
---|
1396 | 1544 | int apicid, sockid; |
---|
.. | .. |
---|
1453 | 1601 | } |
---|
1454 | 1602 | } |
---|
1455 | 1603 | |
---|
| 1604 | +/* Check which reboot to use */ |
---|
| 1605 | +static void check_efi_reboot(void) |
---|
| 1606 | +{ |
---|
| 1607 | + /* If EFI reboot not available, use ACPI reboot */ |
---|
| 1608 | + if (!efi_enabled(EFI_BOOT)) |
---|
| 1609 | + reboot_type = BOOT_ACPI; |
---|
| 1610 | +} |
---|
| 1611 | + |
---|
| 1612 | +/* Setup user proc fs files */ |
---|
| 1613 | +static int __maybe_unused proc_hubbed_show(struct seq_file *file, void *data) |
---|
| 1614 | +{ |
---|
| 1615 | + seq_printf(file, "0x%x\n", uv_hubbed_system); |
---|
| 1616 | + return 0; |
---|
| 1617 | +} |
---|
| 1618 | + |
---|
| 1619 | +static int __maybe_unused proc_hubless_show(struct seq_file *file, void *data) |
---|
| 1620 | +{ |
---|
| 1621 | + seq_printf(file, "0x%x\n", uv_hubless_system); |
---|
| 1622 | + return 0; |
---|
| 1623 | +} |
---|
| 1624 | + |
---|
| 1625 | +static int __maybe_unused proc_archtype_show(struct seq_file *file, void *data) |
---|
| 1626 | +{ |
---|
| 1627 | + seq_printf(file, "%s/%s\n", uv_archtype, oem_table_id); |
---|
| 1628 | + return 0; |
---|
| 1629 | +} |
---|
| 1630 | + |
---|
| 1631 | +static __init void uv_setup_proc_files(int hubless) |
---|
| 1632 | +{ |
---|
| 1633 | + struct proc_dir_entry *pde; |
---|
| 1634 | + |
---|
| 1635 | + pde = proc_mkdir(UV_PROC_NODE, NULL); |
---|
| 1636 | + proc_create_single("archtype", 0, pde, proc_archtype_show); |
---|
| 1637 | + if (hubless) |
---|
| 1638 | + proc_create_single("hubless", 0, pde, proc_hubless_show); |
---|
| 1639 | + else |
---|
| 1640 | + proc_create_single("hubbed", 0, pde, proc_hubbed_show); |
---|
| 1641 | +} |
---|
| 1642 | + |
---|
| 1643 | +/* Initialize UV hubless systems */ |
---|
| 1644 | +static __init int uv_system_init_hubless(void) |
---|
| 1645 | +{ |
---|
| 1646 | + int rc; |
---|
| 1647 | + |
---|
| 1648 | + /* Setup PCH NMI handler */ |
---|
| 1649 | + uv_nmi_setup_hubless(); |
---|
| 1650 | + |
---|
| 1651 | + /* Init kernel/BIOS interface */ |
---|
| 1652 | + rc = uv_bios_init(); |
---|
| 1653 | + if (rc < 0) |
---|
| 1654 | + return rc; |
---|
| 1655 | + |
---|
| 1656 | + /* Process UVsystab */ |
---|
| 1657 | + rc = decode_uv_systab(); |
---|
| 1658 | + if (rc < 0) |
---|
| 1659 | + return rc; |
---|
| 1660 | + |
---|
| 1661 | + /* Set section block size for current node memory */ |
---|
| 1662 | + set_block_size(); |
---|
| 1663 | + |
---|
| 1664 | + /* Create user access node */ |
---|
| 1665 | + if (rc >= 0) |
---|
| 1666 | + uv_setup_proc_files(1); |
---|
| 1667 | + |
---|
| 1668 | + check_efi_reboot(); |
---|
| 1669 | + |
---|
| 1670 | + return rc; |
---|
| 1671 | +} |
---|
| 1672 | + |
---|
1456 | 1673 | static void __init uv_system_init_hub(void) |
---|
1457 | 1674 | { |
---|
1458 | 1675 | struct uv_hub_info_s hub_info = {0}; |
---|
1459 | 1676 | int bytes, cpu, nodeid; |
---|
1460 | 1677 | unsigned short min_pnode = 9999, max_pnode = 0; |
---|
1461 | | - char *hub = is_uv4_hub() ? "UV400" : |
---|
| 1678 | + char *hub = is_uv5_hub() ? "UV500" : |
---|
| 1679 | + is_uv4_hub() ? "UV400" : |
---|
1462 | 1680 | is_uv3_hub() ? "UV300" : |
---|
1463 | | - is_uv2_hub() ? "UV2000/3000" : |
---|
1464 | | - is_uv1_hub() ? "UV100/1000" : NULL; |
---|
| 1681 | + is_uv2_hub() ? "UV2000/3000" : NULL; |
---|
1465 | 1682 | |
---|
1466 | 1683 | if (!hub) { |
---|
1467 | 1684 | pr_err("UV: Unknown/unsupported UV hub\n"); |
---|
.. | .. |
---|
1471 | 1688 | |
---|
1472 | 1689 | map_low_mmrs(); |
---|
1473 | 1690 | |
---|
1474 | | - /* Get uv_systab for decoding: */ |
---|
| 1691 | + /* Get uv_systab for decoding, setup UV BIOS calls */ |
---|
1475 | 1692 | uv_bios_init(); |
---|
1476 | 1693 | |
---|
1477 | 1694 | /* If there's an UVsystab problem then abort UV init: */ |
---|
1478 | | - if (decode_uv_systab() < 0) |
---|
| 1695 | + if (decode_uv_systab() < 0) { |
---|
| 1696 | + pr_err("UV: Mangled UVsystab format\n"); |
---|
1479 | 1697 | return; |
---|
| 1698 | + } |
---|
1480 | 1699 | |
---|
1481 | 1700 | build_socket_tables(); |
---|
1482 | 1701 | build_uv_gr_table(); |
---|
.. | .. |
---|
1521 | 1740 | new_hub->pnode = 0xffff; |
---|
1522 | 1741 | |
---|
1523 | 1742 | new_hub->numa_blade_id = uv_node_to_blade_id(nodeid); |
---|
1524 | | - new_hub->memory_nid = -1; |
---|
| 1743 | + new_hub->memory_nid = NUMA_NO_NODE; |
---|
1525 | 1744 | new_hub->nr_possible_cpus = 0; |
---|
1526 | 1745 | new_hub->nr_online_cpus = 0; |
---|
1527 | 1746 | } |
---|
.. | .. |
---|
1538 | 1757 | |
---|
1539 | 1758 | uv_cpu_info_per(cpu)->p_uv_hub_info = uv_hub_info_list(nodeid); |
---|
1540 | 1759 | uv_cpu_info_per(cpu)->blade_cpu_id = uv_cpu_hub_info(cpu)->nr_possible_cpus++; |
---|
1541 | | - if (uv_cpu_hub_info(cpu)->memory_nid == -1) |
---|
| 1760 | + if (uv_cpu_hub_info(cpu)->memory_nid == NUMA_NO_NODE) |
---|
1542 | 1761 | uv_cpu_hub_info(cpu)->memory_nid = cpu_to_node(cpu); |
---|
1543 | 1762 | |
---|
1544 | 1763 | /* Init memoryless node: */ |
---|
.. | .. |
---|
1547 | 1766 | uv_hub_info_list(numa_node_id)->pnode = pnode; |
---|
1548 | 1767 | else if (uv_cpu_hub_info(cpu)->pnode == 0xffff) |
---|
1549 | 1768 | uv_cpu_hub_info(cpu)->pnode = pnode; |
---|
1550 | | - |
---|
1551 | | - uv_cpu_scir_info(cpu)->offset = uv_scir_offset(apicid); |
---|
1552 | 1769 | } |
---|
1553 | 1770 | |
---|
1554 | 1771 | for_each_node(nodeid) { |
---|
.. | .. |
---|
1577 | 1794 | |
---|
1578 | 1795 | uv_nmi_setup(); |
---|
1579 | 1796 | uv_cpu_init(); |
---|
1580 | | - uv_scir_register_cpu_notifier(); |
---|
1581 | | - proc_mkdir("sgi_uv", NULL); |
---|
| 1797 | + uv_setup_proc_files(0); |
---|
1582 | 1798 | |
---|
1583 | 1799 | /* Register Legacy VGA I/O redirection handler: */ |
---|
1584 | 1800 | pci_register_set_vga_state(uv_set_vga_state); |
---|
1585 | 1801 | |
---|
1586 | | - /* |
---|
1587 | | - * For a kdump kernel the reset must be BOOT_ACPI, not BOOT_EFI, as |
---|
1588 | | - * EFI is not enabled in the kdump kernel: |
---|
1589 | | - */ |
---|
1590 | | - if (is_kdump_kernel()) |
---|
1591 | | - reboot_type = BOOT_ACPI; |
---|
| 1802 | + check_efi_reboot(); |
---|
1592 | 1803 | } |
---|
1593 | 1804 | |
---|
1594 | 1805 | /* |
---|
1595 | | - * There is a small amount of UV specific code needed to initialize a |
---|
1596 | | - * UV system that does not have a "UV HUB" (referred to as "hubless"). |
---|
| 1806 | + * There is a different code path needed to initialize a UV system that does |
---|
| 1807 | + * not have a "UV HUB" (referred to as "hubless"). |
---|
1597 | 1808 | */ |
---|
1598 | 1809 | void __init uv_system_init(void) |
---|
1599 | 1810 | { |
---|
1600 | | - if (likely(!is_uv_system() && !is_uv_hubless())) |
---|
| 1811 | + if (likely(!is_uv_system() && !is_uv_hubless(1))) |
---|
1601 | 1812 | return; |
---|
1602 | 1813 | |
---|
1603 | 1814 | if (is_uv_system()) |
---|
1604 | 1815 | uv_system_init_hub(); |
---|
1605 | 1816 | else |
---|
1606 | | - uv_nmi_setup_hubless(); |
---|
| 1817 | + uv_system_init_hubless(); |
---|
1607 | 1818 | } |
---|
1608 | 1819 | |
---|
1609 | 1820 | apic_driver(apic_x2apic_uv_x); |
---|