]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - mm/memory_hotplug.c
Merge branch 'akpm-current/current'
[karo-tx-linux.git] / mm / memory_hotplug.c
index 979b18cbd343e3422d5b4ccb86d1fab2bb1090e2..92402f8d17e895acf0d99c48f439c47ca2425218 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/hugetlb.h>
 #include <linux/memblock.h>
 #include <linux/bootmem.h>
+#include <linux/compaction.h>
 
 #include <asm/tlbflush.h>
 
@@ -77,6 +78,9 @@ static struct {
 #define memhp_lock_acquire()      lock_map_acquire(&mem_hotplug.dep_map)
 #define memhp_lock_release()      lock_map_release(&mem_hotplug.dep_map)
 
+bool memhp_auto_online;
+EXPORT_SYMBOL_GPL(memhp_auto_online);
+
 void get_online_mems(void)
 {
        might_sleep();
@@ -509,6 +513,8 @@ int __ref __add_pages(int nid, struct zone *zone, unsigned long phys_start_pfn,
        int start_sec, end_sec;
        struct vmem_altmap *altmap;
 
+       clear_zone_contiguous(zone);
+
        /* during initialize mem_map, align hot-added range to section */
        start_sec = pfn_to_section_nr(phys_start_pfn);
        end_sec = pfn_to_section_nr(phys_start_pfn + nr_pages - 1);
@@ -540,6 +546,8 @@ int __ref __add_pages(int nid, struct zone *zone, unsigned long phys_start_pfn,
        }
        vmemmap_populate_print_last();
 
+       set_zone_contiguous(zone);
+
        return err;
 }
 EXPORT_SYMBOL_GPL(__add_pages);
@@ -811,6 +819,8 @@ int __remove_pages(struct zone *zone, unsigned long phys_start_pfn,
                }
        }
 
+       clear_zone_contiguous(zone);
+
        /*
         * We can only remove entire sections
         */
@@ -826,6 +836,9 @@ int __remove_pages(struct zone *zone, unsigned long phys_start_pfn,
                if (ret)
                        break;
        }
+
+       set_zone_contiguous(zone);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(__remove_pages);
@@ -1042,7 +1055,7 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
        arg.nr_pages = nr_pages;
        node_states_check_changes_online(nr_pages, zone, &arg);
 
-       nid = pfn_to_nid(pfn);
+       nid = zone_to_nid(zone);
 
        ret = memory_notify(MEM_GOING_ONLINE, &arg);
        ret = notifier_to_errno(ret);
@@ -1082,7 +1095,7 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
        pgdat_resize_unlock(zone->zone_pgdat, &flags);
 
        if (onlined_pages) {
-               node_states_set_node(zone_to_nid(zone), &arg);
+               node_states_set_node(nid, &arg);
                if (need_zonelists_rebuild)
                        build_all_zonelists(NULL, NULL);
                else
@@ -1093,8 +1106,10 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
 
        init_per_zone_wmark_min();
 
-       if (onlined_pages)
-               kswapd_run(zone_to_nid(zone));
+       if (onlined_pages) {
+               kswapd_run(nid);
+               kcompactd_run(nid);
+       }
 
        vm_total_pages = nr_free_pagecache_pages();
 
@@ -1261,8 +1276,13 @@ int zone_for_memory(int nid, u64 start, u64 size, int zone_default,
        return zone_default;
 }
 
+static int online_memory_block(struct memory_block *mem, void *arg)
+{
+       return memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE);
+}
+
 /* we are OK calling __meminit stuff here - we have CONFIG_MEMORY_HOTPLUG */
-int __ref add_memory_resource(int nid, struct resource *res)
+int __ref add_memory_resource(int nid, struct resource *res, bool online)
 {
        u64 start, size;
        pg_data_t *pgdat = NULL;
@@ -1322,6 +1342,11 @@ int __ref add_memory_resource(int nid, struct resource *res)
        /* create new memmap entry */
        firmware_map_add_hotplug(start, start + size, "System RAM");
 
+       /* online pages if requested */
+       if (online)
+               walk_memory_range(PFN_DOWN(start), PFN_UP(start + size - 1),
+                                 NULL, online_memory_block);
+
        goto out;
 
 error:
@@ -1345,7 +1370,7 @@ int __ref add_memory(int nid, u64 start, u64 size)
        if (IS_ERR(res))
                return PTR_ERR(res);
 
-       ret = add_memory_resource(nid, res);
+       ret = add_memory_resource(nid, res, memhp_auto_online);
        if (ret < 0)
                release_memory_resource(res);
        return ret;
@@ -1858,8 +1883,10 @@ repeat:
                zone_pcp_update(zone);
 
        node_states_clear_node(node, &arg);
-       if (arg.status_change_nid >= 0)
+       if (arg.status_change_nid >= 0) {
                kswapd_stop(node);
+               kcompactd_stop(node);
+       }
 
        vm_total_pages = nr_free_pagecache_pages();
        writeback_set_ratelimit();