-
-static pg_data_t *hotadd_new_pgdat(int nid, u64 start)
-{
- struct pglist_data *pgdat;
- unsigned long zones_size[MAX_NR_ZONES] = {0};
- unsigned long zholes_size[MAX_NR_ZONES] = {0};
- unsigned long start_pfn = start >> PAGE_SHIFT;
-
- pgdat = arch_alloc_nodedata(nid);
- if (!pgdat)
- return NULL;
-
- arch_refresh_nodedata(nid, pgdat);
-
- /* we can use NODE_DATA(nid) from here */
-
- /* init node's zones as empty zones, we don't have any present pages.*/
- free_area_init_node(nid, pgdat, zones_size, start_pfn, zholes_size);
-
- return pgdat;
-}
-
-static void rollback_node_hotadd(int nid, pg_data_t *pgdat)
-{
- arch_refresh_nodedata(nid, NULL);
- arch_free_nodedata(pgdat);
- return;
-}
-
-/* add this memory to iomem resource */
-static struct resource *register_memory_resource(u64 start, u64 size)
-{
- struct resource *res;
- res = kzalloc(sizeof(struct resource), GFP_KERNEL);
- BUG_ON(!res);
-
- res->name = "System RAM";
- res->start = start;
- res->end = start + size - 1;
- res->flags = IORESOURCE_MEM;
- if (request_resource(&iomem_resource, res) < 0) {
- printk("System RAM resource %llx - %llx cannot be added\n",
- (unsigned long long)res->start, (unsigned long long)res->end);
- kfree(res);
- res = NULL;
- }
- return res;
-}
-
-static void release_memory_resource(struct resource *res)
-{
- if (!res)
- return;
- release_resource(res);
- kfree(res);
- return;
-}
-
-
-
-int add_memory(int nid, u64 start, u64 size)
-{
- pg_data_t *pgdat = NULL;
- int new_pgdat = 0;
- struct resource *res;
- int ret;
-
- res = register_memory_resource(start, size);
- if (!res)
- return -EEXIST;
-
- if (!node_online(nid)) {
- pgdat = hotadd_new_pgdat(nid, start);
- if (!pgdat)
- return -ENOMEM;
- new_pgdat = 1;
- ret = kswapd_run(nid);
- if (ret)
- goto error;
- }
-
- /* call arch's memory hotadd */
- ret = arch_add_memory(nid, start, size);
-
- if (ret < 0)
- goto error;
-
- /* we online node here. we can't roll back from here. */
- node_set_online(nid);
-
- if (new_pgdat) {
- ret = register_one_node(nid);
- /*
- * If sysfs file of new node can't create, cpu on the node
- * can't be hot-added. There is no rollback way now.
- * So, check by BUG_ON() to catch it reluctantly..
- */
- BUG_ON(ret);
- }
-
- return ret;
-error:
- /* rollback pgdat allocation and others */
- if (new_pgdat)
- rollback_node_hotadd(nid, pgdat);
- if (res)
- release_memory_resource(res);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(add_memory);