xref: /onnv-gate/usr/src/cmd/picl/plugins/sun4v/mdesc/mdescplugin.c (revision 5095:fb5484f03d1c)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51991Sheppo  * Common Development and Distribution License (the "License").
61991Sheppo  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
211991Sheppo 
220Sstevel@tonic-gate /*
235028Sfw157321  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate  * The MDESC picl plugin serves 2 different functionalities.
310Sstevel@tonic-gate  * --The first is to look up certain CPU properties in the MDESC an to add
320Sstevel@tonic-gate  * these properties in the already created CPU PICL nodes in the /platform
330Sstevel@tonic-gate  * section of the tree.
340Sstevel@tonic-gate  * --The second functionality is to create a /disk_discovery section of the
350Sstevel@tonic-gate  * PICL tree which will have a disk node created for each disk node in the
360Sstevel@tonic-gate  * machine description.
370Sstevel@tonic-gate  */
380Sstevel@tonic-gate 
390Sstevel@tonic-gate #include "mdescplugin.h"
405028Sfw157321 #include <libnvpair.h>
410Sstevel@tonic-gate 
420Sstevel@tonic-gate #pragma init(mdescplugin_register)	/* place in .init section */
430Sstevel@tonic-gate 
440Sstevel@tonic-gate picl_nodehdl_t	root_node;
450Sstevel@tonic-gate md_t		*mdp;
460Sstevel@tonic-gate mde_cookie_t	rootnode;
470Sstevel@tonic-gate 
480Sstevel@tonic-gate void mdescplugin_init(void);
490Sstevel@tonic-gate void mdescplugin_fini(void);
500Sstevel@tonic-gate 
510Sstevel@tonic-gate extern int add_cpu_prop(picl_nodehdl_t node, void *args);
520Sstevel@tonic-gate extern int disk_discovery(void);
530Sstevel@tonic-gate extern md_t *mdesc_devinit(void);
541991Sheppo extern void mdesc_devfini(md_t *mdp);
551991Sheppo extern int update_devices(char *dev, int op);
560Sstevel@tonic-gate 
570Sstevel@tonic-gate picld_plugin_reg_t mdescplugin_reg = {
580Sstevel@tonic-gate 	PICLD_PLUGIN_VERSION_1,
590Sstevel@tonic-gate 	PICLD_PLUGIN_CRITICAL,
600Sstevel@tonic-gate 	"mdesc_plugin",
610Sstevel@tonic-gate 	mdescplugin_init,
620Sstevel@tonic-gate 	mdescplugin_fini
630Sstevel@tonic-gate };
640Sstevel@tonic-gate 
650Sstevel@tonic-gate #define	DISK_FOUND 0x00
660Sstevel@tonic-gate #define	DISK_NOT_FOUND 0x01
670Sstevel@tonic-gate 
680Sstevel@tonic-gate typedef struct disk_lookup {
690Sstevel@tonic-gate 	char *path;
700Sstevel@tonic-gate 	picl_nodehdl_t disk;
710Sstevel@tonic-gate 	int result;
720Sstevel@tonic-gate } disk_lookup_t;
730Sstevel@tonic-gate 
740Sstevel@tonic-gate int
750Sstevel@tonic-gate find_disk(picl_nodehdl_t node, void *args)
760Sstevel@tonic-gate {
770Sstevel@tonic-gate 	disk_lookup_t *lookup  = (disk_lookup_t *)args;
780Sstevel@tonic-gate 	int status;
790Sstevel@tonic-gate 	char path[PICL_PROPNAMELEN_MAX];
800Sstevel@tonic-gate 
810Sstevel@tonic-gate 	status = ptree_get_propval_by_name(node, "Path", (void *)&path,
820Sstevel@tonic-gate 	    PICL_PROPNAMELEN_MAX);
830Sstevel@tonic-gate 	if (status != PICL_SUCCESS) {
840Sstevel@tonic-gate 		return (PICL_WALK_CONTINUE);
850Sstevel@tonic-gate 	}
860Sstevel@tonic-gate 
870Sstevel@tonic-gate 	if (strcmp(path, lookup->path) == 0) {
880Sstevel@tonic-gate 		lookup->disk = node;
890Sstevel@tonic-gate 		lookup->result = DISK_FOUND;
900Sstevel@tonic-gate 		return (PICL_WALK_TERMINATE);
910Sstevel@tonic-gate 	}
920Sstevel@tonic-gate 
930Sstevel@tonic-gate 	return (PICL_WALK_CONTINUE);
940Sstevel@tonic-gate }
950Sstevel@tonic-gate 
960Sstevel@tonic-gate /*
971991Sheppo  * DR event handler
981991Sheppo  * respond to the picl events:
991991Sheppo  *      PICLEVENT_DR_AP_STATE_CHANGE
1001991Sheppo  */
1011991Sheppo static void
1021991Sheppo dr_handler(const char *ename, const void *earg, size_t size, void *cookie)
1031991Sheppo {
1041991Sheppo 	nvlist_t	*nvlp = NULL;
1051991Sheppo 	char		*dtype;
1061991Sheppo 	char		*ap_id;
1071991Sheppo 	char		*hint;
1081991Sheppo 
1091991Sheppo 
1101991Sheppo 	if (strcmp(ename, PICLEVENT_DR_AP_STATE_CHANGE) != 0) {
1111991Sheppo 		return;
1121991Sheppo 	}
1131991Sheppo 
1141991Sheppo 	if (nvlist_unpack((char *)earg, size, &nvlp, NULL)) {
1151991Sheppo 		return;
1161991Sheppo 	}
1171991Sheppo 
1181991Sheppo 	if (nvlist_lookup_string(nvlp, PICLEVENTARG_DATA_TYPE, &dtype)) {
1191991Sheppo 		nvlist_free(nvlp);
1201991Sheppo 		return;
1211991Sheppo 	}
1221991Sheppo 
1231991Sheppo 	if (strcmp(dtype, PICLEVENTARG_PICLEVENT_DATA) != 0) {
1241991Sheppo 		nvlist_free(nvlp);
1251991Sheppo 		return;
1261991Sheppo 	}
1271991Sheppo 
1281991Sheppo 	if (nvlist_lookup_string(nvlp, PICLEVENTARG_AP_ID, &ap_id)) {
1291991Sheppo 		nvlist_free(nvlp);
1301991Sheppo 		return;
1311991Sheppo 	}
1321991Sheppo 
1331991Sheppo 	if (nvlist_lookup_string(nvlp, PICLEVENTARG_HINT, &hint)) {
1341991Sheppo 		nvlist_free(nvlp);
1351991Sheppo 		return;
1361991Sheppo 	}
1371991Sheppo 
1381991Sheppo 	mdp = mdesc_devinit();
1391991Sheppo 	if (mdp == NULL) {
1401991Sheppo 		nvlist_free(nvlp);
1411991Sheppo 		return;
1421991Sheppo 	}
1431991Sheppo 
1441991Sheppo 	rootnode = md_root_node(mdp);
1451991Sheppo 
1461991Sheppo 	if (strcmp(hint, DR_HINT_INSERT) == 0)
1471991Sheppo 		(void) update_devices(ap_id, DEV_ADD);
1481991Sheppo 	else if (strcmp(hint, DR_HINT_REMOVE) == 0)
1491991Sheppo 		(void) update_devices(ap_id, DEV_REMOVE);
1501991Sheppo 
1511991Sheppo 	mdesc_devfini(mdp);
1521991Sheppo 	nvlist_free(nvlp);
1531991Sheppo }
1541991Sheppo 
1551991Sheppo /*
1560Sstevel@tonic-gate  * Discovery event handler
1570Sstevel@tonic-gate  * respond to the picl events:
1580Sstevel@tonic-gate  *      PICLEVENT_SYSEVENT_DEVICE_ADDED
1590Sstevel@tonic-gate  *      PICLEVENT_SYSEVENT_DEVICE_REMOVED
1600Sstevel@tonic-gate  */
1610Sstevel@tonic-gate static void
1620Sstevel@tonic-gate dsc_handler(const char *ename, const void *earg, size_t size, void *cookie)
1630Sstevel@tonic-gate {
1640Sstevel@tonic-gate 	nvlist_t	*nvlp = NULL;
1650Sstevel@tonic-gate 	char		*path;
1660Sstevel@tonic-gate 	disk_lookup_t	lookup;
1670Sstevel@tonic-gate 	int		status;
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate 	/*
1700Sstevel@tonic-gate 	 * retrieve the device's physical path from the event arg
1710Sstevel@tonic-gate 	 * and determine which disk (if any) we are working with
1720Sstevel@tonic-gate 	 */
1730Sstevel@tonic-gate 	if (nvlist_unpack((char *)earg, size, &nvlp, NULL))
1740Sstevel@tonic-gate 		return;
1750Sstevel@tonic-gate 	if (nvlist_lookup_string(nvlp, "devfs-path", &path))
1760Sstevel@tonic-gate 		return;
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate 	lookup.path = strdup(path);
1790Sstevel@tonic-gate 	lookup.disk = NULL;
1800Sstevel@tonic-gate 	lookup.result = DISK_NOT_FOUND;
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate 	status = ptree_walk_tree_by_class(root_node, "disk", (void *)&lookup,
1830Sstevel@tonic-gate 	    find_disk);
1840Sstevel@tonic-gate 	if (status != PICL_SUCCESS) {
1850Sstevel@tonic-gate 		return;
1860Sstevel@tonic-gate 	}
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate 	if (lookup.result == DISK_FOUND) {
1890Sstevel@tonic-gate 		if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_ADDED) == 0)
1900Sstevel@tonic-gate 			ptree_update_propval_by_name(lookup.disk, "State",
1910Sstevel@tonic-gate 			    (void *)strdup(CONFIGURED), PICL_PROPNAMELEN_MAX);
1920Sstevel@tonic-gate 		else if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_REMOVED) == 0)
1930Sstevel@tonic-gate 			ptree_update_propval_by_name(lookup.disk, "State",
1940Sstevel@tonic-gate 			    (void *)strdup(UNCONFIGURED), PICL_PROPNAMELEN_MAX);
1950Sstevel@tonic-gate 	}
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 	nvlist_free(nvlp);
1980Sstevel@tonic-gate }
1990Sstevel@tonic-gate 
2005028Sfw157321 /*ARGSUSED*/
2015028Sfw157321 static void
2025028Sfw157321 mdesc_ev_completion_handler(char *ename, void *earg, size_t size)
2035028Sfw157321 {
2045028Sfw157321 	free(earg);
2055028Sfw157321 }
2065028Sfw157321 
2075028Sfw157321 static void
2085028Sfw157321 signal_devtree(void)
2095028Sfw157321 {
2105028Sfw157321 	nvlist_t *nvl;
2115028Sfw157321 	char *packed_nvl;
2125028Sfw157321 	size_t nvl_size;
2135028Sfw157321 	int status;
2145028Sfw157321 
2155028Sfw157321 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME_TYPE, NULL) != 0)
2165028Sfw157321 		return;
2175028Sfw157321 
2185028Sfw157321 	/*
2195028Sfw157321 	 * Right now (Aug. 2007) snowbird is the only other platform
2205028Sfw157321 	 * which uses this event.  Since that's a sun4u platform and
2215028Sfw157321 	 * this is sun4v we do not have to worry about possible confusion
2225028Sfw157321 	 * or interference between the two by grabbing this event for
2235028Sfw157321 	 * our own use here.  This event is consumed by the devtree
2245028Sfw157321 	 * plug-in.  The event signals the plug-in to re-run its
2255028Sfw157321 	 * cpu initialization function, which will cause it to add
2265028Sfw157321 	 * additional information to the cpu devtree nodes (particularly,
2275028Sfw157321 	 * the administrative state of the cpus.)
2285028Sfw157321 	 */
2295028Sfw157321 	if (nvlist_add_string(nvl, PICLEVENTARG_EVENT_NAME,
2305028Sfw157321 	    PICLEVENT_CPU_STATE_CHANGE) != 0) {
2315028Sfw157321 		free(nvl);
2325028Sfw157321 		return;
2335028Sfw157321 	}
2345028Sfw157321 
2355028Sfw157321 	/*
2365028Sfw157321 	 * The devtree plug-in needs to see a devfs path argument for
2375028Sfw157321 	 * any event it considers.  We supply one here which is essentially
2385028Sfw157321 	 * a dummy since it is not processed by the devtree plug-in for
2395028Sfw157321 	 * this event.
2405028Sfw157321 	 */
2415028Sfw157321 	if (nvlist_add_string(nvl, PICLEVENTARG_DEVFS_PATH, "/cpu") != 0) {
2425028Sfw157321 		free(nvl);
2435028Sfw157321 		return;
2445028Sfw157321 	}
245*5095Sfw157321 	packed_nvl = NULL;
2465028Sfw157321 	if (nvlist_pack(nvl, &packed_nvl, &nvl_size, NV_ENCODE_NATIVE,
247*5095Sfw157321 	    0) != 0) {
2485028Sfw157321 		free(nvl);
2495028Sfw157321 		return;
2505028Sfw157321 	}
2515028Sfw157321 	if ((status = ptree_post_event(PICLEVENT_CPU_STATE_CHANGE,
2525028Sfw157321 	    packed_nvl, nvl_size, mdesc_ev_completion_handler)) !=
2535028Sfw157321 	    PICL_SUCCESS) {
2545028Sfw157321 		free(nvl);
2555028Sfw157321 		syslog(LOG_WARNING,
2565028Sfw157321 		    "signal_devtree: can't post cpu event: %d\n", status);
2575028Sfw157321 	}
2585028Sfw157321 }
2595028Sfw157321 
2600Sstevel@tonic-gate void
2610Sstevel@tonic-gate mdescplugin_init(void)
2620Sstevel@tonic-gate {
2630Sstevel@tonic-gate 	int		status;
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate 	status = ptree_get_root(&root_node);
2660Sstevel@tonic-gate 	if (status != PICL_SUCCESS) {
2670Sstevel@tonic-gate 		return;
2680Sstevel@tonic-gate 	}
2690Sstevel@tonic-gate 
2700Sstevel@tonic-gate 	mdp = mdesc_devinit();
2710Sstevel@tonic-gate 	if (mdp == NULL)
2720Sstevel@tonic-gate 		return;
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	rootnode = md_root_node(mdp);
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate 	/*
2770Sstevel@tonic-gate 	 * This is the start of the CPU property augmentation code.
2780Sstevel@tonic-gate 	 * add_cpu_prop and the rest of the CPU code lives in cpu_prop_update.c
2790Sstevel@tonic-gate 	 */
2800Sstevel@tonic-gate 	status = ptree_walk_tree_by_class(root_node, "cpu", NULL, add_cpu_prop);
2810Sstevel@tonic-gate 	if (status != PICL_SUCCESS) {
2820Sstevel@tonic-gate 		return;
2830Sstevel@tonic-gate 	}
2840Sstevel@tonic-gate 
2855028Sfw157321 	signal_devtree();
2865028Sfw157321 
2870Sstevel@tonic-gate 	(void) disk_discovery();
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate 	/*
2900Sstevel@tonic-gate 	 * register dsc_handler for both "sysevent-device-added" and
2910Sstevel@tonic-gate 	 * and for "sysevent-device-removed" PICL events
2920Sstevel@tonic-gate 	 */
2930Sstevel@tonic-gate 	(void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
2940Sstevel@tonic-gate 	    dsc_handler, NULL);
2950Sstevel@tonic-gate 	(void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
2960Sstevel@tonic-gate 	    dsc_handler, NULL);
2971991Sheppo 	(void) ptree_register_handler(PICLEVENT_DR_AP_STATE_CHANGE,
2981991Sheppo 	    dr_handler, NULL);
2990Sstevel@tonic-gate 
3001991Sheppo 	mdesc_devfini(mdp);
3010Sstevel@tonic-gate }
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate void
3040Sstevel@tonic-gate mdescplugin_fini(void)
3050Sstevel@tonic-gate {
3060Sstevel@tonic-gate 	/* unregister the event handler */
3070Sstevel@tonic-gate 	(void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
3080Sstevel@tonic-gate 	    dsc_handler, NULL);
3090Sstevel@tonic-gate 	(void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
3100Sstevel@tonic-gate 	    dsc_handler, NULL);
3111991Sheppo 	(void) ptree_unregister_handler(PICLEVENT_DR_AP_STATE_CHANGE,
3121991Sheppo 	    dr_handler, NULL);
3130Sstevel@tonic-gate }
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate void
3160Sstevel@tonic-gate mdescplugin_register(void)
3170Sstevel@tonic-gate {
3180Sstevel@tonic-gate 	picld_plugin_register(&mdescplugin_reg);
3190Sstevel@tonic-gate }
320