Merge branch 'acpi-bus'
[cascardo/linux.git] / arch / mips / kernel / smp.c
index f9d01e9..b0baf48 100644 (file)
@@ -72,7 +72,7 @@ EXPORT_SYMBOL(cpu_core_map);
  * A logcal cpu mask containing only one VPE per core to
  * reduce the number of IPIs on large MT systems.
  */
-cpumask_t cpu_foreign_map __read_mostly;
+cpumask_t cpu_foreign_map[NR_CPUS] __read_mostly;
 EXPORT_SYMBOL(cpu_foreign_map);
 
 /* representing cpus for which sibling maps can be computed */
@@ -124,7 +124,7 @@ static inline void set_cpu_core_map(int cpu)
  * Calculate a new cpu_foreign_map mask whenever a
  * new cpu appears or disappears.
  */
-static inline void calculate_cpu_foreign_map(void)
+void calculate_cpu_foreign_map(void)
 {
        int i, k, core_present;
        cpumask_t temp_foreign_map;
@@ -141,7 +141,9 @@ static inline void calculate_cpu_foreign_map(void)
                        cpumask_set_cpu(i, &temp_foreign_map);
        }
 
-       cpumask_copy(&cpu_foreign_map, &temp_foreign_map);
+       for_each_online_cpu(i)
+               cpumask_andnot(&cpu_foreign_map[i],
+                              &temp_foreign_map, &cpu_sibling_map[i]);
 }
 
 struct plat_smp_ops *mp_ops;
@@ -320,6 +322,9 @@ asmlinkage void start_secondary(void)
        cpumask_set_cpu(cpu, &cpu_coherent_mask);
        notify_cpu_starting(cpu);
 
+       cpumask_set_cpu(cpu, &cpu_callin_map);
+       synchronise_count_slave(cpu);
+
        set_cpu_online(cpu, true);
 
        set_cpu_sibling_map(cpu);
@@ -327,10 +332,6 @@ asmlinkage void start_secondary(void)
 
        calculate_cpu_foreign_map();
 
-       cpumask_set_cpu(cpu, &cpu_callin_map);
-
-       synchronise_count_slave(cpu);
-
        /*
         * irq will be enabled in ->smp_finish(), enabling it too early
         * is dangerous.
@@ -344,16 +345,9 @@ asmlinkage void start_secondary(void)
 static void stop_this_cpu(void *dummy)
 {
        /*
-        * Remove this CPU. Be a bit slow here and
-        * set the bits for every online CPU so we don't miss
-        * any IPI whilst taking this VPE down.
+        * Remove this CPU:
         */
 
-       cpumask_copy(&cpu_foreign_map, cpu_online_mask);
-
-       /* Make it visible to every other CPU */
-       smp_mb();
-
        set_cpu_online(smp_processor_id(), false);
        calculate_cpu_foreign_map();
        local_irq_disable();
@@ -512,10 +506,17 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned l
                smp_on_other_tlbs(flush_tlb_range_ipi, &fd);
        } else {
                unsigned int cpu;
+               int exec = vma->vm_flags & VM_EXEC;
 
                for_each_online_cpu(cpu) {
+                       /*
+                        * flush_cache_range() will only fully flush icache if
+                        * the VMA is executable, otherwise we must invalidate
+                        * ASID without it appearing to has_valid_asid() as if
+                        * mm has been completely unused by that CPU.
+                        */
                        if (cpu != smp_processor_id() && cpu_context(cpu, mm))
-                               cpu_context(cpu, mm) = 0;
+                               cpu_context(cpu, mm) = !exec;
                }
        }
        local_flush_tlb_range(vma, start, end);
@@ -560,8 +561,14 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
                unsigned int cpu;
 
                for_each_online_cpu(cpu) {
+                       /*
+                        * flush_cache_page() only does partial flushes, so
+                        * invalidate ASID without it appearing to
+                        * has_valid_asid() as if mm has been completely unused
+                        * by that CPU.
+                        */
                        if (cpu != smp_processor_id() && cpu_context(cpu, vma->vm_mm))
-                               cpu_context(cpu, vma->vm_mm) = 0;
+                               cpu_context(cpu, vma->vm_mm) = 1;
                }
        }
        local_flush_tlb_page(vma, page);