Exemplo n.º 1
0
/**
 * acquire_cpu
 *
 * Acquire a new cpu for this partition from the hypervisor.
 * If drc_index is zero, look up an available index to use.
 *
 * @param drc_index
 * @returns pointer to cpu_info on success, NULL otherwise
 */
static int
acquire_cpu(struct dr_node *cpu, struct dr_info *dr_info)
{
	struct of_node *of_nodes;
	int rc;

	rc = acquire_drc(cpu->drc_index);
	if (rc) {
		say(DEBUG, "Could not acquire drc resources for %s\n",
		    cpu->name);
		return rc;
	}

	of_nodes = configure_connector(cpu->drc_index);
	if (of_nodes == NULL) {
		say(ERROR, "Call to configure_connector failed for %s\n",
		    cpu->name);
		release_drc(cpu->drc_index, CPU_DEV);
		return -1;
	}

	rc = add_device_tree_nodes(CPU_OFDT_BASE, of_nodes);
	free_of_node(of_nodes);
	if (rc) {
		say(ERROR, "Failure to add device tree nodes for %s\n",
		    cpu->name);
		release_drc(cpu->drc_index, CPU_DEV);
		return rc;
	}

	update_cpu_node(cpu, NULL, dr_info);
	refresh_cache_info(dr_info);

	return 0;
}
Exemplo n.º 2
0
/**
 * add_lmbs
 *
 * Attempt to acquire and online the given number of LMBs.
 * This function calls itself recursively to simplify recovery
 * actions in case of an error.  This is intended only for the case
 * where the user does not specify a drc-name.
 *
 * @param nr_lmbs number of lmbs to add
 * @param lmb_list list of lmbs on the partition
 * @returns 0 on success, !0 otherwise
 */
static int add_lmbs(struct lmb_list_head *lmb_list)
{
	int rc = 0;
	struct dr_node *lmb_head = lmb_list->lmbs;
	struct dr_node *lmb;

	lmb_list->lmbs_modified = 0;
	while (lmb_list->lmbs_modified < usr_drc_count) {
		if (drmgr_timed_out())
			break;

		lmb = get_available_lmb(lmb_head);
		if (lmb == NULL)
			return -1;

		/* Iterate only over the remaining LMBs */
		lmb_head = lmb->next;

		rc = acquire_drc(lmb->drc_index);
		if (rc) {
			report_unknown_error(__FILE__, __LINE__);
			lmb->unusable = 1;
			continue;
		}

		rc = add_device_tree_lmb(lmb, lmb_list);
		if (rc) {
			report_unknown_error(__FILE__, __LINE__);
			release_drc(lmb->drc_index, MEM_DEV);
			lmb->unusable = 1;
			continue;
		}

		rc = set_lmb_state(lmb, ONLINE);
		if (rc) {
			report_unknown_error(__FILE__, __LINE__);
			remove_device_tree_lmb(lmb, lmb_list);
			release_drc(lmb->drc_index, MEM_DEV);
			lmb->unusable = 1;
			continue;
		}

		lmb_list->lmbs_modified++;
	}

	return rc;
}
Exemplo n.º 3
0
/**
 * acquire_phb
 *
 */
static int acquire_phb(char *drc_name, struct dr_node **phb)
{
    struct dr_connector drc;
    struct of_node *of_nodes;
    char path[DR_PATH_MAX];
    int rc;

    rc = get_drc_by_name(drc_name, &drc, path, OFDT_BASE);
    if (rc) {
        say(ERROR, "Could not find drc index for %s, unable to add the"
            "PHB.\n", drc_name);
        return rc;
    }

    rc = acquire_drc(drc.index);
    if (rc)
        return rc;

    of_nodes = configure_connector(drc.index);
    if (of_nodes == NULL) {
        release_drc(drc.index, PHB_DEV);
        return -1;
    }

    rc = add_device_tree_nodes(path, of_nodes);
    free_of_node(of_nodes);
    if (rc) {
        say(ERROR, "add_device_tree_nodes failed at %s\n", path);
        release_drc(drc.index, PHB_DEV);
        return -1;
    }

    /* Now that the node has been added to the device-tree, retrieve it.
     * This also acts as a sanity check that everything up to this
     * point has succeeded.
     */
    *phb = get_node_by_name(drc_name, PHB_NODES);
    if (*phb == NULL) {
        say(ERROR, "Could not get find \"%s\"\n", drc_name);
        /* or should we call release_drc? but need device type */
        release_drc(drc.index, PHB_DEV);
        return -1;
    }

    return 0;
}
Exemplo n.º 4
0
/**
 * release_cpu
 *
 * Release a cpu back to the hypervisor, using the cpu's drc-index.
 * The cpu must have already been offlined.  We remove the cpu from the
 * device tree only when the isolate and set_indicator have succeeded.
 * The caller must not use the value given for the cpu parameter after
 * this function has returned.
 *
 * @param cpu
 * @returns 0 on success, !0 otherwise
 */
int
release_cpu(struct dr_node *cpu, struct dr_info *dr_info)
{
	int release_file;
	int rc;

	release_file = open(CPU_RELEASE_FILE, O_WRONLY);
	if (release_file > 0) {
		/* DLPAR can be done in kernel */
		char *path = cpu->ofdt_path + strlen(OFDT_BASE);
		int write_len = strlen(path);

		say(DEBUG, "Releasing cpu \"%s\"\n", path);
		rc = write(release_file, path, write_len);
		if (rc != write_len)
			say(ERROR, "Release failed! rc = %d\n", rc);
		else
			/* set rc to success */
			rc = 0;

		close(release_file);
	} else {
		/* Must do DLPAR from user-space */
		rc = offline_cpu(cpu);
		if (rc) {
			say(ERROR, "Could not offline cpu %s\n", cpu->drc_name);
			return rc;
		}

		rc = release_drc(cpu->drc_index, CPU_DEV);
		if (rc) {
			say(ERROR, "Could not release drc resources for %s\n",
			    cpu->name);
			return rc;
		}

		rc = remove_device_tree_nodes(cpu->ofdt_path);
		if (rc) {
			struct of_node *of_nodes;

			say(ERROR, "Could not remove device tree nodes %s\n",
			    cpu->name);
		
			of_nodes = configure_connector(cpu->drc_index);
			if (of_nodes == NULL) {
				say(ERROR, "Call to configure_connector failed "
				    "for %s. The device tree\nmay contain "
				    "invalid data for this cpu and a "
				    "re-activation of the partition is "
				    "needed to correct it.\n", cpu->name);
			} else {
				rc = add_device_tree_nodes(CPU_OFDT_BASE,
							   of_nodes);
				free_of_node(of_nodes);
			}

			acquire_drc(cpu->drc_index);
			return rc;
		}

		release_caches(cpu, dr_info);
	}

	return rc;
}