146859ac8SHuacai Chen /* SPDX-License-Identifier: GPL-2.0 */ 246859ac8SHuacai Chen /* 346859ac8SHuacai Chen * Author: Huacai Chen <chenhuacai@loongson.cn> 446859ac8SHuacai Chen * Copyright (C) 2020-2022 Loongson Technology Corporation Limited 546859ac8SHuacai Chen */ 646859ac8SHuacai Chen #ifndef __ASM_SMP_H 746859ac8SHuacai Chen #define __ASM_SMP_H 846859ac8SHuacai Chen 946859ac8SHuacai Chen #ifdef CONFIG_SMP 1046859ac8SHuacai Chen 1146859ac8SHuacai Chen #include <linux/atomic.h> 1246859ac8SHuacai Chen #include <linux/bitops.h> 1346859ac8SHuacai Chen #include <linux/linkage.h> 1446859ac8SHuacai Chen #include <linux/threads.h> 15255b4658SHuacai Chen #include <linux/cpumask.h> 16255b4658SHuacai Chen 17255b4658SHuacai Chen struct smp_ops { 18255b4658SHuacai Chen void (*init_ipi)(void); 19255b4658SHuacai Chen void (*send_ipi_single)(int cpu, unsigned int action); 20255b4658SHuacai Chen void (*send_ipi_mask)(const struct cpumask *mask, unsigned int action); 21255b4658SHuacai Chen }; 22c56ab8e8SHuacai Chen extern struct smp_ops mp_ops; 23c56ab8e8SHuacai Chen 24c56ab8e8SHuacai Chen extern int smp_num_siblings; 25c56ab8e8SHuacai Chen extern int num_processors; 26c56ab8e8SHuacai Chen extern int disabled_cpus; 27c56ab8e8SHuacai Chen extern cpumask_t cpu_sibling_map[]; 28c56ab8e8SHuacai Chen extern cpumask_t cpu_llc_shared_map[]; 2946859ac8SHuacai Chen extern cpumask_t cpu_core_map[]; 30c56ab8e8SHuacai Chen extern cpumask_t cpu_foreign_map[]; 31c56ab8e8SHuacai Chen 3246859ac8SHuacai Chen void loongson_smp_setup(void); 3346859ac8SHuacai Chen void loongson_prepare_cpus(unsigned int max_cpus); 3446859ac8SHuacai Chen void loongson_boot_secondary(int cpu, struct task_struct *idle); 3546859ac8SHuacai Chen void loongson_init_secondary(void); 36c56ab8e8SHuacai Chen void loongson_smp_finish(void); 3746859ac8SHuacai Chen #ifdef CONFIG_HOTPLUG_CPU 3846859ac8SHuacai Chen int loongson_cpu_disable(void); 3946859ac8SHuacai Chen void loongson_cpu_die(unsigned int cpu); 4046859ac8SHuacai Chen #endif 4146859ac8SHuacai Chen plat_smp_setup(void)4246859ac8SHuacai Chenstatic inline void __init plat_smp_setup(void) 4346859ac8SHuacai Chen { 4446859ac8SHuacai Chen loongson_smp_setup(); 4546859ac8SHuacai Chen } 4646859ac8SHuacai Chen raw_smp_processor_id(void)4746859ac8SHuacai Chenstatic inline int raw_smp_processor_id(void) 4846859ac8SHuacai Chen { 4946859ac8SHuacai Chen #if defined(__VDSO__) 5046859ac8SHuacai Chen extern int vdso_smp_processor_id(void) 5146859ac8SHuacai Chen __compiletime_error("VDSO should not call smp_processor_id()"); 5246859ac8SHuacai Chen return vdso_smp_processor_id(); 5346859ac8SHuacai Chen #else 5446859ac8SHuacai Chen return current_thread_info()->cpu; 5546859ac8SHuacai Chen #endif 5646859ac8SHuacai Chen } 5746859ac8SHuacai Chen #define raw_smp_processor_id raw_smp_processor_id 5846859ac8SHuacai Chen 5946859ac8SHuacai Chen /* Map from cpu id to sequential logical cpu number. This will only 6046859ac8SHuacai Chen * not be idempotent when cpus failed to come on-line. */ 6146859ac8SHuacai Chen extern int __cpu_number_map[NR_CPUS]; 6246859ac8SHuacai Chen #define cpu_number_map(cpu) __cpu_number_map[cpu] 6346859ac8SHuacai Chen 6446859ac8SHuacai Chen /* The reverse map from sequential logical cpu number to cpu id. */ 6546859ac8SHuacai Chen extern int __cpu_logical_map[NR_CPUS]; 6646859ac8SHuacai Chen #define cpu_logical_map(cpu) __cpu_logical_map[cpu] 6746859ac8SHuacai Chen 6846859ac8SHuacai Chen #define cpu_physical_id(cpu) cpu_logical_map(cpu) 6946859ac8SHuacai Chen 7046859ac8SHuacai Chen #define ACTION_BOOT_CPU 0 7146859ac8SHuacai Chen #define ACTION_RESCHEDULE 1 7246859ac8SHuacai Chen #define ACTION_CALL_FUNCTION 2 73*c718a0baSBibo Mao #define ACTION_IRQ_WORK 3 7446859ac8SHuacai Chen #define ACTION_CLEAR_VECTOR 4 7546859ac8SHuacai Chen #define SMP_BOOT_CPU BIT(ACTION_BOOT_CPU) 7646859ac8SHuacai Chen #define SMP_RESCHEDULE BIT(ACTION_RESCHEDULE) 7746859ac8SHuacai Chen #define SMP_CALL_FUNCTION BIT(ACTION_CALL_FUNCTION) 7846859ac8SHuacai Chen #define SMP_IRQ_WORK BIT(ACTION_IRQ_WORK) 7946859ac8SHuacai Chen #define SMP_CLEAR_VECTOR BIT(ACTION_CLEAR_VECTOR) 8046859ac8SHuacai Chen 8146859ac8SHuacai Chen struct seq_file; 8246859ac8SHuacai Chen 8346859ac8SHuacai Chen struct secondary_data { 84c56ab8e8SHuacai Chen unsigned long stack; 8546859ac8SHuacai Chen unsigned long thread_info; 8646859ac8SHuacai Chen }; 8746859ac8SHuacai Chen extern struct secondary_data cpuboot_data; 8846859ac8SHuacai Chen 89c56ab8e8SHuacai Chen extern asmlinkage void smpboot_entry(void); 9046859ac8SHuacai Chen extern asmlinkage void start_secondary(void); 9146859ac8SHuacai Chen 9246859ac8SHuacai Chen extern void calculate_cpu_foreign_map(void); 9346859ac8SHuacai Chen 9446859ac8SHuacai Chen /* 95c56ab8e8SHuacai Chen * Generate IPI list text 9646859ac8SHuacai Chen */ 9746859ac8SHuacai Chen extern void show_ipi_list(struct seq_file *p, int prec); 9846859ac8SHuacai Chen arch_send_call_function_single_ipi(int cpu)9946859ac8SHuacai Chenstatic inline void arch_send_call_function_single_ipi(int cpu) 100c56ab8e8SHuacai Chen { 10146859ac8SHuacai Chen mp_ops.send_ipi_single(cpu, ACTION_CALL_FUNCTION); 10246859ac8SHuacai Chen } 10346859ac8SHuacai Chen arch_send_call_function_ipi_mask(const struct cpumask * mask)10446859ac8SHuacai Chenstatic inline void arch_send_call_function_ipi_mask(const struct cpumask *mask) 105 { 106 mp_ops.send_ipi_mask(mask, ACTION_CALL_FUNCTION); 107 } 108 109 #ifdef CONFIG_HOTPLUG_CPU __cpu_disable(void)110static inline int __cpu_disable(void) 111 { 112 return loongson_cpu_disable(); 113 } 114 __cpu_die(unsigned int cpu)115static inline void __cpu_die(unsigned int cpu) 116 { 117 loongson_cpu_die(cpu); 118 } 119 #endif 120 121 #else /* !CONFIG_SMP */ 122 #define cpu_logical_map(cpu) 0 123 #endif /* CONFIG_SMP */ 124 125 #endif /* __ASM_SMP_H */ 126