diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/mips/Kconfig | 14 | ||||
-rw-r--r-- | arch/mips/kernel/proc.c | 1 | ||||
-rw-r--r-- | arch/mips/kernel/smp-mt.c | 6 | ||||
-rw-r--r-- | arch/mips/kernel/smp.c | 30 |
4 files changed, 50 insertions, 1 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 11bc17ce0eb..d5a89f3fdfd 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1442,6 +1442,7 @@ config MIPS_MT_SMP select MIPS_MT select NR_CPUS_DEFAULT_2 select SMP + select SYS_SUPPORTS_SCHED_SMT if SMP select SYS_SUPPORTS_SMP help This is a kernel model which is also known a VSMP or lately @@ -1468,6 +1469,19 @@ endchoice config MIPS_MT bool +config SCHED_SMT + bool "SMT (multithreading) scheduler support" + depends on SYS_SUPPORTS_SCHED_SMT + default n + help + SMT scheduler support improves the CPU scheduler's decision making + when dealing with MIPS MT enabled cores at a cost of slightly + increased overhead in some places. If unsure say N here. + +config SYS_SUPPORTS_SCHED_SMT + bool + + config SYS_SUPPORTS_MULTITHREADING bool diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c index 6e6e947cce1..34dd22838fd 100644 --- a/arch/mips/kernel/proc.c +++ b/arch/mips/kernel/proc.c @@ -62,6 +62,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) ); seq_printf(m, "shadow register sets\t: %d\n", cpu_data[n].srsets); + seq_printf(m, "core\t\t\t: %d\n", cpu_data[n].core); sprintf(fmt, "VCE%%c exceptions\t\t: %s\n", cpu_has_vce ? "%u" : "not available"); diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c index 94e210cc6cb..2ab0b7eeaa7 100644 --- a/arch/mips/kernel/smp-mt.c +++ b/arch/mips/kernel/smp-mt.c @@ -22,6 +22,7 @@ #include <linux/cpumask.h> #include <linux/interrupt.h> #include <linux/compiler.h> +#include <linux/smp.h> #include <asm/atomic.h> #include <asm/cacheflush.h> @@ -30,7 +31,6 @@ #include <asm/system.h> #include <asm/hardirq.h> #include <asm/mmu_context.h> -#include <asm/smp.h> #include <asm/time.h> #include <asm/mipsregs.h> #include <asm/mipsmtregs.h> @@ -223,6 +223,7 @@ static void __init smp_tc_init(unsigned int tc, unsigned int mvpconf0) void __init plat_smp_setup(void) { unsigned int mvpconf0, ntc, tc, ncpu = 0; + unsigned int nvpe; #ifdef CONFIG_MIPS_MT_FPAFF /* If we have an FPU, enroll ourselves in the FPU-full mask */ @@ -242,6 +243,9 @@ void __init plat_smp_setup(void) mvpconf0 = read_c0_mvpconf0(); ntc = (mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT; + nvpe = ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1; + smp_num_siblings = nvpe; + /* we'll always have more TC's than VPE's, so loop setting everything to a sensible state */ for (tc = 0; tc <= ntc; tc++) { diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 63989e9df4f..335be9bcf0d 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -56,6 +56,34 @@ EXPORT_SYMBOL(cpu_online_map); extern void __init calibrate_delay(void); extern void cpu_idle(void); +/* Number of TCs (or siblings in Intel speak) per CPU core */ +int smp_num_siblings = 1; +EXPORT_SYMBOL(smp_num_siblings); + +/* representing the TCs (or siblings in Intel speak) of each logical CPU */ +cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; +EXPORT_SYMBOL(cpu_sibling_map); + +/* representing cpus for which sibling maps can be computed */ +static cpumask_t cpu_sibling_setup_map; + +static inline void set_cpu_sibling_map(int cpu) +{ + int i; + + cpu_set(cpu, cpu_sibling_setup_map); + + if (smp_num_siblings > 1) { + for_each_cpu_mask(i, cpu_sibling_setup_map) { + if (cpu_data[cpu].core == cpu_data[i].core) { + cpu_set(i, cpu_sibling_map[cpu]); + cpu_set(cpu, cpu_sibling_map[i]); + } + } + } else + cpu_set(cpu, cpu_sibling_map[cpu]); +} + /* * First C code run on the secondary CPUs after being started up by * the master. @@ -85,6 +113,7 @@ asmlinkage __cpuinit void start_secondary(void) cpu_data[cpu].udelay_val = loops_per_jiffy; prom_smp_finish(); + set_cpu_sibling_map(cpu); cpu_set(cpu, cpu_callin_map); @@ -258,6 +287,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) init_new_context(current, &init_mm); current_thread_info()->cpu = 0; plat_prepare_cpus(max_cpus); + set_cpu_sibling_map(0); #ifndef CONFIG_HOTPLUG_CPU cpu_present_map = cpu_possible_map; #endif |