diff options
author | Ilya Loginov <isloginov@gmail.com> | 2009-11-26 03:16:19 -0500 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2009-11-26 03:16:19 -0500 |
commit | 2d4dc890b5c8fabd818a8586607e6843c4375e62 (patch) | |
tree | 9976ed7b0eed0056f8289aeb6a2b0abf8c940454 | |
parent | 3586e917f2c7df769d173c4ec99554cb40a911e5 (diff) |
block: add helpers to run flush_dcache_page() against a bio and a request's pages
Mtdblock driver doesn't call flush_dcache_page for pages in request. So,
this causes problems on architectures where the icache doesn't fill from
the dcache or with dcache aliases. The patch fixes this.
The ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE symbol was introduced to avoid
pointless empty cache-thrashing loops on architectures for which
flush_dcache_page() is a no-op. Every architecture was provided with this
flush pages on architectires where ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE is
equal 1 or do nothing otherwise.
See "fix mtd_blkdevs problem with caches on some architectures" discussion
on LKML for more information.
Signed-off-by: Ilya Loginov <isloginov@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Peter Horton <phorton@bitbox.co.uk>
Cc: "Ed L. Cashin" <ecashin@coraid.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
29 files changed, 83 insertions, 0 deletions
diff --git a/arch/alpha/include/asm/cacheflush.h b/arch/alpha/include/asm/cacheflush.h index b686cc7fc44e..01d71e1c8a9e 100644 --- a/arch/alpha/include/asm/cacheflush.h +++ b/arch/alpha/include/asm/cacheflush.h | |||
@@ -9,6 +9,7 @@ | |||
9 | #define flush_cache_dup_mm(mm) do { } while (0) | 9 | #define flush_cache_dup_mm(mm) do { } while (0) |
10 | #define flush_cache_range(vma, start, end) do { } while (0) | 10 | #define flush_cache_range(vma, start, end) do { } while (0) |
11 | #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) | 11 | #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) |
12 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 | ||
12 | #define flush_dcache_page(page) do { } while (0) | 13 | #define flush_dcache_page(page) do { } while (0) |
13 | #define flush_dcache_mmap_lock(mapping) do { } while (0) | 14 | #define flush_dcache_mmap_lock(mapping) do { } while (0) |
14 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) | 15 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) |
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index fd03fb63a332..247b7b0adc2a 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h | |||
@@ -408,6 +408,7 @@ extern void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, | |||
408 | * about to change to user space. This is the same method as used on SPARC64. | 408 | * about to change to user space. This is the same method as used on SPARC64. |
409 | * See update_mmu_cache for the user space part. | 409 | * See update_mmu_cache for the user space part. |
410 | */ | 410 | */ |
411 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 | ||
411 | extern void flush_dcache_page(struct page *); | 412 | extern void flush_dcache_page(struct page *); |
412 | 413 | ||
413 | extern void __flush_dcache_page(struct address_space *mapping, struct page *page); | 414 | extern void __flush_dcache_page(struct address_space *mapping, struct page *page); |
diff --git a/arch/avr32/include/asm/cacheflush.h b/arch/avr32/include/asm/cacheflush.h index 670674749b20..96e53820bbbd 100644 --- a/arch/avr32/include/asm/cacheflush.h +++ b/arch/avr32/include/asm/cacheflush.h | |||
@@ -107,6 +107,7 @@ extern void flush_icache_page(struct vm_area_struct *vma, struct page *page); | |||
107 | * do something here, but only for certain configurations. No such | 107 | * do something here, but only for certain configurations. No such |
108 | * configurations exist at this time. | 108 | * configurations exist at this time. |
109 | */ | 109 | */ |
110 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 | ||
110 | #define flush_dcache_page(page) do { } while (0) | 111 | #define flush_dcache_page(page) do { } while (0) |
111 | #define flush_dcache_mmap_lock(page) do { } while (0) | 112 | #define flush_dcache_mmap_lock(page) do { } while (0) |
112 | #define flush_dcache_mmap_unlock(page) do { } while (0) | 113 | #define flush_dcache_mmap_unlock(page) do { } while (0) |
diff --git a/arch/blackfin/include/asm/cacheflush.h b/arch/blackfin/include/asm/cacheflush.h index af03a36c7a4e..417eaac7fe99 100644 --- a/arch/blackfin/include/asm/cacheflush.h +++ b/arch/blackfin/include/asm/cacheflush.h | |||
@@ -68,9 +68,11 @@ do { memcpy(dst, src, len); \ | |||
68 | #endif | 68 | #endif |
69 | #if defined(CONFIG_BFIN_EXTMEM_WRITEBACK) || defined(CONFIG_BFIN_L2_WRITEBACK) | 69 | #if defined(CONFIG_BFIN_EXTMEM_WRITEBACK) || defined(CONFIG_BFIN_L2_WRITEBACK) |
70 | # define flush_dcache_range(start,end) blackfin_dcache_flush_range((start), (end)) | 70 | # define flush_dcache_range(start,end) blackfin_dcache_flush_range((start), (end)) |
71 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 | ||
71 | # define flush_dcache_page(page) blackfin_dflush_page(page_address(page)) | 72 | # define flush_dcache_page(page) blackfin_dflush_page(page_address(page)) |
72 | #else | 73 | #else |
73 | # define flush_dcache_range(start,end) do { } while (0) | 74 | # define flush_dcache_range(start,end) do { } while (0) |
75 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 | ||
74 | # define flush_dcache_page(page) do { } while (0) | 76 | # define flush_dcache_page(page) do { } while (0) |
75 | #endif | 77 | #endif |
76 | 78 | ||
diff --git a/arch/cris/include/asm/cacheflush.h b/arch/cris/include/asm/cacheflush.h index cf60e3f69f8d..36795bca605e 100644 --- a/arch/cris/include/asm/cacheflush.h +++ b/arch/cris/include/asm/cacheflush.h | |||
@@ -12,6 +12,7 @@ | |||
12 | #define flush_cache_dup_mm(mm) do { } while (0) | 12 | #define flush_cache_dup_mm(mm) do { } while (0) |
13 | #define flush_cache_range(vma, start, end) do { } while (0) | 13 | #define flush_cache_range(vma, start, end) do { } while (0) |
14 | #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) | 14 | #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) |
15 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 | ||
15 | #define flush_dcache_page(page) do { } while (0) | 16 | #define flush_dcache_page(page) do { } while (0) |
16 | #define flush_dcache_mmap_lock(mapping) do { } while (0) | 17 | #define flush_dcache_mmap_lock(mapping) do { } while (0) |
17 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) | 18 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) |
diff --git a/arch/frv/include/asm/cacheflush.h b/arch/frv/include/asm/cacheflush.h index 432a69e7f3d4..edbac54ae015 100644 --- a/arch/frv/include/asm/cacheflush.h +++ b/arch/frv/include/asm/cacheflush.h | |||
@@ -47,6 +47,7 @@ static inline void __flush_cache_all(void) | |||
47 | } | 47 | } |
48 | 48 | ||
49 | /* dcache/icache coherency... */ | 49 | /* dcache/icache coherency... */ |
50 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 | ||
50 | #ifdef CONFIG_MMU | 51 | #ifdef CONFIG_MMU |
51 | extern void flush_dcache_page(struct page *page); | 52 | extern void flush_dcache_page(struct page *page); |
52 | #else | 53 | #else |
diff --git a/arch/h8300/include/asm/cacheflush.h b/arch/h8300/include/asm/cacheflush.h index 5ffdca217b95..4cf2df20c1ce 100644 --- a/arch/h8300/include/asm/cacheflush.h +++ b/arch/h8300/include/asm/cacheflush.h | |||
@@ -15,6 +15,7 @@ | |||
15 | #define flush_cache_dup_mm(mm) do { } while (0) | 15 | #define flush_cache_dup_mm(mm) do { } while (0) |
16 | #define flush_cache_range(vma,a,b) | 16 | #define flush_cache_range(vma,a,b) |
17 | #define flush_cache_page(vma,p,pfn) | 17 | #define flush_cache_page(vma,p,pfn) |
18 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 | ||
18 | #define flush_dcache_page(page) | 19 | #define flush_dcache_page(page) |
19 | #define flush_dcache_mmap_lock(mapping) | 20 | #define flush_dcache_mmap_lock(mapping) |
20 | #define flush_dcache_mmap_unlock(mapping) | 21 | #define flush_dcache_mmap_unlock(mapping) |
diff --git a/arch/ia64/include/asm/cacheflush.h b/arch/ia64/include/asm/cacheflush.h index c8ce2719fee8..429eefc93ee7 100644 --- a/arch/ia64/include/asm/cacheflush.h +++ b/arch/ia64/include/asm/cacheflush.h | |||
@@ -25,6 +25,7 @@ | |||
25 | #define flush_cache_vmap(start, end) do { } while (0) | 25 | #define flush_cache_vmap(start, end) do { } while (0) |
26 | #define flush_cache_vunmap(start, end) do { } while (0) | 26 | #define flush_cache_vunmap(start, end) do { } while (0) |
27 | 27 | ||
28 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 | ||
28 | #define flush_dcache_page(page) \ | 29 | #define flush_dcache_page(page) \ |
29 | do { \ | 30 | do { \ |
30 | clear_bit(PG_arch_1, &(page)->flags); \ | 31 | clear_bit(PG_arch_1, &(page)->flags); \ |
diff --git a/arch/m32r/include/asm/cacheflush.h b/arch/m32r/include/asm/cacheflush.h index 78587c958146..8e8e04516c39 100644 --- a/arch/m32r/include/asm/cacheflush.h +++ b/arch/m32r/include/asm/cacheflush.h | |||
@@ -12,6 +12,7 @@ extern void _flush_cache_copyback_all(void); | |||
12 | #define flush_cache_dup_mm(mm) do { } while (0) | 12 | #define flush_cache_dup_mm(mm) do { } while (0) |
13 | #define flush_cache_range(vma, start, end) do { } while (0) | 13 | #define flush_cache_range(vma, start, end) do { } while (0) |
14 | #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) | 14 | #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) |
15 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 | ||
15 | #define flush_dcache_page(page) do { } while (0) | 16 | #define flush_dcache_page(page) do { } while (0) |
16 | #define flush_dcache_mmap_lock(mapping) do { } while (0) | 17 | #define flush_dcache_mmap_lock(mapping) do { } while (0) |
17 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) | 18 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) |
@@ -33,6 +34,7 @@ extern void smp_flush_cache_all(void); | |||
33 | #define flush_cache_dup_mm(mm) do { } while (0) | 34 | #define flush_cache_dup_mm(mm) do { } while (0) |
34 | #define flush_cache_range(vma, start, end) do { } while (0) | 35 | #define flush_cache_range(vma, start, end) do { } while (0) |
35 | #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) | 36 | #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) |
37 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 | ||
36 | #define flush_dcache_page(page) do { } while (0) | 38 | #define flush_dcache_page(page) do { } while (0) |
37 | #define flush_dcache_mmap_lock(mapping) do { } while (0) | 39 | #define flush_dcache_mmap_lock(mapping) do { } while (0) |
38 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) | 40 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) |
@@ -46,6 +48,7 @@ extern void smp_flush_cache_all(void); | |||
46 | #define flush_cache_dup_mm(mm) do { } while (0) | 48 | #define flush_cache_dup_mm(mm) do { } while (0) |
47 | #define flush_cache_range(vma, start, end) do { } while (0) | 49 | #define flush_cache_range(vma, start, end) do { } while (0) |
48 | #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) | 50 | #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) |
51 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 | ||
49 | #define flush_dcache_page(page) do { } while (0) | 52 | #define flush_dcache_page(page) do { } while (0) |
50 | #define flush_dcache_mmap_lock(mapping) do { } while (0) | 53 | #define flush_dcache_mmap_lock(mapping) do { } while (0) |
51 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) | 54 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) |
diff --git a/arch/m68k/include/asm/cacheflush_mm.h b/arch/m68k/include/asm/cacheflush_mm.h index 16bf375fdbe1..73de7c89d8e0 100644 --- a/arch/m68k/include/asm/cacheflush_mm.h +++ b/arch/m68k/include/asm/cacheflush_mm.h | |||
@@ -128,6 +128,7 @@ static inline void __flush_page_to_ram(void *vaddr) | |||
128 | } | 128 | } |
129 | } | 129 | } |
130 | 130 | ||
131 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 | ||
131 | #define flush_dcache_page(page) __flush_page_to_ram(page_address(page)) | 132 | #define flush_dcache_page(page) __flush_page_to_ram(page_address(page)) |
132 | #define flush_dcache_mmap_lock(mapping) do { } while (0) | 133 | #define flush_dcache_mmap_lock(mapping) do { } while (0) |
133 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) | 134 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) |
diff --git a/arch/m68k/include/asm/cacheflush_no.h b/arch/m68k/include/asm/cacheflush_no.h index c65f00a94553..89f195656be7 100644 --- a/arch/m68k/include/asm/cacheflush_no.h +++ b/arch/m68k/include/asm/cacheflush_no.h | |||
@@ -12,6 +12,7 @@ | |||
12 | #define flush_cache_range(vma, start, end) __flush_cache_all() | 12 | #define flush_cache_range(vma, start, end) __flush_cache_all() |
13 | #define flush_cache_page(vma, vmaddr) do { } while (0) | 13 | #define flush_cache_page(vma, vmaddr) do { } while (0) |
14 | #define flush_dcache_range(start,len) __flush_cache_all() | 14 | #define flush_dcache_range(start,len) __flush_cache_all() |
15 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 | ||
15 | #define flush_dcache_page(page) do { } while (0) | 16 | #define flush_dcache_page(page) do { } while (0) |
16 | #define flush_dcache_mmap_lock(mapping) do { } while (0) | 17 | #define flush_dcache_mmap_lock(mapping) do { } while (0) |
17 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) | 18 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) |
diff --git a/arch/microblaze/include/asm/cacheflush.h b/arch/microblaze/include/asm/cacheflush.h index f989d6aad648..088076e657b3 100644 --- a/arch/microblaze/include/asm/cacheflush.h +++ b/arch/microblaze/include/asm/cacheflush.h | |||
@@ -37,6 +37,7 @@ | |||
37 | #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) | 37 | #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) |
38 | 38 | ||
39 | #define flush_dcache_range(start, end) __invalidate_dcache_range(start, end) | 39 | #define flush_dcache_range(start, end) __invalidate_dcache_range(start, end) |
40 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 | ||
40 | #define flush_dcache_page(page) do { } while (0) | 41 | #define flush_dcache_page(page) do { } while (0) |
41 | #define flush_dcache_mmap_lock(mapping) do { } while (0) | 42 | #define flush_dcache_mmap_lock(mapping) do { } while (0) |
42 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) | 43 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) |
diff --git a/arch/mips/include/asm/cacheflush.h b/arch/mips/include/asm/cacheflush.h index 03b1d69b142f..40bb9fde205f 100644 --- a/arch/mips/include/asm/cacheflush.h +++ b/arch/mips/include/asm/cacheflush.h | |||
@@ -38,6 +38,7 @@ extern void (*flush_cache_range)(struct vm_area_struct *vma, | |||
38 | extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn); | 38 | extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn); |
39 | extern void __flush_dcache_page(struct page *page); | 39 | extern void __flush_dcache_page(struct page *page); |
40 | 40 | ||
41 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 | ||
41 | static inline void flush_dcache_page(struct page *page) | 42 | static inline void flush_dcache_page(struct page *page) |
42 | { | 43 | { |
43 | if (cpu_has_dc_aliases || !cpu_has_ic_fills_f_dc) | 44 | if (cpu_has_dc_aliases || !cpu_has_ic_fills_f_dc) |
diff --git a/arch/mn10300/include/asm/cacheflush.h b/arch/mn10300/include/asm/cacheflush.h index 1a55d61f0d06..29e692f7f030 100644 --- a/arch/mn10300/include/asm/cacheflush.h +++ b/arch/mn10300/include/asm/cacheflush.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #define flush_cache_page(vma, vmaddr, pfn) do {} while (0) | 26 | #define flush_cache_page(vma, vmaddr, pfn) do {} while (0) |
27 | #define flush_cache_vmap(start, end) do {} while (0) | 27 | #define flush_cache_vmap(start, end) do {} while (0) |
28 | #define flush_cache_vunmap(start, end) do {} while (0) | 28 | #define flush_cache_vunmap(start, end) do {} while (0) |
29 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 | ||
29 | #define flush_dcache_page(page) do {} while (0) | 30 | #define flush_dcache_page(page) do {} while (0) |
30 | #define flush_dcache_mmap_lock(mapping) do {} while (0) | 31 | #define flush_dcache_mmap_lock(mapping) do {} while (0) |
31 | #define flush_dcache_mmap_unlock(mapping) do {} while (0) | 32 | #define flush_dcache_mmap_unlock(mapping) do {} while (0) |
diff --git a/arch/parisc/include/asm/cacheflush.h b/arch/parisc/include/asm/cacheflush.h index 724395143f26..7a73b615c23d 100644 --- a/arch/parisc/include/asm/cacheflush.h +++ b/arch/parisc/include/asm/cacheflush.h | |||
@@ -42,6 +42,7 @@ void flush_cache_mm(struct mm_struct *mm); | |||
42 | #define flush_cache_vmap(start, end) flush_cache_all() | 42 | #define flush_cache_vmap(start, end) flush_cache_all() |
43 | #define flush_cache_vunmap(start, end) flush_cache_all() | 43 | #define flush_cache_vunmap(start, end) flush_cache_all() |
44 | 44 | ||
45 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 | ||
45 | extern void flush_dcache_page(struct page *page); | 46 | extern void flush_dcache_page(struct page *page); |
46 | 47 | ||
47 | #define flush_dcache_mmap_lock(mapping) \ | 48 | #define flush_dcache_mmap_lock(mapping) \ |
diff --git a/arch/powerpc/include/asm/cacheflush.h b/arch/powerpc/include/asm/cacheflush.h index ba667a383b8c..ab9e402518e8 100644 --- a/arch/powerpc/include/asm/cacheflush.h +++ b/arch/powerpc/include/asm/cacheflush.h | |||
@@ -25,6 +25,7 @@ | |||
25 | #define flush_cache_vmap(start, end) do { } while (0) | 25 | #define flush_cache_vmap(start, end) do { } while (0) |
26 | #define flush_cache_vunmap(start, end) do { } while (0) | 26 | #define flush_cache_vunmap(start, end) do { } while (0) |
27 | 27 | ||
28 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 | ||
28 | extern void flush_dcache_page(struct page *page); | 29 | extern void flush_dcache_page(struct page *page); |
29 | #define flush_dcache_mmap_lock(mapping) do { } while (0) | 30 | #define flush_dcache_mmap_lock(mapping) do { } while (0) |
30 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) | 31 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) |
diff --git a/arch/s390/include/asm/cacheflush.h b/arch/s390/include/asm/cacheflush.h index 49d5af916d01..405cc97c6249 100644 --- a/arch/s390/include/asm/cacheflush.h +++ b/arch/s390/include/asm/cacheflush.h | |||
@@ -10,6 +10,7 @@ | |||
10 | #define flush_cache_dup_mm(mm) do { } while (0) | 10 | #define flush_cache_dup_mm(mm) do { } while (0) |
11 | #define flush_cache_range(vma, start, end) do { } while (0) | 11 | #define flush_cache_range(vma, start, end) do { } while (0) |
12 | #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) | 12 | #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) |
13 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 | ||
13 | #define flush_dcache_page(page) do { } while (0) | 14 | #define flush_dcache_page(page) do { } while (0) |
14 | #define flush_dcache_mmap_lock(mapping) do { } while (0) | 15 | #define flush_dcache_mmap_lock(mapping) do { } while (0) |
15 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) | 16 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) |
diff --git a/arch/score/include/asm/cacheflush.h b/arch/score/include/asm/cacheflush.h index 07cc8fc457cd..caaba24036e3 100644 --- a/arch/score/include/asm/cacheflush.h +++ b/arch/score/include/asm/cacheflush.h | |||
@@ -16,6 +16,7 @@ extern void flush_icache_range(unsigned long start, unsigned long end); | |||
16 | extern void flush_dcache_range(unsigned long start, unsigned long end); | 16 | extern void flush_dcache_range(unsigned long start, unsigned long end); |
17 | 17 | ||
18 | #define flush_cache_dup_mm(mm) do {} while (0) | 18 | #define flush_cache_dup_mm(mm) do {} while (0) |
19 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 | ||
19 | #define flush_dcache_page(page) do {} while (0) | 20 | #define flush_dcache_page(page) do {} while (0) |
20 | #define flush_dcache_mmap_lock(mapping) do {} while (0) | 21 | #define flush_dcache_mmap_lock(mapping) do {} while (0) |
21 | #define flush_dcache_mmap_unlock(mapping) do {} while (0) | 22 | #define flush_dcache_mmap_unlock(mapping) do {} while (0) |
diff --git a/arch/sh/include/asm/cacheflush.h b/arch/sh/include/asm/cacheflush.h index c29918f3c819..dda96eb3e7c0 100644 --- a/arch/sh/include/asm/cacheflush.h +++ b/arch/sh/include/asm/cacheflush.h | |||
@@ -42,6 +42,7 @@ extern void flush_cache_page(struct vm_area_struct *vma, | |||
42 | unsigned long addr, unsigned long pfn); | 42 | unsigned long addr, unsigned long pfn); |
43 | extern void flush_cache_range(struct vm_area_struct *vma, | 43 | extern void flush_cache_range(struct vm_area_struct *vma, |
44 | unsigned long start, unsigned long end); | 44 | unsigned long start, unsigned long end); |
45 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 | ||
45 | extern void flush_dcache_page(struct page *page); | 46 | extern void flush_dcache_page(struct page *page); |
46 | extern void flush_icache_range(unsigned long start, unsigned long end); | 47 | extern void flush_icache_range(unsigned long start, unsigned long end); |
47 | extern void flush_icache_page(struct vm_area_struct *vma, | 48 | extern void flush_icache_page(struct vm_area_struct *vma, |
diff --git a/arch/sparc/include/asm/cacheflush_32.h b/arch/sparc/include/asm/cacheflush_32.h index 68ac10910271..2e468773f250 100644 --- a/arch/sparc/include/asm/cacheflush_32.h +++ b/arch/sparc/include/asm/cacheflush_32.h | |||
@@ -75,6 +75,7 @@ BTFIXUPDEF_CALL(void, flush_sig_insns, struct mm_struct *, unsigned long) | |||
75 | 75 | ||
76 | extern void sparc_flush_page_to_ram(struct page *page); | 76 | extern void sparc_flush_page_to_ram(struct page *page); |
77 | 77 | ||
78 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 | ||
78 | #define flush_dcache_page(page) sparc_flush_page_to_ram(page) | 79 | #define flush_dcache_page(page) sparc_flush_page_to_ram(page) |
79 | #define flush_dcache_mmap_lock(mapping) do { } while (0) | 80 | #define flush_dcache_mmap_lock(mapping) do { } while (0) |
80 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) | 81 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) |
diff --git a/arch/sparc/include/asm/cacheflush_64.h b/arch/sparc/include/asm/cacheflush_64.h index c43321729b3b..b95384033e89 100644 --- a/arch/sparc/include/asm/cacheflush_64.h +++ b/arch/sparc/include/asm/cacheflush_64.h | |||
@@ -37,6 +37,7 @@ extern void flush_dcache_page_all(struct mm_struct *mm, struct page *page); | |||
37 | #endif | 37 | #endif |
38 | 38 | ||
39 | extern void __flush_dcache_range(unsigned long start, unsigned long end); | 39 | extern void __flush_dcache_range(unsigned long start, unsigned long end); |
40 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 | ||
40 | extern void flush_dcache_page(struct page *page); | 41 | extern void flush_dcache_page(struct page *page); |
41 | 42 | ||
42 | #define flush_icache_page(vma, pg) do { } while(0) | 43 | #define flush_icache_page(vma, pg) do { } while(0) |
diff --git a/arch/x86/include/asm/cacheflush.h b/arch/x86/include/asm/cacheflush.h index b54f6afe7ec4..9076add593a8 100644 --- a/arch/x86/include/asm/cacheflush.h +++ b/arch/x86/include/asm/cacheflush.h | |||
@@ -12,6 +12,7 @@ static inline void flush_cache_range(struct vm_area_struct *vma, | |||
12 | unsigned long start, unsigned long end) { } | 12 | unsigned long start, unsigned long end) { } |
13 | static inline void flush_cache_page(struct vm_area_struct *vma, | 13 | static inline void flush_cache_page(struct vm_area_struct *vma, |
14 | unsigned long vmaddr, unsigned long pfn) { } | 14 | unsigned long vmaddr, unsigned long pfn) { } |
15 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 | ||
15 | static inline void flush_dcache_page(struct page *page) { } | 16 | static inline void flush_dcache_page(struct page *page) { } |
16 | static inline void flush_dcache_mmap_lock(struct address_space *mapping) { } | 17 | static inline void flush_dcache_mmap_lock(struct address_space *mapping) { } |
17 | static inline void flush_dcache_mmap_unlock(struct address_space *mapping) { } | 18 | static inline void flush_dcache_mmap_unlock(struct address_space *mapping) { } |
diff --git a/arch/xtensa/include/asm/cacheflush.h b/arch/xtensa/include/asm/cacheflush.h index b7b8fbe47c77..a508f2f73bd7 100644 --- a/arch/xtensa/include/asm/cacheflush.h +++ b/arch/xtensa/include/asm/cacheflush.h | |||
@@ -101,6 +101,7 @@ static inline void __invalidate_icache_page_alias(unsigned long virt, | |||
101 | #define flush_cache_vmap(start,end) flush_cache_all() | 101 | #define flush_cache_vmap(start,end) flush_cache_all() |
102 | #define flush_cache_vunmap(start,end) flush_cache_all() | 102 | #define flush_cache_vunmap(start,end) flush_cache_all() |
103 | 103 | ||
104 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 | ||
104 | extern void flush_dcache_page(struct page*); | 105 | extern void flush_dcache_page(struct page*); |
105 | extern void flush_cache_range(struct vm_area_struct*, ulong, ulong); | 106 | extern void flush_cache_range(struct vm_area_struct*, ulong, ulong); |
106 | extern void flush_cache_page(struct vm_area_struct*, unsigned long, unsigned long); | 107 | extern void flush_cache_page(struct vm_area_struct*, unsigned long, unsigned long); |
diff --git a/block/blk-core.c b/block/blk-core.c index 71da5111120c..718897e6d37f 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
@@ -2358,6 +2358,25 @@ void blk_rq_bio_prep(struct request_queue *q, struct request *rq, | |||
2358 | rq->rq_disk = bio->bi_bdev->bd_disk; | 2358 | rq->rq_disk = bio->bi_bdev->bd_disk; |
2359 | } | 2359 | } |
2360 | 2360 | ||
2361 | #if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE | ||
2362 | /** | ||
2363 | * rq_flush_dcache_pages - Helper function to flush all pages in a request | ||
2364 | * @rq: the request to be flushed | ||
2365 | * | ||
2366 | * Description: | ||
2367 | * Flush all pages in @rq. | ||
2368 | */ | ||
2369 | void rq_flush_dcache_pages(struct request *rq) | ||
2370 | { | ||
2371 | struct req_iterator iter; | ||
2372 | struct bio_vec *bvec; | ||
2373 | |||
2374 | rq_for_each_segment(bvec, rq, iter) | ||
2375 | flush_dcache_page(bvec->bv_page); | ||
2376 | } | ||
2377 | EXPORT_SYMBOL_GPL(rq_flush_dcache_pages); | ||
2378 | #endif | ||
2379 | |||
2361 | /** | 2380 | /** |
2362 | * blk_lld_busy - Check if underlying low-level drivers of a device are busy | 2381 | * blk_lld_busy - Check if underlying low-level drivers of a device are busy |
2363 | * @q : the queue of the device being checked | 2382 | * @q : the queue of the device being checked |
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 8ca17a3e96ea..64e2b379a350 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c | |||
@@ -59,12 +59,14 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr, | |||
59 | for (; nsect > 0; nsect--, block++, buf += tr->blksize) | 59 | for (; nsect > 0; nsect--, block++, buf += tr->blksize) |
60 | if (tr->readsect(dev, block, buf)) | 60 | if (tr->readsect(dev, block, buf)) |
61 | return -EIO; | 61 | return -EIO; |
62 | rq_flush_dcache_pages(req); | ||
62 | return 0; | 63 | return 0; |
63 | 64 | ||
64 | case WRITE: | 65 | case WRITE: |
65 | if (!tr->writesect) | 66 | if (!tr->writesect) |
66 | return -EIO; | 67 | return -EIO; |
67 | 68 | ||
69 | rq_flush_dcache_pages(req); | ||
68 | for (; nsect > 0; nsect--, block++, buf += tr->blksize) | 70 | for (; nsect > 0; nsect--, block++, buf += tr->blksize) |
69 | if (tr->writesect(dev, block, buf)) | 71 | if (tr->writesect(dev, block, buf)) |
70 | return -EIO; | 72 | return -EIO; |
@@ -1393,6 +1393,18 @@ void bio_check_pages_dirty(struct bio *bio) | |||
1393 | } | 1393 | } |
1394 | } | 1394 | } |
1395 | 1395 | ||
1396 | #if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE | ||
1397 | void bio_flush_dcache_pages(struct bio *bi) | ||
1398 | { | ||
1399 | int i; | ||
1400 | struct bio_vec *bvec; | ||
1401 | |||
1402 | bio_for_each_segment(bvec, bi, i) | ||
1403 | flush_dcache_page(bvec->bv_page); | ||
1404 | } | ||
1405 | EXPORT_SYMBOL(bio_flush_dcache_pages); | ||
1406 | #endif | ||
1407 | |||
1396 | /** | 1408 | /** |
1397 | * bio_endio - end I/O on a bio | 1409 | * bio_endio - end I/O on a bio |
1398 | * @bio: bio | 1410 | * @bio: bio |
diff --git a/include/asm-generic/cacheflush.h b/include/asm-generic/cacheflush.h index ba4ec39a1131..57b5c3c82e86 100644 --- a/include/asm-generic/cacheflush.h +++ b/include/asm-generic/cacheflush.h | |||
@@ -13,6 +13,7 @@ | |||
13 | #define flush_cache_dup_mm(mm) do { } while (0) | 13 | #define flush_cache_dup_mm(mm) do { } while (0) |
14 | #define flush_cache_range(vma, start, end) do { } while (0) | 14 | #define flush_cache_range(vma, start, end) do { } while (0) |
15 | #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) | 15 | #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) |
16 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 | ||
16 | #define flush_dcache_page(page) do { } while (0) | 17 | #define flush_dcache_page(page) do { } while (0) |
17 | #define flush_dcache_mmap_lock(mapping) do { } while (0) | 18 | #define flush_dcache_mmap_lock(mapping) do { } while (0) |
18 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) | 19 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) |
diff --git a/include/linux/bio.h b/include/linux/bio.h index 474792b825d0..7fc5606e6ea5 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h | |||
@@ -391,6 +391,18 @@ extern struct bio *bio_copy_kern(struct request_queue *, void *, unsigned int, | |||
391 | gfp_t, int); | 391 | gfp_t, int); |
392 | extern void bio_set_pages_dirty(struct bio *bio); | 392 | extern void bio_set_pages_dirty(struct bio *bio); |
393 | extern void bio_check_pages_dirty(struct bio *bio); | 393 | extern void bio_check_pages_dirty(struct bio *bio); |
394 | |||
395 | #ifndef ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE | ||
396 | # error "You should define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE for your platform" | ||
397 | #endif | ||
398 | #if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE | ||
399 | extern void bio_flush_dcache_pages(struct bio *bi); | ||
400 | #else | ||
401 | static inline void bio_flush_dcache_pages(struct bio *bi) | ||
402 | { | ||
403 | } | ||
404 | #endif | ||
405 | |||
394 | extern struct bio *bio_copy_user(struct request_queue *, struct rq_map_data *, | 406 | extern struct bio *bio_copy_user(struct request_queue *, struct rq_map_data *, |
395 | unsigned long, unsigned int, int, gfp_t); | 407 | unsigned long, unsigned int, int, gfp_t); |
396 | extern struct bio *bio_copy_user_iov(struct request_queue *, | 408 | extern struct bio *bio_copy_user_iov(struct request_queue *, |
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 1cc02972fbe2..e727f6c44c44 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
@@ -752,6 +752,17 @@ struct req_iterator { | |||
752 | #define rq_iter_last(rq, _iter) \ | 752 | #define rq_iter_last(rq, _iter) \ |
753 | (_iter.bio->bi_next == NULL && _iter.i == _iter.bio->bi_vcnt-1) | 753 | (_iter.bio->bi_next == NULL && _iter.i == _iter.bio->bi_vcnt-1) |
754 | 754 | ||
755 | #ifndef ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE | ||
756 | # error "You should define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE for your platform" | ||
757 | #endif | ||
758 | #if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE | ||
759 | extern void rq_flush_dcache_pages(struct request *rq); | ||
760 | #else | ||
761 | static inline void rq_flush_dcache_pages(struct request *rq) | ||
762 | { | ||
763 | } | ||
764 | #endif | ||
765 | |||
755 | extern int blk_register_queue(struct gendisk *disk); | 766 | extern int blk_register_queue(struct gendisk *disk); |
756 | extern void blk_unregister_queue(struct gendisk *disk); | 767 | extern void blk_unregister_queue(struct gendisk *disk); |
757 | extern void register_disk(struct gendisk *dev); | 768 | extern void register_disk(struct gendisk *dev); |