summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2010-02-25 03:36:53 +0100
committerIngo Molnar <mingo@elte.hu>2010-02-26 08:25:35 +0100
commitfb90ef93df654f2678933efbbf864adac0ae490e (patch)
treec590e99bc70fbbfa0e1615a29734ca3c1f586729 /kernel
parentx86: Fix non-bootmem compilation on PowerPC (diff)
downloadlinux-fb90ef93df654f2678933efbbf864adac0ae490e.tar.xz
linux-fb90ef93df654f2678933efbbf864adac0ae490e.zip
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')
-rw-r--r--kernel/early_res.c55
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)
early_res_count--;
}
+static void __init drop_range_partial(int i, u64 start, u64 end)
+{
+ u64 common_start, common_end;
+ u64 old_start, old_end;
+
+ old_start = early_res[i].start;
+ old_end = early_res[i].end;
+ common_start = max(old_start, start);
+ common_end = min(old_end, end);
+
+ /* no overlap ? */
+ if (common_start >= common_end)
+ return;
+
+ if (old_start < common_start) {
+ /* make head segment */
+ early_res[i].end = common_start;
+ if (old_end > common_end) {
+ /* add another for left over on tail */
+ reserve_early_without_check(common_end, old_end,
+ early_res[i].name);
+ }
+ return;
+ } else {
+ if (old_end > common_end) {
+ /* reuse the entry for tail left */
+ early_res[i].start = common_end;
+ return;
+ }
+ /* all covered */
+ drop_range(i);
+ }
+}
+
/*
* Split any existing ranges that:
* 1) are marked 'overlap_ok', and
@@ -284,6 +318,27 @@ void __init free_early(u64 start, u64 end)
drop_range(i);
}
+void __init free_early_partial(u64 start, u64 end)
+{
+ struct early_res *r;
+ int i;
+
+try_next:
+ i = find_overlapped_early(start, end);
+ if (i >= max_early_res)
+ return;
+
+ r = &early_res[i];
+ /* hole ? */
+ if (r->end >= end && r->start <= start) {
+ drop_range_partial(i, start, end);
+ return;
+ }
+
+ drop_range_partial(i, start, end);
+ goto try_next;
+}
+
#ifdef CONFIG_NO_BOOTMEM
static void __init subtract_early_res(struct range *range, int az)
{