diff options
Diffstat (limited to 'arch/tile/include/asm/cacheflush.h')
| -rw-r--r-- | arch/tile/include/asm/cacheflush.h | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/arch/tile/include/asm/cacheflush.h b/arch/tile/include/asm/cacheflush.h index c5741da4eeac..14a3f8556ace 100644 --- a/arch/tile/include/asm/cacheflush.h +++ b/arch/tile/include/asm/cacheflush.h | |||
| @@ -137,4 +137,56 @@ static inline void finv_buffer(void *buffer, size_t size) | |||
| 137 | mb_incoherent(); | 137 | mb_incoherent(); |
| 138 | } | 138 | } |
| 139 | 139 | ||
| 140 | /* | ||
| 141 | * Flush & invalidate a VA range that is homed remotely on a single core, | ||
| 142 | * waiting until the memory controller holds the flushed values. | ||
| 143 | */ | ||
| 144 | static inline void finv_buffer_remote(void *buffer, size_t size) | ||
| 145 | { | ||
| 146 | char *p; | ||
| 147 | int i; | ||
| 148 | |||
| 149 | /* | ||
| 150 | * Flush and invalidate the buffer out of the local L1/L2 | ||
| 151 | * and request the home cache to flush and invalidate as well. | ||
| 152 | */ | ||
| 153 | __finv_buffer(buffer, size); | ||
| 154 | |||
| 155 | /* | ||
| 156 | * Wait for the home cache to acknowledge that it has processed | ||
| 157 | * all the flush-and-invalidate requests. This does not mean | ||
| 158 | * that the flushed data has reached the memory controller yet, | ||
| 159 | * but it does mean the home cache is processing the flushes. | ||
| 160 | */ | ||
| 161 | __insn_mf(); | ||
| 162 | |||
| 163 | /* | ||
| 164 | * Issue a load to the last cache line, which can't complete | ||
| 165 | * until all the previously-issued flushes to the same memory | ||
| 166 | * controller have also completed. If we weren't striping | ||
| 167 | * memory, that one load would be sufficient, but since we may | ||
| 168 | * be, we also need to back up to the last load issued to | ||
| 169 | * another memory controller, which would be the point where | ||
| 170 | * we crossed an 8KB boundary (the granularity of striping | ||
| 171 | * across memory controllers). Keep backing up and doing this | ||
| 172 | * until we are before the beginning of the buffer, or have | ||
| 173 | * hit all the controllers. | ||
| 174 | */ | ||
| 175 | for (i = 0, p = (char *)buffer + size - 1; | ||
| 176 | i < (1 << CHIP_LOG_NUM_MSHIMS()) && p >= (char *)buffer; | ||
| 177 | ++i) { | ||
| 178 | const unsigned long STRIPE_WIDTH = 8192; | ||
| 179 | |||
| 180 | /* Force a load instruction to issue. */ | ||
| 181 | *(volatile char *)p; | ||
| 182 | |||
| 183 | /* Jump to end of previous stripe. */ | ||
| 184 | p -= STRIPE_WIDTH; | ||
| 185 | p = (char *)((unsigned long)p | (STRIPE_WIDTH - 1)); | ||
| 186 | } | ||
| 187 | |||
| 188 | /* Wait for the loads (and thus flushes) to have completed. */ | ||
| 189 | __insn_mf(); | ||
| 190 | } | ||
| 191 | |||
| 140 | #endif /* _ASM_TILE_CACHEFLUSH_H */ | 192 | #endif /* _ASM_TILE_CACHEFLUSH_H */ |
