aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkos Chandras <markos.chandras@imgtec.com>2015-07-10 04:29:10 -0400
committerRalf Baechle <ralf@linux-mips.org>2015-07-10 04:59:16 -0400
commitcccf34e9411c41b0cbfb41980fe55fc8e7c98fd2 (patch)
tree7e210c9313ddac303a47a6b527935f4b00ee3fa7
parent1c885357da2d3cf62132e611c0beaf4cdf607dd9 (diff)
MIPS: c-r4k: Fix cache flushing for MT cores
MT_SMP is not the only SMP option for MT cores. The MT_SMP option allows more than one VPE per core to appear as a secondary CPU in the system. Because of how CM works, it propagates the address-based cache ops to the secondary cores but not the index-based ones. Because of that, the code does not use IPIs to flush the L1 caches on secondary cores because the CM would have done that already. However, the CM functionality is independent of the type of SMP kernel so even in non-MT kernels, IPIs are not necessary. As a result of which, we change the conditional to depend on the CM presence. Moreover, since VPEs on the same core share the same L1 caches, there is no need to send an IPI on all of them so we calculate a suitable cpumask with only one VPE per core. Signed-off-by: Markos Chandras <markos.chandras@imgtec.com> Cc: <stable@vger.kernel.org> # 3.15+ Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/10654/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/include/asm/smp.h1
-rw-r--r--arch/mips/kernel/smp.c44
-rw-r--r--arch/mips/mm/c-r4k.c14
3 files changed, 55 insertions, 4 deletions
diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h
index 2b25d1ba1ea0..16f1ea9ab191 100644
--- a/arch/mips/include/asm/smp.h
+++ b/arch/mips/include/asm/smp.h
@@ -23,6 +23,7 @@
23extern int smp_num_siblings; 23extern int smp_num_siblings;
24extern cpumask_t cpu_sibling_map[]; 24extern cpumask_t cpu_sibling_map[];
25extern cpumask_t cpu_core_map[]; 25extern cpumask_t cpu_core_map[];
26extern cpumask_t cpu_foreign_map;
26 27
27#define raw_smp_processor_id() (current_thread_info()->cpu) 28#define raw_smp_processor_id() (current_thread_info()->cpu)
28 29
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index faa46ebd9dda..d0744cc77ea7 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -63,6 +63,13 @@ EXPORT_SYMBOL(cpu_sibling_map);
63cpumask_t cpu_core_map[NR_CPUS] __read_mostly; 63cpumask_t cpu_core_map[NR_CPUS] __read_mostly;
64EXPORT_SYMBOL(cpu_core_map); 64EXPORT_SYMBOL(cpu_core_map);
65 65
66/*
67 * A logcal cpu mask containing only one VPE per core to
68 * reduce the number of IPIs on large MT systems.
69 */
70cpumask_t cpu_foreign_map __read_mostly;
71EXPORT_SYMBOL(cpu_foreign_map);
72
66/* representing cpus for which sibling maps can be computed */ 73/* representing cpus for which sibling maps can be computed */
67static cpumask_t cpu_sibling_setup_map; 74static cpumask_t cpu_sibling_setup_map;
68 75
@@ -103,6 +110,29 @@ static inline void set_cpu_core_map(int cpu)
103 } 110 }
104} 111}
105 112
113/*
114 * Calculate a new cpu_foreign_map mask whenever a
115 * new cpu appears or disappears.
116 */
117static inline void calculate_cpu_foreign_map(void)
118{
119 int i, k, core_present;
120 cpumask_t temp_foreign_map;
121
122 /* Re-calculate the mask */
123 for_each_online_cpu(i) {
124 core_present = 0;
125 for_each_cpu(k, &temp_foreign_map)
126 if (cpu_data[i].package == cpu_data[k].package &&
127 cpu_data[i].core == cpu_data[k].core)
128 core_present = 1;
129 if (!core_present)
130 cpumask_set_cpu(i, &temp_foreign_map);
131 }
132
133 cpumask_copy(&cpu_foreign_map, &temp_foreign_map);
134}
135
106struct plat_smp_ops *mp_ops; 136struct plat_smp_ops *mp_ops;
107EXPORT_SYMBOL(mp_ops); 137EXPORT_SYMBOL(mp_ops);
108 138
@@ -146,6 +176,8 @@ asmlinkage void start_secondary(void)
146 set_cpu_sibling_map(cpu); 176 set_cpu_sibling_map(cpu);
147 set_cpu_core_map(cpu); 177 set_cpu_core_map(cpu);
148 178
179 calculate_cpu_foreign_map();
180
149 cpumask_set_cpu(cpu, &cpu_callin_map); 181 cpumask_set_cpu(cpu, &cpu_callin_map);
150 182
151 synchronise_count_slave(cpu); 183 synchronise_count_slave(cpu);
@@ -173,9 +205,18 @@ void __irq_entry smp_call_function_interrupt(void)
173static void stop_this_cpu(void *dummy) 205static void stop_this_cpu(void *dummy)
174{ 206{
175 /* 207 /*
176 * Remove this CPU: 208 * Remove this CPU. Be a bit slow here and
209 * set the bits for every online CPU so we don't miss
210 * any IPI whilst taking this VPE down.
177 */ 211 */
212
213 cpumask_copy(&cpu_foreign_map, cpu_online_mask);
214
215 /* Make it visible to every other CPU */
216 smp_mb();
217
178 set_cpu_online(smp_processor_id(), false); 218 set_cpu_online(smp_processor_id(), false);
219 calculate_cpu_foreign_map();
179 local_irq_disable(); 220 local_irq_disable();
180 while (1); 221 while (1);
181} 222}
@@ -197,6 +238,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
197 mp_ops->prepare_cpus(max_cpus); 238 mp_ops->prepare_cpus(max_cpus);
198 set_cpu_sibling_map(0); 239 set_cpu_sibling_map(0);
199 set_cpu_core_map(0); 240 set_cpu_core_map(0);
241 calculate_cpu_foreign_map();
200#ifndef CONFIG_HOTPLUG_CPU 242#ifndef CONFIG_HOTPLUG_CPU
201 init_cpu_present(cpu_possible_mask); 243 init_cpu_present(cpu_possible_mask);
202#endif 244#endif
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 7f660dc67596..a5974ddba44b 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -37,6 +37,7 @@
37#include <asm/cacheflush.h> /* for run_uncached() */ 37#include <asm/cacheflush.h> /* for run_uncached() */
38#include <asm/traps.h> 38#include <asm/traps.h>
39#include <asm/dma-coherence.h> 39#include <asm/dma-coherence.h>
40#include <asm/mips-cm.h>
40 41
41/* 42/*
42 * Special Variant of smp_call_function for use by cache functions: 43 * Special Variant of smp_call_function for use by cache functions:
@@ -51,9 +52,16 @@ static inline void r4k_on_each_cpu(void (*func) (void *info), void *info)
51{ 52{
52 preempt_disable(); 53 preempt_disable();
53 54
54#ifndef CONFIG_MIPS_MT_SMP 55 /*
55 smp_call_function(func, info, 1); 56 * The Coherent Manager propagates address-based cache ops to other
56#endif 57 * cores but not index-based ops. However, r4k_on_each_cpu is used
58 * in both cases so there is no easy way to tell what kind of op is
59 * executed to the other cores. The best we can probably do is
60 * to restrict that call when a CM is not present because both
61 * CM-based SMP protocols (CMP & CPS) restrict index-based cache ops.
62 */
63 if (!mips_cm_present())
64 smp_call_function_many(&cpu_foreign_map, func, info, 1);
57 func(info); 65 func(info);
58 preempt_enable(); 66 preempt_enable();
59} 67}