lkml.org 
[lkml]   [2010]   [Jun]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 08/37] x86, lmb: Add lmb_find_in_range_size()
    Date
    size is returned according free range.
    Will be used to find free ranges for early_memtest and memory corruption check

    Do not mess it up with lib/lmb.c yet.

    Signed-off-by: Yinghai Lu <yinghai@kernel.org>
    ---
    arch/x86/include/asm/lmb.h | 8 ++++
    arch/x86/mm/Makefile | 2 +
    arch/x86/mm/lmb.c | 88 ++++++++++++++++++++++++++++++++++++++++++++
    3 files changed, 98 insertions(+), 0 deletions(-)
    create mode 100644 arch/x86/include/asm/lmb.h
    create mode 100644 arch/x86/mm/lmb.c
    diff --git a/arch/x86/include/asm/lmb.h b/arch/x86/include/asm/lmb.h
    new file mode 100644
    index 0000000..9d26895
    --- /dev/null
    +++ b/arch/x86/include/asm/lmb.h
    @@ -0,0 +1,8 @@
    +#ifndef _X86_LMB_H
    +#define _X86_LMB_H
    +
    +#define ARCH_DISCARD_LMB
    +
    +u64 lmb_find_in_range_size(u64 start, u64 *sizep, u64 align);
    +
    +#endif
    diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile
    index a4c7683..8ab0505 100644
    --- a/arch/x86/mm/Makefile
    +++ b/arch/x86/mm/Makefile
    @@ -26,4 +26,6 @@ obj-$(CONFIG_NUMA) += numa.o numa_$(BITS).o
    obj-$(CONFIG_K8_NUMA) += k8topology_64.o
    obj-$(CONFIG_ACPI_NUMA) += srat_$(BITS).o

    +obj-$(CONFIG_HAVE_LMB) += lmb.o
    +
    obj-$(CONFIG_MEMTEST) += memtest.o
    diff --git a/arch/x86/mm/lmb.c b/arch/x86/mm/lmb.c
    new file mode 100644
    index 0000000..4335f48
    --- /dev/null
    +++ b/arch/x86/mm/lmb.c
    @@ -0,0 +1,88 @@
    +#include <linux/kernel.h>
    +#include <linux/types.h>
    +#include <linux/init.h>
    +#include <linux/bitops.h>
    +#include <linux/lmb.h>
    +#include <linux/bootmem.h>
    +#include <linux/mm.h>
    +#include <linux/range.h>
    +
    +/* Check for already reserved areas */
    +static inline bool __init bad_addr_size(u64 *addrp, u64 *sizep, u64 align)
    +{
    + struct lmb_region *r;
    + u64 addr = *addrp, last;
    + u64 size = *sizep;
    + bool changed = false;
    +
    +again:
    + last = addr + size;
    + for_each_lmb(reserved, r) {
    + if (last > r->base && addr < r->base) {
    + size = r->base - addr;
    + changed = true;
    + goto again;
    + }
    + if (last > (r->base + r->size) && addr < (r->base + r->size)) {
    + addr = round_up(r->base + r->size, align);
    + size = last - addr;
    + changed = true;
    + goto again;
    + }
    + if (last <= (r->base + r->size) && addr >= r->base) {
    + (*sizep)++;
    + return false;
    + }
    + }
    + if (changed) {
    + *addrp = addr;
    + *sizep = size;
    + }
    + return changed;
    +}
    +
    +static u64 __init __lmb_find_in_range_size(u64 ei_start, u64 ei_last, u64 start,
    + u64 *sizep, u64 align)
    +{
    + u64 addr, last;
    +
    + addr = round_up(ei_start, align);
    + if (addr < start)
    + addr = round_up(start, align);
    + if (addr >= ei_last)
    + goto out;
    + *sizep = ei_last - addr;
    + while (bad_addr_size(&addr, sizep, align) && addr + *sizep <= ei_last)
    + ;
    + last = addr + *sizep;
    + if (last > ei_last)
    + goto out;
    +
    + return addr;
    +
    +out:
    + return LMB_ERROR;
    +}
    +
    +/*
    + * Find next free range after start, and size is returned in *sizep
    + */
    +u64 __init lmb_find_in_range_size(u64 start, u64 *sizep, u64 align)
    +{
    + struct lmb_region *r;
    +
    + for_each_lmb(memory, r) {
    + u64 ei_start = r->base;
    + u64 ei_last = ei_start + r->size;
    + u64 addr;
    +
    + addr = __lmb_find_in_range_size(ei_start, ei_last, start,
    + sizep, align);
    +
    + if (addr != LMB_ERROR)
    + return addr;
    + }
    +
    + return LMB_ERROR;
    +}
    +
    --
    1.6.4.2


    \
     
     \ /
      Last update: 2010-06-16 07:55    [from the cache]
    ©2003-2011 Jasper Spaans