aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2014-03-22 19:24:45 -0400
committerMax Filippov <jcmvbkbc@gmail.com>2014-04-01 17:35:53 -0400
commit6232791833785ae591b211609f6f7c4faa7c6e55 (patch)
treeb1a8805d5f884068bdb567a415816779892a3638
parent9d4b52df4b1242e6ba9a00db5f8d62083a56709f (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>
-rw-r--r--arch/xtensa/kernel/setup.c2
-rw-r--r--arch/xtensa/mm/init.c82
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
156int __init mem_reserve(unsigned long start, unsigned long end, int must_exist) 158int __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