diff options
-rw-r--r-- | arch/x86/Kconfig | 1 | ||||
-rw-r--r-- | arch/x86/include/asm/uv/uv_mmrs.h | 5 | ||||
-rw-r--r-- | arch/x86/kernel/apic/x2apic_uv_x.c | 16 | ||||
-rw-r--r-- | arch/x86/kernel/bios_uv.c | 3 | ||||
-rw-r--r-- | arch/x86/kernel/tlb_uv.c | 189 | ||||
-rw-r--r-- | arch/x86/kernel/uv_sysfs.c | 4 |
6 files changed, 154 insertions, 64 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index bc25b9f5e4cd..c9086e6307a5 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -353,6 +353,7 @@ config X86_UV | |||
353 | bool "SGI Ultraviolet" | 353 | bool "SGI Ultraviolet" |
354 | depends on X86_64 | 354 | depends on X86_64 |
355 | depends on X86_EXTENDED_PLATFORM | 355 | depends on X86_EXTENDED_PLATFORM |
356 | depends on NUMA | ||
356 | select X86_X2APIC | 357 | select X86_X2APIC |
357 | ---help--- | 358 | ---help--- |
358 | This option is needed in order to support SGI Ultraviolet systems. | 359 | This option is needed in order to support SGI Ultraviolet systems. |
diff --git a/arch/x86/include/asm/uv/uv_mmrs.h b/arch/x86/include/asm/uv/uv_mmrs.h index db68ac8a5ac2..2cae46c7c8a2 100644 --- a/arch/x86/include/asm/uv/uv_mmrs.h +++ b/arch/x86/include/asm/uv/uv_mmrs.h | |||
@@ -17,6 +17,11 @@ | |||
17 | /* ========================================================================= */ | 17 | /* ========================================================================= */ |
18 | /* UVH_BAU_DATA_CONFIG */ | 18 | /* UVH_BAU_DATA_CONFIG */ |
19 | /* ========================================================================= */ | 19 | /* ========================================================================= */ |
20 | #define UVH_LB_BAU_MISC_CONTROL 0x320170UL | ||
21 | #define UV_ENABLE_INTD_SOFT_ACK_MODE_SHIFT 15 | ||
22 | #define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHIFT 16 | ||
23 | #define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD 0x000000000bUL | ||
24 | /* 1011 timebase 7 (168millisec) * 3 ticks -> 500ms */ | ||
20 | #define UVH_BAU_DATA_CONFIG 0x61680UL | 25 | #define UVH_BAU_DATA_CONFIG 0x61680UL |
21 | #define UVH_BAU_DATA_CONFIG_32 0x0438 | 26 | #define UVH_BAU_DATA_CONFIG_32 0x0438 |
22 | 27 | ||
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 1248318436e8..de1a50af807b 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c | |||
@@ -549,7 +549,8 @@ void __init uv_system_init(void) | |||
549 | unsigned long gnode_upper, lowmem_redir_base, lowmem_redir_size; | 549 | unsigned long gnode_upper, lowmem_redir_base, lowmem_redir_size; |
550 | int bytes, nid, cpu, lcpu, pnode, blade, i, j, m_val, n_val; | 550 | int bytes, nid, cpu, lcpu, pnode, blade, i, j, m_val, n_val; |
551 | int max_pnode = 0; | 551 | int max_pnode = 0; |
552 | unsigned long mmr_base, present; | 552 | unsigned long mmr_base, present, paddr; |
553 | unsigned short pnode_mask; | ||
553 | 554 | ||
554 | map_low_mmrs(); | 555 | map_low_mmrs(); |
555 | 556 | ||
@@ -592,6 +593,7 @@ void __init uv_system_init(void) | |||
592 | } | 593 | } |
593 | } | 594 | } |
594 | 595 | ||
596 | pnode_mask = (1 << n_val) - 1; | ||
595 | node_id.v = uv_read_local_mmr(UVH_NODE_ID); | 597 | node_id.v = uv_read_local_mmr(UVH_NODE_ID); |
596 | gnode_upper = (((unsigned long)node_id.s.node_id) & | 598 | gnode_upper = (((unsigned long)node_id.s.node_id) & |
597 | ~((1 << n_val) - 1)) << m_val; | 599 | ~((1 << n_val) - 1)) << m_val; |
@@ -615,7 +617,7 @@ void __init uv_system_init(void) | |||
615 | uv_cpu_hub_info(cpu)->numa_blade_id = blade; | 617 | uv_cpu_hub_info(cpu)->numa_blade_id = blade; |
616 | uv_cpu_hub_info(cpu)->blade_processor_id = lcpu; | 618 | uv_cpu_hub_info(cpu)->blade_processor_id = lcpu; |
617 | uv_cpu_hub_info(cpu)->pnode = pnode; | 619 | uv_cpu_hub_info(cpu)->pnode = pnode; |
618 | uv_cpu_hub_info(cpu)->pnode_mask = (1 << n_val) - 1; | 620 | uv_cpu_hub_info(cpu)->pnode_mask = pnode_mask; |
619 | uv_cpu_hub_info(cpu)->gpa_mask = (1 << (m_val + n_val)) - 1; | 621 | uv_cpu_hub_info(cpu)->gpa_mask = (1 << (m_val + n_val)) - 1; |
620 | uv_cpu_hub_info(cpu)->gnode_upper = gnode_upper; | 622 | uv_cpu_hub_info(cpu)->gnode_upper = gnode_upper; |
621 | uv_cpu_hub_info(cpu)->global_mmr_base = mmr_base; | 623 | uv_cpu_hub_info(cpu)->global_mmr_base = mmr_base; |
@@ -631,6 +633,16 @@ void __init uv_system_init(void) | |||
631 | lcpu, blade); | 633 | lcpu, blade); |
632 | } | 634 | } |
633 | 635 | ||
636 | /* Add blade/pnode info for nodes without cpus */ | ||
637 | for_each_online_node(nid) { | ||
638 | if (uv_node_to_blade[nid] >= 0) | ||
639 | continue; | ||
640 | paddr = node_start_pfn(nid) << PAGE_SHIFT; | ||
641 | pnode = (paddr >> m_val) & pnode_mask; | ||
642 | blade = boot_pnode_to_blade(pnode); | ||
643 | uv_node_to_blade[nid] = blade; | ||
644 | } | ||
645 | |||
634 | map_gru_high(max_pnode); | 646 | map_gru_high(max_pnode); |
635 | map_mmr_high(max_pnode); | 647 | map_mmr_high(max_pnode); |
636 | map_config_high(max_pnode); | 648 | map_config_high(max_pnode); |
diff --git a/arch/x86/kernel/bios_uv.c b/arch/x86/kernel/bios_uv.c index f63882728d91..63a88e1f987d 100644 --- a/arch/x86/kernel/bios_uv.c +++ b/arch/x86/kernel/bios_uv.c | |||
@@ -182,7 +182,8 @@ void uv_bios_init(void) | |||
182 | memcpy(&uv_systab, tab, sizeof(struct uv_systab)); | 182 | memcpy(&uv_systab, tab, sizeof(struct uv_systab)); |
183 | iounmap(tab); | 183 | iounmap(tab); |
184 | 184 | ||
185 | printk(KERN_INFO "EFI UV System Table Revision %d\n", tab->revision); | 185 | printk(KERN_INFO "EFI UV System Table Revision %d\n", |
186 | uv_systab.revision); | ||
186 | } | 187 | } |
187 | #else /* !CONFIG_EFI */ | 188 | #else /* !CONFIG_EFI */ |
188 | 189 | ||
diff --git a/arch/x86/kernel/tlb_uv.c b/arch/x86/kernel/tlb_uv.c index deb5ebb32c3b..ed0c33761e6d 100644 --- a/arch/x86/kernel/tlb_uv.c +++ b/arch/x86/kernel/tlb_uv.c | |||
@@ -25,6 +25,8 @@ static int uv_bau_retry_limit __read_mostly; | |||
25 | 25 | ||
26 | /* position of pnode (which is nasid>>1): */ | 26 | /* position of pnode (which is nasid>>1): */ |
27 | static int uv_nshift __read_mostly; | 27 | static int uv_nshift __read_mostly; |
28 | /* base pnode in this partition */ | ||
29 | static int uv_partition_base_pnode __read_mostly; | ||
28 | 30 | ||
29 | static unsigned long uv_mmask __read_mostly; | 31 | static unsigned long uv_mmask __read_mostly; |
30 | 32 | ||
@@ -32,6 +34,34 @@ static DEFINE_PER_CPU(struct ptc_stats, ptcstats); | |||
32 | static DEFINE_PER_CPU(struct bau_control, bau_control); | 34 | static DEFINE_PER_CPU(struct bau_control, bau_control); |
33 | 35 | ||
34 | /* | 36 | /* |
37 | * Determine the first node on a blade. | ||
38 | */ | ||
39 | static int __init blade_to_first_node(int blade) | ||
40 | { | ||
41 | int node, b; | ||
42 | |||
43 | for_each_online_node(node) { | ||
44 | b = uv_node_to_blade_id(node); | ||
45 | if (blade == b) | ||
46 | return node; | ||
47 | } | ||
48 | return -1; /* shouldn't happen */ | ||
49 | } | ||
50 | |||
51 | /* | ||
52 | * Determine the apicid of the first cpu on a blade. | ||
53 | */ | ||
54 | static int __init blade_to_first_apicid(int blade) | ||
55 | { | ||
56 | int cpu; | ||
57 | |||
58 | for_each_present_cpu(cpu) | ||
59 | if (blade == uv_cpu_to_blade_id(cpu)) | ||
60 | return per_cpu(x86_cpu_to_apicid, cpu); | ||
61 | return -1; | ||
62 | } | ||
63 | |||
64 | /* | ||
35 | * Free a software acknowledge hardware resource by clearing its Pending | 65 | * Free a software acknowledge hardware resource by clearing its Pending |
36 | * bit. This will return a reply to the sender. | 66 | * bit. This will return a reply to the sender. |
37 | * If the message has timed out, a reply has already been sent by the | 67 | * If the message has timed out, a reply has already been sent by the |
@@ -67,7 +97,7 @@ static void uv_bau_process_message(struct bau_payload_queue_entry *msg, | |||
67 | msp = __get_cpu_var(bau_control).msg_statuses + msg_slot; | 97 | msp = __get_cpu_var(bau_control).msg_statuses + msg_slot; |
68 | cpu = uv_blade_processor_id(); | 98 | cpu = uv_blade_processor_id(); |
69 | msg->number_of_cpus = | 99 | msg->number_of_cpus = |
70 | uv_blade_nr_online_cpus(uv_node_to_blade_id(numa_node_id())); | 100 | uv_blade_nr_online_cpus(uv_node_to_blade_id(numa_node_id())); |
71 | this_cpu_mask = 1UL << cpu; | 101 | this_cpu_mask = 1UL << cpu; |
72 | if (msp->seen_by.bits & this_cpu_mask) | 102 | if (msp->seen_by.bits & this_cpu_mask) |
73 | return; | 103 | return; |
@@ -215,14 +245,14 @@ static int uv_wait_completion(struct bau_desc *bau_desc, | |||
215 | * Returns @flush_mask if some remote flushing remains to be done. The | 245 | * Returns @flush_mask if some remote flushing remains to be done. The |
216 | * mask will have some bits still set. | 246 | * mask will have some bits still set. |
217 | */ | 247 | */ |
218 | const struct cpumask *uv_flush_send_and_wait(int cpu, int this_blade, | 248 | const struct cpumask *uv_flush_send_and_wait(int cpu, int this_pnode, |
219 | struct bau_desc *bau_desc, | 249 | struct bau_desc *bau_desc, |
220 | struct cpumask *flush_mask) | 250 | struct cpumask *flush_mask) |
221 | { | 251 | { |
222 | int completion_status = 0; | 252 | int completion_status = 0; |
223 | int right_shift; | 253 | int right_shift; |
224 | int tries = 0; | 254 | int tries = 0; |
225 | int blade; | 255 | int pnode; |
226 | int bit; | 256 | int bit; |
227 | unsigned long mmr_offset; | 257 | unsigned long mmr_offset; |
228 | unsigned long index; | 258 | unsigned long index; |
@@ -265,8 +295,8 @@ const struct cpumask *uv_flush_send_and_wait(int cpu, int this_blade, | |||
265 | * use the IPI method of shootdown on them. | 295 | * use the IPI method of shootdown on them. |
266 | */ | 296 | */ |
267 | for_each_cpu(bit, flush_mask) { | 297 | for_each_cpu(bit, flush_mask) { |
268 | blade = uv_cpu_to_blade_id(bit); | 298 | pnode = uv_cpu_to_pnode(bit); |
269 | if (blade == this_blade) | 299 | if (pnode == this_pnode) |
270 | continue; | 300 | continue; |
271 | cpumask_clear_cpu(bit, flush_mask); | 301 | cpumask_clear_cpu(bit, flush_mask); |
272 | } | 302 | } |
@@ -309,16 +339,16 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, | |||
309 | struct cpumask *flush_mask = __get_cpu_var(uv_flush_tlb_mask); | 339 | struct cpumask *flush_mask = __get_cpu_var(uv_flush_tlb_mask); |
310 | int i; | 340 | int i; |
311 | int bit; | 341 | int bit; |
312 | int blade; | 342 | int pnode; |
313 | int uv_cpu; | 343 | int uv_cpu; |
314 | int this_blade; | 344 | int this_pnode; |
315 | int locals = 0; | 345 | int locals = 0; |
316 | struct bau_desc *bau_desc; | 346 | struct bau_desc *bau_desc; |
317 | 347 | ||
318 | cpumask_andnot(flush_mask, cpumask, cpumask_of(cpu)); | 348 | cpumask_andnot(flush_mask, cpumask, cpumask_of(cpu)); |
319 | 349 | ||
320 | uv_cpu = uv_blade_processor_id(); | 350 | uv_cpu = uv_blade_processor_id(); |
321 | this_blade = uv_numa_blade_id(); | 351 | this_pnode = uv_hub_info->pnode; |
322 | bau_desc = __get_cpu_var(bau_control).descriptor_base; | 352 | bau_desc = __get_cpu_var(bau_control).descriptor_base; |
323 | bau_desc += UV_ITEMS_PER_DESCRIPTOR * uv_cpu; | 353 | bau_desc += UV_ITEMS_PER_DESCRIPTOR * uv_cpu; |
324 | 354 | ||
@@ -326,13 +356,14 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, | |||
326 | 356 | ||
327 | i = 0; | 357 | i = 0; |
328 | for_each_cpu(bit, flush_mask) { | 358 | for_each_cpu(bit, flush_mask) { |
329 | blade = uv_cpu_to_blade_id(bit); | 359 | pnode = uv_cpu_to_pnode(bit); |
330 | BUG_ON(blade > (UV_DISTRIBUTION_SIZE - 1)); | 360 | BUG_ON(pnode > (UV_DISTRIBUTION_SIZE - 1)); |
331 | if (blade == this_blade) { | 361 | if (pnode == this_pnode) { |
332 | locals++; | 362 | locals++; |
333 | continue; | 363 | continue; |
334 | } | 364 | } |
335 | bau_node_set(blade, &bau_desc->distribution); | 365 | bau_node_set(pnode - uv_partition_base_pnode, |
366 | &bau_desc->distribution); | ||
336 | i++; | 367 | i++; |
337 | } | 368 | } |
338 | if (i == 0) { | 369 | if (i == 0) { |
@@ -350,7 +381,7 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, | |||
350 | bau_desc->payload.address = va; | 381 | bau_desc->payload.address = va; |
351 | bau_desc->payload.sending_cpu = cpu; | 382 | bau_desc->payload.sending_cpu = cpu; |
352 | 383 | ||
353 | return uv_flush_send_and_wait(uv_cpu, this_blade, bau_desc, flush_mask); | 384 | return uv_flush_send_and_wait(uv_cpu, this_pnode, bau_desc, flush_mask); |
354 | } | 385 | } |
355 | 386 | ||
356 | /* | 387 | /* |
@@ -418,24 +449,58 @@ void uv_bau_message_interrupt(struct pt_regs *regs) | |||
418 | set_irq_regs(old_regs); | 449 | set_irq_regs(old_regs); |
419 | } | 450 | } |
420 | 451 | ||
452 | /* | ||
453 | * uv_enable_timeouts | ||
454 | * | ||
455 | * Each target blade (i.e. blades that have cpu's) needs to have | ||
456 | * shootdown message timeouts enabled. The timeout does not cause | ||
457 | * an interrupt, but causes an error message to be returned to | ||
458 | * the sender. | ||
459 | */ | ||
421 | static void uv_enable_timeouts(void) | 460 | static void uv_enable_timeouts(void) |
422 | { | 461 | { |
423 | int i; | ||
424 | int blade; | 462 | int blade; |
425 | int last_blade; | 463 | int nblades; |
426 | int pnode; | 464 | int pnode; |
427 | int cur_cpu = 0; | 465 | unsigned long mmr_image; |
428 | unsigned long apicid; | ||
429 | 466 | ||
430 | last_blade = -1; | 467 | nblades = uv_num_possible_blades(); |
431 | for_each_online_node(i) { | 468 | |
432 | blade = uv_node_to_blade_id(i); | 469 | for (blade = 0; blade < nblades; blade++) { |
433 | if (blade == last_blade) | 470 | if (!uv_blade_nr_possible_cpus(blade)) |
434 | continue; | 471 | continue; |
435 | last_blade = blade; | 472 | |
436 | apicid = per_cpu(x86_cpu_to_apicid, cur_cpu); | ||
437 | pnode = uv_blade_to_pnode(blade); | 473 | pnode = uv_blade_to_pnode(blade); |
438 | cur_cpu += uv_blade_nr_possible_cpus(i); | 474 | mmr_image = |
475 | uv_read_global_mmr64(pnode, UVH_LB_BAU_MISC_CONTROL); | ||
476 | /* | ||
477 | * Set the timeout period and then lock it in, in three | ||
478 | * steps; captures and locks in the period. | ||
479 | * | ||
480 | * To program the period, the SOFT_ACK_MODE must be off. | ||
481 | */ | ||
482 | mmr_image &= ~((unsigned long)1 << | ||
483 | UV_ENABLE_INTD_SOFT_ACK_MODE_SHIFT); | ||
484 | uv_write_global_mmr64 | ||
485 | (pnode, UVH_LB_BAU_MISC_CONTROL, mmr_image); | ||
486 | /* | ||
487 | * Set the 4-bit period. | ||
488 | */ | ||
489 | mmr_image &= ~((unsigned long)0xf << | ||
490 | UV_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHIFT); | ||
491 | mmr_image |= (UV_INTD_SOFT_ACK_TIMEOUT_PERIOD << | ||
492 | UV_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHIFT); | ||
493 | uv_write_global_mmr64 | ||
494 | (pnode, UVH_LB_BAU_MISC_CONTROL, mmr_image); | ||
495 | /* | ||
496 | * Subsequent reversals of the timebase bit (3) cause an | ||
497 | * immediate timeout of one or all INTD resources as | ||
498 | * indicated in bits 2:0 (7 causes all of them to timeout). | ||
499 | */ | ||
500 | mmr_image |= ((unsigned long)1 << | ||
501 | UV_ENABLE_INTD_SOFT_ACK_MODE_SHIFT); | ||
502 | uv_write_global_mmr64 | ||
503 | (pnode, UVH_LB_BAU_MISC_CONTROL, mmr_image); | ||
439 | } | 504 | } |
440 | } | 505 | } |
441 | 506 | ||
@@ -482,8 +547,7 @@ static int uv_ptc_seq_show(struct seq_file *file, void *data) | |||
482 | stat->requestee, stat->onetlb, stat->alltlb, | 547 | stat->requestee, stat->onetlb, stat->alltlb, |
483 | stat->s_retry, stat->d_retry, stat->ptc_i); | 548 | stat->s_retry, stat->d_retry, stat->ptc_i); |
484 | seq_printf(file, "%lx %ld %ld %ld %ld %ld %ld\n", | 549 | seq_printf(file, "%lx %ld %ld %ld %ld %ld %ld\n", |
485 | uv_read_global_mmr64(uv_blade_to_pnode | 550 | uv_read_global_mmr64(uv_cpu_to_pnode(cpu), |
486 | (uv_cpu_to_blade_id(cpu)), | ||
487 | UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE), | 551 | UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE), |
488 | stat->sflush, stat->dflush, | 552 | stat->sflush, stat->dflush, |
489 | stat->retriesok, stat->nomsg, | 553 | stat->retriesok, stat->nomsg, |
@@ -617,16 +681,18 @@ static struct bau_control * __init uv_table_bases_init(int blade, int node) | |||
617 | * finish the initialization of the per-blade control structures | 681 | * finish the initialization of the per-blade control structures |
618 | */ | 682 | */ |
619 | static void __init | 683 | static void __init |
620 | uv_table_bases_finish(int blade, int node, int cur_cpu, | 684 | uv_table_bases_finish(int blade, |
621 | struct bau_control *bau_tablesp, | 685 | struct bau_control *bau_tablesp, |
622 | struct bau_desc *adp) | 686 | struct bau_desc *adp) |
623 | { | 687 | { |
624 | struct bau_control *bcp; | 688 | struct bau_control *bcp; |
625 | int i; | 689 | int cpu; |
626 | 690 | ||
627 | for (i = cur_cpu; i < cur_cpu + uv_blade_nr_possible_cpus(blade); i++) { | 691 | for_each_present_cpu(cpu) { |
628 | bcp = (struct bau_control *)&per_cpu(bau_control, i); | 692 | if (blade != uv_cpu_to_blade_id(cpu)) |
693 | continue; | ||
629 | 694 | ||
695 | bcp = (struct bau_control *)&per_cpu(bau_control, cpu); | ||
630 | bcp->bau_msg_head = bau_tablesp->va_queue_first; | 696 | bcp->bau_msg_head = bau_tablesp->va_queue_first; |
631 | bcp->va_queue_first = bau_tablesp->va_queue_first; | 697 | bcp->va_queue_first = bau_tablesp->va_queue_first; |
632 | bcp->va_queue_last = bau_tablesp->va_queue_last; | 698 | bcp->va_queue_last = bau_tablesp->va_queue_last; |
@@ -649,11 +715,10 @@ uv_activation_descriptor_init(int node, int pnode) | |||
649 | struct bau_desc *adp; | 715 | struct bau_desc *adp; |
650 | struct bau_desc *ad2; | 716 | struct bau_desc *ad2; |
651 | 717 | ||
652 | adp = (struct bau_desc *) | 718 | adp = (struct bau_desc *)kmalloc_node(16384, GFP_KERNEL, node); |
653 | kmalloc_node(16384, GFP_KERNEL, node); | ||
654 | BUG_ON(!adp); | 719 | BUG_ON(!adp); |
655 | 720 | ||
656 | pa = __pa((unsigned long)adp); | 721 | pa = uv_gpa(adp); /* need the real nasid*/ |
657 | n = pa >> uv_nshift; | 722 | n = pa >> uv_nshift; |
658 | m = pa & uv_mmask; | 723 | m = pa & uv_mmask; |
659 | 724 | ||
@@ -667,8 +732,12 @@ uv_activation_descriptor_init(int node, int pnode) | |||
667 | for (i = 0, ad2 = adp; i < UV_ACTIVATION_DESCRIPTOR_SIZE; i++, ad2++) { | 732 | for (i = 0, ad2 = adp; i < UV_ACTIVATION_DESCRIPTOR_SIZE; i++, ad2++) { |
668 | memset(ad2, 0, sizeof(struct bau_desc)); | 733 | memset(ad2, 0, sizeof(struct bau_desc)); |
669 | ad2->header.sw_ack_flag = 1; | 734 | ad2->header.sw_ack_flag = 1; |
670 | ad2->header.base_dest_nodeid = | 735 | /* |
671 | uv_blade_to_pnode(uv_cpu_to_blade_id(0)); | 736 | * base_dest_nodeid is the first node in the partition, so |
737 | * the bit map will indicate partition-relative node numbers. | ||
738 | * note that base_dest_nodeid is actually a nasid. | ||
739 | */ | ||
740 | ad2->header.base_dest_nodeid = uv_partition_base_pnode << 1; | ||
672 | ad2->header.command = UV_NET_ENDPOINT_INTD; | 741 | ad2->header.command = UV_NET_ENDPOINT_INTD; |
673 | ad2->header.int_both = 1; | 742 | ad2->header.int_both = 1; |
674 | /* | 743 | /* |
@@ -686,6 +755,8 @@ static struct bau_payload_queue_entry * __init | |||
686 | uv_payload_queue_init(int node, int pnode, struct bau_control *bau_tablesp) | 755 | uv_payload_queue_init(int node, int pnode, struct bau_control *bau_tablesp) |
687 | { | 756 | { |
688 | struct bau_payload_queue_entry *pqp; | 757 | struct bau_payload_queue_entry *pqp; |
758 | unsigned long pa; | ||
759 | int pn; | ||
689 | char *cp; | 760 | char *cp; |
690 | 761 | ||
691 | pqp = (struct bau_payload_queue_entry *) kmalloc_node( | 762 | pqp = (struct bau_payload_queue_entry *) kmalloc_node( |
@@ -696,10 +767,14 @@ uv_payload_queue_init(int node, int pnode, struct bau_control *bau_tablesp) | |||
696 | cp = (char *)pqp + 31; | 767 | cp = (char *)pqp + 31; |
697 | pqp = (struct bau_payload_queue_entry *)(((unsigned long)cp >> 5) << 5); | 768 | pqp = (struct bau_payload_queue_entry *)(((unsigned long)cp >> 5) << 5); |
698 | bau_tablesp->va_queue_first = pqp; | 769 | bau_tablesp->va_queue_first = pqp; |
770 | /* | ||
771 | * need the pnode of where the memory was really allocated | ||
772 | */ | ||
773 | pa = uv_gpa(pqp); | ||
774 | pn = pa >> uv_nshift; | ||
699 | uv_write_global_mmr64(pnode, | 775 | uv_write_global_mmr64(pnode, |
700 | UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST, | 776 | UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST, |
701 | ((unsigned long)pnode << | 777 | ((unsigned long)pn << UV_PAYLOADQ_PNODE_SHIFT) | |
702 | UV_PAYLOADQ_PNODE_SHIFT) | | ||
703 | uv_physnodeaddr(pqp)); | 778 | uv_physnodeaddr(pqp)); |
704 | uv_write_global_mmr64(pnode, UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL, | 779 | uv_write_global_mmr64(pnode, UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL, |
705 | uv_physnodeaddr(pqp)); | 780 | uv_physnodeaddr(pqp)); |
@@ -715,8 +790,9 @@ uv_payload_queue_init(int node, int pnode, struct bau_control *bau_tablesp) | |||
715 | /* | 790 | /* |
716 | * Initialization of each UV blade's structures | 791 | * Initialization of each UV blade's structures |
717 | */ | 792 | */ |
718 | static int __init uv_init_blade(int blade, int node, int cur_cpu) | 793 | static int __init uv_init_blade(int blade) |
719 | { | 794 | { |
795 | int node; | ||
720 | int pnode; | 796 | int pnode; |
721 | unsigned long pa; | 797 | unsigned long pa; |
722 | unsigned long apicid; | 798 | unsigned long apicid; |
@@ -724,16 +800,17 @@ static int __init uv_init_blade(int blade, int node, int cur_cpu) | |||
724 | struct bau_payload_queue_entry *pqp; | 800 | struct bau_payload_queue_entry *pqp; |
725 | struct bau_control *bau_tablesp; | 801 | struct bau_control *bau_tablesp; |
726 | 802 | ||
803 | node = blade_to_first_node(blade); | ||
727 | bau_tablesp = uv_table_bases_init(blade, node); | 804 | bau_tablesp = uv_table_bases_init(blade, node); |
728 | pnode = uv_blade_to_pnode(blade); | 805 | pnode = uv_blade_to_pnode(blade); |
729 | adp = uv_activation_descriptor_init(node, pnode); | 806 | adp = uv_activation_descriptor_init(node, pnode); |
730 | pqp = uv_payload_queue_init(node, pnode, bau_tablesp); | 807 | pqp = uv_payload_queue_init(node, pnode, bau_tablesp); |
731 | uv_table_bases_finish(blade, node, cur_cpu, bau_tablesp, adp); | 808 | uv_table_bases_finish(blade, bau_tablesp, adp); |
732 | /* | 809 | /* |
733 | * the below initialization can't be in firmware because the | 810 | * the below initialization can't be in firmware because the |
734 | * messaging IRQ will be determined by the OS | 811 | * messaging IRQ will be determined by the OS |
735 | */ | 812 | */ |
736 | apicid = per_cpu(x86_cpu_to_apicid, cur_cpu); | 813 | apicid = blade_to_first_apicid(blade); |
737 | pa = uv_read_global_mmr64(pnode, UVH_BAU_DATA_CONFIG); | 814 | pa = uv_read_global_mmr64(pnode, UVH_BAU_DATA_CONFIG); |
738 | if ((pa & 0xff) != UV_BAU_MESSAGE) { | 815 | if ((pa & 0xff) != UV_BAU_MESSAGE) { |
739 | uv_write_global_mmr64(pnode, UVH_BAU_DATA_CONFIG, | 816 | uv_write_global_mmr64(pnode, UVH_BAU_DATA_CONFIG, |
@@ -748,9 +825,7 @@ static int __init uv_init_blade(int blade, int node, int cur_cpu) | |||
748 | static int __init uv_bau_init(void) | 825 | static int __init uv_bau_init(void) |
749 | { | 826 | { |
750 | int blade; | 827 | int blade; |
751 | int node; | ||
752 | int nblades; | 828 | int nblades; |
753 | int last_blade; | ||
754 | int cur_cpu; | 829 | int cur_cpu; |
755 | 830 | ||
756 | if (!is_uv_system()) | 831 | if (!is_uv_system()) |
@@ -763,29 +838,21 @@ static int __init uv_bau_init(void) | |||
763 | uv_bau_retry_limit = 1; | 838 | uv_bau_retry_limit = 1; |
764 | uv_nshift = uv_hub_info->n_val; | 839 | uv_nshift = uv_hub_info->n_val; |
765 | uv_mmask = (1UL << uv_hub_info->n_val) - 1; | 840 | uv_mmask = (1UL << uv_hub_info->n_val) - 1; |
766 | nblades = 0; | 841 | nblades = uv_num_possible_blades(); |
767 | last_blade = -1; | 842 | |
768 | cur_cpu = 0; | ||
769 | for_each_online_node(node) { | ||
770 | blade = uv_node_to_blade_id(node); | ||
771 | if (blade == last_blade) | ||
772 | continue; | ||
773 | last_blade = blade; | ||
774 | nblades++; | ||
775 | } | ||
776 | uv_bau_table_bases = (struct bau_control **) | 843 | uv_bau_table_bases = (struct bau_control **) |
777 | kmalloc(nblades * sizeof(struct bau_control *), GFP_KERNEL); | 844 | kmalloc(nblades * sizeof(struct bau_control *), GFP_KERNEL); |
778 | BUG_ON(!uv_bau_table_bases); | 845 | BUG_ON(!uv_bau_table_bases); |
779 | 846 | ||
780 | last_blade = -1; | 847 | uv_partition_base_pnode = 0x7fffffff; |
781 | for_each_online_node(node) { | 848 | for (blade = 0; blade < nblades; blade++) |
782 | blade = uv_node_to_blade_id(node); | 849 | if (uv_blade_nr_possible_cpus(blade) && |
783 | if (blade == last_blade) | 850 | (uv_blade_to_pnode(blade) < uv_partition_base_pnode)) |
784 | continue; | 851 | uv_partition_base_pnode = uv_blade_to_pnode(blade); |
785 | last_blade = blade; | 852 | for (blade = 0; blade < nblades; blade++) |
786 | uv_init_blade(blade, node, cur_cpu); | 853 | if (uv_blade_nr_possible_cpus(blade)) |
787 | cur_cpu += uv_blade_nr_possible_cpus(blade); | 854 | uv_init_blade(blade); |
788 | } | 855 | |
789 | alloc_intr_gate(UV_BAU_MESSAGE, uv_bau_message_intr1); | 856 | alloc_intr_gate(UV_BAU_MESSAGE, uv_bau_message_intr1); |
790 | uv_enable_timeouts(); | 857 | uv_enable_timeouts(); |
791 | 858 | ||
diff --git a/arch/x86/kernel/uv_sysfs.c b/arch/x86/kernel/uv_sysfs.c index 67f9b9dbf800..36afb98675a4 100644 --- a/arch/x86/kernel/uv_sysfs.c +++ b/arch/x86/kernel/uv_sysfs.c | |||
@@ -21,6 +21,7 @@ | |||
21 | 21 | ||
22 | #include <linux/sysdev.h> | 22 | #include <linux/sysdev.h> |
23 | #include <asm/uv/bios.h> | 23 | #include <asm/uv/bios.h> |
24 | #include <asm/uv/uv.h> | ||
24 | 25 | ||
25 | struct kobject *sgi_uv_kobj; | 26 | struct kobject *sgi_uv_kobj; |
26 | 27 | ||
@@ -47,6 +48,9 @@ static int __init sgi_uv_sysfs_init(void) | |||
47 | { | 48 | { |
48 | unsigned long ret; | 49 | unsigned long ret; |
49 | 50 | ||
51 | if (!is_uv_system()) | ||
52 | return -ENODEV; | ||
53 | |||
50 | if (!sgi_uv_kobj) | 54 | if (!sgi_uv_kobj) |
51 | sgi_uv_kobj = kobject_create_and_add("sgi_uv", firmware_kobj); | 55 | sgi_uv_kobj = kobject_create_and_add("sgi_uv", firmware_kobj); |
52 | if (!sgi_uv_kobj) { | 56 | if (!sgi_uv_kobj) { |