Exemple #1
0
static int dlpar_add_lmb(struct of_drconf_cell *lmb)
{
	int rc;

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

	rc = dlpar_acquire_drc(lmb->drc_index);
	if (rc)
		return rc;

	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;
	}

	rc = dlpar_add_lmb_memory(lmb);
	if (rc) {
		dlpar_remove_device_tree_lmb(lmb);
		dlpar_release_drc(lmb->drc_index);
	}

	return rc;
}
static ssize_t dlpar_cpu_probe(const char *buf, size_t count)
{
	struct device_node *dn;
	unsigned long drc_index;
	char *cpu_name;
	int rc;

	cpu_hotplug_driver_lock();
	rc = strict_strtoul(buf, 0, &drc_index);
	if (rc) {
		rc = -EINVAL;
		goto out;
	}

	dn = dlpar_configure_connector(drc_index);
	if (!dn) {
		rc = -EINVAL;
		goto out;
	}

	/* configure-connector reports cpus as living in the base
	 * directory of the device tree.  CPUs actually live in the
	 * cpus directory so we need to fixup the full_name.
	 */
	cpu_name = kzalloc(strlen(dn->full_name) + strlen("/cpus") + 1,
			   GFP_KERNEL);
	if (!cpu_name) {
		dlpar_free_cc_nodes(dn);
		rc = -ENOMEM;
		goto out;
	}

	sprintf(cpu_name, "/cpus%s", dn->full_name);
	kfree(dn->full_name);
	dn->full_name = cpu_name;

	rc = dlpar_acquire_drc(drc_index);
	if (rc) {
		dlpar_free_cc_nodes(dn);
		rc = -EINVAL;
		goto out;
	}

	rc = dlpar_attach_node(dn);
	if (rc) {
		dlpar_release_drc(drc_index);
		dlpar_free_cc_nodes(dn);
	}

	rc = dlpar_online_cpu(dn);
out:
	cpu_hotplug_driver_unlock();

	return rc ? rc : count;
}
Exemple #3
0
static ssize_t dlpar_cpu_probe(const char *buf, size_t count)
{
	struct device_node *dn, *parent;
	unsigned long drc_index;
	int rc;

	cpu_hotplug_driver_lock();
	rc = strict_strtoul(buf, 0, &drc_index);
	if (rc) {
		rc = -EINVAL;
		goto out;
	}

	parent = of_find_node_by_path("/cpus");
	if (!parent) {
		rc = -ENODEV;
		goto out;
	}

	dn = dlpar_configure_connector(drc_index, parent);
	if (!dn) {
		rc = -EINVAL;
		goto out;
	}

	of_node_put(parent);

	rc = dlpar_acquire_drc(drc_index);
	if (rc) {
		dlpar_free_cc_nodes(dn);
		rc = -EINVAL;
		goto out;
	}

	rc = dlpar_attach_node(dn);
	if (rc) {
		dlpar_release_drc(drc_index);
		dlpar_free_cc_nodes(dn);
		goto out;
	}

	rc = dlpar_online_cpu(dn);
out:
	cpu_hotplug_driver_unlock();

	return rc ? rc : count;
}
static ssize_t dlpar_cpu_release(const char *buf, size_t count)
{
	struct device_node *dn;
	const u32 *drc_index;
	int rc;

	dn = of_find_node_by_path(buf);
	if (!dn)
		return -EINVAL;

	drc_index = of_get_property(dn, "ibm,my-drc-index", NULL);
	if (!drc_index) {
		of_node_put(dn);
		return -EINVAL;
	}

	cpu_hotplug_driver_lock();
	rc = dlpar_offline_cpu(dn);
	if (rc) {
		of_node_put(dn);
		rc = -EINVAL;
		goto out;
	}

	rc = dlpar_release_drc(*drc_index);
	if (rc) {
		of_node_put(dn);
		goto out;
	}

	rc = dlpar_detach_node(dn);
	if (rc) {
		dlpar_acquire_drc(*drc_index);
		goto out;
	}

	of_node_put(dn);
out:
	cpu_hotplug_driver_unlock();
	return rc ? rc : count;
}
Exemple #5
0
static ssize_t dlpar_cpu_probe(const char *buf, size_t count)
{
	struct device_node *dn, *parent;
	u32 drc_index;
	int rc;

	rc = kstrtou32(buf, 0, &drc_index);
	if (rc)
		return -EINVAL;

	parent = of_find_node_by_path("/cpus");
	if (!parent)
		return -ENODEV;

	dn = dlpar_configure_connector(cpu_to_be32(drc_index), parent);
	if (!dn)
		return -EINVAL;

	of_node_put(parent);

	rc = dlpar_acquire_drc(drc_index);
	if (rc) {
		dlpar_free_cc_nodes(dn);
		return -EINVAL;
	}

	rc = dlpar_attach_node(dn);
	if (rc) {
		dlpar_release_drc(drc_index);
		dlpar_free_cc_nodes(dn);
		return rc;
	}

	rc = dlpar_online_cpu(dn);
	if (rc)
		return rc;

	return count;
}
Exemple #6
0
static int dlpar_memory_add_by_index(u32 drc_index, struct property *prop)
{
	struct of_drconf_cell *lmbs;
	u32 num_lmbs, *p;
	int i, lmb_found;
	int rc;

	pr_info("Attempting to hot-add LMB, drc index %x\n", drc_index);

	p = prop->value;
	num_lmbs = *p++;
	lmbs = (struct of_drconf_cell *)p;

	lmb_found = 0;
	for (i = 0; i < num_lmbs; i++) {
		if (lmbs[i].drc_index == drc_index) {
			lmb_found = 1;
			rc = dlpar_acquire_drc(lmbs[i].drc_index);
			if (!rc) {
				rc = dlpar_add_lmb(&lmbs[i]);
				if (rc)
					dlpar_release_drc(lmbs[i].drc_index);
			}

			break;
		}
	}

	if (!lmb_found)
		rc = -EINVAL;

	if (rc)
		pr_info("Failed to hot-add memory, drc index %x\n", drc_index);
	else
		pr_info("Memory at %llx (drc index %x) was hot-added\n",
			lmbs[i].base_addr, drc_index);

	return rc;
}
Exemple #7
0
static ssize_t dlpar_cpu_release(const char *buf, size_t count)
{
	struct device_node *dn;
	u32 drc_index;
	int rc;

	dn = of_find_node_by_path(buf);
	if (!dn)
		return -EINVAL;

	rc = of_property_read_u32(dn, "ibm,my-drc-index", &drc_index);
	if (rc) {
		of_node_put(dn);
		return -EINVAL;
	}

	rc = dlpar_offline_cpu(dn);
	if (rc) {
		of_node_put(dn);
		return -EINVAL;
	}

	rc = dlpar_release_drc(drc_index);
	if (rc) {
		of_node_put(dn);
		return rc;
	}

	rc = dlpar_detach_node(dn);
	if (rc) {
		dlpar_acquire_drc(drc_index);
		return rc;
	}

	of_node_put(dn);

	return count;
}
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_acquire_drc(lmb->drc_index);
	if (rc)
		return rc;

	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);
		dlpar_release_drc(lmb->drc_index);
	} else {
		lmb->flags |= DRCONF_MEM_ASSIGNED;
	}

	return rc;
}
Exemple #9
0
static int dlpar_memory_add_by_ic(u32 lmbs_to_add, u32 drc_index,
				  struct property *prop)
{
	struct of_drconf_cell *lmbs;
	u32 num_lmbs, *p;
	int i, rc, start_lmb_found;
	int lmbs_available = 0, start_index = 0, end_index;

