static int link_mem_sections(int nid) { unsigned long start_pfn = NODE_DATA(nid)->node_start_pfn; unsigned long end_pfn = start_pfn + NODE_DATA(nid)->node_spanned_pages; unsigned long pfn; int err = 0; for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) { unsigned long section_nr = pfn_to_section_nr(pfn); struct mem_section *mem_sect; struct memory_block *mem_blk; int ret; if (!present_section_nr(section_nr)) continue; mem_sect = __nr_to_section(section_nr); mem_blk = find_memory_block(mem_sect); ret = register_mem_sect_under_node(mem_blk, nid); if (!err) err = ret; /* discard ref obtained in find_memory_block() */ kobject_put(&mem_blk->sysdev.kobj); } return err; }
/* * need an interface for the VM to add new memory regions, * but without onlining it. */ int register_new_memory(int nid, struct mem_section *section) { int ret = 0; struct memory_block *mem; if (is_zone_device_section(section)) return 0; mutex_lock(&mem_sysfs_mutex); mem = find_memory_block(section); if (mem) { mem->section_count++; put_device(&mem->dev); } else { ret = init_memory_block(&mem, section, MEM_OFFLINE); if (ret) goto out; mem->section_count++; } if (mem->section_count == sections_per_block) ret = register_mem_sect_under_node(mem, nid); out: mutex_unlock(&mem_sysfs_mutex); return ret; }
static struct memory_block *lmb_to_memblock(struct of_drconf_cell *lmb) { unsigned long section_nr; struct mem_section *mem_sect; struct memory_block *mem_block; section_nr = pfn_to_section_nr(PFN_DOWN(lmb->base_addr)); mem_sect = __nr_to_section(section_nr); mem_block = find_memory_block(mem_sect); return mem_block; }
static int remove_memory_block(unsigned long node_id, struct mem_section *section, int phys_device) { struct memory_block *mem; mutex_lock(&mem_sysfs_mutex); mem = find_memory_block(section); unregister_mem_sect_under_nodes(mem, __section_nr(section)); mem->section_count--; if (mem->section_count == 0) unregister_memory(mem); else put_device(&mem->dev); mutex_unlock(&mem_sysfs_mutex); return 0; }
static int add_memory_section(int nid, struct mem_section *section, struct memory_block **mem_p, unsigned long state, enum mem_add_context context) { struct memory_block *mem = NULL; int scn_nr = __section_nr(section); int ret = 0; mutex_lock(&mem_sysfs_mutex); if (context == BOOT) { /* same memory block ? */ if (mem_p && *mem_p) if (scn_nr >= (*mem_p)->start_section_nr && scn_nr <= (*mem_p)->end_section_nr) { mem = *mem_p; kobject_get(&mem->dev.kobj); } } else mem = find_memory_block(section); if (mem) { mem->section_count++; kobject_put(&mem->dev.kobj); } else { ret = init_memory_block(&mem, section, state); /* store memory_block pointer for next loop */ if (!ret && context == BOOT) if (mem_p) *mem_p = mem; } if (!ret) { if (context == HOTPLUG && mem->section_count == sections_per_block) ret = register_mem_sect_under_node(mem, nid); } mutex_unlock(&mem_sysfs_mutex); return ret; }
int remove_memory_block(unsigned long node_id, struct mem_section *section, int phys_device) { struct memory_block *mem; mutex_lock(&mem_sysfs_mutex); mem = find_memory_block(section); unregister_mem_sect_under_nodes(mem, __section_nr(section)); mem->section_count--; if (mem->section_count == 0) { mem_remove_simple_file(mem, phys_index); mem_remove_simple_file(mem, end_phys_index); mem_remove_simple_file(mem, state); mem_remove_simple_file(mem, phys_device); mem_remove_simple_file(mem, removable); unregister_memory(mem); kfree(mem); } else kobject_put(&mem->dev.kobj); mutex_unlock(&mem_sysfs_mutex); return 0; }
static int add_memory_section(int nid, struct mem_section *section, unsigned long state, enum mem_add_context context) { struct memory_block *mem; int ret = 0; mutex_lock(&mem_sysfs_mutex); mem = find_memory_block(section); if (mem) { mem->section_count++; kobject_put(&mem->dev.kobj); } else ret = init_memory_block(&mem, section, state); if (!ret) { if (context == HOTPLUG && mem->section_count == sections_per_block) ret = register_mem_sect_under_node(mem, nid); } mutex_unlock(&mem_sysfs_mutex); return ret; }