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