int
drslot_chrp_pci(struct options *opts)
{
	int rc;
	struct dr_node *all_nodes;

	all_nodes = get_hp_nodes();
	if (all_nodes == NULL) {
		say(ERROR, "There are no PCI hot plug slots on this system.\n");
		return -1;
	}

#ifdef DBG_HOT_PLUG
	print_slots_list(all_nodes);
#endif

	if (!opts->usr_drc_name)
		opts->usr_drc_name = find_drc_name(opts->usr_drc_index, all_nodes);

	switch (opts->action) {
	    case ADD:
		rc = do_add(opts, all_nodes);
		break;
	    case REMOVE:
		rc = do_remove(opts, all_nodes);
		break;
	    case REPLACE:
		rc = do_replace(opts, all_nodes);
		break;
	    case IDENTIFY:
		rc = do_identify(opts, all_nodes);
		break;
	    default:
		say(ERROR, "Invalid operation specified!\n");
		rc = -1;
		break;
	}

	free_node(all_nodes);
	return rc;
}
/**
 * release_hp_children
 *
 * @param parent_drc_name
 * @returns 0 on success, !0 otherwise
 */
int
release_hp_children(char *parent_drc_name)
{
	struct dr_node *hp_list, *slot;
	int rc;

	hp_list = get_hp_nodes();
	for (slot = hp_list; slot; slot = slot->next)
		if (!strcmp(parent_drc_name, slot->drc_name))
			break;

	if (slot == NULL) {
		rc = -EINVAL;
		goto out;
	}

	rc = release_hp_children_from_node(slot);

out:
	free_node(hp_list);
	return (rc < 0) ? rc : 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;
}
Exemple #4
0
/**
 * lsslot_chrp_pci
 * @brief main entry point for lsslot command
 *
 * @param opts
 * @returns 0 on success, !0 otherwise
 */
int
lsslot_chrp_pci(struct cmd_opts *opts)
{
	struct dr_node *all_nodes;	/* Pointer to list of all node info */
	struct dr_node *node;	/* Used to traverse list of node info */
	char	fmt[128];
	struct print_node *p;
	char *sheading = "# Slot";	/* Used in printing headers */
	char *dheading = "Description";	/* Used in printing headers */
	char *lheading = "Device(s)";	/* Used in printing headers */
	char *lname_header = "Linux Name";
	int rc = 0;

	/* Set initial column sizes */
	max_sname = MAX(max_sname, strlen(sheading));
	max_desc = MAX(max_desc, strlen(dheading));

	/* Get all of node(logical DR or PCI) node information */
	if (opts->slot_type == PCI)
		all_nodes = get_hp_nodes();
	else
		all_nodes = get_dlpar_nodes(PCI_NODES | VIO_NODES | HEA_NODES);

	/* If nothing returned, then no hot plug node */
	if (all_nodes == NULL) {
		if (opts->slot_type == PCI)
			say(ERROR, "There are no PCI hot plug slots on "
			    "this system.\n");
		else
			say(ERROR, "There are no DR slots on this system.\n");
   		return 0;
	}

	print_node_list(all_nodes);

	/* Otherwise, run through the node list looking for the nodes
	 * we want to print
	 */
	for (node = all_nodes; node; node = node->next) {
		if (! node->is_owned || node->skip)
			continue;
		
		if (opts->s_name != NULL) {
			if (cmp_drcname(node->drc_name, opts->s_name))
				insert_print_node(node);
		}

		/* If aflag and slot is empty, then format the slot */
		else if (opts->a_flag && (node->children == NULL))
			insert_print_node(node);

		/* If oflag and slot occupied, then format the slot */
		else if (opts->o_flag && (node->children != NULL))
			insert_print_node(node);
	}

	if (print_list == NULL) {
		/* If nothing to print, display message based on if
		 * user specified a slot or a device name.
		 */
		if (opts->s_name != NULL) {
			say(ERROR, "The specified PCI slot is either invalid\n"
			    "or does not support hot plug operations.\n");
			rc = 1;
		}
		goto lsslot_pci_exit;
	}

	/* This creates a format string so that slot name and description
	 * prints out in the required field width. When the -F flag is
	 * specified, the format string contains the delimiting character
	 * which the user specified at the command line.
	 */
	if (opts->slot_type == SLOT) {
		if (opts->delim != NULL)
			sprintf(fmt, "%s%s%s%s%s%s", "%s", opts->delim,
				"%s", opts->delim, "%s", opts->delim);
		else {
			sprintf(fmt, "%%-%ds%%-%ds%%-%ds", max_sname + 2,
				max_desc + 2, LNAME_SIZE + 2);
			/* Print out the header. */
			printf(fmt, sheading, dheading, lname_header);
			printf("%s\n", lheading);
		}
	} else {
		if (opts->delim != NULL)
			sprintf(fmt, "%s%s%s%s", "%s", opts->delim,
				"%s", opts->delim);
		else {
			sprintf(fmt, "%%-%ds%%-%ds", max_sname + 2,
				max_desc + 2);
			/* Print out the header. */
			printf(fmt, sheading, dheading);
			printf("%s\n", lheading);
		}
	}

	/* Now run through the list of slots we actually want to print */
	for (p = print_list; p != NULL; p = p->next) {
		if (! p->node->is_owned) {
			/* skip it, because the partition doesn't own it */
			continue;
		}

		if (opts->slot_type == SLOT)
			print_drslot_line(p, fmt);
		else
			print_phpslot_line(p, fmt);
	}

lsslot_pci_exit:
	free_print_list();
	free_node(all_nodes);
	return rc;
}