xref: /onnv-gate/usr/src/cmd/picl/plugins/common/memcfg/piclmemcfg_comm.c (revision 11205:974775d2ff35)
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
5*11205SMichael.Bergknoff@Sun.COM  * Common Development and Distribution License (the "License").
6*11205SMichael.Bergknoff@Sun.COM  * 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  */
210Sstevel@tonic-gate /*
22*11205SMichael.Bergknoff@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate  * This plugin creates memory configuration nodes and properties in the
280Sstevel@tonic-gate  * PICL tree for Cheetah platforms.
290Sstevel@tonic-gate  *
300Sstevel@tonic-gate  * Subtree of memory-controller in the physical aspect.
310Sstevel@tonic-gate  * memory-controller --- memory-module-group --- memory-module
320Sstevel@tonic-gate  *
330Sstevel@tonic-gate  * Subtree of memory in the logical aspect.
340Sstevel@tonic-gate  * memory --- memory-segment --- memory-bank
350Sstevel@tonic-gate  * Add property _memory-module-group_ at memory-segment referring to the
360Sstevel@tonic-gate  * memory-module-group if InterleaveFactor is one, or at memory-bank
370Sstevel@tonic-gate  * if InterleaveFactor is greater than one.
380Sstevel@tonic-gate  *
390Sstevel@tonic-gate  * Undo strategy:
400Sstevel@tonic-gate  * Create all nodes and properties, or none if it fails in physical and
410Sstevel@tonic-gate  * logical memory tree respectively. It keeps on creating logic
420Sstevel@tonic-gate  * memory tree although it falis on physical logic tree, but no link to
430Sstevel@tonic-gate  * memory module group.
440Sstevel@tonic-gate  *
450Sstevel@tonic-gate  * NOTE:
460Sstevel@tonic-gate  * It depends on PICL devtree plugin and currently
470Sstevel@tonic-gate  * there is no refresh routine for DR.
480Sstevel@tonic-gate  */
490Sstevel@tonic-gate #include <stdio.h>
500Sstevel@tonic-gate #include <stdlib.h>
510Sstevel@tonic-gate #include <string.h>
520Sstevel@tonic-gate #include <unistd.h>
530Sstevel@tonic-gate #include <alloca.h>
540Sstevel@tonic-gate #include <syslog.h>
550Sstevel@tonic-gate #include <string.h>
560Sstevel@tonic-gate #include <libintl.h>
570Sstevel@tonic-gate #include <picl.h>
580Sstevel@tonic-gate #include <picltree.h>
590Sstevel@tonic-gate #include <fcntl.h>
600Sstevel@tonic-gate #include <errno.h>
610Sstevel@tonic-gate #include <sys/types.h>
620Sstevel@tonic-gate #include <dirent.h>
630Sstevel@tonic-gate #include <sys/stat.h>
640Sstevel@tonic-gate #include <mc.h>
650Sstevel@tonic-gate #include <libnvpair.h>
660Sstevel@tonic-gate #include <limits.h>
670Sstevel@tonic-gate #include "piclmemcfg.h"
680Sstevel@tonic-gate 
690Sstevel@tonic-gate /*
700Sstevel@tonic-gate  * Plugin registration entry points
710Sstevel@tonic-gate  */
720Sstevel@tonic-gate static	void	piclmemcfg_register(void);
730Sstevel@tonic-gate static	void	piclmemcfg_init(void);
740Sstevel@tonic-gate static	void	piclmemcfg_fini(void);
750Sstevel@tonic-gate 
760Sstevel@tonic-gate /*
770Sstevel@tonic-gate  * PICL event handler
780Sstevel@tonic-gate  */
790Sstevel@tonic-gate static void  piclmemcfg_evhandler(const char *ename, const void *earg,
800Sstevel@tonic-gate 		size_t size, void *cookie);
810Sstevel@tonic-gate 
820Sstevel@tonic-gate #pragma	init(piclmemcfg_register)
830Sstevel@tonic-gate 
840Sstevel@tonic-gate static picld_plugin_reg_t  my_reg_info = {
850Sstevel@tonic-gate 	PICLD_PLUGIN_VERSION_1,
860Sstevel@tonic-gate 	PICLD_PLUGIN_NON_CRITICAL,
870Sstevel@tonic-gate 	"SUNW_piclmemcfg",
880Sstevel@tonic-gate 	piclmemcfg_init,
890Sstevel@tonic-gate 	piclmemcfg_fini
900Sstevel@tonic-gate };
910Sstevel@tonic-gate 
920Sstevel@tonic-gate /*
930Sstevel@tonic-gate  * Log message texts
940Sstevel@tonic-gate  */
950Sstevel@tonic-gate #define	EM_INIT_FAILED		gettext("SUNW_piclmemcfg init failed!\n")
960Sstevel@tonic-gate #define	EM_PHYSIC_MEM_TREE_FAILED	\
970Sstevel@tonic-gate 	gettext("SUNW_piclmemcfg physical memory tree failed!\n")
980Sstevel@tonic-gate #define	EM_LOGIC_MEM_TREE_FAILED		\
990Sstevel@tonic-gate 	gettext("SUNW_piclmemcfg logical memory tree failed!\n")
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate #define	EM_INIT_MC_FAILED	\
1020Sstevel@tonic-gate 	gettext("SUNW_piclmemcfg init mc failed!\n")
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate /*
1050Sstevel@tonic-gate  * Global variables for Memory Controllers
1060Sstevel@tonic-gate  */
1070Sstevel@tonic-gate #define	MC_DIR	"/dev/mc/"
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate static int	nsegments;	/* The number of memory segments */
1100Sstevel@tonic-gate static int	nbanks;		/* The max. number of banks per segment */
1110Sstevel@tonic-gate static int	ndevgrps;	/* The max. number of device groups per mc */
1120Sstevel@tonic-gate static int	ndevs;		/* The max. number of devices per dev group */
1130Sstevel@tonic-gate static int	transfersize;
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate static picl_nodehdl_t	*msegh_info;
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate /*
1180Sstevel@tonic-gate  * Memory-module-group node handle list, a singal linking list, where
1190Sstevel@tonic-gate  * memory module group id is the key to match.
1200Sstevel@tonic-gate  *
1210Sstevel@tonic-gate  * It is allocated and added to the head of list, and freed as well.
1220Sstevel@tonic-gate  * The mmgh field is cleared if failure is encountered in the physical
1230Sstevel@tonic-gate  * memory tree.
1240Sstevel@tonic-gate  *
1250Sstevel@tonic-gate  * This list is accessed in the logical memory tree, and allocated memory
1260Sstevel@tonic-gate  * is released at the end of plugin.
1270Sstevel@tonic-gate  */
1280Sstevel@tonic-gate typedef struct memmodgrp_info {
1290Sstevel@tonic-gate 	int			mmgid;
1300Sstevel@tonic-gate 	struct memmodgrp_info	*next;
1310Sstevel@tonic-gate 	picl_nodehdl_t		mmgh;
1320Sstevel@tonic-gate 	picl_nodehdl_t		mch;
1330Sstevel@tonic-gate } mmodgrp_info_t;
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate static	mmodgrp_info_t		*head2mmodgrp;
1360Sstevel@tonic-gate 
1370Sstevel@tonic-gate /*
1380Sstevel@tonic-gate  * Release the allocated memory of mmodgrp_info
1390Sstevel@tonic-gate  */
1400Sstevel@tonic-gate static void
free_allocated_mem(void)1410Sstevel@tonic-gate free_allocated_mem(void)
1420Sstevel@tonic-gate {
1430Sstevel@tonic-gate 	mmodgrp_info_t		*mmghdl, *currmmghdl;
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate 	mmghdl = head2mmodgrp;
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate 	while (mmghdl) {
1480Sstevel@tonic-gate 		currmmghdl = mmghdl;
1490Sstevel@tonic-gate 		mmghdl = mmghdl->next;
1500Sstevel@tonic-gate 		free(currmmghdl);
1510Sstevel@tonic-gate 	}
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 	head2mmodgrp = NULL;
1540Sstevel@tonic-gate }
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate /*
1570Sstevel@tonic-gate  * Delete nodes whose MC is gone at mmodgrp_info
1580Sstevel@tonic-gate  */
1590Sstevel@tonic-gate static void
del_plugout_mmodgrp(picl_nodehdl_t mch)1600Sstevel@tonic-gate del_plugout_mmodgrp(picl_nodehdl_t mch)
1610Sstevel@tonic-gate {
1620Sstevel@tonic-gate 	mmodgrp_info_t		*mmghdl, *prevmmghdl, *nextmmghdl;
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate 	for (mmghdl = head2mmodgrp, prevmmghdl = NULL; mmghdl != NULL;
1650Sstevel@tonic-gate 	    mmghdl = nextmmghdl) {
1660Sstevel@tonic-gate 		nextmmghdl = mmghdl->next;
1670Sstevel@tonic-gate 		if (mmghdl->mch == mch) {
1680Sstevel@tonic-gate 			if (prevmmghdl == NULL)
1690Sstevel@tonic-gate 				/* we are at the head */
1700Sstevel@tonic-gate 				head2mmodgrp = nextmmghdl;
1710Sstevel@tonic-gate 			else
1720Sstevel@tonic-gate 				prevmmghdl->next = nextmmghdl;
1730Sstevel@tonic-gate 			free(mmghdl);
1740Sstevel@tonic-gate 		} else
1750Sstevel@tonic-gate 			prevmmghdl = mmghdl;
1760Sstevel@tonic-gate 	}
1770Sstevel@tonic-gate }
1780Sstevel@tonic-gate 
1790Sstevel@tonic-gate /*
1800Sstevel@tonic-gate  * Search the memory module group node in the mmodgrp_info by global id.
1810Sstevel@tonic-gate  * The matched memory-module-group node handle will be assigned to
1820Sstevel@tonic-gate  * the second parameter.
1830Sstevel@tonic-gate  */
1840Sstevel@tonic-gate static int
find_mem_mod_grp_hdl(int id,picl_nodehdl_t * mmodgrph)1850Sstevel@tonic-gate find_mem_mod_grp_hdl(int id, picl_nodehdl_t *mmodgrph)
1860Sstevel@tonic-gate {
1870Sstevel@tonic-gate 	mmodgrp_info_t		*mmghdl;
1880Sstevel@tonic-gate 	int			err = PICL_FAILURE;
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 	mmghdl = head2mmodgrp;
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate 	while (mmghdl) {
1930Sstevel@tonic-gate 		if ((mmghdl->mmgh) && (mmghdl->mmgid == id)) {
1940Sstevel@tonic-gate 			*mmodgrph = mmghdl->mmgh;
1950Sstevel@tonic-gate 			err = PICL_SUCCESS;
1960Sstevel@tonic-gate 			break;
1970Sstevel@tonic-gate 		}
1980Sstevel@tonic-gate 		mmghdl = mmghdl->next;
1990Sstevel@tonic-gate 	}
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate 	return (err);
2020Sstevel@tonic-gate }
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate /*
2050Sstevel@tonic-gate  * Delete nodes and properties created in the physical memory tree.
2060Sstevel@tonic-gate  */
2070Sstevel@tonic-gate static void
undo_phymem_tree(void)2080Sstevel@tonic-gate undo_phymem_tree(void)
2090Sstevel@tonic-gate {
2100Sstevel@tonic-gate 	mmodgrp_info_t		*mmghdl;
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate 	mmghdl = head2mmodgrp;
2130Sstevel@tonic-gate 
2140Sstevel@tonic-gate 	while (mmghdl) {
2150Sstevel@tonic-gate 		/*
2160Sstevel@tonic-gate 		 * Delete nodes and properties of memory-module-group(s)
2170Sstevel@tonic-gate 		 */
2180Sstevel@tonic-gate 		if (mmghdl->mmgh == NULL)
2190Sstevel@tonic-gate 			continue;
2200Sstevel@tonic-gate 
2210Sstevel@tonic-gate 		(void) ptree_delete_node(mmghdl->mmgh);
2220Sstevel@tonic-gate 		(void) ptree_destroy_node(mmghdl->mmgh);
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate 		/*
2250Sstevel@tonic-gate 		 * Clear out the saved node handle of memory module group
2260Sstevel@tonic-gate 		 * so that logic memory tree won't link to it.
2270Sstevel@tonic-gate 		 */
2280Sstevel@tonic-gate 		mmghdl->mch = mmghdl->mmgh = NULL;
2290Sstevel@tonic-gate 		mmghdl = mmghdl->next;
2300Sstevel@tonic-gate 	}
2310Sstevel@tonic-gate }
2320Sstevel@tonic-gate 
2330Sstevel@tonic-gate /*
2340Sstevel@tonic-gate  * Create all memory-banks under the given memory-segment.
2350Sstevel@tonic-gate  */
2360Sstevel@tonic-gate static int
add_mem_banks(picl_nodehdl_t msegh,int fd,struct mc_segment * mcseg)2370Sstevel@tonic-gate add_mem_banks(picl_nodehdl_t msegh, int fd, struct mc_segment *mcseg)
2380Sstevel@tonic-gate {
2390Sstevel@tonic-gate 	int			i;
2400Sstevel@tonic-gate 	int			err = PICL_SUCCESS;
2410Sstevel@tonic-gate 	static picl_nodehdl_t	mmodgrph;
2420Sstevel@tonic-gate 	picl_prophdl_t		bankh;
2430Sstevel@tonic-gate 	ptree_propinfo_t	propinfo;
2440Sstevel@tonic-gate 	struct mc_bank		mcbank;
2450Sstevel@tonic-gate 	char			propname[PICL_CLASSNAMELEN_MAX];
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate 	/*
2480Sstevel@tonic-gate 	 * Get all bank information via ioctl
2490Sstevel@tonic-gate 	 */
2500Sstevel@tonic-gate 	for (i = 0; i < mcseg->nbanks; i++) {
2510Sstevel@tonic-gate 		mcbank.id = mcseg->bankids[i].globalid;
2520Sstevel@tonic-gate 		if (ioctl(fd, MCIOC_BANK, &mcbank) == -1)
2530Sstevel@tonic-gate 			return (PICL_FAILURE);
2540Sstevel@tonic-gate 
2550Sstevel@tonic-gate 		/*
2560Sstevel@tonic-gate 		 * Create memory-bank node under memory-segment node
2570Sstevel@tonic-gate 		 */
2580Sstevel@tonic-gate 		err = ptree_create_and_add_node(msegh, PICL_NAME_MEMORY_BANK,
2590Sstevel@tonic-gate 		    PICL_CLASS_MEMORY_BANK, &bankh);
2600Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
2610Sstevel@tonic-gate 			break;
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 		/*
2640Sstevel@tonic-gate 		 * Add property, Size to memory-bank node
2650Sstevel@tonic-gate 		 */
2660Sstevel@tonic-gate 		err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
2670Sstevel@tonic-gate 		    PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (mcbank.size),
2680Sstevel@tonic-gate 		    PICL_PROP_SIZE, NULL, NULL);
2690Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
2700Sstevel@tonic-gate 			break;
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate 		err = ptree_create_and_add_prop(bankh, &propinfo, &mcbank.size,
2730Sstevel@tonic-gate 		    NULL);
2740Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
2750Sstevel@tonic-gate 			break;
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate 		/*
2780Sstevel@tonic-gate 		 * Add property, AddressMask to memory-bank node
2790Sstevel@tonic-gate 		 */
2800Sstevel@tonic-gate 		err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
2810Sstevel@tonic-gate 		    PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (mcbank.mask),
2820Sstevel@tonic-gate 		    PICL_PROP_ADDRESSMASK, NULL, NULL);
2830Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
2840Sstevel@tonic-gate 			break;
2850Sstevel@tonic-gate 
2860Sstevel@tonic-gate 		err = ptree_create_and_add_prop(bankh, &propinfo, &mcbank.mask,
2870Sstevel@tonic-gate 		    NULL);
2880Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
2890Sstevel@tonic-gate 			break;
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate 		/*
2920Sstevel@tonic-gate 		 * Add property, AddressMatch to memory-bank node
2930Sstevel@tonic-gate 		 */
2940Sstevel@tonic-gate 		err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
2950Sstevel@tonic-gate 		    PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (mcbank.match),
2960Sstevel@tonic-gate 		    PICL_PROP_ADDRESSMATCH, NULL, NULL);
2970Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
2980Sstevel@tonic-gate 			break;
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate 		err = ptree_create_and_add_prop(bankh, &propinfo,
3010Sstevel@tonic-gate 		    &mcbank.match, NULL);
3020Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
3030Sstevel@tonic-gate 			break;
3040Sstevel@tonic-gate 
3050Sstevel@tonic-gate 		/*
3060Sstevel@tonic-gate 		 * Add global id of bank to property, ID memory-bank node
3070Sstevel@tonic-gate 		 */
3080Sstevel@tonic-gate 		err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
3090Sstevel@tonic-gate 		    PICL_PTYPE_INT, PICL_READ, sizeof (mcbank.id), PICL_PROP_ID,
3100Sstevel@tonic-gate 		    NULL, NULL);
3110Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
3120Sstevel@tonic-gate 			break;
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate 		err = ptree_create_and_add_prop(bankh, &propinfo, &mcbank.id,
3150Sstevel@tonic-gate 		    NULL);
3160Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
3170Sstevel@tonic-gate 			break;
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate 		/*
3200Sstevel@tonic-gate 		 * Add property, _memory-module-group_ to memory-bank node
3210Sstevel@tonic-gate 		 */
3220Sstevel@tonic-gate 		if ((find_mem_mod_grp_hdl(mcbank.devgrpid.globalid,
3230Sstevel@tonic-gate 		    &mmodgrph)) != PICL_SUCCESS)
3240Sstevel@tonic-gate 			continue;
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 		/*
3270Sstevel@tonic-gate 		 * The number of memory modules > 1 means there needs
3280Sstevel@tonic-gate 		 * memory module group, and then refers to it. Otherwise,
3290Sstevel@tonic-gate 		 * it refers to memory module node handle instead.
3300Sstevel@tonic-gate 		 */
3310Sstevel@tonic-gate 		(void) strlcpy(propname, (ndevs > 1 ?
3320Sstevel@tonic-gate 		    PICL_REFPROP_MEMORY_MODULE_GROUP :
3330Sstevel@tonic-gate 		    PICL_REFPROP_MEMORY_MODULE), PICL_CLASSNAMELEN_MAX);
3340Sstevel@tonic-gate 
3350Sstevel@tonic-gate 		err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
3360Sstevel@tonic-gate 		    PICL_PTYPE_REFERENCE, PICL_READ, sizeof (picl_nodehdl_t),
3370Sstevel@tonic-gate 		    propname, NULL, NULL);
3380Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
3390Sstevel@tonic-gate 			break;
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 		err = ptree_create_and_add_prop(bankh, &propinfo, &mmodgrph,
3420Sstevel@tonic-gate 		    NULL);
3430Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
3440Sstevel@tonic-gate 			break;
3450Sstevel@tonic-gate 	}
3460Sstevel@tonic-gate 	return (PICL_SUCCESS);
3470Sstevel@tonic-gate }
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate static void
undo_logical_tree(int nsegments)3500Sstevel@tonic-gate undo_logical_tree(int nsegments)
3510Sstevel@tonic-gate {
3520Sstevel@tonic-gate 	int	i;
3530Sstevel@tonic-gate 	/*
3540Sstevel@tonic-gate 	 * Undo in the logical memory tree
3550Sstevel@tonic-gate 	 */
3560Sstevel@tonic-gate 	for (i = 0; i < nsegments; i++) {
3570Sstevel@tonic-gate 		(void) ptree_delete_node(msegh_info[i]);
3580Sstevel@tonic-gate 		(void) ptree_destroy_node(msegh_info[i]);
3590Sstevel@tonic-gate 	}
3600Sstevel@tonic-gate }
3610Sstevel@tonic-gate 
3620Sstevel@tonic-gate /*
3630Sstevel@tonic-gate  * Create logical memory tree
3640Sstevel@tonic-gate  * memory --- memory-segment --- memory-bank
3650Sstevel@tonic-gate  * Get information via ioctl of memory control driver
3660Sstevel@tonic-gate  */
3670Sstevel@tonic-gate static int
create_logical_tree(picl_nodehdl_t memh,int fd)3680Sstevel@tonic-gate create_logical_tree(picl_nodehdl_t memh, int fd)
3690Sstevel@tonic-gate {
3700Sstevel@tonic-gate 	int			i;
3710Sstevel@tonic-gate 	int			err = PICL_SUCCESS;
3720Sstevel@tonic-gate 	picl_nodehdl_t		msegh;
3730Sstevel@tonic-gate 	ptree_propinfo_t	propinfo;
3740Sstevel@tonic-gate 	struct mc_memory	*mcmem;
3750Sstevel@tonic-gate 	struct mc_segment	*mcseg;
3760Sstevel@tonic-gate 	picl_prophdl_t		proph;
3770Sstevel@tonic-gate 	uint64_t		memsize = 0;
3780Sstevel@tonic-gate 
3790Sstevel@tonic-gate 	/*
3800Sstevel@tonic-gate 	 * allocate memory for mc_memory where nsegmentids are various
3810Sstevel@tonic-gate 	 */
3820Sstevel@tonic-gate 	if ((mcmem = alloca((nsegments - 1) * sizeof (mcmem->segmentids[0]) +
3830Sstevel@tonic-gate 	    sizeof (*mcmem))) == NULL)
3840Sstevel@tonic-gate 		return (PICL_FAILURE);
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate 	mcmem->nsegments = nsegments;
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate 	/*
3890Sstevel@tonic-gate 	 * Get logical memory information
3900Sstevel@tonic-gate 	 */
3910Sstevel@tonic-gate 	if (ioctl(fd, MCIOC_MEM, mcmem) == -1)
3920Sstevel@tonic-gate 		return (PICL_FAILURE);
3930Sstevel@tonic-gate 
3940Sstevel@tonic-gate 	/*
3950Sstevel@tonic-gate 	 * allocate memory for mc_segment where nbanks are various
3960Sstevel@tonic-gate 	 */
3970Sstevel@tonic-gate 	if ((mcseg = alloca((nbanks - 1) * sizeof (mcseg->bankids[0]) +
3980Sstevel@tonic-gate 	    sizeof (*mcseg))) == NULL)
3990Sstevel@tonic-gate 		return (PICL_FAILURE);
4000Sstevel@tonic-gate 
4010Sstevel@tonic-gate 	/*
4020Sstevel@tonic-gate 	 * Get all segments to create memory-segment nodes and
4030Sstevel@tonic-gate 	 * add properties.
4040Sstevel@tonic-gate 	 */
4050Sstevel@tonic-gate 	for (i = 0; i < nsegments; i++) {
4060Sstevel@tonic-gate 		mcseg->id = mcmem->segmentids[i].globalid;
4070Sstevel@tonic-gate 		mcseg->nbanks = nbanks;
4080Sstevel@tonic-gate 
4090Sstevel@tonic-gate 		if (ioctl(fd, MCIOC_SEG, mcseg) == -1)
4100Sstevel@tonic-gate 			break;
4110Sstevel@tonic-gate 
4120Sstevel@tonic-gate 		/*
4130Sstevel@tonic-gate 		 * Create memory-segment node under memory node
4140Sstevel@tonic-gate 		 */
4150Sstevel@tonic-gate 		err = ptree_create_and_add_node(memh, PICL_NAME_MEMORY_SEGMENT,
4160Sstevel@tonic-gate 		    PICL_CLASS_MEMORY_SEGMENT, &msegh);
4170Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
4180Sstevel@tonic-gate 			break;
4190Sstevel@tonic-gate 
4200Sstevel@tonic-gate 		msegh_info[i] = msegh;
4210Sstevel@tonic-gate 
4220Sstevel@tonic-gate 		/*
4230Sstevel@tonic-gate 		 * Add property, Size to memory-segment node
4240Sstevel@tonic-gate 		 */
4250Sstevel@tonic-gate 		if ((ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
4260Sstevel@tonic-gate 		    PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (mcseg->size),
4270Sstevel@tonic-gate 		    PICL_PROP_SIZE, NULL, NULL)) != PICL_SUCCESS)
4280Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
4290Sstevel@tonic-gate 			break;
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate 		memsize += mcseg->size;
4320Sstevel@tonic-gate 		err = ptree_create_and_add_prop(msegh, &propinfo, &mcseg->size,
4330Sstevel@tonic-gate 		    NULL);
4340Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
4350Sstevel@tonic-gate 			break;
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate 		/*
4380Sstevel@tonic-gate 		 * Add property, BaseAddress to memory-segment node
4390Sstevel@tonic-gate 		 */
4400Sstevel@tonic-gate 		err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
4410Sstevel@tonic-gate 		    PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (mcseg->base),
4420Sstevel@tonic-gate 		    PICL_PROP_BASEADDRESS, NULL, NULL);
4430Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
4440Sstevel@tonic-gate 			break;
4450Sstevel@tonic-gate 
4460Sstevel@tonic-gate 		err = ptree_create_and_add_prop(msegh, &propinfo, &mcseg->base,
4470Sstevel@tonic-gate 		    NULL);
4480Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
4490Sstevel@tonic-gate 			break;
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate 		err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
4520Sstevel@tonic-gate 		    PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (mcseg->ifactor),
4530Sstevel@tonic-gate 		    PICL_PROP_INTERLEAVE_FACTOR, NULL, NULL);
4540Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
4550Sstevel@tonic-gate 			break;
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate 		err = ptree_create_and_add_prop(msegh, &propinfo,
4580Sstevel@tonic-gate 		    &mcseg->ifactor, NULL);
4590Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
4600Sstevel@tonic-gate 			break;
4610Sstevel@tonic-gate 
4620Sstevel@tonic-gate 		err = add_mem_banks(msegh, fd, mcseg);
4630Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
4640Sstevel@tonic-gate 			break;
4650Sstevel@tonic-gate 	}
4660Sstevel@tonic-gate 
4670Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
4680Sstevel@tonic-gate 		undo_logical_tree(nsegments);
4690Sstevel@tonic-gate 		return (err);
4700Sstevel@tonic-gate 	}
4710Sstevel@tonic-gate 
4720Sstevel@tonic-gate 	err = ptree_get_prop_by_name(memh, PICL_PROP_SIZE, &proph);
4730Sstevel@tonic-gate 	if (err == PICL_SUCCESS) {	/* update the value */
4740Sstevel@tonic-gate 		err = ptree_update_propval(proph, &memsize, sizeof (memsize));
4750Sstevel@tonic-gate 		return (err);
4760Sstevel@tonic-gate 	}
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate 	/*
4790Sstevel@tonic-gate 	 * Add the size property
4800Sstevel@tonic-gate 	 */
4810Sstevel@tonic-gate 	(void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
4820Sstevel@tonic-gate 	    PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (memsize),
4830Sstevel@tonic-gate 	    PICL_PROP_SIZE, NULL, NULL);
4840Sstevel@tonic-gate 	err = ptree_create_and_add_prop(memh, &propinfo, &memsize, NULL);
4850Sstevel@tonic-gate 
4860Sstevel@tonic-gate 	return (err);
4870Sstevel@tonic-gate }
4880Sstevel@tonic-gate 
4890Sstevel@tonic-gate /*
4900Sstevel@tonic-gate  * Add memory-module nodes and properties at each enabled memory-module-group.
4910Sstevel@tonic-gate  * The formula of unique id is (id of the given memory module group *
4920Sstevel@tonic-gate  * max number of memory modules per memory module group) + index
4930Sstevel@tonic-gate  * of memory modules in this memory module group
4940Sstevel@tonic-gate  */
4950Sstevel@tonic-gate static int
add_mem_modules(picl_nodehdl_t mmodgrph,struct mc_devgrp * mcdevgrp)4960Sstevel@tonic-gate add_mem_modules(picl_nodehdl_t mmodgrph, struct mc_devgrp *mcdevgrp)
4970Sstevel@tonic-gate {
4980Sstevel@tonic-gate 	uint64_t		size;
4990Sstevel@tonic-gate 	picl_nodehdl_t		dimmh;
5000Sstevel@tonic-gate 	ptree_propinfo_t	propinfo;
5010Sstevel@tonic-gate 	int			i;
5020Sstevel@tonic-gate 	int			err = PICL_SUCCESS;
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate 	size = mcdevgrp->size / mcdevgrp->ndevices;
5050Sstevel@tonic-gate 
5060Sstevel@tonic-gate 	/*
5070Sstevel@tonic-gate 	 * Get all memory-modules of the given memory-module-group
5080Sstevel@tonic-gate 	 */
5090Sstevel@tonic-gate 	for (i = 0; i < mcdevgrp->ndevices; i++) {
5100Sstevel@tonic-gate 		/*
5110Sstevel@tonic-gate 		 * Create memory-module node under memory-module-group
5120Sstevel@tonic-gate 		 */
5130Sstevel@tonic-gate 		err = ptree_create_and_add_node(mmodgrph,
5140Sstevel@tonic-gate 		    PICL_NAME_MEMORY_MODULE, PICL_CLASS_MEMORY_MODULE, &dimmh);
5150Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
5160Sstevel@tonic-gate 			break;
5170Sstevel@tonic-gate 
5180Sstevel@tonic-gate 		/*
5190Sstevel@tonic-gate 		 * Add property, Size to memory-module-group node
5200Sstevel@tonic-gate 		 */
5210Sstevel@tonic-gate 		err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
5220Sstevel@tonic-gate 		    PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (size),
5230Sstevel@tonic-gate 		    PICL_PROP_SIZE, NULL, NULL);
5240Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
5250Sstevel@tonic-gate 			break;
5260Sstevel@tonic-gate 
5270Sstevel@tonic-gate 		err = ptree_create_and_add_prop(dimmh, &propinfo, &size, NULL);
5280Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
5290Sstevel@tonic-gate 			break;
5300Sstevel@tonic-gate 
5310Sstevel@tonic-gate 		/*
5320Sstevel@tonic-gate 		 * Add property, ID to memory-module-group node
5330Sstevel@tonic-gate 		 */
5340Sstevel@tonic-gate 		err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
5350Sstevel@tonic-gate 		    PICL_PTYPE_INT, PICL_READ, sizeof (i), PICL_PROP_ID,
5360Sstevel@tonic-gate 		    NULL, NULL);
5370Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
5380Sstevel@tonic-gate 			break;
5390Sstevel@tonic-gate 
5400Sstevel@tonic-gate 		err = ptree_create_and_add_prop(dimmh, &propinfo, &i,
5410Sstevel@tonic-gate 		    NULL);
5420Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
5430Sstevel@tonic-gate 			break;
5440Sstevel@tonic-gate 	}
5450Sstevel@tonic-gate 	return (err);
5460Sstevel@tonic-gate }
5470Sstevel@tonic-gate 
5480Sstevel@tonic-gate /*
5490Sstevel@tonic-gate  * Create the subtree at every enabled Memory Controller where size of
5500Sstevel@tonic-gate  * memory module group is greater than zero.
5510Sstevel@tonic-gate  * Get information via ioctl of memory control driver
5520Sstevel@tonic-gate  */
5530Sstevel@tonic-gate static int
create_physical_tree(picl_nodehdl_t mch,void * args)5540Sstevel@tonic-gate create_physical_tree(picl_nodehdl_t mch, void *args)
5550Sstevel@tonic-gate {
5560Sstevel@tonic-gate 	int			i, portid;
5570Sstevel@tonic-gate 	int			err = PICL_SUCCESS;
5580Sstevel@tonic-gate 	mmodgrp_info_t		*mmghdl;
5590Sstevel@tonic-gate 	picl_nodehdl_t		mmodgrph;
5600Sstevel@tonic-gate 	ptree_propinfo_t	propinfo;
5610Sstevel@tonic-gate 	struct mc_control 	*mccontrol;
5620Sstevel@tonic-gate 	struct mc_devgrp 	mcdevgrp;
5630Sstevel@tonic-gate 	int			fd;
5640Sstevel@tonic-gate 
5650Sstevel@tonic-gate 	fd = (int)args;
5660Sstevel@tonic-gate 	/*
5670Sstevel@tonic-gate 	 * Get portid of memory-controller as the key to get its
5680Sstevel@tonic-gate 	 * configuration via ioctl.
5690Sstevel@tonic-gate 	 */
5700Sstevel@tonic-gate 	err = ptree_get_propval_by_name(mch, OBP_PROP_PORTID, &portid,
5710Sstevel@tonic-gate 	    sizeof (portid));
5720Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
5730Sstevel@tonic-gate 		return (err);
5740Sstevel@tonic-gate 
5750Sstevel@tonic-gate 	if ((mccontrol = alloca((ndevgrps - 1) *
5760Sstevel@tonic-gate 	    sizeof (mccontrol->devgrpids[0]) + sizeof (*mccontrol))) == NULL)
5770Sstevel@tonic-gate 		return (PICL_FAILURE);
5780Sstevel@tonic-gate 
5790Sstevel@tonic-gate 	mccontrol->id = portid;
5800Sstevel@tonic-gate 	mccontrol->ndevgrps = ndevgrps;
5810Sstevel@tonic-gate 
5820Sstevel@tonic-gate 	if (ioctl(fd, MCIOC_CONTROL, mccontrol) == -1) {
5830Sstevel@tonic-gate 		if (errno == EINVAL)
5840Sstevel@tonic-gate 			return (PICL_WALK_CONTINUE);
5850Sstevel@tonic-gate 		else
5860Sstevel@tonic-gate 			return (PICL_FAILURE);
5870Sstevel@tonic-gate 	}
5880Sstevel@tonic-gate 
5890Sstevel@tonic-gate 	/*
5900Sstevel@tonic-gate 	 * If returned ndevgrps is zero, Memory Controller is disable, and
5910Sstevel@tonic-gate 	 * skip it.
5920Sstevel@tonic-gate 	 */
5930Sstevel@tonic-gate 	if (mccontrol->ndevgrps == 0)
5940Sstevel@tonic-gate 		return (PICL_WALK_CONTINUE);
5950Sstevel@tonic-gate 
5960Sstevel@tonic-gate 	/*
5970Sstevel@tonic-gate 	 * Get all memory module groups of the given memory controller.
5980Sstevel@tonic-gate 	 */
5990Sstevel@tonic-gate 	for (i = 0; i < mccontrol->ndevgrps; i++) {
6000Sstevel@tonic-gate 		int	mmglocalid = mccontrol->devgrpids[i].localid;
6010Sstevel@tonic-gate 
6020Sstevel@tonic-gate 		mcdevgrp.id = mccontrol->devgrpids[i].globalid;
6030Sstevel@tonic-gate 
6040Sstevel@tonic-gate 		if (ioctl(fd, MCIOC_DEVGRP, &mcdevgrp) == -1)
6050Sstevel@tonic-gate 			return (PICL_FAILURE);
6060Sstevel@tonic-gate 
6070Sstevel@tonic-gate 		/*
6080Sstevel@tonic-gate 		 * Node doesn't need to be created if size is 0, i.e.
6090Sstevel@tonic-gate 		 * there is no memory dimm at slot.
6100Sstevel@tonic-gate 		 */
6110Sstevel@tonic-gate 		if (mcdevgrp.size == 0)
6120Sstevel@tonic-gate 			continue;
6130Sstevel@tonic-gate 
6140Sstevel@tonic-gate 		/*
6150Sstevel@tonic-gate 		 * Create memory-module-group node under memory-controller
6160Sstevel@tonic-gate 		 */
6170Sstevel@tonic-gate 		err = ptree_create_and_add_node(mch, PICL_NAME_MEM_MOD_GROUP,
6180Sstevel@tonic-gate 		    PICL_CLASS_MEMORY_MODULE_GROUP, &mmodgrph);
6190Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
6200Sstevel@tonic-gate 			break;
6210Sstevel@tonic-gate 
6220Sstevel@tonic-gate 		/*
6230Sstevel@tonic-gate 		 * Allocate space for mmodgrp_info to save the information
6240Sstevel@tonic-gate 		 * so that it is easier to do the undo and setup of the
6250Sstevel@tonic-gate 		 * reference property in logical memory tree.
6260Sstevel@tonic-gate 		 */
6270Sstevel@tonic-gate 		if ((mmghdl = malloc(sizeof (*mmghdl))) == NULL)
6280Sstevel@tonic-gate 			return (PICL_FAILURE);
6290Sstevel@tonic-gate 
6300Sstevel@tonic-gate 		/*
6310Sstevel@tonic-gate 		 * Save the information and add it to the beginnong of list.
6320Sstevel@tonic-gate 		 */
6330Sstevel@tonic-gate 		mmghdl->mmgid = mcdevgrp.id;
6340Sstevel@tonic-gate 		mmghdl->mmgh = mmodgrph;
6350Sstevel@tonic-gate 		mmghdl->mch = mch;
6360Sstevel@tonic-gate 		mmghdl->next = head2mmodgrp;
6370Sstevel@tonic-gate 
6380Sstevel@tonic-gate 		head2mmodgrp = mmghdl;
6390Sstevel@tonic-gate 
6400Sstevel@tonic-gate 		/*
6410Sstevel@tonic-gate 		 * Add property, Size to memory-module-group node
6420Sstevel@tonic-gate 		 */
6430Sstevel@tonic-gate 		err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
6440Sstevel@tonic-gate 		    PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (mcdevgrp.size),
6450Sstevel@tonic-gate 		    PICL_PROP_SIZE, NULL, NULL);
6460Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
6470Sstevel@tonic-gate 			break;
6480Sstevel@tonic-gate 
6490Sstevel@tonic-gate 		err = ptree_create_and_add_prop(mmodgrph, &propinfo,
6500Sstevel@tonic-gate 		    &mcdevgrp.size, NULL);
6510Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
6520Sstevel@tonic-gate 			break;
6530Sstevel@tonic-gate 
6540Sstevel@tonic-gate 		/*
6550Sstevel@tonic-gate 		 * Add property, ID to memory-module-group node
6560Sstevel@tonic-gate 		 */
6570Sstevel@tonic-gate 		err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
6580Sstevel@tonic-gate 		    PICL_PTYPE_INT, PICL_READ, sizeof (mmglocalid),
6590Sstevel@tonic-gate 		    PICL_PROP_ID, NULL, NULL);
6600Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
6610Sstevel@tonic-gate 			break;
6620Sstevel@tonic-gate 
6630Sstevel@tonic-gate 		err = ptree_create_and_add_prop(mmodgrph, &propinfo,
6640Sstevel@tonic-gate 		    &mmglocalid, NULL);
6650Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
6660Sstevel@tonic-gate 			break;
6670Sstevel@tonic-gate 
6680Sstevel@tonic-gate 		/*
6690Sstevel@tonic-gate 		 * Create all memory-module nodes and properties.
6700Sstevel@tonic-gate 		 */
6710Sstevel@tonic-gate 		err = add_mem_modules(mmodgrph, &mcdevgrp);
6720Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
6730Sstevel@tonic-gate 			break;
6740Sstevel@tonic-gate 	}
6750Sstevel@tonic-gate 
6760Sstevel@tonic-gate 	if (err == PICL_SUCCESS)
6770Sstevel@tonic-gate 		return (PICL_WALK_CONTINUE);
6780Sstevel@tonic-gate 	return (err);
6790Sstevel@tonic-gate }
6800Sstevel@tonic-gate 
6810Sstevel@tonic-gate /*
6820Sstevel@tonic-gate  * Create physical memory tree
6830Sstevel@tonic-gate  * memory-controller --- memory-module-group --- memory-module
6840Sstevel@tonic-gate  *
6850Sstevel@tonic-gate  * It searches all memory-controller nodes in the whole devtree.
6860Sstevel@tonic-gate  * It returns failure if encountering error in physical tree.
6870Sstevel@tonic-gate  */
6880Sstevel@tonic-gate static int
find_mc_create_tree(picl_nodehdl_t rooth,int fd)6890Sstevel@tonic-gate find_mc_create_tree(picl_nodehdl_t rooth, int fd)
6900Sstevel@tonic-gate {
6910Sstevel@tonic-gate 	int		err;
6920Sstevel@tonic-gate 
6930Sstevel@tonic-gate 	err = ptree_walk_tree_by_class(rooth, PICL_CLASS_MEMORY_CONTROLLER,
6940Sstevel@tonic-gate 	    (void *)fd, create_physical_tree);
6950Sstevel@tonic-gate 	return (err);
6960Sstevel@tonic-gate }
6970Sstevel@tonic-gate 
6980Sstevel@tonic-gate static int
init_mc(void)6990Sstevel@tonic-gate init_mc(void)
7000Sstevel@tonic-gate {
7010Sstevel@tonic-gate 	struct mc_memconf	mcmemconf;
7020Sstevel@tonic-gate 	int			fd;
7030Sstevel@tonic-gate 	DIR			*dirp;
704871Scasper 	struct dirent		*retp;
7050Sstevel@tonic-gate 	char			path[PATH_MAX];
7060Sstevel@tonic-gate 	int 			found = 0;
707*11205SMichael.Bergknoff@Sun.COM 	int			valid_entry = 0;
7080Sstevel@tonic-gate 
7090Sstevel@tonic-gate 	/* open the directory */
7100Sstevel@tonic-gate 	if ((dirp = opendir(MC_DIR)) == NULL) {
7110Sstevel@tonic-gate 		/*
7120Sstevel@tonic-gate 		 * As not all platforms have mc drivers that create the
7130Sstevel@tonic-gate 		 * /dev/mc directory, print a message only if there is
7140Sstevel@tonic-gate 		 * an entry found on which the open failed.
7150Sstevel@tonic-gate 		 */
7160Sstevel@tonic-gate 		if (errno != ENOENT)
7170Sstevel@tonic-gate 			syslog(LOG_ERR, EM_INIT_MC_FAILED);
7180Sstevel@tonic-gate 		return (-1);
7190Sstevel@tonic-gate 	}
7200Sstevel@tonic-gate 
7210Sstevel@tonic-gate 	/* start searching this directory */
722871Scasper 	while ((retp = readdir(dirp)) != NULL) {
7230Sstevel@tonic-gate 		/* skip . .. etc... */
7240Sstevel@tonic-gate 		if (strcmp(retp->d_name, ".") == 0 ||
7250Sstevel@tonic-gate 		    strcmp(retp->d_name, "..") == 0)
7260Sstevel@tonic-gate 			continue;
7270Sstevel@tonic-gate 
7280Sstevel@tonic-gate 		(void) strcpy(path, MC_DIR);
7290Sstevel@tonic-gate 		(void) strcat(path, retp->d_name);
7300Sstevel@tonic-gate 		/* open the memory controller driver */
7310Sstevel@tonic-gate 		if ((fd = open(path, O_RDONLY, 0)) != -1) {
7320Sstevel@tonic-gate 			found = 1;
7330Sstevel@tonic-gate 			break;
7340Sstevel@tonic-gate 		}
735*11205SMichael.Bergknoff@Sun.COM 		if (errno != ENOENT)
736*11205SMichael.Bergknoff@Sun.COM 			valid_entry = 1;
7370Sstevel@tonic-gate 	}
7380Sstevel@tonic-gate 	(void) closedir(dirp);
7390Sstevel@tonic-gate 
7400Sstevel@tonic-gate 	if (!found) {
741*11205SMichael.Bergknoff@Sun.COM 		if (valid_entry)
742*11205SMichael.Bergknoff@Sun.COM 			syslog(LOG_ERR, EM_INIT_MC_FAILED);
7430Sstevel@tonic-gate 		return (-1);
7440Sstevel@tonic-gate 	}
7450Sstevel@tonic-gate 
7460Sstevel@tonic-gate 	/*
7470Sstevel@tonic-gate 	 * Initialize some global variables via ioctl
7480Sstevel@tonic-gate 	 */
7490Sstevel@tonic-gate 	if (ioctl(fd, MCIOC_MEMCONF, &mcmemconf) == -1) {
7500Sstevel@tonic-gate 		(void) close(fd);
7510Sstevel@tonic-gate 		return (-1);
7520Sstevel@tonic-gate 	}
7530Sstevel@tonic-gate 
7540Sstevel@tonic-gate 	nsegments = mcmemconf.nsegments;
7550Sstevel@tonic-gate 	nbanks = mcmemconf.nbanks;
7560Sstevel@tonic-gate 	ndevgrps = mcmemconf.ndevgrps;
7570Sstevel@tonic-gate 	ndevs = mcmemconf.ndevs;
7580Sstevel@tonic-gate 	transfersize = mcmemconf.xfer_size;
7590Sstevel@tonic-gate 
7600Sstevel@tonic-gate 	return (fd);
7610Sstevel@tonic-gate }
7620Sstevel@tonic-gate 
7630Sstevel@tonic-gate /*
7640Sstevel@tonic-gate  * executed as part of .init when the plugin is dlopen()ed
7650Sstevel@tonic-gate  */
7660Sstevel@tonic-gate void
piclmemcfg_register(void)7670Sstevel@tonic-gate piclmemcfg_register(void)
7680Sstevel@tonic-gate {
7690Sstevel@tonic-gate 	(void) picld_plugin_register(&my_reg_info);
7700Sstevel@tonic-gate }
7710Sstevel@tonic-gate 
7720Sstevel@tonic-gate /*
7730Sstevel@tonic-gate  * init entry point of the plugin
7740Sstevel@tonic-gate  * Creates the PICL nodes and properties in the physical and logical aspects.
7750Sstevel@tonic-gate  */
7760Sstevel@tonic-gate void
piclmemcfg_init(void)7770Sstevel@tonic-gate piclmemcfg_init(void)
7780Sstevel@tonic-gate {
7790Sstevel@tonic-gate 	picl_nodehdl_t		plfh;
7800Sstevel@tonic-gate 	picl_nodehdl_t		memh;
7810Sstevel@tonic-gate 	ptree_propinfo_t	propinfo;
7820Sstevel@tonic-gate 	int			fd, err;
7830Sstevel@tonic-gate 
7840Sstevel@tonic-gate 	/*
7850Sstevel@tonic-gate 	 * Initialize the header pointer of mmodgrp_info list
7860Sstevel@tonic-gate 	 */
7870Sstevel@tonic-gate 	head2mmodgrp = NULL;
7880Sstevel@tonic-gate 	msegh_info = NULL;
7890Sstevel@tonic-gate 
7900Sstevel@tonic-gate 	if ((fd = init_mc()) < 0)
7910Sstevel@tonic-gate 		return;
7920Sstevel@tonic-gate 
7930Sstevel@tonic-gate 	/*
7940Sstevel@tonic-gate 	 * allocate memory to save memory-segment node handles. Thus,
7950Sstevel@tonic-gate 	 * it is easier to delete them if it fails.
7960Sstevel@tonic-gate 	 */
7970Sstevel@tonic-gate 	if ((msegh_info = malloc(nsegments * sizeof (picl_nodehdl_t))) ==
7980Sstevel@tonic-gate 	    NULL) {
7990Sstevel@tonic-gate 		syslog(LOG_ERR, EM_INIT_FAILED);
8000Sstevel@tonic-gate 		(void) close(fd);
8010Sstevel@tonic-gate 		return;
8020Sstevel@tonic-gate 	}
8030Sstevel@tonic-gate 
8040Sstevel@tonic-gate 	/*
8050Sstevel@tonic-gate 	 * find platform node
8060Sstevel@tonic-gate 	 */
8070Sstevel@tonic-gate 	if ((ptree_get_node_by_path(PLATFORM_PATH, &plfh)) != PICL_SUCCESS) {
8080Sstevel@tonic-gate 		syslog(LOG_ERR, EM_INIT_FAILED);
8090Sstevel@tonic-gate 		(void) close(fd);
8100Sstevel@tonic-gate 		return;
8110Sstevel@tonic-gate 	}
8120Sstevel@tonic-gate 
8130Sstevel@tonic-gate 	/*
8140Sstevel@tonic-gate 	 * Find the memory node
8150Sstevel@tonic-gate 	 */
8160Sstevel@tonic-gate 	if ((ptree_get_node_by_path(MEMORY_PATH, &memh)) != PICL_SUCCESS) {
8170Sstevel@tonic-gate 		syslog(LOG_ERR, EM_INIT_FAILED);
8180Sstevel@tonic-gate 		(void) close(fd);
8190Sstevel@tonic-gate 		return;
8200Sstevel@tonic-gate 	}
8210Sstevel@tonic-gate 
8220Sstevel@tonic-gate 	/*
8230Sstevel@tonic-gate 	 * Create subtree of memory-controller in the physical aspect.
8240Sstevel@tonic-gate 	 * memory-controller --- memory-module-group --- memory-module
8250Sstevel@tonic-gate 	 */
8260Sstevel@tonic-gate 	err = find_mc_create_tree(plfh, fd);
8270Sstevel@tonic-gate 
8280Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
8290Sstevel@tonic-gate 		undo_phymem_tree();
8300Sstevel@tonic-gate 		syslog(LOG_ERR, EM_PHYSIC_MEM_TREE_FAILED);
8310Sstevel@tonic-gate 	}
8320Sstevel@tonic-gate 
8330Sstevel@tonic-gate 	/*
8340Sstevel@tonic-gate 	 * Add property, TransferSize to memory node
8350Sstevel@tonic-gate 	 */
8360Sstevel@tonic-gate 	err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
8370Sstevel@tonic-gate 	    PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (transfersize),
8380Sstevel@tonic-gate 	    PICL_PROP_TRANSFER_SIZE, NULL, NULL);
8390Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
8400Sstevel@tonic-gate 		(void) close(fd);
8410Sstevel@tonic-gate 		return;
8420Sstevel@tonic-gate 	}
8430Sstevel@tonic-gate 
8440Sstevel@tonic-gate 	err = ptree_create_and_add_prop(memh, &propinfo,
8450Sstevel@tonic-gate 	    &transfersize, NULL);
8460Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
8470Sstevel@tonic-gate 		(void) close(fd);
8480Sstevel@tonic-gate 		return;
8490Sstevel@tonic-gate 	}
8500Sstevel@tonic-gate 
8510Sstevel@tonic-gate 	/*
8520Sstevel@tonic-gate 	 * Create subtree of memory in the logical aspect.
8530Sstevel@tonic-gate 	 * memory --- memory-segment --- memory-bank
8540Sstevel@tonic-gate 	 */
8550Sstevel@tonic-gate 	if ((create_logical_tree(memh, fd)) != PICL_SUCCESS) {
8560Sstevel@tonic-gate 		syslog(LOG_ERR, EM_LOGIC_MEM_TREE_FAILED);
8570Sstevel@tonic-gate 		undo_logical_tree(nsegments);
8580Sstevel@tonic-gate 	}
8590Sstevel@tonic-gate 
8600Sstevel@tonic-gate 	(void) close(fd);
8610Sstevel@tonic-gate 	(void) ptree_register_handler(PICLEVENT_MC_ADDED,
8620Sstevel@tonic-gate 	    piclmemcfg_evhandler, NULL);
8630Sstevel@tonic-gate 	(void) ptree_register_handler(PICLEVENT_MC_REMOVED,
8640Sstevel@tonic-gate 	    piclmemcfg_evhandler, NULL);
8650Sstevel@tonic-gate }
8660Sstevel@tonic-gate 
8670Sstevel@tonic-gate /*
8680Sstevel@tonic-gate  * fini entry point of the plugin
8690Sstevel@tonic-gate  */
8700Sstevel@tonic-gate void
piclmemcfg_fini(void)8710Sstevel@tonic-gate piclmemcfg_fini(void)
8720Sstevel@tonic-gate {
8730Sstevel@tonic-gate 	(void) ptree_unregister_handler(PICLEVENT_MC_ADDED,
8740Sstevel@tonic-gate 	    piclmemcfg_evhandler, NULL);
8750Sstevel@tonic-gate 	(void) ptree_unregister_handler(PICLEVENT_MC_REMOVED,
8760Sstevel@tonic-gate 	    piclmemcfg_evhandler, NULL);
8770Sstevel@tonic-gate 	/*
8780Sstevel@tonic-gate 	 * Release all the allocated memory for global structures
8790Sstevel@tonic-gate 	 */
8800Sstevel@tonic-gate 	free_allocated_mem();
8810Sstevel@tonic-gate 	if (msegh_info)
8820Sstevel@tonic-gate 		free(msegh_info);
8830Sstevel@tonic-gate }
8840Sstevel@tonic-gate 
8850Sstevel@tonic-gate /*
8860Sstevel@tonic-gate  * Event handler of this plug-in
8870Sstevel@tonic-gate  */
8880Sstevel@tonic-gate /*ARGSUSED*/
8890Sstevel@tonic-gate static void
piclmemcfg_evhandler(const char * ename,const void * earg,size_t size,void * cookie)8900Sstevel@tonic-gate piclmemcfg_evhandler(const char *ename, const void *earg, size_t size,
8910Sstevel@tonic-gate     void *cookie)
8920Sstevel@tonic-gate {
8930Sstevel@tonic-gate 	int		err;
8940Sstevel@tonic-gate 	int		fd;
8950Sstevel@tonic-gate 	picl_nodehdl_t	memh;
8960Sstevel@tonic-gate 	picl_nodehdl_t	nodeh;
8970Sstevel@tonic-gate 	int		old_nsegs;
8980Sstevel@tonic-gate 	nvlist_t	*nvlp;
8990Sstevel@tonic-gate 
9000Sstevel@tonic-gate 	memh = NULL;
9010Sstevel@tonic-gate 	if (nvlist_unpack((char *)earg, size, &nvlp, NULL))
9020Sstevel@tonic-gate 		return;
9030Sstevel@tonic-gate 
9040Sstevel@tonic-gate 	if (nvlist_lookup_uint64(nvlp, PICLEVENTARG_NODEHANDLE, &nodeh)) {
9050Sstevel@tonic-gate 		nvlist_free(nvlp);
9060Sstevel@tonic-gate 		return;
9070Sstevel@tonic-gate 	}
9080Sstevel@tonic-gate 	nvlist_free(nvlp);
9090Sstevel@tonic-gate 
9100Sstevel@tonic-gate 	/*
9110Sstevel@tonic-gate 	 * get the memory node
9120Sstevel@tonic-gate 	 */
9130Sstevel@tonic-gate 	err = ptree_get_node_by_path(MEMORY_PATH, &memh);
9140Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
9150Sstevel@tonic-gate 		return;
9160Sstevel@tonic-gate 
9170Sstevel@tonic-gate 	/*
9180Sstevel@tonic-gate 	 * nsegments won't be overwritten until init_mc succeeds
9190Sstevel@tonic-gate 	 */
9200Sstevel@tonic-gate 	old_nsegs = nsegments;
9210Sstevel@tonic-gate 	if ((fd = init_mc()) < 0)
9220Sstevel@tonic-gate 		return;
9230Sstevel@tonic-gate 
9240Sstevel@tonic-gate 	if (strcmp(ename, PICLEVENT_MC_ADDED) == 0)
9250Sstevel@tonic-gate 		(void) create_physical_tree(nodeh, (void *)fd);
9260Sstevel@tonic-gate 	else if (strcmp(ename, PICLEVENT_MC_REMOVED) == 0)
9270Sstevel@tonic-gate 		/*
9280Sstevel@tonic-gate 		 * Delete the entry at the list only since class at PICL is
9290Sstevel@tonic-gate 		 * deleted in devtree plugin.
9300Sstevel@tonic-gate 		 */
9310Sstevel@tonic-gate 		(void) del_plugout_mmodgrp(nodeh);
9320Sstevel@tonic-gate 
9330Sstevel@tonic-gate 	(void) undo_logical_tree(old_nsegs);
9340Sstevel@tonic-gate 	free(msegh_info);
9350Sstevel@tonic-gate 
9360Sstevel@tonic-gate 	/*
9370Sstevel@tonic-gate 	 * allocate memory to save memory-segment node handles. Thus,
9380Sstevel@tonic-gate 	 * it is easier to delete them if it fails.
9390Sstevel@tonic-gate 	 */
9400Sstevel@tonic-gate 	if ((msegh_info = malloc(nsegments * sizeof (picl_nodehdl_t))) ==
9410Sstevel@tonic-gate 	    NULL) {
9420Sstevel@tonic-gate 		(void) close(fd);
9430Sstevel@tonic-gate 		return;
9440Sstevel@tonic-gate 	}
9450Sstevel@tonic-gate 
9460Sstevel@tonic-gate 	(void) create_logical_tree(memh, fd);
9470Sstevel@tonic-gate 
9480Sstevel@tonic-gate 	(void) close(fd);
9490Sstevel@tonic-gate }
950