162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 362306a36Sopenharmony_ci * License. See the file "COPYING" in the main directory of this archive 462306a36Sopenharmony_ci * for more details. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2006 by Ralf Baechle (ralf@linux-mips.org) 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci#ifndef __ASM_BARRIER_H 962306a36Sopenharmony_ci#define __ASM_BARRIER_H 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <asm/addrspace.h> 1262306a36Sopenharmony_ci#include <asm/sync.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_cistatic inline void __sync(void) 1562306a36Sopenharmony_ci{ 1662306a36Sopenharmony_ci asm volatile(__SYNC(full, always) ::: "memory"); 1762306a36Sopenharmony_ci} 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cistatic inline void rmb(void) 2062306a36Sopenharmony_ci{ 2162306a36Sopenharmony_ci asm volatile(__SYNC(rmb, always) ::: "memory"); 2262306a36Sopenharmony_ci} 2362306a36Sopenharmony_ci#define rmb rmb 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistatic inline void wmb(void) 2662306a36Sopenharmony_ci{ 2762306a36Sopenharmony_ci asm volatile(__SYNC(wmb, always) ::: "memory"); 2862306a36Sopenharmony_ci} 2962306a36Sopenharmony_ci#define wmb wmb 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#define fast_mb() __sync() 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#define __fast_iob() \ 3462306a36Sopenharmony_ci __asm__ __volatile__( \ 3562306a36Sopenharmony_ci ".set push\n\t" \ 3662306a36Sopenharmony_ci ".set noreorder\n\t" \ 3762306a36Sopenharmony_ci "lw $0,%0\n\t" \ 3862306a36Sopenharmony_ci "nop\n\t" \ 3962306a36Sopenharmony_ci ".set pop" \ 4062306a36Sopenharmony_ci : /* no output */ \ 4162306a36Sopenharmony_ci : "m" (*(int *)CKSEG1) \ 4262306a36Sopenharmony_ci : "memory") 4362306a36Sopenharmony_ci#ifdef CONFIG_CPU_CAVIUM_OCTEON 4462306a36Sopenharmony_ci# define fast_iob() do { } while (0) 4562306a36Sopenharmony_ci#else /* ! CONFIG_CPU_CAVIUM_OCTEON */ 4662306a36Sopenharmony_ci# ifdef CONFIG_SGI_IP28 4762306a36Sopenharmony_ci# define fast_iob() \ 4862306a36Sopenharmony_ci __asm__ __volatile__( \ 4962306a36Sopenharmony_ci ".set push\n\t" \ 5062306a36Sopenharmony_ci ".set noreorder\n\t" \ 5162306a36Sopenharmony_ci "lw $0,%0\n\t" \ 5262306a36Sopenharmony_ci "sync\n\t" \ 5362306a36Sopenharmony_ci "lw $0,%0\n\t" \ 5462306a36Sopenharmony_ci ".set pop" \ 5562306a36Sopenharmony_ci : /* no output */ \ 5662306a36Sopenharmony_ci : "m" (*(int *)CKSEG1ADDR(0x1fa00004)) \ 5762306a36Sopenharmony_ci : "memory") 5862306a36Sopenharmony_ci# else 5962306a36Sopenharmony_ci# define fast_iob() \ 6062306a36Sopenharmony_ci do { \ 6162306a36Sopenharmony_ci __sync(); \ 6262306a36Sopenharmony_ci __fast_iob(); \ 6362306a36Sopenharmony_ci } while (0) 6462306a36Sopenharmony_ci# endif 6562306a36Sopenharmony_ci#endif /* CONFIG_CPU_CAVIUM_OCTEON */ 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci#ifdef CONFIG_CPU_HAS_WB 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci#include <asm/wbflush.h> 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci#define mb() wbflush() 7262306a36Sopenharmony_ci#define iob() wbflush() 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci#else /* !CONFIG_CPU_HAS_WB */ 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci#define mb() fast_mb() 7762306a36Sopenharmony_ci#define iob() fast_iob() 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci#endif /* !CONFIG_CPU_HAS_WB */ 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci#if defined(CONFIG_WEAK_ORDERING) 8262306a36Sopenharmony_ci# define __smp_mb() __sync() 8362306a36Sopenharmony_ci# define __smp_rmb() rmb() 8462306a36Sopenharmony_ci# define __smp_wmb() wmb() 8562306a36Sopenharmony_ci#else 8662306a36Sopenharmony_ci# define __smp_mb() barrier() 8762306a36Sopenharmony_ci# define __smp_rmb() barrier() 8862306a36Sopenharmony_ci# define __smp_wmb() barrier() 8962306a36Sopenharmony_ci#endif 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci/* 9262306a36Sopenharmony_ci * When LL/SC does imply order, it must also be a compiler barrier to avoid the 9362306a36Sopenharmony_ci * compiler from reordering where the CPU will not. When it does not imply 9462306a36Sopenharmony_ci * order, the compiler is also free to reorder across the LL/SC loop and 9562306a36Sopenharmony_ci * ordering will be done by smp_llsc_mb() and friends. 9662306a36Sopenharmony_ci */ 9762306a36Sopenharmony_ci#if defined(CONFIG_WEAK_REORDERING_BEYOND_LLSC) && defined(CONFIG_SMP) 9862306a36Sopenharmony_ci# define __WEAK_LLSC_MB sync 9962306a36Sopenharmony_ci# define smp_llsc_mb() \ 10062306a36Sopenharmony_ci __asm__ __volatile__(__stringify(__WEAK_LLSC_MB) : : :"memory") 10162306a36Sopenharmony_ci# define __LLSC_CLOBBER 10262306a36Sopenharmony_ci#else 10362306a36Sopenharmony_ci# define __WEAK_LLSC_MB 10462306a36Sopenharmony_ci# define smp_llsc_mb() do { } while (0) 10562306a36Sopenharmony_ci# define __LLSC_CLOBBER "memory" 10662306a36Sopenharmony_ci#endif 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci#ifdef CONFIG_CPU_CAVIUM_OCTEON 10962306a36Sopenharmony_ci#define smp_mb__before_llsc() smp_wmb() 11062306a36Sopenharmony_ci#define __smp_mb__before_llsc() __smp_wmb() 11162306a36Sopenharmony_ci/* Cause previous writes to become visible on all CPUs as soon as possible */ 11262306a36Sopenharmony_ci#define nudge_writes() __asm__ __volatile__(".set push\n\t" \ 11362306a36Sopenharmony_ci ".set arch=octeon\n\t" \ 11462306a36Sopenharmony_ci "syncw\n\t" \ 11562306a36Sopenharmony_ci ".set pop" : : : "memory") 11662306a36Sopenharmony_ci#else 11762306a36Sopenharmony_ci#define smp_mb__before_llsc() smp_llsc_mb() 11862306a36Sopenharmony_ci#define __smp_mb__before_llsc() smp_llsc_mb() 11962306a36Sopenharmony_ci#define nudge_writes() mb() 12062306a36Sopenharmony_ci#endif 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci/* 12362306a36Sopenharmony_ci * In the Loongson3 LL/SC workaround case, all of our LL/SC loops already have 12462306a36Sopenharmony_ci * a completion barrier immediately preceding the LL instruction. Therefore we 12562306a36Sopenharmony_ci * can skip emitting a barrier from __smp_mb__before_atomic(). 12662306a36Sopenharmony_ci */ 12762306a36Sopenharmony_ci#ifdef CONFIG_CPU_LOONGSON3_WORKAROUNDS 12862306a36Sopenharmony_ci# define __smp_mb__before_atomic() 12962306a36Sopenharmony_ci#else 13062306a36Sopenharmony_ci# define __smp_mb__before_atomic() __smp_mb__before_llsc() 13162306a36Sopenharmony_ci#endif 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci#define __smp_mb__after_atomic() smp_llsc_mb() 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_cistatic inline void sync_ginv(void) 13662306a36Sopenharmony_ci{ 13762306a36Sopenharmony_ci asm volatile(__SYNC(ginv, always)); 13862306a36Sopenharmony_ci} 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci#include <asm-generic/barrier.h> 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci#endif /* __ASM_BARRIER_H */ 143