aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/mm/cache-sh4.c
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2007-02-17 15:11:43 -0500
committerJeff Garzik <jeff@garzik.org>2007-02-17 15:11:43 -0500
commitf630fe2817601314b2eb7ca5ddc23c7834646731 (patch)
tree3bfb4939b7bbc3859575ca8b58fa3f929b015941 /arch/sh/mm/cache-sh4.c
parent48c871c1f6a7c7044dd76774fb469e65c7e2e4e8 (diff)
parent8a03d9a498eaf02c8a118752050a5154852c13bf (diff)
Merge branch 'master' into upstream
Diffstat (limited to 'arch/sh/mm/cache-sh4.c')
-rw-r--r--arch/sh/mm/cache-sh4.c77
1 files changed, 44 insertions, 33 deletions
diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c
index c6955157c989..e0cd4b7f4aeb 100644
--- a/arch/sh/mm/cache-sh4.c
+++ b/arch/sh/mm/cache-sh4.c
@@ -54,21 +54,21 @@ static void __init emit_cache_params(void)
54 ctrl_inl(CCN_CVR), 54 ctrl_inl(CCN_CVR),
55 ctrl_inl(CCN_PRR)); 55 ctrl_inl(CCN_PRR));
56 printk("I-cache : n_ways=%d n_sets=%d way_incr=%d\n", 56 printk("I-cache : n_ways=%d n_sets=%d way_incr=%d\n",
57 cpu_data->icache.ways, 57 current_cpu_data.icache.ways,
58 cpu_data->icache.sets, 58 current_cpu_data.icache.sets,
59 cpu_data->icache.way_incr); 59 current_cpu_data.icache.way_incr);
60 printk("I-cache : entry_mask=0x%08x alias_mask=0x%08x n_aliases=%d\n", 60 printk("I-cache : entry_mask=0x%08x alias_mask=0x%08x n_aliases=%d\n",
61 cpu_data->icache.entry_mask, 61 current_cpu_data.icache.entry_mask,
62 cpu_data->icache.alias_mask, 62 current_cpu_data.icache.alias_mask,
63 cpu_data->icache.n_aliases); 63 current_cpu_data.icache.n_aliases);
64 printk("D-cache : n_ways=%d n_sets=%d way_incr=%d\n", 64 printk("D-cache : n_ways=%d n_sets=%d way_incr=%d\n",
65 cpu_data->dcache.ways, 65 current_cpu_data.dcache.ways,
66 cpu_data->dcache.sets, 66 current_cpu_data.dcache.sets,
67 cpu_data->dcache.way_incr); 67 current_cpu_data.dcache.way_incr);
68 printk("D-cache : entry_mask=0x%08x alias_mask=0x%08x n_aliases=%d\n", 68 printk("D-cache : entry_mask=0x%08x alias_mask=0x%08x n_aliases=%d\n",
69 cpu_data->dcache.entry_mask, 69 current_cpu_data.dcache.entry_mask,
70 cpu_data->dcache.alias_mask, 70 current_cpu_data.dcache.alias_mask,
71 cpu_data->dcache.n_aliases); 71 current_cpu_data.dcache.n_aliases);
72 72
73 if (!__flush_dcache_segment_fn) 73 if (!__flush_dcache_segment_fn)
74 panic("unknown number of cache ways\n"); 74 panic("unknown number of cache ways\n");
@@ -87,10 +87,10 @@ void __init p3_cache_init(void)
87{ 87{
88 int i; 88 int i;
89 89
90 compute_alias(&cpu_data->icache); 90 compute_alias(&current_cpu_data.icache);
91 compute_alias(&cpu_data->dcache); 91 compute_alias(&current_cpu_data.dcache);
92 92
93 switch (cpu_data->dcache.ways) { 93 switch (current_cpu_data.dcache.ways) {
94 case 1: 94 case 1:
95 __flush_dcache_segment_fn = __flush_dcache_segment_1way; 95 __flush_dcache_segment_fn = __flush_dcache_segment_1way;
96 break; 96 break;
@@ -110,7 +110,7 @@ void __init p3_cache_init(void)
110 if (ioremap_page_range(P3SEG, P3SEG + (PAGE_SIZE * 4), 0, PAGE_KERNEL)) 110 if (ioremap_page_range(P3SEG, P3SEG + (PAGE_SIZE * 4), 0, PAGE_KERNEL))
111 panic("%s failed.", __FUNCTION__); 111 panic("%s failed.", __FUNCTION__);
112 112
113 for (i = 0; i < cpu_data->dcache.n_aliases; i++) 113 for (i = 0; i < current_cpu_data.dcache.n_aliases; i++)
114 mutex_init(&p3map_mutex[i]); 114 mutex_init(&p3map_mutex[i]);
115} 115}
116 116
@@ -200,13 +200,14 @@ void flush_cache_sigtramp(unsigned long addr)
200 : /* no output */ 200 : /* no output */
201 : "m" (__m(v))); 201 : "m" (__m(v)));
202 202
203 index = CACHE_IC_ADDRESS_ARRAY | (v & cpu_data->icache.entry_mask); 203 index = CACHE_IC_ADDRESS_ARRAY |
204 (v & current_cpu_data.icache.entry_mask);
204 205
205 local_irq_save(flags); 206 local_irq_save(flags);
206 jump_to_P2(); 207 jump_to_P2();
207 208
208 for (i = 0; i < cpu_data->icache.ways; 209 for (i = 0; i < current_cpu_data.icache.ways;
209 i++, index += cpu_data->icache.way_incr) 210 i++, index += current_cpu_data.icache.way_incr)
210 ctrl_outl(0, index); /* Clear out Valid-bit */ 211 ctrl_outl(0, index); /* Clear out Valid-bit */
211 212
212 back_to_P1(); 213 back_to_P1();
@@ -223,7 +224,7 @@ static inline void flush_cache_4096(unsigned long start,
223 * All types of SH-4 require PC to be in P2 to operate on the I-cache. 224 * All types of SH-4 require PC to be in P2 to operate on the I-cache.
224 * Some types of SH-4 require PC to be in P2 to operate on the D-cache. 225 * Some types of SH-4 require PC to be in P2 to operate on the D-cache.
225 */ 226 */
226 if ((cpu_data->flags & CPU_HAS_P2_FLUSH_BUG) || 227 if ((current_cpu_data.flags & CPU_HAS_P2_FLUSH_BUG) ||
227 (start < CACHE_OC_ADDRESS_ARRAY)) 228 (start < CACHE_OC_ADDRESS_ARRAY))
228 exec_offset = 0x20000000; 229 exec_offset = 0x20000000;
229 230
@@ -236,16 +237,26 @@ static inline void flush_cache_4096(unsigned long start,
236/* 237/*
237 * Write back & invalidate the D-cache of the page. 238 * Write back & invalidate the D-cache of the page.
238 * (To avoid "alias" issues) 239 * (To avoid "alias" issues)
240 *
241 * This uses a lazy write-back on UP, which is explicitly
242 * disabled on SMP.
239 */ 243 */
240void flush_dcache_page(struct page *page) 244void flush_dcache_page(struct page *page)
241{ 245{
242 if (test_bit(PG_mapped, &page->flags)) { 246#ifndef CONFIG_SMP
247 struct address_space *mapping = page_mapping(page);
248
249 if (mapping && !mapping_mapped(mapping))
250 set_bit(PG_dcache_dirty, &page->flags);
251 else
252#endif
253 {
243 unsigned long phys = PHYSADDR(page_address(page)); 254 unsigned long phys = PHYSADDR(page_address(page));
244 unsigned long addr = CACHE_OC_ADDRESS_ARRAY; 255 unsigned long addr = CACHE_OC_ADDRESS_ARRAY;
245 int i, n; 256 int i, n;
246 257
247 /* Loop all the D-cache */ 258 /* Loop all the D-cache */
248 n = cpu_data->dcache.n_aliases; 259 n = current_cpu_data.dcache.n_aliases;
249 for (i = 0; i < n; i++, addr += 4096) 260 for (i = 0; i < n; i++, addr += 4096)
250 flush_cache_4096(addr, phys); 261 flush_cache_4096(addr, phys);
251 } 262 }
@@ -277,7 +288,7 @@ static inline void flush_icache_all(void)
277 288
278void flush_dcache_all(void) 289void flush_dcache_all(void)
279{ 290{
280 (*__flush_dcache_segment_fn)(0UL, cpu_data->dcache.way_size); 291 (*__flush_dcache_segment_fn)(0UL, current_cpu_data.dcache.way_size);
281 wmb(); 292 wmb();
282} 293}
283 294
@@ -291,8 +302,8 @@ static void __flush_cache_mm(struct mm_struct *mm, unsigned long start,
291 unsigned long end) 302 unsigned long end)
292{ 303{
293 unsigned long d = 0, p = start & PAGE_MASK; 304 unsigned long d = 0, p = start & PAGE_MASK;
294 unsigned long alias_mask = cpu_data->dcache.alias_mask; 305 unsigned long alias_mask = current_cpu_data.dcache.alias_mask;
295 unsigned long n_aliases = cpu_data->dcache.n_aliases; 306 unsigned long n_aliases = current_cpu_data.dcache.n_aliases;
296 unsigned long select_bit; 307 unsigned long select_bit;
297 unsigned long all_aliases_mask; 308 unsigned long all_aliases_mask;
298 unsigned long addr_offset; 309 unsigned long addr_offset;
@@ -379,7 +390,7 @@ void flush_cache_mm(struct mm_struct *mm)
379 * If cache is only 4k-per-way, there are never any 'aliases'. Since 390 * If cache is only 4k-per-way, there are never any 'aliases'. Since
380 * the cache is physically tagged, the data can just be left in there. 391 * the cache is physically tagged, the data can just be left in there.
381 */ 392 */
382 if (cpu_data->dcache.n_aliases == 0) 393 if (current_cpu_data.dcache.n_aliases == 0)
383 return; 394 return;
384 395
385 /* 396 /*
@@ -416,7 +427,7 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long address,
416 unsigned long phys = pfn << PAGE_SHIFT; 427 unsigned long phys = pfn << PAGE_SHIFT;
417 unsigned int alias_mask; 428 unsigned int alias_mask;
418 429
419 alias_mask = cpu_data->dcache.alias_mask; 430 alias_mask = current_cpu_data.dcache.alias_mask;
420 431
421 /* We only need to flush D-cache when we have alias */ 432 /* We only need to flush D-cache when we have alias */
422 if ((address^phys) & alias_mask) { 433 if ((address^phys) & alias_mask) {
@@ -430,7 +441,7 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long address,
430 phys); 441 phys);
431 } 442 }
432 443
433 alias_mask = cpu_data->icache.alias_mask; 444 alias_mask = current_cpu_data.icache.alias_mask;
434 if (vma->vm_flags & VM_EXEC) { 445 if (vma->vm_flags & VM_EXEC) {
435 /* 446 /*
436 * Evict entries from the portion of the cache from which code 447 * Evict entries from the portion of the cache from which code
@@ -462,7 +473,7 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
462 * If cache is only 4k-per-way, there are never any 'aliases'. Since 473 * If cache is only 4k-per-way, there are never any 'aliases'. Since
463 * the cache is physically tagged, the data can just be left in there. 474 * the cache is physically tagged, the data can just be left in there.
464 */ 475 */
465 if (cpu_data->dcache.n_aliases == 0) 476 if (current_cpu_data.dcache.n_aliases == 0)
466 return; 477 return;
467 478
468 /* 479 /*
@@ -523,7 +534,7 @@ static void __flush_cache_4096(unsigned long addr, unsigned long phys,
523 unsigned long a, ea, p; 534 unsigned long a, ea, p;
524 unsigned long temp_pc; 535 unsigned long temp_pc;
525 536
526 dcache = &cpu_data->dcache; 537 dcache = &current_cpu_data.dcache;
527 /* Write this way for better assembly. */ 538 /* Write this way for better assembly. */
528 way_count = dcache->ways; 539 way_count = dcache->ways;
529 way_incr = dcache->way_incr; 540 way_incr = dcache->way_incr;
@@ -598,7 +609,7 @@ static void __flush_dcache_segment_1way(unsigned long start,
598 base_addr = ((base_addr >> 16) << 16); 609 base_addr = ((base_addr >> 16) << 16);
599 base_addr |= start; 610 base_addr |= start;
600 611
601 dcache = &cpu_data->dcache; 612 dcache = &current_cpu_data.dcache;
602 linesz = dcache->linesz; 613 linesz = dcache->linesz;
603 way_incr = dcache->way_incr; 614 way_incr = dcache->way_incr;
604 way_size = dcache->way_size; 615 way_size = dcache->way_size;
@@ -640,7 +651,7 @@ static void __flush_dcache_segment_2way(unsigned long start,
640 base_addr = ((base_addr >> 16) << 16); 651 base_addr = ((base_addr >> 16) << 16);
641 base_addr |= start; 652 base_addr |= start;
642 653
643 dcache = &cpu_data->dcache; 654 dcache = &current_cpu_data.dcache;
644 linesz = dcache->linesz; 655 linesz = dcache->linesz;
645 way_incr = dcache->way_incr; 656 way_incr = dcache->way_incr;
646 way_size = dcache->way_size; 657 way_size = dcache->way_size;
@@ -699,7 +710,7 @@ static void __flush_dcache_segment_4way(unsigned long start,
699 base_addr = ((base_addr >> 16) << 16); 710 base_addr = ((base_addr >> 16) << 16);
700 base_addr |= start; 711 base_addr |= start;
701 712
702 dcache = &cpu_data->dcache; 713 dcache = &current_cpu_data.dcache;
703 linesz = dcache->linesz; 714 linesz = dcache->linesz;
704 way_incr = dcache->way_incr; 715 way_incr = dcache->way_incr;
705 way_size = dcache->way_size; 716 way_size = dcache->way_size;