Beispiel #1
0
/* 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);
}
Beispiel #3
0
/*
 * 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);
}
Beispiel #4
0
/*
 * 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;
		}
	}
}
Beispiel #5
0
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);
}
Beispiel #6
0
/*
 * 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;
		}
	}
}
Beispiel #7
0
/* 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);
}
Beispiel #8
0
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);
}