[IA64] SN: Add support for CPU disable

Add additional support for CPU disable on SN platforms.
Correctly setup the smp_affinity mask for I/O error IRQs.
Restrict the use of the feature to Altix 4000 and 450 systems
running with a CPU disable capable PROM, and do not allow disabling
of CPU 0.

Signed-off-by: John Keller <jpk@sgi.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>

authored by John Keller and committed by Tony Luck 6e9de181 1aac0b57

+64 -4
+6
arch/ia64/kernel/smpboot.c
··· 58 58 #include <asm/system.h> 59 59 #include <asm/tlbflush.h> 60 60 #include <asm/unistd.h> 61 + #include <asm/sn/arch.h> 61 62 62 63 #define SMP_DEBUG 0 63 64 ··· 729 728 if (cpu == 0 && !bsp_remove_ok) { 730 729 printk ("Your platform does not support removal of BSP\n"); 731 730 return (-EBUSY); 731 + } 732 + 733 + if (ia64_platform_is("sn2")) { 734 + if (!sn_cpu_disable_allowed(cpu)) 735 + return -EBUSY; 732 736 } 733 737 734 738 cpu_clear(cpu, cpu_online_map);
+10 -4
arch/ia64/sn/kernel/huberror.c
··· 185 185 */ 186 186 void hub_error_init(struct hubdev_info *hubdev_info) 187 187 { 188 + 188 189 if (request_irq(SGI_II_ERROR, hub_eint_handler, IRQF_SHARED, 189 - "SN_hub_error", (void *)hubdev_info)) 190 + "SN_hub_error", (void *)hubdev_info)) { 190 191 printk("hub_error_init: Failed to request_irq for 0x%p\n", 191 192 hubdev_info); 192 - return; 193 + return; 194 + } 195 + sn_set_err_irq_affinity(SGI_II_ERROR); 193 196 } 194 197 195 198 ··· 205 202 */ 206 203 void ice_error_init(struct hubdev_info *hubdev_info) 207 204 { 205 + 208 206 if (request_irq 209 207 (SGI_TIO_ERROR, (void *)hub_eint_handler, IRQF_SHARED, "SN_TIO_error", 210 - (void *)hubdev_info)) 208 + (void *)hubdev_info)) { 211 209 printk("ice_error_init: request_irq() error hubdev_info 0x%p\n", 212 210 hubdev_info); 213 - return; 211 + return; 212 + } 213 + sn_set_err_irq_affinity(SGI_TIO_ERROR); 214 214 } 215 215
+15
arch/ia64/sn/kernel/irq.c
··· 19 19 #include <asm/sn/pcidev.h> 20 20 #include <asm/sn/shub_mmr.h> 21 21 #include <asm/sn/sn_sal.h> 22 + #include <asm/sn/sn_feature_sets.h> 22 23 23 24 static void force_interrupt(int irq); 24 25 static void register_intr_pda(struct sn_irq_info *sn_irq_info); ··· 233 232 sn_irq_lh[irq], list) 234 233 (void)sn_retarget_vector(sn_irq_info, nasid, slice); 235 234 } 235 + 236 + #ifdef CONFIG_SMP 237 + void sn_set_err_irq_affinity(unsigned int irq) 238 + { 239 + /* 240 + * On systems which support CPU disabling (SHub2), all error interrupts 241 + * are targetted at the boot CPU. 242 + */ 243 + if (is_shub2() && sn_prom_feature_available(PRF_CPU_DISABLE_SUPPORT)) 244 + set_irq_affinity_info(irq, cpu_physical_id(0), 0); 245 + } 246 + #else 247 + void sn_set_err_irq_affinity(unsigned int irq) { } 248 + #endif 236 249 237 250 static void 238 251 sn_mask_irq(unsigned int irq)
+26
arch/ia64/sn/kernel/sn2/sn2_smp.c
··· 40 40 #include <asm/sn/shub_mmr.h> 41 41 #include <asm/sn/nodepda.h> 42 42 #include <asm/sn/rw_mmr.h> 43 + #include <asm/sn/sn_feature_sets.h> 43 44 44 45 DEFINE_PER_CPU(struct ptc_stats, ptcstats); 45 46 DECLARE_PER_CPU(struct ptc_stats, ptcstats); ··· 429 428 430 429 sn_send_IPI_phys(nasid, physid, vector, delivery_mode); 431 430 } 431 + 432 + #ifdef CONFIG_HOTPLUG_CPU 433 + /** 434 + * sn_cpu_disable_allowed - Determine if a CPU can be disabled. 435 + * @cpu - CPU that is requested to be disabled. 436 + * 437 + * CPU disable is only allowed on SHub2 systems running with a PROM 438 + * that supports CPU disable. It is not permitted to disable the boot processor. 439 + */ 440 + bool sn_cpu_disable_allowed(int cpu) 441 + { 442 + if (is_shub2() && sn_prom_feature_available(PRF_CPU_DISABLE_SUPPORT)) { 443 + if (cpu != 0) 444 + return true; 445 + else 446 + printk(KERN_WARNING 447 + "Disabling the boot processor is not allowed.\n"); 448 + 449 + } else 450 + printk(KERN_WARNING 451 + "CPU disable is not supported on this system.\n"); 452 + 453 + return false; 454 + } 455 + #endif /* CONFIG_HOTPLUG_CPU */ 432 456 433 457 #ifdef CONFIG_PROC_FS 434 458
+1
arch/ia64/sn/pci/pcibr/pcibr_provider.c
··· 145 145 printk(KERN_WARNING 146 146 "pcibr cannot allocate interrupt for error handler\n"); 147 147 } 148 + sn_set_err_irq_affinity(SGI_PCIASIC_ERROR); 148 149 149 150 /* 150 151 * Update the Bridge with the "kernel" pagesize
+2
arch/ia64/sn/pci/tioca_provider.c
··· 654 654 __FUNCTION__, SGI_TIOCA_ERROR, 655 655 (int)tioca_common->ca_common.bs_persist_busnum); 656 656 657 + sn_set_err_irq_affinity(SGI_TIOCA_ERROR); 658 + 657 659 /* Setup locality information */ 658 660 controller->node = tioca_kern->ca_closest_node; 659 661 return tioca_common;
+1
arch/ia64/sn/pci/tioce_provider.c
··· 1034 1034 tioce_common->ce_pcibus.bs_persist_segment, 1035 1035 tioce_common->ce_pcibus.bs_persist_busnum); 1036 1036 1037 + sn_set_err_irq_affinity(SGI_PCIASIC_ERROR); 1037 1038 return tioce_common; 1038 1039 } 1039 1040
+1
include/asm-ia64/sn/arch.h
··· 81 81 extern u8 sn_region_size; 82 82 83 83 extern void sn_flush_all_caches(long addr, long bytes); 84 + extern bool sn_cpu_disable_allowed(int cpu); 84 85 85 86 #endif /* _ASM_IA64_SN_ARCH_H */
+1
include/asm-ia64/sn/intr.h
··· 60 60 int, nasid_t, int); 61 61 extern void sn_intr_free(nasid_t, int, struct sn_irq_info *); 62 62 extern struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *, nasid_t, int); 63 + extern void sn_set_err_irq_affinity(unsigned int); 63 64 extern struct list_head **sn_irq_lh; 64 65 65 66 #define CPU_VECTOR_TO_IRQ(cpuid,vector) (vector)
+1
include/asm-ia64/sn/sn_feature_sets.h
··· 31 31 #define PRF_PAL_CACHE_FLUSH_SAFE 0 32 32 #define PRF_DEVICE_FLUSH_LIST 1 33 33 #define PRF_HOTPLUG_SUPPORT 2 34 + #define PRF_CPU_DISABLE_SUPPORT 3 34 35 35 36 /* --------------------- OS Features -------------------------------*/ 36 37