Exemple #1
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;
}
Exemple #2
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;
}
Exemple #3
0
static int pseries_update_drconf_memory(struct of_reconfig_data *pr)
{
	struct of_drconf_cell *new_drmem, *old_drmem;
	unsigned long memblock_size;
	u32 entries;
	__be32 *p;
	int i, rc = -EINVAL;

	if (rtas_hp_event)
		return 0;

	memblock_size = pseries_memory_block_size();
	if (!memblock_size)
		return -EINVAL;

	p = (__be32 *) pr->old_prop->value;
	if (!p)
		return -EINVAL;

	/* The first int of the property is the number of lmb's described
	 * by the property. This is followed by an array of of_drconf_cell
	 * entries. Get the number of entries and skip to the array of
	 * of_drconf_cell's.
	 */
	entries = be32_to_cpu(*p++);
	old_drmem = (struct of_drconf_cell *)p;

	p = (__be32 *)pr->prop->value;
	p++;
	new_drmem = (struct of_drconf_cell *)p;

	for (i = 0; i < entries; i++) {
		if ((be32_to_cpu(old_drmem[i].flags) & DRCONF_MEM_ASSIGNED) &&
		    (!(be32_to_cpu(new_drmem[i].flags) & DRCONF_MEM_ASSIGNED))) {
			rc = pseries_remove_memblock(
				be64_to_cpu(old_drmem[i].base_addr),
						     memblock_size);
			break;
		} else if ((!(be32_to_cpu(old_drmem[i].flags) &
			    DRCONF_MEM_ASSIGNED)) &&
			    (be32_to_cpu(new_drmem[i].flags) &
			    DRCONF_MEM_ASSIGNED)) {
			rc = memblock_add(be64_to_cpu(old_drmem[i].base_addr),
					  memblock_size);
			rc = (rc < 0) ? -EINVAL : 0;
			break;
		}
	}
	return rc;
}