static int dlpar_remove_lmb(struct of_drconf_cell *lmb) { struct memory_block *mem_block; unsigned long block_sz; int nid, rc; if (!lmb_is_removable(lmb)) return -EINVAL; mem_block = lmb_to_memblock(lmb); if (!mem_block) return -EINVAL; rc = device_offline(&mem_block->dev); put_device(&mem_block->dev); if (rc) return rc; block_sz = pseries_memory_block_size(); nid = memory_add_physaddr_to_nid(lmb->base_addr); remove_memory(nid, lmb->base_addr, block_sz); /* Update memory regions for memory remove */ memblock_remove(lmb->base_addr, block_sz); dlpar_remove_device_tree_lmb(lmb); return 0; }
static int dlpar_online_lmb(struct of_drconf_cell *lmb) { struct memory_block *mem_block; int rc; mem_block = lmb_to_memblock(lmb); if (!mem_block) return -EINVAL; rc = device_online(&mem_block->dev); put_device(&mem_block->dev); return rc; }
static int dlpar_add_lmb_memory(struct of_drconf_cell *lmb) { struct memory_block *mem_block; unsigned long block_sz; int nid, rc; block_sz = memory_block_size_bytes(); /* Find the node id for this address */ nid = memory_add_physaddr_to_nid(lmb->base_addr); /* Add the memory */ rc = add_memory(nid, lmb->base_addr, block_sz); if (rc) return rc; /* Register this block of memory */ rc = memblock_add(lmb->base_addr, block_sz); if (rc) { remove_memory(nid, lmb->base_addr, block_sz); return rc; } mem_block = lmb_to_memblock(lmb); if (!mem_block) { remove_memory(nid, lmb->base_addr, block_sz); return -EINVAL; } rc = device_online(&mem_block->dev); put_device(&mem_block->dev); if (rc) { remove_memory(nid, lmb->base_addr, block_sz); return rc; } lmb->flags |= DRCONF_MEM_ASSIGNED; return 0; }