diff options
author | Jeff Garzik <jeff@garzik.org> | 2007-02-17 15:11:43 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-02-17 15:11:43 -0500 |
commit | f630fe2817601314b2eb7ca5ddc23c7834646731 (patch) | |
tree | 3bfb4939b7bbc3859575ca8b58fa3f929b015941 /arch/sh/mm/cache-sh4.c | |
parent | 48c871c1f6a7c7044dd76774fb469e65c7e2e4e8 (diff) | |
parent | 8a03d9a498eaf02c8a118752050a5154852c13bf (diff) |
Merge branch 'master' into upstream
Diffstat (limited to 'arch/sh/mm/cache-sh4.c')
-rw-r--r-- | arch/sh/mm/cache-sh4.c | 77 |
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(¤t_cpu_data.icache); |
91 | compute_alias(&cpu_data->dcache); | 91 | compute_alias(¤t_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 | */ |
240 | void flush_dcache_page(struct page *page) | 244 | void 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 | ||
278 | void flush_dcache_all(void) | 289 | void 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 = ¤t_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 = ¤t_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 = ¤t_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 = ¤t_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; |