|
7 | 7 |
|
8 | 8 | #include <linux/init.h> |
9 | 9 | #include <linux/mm.h> |
| 10 | +#include <linux/sched/task_stack.h> |
10 | 11 | #include <asm/cpu_ops.h> |
| 12 | +#include <asm/cpu_ops_sbi.h> |
11 | 13 | #include <asm/sbi.h> |
12 | 14 | #include <asm/smp.h> |
13 | 15 |
|
14 | 16 | extern char secondary_start_sbi[]; |
15 | 17 | const struct cpu_operations cpu_ops_sbi; |
16 | 18 |
|
| 19 | +/* |
| 20 | + * Ordered booting via HSM brings one cpu at a time. However, cpu hotplug can |
| 21 | + * be invoked from multiple threads in parallel. Define a per cpu data |
| 22 | + * to handle that. |
| 23 | + */ |
| 24 | +DEFINE_PER_CPU(struct sbi_hart_boot_data, boot_data); |
| 25 | + |
17 | 26 | static int sbi_hsm_hart_start(unsigned long hartid, unsigned long saddr, |
18 | 27 | unsigned long priv) |
19 | 28 | { |
@@ -55,14 +64,19 @@ static int sbi_hsm_hart_get_status(unsigned long hartid) |
55 | 64 |
|
56 | 65 | static int sbi_cpu_start(unsigned int cpuid, struct task_struct *tidle) |
57 | 66 | { |
58 | | - int rc; |
59 | 67 | unsigned long boot_addr = __pa_symbol(secondary_start_sbi); |
60 | 68 | int hartid = cpuid_to_hartid_map(cpuid); |
61 | | - |
62 | | - cpu_update_secondary_bootdata(cpuid, tidle); |
63 | | - rc = sbi_hsm_hart_start(hartid, boot_addr, 0); |
64 | | - |
65 | | - return rc; |
| 69 | + unsigned long hsm_data; |
| 70 | + struct sbi_hart_boot_data *bdata = &per_cpu(boot_data, cpuid); |
| 71 | + |
| 72 | + /* Make sure tidle is updated */ |
| 73 | + smp_mb(); |
| 74 | + bdata->task_ptr = tidle; |
| 75 | + bdata->stack_ptr = task_stack_page(tidle) + THREAD_SIZE; |
| 76 | + /* Make sure boot data is updated */ |
| 77 | + smp_mb(); |
| 78 | + hsm_data = __pa(bdata); |
| 79 | + return sbi_hsm_hart_start(hartid, boot_addr, hsm_data); |
66 | 80 | } |
67 | 81 |
|
68 | 82 | static int sbi_cpu_prepare(unsigned int cpuid) |
|
0 commit comments