/* Hotplug routine used to remove an existing power supply */ static int remove_power_supply(int slotnum) { picl_nodehdl_t powersloth; picl_nodehdl_t powermodh; int err; /* Find the node for the given power supply slot */ if (ptree_get_node_by_path(frutree_power_supply[slotnum], &powersloth) == PICL_SUCCESS) { /* Make sure it's got a child, then delete it */ err = ptree_get_propval_by_name(powersloth, PICL_PROP_CHILD, &powermodh, sizeof (picl_nodehdl_t)); if (err != PICL_SUCCESS) { return (err); } err = ptree_delete_node(powermodh); if (err != PICL_SUCCESS) { return (err); } else { (void) ptree_destroy_node(powermodh); } /* Post picl-fru-removed event */ post_frudr_event(PICL_FRU_REMOVED, NULL, powermodh); } return (PICL_SUCCESS); }
void delete_disk_unit(led_dtls_t *dtls, int disk) { int r; picl_nodehdl_t slotndh; picl_nodehdl_t diskndh; r = find_disk_slot(dtls, disk, &slotndh); if (r != PICL_SUCCESS) return; /* * is there a disk-unit node here? */ r = ptree_find_node(slotndh, PICL_PROP_NAME, PICL_PTYPE_CHARSTRING, fcal_disk_unit, sizeof (fcal_disk_unit), &diskndh); if (r != PICL_SUCCESS) return; /* * remove disk-unit node and its properties */ r = ptree_delete_node(diskndh); if (r != PICL_SUCCESS) return; (void) ptree_destroy_node(diskndh); }
/* * Given the start node of the device tree. * find all cpus in the picl tree that don't have * device tree counterparts and remove them. */ static void remove_cpus(di_node_t di_start) { int err; picl_nodehdl_t plath; cpu_lookup_t cpu_arg; err = ptree_get_node_by_path(PLATFORM_PATH, &plath); if (err != PICL_SUCCESS) return; do { cpu_arg.di_node = di_start; cpu_arg.nodeh = 0; cpu_arg.result = 0; if (ptree_walk_tree_by_class(plath, PICL_CLASS_CPU, &cpu_arg, remove_cpu_candidate) != PICL_SUCCESS) return; if (cpu_arg.result == 1) { err = ptree_delete_node(cpu_arg.nodeh); if (err == PICL_SUCCESS) ptree_destroy_node(cpu_arg.nodeh); } } while (cpu_arg.result); }
/* * Delete all sensor nodes and related properties created by the * add_sensor_prop() for each sensor node in the PICL tree. */ static void delete_sensor_nodes_and_props(void) { sensor_node_t *snodep; /* * Delete/destroy any property created in the sensed device * as well as the sensor node and all properties under it. * Note that deleiing/destroying a node deletes/destroys * all properties within that node. */ for (snodep = sensor_nodes; snodep->sensor_name != NULL; snodep++) { if (snodep->sdev_proph != NULL) { (void) ptree_delete_prop(snodep->sdev_proph); (void) ptree_destroy_prop(snodep->sdev_proph); snodep->sdev_proph = NULL; } if (snodep->nodeh != NULL) { /* delete node and all properties under it */ (void) ptree_delete_node(snodep->nodeh); (void) ptree_destroy_node(snodep->nodeh); snodep->nodeh = NULL; snodep->proph = NULL; } } }
static int remove_picl_node(picl_nodehdl_t nodeh) { int err; err = ptree_delete_node(nodeh); if (err != PICL_SUCCESS) return (err); (void) ptree_destroy_node(nodeh); return (PICL_SUCCESS); }
/* * Delete all fan nodes and related properties created by the * add_fan_props() for each fan node in the PICL tree. */ static void delete_fan_nodes_and_props(void) { fan_node_t *fnodep; /* * Delete/destroy fan node and all properties under it. * Note that deleiing/destroying a node deletes/destroys * all properties within that node. */ for (fnodep = fan_nodes; fnodep->fan_name != NULL; fnodep++) { if (fnodep->nodeh != NULL) { (void) ptree_delete_node(fnodep->nodeh); (void) ptree_destroy_node(fnodep->nodeh); fnodep->nodeh = NULL; } } }
/* Deletes and destroys all PICL nodes for which rooth is a ancestor */ static int remove_all_nodes(picl_nodehdl_t rooth) { picl_nodehdl_t chdh; int err, done = 0; while (!done) { err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &chdh, sizeof (picl_nodehdl_t)); if (err != PICL_PROPNOTFOUND) { (void) remove_all_nodes(chdh); } else { err = ptree_delete_node(rooth); if (err != PICL_SUCCESS) { return (err); } else { (void) ptree_destroy_node(rooth); } done = 1; } } return (PICL_SUCCESS); }
void psvc_psr_plugin_init(void) { char *funcname = "psvc_plugin_psr_init"; int32_t i; int err; boolean_t present; /* * So the volatile read/write routines can retrieve data from * psvc or picl */ err = psvc_init(&hdlp); if (err != 0) { init_err(PSVC_INIT_ERR, funcname, strerror(errno)); } /* * Remove nodes whose devices aren't present from the picl tree. */ for (i = 0; i < psvc_hdl.obj_count; ++i) { picl_psvc_t *objp; uint64_t features; objp = &psvc_hdl.objects[i]; err = psvc_get_attr(hdlp, objp->name, PSVC_PRESENCE_ATTR, &present); if (err != PSVC_SUCCESS) continue; err = psvc_get_attr(hdlp, objp->name, PSVC_FEATURES_ATTR, &features); if (err != PSVC_SUCCESS) continue; if ((features & (PSVC_DEV_HOTPLUG | PSVC_DEV_OPTION)) && (present == PSVC_ABSENT)) { err = ptree_delete_node(objp->node); if (err != 0) { init_err(PTREE_DELETE_NODE_ERR, funcname, picl_strerror(err)); return; } } } /* * Remove PICL device nodes if their /devices file isn't present or * if the device file is present but the open returns ENXIO * which indicates that the node file doesn't represent a device * tree node and is probably a relic from some previous boot config */ for (i = 0; i < DEV_PR_COUNT; ++i) { picl_nodehdl_t dev_pr_node; int fd; fd = open(dev_pr_info[i].file, O_RDONLY); if (fd != -1) { close(fd); continue; } if ((errno != ENOENT) && (errno != ENXIO)) continue; err = ptree_get_node_by_path(dev_pr_info[i].path, &dev_pr_node); if (err != 0) { syslog(LOG_ERR, "Bad path: %s", dev_pr_info[i].path); init_err(PTREE_GET_NODE_ERR, funcname, picl_strerror(err)); return; } err = ptree_delete_node(dev_pr_node); if (err != 0) { init_err(PTREE_DELETE_NODE_ERR, funcname, picl_strerror(err)); return; } } free(psvc_hdl.objects); }
/* * update_picl * Called when disk goes off-line or goes to ready status. * In the case of disk ready, locate platform tree node for the disk * and add a target property (if missing). * (The target address is fixed for a given disk slot and is used to * tie the frutree disk-unit to the correct ssd node). * Returns EAGAIN for a retriable failure, otherwise 0. */ static int update_picl(led_dtls_t *dtls, int disk) { static char trailer[] = ",0"; picl_nodehdl_t slotndh; picl_nodehdl_t diskndh; ptree_propinfo_t propinfo; int r; if (dtls->disk_detected[disk] != 0) { picl_nodehdl_t fpndh; picl_nodehdl_t ssdndh; picl_prophdl_t tbl_h; picl_prophdl_t tbl_prop_h; picl_prophdl_t row_props_h[FCAL_DEVTABLE_NCOLS]; char valbuf[80]; char addr[MAXPATHLEN]; char *ptrd; const uchar_t *ptrs; int len; int addr_len; for (;;) { r = ptree_get_node_by_path(dtls->fcal_disk_parent, &fpndh); if (r != PICL_SUCCESS) { return (0); } r = ptree_get_propval_by_name(fpndh, PICL_PROP_CLASSNAME, (void *)valbuf, sizeof (valbuf)); if (r != PICL_SUCCESS) { return (0); } else if (strcmp(valbuf, "fp") == 0) { /* * The node with class fp (if present) is a * holding node representing no actual hardware. * Its presence results in two nodes with the * same effective address. (The fp class node is * UnitAddress 0,0 and the other fp node [class * devctl] has bus-addr 0,0). Locating the * required fp node for dynamic reconfiguration * then goes wrong. So, just remove it. */ SYSLOG(LOG_WARNING, EM_SPURIOUS_FP); r = ptree_delete_node(fpndh); if (r == PICL_SUCCESS) { (void) ptree_destroy_node(fpndh); continue; } return (0); } else { break; } } /* * Got a good parent node. Look at its children for a node * with this new port name. * * generate expected bus-addr property from the port-wwn * Note: dtls->disk_port[disk] points to an array of uchar_t, * the first character contains the length of the residue. * The bus-addr property is formatted as follows: * wabcdef0123456789,0 * where the 16 hex-digits represent 8 bytes from disk_port[]; */ ptrs = dtls->disk_port[disk]; if (ptrs == NULL) return (0); len = *ptrs++; ptrd = addr; *ptrd++ = 'w'; for (r = 0; r < len; r++, ptrd += 2) { (void) snprintf(ptrd, MAXPATHLEN - (ptrd - addr), "%.2x", *ptrs++); } addr_len = 1 + strlcat(addr, trailer, MAXPATHLEN); if (addr_len > MAXPATHLEN) return (0); r = ptree_find_node(fpndh, FCAL_PICL_PROP_BUS_ADDR, PICL_PTYPE_CHARSTRING, addr, addr_len, &ssdndh); /* * If the disk node corresponding to the newly inserted disk * cannot be found in the platform tree, we have probably * got in too early - probably before it's up to speed. In * this case, the WWN gleaned from devinfo may also be wrong. * This case is worth retrying in later polls when it may * succeed, so return EAGAIN. All other failures are probably * terminal, so log a failure and quit. */ if (r == PICL_NODENOTFOUND) return (EAGAIN); if (r != PICL_SUCCESS) { SYSLOG(LOG_ERR, EM_NO_FP_NODE, disk); return (0); } /* * Found platform entry for disk, add target prop */ r = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_INT, PICL_READ, sizeof (int), FCAL_PICL_PROP_TARGET, NULL, NULL); if (r != PICL_SUCCESS) return (0); (void) ptree_create_and_add_prop(ssdndh, &propinfo, &disk, NULL); /* * Remove pre-existing disk-unit node and its * properties - maybe its reference property is * out-of-date. */ delete_disk_unit(dtls, disk); /* * Add a disk-unit node in frutree */ r = find_disk_slot(dtls, disk, &slotndh); if (r != PICL_SUCCESS) return (0); r = ptree_create_and_add_node(slotndh, fcal_disk_unit, PICL_CLASS_FRU, &diskndh); if (r != PICL_SUCCESS) return (0); r = create_Device_table(&tbl_h, &tbl_prop_h); if (r != PICL_SUCCESS) return (0); r = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_CHARSTRING, PICL_READ, sizeof (PICL_CLASS_BLOCK), PICL_PROP_CLASS, NULL, NULL); if (r != PICL_SUCCESS) return (0); r = ptree_create_prop(&propinfo, PICL_CLASS_BLOCK, &row_props_h[0]); if (r != PICL_SUCCESS) return (0); r = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_REFERENCE, PICL_READ, sizeof (picl_prophdl_t), FCAL_PICL_BLOCK_REF, NULL, NULL); if (r != PICL_SUCCESS) return (0); r = ptree_create_prop(&propinfo, &ssdndh, &row_props_h[1]); if (r != PICL_SUCCESS) return (0); r = ptree_add_row_to_table(tbl_h, FCAL_DEVTABLE_NCOLS, row_props_h); if (r != PICL_SUCCESS) return (0); (void) ptree_add_prop(diskndh, tbl_prop_h); } else { /* * disk gone, remove disk_unit fru from frutree */ delete_disk_unit(dtls, disk); } return (0); }