Ejemplo n.º 1
0
static int pseries_remove_memblock(unsigned long base, unsigned int memblock_size)
{
    unsigned long block_sz, start_pfn;
    int sections_per_block;
    int i, nid;

    start_pfn = base >> PAGE_SHIFT;

    lock_device_hotplug();

    if (!pfn_valid(start_pfn))
        goto out;

    block_sz = pseries_memory_block_size();
    sections_per_block = block_sz / MIN_MEMORY_BLOCK_SIZE;
    nid = memory_add_physaddr_to_nid(base);

    for (i = 0; i < sections_per_block; i++) {
        remove_memory(nid, base, MIN_MEMORY_BLOCK_SIZE);
        base += MIN_MEMORY_BLOCK_SIZE;
    }

out:
    /* Update memory regions for memory remove */
    memblock_remove(base, memblock_size);
    unlock_device_hotplug();
    return 0;
}
Ejemplo n.º 2
0
static ssize_t
memory_probe_store(struct device *dev, struct device_attribute *attr,
		   const char *buf, size_t count)
{
	u64 phys_addr;
	int nid, ret;
	unsigned long pages_per_block = PAGES_PER_SECTION * sections_per_block;

	ret = kstrtoull(buf, 0, &phys_addr);
	if (ret)
		return ret;

	if (phys_addr & ((pages_per_block << PAGE_SHIFT) - 1))
		return -EINVAL;

	nid = memory_add_physaddr_to_nid(phys_addr);
	ret = add_memory(nid, phys_addr,
			 MIN_MEMORY_BLOCK_SIZE * sections_per_block);

	if (ret)
		goto out;

	ret = count;
out:
	return ret;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
static ssize_t
memory_probe_store(struct device *dev, struct device_attribute *attr,
		   const char *buf, size_t count)
{
	u64 phys_addr;
	int nid;
	int i, ret;
	unsigned long pages_per_block = PAGES_PER_SECTION * sections_per_block;

	phys_addr = simple_strtoull(buf, NULL, 0);

	if (phys_addr & ((pages_per_block << PAGE_SHIFT) - 1))
		return -EINVAL;

	for (i = 0; i < sections_per_block; i++) {
		nid = memory_add_physaddr_to_nid(phys_addr);
		ret = add_memory(nid, phys_addr,
				 PAGES_PER_SECTION << PAGE_SHIFT);
		if (ret)
			goto out;

		phys_addr += MIN_MEMORY_BLOCK_SIZE;
	}

	ret = count;
out:
	return ret;
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
static int dlpar_add_lmb(struct of_drconf_cell *lmb)
{
	unsigned long block_sz;
	int nid, rc;

	if (lmb->flags & DRCONF_MEM_ASSIGNED)
		return -EINVAL;

	rc = dlpar_add_device_tree_lmb(lmb);
	if (rc) {
		pr_err("Couldn't update device tree for drc index %x\n",
		       lmb->drc_index);
		dlpar_release_drc(lmb->drc_index);
		return 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) {
		dlpar_remove_device_tree_lmb(lmb);
		return rc;
	}

	rc = dlpar_online_lmb(lmb);
	if (rc) {
		remove_memory(nid, lmb->base_addr, block_sz);
		dlpar_remove_device_tree_lmb(lmb);
	} else {
		lmb->flags |= DRCONF_MEM_ASSIGNED;
	}

	return rc;
}
Ejemplo n.º 7
0
static int e820_range_to_nid(resource_size_t addr)
{
	return memory_add_physaddr_to_nid(addr);
}