diff options
| -rw-r--r-- | arch/arm/common/dmabounce.c | 1 | ||||
| -rw-r--r-- | arch/arm/kernel/setup.c | 3 | ||||
| -rw-r--r-- | arch/arm/mm/Kconfig | 3 | ||||
| -rw-r--r-- | arch/arm/mm/consistent.c | 6 | ||||
| -rw-r--r-- | include/asm-arm/cacheflush.h | 37 |
5 files changed, 50 insertions, 0 deletions
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c index 272702accd8b..b4748e3171c6 100644 --- a/arch/arm/common/dmabounce.c +++ b/arch/arm/common/dmabounce.c | |||
| @@ -338,6 +338,7 @@ unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, | |||
| 338 | */ | 338 | */ |
| 339 | ptr = (unsigned long)buf->ptr; | 339 | ptr = (unsigned long)buf->ptr; |
| 340 | dmac_clean_range(ptr, ptr + size); | 340 | dmac_clean_range(ptr, ptr + size); |
| 341 | outer_clean_range(__pa(ptr), __pa(ptr) + size); | ||
| 341 | } | 342 | } |
| 342 | free_safe_buffer(device_info, buf); | 343 | free_safe_buffer(device_info, buf); |
| 343 | } | 344 | } |
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index bbab134cd82d..243aea458057 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c | |||
| @@ -88,6 +88,9 @@ struct cpu_user_fns cpu_user; | |||
| 88 | #ifdef MULTI_CACHE | 88 | #ifdef MULTI_CACHE |
| 89 | struct cpu_cache_fns cpu_cache; | 89 | struct cpu_cache_fns cpu_cache; |
| 90 | #endif | 90 | #endif |
| 91 | #ifdef CONFIG_OUTER_CACHE | ||
| 92 | struct outer_cache_fns outer_cache; | ||
| 93 | #endif | ||
| 91 | 94 | ||
| 92 | struct stack { | 95 | struct stack { |
| 93 | u32 irq[3]; | 96 | u32 irq[3]; |
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index aade2f72c920..a84eed9f8542 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig | |||
| @@ -609,3 +609,6 @@ config NEEDS_SYSCALL_FOR_CMPXCHG | |||
| 609 | Forget about fast user space cmpxchg support. | 609 | Forget about fast user space cmpxchg support. |
| 610 | It is just not possible. | 610 | It is just not possible. |
| 611 | 611 | ||
| 612 | config OUTER_CACHE | ||
| 613 | bool | ||
| 614 | default n | ||
diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c index 6a9c362fef5e..83bd035c7d5e 100644 --- a/arch/arm/mm/consistent.c +++ b/arch/arm/mm/consistent.c | |||
| @@ -208,6 +208,7 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, | |||
| 208 | unsigned long kaddr = (unsigned long)page_address(page); | 208 | unsigned long kaddr = (unsigned long)page_address(page); |
| 209 | memset(page_address(page), 0, size); | 209 | memset(page_address(page), 0, size); |
| 210 | dmac_flush_range(kaddr, kaddr + size); | 210 | dmac_flush_range(kaddr, kaddr + size); |
| 211 | outer_flush_range(__pa(kaddr), __pa(kaddr) + size); | ||
| 211 | } | 212 | } |
| 212 | 213 | ||
| 213 | /* | 214 | /* |
| @@ -485,15 +486,20 @@ void consistent_sync(void *vaddr, size_t size, int direction) | |||
| 485 | unsigned long start = (unsigned long)vaddr; | 486 | unsigned long start = (unsigned long)vaddr; |
| 486 | unsigned long end = start + size; | 487 | unsigned long end = start + size; |
| 487 | 488 | ||
| 489 | BUG_ON(!virt_addr_valid(start) || !virt_addr_valid(end)); | ||
| 490 | |||
| 488 | switch (direction) { | 491 | switch (direction) { |
| 489 | case DMA_FROM_DEVICE: /* invalidate only */ | 492 | case DMA_FROM_DEVICE: /* invalidate only */ |
| 490 | dmac_inv_range(start, end); | 493 | dmac_inv_range(start, end); |
| 494 | outer_inv_range(__pa(start), __pa(end)); | ||
| 491 | break; | 495 | break; |
| 492 | case DMA_TO_DEVICE: /* writeback only */ | 496 | case DMA_TO_DEVICE: /* writeback only */ |
| 493 | dmac_clean_range(start, end); | 497 | dmac_clean_range(start, end); |
| 498 | outer_clean_range(__pa(start), __pa(end)); | ||
| 494 | break; | 499 | break; |
| 495 | case DMA_BIDIRECTIONAL: /* writeback and invalidate */ | 500 | case DMA_BIDIRECTIONAL: /* writeback and invalidate */ |
| 496 | dmac_flush_range(start, end); | 501 | dmac_flush_range(start, end); |
| 502 | outer_flush_range(__pa(start), __pa(end)); | ||
| 497 | break; | 503 | break; |
| 498 | default: | 504 | default: |
| 499 | BUG(); | 505 | BUG(); |
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h index 5f531ea03059..ce60b3702ba5 100644 --- a/include/asm-arm/cacheflush.h +++ b/include/asm-arm/cacheflush.h | |||
| @@ -190,6 +190,12 @@ struct cpu_cache_fns { | |||
| 190 | void (*dma_flush_range)(unsigned long, unsigned long); | 190 | void (*dma_flush_range)(unsigned long, unsigned long); |
| 191 | }; | 191 | }; |
| 192 | 192 | ||
| 193 | struct outer_cache_fns { | ||
| 194 | void (*inv_range)(unsigned long, unsigned long); | ||
| 195 | void (*clean_range)(unsigned long, unsigned long); | ||
| 196 | void (*flush_range)(unsigned long, unsigned long); | ||
| 197 | }; | ||
| 198 | |||
| 193 | /* | 199 | /* |
| 194 | * Select the calling method | 200 | * Select the calling method |
| 195 | */ | 201 | */ |
| @@ -246,6 +252,37 @@ extern void dmac_flush_range(unsigned long, unsigned long); | |||
| 246 | 252 | ||
| 247 | #endif | 253 | #endif |
| 248 | 254 | ||
| 255 | #ifdef CONFIG_OUTER_CACHE | ||
| 256 | |||
| 257 | extern struct outer_cache_fns outer_cache; | ||
| 258 | |||
| 259 | static inline void outer_inv_range(unsigned long start, unsigned long end) | ||
| 260 | { | ||
| 261 | if (outer_cache.inv_range) | ||
| 262 | outer_cache.inv_range(start, end); | ||
| 263 | } | ||
| 264 | static inline void outer_clean_range(unsigned long start, unsigned long end) | ||
| 265 | { | ||
| 266 | if (outer_cache.clean_range) | ||
| 267 | outer_cache.clean_range(start, end); | ||
| 268 | } | ||
| 269 | static inline void outer_flush_range(unsigned long start, unsigned long end) | ||
| 270 | { | ||
| 271 | if (outer_cache.flush_range) | ||
| 272 | outer_cache.flush_range(start, end); | ||
| 273 | } | ||
| 274 | |||
| 275 | #else | ||
| 276 | |||
| 277 | static inline void outer_inv_range(unsigned long start, unsigned long end) | ||
| 278 | { } | ||
| 279 | static inline void outer_clean_range(unsigned long start, unsigned long end) | ||
| 280 | { } | ||
| 281 | static inline void outer_flush_range(unsigned long start, unsigned long end) | ||
| 282 | { } | ||
| 283 | |||
| 284 | #endif | ||
| 285 | |||
| 249 | /* | 286 | /* |
| 250 | * flush_cache_vmap() is used when creating mappings (eg, via vmap, | 287 | * flush_cache_vmap() is used when creating mappings (eg, via vmap, |
| 251 | * vmalloc, ioremap etc) in kernel space for pages. Since the | 288 | * vmalloc, ioremap etc) in kernel space for pages. Since the |
