#endif /* CONFIG_SMP */
enum tlb_flush_type {
+ FLUSH_TYPE_NONE,
FLUSH_TYPE_LOCAL,
FLUSH_TYPE_GLOBAL,
};
static enum tlb_flush_type flush_type_needed(struct mm_struct *mm, bool fullmm)
{
- if (mm_is_thread_local(mm))
+ int active_cpus = atomic_read(&mm->context.active_cpus);
+ int cpu = smp_processor_id();
+
+ if (active_cpus == 0)
+ return FLUSH_TYPE_NONE;
+ if (active_cpus == 1 && cpumask_test_cpu(cpu, mm_cpumask(mm)))
return FLUSH_TYPE_LOCAL;
/* Coprocessors require TLBIE to invalidate nMMU. */
*/
smp_mb();
type = flush_type_needed(mm, false);
- if (type == FLUSH_TYPE_GLOBAL) {
+ if (type == FLUSH_TYPE_LOCAL) {
+ _tlbiel_pid(pid, RIC_FLUSH_TLB);
+ } else if (type == FLUSH_TYPE_GLOBAL) {
if (!mmu_has_feature(MMU_FTR_GTSE)) {
unsigned long tgt = H_RPTI_TARGET_CMMU;
} else {
_tlbiel_pid_multicast(mm, pid, RIC_FLUSH_TLB);
}
- } else {
- _tlbiel_pid(pid, RIC_FLUSH_TLB);
}
preempt_enable();
}
preempt_disable();
smp_mb(); /* see radix__flush_tlb_mm */
type = flush_type_needed(mm, fullmm);
- if (type == FLUSH_TYPE_GLOBAL) {
+ if (type == FLUSH_TYPE_LOCAL) {
+ _tlbiel_pid(pid, RIC_FLUSH_ALL);
+ } else if (type == FLUSH_TYPE_GLOBAL) {
if (!mmu_has_feature(MMU_FTR_GTSE)) {
unsigned long tgt = H_RPTI_TARGET_CMMU;
unsigned long type = H_RPTI_TYPE_TLB | H_RPTI_TYPE_PWC |
_tlbie_pid(pid, RIC_FLUSH_ALL);
else
_tlbiel_pid_multicast(mm, pid, RIC_FLUSH_ALL);
- } else {
- _tlbiel_pid(pid, RIC_FLUSH_ALL);
}
preempt_enable();
}
preempt_disable();
smp_mb(); /* see radix__flush_tlb_mm */
type = flush_type_needed(mm, false);
- if (type == FLUSH_TYPE_GLOBAL) {
+ if (type == FLUSH_TYPE_LOCAL) {
+ _tlbiel_va(vmaddr, pid, psize, RIC_FLUSH_TLB);
+ } else if (type == FLUSH_TYPE_GLOBAL) {
if (!mmu_has_feature(MMU_FTR_GTSE)) {
unsigned long tgt, pg_sizes, size;
_tlbie_va(vmaddr, pid, psize, RIC_FLUSH_TLB);
else
_tlbiel_va_multicast(mm, vmaddr, pid, psize, RIC_FLUSH_TLB);
- } else {
- _tlbiel_va(vmaddr, pid, psize, RIC_FLUSH_TLB);
}
preempt_enable();
}
preempt_disable();
smp_mb(); /* see radix__flush_tlb_mm */
type = flush_type_needed(mm, fullmm);
+ if (type == FLUSH_TYPE_NONE)
+ goto out;
if (fullmm)
flush_pid = true;
hstart, hend, pid, PMD_SIZE, MMU_PAGE_2M, false);
}
}
+out:
preempt_enable();
}
preempt_disable();
smp_mb(); /* see radix__flush_tlb_mm */
type = flush_type_needed(mm, fullmm);
+ if (type == FLUSH_TYPE_NONE)
+ goto out;
if (fullmm)
flush_pid = true;
_tlbiel_va_range_multicast(mm,
start, end, pid, page_size, psize, also_pwc);
}
+out:
preempt_enable();
}
preempt_disable();
smp_mb(); /* see radix__flush_tlb_mm */
type = flush_type_needed(mm, false);
- if (type == FLUSH_TYPE_GLOBAL) {
+ if (type == FLUSH_TYPE_LOCAL) {
+ _tlbiel_va_range(addr, end, pid, PAGE_SIZE, mmu_virtual_psize, true);
+ } else if (type == FLUSH_TYPE_GLOBAL) {
if (!mmu_has_feature(MMU_FTR_GTSE)) {
unsigned long tgt, type, pg_sizes;
else
_tlbiel_va_range_multicast(mm,
addr, end, pid, PAGE_SIZE, mmu_virtual_psize, true);
- } else {
- _tlbiel_va_range(addr, end, pid, PAGE_SIZE, mmu_virtual_psize, true);
}
preempt_enable();