Commit 516db1c6 authored by Paul Burton's avatar Paul Burton Committed by Ralf Baechle
Browse files

MIPS: CM: Avoid per-core locking with CM3 & higher



CM3 provides a GCR_CL_OTHER register per VP, rather than only per core.
This means that we don't need to prevent other VPs within a core from
racing with code that makes use of the core-other register region.

Reduce locking overhead by demoting the per-core spinlock providing
protection for CM2.5 & lower to a per-CPU/per-VP spinlock for CM3 &
higher.

Signed-off-by: default avatarPaul Burton <paul.burton@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/16193/


Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 9b03d8ab
Loading
Loading
Loading
Loading
+32 −6
Original line number Diff line number Diff line
@@ -265,15 +265,34 @@ void mips_cm_lock_other(unsigned int core, unsigned int vp)
	u32 val;

	preempt_disable();
	curr_core = current_cpu_data.core;
	spin_lock_irqsave(&per_cpu(cm_core_lock, curr_core),
			  per_cpu(cm_core_lock_flags, curr_core));

	if (mips_cm_revision() >= CM_REV_CM3) {
		val = core << CM3_GCR_Cx_OTHER_CORE_SHF;
		val |= vp << CM3_GCR_Cx_OTHER_VP_SHF;

		/*
		 * We need to disable interrupts in SMP systems in order to
		 * ensure that we don't interrupt the caller with code which
		 * may modify the redirect register. We do so here in a
		 * slightly obscure way by using a spin lock, since this has
		 * the neat property of also catching any nested uses of
		 * mips_cm_lock_other() leading to a deadlock or a nice warning
		 * with lockdep enabled.
		 */
		spin_lock_irqsave(this_cpu_ptr(&cm_core_lock),
				  *this_cpu_ptr(&cm_core_lock_flags));
	} else {
		BUG_ON(vp != 0);

		/*
		 * We only have a GCR_CL_OTHER per core in systems with
		 * CM 2.5 & older, so have to ensure other VP(E)s don't
		 * race with us.
		 */
		curr_core = current_cpu_data.core;
		spin_lock_irqsave(&per_cpu(cm_core_lock, curr_core),
				  per_cpu(cm_core_lock_flags, curr_core));

		val = core << CM_GCR_Cx_OTHER_CORENUM_SHF;
	}

@@ -288,10 +307,17 @@ void mips_cm_lock_other(unsigned int core, unsigned int vp)

void mips_cm_unlock_other(void)
{
	unsigned curr_core = current_cpu_data.core;
	unsigned int curr_core;

	if (mips_cm_revision() < CM_REV_CM3) {
		curr_core = current_cpu_data.core;
		spin_unlock_irqrestore(&per_cpu(cm_core_lock, curr_core),
				       per_cpu(cm_core_lock_flags, curr_core));
	} else {
		spin_unlock_irqrestore(this_cpu_ptr(&cm_core_lock),
				       *this_cpu_ptr(&cm_core_lock_flags));
	}

	preempt_enable();
}