xref: /titanic_50/usr/src/cmd/picl/plugins/sun4v/mdesc/mdescplugin.c (revision c69cf0c1d2b8a9307b7c87611cff37011309d6e2)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51ae08745Sheppo  * Common Development and Distribution License (the "License").
61ae08745Sheppo  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
211ae08745Sheppo 
227c478bd9Sstevel@tonic-gate /*
23*c69cf0c1SMichael Bergknoff  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate  * The MDESC picl plugin serves 2 different functionalities.
297c478bd9Sstevel@tonic-gate  * --The first is to look up certain CPU properties in the MDESC an to add
307c478bd9Sstevel@tonic-gate  * these properties in the already created CPU PICL nodes in the /platform
317c478bd9Sstevel@tonic-gate  * section of the tree.
327c478bd9Sstevel@tonic-gate  * --The second functionality is to create a /disk_discovery section of the
337c478bd9Sstevel@tonic-gate  * PICL tree which will have a disk node created for each disk node in the
347c478bd9Sstevel@tonic-gate  * machine description.
357c478bd9Sstevel@tonic-gate  */
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #include "mdescplugin.h"
385e3e415aSfw157321 #include <libnvpair.h>
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate #pragma init(mdescplugin_register)	/* place in .init section */
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate picl_nodehdl_t	root_node;
437c478bd9Sstevel@tonic-gate md_t		*mdp;
447c478bd9Sstevel@tonic-gate mde_cookie_t	rootnode;
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate void mdescplugin_init(void);
477c478bd9Sstevel@tonic-gate void mdescplugin_fini(void);
48*c69cf0c1SMichael Bergknoff static void signal_devtree(void);
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate extern int add_cpu_prop(picl_nodehdl_t node, void *args);
517c478bd9Sstevel@tonic-gate extern int disk_discovery(void);
527c478bd9Sstevel@tonic-gate extern md_t *mdesc_devinit(void);
531ae08745Sheppo extern void mdesc_devfini(md_t *mdp);
541ae08745Sheppo extern int update_devices(char *dev, int op);
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate picld_plugin_reg_t mdescplugin_reg = {
577c478bd9Sstevel@tonic-gate 	PICLD_PLUGIN_VERSION_1,
587c478bd9Sstevel@tonic-gate 	PICLD_PLUGIN_CRITICAL,
597c478bd9Sstevel@tonic-gate 	"mdesc_plugin",
607c478bd9Sstevel@tonic-gate 	mdescplugin_init,
617c478bd9Sstevel@tonic-gate 	mdescplugin_fini
627c478bd9Sstevel@tonic-gate };
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate #define	DISK_FOUND 0x00
657c478bd9Sstevel@tonic-gate #define	DISK_NOT_FOUND 0x01
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate typedef struct disk_lookup {
687c478bd9Sstevel@tonic-gate 	char *path;
697c478bd9Sstevel@tonic-gate 	picl_nodehdl_t disk;
707c478bd9Sstevel@tonic-gate 	int result;
717c478bd9Sstevel@tonic-gate } disk_lookup_t;
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate int
find_disk(picl_nodehdl_t node,void * args)747c478bd9Sstevel@tonic-gate find_disk(picl_nodehdl_t node, void *args)
757c478bd9Sstevel@tonic-gate {
767c478bd9Sstevel@tonic-gate 	disk_lookup_t *lookup  = (disk_lookup_t *)args;
777c478bd9Sstevel@tonic-gate 	int status;
787c478bd9Sstevel@tonic-gate 	char path[PICL_PROPNAMELEN_MAX];
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate 	status = ptree_get_propval_by_name(node, "Path", (void *)&path,
817c478bd9Sstevel@tonic-gate 	    PICL_PROPNAMELEN_MAX);
827c478bd9Sstevel@tonic-gate 	if (status != PICL_SUCCESS) {
837c478bd9Sstevel@tonic-gate 		return (PICL_WALK_CONTINUE);
847c478bd9Sstevel@tonic-gate 	}
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate 	if (strcmp(path, lookup->path) == 0) {
877c478bd9Sstevel@tonic-gate 		lookup->disk = node;
887c478bd9Sstevel@tonic-gate 		lookup->result = DISK_FOUND;
897c478bd9Sstevel@tonic-gate 		return (PICL_WALK_TERMINATE);
907c478bd9Sstevel@tonic-gate 	}
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate 	return (PICL_WALK_CONTINUE);
937c478bd9Sstevel@tonic-gate }
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate /*
961ae08745Sheppo  * DR event handler
971ae08745Sheppo  * respond to the picl events:
981ae08745Sheppo  *      PICLEVENT_DR_AP_STATE_CHANGE
991ae08745Sheppo  */
1001ae08745Sheppo static void
dr_handler(const char * ename,const void * earg,size_t size,void * cookie)1011ae08745Sheppo dr_handler(const char *ename, const void *earg, size_t size, void *cookie)
1021ae08745Sheppo {
1031ae08745Sheppo 	nvlist_t	*nvlp = NULL;
1041ae08745Sheppo 	char		*dtype;
1051ae08745Sheppo 	char		*ap_id;
1061ae08745Sheppo 	char		*hint;
1071ae08745Sheppo 
1081ae08745Sheppo 
1091ae08745Sheppo 	if (strcmp(ename, PICLEVENT_DR_AP_STATE_CHANGE) != 0) {
1101ae08745Sheppo 		return;
1111ae08745Sheppo 	}
1121ae08745Sheppo 
1131ae08745Sheppo 	if (nvlist_unpack((char *)earg, size, &nvlp, NULL)) {
1141ae08745Sheppo 		return;
1151ae08745Sheppo 	}
1161ae08745Sheppo 
1171ae08745Sheppo 	if (nvlist_lookup_string(nvlp, PICLEVENTARG_DATA_TYPE, &dtype)) {
1181ae08745Sheppo 		nvlist_free(nvlp);
1191ae08745Sheppo 		return;
1201ae08745Sheppo 	}
1211ae08745Sheppo 
1221ae08745Sheppo 	if (strcmp(dtype, PICLEVENTARG_PICLEVENT_DATA) != 0) {
1231ae08745Sheppo 		nvlist_free(nvlp);
1241ae08745Sheppo 		return;
1251ae08745Sheppo 	}
1261ae08745Sheppo 
1271ae08745Sheppo 	if (nvlist_lookup_string(nvlp, PICLEVENTARG_AP_ID, &ap_id)) {
1281ae08745Sheppo 		nvlist_free(nvlp);
1291ae08745Sheppo 		return;
1301ae08745Sheppo 	}
1311ae08745Sheppo 
1321ae08745Sheppo 	if (nvlist_lookup_string(nvlp, PICLEVENTARG_HINT, &hint)) {
1331ae08745Sheppo 		nvlist_free(nvlp);
1341ae08745Sheppo 		return;
1351ae08745Sheppo 	}
1361ae08745Sheppo 
1371ae08745Sheppo 	mdp = mdesc_devinit();
1381ae08745Sheppo 	if (mdp == NULL) {
1391ae08745Sheppo 		nvlist_free(nvlp);
1401ae08745Sheppo 		return;
1411ae08745Sheppo 	}
1421ae08745Sheppo 
1431ae08745Sheppo 	rootnode = md_root_node(mdp);
1441ae08745Sheppo 
1451ae08745Sheppo 	if (strcmp(hint, DR_HINT_INSERT) == 0)
1461ae08745Sheppo 		(void) update_devices(ap_id, DEV_ADD);
1471ae08745Sheppo 	else if (strcmp(hint, DR_HINT_REMOVE) == 0)
1481ae08745Sheppo 		(void) update_devices(ap_id, DEV_REMOVE);
1491ae08745Sheppo 
1501ae08745Sheppo 	mdesc_devfini(mdp);
1511ae08745Sheppo 	nvlist_free(nvlp);
152*c69cf0c1SMichael Bergknoff 
153*c69cf0c1SMichael Bergknoff 	/*
154*c69cf0c1SMichael Bergknoff 	 * Signal the devtree plugin to add more cpu properties.
155*c69cf0c1SMichael Bergknoff 	 */
156*c69cf0c1SMichael Bergknoff 	signal_devtree();
1571ae08745Sheppo }
1581ae08745Sheppo 
1591ae08745Sheppo /*
1607c478bd9Sstevel@tonic-gate  * Discovery event handler
1617c478bd9Sstevel@tonic-gate  * respond to the picl events:
1627c478bd9Sstevel@tonic-gate  *      PICLEVENT_SYSEVENT_DEVICE_ADDED
1637c478bd9Sstevel@tonic-gate  *      PICLEVENT_SYSEVENT_DEVICE_REMOVED
1647c478bd9Sstevel@tonic-gate  */
1657c478bd9Sstevel@tonic-gate static void
dsc_handler(const char * ename,const void * earg,size_t size,void * cookie)1667c478bd9Sstevel@tonic-gate dsc_handler(const char *ename, const void *earg, size_t size, void *cookie)
1677c478bd9Sstevel@tonic-gate {
1687c478bd9Sstevel@tonic-gate 	nvlist_t	*nvlp = NULL;
1697c478bd9Sstevel@tonic-gate 	char		*path;
1707c478bd9Sstevel@tonic-gate 	disk_lookup_t	lookup;
1717c478bd9Sstevel@tonic-gate 	int		status;
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate 	/*
1747c478bd9Sstevel@tonic-gate 	 * retrieve the device's physical path from the event arg
1757c478bd9Sstevel@tonic-gate 	 * and determine which disk (if any) we are working with
1767c478bd9Sstevel@tonic-gate 	 */
1777c478bd9Sstevel@tonic-gate 	if (nvlist_unpack((char *)earg, size, &nvlp, NULL))
1787c478bd9Sstevel@tonic-gate 		return;
1797c478bd9Sstevel@tonic-gate 	if (nvlist_lookup_string(nvlp, "devfs-path", &path))
1807c478bd9Sstevel@tonic-gate 		return;
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate 	lookup.path = strdup(path);
1837c478bd9Sstevel@tonic-gate 	lookup.disk = NULL;
1847c478bd9Sstevel@tonic-gate 	lookup.result = DISK_NOT_FOUND;
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate 	status = ptree_walk_tree_by_class(root_node, "disk", (void *)&lookup,
1877c478bd9Sstevel@tonic-gate 	    find_disk);
1887c478bd9Sstevel@tonic-gate 	if (status != PICL_SUCCESS) {
1897c478bd9Sstevel@tonic-gate 		return;
1907c478bd9Sstevel@tonic-gate 	}
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 	if (lookup.result == DISK_FOUND) {
1937c478bd9Sstevel@tonic-gate 		if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_ADDED) == 0)
1947c478bd9Sstevel@tonic-gate 			ptree_update_propval_by_name(lookup.disk, "State",
1957c478bd9Sstevel@tonic-gate 			    (void *)strdup(CONFIGURED), PICL_PROPNAMELEN_MAX);
1967c478bd9Sstevel@tonic-gate 		else if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_REMOVED) == 0)
1977c478bd9Sstevel@tonic-gate 			ptree_update_propval_by_name(lookup.disk, "State",
1987c478bd9Sstevel@tonic-gate 			    (void *)strdup(UNCONFIGURED), PICL_PROPNAMELEN_MAX);
1997c478bd9Sstevel@tonic-gate 	}
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 	nvlist_free(nvlp);
2027c478bd9Sstevel@tonic-gate }
2037c478bd9Sstevel@tonic-gate 
2045e3e415aSfw157321 /*ARGSUSED*/
2055e3e415aSfw157321 static void
mdesc_ev_completion_handler(char * ename,void * earg,size_t size)2065e3e415aSfw157321 mdesc_ev_completion_handler(char *ename, void *earg, size_t size)
2075e3e415aSfw157321 {
2085e3e415aSfw157321 	free(earg);
2095e3e415aSfw157321 }
2105e3e415aSfw157321 
2115e3e415aSfw157321 static void
signal_devtree(void)2125e3e415aSfw157321 signal_devtree(void)
2135e3e415aSfw157321 {
2145e3e415aSfw157321 	nvlist_t *nvl;
2155e3e415aSfw157321 	char *packed_nvl;
2165e3e415aSfw157321 	size_t nvl_size;
2175e3e415aSfw157321 	int status;
2185e3e415aSfw157321 
2195e3e415aSfw157321 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME_TYPE, NULL) != 0)
2205e3e415aSfw157321 		return;
2215e3e415aSfw157321 
2225e3e415aSfw157321 	/*
2235e3e415aSfw157321 	 * Right now (Aug. 2007) snowbird is the only other platform
2245e3e415aSfw157321 	 * which uses this event.  Since that's a sun4u platform and
2255e3e415aSfw157321 	 * this is sun4v we do not have to worry about possible confusion
2265e3e415aSfw157321 	 * or interference between the two by grabbing this event for
2275e3e415aSfw157321 	 * our own use here.  This event is consumed by the devtree
2285e3e415aSfw157321 	 * plug-in.  The event signals the plug-in to re-run its
2295e3e415aSfw157321 	 * cpu initialization function, which will cause it to add
2305e3e415aSfw157321 	 * additional information to the cpu devtree nodes (particularly,
2315e3e415aSfw157321 	 * the administrative state of the cpus.)
2325e3e415aSfw157321 	 */
2335e3e415aSfw157321 	if (nvlist_add_string(nvl, PICLEVENTARG_EVENT_NAME,
2345e3e415aSfw157321 	    PICLEVENT_CPU_STATE_CHANGE) != 0) {
2355e3e415aSfw157321 		free(nvl);
2365e3e415aSfw157321 		return;
2375e3e415aSfw157321 	}
2385e3e415aSfw157321 
2395e3e415aSfw157321 	/*
2405e3e415aSfw157321 	 * The devtree plug-in needs to see a devfs path argument for
2415e3e415aSfw157321 	 * any event it considers.  We supply one here which is essentially
2425e3e415aSfw157321 	 * a dummy since it is not processed by the devtree plug-in for
2435e3e415aSfw157321 	 * this event.
2445e3e415aSfw157321 	 */
2455e3e415aSfw157321 	if (nvlist_add_string(nvl, PICLEVENTARG_DEVFS_PATH, "/cpu") != 0) {
2465e3e415aSfw157321 		free(nvl);
2475e3e415aSfw157321 		return;
2485e3e415aSfw157321 	}
249f2a592f8Sfw157321 	packed_nvl = NULL;
2505e3e415aSfw157321 	if (nvlist_pack(nvl, &packed_nvl, &nvl_size, NV_ENCODE_NATIVE,
251f2a592f8Sfw157321 	    0) != 0) {
2525e3e415aSfw157321 		free(nvl);
2535e3e415aSfw157321 		return;
2545e3e415aSfw157321 	}
2555e3e415aSfw157321 	if ((status = ptree_post_event(PICLEVENT_CPU_STATE_CHANGE,
2565e3e415aSfw157321 	    packed_nvl, nvl_size, mdesc_ev_completion_handler)) !=
2575e3e415aSfw157321 	    PICL_SUCCESS) {
2585e3e415aSfw157321 		free(nvl);
2595e3e415aSfw157321 		syslog(LOG_WARNING,
2605e3e415aSfw157321 		    "signal_devtree: can't post cpu event: %d\n", status);
2615e3e415aSfw157321 	}
2625e3e415aSfw157321 }
2635e3e415aSfw157321 
2647c478bd9Sstevel@tonic-gate void
mdescplugin_init(void)2657c478bd9Sstevel@tonic-gate mdescplugin_init(void)
2667c478bd9Sstevel@tonic-gate {
2677c478bd9Sstevel@tonic-gate 	int		status;
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 	status = ptree_get_root(&root_node);
2707c478bd9Sstevel@tonic-gate 	if (status != PICL_SUCCESS) {
2717c478bd9Sstevel@tonic-gate 		return;
2727c478bd9Sstevel@tonic-gate 	}
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	mdp = mdesc_devinit();
2757c478bd9Sstevel@tonic-gate 	if (mdp == NULL)
2767c478bd9Sstevel@tonic-gate 		return;
2777c478bd9Sstevel@tonic-gate 
278535c87f8Smb158278 	/*
279535c87f8Smb158278 	 * update the cpu configuration in case the snapshot cache used by the
280535c87f8Smb158278 	 * devtree plugin is out of date.
281535c87f8Smb158278 	 */
282535c87f8Smb158278 	(void) update_devices(OBP_CPU, DEV_ADD);
283535c87f8Smb158278 	(void) update_devices(OBP_CPU, DEV_REMOVE);
284535c87f8Smb158278 
2857c478bd9Sstevel@tonic-gate 	rootnode = md_root_node(mdp);
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate 	/*
2887c478bd9Sstevel@tonic-gate 	 * This is the start of the CPU property augmentation code.
2897c478bd9Sstevel@tonic-gate 	 * add_cpu_prop and the rest of the CPU code lives in cpu_prop_update.c
2907c478bd9Sstevel@tonic-gate 	 */
2917c478bd9Sstevel@tonic-gate 	status = ptree_walk_tree_by_class(root_node, "cpu", NULL, add_cpu_prop);
2927c478bd9Sstevel@tonic-gate 	if (status != PICL_SUCCESS) {
2937c478bd9Sstevel@tonic-gate 		return;
2947c478bd9Sstevel@tonic-gate 	}
2957c478bd9Sstevel@tonic-gate 
2965e3e415aSfw157321 	signal_devtree();
2975e3e415aSfw157321 
2987c478bd9Sstevel@tonic-gate 	(void) disk_discovery();
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 	/*
3017c478bd9Sstevel@tonic-gate 	 * register dsc_handler for both "sysevent-device-added" and
3027c478bd9Sstevel@tonic-gate 	 * and for "sysevent-device-removed" PICL events
3037c478bd9Sstevel@tonic-gate 	 */
3047c478bd9Sstevel@tonic-gate 	(void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
3057c478bd9Sstevel@tonic-gate 	    dsc_handler, NULL);
3067c478bd9Sstevel@tonic-gate 	(void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
3077c478bd9Sstevel@tonic-gate 	    dsc_handler, NULL);
3081ae08745Sheppo 	(void) ptree_register_handler(PICLEVENT_DR_AP_STATE_CHANGE,
3091ae08745Sheppo 	    dr_handler, NULL);
3107c478bd9Sstevel@tonic-gate 
3111ae08745Sheppo 	mdesc_devfini(mdp);
3127c478bd9Sstevel@tonic-gate }
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate void
mdescplugin_fini(void)3157c478bd9Sstevel@tonic-gate mdescplugin_fini(void)
3167c478bd9Sstevel@tonic-gate {
3177c478bd9Sstevel@tonic-gate 	/* unregister the event handler */
3187c478bd9Sstevel@tonic-gate 	(void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
3197c478bd9Sstevel@tonic-gate 	    dsc_handler, NULL);
3207c478bd9Sstevel@tonic-gate 	(void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
3217c478bd9Sstevel@tonic-gate 	    dsc_handler, NULL);
3221ae08745Sheppo 	(void) ptree_unregister_handler(PICLEVENT_DR_AP_STATE_CHANGE,
3231ae08745Sheppo 	    dr_handler, NULL);
3247c478bd9Sstevel@tonic-gate }
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate void
mdescplugin_register(void)3277c478bd9Sstevel@tonic-gate mdescplugin_register(void)
3287c478bd9Sstevel@tonic-gate {
3297c478bd9Sstevel@tonic-gate 	picld_plugin_register(&mdescplugin_reg);
3307c478bd9Sstevel@tonic-gate }
331