	pr_info("Attempting to hot-add %u LMB(s) at index %x\n",
		lmbs_to_add, drc_index);

	if (lmbs_to_add == 0)
		return -EINVAL;

	p = prop->value;
	num_lmbs = *p++;
	lmbs = (struct of_drconf_cell *)p;
	start_lmb_found = 0;

	/* Navigate to drc_index */
	while (start_index < num_lmbs) {
		if (lmbs[start_index].drc_index == drc_index) {
			start_lmb_found = 1;
			break;
		}

		start_index++;
	}

	if (!start_lmb_found)
		return -EINVAL;

	end_index = start_index + lmbs_to_add;

	/* Validate that the LMBs in this range are not reserved */
	for (i = start_index; i < end_index; i++) {
		if (lmbs[i].flags & DRCONF_MEM_RESERVED)
			break;

		lmbs_available++;
	}

	if (lmbs_available < lmbs_to_add)
		return -EINVAL;

	for (i = start_index; i < end_index; i++) {
		if (lmbs[i].flags & DRCONF_MEM_ASSIGNED)
			continue;

		rc = dlpar_acquire_drc(lmbs[i].drc_index);
		if (rc)
			break;

		rc = dlpar_add_lmb(&lmbs[i]);
		if (rc) {
			dlpar_release_drc(lmbs[i].drc_index);
			break;
		}

		lmbs[i].reserved = 1;
	}

