Esempio n. 1
0
static ssize_t remove_slot_store(struct kobject *kobj,
				 struct kobj_attribute *attr,
				 const char *buf, size_t nbytes)
{
	char drc_name[MAX_DRC_NAME_LEN];
	int rc;
	char *end;

	if (nbytes >= MAX_DRC_NAME_LEN)
		return 0;

	memcpy(drc_name, buf, nbytes);

	end = strchr(drc_name, '\n');
	if (!end)
		end = &drc_name[nbytes];
	*end = '\0';

	rc = dlpar_remove_slot(drc_name);
	if (rc)
		return rc;

	return nbytes;
}
Esempio n. 2
0
/**
 * add_phb
 *
 * @param op
 * @returns 0 on success, !0 otherwise
 */
static int
add_phb(struct options *opts)
{
    struct dr_node *phb = NULL;
    int rc, n_children = 0;

    phb = get_node_by_name(opts->usr_drc_name, PHB_NODES);
    if (phb) {
        say(ERROR, "PHB is already owned by this partition\n");
        rc = RC_ALREADY_OWN;
        goto phb_add_error;
    }

    rc = acquire_phb(opts->usr_drc_name, &phb);
    if (rc)
        return rc;

    rc = acquire_hp_children(phb->ofdt_path, &n_children);
    if (rc) {
        if (release_phb(phb)) {
            say(ERROR, "Unknown failure. Data may be out of sync "
                "and\nthe system may require a reboot.\n");
        }
        goto phb_add_error;
    }

    rc = dlpar_add_slot(phb->drc_name);
    if (rc) {
        if (n_children) {
            if (release_hp_children(phb->drc_name)) {
                say(ERROR, "Unknown failure. Data may be out "
                    "of sync and\nthe system may require "
                    "a reboot.\n");
            }
        }

        if (release_phb(phb)) {
            say(ERROR, "Unknown failure. Data may be out of sync "
                "and\nthe system may require a reboot.\n");
        }
        goto phb_add_error;
    }

    if (n_children) {
        rc = enable_hp_children(phb->drc_name);
        if (rc) {
            say(ERROR, "Adapter configuration failed.\n");
            if (release_hp_children(phb->drc_name)) {
                say(ERROR, "Unknown failure. Data may be out "
                    "of sync and \nthe system may require "
                    "a reboot.\n");
            }

            if (dlpar_remove_slot(phb->drc_name)) {
                say(DEBUG, "remove %s from hotplug subsystem "
                    "failed\n", phb->drc_name);
                say(ERROR, "Unknown failure. Data may be out "
                    "of sync and \nthe system may require "
                    "a reboot.\n");
            }

            if (release_phb(phb)) {
                say(ERROR, "Unknown failure. Data may be out "
                    "of sync and \nthe system may require "
                    "a reboot.\n");
            }
        }
    }

phb_add_error:
    if (phb)
        free_node(phb);

    return rc;
}
Esempio n. 3
0
/**
 * remove_phb
 *
 * @param op
 * @returns 0 on success, !0 otherwise
 */
static int
remove_phb(struct options *opts)
{
    struct dr_node *phb;
    struct dr_node *child;
    struct dr_node *hp_list;
    int rc = 0;

    phb = get_node_by_name(opts->usr_drc_name, PHB_NODES);
    if (phb == NULL) {
        say(ERROR, "Could not find PHB %s\n", opts->usr_drc_name);
        return RC_NONEXISTENT;
    }

    /* If this PHB still owns children that are not hotplug, fail. */
    for (child = phb->children; child; child = child->next) {
        if ((child->is_owned) && (child->dev_type != PCI_HP_DEV)) {
            rc = -1;
            goto phb_remove_error;
        }
    }

    /* Now, disable any hotplug children */
    hp_list = get_hp_nodes();

    for (child = phb->children; child; child = child->next) {
        struct dr_node *slot;

        if (child->dev_type == PCI_HP_DEV) {
            rc = disable_hp_children(child->drc_name);
            if (rc)
                say(ERROR,
                    "failed to disable hotplug children\n");

            /* find dr_node corresponding to child slot's drc_name */
            for (slot = hp_list; slot; slot = slot->next)
                if (!strcmp(child->drc_name, slot->drc_name))
                    break;

            /* release any hp children from the slot */
            rc = release_hp_children_from_node(slot);
            if (rc && rc != -EINVAL) {
                say(ERROR,
                    "failed to release hotplug children\n");
                goto phb_remove_error;
            }
        }
    }

    /* If there are any directories under the phb left at this point,
     * they are OS hotplug devies.  Note: this is different from DR
     * hotplug devices.  This really occurs on systems that do not
     * support DR hotplug devices.  The device tree does not get populated
     * with drc information for these devices and such they do not appear
     * on the list generated by the calls to get_node_*
     *
     * For these devices we simply hotplug remove them from the OS.
     */
    rc = disable_os_hp_children(phb);
    if (rc)
        goto phb_remove_error;

    rc = dlpar_remove_slot(phb->drc_name);
    if (rc) {
        say(ERROR, "kernel remove failed for %s, rc = %d\n",
            phb->drc_name, rc);
        goto phb_remove_error;
    }

    rc = release_phb(phb);

phb_remove_error:
    if (phb)
        free_node(phb);

    return rc;
}