diff options
Diffstat (limited to 'arch/x86/kernel/topology.c')
-rw-r--r-- | arch/x86/kernel/topology.c | 101 |
1 files changed, 94 insertions, 7 deletions
diff --git a/arch/x86/kernel/topology.c b/arch/x86/kernel/topology.c index 76ee97709a00..6e60b5fe2244 100644 --- a/arch/x86/kernel/topology.c +++ b/arch/x86/kernel/topology.c | |||
@@ -30,23 +30,110 @@ | |||
30 | #include <linux/mmzone.h> | 30 | #include <linux/mmzone.h> |
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/smp.h> | 32 | #include <linux/smp.h> |
33 | #include <linux/irq.h> | ||
33 | #include <asm/cpu.h> | 34 | #include <asm/cpu.h> |
34 | 35 | ||
35 | static DEFINE_PER_CPU(struct x86_cpu, cpu_devices); | 36 | static DEFINE_PER_CPU(struct x86_cpu, cpu_devices); |
36 | 37 | ||
37 | #ifdef CONFIG_HOTPLUG_CPU | 38 | #ifdef CONFIG_HOTPLUG_CPU |
39 | |||
40 | #ifdef CONFIG_BOOTPARAM_HOTPLUG_CPU0 | ||
41 | static int cpu0_hotpluggable = 1; | ||
42 | #else | ||
43 | static int cpu0_hotpluggable; | ||
44 | static int __init enable_cpu0_hotplug(char *str) | ||
45 | { | ||
46 | cpu0_hotpluggable = 1; | ||
47 | return 1; | ||
48 | } | ||
49 | |||
50 | __setup("cpu0_hotplug", enable_cpu0_hotplug); | ||
51 | #endif | ||
52 | |||
53 | #ifdef CONFIG_DEBUG_HOTPLUG_CPU0 | ||
54 | /* | ||
55 | * This function offlines a CPU as early as possible and allows userspace to | ||
56 | * boot up without the CPU. The CPU can be onlined back by user after boot. | ||
57 | * | ||
58 | * This is only called for debugging CPU offline/online feature. | ||
59 | */ | ||
60 | int __ref _debug_hotplug_cpu(int cpu, int action) | ||
61 | { | ||
62 | struct device *dev = get_cpu_device(cpu); | ||
63 | int ret; | ||
64 | |||
65 | if (!cpu_is_hotpluggable(cpu)) | ||
66 | return -EINVAL; | ||
67 | |||
68 | cpu_hotplug_driver_lock(); | ||
69 | |||
70 | switch (action) { | ||
71 | case 0: | ||
72 | ret = cpu_down(cpu); | ||
73 | if (!ret) { | ||
74 | pr_info("CPU %u is now offline\n", cpu); | ||
75 | kobject_uevent(&dev->kobj, KOBJ_OFFLINE); | ||
76 | } else | ||
77 | pr_debug("Can't offline CPU%d.\n", cpu); | ||
78 | break; | ||
79 | case 1: | ||
80 | ret = cpu_up(cpu); | ||
81 | if (!ret) | ||
82 | kobject_uevent(&dev->kobj, KOBJ_ONLINE); | ||
83 | else | ||
84 | pr_debug("Can't online CPU%d.\n", cpu); | ||
85 | break; | ||
86 | default: | ||
87 | ret = -EINVAL; | ||
88 | } | ||
89 | |||
90 | cpu_hotplug_driver_unlock(); | ||
91 | |||
92 | return ret; | ||
93 | } | ||
94 | |||
95 | static int __init debug_hotplug_cpu(void) | ||
96 | { | ||
97 | _debug_hotplug_cpu(0, 0); | ||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | late_initcall_sync(debug_hotplug_cpu); | ||
102 | #endif /* CONFIG_DEBUG_HOTPLUG_CPU0 */ | ||
103 | |||
38 | int __ref arch_register_cpu(int num) | 104 | int __ref arch_register_cpu(int num) |
39 | { | 105 | { |
106 | struct cpuinfo_x86 *c = &cpu_data(num); | ||
107 | |||
108 | /* | ||
109 | * Currently CPU0 is only hotpluggable on Intel platforms. Other | ||
110 | * vendors can add hotplug support later. | ||
111 | */ | ||
112 | if (c->x86_vendor != X86_VENDOR_INTEL) | ||
113 | cpu0_hotpluggable = 0; | ||
114 | |||
40 | /* | 115 | /* |
41 | * CPU0 cannot be offlined due to several | 116 | * Two known BSP/CPU0 dependencies: Resume from suspend/hibernate |
42 | * restrictions and assumptions in kernel. This basically | 117 | * depends on BSP. PIC interrupts depend on BSP. |
43 | * doesn't add a control file, one cannot attempt to offline | ||
44 | * BSP. | ||
45 | * | 118 | * |
46 | * Also certain PCI quirks require not to enable hotplug control | 119 | * If the BSP depencies are under control, one can tell kernel to |
47 | * for all CPU's. | 120 | * enable BSP hotplug. This basically adds a control file and |
121 | * one can attempt to offline BSP. | ||
48 | */ | 122 | */ |
49 | if (num) | 123 | if (num == 0 && cpu0_hotpluggable) { |
124 | unsigned int irq; | ||
125 | /* | ||
126 | * We won't take down the boot processor on i386 if some | ||
127 | * interrupts only are able to be serviced by the BSP in PIC. | ||
128 | */ | ||
129 | for_each_active_irq(irq) { | ||
130 | if (!IO_APIC_IRQ(irq) && irq_has_action(irq)) { | ||
131 | cpu0_hotpluggable = 0; | ||
132 | break; | ||
133 | } | ||
134 | } | ||
135 | } | ||
136 | if (num || cpu0_hotpluggable) | ||
50 | per_cpu(cpu_devices, num).cpu.hotpluggable = 1; | 137 | per_cpu(cpu_devices, num).cpu.hotpluggable = 1; |
51 | 138 | ||
52 | return register_cpu(&per_cpu(cpu_devices, num).cpu, num); | 139 | return register_cpu(&per_cpu(cpu_devices, num).cpu, num); |