static int init_memory_block(struct memory_block **memory, struct mem_section *section, unsigned long state) { struct memory_block *mem; unsigned long start_pfn; int scn_nr; int ret = 0; mem = kzalloc(sizeof(*mem), GFP_KERNEL); if (!mem) return -ENOMEM; scn_nr = __section_nr(section); mem->start_section_nr = base_memory_block_id(scn_nr) * sections_per_block; mem->end_section_nr = mem->start_section_nr + sections_per_block - 1; mem->state = state; start_pfn = section_nr_to_pfn(mem->start_section_nr); mem->phys_device = arch_get_memory_phys_device(start_pfn); ret = register_memory(mem); *memory = mem; return ret; }
static bool is_zone_device_section(struct mem_section *ms) { struct page *page; page = sparse_decode_mem_map(ms->section_mem_map, __section_nr(ms)); return is_zone_device_page(page); }
static void unregister_memory(struct memory_block *memory, struct mem_section *section) { BUG_ON(memory->sysdev.cls != &memory_sysdev_class); BUG_ON(memory->sysdev.id != __section_nr(section)); /* drop the ref. we got in remove_memory_block() */ kobject_put(&memory->sysdev.kobj); sysdev_unregister(&memory->sysdev); }
/* * register_memory - Setup a sysfs device for a memory block */ static int register_memory(struct memory_block *memory, struct mem_section *section) { int error; memory->sysdev.cls = &memory_sysdev_class; memory->sysdev.id = __section_nr(section); error = sysdev_register(&memory->sysdev); return error; }
static void unregister_memory(struct memory_block *memory, struct mem_section *section, struct node *root) { BUG_ON(memory->sysdev.cls != &memory_sysdev_class); BUG_ON(memory->sysdev.id != __section_nr(section)); sysdev_unregister(&memory->sysdev); if (root) sysfs_remove_link(&root->sysdev.kobj, kobject_name(&memory->sysdev.kobj)); }
/* * A reference for the returned object is held and the reference for the * hinted object is released. */ struct memory_block *find_memory_block_hinted(struct mem_section *section, struct memory_block *hint) { int block_id = base_memory_block_id(__section_nr(section)); struct device *hintdev = hint ? &hint->dev : NULL; struct device *dev; dev = subsys_find_device_by_id(&memory_subsys, block_id, hintdev); if (hint) put_device(&hint->dev); if (!dev) return NULL; return to_memory_block(dev); }
/* * register_memory - Setup a sysfs device for a memory block */ int register_memory(struct memory_block *memory, struct mem_section *section, struct node *root) { int error; memory->sysdev.cls = &memory_sysdev_class; memory->sysdev.id = __section_nr(section); error = sysdev_register(&memory->sysdev); if (root && !error) error = sysfs_create_link(&root->sysdev.kobj, &memory->sysdev.kobj, kobject_name(&memory->sysdev.kobj)); return error; }
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; }
static int init_memory_block(struct memory_block **memory, struct mem_section *section, unsigned long state) { struct memory_block *mem; unsigned long start_pfn; int scn_nr; int ret = 0; mem = kzalloc(sizeof(*mem), GFP_KERNEL); if (!mem) return -ENOMEM; scn_nr = __section_nr(section); mem->start_section_nr = base_memory_block_id(scn_nr) * sections_per_block; mem->end_section_nr = mem->start_section_nr + sections_per_block - 1; mem->state = state; mem->section_count++; mutex_init(&mem->state_mutex); start_pfn = section_nr_to_pfn(mem->start_section_nr); mem->phys_device = arch_get_memory_phys_device(start_pfn); ret = register_memory(mem); if (!ret) ret = mem_create_simple_file(mem, phys_index); if (!ret) ret = mem_create_simple_file(mem, end_phys_index); if (!ret) ret = mem_create_simple_file(mem, state); if (!ret) ret = mem_create_simple_file(mem, phys_device); if (!ret) ret = mem_create_simple_file(mem, removable); *memory = mem; 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; }