1/* 2 * Copyright 2010 Tilera Corporation. All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation, version 2. 7 * 8 * This program is distributed in the hope that it will be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 11 * NON INFRINGEMENT. See the GNU General Public License for 12 * more details. 13 */ 14 15#ifndef _ASM_TILE_BARRIER_H 16#define _ASM_TILE_BARRIER_H 17 18#ifndef __ASSEMBLY__ 19 20#include <linux/types.h> 21#include <arch/chip.h> 22#include <arch/spr_def.h> 23#include <asm/timex.h> 24 25#define __sync() __insn_mf() 26 27#include <hv/syscall_public.h> 28/* 29 * Issue an uncacheable load to each memory controller, then 30 * wait until those loads have completed. 31 */ 32static inline void __mb_incoherent(void) 33{ 34 long clobber_r10; 35 asm volatile("swint2" 36 : "=R10" (clobber_r10) 37 : "R10" (HV_SYS_fence_incoherent) 38 : "r0", "r1", "r2", "r3", "r4", 39 "r5", "r6", "r7", "r8", "r9", 40 "r11", "r12", "r13", "r14", 41 "r15", "r16", "r17", "r18", "r19", 42 "r20", "r21", "r22", "r23", "r24", 43 "r25", "r26", "r27", "r28", "r29"); 44} 45 46/* Fence to guarantee visibility of stores to incoherent memory. */ 47static inline void 48mb_incoherent(void) 49{ 50 __insn_mf(); 51 52 { 53#if CHIP_HAS_TILE_WRITE_PENDING() 54 const unsigned long WRITE_TIMEOUT_CYCLES = 400; 55 unsigned long start = get_cycles_low(); 56 do { 57 if (__insn_mfspr(SPR_TILE_WRITE_PENDING) == 0) 58 return; 59 } while ((get_cycles_low() - start) < WRITE_TIMEOUT_CYCLES); 60#endif /* CHIP_HAS_TILE_WRITE_PENDING() */ 61 (void) __mb_incoherent(); 62 } 63} 64 65#define fast_wmb() __sync() 66#define fast_rmb() __sync() 67#define fast_mb() __sync() 68#define fast_iob() mb_incoherent() 69 70#define wmb() fast_wmb() 71#define rmb() fast_rmb() 72#define mb() fast_mb() 73#define iob() fast_iob() 74 75#ifndef __tilegx__ /* 32 bit */ 76/* 77 * We need to barrier before modifying the word, since the _atomic_xxx() 78 * routines just tns the lock and then read/modify/write of the word. 79 * But after the word is updated, the routine issues an "mf" before returning, 80 * and since it's a function call, we don't even need a compiler barrier. 81 */ 82#define smp_mb__before_atomic() smp_mb() 83#define smp_mb__after_atomic() do { } while (0) 84#else /* 64 bit */ 85#define smp_mb__before_atomic() smp_mb() 86#define smp_mb__after_atomic() smp_mb() 87#endif 88 89#include <asm-generic/barrier.h> 90 91#endif /* !__ASSEMBLY__ */ 92#endif /* _ASM_TILE_BARRIER_H */ 93