xref: /onnv-gate/usr/src/cmd/picl/plugins/sun4v/mdesc/mdescplugin.c (revision 9764:71add1375290)
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 /*
23*9764SMichael.Bergknoff@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate /*
280Sstevel@tonic-gate  * The MDESC picl plugin serves 2 different functionalities.
290Sstevel@tonic-gate  * --The first is to look up certain CPU properties in the MDESC an to add
300Sstevel@tonic-gate  * these properties in the already created CPU PICL nodes in the /platform
310Sstevel@tonic-gate  * section of the tree.
320Sstevel@tonic-gate  * --The second functionality is to create a /disk_discovery section of the
330Sstevel@tonic-gate  * PICL tree which will have a disk node created for each disk node in the
340Sstevel@tonic-gate  * machine description.
350Sstevel@tonic-gate  */
360Sstevel@tonic-gate 
370Sstevel@tonic-gate #include "mdescplugin.h"
385028Sfw157321 #include <libnvpair.h>
390Sstevel@tonic-gate 
400Sstevel@tonic-gate #pragma init(mdescplugin_register)	/* place in .init section */
410Sstevel@tonic-gate 
420Sstevel@tonic-gate picl_nodehdl_t	root_node;
430Sstevel@tonic-gate md_t		*mdp;
440Sstevel@tonic-gate mde_cookie_t	rootnode;
450Sstevel@tonic-gate 
460Sstevel@tonic-gate void mdescplugin_init(void);
470Sstevel@tonic-gate void mdescplugin_fini(void);
48*9764SMichael.Bergknoff@Sun.COM static void signal_devtree(void);
490Sstevel@tonic-gate 
500Sstevel@tonic-gate extern int add_cpu_prop(picl_nodehdl_t node, void *args);
510Sstevel@tonic-gate extern int disk_discovery(void);
520Sstevel@tonic-gate extern md_t *mdesc_devinit(void);
531991Sheppo extern void mdesc_devfini(md_t *mdp);
541991Sheppo extern int update_devices(char *dev, int op);
550Sstevel@tonic-gate 
560Sstevel@tonic-gate picld_plugin_reg_t mdescplugin_reg = {
570Sstevel@tonic-gate 	PICLD_PLUGIN_VERSION_1,
580Sstevel@tonic-gate 	PICLD_PLUGIN_CRITICAL,
590Sstevel@tonic-gate 	"mdesc_plugin",
600Sstevel@tonic-gate 	mdescplugin_init,
610Sstevel@tonic-gate 	mdescplugin_fini
620Sstevel@tonic-gate };
630Sstevel@tonic-gate 
640Sstevel@tonic-gate #define	DISK_FOUND 0x00
650Sstevel@tonic-gate #define	DISK_NOT_FOUND 0x01
660Sstevel@tonic-gate 
670Sstevel@tonic-gate typedef struct disk_lookup {
680Sstevel@tonic-gate 	char *path;
690Sstevel@tonic-gate 	picl_nodehdl_t disk;
700Sstevel@tonic-gate 	int result;
710Sstevel@tonic-gate } disk_lookup_t;
720Sstevel@tonic-gate 
730Sstevel@tonic-gate int
find_disk(picl_nodehdl_t node,void * args)740Sstevel@tonic-gate find_disk(picl_nodehdl_t node, void *args)
750Sstevel@tonic-gate {
760Sstevel@tonic-gate 	disk_lookup_t *lookup  = (disk_lookup_t *)args;
770Sstevel@tonic-gate 	int status;
780Sstevel@tonic-gate 	char path[PICL_PROPNAMELEN_MAX];
790Sstevel@tonic-gate 
800Sstevel@tonic-gate 	status = ptree_get_propval_by_name(node, "Path", (void *)&path,
810Sstevel@tonic-gate 	    PICL_PROPNAMELEN_MAX);
820Sstevel@tonic-gate 	if (status != PICL_SUCCESS) {
830Sstevel@tonic-gate 		return (PICL_WALK_CONTINUE);
840Sstevel@tonic-gate 	}
850Sstevel@tonic-gate 
860Sstevel@tonic-gate 	if (strcmp(path, lookup->path) == 0) {
870Sstevel@tonic-gate 		lookup->disk = node;
880Sstevel@tonic-gate 		lookup->result = DISK_FOUND;
890Sstevel@tonic-gate 		return (PICL_WALK_TERMINATE);
900Sstevel@tonic-gate 	}
910Sstevel@tonic-gate 
920Sstevel@tonic-gate 	return (PICL_WALK_CONTINUE);
930Sstevel@tonic-gate }
940Sstevel@tonic-gate 
950Sstevel@tonic-gate /*
961991Sheppo  * DR event handler
971991Sheppo  * respond to the picl events:
981991Sheppo  *      PICLEVENT_DR_AP_STATE_CHANGE
991991Sheppo  */
1001991Sheppo static void
dr_handler(const char * ename,const void * earg,size_t size,void * cookie)1011991Sheppo dr_handler(const char *ename, const void *earg, size_t size, void *cookie)
1021991Sheppo {
1031991Sheppo 	nvlist_t	*nvlp = NULL;
1041991Sheppo 	char		*dtype;
1051991Sheppo 	char		*ap_id;
1061991Sheppo 	char		*hint;
1071991Sheppo 
1081991Sheppo 
1091991Sheppo 	if (strcmp(ename, PICLEVENT_DR_AP_STATE_CHANGE) != 0) {
1101991Sheppo 		return;
1111991Sheppo 	}
1121991Sheppo 
1131991Sheppo 	if (nvlist_unpack((char *)earg, size, &nvlp, NULL)) {
1141991Sheppo 		return;
1151991Sheppo 	}
1161991Sheppo 
1171991Sheppo 	if (nvlist_lookup_string(nvlp, PICLEVENTARG_DATA_TYPE, &dtype)) {
1181991Sheppo 		nvlist_free(nvlp);
1191991Sheppo 		return;
1201991Sheppo 	}
1211991Sheppo 
1221991Sheppo 	if (strcmp(dtype, PICLEVENTARG_PICLEVENT_DATA) != 0) {
1231991Sheppo 		nvlist_free(nvlp);
1241991Sheppo 		return;
1251991Sheppo 	}
1261991Sheppo 
1271991Sheppo 	if (nvlist_lookup_string(nvlp, PICLEVENTARG_AP_ID, &ap_id)) {
1281991Sheppo 		nvlist_free(nvlp);
1291991Sheppo 		return;
1301991Sheppo 	}
1311991Sheppo 
1321991Sheppo 	if (nvlist_lookup_string(nvlp, PICLEVENTARG_HINT, &hint)) {
1331991Sheppo 		nvlist_free(nvlp);
1341991Sheppo 		return;
1351991Sheppo 	}
1361991Sheppo 
1371991Sheppo 	mdp = mdesc_devinit();
1381991Sheppo 	if (mdp == NULL) {
1391991Sheppo 		nvlist_free(nvlp);
1401991Sheppo 		return;
1411991Sheppo 	}
1421991Sheppo 
1431991Sheppo 	rootnode = md_root_node(mdp);
1441991Sheppo 
1451991Sheppo 	if (strcmp(hint, DR_HINT_INSERT) == 0)
1461991Sheppo 		(void) update_devices(ap_id, DEV_ADD);
1471991Sheppo 	else if (strcmp(hint, DR_HINT_REMOVE) == 0)
1481991Sheppo 		(void) update_devices(ap_id, DEV_REMOVE);
1491991Sheppo 
1501991Sheppo 	mdesc_devfini(mdp);
1511991Sheppo 	nvlist_free(nvlp);
152*9764SMichael.Bergknoff@Sun.COM 
153*9764SMichael.Bergknoff@Sun.COM 	/*
154*9764SMichael.Bergknoff@Sun.COM 	 * Signal the devtree plugin to add more cpu properties.
155*9764SMichael.Bergknoff@Sun.COM 	 */
156*9764SMichael.Bergknoff@Sun.COM 	signal_devtree();
1571991Sheppo }
1581991Sheppo 
1591991Sheppo /*
1600Sstevel@tonic-gate  * Discovery event handler
1610Sstevel@tonic-gate  * respond to the picl events:
1620Sstevel@tonic-gate  *      PICLEVENT_SYSEVENT_DEVICE_ADDED
1630Sstevel@tonic-gate  *      PICLEVENT_SYSEVENT_DEVICE_REMOVED
1640Sstevel@tonic-gate  */
1650Sstevel@tonic-gate static void
dsc_handler(const char * ename,const void * earg,size_t size,void * cookie)1660Sstevel@tonic-gate dsc_handler(const char *ename, const void *earg, size_t size, void *cookie)
1670Sstevel@tonic-gate {
1680Sstevel@tonic-gate 	nvlist_t	*nvlp = NULL;
1690Sstevel@tonic-gate 	char		*path;
1700Sstevel@tonic-gate 	disk_lookup_t	lookup;
1710Sstevel@tonic-gate 	int		status;
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate 	/*
1740Sstevel@tonic-gate 	 * retrieve the device's physical path from the event arg
1750Sstevel@tonic-gate 	 * and determine which disk (if any) we are working with
1760Sstevel@tonic-gate 	 */
1770Sstevel@tonic-gate 	if (nvlist_unpack((char *)earg, size, &nvlp, NULL))
1780Sstevel@tonic-gate 		return;
1790Sstevel@tonic-gate 	if (nvlist_lookup_string(nvlp, "devfs-path", &path))
1800Sstevel@tonic-gate 		return;
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate 	lookup.path = strdup(path);
1830Sstevel@tonic-gate 	lookup.disk = NULL;
1840Sstevel@tonic-gate 	lookup.result = DISK_NOT_FOUND;
1850Sstevel@tonic-gate 
1860Sstevel@tonic-gate 	status = ptree_walk_tree_by_class(root_node, "disk", (void *)&lookup,
1870Sstevel@tonic-gate 	    find_disk);
1880Sstevel@tonic-gate 	if (status != PICL_SUCCESS) {
1890Sstevel@tonic-gate 		return;
1900Sstevel@tonic-gate 	}
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate 	if (lookup.result == DISK_FOUND) {
1930Sstevel@tonic-gate 		if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_ADDED) == 0)
1940Sstevel@tonic-gate 			ptree_update_propval_by_name(lookup.disk, "State",
1950Sstevel@tonic-gate 			    (void *)strdup(CONFIGURED), PICL_PROPNAMELEN_MAX);
1960Sstevel@tonic-gate 		else if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_REMOVED) == 0)
1970Sstevel@tonic-gate 			ptree_update_propval_by_name(lookup.disk, "State",
1980Sstevel@tonic-gate 			    (void *)strdup(UNCONFIGURED), PICL_PROPNAMELEN_MAX);
1990Sstevel@tonic-gate 	}
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate 	nvlist_free(nvlp);
2020Sstevel@tonic-gate }
2030Sstevel@tonic-gate 
2045028Sfw157321 /*ARGSUSED*/
2055028Sfw157321 static void
mdesc_ev_completion_handler(char * ename,void * earg,size_t size)2065028Sfw157321 mdesc_ev_completion_handler(char *ename, void *earg, size_t size)
2075028Sfw157321 {
2085028Sfw157321 	free(earg);
2095028Sfw157321 }
2105028Sfw157321 
2115028Sfw157321 static void
signal_devtree(void)2125028Sfw157321 signal_devtree(void)
2135028Sfw157321 {
2145028Sfw157321 	nvlist_t *nvl;
2155028Sfw157321 	char *packed_nvl;
2165028Sfw157321 	size_t nvl_size;
2175028Sfw157321 	int status;
2185028Sfw157321 
2195028Sfw157321 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME_TYPE, NULL) != 0)
2205028Sfw157321 		return;
2215028Sfw157321 
2225028Sfw157321 	/*
2235028Sfw157321 	 * Right now (Aug. 2007) snowbird is the only other platform
2245028Sfw157321 	 * which uses this event.  Since that's a sun4u platform and
2255028Sfw157321 	 * this is sun4v we do not have to worry about possible confusion
2265028Sfw157321 	 * or interference between the two by grabbing this event for
2275028Sfw157321 	 * our own use here.  This event is consumed by the devtree
2285028Sfw157321 	 * plug-in.  The event signals the plug-in to re-run its
2295028Sfw157321 	 * cpu initialization function, which will cause it to add
2305028Sfw157321 	 * additional information to the cpu devtree nodes (particularly,
2315028Sfw157321 	 * the administrative state of the cpus.)
2325028Sfw157321 	 */
2335028Sfw157321 	if (nvlist_add_string(nvl, PICLEVENTARG_EVENT_NAME,
2345028Sfw157321 	    PICLEVENT_CPU_STATE_CHANGE) != 0) {
2355028Sfw157321 		free(nvl);
2365028Sfw157321 		return;
2375028Sfw157321 	}
2385028Sfw157321 
2395028Sfw157321 	/*
2405028Sfw157321 	 * The devtree plug-in needs to see a devfs path argument for
2415028Sfw157321 	 * any event it considers.  We supply one here which is essentially
2425028Sfw157321 	 * a dummy since it is not processed by the devtree plug-in for
2435028Sfw157321 	 * this event.
2445028Sfw157321 	 */
2455028Sfw157321 	if (nvlist_add_string(nvl, PICLEVENTARG_DEVFS_PATH, "/cpu") != 0) {
2465028Sfw157321 		free(nvl);
2475028Sfw157321 		return;
2485028Sfw157321 	}
2495095Sfw157321 	packed_nvl = NULL;
2505028Sfw157321 	if (nvlist_pack(nvl, &packed_nvl, &nvl_size, NV_ENCODE_NATIVE,
2515095Sfw157321 	    0) != 0) {
2525028Sfw157321 		free(nvl);
2535028Sfw157321 		return;
2545028Sfw157321 	}
2555028Sfw157321 	if ((status = ptree_post_event(PICLEVENT_CPU_STATE_CHANGE,
2565028Sfw157321 	    packed_nvl, nvl_size, mdesc_ev_completion_handler)) !=
2575028Sfw157321 	    PICL_SUCCESS) {
2585028Sfw157321 		free(nvl);
2595028Sfw157321 		syslog(LOG_WARNING,
2605028Sfw157321 		    "signal_devtree: can't post cpu event: %d\n", status);
2615028Sfw157321 	}
2625028Sfw157321 }
2635028Sfw157321 
2640Sstevel@tonic-gate void
mdescplugin_init(void)2650Sstevel@tonic-gate mdescplugin_init(void)
2660Sstevel@tonic-gate {
2670Sstevel@tonic-gate 	int		status;
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate 	status = ptree_get_root(&root_node);
2700Sstevel@tonic-gate 	if (status != PICL_SUCCESS) {
2710Sstevel@tonic-gate 		return;
2720Sstevel@tonic-gate 	}
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	mdp = mdesc_devinit();
2750Sstevel@tonic-gate 	if (mdp == NULL)
2760Sstevel@tonic-gate 		return;
2770Sstevel@tonic-gate 
2786902Smb158278 	/*
2796902Smb158278 	 * update the cpu configuration in case the snapshot cache used by the
2806902Smb158278 	 * devtree plugin is out of date.
2816902Smb158278 	 */
2826902Smb158278 	(void) update_devices(OBP_CPU, DEV_ADD);
2836902Smb158278 	(void) update_devices(OBP_CPU, DEV_REMOVE);
2846902Smb158278 
2850Sstevel@tonic-gate 	rootnode = md_root_node(mdp);
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate 	/*
2880Sstevel@tonic-gate 	 * This is the start of the CPU property augmentation code.
2890Sstevel@tonic-gate 	 * add_cpu_prop and the rest of the CPU code lives in cpu_prop_update.c
2900Sstevel@tonic-gate 	 */
2910Sstevel@tonic-gate 	status = ptree_walk_tree_by_class(root_node, "cpu", NULL, add_cpu_prop);
2920Sstevel@tonic-gate 	if (status != PICL_SUCCESS) {
2930Sstevel@tonic-gate 		return;
2940Sstevel@tonic-gate 	}
2950Sstevel@tonic-gate 
2965028Sfw157321 	signal_devtree();
2975028Sfw157321 
2980Sstevel@tonic-gate 	(void) disk_discovery();
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate 	/*
3010Sstevel@tonic-gate 	 * register dsc_handler for both "sysevent-device-added" and
3020Sstevel@tonic-gate 	 * and for "sysevent-device-removed" PICL events
3030Sstevel@tonic-gate 	 */
3040Sstevel@tonic-gate 	(void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
3050Sstevel@tonic-gate 	    dsc_handler, NULL);
3060Sstevel@tonic-gate 	(void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
3070Sstevel@tonic-gate 	    dsc_handler, NULL);
3081991Sheppo 	(void) ptree_register_handler(PICLEVENT_DR_AP_STATE_CHANGE,
3091991Sheppo 	    dr_handler, NULL);
3100Sstevel@tonic-gate 
3111991Sheppo 	mdesc_devfini(mdp);
3120Sstevel@tonic-gate }
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate void
mdescplugin_fini(void)3150Sstevel@tonic-gate mdescplugin_fini(void)
3160Sstevel@tonic-gate {
3170Sstevel@tonic-gate 	/* unregister the event handler */
3180Sstevel@tonic-gate 	(void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
3190Sstevel@tonic-gate 	    dsc_handler, NULL);
3200Sstevel@tonic-gate 	(void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
3210Sstevel@tonic-gate 	    dsc_handler, NULL);
3221991Sheppo 	(void) ptree_unregister_handler(PICLEVENT_DR_AP_STATE_CHANGE,
3231991Sheppo 	    dr_handler, NULL);
3240Sstevel@tonic-gate }
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate void
mdescplugin_register(void)3270Sstevel@tonic-gate mdescplugin_register(void)
3280Sstevel@tonic-gate {
3290Sstevel@tonic-gate 	picld_plugin_register(&mdescplugin_reg);
3300Sstevel@tonic-gate }
331