diff options
author | Yinghai Lu <yinghai@kernel.org> | 2010-02-24 21:36:53 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-02-26 02:25:35 -0500 |
commit | fb90ef93df654f2678933efbbf864adac0ae490e (patch) | |
tree | c590e99bc70fbbfa0e1615a29734ca3c1f586729 /kernel/early_res.c | |
parent | 2ee78f7b1d8ada2615ecbcd9fea70580008bd6ce (diff) |
early_res: Add free_early_partial()
To free partial areas in pcpu_setup...
Reported-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Tejun Heo <tj@kernel.org>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: Stephen Rothwell <sfr@canb.auug.org.au>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
LKML-Reference: <4B85E245.5030001@kernel.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/early_res.c')
-rw-r--r-- | kernel/early_res.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/kernel/early_res.c b/kernel/early_res.c index aa5494ac4462..9ab11cd84853 100644 --- a/kernel/early_res.c +++ b/kernel/early_res.c | |||
@@ -61,6 +61,40 @@ static void __init drop_range(int i) | |||
61 | early_res_count--; | 61 | early_res_count--; |
62 | } | 62 | } |
63 | 63 | ||
64 | static void __init drop_range_partial(int i, u64 start, u64 end) | ||
65 | { | ||
66 | u64 common_start, common_end; | ||
67 | u64 old_start, old_end; | ||
68 | |||
69 | old_start = early_res[i].start; | ||
70 | old_end = early_res[i].end; | ||
71 | common_start = max(old_start, start); | ||
72 | common_end = min(old_end, end); | ||
73 | |||
74 | /* no overlap ? */ | ||
75 | if (common_start >= common_end) | ||
76 | return; | ||
77 | |||
78 | if (old_start < common_start) { | ||
79 | /* make head segment */ | ||
80 | early_res[i].end = common_start; | ||
81 | if (old_end > common_end) { | ||
82 | /* add another for left over on tail */ | ||
83 | reserve_early_without_check(common_end, old_end, | ||
84 | early_res[i].name); | ||
85 | } | ||
86 | return; | ||
87 | } else { | ||
88 | if (old_end > common_end) { | ||
89 | /* reuse the entry for tail left */ | ||
90 | early_res[i].start = common_end; | ||
91 | return; | ||
92 | } | ||
93 | /* all covered */ | ||
94 | drop_range(i); | ||
95 | } | ||
96 | } | ||
97 | |||
64 | /* | 98 | /* |
65 | * Split any existing ranges that: | 99 | * Split any existing ranges that: |
66 | * 1) are marked 'overlap_ok', and | 100 | * 1) are marked 'overlap_ok', and |
@@ -284,6 +318,27 @@ void __init free_early(u64 start, u64 end) | |||
284 | drop_range(i); | 318 | drop_range(i); |
285 | } | 319 | } |
286 | 320 | ||
321 | void __init free_early_partial(u64 start, u64 end) | ||
322 | { | ||
323 | struct early_res *r; | ||
324 | int i; | ||
325 | |||
326 | try_next: | ||
327 | i = find_overlapped_early(start, end); | ||
328 | if (i >= max_early_res) | ||
329 | return; | ||
330 | |||
331 | r = &early_res[i]; | ||
332 | /* hole ? */ | ||
333 | if (r->end >= end && r->start <= start) { | ||
334 | drop_range_partial(i, start, end); | ||
335 | return; | ||
336 | } | ||
337 | |||
338 | drop_range_partial(i, start, end); | ||
339 | goto try_next; | ||
340 | } | ||
341 | |||
287 | #ifdef CONFIG_NO_BOOTMEM | 342 | #ifdef CONFIG_NO_BOOTMEM |
288 | static void __init subtract_early_res(struct range *range, int az) | 343 | static void __init subtract_early_res(struct range *range, int az) |
289 | { | 344 | { |