diff options
author | David Daney <ddaney@caviumnetworks.com> | 2010-07-23 13:57:51 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2010-08-05 08:26:12 -0400 |
commit | babba4f11379fb3804de802a3d0bc6b96c59d547 (patch) | |
tree | d64a578bc2999c286518158d738e7c9d909f469f | |
parent | 442f201286bfbbcd5ba5acb616914004be3e6268 (diff) |
MIPS: Octeon: HOTPLUG_CPU fixes.
* Rename camel-case InitTLBStart_addr to octeon_bootloader_entry_addr.
* Convert calls to cvmx_read64_uint32(), to simple pointer
dereferences.
* Set proper ebase.
* Don't confuse coreid and cpu numbers.
* Try to maintain consistent bootloader coremask.
* Update the signature and boot_init_vector of supported bootloaders.
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
To: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/1491/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r-- | arch/mips/cavium-octeon/octeon_boot.h | 16 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/smp.c | 125 | ||||
-rw-r--r-- | arch/mips/include/asm/octeon/octeon.h | 2 |
3 files changed, 65 insertions, 78 deletions
diff --git a/arch/mips/cavium-octeon/octeon_boot.h b/arch/mips/cavium-octeon/octeon_boot.h index 0f7f84accf9a..428864b2ba41 100644 --- a/arch/mips/cavium-octeon/octeon_boot.h +++ b/arch/mips/cavium-octeon/octeon_boot.h | |||
@@ -23,14 +23,16 @@ | |||
23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
24 | 24 | ||
25 | struct boot_init_vector { | 25 | struct boot_init_vector { |
26 | uint32_t stack_addr; | 26 | /* First stage address - in ram instead of flash */ |
27 | uint32_t code_addr; | 27 | uint64_t code_addr; |
28 | /* Setup code for application, NOT application entry point */ | ||
28 | uint32_t app_start_func_addr; | 29 | uint32_t app_start_func_addr; |
30 | /* k0 is used for global data - needs to be passed to other cores */ | ||
29 | uint32_t k0_val; | 31 | uint32_t k0_val; |
30 | uint32_t flags; | 32 | /* Address of boot info block structure */ |
31 | uint32_t boot_info_addr; | 33 | uint64_t boot_info_addr; |
34 | uint32_t flags; /* flags */ | ||
32 | uint32_t pad; | 35 | uint32_t pad; |
33 | uint32_t pad2; | ||
34 | }; | 36 | }; |
35 | 37 | ||
36 | /* similar to bootloader's linux_app_boot_info but without global data */ | 38 | /* similar to bootloader's linux_app_boot_info but without global data */ |
@@ -40,7 +42,7 @@ struct linux_app_boot_info { | |||
40 | uint32_t avail_coremask; | 42 | uint32_t avail_coremask; |
41 | uint32_t pci_console_active; | 43 | uint32_t pci_console_active; |
42 | uint32_t icache_prefetch_disable; | 44 | uint32_t icache_prefetch_disable; |
43 | uint32_t InitTLBStart_addr; | 45 | uint64_t InitTLBStart_addr; |
44 | uint32_t start_app_addr; | 46 | uint32_t start_app_addr; |
45 | uint32_t cur_exception_base; | 47 | uint32_t cur_exception_base; |
46 | uint32_t no_mark_private_data; | 48 | uint32_t no_mark_private_data; |
@@ -58,7 +60,7 @@ struct linux_app_boot_info { | |||
58 | 60 | ||
59 | #define LINUX_APP_BOOT_BLOCK_NAME "linux-app-boot" | 61 | #define LINUX_APP_BOOT_BLOCK_NAME "linux-app-boot" |
60 | 62 | ||
61 | #define LABI_SIGNATURE 0xAABBCCDD | 63 | #define LABI_SIGNATURE 0xAABBCC01 |
62 | 64 | ||
63 | /* from uboot-headers/octeon_mem_map.h */ | 65 | /* from uboot-headers/octeon_mem_map.h */ |
64 | #define EXCEPTION_BASE_INCR (4 * 1024) | 66 | #define EXCEPTION_BASE_INCR (4 * 1024) |
diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index ceb76496e6ad..391cefe556b3 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c | |||
@@ -27,7 +27,8 @@ volatile unsigned long octeon_processor_sp; | |||
27 | volatile unsigned long octeon_processor_gp; | 27 | volatile unsigned long octeon_processor_gp; |
28 | 28 | ||
29 | #ifdef CONFIG_HOTPLUG_CPU | 29 | #ifdef CONFIG_HOTPLUG_CPU |
30 | static unsigned int InitTLBStart_addr; | 30 | uint64_t octeon_bootloader_entry_addr; |
31 | EXPORT_SYMBOL(octeon_bootloader_entry_addr); | ||
31 | #endif | 32 | #endif |
32 | 33 | ||
33 | static irqreturn_t mailbox_interrupt(int irq, void *dev_id) | 34 | static irqreturn_t mailbox_interrupt(int irq, void *dev_id) |
@@ -80,20 +81,13 @@ static inline void octeon_send_ipi_mask(const struct cpumask *mask, | |||
80 | static void octeon_smp_hotplug_setup(void) | 81 | static void octeon_smp_hotplug_setup(void) |
81 | { | 82 | { |
82 | #ifdef CONFIG_HOTPLUG_CPU | 83 | #ifdef CONFIG_HOTPLUG_CPU |
83 | uint32_t labi_signature; | 84 | struct linux_app_boot_info *labi; |
84 | 85 | ||
85 | labi_signature = | 86 | labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER); |
86 | cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, | 87 | if (labi->labi_signature != LABI_SIGNATURE) |
87 | LABI_ADDR_IN_BOOTLOADER + | 88 | panic("The bootloader version on this board is incorrect."); |
88 | offsetof(struct linux_app_boot_info, | 89 | |
89 | labi_signature))); | 90 | octeon_bootloader_entry_addr = labi->InitTLBStart_addr; |
90 | if (labi_signature != LABI_SIGNATURE) | ||
91 | pr_err("The bootloader version on this board is incorrect\n"); | ||
92 | InitTLBStart_addr = | ||
93 | cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, | ||
94 | LABI_ADDR_IN_BOOTLOADER + | ||
95 | offsetof(struct linux_app_boot_info, | ||
96 | InitTLBStart_addr))); | ||
97 | #endif | 91 | #endif |
98 | } | 92 | } |
99 | 93 | ||
@@ -181,18 +175,21 @@ static void octeon_init_secondary(void) | |||
181 | { | 175 | { |
182 | const int coreid = cvmx_get_core_num(); | 176 | const int coreid = cvmx_get_core_num(); |
183 | union cvmx_ciu_intx_sum0 interrupt_enable; | 177 | union cvmx_ciu_intx_sum0 interrupt_enable; |
178 | unsigned int sr; | ||
184 | 179 | ||
185 | #ifdef CONFIG_HOTPLUG_CPU | 180 | #ifdef CONFIG_HOTPLUG_CPU |
186 | unsigned int cur_exception_base; | 181 | struct linux_app_boot_info *labi; |
187 | 182 | ||
188 | cur_exception_base = cvmx_read64_uint32( | 183 | labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER); |
189 | CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, | 184 | |
190 | LABI_ADDR_IN_BOOTLOADER + | 185 | if (labi->labi_signature != LABI_SIGNATURE) |
191 | offsetof(struct linux_app_boot_info, | 186 | panic("The bootloader version on this board is incorrect."); |
192 | cur_exception_base))); | ||
193 | /* cur_exception_base is incremented in bootloader after setting */ | ||
194 | write_c0_ebase((unsigned int)(cur_exception_base - EXCEPTION_BASE_INCR)); | ||
195 | #endif | 187 | #endif |
188 | |||
189 | sr = set_c0_status(ST0_BEV); | ||
190 | write_c0_ebase((u32)ebase); | ||
191 | write_c0_status(sr); | ||
192 | |||
196 | octeon_check_cpu_bist(); | 193 | octeon_check_cpu_bist(); |
197 | octeon_init_cvmcount(); | 194 | octeon_init_cvmcount(); |
198 | /* | 195 | /* |
@@ -299,8 +296,8 @@ static int octeon_cpu_disable(void) | |||
299 | static void octeon_cpu_die(unsigned int cpu) | 296 | static void octeon_cpu_die(unsigned int cpu) |
300 | { | 297 | { |
301 | int coreid = cpu_logical_map(cpu); | 298 | int coreid = cpu_logical_map(cpu); |
302 | uint32_t avail_coremask; | 299 | uint32_t mask, new_mask; |
303 | struct cvmx_bootmem_named_block_desc *block_desc; | 300 | const struct cvmx_bootmem_named_block_desc *block_desc; |
304 | 301 | ||
305 | while (per_cpu(cpu_state, cpu) != CPU_DEAD) | 302 | while (per_cpu(cpu_state, cpu) != CPU_DEAD) |
306 | cpu_relax(); | 303 | cpu_relax(); |
@@ -309,52 +306,40 @@ static void octeon_cpu_die(unsigned int cpu) | |||
309 | * This is a bit complicated strategics of getting/settig available | 306 | * This is a bit complicated strategics of getting/settig available |
310 | * cores mask, copied from bootloader | 307 | * cores mask, copied from bootloader |
311 | */ | 308 | */ |
309 | |||
310 | mask = 1 << coreid; | ||
312 | /* LINUX_APP_BOOT_BLOCK is initialized in bootoct binary */ | 311 | /* LINUX_APP_BOOT_BLOCK is initialized in bootoct binary */ |
313 | block_desc = cvmx_bootmem_find_named_block(LINUX_APP_BOOT_BLOCK_NAME); | 312 | block_desc = cvmx_bootmem_find_named_block(LINUX_APP_BOOT_BLOCK_NAME); |
314 | 313 | ||
315 | if (!block_desc) { | 314 | if (!block_desc) { |
316 | avail_coremask = | 315 | struct linux_app_boot_info *labi; |
317 | cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, | ||
318 | LABI_ADDR_IN_BOOTLOADER + | ||
319 | offsetof | ||
320 | (struct linux_app_boot_info, | ||
321 | avail_coremask))); | ||
322 | } else { /* alternative, already initialized */ | ||
323 | avail_coremask = | ||
324 | cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, | ||
325 | block_desc->base_addr + | ||
326 | AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK)); | ||
327 | } | ||
328 | 316 | ||
329 | avail_coremask |= 1 << coreid; | 317 | labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER); |
330 | 318 | ||
331 | /* Setting avail_coremask for bootoct binary */ | 319 | labi->avail_coremask |= mask; |
332 | if (!block_desc) { | 320 | new_mask = labi->avail_coremask; |
333 | cvmx_write64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, | 321 | } else { /* alternative, already initialized */ |
334 | LABI_ADDR_IN_BOOTLOADER + | 322 | uint32_t *p = (uint32_t *)PHYS_TO_XKSEG_CACHED(block_desc->base_addr + |
335 | offsetof(struct linux_app_boot_info, | 323 | AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK); |
336 | avail_coremask)), | 324 | *p |= mask; |
337 | avail_coremask); | 325 | new_mask = *p; |
338 | } else { | ||
339 | cvmx_write64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, | ||
340 | block_desc->base_addr + | ||
341 | AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK), | ||
342 | avail_coremask); | ||
343 | } | 326 | } |
344 | 327 | ||
345 | pr_info("Reset core %d. Available Coremask = %x\n", coreid, | 328 | pr_info("Reset core %d. Available Coremask = 0x%x \n", coreid, new_mask); |
346 | avail_coremask); | 329 | mb(); |
347 | cvmx_write_csr(CVMX_CIU_PP_RST, 1 << coreid); | 330 | cvmx_write_csr(CVMX_CIU_PP_RST, 1 << coreid); |
348 | cvmx_write_csr(CVMX_CIU_PP_RST, 0); | 331 | cvmx_write_csr(CVMX_CIU_PP_RST, 0); |
349 | } | 332 | } |
350 | 333 | ||
351 | void play_dead(void) | 334 | void play_dead(void) |
352 | { | 335 | { |
353 | int coreid = cvmx_get_core_num(); | 336 | int cpu = cpu_number_map(cvmx_get_core_num()); |
354 | 337 | ||
355 | idle_task_exit(); | 338 | idle_task_exit(); |
356 | octeon_processor_boot = 0xff; | 339 | octeon_processor_boot = 0xff; |
357 | per_cpu(cpu_state, coreid) = CPU_DEAD; | 340 | per_cpu(cpu_state, cpu) = CPU_DEAD; |
341 | |||
342 | mb(); | ||
358 | 343 | ||
359 | while (1) /* core will be reset here */ | 344 | while (1) /* core will be reset here */ |
360 | ; | 345 | ; |
@@ -367,29 +352,27 @@ static void start_after_reset(void) | |||
367 | kernel_entry(0, 0, 0); /* set a2 = 0 for secondary core */ | 352 | kernel_entry(0, 0, 0); /* set a2 = 0 for secondary core */ |
368 | } | 353 | } |
369 | 354 | ||
370 | int octeon_update_boot_vector(unsigned int cpu) | 355 | static int octeon_update_boot_vector(unsigned int cpu) |
371 | { | 356 | { |
372 | 357 | ||
373 | int coreid = cpu_logical_map(cpu); | 358 | int coreid = cpu_logical_map(cpu); |
374 | unsigned int avail_coremask; | 359 | uint32_t avail_coremask; |
375 | struct cvmx_bootmem_named_block_desc *block_desc; | 360 | const struct cvmx_bootmem_named_block_desc *block_desc; |
376 | struct boot_init_vector *boot_vect = | 361 | struct boot_init_vector *boot_vect = |
377 | (struct boot_init_vector *) cvmx_phys_to_ptr(0x0 + | 362 | (struct boot_init_vector *)PHYS_TO_XKSEG_CACHED(BOOTLOADER_BOOT_VECTOR); |
378 | BOOTLOADER_BOOT_VECTOR); | ||
379 | 363 | ||
380 | block_desc = cvmx_bootmem_find_named_block(LINUX_APP_BOOT_BLOCK_NAME); | 364 | block_desc = cvmx_bootmem_find_named_block(LINUX_APP_BOOT_BLOCK_NAME); |
381 | 365 | ||
382 | if (!block_desc) { | 366 | if (!block_desc) { |
383 | avail_coremask = | 367 | struct linux_app_boot_info *labi; |
384 | cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, | 368 | |
385 | LABI_ADDR_IN_BOOTLOADER + | 369 | labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER); |
386 | offsetof(struct linux_app_boot_info, | 370 | |
387 | avail_coremask))); | 371 | avail_coremask = labi->avail_coremask; |
372 | labi->avail_coremask &= ~(1 << coreid); | ||
388 | } else { /* alternative, already initialized */ | 373 | } else { /* alternative, already initialized */ |
389 | avail_coremask = | 374 | avail_coremask = *(uint32_t *)PHYS_TO_XKSEG_CACHED( |
390 | cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, | 375 | block_desc->base_addr + AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK); |
391 | block_desc->base_addr + | ||
392 | AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK)); | ||
393 | } | 376 | } |
394 | 377 | ||
395 | if (!(avail_coremask & (1 << coreid))) { | 378 | if (!(avail_coremask & (1 << coreid))) { |
@@ -400,9 +383,9 @@ int octeon_update_boot_vector(unsigned int cpu) | |||
400 | 383 | ||
401 | boot_vect[coreid].app_start_func_addr = | 384 | boot_vect[coreid].app_start_func_addr = |
402 | (uint32_t) (unsigned long) start_after_reset; | 385 | (uint32_t) (unsigned long) start_after_reset; |
403 | boot_vect[coreid].code_addr = InitTLBStart_addr; | 386 | boot_vect[coreid].code_addr = octeon_bootloader_entry_addr; |
404 | 387 | ||
405 | CVMX_SYNC; | 388 | mb(); |
406 | 389 | ||
407 | cvmx_write_csr(CVMX_CIU_NMI, (1 << coreid) & avail_coremask); | 390 | cvmx_write_csr(CVMX_CIU_NMI, (1 << coreid) & avail_coremask); |
408 | 391 | ||
diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h index ca6214b5ccb9..c29debe7a8ad 100644 --- a/arch/mips/include/asm/octeon/octeon.h +++ b/arch/mips/include/asm/octeon/octeon.h | |||
@@ -253,4 +253,6 @@ static inline uint32_t octeon_npi_read32(uint64_t address) | |||
253 | 253 | ||
254 | extern struct cvmx_bootinfo *octeon_bootinfo; | 254 | extern struct cvmx_bootinfo *octeon_bootinfo; |
255 | 255 | ||
256 | extern uint64_t octeon_bootloader_entry_addr; | ||
257 | |||
256 | #endif /* __ASM_OCTEON_OCTEON_H */ | 258 | #endif /* __ASM_OCTEON_OCTEON_H */ |