aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r--arch/x86/kernel/apb_timer.c29
-rw-r--r--arch/x86/kernel/apic/x2apic_cluster.c80
-rw-r--r--arch/x86/kernel/hpet.c69
-rw-r--r--arch/x86/kernel/tboot.c25
4 files changed, 82 insertions, 121 deletions
diff --git a/arch/x86/kernel/apb_timer.c b/arch/x86/kernel/apb_timer.c
index cefacbad1531..456316f6c868 100644
--- a/arch/x86/kernel/apb_timer.c
+++ b/arch/x86/kernel/apb_timer.c
@@ -215,26 +215,18 @@ void apbt_setup_secondary_clock(void)
215 * cpu timers during the offline process due to the ordering of notification. 215 * cpu timers during the offline process due to the ordering of notification.
216 * the extra interrupt is harmless. 216 * the extra interrupt is harmless.
217 */ 217 */
218static int apbt_cpuhp_notify(struct notifier_block *n, 218static int apbt_cpu_dead(unsigned int cpu)
219 unsigned long action, void *hcpu)
220{ 219{
221 unsigned long cpu = (unsigned long)hcpu;
222 struct apbt_dev *adev = &per_cpu(cpu_apbt_dev, cpu); 220 struct apbt_dev *adev = &per_cpu(cpu_apbt_dev, cpu);
223 221
224 switch (action & ~CPU_TASKS_FROZEN) { 222 dw_apb_clockevent_pause(adev->timer);
225 case CPU_DEAD: 223 if (system_state == SYSTEM_RUNNING) {
226 dw_apb_clockevent_pause(adev->timer); 224 pr_debug("skipping APBT CPU %u offline\n", cpu);
227 if (system_state == SYSTEM_RUNNING) { 225 } else {
228 pr_debug("skipping APBT CPU %lu offline\n", cpu); 226 pr_debug("APBT clockevent for cpu %u offline\n", cpu);
229 } else { 227 dw_apb_clockevent_stop(adev->timer);
230 pr_debug("APBT clockevent for cpu %lu offline\n", cpu);
231 dw_apb_clockevent_stop(adev->timer);
232 }
233 break;
234 default:
235 pr_debug("APBT notified %lu, no action\n", action);
236 } 228 }
237 return NOTIFY_OK; 229 return 0;
238} 230}
239 231
240static __init int apbt_late_init(void) 232static __init int apbt_late_init(void)
@@ -242,9 +234,8 @@ static __init int apbt_late_init(void)
242 if (intel_mid_timer_options == INTEL_MID_TIMER_LAPIC_APBT || 234 if (intel_mid_timer_options == INTEL_MID_TIMER_LAPIC_APBT ||
243 !apb_timer_block_enabled) 235 !apb_timer_block_enabled)
244 return 0; 236 return 0;
245 /* This notifier should be called after workqueue is ready */ 237 return cpuhp_setup_state(CPUHP_X86_APB_DEAD, "X86_APB_DEAD", NULL,
246 hotcpu_notifier(apbt_cpuhp_notify, -20); 238 apbt_cpu_dead);
247 return 0;
248} 239}
249fs_initcall(apbt_late_init); 240fs_initcall(apbt_late_init);
250#else 241#else
diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c
index 24170d0809ba..6368fa69d2af 100644
--- a/arch/x86/kernel/apic/x2apic_cluster.c
+++ b/arch/x86/kernel/apic/x2apic_cluster.c
@@ -152,68 +152,48 @@ static void init_x2apic_ldr(void)
152 } 152 }
153} 153}
154 154
155 /* 155/*
156 * At CPU state changes, update the x2apic cluster sibling info. 156 * At CPU state changes, update the x2apic cluster sibling info.
157 */ 157 */
158static int 158int x2apic_prepare_cpu(unsigned int cpu)
159update_clusterinfo(struct notifier_block *nfb, unsigned long action, void *hcpu)
160{ 159{
161 unsigned int this_cpu = (unsigned long)hcpu; 160 if (!zalloc_cpumask_var(&per_cpu(cpus_in_cluster, cpu), GFP_KERNEL))
162 unsigned int cpu; 161 return -ENOMEM;
163 int err = 0; 162
164 163 if (!zalloc_cpumask_var(&per_cpu(ipi_mask, cpu), GFP_KERNEL)) {
165 switch (action) { 164 free_cpumask_var(per_cpu(cpus_in_cluster, cpu));
166 case CPU_UP_PREPARE: 165 return -ENOMEM;
167 if (!zalloc_cpumask_var(&per_cpu(cpus_in_cluster, this_cpu),
168 GFP_KERNEL)) {
169 err = -ENOMEM;
170 } else if (!zalloc_cpumask_var(&per_cpu(ipi_mask, this_cpu),
171 GFP_KERNEL)) {
172 free_cpumask_var(per_cpu(cpus_in_cluster, this_cpu));
173 err = -ENOMEM;
174 }
175 break;
176 case CPU_UP_CANCELED:
177 case CPU_UP_CANCELED_FROZEN:
178 case CPU_DEAD:
179 for_each_online_cpu(cpu) {
180 if (x2apic_cluster(this_cpu) != x2apic_cluster(cpu))
181 continue;
182 cpumask_clear_cpu(this_cpu, per_cpu(cpus_in_cluster, cpu));
183 cpumask_clear_cpu(cpu, per_cpu(cpus_in_cluster, this_cpu));
184 }
185 free_cpumask_var(per_cpu(cpus_in_cluster, this_cpu));
186 free_cpumask_var(per_cpu(ipi_mask, this_cpu));
187 break;
188 } 166 }
189 167
190 return notifier_from_errno(err); 168 return 0;
191} 169}
192 170
193static struct notifier_block x2apic_cpu_notifier = { 171int x2apic_dead_cpu(unsigned int this_cpu)
194 .notifier_call = update_clusterinfo,
195};
196
197static int x2apic_init_cpu_notifier(void)
198{ 172{
199 int cpu = smp_processor_id(); 173 int cpu;
200
201 zalloc_cpumask_var(&per_cpu(cpus_in_cluster, cpu), GFP_KERNEL);
202 zalloc_cpumask_var(&per_cpu(ipi_mask, cpu), GFP_KERNEL);
203 174
204 BUG_ON(!per_cpu(cpus_in_cluster, cpu) || !per_cpu(ipi_mask, cpu)); 175 for_each_online_cpu(cpu) {
205 176 if (x2apic_cluster(this_cpu) != x2apic_cluster(cpu))
206 cpumask_set_cpu(cpu, per_cpu(cpus_in_cluster, cpu)); 177 continue;
207 register_hotcpu_notifier(&x2apic_cpu_notifier); 178 cpumask_clear_cpu(this_cpu, per_cpu(cpus_in_cluster, cpu));
208 return 1; 179 cpumask_clear_cpu(cpu, per_cpu(cpus_in_cluster, this_cpu));
180 }
181 free_cpumask_var(per_cpu(cpus_in_cluster, this_cpu));
182 free_cpumask_var(per_cpu(ipi_mask, this_cpu));
183 return 0;
209} 184}
210 185
211static int x2apic_cluster_probe(void) 186static int x2apic_cluster_probe(void)
212{ 187{
213 if (x2apic_mode) 188 int cpu = smp_processor_id();
214 return x2apic_init_cpu_notifier(); 189
215 else 190 if (!x2apic_mode)
216 return 0; 191 return 0;
192
193 cpumask_set_cpu(cpu, per_cpu(cpus_in_cluster, cpu));
194 cpuhp_setup_state(CPUHP_X2APIC_PREPARE, "X2APIC_PREPARE",
195 x2apic_prepare_cpu, x2apic_dead_cpu);
196 return 1;
217} 197}
218 198
219static const struct cpumask *x2apic_cluster_target_cpus(void) 199static const struct cpumask *x2apic_cluster_target_cpus(void)
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index f112af7aa62e..3d747070fe67 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -710,31 +710,29 @@ static void hpet_work(struct work_struct *w)
710 complete(&hpet_work->complete); 710 complete(&hpet_work->complete);
711} 711}
712 712
713static int hpet_cpuhp_notify(struct notifier_block *n, 713static int hpet_cpuhp_online(unsigned int cpu)
714 unsigned long action, void *hcpu)
715{ 714{
716 unsigned long cpu = (unsigned long)hcpu;
717 struct hpet_work_struct work; 715 struct hpet_work_struct work;
716
717 INIT_DELAYED_WORK_ONSTACK(&work.work, hpet_work);
718 init_completion(&work.complete);
719 /* FIXME: add schedule_work_on() */
720 schedule_delayed_work_on(cpu, &work.work, 0);
721 wait_for_completion(&work.complete);
722 destroy_delayed_work_on_stack(&work.work);
723 return 0;
724}
725
726static int hpet_cpuhp_dead(unsigned int cpu)
727{
718 struct hpet_dev *hdev = per_cpu(cpu_hpet_dev, cpu); 728 struct hpet_dev *hdev = per_cpu(cpu_hpet_dev, cpu);
719 729
720 switch (action & ~CPU_TASKS_FROZEN) { 730 if (!hdev)
721 case CPU_ONLINE: 731 return 0;
722 INIT_DELAYED_WORK_ONSTACK(&work.work, hpet_work); 732 free_irq(hdev->irq, hdev);
723 init_completion(&work.complete); 733 hdev->flags &= ~HPET_DEV_USED;
724 /* FIXME: add schedule_work_on() */ 734 per_cpu(cpu_hpet_dev, cpu) = NULL;
725 schedule_delayed_work_on(cpu, &work.work, 0); 735 return 0;
726 wait_for_completion(&work.complete);
727 destroy_delayed_work_on_stack(&work.work);
728 break;
729 case CPU_DEAD:
730 if (hdev) {
731 free_irq(hdev->irq, hdev);
732 hdev->flags &= ~HPET_DEV_USED;
733 per_cpu(cpu_hpet_dev, cpu) = NULL;
734 }
735 break;
736 }
737 return NOTIFY_OK;
738} 736}
739#else 737#else
740 738
@@ -750,11 +748,8 @@ static void hpet_reserve_msi_timers(struct hpet_data *hd)
750} 748}
751#endif 749#endif
752 750
753static int hpet_cpuhp_notify(struct notifier_block *n, 751#define hpet_cpuhp_online NULL
754 unsigned long action, void *hcpu) 752#define hpet_cpuhp_dead NULL
755{
756 return NOTIFY_OK;
757}
758 753
759#endif 754#endif
760 755
@@ -931,7 +926,7 @@ out_nohpet:
931 */ 926 */
932static __init int hpet_late_init(void) 927static __init int hpet_late_init(void)
933{ 928{
934 int cpu; 929 int ret;
935 930
936 if (boot_hpet_disable) 931 if (boot_hpet_disable)
937 return -ENODEV; 932 return -ENODEV;
@@ -961,16 +956,20 @@ static __init int hpet_late_init(void)
961 if (boot_cpu_has(X86_FEATURE_ARAT)) 956 if (boot_cpu_has(X86_FEATURE_ARAT))
962 return 0; 957 return 0;
963 958
964 cpu_notifier_register_begin();
965 for_each_online_cpu(cpu) {
966 hpet_cpuhp_notify(NULL, CPU_ONLINE, (void *)(long)cpu);
967 }
968
969 /* This notifier should be called after workqueue is ready */ 959 /* This notifier should be called after workqueue is ready */
970 __hotcpu_notifier(hpet_cpuhp_notify, -20); 960 ret = cpuhp_setup_state(CPUHP_AP_X86_HPET_ONLINE, "AP_X86_HPET_ONLINE",
971 cpu_notifier_register_done(); 961 hpet_cpuhp_online, NULL);
972 962 if (ret)
963 return ret;
964 ret = cpuhp_setup_state(CPUHP_X86_HPET_DEAD, "X86_HPET_DEAD", NULL,
965 hpet_cpuhp_dead);
966 if (ret)
967 goto err_cpuhp;
973 return 0; 968 return 0;
969
970err_cpuhp:
971 cpuhp_remove_state(CPUHP_AP_X86_HPET_ONLINE);
972 return ret;
974} 973}
975fs_initcall(hpet_late_init); 974fs_initcall(hpet_late_init);
976 975
diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c
index 9b0185fbe3eb..654f6c66fe45 100644
--- a/arch/x86/kernel/tboot.c
+++ b/arch/x86/kernel/tboot.c
@@ -323,25 +323,16 @@ static int tboot_wait_for_aps(int num_aps)
323 return !(atomic_read((atomic_t *)&tboot->num_in_wfs) == num_aps); 323 return !(atomic_read((atomic_t *)&tboot->num_in_wfs) == num_aps);
324} 324}
325 325
326static int tboot_cpu_callback(struct notifier_block *nfb, unsigned long action, 326static int tboot_dying_cpu(unsigned int cpu)
327 void *hcpu)
328{ 327{
329 switch (action) { 328 atomic_inc(&ap_wfs_count);
330 case CPU_DYING: 329 if (num_online_cpus() == 1) {
331 atomic_inc(&ap_wfs_count); 330 if (tboot_wait_for_aps(atomic_read(&ap_wfs_count)))
332 if (num_online_cpus() == 1) 331 return -EBUSY;
333 if (tboot_wait_for_aps(atomic_read(&ap_wfs_count)))
334 return NOTIFY_BAD;
335 break;
336 } 332 }
337 return NOTIFY_OK; 333 return 0;
338} 334}
339 335
340static struct notifier_block tboot_cpu_notifier =
341{
342 .notifier_call = tboot_cpu_callback,
343};
344
345#ifdef CONFIG_DEBUG_FS 336#ifdef CONFIG_DEBUG_FS
346 337
347#define TBOOT_LOG_UUID { 0x26, 0x25, 0x19, 0xc0, 0x30, 0x6b, 0xb4, 0x4d, \ 338#define TBOOT_LOG_UUID { 0x26, 0x25, 0x19, 0xc0, 0x30, 0x6b, 0xb4, 0x4d, \
@@ -417,8 +408,8 @@ static __init int tboot_late_init(void)
417 tboot_create_trampoline(); 408 tboot_create_trampoline();
418 409
419 atomic_set(&ap_wfs_count, 0); 410 atomic_set(&ap_wfs_count, 0);
420 register_hotcpu_notifier(&tboot_cpu_notifier); 411 cpuhp_setup_state(CPUHP_AP_X86_TBOOT_DYING, "AP_X86_TBOOT_DYING", NULL,
421 412 tboot_dying_cpu);
422#ifdef CONFIG_DEBUG_FS 413#ifdef CONFIG_DEBUG_FS
423 debugfs_create_file("tboot_log", S_IRUSR, 414 debugfs_create_file("tboot_log", S_IRUSR,
424 arch_debugfs_dir, NULL, &tboot_log_fops); 415 arch_debugfs_dir, NULL, &tboot_log_fops);