diff options
Diffstat (limited to 'arch/arm/kernel/psci_smp.c')
-rw-r--r-- | arch/arm/kernel/psci_smp.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/arch/arm/kernel/psci_smp.c b/arch/arm/kernel/psci_smp.c index 570a48cc3d64..28a1db4da704 100644 --- a/arch/arm/kernel/psci_smp.c +++ b/arch/arm/kernel/psci_smp.c | |||
@@ -16,6 +16,8 @@ | |||
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/smp.h> | 17 | #include <linux/smp.h> |
18 | #include <linux/of.h> | 18 | #include <linux/of.h> |
19 | #include <linux/delay.h> | ||
20 | #include <uapi/linux/psci.h> | ||
19 | 21 | ||
20 | #include <asm/psci.h> | 22 | #include <asm/psci.h> |
21 | #include <asm/smp_plat.h> | 23 | #include <asm/smp_plat.h> |
@@ -66,6 +68,36 @@ void __ref psci_cpu_die(unsigned int cpu) | |||
66 | /* We should never return */ | 68 | /* We should never return */ |
67 | panic("psci: cpu %d failed to shutdown\n", cpu); | 69 | panic("psci: cpu %d failed to shutdown\n", cpu); |
68 | } | 70 | } |
71 | |||
72 | int __ref psci_cpu_kill(unsigned int cpu) | ||
73 | { | ||
74 | int err, i; | ||
75 | |||
76 | if (!psci_ops.affinity_info) | ||
77 | return 1; | ||
78 | /* | ||
79 | * cpu_kill could race with cpu_die and we can | ||
80 | * potentially end up declaring this cpu undead | ||
81 | * while it is dying. So, try again a few times. | ||
82 | */ | ||
83 | |||
84 | for (i = 0; i < 10; i++) { | ||
85 | err = psci_ops.affinity_info(cpu_logical_map(cpu), 0); | ||
86 | if (err == PSCI_0_2_AFFINITY_LEVEL_OFF) { | ||
87 | pr_info("CPU%d killed.\n", cpu); | ||
88 | return 1; | ||
89 | } | ||
90 | |||
91 | msleep(10); | ||
92 | pr_info("Retrying again to check for CPU kill\n"); | ||
93 | } | ||
94 | |||
95 | pr_warn("CPU%d may not have shut down cleanly (AFFINITY_INFO reports %d)\n", | ||
96 | cpu, err); | ||
97 | /* Make platform_cpu_kill() fail. */ | ||
98 | return 0; | ||
99 | } | ||
100 | |||
69 | #endif | 101 | #endif |
70 | 102 | ||
71 | bool __init psci_smp_available(void) | 103 | bool __init psci_smp_available(void) |
@@ -78,5 +110,6 @@ struct smp_operations __initdata psci_smp_ops = { | |||
78 | .smp_boot_secondary = psci_boot_secondary, | 110 | .smp_boot_secondary = psci_boot_secondary, |
79 | #ifdef CONFIG_HOTPLUG_CPU | 111 | #ifdef CONFIG_HOTPLUG_CPU |
80 | .cpu_die = psci_cpu_die, | 112 | .cpu_die = psci_cpu_die, |
113 | .cpu_kill = psci_cpu_kill, | ||
81 | #endif | 114 | #endif |
82 | }; | 115 | }; |