: MIPS: Adjust set_pte() SMP fix to handle R10000_LLSC_WAR
PATCH 1/1 : MIPS: Adjust set_pte() SMP fix to handle R10000_LLSC_WAR
From: Joshua Kinard <[email protected]>
Update the recent changes to set_pte() that were added in 46011e6ea392 to handle R10000_LLSC_WAR, and format the assembly to match other areas of the MIPS tree using the same WAR.
This also incorporates a patch recently sent in my Markos Chandras, "Remove local LL/SC preprocessor variants", so that patch doesn't need to be applied if this one is accepted.
--- arch/mips/include/asm/pgtable.h | 52 ++++++++++++++++++------------ 1 file changed, 32 insertions(+), 20 deletions(-)
Not sure if 'kernel_uses_llsc' or 'cpu_has_llsc' is appropriate for the if conditional. I've seen both used in the tree w/ the R10000_LLSC_WAR construct.
Note: The set_pte() fix appears to be needed for IP27 to boot, so the original patch and this one may need to be backported. Otherwise, the heavy disk I/O lockup bug I've mentioned in the past has a higher chance of triggering and freezing the machine solid, especially if mdraid is rebuilding a disk. The set_pte() fix won't address that bug, but at least mdraid was able to finish the rebuild after it was applied.
linux-mips-set_pte-smp-r10k-war.patch
arch/mips/include/asm/pgtable.h +32 -20
@@ -187,30 +187,42 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)* For SMP, multiple CPUs can race, so we need to do * this atomically. */ -#ifdef CONFIG_64BIT -#define LL_INSN "lld" -#define SC_INSN "scd" -#else /* CONFIG_32BIT */ -#define LL_INSN "ll" -#define SC_INSN "sc" -#endif unsigned long page_global = _PAGE_GLOBAL;unsigned long tmp; - __asm__ __volatile__ ( -" .set push\n" -" .set noreorder\n" -"1: " LL_INSN " %[tmp], %[buddy]\n" -" bnez %[tmp], 2f\n" -" or %[tmp], %[tmp], %[global]\n" -" " SC_INSN " %[tmp], %[buddy]\n" -" beqz %[tmp], 1b\n" -" nop\n" -"2:\n" -" .set pop" - : [buddy]"+m" (buddy->pte), - [tmp]"=&r" (tmp) +if (kernel_uses_llsc &&R10000_LLSC_WAR ) { + __asm__ __volatile__ ( +" .set arch=r4000 \n" +" .set push \n" +" .set noreorder \n" +"1:" __LL"%[tmp], %[buddy] \n" +" bnez %[tmp], 2f \n" +" or %[tmp], %[tmp], %[global] \n" + __SC"%[tmp], %[buddy] \n" +" beqzl %[tmp], 1b \n" +" nop \n" +"2: \n" +" .set pop \n" +" .set mips0 \n" + : [buddy]"+m" (buddy->pte), [tmp]"=&r" (tmp) + : [global]"r" (page_global)); + }else if (kernel_uses_llsc) { + __asm__ __volatile__ ( +" .set " MIPS_ISA_ARCH_LEVEL " \n" +" .set push \n" +" .set noreorder \n" +"1:" __LL"%[tmp], %[buddy] \n" +" bnez %[tmp], 2f \n" +" or %[tmp], %[tmp], %[global] \n" + __SC"%[tmp], %[buddy] \n" +" beqz %[tmp], 1b \n" +" nop \n" +"2: \n" +" .set pop \n" +" .set mips0 \n" + : [buddy]"+m" (buddy->pte), [tmp]"=&r" (tmp) : [global]"r" (page_global)); + }#else /* !CONFIG_SMP */ if (pte_none (*buddy))pte_val (*buddy) =pte_val (*buddy) | _PAGE_GLOBAL;