Exemplo n.º 1
0
/*
 * Given the root node of the device tree.
 * compare it to the picl tree and add to it cpus
 * that are new.
 */
static void
add_cpus(di_node_t di_node)
{
	int		err;
	di_node_t	cnode;
	picl_nodehdl_t	plath;
	cpu_lookup_t	cpu_arg;
	char		*nodename;

	err = ptree_get_node_by_path(PLATFORM_PATH, &plath);
	if (err != PICL_SUCCESS)
		return;

	for (cnode = di_child_node(di_node); cnode != DI_NODE_NIL;
	    cnode = di_sibling_node(cnode)) {
		nodename = di_node_name(cnode);
		if (nodename == NULL)
			continue;
		if (strcmp(nodename, OBP_CPU) == 0) {
			cpu_arg.di_node = cnode;

			if (ptree_walk_tree_by_class(plath,
			    PICL_CLASS_CPU, &cpu_arg, cpu_exists)
			    != PICL_SUCCESS)
				return;

			if (cpu_arg.result == 0)
				/*
				 * Didn't find a matching cpu, add it.
				 */
				(void) construct_cpu_node(plath,
				    cnode);
		}
	}
}
Exemplo n.º 2
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);
}
Exemplo n.º 3
0
void
mdescplugin_init(void)
{
	int		status;

	status = ptree_get_root(&root_node);
	if (status != PICL_SUCCESS) {
		return;
	}

	mdp = mdesc_devinit();
	if (mdp == NULL)
		return;

	/*
	 * update the cpu configuration in case the snapshot cache used by the
	 * devtree plugin is out of date.
	 */
	(void) update_devices(OBP_CPU, DEV_ADD);
	(void) update_devices(OBP_CPU, DEV_REMOVE);

	rootnode = md_root_node(mdp);

	/*
	 * This is the start of the CPU property augmentation code.
	 * add_cpu_prop and the rest of the CPU code lives in cpu_prop_update.c
	 */
	status = ptree_walk_tree_by_class(root_node, "cpu", NULL, add_cpu_prop);
	if (status != PICL_SUCCESS) {
		return;
	}

	signal_devtree();

	(void) disk_discovery();

	/*
	 * register dsc_handler for both "sysevent-device-added" and
	 * and for "sysevent-device-removed" PICL events
	 */
	(void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
	    dsc_handler, NULL);
	(void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
	    dsc_handler, NULL);
	(void) ptree_register_handler(PICLEVENT_DR_AP_STATE_CHANGE,
	    dr_handler, NULL);

	mdesc_devfini(mdp);
}
Exemplo n.º 4
0
/*
 * Discovery event handler
 * respond to the picl events:
 *      PICLEVENT_SYSEVENT_DEVICE_ADDED
 *      PICLEVENT_SYSEVENT_DEVICE_REMOVED
 */
static void
dsc_handler(const char *ename, const void *earg, size_t size, void *cookie)
{
	nvlist_t	*nvlp = NULL;
	char		*path;
	disk_lookup_t	lookup;
	int		status;

	/*
	 * retrieve the device's physical path from the event arg
	 * and determine which disk (if any) we are working with
	 */
	if (nvlist_unpack((char *)earg, size, &nvlp, NULL))
		return;
	if (nvlist_lookup_string(nvlp, "devfs-path", &path))
		return;

	lookup.path = strdup(path);
	lookup.disk = NULL;
	lookup.result = DISK_NOT_FOUND;

	status = ptree_walk_tree_by_class(root_node, "disk", (void *)&lookup,
	    find_disk);
	if (status != PICL_SUCCESS) {
		return;
	}

	if (lookup.result == DISK_FOUND) {
		if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_ADDED) == 0)
			ptree_update_propval_by_name(lookup.disk, "State",
			    (void *)strdup(CONFIGURED), PICL_PROPNAMELEN_MAX);
		else if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_REMOVED) == 0)
			ptree_update_propval_by_name(lookup.disk, "State",
			    (void *)strdup(UNCONFIGURED), PICL_PROPNAMELEN_MAX);
	}

	nvlist_free(nvlp);
}
Exemplo n.º 5
0
/*
 * Ontario SBL event handler, subscribed to:
 * 	PICLEVENT_SYSEVENT_DEVICE_ADDED
 * 	PICLEVENT_SYSEVENT_DEVICE_REMOVED
 */
