[PATCH 1/3] memblock: introduce interfaces to assoicate tag and datawith reserved regions

From: Jiang Liu
Date: Sun Dec 02 2012 - 07:54:32 EST


Currently some subsystems use private static arrays to store information
assoicated with memory blocks allocated/reserved from memblock subsystem.
For example, dma-contiguous.c uses cma_reserved[] to store information
assoicated with allocated memory blocks.

So introduce interfaces to associate tag(type) and caller specific data
with allocated/reserved memblock regions. Users of memblock subsystem
may be simplified by using these new interfaces.

Signed-off-by: Jiang Liu <jiang.liu@xxxxxxxxxx>
---
include/linux/memblock.h | 33 ++++++++++++++++++++++++++
mm/Kconfig | 3 +++
mm/memblock.c | 58 +++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 93 insertions(+), 1 deletion(-)

diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index d452ee1..40dea53 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -22,6 +22,10 @@
struct memblock_region {
phys_addr_t base;
phys_addr_t size;
+#ifdef CONFIG_HAVE_MEMBLOCK_TAG
+ void *data;
+ int tag;
+#endif
#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
int nid;
#endif
@@ -118,6 +122,35 @@ void __next_free_mem_range_rev(u64 *idx, int nid, phys_addr_t *out_start,
i != (u64)ULLONG_MAX; \
__next_free_mem_range_rev(&i, nid, p_start, p_end, p_nid))

+#ifdef CONFIG_HAVE_MEMBLOCK_TAG
+#define MEMBLOCK_TAG_DEFAULT 0x0 /* default tag for bootmem allocatror */
+
+int memblock_mark_tag(phys_addr_t base, phys_addr_t size, int tag, void *data);
+void memblock_free_all_with_tag(int tag);
+
+/* Only merge regions with default tag */
+static inline bool memblock_tag_mergeable(struct memblock_region *prev,
+ struct memblock_region *next)
+{
+ return prev->tag == MEMBLOCK_TAG_DEFAULT &&
+ next->tag == MEMBLOCK_TAG_DEFAULT;
+}
+
+static inline void memblock_init_tag(struct memblock_region *reg)
+{
+ reg->tag = MEMBLOCK_TAG_DEFAULT;
+ reg->data = NULL;
+}
+#else /* CONFIG_HAVE_MEMBLOCK_TAG */
+static inline bool memblock_tag_mergeable(struct memblock_region *prev,
+ struct memblock_region *next)
+{
+ return true;
+}
+
+static inline void memblock_init_tag(struct memblock_region *reg) {}
+#endif /* CONFIG_HAVE_MEMBLOCK_TAG */
+
#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
int memblock_set_node(phys_addr_t base, phys_addr_t size, int nid);

diff --git a/mm/Kconfig b/mm/Kconfig
index a3f8ddd..5080390 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -131,6 +131,9 @@ config SPARSEMEM_VMEMMAP
config HAVE_MEMBLOCK
boolean

+config HAVE_MEMBLOCK_TAG
+ boolean
+
config HAVE_MEMBLOCK_NODE_MAP
boolean

diff --git a/mm/memblock.c b/mm/memblock.c
index 6259055..c2c644e 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -307,7 +307,8 @@ static void __init_memblock memblock_merge_regions(struct memblock_type *type)

if (this->base + this->size != next->base ||
memblock_get_region_node(this) !=
- memblock_get_region_node(next)) {
+ memblock_get_region_node(next) ||
+ !memblock_tag_mergeable(this, next)) {
BUG_ON(this->base + this->size > next->base);
i++;
continue;
@@ -339,6 +340,7 @@ static void __init_memblock memblock_insert_region(struct memblock_type *type,
memmove(rgn + 1, rgn, (type->cnt - idx) * sizeof(*rgn));
rgn->base = base;
rgn->size = size;
+ memblock_init_tag(rgn);
memblock_set_region_node(rgn, nid);
type->cnt++;
type->total_size += size;
@@ -764,6 +766,60 @@ int __init_memblock memblock_set_node(phys_addr_t base, phys_addr_t size,
}
#endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */

+#ifdef CONFIG_HAVE_MEMBLOCK_TAG
+/**
+ * memblock_mark_tag - mark @tag and @data with reserved regions
+ * @base: base of area to mark @tag and @data with
+ * @size: size of area to mark @tag and @data with
+ * @tag: tag (type) to assoicated with reserved regions
+ * @data: caller specific data to associated with reserved regions
+ *
+ * Associate @tag(type) and caller specific @data with reserved memblock
+ * regions in [@base,@base+@size).
+ * Regions which cross the area boundaries are split as necessary.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+int __init_memblock memblock_mark_tag(phys_addr_t base, phys_addr_t size,
+ int tag, void *data)
+{
+ struct memblock_type *type = &memblock.reserved;
+ int start_rgn, end_rgn;
+ int i, ret;
+
+ ret = memblock_isolate_range(type, base, size, &start_rgn, &end_rgn);
+ if (ret)
+ return ret;
+
+ for (i = start_rgn; i < end_rgn; i++) {
+ type->regions[i].tag = tag;
+ type->regions[i].data = data;
+ }
+
+ memblock_merge_regions(type);
+
+ return 0;
+}
+
+/**
+ * memblock_free_all_with_tag - free all reserved regions with @tag
+ * @tag: tag to identify reserved memblock regions to be freed
+ *
+ * Free all reserved memblock regions with tag (type) of @tag
+ */
+void __init_memblock memblock_free_all_with_tag(int tag)
+{
+ int i;
+ struct memblock_type *type = &memblock.reserved;
+
+ /* scan backward because it may remove current region */
+ for (i = type->cnt - 1; i >= 0; i--)
+ if (type->regions[i].tag == tag)
+ memblock_remove_region(type, i);
+}
+#endif /* CONFIG_HAVE_MEMBLOCK_TAG */
+
static phys_addr_t __init memblock_alloc_base_nid(phys_addr_t size,
phys_addr_t align, phys_addr_t max_addr,
int nid)
--
1.7.9.5


--------------060103020608020905070302
Content-Type: text/x-patch;
name="0002-x86-memhotplug-reserve-memory-from-bootmem-allocator.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename*0="0002-x86-memhotplug-reserve-memory-from-bootmem-allocator.pa";
filename*1="tch"