mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-09-18 22:14:16 +00:00 
			
		
		
		
	MIPS: Cavium: Add CPU hotplugging code.
Thanks to Cavium Inc. for the code contribution and help. Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
		
							parent
							
								
									9801b321ec
								
							
						
					
					
						commit
						773cb77d0e
					
				
					 5 changed files with 365 additions and 2 deletions
				
			
		|  | @ -601,6 +601,7 @@ config CAVIUM_OCTEON_SIMULATOR | ||||||
| 	select SYS_SUPPORTS_64BIT_KERNEL | 	select SYS_SUPPORTS_64BIT_KERNEL | ||||||
| 	select SYS_SUPPORTS_BIG_ENDIAN | 	select SYS_SUPPORTS_BIG_ENDIAN | ||||||
| 	select SYS_SUPPORTS_HIGHMEM | 	select SYS_SUPPORTS_HIGHMEM | ||||||
|  | 	select SYS_SUPPORTS_HOTPLUG_CPU | ||||||
| 	select SYS_HAS_CPU_CAVIUM_OCTEON | 	select SYS_HAS_CPU_CAVIUM_OCTEON | ||||||
| 	help | 	help | ||||||
| 	  The Octeon simulator is software performance model of the Cavium | 	  The Octeon simulator is software performance model of the Cavium | ||||||
|  | @ -615,6 +616,7 @@ config CAVIUM_OCTEON_REFERENCE_BOARD | ||||||
| 	select SYS_SUPPORTS_64BIT_KERNEL | 	select SYS_SUPPORTS_64BIT_KERNEL | ||||||
| 	select SYS_SUPPORTS_BIG_ENDIAN | 	select SYS_SUPPORTS_BIG_ENDIAN | ||||||
| 	select SYS_SUPPORTS_HIGHMEM | 	select SYS_SUPPORTS_HIGHMEM | ||||||
|  | 	select SYS_SUPPORTS_HOTPLUG_CPU | ||||||
| 	select SYS_HAS_EARLY_PRINTK | 	select SYS_HAS_EARLY_PRINTK | ||||||
| 	select SYS_HAS_CPU_CAVIUM_OCTEON | 	select SYS_HAS_CPU_CAVIUM_OCTEON | ||||||
| 	select SWAP_IO_SPACE | 	select SWAP_IO_SPACE | ||||||
|  |  | ||||||
|  | @ -501,3 +501,62 @@ asmlinkage void plat_irq_dispatch(void) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | #ifdef CONFIG_HOTPLUG_CPU | ||||||
|  | static int is_irq_enabled_on_cpu(unsigned int irq, unsigned int cpu) | ||||||
|  | { | ||||||
|  |        unsigned int isset; | ||||||
|  | #ifdef CONFIG_SMP | ||||||
|  |        int coreid = cpu_logical_map(cpu); | ||||||
|  | #else | ||||||
|  | 	int coreid = cvmx_get_core_num(); | ||||||
|  | #endif | ||||||
|  | 	int bit = (irq < OCTEON_IRQ_WDOG0) ? | ||||||
|  | 		irq - OCTEON_IRQ_WORKQ0 : irq - OCTEON_IRQ_WDOG0; | ||||||
|  |        if (irq < 64) { | ||||||
|  | 		isset = (cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)) & | ||||||
|  | 			(1ull << bit)) >> bit; | ||||||
|  |        } else { | ||||||
|  | 	       isset = (cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)) & | ||||||
|  | 			(1ull << bit)) >> bit; | ||||||
|  |        } | ||||||
|  |        return isset; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void fixup_irqs(void) | ||||||
|  | { | ||||||
|  |        int irq; | ||||||
|  | 
 | ||||||
|  | 	for (irq = OCTEON_IRQ_SW0; irq <= OCTEON_IRQ_TIMER; irq++) | ||||||
|  | 		octeon_irq_core_disable_local(irq); | ||||||
|  | 
 | ||||||
|  | 	for (irq = OCTEON_IRQ_WORKQ0; irq <= OCTEON_IRQ_GPIO15; irq++) { | ||||||
|  | 		if (is_irq_enabled_on_cpu(irq, smp_processor_id())) { | ||||||
|  | 			/* ciu irq migrates to next cpu */ | ||||||
|  | 			octeon_irq_chip_ciu0.disable(irq); | ||||||
|  | 			octeon_irq_ciu0_set_affinity(irq, &cpu_online_map); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | #if 0 | ||||||
|  | 	for (irq = OCTEON_IRQ_MBOX0; irq <= OCTEON_IRQ_MBOX1; irq++) | ||||||
|  | 		octeon_irq_mailbox_mask(irq); | ||||||
|  | #endif | ||||||
|  | 	for (irq = OCTEON_IRQ_UART0; irq <= OCTEON_IRQ_BOOTDMA; irq++) { | ||||||
|  | 		if (is_irq_enabled_on_cpu(irq, smp_processor_id())) { | ||||||
|  | 			/* ciu irq migrates to next cpu */ | ||||||
|  | 			octeon_irq_chip_ciu0.disable(irq); | ||||||
|  | 			octeon_irq_ciu0_set_affinity(irq, &cpu_online_map); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for (irq = OCTEON_IRQ_UART2; irq <= OCTEON_IRQ_RESERVED135; irq++) { | ||||||
|  | 		if (is_irq_enabled_on_cpu(irq, smp_processor_id())) { | ||||||
|  | 			/* ciu irq migrates to next cpu */ | ||||||
|  | 			octeon_irq_chip_ciu1.disable(irq); | ||||||
|  | 			octeon_irq_ciu1_set_affinity(irq, &cpu_online_map); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #endif /* CONFIG_HOTPLUG_CPU */ | ||||||
|  |  | ||||||
							
								
								
									
										70
									
								
								arch/mips/cavium-octeon/octeon_boot.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								arch/mips/cavium-octeon/octeon_boot.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,70 @@ | ||||||
|  | /*
 | ||||||
|  |  * (C) Copyright 2004, 2005 Cavium Networks | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or | ||||||
|  |  * modify it under the terms of the GNU General Public License as | ||||||
|  |  * published by the Free Software Foundation; either version 2 of | ||||||
|  |  * the License, or (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  * This program is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  * GNU General Public License for more details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU General Public License | ||||||
|  |  * along with this program; if not, write to the Free Software | ||||||
|  |  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | ||||||
|  |  * MA 02111-1307 USA | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #ifndef __OCTEON_BOOT_H__ | ||||||
|  | #define __OCTEON_BOOT_H__ | ||||||
|  | 
 | ||||||
|  | #include <linux/types.h> | ||||||
|  | 
 | ||||||
|  | struct boot_init_vector { | ||||||
|  | 	uint32_t stack_addr; | ||||||
|  | 	uint32_t code_addr; | ||||||
|  | 	uint32_t app_start_func_addr; | ||||||
|  | 	uint32_t k0_val; | ||||||
|  | 	uint32_t flags; | ||||||
|  | 	uint32_t boot_info_addr; | ||||||
|  | 	uint32_t pad; | ||||||
|  | 	uint32_t pad2; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* similar to bootloader's linux_app_boot_info but without global data */ | ||||||
|  | struct linux_app_boot_info { | ||||||
|  | 	uint32_t labi_signature; | ||||||
|  | 	uint32_t start_core0_addr; | ||||||
|  | 	uint32_t avail_coremask; | ||||||
|  | 	uint32_t pci_console_active; | ||||||
|  | 	uint32_t icache_prefetch_disable; | ||||||
|  | 	uint32_t InitTLBStart_addr; | ||||||
|  | 	uint32_t start_app_addr; | ||||||
|  | 	uint32_t cur_exception_base; | ||||||
|  | 	uint32_t no_mark_private_data; | ||||||
|  | 	uint32_t compact_flash_common_base_addr; | ||||||
|  | 	uint32_t compact_flash_attribute_base_addr; | ||||||
|  | 	uint32_t led_display_base_addr; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* If not to copy a lot of bootloader's structures
 | ||||||
|  |    here is only offset of requested member */ | ||||||
|  | #define AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK    0x765c | ||||||
|  | 
 | ||||||
|  | /* hardcoded in bootloader */ | ||||||
|  | #define  LABI_ADDR_IN_BOOTLOADER                         0x700 | ||||||
|  | 
 | ||||||
|  | #define LINUX_APP_BOOT_BLOCK_NAME "linux-app-boot" | ||||||
|  | 
 | ||||||
|  | #define LABI_SIGNATURE 0xAABBCCDD | ||||||
|  | 
 | ||||||
|  | /*  from uboot-headers/octeon_mem_map.h */ | ||||||
|  | #define EXCEPTION_BASE_INCR     (4 * 1024) | ||||||
|  | 			       /* Increment size for exception base addresses (4k minimum) */ | ||||||
|  | #define EXCEPTION_BASE_BASE     0 | ||||||
|  | #define BOOTLOADER_PRIV_DATA_BASE       (EXCEPTION_BASE_BASE + 0x800) | ||||||
|  | #define BOOTLOADER_BOOT_VECTOR          (BOOTLOADER_PRIV_DATA_BASE) | ||||||
|  | 
 | ||||||
|  | #endif /* __OCTEON_BOOT_H__ */ | ||||||
|  | @ -5,6 +5,7 @@ | ||||||
|  * |  * | ||||||
|  * Copyright (C) 2004-2008 Cavium Networks |  * Copyright (C) 2004-2008 Cavium Networks | ||||||
|  */ |  */ | ||||||
|  | #include <linux/cpu.h> | ||||||
| #include <linux/init.h> | #include <linux/init.h> | ||||||
| #include <linux/delay.h> | #include <linux/delay.h> | ||||||
| #include <linux/smp.h> | #include <linux/smp.h> | ||||||
|  | @ -19,10 +20,16 @@ | ||||||
| 
 | 
 | ||||||
| #include <asm/octeon/octeon.h> | #include <asm/octeon/octeon.h> | ||||||
| 
 | 
 | ||||||
|  | #include "octeon_boot.h" | ||||||
|  | 
 | ||||||
| volatile unsigned long octeon_processor_boot = 0xff; | volatile unsigned long octeon_processor_boot = 0xff; | ||||||
| volatile unsigned long octeon_processor_sp; | volatile unsigned long octeon_processor_sp; | ||||||
| volatile unsigned long octeon_processor_gp; | volatile unsigned long octeon_processor_gp; | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_HOTPLUG_CPU | ||||||
|  | static unsigned int InitTLBStart_addr; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| static irqreturn_t mailbox_interrupt(int irq, void *dev_id) | static irqreturn_t mailbox_interrupt(int irq, void *dev_id) | ||||||
| { | { | ||||||
| 	const int coreid = cvmx_get_core_num(); | 	const int coreid = cvmx_get_core_num(); | ||||||
|  | @ -67,8 +74,28 @@ static inline void octeon_send_ipi_mask(cpumask_t mask, unsigned int action) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Detect available CPUs, populate phys_cpu_present_map |  * Detect available CPUs, populate cpu_possible_map | ||||||
|  */ |  */ | ||||||
|  | static void octeon_smp_hotplug_setup(void) | ||||||
|  | { | ||||||
|  | #ifdef CONFIG_HOTPLUG_CPU | ||||||
|  | 	uint32_t labi_signature; | ||||||
|  | 
 | ||||||
|  | 	labi_signature = | ||||||
|  | 		cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, | ||||||
|  | 					LABI_ADDR_IN_BOOTLOADER + | ||||||
|  | 					offsetof(struct linux_app_boot_info, | ||||||
|  | 						    labi_signature))); | ||||||
|  | 	if (labi_signature != LABI_SIGNATURE) | ||||||
|  | 		pr_err("The bootloader version on this board is incorrect\n"); | ||||||
|  | 	InitTLBStart_addr = | ||||||
|  | 		cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, | ||||||
|  | 				   LABI_ADDR_IN_BOOTLOADER + | ||||||
|  | 					   offsetof(struct linux_app_boot_info, | ||||||
|  | 						    InitTLBStart_addr))); | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static void octeon_smp_setup(void) | static void octeon_smp_setup(void) | ||||||
| { | { | ||||||
| 	const int coreid = cvmx_get_core_num(); | 	const int coreid = cvmx_get_core_num(); | ||||||
|  | @ -91,6 +118,9 @@ static void octeon_smp_setup(void) | ||||||
| 			cpus++; | 			cpus++; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 	cpu_present_map = cpu_possible_map; | ||||||
|  | 
 | ||||||
|  | 	octeon_smp_hotplug_setup(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -128,6 +158,17 @@ static void octeon_init_secondary(void) | ||||||
| 	const int coreid = cvmx_get_core_num(); | 	const int coreid = cvmx_get_core_num(); | ||||||
| 	union cvmx_ciu_intx_sum0 interrupt_enable; | 	union cvmx_ciu_intx_sum0 interrupt_enable; | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_HOTPLUG_CPU | ||||||
|  | 	unsigned int cur_exception_base; | ||||||
|  | 
 | ||||||
|  | 	cur_exception_base = cvmx_read64_uint32( | ||||||
|  | 		CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, | ||||||
|  | 			     LABI_ADDR_IN_BOOTLOADER + | ||||||
|  | 			     offsetof(struct linux_app_boot_info, | ||||||
|  | 				      cur_exception_base))); | ||||||
|  | 	/* cur_exception_base is incremented in bootloader after setting */ | ||||||
|  | 	write_c0_ebase((unsigned int)(cur_exception_base - EXCEPTION_BASE_INCR)); | ||||||
|  | #endif | ||||||
| 	octeon_check_cpu_bist(); | 	octeon_check_cpu_bist(); | ||||||
| 	octeon_init_cvmcount(); | 	octeon_init_cvmcount(); | ||||||
| 	/*
 | 	/*
 | ||||||
|  | @ -199,6 +240,193 @@ static void octeon_cpus_done(void) | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_HOTPLUG_CPU | ||||||
|  | 
 | ||||||
|  | /* State of each CPU. */ | ||||||
|  | DEFINE_PER_CPU(int, cpu_state); | ||||||
|  | 
 | ||||||
|  | extern void fixup_irqs(void); | ||||||
|  | 
 | ||||||
|  | static DEFINE_SPINLOCK(smp_reserve_lock); | ||||||
|  | 
 | ||||||
|  | static int octeon_cpu_disable(void) | ||||||
|  | { | ||||||
|  | 	unsigned int cpu = smp_processor_id(); | ||||||
|  | 
 | ||||||
|  | 	if (cpu == 0) | ||||||
|  | 		return -EBUSY; | ||||||
|  | 
 | ||||||
|  | 	spin_lock(&smp_reserve_lock); | ||||||
|  | 
 | ||||||
|  | 	cpu_clear(cpu, cpu_online_map); | ||||||
|  | 	cpu_clear(cpu, cpu_callin_map); | ||||||
|  | 	local_irq_disable(); | ||||||
|  | 	fixup_irqs(); | ||||||
|  | 	local_irq_enable(); | ||||||
|  | 
 | ||||||
|  | 	flush_cache_all(); | ||||||
|  | 	local_flush_tlb_all(); | ||||||
|  | 
 | ||||||
|  | 	spin_unlock(&smp_reserve_lock); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void octeon_cpu_die(unsigned int cpu) | ||||||
|  | { | ||||||
|  | 	int coreid = cpu_logical_map(cpu); | ||||||
|  | 	uint32_t avail_coremask; | ||||||
|  | 	struct cvmx_bootmem_named_block_desc *block_desc; | ||||||
|  | 
 | ||||||
|  | #ifdef CONFIG_CAVIUM_OCTEON_WATCHDOG | ||||||
|  | 	/* Disable the watchdog */ | ||||||
|  | 	cvmx_ciu_wdogx_t ciu_wdog; | ||||||
|  | 	ciu_wdog.u64 = cvmx_read_csr(CVMX_CIU_WDOGX(cpu)); | ||||||
|  | 	ciu_wdog.s.mode = 0; | ||||||
|  | 	cvmx_write_csr(CVMX_CIU_WDOGX(cpu), ciu_wdog.u64); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 	while (per_cpu(cpu_state, cpu) != CPU_DEAD) | ||||||
|  | 		cpu_relax(); | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * This is a bit complicated strategics of getting/settig available | ||||||
|  | 	 * cores mask, copied from bootloader | ||||||
|  | 	 */ | ||||||
|  | 	/* LINUX_APP_BOOT_BLOCK is initialized in bootoct binary */ | ||||||
|  | 	block_desc = cvmx_bootmem_find_named_block(LINUX_APP_BOOT_BLOCK_NAME); | ||||||
|  | 
 | ||||||
|  | 	if (!block_desc) { | ||||||
|  | 		avail_coremask = | ||||||
|  | 			cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, | ||||||
|  | 						   LABI_ADDR_IN_BOOTLOADER + | ||||||
|  | 						   offsetof | ||||||
|  | 						   (struct linux_app_boot_info, | ||||||
|  | 						    avail_coremask))); | ||||||
|  | 	} else {		       /* alternative, already initialized */ | ||||||
|  | 	       avail_coremask = | ||||||
|  | 		   cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, | ||||||
|  | 						   block_desc->base_addr + | ||||||
|  | 						  AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	avail_coremask |= 1 << coreid; | ||||||
|  | 
 | ||||||
|  | 	/* Setting avail_coremask for bootoct binary */ | ||||||
|  | 	if (!block_desc) { | ||||||
|  | 		cvmx_write64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, | ||||||
|  | 						LABI_ADDR_IN_BOOTLOADER + | ||||||
|  | 						offsetof(struct linux_app_boot_info, | ||||||
|  | 							 avail_coremask)), | ||||||
|  | 				   avail_coremask); | ||||||
|  | 	} else { | ||||||
|  | 		cvmx_write64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, | ||||||
|  | 						block_desc->base_addr + | ||||||
|  | 						AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK), | ||||||
|  | 				   avail_coremask); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	pr_info("Reset core %d. Available Coremask = %x \n", coreid, | ||||||
|  | 		avail_coremask); | ||||||
|  | 	cvmx_write_csr(CVMX_CIU_PP_RST, 1 << coreid); | ||||||
|  | 	cvmx_write_csr(CVMX_CIU_PP_RST, 0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void play_dead(void) | ||||||
|  | { | ||||||
|  | 	int coreid = cvmx_get_core_num(); | ||||||
|  | 
 | ||||||
|  | 	idle_task_exit(); | ||||||
|  | 	octeon_processor_boot = 0xff; | ||||||
|  | 	per_cpu(cpu_state, coreid) = CPU_DEAD; | ||||||
|  | 
 | ||||||
|  | 	while (1)	/* core will be reset here */ | ||||||
|  | 		; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | extern void kernel_entry(unsigned long arg1, ...); | ||||||
|  | 
 | ||||||
|  | static void start_after_reset(void) | ||||||
|  | { | ||||||
|  | 	kernel_entry(0, 0, 0);  /* set a2 = 0 for secondary core */ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int octeon_update_boot_vector(unsigned int cpu) | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | 	int coreid = cpu_logical_map(cpu); | ||||||
|  | 	unsigned int avail_coremask; | ||||||
|  | 	struct cvmx_bootmem_named_block_desc *block_desc; | ||||||
|  | 	struct boot_init_vector *boot_vect = | ||||||
|  | 		(struct boot_init_vector *) cvmx_phys_to_ptr(0x0 + | ||||||
|  | 						  BOOTLOADER_BOOT_VECTOR); | ||||||
|  | 
 | ||||||
|  | 	block_desc = cvmx_bootmem_find_named_block(LINUX_APP_BOOT_BLOCK_NAME); | ||||||
|  | 
 | ||||||
|  | 	if (!block_desc) { | ||||||
|  | 		avail_coremask = | ||||||
|  | 			cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, | ||||||
|  | 					   LABI_ADDR_IN_BOOTLOADER + | ||||||
|  | 						offsetof(struct linux_app_boot_info, | ||||||
|  | 						avail_coremask))); | ||||||
|  | 	} else {		       /* alternative, already initialized */ | ||||||
|  | 	       avail_coremask = | ||||||
|  | 		   cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, | ||||||
|  | 						   block_desc->base_addr + | ||||||
|  | 						   AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!(avail_coremask & (1 << coreid))) { | ||||||
|  | 		/* core not available, assume, that catched by simple-executive */ | ||||||
|  | 		cvmx_write_csr(CVMX_CIU_PP_RST, 1 << coreid); | ||||||
|  | 		cvmx_write_csr(CVMX_CIU_PP_RST, 0); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	boot_vect[coreid].app_start_func_addr = | ||||||
|  | 		(uint32_t) (unsigned long) start_after_reset; | ||||||
|  | 	boot_vect[coreid].code_addr = InitTLBStart_addr; | ||||||
|  | 
 | ||||||
|  | 	CVMX_SYNC; | ||||||
|  | 
 | ||||||
|  | 	cvmx_write_csr(CVMX_CIU_NMI, (1 << coreid) & avail_coremask); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int __cpuinit octeon_cpu_callback(struct notifier_block *nfb, | ||||||
|  | 	unsigned long action, void *hcpu) | ||||||
|  | { | ||||||
|  | 	unsigned int cpu = (unsigned long)hcpu; | ||||||
|  | 
 | ||||||
|  | 	switch (action) { | ||||||
|  | 	case CPU_UP_PREPARE: | ||||||
|  | 		octeon_update_boot_vector(cpu); | ||||||
|  | 		break; | ||||||
|  | 	case CPU_ONLINE: | ||||||
|  | 		pr_info("Cpu %d online\n", cpu); | ||||||
|  | 		break; | ||||||
|  | 	case CPU_DEAD: | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return NOTIFY_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static struct notifier_block __cpuinitdata octeon_cpu_notifier = { | ||||||
|  | 	.notifier_call = octeon_cpu_callback, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static int __cpuinit register_cavium_notifier(void) | ||||||
|  | { | ||||||
|  | 	register_hotcpu_notifier(&octeon_cpu_notifier); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | late_initcall(register_cavium_notifier); | ||||||
|  | 
 | ||||||
|  | #endif  /* CONFIG_HOTPLUG_CPU */ | ||||||
|  | 
 | ||||||
| struct plat_smp_ops octeon_smp_ops = { | struct plat_smp_ops octeon_smp_ops = { | ||||||
| 	.send_ipi_single	= octeon_send_ipi_single, | 	.send_ipi_single	= octeon_send_ipi_single, | ||||||
| 	.send_ipi_mask		= octeon_send_ipi_mask, | 	.send_ipi_mask		= octeon_send_ipi_mask, | ||||||
|  | @ -208,4 +436,8 @@ struct plat_smp_ops octeon_smp_ops = { | ||||||
| 	.boot_secondary		= octeon_boot_secondary, | 	.boot_secondary		= octeon_boot_secondary, | ||||||
| 	.smp_setup		= octeon_smp_setup, | 	.smp_setup		= octeon_smp_setup, | ||||||
| 	.prepare_cpus		= octeon_prepare_cpus, | 	.prepare_cpus		= octeon_prepare_cpus, | ||||||
|  | #ifdef CONFIG_HOTPLUG_CPU | ||||||
|  | 	.cpu_disable		= octeon_cpu_disable, | ||||||
|  | 	.cpu_die		= octeon_cpu_die, | ||||||
|  | #endif | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -41,7 +41,7 @@ extern int __cpu_logical_map[NR_CPUS]; | ||||||
| /* Octeon - Tell another core to flush its icache */ | /* Octeon - Tell another core to flush its icache */ | ||||||
| #define SMP_ICACHE_FLUSH	0x4 | #define SMP_ICACHE_FLUSH	0x4 | ||||||
| 
 | 
 | ||||||
| extern cpumask_t cpu_callin_map; | extern volatile cpumask_t cpu_callin_map; | ||||||
| 
 | 
 | ||||||
| extern void asmlinkage smp_bootstrap(void); | extern void asmlinkage smp_bootstrap(void); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Ralf Baechle
						Ralf Baechle