diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2016-07-13 13:16:30 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-07-14 03:34:44 -0400 |
commit | 48d7f6c715782a6f6d4a5535f1233b764ce6b6f2 (patch) | |
tree | e0281b00249bcce4635169fe5597d10645c3bf61 | |
parent | 7ee681b25284782ecf380bf5ccf55f13c52fd0ce (diff) |
x86/hpet: Convert to hotplug state machine
Install the callbacks via the state machine and let the core invoke
the callbacks on the already online CPUs.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@suse.de>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Jan Beulich <JBeulich@suse.com>
Cc: Jiang Liu <jiang.liu@linux.intel.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Cc: rt@linutronix.de
Link: http://lkml.kernel.org/r/20160713153335.279718463@linutronix.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | arch/x86/kernel/hpet.c | 69 | ||||
-rw-r--r-- | include/linux/cpuhotplug.h | 2 |
2 files changed, 36 insertions, 35 deletions
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 | ||
713 | static int hpet_cpuhp_notify(struct notifier_block *n, | 713 | static 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 | |||
726 | static 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 | ||
753 | static 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 | */ |
932 | static __init int hpet_late_init(void) | 927 | static __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 | |||
970 | err_cpuhp: | ||
971 | cpuhp_remove_state(CPUHP_AP_X86_HPET_ONLINE); | ||
972 | return ret; | ||
974 | } | 973 | } |
975 | fs_initcall(hpet_late_init); | 974 | fs_initcall(hpet_late_init); |
976 | 975 | ||
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index 60557a9e783d..7449081ff412 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h | |||
@@ -12,6 +12,7 @@ enum cpuhp_state { | |||
12 | CPUHP_PERF_BFIN, | 12 | CPUHP_PERF_BFIN, |
13 | CPUHP_PERF_POWER, | 13 | CPUHP_PERF_POWER, |
14 | CPUHP_PERF_SUPERH, | 14 | CPUHP_PERF_SUPERH, |
15 | CPUHP_X86_HPET_DEAD, | ||
15 | CPUHP_WORKQUEUE_PREP, | 16 | CPUHP_WORKQUEUE_PREP, |
16 | CPUHP_NOTIFY_PREPARE, | 17 | CPUHP_NOTIFY_PREPARE, |
17 | CPUHP_BRINGUP_CPU, | 18 | CPUHP_BRINGUP_CPU, |
@@ -54,6 +55,7 @@ enum cpuhp_state { | |||
54 | CPUHP_AP_NOTIFY_ONLINE, | 55 | CPUHP_AP_NOTIFY_ONLINE, |
55 | CPUHP_AP_ONLINE_DYN, | 56 | CPUHP_AP_ONLINE_DYN, |
56 | CPUHP_AP_ONLINE_DYN_END = CPUHP_AP_ONLINE_DYN + 30, | 57 | CPUHP_AP_ONLINE_DYN_END = CPUHP_AP_ONLINE_DYN + 30, |
58 | CPUHP_AP_X86_HPET_ONLINE, | ||
57 | CPUHP_AP_ACTIVE, | 59 | CPUHP_AP_ACTIVE, |
58 | CPUHP_ONLINE, | 60 | CPUHP_ONLINE, |
59 | }; | 61 | }; |