aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/mm/cache-sh7705.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2009-08-21 04:23:14 -0400
committerPaul Mundt <lethal@linux-sh.org>2009-08-21 04:23:14 -0400
commitf26b2a562b46ab186c8383993ab1332673ac4a47 (patch)
tree5cf52089da5ca762c07cf6c1364a6aa411fb3038 /arch/sh/mm/cache-sh7705.c
parentf9bd71f255b4349c4f9f596863161fd5182f67fa (diff)
sh: Make cache flushers SMP-aware.
This does a bit of rework for making the cache flushers SMP-aware. The function pointer-based flushers are renamed to local variants with the exported interface being commonly implemented and wrapping as necessary. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/mm/cache-sh7705.c')
-rw-r--r--arch/sh/mm/cache-sh7705.c67
1 files changed, 22 insertions, 45 deletions
diff --git a/arch/sh/mm/cache-sh7705.c b/arch/sh/mm/cache-sh7705.c
index f1d5c803c04b..6293f57fa888 100644
--- a/arch/sh/mm/cache-sh7705.c
+++ b/arch/sh/mm/cache-sh7705.c
@@ -64,8 +64,14 @@ static inline void cache_wback_all(void)
64 * 64 *
65 * 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.
66 */ 66 */
67static void sh7705_flush_icache_range(unsigned long start, unsigned long end) 67static void sh7705_flush_icache_range(void *args)
68{ 68{
69 struct flusher_data *data = args;
70 unsigned long start, end;
71
72 start = data->addr1;
73 end = data->addr2;
74
69 __flush_wback_region((void *)start, end - start); 75 __flush_wback_region((void *)start, end - start);
70} 76}
71 77
@@ -127,7 +133,7 @@ static void __flush_dcache_page(unsigned long phys)
127 * Write back & invalidate the D-cache of the page. 133 * Write back & invalidate the D-cache of the page.
128 * (To avoid "alias" issues) 134 * (To avoid "alias" issues)
129 */ 135 */
130static void sh7705_flush_dcache_page(struct page *page) 136static void sh7705_flush_dcache_page(void *page)
131{ 137{
132 struct address_space *mapping = page_mapping(page); 138 struct address_space *mapping = page_mapping(page);
133 139
@@ -137,7 +143,7 @@ static void sh7705_flush_dcache_page(struct page *page)
137 __flush_dcache_page(PHYSADDR(page_address(page))); 143 __flush_dcache_page(PHYSADDR(page_address(page)));
138} 144}
139 145
140static void sh7705_flush_cache_all(void) 146static void sh7705_flush_cache_all(void *args)
141{ 147{
142 unsigned long flags; 148 unsigned long flags;
143 149
@@ -149,44 +155,16 @@ static void sh7705_flush_cache_all(void)
149 local_irq_restore(flags); 155 local_irq_restore(flags);
150} 156}
151 157
152static void sh7705_flush_cache_mm(struct mm_struct *mm)
153{
154 /* Is there any good way? */
155 /* XXX: possibly call flush_cache_range for each vm area */
156 flush_cache_all();
157}
158
159/*
160 * Write back and invalidate D-caches.
161 *
162 * START, END: Virtual Address (U0 address)
163 *
164 * NOTE: We need to flush the _physical_ page entry.
165 * Flushing the cache lines for U0 only isn't enough.
166 * We need to flush for P1 too, which may contain aliases.
167 */
168static void sh7705_flush_cache_range(struct vm_area_struct *vma,
169 unsigned long start, unsigned long end)
170{
171
172 /*
173 * We could call flush_cache_page for the pages of these range,
174 * but it's not efficient (scan the caches all the time...).
175 *
176 * We can't use A-bit magic, as there's the case we don't have
177 * valid entry on TLB.
178 */
179 flush_cache_all();
180}
181
182/* 158/*
183 * Write back and invalidate I/D-caches for the page. 159 * Write back and invalidate I/D-caches for the page.
184 * 160 *
185 * ADDRESS: Virtual Address (U0 address) 161 * ADDRESS: Virtual Address (U0 address)
186 */ 162 */
187static void sh7705_flush_cache_page(struct vm_area_struct *vma, 163static void sh7705_flush_cache_page(void *args)
188 unsigned long address, unsigned long pfn)
189{ 164{
165 struct flusher_data *data = args;
166 unsigned long pfn = data->addr2;
167
190 __flush_dcache_page(pfn << PAGE_SHIFT); 168 __flush_dcache_page(pfn << PAGE_SHIFT);
191} 169}
192 170
@@ -198,20 +176,19 @@ static void sh7705_flush_cache_page(struct vm_area_struct *vma,
198 * Not entirely sure why this is necessary on SH3 with 32K cache but 176 * Not entirely sure why this is necessary on SH3 with 32K cache but
199 * without it we get occasional "Memory fault" when loading a program. 177 * without it we get occasional "Memory fault" when loading a program.
200 */ 178 */
201static void sh7705_flush_icache_page(struct vm_area_struct *vma, 179static void sh7705_flush_icache_page(void *page)
202 struct page *page)
203{ 180{
204 __flush_purge_region(page_address(page), PAGE_SIZE); 181 __flush_purge_region(page_address(page), PAGE_SIZE);
205} 182}
206 183
207void __init sh7705_cache_init(void) 184void __init sh7705_cache_init(void)
208{ 185{
209 flush_icache_range = sh7705_flush_icache_range; 186 local_flush_icache_range = sh7705_flush_icache_range;
210 flush_dcache_page = sh7705_flush_dcache_page; 187 local_flush_dcache_page = sh7705_flush_dcache_page;
211 flush_cache_all = sh7705_flush_cache_all; 188 local_flush_cache_all = sh7705_flush_cache_all;
212 flush_cache_mm = sh7705_flush_cache_mm; 189 local_flush_cache_mm = sh7705_flush_cache_all;
213 flush_cache_dup_mm = sh7705_flush_cache_mm; 190 local_flush_cache_dup_mm = sh7705_flush_cache_all;
214 flush_cache_range = sh7705_flush_cache_range; 191 local_flush_cache_range = sh7705_flush_cache_all;
215 flush_cache_page = sh7705_flush_cache_page; 192 local_flush_cache_page = sh7705_flush_cache_page;
216 flush_icache_page = sh7705_flush_icache_page; 193 local_flush_icache_page = sh7705_flush_icache_page;
217} 194}