	if (rc) {
		pr_err("Memory indexed-count-add failed, removing any added LMBs\n");

		for (i = start_index; i < end_index; i++) {
			if (!lmbs[i].reserved)
				continue;

			rc = dlpar_remove_lmb(&lmbs[i]);
			if (rc)
				pr_err("Failed to remove LMB, drc index %x\n",
				       be32_to_cpu(lmbs[i].drc_index));
			else
				dlpar_release_drc(lmbs[i].drc_index);
		}
		rc = -EINVAL;
	} else {
		for (i = start_index; i < end_index; i++) {
			if (!lmbs[i].reserved)
				continue;

			pr_info("Memory at %llx (drc index %x) was hot-added\n",
				lmbs[i].base_addr, lmbs[i].drc_index);
			lmbs[i].reserved = 0;
		}
	}

	return rc;
}
Exemple #10
0
static int dlpar_memory_add_by_count(u32 lmbs_to_add, struct property *prop)
{
	struct of_drconf_cell *lmbs;
	u32 num_lmbs, *p;
	int lmbs_available = 0;
	int lmbs_added = 0;
	int i, rc;

	pr_info("Attempting to hot-add %d LMB(s)\n", lmbs_to_add);

	if (lmbs_to_add == 0)
		return -EINVAL;

	p = prop->value;
	num_lmbs = *p++;
	lmbs = (struct of_drconf_cell *)p;

	/* Validate that there are enough LMBs to satisfy the request */
	for (i = 0; i < num_lmbs; i++) {
		if (!(lmbs[i].flags & DRCONF_MEM_ASSIGNED))
			lmbs_available++;
	}

	if (lmbs_available < lmbs_to_add)
		return -EINVAL;

	for (i = 0; i < num_lmbs && lmbs_to_add != lmbs_added; i++) {
		rc = dlpar_acquire_drc(lmbs[i].drc_index);
		if (rc)
			continue;

		rc = dlpar_add_lmb(&lmbs[i]);
		if (rc) {
			dlpar_release_drc(lmbs[i].drc_index);
			continue;
		}

		lmbs_added++;

		/* Mark this lmb so we can remove it later if all of the
		 * requested LMBs cannot be added.
		 */
		lmbs[i].reserved = 1;
	}

	if (lmbs_added != lmbs_to_add) {
		pr_err("Memory hot-add failed, removing any added LMBs\n");

		for (i = 0; i < num_lmbs; i++) {
			if (!lmbs[i].reserved)
				continue;

			rc = dlpar_remove_lmb(&lmbs[i]);
			if (rc)
				pr_err("Failed to remove LMB, drc index %x\n",
				       be32_to_cpu(lmbs[i].drc_index));
			else
				dlpar_release_drc(lmbs[i].drc_index);
		}
		rc = -EINVAL;
	} else {
		for (i = 0; i < num_lmbs; i++) {
			if (!lmbs[i].reserved)
				continue;

			pr_info("Memory at %llx (drc index %x) was hot-added\n",
				lmbs[i].base_addr, lmbs[i].drc_index);
			lmbs[i].reserved = 0;
		}
	}

	return rc;
}