diff options
Diffstat (limited to 'arch/sh/mm/cache-sh7705.c')
-rw-r--r-- | arch/sh/mm/cache-sh7705.c | 72 |
1 files changed, 34 insertions, 38 deletions
diff --git a/arch/sh/mm/cache-sh7705.c b/arch/sh/mm/cache-sh7705.c index 22dacc778823..2cadee2037ac 100644 --- a/arch/sh/mm/cache-sh7705.c +++ b/arch/sh/mm/cache-sh7705.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/mman.h> | 13 | #include <linux/mman.h> |
14 | #include <linux/mm.h> | 14 | #include <linux/mm.h> |
15 | #include <linux/fs.h> | ||
15 | #include <linux/threads.h> | 16 | #include <linux/threads.h> |
16 | #include <asm/addrspace.h> | 17 | #include <asm/addrspace.h> |
17 | #include <asm/page.h> | 18 | #include <asm/page.h> |
@@ -63,15 +64,21 @@ static inline void cache_wback_all(void) | |||
63 | * | 64 | * |
64 | * Called from kernel/module.c:sys_init_module and routine for a.out format. | 65 | * Called from kernel/module.c:sys_init_module and routine for a.out format. |
65 | */ | 66 | */ |
66 | void flush_icache_range(unsigned long start, unsigned long end) | 67 | static void sh7705_flush_icache_range(void *args) |
67 | { | 68 | { |
69 | struct flusher_data *data = args; | ||
70 | unsigned long start, end; | ||
71 | |||
72 | start = data->addr1; | ||
73 | end = data->addr2; | ||
74 | |||
68 | __flush_wback_region((void *)start, end - start); | 75 | __flush_wback_region((void *)start, end - start); |
69 | } | 76 | } |
70 | 77 | ||
71 | /* | 78 | /* |
72 | * Writeback&Invalidate the D-cache of the page | 79 | * Writeback&Invalidate the D-cache of the page |
73 | */ | 80 | */ |
74 | static void __uses_jump_to_uncached __flush_dcache_page(unsigned long phys) | 81 | static void __flush_dcache_page(unsigned long phys) |
75 | { | 82 | { |
76 | unsigned long ways, waysize, addrstart; | 83 | unsigned long ways, waysize, addrstart; |
77 | unsigned long flags; | 84 | unsigned long flags; |
@@ -126,13 +133,18 @@ static void __uses_jump_to_uncached __flush_dcache_page(unsigned long phys) | |||
126 | * Write back & invalidate the D-cache of the page. | 133 | * Write back & invalidate the D-cache of the page. |
127 | * (To avoid "alias" issues) | 134 | * (To avoid "alias" issues) |
128 | */ | 135 | */ |
129 | void flush_dcache_page(struct page *page) | 136 | static void sh7705_flush_dcache_page(void *arg) |
130 | { | 137 | { |
131 | if (test_bit(PG_mapped, &page->flags)) | 138 | struct page *page = arg; |
139 | struct address_space *mapping = page_mapping(page); | ||
140 | |||
141 | if (mapping && !mapping_mapped(mapping)) | ||
142 | set_bit(PG_dcache_dirty, &page->flags); | ||
143 | else | ||
132 | __flush_dcache_page(PHYSADDR(page_address(page))); | 144 | __flush_dcache_page(PHYSADDR(page_address(page))); |
133 | } | 145 | } |
134 | 146 | ||
135 | void __uses_jump_to_uncached flush_cache_all(void) | 147 | static void sh7705_flush_cache_all(void *args) |
136 | { | 148 | { |
137 | unsigned long flags; | 149 | unsigned long flags; |
138 | 150 | ||
@@ -144,44 +156,16 @@ void __uses_jump_to_uncached flush_cache_all(void) | |||
144 | local_irq_restore(flags); | 156 | local_irq_restore(flags); |
145 | } | 157 | } |
146 | 158 | ||
147 | void flush_cache_mm(struct mm_struct *mm) | ||
148 | { | ||
149 | /* Is there any good way? */ | ||
150 | /* XXX: possibly call flush_cache_range for each vm area */ | ||
151 | flush_cache_all(); | ||
152 | } | ||
153 | |||
154 | /* | ||
155 | * Write back and invalidate D-caches. | ||
156 | * | ||
157 | * START, END: Virtual Address (U0 address) | ||
158 | * | ||
159 | * NOTE: We need to flush the _physical_ page entry. | ||
160 | * Flushing the cache lines for U0 only isn't enough. | ||
161 | * We need to flush for P1 too, which may contain aliases. | ||
162 | */ | ||
163 | void flush_cache_range(struct vm_area_struct *vma, unsigned long start, | ||
164 | unsigned long end) | ||
165 | { | ||
166 | |||
167 | /* | ||
168 | * We could call flush_cache_page for the pages of these range, | ||
169 | * but it's not efficient (scan the caches all the time...). | ||
170 | * | ||
171 | * We can't use A-bit magic, as there's the case we don't have | ||
172 | * valid entry on TLB. | ||
173 | */ | ||
174 | flush_cache_all(); | ||
175 | } | ||
176 | |||
177 | /* | 159 | /* |
178 | * Write back and invalidate I/D-caches for the page. | 160 | * Write back and invalidate I/D-caches for the page. |
179 | * | 161 | * |
180 | * ADDRESS: Virtual Address (U0 address) | 162 | * ADDRESS: Virtual Address (U0 address) |
181 | */ | 163 | */ |
182 | void flush_cache_page(struct vm_area_struct *vma, unsigned long address, | 164 | static void sh7705_flush_cache_page(void *args) |
183 | unsigned long pfn) | ||
184 | { | 165 | { |
166 | struct flusher_data *data = args; | ||
167 | unsigned long pfn = data->addr2; | ||
168 | |||
185 | __flush_dcache_page(pfn << PAGE_SHIFT); | 169 | __flush_dcache_page(pfn << PAGE_SHIFT); |
186 | } | 170 | } |
187 | 171 | ||
@@ -193,7 +177,19 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long address, | |||
193 | * Not entirely sure why this is necessary on SH3 with 32K cache but | 177 | * Not entirely sure why this is necessary on SH3 with 32K cache but |
194 | * without it we get occasional "Memory fault" when loading a program. | 178 | * without it we get occasional "Memory fault" when loading a program. |
195 | */ | 179 | */ |
196 | void flush_icache_page(struct vm_area_struct *vma, struct page *page) | 180 | static void sh7705_flush_icache_page(void *page) |
197 | { | 181 | { |
198 | __flush_purge_region(page_address(page), PAGE_SIZE); | 182 | __flush_purge_region(page_address(page), PAGE_SIZE); |
199 | } | 183 | } |
184 | |||
185 | void __init sh7705_cache_init(void) | ||
186 | { | ||
187 | local_flush_icache_range = sh7705_flush_icache_range; | ||
188 | local_flush_dcache_page = sh7705_flush_dcache_page; | ||
189 | local_flush_cache_all = sh7705_flush_cache_all; | ||
190 | local_flush_cache_mm = sh7705_flush_cache_all; | ||
191 | local_flush_cache_dup_mm = sh7705_flush_cache_all; | ||
192 | local_flush_cache_range = sh7705_flush_cache_all; | ||
193 | local_flush_cache_page = sh7705_flush_cache_page; | ||
194 | local_flush_icache_page = sh7705_flush_icache_page; | ||
195 | } | ||