diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2014-03-22 19:24:45 -0400 |
---|---|---|
committer | Max Filippov <jcmvbkbc@gmail.com> | 2014-04-01 17:35:53 -0400 |
commit | 6232791833785ae591b211609f6f7c4faa7c6e55 (patch) | |
tree | b1a8805d5f884068bdb567a415816779892a3638 /arch | |
parent | 9d4b52df4b1242e6ba9a00db5f8d62083a56709f (diff) |
xtensa: keep sysmem banks ordered in mem_reserve
Rewrite mem_reserve so that it keeps bank order.
Also make its return code more traditional.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/xtensa/kernel/setup.c | 2 | ||||
-rw-r--r-- | arch/xtensa/mm/init.c | 82 |
2 files changed, 51 insertions, 33 deletions
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index df2b1d6fc843..017c06aba9b2 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c | |||
@@ -462,7 +462,7 @@ void __init setup_arch(char **cmdline_p) | |||
462 | #ifdef CONFIG_BLK_DEV_INITRD | 462 | #ifdef CONFIG_BLK_DEV_INITRD |
463 | if (initrd_start < initrd_end) { | 463 | if (initrd_start < initrd_end) { |
464 | initrd_is_mapped = mem_reserve(__pa(initrd_start), | 464 | initrd_is_mapped = mem_reserve(__pa(initrd_start), |
465 | __pa(initrd_end), 0); | 465 | __pa(initrd_end), 0) == 0; |
466 | initrd_below_start_ok = 1; | 466 | initrd_below_start_ok = 1; |
467 | } else { | 467 | } else { |
468 | initrd_start = 0; | 468 | initrd_start = 0; |
diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c index 79c0c3d52ae3..5d23697957bf 100644 --- a/arch/xtensa/mm/init.c +++ b/arch/xtensa/mm/init.c | |||
@@ -142,6 +142,8 @@ int __init add_sysmem_bank(unsigned long start, unsigned long end) | |||
142 | * mem_reserve(start, end, must_exist) | 142 | * mem_reserve(start, end, must_exist) |
143 | * | 143 | * |
144 | * Reserve some memory from the memory pool. | 144 | * Reserve some memory from the memory pool. |
145 | * If must_exist is set and a part of the region being reserved does not exist | ||
146 | * memory map is not altered. | ||
145 | * | 147 | * |
146 | * Parameters: | 148 | * Parameters: |
147 | * start Start of region, | 149 | * start Start of region, |
@@ -149,53 +151,69 @@ int __init add_sysmem_bank(unsigned long start, unsigned long end) | |||
149 | * must_exist Must exist in memory pool. | 151 | * must_exist Must exist in memory pool. |
150 | * | 152 | * |
151 | * Returns: | 153 | * Returns: |
152 | * 0 (memory area couldn't be mapped) | 154 | * 0 (success) |
153 | * -1 (success) | 155 | * < 0 (error) |
154 | */ | 156 | */ |
155 | 157 | ||
156 | int __init mem_reserve(unsigned long start, unsigned long end, int must_exist) | 158 | int __init mem_reserve(unsigned long start, unsigned long end, int must_exist) |
157 | { | 159 | { |
158 | int i; | 160 | struct meminfo *it; |
159 | 161 | struct meminfo *rm = NULL; | |
160 | if (start == end) | 162 | unsigned long sz; |
161 | return 0; | 163 | unsigned long bank_sz = 0; |
162 | 164 | ||
163 | start = start & PAGE_MASK; | 165 | start = start & PAGE_MASK; |
164 | end = PAGE_ALIGN(end); | 166 | end = PAGE_ALIGN(end); |
167 | sz = end - start; | ||
168 | if (!sz) | ||
169 | return -EINVAL; | ||
165 | 170 | ||
166 | for (i = 0; i < sysmem.nr_banks; i++) | 171 | it = find_bank(start); |
167 | if (start < sysmem.bank[i].end | 172 | |
168 | && end >= sysmem.bank[i].start) | 173 | if (it) |
169 | break; | 174 | bank_sz = it->end - it->start; |
170 | 175 | ||
171 | if (i == sysmem.nr_banks) { | 176 | if ((!it || end - it->start > bank_sz) && must_exist) { |
172 | if (must_exist) | 177 | pr_warn("mem_reserve: [0x%0lx, 0x%0lx) not in any region!\n", |
173 | printk (KERN_WARNING "mem_reserve: [0x%0lx, 0x%0lx) " | 178 | start, end); |
174 | "not in any region!\n", start, end); | 179 | return -EINVAL; |
175 | return 0; | ||
176 | } | 180 | } |
177 | 181 | ||
178 | if (start > sysmem.bank[i].start) { | 182 | if (it && start - it->start < bank_sz) { |
179 | if (end < sysmem.bank[i].end) { | 183 | if (start == it->start) { |
180 | /* split entry */ | 184 | if (end - it->start < bank_sz) { |
181 | if (sysmem.nr_banks >= SYSMEM_BANKS_MAX) | 185 | it->start = end; |
182 | panic("meminfo overflow\n"); | 186 | return 0; |
183 | sysmem.bank[sysmem.nr_banks].start = end; | 187 | } else { |
184 | sysmem.bank[sysmem.nr_banks].end = sysmem.bank[i].end; | 188 | rm = it; |
185 | sysmem.nr_banks++; | 189 | } |
190 | } else { | ||
191 | it->end = start; | ||
192 | if (end - it->start < bank_sz) | ||
193 | return add_sysmem_bank(end, | ||
194 | it->start + bank_sz); | ||
195 | ++it; | ||
186 | } | 196 | } |
187 | sysmem.bank[i].end = start; | 197 | } |
188 | 198 | ||
189 | } else if (end < sysmem.bank[i].end) { | 199 | if (!it) |
190 | sysmem.bank[i].start = end; | 200 | it = sysmem.bank; |
191 | 201 | ||
192 | } else { | 202 | for (; it < sysmem.bank + sysmem.nr_banks; ++it) { |
193 | /* remove entry */ | 203 | if (it->end - start <= sz) { |
194 | sysmem.nr_banks--; | 204 | if (!rm) |
195 | sysmem.bank[i].start = sysmem.bank[sysmem.nr_banks].start; | 205 | rm = it; |
196 | sysmem.bank[i].end = sysmem.bank[sysmem.nr_banks].end; | 206 | } else { |
207 | if (it->start - start < sz) | ||
208 | it->start = end; | ||
209 | break; | ||
210 | } | ||
197 | } | 211 | } |
198 | return -1; | 212 | |
213 | if (rm) | ||
214 | move_banks(rm, it); | ||
215 | |||
216 | return 0; | ||
199 | } | 217 | } |
200 | 218 | ||
201 | 219 | ||