]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - mm/memory_hotplug.c
pageflags: standardize comment inclusion in asm-offsets.h and fix MIPS
[linux-2.6-omap-h63xx.git] / mm / memory_hotplug.c
index 7469c503580dcf6402000cc339359175a9b417fc..c8b3ca79de2d65ab2430f17f9cd92bfb4c417728 100644 (file)
@@ -101,6 +101,25 @@ static int __add_section(struct zone *zone, unsigned long phys_start_pfn)
        return register_new_memory(__pfn_to_section(phys_start_pfn));
 }
 
+static int __remove_section(struct zone *zone, struct mem_section *ms)
+{
+       unsigned long flags;
+       struct pglist_data *pgdat = zone->zone_pgdat;
+       int ret = -EINVAL;
+
+       if (!valid_section(ms))
+               return ret;
+
+       ret = unregister_memory_section(ms);
+       if (ret)
+               return ret;
+
+       pgdat_resize_lock(pgdat, &flags);
+       sparse_remove_one_section(zone, ms);
+       pgdat_resize_unlock(pgdat, &flags);
+       return 0;
+}
+
 /*
  * Reasonably generic function for adding memory.  It is
  * expected that archs that support memory hotplug will
@@ -134,6 +153,42 @@ int __add_pages(struct zone *zone, unsigned long phys_start_pfn,
 }
 EXPORT_SYMBOL_GPL(__add_pages);
 
+/**
+ * __remove_pages() - remove sections of pages from a zone
+ * @zone: zone from which pages need to be removed
+ * @phys_start_pfn: starting pageframe (must be aligned to start of a section)
+ * @nr_pages: number of pages to remove (must be multiple of section size)
+ *
+ * Generic helper function to remove section mappings and sysfs entries
+ * for the section of the memory we are removing. Caller needs to make
+ * sure that pages are marked reserved and zones are adjust properly by
+ * calling offline_pages().
+ */
+int __remove_pages(struct zone *zone, unsigned long phys_start_pfn,
+                unsigned long nr_pages)
+{
+       unsigned long i, ret = 0;
+       int sections_to_remove;
+
+       /*
+        * We can only remove entire sections
+        */
+       BUG_ON(phys_start_pfn & ~PAGE_SECTION_MASK);
+       BUG_ON(nr_pages % PAGES_PER_SECTION);
+
+       release_mem_region(phys_start_pfn << PAGE_SHIFT, nr_pages * PAGE_SIZE);
+
+       sections_to_remove = nr_pages / PAGES_PER_SECTION;
+       for (i = 0; i < sections_to_remove; i++) {
+               unsigned long pfn = phys_start_pfn + i*PAGES_PER_SECTION;
+               ret = __remove_section(zone, __pfn_to_section(pfn));
+               if (ret)
+                       break;
+       }
+       return ret;
+}
+EXPORT_SYMBOL_GPL(__remove_pages);
+
 static void grow_zone_span(struct zone *zone,
                unsigned long start_pfn, unsigned long end_pfn)
 {
@@ -164,6 +219,25 @@ static void grow_pgdat_span(struct pglist_data *pgdat,
                                        pgdat->node_start_pfn;
 }
 
+void online_page(struct page *page)
+{
+       totalram_pages++;
+       num_physpages++;
+
+#ifdef CONFIG_HIGHMEM
+       if (PageHighMem(page))
+               totalhigh_pages++;
+#endif
+
+#ifdef CONFIG_FLATMEM
+       max_mapnr = max(page_to_pfn(page), max_mapnr);
+#endif
+
+       ClearPageReserved(page);
+       init_page_count(page);
+       __free_page(page);
+}
+
 static int online_pages_range(unsigned long start_pfn, unsigned long nr_pages,
                        void *arg)
 {
@@ -208,7 +282,7 @@ int online_pages(unsigned long pfn, unsigned long nr_pages)
        /*
         * This doesn't need a lock to do pfn_to_page().
         * The section can't be removed here because of the
-        * memory_block->state_sem.
+        * memory_block->state_mutex.
         */
        zone = page_zone(pfn_to_page(pfn));
        pgdat_resize_lock(zone->zone_pgdat, &flags);