1 | // SPDX-License-Identifier: GPL-2.0 |
---|---|
2 | /* |
3 | * Copyright (C) 2020 Western Digital Corporation or its affiliates. |
4 | */ |
5 | |
6 | #include <linux/kernel.h> |
7 | #include <linux/mm.h> |
8 | #include <linux/sched.h> |
9 | #include <linux/err.h> |
10 | #include <linux/irq.h> |
11 | #include <linux/cpuhotplug.h> |
12 | #include <linux/cpu.h> |
13 | #include <linux/sched/hotplug.h> |
14 | #include <asm/irq.h> |
15 | #include <asm/cpu_ops.h> |
16 | #include <asm/numa.h> |
17 | #include <asm/smp.h> |
18 | |
19 | bool cpu_has_hotplug(unsigned int cpu) |
20 | { |
21 | if (cpu_ops->cpu_stop) |
22 | return true; |
23 | |
24 | return false; |
25 | } |
26 | |
27 | /* |
28 | * __cpu_disable runs on the processor to be shutdown. |
29 | */ |
30 | int __cpu_disable(void) |
31 | { |
32 | unsigned int cpu = smp_processor_id(); |
33 | |
34 | if (!cpu_ops->cpu_stop) |
35 | return -EOPNOTSUPP; |
36 | |
37 | remove_cpu_topology(cpu); |
38 | numa_remove_cpu(cpu); |
39 | set_cpu_online(cpu, online: false); |
40 | riscv_ipi_disable(); |
41 | irq_migrate_all_off_this_cpu(); |
42 | |
43 | return 0; |
44 | } |
45 | |
46 | #ifdef CONFIG_HOTPLUG_CPU |
47 | /* |
48 | * Called on the thread which is asking for a CPU to be shutdown, if the |
49 | * CPU reported dead to the hotplug core. |
50 | */ |
51 | void arch_cpuhp_cleanup_dead_cpu(unsigned int cpu) |
52 | { |
53 | int ret = 0; |
54 | |
55 | pr_notice("CPU%u: off\n", cpu); |
56 | |
57 | /* Verify from the firmware if the cpu is really stopped*/ |
58 | if (cpu_ops->cpu_is_stopped) |
59 | ret = cpu_ops->cpu_is_stopped(cpu); |
60 | if (ret) |
61 | pr_warn("CPU%d may not have stopped: %d\n", cpu, ret); |
62 | } |
63 | |
64 | /* |
65 | * Called from the idle thread for the CPU which has been shutdown. |
66 | */ |
67 | void __noreturn arch_cpu_idle_dead(void) |
68 | { |
69 | idle_task_exit(); |
70 | |
71 | cpuhp_ap_report_dead(); |
72 | |
73 | cpu_ops->cpu_stop(); |
74 | /* It should never reach here */ |
75 | BUG(); |
76 | } |
77 | #endif |
78 |