Esempio n. 1
0
static int dlpar_memory_remove_by_index(u32 drc_index, struct property *prop)
{
	struct of_drconf_cell *lmbs;
	u32 num_lmbs, *p;
	int lmb_found;
	int i, rc;

	pr_info("Attempting to hot-remove 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_remove_lmb(&lmbs[i]);
			break;
		}
	}

	if (!lmb_found)
		rc = -EINVAL;

	if (rc)
		pr_info("Failed to hot-remove memory at %llx\n",
			lmbs[i].base_addr);
	else
		pr_info("Memory at %llx was hot-removed\n", lmbs[i].base_addr);

	return rc;
}
Esempio n. 2
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;
}
Esempio n. 3
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;
}
Esempio n. 4
0
static int dlpar_memory_remove_by_count(u32 lmbs_to_remove,
					struct property *prop)
{
	struct of_drconf_cell *lmbs;
	int lmbs_removed = 0;
	int lmbs_available = 0;
	u32 num_lmbs, *p;
	int i, rc;

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

	if (lmbs_to_remove == 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 (lmb_is_removable(&lmbs[i]))
			lmbs_available++;
	}

	if (lmbs_available < lmbs_to_remove) {
		pr_info("Not enough LMBs available (%d of %d) to satisfy request\n",
			lmbs_available, lmbs_to_remove);
		return -EINVAL;
	}

	for (i = 0; i < num_lmbs && lmbs_removed < lmbs_to_remove; i++) {
		rc = dlpar_remove_lmb(&lmbs[i]);
		if (rc)
			continue;

		lmbs_removed++;

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

	if (lmbs_removed != lmbs_to_remove) {
		pr_err("Memory hot-remove failed, adding LMB's back\n");

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

			rc = dlpar_add_lmb(&lmbs[i]);
			if (rc)
				pr_err("Failed to add LMB back, drc index %x\n",
				       lmbs[i].drc_index);

			lmbs[i].reserved = 0;
		}

		rc = -EINVAL;
	} else {
		for (i = 0; i < num_lmbs; i++) {
			if (!lmbs[i].reserved)
				continue;

			dlpar_release_drc(lmbs[i].drc_index);
			pr_info("Memory at %llx was hot-removed\n",
				lmbs[i].base_addr);

			lmbs[i].reserved = 0;
		}
		rc = 0;
	}

	return rc;
}