diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-19 14:37:22 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-19 14:37:22 -0400 |
commit | 1d3c6ff44ad4b5f113602e153026a338f0f9b3ff (patch) | |
tree | 1e1f2932634fc6d0e4acfe68496c1c727b83a13e /arch/arm/mm | |
parent | 7c7cbaf5b82c418cd3b1dcf718f71d0e6057e639 (diff) | |
parent | 717e7c2672e37253a4d3aa70e4716b5b0a658761 (diff) |
Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm: (224 commits)
ARM: remove 'select GENERIC_TIME'
ARM: 6136/1: ARCH_REQUIRE_GPIOLIB selects GENERIC_GPIO
ARM: 6074/1: oprofile: convert from sysdev to platform device
ARM: 6073/1: oprofile: remove old files and update KConfig
ARM: 6072/1: oprofile: use perf-events framework as backend
ARM: 6071/1: perf-events: allow modules to query the number of hardware counters
ARM: 6070/1: perf-events: add support for xscale PMUs
ARM: 6069/1: perf-events: use numeric ID to identify PMU
ARM: 6064/1: pmu: register IRQs at runtime
ARM: Optionally allow ARMv6 to use 'normal, bufferable' memory for DMA
ARM: 6134/1: Handle instruction cache maintenance fault properly
ARM: nwfpe: allow debugging output to be configured at runtime
ARM: rename mach_cpu_disable() to platform_cpu_disable()
ARM: 6132/1: PL330: Add common core driver
ARM: 6094/1: Extend cache-l2x0 to support the 16-way PL310
ARM: Move memory mapping into mmu.c
ARM: Ensure meminfo is sorted prior to sanity_check_meminfo
ARM: Remove useless linux/bootmem.h includes
ARM: convert /proc/cpu/aligment to seq_file
arm: use asm-generic/scatterlist.h
...
Diffstat (limited to 'arch/arm/mm')
-rw-r--r-- | arch/arm/mm/Kconfig | 26 | ||||
-rw-r--r-- | arch/arm/mm/abort-ev7.S | 21 | ||||
-rw-r--r-- | arch/arm/mm/alignment.c | 53 | ||||
-rw-r--r-- | arch/arm/mm/cache-l2x0.c | 39 | ||||
-rw-r--r-- | arch/arm/mm/copypage-fa.c | 2 | ||||
-rw-r--r-- | arch/arm/mm/fault-armv.c | 2 | ||||
-rw-r--r-- | arch/arm/mm/fault.c | 5 | ||||
-rw-r--r-- | arch/arm/mm/init.c | 34 | ||||
-rw-r--r-- | arch/arm/mm/mm.h | 3 | ||||
-rw-r--r-- | arch/arm/mm/mmu.c | 39 |
10 files changed, 149 insertions, 75 deletions
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 5bd7c89a6045..346ae14824a5 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig | |||
@@ -572,6 +572,8 @@ config CPU_TLB_V6 | |||
572 | config CPU_TLB_V7 | 572 | config CPU_TLB_V7 |
573 | bool | 573 | bool |
574 | 574 | ||
575 | config VERIFY_PERMISSION_FAULT | ||
576 | bool | ||
575 | endif | 577 | endif |
576 | 578 | ||
577 | config CPU_HAS_ASID | 579 | config CPU_HAS_ASID |
@@ -760,7 +762,8 @@ config CACHE_FEROCEON_L2_WRITETHROUGH | |||
760 | config CACHE_L2X0 | 762 | config CACHE_L2X0 |
761 | bool "Enable the L2x0 outer cache controller" | 763 | bool "Enable the L2x0 outer cache controller" |
762 | depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \ | 764 | depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \ |
763 | REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX || ARCH_NOMADIK || ARCH_OMAP4 | 765 | REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX || \ |
766 | ARCH_NOMADIK || ARCH_OMAP4 || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 | ||
764 | default y | 767 | default y |
765 | select OUTER_CACHE | 768 | select OUTER_CACHE |
766 | select OUTER_CACHE_SYNC | 769 | select OUTER_CACHE_SYNC |
@@ -769,7 +772,7 @@ config CACHE_L2X0 | |||
769 | 772 | ||
770 | config CACHE_TAUROS2 | 773 | config CACHE_TAUROS2 |
771 | bool "Enable the Tauros2 L2 cache controller" | 774 | bool "Enable the Tauros2 L2 cache controller" |
772 | depends on ARCH_DOVE | 775 | depends on (ARCH_DOVE || ARCH_MMP) |
773 | default y | 776 | default y |
774 | select OUTER_CACHE | 777 | select OUTER_CACHE |
775 | help | 778 | help |
@@ -789,6 +792,25 @@ config ARM_L1_CACHE_SHIFT | |||
789 | default 6 if ARM_L1_CACHE_SHIFT_6 | 792 | default 6 if ARM_L1_CACHE_SHIFT_6 |
790 | default 5 | 793 | default 5 |
791 | 794 | ||
795 | config ARM_DMA_MEM_BUFFERABLE | ||
796 | bool "Use non-cacheable memory for DMA" if CPU_V6 && !CPU_V7 | ||
797 | default y if CPU_V6 || CPU_V7 | ||
798 | help | ||
799 | Historically, the kernel has used strongly ordered mappings to | ||
800 | provide DMA coherent memory. With the advent of ARMv7, mapping | ||
801 | memory with differing types results in unpredictable behaviour, | ||
802 | so on these CPUs, this option is forced on. | ||
803 | |||
804 | Multiple mappings with differing attributes is also unpredictable | ||
805 | on ARMv6 CPUs, but since they do not have aggressive speculative | ||
806 | prefetch, no harm appears to occur. | ||
807 | |||
808 | However, drivers may be missing the necessary barriers for ARMv6, | ||
809 | and therefore turning this on may result in unpredictable driver | ||
810 | behaviour. Therefore, we offer this as an option. | ||
811 | |||
812 | You are recommended say 'Y' here and debug any affected drivers. | ||
813 | |||
792 | config ARCH_HAS_BARRIERS | 814 | config ARCH_HAS_BARRIERS |
793 | bool | 815 | bool |
794 | help | 816 | help |
diff --git a/arch/arm/mm/abort-ev7.S b/arch/arm/mm/abort-ev7.S index 2e6dc040c654..ec88b157d3bb 100644 --- a/arch/arm/mm/abort-ev7.S +++ b/arch/arm/mm/abort-ev7.S | |||
@@ -29,5 +29,26 @@ ENTRY(v7_early_abort) | |||
29 | * V6 code adjusts the returned DFSR. | 29 | * V6 code adjusts the returned DFSR. |
30 | * New designs should not need to patch up faults. | 30 | * New designs should not need to patch up faults. |
31 | */ | 31 | */ |
32 | |||
33 | #if defined(CONFIG_VERIFY_PERMISSION_FAULT) | ||
34 | /* | ||
35 | * Detect erroneous permission failures and fix | ||
36 | */ | ||
37 | ldr r3, =0x40d @ On permission fault | ||
38 | and r3, r1, r3 | ||
39 | cmp r3, #0x0d | ||
40 | movne pc, lr | ||
41 | |||
42 | mcr p15, 0, r0, c7, c8, 0 @ Retranslate FAR | ||
43 | isb | ||
44 | mrc p15, 0, r2, c7, c4, 0 @ Read the PAR | ||
45 | and r3, r2, #0x7b @ On translation fault | ||
46 | cmp r3, #0x0b | ||
47 | movne pc, lr | ||
48 | bic r1, r1, #0xf @ Fix up FSR FS[5:0] | ||
49 | and r2, r2, #0x7e | ||
50 | orr r1, r1, r2, LSR #1 | ||
51 | #endif | ||
52 | |||
32 | mov pc, lr | 53 | mov pc, lr |
33 | ENDPROC(v7_early_abort) | 54 | ENDPROC(v7_early_abort) |
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index a2ab51fa73e2..6f98c358989a 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
18 | #include <linux/string.h> | 18 | #include <linux/string.h> |
19 | #include <linux/proc_fs.h> | 19 | #include <linux/proc_fs.h> |
20 | #include <linux/seq_file.h> | ||
20 | #include <linux/init.h> | 21 | #include <linux/init.h> |
21 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
22 | #include <linux/uaccess.h> | 23 | #include <linux/uaccess.h> |
@@ -94,36 +95,29 @@ static const char *usermode_action[] = { | |||
94 | "signal+warn" | 95 | "signal+warn" |
95 | }; | 96 | }; |
96 | 97 | ||
97 | static int | 98 | static int alignment_proc_show(struct seq_file *m, void *v) |
98 | proc_alignment_read(char *page, char **start, off_t off, int count, int *eof, | ||
99 | void *data) | ||
100 | { | 99 | { |
101 | char *p = page; | 100 | seq_printf(m, "User:\t\t%lu\n", ai_user); |
102 | int len; | 101 | seq_printf(m, "System:\t\t%lu\n", ai_sys); |
103 | 102 | seq_printf(m, "Skipped:\t%lu\n", ai_skipped); | |
104 | p += sprintf(p, "User:\t\t%lu\n", ai_user); | 103 | seq_printf(m, "Half:\t\t%lu\n", ai_half); |
105 | p += sprintf(p, "System:\t\t%lu\n", ai_sys); | 104 | seq_printf(m, "Word:\t\t%lu\n", ai_word); |
106 | p += sprintf(p, "Skipped:\t%lu\n", ai_skipped); | ||
107 | p += sprintf(p, "Half:\t\t%lu\n", ai_half); | ||
108 | p += sprintf(p, "Word:\t\t%lu\n", ai_word); | ||
109 | if (cpu_architecture() >= CPU_ARCH_ARMv5TE) | 105 | if (cpu_architecture() >= CPU_ARCH_ARMv5TE) |
110 | p += sprintf(p, "DWord:\t\t%lu\n", ai_dword); | 106 | seq_printf(m, "DWord:\t\t%lu\n", ai_dword); |
111 | p += sprintf(p, "Multi:\t\t%lu\n", ai_multi); | 107 | seq_printf(m, "Multi:\t\t%lu\n", ai_multi); |
112 | p += sprintf(p, "User faults:\t%i (%s)\n", ai_usermode, | 108 | seq_printf(m, "User faults:\t%i (%s)\n", ai_usermode, |
113 | usermode_action[ai_usermode]); | 109 | usermode_action[ai_usermode]); |
114 | 110 | ||
115 | len = (p - page) - off; | 111 | return 0; |
116 | if (len < 0) | 112 | } |
117 | len = 0; | ||
118 | |||
119 | *eof = (len <= count) ? 1 : 0; | ||
120 | *start = page + off; | ||
121 | 113 | ||
122 | return len; | 114 | static int alignment_proc_open(struct inode *inode, struct file *file) |
115 | { | ||
116 | return single_open(file, alignment_proc_show, NULL); | ||
123 | } | 117 | } |
124 | 118 | ||
125 | static int proc_alignment_write(struct file *file, const char __user *buffer, | 119 | static ssize_t alignment_proc_write(struct file *file, const char __user *buffer, |
126 | unsigned long count, void *data) | 120 | size_t count, loff_t *pos) |
127 | { | 121 | { |
128 | char mode; | 122 | char mode; |
129 | 123 | ||
@@ -136,6 +130,13 @@ static int proc_alignment_write(struct file *file, const char __user *buffer, | |||
136 | return count; | 130 | return count; |
137 | } | 131 | } |
138 | 132 | ||
133 | static const struct file_operations alignment_proc_fops = { | ||
134 | .open = alignment_proc_open, | ||
135 | .read = seq_read, | ||
136 | .llseek = seq_lseek, | ||
137 | .release = single_release, | ||
138 | .write = alignment_proc_write, | ||
139 | }; | ||
139 | #endif /* CONFIG_PROC_FS */ | 140 | #endif /* CONFIG_PROC_FS */ |
140 | 141 | ||
141 | union offset_union { | 142 | union offset_union { |
@@ -901,12 +902,10 @@ static int __init alignment_init(void) | |||
901 | #ifdef CONFIG_PROC_FS | 902 | #ifdef CONFIG_PROC_FS |
902 | struct proc_dir_entry *res; | 903 | struct proc_dir_entry *res; |
903 | 904 | ||
904 | res = create_proc_entry("cpu/alignment", S_IWUSR | S_IRUGO, NULL); | 905 | res = proc_create("cpu/alignment", S_IWUSR | S_IRUGO, NULL, |
906 | &alignment_proc_fops); | ||
905 | if (!res) | 907 | if (!res) |
906 | return -ENOMEM; | 908 | return -ENOMEM; |
907 | |||
908 | res->read_proc = proc_alignment_read; | ||
909 | res->write_proc = proc_alignment_write; | ||
910 | #endif | 909 | #endif |
911 | 910 | ||
912 | /* | 911 | /* |
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 21ad68ba22ba..9819869d2bc9 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c | |||
@@ -27,6 +27,7 @@ | |||
27 | 27 | ||
28 | static void __iomem *l2x0_base; | 28 | static void __iomem *l2x0_base; |
29 | static DEFINE_SPINLOCK(l2x0_lock); | 29 | static DEFINE_SPINLOCK(l2x0_lock); |
30 | static uint32_t l2x0_way_mask; /* Bitmask of active ways */ | ||
30 | 31 | ||
31 | static inline void cache_wait(void __iomem *reg, unsigned long mask) | 32 | static inline void cache_wait(void __iomem *reg, unsigned long mask) |
32 | { | 33 | { |
@@ -108,8 +109,8 @@ static inline void l2x0_inv_all(void) | |||
108 | 109 | ||
109 | /* invalidate all ways */ | 110 | /* invalidate all ways */ |
110 | spin_lock_irqsave(&l2x0_lock, flags); | 111 | spin_lock_irqsave(&l2x0_lock, flags); |
111 | writel(0xff, l2x0_base + L2X0_INV_WAY); | 112 | writel(l2x0_way_mask, l2x0_base + L2X0_INV_WAY); |
112 | cache_wait(l2x0_base + L2X0_INV_WAY, 0xff); | 113 | cache_wait(l2x0_base + L2X0_INV_WAY, l2x0_way_mask); |
113 | cache_sync(); | 114 | cache_sync(); |
114 | spin_unlock_irqrestore(&l2x0_lock, flags); | 115 | spin_unlock_irqrestore(&l2x0_lock, flags); |
115 | } | 116 | } |
@@ -208,9 +209,37 @@ static void l2x0_flush_range(unsigned long start, unsigned long end) | |||
208 | void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) | 209 | void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) |
209 | { | 210 | { |
210 | __u32 aux; | 211 | __u32 aux; |
212 | __u32 cache_id; | ||
213 | int ways; | ||
214 | const char *type; | ||
211 | 215 | ||
212 | l2x0_base = base; | 216 | l2x0_base = base; |
213 | 217 | ||
218 | cache_id = readl(l2x0_base + L2X0_CACHE_ID); | ||
219 | aux = readl(l2x0_base + L2X0_AUX_CTRL); | ||
220 | |||
221 | /* Determine the number of ways */ | ||
222 | switch (cache_id & L2X0_CACHE_ID_PART_MASK) { | ||
223 | case L2X0_CACHE_ID_PART_L310: | ||
224 | if (aux & (1 << 16)) | ||
225 | ways = 16; | ||
226 | else | ||
227 | ways = 8; | ||
228 | type = "L310"; | ||
229 | break; | ||
230 | case L2X0_CACHE_ID_PART_L210: | ||
231 | ways = (aux >> 13) & 0xf; | ||
232 | type = "L210"; | ||
233 | break; | ||
234 | default: | ||
235 | /* Assume unknown chips have 8 ways */ | ||
236 | ways = 8; | ||
237 | type = "L2x0 series"; | ||
238 | break; | ||
239 | } | ||
240 | |||
241 | l2x0_way_mask = (1 << ways) - 1; | ||
242 | |||
214 | /* | 243 | /* |
215 | * Check if l2x0 controller is already enabled. | 244 | * Check if l2x0 controller is already enabled. |
216 | * If you are booting from non-secure mode | 245 | * If you are booting from non-secure mode |
@@ -219,8 +248,6 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) | |||
219 | if (!(readl(l2x0_base + L2X0_CTRL) & 1)) { | 248 | if (!(readl(l2x0_base + L2X0_CTRL) & 1)) { |
220 | 249 | ||
221 | /* l2x0 controller is disabled */ | 250 | /* l2x0 controller is disabled */ |
222 | |||
223 | aux = readl(l2x0_base + L2X0_AUX_CTRL); | ||
224 | aux &= aux_mask; | 251 | aux &= aux_mask; |
225 | aux |= aux_val; | 252 | aux |= aux_val; |
226 | writel(aux, l2x0_base + L2X0_AUX_CTRL); | 253 | writel(aux, l2x0_base + L2X0_AUX_CTRL); |
@@ -236,5 +263,7 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) | |||
236 | outer_cache.flush_range = l2x0_flush_range; | 263 | outer_cache.flush_range = l2x0_flush_range; |
237 | outer_cache.sync = l2x0_cache_sync; | 264 | outer_cache.sync = l2x0_cache_sync; |
238 | 265 | ||
239 | printk(KERN_INFO "L2X0 cache controller enabled\n"); | 266 | printk(KERN_INFO "%s cache controller enabled\n", type); |
267 | printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x\n", | ||
268 | ways, cache_id, aux); | ||
240 | } | 269 | } |
diff --git a/arch/arm/mm/copypage-fa.c b/arch/arm/mm/copypage-fa.c index b2a6008b0111..d2852e1635b1 100644 --- a/arch/arm/mm/copypage-fa.c +++ b/arch/arm/mm/copypage-fa.c | |||
@@ -40,7 +40,7 @@ fa_copy_user_page(void *kto, const void *kfrom) | |||
40 | } | 40 | } |
41 | 41 | ||
42 | void fa_copy_user_highpage(struct page *to, struct page *from, | 42 | void fa_copy_user_highpage(struct page *to, struct page *from, |
43 | unsigned long vaddr) | 43 | unsigned long vaddr, struct vm_area_struct *vma) |
44 | { | 44 | { |
45 | void *kto, *kfrom; | 45 | void *kto, *kfrom; |
46 | 46 | ||
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index 0d414c28eb2c..9b906dec1ca1 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c | |||
@@ -134,8 +134,6 @@ make_coherent(struct address_space *mapping, struct vm_area_struct *vma, | |||
134 | flush_dcache_mmap_unlock(mapping); | 134 | flush_dcache_mmap_unlock(mapping); |
135 | if (aliases) | 135 | if (aliases) |
136 | do_adjust_pte(vma, addr, pfn, ptep); | 136 | do_adjust_pte(vma, addr, pfn, ptep); |
137 | else | ||
138 | flush_cache_page(vma, addr, pfn); | ||
139 | } | 137 | } |
140 | 138 | ||
141 | /* | 139 | /* |
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 9d40c341e07e..92f5801f99c1 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c | |||
@@ -463,7 +463,12 @@ static struct fsr_info { | |||
463 | { do_bad, SIGILL, BUS_ADRALN, "alignment exception" }, | 463 | { do_bad, SIGILL, BUS_ADRALN, "alignment exception" }, |
464 | { do_bad, SIGKILL, 0, "terminal exception" }, | 464 | { do_bad, SIGKILL, 0, "terminal exception" }, |
465 | { do_bad, SIGILL, BUS_ADRALN, "alignment exception" }, | 465 | { do_bad, SIGILL, BUS_ADRALN, "alignment exception" }, |
466 | /* Do we need runtime check ? */ | ||
467 | #if __LINUX_ARM_ARCH__ < 6 | ||
466 | { do_bad, SIGBUS, 0, "external abort on linefetch" }, | 468 | { do_bad, SIGBUS, 0, "external abort on linefetch" }, |
469 | #else | ||
470 | { do_translation_fault, SIGSEGV, SEGV_MAPERR, "I-cache maintenance fault" }, | ||
471 | #endif | ||
467 | { do_translation_fault, SIGSEGV, SEGV_MAPERR, "section translation fault" }, | 472 | { do_translation_fault, SIGSEGV, SEGV_MAPERR, "section translation fault" }, |
468 | { do_bad, SIGBUS, 0, "external abort on linefetch" }, | 473 | { do_bad, SIGBUS, 0, "external abort on linefetch" }, |
469 | { do_page_fault, SIGSEGV, SEGV_MAPERR, "page translation fault" }, | 474 | { do_page_fault, SIGSEGV, SEGV_MAPERR, "page translation fault" }, |
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 0ed29bfeba1c..1ba6cf5a2c02 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <linux/mman.h> | 15 | #include <linux/mman.h> |
16 | #include <linux/nodemask.h> | 16 | #include <linux/nodemask.h> |
17 | #include <linux/initrd.h> | 17 | #include <linux/initrd.h> |
18 | #include <linux/sort.h> | ||
19 | #include <linux/highmem.h> | 18 | #include <linux/highmem.h> |
20 | #include <linux/gfp.h> | 19 | #include <linux/gfp.h> |
21 | 20 | ||
@@ -224,20 +223,6 @@ static int __init check_initrd(struct meminfo *mi) | |||
224 | return initrd_node; | 223 | return initrd_node; |
225 | } | 224 | } |
226 | 225 | ||
227 | static inline void map_memory_bank(struct membank *bank) | ||
228 | { | ||
229 | #ifdef CONFIG_MMU | ||
230 | struct map_desc map; | ||
231 | |||
232 | map.pfn = bank_pfn_start(bank); | ||
233 | map.virtual = __phys_to_virt(bank_phys_start(bank)); | ||
234 | map.length = bank_phys_size(bank); | ||
235 | map.type = MT_MEMORY; | ||
236 | |||
237 | create_mapping(&map); | ||
238 | #endif | ||
239 | } | ||
240 | |||
241 | static void __init bootmem_init_node(int node, struct meminfo *mi, | 226 | static void __init bootmem_init_node(int node, struct meminfo *mi, |
242 | unsigned long start_pfn, unsigned long end_pfn) | 227 | unsigned long start_pfn, unsigned long end_pfn) |
243 | { | 228 | { |
@@ -247,16 +232,6 @@ static void __init bootmem_init_node(int node, struct meminfo *mi, | |||
247 | int i; | 232 | int i; |
248 | 233 | ||
249 | /* | 234 | /* |
250 | * Map the memory banks for this node. | ||
251 | */ | ||
252 | for_each_nodebank(i, mi, node) { | ||
253 | struct membank *bank = &mi->bank[i]; | ||
254 | |||
255 | if (!bank->highmem) | ||
256 | map_memory_bank(bank); | ||
257 | } | ||
258 | |||
259 | /* | ||
260 | * Allocate the bootmem bitmap page. | 235 | * Allocate the bootmem bitmap page. |
261 | */ | 236 | */ |
262 | boot_pages = bootmem_bootmap_pages(end_pfn - start_pfn); | 237 | boot_pages = bootmem_bootmap_pages(end_pfn - start_pfn); |
@@ -385,21 +360,12 @@ static void arm_memory_present(struct meminfo *mi, int node) | |||
385 | } | 360 | } |
386 | #endif | 361 | #endif |
387 | 362 | ||
388 | static int __init meminfo_cmp(const void *_a, const void *_b) | ||
389 | { | ||
390 | const struct membank *a = _a, *b = _b; | ||
391 | long cmp = bank_pfn_start(a) - bank_pfn_start(b); | ||
392 | return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; | ||
393 | } | ||
394 | |||
395 | void __init bootmem_init(void) | 363 | void __init bootmem_init(void) |
396 | { | 364 | { |
397 | struct meminfo *mi = &meminfo; | 365 | struct meminfo *mi = &meminfo; |
398 | unsigned long min, max_low, max_high; | 366 | unsigned long min, max_low, max_high; |
399 | int node, initrd_node; | 367 | int node, initrd_node; |
400 | 368 | ||
401 | sort(&mi->bank, mi->nr_banks, sizeof(mi->bank[0]), meminfo_cmp, NULL); | ||
402 | |||
403 | /* | 369 | /* |
404 | * Locate which node contains the ramdisk image, if any. | 370 | * Locate which node contains the ramdisk image, if any. |
405 | */ | 371 | */ |
diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index a888363398f8..815d08eecbb0 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h | |||
@@ -28,10 +28,7 @@ extern void __flush_dcache_page(struct address_space *mapping, struct page *page | |||
28 | 28 | ||
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | struct map_desc; | ||
32 | struct meminfo; | ||
33 | struct pglist_data; | 31 | struct pglist_data; |
34 | 32 | ||
35 | void __init create_mapping(struct map_desc *md); | ||
36 | void __init bootmem_init(void); | 33 | void __init bootmem_init(void); |
37 | void reserve_node_zero(struct pglist_data *pgdat); | 34 | void reserve_node_zero(struct pglist_data *pgdat); |
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 241c24a1c18f..e7113d0b8168 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/bootmem.h> | 14 | #include <linux/bootmem.h> |
15 | #include <linux/mman.h> | 15 | #include <linux/mman.h> |
16 | #include <linux/nodemask.h> | 16 | #include <linux/nodemask.h> |
17 | #include <linux/sort.h> | ||
17 | 18 | ||
18 | #include <asm/cputype.h> | 19 | #include <asm/cputype.h> |
19 | #include <asm/mach-types.h> | 20 | #include <asm/mach-types.h> |
@@ -603,7 +604,7 @@ static void __init create_36bit_mapping(struct map_desc *md, | |||
603 | * offsets, and we take full advantage of sections and | 604 | * offsets, and we take full advantage of sections and |
604 | * supersections. | 605 | * supersections. |
605 | */ | 606 | */ |
606 | void __init create_mapping(struct map_desc *md) | 607 | static void __init create_mapping(struct map_desc *md) |
607 | { | 608 | { |
608 | unsigned long phys, addr, length, end; | 609 | unsigned long phys, addr, length, end; |
609 | const struct mem_type *type; | 610 | const struct mem_type *type; |
@@ -1017,6 +1018,39 @@ static void __init kmap_init(void) | |||
1017 | #endif | 1018 | #endif |
1018 | } | 1019 | } |
1019 | 1020 | ||
1021 | static inline void map_memory_bank(struct membank *bank) | ||
1022 | { | ||
1023 | struct map_desc map; | ||
1024 | |||
1025 | map.pfn = bank_pfn_start(bank); | ||
1026 | map.virtual = __phys_to_virt(bank_phys_start(bank)); | ||
1027 | map.length = bank_phys_size(bank); | ||
1028 | map.type = MT_MEMORY; | ||
1029 | |||
1030 | create_mapping(&map); | ||
1031 | } | ||
1032 | |||
1033 | static void __init map_lowmem(void) | ||
1034 | { | ||
1035 | struct meminfo *mi = &meminfo; | ||
1036 | int i; | ||
1037 | |||
1038 | /* Map all the lowmem memory banks. */ | ||
1039 | for (i = 0; i < mi->nr_banks; i++) { | ||
1040 | struct membank *bank = &mi->bank[i]; | ||
1041 | |||
1042 | if (!bank->highmem) | ||
1043 | map_memory_bank(bank); | ||
1044 | } | ||
1045 | } | ||
1046 | |||
1047 | static int __init meminfo_cmp(const void *_a, const void *_b) | ||
1048 | { | ||
1049 | const struct membank *a = _a, *b = _b; | ||
1050 | long cmp = bank_pfn_start(a) - bank_pfn_start(b); | ||
1051 | return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; | ||
1052 | } | ||
1053 | |||
1020 | /* | 1054 | /* |
1021 | * paging_init() sets up the page tables, initialises the zone memory | 1055 | * paging_init() sets up the page tables, initialises the zone memory |
1022 | * maps, and sets up the zero page, bad page and bad page tables. | 1056 | * maps, and sets up the zero page, bad page and bad page tables. |
@@ -1025,9 +1059,12 @@ void __init paging_init(struct machine_desc *mdesc) | |||
1025 | { | 1059 | { |
1026 | void *zero_page; | 1060 | void *zero_page; |
1027 | 1061 | ||
1062 | sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]), meminfo_cmp, NULL); | ||
1063 | |||
1028 | build_mem_type_table(); | 1064 | build_mem_type_table(); |
1029 | sanity_check_meminfo(); | 1065 | sanity_check_meminfo(); |
1030 | prepare_page_table(); | 1066 | prepare_page_table(); |
1067 | map_lowmem(); | ||
1031 | bootmem_init(); | 1068 | bootmem_init(); |
1032 | devicemaps_init(mdesc); | 1069 | devicemaps_init(mdesc); |
1033 | kmap_init(); | 1070 | kmap_init(); |