diff options
author | Zoltan Menyhart <Zoltan.Menyhart@bull.net> | 2005-06-03 08:36:00 -0400 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2005-07-12 18:33:18 -0400 |
commit | 08357f82d4decc48bbfd39ae30d5fe0754f7f576 (patch) | |
tree | c8516a8f208e1cb253bd33f41857b0699104b130 /arch/ia64/kernel/setup.c | |
parent | 60a762b6a6dec17cc4339b60154902fd04c2f9f2 (diff) |
[IA64] improve flush_icache_range()
Check with PAL to see what the i-cache line size is for
each level of the cache, and so use the correct stride
when flushing the cache.
Acked-by: David Mosberger
Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64/kernel/setup.c')
-rw-r--r-- | arch/ia64/kernel/setup.c | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 2693e1522d7c..7fc891aca446 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c | |||
@@ -20,6 +20,7 @@ | |||
20 | * 02/01/00 R.Seth fixed get_cpuinfo for SMP | 20 | * 02/01/00 R.Seth fixed get_cpuinfo for SMP |
21 | * 01/07/99 S.Eranian added the support for command line argument | 21 | * 01/07/99 S.Eranian added the support for command line argument |
22 | * 06/24/99 W.Drummond added boot_cpu_data. | 22 | * 06/24/99 W.Drummond added boot_cpu_data. |
23 | * 05/28/05 Z. Menyhart Dynamic stride size for "flush_icache_range()" | ||
23 | */ | 24 | */ |
24 | #include <linux/config.h> | 25 | #include <linux/config.h> |
25 | #include <linux/module.h> | 26 | #include <linux/module.h> |
@@ -83,6 +84,13 @@ EXPORT_SYMBOL(io_space); | |||
83 | unsigned int num_io_spaces; | 84 | unsigned int num_io_spaces; |
84 | 85 | ||
85 | /* | 86 | /* |
87 | * "flush_icache_range()" needs to know what processor dependent stride size to use | ||
88 | * when it makes i-cache(s) coherent with d-caches. | ||
89 | */ | ||
90 | #define I_CACHE_STRIDE_SHIFT 5 /* Safest way to go: 32 bytes by 32 bytes */ | ||
91 | unsigned long ia64_i_cache_stride_shift = ~0; | ||
92 | |||
93 | /* | ||
86 | * The merge_mask variable needs to be set to (max(iommu_page_size(iommu)) - 1). This | 94 | * The merge_mask variable needs to be set to (max(iommu_page_size(iommu)) - 1). This |
87 | * mask specifies a mask of address bits that must be 0 in order for two buffers to be | 95 | * mask specifies a mask of address bits that must be 0 in order for two buffers to be |
88 | * mergeable by the I/O MMU (i.e., the end address of the first buffer and the start | 96 | * mergeable by the I/O MMU (i.e., the end address of the first buffer and the start |
@@ -626,6 +634,12 @@ setup_per_cpu_areas (void) | |||
626 | /* start_kernel() requires this... */ | 634 | /* start_kernel() requires this... */ |
627 | } | 635 | } |
628 | 636 | ||
637 | /* | ||
638 | * Calculate the max. cache line size. | ||
639 | * | ||
640 | * In addition, the minimum of the i-cache stride sizes is calculated for | ||
641 | * "flush_icache_range()". | ||
642 | */ | ||
629 | static void | 643 | static void |
630 | get_max_cacheline_size (void) | 644 | get_max_cacheline_size (void) |
631 | { | 645 | { |
@@ -639,6 +653,8 @@ get_max_cacheline_size (void) | |||
639 | printk(KERN_ERR "%s: ia64_pal_cache_summary() failed (status=%ld)\n", | 653 | printk(KERN_ERR "%s: ia64_pal_cache_summary() failed (status=%ld)\n", |
640 | __FUNCTION__, status); | 654 | __FUNCTION__, status); |
641 | max = SMP_CACHE_BYTES; | 655 | max = SMP_CACHE_BYTES; |
656 | /* Safest setup for "flush_icache_range()" */ | ||
657 | ia64_i_cache_stride_shift = I_CACHE_STRIDE_SHIFT; | ||
642 | goto out; | 658 | goto out; |
643 | } | 659 | } |
644 | 660 | ||
@@ -647,14 +663,31 @@ get_max_cacheline_size (void) | |||
647 | &cci); | 663 | &cci); |
648 | if (status != 0) { | 664 | if (status != 0) { |
649 | printk(KERN_ERR | 665 | printk(KERN_ERR |
650 | "%s: ia64_pal_cache_config_info(l=%lu) failed (status=%ld)\n", | 666 | "%s: ia64_pal_cache_config_info(l=%lu, 2) failed (status=%ld)\n", |
651 | __FUNCTION__, l, status); | 667 | __FUNCTION__, l, status); |
652 | max = SMP_CACHE_BYTES; | 668 | max = SMP_CACHE_BYTES; |
669 | /* The safest setup for "flush_icache_range()" */ | ||
670 | cci.pcci_stride = I_CACHE_STRIDE_SHIFT; | ||
671 | cci.pcci_unified = 1; | ||
653 | } | 672 | } |
654 | line_size = 1 << cci.pcci_line_size; | 673 | line_size = 1 << cci.pcci_line_size; |
655 | if (line_size > max) | 674 | if (line_size > max) |
656 | max = line_size; | 675 | max = line_size; |
657 | } | 676 | if (!cci.pcci_unified) { |
677 | status = ia64_pal_cache_config_info(l, | ||
678 | /* cache_type (instruction)= */ 1, | ||
679 | &cci); | ||
680 | if (status != 0) { | ||
681 | printk(KERN_ERR | ||
682 | "%s: ia64_pal_cache_config_info(l=%lu, 1) failed (status=%ld)\n", | ||
683 | __FUNCTION__, l, status); | ||
684 | /* The safest setup for "flush_icache_range()" */ | ||
685 | cci.pcci_stride = I_CACHE_STRIDE_SHIFT; | ||
686 | } | ||
687 | } | ||
688 | if (cci.pcci_stride < ia64_i_cache_stride_shift) | ||
689 | ia64_i_cache_stride_shift = cci.pcci_stride; | ||
690 | } | ||
658 | out: | 691 | out: |
659 | if (max > ia64_max_cacheline_size) | 692 | if (max > ia64_max_cacheline_size) |
660 | ia64_max_cacheline_size = max; | 693 | ia64_max_cacheline_size = max; |