[PATCH] early_res: add free_early_partial

From: Yinghai Lu
Date: Wed Feb 24 2010 - 21:38:55 EST




to free partial for pcpu_setup...

Signed-off-by: Yinghai Lu <yinghai@xxxxxxxxxx>

---
arch/x86/kernel/setup_percpu.c | 6 ++++
include/linux/early_res.h | 1
kernel/early_res.c | 55 +++++++++++++++++++++++++++++++++++++++++
mm/percpu.c | 3 --
4 files changed, 62 insertions(+), 3 deletions(-)

Index: linux-2.6/arch/x86/kernel/setup_percpu.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/setup_percpu.c
+++ linux-2.6/arch/x86/kernel/setup_percpu.c
@@ -137,7 +137,13 @@ static void * __init pcpu_fc_alloc(unsig

static void __init pcpu_fc_free(void *ptr, size_t size)
{
+#ifdef CONFIG_NO_BOOTMEM
+ u64 start = __pa(ptr);
+ u64 end = start + size;
+ free_early_partial(start, end);
+#else
free_bootmem(__pa(ptr), size);
+#endif
}

static int __init pcpu_cpu_distance(unsigned int from, unsigned int to)
Index: linux-2.6/include/linux/early_res.h
===================================================================
--- linux-2.6.orig/include/linux/early_res.h
+++ linux-2.6/include/linux/early_res.h
@@ -5,6 +5,7 @@
extern void reserve_early(u64 start, u64 end, char *name);
extern void reserve_early_overlap_ok(u64 start, u64 end, char *name);
extern void free_early(u64 start, u64 end);
+void free_early_partial(u64 start, u64 end);
extern void early_res_to_bootmem(u64 start, u64 end);

void reserve_early_without_check(u64 start, u64 end, char *name);
Index: linux-2.6/kernel/early_res.c
===================================================================
--- linux-2.6.orig/kernel/early_res.c
+++ linux-2.6/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 en
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)
{
Index: linux-2.6/mm/percpu.c
===================================================================
--- linux-2.6.orig/mm/percpu.c
+++ linux-2.6/mm/percpu.c
@@ -1929,10 +1929,7 @@ int __init pcpu_embed_first_chunk(size_t
}
/* copy and return the unused part */
memcpy(ptr, __per_cpu_load, ai->static_size);
-#ifndef CONFIG_NO_BOOTMEM
- /* fix partial free ! */
free_fn(ptr + size_sum, ai->unit_size - size_sum);
-#endif
}
}

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/