@@ -19,6 +19,11 @@
#define INIT_MEMBLOCK_REGIONS 128
+/* Allocation order. */
+#define MEMBLOCK_DIRECTION_HIGH_TO_LOW 0
+#define MEMBLOCK_DIRECTION_LOW_TO_HIGH 1
+#define MEMBLOCK_DIRECTION_DEFAULT MEMBLOCK_DIRECTION_HIGH_TO_LOW
+
struct memblock_region {
phys_addr_t base;
phys_addr_t size;
@@ -35,6 +40,7 @@ struct memblock_type {
};
struct memblock {
+ int current_direction; /* allocate from higher or lower address */
phys_addr_t current_limit;
struct memblock_type memory;
struct memblock_type reserved;
@@ -148,6 +154,12 @@ phys_addr_t memblock_alloc_try_nid(phys_addr_t size, phys_addr_t align, int nid)
phys_addr_t memblock_alloc(phys_addr_t size, phys_addr_t align);
+static inline bool memblock_direction_bottom_up(void)
+{
+ return memblock.current_direction == MEMBLOCK_DIRECTION_LOW_TO_HIGH;
+}
+
+
/* Flags for memblock_alloc_base() amd __memblock_alloc_base() */
#define MEMBLOCK_ALLOC_ANYWHERE (~(phys_addr_t)0)
#define MEMBLOCK_ALLOC_ACCESSIBLE 0
@@ -175,6 +187,16 @@ static inline void memblock_dump_all(void)
}
/**
+ * memblock_set_current_direction - Set current allocation direction to allow
+ * allocating memory from higher to lower
+ * address or from lower to higher address
+ *
+ * @direction: In which order to allocate memory. Could be
+ * MEMBLOCK_DIRECTION_{HIGH_TO_LOW|LOW_TO_HIGH}
+ */
+void memblock_set_current_direction(int direction);
+
+/**
* memblock_set_current_limit - Set the current allocation limit to allow
* limiting allocations to what is currently
* accessible during boot
@@ -32,6 +32,7 @@ struct memblock memblock __initdata_memblock = {
.reserved.cnt = 1, /* empty dummy entry */
.reserved.max = INIT_MEMBLOCK_REGIONS,
+ .current_direction = MEMBLOCK_DIRECTION_DEFAULT,
.current_limit = MEMBLOCK_ALLOC_ANYWHERE,
};
@@ -995,6 +996,18 @@ void __init_memblock memblock_trim_memory(phys_addr_t align)
}
}
+void __init_memblock memblock_set_current_direction(int direction)
+{
+ if (direction != MEMBLOCK_DIRECTION_HIGH_TO_LOW &&
+ direction != MEMBLOCK_DIRECTION_LOW_TO_HIGH) {
+ pr_warn("memblock: Failed to set allocation order. "
+ "Invalid order type: %d\n", direction);
+ return;
+ }
+
+ memblock.current_direction = direction;
+}
+
void __init_memblock memblock_set_current_limit(phys_addr_t limit)
{
memblock.current_limit = limit;