static void
piclsbl_handler(const char *ename, const void *earg, size_t size,
		void *cookie)
{
	char		*devfs_path;
	char		hdd_location[PICL_PROPNAMELEN_MAX];
	nvlist_t	*nvlp = NULL;
	pcp_msg_t	send_msg;
	pcp_msg_t	recv_msg;
	pcp_sbl_req_t	*req_ptr = NULL;
	pcp_sbl_resp_t	*resp_ptr = NULL;
	int		status = -1;
	int		target;
	disk_lookup_t	lookup;
	int		channel_fd;

	/*
	 * setup the request data to attach to the libpcp msg
	 */
	if ((req_ptr = (pcp_sbl_req_t *)umem_zalloc(sizeof (pcp_sbl_req_t),
			UMEM_DEFAULT)) == NULL)
		goto sbl_return;

	/*
	 * This plugin serves to enable or disable the blue RAS
	 * 'ok-to-remove' LED that is on each of the 4 disks on the
	 * Ontario.  We catch the event via the picl handler, and
	 * if the event is DEVICE_ADDED for one of our onboard disks,
	 * then we'll be turning off the LED. Otherwise, if the event
	 * is DEVICE_REMOVED, then we turn it on.
	 */
	if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_ADDED) == 0)
		req_ptr->sbl_action = PCP_SBL_DISABLE;
	else if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_REMOVED) == 0)
		req_ptr->sbl_action = PCP_SBL_ENABLE;
	else
		goto sbl_return;

	/*
	 * retrieve the device's physical path from the event payload
	 */
	if (nvlist_unpack((char *)earg, size, &nvlp, NULL))
		goto sbl_return;
	if (nvlist_lookup_string(nvlp, "devfs-path", &devfs_path))
		goto sbl_return;

	/*
	 * look for this disk in the picl tree, and if it's
	 * location indicates that it's one of our internal
	 * disks, then set sbl_id to incdicate which one.
	 * otherwise, return as it is not one of our disks.
	 */
	lookup.path = strdup(devfs_path);
	lookup.disk = NULL;
	lookup.result = DISK_NOT_FOUND;

	/* first, find the disk */
	status = ptree_walk_tree_by_class(root_node, "disk", (void *)&lookup,
						cb_find_disk);
	if (status != PICL_SUCCESS)
		goto sbl_return;

	if (lookup.result == DISK_FOUND) {
		/* now, lookup it's location in the node */
		status = ptree_get_propval_by_name(lookup.disk, "Location",
				(void *)&hdd_location, PICL_PROPNAMELEN_MAX);
		if (status != PICL_SUCCESS) {
			syslog(LOG_ERR, "piclsbl: failed hdd discovery");
			goto sbl_return;
		}
	}

	if (strcmp(hdd_location, HDD0) == 0) {
		req_ptr->sbl_id = PCP_SBL_HDD0;
		target = 0;
	} else if (strcmp(hdd_location, HDD1) == 0) {
		req_ptr->sbl_id = PCP_SBL_HDD1;
		target = 1;
	} else if (strcmp(hdd_location, HDD2) == 0) {
		req_ptr->sbl_id = PCP_SBL_HDD2;
		target = 2;
	} else if (strcmp(hdd_location, HDD3) == 0) {
		req_ptr->sbl_id = PCP_SBL_HDD3;
		target = 3;
	} else {
		/* this is not one of the onboard disks */
		goto sbl_return;
	}

	/*
	 * check the onboard RAID configuration for this disk. if it is
	 * a member of a RAID and is not the RAID itself, ignore the event
	 */
	if (check_raid(target))
		goto sbl_return;

	/*
	 * we have the information we need, init the platform channel.
	 * the platform channel driver will only allow one connection
	 * at a time on this socket. on the offchance that more than
	 * one event comes in, we'll retry to initialize this connection
	 * up to 3 times
	 */
	if ((channel_fd = (*pcp_init_ptr)(LED_CHANNEL)) < 0) {
		/* failed to init; wait and retry up to 3 times */
		int s = PCPINIT_TIMEOUT;
		int retries = 0;
		while (++retries) {
			(void) sleep(s);
			if ((channel_fd = (*pcp_init_ptr)(LED_CHANNEL)) >= 0)
				break;
			else if (retries == 3) {
				syslog(LOG_ERR, "piclsbl: ",
					"SC channel initialization failed");
				goto sbl_return;
			}
			/* continue */
		}
	}

	/*
	 * populate the message for libpcp
	 */
	send_msg.msg_type = PCP_SBL_CONTROL;
	send_msg.sub_type = NULL;
	send_msg.msg_len = sizeof (pcp_sbl_req_t);
	send_msg.msg_data = (uint8_t *)req_ptr;

	/*
	 * send the request, receive the response
	 */
	if ((*pcp_send_recv_ptr)(channel_fd, &send_msg, &recv_msg,
		PCPCOMM_TIMEOUT) < 0) {
		/* we either timed out or erred; either way try again */
		int s = PCPCOMM_TIMEOUT;
		(void) sleep(s);
		if ((*pcp_send_recv_ptr)(channel_fd, &send_msg, &recv_msg,
				PCPCOMM_TIMEOUT) < 0) {
			syslog(LOG_ERR, "piclsbl: communication failure");
			goto sbl_return;
		}
	}

	/*
	 * validate that this data was meant for us
	 */
	if (recv_msg.msg_type != PCP_SBL_CONTROL_R) {
		syslog(LOG_ERR, "piclsbl: unbound packet received");
		goto sbl_return;
	}

	/*
	 * verify that the LED action has taken place
	 */
	resp_ptr = (pcp_sbl_resp_t *)recv_msg.msg_data;
	if (resp_ptr->status == PCP_SBL_ERROR) {
		syslog(LOG_ERR, "piclsbl: OK2RM LED action error");
		goto sbl_return;
	}

	/*
	 * ensure the LED action taken is the one requested
	 */
	if ((req_ptr->sbl_action == PCP_SBL_DISABLE) &&
		(resp_ptr->sbl_state != SBL_STATE_OFF))
		syslog(LOG_ERR, "piclsbl: OK2RM LED not OFF after disk "
				"configuration");
	else if ((req_ptr->sbl_action == PCP_SBL_ENABLE) &&
			(resp_ptr->sbl_state != SBL_STATE_ON))
		syslog(LOG_ERR, "piclsbl: OK2RM LED not ON after disk "
				"unconfiguration");
	else if (resp_ptr->sbl_state == SBL_STATE_UNKNOWN)
		syslog(LOG_ERR, "piclsbl: OK2RM LED set to unknown state");

sbl_return:

	(*pcp_close_ptr)(channel_fd);
	if (req_ptr != NULL)
		umem_free(req_ptr, sizeof (pcp_sbl_req_t));
	if (resp_ptr != NULL)
		free(resp_ptr);
	if (nvlp != NULL)
		nvlist_free(nvlp);
}