Initial Contribution

msm-2.6.38: tag AU_LINUX_ANDROID_GINGERBREAD.02.03.04.00.142

Signed-off-by: Bryan Huntsman <bryanh@codeaurora.org>
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index c46887b..b4e4296 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -112,9 +112,10 @@
 
 static void register_page_bootmem_info_section(unsigned long start_pfn)
 {
-	unsigned long *usemap, mapsize, section_nr, i;
+	unsigned long *usemap, mapsize, page_mapsize, section_nr, i, j;
 	struct mem_section *ms;
-	struct page *page, *memmap;
+	struct page *page, *memmap, *page_page;
+	int memmap_page_valid;
 
 	if (!pfn_valid(start_pfn))
 		return;
@@ -133,9 +134,21 @@
 	mapsize = sizeof(struct page) * PAGES_PER_SECTION;
 	mapsize = PAGE_ALIGN(mapsize) >> PAGE_SHIFT;
 
-	/* remember memmap's page */
-	for (i = 0; i < mapsize; i++, page++)
-		get_page_bootmem(section_nr, page, SECTION_INFO);
+	page_mapsize = PAGE_SIZE/sizeof(struct page);
+
+	/* remember memmap's page, except those that reference only holes */
+	for (i = 0; i < mapsize; i++, page++) {
+		memmap_page_valid = 0;
+		page_page = __va(page_to_pfn(page) << PAGE_SHIFT);
+		for (j = 0; j < page_mapsize; j++, page_page++) {
+			if (early_pfn_valid(page_to_pfn(page_page))) {
+				memmap_page_valid = 1;
+				break;
+			}
+		}
+		if (memmap_page_valid)
+			get_page_bootmem(section_nr, page, SECTION_INFO);
+	}
 
 	usemap = __nr_to_section(section_nr)->pageblock_flags;
 	page = virt_to_page(usemap);
@@ -596,6 +609,51 @@
 }
 EXPORT_SYMBOL_GPL(add_memory);
 
+int __ref physical_remove_memory(u64 start, u64 size)
+{
+	int ret;
+	struct resource *res, *res_old;
+	res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+	BUG_ON(!res);
+
+	ret = arch_physical_remove_memory(start, size);
+	if (ret) {
+		kfree(res);
+		return ret;
+	}
+
+	res->name = "System RAM";
+	res->start = start;
+	res->end = start + size - 1;
+	res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+
+	res_old = locate_resource(&iomem_resource, res);
+	if (res_old)
+		release_memory_resource(res_old);
+	kfree(res);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(physical_remove_memory);
+
+int __ref physical_active_memory(u64 start, u64 size)
+{
+	int ret;
+
+	ret = arch_physical_active_memory(start, size);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(physical_active_memory);
+
+int __ref physical_low_power_memory(u64 start, u64 size)
+{
+	int ret;
+
+	ret = arch_physical_low_power_memory(start, size);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(physical_low_power_memory);
+
 #ifdef CONFIG_MEMORY_HOTREMOVE
 /*
  * A free page on the buddy free lists (not the per-cpu lists) has PageBuddy
@@ -934,6 +992,23 @@
 	end_pfn = start_pfn + PFN_DOWN(size);
 	return offline_pages(start_pfn, end_pfn, 120 * HZ);
 }
+
+void reserve_hotplug_pages(unsigned long start_pfn, unsigned long nr_pages)
+{
+	nr_pages = ((nr_pages + pageblock_nr_pages - 1) >> pageblock_order)
+		<< pageblock_order;
+	offline_isolated_pages(start_pfn, start_pfn + nr_pages);
+}
+
+void unreserve_hotplug_pages(unsigned long start_pfn, unsigned long nr_pages)
+{
+	unsigned long onlined_pages = 0;
+
+	nr_pages = ((nr_pages + pageblock_nr_pages - 1) >> pageblock_order)
+		<< pageblock_order;
+	online_pages_range(start_pfn, nr_pages, &onlined_pages);
+}
+
 #else
 int remove_memory(u64 start, u64 size)
 {