diff options
Diffstat (limited to 'arch/s390/kernel/smp.c')
-rw-r--r-- | arch/s390/kernel/smp.c | 261 |
1 files changed, 205 insertions, 56 deletions
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 0b499f5cbe19..370ff3a092a3 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -71,9 +71,30 @@ struct pcpu { | |||
71 | }; | 71 | }; |
72 | 72 | ||
73 | static u8 boot_cpu_type; | 73 | static u8 boot_cpu_type; |
74 | static u16 boot_cpu_address; | ||
75 | static struct pcpu pcpu_devices[NR_CPUS]; | 74 | static struct pcpu pcpu_devices[NR_CPUS]; |
76 | 75 | ||
76 | unsigned int smp_cpu_mt_shift; | ||
77 | EXPORT_SYMBOL(smp_cpu_mt_shift); | ||
78 | |||
79 | unsigned int smp_cpu_mtid; | ||
80 | EXPORT_SYMBOL(smp_cpu_mtid); | ||
81 | |||
82 | static unsigned int smp_max_threads __initdata = -1U; | ||
83 | |||
84 | static int __init early_nosmt(char *s) | ||
85 | { | ||
86 | smp_max_threads = 1; | ||
87 | return 0; | ||
88 | } | ||
89 | early_param("nosmt", early_nosmt); | ||
90 | |||
91 | static int __init early_smt(char *s) | ||
92 | { | ||
93 | get_option(&s, &smp_max_threads); | ||
94 | return 0; | ||
95 | } | ||
96 | early_param("smt", early_smt); | ||
97 | |||
77 | /* | 98 | /* |
78 | * The smp_cpu_state_mutex must be held when changing the state or polarization | 99 | * The smp_cpu_state_mutex must be held when changing the state or polarization |
79 | * member of a pcpu data structure within the pcpu_devices arreay. | 100 | * member of a pcpu data structure within the pcpu_devices arreay. |
@@ -132,7 +153,7 @@ static inline int pcpu_running(struct pcpu *pcpu) | |||
132 | /* | 153 | /* |
133 | * Find struct pcpu by cpu address. | 154 | * Find struct pcpu by cpu address. |
134 | */ | 155 | */ |
135 | static struct pcpu *pcpu_find_address(const struct cpumask *mask, int address) | 156 | static struct pcpu *pcpu_find_address(const struct cpumask *mask, u16 address) |
136 | { | 157 | { |
137 | int cpu; | 158 | int cpu; |
138 | 159 | ||
@@ -299,6 +320,32 @@ static void pcpu_delegate(struct pcpu *pcpu, void (*func)(void *), | |||
299 | } | 320 | } |
300 | 321 | ||
301 | /* | 322 | /* |
323 | * Enable additional logical cpus for multi-threading. | ||
324 | */ | ||
325 | static int pcpu_set_smt(unsigned int mtid) | ||
326 | { | ||
327 | register unsigned long reg1 asm ("1") = (unsigned long) mtid; | ||
328 | int cc; | ||
329 | |||
330 | if (smp_cpu_mtid == mtid) | ||
331 | return 0; | ||
332 | asm volatile( | ||
333 | " sigp %1,0,%2 # sigp set multi-threading\n" | ||
334 | " ipm %0\n" | ||
335 | " srl %0,28\n" | ||
336 | : "=d" (cc) : "d" (reg1), "K" (SIGP_SET_MULTI_THREADING) | ||
337 | : "cc"); | ||
338 | if (cc == 0) { | ||
339 | smp_cpu_mtid = mtid; | ||
340 | smp_cpu_mt_shift = 0; | ||
341 | while (smp_cpu_mtid >= (1U << smp_cpu_mt_shift)) | ||
342 | smp_cpu_mt_shift++; | ||
343 | pcpu_devices[0].address = stap(); | ||
344 | } | ||
345 | return cc; | ||
346 | } | ||
347 | |||
348 | /* | ||
302 | * Call function on an online CPU. | 349 | * Call function on an online CPU. |
303 | */ | 350 | */ |
304 | void smp_call_online_cpu(void (*func)(void *), void *data) | 351 | void smp_call_online_cpu(void (*func)(void *), void *data) |
@@ -512,22 +559,17 @@ EXPORT_SYMBOL(smp_ctl_clear_bit); | |||
512 | 559 | ||
513 | #ifdef CONFIG_CRASH_DUMP | 560 | #ifdef CONFIG_CRASH_DUMP |
514 | 561 | ||
515 | static void __init smp_get_save_area(int cpu, u16 address) | 562 | static inline void __smp_store_cpu_state(int cpu, u16 address, int is_boot_cpu) |
516 | { | 563 | { |
517 | void *lc = pcpu_devices[0].lowcore; | 564 | void *lc = pcpu_devices[0].lowcore; |
518 | struct save_area_ext *sa_ext; | 565 | struct save_area_ext *sa_ext; |
519 | unsigned long vx_sa; | 566 | unsigned long vx_sa; |
520 | 567 | ||
521 | if (is_kdump_kernel()) | ||
522 | return; | ||
523 | if (!OLDMEM_BASE && (address == boot_cpu_address || | ||
524 | ipl_info.type != IPL_TYPE_FCP_DUMP)) | ||
525 | return; | ||
526 | sa_ext = dump_save_area_create(cpu); | 568 | sa_ext = dump_save_area_create(cpu); |
527 | if (!sa_ext) | 569 | if (!sa_ext) |
528 | panic("could not allocate memory for save area\n"); | 570 | panic("could not allocate memory for save area\n"); |
529 | if (address == boot_cpu_address) { | 571 | if (is_boot_cpu) { |
530 | /* Copy the registers of the boot cpu. */ | 572 | /* Copy the registers of the boot CPU. */ |
531 | copy_oldmem_page(1, (void *) &sa_ext->sa, sizeof(sa_ext->sa), | 573 | copy_oldmem_page(1, (void *) &sa_ext->sa, sizeof(sa_ext->sa), |
532 | SAVE_AREA_BASE - PAGE_SIZE, 0); | 574 | SAVE_AREA_BASE - PAGE_SIZE, 0); |
533 | if (MACHINE_HAS_VX) | 575 | if (MACHINE_HAS_VX) |
@@ -548,6 +590,64 @@ static void __init smp_get_save_area(int cpu, u16 address) | |||
548 | free_page(vx_sa); | 590 | free_page(vx_sa); |
549 | } | 591 | } |
550 | 592 | ||
593 | /* | ||
594 | * Collect CPU state of the previous, crashed system. | ||
595 | * There are four cases: | ||
596 | * 1) standard zfcp dump | ||
597 | * condition: OLDMEM_BASE == NULL && ipl_info.type == IPL_TYPE_FCP_DUMP | ||
598 | * The state for all CPUs except the boot CPU needs to be collected | ||
599 | * with sigp stop-and-store-status. The boot CPU state is located in | ||
600 | * the absolute lowcore of the memory stored in the HSA. The zcore code | ||
601 | * will allocate the save area and copy the boot CPU state from the HSA. | ||
602 | * 2) stand-alone kdump for SCSI (zfcp dump with swapped memory) | ||
603 | * condition: OLDMEM_BASE != NULL && ipl_info.type == IPL_TYPE_FCP_DUMP | ||
604 | * The state for all CPUs except the boot CPU needs to be collected | ||
605 | * with sigp stop-and-store-status. The firmware or the boot-loader | ||
606 | * stored the registers of the boot CPU in the absolute lowcore in the | ||
607 | * memory of the old system. | ||
608 | * 3) kdump and the old kernel did not store the CPU state, | ||
609 | * or stand-alone kdump for DASD | ||
610 | * condition: OLDMEM_BASE != NULL && !is_kdump_kernel() | ||
611 | * The state for all CPUs except the boot CPU needs to be collected | ||
612 | * with sigp stop-and-store-status. The kexec code or the boot-loader | ||
613 | * stored the registers of the boot CPU in the memory of the old system. | ||
614 | * 4) kdump and the old kernel stored the CPU state | ||
615 | * condition: OLDMEM_BASE != NULL && is_kdump_kernel() | ||
616 | * The state of all CPUs is stored in ELF sections in the memory of the | ||
617 | * old system. The ELF sections are picked up by the crash_dump code | ||
618 | * via elfcorehdr_addr. | ||
619 | */ | ||
620 | static void __init smp_store_cpu_states(struct sclp_cpu_info *info) | ||
621 | { | ||
622 | unsigned int cpu, address, i, j; | ||
623 | int is_boot_cpu; | ||
624 | |||
625 | if (is_kdump_kernel()) | ||
626 | /* Previous system stored the CPU states. Nothing to do. */ | ||
627 | return; | ||
628 | if (!(OLDMEM_BASE || ipl_info.type == IPL_TYPE_FCP_DUMP)) | ||
629 | /* No previous system present, normal boot. */ | ||
630 | return; | ||
631 | /* Set multi-threading state to the previous system. */ | ||
632 | pcpu_set_smt(sclp_get_mtid_prev()); | ||
633 | /* Collect CPU states. */ | ||
634 | cpu = 0; | ||
635 | for (i = 0; i < info->configured; i++) { | ||
636 | /* Skip CPUs with different CPU type. */ | ||
637 | if (info->has_cpu_type && info->cpu[i].type != boot_cpu_type) | ||
638 | continue; | ||
639 | for (j = 0; j <= smp_cpu_mtid; j++, cpu++) { | ||
640 | address = (info->cpu[i].core_id << smp_cpu_mt_shift) + j; | ||
641 | is_boot_cpu = (address == pcpu_devices[0].address); | ||
642 | if (is_boot_cpu && !OLDMEM_BASE) | ||
643 | /* Skip boot CPU for standard zfcp dump. */ | ||
644 | continue; | ||
645 | /* Get state for this CPu. */ | ||
646 | __smp_store_cpu_state(cpu, address, is_boot_cpu); | ||
647 | } | ||
648 | } | ||
649 | } | ||
650 | |||
551 | int smp_store_status(int cpu) | 651 | int smp_store_status(int cpu) |
552 | { | 652 | { |
553 | unsigned long vx_sa; | 653 | unsigned long vx_sa; |
@@ -565,10 +665,6 @@ int smp_store_status(int cpu) | |||
565 | return 0; | 665 | return 0; |
566 | } | 666 | } |
567 | 667 | ||
568 | #else /* CONFIG_CRASH_DUMP */ | ||
569 | |||
570 | static inline void smp_get_save_area(int cpu, u16 address) { } | ||
571 | |||
572 | #endif /* CONFIG_CRASH_DUMP */ | 668 | #endif /* CONFIG_CRASH_DUMP */ |
573 | 669 | ||
574 | void smp_cpu_set_polarization(int cpu, int val) | 670 | void smp_cpu_set_polarization(int cpu, int val) |
@@ -590,11 +686,13 @@ static struct sclp_cpu_info *smp_get_cpu_info(void) | |||
590 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 686 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
591 | if (info && (use_sigp_detection || sclp_get_cpu_info(info))) { | 687 | if (info && (use_sigp_detection || sclp_get_cpu_info(info))) { |
592 | use_sigp_detection = 1; | 688 | use_sigp_detection = 1; |
593 | for (address = 0; address <= MAX_CPU_ADDRESS; address++) { | 689 | for (address = 0; address <= MAX_CPU_ADDRESS; |
690 | address += (1U << smp_cpu_mt_shift)) { | ||
594 | if (__pcpu_sigp_relax(address, SIGP_SENSE, 0, NULL) == | 691 | if (__pcpu_sigp_relax(address, SIGP_SENSE, 0, NULL) == |
595 | SIGP_CC_NOT_OPERATIONAL) | 692 | SIGP_CC_NOT_OPERATIONAL) |
596 | continue; | 693 | continue; |
597 | info->cpu[info->configured].address = address; | 694 | info->cpu[info->configured].core_id = |
695 | address >> smp_cpu_mt_shift; | ||
598 | info->configured++; | 696 | info->configured++; |
599 | } | 697 | } |
600 | info->combined = info->configured; | 698 | info->combined = info->configured; |
@@ -608,7 +706,8 @@ static int __smp_rescan_cpus(struct sclp_cpu_info *info, int sysfs_add) | |||
608 | { | 706 | { |
609 | struct pcpu *pcpu; | 707 | struct pcpu *pcpu; |
610 | cpumask_t avail; | 708 | cpumask_t avail; |
611 | int cpu, nr, i; | 709 | int cpu, nr, i, j; |
710 | u16 address; | ||
612 | 711 | ||
613 | nr = 0; | 712 | nr = 0; |
614 | cpumask_xor(&avail, cpu_possible_mask, cpu_present_mask); | 713 | cpumask_xor(&avail, cpu_possible_mask, cpu_present_mask); |
@@ -616,51 +715,76 @@ static int __smp_rescan_cpus(struct sclp_cpu_info *info, int sysfs_add) | |||
616 | for (i = 0; (i < info->combined) && (cpu < nr_cpu_ids); i++) { | 715 | for (i = 0; (i < info->combined) && (cpu < nr_cpu_ids); i++) { |
617 | if (info->has_cpu_type && info->cpu[i].type != boot_cpu_type) | 716 | if (info->has_cpu_type && info->cpu[i].type != boot_cpu_type) |
618 | continue; | 717 | continue; |
619 | if (pcpu_find_address(cpu_present_mask, info->cpu[i].address)) | 718 | address = info->cpu[i].core_id << smp_cpu_mt_shift; |
620 | continue; | 719 | for (j = 0; j <= smp_cpu_mtid; j++) { |
621 | pcpu = pcpu_devices + cpu; | 720 | if (pcpu_find_address(cpu_present_mask, address + j)) |
622 | pcpu->address = info->cpu[i].address; | 721 | continue; |
623 | pcpu->state = (i >= info->configured) ? | 722 | pcpu = pcpu_devices + cpu; |
624 | CPU_STATE_STANDBY : CPU_STATE_CONFIGURED; | 723 | pcpu->address = address + j; |
625 | smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); | 724 | pcpu->state = |
626 | set_cpu_present(cpu, true); | 725 | (cpu >= info->configured*(smp_cpu_mtid + 1)) ? |
627 | if (sysfs_add && smp_add_present_cpu(cpu) != 0) | 726 | CPU_STATE_STANDBY : CPU_STATE_CONFIGURED; |
628 | set_cpu_present(cpu, false); | 727 | smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); |
629 | else | 728 | set_cpu_present(cpu, true); |
630 | nr++; | 729 | if (sysfs_add && smp_add_present_cpu(cpu) != 0) |
631 | cpu = cpumask_next(cpu, &avail); | 730 | set_cpu_present(cpu, false); |
731 | else | ||
732 | nr++; | ||
733 | cpu = cpumask_next(cpu, &avail); | ||
734 | if (cpu >= nr_cpu_ids) | ||
735 | break; | ||
736 | } | ||
632 | } | 737 | } |
633 | return nr; | 738 | return nr; |
634 | } | 739 | } |
635 | 740 | ||
636 | static void __init smp_detect_cpus(void) | 741 | static void __init smp_detect_cpus(void) |
637 | { | 742 | { |
638 | unsigned int cpu, c_cpus, s_cpus; | 743 | unsigned int cpu, mtid, c_cpus, s_cpus; |
639 | struct sclp_cpu_info *info; | 744 | struct sclp_cpu_info *info; |
745 | u16 address; | ||
640 | 746 | ||
747 | /* Get CPU information */ | ||
641 | info = smp_get_cpu_info(); | 748 | info = smp_get_cpu_info(); |
642 | if (!info) | 749 | if (!info) |
643 | panic("smp_detect_cpus failed to allocate memory\n"); | 750 | panic("smp_detect_cpus failed to allocate memory\n"); |
751 | |||
752 | /* Find boot CPU type */ | ||
644 | if (info->has_cpu_type) { | 753 | if (info->has_cpu_type) { |
645 | for (cpu = 0; cpu < info->combined; cpu++) { | 754 | address = stap(); |
646 | if (info->cpu[cpu].address != boot_cpu_address) | 755 | for (cpu = 0; cpu < info->combined; cpu++) |
647 | continue; | 756 | if (info->cpu[cpu].core_id == address) { |
648 | /* The boot cpu dictates the cpu type. */ | 757 | /* The boot cpu dictates the cpu type. */ |
649 | boot_cpu_type = info->cpu[cpu].type; | 758 | boot_cpu_type = info->cpu[cpu].type; |
650 | break; | 759 | break; |
651 | } | 760 | } |
761 | if (cpu >= info->combined) | ||
762 | panic("Could not find boot CPU type"); | ||
652 | } | 763 | } |
764 | |||
765 | #if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_CRASH_DUMP) | ||
766 | /* Collect CPU state of previous system */ | ||
767 | smp_store_cpu_states(info); | ||
768 | #endif | ||
769 | |||
770 | /* Set multi-threading state for the current system */ | ||
771 | mtid = sclp_get_mtid(boot_cpu_type); | ||
772 | mtid = (mtid < smp_max_threads) ? mtid : smp_max_threads - 1; | ||
773 | pcpu_set_smt(mtid); | ||
774 | |||
775 | /* Print number of CPUs */ | ||
653 | c_cpus = s_cpus = 0; | 776 | c_cpus = s_cpus = 0; |
654 | for (cpu = 0; cpu < info->combined; cpu++) { | 777 | for (cpu = 0; cpu < info->combined; cpu++) { |
655 | if (info->has_cpu_type && info->cpu[cpu].type != boot_cpu_type) | 778 | if (info->has_cpu_type && info->cpu[cpu].type != boot_cpu_type) |
656 | continue; | 779 | continue; |
657 | if (cpu < info->configured) { | 780 | if (cpu < info->configured) |
658 | smp_get_save_area(c_cpus, info->cpu[cpu].address); | 781 | c_cpus += smp_cpu_mtid + 1; |
659 | c_cpus++; | 782 | else |
660 | } else | 783 | s_cpus += smp_cpu_mtid + 1; |
661 | s_cpus++; | ||
662 | } | 784 | } |
663 | pr_info("%d configured CPUs, %d standby CPUs\n", c_cpus, s_cpus); | 785 | pr_info("%d configured CPUs, %d standby CPUs\n", c_cpus, s_cpus); |
786 | |||
787 | /* Add CPUs present at boot */ | ||
664 | get_online_cpus(); | 788 | get_online_cpus(); |
665 | __smp_rescan_cpus(info, 0); | 789 | __smp_rescan_cpus(info, 0); |
666 | put_online_cpus(); | 790 | put_online_cpus(); |
@@ -696,12 +820,23 @@ static void smp_start_secondary(void *cpuvoid) | |||
696 | int __cpu_up(unsigned int cpu, struct task_struct *tidle) | 820 | int __cpu_up(unsigned int cpu, struct task_struct *tidle) |
697 | { | 821 | { |
698 | struct pcpu *pcpu; | 822 | struct pcpu *pcpu; |
699 | int rc; | 823 | int base, i, rc; |
700 | 824 | ||
701 | pcpu = pcpu_devices + cpu; | 825 | pcpu = pcpu_devices + cpu; |
702 | if (pcpu->state != CPU_STATE_CONFIGURED) | 826 | if (pcpu->state != CPU_STATE_CONFIGURED) |
703 | return -EIO; | 827 | return -EIO; |
704 | if (pcpu_sigp_retry(pcpu, SIGP_INITIAL_CPU_RESET, 0) != | 828 | base = cpu - (cpu % (smp_cpu_mtid + 1)); |
829 | for (i = 0; i <= smp_cpu_mtid; i++) { | ||
830 | if (base + i < nr_cpu_ids) | ||
831 | if (cpu_online(base + i)) | ||
832 | break; | ||
833 | } | ||
834 | /* | ||
835 | * If this is the first CPU of the core to get online | ||
836 | * do an initial CPU reset. | ||
837 | */ | ||
838 | if (i > smp_cpu_mtid && | ||
839 | pcpu_sigp_retry(pcpu_devices + base, SIGP_INITIAL_CPU_RESET, 0) != | ||
705 | SIGP_CC_ORDER_CODE_ACCEPTED) | 840 | SIGP_CC_ORDER_CODE_ACCEPTED) |
706 | return -EIO; | 841 | return -EIO; |
707 | 842 | ||
@@ -774,7 +909,8 @@ void __init smp_fill_possible_mask(void) | |||
774 | { | 909 | { |
775 | unsigned int possible, sclp, cpu; | 910 | unsigned int possible, sclp, cpu; |
776 | 911 | ||
777 | sclp = sclp_get_max_cpu() ?: nr_cpu_ids; | 912 | sclp = min(smp_max_threads, sclp_get_mtid_max() + 1); |
913 | sclp = sclp_get_max_cpu()*sclp ?: nr_cpu_ids; | ||
778 | possible = setup_possible_cpus ?: nr_cpu_ids; | 914 | possible = setup_possible_cpus ?: nr_cpu_ids; |
779 | possible = min(possible, sclp); | 915 | possible = min(possible, sclp); |
780 | for (cpu = 0; cpu < possible && cpu < nr_cpu_ids; cpu++) | 916 | for (cpu = 0; cpu < possible && cpu < nr_cpu_ids; cpu++) |
@@ -796,9 +932,8 @@ void __init smp_prepare_boot_cpu(void) | |||
796 | { | 932 | { |
797 | struct pcpu *pcpu = pcpu_devices; | 933 | struct pcpu *pcpu = pcpu_devices; |
798 | 934 | ||
799 | boot_cpu_address = stap(); | ||
800 | pcpu->state = CPU_STATE_CONFIGURED; | 935 | pcpu->state = CPU_STATE_CONFIGURED; |
801 | pcpu->address = boot_cpu_address; | 936 | pcpu->address = stap(); |
802 | pcpu->lowcore = (struct _lowcore *)(unsigned long) store_prefix(); | 937 | pcpu->lowcore = (struct _lowcore *)(unsigned long) store_prefix(); |
803 | pcpu->async_stack = S390_lowcore.async_stack - ASYNC_SIZE | 938 | pcpu->async_stack = S390_lowcore.async_stack - ASYNC_SIZE |
804 | + STACK_FRAME_OVERHEAD + sizeof(struct pt_regs); | 939 | + STACK_FRAME_OVERHEAD + sizeof(struct pt_regs); |
@@ -848,7 +983,7 @@ static ssize_t cpu_configure_store(struct device *dev, | |||
848 | const char *buf, size_t count) | 983 | const char *buf, size_t count) |
849 | { | 984 | { |
850 | struct pcpu *pcpu; | 985 | struct pcpu *pcpu; |
851 | int cpu, val, rc; | 986 | int cpu, val, rc, i; |
852 | char delim; | 987 | char delim; |
853 | 988 | ||
854 | if (sscanf(buf, "%d %c", &val, &delim) != 1) | 989 | if (sscanf(buf, "%d %c", &val, &delim) != 1) |
@@ -860,29 +995,43 @@ static ssize_t cpu_configure_store(struct device *dev, | |||
860 | rc = -EBUSY; | 995 | rc = -EBUSY; |
861 | /* disallow configuration changes of online cpus and cpu 0 */ | 996 | /* disallow configuration changes of online cpus and cpu 0 */ |
862 | cpu = dev->id; | 997 | cpu = dev->id; |
863 | if (cpu_online(cpu) || cpu == 0) | 998 | cpu -= cpu % (smp_cpu_mtid + 1); |
999 | if (cpu == 0) | ||
864 | goto out; | 1000 | goto out; |
1001 | for (i = 0; i <= smp_cpu_mtid; i++) | ||
1002 | if (cpu_online(cpu + i)) | ||
1003 | goto out; | ||
865 | pcpu = pcpu_devices + cpu; | 1004 | pcpu = pcpu_devices + cpu; |
866 | rc = 0; | 1005 | rc = 0; |
867 | switch (val) { | 1006 | switch (val) { |
868 | case 0: | 1007 | case 0: |
869 | if (pcpu->state != CPU_STATE_CONFIGURED) | 1008 | if (pcpu->state != CPU_STATE_CONFIGURED) |
870 | break; | 1009 | break; |
871 | rc = sclp_cpu_deconfigure(pcpu->address); | 1010 | rc = sclp_cpu_deconfigure(pcpu->address >> smp_cpu_mt_shift); |
872 | if (rc) | 1011 | if (rc) |
873 | break; | 1012 | break; |
874 | pcpu->state = CPU_STATE_STANDBY; | 1013 | for (i = 0; i <= smp_cpu_mtid; i++) { |
875 | smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); | 1014 | if (cpu + i >= nr_cpu_ids || !cpu_present(cpu + i)) |
1015 | continue; | ||
1016 | pcpu[i].state = CPU_STATE_STANDBY; | ||
1017 | smp_cpu_set_polarization(cpu + i, | ||
1018 | POLARIZATION_UNKNOWN); | ||
1019 | } | ||
876 | topology_expect_change(); | 1020 | topology_expect_change(); |
877 | break; | 1021 | break; |
878 | case 1: | 1022 | case 1: |
879 | if (pcpu->state != CPU_STATE_STANDBY) | 1023 | if (pcpu->state != CPU_STATE_STANDBY) |
880 | break; | 1024 | break; |
881 | rc = sclp_cpu_configure(pcpu->address); | 1025 | rc = sclp_cpu_configure(pcpu->address >> smp_cpu_mt_shift); |
882 | if (rc) | 1026 | if (rc) |
883 | break; | 1027 | break; |
884 | pcpu->state = CPU_STATE_CONFIGURED; | 1028 | for (i = 0; i <= smp_cpu_mtid; i++) { |
885 | smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); | 1029 | if (cpu + i >= nr_cpu_ids || !cpu_present(cpu + i)) |
1030 | continue; | ||
1031 | pcpu[i].state = CPU_STATE_CONFIGURED; | ||
1032 | smp_cpu_set_polarization(cpu + i, | ||
1033 | POLARIZATION_UNKNOWN); | ||
1034 | } | ||
886 | topology_expect_change(); | 1035 | topology_expect_change(); |
887 | break; | 1036 | break; |
888 | default: | 1037 | default: |