msm: do not create memory pools from unstable memory

When reserving memory for memory pools, do not use
memory which can potentially be powered off.

Signed-off-by: Larry Bassel <lbassel@codeaurora.org>
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index 2ece32e..0e0644b 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -229,12 +229,23 @@
 
 struct reserve_info *reserve_info;
 
+static unsigned long stable_size(struct membank *mb,
+	unsigned long unstable_limit)
+{
+	if (!unstable_limit || mb->start + mb->size <= unstable_limit)
+		return mb->size;
+	if (mb->start >= unstable_limit)
+		return 0;
+	return unstable_limit - mb->start;
+}
+
 static void __init calculate_reserve_limits(void)
 {
 	int i;
 	struct membank *mb;
 	int memtype;
 	struct memtype_reserve *mt;
+	unsigned long size;
 
 	for (i = 0, mb = &meminfo.bank[0]; i < meminfo.nr_banks; i++, mb++)  {
 		memtype = reserve_info->paddr_to_memtype(mb->start);
@@ -244,7 +255,8 @@
 			continue;
 		}
 		mt = &reserve_info->memtype_reserve_table[memtype];
-		mt->limit = max(mt->limit, mb->size);
+		size = stable_size(mb, reserve_info->low_unstable_address);
+		mt->limit = max(mt->limit, size);
 	}
 }
 
@@ -271,6 +283,7 @@
 	struct memtype_reserve *mt;
 	struct membank *mb;
 	int ret;
+	unsigned long size;
 
 	mt = &reserve_info->memtype_reserve_table[0];
 	for (memtype = 0; memtype < MEMTYPE_MAX; memtype++, mt++) {
@@ -285,7 +298,7 @@
 		 * take memory from the lowest memory bank which the kernel
 		 * is in (and cause boot problems) and so that we might
 		 * be able to steal memory that would otherwise become
-		 * highmem.
+		 * highmem. However, do not use unstable memory.
 		 */
 		for (i = meminfo.nr_banks - 1; i >= 0; i--) {
 			mb = &meminfo.bank[i];
@@ -293,8 +306,10 @@
 				reserve_info->paddr_to_memtype(mb->start);
 			if (memtype != membank_type)
 				continue;
-			if (mb->size >= mt->size) {
-				mt->start = mb->start + mb->size - mt->size;
+			size = stable_size(mb,
+				reserve_info->low_unstable_address);
+			if (size >= mt->size) {
+				mt->start = mb->start + size - mt->size;
 				ret = memblock_remove(mt->start, mt->size);
 				BUG_ON(ret);
 				break;