Machine as follows, [ 0.000000] MIPS: machine is loongson,loongson64c-4core-ls7a If SMP if off, error as follows: 0x0: In file included from ./include/linux/gfp.h:9:0, from ./include/linux/xarray.h:14, from ./include/linux/radix-tree.h:18, from ./include/linux/fs.h:15, from ./include/linux/compat.h:17, from arch/mips/kernel/asm-offsets.c:12: ./include/linux/topology.h: In function ‘numa_node_id’: ./include/linux/topology.h:119:2: error: implicit declaration of function ‘cpu_logical_map’ [-Werror=implicit-function-declaration] return cpu_to_node(raw_smp_processor_id()); ^ In uniprocessor machines cpu_to_node(cpu) values 0. arch/mips/include/asm/mach-loongson64/topology.h -> 0x0 And then errors follows, 0x1: In file included from ./arch/mips/include/asm/mach-loongson64/topology.h:5:0, from ./arch/mips/include/asm/topology.h:11, from ./include/linux/topology.h:36, from ./include/linux/gfp.h:9, from ./include/linux/xarray.h:14, from ./include/linux/radix-tree.h:18, from ./include/linux/fs.h:15, from ./include/linux/compat.h:17, from arch/mips/kernel/asm-offsets.c:12: ./arch/mips/include/asm/smp.h:28:44: error: macro "raw_smp_processor_id" passed 1 arguments, but takes just 0 static inline int raw_smp_processor_id(void) ^ ./arch/mips/include/asm/smp.h:29:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘{’ token { ^ ./arch/mips/include/asm/smp.h:38:0: warning: "raw_smp_processor_id" redefined #define raw_smp_processor_id raw_smp_processor_id ^ In file included from ./arch/mips/include/asm/cpu-type.h:12:0, from ./arch/mips/include/asm/timex.h:19, from ./include/linux/timex.h:65, from ./include/linux/time32.h:13, from ./include/linux/time.h:73, from ./include/linux/compat.h:10, from arch/mips/kernel/asm-offsets.c:12: ./include/linux/smp.h:160:0: note: this is the location of the previous definition #define raw_smp_processor_id() 0 ^ 0x2: In file included from ./arch/mips/include/asm/mach-loongson64/topology.h:5:0, from ./arch/mips/include/asm/topology.h:11, from ./include/linux/topology.h:36, from ./include/linux/gfp.h:9, from ./include/linux/xarray.h:14, from ./include/linux/radix-tree.h:18, from ./include/linux/fs.h:15, from ./include/linux/compat.h:17, from arch/mips/kernel/asm-offsets.c:12: ./arch/mips/include/asm/smp.h:42:29: error: ‘CONFIG_MIPS_NR_CPU_NR_MAP’ undeclared here (not in a function) extern int __cpu_number_map[CONFIG_MIPS_NR_CPU_NR_MAP]; ^ 0x3: ./arch/mips/include/asm/smp.h:69:20: error: redefinition of ‘smp_send_reschedule’ static inline void smp_send_reschedule(int cpu) ^ In file included from ./arch/mips/include/asm/cpu-type.h:12:0, from ./arch/mips/include/asm/timex.h:19, from ./include/linux/timex.h:65, from ./include/linux/time32.h:13, from ./include/linux/time.h:73, from ./include/linux/compat.h:10, from arch/mips/kernel/asm-offsets.c:12: ./include/linux/smp.h:167:20: note: previous definition of ‘smp_send_reschedule’ was here static inline void smp_send_reschedule(int cpu) { } ^ In file included from ./arch/mips/include/asm/mach-loongson64/topology.h:5:0, from ./arch/mips/include/asm/topology.h:11, from ./include/linux/topology.h:36, from ./include/linux/gfp.h:9, from ./include/linux/xarray.h:14, from ./include/linux/radix-tree.h:18, from ./include/linux/fs.h:15, from ./include/linux/compat.h:17, from arch/mips/kernel/asm-offsets.c:12: ./arch/mips/include/asm/smp.h: In function ‘smp_send_reschedule’: 0x4: ./arch/mips/include/asm/smp.h:73:8: error: dereferencing pointer to incomplete type mp_ops->send_ipi_single(cpu, SMP_RESCHEDULE_YOURSELF); ^ ./arch/mips/include/asm/smp.h: In function ‘kexec_nonboot_cpu’: ./arch/mips/include/asm/smp.h:99:15: error: dereferencing pointer to incomplete type return mp_ops->kexec_nonboot_cpu(); ^ ./arch/mips/include/asm/smp.h:99:2: warning: ‘return’ with a value, in function returning void return mp_ops->kexec_nonboot_cpu(); ^ ./arch/mips/include/asm/smp.h: In function ‘kexec_nonboot_cpu_func’: ./arch/mips/include/asm/smp.h:106:15: error: dereferencing pointer to incomplete type return mp_ops->kexec_nonboot_cpu; ^ ./arch/mips/include/asm/smp.h: In function ‘arch_send_call_function_single_ipi’: ./arch/mips/include/asm/smp.h:128:8: error: dereferencing pointer to incomplete type mp_ops->send_ipi_single(cpu, SMP_CALL_FUNCTION); ^ ./arch/mips/include/asm/smp.h: In function ‘arch_send_call_function_ipi_mask’: ./arch/mips/include/asm/smp.h:135:8: error: dereferencing pointer to incomplete type mp_ops->send_ipi_mask(mask, SMP_CALL_FUNCTION); ^ For 0x2, CONFIG_MIPS_NR_CPU_NR_MAP can't depend on SMP, otherwise its ranges not include 1. arch/mips/Kconfig -> 0x2 For 0x1, 0x3, 0x4 can be fixed by checking CONFIG_SMP, arch/mips/include/asm/smp.h -> 0x1, 0x3, 0x4 After fix them, errors as follows, 0x5: mm/percpu.o: In function `setup_per_cpu_areas': (.init.text+0xa00): multiple definition of `setup_per_cpu_areas' arch/mips/mm/init.o:(.init.text+0xa8): first defined here Normally, setup_per_cpu_areas is defined at arch/mips/mm/init.c with CONFIG_HAVE_SETUP_PER_CPU_AREA. mm/percpu.c defines it with CONFIG_SMP && !CONFIG_HAVE_SETUP_PER_CPU_AREA || !CONFIG_SMP. Obviously, !CONFIG_SMP causes the multiple definition. arch/mips/mm/init.c -> 0x5 New errors as follows, 0x6: mm/page_alloc.o: In function `get_page_from_freelist': page_alloc.c:(.text+0x4734): undefined reference to `node_reclaim_distance' page_alloc.c:(.text+0x473c): undefined reference to `node_reclaim_distance' mm/page_alloc.c -> 0x6 Now, it can complie right and loongson3-llsc-check returns success. And it can start success. Origin(use SMP): $ lscpu Architecture: mips64 Byte Order: Little Endian CPU(s): 4 On-line CPU(s) list: 0-3 Thread(s) per core: 1 Core(s) per socket: 4 Socket(s): 1 NUMA node(s): 1 Model name: Loongson-3A R3 (Loongson-3A3000) @ 1450MHz CPU max MHz: 1450.0000 CPU min MHz: 725.0000 L1d cache: 64K L1i cache: 64K L2 cache: 256K L3 cache: 2048K NUMA node0 CPU(s): 0-3 Now(not use SMP): $ lscpu Architecture: mips64 Byte Order: Little Endian CPU(s): 1 On-line CPU(s) list: 0 Thread(s) per core: 1 Core(s) per socket: 1 Socket(s): 1 NUMA node(s): 1 L1d cache: 64K L1i cache: 64K L2 cache: 2048K NUMA node0 CPU(s): 0 Signed-off-by: Jinyang He <hejinyang@xxxxxxxxxxx> --- arch/mips/Kconfig | 2 +- arch/mips/include/asm/mach-loongson64/topology.h | 4 ++++ arch/mips/include/asm/smp.h | 20 ++++++++++++++++++++ arch/mips/mm/init.c | 2 +- mm/page_alloc.c | 6 +++--- 5 files changed, 29 insertions(+), 5 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index c95fa3a..c3b2864 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2876,7 +2876,7 @@ config MIPS_NR_CPU_NR_MAP_1024 config MIPS_NR_CPU_NR_MAP int - depends on SMP + default 1 if !SMP default 1024 if MIPS_NR_CPU_NR_MAP_1024 default NR_CPUS if !MIPS_NR_CPU_NR_MAP_1024 diff --git a/arch/mips/include/asm/mach-loongson64/topology.h b/arch/mips/include/asm/mach-loongson64/topology.h index 3414a1f..2157fe1 100644 --- a/arch/mips/include/asm/mach-loongson64/topology.h +++ b/arch/mips/include/asm/mach-loongson64/topology.h @@ -4,7 +4,11 @@ #ifdef CONFIG_NUMA +#ifdef CONFIG_SMP #define cpu_to_node(cpu) (cpu_logical_map(cpu) >> 2) +#else +#define cpu_to_node(cpu) 0 +#endif extern cpumask_t __node_cpumask[]; #define cpumask_of_node(node) (&__node_cpumask[node]) diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h index 5d9ff61..8ea3733 100644 --- a/arch/mips/include/asm/smp.h +++ b/arch/mips/include/asm/smp.h @@ -25,6 +25,7 @@ extern cpumask_t cpu_sibling_map[]; extern cpumask_t cpu_core_map[]; extern cpumask_t cpu_foreign_map[]; +#ifdef CONFIG_SMP static inline int raw_smp_processor_id(void) { #if defined(__VDSO__) @@ -36,6 +37,7 @@ static inline int raw_smp_processor_id(void) #endif } #define raw_smp_processor_id raw_smp_processor_id +#endif /* Map from cpu id to sequential logical cpu number. This will only not be idempotent when cpus failed to come on-line. */ @@ -66,12 +68,14 @@ extern void calculate_cpu_foreign_map(void); * it goes straight through and wastes no time serializing * anything. Worst case is that we lose a reschedule ... */ +#ifdef CONFIG_SMP static inline void smp_send_reschedule(int cpu) { extern const struct plat_smp_ops *mp_ops; /* private */ mp_ops->send_ipi_single(cpu, SMP_RESCHEDULE_YOURSELF); } +#endif #ifdef CONFIG_HOTPLUG_CPU static inline int __cpu_disable(void) @@ -92,6 +96,8 @@ extern void play_dead(void); #endif #ifdef CONFIG_KEXEC + +#ifdef CONFIG_SMP static inline void kexec_nonboot_cpu(void) { extern const struct plat_smp_ops *mp_ops; /* private */ @@ -105,6 +111,15 @@ static inline void *kexec_nonboot_cpu_func(void) return mp_ops->kexec_nonboot_cpu; } +#else /* CONFIG_SMP */ +static inline void kexec_nonboot_cpu(void) { } + +static inline void *kexec_nonboot_cpu_func(void) +{ + return NULL; +} +#endif /* CONFIG_SMP */ + #endif /* @@ -121,6 +136,7 @@ int mips_smp_ipi_allocate(const struct cpumask *mask); */ int mips_smp_ipi_free(const struct cpumask *mask); +#ifdef CONFIG_SMP static inline void arch_send_call_function_single_ipi(int cpu) { extern const struct plat_smp_ops *mp_ops; /* private */ @@ -134,5 +150,9 @@ static inline void arch_send_call_function_ipi_mask(const struct cpumask *mask) mp_ops->send_ipi_mask(mask, SMP_CALL_FUNCTION); } +#else /* CONFIG_SMP */ +static inline void arch_send_call_function_single_ipi(int cpu) { } +static inline void arch_send_call_function_ipi_mask(const struct cpumask *mask) { } +#endif /* CONFIG_SMP */ #endif /* __ASM_SMP_H */ diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 6c7bbfe..867bff2 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -513,7 +513,7 @@ void __ref free_initmem(void) free_initmem_default(POISON_FREE_INITMEM); } -#ifdef CONFIG_HAVE_SETUP_PER_CPU_AREA +#if defined(CONFIG_HAVE_SETUP_PER_CPU_AREA) && defined(CONFIG_SMP) unsigned long __per_cpu_offset[NR_CPUS] __read_mostly; EXPORT_SYMBOL(__per_cpu_offset); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 0e2bab4..45a891c 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -3635,18 +3635,18 @@ bool zone_watermark_ok_safe(struct zone *z, unsigned int order, free_pages); } -#ifdef CONFIG_NUMA +#if defined(CONFIG_NUMA) && defined(CONFIG_SMP) static bool zone_allows_reclaim(struct zone *local_zone, struct zone *zone) { return node_distance(zone_to_nid(local_zone), zone_to_nid(zone)) <= node_reclaim_distance; } -#else /* CONFIG_NUMA */ +#else /* CONFIG_NUMA && CONFIG_SMP */ static bool zone_allows_reclaim(struct zone *local_zone, struct zone *zone) { return true; } -#endif /* CONFIG_NUMA */ +#endif /* CONFIG_NUMA && CONFIG_SMP */ /* * The restriction on ZONE_DMA32 as being a suitable zone to use to avoid -- 2.1.0